diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..1027042a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots (OPTIONAL)** +If applicable, add screenshots to help explain your problem. + +**Logs** +- Paste the output of the console window in a text file, and attach the text file. +- If applicable (`logfile` set to 2), attach the `qconsole.log` file. On Windows, it can be found in **%APPDATA%\...\qconsole.log** and on Linux, it can be found on the home directory **~/.openmohaa/.../qconsole.log**. + +**Version information (please complete the following information):** + - OS: [e.g. `Debian`] + - OS Version [e.g `12`] + - OpenMoHAA Version: [e.g `0.70.0-alpha+0.0b1a20dcf win_msvc64-x86_64-debug`, can be found below **Common Initialization** in the console, or by typing `version`] + +**Dump (OPTIONAL)** +You can include a core dump generated by the OS (`.dmp` file). If you compiled OpenMoHAA yourself, also add all output openmohaa binaries (except libopenal and libSDL). + +**Additional context (OPTIONAL)** +Add any other context about the problem here. diff --git a/.github/workflows/branches-build.yml b/.github/workflows/branches-build.yml new file mode 100644 index 00000000..c3fa846a --- /dev/null +++ b/.github/workflows/branches-build.yml @@ -0,0 +1,17 @@ +name: Build branch + +on: + push: + branches: + - '**' + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-all: + uses: ./.github/workflows/shared-build.yml + with: + environment: "testing" diff --git a/.github/workflows/build-cmake.yml b/.github/workflows/build-cmake.yml deleted file mode 100644 index a4935463..00000000 --- a/.github/workflows/build-cmake.yml +++ /dev/null @@ -1,192 +0,0 @@ -name: Build - -on: - push: - pull_request: - workflow_call: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: RelWithDebInfo - -jobs: - build-platform-linux: - strategy: - matrix: - architecture: [ - {name: 'amd64', triple: 'x86_64-linux-gnu'}, - {name: 'i686', triple: 'i686-linux-gnu'}, - {name: 'aarch64', triple: 'aarch64-linux-gnu'}, - {name: 'armhf', triple: 'arm-linux-gnueabihf'} - ] - - name: "Building for platform linux-${{matrix.architecture.name}}" - runs-on: ubuntu-22.04 - - steps: - - name: Settings - working-directory: ${{github.workspace}} - run: | - echo "CMAKE_BUILD_PARALLEL_LEVEL=$(($(nproc) * 16))" >> $GITHUB_ENV -# echo "CMAKE_GENERATOR=Ninja" >> $GITHUB_ENV - - - name: Install required packages - run: | - sudo apt update && sudo apt install -y flex bison - - - name: Install required cross-platform packages (${{ matrix.architecture.triple }}) - if: matrix.architecture.name != 'amd64' - run: sudo apt install -y gcc-12-${{ matrix.architecture.triple }} g++-12-${{ matrix.architecture.triple }} - - # Setup SDL - - name: Set up SDL - id: sdl - uses: libsdl-org/setup-sdl@main - with: - version: sdl2-latest - build-type: Release - cmake-arguments: "-DCMAKE_C_COMPILER=clang - -DCMAKE_CXX_COMPILER=clang++ - -DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }} - -DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }}" - - - uses: actions/checkout@v3 - with: - path: 'source' - - - name: CMake Settings - run: | - echo "CMAKE_PARAM=--log-level=VERBOSE \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ - -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \ - -DCMAKE_C_COMPILER=clang \ - -DCMAKE_CXX_COMPILER=clang++ \ - -DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }} \ - -DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }} \ - -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }}" >> $GITHUB_ENV - - - name: Configure CMake - working-directory: ${{github.workspace}} - run: | - cmake -B ./build ${{ env.CMAKE_PARAM }} ./source - - - name: Build - working-directory: ${{github.workspace}} - run: | - cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Test - working-directory: ${{github.workspace}} - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: | - cd "${{github.workspace}}/build" - ctest -C ${{env.BUILD_TYPE}} - - - name: Install - working-directory: ${{github.workspace}} - # Install to the directory defined in CMAKE_INSTALL_PREFIX - run: | - cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - cp '${{steps.sdl.outputs.prefix}}/lib/libSDL2.so' '${{github.workspace}}/install' - - - uses: actions/upload-artifact@v3 - with: - name: out-linux-${{matrix.architecture.name}} - if-no-files-found: error - path: - ${{github.workspace}}/install - - build-platform-windows: - strategy: - matrix: - architecture: [ - {name: 'x64', config: 'x64' }, - {name: 'x86', config: 'Win32' }, - {name: 'arm64', config: 'ARM64' } - ] - - name: "Building for platform windows-${{matrix.architecture.name}}" - runs-on: windows-2022 - - steps: - - name: Settings - working-directory: ${{github.workspace}} - run: | - echo "CMAKE_BUILD_PARALLEL_LEVEL=$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors * 16)" >> $GITHUB_ENV - - # Setup SDL - - name: Set up SDL - id: sdl - uses: libsdl-org/setup-sdl@main - with: - version: sdl2-latest - build-type: Release - cmake-arguments: "-A ${{ matrix.architecture.config }}" - - - name: Install Flex/Bison - working-directory: ${{github.workspace}} - run: | - mkdir thirdparties && cd thirdparties - git clone --depth 1 --single-branch --branch v2.5.25 https://github.com/lexxmark/winflexbison.git - cmake -B winflexbison-build -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/winflexbison-install' ./winflexbison - cmake --build winflexbison-build --config Release --parallel - cmake --install winflexbison-build - - - uses: actions/checkout@v3 - with: - path: 'source' - - - name: CMake Settings - run: | - echo "CMAKE_PARAM=-A ${{ matrix.architecture.config }} ` - --log-level=VERBOSE ` - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ` - -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' ` - -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} ` - -DBISON_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_bison.exe' ` - -DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe'".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV - - - name: Configure CMake - working-directory: ${{github.workspace}} - run: | - cmake -B ./build ${{ env.CMAKE_PARAM }} ./source - - - name: Build - working-directory: ${{github.workspace}} - run: | - cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Test - working-directory: ${{github.workspace}} - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: | - cd "${{github.workspace}}/build" - ctest -C ${{env.BUILD_TYPE}} - - - name: Install - working-directory: ${{github.workspace}} - # Install to the directory defined in CMAKE_INSTALL_PREFIX - run: | - cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - Copy-Item '${{steps.sdl.outputs.prefix}}/bin/*.dll' -Destination '${{github.workspace}}/install' - - - uses: actions/upload-artifact@v3 - with: - name: out-windows-${{matrix.architecture.name}} - if-no-files-found: error - path: | - ${{github.workspace}}/install - !${{github.workspace}}/install/**/*.pdb - - - uses: actions/upload-artifact@v3 - with: - name: out-windows-${{matrix.architecture.name}}-pdb - if-no-files-found: error - path: | - ${{github.workspace}}/install diff --git a/.github/workflows/codeql.yml b/.github/workflows/main-codeql.yml similarity index 85% rename from .github/workflows/codeql.yml rename to .github/workflows/main-codeql.yml index fc4f71a7..5de08e79 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/main-codeql.yml @@ -20,6 +20,10 @@ on: schedule: - cron: '42 8 * * 1' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: analyze: name: Analyze @@ -41,7 +45,13 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + - uses: awalsh128/cache-apt-pkgs-action@latest + name: Install required packages + with: + packages: libopenal-dev libpulse-dev portaudio19-dev libasound2-dev libjack-dev libpipewire-0.3-dev qtbase5-dev libdbus-1-dev + version: "0.1" # Setup SDL - name: Set up SDL @@ -52,7 +62,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +76,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -79,6 +89,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/shared-build-linux.yml b/.github/workflows/shared-build-linux.yml new file mode 100644 index 00000000..9bbf28c3 --- /dev/null +++ b/.github/workflows/shared-build-linux.yml @@ -0,0 +1,246 @@ +########################## +# +# Linux +# Ubuntu 22.04 +# +# Using this version instead of 24.04 to use a lower GLIBC version (2.34). +# ARM is used for more efficiency, and x64 is used for legacy architectures like PowerPC. +########################## +name: Linux build workflow + +on: + workflow_call: + inputs: + environment: + required: true + type: string + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: RelWithDebInfo + RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }} + +jobs: + build: + strategy: + matrix: + architecture: [ + {name: 'amd64', os: "ubuntu-22.04-arm", package: 'x86-64-linux-gnu', triple: 'x86_64-linux-gnu', arch_option: 'linux-x86_64'}, + {name: 'i686', os: "ubuntu-22.04-arm", package: 'i686-linux-gnu', triple: 'i686-linux-gnu', arch_option: 'linux-x86'}, + {name: 'arm64', os: "ubuntu-22.04-arm", package: 'aarch64-linux-gnu', triple: 'aarch64-linux-gnu', arch_option: 'linux-aarch64'}, + {name: 'armhf', os: "ubuntu-22.04-arm", package: 'arm-linux-gnueabihf', triple: 'arm-linux-gnueabihf', arch_option: 'linux-armv4'}, + {name: 'powerpc', os: "ubuntu-22.04", package: 'powerpc-linux-gnu', triple: 'powerpc-linux-gnu', arch_option: 'linux-ppc'}, + {name: 'ppc64', os: "ubuntu-22.04", package: 'powerpc64-linux-gnu', triple: 'powerpc64-linux-gnu', arch_option: 'linux-ppc64'}, + {name: 'ppc64el', os: "ubuntu-22.04-arm", package: 'powerpc64le-linux-gnu', triple: 'powerpc64le-linux-gnu', arch_option: 'linux-ppc64le'} + ] + + name: "Building for platform linux-${{matrix.architecture.name}}" + runs-on: ${{ matrix.architecture.os }} + environment: ${{ inputs.environment }} + env: + wolfssl-version: 'v5.7.6-stable' + curl-version: '8_12_1' + openal-soft-branch: '1.24.3' + + steps: + ### + # Packages + ### + + - uses: awalsh128/cache-apt-pkgs-action@latest + name: Install required packages + with: + packages: flex bison ninja-build cmake clang libpulse-dev portaudio19-dev libasound2-dev libjack-dev libpipewire-0.3-dev qtbase5-dev libdbus-1-dev + version: "${{ runner.os }}-${{ runner.arch }}-v1" + + - name: Settings + working-directory: ${{github.workspace}} + run: | + echo "HOST_TRIPLE=$(gcc -dumpmachine)" >> $GITHUB_ENV + + - uses: awalsh128/cache-apt-pkgs-action@latest + name: Install required cross-platform packages (${{ matrix.architecture.package }}) + if: env.HOST_TRIPLE != matrix.architecture.triple + with: + packages: gcc-12-${{ matrix.architecture.package }} g++-12-${{ matrix.architecture.package }} + version: "${{ runner.os }}-${{ runner.arch }}-v1" + + - name: Settings + working-directory: ${{github.workspace}} + run: | + echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $GITHUB_ENV + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + echo "CFLAGS='--target=${{ matrix.architecture.triple }}'" >> $GITHUB_ENV + echo "CXXFLAGS='--target=${{ matrix.architecture.triple }}'" >> $GITHUB_ENV + + ### + # SDL + ### + + # Setup SDL + - name: Set up SDL + id: sdl + uses: libsdl-org/setup-sdl@main + with: + version: 2-latest + build-type: Release + # Workaround for when changing the runner OS version + cmake-arguments: "-DCACHE_OS_VERSION=Ubuntu_22.04" + + ### + # OpenAL + ### + - name: Cache OpenAL + id: cache-openal-soft + uses: actions/cache@v4 + with: + path: 'thirdparties/soft-oal/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-openal-soft-${{ env.openal-soft-branch }}-v1 + + # soft-oal setup + - name: Checkout soft-oal + if: steps.cache-openal-soft.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'kcat/openal-soft' + path: 'thirdparties/soft-oal' + ref: '${{ env.openal-soft-branch }}' + + - name: Configure and install soft-oal + if: steps.cache-openal-soft.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/soft-oal + run: | + cmake -B ./build \ + -DALSOFT_UTILS=OFF \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + + ### + # WolfSSL + ### + - name: Cache WolfSSL + id: cache-wolfssl + uses: actions/cache@v4 + with: + path: 'thirdparties/wolfssl/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-wolfssl-${{ env.wolfssl-version }}-v1 + + # WolfSSL setup + - name: Checkout WolfSSL + if: steps.cache-wolfssl.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'wolfssl/wolfssl' + path: 'thirdparties/wolfssl' + ref: '${{ env.wolfssl-version }}' + + # WolfSSL build + - name: Configure and install wolfssl + if: steps.cache-wolfssl.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/wolfssl + run: | + cmake -B ./build \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/wolfssl/install' \ + -DCMAKE_C_FLAGS="$CFLAGS -fPIC" \ + -DCMAKE_CXX_FLAGS="$CFLAGS -fPIC" \ + -DBUILD_SHARED_LIBS=OFF -DWOLFSSL_OPENSSLEXTRA=ON -DWOLFSSL_ASM=OFF -DWOLFSSL_EXAMPLES=OFF -DWOLFSSL_CURL=ON + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + + ### + # cURL + ### + - name: Cache cURL + id: cache-curl + uses: actions/cache@v4 + with: + path: 'thirdparties/curl/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-curl-${{ env.curl-version }}-v1 + + # cURL setup + - name: Checkout cURL + if: steps.cache-curl.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'curl/curl' + path: 'thirdparties/curl' + ref: 'curl-${{ env.curl-version }}' + + # cURL build + - name: Configure and install curl + if: steps.cache-curl.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/curl + run: | + cmake -B ./build \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/curl/install' \ + -DCURL_USE_LIBPSL=OFF \ + -DCURL_USE_WOLFSSL=ON \ + -DCURL_ZLIB="" \ + -DCURL_BROTLI="" \ + -DCURL_ZSTD="" \ + -DCMAKE_SHARED_LINKER_FLAGS="-lm" \ + -DWolfSSL_ROOT='${{github.workspace}}/thirdparties/wolfssl/install' + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + + ### + # Project + ### + + - uses: actions/checkout@v4 + with: + path: 'source' + + - name: CMake Settings + run: | + echo "CMAKE_PARAM=--log-level=VERBOSE \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \ + -DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' \ + -DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/install/include' \ + -DCURL_ROOT='${{github.workspace}}/thirdparties/curl/install' \ + -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \ + -DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'" >> $GITHUB_ENV + + - name: Configure CMake + working-directory: ${{github.workspace}} + run: | + cmake -B ./build ${{ env.CMAKE_PARAM }} ./source + + - name: Build + working-directory: ${{github.workspace}} + run: | + cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + + - name: Test + working-directory: ${{github.workspace}} + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: | + cd "${{github.workspace}}/build" + ctest -C ${{env.BUILD_TYPE}} + + - name: Install + working-directory: ${{github.workspace}} + # Install to the directory defined in CMAKE_INSTALL_PREFIX + run: | + cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + # Copy libraries + mkdir ${{github.workspace}}/package + cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.so.0 '${{github.workspace}}/package/' + cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.so.1 '${{github.workspace}}/package/' + cp -l ${{github.workspace}}/thirdparties/curl/install/lib*/libcurl.so.4 '${{github.workspace}}/package/' + if [ -d ${{github.workspace}}/install/bin ]; then cp -r ${{github.workspace}}/install/bin/openmohaa/. '${{github.workspace}}/package'; fi + if [ -d ${{github.workspace}}/install/lib ]; then cp -r ${{github.workspace}}/install/lib/openmohaa/. '${{github.workspace}}/package'; fi + + ### + # Artifacts + ### + + - uses: actions/upload-artifact@v4 + with: + name: out-linux-${{matrix.architecture.name}} + if-no-files-found: error + path: + ${{github.workspace}}/package \ No newline at end of file diff --git a/.github/workflows/shared-build-macos.yml b/.github/workflows/shared-build-macos.yml new file mode 100644 index 00000000..d4ba04c1 --- /dev/null +++ b/.github/workflows/shared-build-macos.yml @@ -0,0 +1,239 @@ +########################## +# +# Apple macOS +# macOS 15 +# +# This version is used as the OS, as it's faster than other versions. +########################## +name: MacOS build workflow + +on: + workflow_call: + inputs: + environment: + required: true + type: string + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: RelWithDebInfo + RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }} + +jobs: + build: + strategy: + matrix: + architecture: [ + #{name: 'x86_64', triple: 'x86_64-apple-macos10.8'}, + #{name: 'arm64', triple: 'arm64-apple-macos11'} + #{name: 'x86_64', build_name: 'x86_64'}, + #{name: 'arm64', build_name: 'arm64'}, + # Compile into an universal binary + {name: 'multiarch(arm64-x86_64)', build_name: 'arm64;x86_64' } + ] + + name: "Building for platform macos-${{matrix.architecture.name}}" + runs-on: "macos-15" + env: + openal-soft-branch: '1.24.3' + wolfssl-version: 'v5.7.6-stable' + curl-version: '8_12_1' + + steps: + ### + # Packages + ### + + - name: Install required packages + run: | + brew install git flex bison ninja cmake llvm perl + + - name: Settings + working-directory: ${{github.workspace}} + run: | + echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $GITHUB_ENV + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV + + ### + # SDL + ### + + # Setup SDL + - name: Set up SDL + id: sdl + uses: libsdl-org/setup-sdl@main + with: + version: 2-latest + build-type: Release + cmake-arguments: "-DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' + -DCMAKE_VERBOSE_MAKEFILE=on" + + ### + # OpenAL + ### + - name: Cache OpenAL + id: cache-openal-soft + uses: actions/cache@v4 + with: + path: 'thirdparties/soft-oal/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-openal-soft-${{ env.openal-soft-branch }}-v1 + + # soft-oal setup + # Use GCC instead of Clang because of missing SSE intrinsics + # It also doesn't enable altivec support on PowerPC by default + - name: Checkout soft-oal + if: steps.cache-openal-soft.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'kcat/openal-soft' + path: 'thirdparties/soft-oal' + ref: '${{ env.openal-soft-branch }}' + + # soft-oal build + - name: Configure and install soft-oal + if: steps.cache-openal-soft.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/soft-oal + run: | + cmake -B ./build \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' \ + -DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \ + -DCMAKE_VERBOSE_MAKEFILE=on + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + + ### + # WolfSSL + ### +# FIXME: Figure out how to compile WolfSSL cross-architecture +# +# - name: Cache WolfSSL +# id: cache-wolfssl +# uses: actions/cache@v4 +# with: +# path: 'thirdparties/wolfssl_install' +# key: ${{ runner.os }}-${{ matrix.architecture.name }}-wolfssl-${{ env.wolfssl-version }}-v1 +# +# # WolfSSL setup +# - name: Checkout WolfSSL +# if: steps.cache-wolfssl.outputs.cache-hit != 'true' +# uses: actions/checkout@v4 +# with: +# repository: 'wolfssl/wolfssl' +# path: 'thirdparties/wolfssl' +# ref: '${{ env.wolfssl-version }}' +# +# # WolfSSL build +# - name: Configure and install wolfssl +# if: steps.cache-wolfssl.outputs.cache-hit != 'true' +# working-directory: ${{github.workspace}}/thirdparties/wolfssl +# run: | +# cmake -B ./build \ +# -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/wolfssl_install' \ +# -DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \ +# -DBUILD_SHARED_LIBS=OFF -DWOLFSSL_OPENSSLEXTRA=ON -DWOLFSSL_ASM=OFF -DWOLFSSL_EXAMPLES=OFF -DWOLFSSL_CURL=ON +# cmake --build ./build --config Release --parallel +# cmake --install ./build --config Release + + ### + # cURL + ### + - name: Cache cURL + id: cache-curl + uses: actions/cache@v4 + with: + path: 'thirdparties/curl/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-curl-${{ env.curl-version }}-v1 + + # cURL setup + - name: Checkout cURL + if: steps.cache-curl.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'curl/curl' + path: 'thirdparties/curl' + ref: 'curl-${{ env.curl-version }}' + + # cURL build + - name: Configure and install curl + if: steps.cache-curl.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/curl + run: | + cmake -B ./build \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/curl/install' \ + -DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \ + -DCURL_USE_LIBPSL=OFF \ + -DCURL_USE_WOLFSSL=OFF \ + -DCURL_USE_LIBSSH2=OFF \ + -DUSE_LIBIDN2=OFF \ + -DUSE_NGHTTP2=OFF \ + -DCURL_ENABLE_SSL=OFF \ + -DCURL_ZLIB="" \ + -DCURL_BROTLI="" \ + -DCURL_ZSTD="" \ + -DWolfSSL_ROOT='${{github.workspace}}/thirdparties/wolfssl_install' + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + + ### + # Project + ### + + - uses: actions/checkout@v4 + with: + path: 'source' + + - name: CMake Settings + run: | + echo "CMAKE_PARAM=--log-level=VERBOSE \ + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \ + -DCMAKE_VERBOSE_MAKEFILE=on \ + -DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \ + -DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal/install' \ + -DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/install/include/AL' \ + -DCURL_ROOT='${{github.workspace}}/thirdparties/curl/install' \ + -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \ + -DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'" >> $GITHUB_ENV + + - name: Configure CMake + working-directory: ${{github.workspace}} + run: | + cmake -B ./build ${{ env.CMAKE_PARAM }} ./source + + - name: Build + working-directory: ${{github.workspace}} + run: | + cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + + - name: Test + working-directory: ${{github.workspace}} + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: | + cd "${{github.workspace}}/build" + ctest -C ${{env.BUILD_TYPE}} + + - name: Install + working-directory: ${{github.workspace}} + # Install to the directory defined in CMAKE_INSTALL_PREFIX + run: | + cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + # Create hard-link and copy symbolic links + mkdir ${{github.workspace}}/package + cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.0.dylib '${{github.workspace}}/package/' + cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.1.dylib '${{github.workspace}}/package/' + cp -l ${{github.workspace}}/thirdparties/curl/install/lib*/libcurl.4.dylib '${{github.workspace}}/package/' + if [ -d ${{github.workspace}}/install/bin ]; then cp -r ${{github.workspace}}/install/bin/openmohaa/. '${{github.workspace}}/package'; fi + if [ -d ${{github.workspace}}/install/lib ]; then cp -r ${{github.workspace}}/install/lib/openmohaa/. '${{github.workspace}}/package'; fi + + ### + # Artifacts + ### + + - uses: actions/upload-artifact@v4 + with: + name: out-macos-${{matrix.architecture.name}} + if-no-files-found: error + path: + ${{github.workspace}}/package diff --git a/.github/workflows/shared-build-windows.yml b/.github/workflows/shared-build-windows.yml new file mode 100644 index 00000000..6aa11ad6 --- /dev/null +++ b/.github/workflows/shared-build-windows.yml @@ -0,0 +1,259 @@ +########################## +# +# Microsoft Windows +# Windows Server 2025 +# +########################## +name: Windows build workflow + +on: + workflow_call: + inputs: + environment: + required: true + type: string + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: RelWithDebInfo + RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }} + +jobs: + build: + strategy: + matrix: + architecture: [ + {name: 'x64', os: 'windows-2025', config: 'x64', toolset: 'x64', arch_option: 'VC-WIN64A' }, + {name: 'x86', os: 'windows-2025', config: 'Win32', toolset: 'x64_x86', arch_option: 'VC-WIN32' }, + {name: 'arm64', os: 'windows-11-arm', config: 'ARM64', toolset: 'x64_arm64', arch_option: 'VC-WIN64-ARM' } + ] + + name: "Building for platform windows-${{matrix.architecture.name}}" + runs-on: ${{ matrix.architecture.os }} + environment: ${{ inputs.environment }} + env: + flexbison-branch: 'v2.5.25' + wolfssl-version: 'v5.7.6-stable' + curl-version: '8_12_1' + openal-soft-branch: '1.24.3' + + steps: + ### + # Packages + ### + + - name: Cache Flex/Bison + id: cache-flexbison + uses: actions/cache@v4 + with: + path: 'thirdparties/winflexbison-install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-flexbison-${{ env.flexbison-branch }}-v1 + + - name: Install Flex/Bison + if: steps.cache-flexbison.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}} + run: | + mkdir thirdparties && cd thirdparties + git clone --depth 1 --single-branch --branch ${{ env.flexbison-branch }} https://github.com/lexxmark/winflexbison.git + cmake -B winflexbison-build -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/winflexbison-install' ./winflexbison + cmake --build winflexbison-build --config Release --parallel + cmake --install winflexbison-build --config Release + + - name: Settings + working-directory: ${{github.workspace}} + run: | + echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $env:GITHUB_ENV + echo "CC=cl.exe" >> $env:GITHUB_ENV + echo "CXX=cl.exe" >> $env:GITHUB_ENV + pushd "$($env:PROGRAMFILES)\Microsoft Visual Studio\*\*\VC\Auxiliary\Build" + cmd /c "vcvarsall.bat ${{ matrix.architecture.toolset }} & set" | ForEach-Object { + if ($_ -match "=") { + # Split into key=value + $var = $_.split("=", 2); + echo "$($var[0])=$($var[1])" >> $env:GITHUB_ENV + } + } + popd + + - name: Cache Required Packages + id: cache-required-packages + uses: actions/cache@v4 + with: + path: 'C:\Packages' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-required-packages-v1 + + - name: Install required packages + if: steps.cache-required-packages.outputs.cache-hit != 'true' + run: | + $DownloadPath="$($env:USERPROFILE)\Downloads" + if ("${{ matrix.architecture.config }}" -ieq "ARM64") { + Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-winarm64.zip" -OutFile "$DownloadPath\ninja-win.zip" + } else { + Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-win.zip" -OutFile "$DownloadPath\ninja-win.zip" + } + Expand-Archive -Path "$DownloadPath\ninja-win.zip" -DestinationPath "C:\Packages\ninja" + Invoke-WebRequest "https://download.qt.io/official_releases/jom/jom.zip" -OutFile "$DownloadPath\jom.zip" + Expand-Archive -Path "$DownloadPath\jom.zip" -DestinationPath "C:\Packages\jom" + + - name: Setup required packages path + run: | + $env:PATH += ";C:\Packages\ninja;C:\Packages\jom;" + echo "PATH=$($env:PATH)" >> $env:GITHUB_ENV + + ### + # SDL + ### + + # Setup SDL + - name: Set up SDL + id: sdl + uses: libsdl-org/setup-sdl@main + with: + version: 2-latest + build-type: Release + cmake-arguments: "" + + ### + # OpenAL + ### + - name: Cache OpenAL + id: cache-openal-soft + uses: actions/cache@v4 + with: + path: 'thirdparties/soft-oal/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-openal-soft-${{ env.openal-soft-branch }}-v1 + + # soft-oal setup + - name: Checkout soft-oal + if: steps.cache-openal-soft.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'kcat/openal-soft' + path: 'thirdparties/soft-oal' + ref: '${{ env.openal-soft-branch }}' + + # soft-oal build + # Statically link the CRT runtime into OAL as a workaround to prevent crashes + - name: Configure and install soft-oal + if: steps.cache-openal-soft.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/soft-oal + run: | + cmake -B ./build ` + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' ` + -DALSOFT_BUILD_ROUTER=OFF ` + -DALSOFT_REQUIRE_WINMM=ON ` + -DALSOFT_REQUIRE_DSOUND=ON ` + -DALSOFT_REQUIRE_WASAPI=ON ` + -DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" ` + -DCMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" ` + -DCMAKE_C_FLAGS_MINSIZEREL="/MT /O2 /Ob2 /DNDEBUG" ` + -DCMAKE_CXX_FLAGS_MINSIZEREL="/MT /O1 /Ob1 /DNDEBUG" ` + -DCMAKE_C_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG" ` + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG" + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + # Unfortunately soft-oal produces a binary called OpenAL32 even in 64-bit + if (("x64", "ARM64") -icontains "${{ matrix.architecture.config }}") { Rename-Item -Path '.\install\bin\OpenAL32.dll' -NewName 'OpenAL64.dll' } + + ### + # cURL + # + # Uses Schannel as SSL backend, native CAs are used + ### + - name: Cache cURL + id: cache-curl + uses: actions/cache@v4 + with: + path: 'thirdparties/curl/install' + key: ${{ runner.os }}-${{ matrix.architecture.name }}-curl-${{ env.curl-version }}-v1 + + # cURL setup + - name: Checkout cURL + if: steps.cache-curl.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + repository: 'curl/curl' + path: 'thirdparties/curl' + ref: 'curl-${{ env.curl-version }}' + + # cURL build + - name: Configure and install curl + if: steps.cache-curl.outputs.cache-hit != 'true' + working-directory: ${{github.workspace}}/thirdparties/curl + run: | + cmake -B ./build ` + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/curl/install' ` + -DCURL_USE_LIBPSL=OFF ` + -DCURL_USE_SCHANNEL=ON + cmake --build ./build --config Release --parallel + cmake --install ./build --config Release + + ### + # Project + ### + + - uses: actions/checkout@v4 + with: + path: 'source' + + - name: CMake Settings + run: | + echo "CMAKE_PARAM= ` + --log-level=VERBOSE ` + -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' ` + -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} ` + -DBISON_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_bison.exe' ` + -DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' ` + -DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/install/include' ` + -DCURL_ROOT='${{github.workspace}}/thirdparties/curl/install' ` + -DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe' ` + -DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV + + - name: Configure CMake + working-directory: ${{github.workspace}} + run: | + cmake -B ./build ${{ env.CMAKE_PARAM }} ./source + + - name: Build + working-directory: ${{github.workspace}} + run: | + cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel + + - name: Test + working-directory: ${{github.workspace}} + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: | + cd "${{github.workspace}}/build" + ctest -C ${{env.BUILD_TYPE}} + + - name: Install + working-directory: ${{github.workspace}} + # Install to the directory defined in CMAKE_INSTALL_PREFIX + run: | + cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + New-Item -ItemType Directory '${{github.workspace}}/package' + Copy-Item '${{steps.sdl.outputs.prefix}}/bin/*.dll' -Destination '${{github.workspace}}/package' + Copy-Item '${{github.workspace}}/thirdparties/soft-oal/install/bin/*.dll' -Destination '${{github.workspace}}/package' + Copy-Item '${{github.workspace}}/thirdparties/curl/install/bin/*.dll' -Destination '${{github.workspace}}/package' + if (Test-Path ${{github.workspace}}/install/bin) { Copy-Item '${{github.workspace}}/install/bin/*' -Include '*.dll','*.exe','*.pdb' -Destination '${{github.workspace}}/package' } + if (Test-Path ${{github.workspace}}/install/lib) { Copy-Item '${{github.workspace}}/install/lib/*' -Include '*.dll','*.exe','*.pdb' -Destination '${{github.workspace}}/package' } + + ### + # Artifact + ### + + - uses: actions/upload-artifact@v4 + with: + name: out-windows-${{matrix.architecture.name}} + if-no-files-found: error + path: | + ${{github.workspace}}/package + !${{github.workspace}}/package/**/*.pdb + + - uses: actions/upload-artifact@v4 + with: + name: out-windows-${{matrix.architecture.name}}-pdb + if-no-files-found: error + path: | + ${{github.workspace}}/package \ No newline at end of file diff --git a/.github/workflows/shared-build.yml b/.github/workflows/shared-build.yml new file mode 100644 index 00000000..3bac5e21 --- /dev/null +++ b/.github/workflows/shared-build.yml @@ -0,0 +1,24 @@ +name: Shared build workflow + +on: + workflow_call: + inputs: + environment: + required: true + type: string + +jobs: + build-platform-linux: + uses: ./.github/workflows/shared-build-linux.yml + with: + environment: ${{inputs.environment}} + + build-platform-windows: + uses: ./.github/workflows/shared-build-windows.yml + with: + environment: ${{inputs.environment}} + + build-platform-macos: + uses: ./.github/workflows/shared-build-macos.yml + with: + environment: ${{inputs.environment}} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/tags-publish-release.yml similarity index 59% rename from .github/workflows/publish-release.yml rename to .github/workflows/tags-publish-release.yml index 1ff4bcd0..a1d44b74 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/tags-publish-release.yml @@ -6,7 +6,7 @@ on: - "v*.*.*" env: - RELEASE_TYPE: ${{ vars.RELEASE_TYPE || 'test' }} + RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }} RELEASE_IS_PRERELEASE: ${{ vars.RELEASE_IS_PRELEASE }} permissions: @@ -14,7 +14,9 @@ permissions: jobs: build-all: - uses: ./.github/workflows/build-cmake.yml + uses: ./.github/workflows/shared-build.yml + with: + environment: "release" deploy_all: strategy: @@ -25,36 +27,42 @@ jobs: target_os: [ 'linux-amd64', 'linux-i686', - 'linux-aarch64', + 'linux-arm64', 'linux-armhf', + 'linux-powerpc', + 'linux-ppc64', + 'linux-ppc64el', 'windows-x64', - 'windows-x86', 'windows-x64-pdb', + 'windows-x86', 'windows-x86-pdb', 'windows-arm64', - 'windows-arm64-pdb' + 'windows-arm64-pdb', + #'macos-x86_64', + #'macos-arm64', + 'macos-multiarch(arm64-x86_64)', ] - runs-on: ubuntu-22.04 - environment: release + runs-on: ubuntu-24.04 + environment: "release" needs: [build-all] env: RELEASE_NAME: ${{ github.event.repository.name }}-${{github.ref_name}}-${{matrix.target_os}} steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: 'out-${{matrix.target_os}}' path: ${{github.workspace}}/${{matrix.target_os}} - name: Zip - working-directory: ${{github.workspace}}/${{matrix.target_os}} - run: zip -r ../${{ env.RELEASE_NAME }}.zip ./ + working-directory: '${{github.workspace}}/${{matrix.target_os}}' + run: zip -r "../${{ env.RELEASE_NAME }}.zip" ./ - name: Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: - name: '${{github.ref_name}}-${{env.RELEASE_TYPE}}' + name: '${{github.ref_name}}-${{env.RELEASE_STAGE}}' prerelease: ${{env.RELEASE_IS_PRERELEASE}} files: ${{github.workspace}}/${{ env.RELEASE_NAME }}.zip diff --git a/.gitignore b/.gitignore index d5cccbae..642e22a5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ Makefile.local *.swp *tags *~ +/.vscode/ +/baseq3 # OS X #################### @@ -44,5 +46,6 @@ profile *.suo .vs -out code_unfinished/* +thirdparties/ +code/parser/generated/* diff --git a/CMakeLists.txt b/CMakeLists.txt index c0b248ae..ba983bc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,69 +1,164 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(openmohaa) -include(TargetArch.cmake) +include(misc/cmake/TargetArch.cmake) target_architecture(TARGET_ARCH) +list(LENGTH TARGET_ARCH TARGET_ARCH_COUNT) +set(USE_INTERNAL_LIBS ON) +if(USE_SYSTEM_LIBS) + set(USE_INTERNAL_LIBS OFF) +endif() + +option(USE_INTERNAL_JPEG "If set, use bundled libjpeg." ${USE_INTERNAL_LIBS}) +option(USE_INTERNAL_MAD "If set, use bundled libmad." ${USE_INTERNAL_LIBS}) +option(USE_INTERNAL_ZLIB "If set, use bundled zlib." ${USE_INTERNAL_LIBS}) +option(USE_RENDERER_DLOPEN "Whether to compile the renderer as separate pluggable modules" OFF) +option(TARGET_LOCAL_SYSTEM "Indicate that the project will be compiled and installed for the local system" OFF) if(TARGET_GAME_TYPE) message(SEND_ERROR "TARGET_GAME_TYPE is now unsupported, it is now done at runtime.") endif() - -set(TARGET_BASE_GAME "main") +set(TARGET_BASE_GAME "./") set(CMAKE_DEBUG_POSTFIX "-dbg") +# +# Microsoft compiler specific parameters +# if(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # Treat no return type as error + add_compile_options(/we4715) +endif() + +# +# Clang and GCC specific parameters +# +if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options(-Wno-comment) + # Treat no return type as error + add_compile_options(-Werror=return-type) +endif() + +# +# Clang specific parameters +# +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # Ignore warnings for code like 'assert("Assert string")' add_compile_options(-Wno-pointer-bool-conversion) endif() +# +# GCC specific parameters +# +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # Add this option on gcc to prevent functions from having the STB_GNU_UNIQUE binding + # Otherwise, it would prevent libraries from being unloaded + # which will cause undefined behavior and crashes due to memory corruption + add_compile_options(-fno-gnu-unique) +endif() + if(DEBUG_MEMORY) add_definitions(-D_DEBUG_MEM) endif() -IF("${TARGET_ARCH}" STREQUAL "i386") +if("${TARGET_ARCH}" STREQUAL "i386") set(TARGET_ARCH_SUFFIX "x86") -ELSE() +else() set(TARGET_ARCH_SUFFIX ${TARGET_ARCH}) -ENDIF() +endif() -message(STATUS "Architecture detected: ${TARGET_ARCH}, suffix set to ${TARGET_ARCH_SUFFIX}.") +message(STATUS "Architecture detected: ${TARGET_ARCH}") -IF(WIN32) +if(TARGET_LOCAL_SYSTEM) + add_definitions(-DTARGET_LOCAL_SYSTEM) + # As it targets the local system, no need to know about the architecture used + set(TARGET_BIN_SUFFIX "") + message(STATUS "Binary suffix will not be used as the local system is the target") +elseif(${TARGET_ARCH_COUNT} GREATER 1) + add_definitions(-DTARGET_MULTIPLE_ARCHITECTURES) + set(TARGET_BIN_SUFFIX ".multiarch") + message(STATUS "Multiple architectures were specified, suffix set to 'multiarch'.") +else() + set(TARGET_BIN_SUFFIX ".${TARGET_ARCH}") + message(STATUS "Binary suffix set to '${TARGET_ARCH_SUFFIX}'.") +endif() + +if(WIN32) set(TARGET_PLATFORM_PREFIX "") message(STATUS "Using Win32 naming convention") -ELSEIF(UNIX) +elseif(UNIX) set(TARGET_PLATFORM_PREFIX "") message(STATUS "Using Unix naming convention") -ELSE() +else() set(TARGET_PLATFORM_PREFIX "") -ENDIF() +endif() -IF(CMAKE_BUILD_TYPE MATCHES Debug) - add_definitions(-D_DEBUG) +if(CMAKE_BUILD_TYPE MATCHES Debug) + add_compile_definitions(_DEBUG) + # NOTE: The following may mess up function importation #if(UNIX) # # Enable all exports so all functions name can be seen during executable crash # set(CMAKE_ENABLE_EXPORTS ON) # message(STATUS "Enabling exports on Unix for backtrace") #endif() -ENDIF() +else() + # Non-debug builds + add_compile_definitions(NDEBUG) +endif() +if(APPLE) + # macOS doesn't search the executable path by default + # so, locate libraries like SDL in the executable path + set(CMAKE_INSTALL_RPATH "@executable_path") + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + + if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU") + # Set the visibility to hidden on macOS to prevent shared libraries from + # using functions in the executable + # it's ok to hide them because the backtrace on macOS will still print the name of the functions + add_compile_options(-fvisibility=hidden) + endif() +endif() + +# +# Setup the installation directory +# +if(WIN32) + # By default, both DLLs and EXEs are in the same directory + set(CMAKE_DEFAULT_INSTALL_RUNTIME_DIR bin) + set(BIN_INSTALL_SUBDIR ".") + set(LIB_INSTALL_SUBDIR ".") +else() + # Unix + set(CMAKE_DEFAULT_INSTALL_RUNTIME_DIR lib${CMAKE_LIB_SUFFIX}) + set(BIN_INSTALL_SUBDIR ${CMAKE_PROJECT_NAME}) + set(LIB_INSTALL_SUBDIR ${CMAKE_PROJECT_NAME}) +endif() + +# By default, put both binaries and shared libraries in the same directory +# the game uses internal shared libraries that must be in the same folder as the binaries +set(CMAKE_INSTALL_BINDIR ${CMAKE_DEFAULT_INSTALL_RUNTIME_DIR} CACHE PATH "Binary dir") +set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Library dir") +include(GNUInstallDirs) + +# # Common stuff - +# add_subdirectory("code/qcommon") add_subdirectory("code/gamespy") +# # Application - +# add_subdirectory("code/sys") +## ## Server app +## add_subdirectory("code/server") add_executable(omohaaded "code/null/null_client.c" "code/null/null_input.c" "code/null/null_snddma.c") @@ -73,57 +168,105 @@ target_compile_features(omohaaded PUBLIC c_variadic_macros) target_link_libraries(omohaaded PRIVATE omohserver) target_link_libraries(omohaaded PRIVATE syslib) target_link_libraries(omohaaded PRIVATE qcommon qcommon_standalone) -# Gamespy dependency + +# Add the gamespy dependency target_include_directories(omohaaded PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server") -set_target_properties(omohaaded PROPERTIES OUTPUT_NAME "omohaaded${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}") +set_target_properties(omohaaded PROPERTIES OUTPUT_NAME "omohaaded${TARGET_BIN_SUFFIX}") set_target_properties(omohaaded PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) +INSTALL(TARGETS omohaaded DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR}) + if (MSVC) target_link_options(omohaaded PRIVATE "/MANIFEST:NO") - INSTALL(FILES $ DESTINATION "./" OPTIONAL) + INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR} OPTIONAL) endif() -INSTALL(TARGETS omohaaded DESTINATION "./") - if (NOT BUILD_NO_CLIENT) + ## ## Client app + ## + option(NO_MODERN_DMA "Use older sound-system" FALSE) - add_subdirectory("code/renderer") - add_subdirectory("code/sdl") add_subdirectory("code/client") - - #include("code/renderergl2/glsl/shaders.cmake") - #file(GLOB_RECURSE SOURCES_RENDERER "code/sdl/*.c" "code/renderercommon/*.c" "code/renderergl2/*.c" "code/renderergl2/*.cpp") - #list(FILTER SOURCES_RENDERER EXCLUDE REGEX "code/renderergl2/tr_subs.c") - #list(FILTER SOURCES_RENDERER EXCLUDE REGEX "code/renderergl2/tr_model.c") + add_subdirectory("code/renderercommon") + add_subdirectory("code/sdl") add_executable(openmohaa "misc/dummy.c") target_link_libraries(openmohaa PRIVATE syslib) target_link_libraries(openmohaa PRIVATE omohserver) target_link_libraries(openmohaa PRIVATE omohclient) - target_link_libraries(openmohaa PRIVATE omohrenderer omohsdl) + target_link_libraries(openmohaa PRIVATE omohrenderer) target_link_libraries(openmohaa PRIVATE qcommon qcommon_standalone) - ### Gamespy dependency - target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib" "code/jpeg-8c") - set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}") + # Add the gamespy dependency + target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib") + set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BIN_SUFFIX}") set_target_properties(openmohaa PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) - target_link_libraries(openmohaa PRIVATE jpeg8) - if (USE_OPENAL) - # Try to use OpenAL - find_package(OpenAL) - if (OPENAL_FOUND) - target_compile_definitions(openmohaa PRIVATE USE_OPENAL=1) - target_include_directories(openmohaa PRIVATE ${OPENAL_INCLUDE_DIR}) - target_link_libraries(openmohaa PRIVATE ${OPENAL_LIBRARY}) - endif() + if(USE_INTERNAL_JPEG) + target_include_directories(openmohaa PUBLIC "code/jpeg-8c") + target_link_libraries(openmohaa PRIVATE jpeg8) + else() + find_package(JPEG REQUIRED) + target_include_directories(openmohaa PUBLIC ${JPEG_INCLUDE_DIRS}) + target_link_libraries(openmohaa PRIVATE ${JPEG_LIBRARIES}) endif() + INSTALL(TARGETS openmohaa DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR}) + if (MSVC) target_link_options(openmohaa PRIVATE "/MANIFEST:NO") - INSTALL(FILES $ DESTINATION "./" OPTIONAL) + INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR} OPTIONAL) endif() - INSTALL(TARGETS openmohaa DESTINATION "./") + if(UNIX AND NOT APPLE) + # + # Desktop entries installation on Unix + # + set(TARGET_ARCH ${TARGET_BIN_SUFFIX}) + + # Configure the .desktop entries with the arch suffix + configure_file( + misc/linux/org.openmoh.openmohaa.desktop.in + ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaa.desktop + @ONLY + ) + configure_file( + misc/linux/org.openmoh.openmohaab.desktop.in + ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaab.desktop + @ONLY + ) + configure_file( + misc/linux/org.openmoh.openmohaas.desktop.in + ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaas.desktop + @ONLY + ) + + # Install .desktop entries + install(FILES ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaa.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) + install(FILES ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaab.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) + install(FILES ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaas.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) + + install(FILES misc/linux/org.openmoh.openmohaa.metainfo.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo) + + install(FILES misc/openmohaa.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/symbolic/apps/ RENAME org.openmoh.openmohaa.svg) + endif() +endif() + +# +# Launcher +# +add_subdirectory(code/Launcher) + +# +# uninstall target +# +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) endif() diff --git a/README.md b/README.md index d80136c2..9d221b94 100644 --- a/README.md +++ b/README.md @@ -1,130 +1,63 @@ # OpenMoHAA -![Build](https://github.com/openmoh/openmohaa/actions/workflows/build-cmake.yml/badge.svg?branch=main) [![Release](https://img.shields.io/github/v/release/openmoh/openmohaa)](https://github.com/openmoh/openmohaa/releases) [![Downloads](https://img.shields.io/github/downloads/openmoh/openmohaa/total)](https://github.com/openmoh/openmohaa/releases) +[![Build](https://github.com/openmoh/openmohaa/actions/workflows/branches-build.yml/badge.svg?branch=main)](https://github.com/openmoh/openmohaa/actions/workflows/branches-build.yml) [![Release](https://img.shields.io/github/v/release/openmoh/openmohaa)](https://github.com/openmoh/openmohaa/releases) [![Downloads](https://img.shields.io/github/downloads/openmoh/openmohaa/total)](https://github.com/openmoh/openmohaa/releases) ![License](https://img.shields.io/github/license/openmoh/openmohaa) ![Commits](https://img.shields.io/github/commit-activity/t/openmoh/openmohaa) ![Discord](https://img.shields.io/discord/596049712579215361?logo=discord&logoColor=white&color=5865F2) +![logo](misc/openmohaa-text-sm.png) -``` - / _ \ _ __ ___ _ __ | \/ |/ _ \| | | | / \ / \ - | | | | '_ \ / _ \ '_ \| |\/| | | | | |_| | / _ \ / _ \ - | |_| | |_) | __/ | | | | | | |_| | _ |/ ___ \ / ___ \ - \___/| .__/ \___|_| |_|_| |_|\___/|_| |_/_/ \_\/_/ \_\ - |_| -``` +## Intro -## Current State +The main goal of OpenMoHAA is to ensure the future and continuity of **Medal of Honor: Allied Assault** (including Spearhead and Breakthrough expansions) on all platforms/architectures by providing new patches/features. Thanks to the ioquake3 project and the F.A.K.K SDK, OpenMoHAA has already reached more than half of its goal: an open-source version of MoH:AA (based on version 2.40) that is fully compatible with both the original game and expansions, in terms of network protocol, assets, and scripts. OpenMoHAA is compatible with both MOH:AA servers and clients (Spearhead and Breakthrough included). -OpenMoHAA is still under development. The single-player campaign is not yet functional due to AI not being fully implemented, and due to the script engine having a few issues. But the `training` map can be played from start to end. The current focus is on multiplayer. +## Getting started -## Running +- [Downloading and installing OpenMoHAA](docs/getting_started_installation.md) +- [Running OpenMoHAA and using expansion assets](docs/getting_started_running.md) +- [Game configuration](docs/configuration.md) -Backup existing mohaa files, **cgamex86.dll** and **gamex86.dll** (set their extension to **.bak**) +If you encounter any issues, please refer to the [FAQ](docs/faq.md) for possible solutions. -a) extract archive to your MOHAA installation directory. +## Current state --or- +### Single-player -b) Copy all pak*.pk3 files and the sound/ directory from your **MOHAA/main** directory into openmohaa's 'main' directory. +The entire single-player campaign should work (Allied Assault, Spearhead and Breakthrough). If you encounter any bug, please create a new [GitHub issue](https://github.com/openmoh/openmohaa/issues) describing them. -If you have problems running the game : +### Multiplayer -You may need to install Microsoft Visual C++ 2015/2017/2019/2022 Redistributable from +The Multiplayer part is almost fully stable, all game modes including `Tug-of-War` from Medal of Honor: Spearhead, and `Liberation` from Medal of Honor: Breakthrough are implemented and are working as intended. Mods like `Freeze-Tag` are working as well. -https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170 +OpenMoHAA can be used to [host](docs/getting_started_installation.md#server) a mohaa/mohaas/mohaab server and players can use OpenMoHAA to [play](docs/getting_started_installation.md#client) on any server. If some bugs/strange behavior occurs, the best way to report them is by [creating a new issue](https://github.com/openmoh/openmohaa/issues) on the [OpenMoHAA GitHub](https://github.com/openmoh/openmohaa) project with the steps to reproduce (with eventually the problematic mods). -You can now start a local OpenMOHAA server or play on a server. +One of the big multiplayer features are bots. They were introduced for testing and for entertainment purposes so players can have fun alone. See [Configuring bots](docs/configuration/server.md#bots) in the dedicated server configuration documentation to set them up. -**Medal of Honor: Allied Assault Spearhead** and **Medal of Honor: Allied Assault Breakthrough** are supported in OpenMoHAA using the `com_target_game` variable. To play an expansion, append the following command-line arguments to the executable: +## Features -- `+set com_target_game 1` for Spearhead (mohaas/mohta) -- `+set com_target_game 2` for Breakthrough (mohaab/mohtt) +- [List of new features](docs/features.md) +- [Scripting](docs/scripting.md) -On Windows, you can create a shortcut to OpenMoHAA with these command-line arguments. -The default value of `com_target_game` is 0 for the base game. +## Reporting issues -With `com_target_game`, OpenMoHAA will support the network protocol accordingly +If you encounter a bug, report it by creating a new [issue](https://github.com/openmoh/openmohaa/issues). Make sure to select the `Bug report` template and fill in the appropriate fields. -### Playing with bots - -OpenMoHAA has a basic bot system that emulates real players. The maximum number of bots is defined by the `sv_maxbots` variable, and the number of initial bots is defined by the `sv_numbots` variable. Bots can also be added or removed using the `addbot` and `removebot` commands. - -This feature is a great way to test the gameplay and mods. - -## Builds - -### Server - -The server version can be built successfully, but some features are not functional. For example, the Actor and Vehicle systems are almost fully implemented, but they are not yet stable. This means that they may not work as expected and could cause crashes. - -Overall, the server and the fgame components are almost fully implemented, but they may not be completely stable. There could be some minor bugs (and rare crashes), but the game should be playable. - -### Client - -The client version of OpenMoHAA has undergone partial implementation, with the cgame module being nearly completed. Credits to the SDK of **Heavy Metal: F.A.K.K. 2** both the cgame and fgame modules. - -The current operational status for each component is as follow: - -| Component | Full | Almost | Half | Early | Bad | Not working | Comment | -|-------------------------|------|--------|------|-------|-----|-------------|-------------------------------------------------------------------| -| Audio | | | | | x | | Very basic implementation from Quake III | -| CG Module | | x | | | | | Missing FX, Marks and decals | -| Client | | x | | | | | Missing GameSpy, server list, binds, map picker, ... | -| Collision | x | | | | | | | -| Model/TIKI/Skeletor | x | | | | | | | -| Renderer | | x | | | | | Missing ghost, marks, sphere lights, sky portal, sun flare, swipe | -| Server | | x | | | | | Probably a few bugs remaining | -| Server module (fgame) | | x | | | | | Actor, vehicle, and few gameplay bugs | -| UI | | | x | | | | Has core features only (menu, widgets, console, hud, urc loading) | +If you need help or have a problem, you can head over to the [discussions](https://github.com/openmoh/openmohaa/discussions) or join the OpenMoHAA Discord server (the link is at the bottom of this README). ## Compiling -OpenMoHAA supports any architecture, thanks to the CMake build system and cross-platform code/libraries. While the most common little-Endian architectures (arm, aarch64, x86, x86_64) have been tested and confirmed to work, big-Endian architectures should be supported as well; however, they remain untested. - -The following tools are required for all platforms: -- CMake >= 3.5 -- Flex and Bison -- A C++11 compiler is also required. - -The installation directory can be set to the MOHAA directory. - -By default, the build will produce both the client and dedicated server versions. The client build can be excluded by appending `-DBUILD_NO_CLIENT=1` to the CMake command-line arguments. Using this parameter will result in only the server portion being built. - -### Linux - -These are the tools required on Linux : -- Clang >= 3.3 or GCC >= 4.8.1 - -**clang-3.5** and **gcc-4.8.5** should work (tested on Ubuntu 16.04). Use the latest possible version of those compilers. - -SDL2 library is required (libsdl2-dev). - -1 line install command with latest clang version : `sudo apt-get install -y ninja-build cmake make clang-15 lld-15 flex bison libsdl2-dev` - -Example with **CMake**, **clang-15** and **ninja-build** installed: -```sh -mkdir .cmake && cd .cmake -cmake -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -G Ninja -``` - -### Windows - -Visual Studio (2019 or 2022) is generally preferred. - -Flex and Bison can be downloaded from here: https://github.com/lexxmark/winflexbison/releases/tag/v2.5.25 - -Append `-DFLEX_EXECUTABLE=...\win_flex.exe -DBISON_EXECUTABLE=...\win_bison.exe` to the CMake command-line to use the package from the link above. +- See [Compiling OpenMoHAA](docs/compiling.md) ## Screenshots -| | | -|-------------------------------------------------------------------------------|----------------------------------------------------------------------| -| ![](docs/images/opmtt-x86_64_0.56.0_1.png "Playing on a Breakthrough server") | ![](docs/images/opmtt-x86_64_0.56.0_2.png) | -| ![](docs/images/opmtt-x86_64_0.56.0_3.png) | ![](docs/images/opm-arm_53_tt_1.png "OpenMoHAA on Raspberry Pi 4 B") | -| ![](docs/images/opm-x86_64_0.58.0_1.png "Playing Freeze-Tag mode with bots") | ![](docs/images/opm-x86_64_0.58.0_2.png "Single-Player training") | +| | | +|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------| +| ![](docs/images/v0.60.0-x86_64/mohdm1_1.png) | ![](docs/images/v0.60.0-x86_64/training_1.png) | +| ![](docs/images/v0.60.0-x86_64/flughafen_1.png) | ![](docs/images/v0.60.0-x86_64/flughafen_2.png) | +| ![](docs/images/v0.60.0-x86_64/mohdm2_1.png "Playing Freeze-Tag mode with bots") | ![](docs/images/v0.60.0-x86_64/training_3.png "Single-Player training") | +*More screenshots [here](docs/images)* ## Third party diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in new file mode 100644 index 00000000..7db7869a --- /dev/null +++ b/cmake_uninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") +endif() + +file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + execute_process( + COMMAND "@CMAKE_COMMAND@" -E remove "$ENV{DESTDIR}${file}" + OUTPUT_VARIABLE rm_out + RESULT_VARIABLE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif() + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif() +endforeach() diff --git a/code/AL/al.h b/code/AL/al.h index 413b3833..a4e3ad51 100644 --- a/code/AL/al.h +++ b/code/AL/al.h @@ -1,8 +1,40 @@ #ifndef AL_AL_H #define AL_AL_H -#if defined(__cplusplus) +/* NOLINTBEGIN */ +#ifdef __cplusplus extern "C" { + +#ifdef _MSVC_LANG +#define AL_CPLUSPLUS _MSVC_LANG +#else +#define AL_CPLUSPLUS __cplusplus +#endif + +#ifndef AL_DISABLE_NOEXCEPT +#if AL_CPLUSPLUS >= 201103L +#define AL_API_NOEXCEPT noexcept +#else +#define AL_API_NOEXCEPT +#endif +#if AL_CPLUSPLUS >= 201703L +#define AL_API_NOEXCEPT17 noexcept +#else +#define AL_API_NOEXCEPT17 +#endif + +#else /* AL_DISABLE_NOEXCEPT */ + +#define AL_API_NOEXCEPT +#define AL_API_NOEXCEPT17 +#endif + +#undef AL_CPLUSPLUS + +#else /* __cplusplus */ + +#define AL_API_NOEXCEPT +#define AL_API_NOEXCEPT17 #endif #ifndef AL_API @@ -15,14 +47,14 @@ extern "C" { #endif #endif -#if defined(_WIN32) +#ifdef _WIN32 #define AL_APIENTRY __cdecl #else #define AL_APIENTRY #endif -/** Deprecated macro. */ +/* Deprecated macros. */ #define OPENAL #define ALAPI AL_API #define ALAPIENTRY AL_APIENTRY @@ -30,7 +62,7 @@ extern "C" { #define AL_ILLEGAL_ENUM AL_INVALID_ENUM #define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION -/** Supported AL version. */ +/* Supported AL versions. */ #define AL_VERSION_1_0 #define AL_VERSION_1_1 @@ -40,43 +72,43 @@ typedef char ALboolean; /** character */ typedef char ALchar; -/** signed 8-bit 2's complement integer */ +/** signed 8-bit integer */ typedef signed char ALbyte; /** unsigned 8-bit integer */ typedef unsigned char ALubyte; -/** signed 16-bit 2's complement integer */ +/** signed 16-bit integer */ typedef short ALshort; /** unsigned 16-bit integer */ typedef unsigned short ALushort; -/** signed 32-bit 2's complement integer */ +/** signed 32-bit integer */ typedef int ALint; /** unsigned 32-bit integer */ typedef unsigned int ALuint; -/** non-negative 32-bit binary integer size */ +/** non-negative 32-bit integer size */ typedef int ALsizei; -/** enumerated 32-bit value */ +/** 32-bit enumeration value */ typedef int ALenum; -/** 32-bit IEEE754 floating-point */ +/** 32-bit IEEE-754 floating-point */ typedef float ALfloat; -/** 64-bit IEEE754 floating-point */ +/** 64-bit IEEE-754 floating-point */ typedef double ALdouble; -/** void type (for opaque pointers only) */ +/** void type (opaque pointers only) */ typedef void ALvoid; -/* Enumerant values begin at column 50. No tabs. */ +/* Enumeration values begin at column 50. Do not use tabs. */ -/** "no distance model" or "no buffer" */ +/** No distance model or no buffer */ #define AL_NONE 0 /** Boolean False. */ @@ -89,10 +121,10 @@ typedef void ALvoid; /** * Relative source. * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] + * Range: [AL_FALSE, AL_TRUE] * Default: AL_FALSE * - * Specifies if the Source has relative coordinates. + * Specifies if the source uses relative coordinates. */ #define AL_SOURCE_RELATIVE 0x202 @@ -103,7 +135,8 @@ typedef void ALvoid; * Range: [0 - 360] * Default: 360 * - * The angle covered by the inner cone, where the source will not attenuate. + * The angle covered by the inner cone, the area within which the source will + * not be attenuated by direction. */ #define AL_CONE_INNER_ANGLE 0x1001 @@ -112,8 +145,8 @@ typedef void ALvoid; * Range: [0 - 360] * Default: 360 * - * The angle covered by the outer cone, where the source will be fully - * attenuated. + * The angle covered by the outer cone, the area outside of which the source + * will be fully attenuated by direction. */ #define AL_CONE_OUTER_ANGLE 0x1002 @@ -123,7 +156,7 @@ typedef void ALvoid; * Range: [0.5 - 2.0] * Default: 1.0 * - * A multiplier for the frequency (sample rate) of the source's buffer. + * A multiplier for the sample rate of the source's buffer. */ #define AL_PITCH 0x1003 @@ -134,12 +167,12 @@ typedef void ALvoid; * * The source or listener location in three dimensional space. * - * OpenAL, like OpenGL, uses a right handed coordinate system, where in a - * frontal default view X (thumb) points right, Y points up (index finger), and - * Z points towards the viewer/camera (middle finger). + * OpenAL uses a right handed coordinate system, like OpenGL, where with a + * default view, X points right (thumb), Y points up (index finger), and Z + * points towards the viewer/camera (middle finger). * - * To switch from a left handed coordinate system, flip the sign on the Z - * coordinate. + * To change from or to a left handed coordinate system, negate the Z + * component. */ #define AL_POSITION 0x1004 @@ -148,8 +181,11 @@ typedef void ALvoid; * Type: ALfloat[3], ALint[3] * Default: {0, 0, 0} * - * Specifies the current direction in local space. - * A zero-length vector specifies an omni-directional source (cone is ignored). + * Specifies the current direction in local space. A zero-length vector + * specifies an omni-directional source (cone is ignored). + * + * To change from or to a left handed coordinate system, negate the Z + * component. */ #define AL_DIRECTION 0x1005 @@ -158,26 +194,30 @@ typedef void ALvoid; * Type: ALfloat[3], ALint[3] * Default: {0, 0, 0} * - * Specifies the current velocity in local space. + * Specifies the current velocity, relative to the position. + * + * To change from or to a left handed coordinate system, negate the Z + * component. */ #define AL_VELOCITY 0x1006 /** * Source looping. * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] + * Range: [AL_FALSE, AL_TRUE] * Default: AL_FALSE * - * Specifies whether source is looping. + * Specifies whether source playback loops. */ #define AL_LOOPING 0x1007 /** * Source buffer. - * Type: ALuint - * Range: any valid Buffer. + * Type: ALuint + * Range: any valid Buffer ID + * Default: AL_NONE * - * Specifies the buffer to provide sound samples. + * Specifies the buffer to provide sound samples for a source. */ #define AL_BUFFER 0x1009 @@ -186,12 +226,12 @@ typedef void ALvoid; * Type: ALfloat * Range: [0.0 - ] * - * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation - * of about -6dB. Each multiplicaton by 2 equals an amplification of about - * +6dB. + * For sources, an initial linear gain value (before attenuation is applied). + * For the listener, an output linear gain adjustment. * - * A value of 0.0 is meaningless with respect to a logarithmic scale; it is - * silent. + * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation + * of about -6dB. Each multiplication by 2 equals an amplification of about + * +6dB. */ #define AL_GAIN 0x100A @@ -200,8 +240,8 @@ typedef void ALvoid; * Type: ALfloat * Range: [0.0 - 1.0] * - * The minimum gain allowed for a source, after distance and cone attenation is - * applied (if applicable). + * The minimum gain allowed for a source, after distance and cone attenuation + * are applied (if applicable). */ #define AL_MIN_GAIN 0x100D @@ -210,31 +250,33 @@ typedef void ALvoid; * Type: ALfloat * Range: [0.0 - 1.0] * - * The maximum gain allowed for a source, after distance and cone attenation is - * applied (if applicable). + * The maximum gain allowed for a source, after distance and cone attenuation + * are applied (if applicable). */ #define AL_MAX_GAIN 0x100E /** * Listener orientation. - * Type: ALfloat[6] + * Type: ALfloat[6] * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0} * * Effectively two three dimensional vectors. The first vector is the front (or - * "at") and the second is the top (or "up"). + * "at") and the second is the top (or "up"). Both vectors are relative to the + * listener position. * - * Both vectors are in local space. + * To change from or to a left handed coordinate system, negate the Z + * component of both vectors. */ #define AL_ORIENTATION 0x100F /** * Source state (query only). - * Type: ALint + * Type: ALenum * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED] */ #define AL_SOURCE_STATE 0x1010 -/** Source state value. */ +/* Source state values. */ #define AL_INITIAL 0x1011 #define AL_PLAYING 0x1012 #define AL_PAUSED 0x1013 @@ -267,9 +309,9 @@ typedef void ALvoid; * Range: [0.0 - ] * Default: 1.0 * - * The distance in units that no attenuation occurs. + * The distance in units that no distance attenuation occurs. * - * At 0.0, no distance attenuation ever occurs on non-linear attenuation models. + * At 0.0, no distance attenuation occurs with non-linear attenuation models. */ #define AL_REFERENCE_DISTANCE 0x1020 @@ -292,7 +334,7 @@ typedef void ALvoid; * Default: 0.0 * * The gain attenuation applied when the listener is outside of the source's - * outer cone. + * outer cone angle. */ #define AL_CONE_OUTER_GAIN 0x1022 @@ -300,7 +342,7 @@ typedef void ALvoid; * Source maximum distance. * Type: ALfloat * Range: [0.0 - ] - * Default: +inf + * Default: FLT_MAX * * The distance above which the source is not attenuated any further with a * clamped distance model, or where attenuation reaches 0.0 gain for linear @@ -308,16 +350,16 @@ typedef void ALvoid; */ #define AL_MAX_DISTANCE 0x1023 -/** Source buffer position, in seconds */ +/** Source buffer offset, in seconds */ #define AL_SEC_OFFSET 0x1024 -/** Source buffer position, in sample frames */ +/** Source buffer offset, in sample frames */ #define AL_SAMPLE_OFFSET 0x1025 -/** Source buffer position, in bytes */ +/** Source buffer offset, in bytes */ #define AL_BYTE_OFFSET 0x1026 /** * Source type (query only). - * Type: ALint + * Type: ALenum * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED] * * A Source is Static if a Buffer has been attached using AL_BUFFER. @@ -330,31 +372,30 @@ typedef void ALvoid; */ #define AL_SOURCE_TYPE 0x1027 -/** Source type value. */ +/* Source type values. */ #define AL_STATIC 0x1028 #define AL_STREAMING 0x1029 #define AL_UNDETERMINED 0x1030 -/** Buffer format specifier. */ +/** Unsigned 8-bit mono buffer format. */ #define AL_FORMAT_MONO8 0x1100 +/** Signed 16-bit mono buffer format. */ #define AL_FORMAT_MONO16 0x1101 +/** Unsigned 8-bit stereo buffer format. */ #define AL_FORMAT_STEREO8 0x1102 +/** Signed 16-bit stereo buffer format. */ #define AL_FORMAT_STEREO16 0x1103 -/** Buffer frequency (query only). */ +/** Buffer frequency/sample rate (query only). */ #define AL_FREQUENCY 0x2001 /** Buffer bits per sample (query only). */ #define AL_BITS 0x2002 /** Buffer channel count (query only). */ #define AL_CHANNELS 0x2003 -/** Buffer data size (query only). */ +/** Buffer data size in bytes (query only). */ #define AL_SIZE 0x2004 -/** - * Buffer state. - * - * Not for public use. - */ +/* Buffer state. Not for public use. */ #define AL_UNUSED 0x2010 #define AL_PENDING 0x2011 #define AL_PROCESSED 0x2012 @@ -363,32 +404,31 @@ typedef void ALvoid; /** No error. */ #define AL_NO_ERROR 0 -/** Invalid name paramater passed to AL call. */ +/** Invalid name (ID) passed to an AL call. */ #define AL_INVALID_NAME 0xA001 -/** Invalid enum parameter passed to AL call. */ +/** Invalid enumeration passed to AL call. */ #define AL_INVALID_ENUM 0xA002 -/** Invalid value parameter passed to AL call. */ +/** Invalid value passed to AL call. */ #define AL_INVALID_VALUE 0xA003 /** Illegal AL call. */ #define AL_INVALID_OPERATION 0xA004 -/** Not enough memory. */ +/** Not enough memory to execute the AL call. */ #define AL_OUT_OF_MEMORY 0xA005 -/** Context string: Vendor ID. */ +/** Context string: Vendor name. */ #define AL_VENDOR 0xB001 /** Context string: Version. */ #define AL_VERSION 0xB002 -/** Context string: Renderer ID. */ +/** Context string: Renderer name. */ #define AL_RENDERER 0xB003 /** Context string: Space-separated extension list. */ #define AL_EXTENSIONS 0xB004 - /** * Doppler scale. * Type: ALfloat @@ -398,7 +438,6 @@ typedef void ALvoid; * Scale for source and listener velocities. */ #define AL_DOPPLER_FACTOR 0xC000 -AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); /** * Doppler velocity (deprecated). @@ -406,7 +445,6 @@ AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); * A multiplier applied to the Speed of Sound. */ #define AL_DOPPLER_VELOCITY 0xC001 -AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); /** * Speed of Sound, in units per second. @@ -415,14 +453,13 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); * Default: 343.3 * * The speed at which sound waves are assumed to travel, when calculating the - * doppler effect. + * doppler effect from source and listener velocities. */ #define AL_SPEED_OF_SOUND 0xC003 -AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); /** * Distance attenuation model. - * Type: ALint + * Type: ALenum * Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED, * AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, * AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED] @@ -439,9 +476,8 @@ AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); * distance calculated is clamped between the reference and max distances. */ #define AL_DISTANCE_MODEL 0xD000 -AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); -/** Distance model value. */ +/* Distance model values. */ #define AL_INVERSE_DISTANCE 0xD001 #define AL_INVERSE_DISTANCE_CLAMPED 0xD002 #define AL_LINEAR_DISTANCE 0xD003 @@ -449,208 +485,223 @@ AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); #define AL_EXPONENT_DISTANCE 0xD005 #define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 -/** Renderer State management. */ -AL_API void AL_APIENTRY alEnable(ALenum capability); -AL_API void AL_APIENTRY alDisable(ALenum capability); -AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); +#ifndef AL_NO_PROTOTYPES +/* Renderer State management. */ +AL_API void AL_APIENTRY alEnable(ALenum capability) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDisable(ALenum capability) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability) AL_API_NOEXCEPT; -/** State retrieval. */ -AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); -AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); -AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); -AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); -AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); -AL_API ALint AL_APIENTRY alGetInteger(ALenum param); -AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); -AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); +/* Context state setting. */ +AL_API void AL_APIENTRY alDopplerFactor(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel) AL_API_NOEXCEPT; + +/* Context state retrieval. */ +AL_API const ALchar* AL_APIENTRY alGetString(ALenum param) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param) AL_API_NOEXCEPT; +AL_API ALint AL_APIENTRY alGetInteger(ALenum param) AL_API_NOEXCEPT; +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param) AL_API_NOEXCEPT; +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param) AL_API_NOEXCEPT; /** - * Error retrieval. - * - * Obtain the first error generated in the AL context since the last check. + * Obtain the first error generated in the AL context since the last call to + * this function. */ -AL_API ALenum AL_APIENTRY alGetError(void); +AL_API ALenum AL_APIENTRY alGetError(void) AL_API_NOEXCEPT; +/** Query for the presence of an extension on the AL context. */ +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname) AL_API_NOEXCEPT; /** - * Extension support. - * - * Query for the presence of an extension, and obtain any appropriate function - * pointers and enum values. + * Retrieve the address of a function. The returned function may be context- + * specific. */ -AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); -AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); -AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); +AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname) AL_API_NOEXCEPT; +/** + * Retrieve the value of an enum. The returned value may be context-specific. + */ +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename) AL_API_NOEXCEPT; -/** Set Listener parameters */ -AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); -AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); -AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); +/* Set listener parameters. */ +AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values) AL_API_NOEXCEPT; -/** Get Listener parameters */ -AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); +/* Get listener parameters. */ +AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values) AL_API_NOEXCEPT; -/** Create Source objects. */ -AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); -/** Delete Source objects. */ -AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); -/** Verify a handle is a valid Source. */ -AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); +/** Create source objects. */ +AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources) AL_API_NOEXCEPT; +/** Delete source objects. */ +AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +/** Verify an ID is for a valid source. */ +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source) AL_API_NOEXCEPT; -/** Set Source parameters. */ -AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); -AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); +/* Set source parameters. */ +AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; -/** Get Source parameters. */ -AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); +/* Get source parameters. */ +AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; -/** Play, replay, or resume (if paused) a list of Sources */ -AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); -/** Stop a list of Sources */ -AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); -/** Rewind a list of Sources */ -AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); -/** Pause a list of Sources */ -AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); +/** Play, restart, or resume a source, setting its state to AL_PLAYING. */ +AL_API void AL_APIENTRY alSourcePlay(ALuint source) AL_API_NOEXCEPT; +/** Stop a source, setting its state to AL_STOPPED if playing or paused. */ +AL_API void AL_APIENTRY alSourceStop(ALuint source) AL_API_NOEXCEPT; +/** Rewind a source, setting its state to AL_INITIAL. */ +AL_API void AL_APIENTRY alSourceRewind(ALuint source) AL_API_NOEXCEPT; +/** Pause a source, setting its state to AL_PAUSED if playing. */ +AL_API void AL_APIENTRY alSourcePause(ALuint source) AL_API_NOEXCEPT; -/** Play, replay, or resume a Source */ -AL_API void AL_APIENTRY alSourcePlay(ALuint source); -/** Stop a Source */ -AL_API void AL_APIENTRY alSourceStop(ALuint source); -/** Rewind a Source (set playback postiton to beginning) */ -AL_API void AL_APIENTRY alSourceRewind(ALuint source); -/** Pause a Source */ -AL_API void AL_APIENTRY alSourcePause(ALuint source); +/** Play, restart, or resume a list of sources atomically. */ +AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +/** Stop a list of sources atomically. */ +AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +/** Rewind a list of sources atomically. */ +AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +/** Pause a list of sources atomically. */ +AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Queue buffers onto a source */ -AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); +AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; /** Unqueue processed buffers from a source */ -AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); +AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; -/** Create Buffer objects */ -AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); -/** Delete Buffer objects */ -AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); -/** Verify a handle is a valid Buffer */ -AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); +/** Create buffer objects */ +AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; +/** Delete buffer objects */ +AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; +/** Verify an ID is a valid buffer (including the NULL buffer) */ +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) AL_API_NOEXCEPT; -/** Specifies the data to be copied into a buffer */ -AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); +/** + * Copies data into the buffer, interpreting it using the specified format and + * samplerate. + */ +AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; -/** Set Buffer parameters, */ -AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); -AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); +/* Set buffer parameters. */ +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; -/** Get Buffer parameters. */ -AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); +/* Get buffer parameters. */ +AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; +#endif /* AL_NO_PROTOTYPES */ -/** Pointer-to-function type, useful for dynamically getting AL entry points. */ -typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); -typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); -typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); -typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); -typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); -typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); -typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); -typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); -typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); -typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); -typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); -typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); -typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); -typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); -typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); -typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); -typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); -typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); -typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); -typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); -typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); +/* Pointer-to-function types, useful for storing dynamically loaded AL entry + * points. + */ +typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERROR)(void) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel) AL_API_NOEXCEPT17; -#if defined(__cplusplus) +#ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_AL_H */ diff --git a/code/AL/alc.h b/code/AL/alc.h index 294e8b33..d048ca04 100644 --- a/code/AL/alc.h +++ b/code/AL/alc.h @@ -1,8 +1,40 @@ #ifndef AL_ALC_H #define AL_ALC_H -#if defined(__cplusplus) +/* NOLINTBEGIN */ +#ifdef __cplusplus extern "C" { + +#ifdef _MSVC_LANG +#define ALC_CPLUSPLUS _MSVC_LANG +#else +#define ALC_CPLUSPLUS __cplusplus +#endif + +#ifndef AL_DISABLE_NOEXCEPT +#if ALC_CPLUSPLUS >= 201103L +#define ALC_API_NOEXCEPT noexcept +#else +#define ALC_API_NOEXCEPT +#endif +#if ALC_CPLUSPLUS >= 201703L +#define ALC_API_NOEXCEPT17 noexcept +#else +#define ALC_API_NOEXCEPT17 +#endif + +#else /* AL_DISABLE_NOEXCEPT */ + +#define ALC_API_NOEXCEPT +#define ALC_API_NOEXCEPT17 +#endif + +#undef ALC_CPLUSPLUS + +#else /* __cplusplus */ + +#define ALC_API_NOEXCEPT +#define ALC_API_NOEXCEPT17 #endif #ifndef ALC_API @@ -15,14 +47,14 @@ extern "C" { #endif #endif -#if defined(_WIN32) +#ifdef _WIN32 #define ALC_APIENTRY __cdecl #else #define ALC_APIENTRY #endif -/** Deprecated macro. */ +/* Deprecated macros. */ #define ALCAPI ALC_API #define ALCAPIENTRY ALC_APIENTRY #define ALC_INVALID 0 @@ -31,9 +63,9 @@ extern "C" { #define ALC_VERSION_0_1 1 /** Opaque device handle */ -typedef struct ALCdevice_struct ALCdevice; +typedef struct ALCdevice ALCdevice; /** Opaque context handle */ -typedef struct ALCcontext_struct ALCcontext; +typedef struct ALCcontext ALCcontext; /** 8-bit boolean */ typedef char ALCboolean; @@ -41,41 +73,41 @@ typedef char ALCboolean; /** character */ typedef char ALCchar; -/** signed 8-bit 2's complement integer */ +/** signed 8-bit integer */ typedef signed char ALCbyte; /** unsigned 8-bit integer */ typedef unsigned char ALCubyte; -/** signed 16-bit 2's complement integer */ +/** signed 16-bit integer */ typedef short ALCshort; /** unsigned 16-bit integer */ typedef unsigned short ALCushort; -/** signed 32-bit 2's complement integer */ +/** signed 32-bit integer */ typedef int ALCint; /** unsigned 32-bit integer */ typedef unsigned int ALCuint; -/** non-negative 32-bit binary integer size */ +/** non-negative 32-bit integer size */ typedef int ALCsizei; -/** enumerated 32-bit value */ +/** 32-bit enumeration value */ typedef int ALCenum; -/** 32-bit IEEE754 floating-point */ +/** 32-bit IEEE-754 floating-point */ typedef float ALCfloat; -/** 64-bit IEEE754 floating-point */ +/** 64-bit IEEE-754 floating-point */ typedef double ALCdouble; /** void type (for opaque pointers only) */ typedef void ALCvoid; -/* Enumerant values begin at column 50. No tabs. */ +/* Enumeration values begin at column 50. Do not use tabs. */ /** Boolean False. */ #define ALC_FALSE 0 @@ -89,7 +121,7 @@ typedef void ALCvoid; /** Context attribute: Hz. */ #define ALC_REFRESH 0x1008 -/** Context attribute: AL_TRUE or AL_FALSE. */ +/** Context attribute: AL_TRUE or AL_FALSE synchronous context? */ #define ALC_SYNC 0x1009 /** Context attribute: requested Mono (3D) Sources. */ @@ -107,30 +139,32 @@ typedef void ALCvoid; /** Invalid context handle. */ #define ALC_INVALID_CONTEXT 0xA002 -/** Invalid enum parameter passed to an ALC call. */ +/** Invalid enumeration passed to an ALC call. */ #define ALC_INVALID_ENUM 0xA003 -/** Invalid value parameter passed to an ALC call. */ +/** Invalid value passed to an ALC call. */ #define ALC_INVALID_VALUE 0xA004 /** Out of memory. */ #define ALC_OUT_OF_MEMORY 0xA005 -/** Runtime ALC version. */ +/** Runtime ALC major version. */ #define ALC_MAJOR_VERSION 0x1000 +/** Runtime ALC minor version. */ #define ALC_MINOR_VERSION 0x1001 -/** Context attribute list properties. */ +/** Context attribute list size. */ #define ALC_ATTRIBUTES_SIZE 0x1002 +/** Context attribute list properties. */ #define ALC_ALL_ATTRIBUTES 0x1003 /** String for the default device specifier. */ #define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 /** - * String for the given device's specifier. + * Device specifier string. * - * If device handle is NULL, it is instead a null-char separated list of + * If device handle is NULL, it is instead a null-character separated list of * strings of known device specifiers (list ends with an empty string). */ #define ALC_DEVICE_SPECIFIER 0x1005 @@ -141,9 +175,9 @@ typedef void ALCvoid; /** Capture extension */ #define ALC_EXT_CAPTURE 1 /** - * String for the given capture device's specifier. + * Capture device specifier string. * - * If device handle is NULL, it is instead a null-char separated list of + * If device handle is NULL, it is instead a null-character separated list of * strings of known capture device specifiers (list ends with an empty string). */ #define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 @@ -158,80 +192,116 @@ typedef void ALCvoid; /** String for the default extended device specifier. */ #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 /** - * String for the given extended device's specifier. + * Device's extended specifier string. * - * If device handle is NULL, it is instead a null-char separated list of + * If device handle is NULL, it is instead a null-character separated list of * strings of known extended device specifiers (list ends with an empty string). */ #define ALC_ALL_DEVICES_SPECIFIER 0x1013 -/** Context management. */ -ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist); -ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); -ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); -ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); -ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); -ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); +#ifndef ALC_NO_PROTOTYPES +/* Context management. */ -/** Device management. */ -ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); +/** Create and attach a context to the given device. */ +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist) ALC_API_NOEXCEPT; +/** + * Makes the given context the active process-wide context. Passing NULL clears + * the active context. + */ +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) ALC_API_NOEXCEPT; +/** Resumes processing updates for the given context. */ +ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) ALC_API_NOEXCEPT; +/** Suspends updates for the given context. */ +ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) ALC_API_NOEXCEPT; +/** Remove a context from its device and destroys it. */ +ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) ALC_API_NOEXCEPT; +/** Returns the currently active context. */ +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) ALC_API_NOEXCEPT; +/** Returns the device that a particular context is attached to. */ +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context) ALC_API_NOEXCEPT; +/* Device management. */ + +/** Opens the named playback device. */ +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename) ALC_API_NOEXCEPT; +/** Closes the given playback device. */ +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) ALC_API_NOEXCEPT; + +/* Error support. */ + +/** Obtain the most recent Device error. */ +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) ALC_API_NOEXCEPT; + +/* Extension support. */ /** - * Error support. - * - * Obtain the most recent Device error. + * Query for the presence of an extension on the device. Pass a NULL device to + * query a device-inspecific extension. */ -ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname) ALC_API_NOEXCEPT; +/** + * Retrieve the address of a function. Given a non-NULL device, the returned + * function may be device-specific. + */ +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname) ALC_API_NOEXCEPT; +/** + * Retrieve the value of an enum. Given a non-NULL device, the returned value + * may be device-specific. + */ +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname) ALC_API_NOEXCEPT; + +/* Query functions. */ + +/** Returns information about the device, and error strings. */ +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param) ALC_API_NOEXCEPT; +/** Returns information about the device and the version of OpenAL. */ +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) ALC_API_NOEXCEPT; + +/* Capture functions. */ /** - * Extension support. - * - * Query for the presence of an extension, and obtain any appropriate - * function pointers and enum values. + * Opens the named capture device with the given frequency, format, and buffer + * size. */ -ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); -ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); -ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) ALC_API_NOEXCEPT; +/** Closes the given capture device. */ +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) ALC_API_NOEXCEPT; +/** Starts capturing samples into the device buffer. */ +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) ALC_API_NOEXCEPT; +/** Stops capturing samples. Samples in the device buffer remain available. */ +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) ALC_API_NOEXCEPT; +/** Reads samples from the device buffer. */ +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) ALC_API_NOEXCEPT; +#endif /* ALC_NO_PROTOTYPES */ -/** Query function. */ -ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); -ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); +/* Pointer-to-function types, useful for storing dynamically loaded ALC entry + * points. + */ +typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname) ALC_API_NOEXCEPT17; +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname) ALC_API_NOEXCEPT17; +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) ALC_API_NOEXCEPT17; -/** Capture function. */ -ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); -ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); -ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); -ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); - -/** Pointer-to-function type, useful for dynamically getting ALC entry points. */ -typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); -typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); -typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); -typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); -typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); -typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); -typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); -typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); -typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); -typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); -typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); -typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); -typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); - -#if defined(__cplusplus) -} +#ifdef __cplusplus +} /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_ALC_H */ diff --git a/code/AL/alext.h b/code/AL/alext.h index 0447f2bb..3908e194 100644 --- a/code/AL/alext.h +++ b/code/AL/alext.h @@ -1,38 +1,22 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 2008 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - #ifndef AL_ALEXT_H #define AL_ALEXT_H +/* NOLINTBEGIN */ #include -/* Define int64_t and uint64_t types */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#include -#elif defined(_WIN32) && defined(__GNUC__) +/* Define int64 and uint64 types */ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) #include +typedef int64_t _alsoft_int64_t; +typedef uint64_t _alsoft_uint64_t; #elif defined(_WIN32) -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; +typedef __int64 _alsoft_int64_t; +typedef unsigned __int64 _alsoft_uint64_t; #else /* Fallback if nothing above works */ -#include +#include +typedef int64_t _alsoft_int64_t; +typedef uint64_t _alsoft_uint64_t; #endif #include "alc.h" @@ -42,6 +26,8 @@ typedef unsigned __int64 uint64_t; extern "C" { #endif +struct _GUID; + #ifndef AL_LOKI_IMA_ADPCM_format #define AL_LOKI_IMA_ADPCM_format 1 #define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 @@ -97,6 +83,31 @@ extern "C" { #ifndef AL_EXT_MCFORMATS #define AL_EXT_MCFORMATS 1 +/* Provides support for surround sound buffer formats with 8, 16, and 32-bit + * samples. + * + * QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left, + * Rear Right). + * QUAD16: Signed 16-bit, Quadraphonic. + * QUAD32: 32-bit float, Quadraphonic. + * REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right). + * REAR16: Signed 16-bit, Rear Stereo. + * REAR32: 32-bit float, Rear Stereo. + * 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center, + * LFE, Side Left, Side Right). Note that some audio systems may label + * 5.1's Side channels as Rear or Surround; they are equivalent for the + * purposes of this extension. + * 51CHN16: Signed 16-bit, 5.1 Surround. + * 51CHN32: 32-bit float, 5.1 Surround. + * 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center, + * LFE, Rear Center, Side Left, Side Right). + * 61CHN16: Signed 16-bit, 6.1 Surround. + * 61CHN32: 32-bit float, 6.1 Surround. + * 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center, + * LFE, Rear Left, Rear Right, Side Left, Side Right). + * 71CHN16: Signed 16-bit, 7.1 Surround. + * 71CHN32: 32-bit float, 7.1 Surround. + */ #define AL_FORMAT_QUAD8 0x1204 #define AL_FORMAT_QUAD16 0x1205 #define AL_FORMAT_QUAD32 0x1206 @@ -133,9 +144,9 @@ extern "C" { #ifndef AL_EXT_STATIC_BUFFER #define AL_EXT_STATIC_BUFFER 1 -typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALuint,ALenum,ALvoid*,ALsizei,ALsizei) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); +void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; #endif #endif @@ -151,11 +162,11 @@ AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, #ifndef ALC_EXT_thread_local_context #define ALC_EXT_thread_local_context 1 -typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); +typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) ALC_API_NOEXCEPT; +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) ALC_API_NOEXCEPT; #endif #endif @@ -168,9 +179,9 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); #define AL_SOFT_buffer_sub_data 1 #define AL_BYTE_RW_OFFSETS_SOFT 0x1031 #define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 -typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); +AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length) AL_API_NOEXCEPT; #endif #endif @@ -187,12 +198,12 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const #define AL_FOLDBACK_EVENT_STOP 0x4113 #define AL_FOLDBACK_MODE_MONO 0x4101 #define AL_FOLDBACK_MODE_STEREO 0x4102 -typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); +typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); -AL_API void AL_APIENTRY alRequestFoldbackStop(void); +AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alRequestFoldbackStop(void) AL_API_NOEXCEPT; #endif #endif @@ -255,15 +266,15 @@ AL_API void AL_APIENTRY alRequestFoldbackStop(void); #define AL_SAMPLE_LENGTH_SOFT 0x200A #define AL_SEC_LENGTH_SOFT 0x200B -typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); -typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); +typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) AL_API_NOEXCEPT; #endif #endif @@ -294,13 +305,13 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); #define ALC_6POINT1_SOFT 0x1505 #define ALC_7POINT1_SOFT 0x1506 -typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*); -typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum); -typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei); +typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName); -ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); -ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName) AL_API_NOEXCEPT; +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) AL_API_NOEXCEPT; +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) AL_API_NOEXCEPT; #endif #endif @@ -318,38 +329,764 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe #define AL_SOFT_source_latency 1 #define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200 #define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 -typedef int64_t ALint64SOFT; -typedef uint64_t ALuint64SOFT; -typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*); +typedef _alsoft_int64_t ALint64SOFT; +typedef _alsoft_uint64_t ALuint64SOFT; +typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value); -AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); -AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values); -AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value); -AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); -AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values); -AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value); -AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); -AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values); -AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value); -AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); -AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values); +AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; #endif #endif +#ifndef ALC_EXT_DEFAULT_FILTER_ORDER +#define ALC_EXT_DEFAULT_FILTER_ORDER 1 +#define ALC_DEFAULT_FILTER_ORDER 0x1100 +#endif + +#ifndef AL_SOFT_deferred_updates +#define AL_SOFT_deferred_updates 1 +#define AL_DEFERRED_UPDATES_SOFT 0xC002 +typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alDeferUpdatesSOFT(void) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alProcessUpdatesSOFT(void) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_block_alignment +#define AL_SOFT_block_alignment 1 +#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT 0x200C +#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D +#endif + +#ifndef AL_SOFT_MSADPCM +#define AL_SOFT_MSADPCM 1 +#define AL_FORMAT_MONO_MSADPCM_SOFT 0x1302 +#define AL_FORMAT_STEREO_MSADPCM_SOFT 0x1303 +#endif + +#ifndef AL_SOFT_source_length +#define AL_SOFT_source_length 1 +/*#define AL_BYTE_LENGTH_SOFT 0x2009*/ +/*#define AL_SAMPLE_LENGTH_SOFT 0x200A*/ +/*#define AL_SEC_LENGTH_SOFT 0x200B*/ +#endif + +#ifndef AL_SOFT_buffer_length_query +#define AL_SOFT_buffer_length_query 1 +/*#define AL_BYTE_LENGTH_SOFT 0x2009*/ +/*#define AL_SAMPLE_LENGTH_SOFT 0x200A*/ +/*#define AL_SEC_LENGTH_SOFT 0x200B*/ +#endif + +#ifndef ALC_SOFT_pause_device +#define ALC_SOFT_pause_device 1 +typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) ALC_API_NOEXCEPT; +ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) ALC_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_EXT_BFORMAT +#define AL_EXT_BFORMAT 1 +/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling + * and layout). + * + * BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY). + * BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY). + * BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY). + * BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ). + * BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ). + * BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ). + */ +#define AL_FORMAT_BFORMAT2D_8 0x20021 +#define AL_FORMAT_BFORMAT2D_16 0x20022 +#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023 +#define AL_FORMAT_BFORMAT3D_8 0x20031 +#define AL_FORMAT_BFORMAT3D_16 0x20032 +#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033 +#endif + +#ifndef AL_EXT_MULAW_BFORMAT +#define AL_EXT_MULAW_BFORMAT 1 +#define AL_FORMAT_BFORMAT2D_MULAW 0x10031 +#define AL_FORMAT_BFORMAT3D_MULAW 0x10032 +#endif + +#ifndef ALC_SOFT_HRTF +#define ALC_SOFT_HRTF 1 +#define ALC_HRTF_SOFT 0x1992 +#define ALC_DONT_CARE_SOFT 0x0002 +#define ALC_HRTF_STATUS_SOFT 0x1993 +#define ALC_HRTF_DISABLED_SOFT 0x0000 +#define ALC_HRTF_ENABLED_SOFT 0x0001 +#define ALC_HRTF_DENIED_SOFT 0x0002 +#define ALC_HRTF_REQUIRED_SOFT 0x0003 +#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004 +#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005 +#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 +#define ALC_HRTF_SPECIFIER_SOFT 0x1995 +#define ALC_HRTF_ID_SOFT 0x1996 +typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index) ALC_API_NOEXCEPT; +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs) ALC_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_gain_clamp_ex +#define AL_SOFT_gain_clamp_ex 1 +#define AL_GAIN_LIMIT_SOFT 0x200E +#endif + +#ifndef AL_SOFT_source_resampler +#define AL_SOFT_source_resampler +#define AL_NUM_RESAMPLERS_SOFT 0x1210 +#define AL_DEFAULT_RESAMPLER_SOFT 0x1211 +#define AL_SOURCE_RESAMPLER_SOFT 0x1212 +#define AL_RESAMPLER_NAME_SOFT 0x1213 +typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_source_spatialize +#define AL_SOFT_source_spatialize +#define AL_SOURCE_SPATIALIZE_SOFT 0x1214 +#define AL_AUTO_SOFT 0x0002 +#endif + +#ifndef ALC_SOFT_output_limiter +#define ALC_SOFT_output_limiter +#define ALC_OUTPUT_LIMITER_SOFT 0x199A +#endif + +#ifndef ALC_SOFT_device_clock +#define ALC_SOFT_device_clock 1 +typedef _alsoft_int64_t ALCint64SOFT; +typedef _alsoft_uint64_t ALCuint64SOFT; +#define ALC_DEVICE_CLOCK_SOFT 0x1600 +#define ALC_DEVICE_LATENCY_SOFT 0x1601 +#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 +#define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202 +#define AL_SEC_OFFSET_CLOCK_SOFT 0x1203 +typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values) ALC_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_direct_channels_remix +#define AL_SOFT_direct_channels_remix 1 +#define AL_DROP_UNMATCHED_SOFT 0x0001 +#define AL_REMIX_UNMATCHED_SOFT 0x0002 +#endif + +#ifndef AL_SOFT_bformat_ex +#define AL_SOFT_bformat_ex 1 +#define AL_AMBISONIC_LAYOUT_SOFT 0x1997 +#define AL_AMBISONIC_SCALING_SOFT 0x1998 + +/* Ambisonic layouts */ +#define AL_FUMA_SOFT 0x0000 +#define AL_ACN_SOFT 0x0001 + +/* Ambisonic scalings (normalization) */ +/*#define AL_FUMA_SOFT*/ +#define AL_SN3D_SOFT 0x0001 +#define AL_N3D_SOFT 0x0002 +#endif + +#ifndef ALC_SOFT_loopback_bformat +#define ALC_SOFT_loopback_bformat 1 +#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997 +#define ALC_AMBISONIC_SCALING_SOFT 0x1998 +#define ALC_AMBISONIC_ORDER_SOFT 0x1999 +#define ALC_MAX_AMBISONIC_ORDER_SOFT 0x199B + +#define ALC_BFORMAT3D_SOFT 0x1507 + +/* Ambisonic layouts */ +#define ALC_FUMA_SOFT 0x0000 +#define ALC_ACN_SOFT 0x0001 + +/* Ambisonic scalings (normalization) */ +/*#define ALC_FUMA_SOFT*/ +#define ALC_SN3D_SOFT 0x0001 +#define ALC_N3D_SOFT 0x0002 +#endif + +#ifndef AL_SOFT_effect_target +#define AL_SOFT_effect_target +#define AL_EFFECTSLOT_TARGET_SOFT 0x199C +#endif + +#ifndef AL_SOFT_events +#define AL_SOFT_events 1 +#define AL_EVENT_CALLBACK_FUNCTION_SOFT 0x19A2 +#define AL_EVENT_CALLBACK_USER_PARAM_SOFT 0x19A3 +#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT 0x19A4 +#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5 +#define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6 +typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param, + ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef ALC_SOFT_reopen_device +#define ALC_SOFT_reopen_device +typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device, + const ALCchar *deviceName, const ALCint *attribs) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName, + const ALCint *attribs) ALC_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_callback_buffer +#define AL_SOFT_callback_buffer +#define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0 +#define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1 +typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_UHJ +#define AL_SOFT_UHJ +#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2 +#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3 +#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4 +#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5 +#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6 +#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7 +#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8 +#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9 +#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA + +#define AL_STEREO_MODE_SOFT 0x19B0 +#define AL_NORMAL_SOFT 0x0000 +#define AL_SUPER_STEREO_SOFT 0x0001 +#define AL_SUPER_STEREO_WIDTH_SOFT 0x19B1 +#endif + +#ifndef AL_SOFT_UHJ_ex +#define AL_SOFT_UHJ_ex +#define AL_FORMAT_UHJ2CHN_MULAW_SOFT 0x19B3 +#define AL_FORMAT_UHJ2CHN_ALAW_SOFT 0x19B4 +#define AL_FORMAT_UHJ2CHN_IMA4_SOFT 0x19B5 +#define AL_FORMAT_UHJ2CHN_MSADPCM_SOFT 0x19B6 +#define AL_FORMAT_UHJ3CHN_MULAW_SOFT 0x19B7 +#define AL_FORMAT_UHJ3CHN_ALAW_SOFT 0x19B8 +#define AL_FORMAT_UHJ4CHN_MULAW_SOFT 0x19B9 +#define AL_FORMAT_UHJ4CHN_ALAW_SOFT 0x19BA +#endif + +#ifndef ALC_SOFT_output_mode +#define ALC_SOFT_output_mode +#define ALC_OUTPUT_MODE_SOFT 0x19AC +#define ALC_ANY_SOFT 0x19AD +/*#define ALC_MONO_SOFT 0x1500*/ +/*#define ALC_STEREO_SOFT 0x1501*/ +#define ALC_STEREO_BASIC_SOFT 0x19AE +#define ALC_STEREO_UHJ_SOFT 0x19AF +#define ALC_STEREO_HRTF_SOFT 0x19B2 +/*#define ALC_QUAD_SOFT 0x1503*/ +#define ALC_SURROUND_5_1_SOFT 0x1504 +#define ALC_SURROUND_6_1_SOFT 0x1505 +#define ALC_SURROUND_7_1_SOFT 0x1506 +#endif + +#ifndef AL_SOFT_source_start_delay +#define AL_SOFT_source_start_delay +typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMESOFT)(ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMEVSOFT)(ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef ALC_EXT_debug +#define ALC_EXT_debug +#define ALC_CONTEXT_FLAGS_EXT 0x19CF +#define ALC_CONTEXT_DEBUG_BIT_EXT 0x0001 +#endif + +#ifndef AL_EXT_debug +#define AL_EXT_debug +#define AL_DONT_CARE_EXT 0x0002 +#define AL_DEBUG_OUTPUT_EXT 0x19B2 +#define AL_DEBUG_CALLBACK_FUNCTION_EXT 0x19B3 +#define AL_DEBUG_CALLBACK_USER_PARAM_EXT 0x19B4 +#define AL_DEBUG_SOURCE_API_EXT 0x19B5 +#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT 0x19B6 +#define AL_DEBUG_SOURCE_THIRD_PARTY_EXT 0x19B7 +#define AL_DEBUG_SOURCE_APPLICATION_EXT 0x19B8 +#define AL_DEBUG_SOURCE_OTHER_EXT 0x19B9 +#define AL_DEBUG_TYPE_ERROR_EXT 0x19BA +#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT 0x19BB +#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT 0x19BC +#define AL_DEBUG_TYPE_PORTABILITY_EXT 0x19BD +#define AL_DEBUG_TYPE_PERFORMANCE_EXT 0x19BE +#define AL_DEBUG_TYPE_MARKER_EXT 0x19BF +#define AL_DEBUG_TYPE_PUSH_GROUP_EXT 0x19C0 +#define AL_DEBUG_TYPE_POP_GROUP_EXT 0x19C1 +#define AL_DEBUG_TYPE_OTHER_EXT 0x19C2 +#define AL_DEBUG_SEVERITY_HIGH_EXT 0x19C3 +#define AL_DEBUG_SEVERITY_MEDIUM_EXT 0x19C4 +#define AL_DEBUG_SEVERITY_LOW_EXT 0x19C5 +#define AL_DEBUG_SEVERITY_NOTIFICATION_EXT 0x19C6 +#define AL_DEBUG_LOGGED_MESSAGES_EXT 0x19C7 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT 0x19C8 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA +#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB +#define AL_MAX_LABEL_LENGTH_EXT 0x19CC +#define AL_STACK_OVERFLOW_EXT 0x19CD +#define AL_STACK_UNDERFLOW_EXT 0x19CE +#define AL_CONTEXT_FLAGS_EXT 0x19CF +#define AL_BUFFER_EXT 0x1009 /* Same as AL_BUFFER */ +#define AL_SOURCE_EXT 0x19D0 +#define AL_FILTER_EXT 0x19D1 +#define AL_EFFECT_EXT 0x19D2 +#define AL_AUXILIARY_EFFECT_SLOT_EXT 0x19D3 + +typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTEREXT)(ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVEXT)(ALenum pname, void **values) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerEXT(ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervEXT(ALenum pname, void **values) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef ALC_SOFT_system_events +#define ALC_SOFT_system_events +#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4 +#define ALC_CAPTURE_DEVICE_SOFT 0x19D5 +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 +#define ALC_EVENT_SUPPORTED_SOFT 0x19D9 +#define ALC_EVENT_NOT_SUPPORTED_SOFT 0x19DA +typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, + ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY*LPALCEVENTISSUPPORTEDSOFT)(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT; +ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; +void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_EXT_direct_context +#define AL_EXT_direct_context +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS2)(ALCdevice *device, const ALCchar *funcname) AL_API_NOEXCEPT17; + +typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; +/* ALC_EXT_EFX */ +typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +/* AL_EXT_BUFFER_DATA_STATIC */ +typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT17; +/* AL_EXT_debug */ +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTERDIRECTEXT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVDIRECTEXT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; +/* AL_EXT_FOLDBACK */ +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_buffer_sub_data */ +typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; +/* AL_SOFT_source_latency */ +typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +/* AL_SOFT_deferred_updates */ +typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_source_resampler */ +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT17; +/* AL_SOFT_events */ +typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; +/* AL_SOFT_callback_buffer */ +typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; +/* AL_SOFT_source_start_delay */ +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; +/* EAX */ +typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCvoid* ALC_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALCchar *funcName) AL_API_NOEXCEPT; + +void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; + +void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT; +ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT; + +void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT; +void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; + +void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectEXT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectEXT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; +void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT; + +void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_bformat_hoa +#define AL_SOFT_bformat_hoa +#define AL_UNPACK_AMBISONIC_ORDER_SOFT 0x199D +#endif + #ifdef __cplusplus } #endif +/* NOLINTEND */ #endif diff --git a/code/AL/efx-presets.h b/code/AL/efx-presets.h index 86dcbda2..acd5bf39 100644 --- a/code/AL/efx-presets.h +++ b/code/AL/efx-presets.h @@ -2,6 +2,7 @@ #ifndef EFX_PRESETS_H #define EFX_PRESETS_H +/* NOLINTBEGIN */ #ifndef EFXEAXREVERBPROPERTIES_DEFINED #define EFXEAXREVERBPROPERTIES_DEFINED @@ -345,7 +346,7 @@ typedef struct { /* Driving Presets */ #define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \ - { 1.0000f, 0.0000f, 3.1623f, 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 } + { 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 } #define EFX_REVERB_PRESET_DRIVING_PITGARAGE \ { 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 } @@ -399,4 +400,5 @@ typedef struct { #define EFX_REVERB_PRESET_SMALLWATERROOM \ { 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 } +/* NOLINTEND */ #endif /* EFX_PRESETS_H */ diff --git a/code/AL/efx.h b/code/AL/efx.h index 57766983..1e93bf22 100644 --- a/code/AL/efx.h +++ b/code/AL/efx.h @@ -1,6 +1,8 @@ #ifndef AL_EFX_H #define AL_EFX_H +/* NOLINTBEGIN */ +#include #include "alc.h" #include "al.h" @@ -203,80 +205,80 @@ extern "C" { /* Effect object function types. */ -typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); -typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; /* Filter object function types. */ -typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); -typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; /* Auxiliary Effect Slot object function types. */ -typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); -AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects); -AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); -AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues); -AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; -AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); -AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters); -AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); -AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues); -AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; -AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); -AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots); -AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; #endif /* Filter ranges and defaults. */ @@ -757,5 +759,6 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_EFX_H */ diff --git a/code/Launcher/CMakeLists.txt b/code/Launcher/CMakeLists.txt new file mode 100644 index 00000000..133435ff --- /dev/null +++ b/code/Launcher/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.12) + +project(Launcher) + +set(LAUNCHER_SOURCES "${CMAKE_SOURCE_DIR}/code/Launcher/launch_main.cpp") + +if (WIN32) + set(LAUNCHER_SOURCES ${LAUNCHER_SOURCES} + "${CMAKE_SOURCE_DIR}/code/Launcher/launch_win32.cpp" + "${CMAKE_SOURCE_DIR}/code/sys/win_resource.rc") +else() + set(LAUNCHER_SOURCES ${LAUNCHER_SOURCES} + "${CMAKE_SOURCE_DIR}/code/Launcher/launch_linux.cpp") +endif() + +function (create_launcher name type) + if (NOT BUILD_NO_CLIENT) + add_executable(openmohaa_launcher_${name} ${LAUNCHER_SOURCES}) + target_include_directories(openmohaa_launcher_${name} PUBLIC "../qcommon") + target_compile_definitions(openmohaa_launcher_${name} PRIVATE NO_RC_MANIFEST=1 TARGET_GAME=${type}) + target_compile_features(openmohaa_launcher_${name} PRIVATE cxx_std_17) + set_target_properties(openmohaa_launcher_${name} PROPERTIES OUTPUT_NAME "launch_openmohaa_${name}${TARGET_BIN_SUFFIX}") + + INSTALL(TARGETS openmohaa_launcher_${name} DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR}) + endif() + + #add_executable(omohaaded_launcher_${name} ${LAUNCHER_SOURCES}) + #target_include_directories(omohaaded_launcher_${name} PUBLIC "../qcommon") + #target_compile_definitions(omohaaded_launcher_${name} PRIVATE NO_RC_MANIFEST=1 TARGET_GAME=${type} DEDICATED=1) + #target_compile_features(omohaaded_launcher_${name} PRIVATE cxx_std_17) + #set_target_properties(omohaaded_launcher_${name} PROPERTIES OUTPUT_NAME "launch_omohaaded_${name}${TARGET_BIN_SUFFIX}") + # + #INSTALL(TARGETS omohaaded_launcher_${name} DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_INSTALL_SUBDIR}) +endfunction() + +create_launcher(base 0) +create_launcher(spearhead 1) +create_launcher(breakthrough 2) diff --git a/code/renderer/tr_vis.cpp b/code/Launcher/launch.h similarity index 74% rename from code/renderer/tr_vis.cpp rename to code/Launcher/launch.h index 0236e4e9..3ac1ff8c 100644 --- a/code/renderer/tr_vis.cpp +++ b/code/Launcher/launch.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,15 +20,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -// tr_vis.cpp: visibility culling +// launch.h: Base interface for starting programs -#include "tr_local.h" -#include "tr_vis.h" +#include "q_platform.h" -void R_VisDebug() { - // FIXME: unimplemented -} +#include +#include +#include -void R_VisDebugLoad(const char* szBSPName) { - // FIXME: unimplemented -} +std::filesystem::path GetProgramLocation(); +void LaunchProgram(const std::filesystem::path& path, const std::vector& argumentList); diff --git a/code/Launcher/launch_linux.cpp b/code/Launcher/launch_linux.cpp new file mode 100644 index 00000000..ee7e7764 --- /dev/null +++ b/code/Launcher/launch_linux.cpp @@ -0,0 +1,80 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// main.cpp: Windows implementation of the launcher + +#include "launch.h" + +#include +#include +#include +#include + +#include +#include + +extern "C" char** environ; + +std::filesystem::path GetProgramLocation() +{ + char path[FILENAME_MAX]; + ssize_t count = readlink("/proc/self/exe", path, FILENAME_MAX); + + return std::filesystem::path(std::string(path, (count > 0) ? count : 0)).parent_path(); +} + +void LaunchProgram(const std::filesystem::path& path, const std::vector& argumentList) +{ + pid_t pid; + std::string pathString = path.string(); + size_t argCount = argumentList.size(); + char** argv; + int status; + + argv = new char*[argCount + 2]; + argv[0] = (char*)pathString.c_str(); + + for (size_t i = 0; i < argCount; i++) { + argv[i + 1] = (char*)argumentList[i].c_str(); + } + argv[argCount + 1] = NULL; + + //status = posix_spawn(&pid, pathString.c_str(), NULL, NULL, argv, environ); + //delete[] argv; + //if (status != 0) { + // std::cout << "posix_spawn returned error: " << status << std::endl; + // return; + //} + + // + // Using execve rather than posix_spawn + // This replaces the current process that is not needed anyway + // + status = execve(pathString.c_str(), argv, environ); + delete[] argv; + if (status == -1) { + std::cout << "posix_spawn returned error: " << errno << std::endl; + return; + } + + waitpid(pid, NULL, 0); +} diff --git a/code/Launcher/launch_main.cpp b/code/Launcher/launch_main.cpp new file mode 100644 index 00000000..afefd20a --- /dev/null +++ b/code/Launcher/launch_main.cpp @@ -0,0 +1,67 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// main.cpp: The launcher + +#include "launch.h" + +#include +#include +#include + +const char* targetGameList[] = +{ + "Base", + "Spearhead", + "Breakthrough" +}; + +int main(int argc, const char* argv[]) { + std::vector argumentList; +#if !defined(DEDICATED) || !DEDICATED + const char* programName = "openmohaa" ARCH_SUFFIX DLL_SUFFIX EXE_EXT; +#else + const char* programName = "omohaaded" ARCH_SUFFIX DLL_SUFFIX EXE_EXT; +#endif + + argumentList.push_back("+set"); + argumentList.push_back("com_target_game"); + argumentList.push_back(std::to_string(TARGET_GAME)); + + for (size_t i = 1; i < argc; i++) { + argumentList.push_back(argv[i]); + } + + std::cout << "Using the target game: " << targetGameList[TARGET_GAME] << std::endl; + std::cout << std::endl; + std::cout << "Expected program name: " << programName << std::endl; + + const std::filesystem::path programLocation = GetProgramLocation(); + const std::filesystem::path programPath = programLocation / programName; + + std::cout << "Program location: " << programLocation << std::endl; + std::cout << "Expected path: " << programPath << std::endl; + + LaunchProgram(programPath, argumentList); + + return 0; +} diff --git a/code/Launcher/launch_win32.cpp b/code/Launcher/launch_win32.cpp new file mode 100644 index 00000000..ed506df7 --- /dev/null +++ b/code/Launcher/launch_win32.cpp @@ -0,0 +1,87 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// main.cpp: Windows implementation of the launcher + +#include "launch.h" + +#include +#include +#include + +std::filesystem::path GetProgramLocation() +{ + wchar_t path[FILENAME_MAX] = { 0 }; + GetModuleFileNameW(nullptr, path, FILENAME_MAX); + + return std::filesystem::path(path).parent_path(); +} + +void LaunchProgram(const std::filesystem::path& path, const std::vector& argumentList) +{ + PROCESS_INFORMATION processInfo; + STARTUPINFOW startupInfo; + BOOL returnValue; + std::wstring osCommandLine; + std::wstring commandLine; + size_t argCount = argumentList.size(); + + memset(&processInfo, 0, sizeof(processInfo)); + memset(&startupInfo, 0, sizeof(startupInfo)); + startupInfo.cb = sizeof(startupInfo); + + for (size_t i = 0; i < argCount; i++) { + commandLine += L"\""; + commandLine += std::wstring(argumentList[i].begin(), argumentList[i].end()); + commandLine += L"\""; + if (i != argCount - 1) { + commandLine += L" "; + } + } + + osCommandLine = path.wstring(); + osCommandLine += L" "; + osCommandLine += commandLine; + + returnValue = CreateProcessW( + path.wstring().c_str(), + (LPWSTR)osCommandLine.c_str(), + NULL, + NULL, + FALSE, + 0, + NULL, + std::filesystem::current_path().wstring().c_str(), + &startupInfo, + &processInfo + ); + + if (!returnValue) { + std::cout << "Error in CreateProcess: " << GetLastError() << std::endl; + return; + } + + WaitForSingleObject(processInfo.hProcess, INFINITE); + + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); +} diff --git a/code/autoupdater/autoupdater.c b/code/autoupdater/autoupdater.c index 4a052027..e013a1f4 100644 --- a/code/autoupdater/autoupdater.c +++ b/code/autoupdater/autoupdater.c @@ -933,10 +933,13 @@ static void waitToApplyUpdates(void) OS forcibly closes the pipe), we will unblock. Then we can loop on kill() until the process is truly gone. */ int x = 0; + struct timespec req; + req.tv_sec = 0; + req.tv_nsec = 100000000; read(3, &x, sizeof (x)); info("Pipe has closed, waiting for process to fully go away now."); while (kill(options.waitforprocess, 0) == 0) { - usleep(100000); + nanosleep(&req, NULL); } #endif } diff --git a/code/cgame/CMakeLists.txt b/code/cgame/CMakeLists.txt index f771fcfe..a0423773 100644 --- a/code/cgame/CMakeLists.txt +++ b/code/cgame/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(cgame) # Shared source files for modules @@ -18,7 +18,7 @@ set(SOURCES_SHARED "../script/scriptvariable.cpp" ) -file(GLOB_RECURSE SOURCES_BG "../fgame/bg_misc.cpp" "../fgame/bg_pmove.cpp" "../fgame/bg_slidemove.cpp") +file(GLOB_RECURSE SOURCES_BG "../fgame/bg_misc.cpp" "../fgame/bg_pmove.cpp" "../fgame/bg_slidemove.cpp" "../fgame/bg_voteoptions.cpp") file(GLOB_RECURSE SOURCES_CGAME "./*.c" "./*.cpp") add_library(cgame SHARED ${SOURCES_CGAME} ${SOURCES_BG}) @@ -27,16 +27,11 @@ target_compile_features(cgame PUBLIC cxx_nullptr) target_compile_features(cgame PUBLIC c_variadic_macros) target_link_libraries(cgame PUBLIC qcommon) -set_target_properties(cgame PROPERTIES PREFIX "${TARGET_PLATFORM_PREFIX}") -set_target_properties(cgame PROPERTIES OUTPUT_NAME "cgame${TARGET_ARCH_SUFFIX}") -set_target_properties(cgame PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TARGET_BASE_GAME}") +set_target_properties(cgame PROPERTIES PREFIX "") +set_target_properties(cgame PROPERTIES OUTPUT_NAME "cgame${TARGET_BIN_SUFFIX}") -INSTALL( - TARGETS cgame - LIBRARY DESTINATION "${TARGET_BASE_GAME}" - RUNTIME DESTINATION "${TARGET_BASE_GAME}" -) +INSTALL(TARGETS cgame DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR}) if(MSVC) - INSTALL(FILES $ DESTINATION "${TARGET_BASE_GAME}" OPTIONAL) + INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR} OPTIONAL) endif() \ No newline at end of file diff --git a/code/cgame/cg_archive.cpp b/code/cgame/cg_archive.cpp index 3609099f..3d944fb9 100644 --- a/code/cgame/cg_archive.cpp +++ b/code/cgame/cg_archive.cpp @@ -22,43 +22,175 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_local.h" #include "cg_archive.h" +#include "cg_commands.h" +#include "memarchiver.h" +#include "../qcommon/tiki.h" void CG_ArchiveStuff(MemArchiver& archiver, int svsTime) { - // FIXME: unimplemented + archiver.SetBaseTime(svsTime); + commandManager.ArchiveToMemory(archiver); + CG_ArchiveVSSGlobals(archiver); } -void CG_SaveStateToBuffer(void** out, int svsTime) +size_t CG_SaveStateToBuffer(void** out, int svsTime) { - // FIXME: unimplemented + MemArchiver archiver; + size_t size; + + archiver.SetupForWriting(0x200000); + CG_ArchiveStuff(archiver, svsTime); + size = archiver.BufferSize(); + if (size && out) { + *out = archiver.ConfiscateBuffer(); + } + + return size; } -void CG_LoadStateToBuffer(void* state, int size, int svsTime) +qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime) { - // FIXME: unimplemented + MemArchiver archiver; + + archiver.SetupForReading((byte*)state, size); + CG_ArchiveStuff(archiver, svsTime); + + return archiver.FinishedReading(); } void CG_ArchiveStringContainer(MemArchiver& archiver, Container* container) { - // FIXME: unimplemented + int num; + int i; + + if (archiver.IsReading()) { + str tmp; + + archiver.ArchiveInteger(&num); + container->ClearObjectList(); + + for (i = 0; i < num; i++) { + archiver.ArchiveString(&tmp); + container->AddObject(tmp); + } + } else { + num = container->NumObjects(); + archiver.ArchiveInteger(&num); + + for (i = 0; i < num; i++) { + str& tmp = container->ObjectAt(i + 1); + archiver.ArchiveString(&tmp); + } + } } void CG_ArchiveTikiPointer(MemArchiver& archiver, dtiki_t** pTiki) { - // FIXME: unimplemented + str tmp; + + if (archiver.IsReading()) { + archiver.ArchiveString(&tmp); + if (tmp.length()) { + *pTiki = cgi.R_Model_GetHandle(cgi.R_RegisterModel(tmp.c_str())); + } else { + *pTiki = NULL; + } + } else { + if (*pTiki) { + tmp = (*pTiki)->name; + } + + archiver.ArchiveString(&tmp); + } } void CG_ArchiveModelHandle(MemArchiver& archiver, qhandle_t* handle) { - // FIXME: unimplemented + str tmp; + + if (archiver.IsReading()) { + archiver.ArchiveString(&tmp); + if (tmp.length()) { + *handle = cgi.R_RegisterModel(tmp.c_str()); + } else { + *handle = (qhandle_t)0; + } + } else { + if (*handle) { + tmp = cgi.R_GetModelName(*handle); + } else { + tmp = ""; + } + + archiver.ArchiveString(&tmp); + } } void CG_ArchiveShaderHandle(MemArchiver& archiver, qhandle_t* handle) { - // FIXME: unimplemented + str tmp; + + if (archiver.IsReading()) { + archiver.ArchiveString(&tmp); + if (tmp.length()) { + *handle = cgi.R_RegisterShader(tmp.c_str()); + } else { + *handle = (qhandle_t)0; + } + } else { + if (*handle) { + tmp = cgi.R_GetShaderName(*handle); + } else { + tmp = ""; + } + + archiver.ArchiveString(&tmp); + } } void CG_ArchiveRefEntity(MemArchiver& archiver, refEntity_t* ref) { - // FIXME: unimplemented + archiver.ArchiveRaw(&ref->reType, sizeof(ref->reType)); + archiver.ArchiveInteger(&ref->renderfx); + + CG_ArchiveModelHandle(archiver, &ref->hModel); + CG_ArchiveModelHandle(archiver, &ref->hOldModel); + + archiver.ArchiveVec3(ref->lightingOrigin); + archiver.ArchiveInteger(&ref->parentEntity); + archiver.ArchiveVec3(ref->axis[0]); + archiver.ArchiveVec3(ref->axis[1]); + archiver.ArchiveVec3(ref->axis[2]); + archiver.ArchiveBoolean(&ref->nonNormalizedAxes); + archiver.ArchiveVec3(ref->origin); + archiver.ArchiveRaw(ref->frameInfo, sizeof(ref->frameInfo)); + archiver.ArchiveFloat(&ref->actionWeight); + archiver.ArchiveShort(&ref->wasframe); + archiver.ArchiveFloat(&ref->scale); + archiver.ArchiveVec3(ref->oldorigin); + archiver.ArchiveInteger(&ref->skinNum); + + CG_ArchiveShaderHandle(archiver, &ref->customShader); + archiver.ArchiveRaw(ref->shaderRGBA, sizeof(ref->shaderRGBA)); + archiver.ArchiveFloat(ref->shaderTexCoord); + archiver.ArchiveFloat(&ref->shaderTexCoord[1]); + archiver.ArchiveFloat(&ref->shaderTime); + + archiver.ArchiveInteger(&ref->entityNumber); + archiver.ArchiveRaw(ref->surfaces, 32); + archiver.ArchiveFloat(ref->shader_data); + archiver.ArchiveFloat(&ref->shader_data[1]); + + ref->bone_tag = NULL; + ref->bone_quat = NULL; + ref->of = NULL; + ref->nf = NULL; + + CG_ArchiveTikiPointer(archiver, &ref->tiki); + + archiver.ArchiveInteger(&ref->bonestart); + archiver.ArchiveInteger(&ref->morphstart); + archiver.ArchiveBoolean(&ref->hasMorph); + archiver.ArchiveFloat(&ref->radius); + archiver.ArchiveFloat(&ref->rotation); } diff --git a/code/cgame/cg_archive.h b/code/cgame/cg_archive.h index de095674..27ad8fbd 100644 --- a/code/cgame/cg_archive.h +++ b/code/cgame/cg_archive.h @@ -30,15 +30,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/container.h" #include "../qcommon/str.h" -class MemArchiver { - -}; +class MemArchiver; extern "C" { #endif -void CG_SaveStateToBuffer(void** out, int svsTime); -void CG_LoadStateToBuffer(void* state, int size, int svsTime); +size_t CG_SaveStateToBuffer(void** out, int svsTime); +qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime); #ifdef __cplusplus void CG_ArchiveStuff(MemArchiver& archiver, int svsTime); diff --git a/code/cgame/cg_commands.cpp b/code/cgame/cg_commands.cpp index 77506a88..0ccee1bc 100644 --- a/code/cgame/cg_commands.cpp +++ b/code/cgame/cg_commands.cpp @@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_specialfx.h" #include "scriptexception.h" #include "tiki.h" +#include "cg_archive.h" +#include "memarchiver.h" refEntity_t *current_entity = NULL; int current_entity_number = -1; @@ -43,14 +45,45 @@ void CacheResource(const char *stuff); ClientGameCommandManager commandManager; -Event EV_Client_StartBlock("(", EV_DEFAULT, NULL, NULL, "Signals the beginning of a block of commands"); -Event EV_Client_EndBlock(")", EV_DEFAULT, NULL, NULL, "Signals the end of a block of commands"); -Event EV_Client_EmitterStartOff( - "startoff", EV_DEFAULT, NULL, NULL, "Signals an emitter to start in the off state (no tempmodels are emitted)" +Event EV_Client_StartBlock +( + "(", + EV_DEFAULT, + NULL, + NULL, + "Signals the beginning of a block of commands" ); -Event EV_Client_SetAlpha("alpha", EV_DEFAULT, "f", "alpha", "Set the alpha of the spawned tempmodel"); -Event EV_Client_SetDieTouch( - "dietouch", EV_DEFAULT, NULL, NULL, "Set the spawned tempmodels to die when they touch a solid" +Event EV_Client_EndBlock +( + ")", + EV_DEFAULT, + NULL, + NULL, + "Signals the end of a block of commands" +); +Event EV_Client_EmitterStartOff +( + "startoff", + EV_DEFAULT, + NULL, + NULL, + "Signals an emitter to start in the off state (no tempmodels are emitted)" +); +Event EV_Client_SetAlpha +( + "alpha", + EV_DEFAULT, + "f", + "alpha", + "Set the alpha of the spawned tempmodel" +); +Event EV_Client_SetDieTouch +( + "dietouch", + EV_DEFAULT, + NULL, + NULL, + "Set the spawned tempmodels to die when they touch a solid" ); Event EV_Client_SetBounceFactor( "bouncefactor", @@ -67,15 +100,46 @@ Event EV_Client_SetBounceSound( "sound [delay]", "When bouncing, what sound to play on impact and an option delay (default is 1 second) between playing this sound" ); -Event EV_Client_SetBounceSoundOnce( - "bouncesoundonce", EV_DEFAULT, "s", "sound", "When bouncing, what sound to play on impact one time" +Event EV_Client_SetBounceSoundOnce +( + "bouncesoundonce", + EV_DEFAULT, + "s", + "sound", + "When bouncing, what sound to play on impact one time" ); -Event EV_Client_SetScale("scale", EV_DEFAULT, "f", "scale", "Set the scale of a spawned tempmodel"); -Event EV_Client_SetScaleUpDown( - "scaleupdown", EV_DEFAULT, NULL, NULL, "Set the tempmodel to scale up to scale value and then down." +Event EV_Client_SetScale +( + "scale", + EV_DEFAULT, + "f", + "scale", + "Set the scale of a spawned tempmodel" +); +Event EV_Client_SetScaleUpDown +( + "scaleupdown", + EV_DEFAULT, + NULL, + NULL, + "Set the tempmodel to scale up to scale value and then down." +); +Event EV_Client_SetScaleMin +( + "scalemin", + EV_DEFAULT, + "f", + "scalemin", + "Set the minimum scale of a spawned tempmodel" +); +Event EV_Client_SetScaleMax +( + "scalemax", + EV_DEFAULT, + "f", + "scalemax", + "Set the maximum scale of a spawned tempmodel" ); -Event EV_Client_SetScaleMin("scalemin", EV_DEFAULT, "f", "scalemin", "Set the minimum scale of a spawned tempmodel"); -Event EV_Client_SetScaleMax("scalemax", EV_DEFAULT, "f", "scalemax", "Set the maximum scale of a spawned tempmodel"); Event EV_Client_SetModel( "model", EV_DEFAULT, @@ -84,9 +148,21 @@ Event EV_Client_SetModel( "Set the modelname of the tempmodel. If more than 1 model is specified, it will\n" "be randomly chosen when spawned" ); -Event EV_Client_SetLife("life", EV_DEFAULT, "f", "life", "Set the life (in seconds) of the spawned tempmodel"); -Event EV_Client_SetColor( - "color", EV_DEFAULT, "fffF", "red green blue alpha", "Set the color (modulate) of the spawned tempmodel." +Event EV_Client_SetLife +( + "life", + EV_DEFAULT, + "f", + "life", + "Set the life (in seconds) of the spawned tempmodel" +); +Event EV_Client_SetColor +( + "color", + EV_DEFAULT, + "fffF", + "red green blue alpha", + "Set the color (modulate) of the spawned tempmodel." ); Event EV_Client_SetRadialVelocity( "radialvelocity", @@ -96,16 +172,32 @@ Event EV_Client_SetRadialVelocity( "Subtracts the particle origin from origin and multiplies by scale, then adds additional velocity\n" "between min and max... negative values bring toward origin\n" ); -Event EV_Client_SetVelocity( - "velocity", EV_DEFAULT, "f", "forwardVelocity", "Set the forward velocity of the spawned tempmodel" +Event EV_Client_SetVelocity +( + "velocity", + EV_DEFAULT, + "f", + "forwardVelocity", + "Set the forward velocity of the spawned tempmodel" ); -Event EV_Client_SetAngularVelocity( - "avelocity", EV_DEFAULT, "fff", "yawVel pitchVel rollVel", "Set the angular velocity of the spawned tempmodel" +Event EV_Client_SetAngularVelocity +( + "avelocity", + EV_DEFAULT, + "fff", + "yawVel pitchVel rollVel", + "Set the angular velocity of the spawned tempmodel" ); -Event EV_Client_SetColorVelocity( - "colorvelocity", EV_DEFAULT, "fff", "rVel gVel bVel", "Set the color velocity of the spawned dlight tempmodel" +Event EV_Client_SetColorVelocity +( + "colorvelocity", + EV_DEFAULT, + "fff", + "rVel gVel bVel", + "Set the color velocity of the spawned dlight tempmodel" ); -Event EV_Client_SetRandomVelocity( +Event EV_Client_SetRandomVelocity +( "randvel", EV_DEFAULT, "SfFSfFSfF", @@ -119,7 +211,8 @@ Event EV_Client_SetRandomVelocity( "without randomness.\n" "This velocity is applied using the world axis" ); -Event EV_Client_SetRandomVelocityAlongAxis( +Event EV_Client_SetRandomVelocityAlongAxis +( "randvelaxis", EV_DEFAULT, "SfFSfFSfF", @@ -134,7 +227,16 @@ Event EV_Client_SetRandomVelocityAlongAxis( "without randomness.\n" "This velocity is applied using the parent axis" ); -Event EV_Client_SetAccel( +Event EV_Client_NoTagAxis +( + "notagaxis", + EV_DEFAULT, + NULL, + NULL, + "Forces the effect to use the model's orientation for randvelaxis and offsetalongaxis" +); +Event EV_Client_SetAccel +( "accel", EV_DEFAULT, "fff", @@ -150,7 +252,8 @@ Event EV_Client_SetFriction( "Set the friction as a fraction of velocity per second... exact effect depends on physics rate:\n" "slowdown per second = [1 - (friction / physicsrate)] ^ physicsrate; physicsrate defaults to 10" ); -Event EV_Client_SetSpin( +Event EV_Client_SetSpin +( "spin", EV_DEFAULT, "f", @@ -160,8 +263,13 @@ Event EV_Client_SetSpin( Event EV_Client_SetVaryColor( "varycolor", EV_DEFAULT, NULL, NULL, "Sets the color to vary by 0 to -20% of specified color" ); -Event EV_Client_SetSmokeParms( - "smokeparms", EV_DEFAULT, "fff", "typeinfo fademult scalemult", "Sets some misc parms for smoke" +Event EV_Client_SetSmokeParms +( + "smokeparms", + EV_DEFAULT, + "fff", + "typeinfo fademult scalemult", + "Sets some misc parms for smoke" ); Event EV_Client_SetCount( "count", @@ -172,18 +280,45 @@ Event EV_Client_SetCount( "This is only used for the originspawn and tagspawn commands,\n" "and not for emitters, use spawnrate instead" ); -Event EV_Client_SetFade("fade", EV_DEFAULT, NULL, NULL, "Set the tempmodel to fade out over it's life"); -Event EV_Client_SetFadeDelay("fadedelay", EV_DEFAULT, "f", "time", "Set the amount of time to delay a fade"); -Event EV_Client_SetFadeIn("fadein", EV_DEFAULT, "f", "time", "Set the tempmodel to fade in over the specified time"); -Event EV_Client_SetTwinkle( +Event EV_Client_SetFade +( + "fade", + EV_DEFAULT, + NULL, + NULL, + "Set the tempmodel to fade out over it's life" +); +Event EV_Client_SetFadeDelay +( + "fadedelay", + EV_DEFAULT, + "f", + "time", + "Set the amount of time to delay a fade" +); +Event EV_Client_SetFadeIn +( + "fadein", + EV_DEFAULT, + "f", + "time", + "Set the tempmodel to fade in over the specified time" +); +Event EV_Client_SetTwinkle +( "twinkle", EV_DEFAULT, "ffff", "mintimeoff maxtimeoff mintimeon maxtimeon", "Set the tempmodel to twinkle with the specified settings" ); -Event EV_Client_SetTrail( - "trail", EV_DEFAULT, "sssf", "shader startTag endTag life", "Set the tempmodel to have a swipe that follows it" +Event EV_Client_SetTrail +( + "trail", + EV_DEFAULT, + "sssf", + "shader startTag endTag life", + "Set the tempmodel to have a swipe that follows it" ); Event EV_Client_SetSpawnRange( "spawnrange", @@ -193,7 +328,8 @@ Event EV_Client_SetSpawnRange( "Sets the range in which this effect will spawn tempmodels. If one number is specified, it is the max range\n" "and 0 is the min range; if two numbers are specified, the larger is the max range.\n" ); -Event EV_Client_SetSpawnRate( +Event EV_Client_SetSpawnRate +( "spawnrate", EV_DEFAULT, "f", @@ -223,7 +359,8 @@ Event EV_Client_SetScaleRate( "Set the scaling rate of the spawned tempmodel\n" "If a negative rate is used, the model will shrink" ); -Event EV_Client_SetCircle( +Event EV_Client_SetCircle +( "circle", EV_DEFAULT, NULL, @@ -250,10 +387,16 @@ Event EV_Client_SetInwardSphere( "spehere radius and some velocity so the models look like they're heading toward the\n" "center of the sphere." ); -Event EV_Client_SetRadius( - "radius", EV_DEFAULT, "f", "radius", "Set the radius of the sphere for the inwardsphere amd sphere settings" +Event EV_Client_SetRadius +( + "radius", + EV_DEFAULT, + "f", + "radius", + "Set the radius of the sphere for the inwardsphere amd sphere settings" ); -Event EV_Client_SetSwarm( +Event EV_Client_SetSwarm +( "swarm", EV_DEFAULT, "iff", @@ -273,15 +416,24 @@ Event EV_Client_SetWavy( "If random is specified, the distance is between 0 and +specified distance\n" "If crandom is specified, the distance is between -specified and +specified distance" ); -Event EV_Client_SetAlign("align", EV_DEFAULT, NULL, NULL, "Align the tempmodels to the direction they are traveling"); -Event EV_Client_SetAlignOnce( +Event EV_Client_SetAlign +( + "align", + EV_DEFAULT, + NULL, + NULL, + "Align the tempmodels to the direction they are traveling" +); +Event EV_Client_SetAlignOnce +( "alignonce", EV_DEFAULT, NULL, NULL, "Align the tempmodels to the direction they are traveling at the time they are initialized" ); -Event EV_Client_SetFlickerAlpha( +Event EV_Client_SetFlickerAlpha +( "flicker", EV_DEFAULT, NULL, @@ -296,7 +448,8 @@ Event EV_Client_SetCollision( "Turn on collision for the tempmodel.\n" "If the keyword water is specified, then the tempmodel will collide with water" ); -Event EV_Client_TagSpawn( +Event EV_Client_TagSpawn +( "tagspawn", EV_DEFAULT, "s", @@ -312,7 +465,8 @@ Event EV_Client_TagSpawnLinked( "Spawn tempmodels from the specified tag, linked to the entity at the tag.\n" "This command is followed by a ( to specify a block of commands that modify the tempmodels" ); -Event EV_Client_OriginSpawn( +Event EV_Client_OriginSpawn +( "originspawn", EV_DEFAULT, NULL, @@ -320,7 +474,8 @@ Event EV_Client_OriginSpawn( "Spawn tempmodels from the origin.\n" "This command is followed by a ( to specify a block of commands that modify the tempmodels" ); -Event EV_Client_OriginBeamSpawn( +Event EV_Client_OriginBeamSpawn +( "originbeamspawn", EV_DEFAULT, NULL, @@ -328,7 +483,8 @@ Event EV_Client_OriginBeamSpawn( "Spawn a beam from the origin.\n" "This command is followed by a ( to specify a block of commands that modify the beam" ); -Event EV_Client_OriginBeamEmitter( +Event EV_Client_OriginBeamEmitter +( "originbeamemitter", EV_DEFAULT, NULL, @@ -336,7 +492,8 @@ Event EV_Client_OriginBeamEmitter( "Spawn beams from the origin.\n" "This command is followed by a ( to specify a block of commands that modify the beam" ); -Event EV_Client_TagEmitter( +Event EV_Client_TagEmitter +( "tagemitter", EV_DEFAULT, "ss", @@ -344,7 +501,8 @@ Event EV_Client_TagEmitter( "Create an emitter that spawns tempmodels from the specified tag.\n" "This command is followed by a ( to specify a block of commands that modify the tempmodels" ); -Event EV_Client_OriginEmitter( +Event EV_Client_OriginEmitter +( "originemitter", EV_DEFAULT, "s", @@ -352,54 +510,118 @@ Event EV_Client_OriginEmitter( "Create an emitter that spawns tempmodels from the origin.\n" "This command is followed by a ( to specify a block of commands that modify the tempmodels" ); -Event EV_Client_EmitterOn("emitteron", EV_DEFAULT, "s", "emitterName", "Turn the specified emitter on"); -Event EV_Client_EmitterOff("emitteroff", EV_DEFAULT, "s", "emitterName", "Turn the specified emitter off"); -Event EV_Client_Sound( +Event EV_Client_EmitterOn +( + "emitteron", + EV_DEFAULT, + "s", + "emitterName", + "Turn the specified emitter on" +); +Event EV_Client_EmitterOff +( + "emitteroff", + EV_DEFAULT, + "s", + "emitterName", + "Turn the specified emitter off" +); +Event EV_Client_Sound +( "sound", EV_DEFAULT, "sSFFFFS", "soundName channelName volume min_distance pitch randompitch randomvolume argstype", "Play the specified sound" ); -Event EV_Set_Current_Tiki( +Event EV_Set_Current_Tiki +( "settiki", EV_DEFAULT, "s", "settiki tikiname - all subsequent events are applied to this tiki", "sets the tiki the aliases should be on in the sound uberfile" ); -Event EV_Client_StopSound("stopsound", EV_DEFAULT, "i", "channel", "Stops the sound on the specified channel."); -Event EV_Client_StopAliasChannel( - "stopaliaschannel", EV_DEFAULT, "s", "alias", "Stops the sound channel used by the specified alias." +Event EV_Client_StopSound +( + "stopsound", + EV_DEFAULT, + "i", + "channel", + "Stops the sound on the specified channel." ); -Event EV_Client_LoopSound( - "loopsound", EV_DEFAULT, "sFFf", "soundName volume min_distance pitch", "Play the specifed sound as a looping sound" +Event EV_Client_StopAliasChannel +( + "stopaliaschannel", + EV_DEFAULT, + "s", + "alias", + "Stops the sound channel used by the specified alias." ); -Event EV_Client_Cache("cache", EV_CACHE, "s", "resourceName", "Cache the specified resource"); -Event EV_Client_CacheImage( +Event EV_Client_LoopSound +( + "loopsound", + EV_DEFAULT, + "sFFf", + "soundName volume min_distance pitch", + "Play the specified sound as a looping sound" +); +// Added in 2.0 +Event EV_Client_StopLoopSound +( + "stoploopsound", + EV_DEFAULT, + NULL, + NULL, + "Stop the looping sound" +); +Event EV_Client_Cache +( + "cache", + EV_CACHE, + "s", + "resourceName", + "Cache the specified resource" +); +Event EV_Client_CacheImage +( "cacheimage", EV_CACHE, "s", "imageName", "Cache the specified image (For menu graphics that should never be picmiped)" ); -Event EV_Client_CacheFont("cachefont", EV_CACHE, "s", "resourceName", "Cache the specified resource"); -Event EV_Client_AliasCache( +Event EV_Client_CacheFont +( + "cachefont", + EV_CACHE, + "s", + "resourceName", + "Cache the specified resource" +); +Event EV_Client_AliasCache +( "aliascache", EV_DEFAULT, "ssSSSSSS", "alias realPath arg1 arg2 arg3 arg4 arg5 arg6", "Create an alias to the specified path and cache the resource" ); -Event EV_Client_Alias( +Event EV_Client_Alias +( "alias", EV_DEFAULT, "ssSSSSSS", "alias realPath arg1 arg2 arg3 arg4 arg5 arg6", "Create an alias to the specified path" ); -Event EV_Client_CacheAlias( - "cachefromalias", EV_DEFAULT, "s", "alias", "Caches all data matching a previously specified alias" +Event EV_Client_CacheAlias +( + "cachefromalias", + EV_DEFAULT, + "s", + "alias", + "Caches all data matching a previously specified alias" ); Event EV_Client_Footstep( "footstep", @@ -409,22 +631,29 @@ Event EV_Client_Footstep( "Play a footstep sound that is appropriate to the surface we are currently stepping on\n" "sRunning should be set to run, walk, or ladder" ); -Event EV_Client_Landing( - "footstep", +Event EV_Client_Landing +( + "landing", EV_DEFAULT, "FI", "fVolume iEquipment", "Play a landing sound that is appropriate to the surface we are landing on\n" ); -Event EV_Client_BodyFall( +Event EV_Client_BodyFall +( "bodyfall", EV_DEFAULT, "F", "fVolume", "Play a body fall sound that is appropriate to the surface we are falling on\n" ); -Event EV_Client_Client( - "client", EV_DEFAULT, "SSSSSS", "arg1 arg2 arg3 arg4 arg5 arg6", "Execute the specified command arg string" +Event EV_Client_Client +( + "client", + EV_DEFAULT, + "SSSSSS", + "arg1 arg2 arg3 arg4 arg5 arg6", + "Execute the specified command arg string" ); Event EV_Client_OriginDynamicLight( "origindlight", @@ -466,15 +695,36 @@ Event EV_Client_BlockDynamicLight( "The intensity is the radius of the light\n" "type is the type of light to create (lensflare,viewlensflare,additive)" ); -Event EV_Client_SetEntityColor( - "entcolor", EV_DEFAULT, "fffF", "red green blue alpha", "Set the color(modulate) of this entity" +Event EV_Client_SetEntityColor +( + "entcolor", + EV_DEFAULT, + "fffF", + "red green blue alpha", + "Set the color(modulate) of this entity" ); -Event EV_Client_SetTexAnimTime("texanimtime", EV_DEFAULT, "f", "time", "Set the texture animation speed"); -Event EV_Client_SetGlobalFade( - "globalfade", EV_DEFAULT, "S", "[in|out]", "Set the tempmodels to globally fade in or out together" +Event EV_Client_SetTexAnimTime +( + "texanimtime", + EV_DEFAULT, + "f", + "time", + "Set the texture animation speed" ); -Event EV_Client_SetParentLink( - "parentlink", EV_DEFAULT, NULL, NULL, "Set the tempmodels linked to the parent, so they move with the parent model" +Event EV_Client_SetGlobalFade +( + "globalfade", + EV_DEFAULT, + "S", + "[in|out]", + "Set the tempmodels to globally fade in or out together" +); +Event EV_Client_SetParentLink +( + "parentlink", EV_DEFAULT, + NULL, + NULL, + "Set the tempmodels linked to the parent, so they move with the parent model" ); Event EV_Client_SetHardLink( "hardlink", @@ -483,11 +733,24 @@ Event EV_Client_SetHardLink( NULL, "Set the tempmodels linked to the model they are spawned from, so they move with it" ); -Event EV_Client_SetRandomRoll( - "randomroll", EV_DEFAULT, NULL, NULL, "Set the tempmodels so they pick a random roll value every frame" +Event EV_Client_SetRandomRoll +( + "randomroll", + EV_DEFAULT, + NULL, + NULL, + "Set the tempmodels so they pick a random roll value every frame" ); -Event EV_Client_ParentAngles("parentangles", EV_DEFAULT, NULL, NULL, "Set the tempmodels angles to that of its parent"); -Event EV_Client_EmitterAngles( +Event EV_Client_ParentAngles +( + "parentangles", + EV_DEFAULT, + NULL, + NULL, + "Set the tempmodels angles to that of its parent" +); +Event EV_Client_EmitterAngles +( "emitterangles", EV_DEFAULT, "FFF", @@ -506,46 +769,109 @@ Event EV_Client_SetAngles( "from the first number to the first number plus the second number.\n" "If no keyword is explicitly specified, then the component will be just set\n" ); -Event EV_Client_SetRelativeAngles( +Event EV_Client_SetRelativeAngles +( "relativeangles", EV_DEFAULT, "", "", "makes the spawn angles get applied relative to the orientation of the model" ); -Event EV_Client_Swipe("swipe", EV_DEFAULT, "V", "origin", "Do a swipe and add it on to the swipe rendering list."); -Event EV_Client_SwipeOn( +Event EV_Client_Swipe +( + "swipe", + EV_DEFAULT, + "V", + "origin", + "Do a swipe and add it on to the swipe rendering list." +); +Event EV_Client_SwipeOn +( "swipeon", EV_DEFAULT, "ssff", "shader startTagName endTagNamelife life", "Signal the start of a swipe from the current tag" ); -Event EV_Client_SwipeOff("swipeoff", EV_DEFAULT, NULL, NULL, "Signal the end of a swipe"); -Event EV_Client_BeginTagBeamEmitter( +Event EV_Client_SwipeOff +( + "swipeoff", + EV_DEFAULT, + NULL, + NULL, + "Signal the end of a swipe" +); +Event EV_Client_BeginTagBeamEmitter +( "tagbeamemitter", EV_DEFAULT, "sss", "tagstart tagend name", "Create a beam emitter that uses 2 tags to determine it's start and end position" ); -Event EV_Client_BeginTagBeamSpawn( +Event EV_Client_BeginTagBeamSpawn +( "tagbeamspawn", EV_DEFAULT, "sf", "tagstart name", "Create a beam emitter that uses the tag to determine it's starting position." ); -Event EV_Client_AnimateOnce( - "animateonce", EV_DEFAULT, NULL, NULL, "Set a tempmodel to animate once and then get removed" +Event EV_Client_AnimateOnce +( + "animateonce", + EV_DEFAULT, + NULL, + NULL, + "Set a tempmodel to animate once and then get removed" ); -Event EV_Client_SetAnim("anim", EV_DEFAULT, "s", "animation", "Set a tempmodel the the specified animation"); -Event EV_Client_SetSubdivisions("numsegments", EV_DEFAULT, "i", "numsegments", "Set the number of segments in a beam"); -Event EV_Client_SetMinOffset("minoffset", EV_DEFAULT, "f", "minoffset", "Set the minimum offset from center in a beam"); -Event EV_Client_SetMaxOffset("maxoffset", EV_DEFAULT, "f", "maxoffset", "Set the maximum offset from center in a beam"); -Event EV_Client_SetBeamShader("beamshader", EV_DEFAULT, "s", "shadername", "Set the shader to use for the beam"); -Event EV_Client_SetBeamLength( - "beamlength", EV_DEFAULT, "f", "length", "Set the length of the beam or trace length (for decals)" +Event EV_Client_SetAnim +( + "anim", + EV_DEFAULT, + "s", + "animation", + "Set a tempmodel the the specified animation" +); +Event EV_Client_SetSubdivisions +( + "numsegments", + EV_DEFAULT, + "i", + "numsegments", + "Set the number of segments in a beam" +); +Event EV_Client_SetMinOffset +( + "minoffset", + EV_DEFAULT, + "f", + "minoffset", + "Set the minimum offset from center in a beam" +); +Event EV_Client_SetMaxOffset +( + "maxoffset", + EV_DEFAULT, + "f", + "maxoffset", + "Set the maximum offset from center in a beam" +); +Event EV_Client_SetBeamShader +( + "beamshader", + EV_DEFAULT, + "s", + "shadername", + "Set the shader to use for the beam" +); +Event EV_Client_SetBeamLength +( + "beamlength", + EV_DEFAULT, + "f", + "length", + "Set the length of the beam or trace length (for decals)" ); Event EV_Client_SetBeamDelay( "beamdelay", @@ -564,26 +890,45 @@ Event EV_Client_SetBeamToggleDelay( "If the keyword random is specified, the delay between toggling will occur randomly between 0 and the time " "specified" ); -Event EV_Client_SetBeamPersist("beampersist", EV_DEFAULT, NULL, NULL, "Make the beams persist instead of blinking out"); -Event EV_Client_SetBeamOffsetEndpoints( - "beam_offset_endpoints", EV_DEFAULT, NULL, NULL, "Make the beams endpoints offset to reduce the bunching up effect" +Event EV_Client_SetBeamPersist +( + "beampersist", + EV_DEFAULT, + NULL, + NULL, + "Make the beams persist instead of blinking out" ); -Event EV_Client_BeamSphere( +Event EV_Client_SetBeamOffsetEndpoints +( + "beam_offset_endpoints", + EV_DEFAULT, + NULL, + NULL, + "Make the beams endpoints offset to reduce the bunching up effect" +); +Event EV_Client_BeamSphere +( "beamsphere", EV_DEFAULT, "i", "count", "Create a sphere shaped beam effect from the origin. Count is the number of beams" ); -Event EV_Client_Spread( +Event EV_Client_Spread +( "spread", EV_DEFAULT, "ff", "spreadx spready", "Add a random variance in the spawned beam in the forward direction by the amound specified in spreadx and spready" ); -Event EV_Client_UseLastTraceEnd( - "uselasttraceend", EV_DEFAULT, NULL, NULL, "Makes this trace command use the end results of the last trace command" +Event EV_Client_UseLastTraceEnd +( + "uselasttraceend", + EV_DEFAULT, + NULL, + NULL, + "Makes this trace command use the end results of the last trace command" ); Event EV_Client_OffsetAlongAxis( "offsetalongaxis", @@ -599,22 +944,32 @@ Event EV_Client_OffsetAlongAxis( "without randomness.\n" "This offset is applied using the model's local axis" ); -Event EV_Client_Cone( +Event EV_Client_Cone +( "cone", EV_DEFAULT, "ff", "height radius", "Randomly spawns the particle somewhere inside a cone along the model's local x axis" ); -Event EV_Client_SetEndAlpha("endalpha", EV_DEFAULT, "f", "alpha", "Set the alpha of the beam's endpoint"); -Event EV_Client_RandomChance( +Event EV_Client_SetEndAlpha +( + "endalpha", + EV_DEFAULT, + "f", + "alpha", + "Set the alpha of the beam's endpoint" +); +Event EV_Client_RandomChance +( "randomchance", EV_DEFAULT, "fSSSSSS", "percentage [arg1] [arg2] [arg3] [arg4] [arg5] [arg6]", "Set the percentage chance that command will occur" ); -Event EV_Client_DelayedRepeat( +Event EV_Client_DelayedRepeat +( "delayedrepeat", EV_DEFAULT, "fiSSSSSS", @@ -623,7 +978,8 @@ Event EV_Client_DelayedRepeat( "This is internally used to keep track of the commands this entity executes and will resolve naming conflicts.\n" "This is only useful if the command gets called continuously but must execute at regular intervals.\n" ); -Event EV_Client_CommandDelay( +Event EV_Client_CommandDelay +( "commanddelay", EV_DEFAULT, "fiSSSSSS", @@ -638,25 +994,51 @@ Event EV_Client_BounceDecal( "maxamount temporary", "Put a mark when the tempmodel bounces and hits a surface\n" "maxamount = Max amount of decals to make when bouncing\n" - "temporary = specify 1 for a temporary mark that only appears for a short time, 0 for a decal that stays aroung " + "temporary = specify 1 for a temporary mark that only appears for a short time, 0 for a decal that stays around " "longer (default is 0)\n" ); -Event EV_Client_SetDecalRadius("decalradius", EV_DEFAULT, "f", "radius", "Set the radius of the decal"); -Event EV_Client_SetDecalOrientation( +Event EV_Client_SetDecalRadius +( + "decalradius", + EV_DEFAULT, + "f", + "radius", + "Set the radius of the decal" +); +Event EV_Client_SetDecalOrientation +( "orientation", EV_DEFAULT, "f", "degrees", "Set the degrees to orient the decal. Specify 'random' to use a random orientation" ); -Event EV_Client_SetDecalShader( - "decalshader", EV_DEFAULT, "s", "shadername", "Set the shader to use for the impact decal" +Event EV_Client_SetDecalShader +( + "decalshader", + EV_DEFAULT, + "s", + "shadername", + "Set the shader to use for the impact decal" ); -Event EV_Client_SetTraceLength("tracelength", EV_DEFAULT, "f", "length", "Set the length of the trace for the decal"); -Event EV_Client_TraceSpawn( - "tracespawn", EV_DEFAULT, "s", "modelname", "Spawn the specified model when the trace hits a solid object" +Event EV_Client_SetTraceLength +( + "tracelength", + EV_DEFAULT, + "f", + "length", + "Set the length of the trace for the decal" ); -Event EV_Client_TagList( +Event EV_Client_TraceSpawn +( + "tracespawn", + EV_DEFAULT, + "s", + "modelname", + "Spawn the specified model when the trace hits a solid object" +); +Event EV_Client_TagList +( "taglist", EV_DEFAULT, "ssSSSSSS", @@ -671,71 +1053,137 @@ Event EV_Client_Lightstyle( "Set a lightstyle to determine the color of this tempmodel, the image\n" "specified is used to determine the look of the light style" ); -Event EV_Client_PhysicsRate( +Event EV_Client_PhysicsRate +( "physicsrate", EV_DEFAULT, "s", "rate", "Set the rate (in updates per second) for the tempmodel's physics to be updated" + ); -Event EV_Client_Parallel("parallel", EV_DEFAULT, NULL, NULL, "Set tempmodel to be parallel to the viewer"); -Event EV_Client_AlwaysDraw( +Event EV_Client_Parallel +( + "parallel", + EV_DEFAULT, + NULL, + NULL, + "Set tempmodel to be parallel to the viewer" +); +Event EV_Client_AlwaysDraw +( "alwaysdraw", EV_DEFAULT, NULL, NULL, "Set emitter/tempmodel to be alwaysdraw. Which can be turned off by alwaysdraw" ); -Event EV_Client_Detail( - "detail", EV_DEFAULT, NULL, NULL, "Set emitter/tempmodel to be detail. Which can be turned off by detail" +Event EV_Client_Detail +( + "detail", + EV_DEFAULT, + NULL, + NULL, + "Set emitter/tempmodel to be detail. Which can be turned off by detail" ); -Event EV_Client_Print("print", EV_DEFAULT, "s", "string", "Prints a string."); -Event EV_Client_SetVolumetric( - "volumetric", EV_DEFAULT, NULL, NULL, "Set the effect to spawn volumetric sources rather than tempmodels" +Event EV_Client_Print +( + "print", + EV_DEFAULT, + "s", + "string", + "Prints a string." +); +// Added in 2.0 +Event EV_Client_PrintDeathMsg +( + "printdeathmsg", + EV_DEFAULT, + "sssss", + "msg1, msg2, killer, victim, deathType", + "Prints a death message string. Used to allow death messages to appear in their correct language on client machines.." +); +Event EV_Client_SetVolumetric +( + "volumetric", + EV_DEFAULT, + NULL, + NULL, + "Set the effect to spawn volumetric sources rather than tempmodels" +); +Event EV_Client_Wind +( + "wind", + EV_DEFAULT, + NULL, + NULL, + "Makes the temp model be affected by wind" +); +Event EV_Client_SpriteGridLighting +( + "spritegridlighting", + EV_DEFAULT, + NULL, + NULL, + "Calculates grid lighting for a sprite" +); +Event EV_Client_WaterOnly +( + "wateronly", + EV_DEFAULT, + NULL, + NULL, + "makes the temp model remove itself if it leaves water" ); -Event EV_Client_Wind("wind", EV_DEFAULT, NULL, NULL, "Makes the temp model be affected by wind"); -Event - EV_Client_SpriteGridLighting("spritegridlighting", EV_DEFAULT, NULL, NULL, "Calculates grid lighting for a sprite"); -Event EV_Client_WaterOnly("wateronly", EV_DEFAULT, NULL, NULL, "makes the temp model remove itself if it leaves water"); Event EV_Client_SetAlignStretch( "alignstretch", EV_DEFAULT, "F", "scaleMultiplier", - "Aligns the temp model to the direction of travel, and stretches it betwen the last and current positions.\n" + "Aligns the temp model to the direction of travel, and stretches it between the last and current positions.\n" ); -Event EV_Client_SetClampVelocity( +Event EV_Client_SetClampVelocity +( "clampvel", EV_DEFAULT, "ffffff", "minX maxX minY maxY minZ maxZ", "sets the valid range for velocities along global axes. Cannot be used with clampvelaxis." ); -Event EV_Client_SetClampVelocityAxis( +Event EV_Client_SetClampVelocityAxis +( "clampvelaxis", EV_DEFAULT, "ffffff", "minX maxX minY maxY minZ maxZ", "sets the valid range for velocities along oriented axes. Cannot be used with clampvel." ); -Event EV_Client_Treads( +Event EV_Client_Treads +( "treads", EV_DEFAULT, "ssi", "tagName shader localrefnumber", "Spawn treads from the specified tag using the specified tread type." ); -Event EV_Client_Treads_Off( - "treadsoff", EV_DEFAULT, "si", "tagName localrefnumber", "Stops spawning treads from the specified tag." +Event EV_Client_Treads_Off +( + "treadsoff", + EV_DEFAULT, + "si", + "tagName localrefnumber", + "Stops spawning treads from the specified tag." ); -Event EV_Client_ViewKick( +Event EV_Client_ViewKick +( "viewkick", EV_DEFAULT, "fffffsff", "pitchmin pitchmax yawmin yawmax recenterspeed patters pitchmax yawmax scatterpitchmax", "Adds kick to the view of the owner when fired." ); -Event EV_Client_EyeLimits( +Event EV_Client_EyeLimits +( "eyelimits", EV_DEFAULT, "fff", @@ -749,20 +1197,30 @@ Event EV_Client_EyeMovement( "fMovement", "Sets the amount of the head's movement to apply to the players view. 1 is full, 0 is none" ); -Event EV_Client_SFXStart( +Event EV_Client_SFXStart +( "sfx", EV_DEFAULT, "sSSSSSSSS", "sCommand arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8", "Used for adding commands to a special effect" ); -Event EV_Client_SFXStartDelayed( +Event EV_Client_SFXStartDelayed +( "delayedsfx", EV_DEFAULT, "fsSSSSSSSS", "fDelay sCommand arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8", "Used for adding commands to a special effect with a time delay" ); +Event EV_Client_PlayForceFeedback +( + "playforcefeedback", + EV_DEFAULT, + "s", + "effectname", + "Starts a force feedback effect." +); EffectsEventQueueNode EffectsEventQueue; @@ -799,6 +1257,7 @@ CLASS_DECLARATION(Listener, ClientGameCommandManager, NULL) { {&EV_Client_SetColorVelocity, &ClientGameCommandManager::SetAngularVelocity }, {&EV_Client_SetRandomVelocity, &ClientGameCommandManager::SetRandomVelocity }, {&EV_Client_SetRandomVelocityAlongAxis, &ClientGameCommandManager::SetRandomVelocityAlongAxis}, + {&EV_Client_NoTagAxis, &ClientGameCommandManager::SetNoTagAxis }, {&EV_Client_SetAccel, &ClientGameCommandManager::SetAccel }, {&EV_Client_SetFriction, &ClientGameCommandManager::SetFriction }, {&EV_Client_SetSpin, &ClientGameCommandManager::SetSpin }, @@ -828,6 +1287,7 @@ CLASS_DECLARATION(Listener, ClientGameCommandManager, NULL) { {&EV_Client_StopSound, &ClientGameCommandManager::StopSound }, {&EV_Client_StopAliasChannel, &ClientGameCommandManager::StopAliasChannel }, {&EV_Client_LoopSound, &ClientGameCommandManager::LoopSound }, + {&EV_Client_StopLoopSound, &ClientGameCommandManager::StopLoopSound }, {&EV_Client_Cache, &ClientGameCommandManager::Cache }, {&EV_Client_CacheImage, &ClientGameCommandManager::CacheImage }, {&EV_Client_CacheFont, &ClientGameCommandManager::CacheFont }, @@ -890,6 +1350,7 @@ CLASS_DECLARATION(Listener, ClientGameCommandManager, NULL) { {&EV_Client_SetClampVelocity, &ClientGameCommandManager::SetClampVel }, {&EV_Client_SetClampVelocityAxis, &ClientGameCommandManager::SetClampVelAxis }, {&EV_Client_Print, &ClientGameCommandManager::Print }, + {&EV_Client_PrintDeathMsg, &ClientGameCommandManager::PrintDeathMsg }, {&EV_Client_EyeLimits, &ClientGameCommandManager::SetEyeLimits }, {&EV_Client_EyeMovement, &ClientGameCommandManager::SetEyeMovement }, {&EV_Client_SFXStart, &ClientGameCommandManager::StartSFX }, @@ -961,9 +1422,11 @@ qboolean ClientGameCommandManager::PostEventForEntity(Event *ev, float fWait) EffectsEventQueueNode *node; int inttime; - if (!m_fEventWait || current_entity_number < 0) { - if (!str::icmp(ev->getName(), ")")) { - m_fEventWait = 0.0; + if (m_fEventWait < 0 || current_entity_number < 0) { + if (m_fEventWait != 0.0) { + if (!str::icmp(ev->getName(), ")")) { + m_fEventWait = 0.0; + } } delete ev; @@ -980,7 +1443,7 @@ qboolean ClientGameCommandManager::PostEventForEntity(Event *ev, float fWait) event = EffectsEventQueue.next; inttime = EVENT_msec + (fWait * 1000.0f + 0.5f); - while (event != &EffectsEventQueue && inttime > event->inttime) { + while (event != &EffectsEventQueue && inttime >= event->inttime) { event = event->next; } @@ -1016,8 +1479,8 @@ void ClientGameCommandManager::SetBaseAndAmplitude(Event *ev, Vector& base, Vect base[j] = ev->GetFloat(i++); amplitude[j] = ev->GetFloat(i++); } else { - base[j] = 0.0; - amplitude[j] = atof(org.c_str()); + base[j] = atof(org.c_str()); + amplitude[j] = 0.0; } } } @@ -1040,6 +1503,13 @@ void ClientGameCommandManager::Print(Event *ev) } } +void ClientGameCommandManager::PrintDeathMsg(Event* ev) +{ + if (current_entity) { + cgi.DPrintf("%d:%s\n", current_entity->entityNumber, ev->GetString(1).c_str()); + } +} + qboolean ClientGameCommandManager::IsBlockCommand(const str& name) { if (!str::icmp(name, "originspawn")) { @@ -1119,7 +1589,6 @@ void ClientGameCommandManager::CommandDelay(Event *ev) ev1->AddValue(ev->GetValue(i)); } - delay = ev->GetFloat(1) * 1000; if (current_entity_number != -1) { PostEventForEntity(ev1, fWait); } else { @@ -1129,6 +1598,16 @@ void ClientGameCommandManager::CommandDelay(Event *ev) current_tiki->name ); } + + if (IsBlockCommand(eventName)) { + m_fEventWait = fWait; + } else { + m_fEventWait = 0; + } + + if (current_entity_number == -1 && m_fEventWait > 0) { + m_fEventWait = -1; + } } void ClientGameCommandManager::StartSFX(Event *ev) @@ -1192,7 +1671,7 @@ void ClientGameCommandManager::StartSFXCommand(Event *ev, qboolean bDelayed) if (bBlockCommand) { ProcessEvent(ev1); pCommand->endfcn = endblockfcn; - endblockfcn = NULL; + endblockfcn = NULL; } else { pCommand->pEvent = ev1; } @@ -1735,7 +2214,9 @@ void ClientGameCommandManager::SetInwardSphere(Event *ev) } m_spawnthing->cgd.flags |= T_INWARDSPHERE; - m_spawnthing->sphereRadius = ev->GetFloat(1); + if (ev->NumArgs() > 0) { + m_spawnthing->sphereRadius = ev->GetFloat(1); + } } //============= @@ -2164,7 +2645,9 @@ void ClientGameCommandManager::SetColorRange(Event *ev) return; } - // FIXME: unused stub?? + // + // Unused + // } //============= @@ -2244,6 +2727,15 @@ void ClientGameCommandManager::SetRandomVelocityAlongAxis(Event *ev) SetRandomVelocity(ev); } +void ClientGameCommandManager::SetNoTagAxis(Event* ev) +{ + if (!m_spawnthing) { + return; + } + + m_spawnthing->cgd.flags2 |= T2_NOTAGAXIS; +} + void ClientGameCommandManager::SetRadialVelocity(Event *ev) { if (!m_spawnthing) { @@ -2324,7 +2816,7 @@ void ClientGameCommandManager::SetAngles(Event *ev) //============= // SetRelativeAngles //============= -void ClientGameCommandManager::SetRelativeAngles(Event* ev) +void ClientGameCommandManager::SetRelativeAngles(Event *ev) { if (!m_spawnthing) { return; @@ -2381,7 +2873,9 @@ void ClientGameCommandManager::SetAccel(Event *ev) m_spawnthing->cgd.accel[1] = ev->GetFloat(2); m_spawnthing->cgd.accel[2] = ev->GetFloat(3); - m_spawnthing->cgd.flags2 |= T2_ACCEL; + if (!(m_spawnthing->cgd.flags & T_SWARM)) { + m_spawnthing->cgd.flags2 |= T2_ACCEL; + } } void ClientGameCommandManager::SetFriction(Event *ev) @@ -2610,7 +3104,7 @@ spawnthing_t *ClientGameCommandManager::InitializeSpawnthing(spawnthing_t *sp) sp->cgd.parent = -1; sp->cgd.tiki = nullptr; sp->cgd.lightstyle = -1; - sp->cgd.physicsRate = 10; + sp->cgd.physicsRate = cg_effect_physicsrate->integer; sp->cgd.shadername = "beamshader"; sp->cgd.decal_orientation = 0; sp->cgd.decal_radius = 10; @@ -2704,8 +3198,7 @@ void ClientGameCommandManager::DeleteEmitters(dtiki_t *tiki) for (i = m_emitters.NumObjects(); i > 0; i--) { spawnthing = m_emitters.ObjectAt(i); if (spawnthing->cgd.tiki == tiki) { - m_emitters.RemoveObjectAt(i); - delete spawnthing; + FreeSpawnthing(spawnthing); } } } @@ -2739,7 +3232,9 @@ void ClientGameCommandManager::BeginOriginSpawn(Event *ev) if (!m_pCurrentSfx) { m_spawnthing = &m_localemitter; } - if (!m_spawnthing) return; + if (!m_spawnthing) { + return; + } InitializeSpawnthing(m_spawnthing); // Set the origin based on the entity's origin @@ -2997,15 +3492,16 @@ void ClientGameCommandManager::GetOrientation(int tagnum, spawnthing_t *sp) //=============== // BeginTagSpawnLinked //=============== -void ClientGameCommandManager::BeginTagSpawnLinked(Event *ev) { - str tagname; - int tagnum; - int i; +void ClientGameCommandManager::BeginTagSpawnLinked(Event *ev) +{ + str tagname; + int tagnum; + int i; orientation_t ori; // Get the tagname and orientation tagname = ev->GetString(1); - tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str()); + tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str()); if (tagnum == -1) { throw ScriptException("Tagname '%s' does not exist", tagname.c_str()); } @@ -3014,12 +3510,12 @@ void ClientGameCommandManager::BeginTagSpawnLinked(Event *ev) { endblockfcn = &ClientGameCommandManager::EndTagSpawn; // Create a new emitter - m_spawnthing = CreateNewEmitter(); - m_spawnthing->tagnum = tagnum; - m_spawnthing->entnum = current_entity->entityNumber; + m_spawnthing = CreateNewEmitter(); + m_spawnthing->tagnum = tagnum; + m_spawnthing->entnum = current_entity->entityNumber; m_spawnthing->cgd.tiki = current_tiki; m_spawnthing->cgd.flags |= T_WAVE; - m_spawnthing->cgd.origin = Vector(0, 0, 0); + m_spawnthing->cgd.origin = current_entity->origin; ori = cgi.TIKI_Orientation(current_entity, tagnum); @@ -3064,6 +3560,10 @@ void ClientGameCommandManager::BeginTagSpawn(Event *ev) //=============== void ClientGameCommandManager::EndTagSpawn(void) { + if (!m_spawnthing) { + return; + } + // Okay we should have a valid spawnthing, let's create a render entity SpawnEffect(m_spawnthing->count, 0); } @@ -3366,7 +3866,7 @@ void ClientGameCommandManager::PlaySound( } if (!name || !soundAlias) { - Com_Printf( + cgi.DPrintf( "\nERROR PlaySound: %s needs an alias in ubersound.scr or uberdialog.scr - Please fix.\n", sound_name.c_str() ); @@ -3423,7 +3923,7 @@ void ClientGameCommandManager::PlaySound( } else { if (debugSound->integer) { Com_Printf( - "\nWARNING: OVERRIDE OVERRIDE OVERRIDESound %s had all its parm overriden by code.\n\n", + "\nWARNING: OVERRIDE OVERRIDE OVERRIDESound %s had all its parm overridden by code.\n\n", sound_name.c_str() ); } @@ -3488,6 +3988,11 @@ void ClientGameCommandManager::Sound(Event *ev) float volume = -1.0; float min_distance = -1.0; + if (!current_entity) { + // don't play sound for nonexistent entities + return; + } + if (ev->NumArgs() < 1) { return; } @@ -3532,6 +4037,9 @@ void ClientGameCommandManager::StopSound(Event *ev) cgi.S_StopSound(current_entity_number, channel); } +//=============== +// StopAliasChannel +//=============== void ClientGameCommandManager::StopAliasChannel(Event *ev) { str sound_name; @@ -3558,7 +4066,7 @@ void ClientGameCommandManager::StopAliasChannel(Event *ev) } if (!name || !soundAlias) { - Com_Printf("\nERROR stopaliaschannel: couldn't find alias %s\n", sound_name.c_str()); + cgi.DPrintf("\nERROR stopaliaschannel: couldn't find alias %s\n", sound_name.c_str()); return; } @@ -3627,6 +4135,54 @@ void ClientGameCommandManager::LoopSound(Event *ev) current_centity->tikiLoopSoundFlags = 0; } +//=============== +// StopLoopSound +//=============== +void ClientGameCommandManager::StopLoopSound(Event* ev) +{ + if (!current_centity) { + cgi.DPrintf("CCM::StopLoopSound : StopLoopSound in %s without current_centity\n", cgi.TIKI_Name(current_tiki)); + return; + } + + cgi.DPrintf("\n\nClientGameCommandManager::StopLoopSound\n\n"); + current_centity->tikiLoopSound = (sfxHandle_t)0; +} + +//=============== +// CacheImageResource +//=============== +void CacheImageResource(const char* stuff) { + str real_stuff; + char filename[1024]; + + if (cgi.fsDebug->integer == 2) { + Com_Printf("client cacheimage: %s\n", stuff); + } + + Q_strncpyz(filename, stuff, sizeof(filename)); + cgi.FS_CanonicalFilename(filename); + + cgi.R_RegisterShaderNoMip(filename); +} + +//=============== +// CacheFontResource +//=============== +void CacheFontResource(const char* stuff) { + str real_stuff; + char filename[1024]; + + if (cgi.fsDebug->integer == 2) { + Com_Printf("client cacheimage: %s\n", stuff); + } + + Q_strncpyz(filename, stuff, sizeof(filename)); + cgi.FS_CanonicalFilename(filename); + + cgi.R_LoadFont(filename); +} + //=============== // CacheResource //=============== @@ -3666,12 +4222,12 @@ void ClientGameCommandManager::Cache(Event *ev) void ClientGameCommandManager::CacheImage(Event *ev) { - // FIXME: stub + CacheImageResource(ev->GetString(1).c_str()); } void ClientGameCommandManager::CacheFont(Event *ev) { - // FIXME: stub + CacheFontResource(ev->GetString(1).c_str()); } //=============== @@ -3679,15 +4235,16 @@ void ClientGameCommandManager::CacheFont(Event *ev) //=============== void AliasResource(dtiki_t *pmdl, const char *alias, const char *realname, const char *parameters) { - if (pmdl) { - if (!pmdl->a->alias_list) { - pmdl->a->alias_list = cgi.AliasList_New(pmdl->a->name); - } - - cgi.Alias_ListAdd((AliasList_t *)pmdl->a->alias_list, alias, realname, parameters); - } else { + if (!pmdl) { cgi.Alias_Add(alias, realname, parameters); + return; } + + if (!pmdl->a->alias_list) { + pmdl->a->alias_list = cgi.AliasList_New(pmdl->a->name); + } + + cgi.Alias_ListAdd((AliasList_t*)pmdl->a->alias_list, alias, realname, parameters); } qboolean bLoadForMap(const char *psMapsBuffer, const char *name) @@ -3708,7 +4265,7 @@ qboolean bLoadForMap(const char *psMapsBuffer, const char *name) } if (!token || !token[0]) { - Com_Printf("ERROR bLoadForMap: %s alias with empty maps specification.\n", name); + cgi.DPrintf("ERROR bLoadForMap: %s alias with empty maps specification.\n", name); return false; } @@ -3748,19 +4305,32 @@ void ClientGameCommandManager::AliasCache(Event *ev) psMapsBuffer = NULL; for (i = 3; i <= ev->NumArgs(); i++) { - if (!strcmp(ev->GetToken(i).c_str(), "maps")) { + str s = ev->GetString(i); + + if (!s.icmp("maps")) { i++; - psMapsBuffer = ev->GetToken(i); - } else if (!strcmp(ev->GetToken(i).c_str(), "always")) { - bAlwaysLoaded = true; - } else { - strcat(parmbuffer, ev->GetToken(i)); - strcat(parmbuffer, " "); + psMapsBuffer = (char *)ev->GetToken(i).c_str(); + continue; } + + if (!s.icmp("always")) { + bAlwaysLoaded = true; + continue; + } + + strcat(parmbuffer, s); + strcat(parmbuffer, " "); } - if (bAlwaysLoaded || bLoadForMap(psMapsBuffer, ev->GetString(1))) { + if (bAlwaysLoaded) { AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer); + } + + if (bLoadForMap(psMapsBuffer, ev->GetString(1))) { + if (!bAlwaysLoaded) { + AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer); + } + CacheResource(ev->GetString(2)); } } @@ -3790,28 +4360,33 @@ void ClientGameCommandManager::Alias(Event *ev) psMapsBuffer = NULL; for (i = 3; i <= ev->NumArgs(); i++) { - if (!strcmp(ev->GetToken(i).c_str(), "maps")) { + str s = ev->GetString(i); + + if (!s.icmp("maps")) { i++; - psMapsBuffer = ev->GetToken(i); - } else if (!strcmp(ev->GetToken(i).c_str(), "always")) { + psMapsBuffer = (char *)ev->GetToken(i).c_str(); + continue; + } + + if (!s.icmp("always")) { bAlwaysLoaded = true; + } else if (subtitle) { + strcat(parmbuffer, "\""); + strcat(parmbuffer, s); + strcat(parmbuffer, "\" "); + + subtitle = 0; } else { + subtitle = s.icmp("subtitle") == 0; + if (!subtitle) { - if (!Q_stricmp(ev->GetToken(i), "subtitle") || !Q_stricmp(ev->GetToken(i), "forcesubtitle")) { - subtitle = qtrue; - strcat(parmbuffer, ev->GetToken(i)); - } else { - strcat(parmbuffer, ev->GetToken(i)); - } - } else { - strcat(parmbuffer, "\""); - strcat(parmbuffer, ev->GetToken(i)); - strcat(parmbuffer, "\""); - subtitle = qfalse; + subtitle = s.icmp("forcesubtitle") == 0; } - strcat(parmbuffer, " "); + strcat(parmbuffer, s); } + + strcat(parmbuffer, " "); } if (bAlwaysLoaded || bLoadForMap(psMapsBuffer, ev->GetString(1))) { @@ -4274,14 +4849,11 @@ void ClientGameCommandManager::UpdateEmitter( float scale = 1.0f; int entnum; - if (current_entity) - { - scale = current_entity->scale; + if (current_entity) { + scale = current_entity->scale; entnum = current_entity->entityNumber; - } - else - { - entnum = 1023; + } else { + entnum = ENTITYNUM_NONE; } // Find the emitter associated with this model @@ -4306,17 +4878,19 @@ void ClientGameCommandManager::UpdateEmitter( if (m_spawnthing->cgd.flags & T_WAVE) { if (m_spawnthing->entnum == entnum) { orientation_t ori; - int j; + int j; // Set the default origin (spawn from the parent's origin) VectorCopy(entity_origin, m_spawnthing->cgd.origin); - + ori = cgi.TIKI_Orientation(current_entity, m_spawnthing->tagnum); VectorCopy(current_entity->origin, m_spawnthing->linked_origin); for (j = 0; j < 3; j++) { - VectorMA(m_spawnthing->linked_origin, ori.origin[i], current_entity->axis[j], m_spawnthing->linked_origin); + VectorMA( + m_spawnthing->linked_origin, ori.origin[j], current_entity->axis[j], m_spawnthing->linked_origin + ); } MatrixMultiply(ori.axis, current_entity->axis, m_spawnthing->linked_axis); } @@ -4374,7 +4948,7 @@ void ClientGameCommandManager::UpdateEmitter( } m_spawnthing->cgd.createTime = cg.time; - m_spawnthing->cgd.parentOrigin = Vector(entity_origin); + m_spawnthing->cgd.parentOrigin = entity_origin; if (m_spawnthing->cgd.flags & T_DLIGHT) { cgi.R_AddLightToScene( @@ -4406,7 +4980,8 @@ void ClientGameCommandManager::UpdateEmitter( et->last_emit_time = cg.time; } - count = dtime / (m_spawnthing->spawnRate * (1.0f / cg_effectdetail->value)); + count = dtime * cg_effectdetail->value / m_spawnthing->spawnRate; + et->last_emit_time += count * m_spawnthing->spawnRate; // This is kind of a nasty bit of code. If the count is 1, just // spawn a single tempmodel, if it's greater than 1, then spawn the @@ -4436,6 +5011,11 @@ void ClientGameCommandManager::UpdateEmitter( SpawnEffect(1, dtime); + et = m_spawnthing->GetEmitTime(entity_number); + if (!et) { + break; + } + lerp += lerpfrac; } } @@ -4454,6 +5034,8 @@ void ClientGameCommandManager::UpdateEmitter( et->oldorigin = save_origin; et->lerp_emitter = qtrue; } + + m_spawnthing = NULL; } //=============== @@ -4531,34 +5113,20 @@ bool ClientGameCommandManager::GetTagPositionAndOrientation(str tagname, orienta return ClientGameCommandManager::GetTagPositionAndOrientation(tagnum, new_or); } -//=============== -// FreeAllTempModels -//=============== -void ClientGameCommandManager::FreeAllTempModels(void) -{ - ctempmodel_t *p, *next; - - // Go through all the temp models and run the physics if necessary, - // then add them to the ref - p = m_active_tempmodels.prev; - for (; p != &m_active_tempmodels; p = next) { - // grab next now, so if the local entity is freed we still have it - next = p->prev; - FreeTempModel(p); - } -} - -void ClientGameCommandManager::FreeSomeTempModels(void) -{ - // FIXME: unimplemented -} - //=============== // FreeAllEmitters //=============== void ClientGameCommandManager::RestartAllEmitters(void) { - // FIXME: stub?? + ctempmodel_t *p; + + // + // FIXME: not sure if it's the right thing + // + + for (p = m_active_tempmodels.prev; p != &m_active_tempmodels; p = p->next) { + p->cgd.createTime = cg.time; + } } //=============== @@ -4569,6 +5137,9 @@ void CG_RestartCommandManager() commandManager.FreeAllTempModels(); } +//================= +// CG_CleanUpTempModels +//================= void CG_CleanUpTempModels() { commandManager.FreeSomeTempModels(); @@ -4608,7 +5179,7 @@ void CG_ProcessInitCommands(dtiki_t *tiki, refEntity_t *ent) } if (!commandManager.SelectProcessEvent(ev)) { - Com_Printf( + cgi.DPrintf( "^~^~^ CG_ProcessInitCommands: Bad init client command '%s' in '%s'\n", pcmd->args[0], tiki->name ); } @@ -4654,7 +5225,7 @@ void CG_ProcessCacheInitCommands(dtiki_t *tiki) } if (!commandManager.SelectProcessEvent(ev)) { - Com_Printf( + cgi.DPrintf( "^~^~^ CG_ProcessInitCommands: Bad init client command '%s' in '%s'\n", pcmd->args[0], tiki->name ); } @@ -4698,6 +5269,10 @@ void CG_UpdateEntityEmitters(int entnum, refEntity_t *ent, centity_t *cent) ent->tiki, ent->axis, cent->currentState.number, cent->currentState.parent, cent->lerpOrigin ); } + + // process events for the entity + commandManager.ProcessPendingEventsForEntity(); + current_entity = old_entity; current_tiki = old_tiki; current_centity = oldcent; @@ -4723,7 +5298,7 @@ qboolean CG_ProcessEntityCommands(int frame, int anim, int entnum, refEntity_t * current_centity = cent; current_entity_number = entnum; current_tiki = ent->tiki; - CG_AnimationDebugMessage(entnum, "Processing Ent Commands: Entity: %3d Anim:#(%i) Frame:#(%i)\n", anim, frame); + CG_AnimationDebugMessage(entnum, "Processing Ent Commands: Entity: %3d Anim:#(%i) Frame:#(%i)\n", entnum, anim, frame); for (i = 0; i < tikicmds.num_cmds; i++) { Event *ev; @@ -4762,7 +5337,7 @@ void CG_ClientCommandDebugMessage(centity_t *cent, const char *fmt, ...) char msg[1024]; va_start(argptr, fmt); - vsprintf(msg, fmt, argptr); + Q_vsnprintf(msg, sizeof(msg), fmt, argptr); va_end(argptr); if ((!cg_debugAnimWatch->integer) || ((cg_debugAnimWatch->integer - 1) == cent->currentState.number)) { @@ -4781,152 +5356,90 @@ void CG_ClientCommandDebugMessage(centity_t *cent, const char *fmt, ...) //================= void CG_ClientCommands(refEntity_t *ent, centity_t *cent, int slot) { -#if 0 - int anim; - int frame; - - if (!tiki) { - return; - } + int i; + int iStartFrame, iEndFrame; + dtiki_t *tiki = ent->tiki; + int iAnim; + float fAnimLength; + int iAnimFrames; + float fAnimFrameMult; + int iEntNumber; + float time, lastTime; + int lastAnim; if (paused->integer) { return; } - if (cent->currentState.eFlags & EF_DONT_PROCESS_COMMANDS) { + iAnim = ent->frameInfo[slot].index; + + fAnimLength = cgi.Anim_Time(tiki, iAnim); + iAnimFrames = cgi.Anim_NumFrames(tiki, iAnim); + fAnimFrameMult = cgi.Anim_Frametime(tiki, iAnim); + iEntNumber = cent->currentState.number; + + time = ent->frameInfo[slot].time; + lastTime = cent->animLastTimes[slot]; + lastAnim = cent->animLast[slot]; + cgi.Anim_NameForNum(tiki, iAnim); + + if (time < 0 || time > fAnimLength) { return; } - assert(cent); - - // don't do anything if the frame is illegal - if ((new_frame < 0) || (new_frame >= state->numframes)) { + if (time == fAnimLength && time < lastTime) { return; } -# if 0 -# ifndef NDEBUG - CG_ClientCommandDebugMessage( - cent, - "Client Commands: cg.time %d checking Entity %d anim %d frame %d\n", - cg.time, - cent->currentState.number, - new_anim, - new_frame - ); -# endif -# endif + if (cgi.Anim_HasCommands(tiki, iAnim)) { + if (iAnim == lastAnim && time < lastTime) { + iStartFrame = (lastTime + 0.01) / fAnimFrameMult + 1.0; + iEndFrame = (time + 0.01) / fAnimFrameMult + 1.0; - anim = state->last_cmd_anim - 1; - frame = state->last_cmd_frame; + for (i = iStartFrame; i < iAnimFrames; i++) { + CG_ProcessEntityCommands(i, iAnim, iEntNumber, ent, cent); + } - // if we had a last anim and it it wasn't same as ours then - // we need to run any exit commands from the last animation - if ((anim != new_anim) && (anim >= 0)) { - // play the exit command - CG_ProcessEntityCommands(TIKI_FRAME_EXIT, anim, - cent->currentState.number, ent, cent); -# ifndef NDEBUG - CG_ClientCommandDebugMessage( - cent, "Client Commands: Entity %d Exiting Anim: %s\n", - cent->currentState.number, cgi.Anim_NameForNum(tiki, anim)); -# endif - frame = 0; + for (i = 0; i < iEndFrame; i++) { + CG_ProcessEntityCommands(i, iAnim, iEntNumber, ent, cent); + } + } else if (time >= 0.01) { + if (iAnim == lastAnim) { + iStartFrame = (lastTime + 0.01) / fAnimFrameMult + 1.0; + } else { + iStartFrame = 0; + } + iEndFrame = (time + 0.01) / fAnimFrameMult + 1.0; - // Reset the tiki looping sound if changing animation - cent->tikiLoopSound = NULL; - } - - if (state->has_commands) { - // if we are entering a new animation, than - // we need to run any entry commands for the new animation - if (anim != new_anim) { - // play the exit command - CG_ProcessEntityCommands(TIKI_FRAME_ENTRY, new_anim, - cent->currentState.number, ent, cent); -# ifndef NDEBUG - CG_ClientCommandDebugMessage( - cent, "Client Commands: Entity %d Entering Anim: %s\n", - cent->currentState.number, - cgi.Anim_NameForNum(tiki, new_anim)); -# endif - } - - if (state->driven) { - // make sure we process this frame if we are on a new frame - // although this is a hack, it guarantees that the frame will be - // processed below. - frame %= state->numframes; - if (frame < new_frame) { - frame = new_frame; + for (i = iStartFrame; i < iEndFrame; i++) { + CG_ProcessEntityCommands(i, iAnim, iEntNumber, ent, cent); } } else { - // - // we need to catch up on the frames we haven't played yet - // - if ((new_frame != (frame - 1)) && (state->numframes > 1)) { - // and frame number so that it wraps properly - frame %= state->numframes; - - // lerp to one minus the current frame - while (frame != new_frame) { -# ifndef NDEBUG - CG_ClientCommandDebugMessage( - cent, - "Client Commands: cg.time %d Catching up Entity: %d " - "Anim: %s frame: %d numframes: %d\n", - cg.time, cent->currentState.number, - cgi.Anim_NameForNum(tiki, new_anim), frame, - state->numframes); -# endif - state->last_cmd_time = - cg.time + TIKI_FRAME_MAXFRAMERATE; - CG_ProcessEntityCommands(frame, new_anim, - cent->currentState.number, ent, - cent); - frame = (frame + 1) % state->numframes; - } - } - } - - // - // handle the single frame and every frame case - // - if ((frame == new_frame) || - ((cg.time > state->last_cmd_time) && - (cent->currentState.eFlags & EF_EVERYFRAME))) { -# ifndef NDEBUG - CG_ClientCommandDebugMessage( - cent, - "Client Commands: cg.time %d Processing Entity: %d Anim: %s " - "frame: %d numframes: %d\n", - cg.time, cent->currentState.number, - cgi.Anim_NameForNum(tiki, new_anim), new_frame, - state->numframes); -# endif - state->last_cmd_time = cg.time + TIKI_FRAME_MAXFRAMERATE; - CG_ProcessEntityCommands(new_frame, new_anim, - cent->currentState.number, ent, cent); + CG_ProcessEntityCommands(TIKI_FRAME_FIRST, iAnim, iEntNumber, ent, cent); } } if (cent->clientFlags & CF_UPDATESWIPE) { - current_entity = ent; - current_centity = cent; - current_entity_number = cent->currentState.number; - current_tiki = tiki; + refEntity_t *old_entity = current_entity; + dtiki_t *old_tiki = current_tiki; + int oldnum = current_entity_number; + centity_t *oldcent = current_centity; + + // + // swipe the entity + // + current_entity = ent; + current_tiki = ent->tiki; + current_centity = cent; + current_entity_number = iEntNumber; commandManager.ProcessEvent(EV_Client_Swipe); - current_tiki = NULL; - current_entity_number = -1; - current_entity = NULL; - current_centity = NULL; + current_entity = old_entity; + current_tiki = old_tiki; + current_entity_number = oldnum; + current_centity = oldcent; } - - state->last_cmd_anim = new_anim + 1; - state->last_cmd_frame = new_frame + 1; -#endif } //=============== @@ -4979,7 +5492,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c current_tiki = NULL; // Update the loading screen - sprintf(tempName, "m%s", filename); + Com_sprintf(tempName, sizeof(tempName), "m%s", filename); cgi.LoadResource(tempName); bufstart = buffer; @@ -4988,7 +5501,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c Event *ev; // grab each line as we go - strcpy(com_token, COM_ParseExt(&buffer, qtrue)); + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); if (!com_token[0]) { break; } @@ -4996,7 +5509,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c if (!Q_stricmp(com_token, "end") || !Q_stricmp(com_token, "server")) { // skip the line while (1) { - strcpy(com_token, COM_ParseExt(&buffer, qfalse)); + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); if (!com_token[0]) { break; } @@ -5009,7 +5522,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c // get the rest of the line while (1) { - strcpy(com_token, COM_ParseExt(&buffer, qfalse)); + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); if (!com_token[0]) { break; } @@ -5021,7 +5534,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c cgi.FS_FreeFile((void *)bufstart); // Update the loading screen - sprintf(tempName, "o%s", filename); + Com_sprintf(tempName, sizeof(tempName), "o%s", filename); cgi.LoadResource(tempName); return qtrue; @@ -5115,7 +5628,14 @@ void CG_DumpAllClasses_f(void) EmitterLoader emitterLoader; -Event EV_EmitterLoader_Emitter("emitter", EV_DEFAULT, "s", "emittername", "Create a new emitter"); +Event EV_EmitterLoader_Emitter +( + "emitter", + EV_DEFAULT, + "s", + "emittername", + "Create a new emitter" +); CLASS_DECLARATION(Listener, EmitterLoader, NULL) { {&EV_EmitterLoader_Emitter, &EmitterLoader::Emitter}, @@ -5320,7 +5840,7 @@ void ClientGameCommandManager::SetCurrentTiki(Event *ev) str tikiName; if (ev->NumArgs() != 1) { - Com_Printf("ERROR: settiki command takes 1 parameter.\n"); + cgi.DPrintf("ERROR: settiki command takes 1 parameter.\n"); return; } @@ -5399,3 +5919,470 @@ void ClientGameCommandManager::EventViewKick(Event *ev) cg.viewkick[1] = -fYawMax; } } + +int ClientGameCommandManager::IdForTempModel(const ctempmodel_t *model) +{ + int index; + + if (model == &m_active_tempmodels) { + return -1; + } + + if (!model) { + return -2; + } + + index = model - m_tempmodels; + if (index >= MAX_TEMPMODELS) { + return -2; + } + + if (model != &m_tempmodels[index]) { + return -2; + } + + return model - m_tempmodels; +} + +ctempmodel_t *ClientGameCommandManager::TempModelForId(int id) +{ + if (id == -1) { + return &m_active_tempmodels; + } + + if (id == -2) { + return NULL; + } + + return &m_tempmodels[id]; +} + +int ClientGameCommandManager::IdForSpawnThing(const spawnthing_t *sp) +{ + int i; + + if (!sp) { + return 0; + } + + for (i = 1; i <= m_emitters.NumObjects(); i++) { + if (sp == m_emitters.ObjectAt(i)) { + return i; + } + } + + return 0; +} + +spawnthing_t *ClientGameCommandManager::SpawnThingForId(int id) +{ + if (!id) { + return 0; + } + + return m_emitters.ObjectAt(id); +} + +int ClientGameCommandManager::IdForVssSource(const cvssource_t *source) +{ + int index; + + if (source == &m_active_vsssources) { + return -1; + } + + if (!source) { + return -2; + } + + index = source - m_vsssources; + if (index < 0 || index >= m_iAllocatedvsssources) { + return -2; + } + + if (source != &m_vsssources[index]) { + return -2; + } + + return source - m_vsssources; +} + +cvssource_t *ClientGameCommandManager::VssSourceForId(int id) +{ + if (id == -1) { + return &m_active_vsssources; + } + + if (id == -2) { + return 0; + } + + return &m_vsssources[id]; +} + +void ClientGameCommandManager::ArchiveTempModelPointerToMemory(MemArchiver& archiver, ctempmodel_t **model) +{ + int id; + + if (archiver.IsReading()) { + archiver.ArchiveInteger(&id); + *model = TempModelForId(id); + } else { + id = IdForTempModel(*model); + archiver.ArchiveInteger(&id); + } +} + +void ClientGameCommandManager::ArchiveSpawnThingPointerToMemory(MemArchiver& archiver, spawnthing_t **sp) +{ + int id; + + if (archiver.IsReading()) { + archiver.ArchiveInteger(&id); + *sp = SpawnThingForId(id); + } else { + id = IdForSpawnThing(*sp); + archiver.ArchiveInteger(&id); + } +} + +void ClientGameCommandManager::ArchiveVssSourcePointerToMemory(MemArchiver& archiver, cvssource_t **source) +{ + int id; + + if (archiver.IsReading()) { + archiver.ArchiveInteger(&id); + *source = VssSourceForId(id); + } else { + id = IdForVssSource(*source); + archiver.ArchiveInteger(&id); + } +} + +void ClientGameCommandManager::ArchiveToMemory(MemArchiver& archiver) +{ + spawnthing_t *sp; + int num; + int i; + + m_localemitter.ArchiveToMemory(archiver); + + if (archiver.IsReading()) { + archiver.ArchiveInteger(&num); + + for (i = 0; i < num; i++) { + sp = new spawnthing_t(); + sp->ArchiveToMemory(archiver); + + m_emitters.AddObjectAt(i + 1, sp); + } + } else { + num = m_emitters.NumObjects(); + archiver.ArchiveInteger(&num); + + for (i = 0; i < num; i++) { + sp = m_emitters[i]; + sp->ArchiveToMemory(archiver); + } + } + + ArchiveTempModelPointerToMemory(archiver, &m_active_tempmodels.prev); + ArchiveTempModelPointerToMemory(archiver, &m_active_tempmodels.next); + ArchiveTempModelPointerToMemory(archiver, &m_free_tempmodels); + + for (i = 0; i < MAX_TEMPMODELS; i++) { + m_tempmodels[i].ArchiveToMemory(archiver); + } + + if (archiver.IsReading()) { + archiver.ArchiveInteger(&num); + if (m_iAllocatedvsssources != num) { + m_iAllocatedvsssources = num; + + m_vsssources = (cvssource_t *)cgi.Malloc(m_iAllocatedvsssources * sizeof(cvssource_t)); + // instead of using memset, call the constructor + for (i = 0; i < m_iAllocatedvsssources; i++) { + new (&m_vsssources[i]) cvssource_t(); + } + } + } else { + archiver.ArchiveInteger(&m_iAllocatedvsssources); + } + + ArchiveVssSourcePointerToMemory(archiver, &m_active_vsssources.prev); + ArchiveVssSourcePointerToMemory(archiver, &m_active_vsssources.next); + ArchiveVssSourcePointerToMemory(archiver, &m_free_vsssources); + + for (i = 0; i < m_iAllocatedvsssources; i++) { + m_vsssources[i].ArchiveToMemory(archiver); + } + + archiver.ArchiveTime(&m_iLastVSSRepulsionTime); + m_command_time_manager.ArchiveToMemory(archiver); + archiver.ArchiveInteger(&m_seed); + archiver.ArchiveFloat(&m_fEventWait); + + m_pCurrentSfx = NULL; +} + +void commandthing_t::ArchiveToMemory(MemArchiver& archiver) +{ + int num; + int i; + + enttracker_t::ArchiveToMemory(archiver); + + if (archiver.IsReading()) { + archiver.ArchiveInteger(&num); + + for (i = 0; i < num; i++) { + commandtime_t ct; + + ct.ArchiveToMemory(archiver); + m_commandtimes.AddObject(ct); + } + } else { + num = m_commandtimes.NumObjects(); + + archiver.ArchiveInteger(&num); + m_commandtimes.ClearObjectList(); + + for (i = 0; i < num; i++) { + commandtime_t& ct = m_commandtimes.ObjectAt(i); + + ct.ArchiveToMemory(archiver); + } + } +} + +void cvssource_t::ArchiveToMemory(MemArchiver& archiver) +{ + commandManager.ArchiveVssSourcePointerToMemory(archiver, &next); + commandManager.ArchiveVssSourcePointerToMemory(archiver, &prev); + commandManager.ArchiveVssSourcePointerToMemory(archiver, &stnext); + archiver.ArchiveInteger(&stindex); + archiver.ArchiveVector(&lastOrigin); + archiver.ArchiveFloat(&lastRadius); + archiver.ArchiveFloat(&lastDensity); + archiver.ArchiveVec3(lastColor); + archiver.ArchiveVec3(lastLighting); + archiver.ArchiveVector(&newOrigin); + archiver.ArchiveFloat(&newRadius); + archiver.ArchiveFloat(&newDensity); + archiver.ArchiveVec3(newColor); + archiver.ArchiveVec3(newLighting); + archiver.ArchiveFloat(&ooRadius); + archiver.ArchiveVector(&velocity); + archiver.ArchiveFloat(&startAlpha); + archiver.ArchiveInteger(&roll); + archiver.ArchiveVector(&repulsion); + archiver.ArchiveInteger(&lifeTime); + archiver.ArchiveInteger(&collisionmask); + archiver.ArchiveInteger(&parent); + archiver.ArchiveInteger(&flags); + archiver.ArchiveInteger(&flags2); + archiver.ArchiveInteger(&smokeType); + archiver.ArchiveFloat(&typeInfo); + archiver.ArchiveFloat(&fadeMult); + archiver.ArchiveFloat(&scaleMult); + archiver.ArchiveTime(&lastPhysicsTime); + archiver.ArchiveTime(&lastLightingTime); + archiver.ArchiveBoolean(&lastValid); +} + +void ctempmodel_t::ArchiveToMemory(MemArchiver& archiver) +{ + commandManager.ArchiveTempModelPointerToMemory(archiver, &next); + commandManager.ArchiveTempModelPointerToMemory(archiver, &prev); + + cgd.ArchiveToMemory(archiver); + archiver.ArchiveString(&modelname); + + CG_ArchiveRefEntity(archiver, &lastEnt); + CG_ArchiveRefEntity(archiver, &ent); + + archiver.ArchiveInteger(&number); + archiver.ArchiveTime(&lastAnimTime); + archiver.ArchiveTime(&lastPhysicsTime); + archiver.ArchiveTime(&killTime); + archiver.ArchiveTime(&next_bouncesound_time); + archiver.ArchiveInteger(&seed); + archiver.ArchiveInteger(&twinkleTime); + archiver.ArchiveInteger(&aliveTime); + archiver.ArchiveBoolean(&addedOnce); + archiver.ArchiveBoolean(&lastEntValid); + commandManager.ArchiveSpawnThingPointerToMemory(archiver, &m_spawnthing); +} + +void enttracker_t::ArchiveToMemory(MemArchiver& archiver) +{ + archiver.ArchiveRaw(usedNumbers, sizeof(usedNumbers)); +} + +void emittertime_t::ArchiveToMemory(MemArchiver& archiver) +{ + archiver.ArchiveInteger(&entity_number); + archiver.ArchiveTime(&last_emit_time); + archiver.ArchiveVector(&oldorigin); + archiver.ArchiveBoolean(&active); + archiver.ArchiveBoolean(&lerp_emitter); +} + +void emitterthing_t::ArchiveToMemory(MemArchiver& archiver) +{ + int num; + int i; + + enttracker_t::ArchiveToMemory(archiver); + + if (archiver.IsReading()) { + emittertime_t et; + + archiver.ArchiveInteger(&num); + for (i = 0; i < num; i++) { + et.ArchiveToMemory(archiver); + m_emittertimes.AddObject(et); + } + } else { + num = m_emittertimes.NumObjects(); + archiver.ArchiveInteger(&num); + + for (i = 0; i < num; i++) { + emittertime_t& et = m_emittertimes[i]; + et.ArchiveToMemory(archiver); + } + } + + archiver.ArchiveBoolean(&startoff); +} + +void cg_common_data::ArchiveToMemory(MemArchiver& archiver) +{ + archiver.ArchiveInteger(&life); + archiver.ArchiveTime(&createTime); + archiver.ArchiveVector(&origin); + archiver.ArchiveVector(&oldorigin); + archiver.ArchiveVector(&accel); + archiver.ArchiveVector(&angles); + archiver.ArchiveVector(&velocity); + archiver.ArchiveVector(&avelocity); + archiver.ArchiveVector(&parentOrigin); + archiver.ArchiveVector(&parentMins); + archiver.ArchiveVector(&parentMaxs); + archiver.ArchiveVector(&minVel); + archiver.ArchiveVector(&maxVel); + archiver.ArchiveFloat(color); + archiver.ArchiveFloat(&color[1]); + archiver.ArchiveFloat(&color[2]); + archiver.ArchiveFloat(&color[3]); + archiver.ArchiveFloat(&alpha); + archiver.ArchiveFloat(&scaleRate); + archiver.ArchiveFloat(&scalemin); + archiver.ArchiveFloat(&scalemax); + archiver.ArchiveFloat(&bouncefactor); + archiver.ArchiveInteger(&bouncecount); + archiver.ArchiveInteger(&maxbouncecount); + archiver.ArchiveString(&bouncesound); + archiver.ArchiveInteger(&bouncesound_delay); + archiver.ArchiveInteger(&flags); + archiver.ArchiveInteger(&flags2); + + CG_ArchiveTikiPointer(archiver, &tiki); + + archiver.ArchiveInteger(&swarmfreq); + archiver.ArchiveFloat(&swarmmaxspeed); + archiver.ArchiveFloat(&swarmdelta); + archiver.ArchiveFloat(&lightIntensity); + archiver.ArchiveInteger(&lightType); + archiver.ArchiveInteger(&fadeintime); + archiver.ArchiveInteger(&fadedelay); + archiver.ArchiveInteger(&parent); + archiver.ArchiveInteger(&collisionmask); + archiver.ArchiveInteger(&min_twinkletimeoff); + archiver.ArchiveInteger(&max_twinkletimeoff); + archiver.ArchiveInteger(&min_twinkletimeon); + archiver.ArchiveInteger(&max_twinkletimeon); + archiver.ArchiveInteger(&lightstyle); + archiver.ArchiveInteger(&physicsRate); + archiver.ArchiveFloat(&scale); + archiver.ArchiveFloat(&scale2); + archiver.ArchiveString(&swipe_shader); + archiver.ArchiveString(&swipe_tag_start); + archiver.ArchiveString(&swipe_tag_end); + archiver.ArchiveString(&shadername); + archiver.ArchiveFloat(&swipe_life); + archiver.ArchiveFloat(&friction); + archiver.ArchiveFloat(&spin_rotation); + archiver.ArchiveFloat(&decal_orientation); + archiver.ArchiveFloat(&decal_radius); +} + +void spawnthing_t::ArchiveToMemory(MemArchiver& archiver) +{ + emitterthing_t::ArchiveToMemory(archiver); + + CG_ArchiveStringContainer(archiver, &m_modellist); + CG_ArchiveStringContainer(archiver, &m_taglist); + + cgd.ArchiveToMemory(archiver); + + archiver.ArchiveInteger(&entnum); + archiver.ArchiveVector(&origin_offset_base); + archiver.ArchiveVector(&origin_offset_amplitude); + archiver.ArchiveVector(&axis_offset_base); + archiver.ArchiveVector(&axis_offset_amplitude); + archiver.ArchiveVector(&randvel_base); + archiver.ArchiveVector(&randvel_amplitude); + archiver.ArchiveVector(&avelocity_base); + archiver.ArchiveVector(&avelocity_amplitude); + archiver.ArchiveVector(&angles_amplitude); + archiver.ArchiveVec3(axis[0]); + archiver.ArchiveVec3(axis[1]); + archiver.ArchiveVec3(axis[2]); + archiver.ArchiveVec3(tag_axis[0]); + archiver.ArchiveVec3(tag_axis[1]); + archiver.ArchiveVec3(tag_axis[2]); + archiver.ArchiveFloat(&life_random); + archiver.ArchiveFloat(&forwardVelocity); + archiver.ArchiveFloat(&sphereRadius); + archiver.ArchiveFloat(&coneHeight); + archiver.ArchiveFloat(&spawnRate); + archiver.ArchiveTime(&lastTime); + archiver.ArchiveInteger(&count); + archiver.ArchiveInteger(&tagnum); + archiver.ArchiveString(&emittername); + archiver.ArchiveString(&animName); + archiver.ArchiveFloat(dcolor); + archiver.ArchiveFloat(&dcolor[1]); + archiver.ArchiveFloat(&dcolor[2]); + archiver.ArchiveBoolean(&dlight); + archiver.ArchiveInteger(&numtempmodels); + archiver.ArchiveVec3(linked_origin); + archiver.ArchiveVec3(linked_axis[0]); + archiver.ArchiveVec3(linked_axis[1]); + archiver.ArchiveVec3(linked_axis[2]); + archiver.ArchiveFloat(&fMinRangeSquared); + archiver.ArchiveFloat(&fMaxRangeSquared); + archiver.ArchiveString(&startTag); + archiver.ArchiveString(&endTag); + archiver.ArchiveFloat(&length); + archiver.ArchiveFloat(&min_offset); + archiver.ArchiveFloat(&max_offset); + archiver.ArchiveFloat(&overlap); + archiver.ArchiveFloat(&numSubdivisions); + archiver.ArchiveFloat(&delay); + archiver.ArchiveFloat(&toggledelay); + archiver.ArchiveInteger(&beamflags); + archiver.ArchiveInteger(&numspherebeams); + archiver.ArchiveFloat(&endalpha); + archiver.ArchiveFloat(&spreadx); + archiver.ArchiveFloat(&spready); + archiver.ArchiveBoolean(&use_last_trace_end); +} + +void commandtime_t::ArchiveToMemory(MemArchiver& archiver) +{ + archiver.ArchiveInteger(&entity_number); + archiver.ArchiveInteger(&command_number); + archiver.ArchiveTime(&last_command_time); +} diff --git a/code/cgame/cg_commands.h b/code/cgame/cg_commands.h index a2097288..60e39dec 100644 --- a/code/cgame/cg_commands.h +++ b/code/cgame/cg_commands.h @@ -113,9 +113,11 @@ TIKI file, similar to ScriptMaster in the server game dll. #define T2_VARYCOLOR (1 << 20) #define T2_SPIN (1 << 21) #define T2_RELATIVEANGLES (1 << 22) +#define T2_NOTAGAXIS (1 << 23) class spawnthing_t; class specialeffect_t; +class MemArchiver; typedef enum { NOT_RANDOM, @@ -181,6 +183,9 @@ public: float decal_orientation; float decal_radius; float spin_rotation; + +public: + void ArchiveToMemory(MemArchiver& archiver); }; inline cg_common_data::cg_common_data() @@ -249,6 +254,9 @@ public: spawnthing_t *m_spawnthing; void (*touchfcn)(ctempmodel_t *ct, trace_t *trace); + +public: + void ArchiveToMemory(MemArchiver& archiver); }; inline ctempmodel_t::ctempmodel_t() @@ -315,8 +323,44 @@ public: int lastPhysicsTime; int lastLightingTime; qboolean lastValid; + +public: + cvssource_t(); + +public: + void ArchiveToMemory(MemArchiver& archiver); }; +inline cvssource_t::cvssource_t() + : next(NULL) + , prev(NULL) + , stnext(NULL) + , stindex(0) + , lastRadius(0) + , lastDensity(0) + , lastColor {0} + , lastLighting {0} + , newRadius(0) + , newDensity(0) + , newColor {0} + , newLighting {0} + , ooRadius(0) + , startAlpha(0) + , roll(0) + , lifeTime(0) + , collisionmask(0) + , parent(0) + , flags(0) + , flags2(0) + , smokeType(0) + , typeInfo(0) + , fadeMult(0) + , scaleMult(0) + , lastPhysicsTime(0) + , lastLightingTime(0) + , lastValid(qfalse) +{} + class cvssourcestate_t { public: @@ -387,6 +431,9 @@ public: protected: qboolean usedNumbers[256]; virtual void RemoveEntity(int entnum); + +public: + void ArchiveToMemory(MemArchiver& archiver); }; inline enttracker_t::enttracker_t() @@ -437,6 +484,9 @@ public: Vector oldorigin; qboolean active; qboolean lerp_emitter; + +public: + void ArchiveToMemory(MemArchiver& archiver); }; // emitterthing_t is used to keep track of the last time and emitter was updated @@ -452,6 +502,9 @@ public: emittertime_t *GetEmitTime(int entnum); virtual void RemoveEntity(int entnum); qboolean startoff; + +public: + void ArchiveToMemory(MemArchiver& archiver); }; inline void emitterthing_t::RemoveEntity(int entnum) @@ -510,18 +563,23 @@ public: int entity_number; int command_number; int last_command_time; + +public: + void ArchiveToMemory(MemArchiver& archiver); }; // This class is used for keeping track of the last time an entity executed a // particular command. A command number must be assigned externally by the user class commandthing_t : public enttracker_t { - Container m_commandtimes; // A list of entity numbers and the last time they - // executed a command + Container m_commandtimes; // A list of entity numbers and the last time they + // executed a command public: commandtime_t *GetLastCommandTime(int entnum, int commandnum); virtual void RemoveEntity(int entnum); + + void ArchiveToMemory(MemArchiver& archiver); }; inline void commandthing_t::RemoveEntity(int entnum) @@ -532,7 +590,7 @@ inline void commandthing_t::RemoveEntity(int entnum) count = m_commandtimes.NumObjects(); for (num = count; num >= 1; num--) { - ct = m_commandtimes.ObjectAt(num); + ct = &m_commandtimes.ObjectAt(num); if (ct->entity_number == entnum) { m_commandtimes.RemoveObjectAt(num); } @@ -543,28 +601,27 @@ inline void commandthing_t::RemoveEntity(int entnum) inline commandtime_t *commandthing_t::GetLastCommandTime(int entnum, int commandnum) { - int num, count; - commandtime_t *ct; + int num, count; // Search for this entity number count = m_commandtimes.NumObjects(); for (num = 1; num <= count; num++) { - ct = m_commandtimes.ObjectAt(num); + commandtime_t *ct = &m_commandtimes.ObjectAt(num); if ((ct->entity_number == entnum) && (ct->command_number == commandnum)) { return ct; } } // Add a new entry if we didn't find it - ct = new commandtime_t; - ct->entity_number = entnum; - ct->command_number = commandnum; - ct->last_command_time = 0; + commandtime_t ct; + ct.entity_number = entnum; + ct.command_number = commandnum; + ct.last_command_time = 0; m_commandtimes.AddObject(ct); - return ct; + return &m_commandtimes.ObjectAt(m_commandtimes.NumObjects()); } class spawnthing_t : public emitterthing_t @@ -625,6 +682,9 @@ public: void (*touchfcn)(ctempmodel_t *ct, trace_t *trace); str GetModel(void); void SetModel(str model); + +public: + void ArchiveToMemory(MemArchiver& archiver); }; inline void spawnthing_t::SetModel(str model) @@ -704,6 +764,7 @@ private: void SpawnVSSSource(int count, int timealive); void EventViewKick(Event *ev); void Print(Event *ev); + void PrintDeathMsg(Event *ev); // Added in 2.0 void StartBlock(Event *ev); void EndBlock(Event *ev); void UpdateSpawnThing(spawnthing_t *ep); @@ -729,6 +790,7 @@ private: void SetScaleRate(Event *ev); void SetRandomVelocity(Event *ev); void SetRandomVelocityAlongAxis(Event *ev); + void SetNoTagAxis(Event *ev); // Added in 2.0 void SetAccel(Event *ev); void SetFriction(Event *ev); void SetSpin(Event *ev); @@ -790,6 +852,7 @@ private: void StopSound(Event *ev); void StopAliasChannel(Event *ev); void LoopSound(Event *ev); + void StopLoopSound(Event *ev); // Added in 2.0 void Cache(Event *ev); void CacheImage(Event *ev); void CacheFont(Event *ev); @@ -824,8 +887,8 @@ private: void SetClampVel(Event *ev); void SetClampVelAxis(Event *ev); ctempmodel_t *AllocateTempModel(void); - qboolean TempModelPhysics(ctempmodel_t *p, float ftime, float time2, float scale); - qboolean TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float time2, float scale); + qboolean TempModelPhysics(ctempmodel_t *p, float ftime, float scale); + qboolean TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float scale); qboolean LerpTempModel(refEntity_t *newEnt, ctempmodel_t *p, float frac); void SpawnEffect(int count, int timealive); void SpawnTempModel(int count); @@ -871,13 +934,13 @@ public: void UpdateEmitter(dtiki_t *tiki, vec3_t axis[3], int entity_number, int parent_number, Vector entity_origin); void UpdateBeam(dtiki_t *tiki, int entity_number, spawnthing_t *beamthing); void PlaySound( - str sound_name, + str sound_name, const vec3_t origin = NULL, - int channel = CHAN_AUTO, - float volume = -1, - float min_distance = -1, - float pitch = -1, - int argstype = 0 + int channel = CHAN_AUTO, + float volume = -1, + float min_distance = -1, + float pitch = -1, + int argstype = 0 ); spawnthing_t *InitializeSpawnthing(spawnthing_t *ep); @@ -891,6 +954,7 @@ public: void InitializeEmitters(void); void RemoveClientEntity(int number, dtiki_t *tiki, centity_t *cent, ctempmodel_t *p = NULL); void ClearSwipes(void); + void FreeSpawnthing(spawnthing_t *sp); void ResetTempModels(void); void SpawnTempModel(int count, spawnthing_t *sp); @@ -921,6 +985,21 @@ public: void ResetTreadMarkSources(Event *ev); void InitializeRainCvars(); void InitializeBeams(); + + // + // archive stuff + // + int IdForTempModel(const ctempmodel_t *model); + ctempmodel_t *TempModelForId(int id); + int IdForSpawnThing(const spawnthing_t *sp); + spawnthing_t *SpawnThingForId(int id); + int IdForVssSource(const cvssource_t *source); + cvssource_t *VssSourceForId(int id); + + void ArchiveTempModelPointerToMemory(MemArchiver& archiver, ctempmodel_t **model); + void ArchiveSpawnThingPointerToMemory(MemArchiver& archiver, spawnthing_t **sp); + void ArchiveVssSourcePointerToMemory(MemArchiver& archiver, cvssource_t **source); + void ArchiveToMemory(MemArchiver& archiver); }; class EmitterLoader : public Listener diff --git a/code/cgame/cg_consolecmds.c b/code/cgame/cg_consolecmds.c index d9413d23..9ab3817f 100644 --- a/code/cgame/cg_consolecmds.c +++ b/code/cgame/cg_consolecmds.c @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2008-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // text commands typed in at the local console, or executed by a key binding #include "cg_local.h" +#include "../fgame/bg_voteoptions.h" void CG_TargetCommand_f(void); @@ -159,17 +160,157 @@ baseshader_t *CG_GetShaderUnderCrosshair(qboolean bVerbose, trace_t *pRetTrace) static void CG_PrintContentTypes(int iContentFlags) { - // FIXME: unimplemented + if (iContentFlags & CONTENTS_SOLID) { + cgi.Printf(" solid"); + } + if (iContentFlags & CONTENTS_LAVA) { + cgi.Printf(" lava"); + } + if (iContentFlags & CONTENTS_SLIME) { + cgi.Printf(" slime"); + } + if (iContentFlags & CONTENTS_WATER) { + cgi.Printf(" water"); + } + if (iContentFlags & CONTENTS_FOG) { + cgi.Printf(" fog"); + } + if (iContentFlags & CONTENTS_FENCE) { + cgi.Printf(" fence"); + } + if (iContentFlags & CONTENTS_AREAPORTAL) { + cgi.Printf(" areaportal"); + } + if (iContentFlags & CONTENTS_PLAYERCLIP) { + cgi.Printf(" playerclip"); + } + if (iContentFlags & CONTENTS_VEHICLECLIP) { + cgi.Printf(" vehicleclip"); + } + if (iContentFlags & CONTENTS_MONSTERCLIP) { + cgi.Printf(" monsterclip"); + } + if (iContentFlags & CONTENTS_WEAPONCLIP) { + cgi.Printf(" weaponclip"); + } + if (iContentFlags & CONTENTS_SHOOTONLY) { + cgi.Printf(" shootableonly"); + } + if (iContentFlags & CONTENTS_ORIGIN) { + cgi.Printf(" origin"); + } + if (iContentFlags & CONTENTS_TRANSLUCENT) { + cgi.Printf(" trans"); + } } static void CG_PrintSurfaceProperties(int iSurfaceFlags) { - // FIXME: unimplemented + if (iSurfaceFlags & SURF_NODAMAGE) { + cgi.Printf(" nodamage"); + } + if (iSurfaceFlags & SURF_SLICK) { + cgi.Printf(" slick"); + } + if (iSurfaceFlags & SURF_SKY) { + cgi.Printf(" sky"); + } + if (iSurfaceFlags & SURF_LADDER) { + cgi.Printf(" ladder"); + } + if (iSurfaceFlags & SURF_NOIMPACT) { + cgi.Printf(" noimpact"); + } + if (iSurfaceFlags & SURF_NOMARKS) { + cgi.Printf(" nomarks"); + } + if (iSurfaceFlags & SURF_CASTSHADOW) { + cgi.Printf(" castshadow"); + } + if (iSurfaceFlags & SURF_NODRAW) { + cgi.Printf(" nodraw"); + } + if (iSurfaceFlags & SURF_NOLIGHTMAP) { + cgi.Printf(" nolightmap"); + } + if (iSurfaceFlags & SURF_ALPHASHADOW) { + cgi.Printf(" alphashadow"); + } + if (iSurfaceFlags & SURF_NOSTEPS) { + cgi.Printf(" nofootsteps"); + } + if (iSurfaceFlags & SURF_NONSOLID) { + cgi.Printf(" nonsolid"); + } + if (iSurfaceFlags & SURF_OVERBRIGHT) { + cgi.Printf(" overbright"); + } + if (iSurfaceFlags & SURF_BACKSIDE) { + cgi.Printf(" backside"); + } + if (iSurfaceFlags & SURF_NODLIGHT) { + cgi.Printf(" nodlight"); + } + if (iSurfaceFlags & SURF_HINT) { + cgi.Printf(" hint"); + } + if (iSurfaceFlags & SURF_PATCH) { + cgi.Printf(" patch"); + } } static void CG_PrintSurfaceType(int iSurfType) { - // FIXME: unimplemented + switch (iSurfType & MASK_SURF_TYPE) { + case SURF_FOLIAGE: + cgi.Printf("foliage"); + break; + case SURF_SNOW: + cgi.Printf("snow"); + break; + case SURF_CARPET: + cgi.Printf("carpet"); + break; + case SURF_SAND: + cgi.Printf("sand"); + break; + case SURF_PUDDLE: + cgi.Printf("puddle"); + break; + case SURF_GLASS: + cgi.Printf("glass"); + break; + case SURF_GRAVEL: + cgi.Printf("gravel"); + break; + case SURF_MUD: + cgi.Printf("mud"); + break; + case SURF_DIRT: + cgi.Printf("dirt"); + break; + case SURF_GRILL: + cgi.Printf("metal grill"); + break; + case SURF_GRASS: + cgi.Printf("grass"); + break; + case SURF_ROCK: + cgi.Printf("rock"); + break; + case SURF_PAPER: + cgi.Printf("paper"); + break; + case SURF_WOOD: + cgi.Printf("wood"); + break; + case SURF_METAL: + cgi.Printf("metal"); + break; + default: + cgi.Printf("!!*none specified*!!"); + break; + } } void CG_GetCHShader(void) @@ -215,9 +356,9 @@ void CG_EditCHShader(void) pShader = CG_GetShaderUnderCrosshair(qfalse, NULL); if (pShader) { - strcpy(name, "editspecificshader "); - strcat(name, pShader->shader); - strcat(name, "\n"); + Q_strncpyz(name, "editspecificshader ", sizeof(name)); + Q_strcat(name, sizeof(name), pShader->shader); + Q_strcat(name, sizeof(name), "\n"); cgi.AddCommand(name); } else { cgi.Printf("No surface selected\n"); @@ -339,56 +480,65 @@ typedef struct { } consoleCommand_t; static consoleCommand_t commands[] = { - {"useweaponclass", &CG_UseWeaponClass_f }, - {"weapnext", &CG_NextWeapon_f }, - {"weapprev", &CG_PrevWeapon_f }, - {"uselast", &CG_UseLastWeapon_f }, - {"holster", &CG_HolsterWeapon_f }, - {"weapdrop", &CG_DropWeapon_f }, - {"toggleitem", &CG_ToggleItem_f }, - {"+scores", &CG_ScoresDown_f }, - {"-scores", &CG_ScoresUp_f }, - {"viewpos", &CG_Viewpos_f }, - {"sizeup", &CG_SizeUp_f }, - {"sizedown", &CG_SizeDown_f }, - {"cg_eventlist", &CG_EventList_f }, - {"cg_eventhelp", &CG_EventHelp_f }, - {"cg_dumpevents", &CG_DumpEventHelp_f }, - {"cg_pendingevents", &CG_PendingEvents_f }, - {"cg_classlist", &CG_ClassList_f }, - {"cg_classtree", &CG_ClassTree_f }, - {"cg_classevents", &CG_ClassEvents_f }, - {"cg_dumpclassevents", &CG_DumpClassEvents_f }, - {"cg_dumpallclasses", &CG_DumpAllClasses_f }, - {"testemitter", &CG_TestEmitter_f }, - {"triggertestemitter", &CG_TriggerTestEmitter_f }, - {"prevemittercommand", &CG_PrevEmitterCommand_f }, - {"nextemittercommand", &CG_NextEmitterCommand_f }, - {"newemittercommand", &CG_NewEmitterCommand_f }, - {"deleteemittercommand", &CG_DeleteEmitterCommand_f}, - {"dumpemitter", &CG_DumpEmitter_f }, - {"loademitter", &CG_LoadEmitter_f }, - {"resetvss", &CG_ResetVSSSources }, - {"getchshader", &CG_GetCHShader }, - {"editchshader", &CG_EditCHShader }, - {"messagemode", &CG_MessageMode_f }, - {"messagemode_all", &CG_MessageMode_All_f }, - {"messagemode_team", &CG_MessageMode_Team_f }, - {"messagemode_private", &CG_MessageMode_Private_f }, - {"say", &CG_MessageSingleAll_f }, - {"sayteam", &CG_MessageSingleTeam_f }, - {"teamsay", &CG_MessageSingleTeam_f }, - {"sayprivate", &CG_MessageSingleClient_f }, - {"sayone", &CG_MessageSingleClient_f }, - {"wisper", &CG_MessageSingleClient_f }, - {"instamsg_main", &CG_InstaMessageMain_f }, - {"instamsg_group_a", &CG_InstaMessageGroupA_f }, - {"instamsg_group_b", &CG_InstaMessageGroupB_f }, - {"instamsg_group_c", &CG_InstaMessageGroupC_f }, - {"instamsg_group_d", &CG_InstaMessageGroupD_f }, - {"instamsg_group_e", &CG_InstaMessageGroupE_f }, - {"pushmenu_teamselect", &CG_PushMenuTeamSelect_f }, - {"pushmenu_weaponselect", &CG_PushMenuWeaponSelect_f}, + {"useweaponclass", &CG_UseWeaponClass_f }, + {"weapnext", &CG_NextWeapon_f }, + {"weapprev", &CG_PrevWeapon_f }, + {"uselast", &CG_UseLastWeapon_f }, + {"holster", &CG_HolsterWeapon_f }, + {"weapdrop", &CG_DropWeapon_f }, + {"toggleitem", &CG_ToggleItem_f }, + {"+scores", &CG_ScoresDown_f }, + {"-scores", &CG_ScoresUp_f }, + {"viewpos", &CG_Viewpos_f }, + {"sizeup", &CG_SizeUp_f }, + {"sizedown", &CG_SizeDown_f }, + {"cg_eventlist", &CG_EventList_f }, + {"cg_eventhelp", &CG_EventHelp_f }, + {"cg_dumpevents", &CG_DumpEventHelp_f }, + {"cg_pendingevents", &CG_PendingEvents_f }, + {"cg_classlist", &CG_ClassList_f }, + {"cg_classtree", &CG_ClassTree_f }, + {"cg_classevents", &CG_ClassEvents_f }, + {"cg_dumpclassevents", &CG_DumpClassEvents_f }, + {"cg_dumpallclasses", &CG_DumpAllClasses_f }, + {"testemitter", &CG_TestEmitter_f }, + {"triggertestemitter", &CG_TriggerTestEmitter_f }, + {"prevemittercommand", &CG_PrevEmitterCommand_f }, + {"nextemittercommand", &CG_NextEmitterCommand_f }, + {"newemittercommand", &CG_NewEmitterCommand_f }, + {"deleteemittercommand", &CG_DeleteEmitterCommand_f }, + {"dumpemitter", &CG_DumpEmitter_f }, + {"loademitter", &CG_LoadEmitter_f }, + {"resetvss", &CG_ResetVSSSources }, + {"getchshader", &CG_GetCHShader }, + {"editchshader", &CG_EditCHShader }, + {"messagemode", &CG_MessageMode_f }, + {"messagemode_all", &CG_MessageMode_All_f }, + {"messagemode_team", &CG_MessageMode_Team_f }, + {"messagemode_private", &CG_MessageMode_Private_f }, + {"say", &CG_MessageSingleAll_f }, + {"sayteam", &CG_MessageSingleTeam_f }, + {"teamsay", &CG_MessageSingleTeam_f }, + {"sayprivate", &CG_MessageSingleClient_f }, + {"sayone", &CG_MessageSingleClient_f }, + {"wisper", &CG_MessageSingleClient_f }, + {"instamsg_main", &CG_InstaMessageMain_f }, + {"instamsg_group_a", &CG_InstaMessageGroupA_f }, + {"instamsg_group_b", &CG_InstaMessageGroupB_f }, + {"instamsg_group_c", &CG_InstaMessageGroupC_f }, + {"instamsg_group_d", &CG_InstaMessageGroupD_f }, + {"instamsg_group_e", &CG_InstaMessageGroupE_f }, + {"pushmenu_teamselect", &CG_PushMenuTeamSelect_f }, + {"pushmenu_weaponselect", &CG_PushMenuWeaponSelect_f }, + // Added in 2.0 + {"pushcallvote", &CG_PushCallVote_f }, + {"pushcallvotesublist", &CG_PushCallVoteSubList_f }, + {"pushcallvotesubtext", &CG_PushCallVoteSubText_f }, + {"pushcallvotesubinteger", &CG_PushCallVoteSubInteger_f}, + {"pushcallvotesubfloat", &CG_PushCallVoteSubFloat_f }, + {"pushcallvotesubclient", &CG_PushCallVoteSubClient_f }, + {"pushvote", &CG_PushVote_f }, + {"callentryvote", &CG_CallEntryVote_f }, }; /* @@ -555,5 +705,5 @@ int CG_WeaponCommandButtonBits(void) cg.iWeaponCommand = 0; } - return iShiftedWeaponCommand & WEAPON_COMMAND_MASK; + return iShiftedWeaponCommand & GetWeaponCommandMask(cg_protocol >= PROTOCOL_MOHTA_MIN ? WEAPON_COMMAND_MAX_VER17 : WEAPON_COMMAND_MAX_VER6); } diff --git a/code/cgame/cg_drawtools.cpp b/code/cgame/cg_drawtools.cpp index abc01c5f..043b3882 100644 --- a/code/cgame/cg_drawtools.cpp +++ b/code/cgame/cg_drawtools.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -191,8 +191,8 @@ void CG_DrawDisconnect(void) } handle = cgi.R_RegisterShader("gfx/2d/net.tga"); - w = cgi.R_GetShaderWidth(handle); - h = cgi.R_GetShaderHeight(handle); + w = cgi.R_GetShaderWidth(handle) * cgs.uiHiResScale[0]; + h = cgi.R_GetShaderHeight(handle) * cgs.uiHiResScale[1]; x = ((float)cgs.glconfig.vidWidth - w) * 0.5; y = (float)cgs.glconfig.vidHeight - h; @@ -323,11 +323,15 @@ static void CG_DrawPauseIcon() } w = cgi.R_GetShaderWidth(handle); h = cgi.R_GetShaderHeight(handle); - x = w / 4; - y = cgs.glconfig.vidHeight - (1.25f * h); + if (cg.snap && cg.snap->ps.blend[3] > 0) { + y = cgs.glconfig.vidHeight * 0.45f - h / 2.f; + } else { + y = cgs.glconfig.vidHeight * 0.75f - h / 2.f; + } + x = (cgs.glconfig.vidWidth - w) / 2.f; cgi.R_SetColor(colorWhite); - cgi.R_DrawStretchPic(x, y, w, h, 0, 0, 1, 1, handle); + cgi.R_DrawStretchPic(x, y, w * cgs.uiHiResScale[0], h * cgs.uiHiResScale[1], 0, 0, 1, 1, handle); } static void CG_DrawServerLag() @@ -358,8 +362,8 @@ static void CG_DrawServerLag() } handle = cgi.R_RegisterShader("gfx/2d/slowserver"); - w = (float)cgi.R_GetShaderWidth(handle) / 4; - h = (float)cgi.R_GetShaderHeight(handle) / 4; + w = (float)cgi.R_GetShaderWidth(handle) * cgs.uiHiResScale[0] / 4; + h = (float)cgi.R_GetShaderHeight(handle) * cgs.uiHiResScale[1] / 4; x = ((float)cgs.glconfig.vidWidth - w) / 2; y = (float)cgs.glconfig.vidHeight - h; cgi.R_DrawStretchPic(x, y, w, h, 0.0, 0.0, 1.0, 1.0, handle); @@ -573,14 +577,18 @@ void CG_RefreshHudDrawElements() void CG_HudDrawElements() { - int i; - float fX, fY; - float fWidth, fHeight; + int i; + float fX, fY; + float fWidth, fHeight; + vec2_t virtualScale; if (!cg_huddraw_force->integer && !cg_hud->integer) { return; } + virtualScale[0] = cgs.glconfig.vidWidth / 640.0; + virtualScale[1] = cgs.glconfig.vidHeight / 480.0; + for (i = 0; i < MAX_HUDDRAW_ELEMENTS; i++) { if ((!cgi.HudDrawElements[i].hShader && !cgi.HudDrawElements[i].string[0]) || !cgi.HudDrawElements[i].vColor[3]) { @@ -593,6 +601,13 @@ void CG_HudDrawElements() fWidth = cgi.HudDrawElements[i].iWidth; fHeight = cgi.HudDrawElements[i].iHeight; + if (!cgi.HudDrawElements[i].bVirtualScreen) { + fWidth *= cgs.uiHiResScale[0]; + fHeight *= cgs.uiHiResScale[1]; + fX *= cgs.uiHiResScale[0]; + fY *= cgs.uiHiResScale[1]; + } + if (cgi.HudDrawElements[i].iHorizontalAlign == HUD_ALIGN_X_CENTER) { if (cgi.HudDrawElements[i].bVirtualScreen) { fX += 320.0 - fWidth * 0.5; @@ -623,23 +638,21 @@ void CG_HudDrawElements() cgi.R_SetColor(cgi.HudDrawElements[i].vColor); if (cgi.HudDrawElements[i].string[0]) { - if (cgi.HudDrawElements[i].pFont) { - cgi.R_DrawString( - cgi.HudDrawElements[i].pFont, - cgi.LV_ConvertString(cgi.HudDrawElements[i].string), - fX, - fY, - -1, - cgi.HudDrawElements[i].bVirtualScreen - ); + fontheader_t *pFont = cgi.HudDrawElements[i].pFont; + if (!pFont) { + pFont = cgs.media.hudDrawFont; + } + + if (cgi.HudDrawElements[i].bVirtualScreen) { + cgi.R_DrawString(pFont, cgi.LV_ConvertString(cgi.HudDrawElements[i].string), fX, fY, -1, virtualScale); } else { cgi.R_DrawString( - cgs.media.hudDrawFont, + pFont, cgi.LV_ConvertString(cgi.HudDrawElements[i].string), - fX, - fY, + fX / cgs.uiHiResScale[0], + fY / cgs.uiHiResScale[1], -1, - cgi.HudDrawElements[i].bVirtualScreen + cgs.uiHiResScale ); } } else { @@ -671,22 +684,25 @@ void CG_DrawObjectives() { float vColor[4]; float fX, fY; + int iNumObjectives; + float fObjectivesTop; static float fWidth; float fHeight; int iNumLines[20]; int iTotalNumLines; int i; - int ii; int iCurrentObjective; float fTimeDelta; + const char *pszLocalizedText; + const char *pszLine; iTotalNumLines = 0; for (i = CS_OBJECTIVES; i < CS_OBJECTIVES + MAX_OBJECTIVES; ++i) { - CG_ProcessConfigString(i); + CG_ProcessConfigString(i, qfalse); } - iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE)); - fTimeDelta = cg.ObjectivesAlphaTime - cg.time; + iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE)); + fTimeDelta = cg.ObjectivesAlphaTime - cg.time; cg.ObjectivesCurrentAlpha = cg.ObjectivesDesiredAlpha; if (fTimeDelta > 0) { cg.ObjectivesCurrentAlpha = @@ -698,50 +714,78 @@ void CG_DrawObjectives() return; } - for (i = 0; i < MAX_OBJECTIVES; i++) { - if ((cg.Objectives[i].flags & 0xFFFFFFFE)) { - iNumLines[i] = 0; + // Added in 2.0 + // Get the minimum Y value, it should be below the compass + fObjectivesTop = cgi.UI_GetObjectivesTop(); + iNumObjectives = 0; - for (ii = 0; ii < MAX_STRING_CHARS; ii++) { - if (cg.Objectives[i].text[ii] == '\n') { - iTotalNumLines++; - iNumLines[i]++; - } else if (!cg.Objectives[i].text[ii]) { - iTotalNumLines++; - iNumLines[i]++; - break; - } - } + for (i = 0; i < MAX_OBJECTIVES; i++) { + if ((cg.Objectives[i].flags == OBJ_FLAG_NONE) || (cg.Objectives[i].flags & OBJ_FLAG_HIDDEN)) { + continue; } + + iNumObjectives++; + iNumLines[i] = 0; + pszLocalizedText = cgi.LV_ConvertString(cg.Objectives[i].text); + + for (pszLine = strchr(pszLocalizedText, '\n'); pszLine; pszLine = strchr(pszLine + 1, '\n')) { + iNumLines[i]++; + } + + iTotalNumLines += iNumLines[i]; } fX = 25.0; - fY = 125.0; - fWidth = (float)(25 * iTotalNumLines + 155) + 5.0 - 130.0; + fY = fObjectivesTop + 5; + fWidth = (float)(iTotalNumLines * 12 + fObjectivesTop + iNumObjectives * 25 + 32) - fY; vColor[2] = 0.2f; vColor[1] = 0.2f; vColor[0] = 0.2f; vColor[3] = cg.ObjectivesCurrentAlpha * 0.75; cgi.R_SetColor(vColor); - cgi.R_DrawStretchPic(fX, fY, 450.0, fWidth, 0.0, 0.0, 1.0, 1.0, cgs.media.objectivesBackShader); + cgi.R_DrawStretchPic( + fX, + fY, + 450.0 * cgs.uiHiResScale[0], + fWidth * cgs.uiHiResScale[1], + 0.0, + 0.0, + 1.0, + 1.0, + cgs.media.objectivesBackShader + ); fX = 30.0; - fY = 130.0; + fY = fObjectivesTop + 10; vColor[0] = 1.0; vColor[1] = 1.0; vColor[2] = 1.0; vColor[3] = cg.ObjectivesCurrentAlpha; cgi.R_SetColor(vColor); - cgi.R_DrawString(cgs.media.objectiveFont, cgi.LV_ConvertString("Mission Objectives:"), fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.objectiveFont, + cgi.LV_ConvertString("Mission Objectives:"), + fX, + fY / cgs.uiHiResScale[1], + -1, + cgs.uiHiResScale + ); fY = fY + 5.0; - cgi.R_DrawString(cgs.media.objectiveFont, "_______________________________________________________", fX, fY, -1, 0); - fHeight = 155.0; + cgi.R_DrawString( + cgs.media.objectiveFont, + "_______________________________________________________", + fX, + fY / cgs.uiHiResScale[1], + -1, + cgs.uiHiResScale + ); + fHeight = fObjectivesTop + 35 * cgs.uiHiResScale[1]; for (i = 0; i < MAX_OBJECTIVES; ++i) { qhandle_t hBoxShader; - if ((cg.Objectives[i].flags & OBJ_FLAG_HIDDEN) || !cg.Objectives[i].flags) { + if ((cg.Objectives[i].flags == OBJ_FLAG_NONE) || (cg.Objectives[i].flags & OBJ_FLAG_HIDDEN)) { continue; } @@ -774,7 +818,14 @@ void CG_DrawObjectives() cgi.R_SetColor(vColor); fX = 55.0; fY = fHeight; - cgi.R_DrawString(cgs.media.objectiveFont, cgi.LV_ConvertString(cg.Objectives[i].text), 55.0, fHeight, -1, 0); + cgi.R_DrawString( + cgs.media.objectiveFont, + cgi.LV_ConvertString(cg.Objectives[i].text), + 55.0, + fY / cgs.uiHiResScale[1], + -1, + cgs.uiHiResScale + ); fX = 30.0; fY = fHeight; @@ -783,9 +834,19 @@ void CG_DrawObjectives() vColor[2] = 1.0; vColor[3] = cg.ObjectivesCurrentAlpha; cgi.R_SetColor(vColor); - cgi.R_DrawStretchPic(fX, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, hBoxShader); + cgi.R_DrawStretchPic( + fX * cgs.uiHiResScale[0], + fY, + 16.0 * cgs.uiHiResScale[0], + 16.0 * cgs.uiHiResScale[1], + 0.0, + 0.0, + 1.0, + 1.0, + hBoxShader + ); - fHeight += 25 * iNumLines[i]; + fHeight += iNumLines[i] * 12 + 25 * cgs.uiHiResScale[1]; } } @@ -809,7 +870,17 @@ void CG_DrawPlayerTeam() if (handle) { cgi.R_SetColor(NULL); - cgi.R_DrawStretchPic(96.0, cgs.glconfig.vidHeight - 46, 24.0, 24.0, 0.0, 0.0, 1.0, 1.0, handle); + cgi.R_DrawStretchPic( + 96.0 * cgs.uiHiResScale[0], + cgs.glconfig.vidHeight - 46 * cgs.uiHiResScale[1], + 24.0 * cgs.uiHiResScale[0], + 24.0 * cgs.uiHiResScale[1], + 0.0, + 0.0, + 1.0, + 1.0, + handle + ); } } @@ -851,13 +922,28 @@ void CG_DrawPlayerEntInfo() if (handle) { cgi.R_SetColor(0); - cgi.R_DrawStretchPic(56.0, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, handle); - fX = 56.0 + 24.0; + cgi.R_DrawStretchPic( + fX, fY, 16.0 * cgs.uiHiResScale[0], 16.0 * cgs.uiHiResScale[1], 0.0, 0.0, 1.0, 1.0, handle + ); } cgi.R_SetColor(color); - cgi.R_DrawString(cgs.media.hudDrawFont, (char *)pszName, fX, fY, -1, 0); - cgi.R_DrawString(cgs.media.hudDrawFont, va("%i", cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]), fX, fY + 20.0, -1, 0); + cgi.R_DrawString( + cgs.media.hudDrawFont, + (char *)pszName, + fX / cgs.uiHiResScale[0] + 24.0, + fY / cgs.uiHiResScale[1], + -1, + cgs.uiHiResScale + ); + cgi.R_DrawString( + cgs.media.hudDrawFont, + va("%i", cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]), + fX / cgs.uiHiResScale[0] + 24.0, + fY / cgs.uiHiResScale[1] + 20.0, + -1, + cgs.uiHiResScale + ); } void CG_UpdateAttackerDisplay() @@ -896,7 +982,17 @@ void CG_UpdateAttackerDisplay() if (handle) { cgi.R_SetColor(0); - cgi.R_DrawStretchPic(56.0, fY, 24.0, 24.0, 0.0, 0.0, 1.0, 1.0, handle); + cgi.R_DrawStretchPic( + 56.0 * cgs.uiHiResScale[0], + fY, + 24.0 * cgs.uiHiResScale[0], + 24.0 * cgs.uiHiResScale[1], + 0.0, + 0.0, + 1.0, + 1.0, + handle + ); } if ((cg.snap->ps.stats[STAT_TEAM] == TEAM_ALLIES || cg.snap->ps.stats[STAT_TEAM] == TEAM_AXIS) @@ -910,7 +1006,7 @@ void CG_UpdateAttackerDisplay() color[2] = 0.5; } - fX = 56.0 + 32.0; + fX = 56.0; } else { color[0] = 1.0; color[1] = 0.5; @@ -918,11 +1014,15 @@ void CG_UpdateAttackerDisplay() } cgi.R_SetColor(color); - cgi.R_DrawString(cgs.media.attackerFont, pszName, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, pszName, fX / cgs.uiHiResScale[0] + 32.0, fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); } void CG_UpdateCountdown() { + const char *message = ""; + if (!cg.snap) { return; } @@ -933,16 +1033,25 @@ void CG_UpdateCountdown() iSecondsLeft = (cgs.matchEndTime - cg.time) / 1000; if (iSecondsLeft >= 0) { iMinutesLeft = iSecondsLeft / 60; - cgi.Cvar_Set( - "ui_timemessage", va("%s %2i:%02i", cgi.LV_ConvertString("Time Left:"), iMinutesLeft, iSecondsLeft % 60) - ); + message = va("%s %2i:%02i", cgi.LV_ConvertString("Time Left:"), iMinutesLeft, iSecondsLeft % 60); } else if (!cgs.matchEndTime) { - cgi.Cvar_Set("ui_timemessage", ""); + message = ""; } } else { // The match has not started yet - cgi.Cvar_Set("ui_timemessage", "Waiting For Players"); + message = "Waiting For Players"; } + + if (strcmp(ui_timemessage->string, message)) { + cgi.Cvar_Set("ui_timemessage", message); + } +} + +static void CG_RemoveStopwatch() +{ + cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_fuse\n"); + cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_fuse_wet\n"); } void CG_DrawStopwatch() @@ -950,38 +1059,55 @@ void CG_DrawStopwatch() int iFraction; if (!cg_hud->integer) { - cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + CG_RemoveStopwatch(); return; } if (!cgi.stopWatch->iStartTime) { - cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + CG_RemoveStopwatch(); return; } if (cgi.stopWatch->iStartTime >= cgi.stopWatch->iEndTime) { - cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + CG_RemoveStopwatch(); return; } if (cgi.stopWatch->iEndTime <= cg.time) { - cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + CG_RemoveStopwatch(); return; } if (cg.ObjectivesCurrentAlpha >= 0.02) { - cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + CG_RemoveStopwatch(); return; } if (cg.snap && cg.snap->ps.stats[STAT_HEALTH] <= 0) { - cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n"); + CG_RemoveStopwatch(); return; } + if (cgi.stopWatch->eType >= SWT_FUSE_WET) { + iFraction = cgi.stopWatch->iEndTime - cgi.stopWatch->iStartTime; + } else { + iFraction = cgi.stopWatch->iEndTime - cg.time; + } - iFraction = cgi.stopWatch->iEndTime - cg.time; cgi.Cvar_Set("ui_stopwatch", va("%i", iFraction)); - cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_stopwatch\n"); + + switch (cgi.stopWatch->eType) { + case SWT_NORMAL: + default: + cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_stopwatch\n"); + break; + case SWT_FUSE: + cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_fuse\n"); + break; + case SWT_FUSE_WET: + cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_fuse\n"); + cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_fuse_wet\n"); + break; + } } void CG_DrawInstantMessageMenu() @@ -1005,7 +1131,9 @@ void CG_DrawInstantMessageMenu() x = 8.0; y = ((float)cgs.glconfig.vidHeight - h) * 0.5; cgi.R_SetColor(0); - cgi.R_DrawStretchPic(x, y, w, h, 0.0, 0.0, 1.0, 1.0, handle); + cgi.R_DrawStretchPic( + x * cgs.uiHiResScale[0], y, w * cgs.uiHiResScale[0], h * cgs.uiHiResScale[1], 0.0, 0.0, 1.0, 1.0, handle + ); } void CG_DrawSpectatorView_ver_15() @@ -1028,10 +1156,14 @@ void CG_DrawSpectatorView_ver_15() if (!bOnTeam) { cgi.Key_GetKeysForCommand("+attackprimary", &iKey1, &iKey2); pszString = cgi.LV_ConvertString(va("Press Fire(%s) to join the battle!", cgi.Key_KeynumToBindString(iKey1))); - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5; - fY = cgs.glconfig.vidHeight - 64.0; + fX = (float)(cgs.glconfig.vidWidth + - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) * cgs.uiHiResScale[0]) + * 0.5; + fY = cgs.glconfig.vidHeight - 64.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(NULL); - cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, qfalse); + cgi.R_DrawString( + cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); } if (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW) { @@ -1044,10 +1176,14 @@ void CG_DrawSpectatorView_ver_15() cgi.Key_KeynumToBindString(iKey1b)) ); - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5; - fY = (float)cgs.glconfig.vidHeight - 40.0; + fX = (float)(cgs.glconfig.vidWidth + - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) * cgs.uiHiResScale[0]) + * 0.5; + fY = (float)cgs.glconfig.vidHeight - 40.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(0); - cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); } if (!bOnTeam && (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) { @@ -1055,10 +1191,14 @@ void CG_DrawSpectatorView_ver_15() pszString = cgi.LV_ConvertString(va("Press Use(%s) to enter free spectate mode.", cgi.Key_KeynumToBindString(iKey1))); - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5; - fY = (float)cgs.glconfig.vidHeight - 24.0; + fX = (float)(cgs.glconfig.vidWidth + - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) * cgs.uiHiResScale[0]) + * 0.5; + fY = (float)cgs.glconfig.vidHeight - 24.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(0); - cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); } if (!(cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) { @@ -1068,31 +1208,42 @@ void CG_DrawSpectatorView_ver_15() va("Press Use(%s) to enter player following spectate mode.", cgi.Key_KeynumToBindString(iKey1)) ); - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5; - fY = (float)cgs.glconfig.vidHeight - 24.0; + fX = (float)(cgs.glconfig.vidWidth + - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) * cgs.uiHiResScale[0]) + * 0.5; + fY = (float)cgs.glconfig.vidHeight - 24.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(0); - cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); } - if ((cg.predicted_player_state.pm_flags & 0x80) != 0 && cg.snap && cg.snap->ps.stats[STAT_INFOCLIENT] != -1) { + if ((cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW) != 0 && cg.snap + && cg.snap->ps.stats[STAT_INFOCLIENT] != -1) { int iClientNum; qhandle_t hShader; vec4_t color; char buf[128]; iClientNum = cg.snap->ps.stats[STAT_INFOCLIENT]; - sprintf(buf, "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]); + Com_sprintf( + buf, sizeof(buf), "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH] + ); - hShader = 0; + hShader = 0; color[0] = 0.5; color[1] = 1.0; color[2] = 0.5; color[3] = 1.0; - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) - 16) * 0.5; - fY = (float)cgs.glconfig.vidHeight - 80.0; + fX = (float)(cgs.glconfig.vidWidth + - (cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) - 16) * cgs.uiHiResScale[0]) + * 0.5; + fY = (float)cgs.glconfig.vidHeight - 80.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(color); - cgi.R_DrawString(cgs.media.attackerFont, buf, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, buf, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); if (cg.clientinfo[iClientNum].team == TEAM_ALLIES) { hShader = cgi.R_RegisterShader("textures/hud/allies"); @@ -1101,9 +1252,18 @@ void CG_DrawSpectatorView_ver_15() } if (hShader) { - fX -= 20.0; cgi.R_SetColor(NULL); - cgi.R_DrawStretchPic(fX, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, hShader); + cgi.R_DrawStretchPic( + fX - 20.0 * cgs.uiHiResScale[0], + fY, + 16.0 * cgs.uiHiResScale[0], + 16.0 * cgs.uiHiResScale[1], + 0.0, + 0.0, + 1.0, + 1.0, + hShader + ); } } } @@ -1135,10 +1295,14 @@ void CG_DrawSpectatorView_ver_6() pszString = cgi.LV_ConvertString(va("Press Use(%s) to follow a player.", cgi.Key_KeynumToBindString(iKey1))); } - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5; - fY = (float)cgs.glconfig.vidHeight - 40.0; + fX = (float)(cgs.glconfig.vidWidth + - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) * cgs.uiHiResScale[0]) + * 0.5; + fY = (float)cgs.glconfig.vidHeight - 40.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(0); - cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); if (!bOnTeam && (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) { cgi.Key_GetKeysForCommand("+moveup", &iKey1, &iKey2); @@ -1149,10 +1313,14 @@ void CG_DrawSpectatorView_ver_6() cgi.Key_KeynumToBindString(iKey1b)) ); - fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5; - fY = (float)cgs.glconfig.vidHeight - 24.0; + fX = (float)(cgs.glconfig.vidWidth + - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) * cgs.uiHiResScale[0]) + * 0.5; + fY = (float)cgs.glconfig.vidHeight - 24.0 * cgs.uiHiResScale[1]; cgi.R_SetColor(0); - cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0); + cgi.R_DrawString( + cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); } } @@ -1165,6 +1333,174 @@ void CG_DrawSpectatorView() } } +void CG_DrawCrosshair() +{ + centity_t *friendEnt; + qhandle_t shader; + vec3_t forward; + vec3_t end; + vec3_t mins, maxs; + trace_t trace; + float x, y; + float width, height; + + shader = (qhandle_t)0; + + if (!cg_hud->integer || !ui_crosshair->integer) { + return; + } + + if (!cg.snap) { + return; + } + + if ((cg.snap->ps.pm_flags & PMF_NO_HUD) || (cg.snap->ps.pm_flags & PMF_INTERMISSION)) { + return; + } + + if (!cg.snap->ps.stats[STAT_CROSSHAIR] + && (!cg.snap->ps.stats[STAT_INZOOM] || cg.snap->ps.stats[STAT_INZOOM] > 30)) { + return; + } + + // Fixed in OPM: R_RegisterShaderNoMip + // Use R_RegisterShaderNoMip, as it's UI stuff + + if (cgs.gametype != GT_FFA) { + AngleVectorsLeft(cg.refdefViewAngles, forward, NULL, NULL); + + VectorMA(cg.refdef.vieworg, 8192, forward, end); + VectorClear(mins); + VectorClear(maxs); + + CG_Trace(&trace, cg.refdef.vieworg, mins, maxs, end, 9999, MASK_SOLID, qfalse, qtrue, "CG_DrawCrosshair"); + + // ENTITYNUM_WORLD check added in OPM + if ((trace.entityNum != ENTITYNUM_NONE && trace.entityNum != ENTITYNUM_WORLD) + && trace.entityNum != cg.snap->ps.clientNum) { + int myFlags; + + friendEnt = &cg_entities[trace.entityNum]; + if (cgs.gametype != GT_SINGLE_PLAYER) { + myFlags = cg_entities[cg.snap->ps.clientNum].currentState.eFlags & EF_ANY_TEAM; + } else { + // the player will always be considered as an allied + // in single-player + myFlags = EF_ALLIES; + } + + if (((myFlags & EF_ALLIES) && (friendEnt->currentState.eFlags & EF_ALLIES)) + || ((myFlags & EF_AXIS) && (friendEnt->currentState.eFlags & EF_AXIS))) { + // friend + if (cg.snap->ps.stats[STAT_CROSSHAIR]) { + shader = cgi.R_RegisterShaderNoMip(cg_crosshair_friend->string); + } + } else { + // enemy + if (cg.snap->ps.stats[STAT_CROSSHAIR]) { + shader = cgi.R_RegisterShaderNoMip(cg_crosshair->string); + } + } + } else { + if (cg.snap->ps.stats[STAT_CROSSHAIR]) { + shader = cgi.R_RegisterShaderNoMip(cg_crosshair->string); + } + } + } else { + // FFA + if (cg.snap->ps.stats[STAT_CROSSHAIR]) { + shader = cgi.R_RegisterShaderNoMip(cg_crosshair->string); + } + } + + if (shader) { + width = cgi.R_GetShaderWidth(shader); + height = cgi.R_GetShaderHeight(shader); + x = (cgs.glconfig.vidWidth - width) * 0.5f; + y = (cgs.glconfig.vidHeight - height) * 0.5f; + + cgi.R_SetColor(NULL); + cgi.R_DrawStretchPic(x, y, width * cgs.uiHiResScale[0], height * cgs.uiHiResScale[1], 0, 0, 1, 1, shader); + } +} + +void CG_DrawVote() +{ + const char *text; + int seconds; + int percentYes; + int percentNo; + int percentUndecided; + float x, y; + vec4_t col; + + if (!cgs.voteTime) { + return; + } + + if (cgs.voteRefreshed) { + cgs.voteRefreshed = qfalse; + } + + seconds = (30000 - (cg.time - cgs.voteTime)) / 1000 + 1; + if (seconds < 0) { + seconds = 0; + } + + percentYes = cgs.numVotesYes * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes); + percentNo = cgs.numVotesNo * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes); + percentUndecided = cgs.numUndecidedVotes * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes); + + x = 8 * cgs.uiHiResScale[0]; + y = ((cgs.glconfig.vidHeight > 480) ? (cgs.glconfig.vidHeight * 0.725f) : (cgs.glconfig.vidHeight * 0.75f)); + + cgi.R_SetColor(NULL); + + text = va("%s: %s", cgi.LV_ConvertString("Vote Running"), cgs.voteString); + cgi.R_DrawString( + cgs.media.attackerFont, text, x / cgs.uiHiResScale[0], y / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); + + y += 12 * cgs.uiHiResScale[1]; + + text = + va("%s: %isec %s: %i%% %s: %i%% %s: %i%%", + cgi.LV_ConvertString("Time"), + seconds, + cgi.LV_ConvertString("Yes"), + percentYes, + cgi.LV_ConvertString("No"), + percentNo, + cgi.LV_ConvertString("Undecided"), + percentUndecided); + cgi.R_DrawString( + cgs.media.attackerFont, text, x / cgs.uiHiResScale[0], y / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); + + if (cg.snap && !cg.snap->ps.voted) { + col[0] = 0.5; + col[1] = 1.0; + col[2] = 0.5; + col[3] = 1.0; + cgi.R_SetColor(col); + + y += 12 * cgs.uiHiResScale[1]; + + text = cgi.LV_ConvertString("Vote now, it's your patriotic duty!"); + cgi.R_DrawString( + cgs.media.attackerFont, text, x / cgs.uiHiResScale[0], y / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); + + y += 12 * cgs.uiHiResScale[1]; + + text = cgi.LV_ConvertString("To vote Yes, press F1. To vote No, press F2."); + cgi.R_DrawString( + cgs.media.attackerFont, text, x / cgs.uiHiResScale[0], y / cgs.uiHiResScale[1], -1, cgs.uiHiResScale + ); + cgi.R_SetColor(NULL); + } +} + /* ============== CG_Draw2D @@ -1183,5 +1519,7 @@ void CG_Draw2D(void) CG_DrawPlayerTeam(); CG_DrawPlayerEntInfo(); CG_UpdateAttackerDisplay(); + CG_DrawVote(); CG_DrawInstantMessageMenu(); + CG_DrawCrosshair(); } diff --git a/code/cgame/cg_lightstyles.cpp b/code/cgame/cg_lightstyles.cpp index dfb9e76f..3a280a66 100644 --- a/code/cgame/cg_lightstyles.cpp +++ b/code/cgame/cg_lightstyles.cpp @@ -59,7 +59,7 @@ qboolean CG_LightStyleColor(int style, int realtime, vec4_t color, qboolean clam time = realtime / 50; frac = (realtime - (time * 50.0f)) / 50.0f; - memset(color, 0, sizeof(color)); + VectorClear4(color); if ((style < 0) || (style >= (MAX_LIGHTSTYLES * 2))) { cgi.DPrintf("CG_LightStyleColor: style out of range.\n"); return qtrue; diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 1f2bbec5..86921201 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_public.h" #ifdef __cplusplus +class MemArchiver; + extern "C" { #endif @@ -185,6 +187,7 @@ extern "C" { float min_dist; float width; char shader[MAX_RAIN_SHADERS][MAX_STRING_CHARS]; + char currentShader[MAX_STRING_CHARS]; int numshaders; } crain_t; @@ -267,6 +270,8 @@ extern "C" { qhandle_t hAlliedPlayerModelHandle; dtiki_t *pAxisPlayerModel; qhandle_t hAxisPlayerModelHandle; + qboolean serverAlliedModelValid; + qboolean serverAxisModelValid; // view eyes vec3_t vOffsetViewAngles; @@ -338,6 +343,7 @@ extern "C" { float ObjectivesBaseAlpha; float ObjectivesDesiredAlpha; float ObjectivesCurrentAlpha; + int ObjectivesCurrentIndex; // misc crain_t rain; @@ -376,6 +382,7 @@ extern "C" { float screenXScale; // derived from glconfig float screenYScale; float screenXBias; + vec2_t uiHiResScale; int serverCommandSequence; // reliable command stream counter int processedSnapshotNum; // the number of snapshots cgame has requested @@ -394,8 +401,19 @@ extern "C" { int maxclients; int cinematic; int mapChecksum; + qboolean useMapChecksum; char mapname[MAX_QPATH]; + // + // vote + // + int voteTime; + int numVotesYes; + int numVotesNo; + int numUndecidedVotes; + qboolean voteRefreshed; + char voteString[1024]; + // // locally derived information from gamestate // @@ -416,6 +434,7 @@ extern "C" { extern cgs_t cgs; extern cg_t cg; extern clientGameImport_t cgi; + extern target_game_e cg_target_game; extern int cg_protocol; extern centity_t cg_entities[MAX_GENTITIES]; extern markPoly_t *cg_markPolys; @@ -458,6 +477,9 @@ extern "C" { extern cvar_t *cg_hud; extern cvar_t *cg_huddraw_force; extern cvar_t *cg_drawsvlag; + extern cvar_t *cg_crosshair; + extern cvar_t *cg_crosshair_friend; + extern cvar_t *ui_crosshair; extern cvar_t *vm_offset_max; extern cvar_t *vm_offset_speed; extern cvar_t *vm_sway_front; @@ -484,11 +506,19 @@ extern "C" { extern cvar_t *voiceChat; extern cvar_t *cg_shadowscount; extern cvar_t *cg_shadowdebug; + extern cvar_t *ui_timemessage; + + // + // Added in OPM + // + extern cvar_t *cg_fov; + extern cvar_t *cg_cheats; // // cg_main.c // - void CG_ProcessConfigString(int num); + qboolean CG_UseLargeLightmaps(const char* mapName); + void CG_ProcessConfigString(int num, qboolean modelOnly); const char *CG_ConfigString(int index); void CG_AddToTeamChat(const char *str); void CG_NewClientinfo(int clientNum); @@ -503,6 +533,9 @@ extern "C" { // // cg_modelanim.cpp // + void CG_ProcessPlayerModel(); + void CG_ServerModelLoaded(const char* name, qhandle_t handle); + void CG_ServerModelUnloaded(qhandle_t handle); void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime); void CG_AttachEntity( refEntity_t *entity, refEntity_t *parent, dtiki_t *tiki, int tagnum, qboolean use_angles, vec3_t attach_offset @@ -530,6 +563,8 @@ extern "C" { // cg_tempmodels.cpp // extern cvar_t *cg_showtempmodels; + extern cvar_t *cg_max_tempmodels; + extern cvar_t *cg_reserve_tempmodels; extern cvar_t *cg_detail; extern cvar_t *cg_effectdetail; extern cvar_t *cg_effect_physicsrate; @@ -708,8 +743,8 @@ extern "C" { void CG_InitTestTreadMark(); void CG_AddTreadMarks(); int CG_PermanentMark( - const vec3_t origin, - const vec3_t dir, + vec3_t origin, + vec3_t dir, float orientation, float fSScale, float fTScale, @@ -902,7 +937,8 @@ qboolean CG_LightStyleColor(int style, int realtime, vec4_t color, qboolean clam void CG_InstaMessageGroupD_f(void); void CG_InstaMessageGroupE_f(void); void CG_HudPrint_f(void); - int CG_CheckCaptureKey(int key, qboolean down, unsigned int time); + + qboolean CG_CheckCaptureKey(int key, qboolean down, unsigned int time); // // cg_vehicle.cpp @@ -911,6 +947,9 @@ qboolean CG_LightStyleColor(int style, int realtime, vec4_t color, qboolean clam // // cg_volumetricsmoke.cpp void CG_ResetVSSSources(void); +#ifdef __cplusplus + void CG_ArchiveVSSGlobals(MemArchiver& archiver); +#endif void CG_AddVSSSources(void); extern cvar_t *vss_draw; diff --git a/code/cgame/cg_main.c b/code/cgame/cg_main.c index 6df6b357..71295f3e 100644 --- a/code/cgame/cg_main.c +++ b/code/cgame/cg_main.c @@ -35,12 +35,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA clientGameImport_t cgi; static clientGameExport_t cge; -cvar_t *paused; -cvar_t *developer; -cg_t cg; -cgs_t cgs; -int cg_protocol; -centity_t cg_entities[MAX_GENTITIES]; +cvar_t *paused; +cvar_t *developer; +cg_t cg; +cgs_t cgs; +target_game_e cg_target_game = TG_INVALID; +int cg_protocol; +centity_t cg_entities[MAX_GENTITIES]; cvar_t *cg_animSpeed; cvar_t *cg_debugAnim; @@ -80,6 +81,9 @@ cvar_t *cg_acidtrip; cvar_t *cg_hud; cvar_t *cg_huddraw_force; cvar_t *cg_drawsvlag; +cvar_t *cg_crosshair; +cvar_t *cg_crosshair_friend; +cvar_t *ui_crosshair; cvar_t *vm_offset_max; cvar_t *vm_offset_speed; cvar_t *vm_sway_front; @@ -106,6 +110,13 @@ cvar_t *vm_lean_lower; cvar_t *voiceChat; cvar_t *cg_shadowscount; cvar_t *cg_shadowdebug; +cvar_t *ui_timemessage; + +// +// Added in OPM +// +cvar_t *cg_fov; +cvar_t *cg_cheats; /* ================= @@ -151,14 +162,23 @@ void CG_RegisterCvars(void) cg_shadowdebug = cgi.Cvar_Get("cg_shadowdebug", "0", 0); developer = cgi.Cvar_Get("developer", "0", 0); dm_playermodel = cgi.Cvar_Get("dm_playermodel", "american_army", 3); - dm_playergermanmodel = cgi.Cvar_Get("dm_playergermanmodel", "german_wehrmacht_soldier", 3); + dm_playergermanmodel = cgi.Cvar_Get("dm_playergermanmodel", "german_wehrmacht_soldier", CVAR_ARCHIVE | CVAR_USERINFO); cg_forceModel = cgi.Cvar_Get("cg_forceModel", "0", CVAR_ARCHIVE); - cg_animationviewmodel = cgi.Cvar_Get("cg_animationviewmodel", "0", 8); + cg_animationviewmodel = cgi.Cvar_Get("cg_animationviewmodel", "0", CVAR_SYSTEMINFO); cg_hitmessages = cgi.Cvar_Get("cg_hitmessages", "1", CVAR_ARCHIVE); cg_acidtrip = cgi.Cvar_Get("cg_acidtrip", "0", CVAR_CHEAT); cg_hud = cgi.Cvar_Get("cg_hud", "0", 0); cg_huddraw_force = cgi.Cvar_Get("cg_huddraw_force", "0", CVAR_SAVEGAME); cg_drawsvlag = cgi.Cvar_Get("cg_drawsvlag", "1", CVAR_ARCHIVE); + cg_crosshair = cgi.Cvar_Get("cg_crosshair", "textures/hud/crosshair", CVAR_ARCHIVE); + if (cg_protocol >= PROTOCOL_MOHTA_MIN) { + cg_crosshair_friend = cgi.Cvar_Get("cg_crosshair_friend", "textures/hud/crosshair_friend", CVAR_ARCHIVE); + } else { + // on 1.11 and below, fallback to standard crosshair + // as it doesn't have crosshair_friend texture + cg_crosshair_friend = cgi.Cvar_Get("cg_crosshair_friend", "textures/hud/crosshair", CVAR_ARCHIVE); + } + ui_crosshair = cgi.Cvar_Get("ui_crosshair", "1", CVAR_ARCHIVE); vm_offset_max = cgi.Cvar_Get("vm_offset_max", "8.0", 0); vm_offset_speed = cgi.Cvar_Get("vm_offset_speed", "8.0", 0); vm_sway_front = cgi.Cvar_Get("vm_sway_front", "0.1", 0); @@ -184,53 +204,137 @@ void CG_RegisterCvars(void) vm_lean_lower = cgi.Cvar_Get("vm_lean_lower", "0.1", 0); voiceChat = cgi.Cvar_Get("cg_voicechat", "1", 0); + ui_timemessage = cgi.Cvar_Get("ui_timemessage", "", 0); + // see if we are also running the server on this machine temp = cgi.Cvar_Get("sv_running", "0", 0); cgs.localServer = temp->integer; + + // + // Added in OPM + // + + cg_fov = cgi.Cvar_Get("cg_fov", "80", CVAR_ARCHIVE); + cg_cheats = cgi.Cvar_Get("cheats", "0", CVAR_USERINFO | CVAR_SERVERINFO | CVAR_LATCH); +} +/* +=============== +CG_UseLargeLightmaps + +Added in 2.0 +Returns true if the standard BSP file should be used, false if the smaller lightmap BSP file should be used +=============== +*/ +qboolean CG_UseLargeLightmaps(const char* mapName) { + char buffer[MAX_QPATH]; + + Com_sprintf(buffer, sizeof(buffer), "maps/%s_sml.bsp", mapName); + + if (cgi.FS_ReadFile(buffer, NULL, qtrue) == -1) { + return qtrue; + } + + return cgi.Cvar_Get("r_largemap", "0", 0)->integer; +} + +/* +================ +CG_RegisterSoundsForFile + +Register the specified ubersound source file +================ +*/ +void CG_RegisterSoundsForFile(const char *name) +{ + int startTime; + int endTime; + + Com_Printf("\n\n-----------PARSING '%s'------------\n", name); + Com_Printf( + "Any SetCurrentTiki errors means that tiki wasn't prefetched and tiki-specific sounds for it won't work. To " + "fix prefetch the tiki. Ignore if you don't use that tiki on this level.\n" + ); + + startTime = cgi.Milliseconds(); + CG_Command_ProcessFile(name, qfalse, NULL); + endTime = cgi.Milliseconds(); + + Com_Printf("Parse/Load time: %f seconds.\n", (float)(endTime - startTime) / 1000.0); + Com_Printf("-------------PARSING '%s' DONE---------------\n\n", name); +} + +/* +================= +qsort_compare_strings + +perform case-insensitive sorting +================= +*/ +int qsort_compare_strings(const void *s1, const void *s2) +{ + return Q_stricmp(*(const char **)s1, *(const char **)s2); } /* ================= CG_RegisterSounds -called during a precache command +Called during a precache command ================= */ void CG_RegisterSounds(void) { - int startTime; - int endTime; - char filename[MAX_QPATH]; + char **fileList; + int numFiles; + int i; - Com_Printf("\n\n-----------PARSING UBERSOUND------------\n"); - Com_Printf( - "Any SetCurrentTiki errors means that tiki wasn't prefetched and " - "tiki-specific sounds for it won't work. To fix prefe" - "tch the tiki. Ignore if you don't use that tiki on this level.\n" - ); - Com_sprintf(filename, sizeof(filename), "ubersound/ubersound.scr"); + fileList = cgi.FS_ListFilteredFiles("ubersound/", "scr", "*.scr", qfalse, &numFiles, qtrue); + if (cg_target_game >= TG_MOHTA) { + // Fixed in 2.0 + // The behavior has changed, all aliases get cleared + if (cgs.gametype != GT_SINGLE_PLAYER) { + cgi.Alias_Clear(); + } + } else { + if (!cgs.localServer) { + cgi.Alias_Clear(); + } + } + + qsort(fileList, numFiles, sizeof(char *), &qsort_compare_strings); - startTime = cgi.Milliseconds(); - CG_Command_ProcessFile(filename, 0, 0); - endTime = cgi.Milliseconds(); + for (i = 0; i < numFiles; i++) { + // Added in 2.0 + // Since 2.0, all files in the ubersound folder + // are parsed + CG_RegisterSoundsForFile(va("ubersound/%s", fileList[i])); + } - Com_Printf("Parse/Load time: %f seconds.\n", (endTime - startTime) / 1000.0f); + cgi.FS_FreeFileList(fileList); +} - Com_Printf("-------------UBERSOUND DONE---------------\n\n"); - Com_Printf("\n\n-----------PARSING UBERDIALOG------------\n"); - Com_Printf( - "Any SetCurrentTiki errors means that tiki wasn't prefetched and " - "tiki-specific sounds for it won't work. To fix prefe" - "tch the tiki. Ignore if you don't use that tiki on this level.\n" - ); - Com_sprintf(filename, sizeof(filename), "ubersound/uberdialog.scr"); +/* +================ +CG_IsHandleUnique - startTime = cgi.Milliseconds(); - CG_Command_ProcessFile(filename, 0, 0); - endTime = cgi.Milliseconds() - startTime; +Check if the model handle is unique +================ +*/ +static qboolean CG_IsHandleUnique(qhandle_t handle) { + int i; + int numRef; - Com_Printf("Parse/Load time: %f seconds.\n", endTime / 1000.0f); - Com_Printf("-------------UBERDIALOG DONE---------------\n\n"); + numRef = 0; + for (i = 0; i < MAX_MODELS; i++) { + if (cgs.model_draw[i] == handle) { + numRef++; + if (numRef >= 2) { + return qfalse; + } + } + } + + return qtrue; } /* @@ -238,86 +342,17 @@ void CG_RegisterSounds(void) CG_ProcessConfigString ================ */ -void CG_ProcessConfigString(int num) +void CG_ProcessConfigString(int num, qboolean modelOnly) { - const char *str = CG_ConfigString(num); - int i; + const char* str; + int i; - switch (num) { - case CS_RAIN_DENSITY: - cg.rain.density = atof(str); - return; - case CS_RAIN_SPEED: - cg.rain.speed = atof(str); - return; - case CS_RAIN_SPEEDVARY: - cg.rain.speed_vary = atoi(str); - return; - case CS_RAIN_SLANT: - cg.rain.slant = atoi(str); - return; - case CS_RAIN_LENGTH: - cg.rain.length = atof(str); - return; - case CS_RAIN_MINDIST: - cg.rain.min_dist = atof(str); - return; - case CS_RAIN_WIDTH: - cg.rain.width = atof(str); - return; - case CS_RAIN_SHADER: - if (cg.rain.numshaders) { - for (i = 0; i < cg.rain.numshaders; i++) { - sprintf(cg.rain.shader[i], "%s%i", str, i); - } - } else { - strcpy(cg.rain.shader[0], str); - } - return; - case CS_RAIN_NUMSHADERS: - cg.rain.numshaders = atoi(str); - if (cg.rain.numshaders) { - for (i = 0; i < cg.rain.numshaders; i++) { - sprintf(cg.rain.shader[i], "%s%i", str, i); - } - } - return; - } - - if (num >= CS_OBJECTIVES && num < CS_OBJECTIVES + MAX_OBJECTIVES) { - cobjective_t *objective = &cg.Objectives[num - CS_OBJECTIVES]; - objective->flags = atoi(Info_ValueForKey(str, "flags")); - strcpy(objective->text, Info_ValueForKey(str, "text")); - } - - switch (num) { - case CS_MUSIC: - cgi.MUSIC_NewSoundtrack(str); - return; - case CS_WARMUP: - cg.matchStartTime = atoi(str); - return; - case CS_FOGINFO: - CG_ParseFogInfo(str); - return; - case CS_SKYINFO: - sscanf(str, "%f %d", &cg.sky_alpha, &cg.sky_portal); - return; - case CS_SERVERINFO: - CG_ParseServerinfo(); - return; - case CS_LEVEL_START_TIME: - cgs.levelStartTime = atoi(str); - return; - case CS_MATCHEND: - cgs.matchEndTime = atoi(str); - return; - } + str = CG_ConfigString(num); if (num >= CS_MODELS && num < CS_MODELS + MAX_MODELS) { qhandle_t hOldModel = cgs.model_draw[num - CS_MODELS]; - if (str && str[0]) { + if (str && str[0] && !modelOnly) { qhandle_t hModel = cgi.R_RegisterServerModel(str); dtiki_t *tiki; @@ -332,45 +367,161 @@ void CG_ProcessConfigString(int num) if (tiki) { CG_ProcessCacheInitCommands(tiki); } + + CG_ServerModelLoaded(str, hModel); } else { // clear out the model - if (hOldModel) { + if (hOldModel && CG_IsHandleUnique(hOldModel)) { + // Handle uniqueness added in OPM cgi.R_UnregisterServerModel(hOldModel); } cgs.model_draw[num - CS_MODELS] = 0; - } - } else if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS) { - size_t len = strlen(str); - if (len) { - qboolean streamed; - char buf[1024]; - strcpy(buf, str); - streamed = buf[len - 1] != '0'; - buf[len - 1] = 0; - if (buf[0] != '*') { - cgs.sound_precache[num - CS_SOUNDS] = cgi.S_RegisterSound(buf, streamed); + if (!str || !str[0]) { + CG_ServerModelUnloaded(hOldModel); } } - } else if (num >= CS_LIGHTSTYLES && num < CS_LIGHTSTYLES + MAX_LIGHTSTYLES) { - CG_SetLightStyle(num - CS_LIGHTSTYLES, str); - } else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS) { - const char *value; + } - value = Info_ValueForKey(str, "name"); - if (value) { - strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name)); - } else { - strncpy( - cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name) - ); + if (!modelOnly) { + switch (num) { + case CS_RAIN_DENSITY: + cg.rain.density = atof(str); + return; + case CS_RAIN_SPEED: + cg.rain.speed = atof(str); + return; + case CS_RAIN_SPEEDVARY: + cg.rain.speed_vary = atoi(str); + return; + case CS_RAIN_SLANT: + cg.rain.slant = atoi(str); + return; + case CS_RAIN_LENGTH: + cg.rain.length = atof(str); + return; + case CS_RAIN_MINDIST: + cg.rain.min_dist = atof(str); + return; + case CS_RAIN_WIDTH: + cg.rain.width = atof(str); + return; + case CS_RAIN_SHADER: + Q_strncpyz(cg.rain.currentShader, str, sizeof(cg.rain.currentShader)); + if (cg.rain.numshaders) { + // Fixed in OPM + // not sure why some maps set a digit at the end... + size_t len = strlen(cg.rain.currentShader); + if (isdigit(cg.rain.currentShader[len - 1])) { + cg.rain.currentShader[len - 1] = 0; + } + } + for (i = 0; i < cg.rain.numshaders; ++i) { + Com_sprintf(cg.rain.shader[i], sizeof(cg.rain.shader[i]), "%s%i", cg.rain.currentShader, i); + } + if (!cg.rain.numshaders) { + Q_strncpyz(cg.rain.shader[0], cg.rain.currentShader, sizeof(cg.rain.shader[0])); + } + return; + case CS_RAIN_NUMSHADERS: + cg.rain.numshaders = atoi(str); + if (cg.rain.numshaders) { + for (i = 0; i < cg.rain.numshaders; i++) { + Com_sprintf(cg.rain.shader[i], sizeof(cg.rain.shader[i]), "%s%i", cg.rain.currentShader, i); + } + } + return; + case CS_CURRENT_OBJECTIVE: + cg.ObjectivesCurrentIndex = atoi(str); + return; } - value = Info_ValueForKey(str, "team"); - if (value) { - cg.clientinfo[num - CS_PLAYERS].team = atoi(value); - } else { - cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE; + if (num >= CS_OBJECTIVES && num < CS_OBJECTIVES + MAX_OBJECTIVES) { + cobjective_t *objective = &cg.Objectives[num - CS_OBJECTIVES]; + objective->flags = atoi(Info_ValueForKey(str, "flags")); + Q_strncpyz(objective->text, Info_ValueForKey(str, "text"), sizeof(objective->text)); + } + + switch (num) { + case CS_MUSIC: + cgi.MUSIC_NewSoundtrack(str); + return; + case CS_WARMUP: + cg.matchStartTime = atoi(str); + return; + case CS_FOGINFO: + cg.farclipOverride = 0; + cg.farplaneColorOverride[0] = -1; + cg.farplaneColorOverride[1] = -1; + cg.farplaneColorOverride[2] = -1; + CG_ParseFogInfo(str); + return; + case CS_SKYINFO: + sscanf(str, "%f %d", &cg.sky_alpha, &cg.sky_portal); + return; + case CS_SERVERINFO: + CG_ParseServerinfo(); + return; + case CS_LEVEL_START_TIME: + cgs.levelStartTime = atoi(str); + return; + case CS_VOTE_TIME: + cgs.voteTime = atoi(str); + cgs.voteRefreshed = qtrue; + break; + case CS_VOTE_STRING: + Q_strncpyz(cgs.voteString, str, sizeof(cgs.voteString)); + break; + case CS_VOTE_YES: + cgs.numVotesYes = atoi(str); + cgs.voteRefreshed = qtrue; + break; + case CS_VOTE_NO: + cgs.numVotesNo = atoi(str); + cgs.voteRefreshed = qtrue; + break; + case CS_VOTE_UNDECIDED: + cgs.numUndecidedVotes = atoi(str); + cgs.voteRefreshed = qtrue; + break; + case CS_MATCHEND: + cgs.matchEndTime = atoi(str); + return; + } + + if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS) { + size_t len = strlen(str); + if (len) { + qboolean streamed; + char buf[1024]; + Q_strncpyz(buf, str, sizeof(buf)); + + streamed = buf[len - 1] != '0'; + buf[len - 1] = 0; + if (buf[0] != '*') { + cgs.sound_precache[num - CS_SOUNDS] = cgi.S_RegisterSound(buf, streamed); + } + } + } else if (num >= CS_LIGHTSTYLES && num < CS_LIGHTSTYLES + MAX_LIGHTSTYLES) { + CG_SetLightStyle(num - CS_LIGHTSTYLES, str); + } else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS) { + const char *value; + + value = Info_ValueForKey(str, "name"); + if (value) { + strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name)); + } else { + strncpy( + cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name) + ); + } + + value = Info_ValueForKey(str, "team"); + if (value) { + cg.clientinfo[num - CS_PLAYERS].team = atoi(value); + } else { + cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE; + } } } } @@ -423,14 +574,14 @@ void CG_PrepRefresh(void) cgs.media.binocularsOverlayShader = cgi.R_RegisterShaderNoMip("textures/hud/binocularsoverlay"); cgs.media.hudDrawFont = cgi.R_LoadFont("verdana-14"); cgs.media.attackerFont = cgi.R_LoadFont("facfont-20"); - cgs.media.objectiveFont = cgi.R_LoadFont("courier-16"); + cgs.media.objectiveFont = cgi.R_LoadFont("facfont-20"); // was courier-16 before 2.0 cgs.media.objectivesBackShader = cgi.R_RegisterShaderNoMip("textures/hud/objectives_backdrop"); cgs.media.checkedBoxShader = cgi.R_RegisterShaderNoMip("textures/objectives/filledbox"); cgs.media.uncheckedBoxShader = cgi.R_RegisterShaderNoMip("textures/objectives/emptybox"); // go through all the configstrings and process them for (i = CS_SYSTEMINFO + 1; i < MAX_CONFIGSTRINGS; i++) { - CG_ProcessConfigString(i); + CG_ProcessConfigString(i, qfalse); } } @@ -457,6 +608,7 @@ void CG_GetRendererConfig(void) cgi.GetGlconfig(&cgs.glconfig); cgs.screenXScale = cgs.glconfig.vidWidth / 640.0; cgs.screenYScale = cgs.glconfig.vidHeight / 480.0; + cgi.UI_GetHighResolutionScale(cgs.uiHiResScale); } /* @@ -469,6 +621,7 @@ Displays the info screen while loading media void CG_GameStateReceived(void) { const char *s; + int checksum; // clear everything memset(&cg, 0, sizeof(cg)); @@ -495,7 +648,10 @@ void CG_GameStateReceived(void) CG_ParseServerinfo(); // load the new map - cgi.CM_LoadMap(cgs.mapname); + cgi.CM_LoadMap(cgs.mapname, &checksum); + if (cgs.useMapChecksum && checksum != cgs.mapChecksum && cgs.gametype != GT_SINGLE_PLAYER) { + cgi.Error(ERR_DROP, "Client/Server map checksum mismatch: %x/%x", checksum, cgs.mapChecksum); + } CG_InitMarks(); @@ -539,16 +695,6 @@ void CG_ServerRestarted(void) CG_InitializeObjectives(); } -void *CG_Malloc(int size) -{ - return malloc(size); -} - -void CG_Free(void *ptr) -{ - free(ptr); -} - /* ================= CG_Init @@ -559,17 +705,20 @@ Called after every level change or subsystem restart void CG_Init(clientGameImport_t *imported, int serverMessageNum, int serverCommandSequence, int clientNum) { cgi = *imported; -#if _DEBUG - cgi.Malloc = &CG_Malloc; - cgi.Free = &CG_Free; -#endif cg_protocol = cgi.Cvar_Get("com_protocol", "", 0)->integer; + cg_target_game = (target_game_e)cgi.Cvar_Get("com_target_game", "0", 0)->integer; + CG_InitCGMessageAPI(&cge); CG_InitScoresAPI(&cge); memset(&cg, 0, sizeof(cg)); memset(&cgs, 0, sizeof(cgs)); + // clear fog values + cg.farclipOverride = 0; + cg.farplaneColorOverride[0] = -1; + cg.farplaneColorOverride[1] = -1; + cg.farplaneColorOverride[2] = -1; cg.clientNum = clientNum; cgs.processedSnapshotNum = serverMessageNum; @@ -626,11 +775,14 @@ Called before every level change or subsystem restart void CG_Shutdown(void) { L_ShutdownEvents(); + // Shutdown radar + cgi.CL_InitRadar(NULL, NULL, -1); + // some mods may need to do cleanup work here, // like closing files or archiving session data // hide the stats screen - cgi.UI_HideMenu("StatsScreen", 1); + cgi.UI_HideMenu("StatsScreen", qtrue); // reset the scoreboard CG_PrepScoreBoardInfo(); @@ -745,7 +897,7 @@ void Com_Error(int level, const char *error, ...) char text[1024]; va_start(argptr, error); - vsprintf(text, error, argptr); + Q_vsnprintf(text, sizeof(text), error, argptr); va_end(argptr); cgi.Error(level, "%s", text); @@ -757,7 +909,7 @@ void Com_Printf(const char *msg, ...) char text[1024]; va_start(argptr, msg); - vsprintf(text, msg, argptr); + Q_vsnprintf(text, sizeof(text), msg, argptr); va_end(argptr); cgi.Printf("%s", text); @@ -788,10 +940,20 @@ void CG_ParseFogInfo_ver_15(const char *str) void CG_ParseFogInfo_ver_6(const char *str) { - cg.farclipOverride = 0.0; + // + // clear all unsupported fields in protocol below version 15 + // + + // don't set the farplane_bias 0, otherwise the renderer will set a minimum value + cg.farplane_bias = 0.001f; + cg.skyboxFarplane = 0; + cg.skyboxSpeed = 0; + cg.renderTerrain = qtrue; + cg.farclipOverride = -1.0; cg.farplaneColorOverride[0] = -1.0; cg.farplaneColorOverride[1] = -1.0; cg.farplaneColorOverride[2] = -1.0; + sscanf( str, "%d %f %f %f %f", diff --git a/code/cgame/cg_marks.c b/code/cgame/cg_marks.c index fa91f7b3..27e681ac 100644 --- a/code/cgame/cg_marks.c +++ b/code/cgame/cg_marks.c @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -36,93 +36,94 @@ MARK POLYS #define MAX_MARK_FRAGMENTS 128 #define MAX_MARK_POINTS 384 -static vec3_t cg_vEntAngles; -static vec3_t cg_vEntOrigin; -static vec3_t cg_fEntAxis[3]; +static vec3_t cg_vEntAngles; +static vec3_t cg_vEntOrigin; +static vec3_t cg_fEntAxis[3]; static qboolean cg_bEntAnglesSet; -static int cg_iLastEntIndex; -static int cg_iLastEntTime; +static int cg_iLastEntIndex; +static int cg_iLastEntTime; static qboolean cg_bLastEntValid; -markPoly_t* cg_freeMarkPolys; // single linked list -markObj_t cg_activeMarkObjs; -markObj_t* cg_freeMarkObjs; +markPoly_t *cg_freeMarkPolys; // single linked list +markObj_t cg_activeMarkObjs; +markObj_t *cg_freeMarkObjs; treadMark_t cg_treadMarks[MAX_TREAD_MARKS]; -markPoly_t* cg_markPolys; -int cg_iNumMarkPolys; -markObj_t* cg_markObjs; -int cg_iNumFreeMarkObjs; -int cg_iMinFreeMarkObjs; -qboolean cg_bMarksInitialized; -cvar_t* cg_treadmark_test; +markPoly_t *cg_markPolys; +int cg_iNumMarkPolys; +markObj_t *cg_markObjs; +int cg_iNumFreeMarkObjs; +int cg_iMinFreeMarkObjs; +qboolean cg_bMarksInitialized; +cvar_t *cg_treadmark_test; -vec3_t vec_upwards; +vec3_t vec_upwards = {0, 0, 1}; typedef struct cg_impactmarkinfo_s { vec3_t axis[3]; vec3_t origin; - float fSCenter; - float fTCenter; - float texCoordScaleS; - float texCoordScaleT; - byte colors[4]; - int leafnum; + float fSCenter; + float fTCenter; + float texCoordScaleS; + float texCoordScaleT; + byte colors[4]; + int leafnum; } cg_impactmarkinfo_t; typedef struct cg_treadmarkinfo_s { - treadMark_t* pTread; - vec3_t vDirection; - vec3_t vRight; - float fStartDist; - float fStartTex; - float fStartAlpha; - float fLeftStartDist; - float fRightStartDist; - float fRightCenterDist; - float fLeftTexScale; - float fRightTexScale; - float fCenterTexScale; - float fLeftAlphaScale; - float fRightAlphaScale; - float fCenterAlphaScale; - float fOOWidth; - float fOODoubleWidth; - byte colors[4]; - int leafnum; + treadMark_t *pTread; + vec3_t vDirection; + vec3_t vRight; + float fStartDist; + float fStartTex; + float fStartAlpha; + float fLeftStartDist; + float fRightStartDist; + float fRightCenterDist; + float fLeftTexScale; + float fRightTexScale; + float fCenterTexScale; + float fLeftAlphaScale; + float fRightAlphaScale; + float fCenterAlphaScale; + float fOOWidth; + float fOODoubleWidth; + byte colors[4]; + int leafnum; } cg_treadmarkinfo_t; int CG_GetMarkFragments( - int numVerts, - const vec3_t* pVerts, - const vec3_t vProjection, - const vec3_t* pPointBuffer, - markFragment_t* pFragmentBuffer, - float fRadiusSquared -) { - int i, j; - int iNumEnts; - int iCurrPoints, iCurrFragments; - int iCurrMaxPoints, iCurrMaxFragments; - int iNewPoints, iNewFragments; - clipHandle_t cmodel; - vec3_t vProjectionDir; - vec3_t vMins, vMaxs; - vec3_t vTemp; - vec3_t vAngles, vOrigin; - const vec3_t* pCurrPoint; - centity_t* pEntList[64]; - entityState_t* pEnt; - markFragment_t* pCurrFragment; - markFragment_t* pFragment; + int numVerts, + const vec3_t *pVerts, + const vec3_t vProjection, + const vec3_t *pPointBuffer, + markFragment_t *pFragmentBuffer, + float fRadiusSquared +) +{ + int i, j; + int iNumEnts; + int iCurrPoints, iCurrFragments; + int iCurrMaxPoints, iCurrMaxFragments; + int iNewPoints, iNewFragments; + clipHandle_t cmodel; + vec3_t vProjectionDir; + vec3_t vMins, vMaxs; + vec3_t vTemp; + vec3_t vAngles, vOrigin; + const vec3_t *pCurrPoint; + centity_t *pEntList[64]; + entityState_t *pEnt; + markFragment_t *pCurrFragment; + markFragment_t *pFragment; iNewFragments = cgi.R_MarkFragments( numVerts, pVerts, vProjection, MAX_MARK_POINTS, - (float*)pPointBuffer, + (float *)pPointBuffer, MAX_MARK_FRAGMENTS, pFragmentBuffer, fRadiusSquared @@ -141,12 +142,12 @@ int CG_GetMarkFragments( return iNewFragments; } - iCurrPoints = iNewPoints; - iCurrFragments = iNewFragments; - iCurrMaxPoints = MAX_MARK_POINTS - iNewPoints; + iCurrPoints = iNewPoints; + iCurrFragments = iNewFragments; + iCurrMaxPoints = MAX_MARK_POINTS - iNewPoints; iCurrMaxFragments = MAX_MARK_FRAGMENTS - iNewFragments; - pCurrPoint = &pPointBuffer[iNewPoints]; - pCurrFragment = &pFragmentBuffer[iNewFragments]; + pCurrPoint = &pPointBuffer[iNewPoints]; + pCurrFragment = &pFragmentBuffer[iNewFragments]; VectorNormalize2(vProjection, vProjectionDir); ClearBounds(vMins, vMaxs); @@ -170,7 +171,7 @@ int CG_GetMarkFragments( VectorCopy(pEntList[i]->lerpOrigin, vOrigin); cmodel = cgi.CM_InlineModel(pEnt->modelindex); - + iNewFragments = cgi.R_MarkFragmentsForInlineModel( cmodel, vAngles, @@ -179,7 +180,7 @@ int CG_GetMarkFragments( pVerts, vProjection, iCurrMaxPoints, - (float*)pCurrPoint, + (float *)pCurrPoint, iCurrMaxFragments, pCurrFragment, fRadiusSquared @@ -191,7 +192,7 @@ int CG_GetMarkFragments( } iNewPoints = 0; - for (j = 0, pFragment = pCurrFragment; j < iNewPoints; j++, pFragment++) { + for (j = 0, pFragment = pCurrFragment; j < iNewFragments; j++, pFragment++) { pFragment->firstPoint += iCurrPoints; pFragment->iIndex = -pEnt->number; iNewPoints += pFragment->numPoints; @@ -211,18 +212,19 @@ int CG_GetMarkFragments( return iCurrFragments; } -static qboolean CG_GetMarkInlineModelOrientation(int iIndex) { - centity_t* pCEnt; +static qboolean CG_GetMarkInlineModelOrientation(int iIndex) +{ + centity_t *pCEnt; if (iIndex == cg_iLastEntIndex && cg_iLastEntTime == cg.time) { return cg_bLastEntValid; } pCEnt = &cg_entities[-iIndex]; - if (pCEnt->currentValid && pCEnt->currentState.modelindex < cgs.inlineDrawModel[ENTITYNUM_NONE]) - { + if (pCEnt->currentValid && pCEnt->currentState.modelindex < cgs.numInlineModels) { VectorCopy(pCEnt->lerpAngles, cg_vEntAngles); VectorCopy(pCEnt->lerpOrigin, cg_vEntOrigin); + cg_bLastEntValid = qtrue; if (cg_vEntAngles[0] || cg_vEntAngles[1] || cg_vEntAngles[2]) { AngleVectorsLeft(cg_vEntAngles, cg_fEntAxis[0], cg_fEntAxis[1], cg_fEntAxis[2]); @@ -233,7 +235,7 @@ static qboolean CG_GetMarkInlineModelOrientation(int iIndex) { } cg_iLastEntIndex = iIndex; - cg_iLastEntTime = cg.time; + cg_iLastEntTime = cg.time; return cg_bLastEntValid; } @@ -249,25 +251,24 @@ static qboolean CG_GetMarkInlineModelOrientation(int iIndex) { return qfalse; } -static void CG_FragmentPosToWorldPos(const vec3_t vFrom, vec3_t vTo) { - if (cg_bEntAnglesSet) - { +static void CG_FragmentPosToWorldPos(const vec3_t vFrom, vec3_t vTo) +{ + if (cg_bEntAnglesSet) { VectorMA(cg_vEntOrigin, vFrom[0], cg_fEntAxis[0], vTo); VectorMA(vTo, vFrom[1], cg_fEntAxis[1], vTo); VectorMA(vTo, vFrom[2], cg_fEntAxis[2], vTo); - } - else - { + } else { vTo[0] = cg_vEntOrigin[0] + *vFrom; vTo[1] = cg_vEntOrigin[1] + vFrom[1]; vTo[2] = cg_vEntOrigin[2] + vFrom[2]; } } -qboolean CG_UpdateMarkPosition(markObj_t* pMark) { +qboolean CG_UpdateMarkPosition(markObj_t *pMark) +{ vec3_t v; vec3_t pt; - int iIndex; + int iIndex; iIndex = pMark->markPolys->iIndex; if (!CG_GetMarkInlineModelOrientation(iIndex)) { @@ -276,8 +277,7 @@ qboolean CG_UpdateMarkPosition(markObj_t* pMark) { VectorCopy(pMark->markPolys->verts[0].xyz, v); - if (cg_bEntAnglesSet) - { + if (cg_bEntAnglesSet) { VectorScale(cg_fEntAxis[0], v[0], pt); VectorMA(pt, v[1], cg_fEntAxis[1], pt); VectorMA(pt, v[2], cg_fEntAxis[2], pt); @@ -291,12 +291,8 @@ qboolean CG_UpdateMarkPosition(markObj_t* pMark) { return qtrue; } -void CG_AddFragmentToScene( - int iIndex, - qhandle_t hShader, - int iNumVerts, - polyVert_t* pVerts -) { +void CG_AddFragmentToScene(int iIndex, qhandle_t hShader, int iNumVerts, polyVert_t *pVerts) +{ if (!iIndex) { cgi.R_AddPolyToScene(hShader, iNumVerts, pVerts, 0); return; @@ -308,9 +304,9 @@ void CG_AddFragmentToScene( } if (cg_bEntAnglesSet) { - int i; - vec3_t vTmp; - polyVert_t* pCurrVert; + int i; + vec3_t vTmp; + polyVert_t *pCurrVert; for (i = 0; i < iNumVerts; i++) { pCurrVert = &pVerts[i]; @@ -323,8 +319,8 @@ void CG_AddFragmentToScene( VectorAdd(vTmp, cg_vEntOrigin, pCurrVert->xyz); } } else { - int i; - polyVert_t* pCurrVert; + int i; + polyVert_t *pCurrVert; for (i = 0; i < iNumVerts; i++) { pCurrVert = &pVerts[i]; @@ -366,7 +362,7 @@ void CG_InitMarks(void) cgi.Free(cg_markPolys); } - cg_markPolys = (markPoly_t*)cgi.Malloc(sizeof(markPoly_t) * cg_iNumMarkPolys); + cg_markPolys = (markPoly_t *)cgi.Malloc(sizeof(markPoly_t) * cg_iNumMarkPolys); if (!cg_markPolys) { cgi.Error(ERR_DROP, "CG_InitMarks: Could not allocate array for mark polys"); @@ -376,7 +372,7 @@ void CG_InitMarks(void) cgi.Free(cg_markObjs); } - cg_markObjs = (markObj_t*)cgi.Malloc(sizeof(markObj_t) * iMaxMarks); + cg_markObjs = (markObj_t *)cgi.Malloc(sizeof(markObj_t) * iMaxMarks); if (!cg_markObjs) { cgi.Error(ERR_DROP, "CG_InitMarks: Could not allocate array for mark objects"); @@ -400,7 +396,7 @@ void CG_InitMarks(void) } cg_markObjs[i].nextMark = NULL; - cg_iNumFreeMarkObjs = iMaxMarks; + cg_iNumFreeMarkObjs = iMaxMarks; cg_bMarksInitialized = qtrue; } @@ -415,7 +411,7 @@ void CG_FreeMarkPoly(markPoly_t *le) return; } - le->nextPoly = cg_freeMarkPolys; + le->nextPoly = cg_freeMarkPolys; cg_freeMarkPolys = le; } @@ -424,11 +420,13 @@ void CG_FreeMarkPoly(markPoly_t *le) CG_FreeMarkObj ================== */ -void CG_FreeMarkObj(markObj_t* pMark) { - markPoly_t* pPoly; - markPoly_t* pNextPoly; +void CG_FreeMarkObj(markObj_t *pMark) +{ + markPoly_t *pPoly; + markPoly_t *pNextPoly; + + assert(pMark != &cg_activeMarkObjs); - pPoly = pMark->markPolys; for (pPoly = pMark->markPolys; pPoly; pPoly = pNextPoly) { pNextPoly = pPoly->nextPoly; CG_FreeMarkPoly(pPoly); @@ -436,8 +434,8 @@ void CG_FreeMarkObj(markObj_t* pMark) { pMark->prevMark->nextMark = pMark->nextMark; pMark->nextMark->prevMark = pMark->prevMark; - pMark->nextMark = cg_freeMarkObjs; - cg_freeMarkObjs = pMark; + pMark->nextMark = cg_freeMarkObjs; + cg_freeMarkObjs = pMark; cg_iNumFreeMarkObjs++; } @@ -446,13 +444,12 @@ void CG_FreeMarkObj(markObj_t* pMark) { CG_FreeBestMarkObj ================== */ -void CG_FreeBestMarkObj(qboolean bAllowFade) { - markObj_t* pMark; +void CG_FreeBestMarkObj(qboolean bAllowFade) +{ + markObj_t *pMark; - for (pMark = cg_activeMarkObjs.prevMark; pMark != &cg_activeMarkObjs; pMark = pMark->prevMark) - { - if (pMark->lastVisTime < cg.time - 250) - { + for (pMark = cg_activeMarkObjs.prevMark; pMark != &cg_activeMarkObjs; pMark = pMark->prevMark) { + if (pMark->lastVisTime < cg.time - 250) { CG_FreeMarkObj(pMark); return; } @@ -463,13 +460,14 @@ void CG_FreeBestMarkObj(qboolean bAllowFade) { return; } - for (pMark = cg_activeMarkObjs.prevMark; pMark != &cg_activeMarkObjs; pMark = pMark->prevMark) - { + for (pMark = cg_activeMarkObjs.prevMark; pMark != &cg_activeMarkObjs; pMark = pMark->prevMark) { if (!pMark->alphaFade || pMark->time > cg.time - 9000) { - pMark->time = cg.time - 9000; - pMark->alphaFade = 1; + break; } } + + pMark->time = cg.time - 9000; + pMark->alphaFade = qtrue; } /* @@ -479,11 +477,11 @@ CG_AllocMark Will allways succeed, even if it requires freeing an old active mark =================== */ -markObj_t* CG_AllocMark(int iNumPolys) +markObj_t *CG_AllocMark(int iNumPolys) { - int iPolyCount; - markPoly_t* pPoly; - markObj_t* pMark; + int iPolyCount; + markPoly_t *pPoly; + markObj_t *pMark; if (!cg_bMarksInitialized) { return NULL; @@ -493,79 +491,79 @@ markObj_t* CG_AllocMark(int iNumPolys) return NULL; } + if (iNumPolys > cg_iNumMarkPolys) { + // Added in OPM + // Make sure to not over allocate polys + return NULL; + } + if (cg_iNumFreeMarkObjs <= cg_iMinFreeMarkObjs) { CG_FreeBestMarkObj(1); } - pMark = cg_freeMarkObjs; + pMark = cg_freeMarkObjs; cg_freeMarkObjs = cg_freeMarkObjs->nextMark; memset(pMark, 0, sizeof(markObj_t)); pMark->lastVisTime = cg.time; - for (iPolyCount = 0; iPolyCount < iNumPolys; iPolyCount++) - { + for (iPolyCount = 0; iPolyCount < iNumPolys; iPolyCount++) { while (!cg_freeMarkPolys) { CG_FreeBestMarkObj(qfalse); } - pPoly = cg_freeMarkPolys; + pPoly = cg_freeMarkPolys; cg_freeMarkPolys = pPoly->nextPoly; memset(pPoly, 0, sizeof(*pPoly)); - pPoly->nextPoly = pMark->markPolys; + pPoly->nextPoly = pMark->markPolys; pMark->markPolys = pPoly; } - // link into the active list - pMark->nextMark = cg_activeMarkObjs.nextMark; - pMark->prevMark = &cg_activeMarkObjs; + pMark->nextMark = cg_activeMarkObjs.nextMark; + pMark->prevMark = &cg_activeMarkObjs; cg_activeMarkObjs.nextMark->prevMark = pMark; - cg_activeMarkObjs.nextMark = pMark; + cg_activeMarkObjs.nextMark = pMark; + cg_iNumFreeMarkObjs--; + assert(cg_iNumFreeMarkObjs >= 0); + return pMark; } -int CG_ImpactMark_GetLeafCallback(markFragment_t* mf, void* pCustom) { - return ((cg_impactmarkinfo_t*)pCustom)->leafnum; +int CG_ImpactMark_GetLeafCallback(markFragment_t *mf, void *pCustom) +{ + return ((cg_impactmarkinfo_t *)pCustom)->leafnum; } -qboolean CG_ImpactMark_PerPolyCallback( - const vec3_t* markPoints, - markFragment_t* mf, - polyVert_t* verts, - void* pCustom -) { - int j; - polyVert_t* v; - cg_impactmarkinfo_t* pInfo; +qboolean CG_ImpactMark_PerPolyCallback(const vec3_t *markPoints, markFragment_t *mf, polyVert_t *verts, void *pCustom) +{ + int j; + polyVert_t *v; + cg_impactmarkinfo_t *pInfo; - pInfo = (cg_impactmarkinfo_t*)pCustom; + pInfo = (cg_impactmarkinfo_t *)pCustom; - if (mf->iIndex >= 0) - { + if (mf->iIndex >= 0) { for (j = 0; j < mf->numPoints; j++) { vec3_t delta; v = &verts[j]; VectorCopy(markPoints[j + mf->firstPoint], v->xyz); VectorSubtract(v->xyz, pInfo->origin, delta); - v->st[0] = pInfo->fSCenter + DotProduct(delta, pInfo->axis[1]) * pInfo->texCoordScaleS; - v->st[1] = pInfo->fTCenter + DotProduct(delta, pInfo->axis[2]) * pInfo->texCoordScaleT; + v->st[0] = pInfo->fSCenter + DotProduct(delta, pInfo->axis[1]) * pInfo->texCoordScaleS; + v->st[1] = pInfo->fTCenter + DotProduct(delta, pInfo->axis[2]) * pInfo->texCoordScaleT; v->modulate[0] = pInfo->colors[0]; v->modulate[1] = pInfo->colors[1]; v->modulate[2] = pInfo->colors[2]; v->modulate[3] = pInfo->colors[3]; } - } - else - { + } else { if (!CG_GetMarkInlineModelOrientation(mf->iIndex)) { return qfalse; } - for (j = 0; j < mf->numPoints; j++) { vec3_t vWorldPos; vec3_t delta; @@ -575,8 +573,8 @@ qboolean CG_ImpactMark_PerPolyCallback( CG_FragmentPosToWorldPos(v->xyz, vWorldPos); VectorSubtract(vWorldPos, pInfo->origin, delta); - v->st[0] = pInfo->fSCenter + DotProduct(delta, pInfo->axis[1]) * pInfo->texCoordScaleS; - v->st[1] = pInfo->fTCenter + DotProduct(delta, pInfo->axis[2]) * pInfo->texCoordScaleT; + v->st[0] = pInfo->fSCenter + DotProduct(delta, pInfo->axis[1]) * pInfo->texCoordScaleS; + v->st[1] = pInfo->fTCenter + DotProduct(delta, pInfo->axis[2]) * pInfo->texCoordScaleT; v->modulate[0] = pInfo->colors[0]; v->modulate[1] = pInfo->colors[1]; v->modulate[2] = pInfo->colors[2]; @@ -618,24 +616,23 @@ void CG_ImpactMark( float fTCenter ) { - int i; - int numFragments; - float fSScale2, fTScale2; - float fSScale3, fTScale3; - vec3_t originalPoints[4]; - vec3_t markPoints[MAX_MARK_POINTS]; - vec3_t projection; - markFragment_t markFragments[MAX_MARK_FRAGMENTS], *mf; - vec3_t v; - float fRadiusSquared; + int i; + int numFragments; + float fSScale2, fTScale2; + float fSScale3, fTScale3; + vec3_t originalPoints[4]; + vec3_t markPoints[MAX_MARK_POINTS]; + vec3_t projection; + markFragment_t markFragments[MAX_MARK_FRAGMENTS], *mf; + vec3_t v; + float fRadiusSquared; cg_impactmarkinfo_t info; if (!cg_bMarksInitialized) { return; } - if (!cg_addMarks->integer - && markShader != cgs.media.shadowMarkShader + if (!cg_addMarks->integer && markShader != cgs.media.shadowMarkShader && markShader != cgs.media.footShadowMarkShader) { return; } @@ -647,7 +644,7 @@ void CG_ImpactMark( fTScale = 1.0; } - fRadiusSquared = fSScale * fSScale + fTScale * fTScale; + fRadiusSquared = fSScale * fSScale + fTScale * fTScale; info.texCoordScaleS = 0.5 / fSScale; info.texCoordScaleT = 0.5 / fTScale; @@ -685,34 +682,24 @@ void CG_ImpactMark( // create the full polygon for (i = 0; i < 3; i++) { originalPoints[0][i] = origin[i] - fSScale2 * info.axis[1][i] - fTScale2 * info.axis[2][i]; - originalPoints[1][i] = origin[i] + fSScale3 * info.axis[1][i] - fTScale3 * info.axis[2][i]; + originalPoints[1][i] = origin[i] + fSScale3 * info.axis[1][i] - fTScale2 * info.axis[2][i]; originalPoints[2][i] = origin[i] + fSScale3 * info.axis[1][i] + fTScale3 * info.axis[2][i]; - originalPoints[3][i] = origin[i] - fSScale2 * info.axis[1][i] + fTScale2 * info.axis[2][i]; + originalPoints[3][i] = origin[i] - fSScale2 * info.axis[1][i] + fTScale3 * info.axis[2][i]; } // get the fragments VectorScale(dir, -32, projection); - numFragments = CG_GetMarkFragments( - 4, - originalPoints, - projection, - markPoints, - markFragments, - fRadiusSquared - ); + numFragments = CG_GetMarkFragments(4, originalPoints, projection, markPoints, markFragments, fRadiusSquared); - if (dolighting) - { + if (dolighting) { vec3_t vLight; cgi.R_GetLightingForDecal(vLight, dir, origin); info.colors[0] = (int)(red * vLight[0]); info.colors[1] = (int)(green * vLight[1]); info.colors[2] = (int)(blue * vLight[2]); - } - else - { + } else { info.colors[0] = (int)(red * 255.0f); info.colors[1] = (int)(green * 255.0f); info.colors[2] = (int)(blue * 255.0f); @@ -730,8 +717,7 @@ void CG_ImpactMark( VectorAdd(origin, dir, v); info.leafnum = cgi.CM_PointLeafnum(v); - if (temporary) - { + if (temporary) { polyVert_t verts[8]; for (i = 0, mf = markFragments; i < numFragments; i++, mf++) { @@ -739,20 +725,18 @@ void CG_ImpactMark( mf->numPoints = 8; } - if (CG_ImpactMark_PerPolyCallback(markPoints, mf, verts, (void*)&info)) { + if (CG_ImpactMark_PerPolyCallback(markPoints, mf, verts, (void *)&info)) { CG_AddFragmentToScene(mf->iIndex, markShader, mf->numPoints, verts); } } - } - else - { + } else { CG_AssembleFinalMarks( markPoints, markFragments, numFragments, &CG_ImpactMark_PerPolyCallback, &CG_ImpactMark_GetLeafCallback, - (void*)&info, + (void *)&info, info.origin, sqrt(fRadiusSquared), markShader, @@ -763,32 +747,31 @@ void CG_ImpactMark( } void CG_AssembleFinalMarks( - vec3_t *markPoints, - markFragment_t *markFragments, - int numFragments, - qboolean (*PerPolyCallback)(const vec3_t* markPoints, markFragment_t* mf, polyVert_t* verts, void* pCustom), - int (*GetLeafCallback)(markFragment_t* mf, void* pCustom), - void *pCustom, - vec3_t pos, - float radius, - qhandle_t markShader, - qboolean fadein, - qboolean alphaFade + vec3_t *markPoints, + markFragment_t *markFragments, + int numFragments, + qboolean (*PerPolyCallback)(const vec3_t *markPoints, markFragment_t *mf, polyVert_t *verts, void *pCustom), + int (*GetLeafCallback)(markFragment_t *mf, void *pCustom), + void *pCustom, + vec3_t pos, + float radius, + qhandle_t markShader, + qboolean fadein, + qboolean alphaFade ) { - markObj_t* pMark; - markPoly_t* pPoly; - int iGroup, iFirstNewGroup; - int numFragsForMark; - int i; - markFragment_t* mf; + markObj_t *pMark; + markPoly_t *pPoly; + int iGroup, iFirstNewGroup; + int numFragsForMark; + int i; + markFragment_t *mf; iFirstNewGroup = 0; - do - { - i = iFirstNewGroup; - mf = &markFragments[iFirstNewGroup]; - iGroup = mf->iIndex; + do { + i = iFirstNewGroup; + mf = &markFragments[iFirstNewGroup]; + iGroup = mf->iIndex; numFragsForMark = 0; for (; i < numFragments; i++, mf++) { @@ -804,19 +787,35 @@ void CG_AssembleFinalMarks( break; } - pMark->time = cg.time; - pMark->alphaFade = alphaFade; + pMark->time = cg.time; + pMark->alphaFade = alphaFade; pMark->markShader = markShader; - pMark->fadein = fadein; + pMark->fadein = fadein; VectorCopy(pos, pMark->pos); pMark->radius = radius; - i = iFirstNewGroup; - mf = &markFragments[iFirstNewGroup]; + i = iFirstNewGroup; + mf = &markFragments[iFirstNewGroup]; iFirstNewGroup = 0; if (mf->iIndex < 0) { - VectorSubtract(pMark->pos, cg_entities[-mf->iIndex].lerpOrigin, pMark->pos); + centity_t *cent; + vec3_t pos; + + cent = &cg_entities[-mf->iIndex]; + + VectorSubtract(pMark->pos, cent->lerpOrigin, pos); + + if (cent->lerpAngles[0] || cent->lerpAngles[1] || cent->lerpAngles[2]) { + vec3_t axis[3]; + + // Fixed in OPM + // Make the position completely local to the entity + AngleVectorsLeft(cent->lerpAngles, axis[0], axis[1], axis[2]); + MatrixTransformVectorRight(axis, pos, pMark->pos); + } else { + VectorCopy(pos, pMark->pos); + } } pPoly = pMark->markPolys; @@ -836,8 +835,8 @@ void CG_AssembleFinalMarks( if (PerPolyCallback(markPoints, mf, pPoly->verts, pCustom)) { pPoly->numVerts = mf->numPoints; - pPoly->iIndex = mf->iIndex; - pPoly = pPoly->nextPoly; + pPoly->iIndex = mf->iIndex; + pPoly = pPoly->nextPoly; } } } @@ -894,15 +893,15 @@ CG_AddMarks void CG_AddMarks(void) { - int j; - int t; - int fade; - markObj_t* pMark; - markObj_t* pNext; - markPoly_t* pPoly; - polyVert_t* pVert; - polyVert_t tmpVerts[8]; - int viewleafnum; + int j; + int t; + int fade; + markObj_t *pMark; + markObj_t *pNext; + markPoly_t *pPoly; + polyVert_t *pVert; + polyVert_t tmpVerts[8]; + int viewleafnum; if (!cg_bMarksInitialized) { return; @@ -919,8 +918,7 @@ void CG_AddMarks(void) pNext = pMark->nextMark; // see if it is time to completely remove it - if (pMark->alphaFade && cg.time > pMark->time + MARK_TOTAL_TIME) - { + if (pMark->alphaFade && cg.time > pMark->time + MARK_TOTAL_TIME) { CG_FreeMarkObj(pMark); continue; } @@ -937,26 +935,25 @@ void CG_AddMarks(void) } if (pMark->markPolys->iIndex < 0) { - if (CG_FrustumCullSphere(pMark->pos, pMark->radius)) { - continue; - } - } else { vec3_t vWorldPos; CG_FragmentPosToWorldPos(pMark->pos, vWorldPos); if (CG_FrustumCullSphere(vWorldPos, pMark->radius)) { continue; } + } else { + if (CG_FrustumCullSphere(pMark->pos, pMark->radius)) { + continue; + } } pMark->lastVisTime = cg.time; if (pMark->fadein) { fade = 255 * (cg.time - pMark->time) / MARK_FADE_TIME; if (fade > 255) { - fade = 255; + fade = 255; pMark->fadein = 0; } - for (pPoly = pMark->markPolys; pPoly; pPoly = pPoly->nextPoly) { for (j = 0; j < pPoly->numVerts; j++) { pPoly->verts[j].modulate[3] = fade; @@ -976,10 +973,8 @@ void CG_AddMarks(void) } } - for (pPoly = pMark->markPolys; pPoly; pPoly = pPoly->nextPoly) - { - if (pPoly->iIndex < 0) - { + for (pPoly = pMark->markPolys; pPoly; pPoly = pPoly->nextPoly) { + if (pPoly->iIndex < 0) { memcpy(tmpVerts, pPoly->verts, 24 * pPoly->numVerts); pVert = tmpVerts; } else { @@ -1007,7 +1002,8 @@ qboolean CG_CheckMakeMarkOnEntity(int iEntIndex) return qfalse; } - if (cg_entities[iEntIndex].currentState.modelindex < 0 || cg_entities[iEntIndex].currentState.modelindex > cgi.CM_NumInlineModels()) { + if (cg_entities[iEntIndex].currentState.modelindex < 0 + || cg_entities[iEntIndex].currentState.modelindex > cgi.CM_NumInlineModels()) { return qfalse; } @@ -1021,9 +1017,9 @@ void CG_InitTestTreadMark() int CG_StartTreadMark(int iReference, qhandle_t treadShader, const vec3_t vStartPos, float fWidth, float fAlpha) { - int i; - int iTreadNum; - treadMark_t* pTread; + int i; + int iTreadNum; + treadMark_t *pTread; if (!cg_bMarksInitialized) { return -1; @@ -1037,7 +1033,7 @@ int CG_StartTreadMark(int iReference, qhandle_t treadShader, const vec3_t vStart for (i = 0; i < MAX_TREAD_MARKS; i++) { if (!cg_treadMarks[i].iState) { iTreadNum = i; - pTread = &cg_treadMarks[i]; + pTread = &cg_treadMarks[i]; break; } } @@ -1047,11 +1043,11 @@ int CG_StartTreadMark(int iReference, qhandle_t treadShader, const vec3_t vStart } memset(pTread, 0, sizeof(*pTread)); - pTread->iState = 1; + pTread->iState = 1; pTread->iReferenceNumber = iReference; - pTread->iLastTime = cg.time; - pTread->hTreadShader = treadShader; - pTread->fWidth = fWidth * 0.5; + pTread->iLastTime = cg.time; + pTread->hTreadShader = treadShader; + pTread->fWidth = fWidth * 0.5; VectorCopy(vStartPos, pTread->vMidPos); VectorCopy(vStartPos, pTread->vEndPos); @@ -1065,33 +1061,390 @@ int CG_StartTreadMark(int iReference, qhandle_t treadShader, const vec3_t vStart return iTreadNum; } -qboolean CG_MakeTreadMarkDecal_PerPolyCallback(const vec3_t *markPoints, markFragment_t *mf, polyVert_t *verts, void *pCustom) +qboolean +CG_MakeTreadMarkDecal_PerPolyCallback(const vec3_t *markPoints, markFragment_t *mf, polyVert_t *verts, void *pCustom) { - // FIXME: unimplemented - return qfalse; + int j; + float fDist; + float fSideDist; + float fSideAlpha; + float fCenterAlpha; + float fFrac; + float fTex, fAlpha; + polyVert_t *v; + cg_treadmarkinfo_t *pInfo; + + pInfo = (cg_treadmarkinfo_t *)pCustom; + + if (mf->iIndex < 0) { + vec3_t vWorldPos; + + if (!CG_GetMarkInlineModelOrientation(mf->iIndex)) { + return qfalse; + } + + for (j = 0; j < mf->numPoints; j++) { + v = &verts[j]; + VectorCopy(markPoints[mf->firstPoint + j], v->xyz); + v->modulate[0] = pInfo->colors[0]; + v->modulate[1] = pInfo->colors[1]; + v->modulate[2] = pInfo->colors[2]; + v->modulate[3] = pInfo->colors[3]; + + CG_FragmentPosToWorldPos(v->xyz, vWorldPos); + fSideDist = DotProduct(pInfo->vRight, vWorldPos) - pInfo->fRightCenterDist; + v->st[0] = (fSideDist + pInfo->pTread->fWidth) * pInfo->fOODoubleWidth; + + fSideAlpha = fSideDist * pInfo->fOOWidth; + fDist = DotProduct(vWorldPos, pInfo->vDirection); + if (fSideAlpha < 0) { + fSideAlpha = -fSideAlpha; + v->st[1] = pInfo->fStartTex + ((fDist - pInfo->fLeftStartDist) * pInfo->fLeftTexScale * fSideAlpha) + + ((fDist - pInfo->fStartDist) * pInfo->fCenterTexScale * (1.0 - fSideAlpha)); + v->modulate[3] = pInfo->fStartAlpha + + (1.0 - fSideAlpha) + * ((fDist - pInfo->fStartDist) * pInfo->fCenterTexScale * pInfo->fCenterAlphaScale) + + (fDist - pInfo->fLeftStartDist) * pInfo->fLeftAlphaScale * fSideAlpha; + } else { + v->st[1] = pInfo->fStartTex + ((fDist - pInfo->fRightStartDist) * pInfo->fRightTexScale * fSideAlpha) + + ((fDist - pInfo->fStartDist) * pInfo->fCenterTexScale * (1.0 - fSideAlpha)); + v->modulate[3] = pInfo->fStartAlpha + + (1.0 - fSideAlpha) + * ((fDist - pInfo->fStartDist) * pInfo->fCenterTexScale * pInfo->fCenterAlphaScale) + + (fDist - pInfo->fRightStartDist) * pInfo->fRightAlphaScale * fSideAlpha; + } + } + } else { + for (j = 0; j < mf->numPoints; j++) { + v = &verts[j]; + VectorCopy(markPoints[mf->firstPoint + j], v->xyz); + v->modulate[0] = pInfo->colors[0]; + v->modulate[1] = pInfo->colors[1]; + v->modulate[2] = pInfo->colors[2]; + v->modulate[3] = pInfo->colors[3]; + + fSideDist = DotProduct(pInfo->vRight, v->xyz) - pInfo->fRightCenterDist; + v->st[0] = (fSideDist + pInfo->pTread->fWidth) * pInfo->fOODoubleWidth; + + fSideAlpha = fSideDist * pInfo->fOOWidth; + fDist = DotProduct(v->xyz, pInfo->vDirection); + if (fSideAlpha < 0) { + fSideAlpha = -fSideAlpha; + fTex = (fDist - pInfo->fLeftStartDist) * pInfo->fLeftTexScale; + fAlpha = (fDist - pInfo->fLeftStartDist) * pInfo->fLeftAlphaScale; + } else { + fTex = (fDist - pInfo->fRightStartDist) * pInfo->fRightTexScale; + fAlpha = (fDist - pInfo->fRightStartDist) * pInfo->fRightAlphaScale; + } + + v->st[1] = pInfo->fStartTex + (fTex * fSideAlpha) + + (fDist - pInfo->fStartDist) * pInfo->fCenterTexScale * (1.0 - fSideAlpha); + v->modulate[3] = pInfo->fStartAlpha + + ((1.0 - fSideAlpha) * ((fDist - pInfo->fStartDist) * pInfo->fCenterAlphaScale)) + + (fAlpha * fSideAlpha); + } + } + + return qtrue; } int CG_MakeTreadMarkDecal_GetLeafCallback(markFragment_t *mf, void *pCustom) { - return ((cg_treadmarkinfo_t*)pCustom)->leafnum; + return ((cg_treadmarkinfo_t *)pCustom)->leafnum; } void CG_MakeTreadMarkDecal(treadMark_t *pTread, qboolean bStartSegment, qboolean bTemporary) { - // FIXME: unimplemented + int i; + int numFragments; + vec3_t originalPoints[4]; + vec3_t markPoints[MAX_MARK_POLYVERTS]; + vec3_t projection; + markFragment_t markFragments[MAX_MARK_FRAGMENTS]; + markFragment_t *mf; + cg_treadmarkinfo_t info; + float fEndAlpha, fEndTex; + float fDist; + vec3_t vStartCenter; + vec3_t vEndCenter; + vec3_t vDelta; + vec3_t origin; + float fRadiusSquared; + + if (bStartSegment) { + VectorCopy(pTread->vStartVerts[1], originalPoints[0]); + VectorCopy(pTread->vStartVerts[0], originalPoints[1]); + VectorCopy(pTread->vMidVerts[0], originalPoints[2]); + VectorCopy(pTread->vMidVerts[1], originalPoints[3]); + + info.fStartAlpha = pTread->fStartAlpha; + fEndAlpha = pTread->fMidAlpha; + info.fStartTex = pTread->fStartTexCoord; + fEndTex = pTread->fMidTexCoord; + + // Calculate the start center + VectorAdd(originalPoints[1], originalPoints[0], vStartCenter); + VectorScale(vStartCenter, 0.5, vStartCenter); + VectorCopy(pTread->vMidPos, vEndCenter); + VectorCopy(pTread->vStartDir, info.vDirection); + } else { + VectorCopy(pTread->vMidVerts[1], originalPoints[0]); + VectorCopy(pTread->vMidVerts[0], originalPoints[1]); + VectorCopy(pTread->vEndVerts[0], originalPoints[2]); + VectorCopy(pTread->vEndVerts[1], originalPoints[3]); + + info.fStartAlpha = pTread->fMidAlpha; + fEndAlpha = pTread->fEndAlpha; + info.fStartTex = pTread->fMidTexCoord; + fEndTex = pTread->fEndTexCoord; + + VectorCopy(pTread->vMidPos, vStartCenter); + VectorCopy(pTread->vEndPos, vEndCenter); + + // Calculate the direction + VectorSubtract(vEndCenter, vStartCenter, info.vDirection); + VectorNormalizeFast(info.vDirection); + } + + CrossProduct(vec_upwards, info.vDirection, info.vRight); + info.fRightCenterDist = DotProduct(vEndCenter, info.vRight); + info.fOODoubleWidth = 0.5 / pTread->fWidth; + info.fOOWidth = info.fOODoubleWidth * 2; + info.fStartDist = DotProduct(info.vDirection, vStartCenter); + info.fRightStartDist = DotProduct(info.vDirection, originalPoints[1]); + info.fLeftStartDist = DotProduct(info.vDirection, originalPoints[0]); + + // + // Center + // + + VectorSubtract(vEndCenter, vStartCenter, vDelta); + fDist = VectorLength(vDelta); + + fRadiusSquared = (Square(fDist) + Square(pTread->fWidth)) * 0.25; + + info.fCenterTexScale = (fEndTex - info.fStartTex) / fDist; + info.fCenterAlphaScale = (fEndAlpha - info.fStartAlpha) / fDist; + + // + // Right + // + + VectorSubtract(originalPoints[2], originalPoints[1], vDelta); + fDist = VectorLength(vDelta); + + info.fRightTexScale = (fEndTex - info.fStartTex) / fDist; + info.fRightAlphaScale = (fEndAlpha - info.fStartAlpha) / fDist; + + // + // Left + // + + VectorSubtract(originalPoints[3], originalPoints[1], vDelta); + fDist = VectorLength(vDelta); + + info.fLeftTexScale = (fEndTex - info.fStartTex) / fDist; + info.fLeftAlphaScale = (fEndAlpha - info.fStartAlpha) / fDist; + + VectorSet(projection, 0, 0, -32); + info.colors[0] = info.colors[1] = info.colors[2] = info.colors[3] = -1; + + numFragments = CG_GetMarkFragments(4, originalPoints, projection, markPoints, markFragments, fRadiusSquared); + VectorAdd(vStartCenter, vEndCenter, origin); + VectorScale(origin, 0.5, origin); + info.leafnum = cgi.CM_PointLeafnum(origin); + info.pTread = pTread; + + if (bTemporary) { + for (i = 0; i < numFragments; i++) { + polyVert_t verts[8]; + + mf = &markFragments[i]; + if (mf->numPoints > 8) { + mf->numPoints = 8; + } + if (CG_MakeTreadMarkDecal_PerPolyCallback(markPoints, mf, verts, &info)) { + CG_AddFragmentToScene(mf->iIndex, pTread->hTreadShader, mf->numPoints, verts); + } + } + } else { + CG_AssembleFinalMarks( + markPoints, + markFragments, + numFragments, + &CG_MakeTreadMarkDecal_PerPolyCallback, + &CG_MakeTreadMarkDecal_GetLeafCallback, + &info, + origin, + sqrt(fRadiusSquared), + pTread->hTreadShader, + qfalse, + qfalse + ); + } } -int CG_UpdateTreadMark(int iReference, vec_t *vNewPos, float fAlpha) +int CG_UpdateTreadMark(int iReference, const vec3_t vNewPos, float fAlpha) { - // FIXME: unimplemented + int i; + int iTreadNum; + float fDist; + float fSplitLength; + float fNewLength; + float fTmp; + qboolean bDoSegmentation; + vec3_t vDelta, vDeltaNorm; + vec3_t vDir, vMidDir; + vec3_t vRight; + treadMark_t *pTread; + + iTreadNum = -1; + + for (i = 0; i < MAX_TREAD_MARKS; i++) { + if (cg_treadMarks[i].iReferenceNumber == iReference) { + iTreadNum = i; + pTread = &cg_treadMarks[i]; + } + } + + if (iTreadNum == -1 || !pTread->iState) { + return -1; + } + + pTread->iLastTime = cg.time; + + if (VectorCompare(pTread->vEndPos, vNewPos)) { + if (fAlpha >= 0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + return 0; + } + + VectorSubtract(vNewPos, pTread->vMidPos, vDelta); + fDist = VectorNormalize2(vDelta, vDeltaNorm); + if (pTread->iState == 1) { + fSplitLength = 0; + bDoSegmentation = qfalse; + } else { + VectorAdd(vDeltaNorm, pTread->vStartDir, vMidDir); + VectorScale(vMidDir, 0.5, vMidDir); + VectorNormalizeFast(vMidDir); + + fTmp = DotProduct(vMidDir, vDeltaNorm); + fSplitLength = pTread->fWidth / fTmp; + + if (fTmp < -0.5) { + fTmp = fTmp + * (fTmp + * (fTmp + * (fTmp * (fTmp * (fTmp * -337.31875783205 + -1237.54375255107) + -1802.11467325687) + + -1303.19904613494) + + -471.347871690988) + + -70.0883838161826); + } else if (fTmp > 0.5) { + fTmp = fTmp + * (fTmp + * (fTmp + * (fTmp * (fTmp * (fTmp * -1507.55394345521 + 6580.58002318442) + -11860.0735285953) + + 11290.7510782536) + + -5986.89654545347) + + 1675.66417006387) + + -192.426950291139; + } else { + fTmp = fTmp * (fTmp * -0.531387674508458 + -2.11e-14) + 1.00086138065435; + } + + fNewLength = fSplitLength * fTmp; + if (fNewLength + 24 > fDist) { + bDoSegmentation = qfalse; + } else if (fSplitLength < -1) { + fSplitLength = -fSplitLength; + bDoSegmentation = qtrue; + } else if (fDist > 256) { + bDoSegmentation = qtrue; + } else { + CrossProduct(vec_upwards, pTread->vStartDir, vRight); + VectorNormalizeFast(vRight); + bDoSegmentation = fabs(DotProduct(vRight, vDelta)) > 16; + } + } + + if (pTread->iState == 2 && bDoSegmentation) { + VectorCopy(pTread->vMidVerts[0], pTread->vStartVerts[0]); + VectorCopy(pTread->vMidVerts[1], pTread->vStartVerts[1]); + pTread->fMidTexCoord = pTread->fEndTexCoord; + pTread->fMidAlpha = pTread->fEndAlpha; + VectorCopy(vNewPos, pTread->vEndPos); + + if (fAlpha >= 0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + + pTread->iState = 3; + } else if (pTread->iState == 0 || pTread->iState == 1) { + VectorCopy(vNewPos, pTread->vEndPos); + + if (fAlpha >= 0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + + CrossProduct(vec_upwards, vDeltaNorm, vDir); + VectorMA(pTread->vMidPos, pTread->fWidth, vDir, pTread->vMidVerts[0]); + VectorMA(pTread->vMidPos, 0.0 - pTread->fWidth, vDir, pTread->vMidVerts[1]); + VectorMA(pTread->vEndPos, pTread->fWidth, vDir, pTread->vEndVerts[0]); + VectorMA(pTread->vEndPos, 0.0 - pTread->fWidth, vDir, pTread->vEndVerts[1]); + + pTread->fEndTexCoord = fDist / 32.0; + + if (pTread->iState == 1 && fDist > 8) { + VectorCopy(vDelta, pTread->vStartDir); + pTread->iState = 2; + } + return 0; + } else { + if (bDoSegmentation) { + CG_MakeTreadMarkDecal(pTread, qtrue, qfalse); + + VectorCopy(pTread->vMidVerts[0], pTread->vStartVerts[0]); + VectorCopy(pTread->vMidVerts[1], pTread->vStartVerts[1]); + VectorSubtract(pTread->vEndPos, pTread->vMidPos, pTread->vStartDir); + VectorNormalizeFast(pTread->vStartDir); + VectorCopy(pTread->vEndPos, pTread->vMidPos); + pTread->fMidTexCoord = pTread->fEndTexCoord; + pTread->fMidAlpha = pTread->fEndAlpha; + + if (pTread->fStartTexCoord >= 1.0) { + pTread->fMidTexCoord -= (int)pTread->fStartTexCoord; + pTread->fStartTexCoord -= (int)pTread->fStartTexCoord; + } + } + + VectorCopy(vNewPos, pTread->vEndPos); + pTread->fEndTexCoord = pTread->fMidTexCoord + fDist / 32.0; + + if (fAlpha >= 0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + } + + CrossProduct(vec_upwards, vMidDir, vRight); + VectorNormalizeFast(vRight); + VectorMA(pTread->vMidPos, fSplitLength, vRight, pTread->vMidVerts[0]); + VectorMA(pTread->vMidPos, 0.0 - fSplitLength, vRight, pTread->vMidVerts[1]); + CrossProduct(vec_upwards, vDeltaNorm, vRight); + VectorNormalizeFast(vRight); + VectorMA(pTread->vEndPos, pTread->fWidth, vRight, pTread->vEndVerts[0]); + VectorMA(pTread->vEndPos, 0.0 - pTread->fWidth, vRight, pTread->vEndVerts[1]); + return 0; } void CG_AddTreadMarks() { - trace_t trace; - vec3_t vPos, vEnd; - int i; + treadMark_t *pTread; + trace_t trace; + vec3_t vPos, vEnd; + int i; if (cg_treadmark_test->integer) { VectorCopy(cg.predicted_player_state.origin, vPos); @@ -1112,39 +1465,38 @@ void CG_AddTreadMarks() "CG_AddTreadMarks test" ); - if (trace.fraction < 1.0 && CG_UpdateTreadMark(1, trace.endpos, 0.f) == -1) { + if (trace.fraction < 1.0 && CG_UpdateTreadMark(1, trace.endpos, 1.0) == -1) { qhandle_t shader = cgi.R_RegisterShader("testtread"); - CG_StartTreadMark(1, shader, trace.endpos, cg_treadmark_test->integer, 1.0f); + CG_StartTreadMark(1, shader, trace.endpos, cg_treadmark_test->integer, 1.0); } } for (i = 0; i < MAX_TREAD_MARKS; i++) { - if (!cg_treadMarks[i].iState) { + pTread = &cg_treadMarks[i]; + + if (!pTread->iState) { continue; } - if (cg.time - cg_treadMarks[i].iLastTime > 500) { - CG_MakeTreadMarkDecal( - &cg_treadMarks[i], - cg_treadMarks[i].iState == 3 ? qtrue : qfalse, - qfalse - ); - cg_treadMarks[i].iState = 0; - } - else { - CG_MakeTreadMarkDecal( - &cg_treadMarks[i], - cg_treadMarks[i].iState == 3 ? qtrue : qfalse, - qtrue - ); + if (cg.time - pTread->iLastTime > 500) { + if (pTread->iState == 3) { + CG_MakeTreadMarkDecal(pTread, qtrue, qfalse); + } + CG_MakeTreadMarkDecal(pTread, qfalse, qfalse); + pTread->iState = 0; + } else { + if (pTread->iState == 3) { + CG_MakeTreadMarkDecal(pTread, qtrue, qtrue); + } + CG_MakeTreadMarkDecal(pTread, qfalse, qtrue); } } } int CG_PermanentMark( - const vec3_t origin, - const vec3_t dir, + vec3_t origin, + vec3_t dir, float orientation, float fSScale, float fTScale, @@ -1159,8 +1511,148 @@ int CG_PermanentMark( void *pVoidPolyVerts ) { - // FIXME: unimplemented - return 0; + byte colors[4]; + int i, j; + int numFragments; + float fSScale2, fTScale2; + float fSScale3, fTScale3; + float texCoordScaleS, texCoordScaleT; + vec3_t originalPoints[4]; + vec3_t markPoints[MAX_MARK_POLYVERTS]; + vec3_t projection; + vec3_t vLight; + vec3_t vTmp; + vec3_t axis[3]; + markFragment_t *mf; + polyVert_t *pPolyVerts; + polyVert_t *v; + clipHandle_t cmodel; + trace_t trace; + float fRadiusSquared; + + pPolyVerts = (polyVert_t *)pVoidPolyVerts; + + VectorMA(origin, -2048, dir, vTmp); + VectorAdd(origin, dir, origin); + CG_Trace( + &trace, origin, vec3_origin, vec3_origin, vTmp, ENTITYNUM_NONE, MASK_MARK, qfalse, qtrue, "CG_PermanentMark" + ); + + if (trace.fraction == 1) { + return 0; + } + + VectorCopy(trace.endpos, origin); + VectorCopy(trace.plane.normal, dir); + + if (!fSScale) { + fSScale = 1.0; + } + if (!fTScale) { + fTScale = 1.0; + } + texCoordScaleT = 0.5 / fTScale; + texCoordScaleS = 0.5 / fSScale; + if (fSCenter < 0.0 || fSCenter > 1.0) { + fSCenter = 0.5; + } + if (fTCenter < 0.0 || fTCenter > 1.0) { + fTCenter = 0.5; + } + fRadiusSquared = fSScale * fSScale; + fRadiusSquared = fTScale * fTScale + fRadiusSquared; + fSScale2 = (fSScale * (1.0 - fSCenter)) * 2; + fTScale2 = (fTScale * (1.0 - fTCenter)) * 2; + fSScale3 = fSCenter * 2 * fSScale; + fTScale3 = fTCenter * 2 * fTScale; + + VectorNormalize2(dir, axis[0]); + PerpendicularVector(axis[1], axis[0]); + RotatePointAroundVector(axis[2], axis[0], axis[1], orientation); + CrossProduct(axis[0], axis[2], axis[1]); + + // create the full polygon + for (i = 0; i < 3; i++) { + originalPoints[0][i] = origin[i] - fSScale3 * axis[1][i] - fTScale3 * axis[2][i]; + originalPoints[1][i] = origin[i] + fSScale2 * axis[1][i] - fTScale3 * axis[2][i]; + originalPoints[2][i] = origin[i] + fSScale2 * axis[1][i] + fTScale2 * axis[2][i]; + originalPoints[3][i] = origin[i] - fSScale3 * axis[1][i] + fTScale2 * axis[2][i]; + } + + VectorScale(dir, -32, projection); + numFragments = CG_GetMarkFragments( + ARRAY_LEN(originalPoints), originalPoints, projection, markPoints, pMarkFragments, fRadiusSquared + ); + + if (!dolighting) { + colors[0] = (int)(red * 255.0f); + colors[1] = (int)(green * 255.0f); + colors[2] = (int)(blue * 255.0f); + } + + colors[3] = (int)(alpha * 255.0f); + + for (i = 0, mf = pMarkFragments; i < numFragments; i++, mf++) { + vec3_t vWorldPos; + vec3_t delta; + + if (mf->numPoints > 8) { + mf->numPoints = 8; + } + + if (mf->iIndex >= 0) { + for (j = 0; j < mf->numPoints; j++) { + v = &pPolyVerts[mf->firstPoint + j]; + VectorCopy(markPoints[mf->firstPoint + j], v->xyz); + + if (dolighting) { + cgi.R_GetLightingForDecal(vLight, dir, v->xyz); + + colors[0] = (int)(red * vLight[0]); + colors[1] = (int)(green * vLight[1]); + colors[2] = (int)(blue * vLight[2]); + } + + v->modulate[0] = colors[0]; + v->modulate[1] = colors[1]; + v->modulate[2] = colors[2]; + v->modulate[3] = colors[3]; + + VectorSubtract(v->xyz, origin, delta); + v->st[0] = fSCenter + DotProduct(delta, axis[1]) * texCoordScaleS; + v->st[1] = fTCenter + DotProduct(delta, axis[2]) * texCoordScaleT; + } + } else if (CG_GetMarkInlineModelOrientation(mf->iIndex)) { + for (j = 0; j < mf->numPoints; j++) { + v = &pPolyVerts[mf->firstPoint + j]; + VectorCopy(markPoints[mf->firstPoint + j], v->xyz); + + if (dolighting) { + CG_FragmentPosToWorldPos(v->xyz, vWorldPos); + cgi.R_GetLightingForDecal(vLight, dir, v->xyz); + + colors[0] = (int)(red * vLight[0]); + colors[1] = (int)(green * vLight[1]); + colors[2] = (int)(blue * vLight[2]); + } + + v->modulate[0] = colors[0]; + v->modulate[1] = colors[1]; + v->modulate[2] = colors[2]; + v->modulate[3] = colors[3]; + + VectorSubtract(v->xyz, origin, delta); + v->st[0] = fSCenter + DotProduct(delta, axis[1]) * texCoordScaleS; + v->st[1] = fTCenter + DotProduct(delta, axis[2]) * texCoordScaleT; + } + + mf->iIndex = -cgi.CM_InlineModel(cg_entities[-mf->iIndex].currentState.modelindex); + } else { + mf->numPoints = 0; + } + } + + return numFragments; } int CG_PermanentTreadMarkDecal( @@ -1171,14 +1663,412 @@ int CG_PermanentTreadMarkDecal( void *pVoidPolyVerts ) { - // FIXME: unimplemented - return 0; + byte colors[4]; + int i, j; + int numFragments; + vec3_t originalPoints[4]; + vec3_t markPoints[MAX_MARK_POLYVERTS]; + vec3_t projection; + vec3_t vLight; + markFragment_t *mf; + polyVert_t *pPolyVerts; + polyVert_t *v; + clipHandle_t cmodel; + float fStartAlpha, fEndAlpha; + float fStartTex, fEndTex; + float fRightCenterDist; + float fOOWidth, fOODoubleWidth; + float fDist, fSideDist; + float fFrac; + float fStartDist, fRightStartDist, fLeftStartDist; + float fCenterTexScale, fRightTexScale, fLeftTexScale; + float fCenterAlphaScale, fRightAlphaScale, fLeftAlphaScale; + float fSideAlpha, fCenterAlpha; + vec3_t vStartCenter, vEndCenter; + vec3_t vDirection; + vec3_t vRight; + vec3_t vDelta; + float fRadiusSquared; + + pPolyVerts = (polyVert_t *)pVoidPolyVerts; + + if (bStartSegment) { + VectorCopy(pTread->vStartVerts[1], originalPoints[0]); + VectorCopy(pTread->vStartVerts[0], originalPoints[1]); + VectorCopy(pTread->vMidVerts[0], originalPoints[2]); + VectorCopy(pTread->vMidVerts[1], originalPoints[3]); + + fStartAlpha = pTread->fStartAlpha; + fEndAlpha = pTread->fMidAlpha; + fStartTex = pTread->fStartTexCoord; + fEndTex = pTread->fMidTexCoord; + + // Calculate the start center + vStartCenter[0] = (originalPoints[1][0] + originalPoints[0][0]) * 0.5; + vStartCenter[1] = (originalPoints[1][1] + originalPoints[0][1]) * 0.5; + vStartCenter[2] = (originalPoints[1][2] + originalPoints[0][2]) * 0.5; + VectorCopy(pTread->vMidPos, vEndCenter); + VectorCopy(pTread->vStartDir, vDirection); + } else { + VectorCopy(pTread->vMidVerts[1], originalPoints[0]); + VectorCopy(pTread->vMidVerts[0], originalPoints[1]); + VectorCopy(pTread->vEndVerts[0], originalPoints[2]); + VectorCopy(pTread->vEndVerts[1], originalPoints[3]); + + fStartAlpha = pTread->fMidAlpha; + fEndAlpha = pTread->fEndAlpha; + fStartTex = pTread->fMidTexCoord; + fEndTex = pTread->fEndTexCoord; + + VectorCopy(pTread->vMidPos, vStartCenter); + VectorCopy(pTread->vEndPos, vEndCenter); + + // Calculate the direction + VectorSubtract(vEndCenter, vStartCenter, vDirection); + VectorNormalizeFast(vDirection); + } + + CrossProduct(vec_upwards, vDirection, vRight); + fRightCenterDist = DotProduct(vEndCenter, vRight); + fOOWidth = 1.0 / pTread->fWidth; + fOODoubleWidth = 1.0 / (pTread->fWidth * 2); + fStartDist = DotProduct(vDirection, vStartCenter); + fRightStartDist = DotProduct(vDirection, originalPoints[1]); + fLeftStartDist = DotProduct(vDirection, originalPoints[1]); + + // + // Calculate center + // + VectorSubtract(vEndCenter, vStartCenter, vDelta); + fDist = VectorLength(vDelta); + fCenterTexScale = (fEndTex - fStartTex) / fDist; + fCenterAlphaScale = (fEndAlpha - fStartAlpha) / fDist; + fSideDist = fDist; + + // + // Calculate right + // + VectorSubtract(originalPoints[2], originalPoints[1], vDelta); + fDist = VectorLength(vDelta); + fRightTexScale = (fEndTex - fStartTex) / fDist; + fRightAlphaScale = (fEndAlpha - fStartAlpha) / fDist; + + // + // Calculate left + // + VectorSubtract(originalPoints[3], originalPoints[0], vDelta); + fDist = VectorLength(vDelta); + fLeftTexScale = (fEndTex - fStartTex) / fDist; + fLeftAlphaScale = (fEndAlpha - fStartAlpha) / fDist; + + VectorSet(projection, 0, 0, -32); + colors[0] = colors[1] = colors[2] = colors[3] = 0xff; + + numFragments = CG_GetMarkFragments( + 4, originalPoints, projection, markPoints, pMarkFragments, (Square(pTread->fWidth) + Square(fSideDist)) * 0.25 + ); + + for (i = 0; i < numFragments; i++) { + vec3_t vWorldPos; + + mf = &pMarkFragments[i]; + + if (mf->numPoints > 8) { + mf->numPoints = 8; + } + + if (mf->iIndex >= 0) { + for (j = 0; j < mf->numPoints; j++) { + v = &pPolyVerts[mf->firstPoint + j]; + VectorCopy(markPoints[mf->firstPoint + j], v->xyz); + + if (dolighting) { + cgi.R_GetLightingForDecal(vLight, projection, v->xyz); + + colors[0] = vLight[0]; + colors[1] = vLight[1]; + colors[2] = vLight[2]; + } + + fSideDist = DotProduct(v->xyz, vRight) - fRightCenterDist; + fSideAlpha = fSideDist * fOOWidth; + v->st[0] = (fSideDist + pTread->fWidth) * fOODoubleWidth; + + if (fSideAlpha < 0) { + fSideAlpha = -fSideAlpha; + v->st[1] = + fStartTex + ((DotProduct(v->xyz, vDirection) - fLeftStartDist) * fLeftTexScale * fSideAlpha); + } else { + v->st[1] = + fStartTex + ((DotProduct(v->xyz, vDirection) - fRightStartDist) * fRightTexScale * fSideAlpha); + } + + v->st[1] += (DotProduct(v->xyz, vDirection) - fStartDist) * fCenterTexScale * (1.0 - fSideAlpha); + } + } else if (CG_GetMarkInlineModelOrientation(mf->iIndex)) { + for (j = 0; j < mf->numPoints; j++) { + v = &pPolyVerts[mf->firstPoint + j]; + VectorCopy(markPoints[mf->firstPoint + j], v->xyz); + + if (dolighting) { + cgi.R_GetLightingForDecal(vLight, projection, v->xyz); + + colors[0] = vLight[0]; + colors[1] = vLight[1]; + colors[2] = vLight[2]; + } + + v->modulate[0] = colors[0]; + v->modulate[1] = colors[1]; + v->modulate[2] = colors[2]; + v->modulate[3] = colors[3]; + + CG_FragmentPosToWorldPos(v->xyz, vWorldPos); + + fSideDist = DotProduct(vWorldPos, vRight) - fRightCenterDist; + fSideAlpha = fSideDist * fOOWidth; + v->st[0] = (fSideDist + pTread->fWidth) * fOODoubleWidth; + + if (fSideAlpha < 0) { + fSideAlpha = -fSideAlpha; + v->st[1] = + fStartTex + ((DotProduct(vWorldPos, vDirection) - fLeftStartDist) * fLeftTexScale * fSideAlpha); + } else { + v->st[1] = fStartTex + + ((DotProduct(vWorldPos, vDirection) - fRightStartDist) * fRightTexScale * fSideAlpha); + } + + v->st[1] += (DotProduct(vWorldPos, vDirection) - fStartDist) * fCenterTexScale * (1.0 - fSideAlpha); + } + + mf->iIndex = -cgi.CM_InlineModel(cg_entities[-mf->iIndex].currentState.modelindex); + } else { + mf->numPoints = 0; + } + } + + return numFragments; } int CG_PermanentUpdateTreadMark( treadMark_t *pTread, float fAlpha, float fMinSegment, float fMaxSegment, float fMaxOffset, float fTexScale ) { - // FIXME: unimplemented + trace_t trace; + float fDist; + float fSplitLength; + float fNewLength; + float fTmp; + qboolean bDoSegmentation; + vec3_t vPos; + vec3_t vEnd; + vec3_t vNewPos; + vec3_t vDelta, vDeltaNorm; + vec3_t vDir, vMidDir; + vec3_t vRight; + + VectorCopy(cg.predicted_player_state.origin, vPos); + VectorCopy(cg.predicted_player_state.origin, vEnd); + + vPos[2] += 32; + vEnd[2] -= 256; + + CG_Trace( + &trace, + vPos, + vec3_origin, + vec3_origin, + vEnd, + cg.snap->ps.clientNum, + MASK_TREADMARK, + qfalse, + qtrue, + "CG_PermanentUpdateTreadMark" + ); + + VectorCopy(trace.endpos, vNewPos); + + if (cg.time - pTread->iLastTime > 500) { + VectorClear(pTread->vStartDir); + VectorClear(pTread->vStartVerts[0]); + VectorClear(pTread->vStartVerts[1]); + pTread->fStartTexCoord = 0; + pTread->fStartAlpha = 0; + + VectorClear(pTread->vMidPos); + VectorClear(pTread->vMidVerts[0]); + VectorClear(pTread->vMidVerts[1]); + pTread->fMidTexCoord = 0; + pTread->fMidAlpha = 0; + + VectorClear(pTread->vEndPos); + VectorClear(pTread->vEndVerts[0]); + VectorClear(pTread->vEndVerts[1]); + pTread->fEndTexCoord = 0; + pTread->fEndAlpha = 0; + + pTread->iState = 1; + pTread->iReferenceNumber = 0; + pTread->iLastTime = cg.time; + VectorCopy(vNewPos, pTread->vMidPos); + VectorCopy(vNewPos, pTread->vEndPos); + + if (fAlpha < 0) { + pTread->fMidAlpha = 255.0; + } else { + pTread->fMidAlpha = fAlpha * 255.0; + } + pTread->fEndAlpha = pTread->fMidAlpha; + + return 0; + } + + if (VectorCompare(pTread->vEndPos, vNewPos)) { + if (fAlpha < 0) { + return -1; + } + + fTmp = pTread->fEndAlpha; + pTread->fEndAlpha = fAlpha * 255; + + //if (fabs(fTmp - pTread->fEndAlpha > 0.05)) { + // Fixed in OPM + // Looks like this was accidental + if (fabs(fTmp - pTread->fEndAlpha) > 0.05) { + return -1; + } + + return 0; + } + + VectorSubtract(vNewPos, pTread->vMidPos, vDelta); + fDist = VectorNormalize2(vDelta, vDeltaNorm); + + if (pTread->iState == 1) { + fSplitLength = 0.0; + bDoSegmentation = qfalse; + } else { + VectorAdd(vDeltaNorm, pTread->vStartDir, vMidDir); + VectorScale(vMidDir, 0.5, vMidDir); + VectorNormalizeFast(vMidDir); + + fTmp = DotProduct(vMidDir, vDeltaNorm); + fSplitLength = pTread->fWidth / fTmp; + + if (fTmp < -0.5) { + fNewLength = + fTmp + * (fTmp + * (fTmp + * (fTmp * (fTmp * (fTmp * -337.31875783205 + -1237.54375255107) + -1802.11467325687) + + -1303.19904613494) + + -471.347871690988) + + -70.0883838161826); + } else if (fTmp > 0.5) { + fNewLength = + fTmp + * (fTmp + * (fTmp + * (fTmp * (fTmp * (fTmp * -1507.55394345521 + 6580.58002318442) + -11860.0735285953) + + 11290.7510782536) + + -5986.89654545347) + + 1675.66417006387) + + -192.426950291139; + } else { + fNewLength = fTmp * (fTmp * -0.531387674508458 + -2.11e-14) + 1.00086138065435; + } + + fNewLength *= fSplitLength; + if (fNewLength + fMinSegment > fDist) { + bDoSegmentation = qfalse; + } else if (fSplitLength < -1) { + fSplitLength = -fSplitLength; + bDoSegmentation = qtrue; + } else if (fDist > fMaxSegment) { + bDoSegmentation = qtrue; + } else { + CrossProduct(vec_upwards, pTread->vStartDir, vRight); + VectorNormalizeFast(vRight); + + if (fabs(DotProduct(vRight, vDelta)) > fMaxOffset) { + bDoSegmentation = qtrue; + } else { + bDoSegmentation = qfalse; + } + } + } + + if (pTread->iState == 2 && bDoSegmentation) { + VectorCopy(pTread->vStartVerts[0], pTread->vMidVerts[0]); + VectorCopy(pTread->vStartVerts[1], pTread->vMidVerts[1]); + pTread->fMidTexCoord = pTread->fEndTexCoord; + pTread->fMidAlpha = pTread->fEndAlpha; + VectorCopy(vNewPos, pTread->vEndPos); + + if (fAlpha >= 0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + + pTread->iState = 3; + + return 0; + } else if (pTread->iState == 1 || pTread->iState == 2) { + VectorCopy(vNewPos, pTread->vEndPos); + + if (fAlpha >= 0.0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + + CrossProduct(vec_upwards, vDeltaNorm, vDir); + VectorMA(pTread->vMidPos, pTread->fWidth, vDir, pTread->vMidVerts[0]); + VectorMA(pTread->vMidPos, -pTread->fWidth, vDir, pTread->vMidVerts[1]); + VectorMA(pTread->vEndPos, pTread->fWidth, vDir, pTread->vEndVerts[0]); + VectorMA(pTread->vEndPos, -pTread->fWidth, vDir, pTread->vEndVerts[1]); + + pTread->fEndTexCoord = fDist * fTexScale; + + if (pTread->iState == 1 && fDist > 8.0) { + VectorCopy(vDelta, pTread->vStartDir); + pTread->iState = 2; + } + + return 0; + } else if (bDoSegmentation) { + if (!pTread->iReferenceNumber) { + pTread->iReferenceNumber = 1; + return 1; + } + + pTread->iReferenceNumber = 0; + VectorCopy(pTread->vStartVerts[0], pTread->vMidVerts[0]); + VectorCopy(pTread->vStartVerts[1], pTread->vMidVerts[1]); + VectorSubtract(pTread->vEndPos, pTread->vMidPos, pTread->vStartDir); + VectorNormalizeFast(pTread->vStartDir); + + VectorCopy(pTread->vEndPos, pTread->vMidPos); + pTread->fMidTexCoord = pTread->fEndTexCoord; + pTread->fMidAlpha = pTread->fEndAlpha; + + if (pTread->fStartTexCoord >= 1.0) { + pTread->fStartTexCoord = pTread->fStartTexCoord - floor(pTread->fStartTexCoord); + pTread->fMidTexCoord = pTread->fMidTexCoord - floor(pTread->fStartTexCoord); + } + + VectorCopy(vNewPos, pTread->vEndPos); + pTread->fEndTexCoord = fDist * fTexScale + pTread->fMidTexCoord; + if (fAlpha >= 0) { + pTread->fEndAlpha = fAlpha * 255.0; + } + } + + CrossProduct(vec_upwards, vMidDir, vRight); + VectorNormalizeFast(vRight); + VectorMA(pTread->vMidPos, fSplitLength, vRight, pTread->vMidVerts[0]); + VectorMA(pTread->vMidPos, -fSplitLength, vRight, pTread->vMidVerts[1]); + CrossProduct(vec_upwards, vDeltaNorm, vRight); + VectorNormalizeFast(vRight); + VectorMA(pTread->vEndPos, pTread->fWidth, vRight, pTread->vEndVerts[0]); + VectorMA(pTread->vEndPos, -pTread->fWidth, vRight, pTread->vEndVerts[1]); + return 0; } diff --git a/code/cgame/cg_modelanim.c b/code/cgame/cg_modelanim.c index 49a67a2b..d47dc1cc 100644 --- a/code/cgame/cg_modelanim.c +++ b/code/cgame/cg_modelanim.c @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -26,6 +26,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_local.h" #include "tiki.h" +static qboolean cg_forceModelAllowed = qfalse; + +/* +=============== +CG_GetPlayerModelTiki +=============== +*/ +const char *CG_GetPlayerModelTiki(const char *modelName) +{ + return va("models/player/%s.tik", modelName); +} + +/* +=============== +CG_GetPlayerLocalModelTiki +=============== +*/ +const char *CG_GetPlayerLocalModelTiki(const char *modelName) +{ + return va("models/player/%s.tik", modelName); +} + +/* +=============== +CG_PlayerTeamIcon +=============== +*/ void CG_PlayerTeamIcon(refEntity_t *pModel, entityState_t *pPlayerState) { qboolean bInArtillery, bInTeam, bSpecialIcon; @@ -180,6 +207,344 @@ void CG_PlayerTeamIcon(refEntity_t *pModel, entityState_t *pPlayerState) } } +/* +=============== +CG_InterpolateAnimParms + +Interpolate between current and next entity +=============== +*/ +void CG_InterpolateAnimParms(entityState_t *state, entityState_t *sNext, refEntity_t *model) +{ + static cvar_t *vmEntity = NULL; + int i; + float t; + float animLength; + float t1, t2; + + if (!vmEntity) { + vmEntity = cgi.Cvar_Get("viewmodelanim", "1", 0); + } + + if (sNext && sNext->usageIndex == state->usageIndex) { + t1 = cg.time - cg.snap->serverTime; + t2 = cg.nextSnap->serverTime - cg.snap->serverTime; + t = t1 / t2; + + model->actionWeight = (sNext->actionWeight - state->actionWeight) * t + state->actionWeight; + + for (i = 0; i < MAX_FRAMEINFOS; i++) { + if (sNext->frameInfo[i].weight) { + model->frameInfo[i].index = sNext->frameInfo[i].index; + if (sNext->frameInfo[i].index == state->frameInfo[i].index && state->frameInfo[i].weight) { + model->frameInfo[i].weight = + (sNext->frameInfo[i].weight - state->frameInfo[i].weight) * t + state->frameInfo[i].weight; + + if (sNext->frameInfo[i].time >= state->frameInfo[i].time) { + model->frameInfo[i].time = + (sNext->frameInfo[i].time - state->frameInfo[i].time) * t + state->frameInfo[i].time; + } else { + animLength = cgi.Anim_Time(model->tiki, sNext->frameInfo[i].index); + if (!animLength) { + t1 = 0.0; + } else { + t1 = (animLength + sNext->frameInfo[i].time - state->frameInfo[i].time) * t + + state->frameInfo[i].time; + } + + t2 = t1; + while (t2 > animLength) { + t2 -= animLength; + + if (t2 == t1) { + t2 = 1.0; + break; + } + + t1 = t2; + } + + model->frameInfo[i].time = t2; + } + } else { + animLength = cgi.Anim_Time(model->tiki, sNext->frameInfo[i].index); + if (!animLength) { + t1 = 0.0; + } else { + t1 = sNext->frameInfo[i].time - (cg.nextSnap->serverTime - cg.time) / 1000.0; + } + + model->frameInfo[i].time = Q_max(0, t1); + model->frameInfo[i].weight = sNext->frameInfo[i].weight; + } + } else if (sNext->frameInfo[i].index == state->frameInfo[i].index) { + animLength = cgi.Anim_Time(model->tiki, sNext->frameInfo[i].index); + if (!animLength) { + t1 = 0.0; + } else { + t1 = (cg.time - cg.snap->serverTime) / 1000.0 + state->frameInfo[i].time; + } + + model->frameInfo[i].index = Q_clamp_int(state->frameInfo[i].index, 0, model->tiki->a->num_anims - 1); + model->frameInfo[i].time = Q_min(animLength, t1); + model->frameInfo[i].weight = (1.0 - t) * state->frameInfo[i].weight; + } else { + model->frameInfo[i].index = -1; + model->frameInfo[i].weight = 0.0; + } + } + } else { + // no next state, don't blend anims + + model->actionWeight = state->actionWeight; + for (i = 0; i < MAX_FRAMEINFOS; i++) { + if (state->frameInfo[i].weight) { + model->frameInfo[i].index = Q_clamp_int(state->frameInfo[i].index, 0, model->tiki->a->num_anims - 1); + model->frameInfo[i].time = state->frameInfo[i].time; + model->frameInfo[i].weight = state->frameInfo[i].weight; + } else { + model->frameInfo[i].index = -1; + model->frameInfo[i].weight = 0.0; + } + } + } + + if (vmEntity->integer == state->number) { + static cvar_t *curanim; + if (!curanim) { + curanim = cgi.Cvar_Get("viewmodelanimslot", "1", 0); + } + + cgi.Cvar_Set("viewmodelanimclienttime", va("%0.2f", model->frameInfo[curanim->integer].time)); + } +} + +/* +=============== +CG_CastFootShadow + +Cast complex foot shadow using lights +=============== +*/ +void CG_CastFootShadow(const vec_t *vLightPos, vec_t *vLightIntensity, int iTag, refEntity_t *model) +{ + int i; + float fAlpha; + float fLength; + float fWidth; + float fAlphaOfs; + float fOfs; + float fPitchCos; + vec3_t vPos; + vec3_t vEnd; + vec3_t vDelta; + vec3_t vLightAngles; + trace_t trace; + orientation_t oFoot; + + VectorCopy(model->origin, vPos); + oFoot = cgi.TIKI_Orientation(model, iTag); + VectorMA(oFoot.origin, 2, oFoot.axis[1], vEnd); + for (i = 0; i < 3; i++) { + VectorMA(vPos, vEnd[i], model->axis[i], vPos); + } + + if (cg_shadowdebug->integer) { + vec3_t vDir; + + // + // show debug lines + // + memset(vDir, 0, sizeof(vDir)); + for (i = 0; i < 3; ++i) { + VectorMA(vDir, oFoot.axis[0][i], model->axis[i], vDir); + } + VectorMA(vPos, 32.0, vDir, vEnd); + cgi.R_DebugLine(vPos, vEnd, 1.0, 0.0, 0.0, 1.0); + + memset(vDir, 0, sizeof(vDir)); + for (i = 0; i < 3; ++i) { + VectorMA(vDir, oFoot.axis[1][i], model->axis[i], vDir); + } + VectorMA(vPos, 32.0, vDir, vEnd); + cgi.R_DebugLine(vPos, vEnd, 0.0, 1.0, 0.0, 1.0); + + memset(vDir, 0, sizeof(vDir)); + for (i = 0; i < 3; ++i) { + VectorMA(vDir, oFoot.axis[2][i], model->axis[i], vDir); + } + VectorMA(vPos, 32.0, vDir, vEnd); + cgi.R_DebugLine(vPos, vEnd, 0.0, 0.0, 1.0, 1.0); + } + + // calculate the direction + VectorSubtract(vLightPos, vPos, vDelta); + VectorNormalizeFast(vDelta); + vectoangles(vDelta, vLightAngles); + + // normalize to 180 degrees + if (vLightAngles[0] > 180) { + vLightAngles[0] -= 360; + } + + if (vLightAngles[0] > -5.7319679) { + // FIXME: what is -5.7319679? + return; + } + + fPitchCos = cos(DEG2RAD(vLightAngles[0])); + if (fPitchCos > 0.955) { + fAlpha = 1.0 - (fPitchCos - 0.955) * 25; + } else { + fAlpha = 1.0; + } + + fLength = fPitchCos * fPitchCos * 32.0 + fPitchCos * 8.0 + 10.0; + fOfs = 0.5 - (-4.1 / tan(DEG2RAD(vLightAngles[0])) + 4.0 - fLength) / fLength * 0.5; + VectorMA(vPos, -96.0, vDelta, vEnd); + CG_Trace(&trace, vPos, vec3_origin, vec3_origin, vEnd, 0, MASK_FOOTSHADOW, qfalse, qtrue, "CG_CastFootShadow"); + + if (cg_shadowdebug->integer) { + cgi.R_DebugLine(vPos, vLightPos, 0.75, 0.75, 0.5, 1.0); + cgi.R_DebugLine(vPos, vEnd, 1.0, 1.0, 1.0, 1.0); + } + + if (trace.fraction == 1.0) { + return; + } + + trace.fraction -= 0.0427f; + if (trace.fraction < 0) { + trace.fraction = 0; + } + + fWidth = 10.f - (1.f - trace.fraction) * 6.f; + fAlphaOfs = (1.f - trace.fraction) * fAlpha; + + fAlpha = Q_max(vLightIntensity[0], Q_max(vLightIntensity[1], vLightIntensity[2])); + + if (fAlpha < 0.1) { + vLightIntensity[0] *= 0.1 / fAlpha * fAlphaOfs; + vLightIntensity[1] *= 0.1 / fAlpha * fAlphaOfs; + vLightIntensity[2] *= 0.1 / fAlpha * fAlphaOfs; + } else { + vLightIntensity[0] *= fAlphaOfs; + vLightIntensity[1] *= fAlphaOfs; + vLightIntensity[2] *= fAlphaOfs; + } + + fAlpha = Q_max(vLightIntensity[0], Q_max(vLightIntensity[1], vLightIntensity[2])); + if (fAlpha > 0.6) { + vLightIntensity[0] *= 0.6 / fAlpha; + vLightIntensity[1] *= 0.6 / fAlpha; + vLightIntensity[2] *= 0.6 / fAlpha; + } + + if (vLightIntensity[0] <= 0.01 && vLightIntensity[1] <= 0.01 && vLightIntensity[2] <= 0.01) { + return; + } + + CG_ImpactMark( + cgs.media.footShadowMarkShader, + trace.endpos, + trace.plane.normal, + vLightAngles[1], + fWidth, + fLength, + vLightIntensity[0], + vLightIntensity[1], + vLightIntensity[2], + 1.0, + qfalse, + qtrue, + qfalse, + qfalse, + 0.5, + fOfs + ); +} + +/* +=============== +CG_CastSimpleFeetShadow + +Cast basic feet shadow +=============== +*/ +void CG_CastSimpleFeetShadow( + const trace_t *pTrace, + float fWidth, + float fAlpha, + int iRightTag, + int iLeftTag, + const dtiki_t *tiki, + refEntity_t *model +) +{ + int i; + float fShadowYaw; + float fLength; + vec3_t vPos, vRightPos, vLeftPos; + vec3_t vDelta; + orientation_t oFoot; + + // + // right foot + // + VectorCopy(pTrace->endpos, vRightPos); + oFoot = cgi.TIKI_Orientation(model, iRightTag); + VectorMA(oFoot.origin, 3, oFoot.axis[1], vPos); + + for (i = 0; i < 3; i++) { + VectorMA(vRightPos, vPos[i], model->axis[i], vRightPos); + } + + VectorMA(vRightPos, -2, oFoot.axis[1], vRightPos); + + // + // left foot + // + VectorCopy(pTrace->endpos, vLeftPos); + oFoot = cgi.TIKI_Orientation(model, iLeftTag); + VectorMA(oFoot.origin, 3, oFoot.axis[1], vPos); + + for (i = 0; i < 3; i++) { + VectorMA(vLeftPos, vPos[i], model->axis[i], vLeftPos); + } + + VectorAdd(vRightPos, vLeftPos, vPos); + VectorScale(vPos, 0.5, vPos); + VectorSubtract(vRightPos, vLeftPos, vDelta); + VectorMA(vLeftPos, 0.5, vDelta, vPos); + + // get the facing yaw + fShadowYaw = vectoyaw(vDelta); + fLength = VectorNormalize(vDelta) * 0.5 + 12; + if (fLength < fWidth * 0.7) { + fLength = fWidth * 0.7; + } + + // add the mark + CG_ImpactMark( + cgs.media.shadowMarkShader, + vPos, + pTrace->plane.normal, + fShadowYaw, + fWidth * 0.7, + fLength, + fAlpha, + fAlpha, + fAlpha, + 1.0, + qfalse, + qtrue, + qfalse, + qfalse, + 0.5, + 0.5 + ); +} + /* =============== CG_EntityShadow @@ -193,9 +558,15 @@ Returns the Z component of the surface being shadowed qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model) { + int iTagL, iTagR; + float alpha; + float fWidth; vec3_t end; + vec3_t vMins, vMaxs; + vec3_t vSize; trace_t trace; - float alpha, radius; + + iTagR = -1; if (cg_shadows->integer == 0) { return qfalse; @@ -206,10 +577,29 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model) return qfalse; } - // no shadows when invisible - // if ( cent->currentState.powerups & ( 1 << PW_INVIS ) ) { - // return qfalse; - // } + if (cg_shadows->integer == 2 && (model->renderfx & RF_SHADOW_PRECISE)) { + iTagL = cgi.Tag_NumForName(model->tiki, "Bip01 L Foot"); + if (iTagL != -1) { + iTagR = cgi.Tag_NumForName(model->tiki, "Bip01 R Foot"); + } + + if (iTagR != -1) { + int iNumLights, iCurrLight; + vec3_t avLightPos[16], avLightIntensity[16]; + + iNumLights = Q_clamp(cg_shadowscount->integer, 1, 8); + iNumLights = cgi.R_GatherLightSources(model->origin, avLightPos, avLightIntensity, iNumLights); + if (iNumLights) { + for (iCurrLight = 0; iCurrLight < iNumLights; iCurrLight++) { + CG_CastFootShadow(avLightPos[iCurrLight], avLightIntensity[iCurrLight], iTagL, model); + CG_CastFootShadow(avLightPos[iCurrLight], avLightIntensity[iCurrLight], iTagR, model); + } + + // shadow was casted properly + return qtrue; + } + } + } // send a trace down from the player to the ground VectorCopy(model->origin, end); @@ -222,29 +612,46 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model) return qfalse; } - if ((cg_shadows->integer == 2) && (model->renderfx & RF_SHADOW_PRECISE)) { + // since 2.0: no shadow if solid + if (trace.startsolid || trace.allsolid) { + return qfalse; + } + + if ((cg_shadows->integer == 3) && (model->renderfx & RF_SHADOW_PRECISE)) { return qtrue; } // // get the bounds of the current frame // - radius = model->scale * cgi.R_ModelRadius(model->hModel); - - if (radius < 1) { + fWidth = model->scale * cgi.R_ModelRadius(model->hModel); + if (fWidth < 1) { return qfalse; } // fade the shadow out with height - alpha = (1.0 - trace.fraction) * 0.8f; + alpha = (1.0 - trace.fraction) * 0.65f; - if ((cg_shadows->integer == 3) && (model->renderfx & RF_SHADOW_PRECISE)) { - if (model->shaderRGBA[3] == 255) { - model->shaderRGBA[3] = alpha * 255; + if (model->renderfx & RF_SHADOW_PRECISE) { + iTagL = cgi.Tag_NumForName(model->tiki, "Bip01 L Foot"); + if (iTagL != -1) { + iTagR = cgi.Tag_NumForName(model->tiki, "Bip01 R Foot"); + } + + if (iTagR != -1) { + if (cg_shadows->integer == 2) { + alpha *= 0.6f; + } + + CG_CastSimpleFeetShadow(&trace, fWidth, alpha, iTagR, iTagL, model->tiki, model); + return qtrue; } - return qtrue; } + cgi.R_ModelBounds(model->hModel, vMins, vMaxs); + VectorSubtract(vMaxs, vMins, vSize); + VectorScale(vSize, 0.6f, vSize); + // add the mark as a temporary, so it goes directly to the renderer // without taking a spot in the cg_marks array CG_ImpactMark( @@ -252,15 +659,15 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model) trace.endpos, trace.plane.normal, cent->lerpAngles[YAW], - radius, - radius, + vSize[1], + vSize[0], alpha, alpha, alpha, 1, qfalse, qtrue, - qtrue, + qfalse, qfalse, 0.5f, 0.5f @@ -286,7 +693,7 @@ void CG_AnimationDebugMessage(int number, const char *fmt, ...) char msg[1024]; va_start(argptr, fmt); - vsprintf(msg, fmt, argptr); + Q_vsnprintf(msg, sizeof(msg), fmt, argptr); va_end(argptr); if ((!cg_debugAnimWatch->integer) || ((cg_debugAnimWatch->integer - 1) == number)) { @@ -316,10 +723,12 @@ void CG_AttachEntity( orientation_t or ; vec3_t tempAxis[3]; vec3_t vOrigin; + vec3_t vDeltaLightOrg; or = cgi.TIKI_Orientation(parent, tagnum); //cgi.Printf( "th = %d %.2f %.2f %.2f\n", tikihandle, or.origin[ 0 ], or.origin[ 1 ], or.origin[ 2 ] ); + VectorSubtract(entity->lightingOrigin, entity->origin, vDeltaLightOrg); VectorCopy(parent->origin, entity->origin); for (i = 0; i < 3; i++) { @@ -337,17 +746,22 @@ void CG_AttachEntity( VectorCopy(entity->origin, entity->oldorigin); if (use_angles) { - MatrixMultiply(entity->axis, parent->axis, tempAxis); - MatrixMultiply(or.axis, tempAxis, entity->axis); + MatrixMultiply(entity->axis, or.axis, tempAxis); + MatrixMultiply(tempAxis, parent->axis, entity->axis); } entity->scale *= parent->scale; entity->renderfx |= (parent->renderfx & ~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN)); - MatrixTransformVectorRight(entity->axis, entity->lightingOrigin, vOrigin); + MatrixTransformVectorRight(entity->axis, vDeltaLightOrg, vOrigin); VectorAdd(entity->origin, vOrigin, entity->lightingOrigin); } +/* +=============== +CG_AttachEyeEntity +=============== +*/ void CG_AttachEyeEntity( refEntity_t *entity, refEntity_t *parent, dtiki_t *tiki, int tagnum, qboolean use_angles, vec_t *attach_offset ) @@ -360,8 +774,7 @@ void CG_AttachEyeEntity( AnglesToAxis(cg.refdefViewAngles, entity->axis); } - if (attach_offset[0] || attach_offset[1] || attach_offset[2]) - { + if (attach_offset[0] || attach_offset[1] || attach_offset[2]) { for (i = 0; i < 3; i++) { VectorMA(entity->origin, attach_offset[i], entity->axis[i], entity->origin); } @@ -373,56 +786,219 @@ void CG_AttachEyeEntity( VectorCopy(parent->lightingOrigin, entity->lightingOrigin); } +/* +=============== +CG_IsValidServerModel +=============== +*/ +qboolean CG_IsValidServerModel(const char *modelpath) +{ + const char *str; + int i; + + for (i = 1; i < MAX_MODELS; i++) { + str = CG_ConfigString(CS_MODELS + i); + if (!Q_stricmp(str, modelpath)) { + return qtrue; + } + } + + return qfalse; +} + +/* +=============== +CG_CheckValidModels + +This verifies the allied player model and the german player model: +- If they don't exist on the client, reset to the default allied player model +- If they don't exist on the server, don't allow forceModel so the client explicitly know the skin isn't supported +=============== +*/ +void CG_CheckValidModels() +{ + const char *modelpath; + qboolean isDirty = qfalse; + + if (dm_playermodel->modified) { + // Check for allied model + modelpath = va("models/player/%s.tik", dm_playermodel->string); + if (!cgi.R_RegisterModel(modelpath)) { + cgi.Printf( + "Allied model '%s' is invalid, resetting to '%s'\n", dm_playermodel->string, dm_playermodel->resetString + ); + + cgi.Cvar_Set("dm_playermodel", dm_playermodel->resetString); + modelpath = va("models/player/%s.tik", dm_playermodel->string); + } + + cg.serverAlliedModelValid = CG_IsValidServerModel(modelpath); + } + + if (dm_playergermanmodel->modified) { + // Check for axis model + modelpath = va("models/player/%s.tik", dm_playergermanmodel->string); + if (!cgi.R_RegisterModel(modelpath)) { + cgi.Printf( + "Allied model '%s' is invalid, resetting to '%s'\n", + dm_playergermanmodel->string, + dm_playergermanmodel->resetString + ); + + cgi.Cvar_Set("dm_playergermanmodel", dm_playergermanmodel->resetString); + modelpath = va("models/player/%s.tik", dm_playergermanmodel->string); + } + + cg.serverAxisModelValid = CG_IsValidServerModel(modelpath); + } + + if (dm_playermodel->modified || dm_playergermanmodel->modified) { + cg_forceModelAllowed = cg.serverAlliedModelValid && cg.serverAxisModelValid; + } +} + +/* +=============== +CG_ServerModelLoaded +=============== +*/ +void CG_ServerModelLoaded(const char *name, qhandle_t handle) +{ + if (!Q_stricmpn(name, "models/player/", 14) && (!cg.serverAlliedModelValid || !cg.serverAxisModelValid)) { + char modelName[MAX_QPATH]; + COM_StripExtension(name + 14, modelName, sizeof(modelName)); + + // + // The player model has been loaded on the server + // so try again parsing + // + if (!Q_stricmp(modelName, dm_playermodel->string)) { + dm_playermodel->modified = qtrue; + } + if (!Q_stricmp(modelName, dm_playergermanmodel->string)) { + dm_playergermanmodel->modified = qtrue; + } + } +} + +/* +=============== +CG_ServerModelUnloaded +=============== +*/ +void CG_ServerModelUnloaded(qhandle_t handle) +{ +#if 0 + if (cg.serverAlliedModelValid && handle == cg.hAlliedPlayerModelHandle) { + dm_playermodel->modified = qtrue; + } + if (cg.serverAxisModelValid && handle == cg.hAxisPlayerModelHandle) { + dm_playergermanmodel->modified = qtrue; + } +#endif +} + +/* +=============== +CG_UpdateForceModels +=============== +*/ void CG_UpdateForceModels() { qhandle_t hModel; - char* pszAlliesPartial; - char* pszAxisPartial; - char szAlliesModel[256]; - char szAxisModel[256]; + char *pszAlliesPartial; + char *pszAxisPartial; + char szAlliesModel[256]; + char szAxisModel[256]; + qboolean isDirty; - if (cg.pAlliedPlayerModel && cg.pAxisPlayerModel && !dm_playermodel->modified && !dm_playergermanmodel->modified) { + isDirty = dm_playermodel->modified || dm_playergermanmodel->modified || cg_forceModel->modified; + + if (!cg_forceModelAllowed) { + if (isDirty) { + cgi.Printf( + "One or more of the selected players model don't exist on the server or are not loaded, using the " + "default skin\n" + ); + } + + return; + } + + if (cg.pAlliedPlayerModel && cg.pAxisPlayerModel && !isDirty) { return; } pszAlliesPartial = dm_playermodel->string; - pszAxisPartial = dm_playergermanmodel->string; + pszAxisPartial = dm_playergermanmodel->string; - sprintf(szAlliesModel, "models/player/%s.tik", pszAlliesPartial); - sprintf(szAxisModel, "models/player/%s.tik", pszAxisPartial); - hModel = cgi.R_RegisterModel(szAlliesModel); - if (!hModel) hModel = cgi.R_RegisterModel("models/player/american_army.tik"); + Com_sprintf(szAlliesModel, sizeof(szAlliesModel), "models/player/%s.tik", pszAlliesPartial); + Com_sprintf(szAxisModel, sizeof(szAxisModel), "models/player/%s.tik", pszAxisPartial); + + hModel = cg.serverAlliedModelValid ? cgi.R_RegisterModel(szAlliesModel) : 0; + if (!hModel) { + Com_sprintf(szAlliesModel, sizeof(szAlliesModel), "models/player/%s.tik", dm_playermodel->resetString); + hModel = cgi.R_RegisterModel(szAlliesModel); + } if (hModel) { cg.hAlliedPlayerModelHandle = hModel; - cg.pAlliedPlayerModel = cgi.R_Model_GetHandle(hModel); + cg.pAlliedPlayerModel = cgi.R_Model_GetHandle(hModel); if (!cg.pAlliedPlayerModel) { cg.hAlliedPlayerModelHandle = 0; } } else { cg.hAlliedPlayerModelHandle = 0; - cg.pAlliedPlayerModel = 0; + cg.pAlliedPlayerModel = NULL; } - hModel = cgi.R_RegisterModel(szAxisModel); - if (!hModel) hModel = cgi.R_RegisterModel("models/player/german_wehrmacht_soldier.tik"); + hModel = cg.serverAxisModelValid ? cgi.R_RegisterModel(szAxisModel) : 0; + if (!hModel) { + Com_sprintf(szAxisModel, sizeof(szAxisModel), "models/player/%s.tik", dm_playergermanmodel->resetString); + hModel = cgi.R_RegisterModel(szAxisModel); + } if (hModel) { cg.hAxisPlayerModelHandle = hModel; - cg.pAxisPlayerModel = cgi.R_Model_GetHandle(hModel); + cg.pAxisPlayerModel = cgi.R_Model_GetHandle(hModel); if (!cg.pAxisPlayerModel) { cg.hAxisPlayerModelHandle = 0; } } else { cg.hAxisPlayerModelHandle = 0; - cg.pAxisPlayerModel = 0; + cg.pAxisPlayerModel = 0; } // Clear modified flag - dm_playermodel->modified = qfalse; - dm_playergermanmodel->modified = qfalse; + //dm_playermodel->modified = qfalse; + //dm_playergermanmodel->modified = qfalse; } +/* +=============== +CG_ProcessPlayerModel + +Checks player models, and update force models +=============== +*/ +void CG_ProcessPlayerModel() +{ + CG_CheckValidModels(); + if (cg_forceModel->integer) { + CG_UpdateForceModels(); + } + + // Clear modified flag + dm_playermodel->modified = qfalse; + dm_playergermanmodel->modified = qfalse; + cg_forceModel->modified = qfalse; +} + +/* +=============== +CG_ModelAnim +=============== +*/ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) { entityState_t *s1; @@ -431,7 +1007,6 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) int i; vec3_t vMins, vMaxs, vTmp; const char *szTagName; - static cvar_t *vmEntity = NULL; int iAnimFlags; s1 = ¢->currentState; @@ -443,10 +1018,6 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) memset(&model, 0, sizeof(model)); - if (!vmEntity) { - vmEntity = cgi.Cvar_Get("viewmodelanim", "1", 0); - } - if (cent->interpolate) { sNext = ¢->nextState; } @@ -568,8 +1139,8 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) model.tiki = cgi.R_Model_GetHandle(cgs.model_draw[s1->modelindex]); if (s1->number != cg.snap->ps.clientNum && (s1->eType == ET_PLAYER || (s1->eFlags & EF_DEAD))) { - if (cg_forceModel->integer) { - CG_UpdateForceModels(); + if (cg_forceModel->integer && cg_forceModelAllowed) { + //CG_UpdateForceModels(); if (s1->eFlags & EF_AXIS) { model.hModel = cg.hAxisPlayerModelHandle; @@ -593,9 +1164,9 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) if (!model.hModel || !model.tiki) { // Use a model in case it still doesn't exist if (s1->eFlags & EF_AXIS) { - model.hModel = cgi.R_RegisterModel("models/player/german_wehrmacht_soldier.tik"); + model.hModel = cgi.R_RegisterModel(CG_GetPlayerModelTiki(dm_playergermanmodel->resetString)); } else { - model.hModel = cgi.R_RegisterModel("models/player/american_army.tik"); + model.hModel = cgi.R_RegisterModel(CG_GetPlayerModelTiki(dm_playermodel->resetString)); } model.tiki = cgi.R_Model_GetHandle(model.hModel); model.hOldModel = cgs.model_draw[s1->modelindex]; @@ -614,103 +1185,7 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) model.renderfx |= s1->renderfx; cgi.TIKI_SetEyeTargetPos(model.tiki, model.entityNumber, s1->eyeVector); - if (sNext && sNext->usageIndex == s1->usageIndex) { - float t; - float animLength; - float t1, t2; - - t1 = cg.time - cg.snap->serverTime; - t2 = cg.nextSnap->serverTime - cg.snap->serverTime; - t = t1 / t2; - model.actionWeight = (sNext->actionWeight - s1->actionWeight) * t + s1->actionWeight; - - for (i = 0; i < MAX_FRAMEINFOS; i++) { - if (sNext->frameInfo[i].weight) { - model.frameInfo[i].index = sNext->frameInfo[i].index; - if (sNext->frameInfo[i].index == s1->frameInfo[i].index && s1->frameInfo[i].weight) { - model.frameInfo[i].weight = - (sNext->frameInfo[i].weight - s1->frameInfo[i].weight) * t + s1->frameInfo[i].weight; - - if (sNext->frameInfo[i].time >= s1->frameInfo[i].time) { - model.frameInfo[i].time = - (sNext->frameInfo[i].time - s1->frameInfo[i].time) * t + s1->frameInfo[i].time; - } else { - animLength = cgi.Anim_Time(model.tiki, sNext->frameInfo[i].index); - if (!animLength) { - t1 = 0.0; - } else { - t1 = (animLength + sNext->frameInfo[i].time - s1->frameInfo[i].time) * t - + s1->frameInfo[i].time; - } - - t2 = t1; - while (t2 > animLength) { - t2 -= animLength; - } - - model.frameInfo[i].time = t2; - } - } else { - animLength = cgi.Anim_Time(model.tiki, sNext->frameInfo[i].index); - if (!animLength) { - t1 = 0.0; - } else { - t1 = sNext->frameInfo[i].time - (cg.nextSnap->serverTime - cg.time) / 1000.0; - } - - t2 = t1; - if (t2 < 0.0) { - t2 = 0.0; - } - - model.frameInfo[i].time = t2; - model.frameInfo[i].weight = sNext->frameInfo[i].weight; - } - } else if (sNext->frameInfo[i].index == s1->frameInfo[i].index) { - animLength = cgi.Anim_Time(model.tiki, sNext->frameInfo[i].index); - if (!animLength) { - t1 = 0.0; - } else { - t1 = (cg.time - cg.snap->serverTime) / 1000.0 + s1->frameInfo[i].time; - } - - t2 = t1; - if (t2 < animLength) { - t2 = animLength; - } - - model.frameInfo[i].index = s1->frameInfo[i].index; - model.frameInfo[i].time = t2; - model.frameInfo[i].weight = (1.0 - t) * s1->frameInfo[i].weight; - } else { - model.frameInfo[i].index = -1; - model.frameInfo[i].weight = 0.0; - } - } - } else { - // no next state, don't blend anims - - model.actionWeight = s1->actionWeight; - for (i = 0; i < MAX_FRAMEINFOS; i++) { - if (s1->frameInfo[i].weight) { - model.frameInfo[i].index = s1->frameInfo[i].index; - model.frameInfo[i].time = s1->frameInfo[i].time; - model.frameInfo[i].weight = s1->frameInfo[i].weight; - } else { - model.frameInfo[i].index = -1; - model.frameInfo[i].weight = 0.0; - } - } - } - - if (vmEntity->integer == s1->number) { - static cvar_t *curanim; - if (!curanim) { - curanim = cgi.Cvar_Get("viewmodelanimslot", "1", 0); - } - - cgi.Cvar_Set("viewmodelanimclienttime", va("%0.2f", model.frameInfo[curanim->integer].time)); - } + CG_InterpolateAnimParms(s1, sNext, &model); if (cent->currentState.parent != ENTITYNUM_NONE) { int iTagNum; @@ -924,7 +1399,9 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) if (!cg.pLastPlayerWorldModel || cg.pLastPlayerWorldModel != model.tiki) { qhandle_t hModel; char fpsname[128]; + COM_StripExtension(model.tiki->a->name, fpsname, sizeof(fpsname)); + Q_strcat(fpsname, sizeof(fpsname), "_fps.tik"); hModel = cgi.R_RegisterModel(fpsname); if (hModel) { @@ -935,9 +1412,9 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) } } else { if (cg.snap->ps.stats[STAT_TEAM] == TEAM_AXIS) { - hModel = cgi.R_RegisterModel("models/player/german_wehrmacht_soldier_fps.tik"); + hModel = cgi.R_RegisterModel(CG_GetPlayerLocalModelTiki(dm_playergermanmodel->resetString)); } else { - hModel = cgi.R_RegisterModel("models/player/american_army_fps.tik"); + hModel = cgi.R_RegisterModel(CG_GetPlayerLocalModelTiki(dm_playermodel->resetString)); } if (hModel) { @@ -961,6 +1438,7 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) memset(model.surfaces, 0, sizeof(model.surfaces)); CG_ViewModelAnimation(&model); + model.renderfx |= RF_FRAMELERP; cgi.ForceUpdatePose(&model); if ((cent->currentState.eFlags & EF_UNARMED) || cg_drawviewmodel->integer <= 1 @@ -1057,7 +1535,12 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime) if (model.frameInfo[i].weight) { if (!((cent->animLastWeight >> i) & 1) || model.frameInfo[i].index != cent->animLast[i]) { CG_ProcessEntityCommands(TIKI_FRAME_ENTRY, model.frameInfo[i].index, s1->number, &model, cent); - cent->animLastTimes[i] = 0.0; + if (cent->animLastTimes[i] == -1) { + cent->animLast[i] = model.frameInfo[i].index; + cent->animLastTimes[i] = model.frameInfo[i].time; + } else { + cent->animLastTimes[i] = 0; + } } CG_ClientCommands(&model, cent, i); diff --git a/code/cgame/cg_nature.cpp b/code/cgame/cg_nature.cpp index 304f0906..c7a623c8 100644 --- a/code/cgame/cg_nature.cpp +++ b/code/cgame/cg_nature.cpp @@ -51,16 +51,16 @@ void RainTouch(ctempmodel_t *ct, trace_t *trace) void ClientGameCommandManager::RainTouch(Event *ev) { - // FIXME: unimplemented + // Nothing to do } void ClientGameCommandManager::InitializeRainCvars() { int i; - cg_rain = cgi.Cvar_Get("cg_rain", "0", CVAR_ARCHIVE); + cg_rain = cgi.Cvar_Get("cg_rain", "1", CVAR_ARCHIVE); cg_rain_drawcoverage = - cgi.Cvar_Get("cg_rain_drawcoverage", "0", CVAR_SAVEGAME | CVAR_SERVER_CREATED | CVAR_SYSTEMINFO); + cgi.Cvar_Get("cg_rain_drawcoverage", "0", CVAR_SAVEGAME | CVAR_RESETSTRING | CVAR_SYSTEMINFO); cg.rain.density = 0.0; cg.rain.speed = 2048.0f; diff --git a/code/cgame/cg_parsemsg.cpp b/code/cgame/cg_parsemsg.cpp index 6fad5ee6..fe723d77 100644 --- a/code/cgame/cg_parsemsg.cpp +++ b/code/cgame/cg_parsemsg.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_local.h" #include "cg_parsemsg.h" #include "cg_specialfx.h" +#include "cg_radar.h" #include "str.h" @@ -37,6 +38,7 @@ typedef struct { vec3_t *i_vEnd; int i_iNumBullets; qboolean iLarge; + float alpha; int iTracerVisible; qboolean bIgnoreEntities; } bullet_tracer_t; @@ -60,21 +62,22 @@ static vec3_t flesh_impact_pos[MAX_IMPACTS]; static vec3_t flesh_impact_norm[MAX_IMPACTS]; static int flesh_impact_large[MAX_IMPACTS]; -void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t* pPreTrace) { - - int iSurfType; - float fVolume; - str sSoundName; - vec3_t vFrom, vDest; +void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace) +{ + int iSurfType; + float fVolume; + str sSoundName; + vec3_t vFrom, vDest; trace_t trace; if (pPreTrace) { trace = *pPreTrace; - } - else { + } else { VectorMA(i_vPos, 2.0f, i_vNorm, vFrom); VectorMA(i_vPos, -4.0f, i_vNorm, vDest); - CG_Trace(&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"); + CG_Trace( + &trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole" + ); } iSurfType = trace.surfaceFlags & MASK_SURF_TYPE; @@ -82,7 +85,12 @@ void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarg iSurfType = SURF_PUDDLE; } - if (trace.fraction == 1.0f || trace.startsolid || (trace.surfaceFlags & SURF_SKY)) { + if (trace.fraction == 1) { + // no reason to make a sound if it nothing was hit + return; + } + + if ((trace.surfaceFlags & SURF_SKY) || !CG_CheckMakeMarkOnEntity(trace.entityNum)) { return; } @@ -149,55 +157,58 @@ void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarg commandManager.PlaySound(sSoundName, vFrom, -1, fVolume, -1.f, -1.f, 1); } -static void CG_MakeBulletHoleType(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound) { +static void CG_MakeBulletHoleType( + const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound +) +{ if (bMakeSound) { - str sBulletHole = "snd_bh_"; + str sBulletHole = "snd_bh_"; float fVolume; switch (iEffectNum) { - case 0: + case SFX_BHIT_PAPER_LITE: sBulletHole += "paper"; break; - case 2: + case SFX_BHIT_WOOD_LITE: sBulletHole += "wood"; break; - case 4: + case SFX_BHIT_METAL_LITE: sBulletHole += "metal"; break; - case 6: + case SFX_BHIT_STONE_LITE: sBulletHole += "stone"; break; - case 8: + case SFX_BHIT_DIRT_LITE: sBulletHole += "dirt"; break; - case 10: + case SFX_BHIT_GRILL_LITE: sBulletHole += "grill"; break; - case 12: + case SFX_BHIT_GRASS_LITE: sBulletHole += "grass"; break; - case 14: + case SFX_BHIT_MUD_LITE: sBulletHole += "mud"; break; - case 16: + case SFX_BHIT_PUDDLE_LITE: sBulletHole += "puddle"; break; - case 18: + case SFX_BHIT_GLASS_LITE: sBulletHole += "glass"; break; - case 20: + case SFX_BHIT_GRAVEL_LITE: sBulletHole += "gravel"; break; - case 22: + case SFX_BHIT_SAND_LITE: sBulletHole += "sand"; break; - case 24: + case SFX_BHIT_FOLIAGE_LITE: sBulletHole += "foliage"; break; - case 26: + case SFX_BHIT_SNOW_LITE: sBulletHole += "snow"; break; - case 28: + case SFX_BHIT_CARPET_LITE: sBulletHole += "carpet"; break; default: @@ -221,14 +232,15 @@ static void CG_MakeBulletHoleType(const vec3_t i_vPos, const vec3_t i_vNorm, int sfxManager.MakeEffect_Normal(iEffectNum, i_vPos, i_vNorm); } -static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound) +static void +CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound) { - int iSurfType; - int iEffect; - float fRadius; - str sEffectModel; - str sBulletHole; - vec3_t vFrom, vDest; + int iSurfType; + int iEffect; + float fRadius; + str sEffectModel; + str sBulletHole; + vec3_t vFrom, vDest; trace_t trace; if (pPreTrace) { @@ -236,7 +248,9 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa } else { VectorMA(i_vPos, 2.0f, i_vNorm, vFrom); VectorMA(i_vPos, -4.0f, i_vNorm, vDest); - CG_Trace(&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"); + CG_Trace( + &trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole" + ); } iSurfType = trace.surfaceFlags & MASK_SURF_TYPE; @@ -244,12 +258,17 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa iSurfType = SURF_PUDDLE; } - if (trace.fraction == 1.0f || trace.startsolid || (trace.surfaceFlags & SURF_SKY)) { + if (trace.fraction == 1.0f || trace.startsolid) { + return; + } + + if (trace.surfaceFlags & SURF_SKY) { + // ignore sky surfaces return; } VectorAdd(trace.endpos, trace.plane.normal, vFrom); - fRadius = 2.0f; + fRadius = 2.0f; sBulletHole = "bhole_"; switch (iSurfType) { @@ -259,7 +278,7 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa break; case SURF_SNOW: sBulletHole += "snow"; - iEffect = SFX_BHIT_FOLIAGE_LITE; + iEffect = SFX_BHIT_SNOW_LITE; break; case SURF_CARPET: sBulletHole += "carpet"; @@ -275,7 +294,7 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa break; case SURF_GLASS: sBulletHole += "glass"; - iEffect = SFX_BHIT_GRASS_LITE; + iEffect = SFX_BHIT_GLASS_LITE; break; case SURF_GRAVEL: fRadius = 0.f; @@ -347,36 +366,48 @@ static void CG_MakeBubbleTrail(const vec3_t i_vStart, const vec3_t i_vEnd, int i { vec3_t vDir; vec3_t vPos; - float fDist; - float fMove; + float fDist; + float fMove; VectorSubtract(i_vEnd, i_vStart, vDir); fDist = VectorNormalize(vDir); VectorCopy(i_vStart, vPos); - fMove = random() * 8.f; + fMove = random() * 8.f * alpha; fDist -= fMove; while (fDist > 0.f) { VectorMA(vPos, fMove, vDir, vPos); - sfxManager.MakeEffect_Angles(32, vPos, vec_zero); + sfxManager.MakeEffect_Angles(SFX_WATER_TRAIL_BUBBLE, vPos, vec_zero); - fMove = 16.f + crandom() * 8.f; + fMove = 16.f + crandom() * 8.f * alpha; fDist -= fMove; } } -static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd) +static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd, int iLarge, float alpha) { - int iLife; - int iTracerLength; - float fLength, fDist; + int iLife; + int iTracerLength; + float fLength, fDist; vec4_t fTracerColor; vec3_t vDir, vNewStart; + float alphaMult; + float scale; iTracerLength = 450.0f + random() * 150.f; VectorSubtract(i_vEnd, i_vStart, vDir); fLength = VectorNormalize(vDir); + + if (iLarge > 1) { + alphaMult = random() * 0.2f + 0.9f; + scale = iLarge * 2; + } else { + alphaMult = 1; + scale = 1; + } + fDist = 450.0f + random() * 150.f; + if (fLength < fDist + 150.f) { float fFrac; @@ -384,13 +415,15 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd) return; } - fFrac = fLength / (fDist + 150.0); + fFrac = fLength / (fDist + 150.0); iTracerLength = (int)((float)iTracerLength * fFrac + 0.5f); fDist *= fFrac; } - iLife = (int)((fLength - fDist) / 12000.f * 1000.f); - if (iLife < 20) iLife = 20; + iLife = (int)((fLength - fDist) / 12000.f * 1000.f / (alpha * alphaMult)); + if (iLife < 20) { + iLife = 20; + } VectorMA(i_vStart, fDist, vDir, vNewStart); fTracerColor[0] = 1.f; @@ -404,7 +437,7 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd) 0, 1, 1.0, - 1.0, + scale, BEAM_INVERTED, 1000.0, iLife, @@ -427,53 +460,55 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd) } static void CG_MakeBulletTracerInternal( - const vec3_t i_vBarrel, - const vec3_t i_vStart, - const vec3_t *i_vEnd, - int i_iNumBullets, - qboolean iLarge, - int iTracerVisible, - qboolean bIgnoreEntities + const vec3_t i_vBarrel, + const vec3_t i_vStart, + const vec3_t *i_vEnd, + int i_iNumBullets, + qboolean iLarge, + int iTracerVisible, + qboolean bIgnoreEntities, + float alpha ) { - vec3_t vPos; - int iBullet; - int iContinueCount; - int iDist; - int iHeadDist; - int iTravelDist; - float fLen, fDist; - trace_t trace; + vec3_t vPos; + int iBullet; + int iContinueCount; + int iDist; + int iHeadDist; + int iTravelDist; + float fLen, fDist; + trace_t trace; qboolean bStartInWater, bInWater; qboolean bBulletDone; qboolean bMadeTracer; - vec3_t vDir; - vec3_t vTrailStart; - vec3_t vTraceStart; - vec3_t vTraceEnd; - vec3_t vTmp; - int iNumImpacts; - trace_t tImpacts[128]; - float fImpSndDistRA; - static float fImpSndDistLA; - float fImpSndDistRB; - float fImpSndDistLB; - int iImpSndIndexRA; - int iImpSndIndexRB; - int iImpSndIndexLB; - float fVolume; - float fPitch; - float fZingDistA, fZingDistB, fZingDistC; - vec3_t vZingPosA, vZingPosB, vZingPosC; + vec3_t vDir; + vec3_t vTrailStart; + vec3_t vTraceStart; + vec3_t vTraceEnd; + vec3_t vTmp; + int iNumImpacts; + trace_t tImpacts[128]; + float fImpSndDistRA; + float fImpSndDistLA; + float fImpSndDistRB; + float fImpSndDistLB; + int iImpSndIndexRA; + int iImpSndIndexLA; + int iImpSndIndexRB; + int iImpSndIndexLB; + float fVolume; + float fPitch; + float fZingDistA, fZingDistB, fZingDistC; + vec3_t vZingPosA, vZingPosB, vZingPosC; - fZingDistB = 9999.0; - fZingDistA = 9999.0; - fZingDistC = 9999.0; + fZingDistB = 9999.0; + fZingDistA = 9999.0; + fZingDistC = 9999.0; iNumImpacts = 0; // check to see if it starts in water bStartInWater = (cgi.CM_PointContents(i_vStart, 0) & CONTENTS_FLUID) != 0; - + for (iBullet = 0; iBullet < i_iNumBullets; iBullet++) { bInWater = bStartInWater; VectorCopy(i_vBarrel, vTrailStart); @@ -481,8 +516,8 @@ static void CG_MakeBulletTracerInternal( fLen = VectorNormalize(vDir); trace.fraction = 0; - iDist = (int)fLen + 32; - bBulletDone = qfalse; + iDist = (int)fLen + 32; + bBulletDone = qfalse; iContinueCount = 0; if (bStartInWater) { @@ -501,8 +536,7 @@ static void CG_MakeBulletTracerInternal( if (iDist > BULLET_TRAVEL_DIST) { iTravelDist += BULLET_TRAVEL_DIST; iDist -= BULLET_TRAVEL_DIST; - } - else { + } else { iTravelDist += iDist; iDist = 0; } @@ -513,16 +547,7 @@ static void CG_MakeBulletTracerInternal( while (trace.fraction < 1) { if (bIgnoreEntities) { - cgi.CM_BoxTrace( - &trace, - vTraceStart, - vTraceEnd, - vec_zero, - vec_zero, - 0, - MASK_SHOT, - qfalse - ); + cgi.CM_BoxTrace(&trace, vTraceStart, vTraceEnd, vec_zero, vec_zero, 0, MASK_SHOT_FLUID, qfalse); if (trace.fraction == 1.0f) { trace.entityNum = ENTITYNUM_NONE; @@ -533,8 +558,7 @@ static void CG_MakeBulletTracerInternal( if (trace.startsolid) { trace.entityNum = ENTITYNUM_WORLD; } - } - else { + } else { CG_Trace( &trace, vTraceStart, @@ -542,7 +566,7 @@ static void CG_MakeBulletTracerInternal( vec_zero, vTraceStart, ENTITYNUM_NONE, - MASK_SHOT, + MASK_SHOT_FLUID, qfalse, qfalse, "CG_MakeBulletTracerInternal" @@ -552,52 +576,44 @@ static void CG_MakeBulletTracerInternal( if (trace.contents & CONTENTS_FLUID) { fDist = DotProduct(vDir, trace.plane.normal) * -2.0f; VectorMA(vDir, fDist, trace.plane.normal, vTmp); - VectorAdd(vTmp, vTmp, trace.plane.normal); + VectorMA(trace.plane.normal, 2.0, vTmp, trace.plane.normal); VectorNormalizeFast(trace.plane.normal); } - if (!bInWater && trace.fraction < 1.0f && iNumImpacts <= 127) - { + if (!bInWater && trace.fraction < 1.0f && iNumImpacts < ARRAY_LEN(tImpacts)) { memcpy(&tImpacts[iNumImpacts], &trace, sizeof(trace_t)); iNumImpacts++; } - if (iTracerVisible && !bMadeTracer) - { - CG_BulletTracerEffect(vTrailStart, trace.endpos); + if (iTracerVisible && !bMadeTracer) { + CG_BulletTracerEffect(vTrailStart, trace.endpos, iLarge, alpha); bMadeTracer = qtrue; } if (trace.fraction < 1.0f) { - if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT)) || (trace.contents & CONTENTS_WATER)) - && iContinueCount < 5) - { - if (bInWater) - { - VectorSubtract(trace.endpos, vDir, vTmp); - if (!(trace.contents & CONTENTS_FLUID) - && !(trace.surfaceFlags & SURF_PUDDLE) - && !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID)) - { - CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge); + if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT)) + || (trace.contents & CONTENTS_WATER)) + && iContinueCount < 5) { + if (bInWater) { + VectorMA(trace.endpos, -1.0, vDir, vTmp); + + if (!(trace.contents & CONTENTS_FLUID) && !(trace.surfaceFlags & SURF_PUDDLE) + && !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID)) { + CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge, alpha); VectorCopy(trace.endpos, vTrailStart); bInWater = qfalse; } - } - else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) { + } else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) { VectorCopy(trace.endpos, vTrailStart); bInWater = qtrue; } - VectorAdd(vDir, vDir, vTraceStart); - VectorAdd(vTraceStart, vTraceStart, trace.endpos); + VectorMA(trace.endpos, 2.0, vDir, vTraceStart); iContinueCount++; - } - else - { + } else { trace.fraction = 1.0f; - bBulletDone = qtrue; + bBulletDone = qtrue; } } } @@ -605,14 +621,14 @@ static void CG_MakeBulletTracerInternal( } if (bInWater) { - CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge); + CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge, alpha); } if (iTracerVisible) { iTracerVisible--; } - fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos); + fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos); iHeadDist = (int)Distance(vPos, cg.SoundOrg); if (iHeadDist > 255) { continue; @@ -629,7 +645,7 @@ static void CG_MakeBulletTracerInternal( if (fLen < 0.f) { VectorCopy(i_vStart, vPos); - } else if(fDist >= fLen) { + } else if (fDist >= fLen) { VectorCopy(i_vEnd[iBullet], vPos); } @@ -652,52 +668,48 @@ static void CG_MakeBulletTracerInternal( } if (iNumImpacts > 2) { - fImpSndDistRA = 9999.0f; - fImpSndDistRB = 9999.0f; + fImpSndDistRA = 9999.0f; + fImpSndDistRB = 9999.0f; + fImpSndDistLA = 9999.0f; + fImpSndDistLB = 9999.0f; iImpSndIndexRA = 0; + iImpSndIndexLA = 0; iImpSndIndexRB = 0; - fImpSndDistLB = 9999.0f; iImpSndIndexLB = 0; for (iBullet = 0; iBullet < iNumImpacts; iBullet++) { CG_MakeBulletHole( - tImpacts[iImpSndIndexLB].endpos, - tImpacts[iImpSndIndexLB].plane.normal, - iLarge, - &tImpacts[iImpSndIndexLB], - qfalse + tImpacts[iBullet].endpos, tImpacts[iBullet].plane.normal, iLarge, &tImpacts[iBullet], qfalse ); - VectorSubtract(tImpacts[iImpSndIndexLB].endpos, cg.SoundOrg, vTmp); + VectorSubtract(tImpacts[iBullet].endpos, cg.SoundOrg, vTmp); iHeadDist = VectorLength(vTmp); - if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f) - { - if (iHeadDist < 9999.0f || iHeadDist < fImpSndDistLB) { - if (iHeadDist < 9999.0f) { - fImpSndDistRA = iHeadDist; - fImpSndDistLB = 9999.0; + if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f) { + if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB) { + if (iHeadDist < fImpSndDistLA) { + iImpSndIndexLB = iImpSndIndexLA; + fImpSndDistLB = fImpSndDistLA; iImpSndIndexRA = iBullet; + fImpSndDistRA = iHeadDist; } else if (iHeadDist < fImpSndDistLB) { - fImpSndDistLB = iHeadDist; + iImpSndIndexLB = iBullet; + fImpSndDistLB = iHeadDist; } } - } - else - { - if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) - { + } else { + if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) { if (iHeadDist < fImpSndDistRA) { iImpSndIndexRB = iImpSndIndexRA; + fImpSndDistRB = fImpSndDistRA; iImpSndIndexRA = iBullet; + fImpSndDistRA = iHeadDist; } else if (iHeadDist < fImpSndDistRB) { - fImpSndDistRB = iHeadDist; iImpSndIndexRB = iBullet; + fImpSndDistRB = iHeadDist; } } } - - iImpSndIndexLB++; } if (fImpSndDistRA < 9999.0f) { @@ -717,14 +729,28 @@ static void CG_MakeBulletTracerInternal( ); } } + + if (fImpSndDistLA < 9999.0f) { + CG_MakeBulletHoleSound( + tImpacts[iImpSndIndexLA].endpos, + tImpacts[iImpSndIndexLA].plane.normal, + iLarge, + &tImpacts[iImpSndIndexLA] + ); + + if (fImpSndDistLB < 9999.0f) { + CG_MakeBulletHoleSound( + tImpacts[iImpSndIndexLB].endpos, + tImpacts[iImpSndIndexLB].plane.normal, + iLarge, + &tImpacts[iImpSndIndexLB] + ); + } + } } else { for (iBullet = 0; iBullet < iNumImpacts; iBullet++) { CG_MakeBulletHole( - tImpacts[iBullet].endpos, - tImpacts[iBullet].plane.normal, - iNumImpacts, - &tImpacts[iBullet], - qtrue + tImpacts[iBullet].endpos, tImpacts[iBullet].plane.normal, iNumImpacts, &tImpacts[iBullet], qtrue ); } } @@ -732,15 +758,21 @@ static void CG_MakeBulletTracerInternal( if (fZingDistA < 9999.0f) { if (iLarge) { fVolume = 1.0f; - fPitch = 0.8f; + fPitch = 0.8f; } else { fVolume = 0.8f; - fPitch = 1.0f; + fPitch = 1.0f; } commandManager.PlaySound("snd_b_zing", vZingPosA, -1, fVolume, -1.0f, fPitch, 1); - commandManager.PlaySound("snd_b_zing", vZingPosB, -1, fVolume, -1.0f, fPitch, 1); - commandManager.PlaySound("snd_b_zing", vZingPosC, -1, fVolume, -1.0f, fPitch, 1); + + if (fZingDistB != 9999) { + commandManager.PlaySound("snd_b_zing", vZingPosB, -1, fVolume, -1.0f, fPitch, 1); + + if (fZingDistC != 9999) { + commandManager.PlaySound("snd_b_zing", vZingPosC, -1, fVolume, -1.0f, fPitch, 1); + } + } } } @@ -774,13 +806,14 @@ static void CG_MakeBulletTracer( bullet_tracer->i_vEnd = &bullet_tracer_bullets[bullet_tracers_count]; bullet_tracer->i_iNumBullets = i_iNumBullets; - for (i = 0; i < i_iNumBullets; ++i) { - bullet_tracer_bullets[bullet_tracers_count][0] = (*i_vEnd)[i]; - bullet_tracer_bullets[bullet_tracers_count][1] = (*i_vEnd)[i + 1]; - bullet_tracer_bullets[bullet_tracers_count++][2] = (*i_vEnd)[i + 2]; + for (i = 0; i < i_iNumBullets; i++, bullet_tracers_count++) { + bullet_tracer_bullets[bullet_tracers_count][0] = i_vEnd[i][0]; + bullet_tracer_bullets[bullet_tracers_count][1] = i_vEnd[i][1]; + bullet_tracer_bullets[bullet_tracers_count][2] = i_vEnd[i][2]; } bullet_tracer->iLarge = iLarge; + bullet_tracer->alpha = alpha; bullet_tracer->iTracerVisible = iTracerVisible; bullet_tracer->bIgnoreEntities = bIgnoreEntities; } @@ -797,7 +830,8 @@ void CG_AddBulletTracers() bullet_tracers[i].i_iNumBullets, bullet_tracers[i].iLarge, bullet_tracers[i].iTracerVisible, - bullet_tracers[i].bIgnoreEntities + bullet_tracers[i].bIgnoreEntities, + bullet_tracers[i].alpha ); } @@ -807,26 +841,24 @@ void CG_AddBulletTracers() void CG_AddBulletImpacts() { - int i; - int iHeadDist; - float fVolume; - float fImpSndDistRA; + int i; + int iHeadDist; + float fVolume; + float fImpSndDistRA; static float fImpSndDistLA = 9999.f; - float fImpSndDistRB; - float fImpSndDistLB; - int iImpSndIndexRA; - int iImpSndIndexRB; - int iImpSndIndexLB; - vec3_t vTmp; - str sSoundName; + float fImpSndDistRB; + float fImpSndDistLB; + int iImpSndIndexRA; + int iImpSndIndexRB; + int iImpSndIndexLB; + vec3_t vTmp; + str sSoundName; - if (wall_impact_count) - { - if (wall_impact_count > 4) - { - fImpSndDistRA = fImpSndDistLA; - fImpSndDistRB = fImpSndDistLA; - fImpSndDistLB = fImpSndDistLA; + if (wall_impact_count) { + if (wall_impact_count > 4) { + fImpSndDistRA = fImpSndDistLA; + fImpSndDistRB = fImpSndDistLA; + fImpSndDistLB = fImpSndDistLA; iImpSndIndexRA = 0; iImpSndIndexRB = 0; iImpSndIndexLB = 0; @@ -834,33 +866,28 @@ void CG_AddBulletImpacts() for (i = 0; i < wall_impact_count; i++) { VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp); iHeadDist = VectorLength(vTmp); - - if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) - { - if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) - { + + if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) { + if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) { if (iHeadDist < fImpSndDistRA) { - fImpSndDistRB = fImpSndDistRA; - fImpSndDistRA = iHeadDist; + fImpSndDistRB = fImpSndDistRA; + fImpSndDistRA = iHeadDist; iImpSndIndexRB = iImpSndIndexRA; iImpSndIndexRA = i; } else if (iHeadDist < fImpSndDistRB) { - fImpSndDistRB = iHeadDist; + fImpSndDistRB = iHeadDist; iImpSndIndexRB = i; } } - } - else - { - if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB) - { + } else { + if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB) { if (iHeadDist < fImpSndDistLA) { - fImpSndDistRA = iHeadDist; - fImpSndDistLB = fImpSndDistLA; + fImpSndDistRA = iHeadDist; + fImpSndDistLB = fImpSndDistLA; iImpSndIndexLB = 0; iImpSndIndexRA = i; } else if (iHeadDist < fImpSndDistLB) { - fImpSndDistLB = iHeadDist; + fImpSndDistLB = iHeadDist; iImpSndIndexLB = i; } } @@ -868,14 +895,15 @@ void CG_AddBulletImpacts() } if (fImpSndDistRA < fImpSndDistLA) { - if (wall_impact_type[iImpSndIndexRA]) { + if (wall_impact_type[iImpSndIndexRA] != SFX_BHIT_PAPER_LITE) { if (wall_impact_large[iImpSndIndexRA]) { fVolume = 1.f; } else { fVolume = 0.75f; } - if (wall_impact_type[iImpSndIndexRA] == 2 || wall_impact_type[iImpSndIndexRA] == 3) { + if (wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_LITE + || wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_HARD) { sSoundName = "snd_bh_metal"; } else { sSoundName = "snd_bh_wood"; @@ -906,10 +934,10 @@ void CG_AddBulletImpacts() fVolume = 0.75f; } - if (wall_impact_type[iImpSndIndexRB] == 2 || wall_impact_type[iImpSndIndexRB] == 3) { + if (wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_LITE + || wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_HARD) { sSoundName = "snd_bh_metal"; - } - else { + } else { sSoundName = "snd_bh_wood"; } @@ -933,51 +961,39 @@ void CG_AddBulletImpacts() } if (fImpSndDistLA > 9999.0f) { - if (wall_impact_type[0]) { + if (wall_impact_type[0] != SFX_BHIT_PAPER_LITE) { if (wall_impact_large[0]) { fVolume = 1.f; } else { fVolume = 0.75f; } - if (wall_impact_type[0] == 2 || wall_impact_type[0] == 3) { + if (wall_impact_type[0] == SFX_BHIT_WOOD_LITE || wall_impact_type[0] == SFX_BHIT_WOOD_HARD) { sSoundName = "snd_bh_metal"; - } - else { + } else { sSoundName = "snd_bh_wood"; } commandManager.PlaySound(sSoundName, wall_impact_pos[0], -1, fVolume, -1, -1, 1); - sfxManager.MakeEffect_Normal( - wall_impact_type[0], - wall_impact_pos[0], - wall_impact_norm[0] - ); + sfxManager.MakeEffect_Normal(wall_impact_type[0], wall_impact_pos[0], wall_impact_norm[0]); } else { - CG_MakeBulletHole( - wall_impact_pos[0], - wall_impact_norm[0], - wall_impact_large[0], - NULL, - qtrue - ); + CG_MakeBulletHole(wall_impact_pos[0], wall_impact_norm[0], wall_impact_large[0], NULL, qtrue); } } if (fImpSndDistLB < fImpSndDistLA) { - if (wall_impact_type[iImpSndIndexLB]) { + if (wall_impact_type[iImpSndIndexLB] != SFX_BHIT_PAPER_LITE) { if (wall_impact_large[iImpSndIndexLB]) { fVolume = 1.f; - } - else { + } else { fVolume = 0.75f; } - if (wall_impact_type[iImpSndIndexLB] == 2 || wall_impact_type[iImpSndIndexLB] == 3) { + if (wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_LITE + || wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_HARD) { sSoundName = "snd_bh_metal"; - } - else { + } else { sSoundName = "snd_bh_wood"; } @@ -998,48 +1014,60 @@ void CG_AddBulletImpacts() ); } } - } - else - { + } else { for (i = 0; i < wall_impact_count; i++) { - CG_MakeBulletHole( - wall_impact_pos[i], - wall_impact_norm[i], - wall_impact_large[i], - NULL, - qtrue - ); + CG_MakeBulletHole(wall_impact_pos[i], wall_impact_norm[i], wall_impact_large[i], NULL, qtrue); } } wall_impact_count = 0; } - if (flesh_impact_count) - { - if (flesh_impact_count > 1) - { - fImpSndDistRA = 9999.0; + if (flesh_impact_count) { + if (flesh_impact_count > 1) { + fImpSndDistRA = 9999.0; + fImpSndDistRB = 9999.0; iImpSndIndexRA = 0; + iImpSndIndexRB = 0; for (i = 0; i < flesh_impact_count; i++) { - VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp); + VectorSubtract(flesh_impact_pos[i], cg.SoundOrg, vTmp); iHeadDist = VectorLength(vTmp); - - if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) - { - if (iHeadDist < fImpSndDistRA) - { - fImpSndDistRA = iHeadDist; + + if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) { + if (iHeadDist < fImpSndDistRB) { + fImpSndDistRA = iHeadDist; iImpSndIndexRA = i; } - } - else if (iHeadDist < fImpSndDistLA) - { - fImpSndDistRA = iHeadDist; + } else if (iHeadDist < fImpSndDistLA) { + fImpSndDistRA = iHeadDist; iImpSndIndexRA = i; } } + + if (fImpSndDistRA < 9999) { + sfxManager.MakeEffect_Normal( + flesh_impact_large[iImpSndIndexRA] ? SFX_BHIT_HUMAN_UNIFORM_HARD : SFX_BHIT_HUMAN_UNIFORM_LITE, + flesh_impact_pos[iImpSndIndexRA], + flesh_impact_norm[iImpSndIndexRA] + ); + } + + if (fImpSndDistRB < 9999) { + sfxManager.MakeEffect_Normal( + flesh_impact_large[iImpSndIndexRB] ? SFX_BHIT_HUMAN_UNIFORM_HARD : SFX_BHIT_HUMAN_UNIFORM_LITE, + flesh_impact_pos[iImpSndIndexRB], + flesh_impact_norm[iImpSndIndexRB] + ); + } + } else { + for (i = 0; i < flesh_impact_count; i++) { + sfxManager.MakeEffect_Normal( + flesh_impact_large[i] ? SFX_BHIT_HUMAN_UNIFORM_HARD : SFX_BHIT_HUMAN_UNIFORM_LITE, + flesh_impact_pos[i], + flesh_impact_norm[i] + ); + } } flesh_impact_count = 0; @@ -1068,22 +1096,33 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType) return; } - switch (iType) { - case 13: - iBaseEffect = SFX_EXP_GREN_BASE; - break; - case 14: - iBaseEffect = SFX_EXP_BAZOOKA_BASE; - break; - case 15: - iBaseEffect = SFX_EXP_HEAVYSHELL_BASE; - break; - case 16: - iBaseEffect = SFX_EXP_TANK_BASE; - break; - default: - iBaseEffect = SFX_EXP_GREN_BASE; - break; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + switch (iType) { + case CGM_EXPLOSION_EFFECT_1: + iBaseEffect = SFX_EXP_GREN_BASE; + break; + case CGM_EXPLOSION_EFFECT_2: + iBaseEffect = SFX_EXP_BAZOOKA_BASE; + break; + case CGM_EXPLOSION_EFFECT_3: + iBaseEffect = SFX_EXP_HEAVYSHELL_BASE; + break; + case CGM_EXPLOSION_EFFECT_4: + iBaseEffect = SFX_EXP_TANK_BASE; + break; + default: + iBaseEffect = SFX_EXP_GREN_BASE; + break; + } + } else { + switch (iType) { + case CGM6_EXPLOSION_EFFECT_2: + iBaseEffect = SFX_EXP_BAZOOKA_BASE; + break; + default: + iBaseEffect = SFX_EXP_GREN_BASE; + break; + } } CG_Trace( @@ -1105,24 +1144,27 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType) fRadius = 0; break; case SURF_SNOW: - switch (iBaseEffect) - { + switch (iBaseEffect) { case SFX_EXP_TANK_BASE: iSurfEffect = SFX_EXP_TANK_SNOW; break; case SFX_EXP_BAZOOKA_BASE: iSurfEffect = SFX_EXP_BAZOOKA_SNOW; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; case SFX_EXP_HEAVYSHELL_BASE: iSurfEffect = SFX_EXP_HEAVYSHELL_SNOW; break; default: iSurfEffect = SFX_EXP_GREN_SNOW; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; } - fRadius = 0; + fRadius = 0; break; case SURF_CARPET: iSurfEffect = SFX_EXP_GREN_CARPET; @@ -1147,32 +1189,34 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType) fRadius = 0; break; case SURF_DIRT: - switch (iBaseEffect) - { + switch (iBaseEffect) { case SFX_EXP_TANK_BASE: iSurfEffect = SFX_EXP_TANK_DIRT; break; case SFX_EXP_BAZOOKA_BASE: iSurfEffect = SFX_EXP_BAZOOKA_DIRT; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; case SFX_EXP_HEAVYSHELL_BASE: iSurfEffect = SFX_EXP_HEAVYSHELL_DIRT; break; default: iSurfEffect = SFX_EXP_GREN_DIRT; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; } - fRadius = 0; + fRadius = 0; break; case SURF_GRILL: iSurfEffect = SFX_EXP_GREN_GRILL; fRadius = 0; break; case SURF_GRASS: - switch (iBaseEffect) - { + switch (iBaseEffect) { case SFX_EXP_TANK_BASE: iSurfEffect = SFX_EXP_TANK_DIRT; break; @@ -1184,27 +1228,32 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType) break; default: iSurfEffect = SFX_EXP_GREN_GRASS; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; } fRadius = 0; break; case SURF_ROCK: - switch (iBaseEffect) - { + switch (iBaseEffect) { case SFX_EXP_TANK_BASE: iSurfEffect = SFX_EXP_TANK_STONE; break; case SFX_EXP_BAZOOKA_BASE: iSurfEffect = SFX_EXP_BAZOOKA_STONE; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; case SFX_EXP_HEAVYSHELL_BASE: iSurfEffect = SFX_EXP_HEAVYSHELL_STONE; break; default: iSurfEffect = SFX_EXP_GREN_STONE; - iBaseEffect = -1; + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + iBaseEffect = -1; + } break; } break; @@ -1252,7 +1301,9 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType) ); } - sfxManager.MakeEffect_Normal(iBaseEffect, vEnd, trace.plane.normal); + if (iBaseEffect != -1) { + sfxManager.MakeEffect_Normal(iBaseEffect, vEnd, trace.plane.normal); + } } void CG_MakeVehicleEffect(vec3_t i_vStart, vec3_t i_vEnd, vec3_t i_vDir) @@ -1288,10 +1339,10 @@ void CG_ParseCGMessage_ver_15() iType = cgi.MSG_ReadBits(6); switch (iType) { - case 1: - case 2: - case 5: - if (iType == 1) { + case CGM_BULLET_1: + case CGM_BULLET_2: + case CGM_BULLET_5: + if (iType == CGM_BULLET_1) { vTmp[0] = cgi.MSG_ReadCoord(); vTmp[1] = cgi.MSG_ReadCoord(); vTmp[2] = cgi.MSG_ReadCoord(); @@ -1300,7 +1351,7 @@ void CG_ParseCGMessage_ver_15() vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); - if (iType != 1) { + if (iType != CGM_BULLET_1) { vTmp[0] = vStart[0]; vTmp[1] = vStart[1]; vTmp[2] = vStart[2]; @@ -1320,18 +1371,18 @@ void CG_ParseCGMessage_ver_15() alpha = 1.0f; } - if (iType == 1) { - CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha); - } else if (iType == 2) { + if (iType == CGM_BULLET_1) { + CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha); + } else if (iType == CGM_BULLET_2) { CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha); } else { CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge, alpha); } break; - case 3: - case 4: - if (iType == 3) { + case CGM_BULLET_3: + case CGM_BULLET_4: + if (iType == CGM_BULLET_3) { vTmp[0] = cgi.MSG_ReadCoord(); vTmp[1] = cgi.MSG_ReadCoord(); vTmp[2] = cgi.MSG_ReadCoord(); @@ -1365,12 +1416,12 @@ void CG_ParseCGMessage_ver_15() CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue, alpha); } break; - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: + case CGM_BULLET_6: + case CGM_BULLET_7: + case CGM_BULLET_8: + case CGM_BULLET_9: + case CGM_BULLET_10: + case CGM_BULLET_11: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); @@ -1378,7 +1429,7 @@ void CG_ParseCGMessage_ver_15() iLarge = cgi.MSG_ReadBits(2); switch (iType) { - case 6: + case CGM_BULLET_6: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); @@ -1387,16 +1438,16 @@ void CG_ParseCGMessage_ver_15() wall_impact_count++; } break; - case 7: + case CGM_BULLET_7: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); wall_impact_large[wall_impact_count] = iLarge; - wall_impact_type[wall_impact_count] = 6; + wall_impact_type[wall_impact_count] = SFX_BHIT_STONE_LITE; wall_impact_count++; } break; - case 8: + case CGM_BULLET_8: if (flesh_impact_count < MAX_IMPACTS) { // negative VectorNegate(vEnd, vEnd); @@ -1406,7 +1457,7 @@ void CG_ParseCGMessage_ver_15() flesh_impact_count++; } break; - case 9: + case CGM_BULLET_9: if (flesh_impact_count < MAX_IMPACTS) { // negative VectorNegate(vEnd, vEnd); @@ -1416,21 +1467,21 @@ void CG_ParseCGMessage_ver_15() flesh_impact_count++; } break; - case 10: + case CGM_BULLET_10: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); wall_impact_large[wall_impact_count] = iLarge; - wall_impact_type[wall_impact_count] = 2; + wall_impact_type[wall_impact_count] = SFX_BHIT_WOOD_LITE; wall_impact_count++; } break; - case 11: + case CGM_BULLET_11: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); wall_impact_large[wall_impact_count] = iLarge; - wall_impact_type[wall_impact_count] = 4; + wall_impact_type[wall_impact_count] = SFX_BHIT_METAL_LITE; wall_impact_count++; } break; @@ -1439,7 +1490,7 @@ void CG_ParseCGMessage_ver_15() } break; - case 12: + case CGM_MELEE_IMPACT: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); @@ -1448,33 +1499,33 @@ void CG_ParseCGMessage_ver_15() vEnd[2] = cgi.MSG_ReadCoord(); CG_MeleeImpact(vStart, vEnd); break; - case 13: - case 14: - case 15: - case 16: + case CGM_EXPLOSION_EFFECT_1: + case CGM_EXPLOSION_EFFECT_2: + case CGM_EXPLOSION_EFFECT_3: + case CGM_EXPLOSION_EFFECT_4: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); CG_MakeExplosionEffect(vStart, iType); break; - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: + case CGM_MAKE_EFFECT_1: + case CGM_MAKE_EFFECT_2: + case CGM_MAKE_EFFECT_3: + case CGM_MAKE_EFFECT_4: + case CGM_MAKE_EFFECT_5: + case CGM_MAKE_EFFECT_6: + case CGM_MAKE_EFFECT_7: + case CGM_MAKE_EFFECT_8: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); cgi.MSG_ReadDir(vEnd); - sfxManager.MakeEffect_Normal(iType + SFX_EXP_GREN_PUDDLE, vStart, vEnd); + sfxManager.MakeEffect_Normal((iType - CGM_MAKE_EFFECT_1) + SFX_OIL_LEAK_BIG, vStart, vEnd); break; - case 26: - case 27: + case CGM_MAKE_CRATE_DEBRIS: + case CGM_MAKE_WINDOW_DEBRIS: { str sEffect; char cTmp[8]; @@ -1487,7 +1538,7 @@ void CG_ParseCGMessage_ver_15() // get the integer as string snprintf(cTmp, sizeof(cTmp), "%d", iLarge); - if (iType == 26) { + if (iType == CGM_MAKE_CRATE_DEBRIS) { sEffect = "models/fx/crates/debris_"; } else { sEffect = "models/fx/windows/debris_"; @@ -1504,7 +1555,7 @@ void CG_ParseCGMessage_ver_15() } break; - case 28: + case CGM_BULLET_NO_BARREL_1: vTmp[0] = cgi.MSG_ReadCoord(); vTmp[1] = cgi.MSG_ReadCoord(); vTmp[2] = cgi.MSG_ReadCoord(); @@ -1515,6 +1566,7 @@ void CG_ParseCGMessage_ver_15() vEndArray[0][1] = cgi.MSG_ReadCoord(); vEndArray[0][2] = cgi.MSG_ReadCoord(); iLarge = cgi.MSG_ReadBits(2); + if (cgi.MSG_ReadBits(1)) { int iAlpha = cgi.MSG_ReadBits(10); alpha = (float)iAlpha / 512.0; @@ -1528,7 +1580,7 @@ void CG_ParseCGMessage_ver_15() CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha); break; - case 29: + case CGM_BULLET_NO_BARREL_2: memset(vTmp, 0, sizeof(vTmp)); vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); @@ -1537,6 +1589,7 @@ void CG_ParseCGMessage_ver_15() vEndArray[0][1] = cgi.MSG_ReadCoord(); vEndArray[0][2] = cgi.MSG_ReadCoord(); iLarge = cgi.MSG_ReadBits(1); + if (cgi.MSG_ReadBits(1)) { int iAlpha = cgi.MSG_ReadBits(10); alpha = (float)iAlpha / 512.0; @@ -1550,9 +1603,13 @@ void CG_ParseCGMessage_ver_15() CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha); break; - case 30: + case CGM_HUDDRAW_SHADER: iInfo = cgi.MSG_ReadByte(); - strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString()); + Q_strncpyz( + cgi.HudDrawElements[iInfo].shaderName, + cgi.MSG_ReadString(), + sizeof(cgi.HudDrawElements[iInfo].shaderName) + ); cgi.HudDrawElements[iInfo].string[0] = 0; cgi.HudDrawElements[iInfo].pFont = NULL; cgi.HudDrawElements[iInfo].fontName[0] = 0; @@ -1560,13 +1617,13 @@ void CG_ParseCGMessage_ver_15() CG_HudDrawShader(iInfo); break; - case 31: + case CGM_HUDDRAW_ALIGN: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2); cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2); break; - case 32: + case CGM_HUDDRAW_RECT: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort(); cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort(); @@ -1574,46 +1631,52 @@ void CG_ParseCGMessage_ver_15() cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort(); break; - case 33: + case CGM_HUDDRAW_VIRTUALSIZE: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1); break; - case 34: + case CGM_HUDDRAW_COLOR: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0; cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0; cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0; break; - case 35: + case CGM_HUDDRAW_ALPHA: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0; break; - case 36: + case CGM_HUDDRAW_STRING: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].hShader = 0; - strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString()); + Q_strncpyz( + cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].string) + ); break; - case 37: + case CGM_HUDDRAW_FONT: iInfo = cgi.MSG_ReadByte(); - strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString()); + Q_strncpyz( + cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].fontName) + ); cgi.HudDrawElements[iInfo].hShader = 0; cgi.HudDrawElements[iInfo].shaderName[0] = 0; // load the font CG_HudDrawFont(iInfo); break; - case 38: - case 39: - { - int iOldEnt; + case CGM_NOTIFY_HIT: + case CGM_NOTIFY_KILL: + if (cg.snap) { + const char *soundName; + int iOldEnt; + + iOldEnt = current_entity_number; - iOldEnt = current_entity_number; current_entity_number = cg.snap->ps.clientNum; - if (iType == 36) { + if (iType == CGM_NOTIFY_KILL) { commandManager.PlaySound("dm_kill_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1); } else { commandManager.PlaySound("dm_hit_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1); @@ -1623,7 +1686,7 @@ void CG_ParseCGMessage_ver_15() } break; - case 40: + case CGM_VOICE_CHAT: { int iOldEnt; @@ -1639,29 +1702,58 @@ void CG_ParseCGMessage_ver_15() if (iLarge) { current_entity_number = iInfo; - commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 0); - } else { + commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 0); + } else if (cg.snap) { current_entity_number = cg.snap->ps.clientNum; - commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 1); + commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 1); } + CG_RadarClientSpeaks(iInfo); current_entity_number = iOldEnt; } break; - case 41: - vStart[0] = cgi.MSG_ReadCoord(); - vStart[1] = cgi.MSG_ReadCoord(); - vStart[2] = cgi.MSG_ReadCoord(); - vEnd[0] = cgi.MSG_ReadCoord(); - vEnd[1] = cgi.MSG_ReadCoord(); - vEnd[2] = cgi.MSG_ReadCoord(); - cgi.MSG_ReadByte(); - cgi.MSG_ReadByte(); - VectorSubtract(vEnd, vStart, vTmp); + case CGM_FENCEPOST: + { + int iHalf; + vec3_t vForward, vRight, vUp; + float fLength; - // FIXME: unimplemented - // ?? can't figure out what is this + vStart[0] = cgi.MSG_ReadCoord(); + vStart[1] = cgi.MSG_ReadCoord(); + vStart[2] = cgi.MSG_ReadCoord(); + vEnd[0] = cgi.MSG_ReadCoord(); + vEnd[1] = cgi.MSG_ReadCoord(); + vEnd[2] = cgi.MSG_ReadCoord(); + iHalf = cgi.MSG_ReadByte(); + cgi.MSG_ReadByte(); + + VectorSubtract(vEnd, vStart, vForward); + fLength = VectorNormalize(vForward); + iCount = fLength / 2.0; + + MakeNormalVectors(vForward, vRight, vUp); + + for (i = 0; i < iCount; i++) { + vec3_t vOrg; + vec3_t vNormal; + + VectorCopy(vStart, vOrg); + + VectorMA(vOrg, random(), vForward, vOrg); + VectorMA(vOrg, crandom() * iHalf, vRight, vOrg); + VectorMA(vOrg, crandom() * iHalf, vUp, vOrg); + + // + // Spawn the fence wood effect + // + + VectorSubtract(vStart, vOrg, vNormal); + VectorNormalize(vNormal); + + sfxManager.MakeEffect_Normal(SFX_FENCE_WOOD, vOrg, vNormal); + } + } break; default: cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type"); @@ -1688,10 +1780,10 @@ void CG_ParseCGMessage_ver_6() iType = cgi.MSG_ReadBits(6); switch (iType) { - case 1: - case 2: - case 5: - if (iType == 1) { + case CGM6_BULLET_1: + case CGM6_BULLET_2: + case CGM6_BULLET_5: + if (iType == CGM6_BULLET_1) { vTmp[0] = cgi.MSG_ReadCoord(); vTmp[1] = cgi.MSG_ReadCoord(); vTmp[2] = cgi.MSG_ReadCoord(); @@ -1700,7 +1792,7 @@ void CG_ParseCGMessage_ver_6() vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); - if (iType != 1) { + if (iType != CGM6_BULLET_1) { vTmp[0] = vStart[0]; vTmp[1] = vStart[1]; vTmp[2] = vStart[2]; @@ -1711,18 +1803,18 @@ void CG_ParseCGMessage_ver_6() vEndArray[0][2] = cgi.MSG_ReadCoord(); iLarge = cgi.MSG_ReadBits(1); - if (iType == 1) { - CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue); - } else if (iType == 2) { + if (iType == CGM6_BULLET_1) { + CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue); + } else if (iType == CGM6_BULLET_2) { CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue); } else { CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge); } break; - case 3: - case 4: - if (iType == 3) { + case CGM6_BULLET_3: + case CGM6_BULLET_4: + if (iType == CGM6_BULLET_3) { vTmp[0] = cgi.MSG_ReadCoord(); vTmp[1] = cgi.MSG_ReadCoord(); vTmp[2] = cgi.MSG_ReadCoord(); @@ -1746,11 +1838,11 @@ void CG_ParseCGMessage_ver_6() CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue); } break; - case 6: - case 7: - case 8: - case 9: - case 10: + case CGM6_BULLET_6: + case CGM6_BULLET_7: + case CGM6_BULLET_8: + case CGM6_BULLET_9: + case CGM6_BULLET_10: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); @@ -1758,16 +1850,16 @@ void CG_ParseCGMessage_ver_6() iLarge = cgi.MSG_ReadBits(1); switch (iType) { - case 6: + case CGM6_BULLET_6: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); wall_impact_large[wall_impact_count] = iLarge; - wall_impact_type[wall_impact_count] = 0; + wall_impact_type[wall_impact_count] = SFX_BHIT_PAPER_LITE; wall_impact_count++; } break; - case 7: + case CGM6_BULLET_7: if (flesh_impact_count < MAX_IMPACTS) { // negative VectorNegate(vEnd, vEnd); @@ -1777,7 +1869,7 @@ void CG_ParseCGMessage_ver_6() flesh_impact_count++; } break; - case 8: + case CGM6_BULLET_8: if (flesh_impact_count < MAX_IMPACTS) { // negative VectorNegate(vEnd, vEnd); @@ -1787,21 +1879,21 @@ void CG_ParseCGMessage_ver_6() flesh_impact_count++; } break; - case 9: + case CGM6_BULLET_9: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); wall_impact_large[wall_impact_count] = iLarge; - wall_impact_type[wall_impact_count] = (iLarge != 0) + 2; + wall_impact_type[wall_impact_count] = iLarge ? SFX_BHIT_WOOD_HARD : SFX_BHIT_WOOD_LITE; wall_impact_count++; } break; - case 10: + case CGM6_BULLET_10: if (wall_impact_count < MAX_IMPACTS) { VectorCopy(vStart, wall_impact_pos[wall_impact_count]); VectorCopy(vEnd, wall_impact_norm[wall_impact_count]); wall_impact_large[wall_impact_count] = iLarge; - wall_impact_type[wall_impact_count] = (iLarge != 0) + 4; + wall_impact_type[wall_impact_count] = iLarge ? SFX_BHIT_METAL_HARD : SFX_BHIT_METAL_LITE; wall_impact_count++; } break; @@ -1810,7 +1902,7 @@ void CG_ParseCGMessage_ver_6() } break; - case 11: + case CGM6_MELEE_IMPACT: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); @@ -1819,31 +1911,31 @@ void CG_ParseCGMessage_ver_6() vEnd[2] = cgi.MSG_ReadCoord(); CG_MeleeImpact(vStart, vEnd); break; - case 12: - case 13: + case CGM6_EXPLOSION_EFFECT_1: + case CGM6_EXPLOSION_EFFECT_2: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); CG_MakeExplosionEffect(vStart, iType); break; - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: + case CGM6_MAKE_EFFECT_1: + case CGM6_MAKE_EFFECT_2: + case CGM6_MAKE_EFFECT_3: + case CGM6_MAKE_EFFECT_4: + case CGM6_MAKE_EFFECT_5: + case CGM6_MAKE_EFFECT_6: + case CGM6_MAKE_EFFECT_7: + case CGM6_MAKE_EFFECT_8: vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); vStart[2] = cgi.MSG_ReadCoord(); cgi.MSG_ReadDir(vEnd); - sfxManager.MakeEffect_Normal(iType + SFX_EXP_GREN_PUDDLE, vStart, vEnd); + sfxManager.MakeEffect_Normal((iType - CGM6_MAKE_EFFECT_1) + SFX_OIL_LEAK_BIG, vStart, vEnd); break; - case 23: - case 24: + case CGM6_MAKE_CRATE_DEBRIS: + case CGM6_MAKE_WINDOW_DEBRIS: { str sEffect; char cTmp[8]; @@ -1856,7 +1948,7 @@ void CG_ParseCGMessage_ver_6() // get the integer as string snprintf(cTmp, sizeof(cTmp), "%d", iLarge); - if (iType == 23) { + if (iType == CGM6_MAKE_CRATE_DEBRIS) { sEffect = "models/fx/crates/debris_"; } else { sEffect = "models/fx/windows/debris_"; @@ -1873,7 +1965,7 @@ void CG_ParseCGMessage_ver_6() } break; - case 25: + case CGM6_BULLET_NO_BARREL_1: vTmp[0] = cgi.MSG_ReadCoord(); vTmp[1] = cgi.MSG_ReadCoord(); vTmp[2] = cgi.MSG_ReadCoord(); @@ -1888,7 +1980,7 @@ void CG_ParseCGMessage_ver_6() CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue); break; - case 26: + case CGM6_BULLET_NO_BARREL_2: memset(vTmp, 0, sizeof(vTmp)); vStart[0] = cgi.MSG_ReadCoord(); vStart[1] = cgi.MSG_ReadCoord(); @@ -1901,9 +1993,13 @@ void CG_ParseCGMessage_ver_6() CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue); break; - case 27: + case CGM6_HUDDRAW_SHADER: iInfo = cgi.MSG_ReadByte(); - strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString()); + Q_strncpyz( + cgi.HudDrawElements[iInfo].shaderName, + cgi.MSG_ReadString(), + sizeof(cgi.HudDrawElements[iInfo].shaderName) + ); cgi.HudDrawElements[iInfo].string[0] = 0; cgi.HudDrawElements[iInfo].pFont = NULL; cgi.HudDrawElements[iInfo].fontName[0] = 0; @@ -1911,13 +2007,13 @@ void CG_ParseCGMessage_ver_6() CG_HudDrawShader(iInfo); break; - case 28: + case CGM6_HUDDRAW_ALIGN: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2); cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2); break; - case 29: + case CGM6_HUDDRAW_RECT: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort(); cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort(); @@ -1925,46 +2021,51 @@ void CG_ParseCGMessage_ver_6() cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort(); break; - case 30: + case CGM6_HUDDRAW_VIRTUALSIZE: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1); break; - case 31: + case CGM6_HUDDRAW_COLOR: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0; cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0; cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0; break; - case 32: + case CGM6_HUDDRAW_ALPHA: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0; break; - case 33: + case CGM6_HUDDRAW_STRING: iInfo = cgi.MSG_ReadByte(); cgi.HudDrawElements[iInfo].hShader = 0; - strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString()); + Q_strncpyz( + cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].string) + ); break; - case 34: + case CGM6_HUDDRAW_FONT: iInfo = cgi.MSG_ReadByte(); - strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString()); + Q_strncpyz( + cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].fontName) + ); cgi.HudDrawElements[iInfo].hShader = 0; cgi.HudDrawElements[iInfo].shaderName[0] = 0; // load the font CG_HudDrawFont(iInfo); break; - case 35: - case 36: - { + case CGM6_NOTIFY_HIT: + case CGM6_NOTIFY_KILL: + if (cg.snap) { int iOldEnt; - iOldEnt = current_entity_number; + iOldEnt = current_entity_number; + current_entity_number = cg.snap->ps.clientNum; - if (iType == 36) { + if (iType == CGM6_NOTIFY_KILL) { commandManager.PlaySound("dm_kill_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1); } else { commandManager.PlaySound("dm_hit_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1); @@ -1974,7 +2075,7 @@ void CG_ParseCGMessage_ver_6() } break; - case 37: + case CGM6_VOICE_CHAT: { int iOldEnt; @@ -1991,10 +2092,10 @@ void CG_ParseCGMessage_ver_6() current_entity_number = iInfo; commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 0); - } else { + } else if (cg.snap) { current_entity_number = cg.snap->ps.clientNum; - commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 1); + commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 1); } current_entity_number = iOldEnt; diff --git a/code/cgame/cg_predict.c b/code/cgame/cg_predict.c index 7fc43553..4eeb4ac1 100644 --- a/code/cgame/cg_predict.c +++ b/code/cgame/cg_predict.c @@ -25,6 +25,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // interpolating between snapshots from the server or locally predicting // ahead the client's movement. It also handles local physics interaction, // like fragments bouncing off walls +// +// ADDITIONS: +// - CG_InterpolatePlayerState() footer: Interpolate the lean angles #include "cg_local.h" @@ -187,8 +190,9 @@ void CG_ShowTrace(trace_t *trace, int passent, const char *reason) assert(reason); assert(trace); - sprintf( + Com_sprintf( text, + sizeof(text), "%0.2f : Pass (%d) Frac %f Hit (%d): '%s'\n", (float)cg.time / 1000.0f, passent, @@ -326,8 +330,18 @@ static void CG_InterpolatePlayerStateCamera(void) // VectorCopy(cg.predicted_player_state.camera_angles, cg.camera_angles); VectorCopy(cg.predicted_player_state.camera_origin, cg.camera_origin); - cg.camera_fov = cg.predicted_player_state.fov; + // + // Added in OPM + // Use the specified fov specified by the server + // when zooming + // + if (cg.predicted_player_state.stats[STAT_INZOOM]) { + cg.camera_fov = cg.predicted_player_state.fov; + } else { + cg.camera_fov = cg_fov->value; + } + // if the next frame is a teleport, we can't lerp to it if (cg.nextFrameCameraCut) { return; @@ -339,13 +353,24 @@ static void CG_InterpolatePlayerStateCamera(void) f = (float)(cg.time - prev->serverTime) / (next->serverTime - prev->serverTime); - // interpolate fov - cg.camera_fov = prev->ps.fov + f * (next->ps.fov - prev->ps.fov); + if (cg.predicted_player_state.stats[STAT_INZOOM]) { + // interpolate fov + cg.camera_fov = prev->ps.fov + f * (next->ps.fov - prev->ps.fov); + } else { + cg.camera_fov = cg_fov->value; + } if (!(cg.snap->ps.pm_flags & PMF_CAMERA_VIEW)) { return; } + // Added in 2.0 + if (cg.predicted_player_state.camera_flags & CF_CAMERA_ANGLES_TURRETMODE) { + VectorCopy(cg.nextSnap->ps.camera_origin, cg.camera_origin); + VectorCopy(cg.nextSnap->ps.camera_angles, cg.camera_angles); + return; + } + for (i = 0; i < 3; i++) { cg.camera_origin[i] = prev->ps.camera_origin[i] + f * (next->ps.camera_origin[i] - prev->ps.camera_origin[i]); cg.camera_angles[i] = LerpAngle(prev->ps.camera_angles[i], next->ps.camera_angles[i], f); @@ -405,6 +430,9 @@ static void CG_InterpolatePlayerState(qboolean grabAngles) } out->velocity[i] = prev->ps.velocity[i] + f * (next->ps.velocity[i] - prev->ps.velocity[i]); } + + // interpolate the lean angle + out->fLeanAngle = LerpAngle(prev->ps.fLeanAngle, next->ps.fLeanAngle, f); } /* @@ -487,8 +515,13 @@ void CG_PredictPlayerState(void) cg_pmove.leanSpeed = 2.f; } else { cg_pmove.alwaysAllowLean = qtrue; + if (cgs.gametype != GT_SINGLE_PLAYER) { + cg_pmove.leanMax = 40.f; + } else { + // Don't allow lean in single-player, like in the original game + cg_pmove.leanMax = 0; + } - cg_pmove.leanMax = 40.f; cg_pmove.leanAdd = 10.f; cg_pmove.leanRecoverSpeed = 15.f; cg_pmove.leanSpeed = 4.f; @@ -509,7 +542,11 @@ void CG_PredictPlayerState(void) // the server time is beyond our current cg.time, // because predicted player positions are going to // be ahead of everything else anyway - if (cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport) { + // Added in OPM: prediction check + // Don't use the next snapshot if the prediction is about to be disabled + // this prevent "blinking" issues like when entering a vehicle turret gun + // where arms would be seen shortly + if (cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport && !(cg.nextSnap->ps.pm_flags & PMF_NO_PREDICTION)) { cg.predicted_player_state = cg.nextSnap->ps; cg.physicsTime = cg.nextSnap->serverTime; } else { diff --git a/code/cgame/cg_public.h b/code/cgame/cg_public.h index 4aeda9cf..4e5de840 100644 --- a/code/cgame/cg_public.h +++ b/code/cgame/cg_public.h @@ -120,7 +120,9 @@ functions exported to the main executable // console variable interaction cvar_t *(*Cvar_Get)(const char *var_name, const char *value, int flags); + cvar_t *(*Cvar_Find)(const char *var_name); void (*Cvar_Set)(const char *var_name, const char *value); + void (*Cvar_CheckRange)(cvar_t* var, float min, float max, qboolean integral); // ClientCommand and ConsoleCommand parameter access int (*Argc)(void); @@ -137,6 +139,8 @@ functions exported to the main executable void (*FS_FreeFile)(void *buf); int (*FS_WriteFile)(const char *qpath, const void *buffer, int size); void (*FS_WriteTextFile)(const char *qpath, const void *buffer, int size); + char** (*FS_ListFilteredFiles)(const char* path, const char* extension, const char* filter, qboolean wantSubs, int* numfiles, qboolean allowNonPureFilesOnDisk); + void (*FS_FreeFileList)(char **list); // add commands to the local console as if they were typed in // for map changing, etc. The command is not executed immediately, // but will be executed in order the next time console commands @@ -163,7 +167,7 @@ functions exported to the main executable void (*SendClientCommand)(const char *s); // CM functions - void (*CM_LoadMap)(const char *name); + void (*CM_LoadMap)(const char *name, int* checksum); clipHandle_t (*CM_InlineModel)(int index); // 0 = world, 1+ = bmodels int (*CM_NumInlineModels)(void); int (*CM_PointContents)(const vec3_t p, int headnode); @@ -283,9 +287,11 @@ functions exported to the main executable qhandle_t (*R_RegisterModel)(const char *name); qhandle_t (*R_SpawnEffectModel)(const char *name, vec3_t pos, vec3_t axis[3]); qhandle_t (*R_RegisterServerModel)(const char *name); + const char * (*R_GetModelName)(qhandle_t hModel); void (*R_UnregisterServerModel)(qhandle_t hModel); qhandle_t (*R_RegisterShader)(const char *name); qhandle_t (*R_RegisterShaderNoMip)(const char *name); + const char* (*R_GetShaderName)(qhandle_t hShader); void (*R_AddRefEntityToScene)(const refEntity_t *ent, int parentEntityNumber); void (*R_AddRefSpriteToScene)(const refEntity_t *ent); void (*R_AddLightToScene)(const vec3_t origin, float intensity, float r, float g, float b, int type); @@ -307,12 +313,12 @@ functions exported to the main executable ); // 0 = white fontheader_t *(*R_LoadFont)(const char *name); void (*R_DrawString)( - fontheader_t *font, const char *text, float x, float y, int maxLen, qboolean virtualScreen + fontheader_t *font, const char *text, float x, float y, int maxLen, const float *pvVirtualScreen ); refEntity_t *(*R_GetRenderEntity)(int entityNumber); void (*R_ModelBounds)(clipHandle_t model, vec3_t mins, vec3_t maxs); float (*R_ModelRadius)(clipHandle_t model); - float (*R_Noise)(float x, float y, float z, float t); + float (*R_Noise)(float x, float y, float z, double t); void (*R_DebugLine)(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha); baseshader_t *(*GetShader)(int shaderNum); // =========== Swipes ============= @@ -356,6 +362,9 @@ functions exported to the main executable void (*UI_ShowMenu)(const char *name, qboolean bForce); void (*UI_HideMenu)(const char *name, qboolean bForce); int (*UI_FontStringWidth)(fontheader_t *font, const char *string, int maxLen); + // Added in 2.0 + float (*UI_GetObjectivesTop)(void); + void (*UI_GetHighResolutionScale)(vec2_t scale); int (*Key_StringToKeynum)(const char *str); const char *(*Key_KeynumToBindString)(int keyNum); @@ -426,6 +435,8 @@ functions exported to the main executable void (*CL_RestoreSavedCgameState)(); void (*CL_ClearSavedCgameState)(); + size_t (*getConfigStringIdNormalized)(size_t num); + cvar_t *fsDebug; hdelement_t *HudDrawElements; clientAnim_t *anim; @@ -459,8 +470,8 @@ functions exported to the main executable int (*CG_GetParent)(int entNum); float (*CG_GetObjectiveAlpha)(); int (*CG_PermanentMark)( - const vec3_t origin, - const vec3_t dir, + vec3_t origin, + vec3_t dir, float orientation, float sScale, float tScale, @@ -499,8 +510,8 @@ functions exported to the main executable // void (*CG_ReadNonPVSClient)(radarUnpacked_t* radarUnpacked); void (*CG_UpdateRadar)(); - void (*CG_SaveStateToBuffer)(void** out, int svsTime); - void (*CG_LoadStateToBuffer)(void** state, int size, int svsTime); + size_t (*CG_SaveStateToBuffer)(void** out, int svsTime); + qboolean (*CG_LoadStateToBuffer)(void* state, size_t size, int svsTime); void (*CG_CleanUpTempModels)(); // FIXME diff --git a/code/cgame/cg_scoreboard.cpp b/code/cgame/cg_scoreboard.cpp index fe3a0846..f6cb81c8 100644 --- a/code/cgame/cg_scoreboard.cpp +++ b/code/cgame/cg_scoreboard.cpp @@ -58,19 +58,19 @@ void CG_PrepScoreBoardInfo() { switch (cgs.gametype) { case GT_TEAM_ROUNDS: - strcpy(cg.scoresMenuName, "DM_Round_Scoreboard"); + Q_strncpyz(cg.scoresMenuName, "DM_Round_Scoreboard", sizeof(cg.scoresMenuName)); break; case GT_OBJECTIVE: - strcpy(cg.scoresMenuName, "Obj_Scoreboard"); + Q_strncpyz(cg.scoresMenuName, "Obj_Scoreboard", sizeof(cg.scoresMenuName)); break; case GT_TOW: - strcpy(cg.scoresMenuName, "Tow_Scoreboard"); + Q_strncpyz(cg.scoresMenuName, "Tow_Scoreboard", sizeof(cg.scoresMenuName)); break; case GT_LIBERATION: - strcpy(cg.scoresMenuName, "Lib_Scoreboard"); + Q_strncpyz(cg.scoresMenuName, "Lib_Scoreboard", sizeof(cg.scoresMenuName)); break; default: - strcpy(cg.scoresMenuName, "DM_Scoreboard"); + Q_strncpyz(cg.scoresMenuName, "DM_Scoreboard", sizeof(cg.scoresMenuName)); break; } } @@ -296,14 +296,15 @@ void CG_ParseScores_ver_15() switch (iClientTeam) { case 1: - strcpy(szString3, cgi.LV_ConvertString("Spectators")); + Q_strncpyz(szString3, cgi.LV_ConvertString("Spectators"), sizeof(szString3)); break; case 2: - strcpy(szString3, cgi.LV_ConvertString("Free-For-Allers")); + Q_strncpyz(szString3, cgi.LV_ConvertString("Free-For-Allers"), sizeof(szString3)); break; case 3: - sprintf( + Com_sprintf( szString3, + sizeof(szString3), "%s - %d %s", cgi.LV_ConvertString("Allies"), atoi(cgi.Argv(2 + iCurrentEntry + iDatumCount * i)), @@ -312,8 +313,9 @@ void CG_ParseScores_ver_15() iCurrentEntry++; break; case 4: - sprintf( + Com_sprintf( szString3, + sizeof(szString3), "%s - %d %s", cgi.LV_ConvertString("Axis"), atoi(cgi.Argv(2 + iCurrentEntry + iDatumCount * i)), @@ -322,7 +324,7 @@ void CG_ParseScores_ver_15() iCurrentEntry++; break; default: - strcpy(szString3, cgi.LV_ConvertString("No Team")); + Q_strncpyz(szString3, cgi.LV_ConvertString("No Team"), sizeof(szString3)); break; } } else if (iClientNum == -2) { @@ -330,14 +332,14 @@ void CG_ParseScores_ver_15() szString2[0] = 0; szString3[0] = 0; } else { - strcpy(szString2, va("%i", iClientNum)); - strcpy(szString3, cg.clientinfo[iClientNum].name); + Q_strncpyz(szString2, va("%i", iClientNum), sizeof(szString2)); + Q_strncpyz(szString3, cg.clientinfo[iClientNum].name, sizeof(szString3)); } - strcpy(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i)); - strcpy(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i)); - strcpy(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i)); - strcpy(szString7, cgi.Argv(5 + iCurrentEntry + iDatumCount * i)); + Q_strncpyz(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString4)); + Q_strncpyz(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString5)); + Q_strncpyz(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString6)); + Q_strncpyz(szString7, cgi.Argv(5 + iCurrentEntry + iDatumCount * i), sizeof(szString7)); if (cgs.gametype >= GT_TEAM_ROUNDS && iClientNum == -1 && (iClientTeam == TEAM_ALLIES || iClientTeam == TEAM_AXIS)) { @@ -370,19 +372,19 @@ void CG_ParseScores_ver_15() } else { iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i)); if (iClientNum >= 0) { - strcpy(szString2, va("%i", iClientNum)); - strcpy(szString3, cg.clientinfo[iClientNum].name); - strcpy(szString4, cgi.Argv(1 + iCurrentEntry + iDatumCount * i)); - strcpy(szString5, cgi.Argv(2 + iCurrentEntry + iDatumCount * i)); - strcpy(szString6, cgi.Argv(3 + iCurrentEntry + iDatumCount * i)); - strcpy(szString7, cgi.Argv(4 + iCurrentEntry + iDatumCount * i)); + Q_strncpyz(szString2, va("%i", iClientNum), sizeof(szString2)); + Q_strncpyz(szString3, cg.clientinfo[iClientNum].name, sizeof(szString3)); + Q_strncpyz(szString4, cgi.Argv(1 + iCurrentEntry + iDatumCount * i), sizeof(szString4)); + Q_strncpyz(szString5, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString5)); + Q_strncpyz(szString6, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString6)); + Q_strncpyz(szString7, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString7)); } else { szString2[0] = 0; if (iClientNum == -3) { - strcpy(szString2, cgi.LV_ConvertString("Players")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Players"), sizeof(szString2)); bIsHeader = qtrue; } else if (iClientNum == -2) { - strcpy(szString2, cgi.LV_ConvertString("Spectators")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Spectators"), sizeof(szString2)); bIsHeader = qtrue; } else { // unknown @@ -535,32 +537,32 @@ void CG_ParseScores_ver_6() switch (iClientTeam) { case 1: - strcpy(szString2, cgi.LV_ConvertString("Spectators")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Spectators"), sizeof(szString2)); break; case 2: - strcpy(szString2, cgi.LV_ConvertString("Free-For-Allers")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Free-For-Allers"), sizeof(szString2)); break; case 3: - strcpy(szString2, cgi.LV_ConvertString("Allies")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Allies"), sizeof(szString2)); break; case 4: - strcpy(szString2, cgi.LV_ConvertString("Axis")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Axis"), sizeof(szString2)); break; default: - strcpy(szString2, cgi.LV_ConvertString("No Team")); + Q_strncpyz(szString2, cgi.LV_ConvertString("No Team"), sizeof(szString2)); break; } } else if (iClientNum == -2) { // spectating szString2[0] = 0; } else { - strcpy(szString2, cg.clientinfo[iClientNum].name); + Q_strncpyz(szString2, cg.clientinfo[iClientNum].name, sizeof(szString2)); } - strcpy(szString3, cgi.Argv(2 + iCurrentEntry + iDatumCount * i)); - strcpy(szString4, cgi.Argv(3 + iCurrentEntry + iDatumCount * i)); - strcpy(szString5, cgi.Argv(4 + iCurrentEntry + iDatumCount * i)); - strcpy(szString6, cgi.Argv(5 + iCurrentEntry + iDatumCount * i)); + Q_strncpyz(szString3, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString3)); + Q_strncpyz(szString4, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString4)); + Q_strncpyz(szString5, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString5)); + Q_strncpyz(szString6, cgi.Argv(5 + iCurrentEntry + iDatumCount * i), sizeof(szString6)); if (iClientNum == cg.snap->ps.clientNum) { pItemTextColor = vThisClientTextColor; @@ -587,17 +589,17 @@ void CG_ParseScores_ver_6() } else { iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i)); if (iClientNum >= 0) { - strcpy(szString2, cg.clientinfo[iClientNum].name); - strcpy(szString3, cgi.Argv(1 + iCurrentEntry + iDatumCount * i)); - strcpy(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i)); - strcpy(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i)); - strcpy(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i)); + Q_strncpyz(szString2, cg.clientinfo[iClientNum].name, sizeof(szString2)); + Q_strncpyz(szString3, cgi.Argv(1 + iCurrentEntry + iDatumCount * i), sizeof(szString3)); + Q_strncpyz(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString4)); + Q_strncpyz(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString5)); + Q_strncpyz(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString6)); } else { if (iClientNum == -3) { - strcpy(szString2, cgi.LV_ConvertString("Players")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Players"), sizeof(szString2)); bIsHeader = qtrue; } else if (iClientNum == -2) { - strcpy(szString2, cgi.LV_ConvertString("Spectators")); + Q_strncpyz(szString2, cgi.LV_ConvertString("Spectators"), sizeof(szString2)); bIsHeader = qtrue; } else { // unknown diff --git a/code/cgame/cg_servercmds.c b/code/cgame/cg_servercmds.c index 9e932721..bc9f100a 100644 --- a/code/cgame/cg_servercmds.c +++ b/code/cgame/cg_servercmds.c @@ -1,6 +1,7 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2008-2024 the OpenMoHAA team +Copyright (C) 1999-2005 Id Software, Inc. This file is part of OpenMoHAA source code. @@ -24,12 +25,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // cg_servercmds.c -- text commands sent by the server #include "cg_local.h" +#include "../fgame/bg_voteoptions.h" +#include "cg_servercmds_filter.h" +/* +================ +IsWeaponAllowed + +Returns true if the weapon is allowed +================ +*/ static const char *IsWeaponAllowed(int dmFlags, int flags) { return (dmFlags & flags) ? "0" : "1"; } +/* +================ +QueryLandminesAllowed2 + +Returns true if landmines is allowed by the map or by a dm flag +================ +*/ static qboolean QueryLandminesAllowed2(const char *mapname, int dmflags) { if (dmflags & DF_WEAPON_NO_LANDMINE) { @@ -112,6 +129,7 @@ void CG_ParseServerinfo(void) char map[MAX_QPATH]; char *spawnpos; const char *version; + const char *mapChecksumStr; info = CG_ConfigString(CS_SERVERINFO); cgs.gametype = atoi(Info_ValueForKey(info, "g_gametype")); @@ -132,15 +150,27 @@ void CG_ParseServerinfo(void) cgi.Cvar_Set("cg_fraglimit", Info_ValueForKey(info, "fraglimit")); cgi.Cvar_Set("cg_timelimit", Info_ValueForKey(info, "timelimit")); cgi.Cvar_Set("cg_maxclients", Info_ValueForKey(info, "sv_gametype")); + cgi.Cvar_Set("cg_allowvote", Info_ValueForKey(info, "g_allowvote")); cgi.Cvar_Set("cg_obj_alliedtext1", Info_ValueForKey(info, "g_obj_alliedtext1")); cgi.Cvar_Set("cg_obj_alliedtext2", Info_ValueForKey(info, "g_obj_alliedtext2")); cgi.Cvar_Set("cg_obj_alliedtext3", Info_ValueForKey(info, "g_obj_alliedtext3")); - cgi.Cvar_Set("cg_obj_axistext1", Info_ValueForKey(info, "cg_obj_axistext1")); - cgi.Cvar_Set("cg_obj_axistext2", Info_ValueForKey(info, "cg_obj_axistext2")); - cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "cg_obj_axistext3")); + cgi.Cvar_Set("cg_obj_alliedtext4", Info_ValueForKey(info, "g_obj_alliedtext4")); + cgi.Cvar_Set("cg_obj_alliedtext5", Info_ValueForKey(info, "g_obj_alliedtext5")); + cgi.Cvar_Set("cg_obj_axistext1", Info_ValueForKey(info, "g_obj_axistext1")); + cgi.Cvar_Set("cg_obj_axistext2", Info_ValueForKey(info, "g_obj_axistext2")); + cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "g_obj_axistext3")); + cgi.Cvar_Set("cg_obj_axistext4", Info_ValueForKey(info, "g_obj_axistext4")); + cgi.Cvar_Set("cg_obj_axistext5", Info_ValueForKey(info, "g_obj_axistext5")); cgi.Cvar_Set("cg_scoreboardpic", Info_ValueForKey(info, "g_scoreboardpic")); cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover")); - cgs.mapChecksum = atoi(Info_ValueForKey(info, "sv_mapChecksum")); + mapChecksumStr = Info_ValueForKey(info, "sv_mapChecksum"); + if (mapChecksumStr && mapChecksumStr[0]) { + cgs.mapChecksum = atoi(mapChecksumStr); + cgs.useMapChecksum = qtrue; + } else { + cgs.mapChecksum = 0; + cgs.useMapChecksum = qfalse; + } mapname = Info_ValueForKey(info, "mapname"); @@ -156,11 +186,15 @@ void CG_ParseServerinfo(void) if (spawnpos) { Q_strncpyz(map, mapname, spawnpos - mapname + 1); } else { - strcpy(map, mapname); + Q_strncpyz(map, mapname, sizeof(map)); } - Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s.bsp", map); - + if (CG_UseLargeLightmaps(mapname)) { + Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s.bsp", map); + } else { + Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s_sml.bsp", map); + } + // hide/show huds if (cgs.gametype) { cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_timelimit\n"); @@ -184,17 +218,13 @@ CG_ConfigStringModified ================ */ -static void CG_ConfigStringModified(void) +static void CG_ConfigStringModified(int num, qboolean modelOnly) { - int num; - - num = atoi(cgi.Argv(1)); - // get the gamestate from the client system, which will have the // new configstring already integrated cgi.GetGameState(&cgs.gameState); - CG_ProcessConfigString(num); + CG_ProcessConfigString(num, modelOnly); } /* @@ -275,7 +305,7 @@ The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() ================= */ -static void CG_ServerCommand(void) +static void CG_ServerCommand(qboolean modelOnly) { const char *cmd; @@ -287,7 +317,11 @@ static void CG_ServerCommand(void) } if (!strcmp(cmd, "cs")) { - CG_ConfigStringModified(); + CG_ConfigStringModified(cgi.getConfigStringIdNormalized(atoi(cgi.Argv(1))), modelOnly); + return; + } + + if (modelOnly) { return; } @@ -298,12 +332,12 @@ static void CG_ServerCommand(void) } return; } else if (!strcmp(cmd, "printdeathmsg")) { - const char *s1, *s2, * attackerName, * victimName, *type; + const char *s1, *s2, *attackerName, *victimName, *type; const char *result1, *result2; int hudColor; - result1 = NULL; - result2 = NULL; + result1 = NULL; + result2 = NULL; s1 = cgi.Argv(1); s2 = cgi.Argv(2); attackerName = cgi.Argv(3); @@ -339,7 +373,14 @@ static void CG_ServerCommand(void) } if (!strcmp(cmd, "stufftext")) { - cgi.Cmd_Stuff(cgi.Argv(1)); + char *cmd = cgi.Argv(1); + if (CG_IsStatementFiltered(cmd)) { + // Added in OPM + // Don't execute filtered commands + return; + } + + cgi.Cmd_Stuff(cmd); cgi.Cmd_Stuff("\n"); return; } @@ -364,6 +405,28 @@ static void CG_ServerCommand(void) return; } + if (!strcmp(cmd, "voteresult")) { + cmd = cgi.Argv(1); + if (*cmd) { + strcmp(cmd, "passed"); + } + } + + if (!strcmp(cmd, "vo0")) { + CG_VoteOptions_StartReadFromServer(cgi.Argv(1)); + return; + } + + if (!strcmp(cmd, "vo1")) { + CG_VoteOptions_ContinueReadFromServer(cgi.Argv(1)); + return; + } + + if (!strcmp(cmd, "vo2")) { + CG_VoteOptions_FinishReadFromServer(cgi.Argv(1)); + return; + } + cgi.Printf("Unknown client game command: %s\n", cmd); } @@ -377,9 +440,20 @@ with this this snapshot. */ void CG_ExecuteNewServerCommands(int latestSequence, qboolean differentServer) { + int lastServerCommandSequence; + + lastServerCommandSequence = cgs.serverCommandSequence; + while (cgs.serverCommandSequence < latestSequence) { if (cgi.GetServerCommand(++cgs.serverCommandSequence, differentServer)) { - CG_ServerCommand(); + CG_ServerCommand(qtrue); + } + } + + cgs.serverCommandSequence = lastServerCommandSequence; + while (cgs.serverCommandSequence < latestSequence) { + if (cgi.GetServerCommand(++cgs.serverCommandSequence, differentServer)) { + CG_ServerCommand(qfalse); } } } diff --git a/code/cgame/cg_servercmds_filter.c b/code/cgame/cg_servercmds_filter.c new file mode 100644 index 00000000..9e2170f7 --- /dev/null +++ b/code/cgame/cg_servercmds_filter.c @@ -0,0 +1,292 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// DESCRIPTION: +// cg_servercmds_filter.c -- filtered server commands + +#include "cg_local.h" +#include "cg_servercmds_filter.h" + +// +// List of variables allowed to be changed by the server +// +static const char *whiteListedVariables[] = { + // some mods set this variable to make the sky uniform + "r_fastsky", + + "ui_hud", + "subtitle0", + "subtitle1", + "subtitle2", + "subtitle3", + "name", + + // for 3rd person server + "cg_3rd_person", + "cg_cameraverticaldisplacement" +}; + +// +// List of variables allowed to be changed by the server +// +static const char *whiteListedLocalServerVariables[] = {"ui_hidemouse", "ui_showmouse", "cg_marks_add"}; + +// +// List of commands allowed to be executed by the server +// +static const char *whiteListedCommands[] = { + // + // HUD + //========== + "pushmenu", + "pushmenu_teamselect", + "pushmenu_weaponselect", + "popmenu", + "globalwidgetcommand", // used for mods adding custom HUDs + "ui_addhud", + "ui_removehud", + "echo", // to print stuff client-side + + // + // Sounds + //========== + "tmstart", + "tmstartloop", + "tmstop", + "tmvolume", + "play", + "playmp3", + "stopmp3", + + // + // Misc + //========== + "primarydmweapon", + "wait", + "+moveup", // workaround for mods that want to prevent inactivity when handling the spectate + "-moveup", + "screenshot", + "screenshotJPEG", + "levelshot", + "`stufftext" // Stufftext detection from Reborn, the player gets kicked without it +}; + +// +// List of commands allowed to be executed locally +// (when the client also runs the server) +// +static const char *whiteListedLocalServerCommands[] = { + // Used by briefings + "spmap", + "map", + "disconnect", + + "cinematic", + "showmenu", + "hidemenu" +}; + + +/* +==================== +CG_IsVariableFiltered + +Returns whether or not the variable should be filtered +==================== +*/ +static qboolean CG_IsVariableFiltered(const char *name) +{ + size_t i; + + for (i = 0; i < ARRAY_LEN(whiteListedVariables); i++) { + if (!Q_stricmp(name, whiteListedVariables[i])) { + return qfalse; + } + } + + if (cgs.localServer) { + for (i = 0; i < ARRAY_LEN(whiteListedLocalServerVariables); i++) { + if (!Q_stricmp(name, whiteListedLocalServerVariables[i])) { + return qfalse; + } + } + } + + // Filtered + return qtrue; +} + +/* +==================== +CG_IsSetVariableFiltered + +Returns whether or not the variable should be filtered +==================== +*/ +static qboolean CG_IsSetVariableFiltered(const char *name, char type) +{ + cvar_t *var; + + if (!CG_IsVariableFiltered(name)) { + return qfalse; + } + + if (type != 'u' && type != 's') { + // Don't allow custom info variables to avoid flooding + // the client with many serverinfo and userinfo variables + + var = cgi.Cvar_Find(name); + if (!var) { + // Allow as it doesn't exist + return qfalse; + } + + if (var->flags & CVAR_USER_CREATED) { + // Allow, it's user-created, wouldn't cause issues + return qfalse; + } + } + + // Filtered + return qtrue; +} + +/* +==================== +CG_IsCommandFiltered + +Returns whether or not the variable should be filtered +==================== +*/ +static qboolean CG_IsCommandFiltered(const char *name) +{ + size_t i; + + for (i = 0; i < ARRAY_LEN(whiteListedCommands); i++) { + if (!Q_stricmp(name, whiteListedCommands[i])) { + return qfalse; + } + } + + if (cgs.localServer) { + // Allow more commands when the client is hosting the server + // Mostly used on single-player mode, like when briefings switch to the next map + for (i = 0; i < ARRAY_LEN(whiteListedLocalServerCommands); i++) { + if (!Q_stricmp(name, whiteListedLocalServerCommands[i])) { + return qfalse; + } + } + } + + // + // Test variables + // + return CG_IsVariableFiltered(name); +} + +/* +==================== +RemoveEndToken +==================== +*/ +static qboolean RemoveEndToken(char* com_token) { + char* p; + + for (p = com_token; p[0]; p++) { + if (*p == ';') { + *p = 0; + return qtrue; + } + } + + return qfalse; +} + +/* +==================== +CG_IsStatementFiltered + +Returns whether or not the statement is filtered +==================== +*/ +qboolean CG_IsStatementFiltered(char *cmd) +{ + char* parsed; + char com_token[256]; + qboolean bNextStatement = qfalse; + + parsed = cmd; + + for (Q_strncpyz(com_token, COM_ParseExt(&parsed, qtrue), sizeof(com_token)); com_token[0]; Q_strncpyz(com_token, COM_ParseExt(&parsed, qtrue), sizeof(com_token))) { + bNextStatement = RemoveEndToken(com_token); + + if (com_token[0] == ';') { + continue; + } + + if (!Q_stricmp(com_token, "set") || !Q_stricmp(com_token, "setu") || !Q_stricmp(com_token, "seta") + || !Q_stricmp(com_token, "sets") || !Q_stricmp(com_token, "append")) { + char type; + + if (Q_stricmp(com_token, "append")) { + type = com_token[3]; + } else { + type = 0; + } + + // + // variable + // + Q_strncpyz(com_token, COM_ParseExt(&parsed, qfalse), sizeof(com_token)); + bNextStatement |= RemoveEndToken(com_token); + if (com_token[0] == ';') { + continue; + } + + if (CG_IsSetVariableFiltered(com_token, type)) { + return qtrue; + } + } else { + // + // normal command + // + if (CG_IsCommandFiltered(com_token)) { + return qtrue; + } + } + + if (!bNextStatement) { + // Skip up to the next statement + while (parsed && parsed[0]) { + char c = parsed[0]; + + parsed++; + if (c == '\n' || c == ';') { + break; + } + } + } + } + + return qfalse; +} + diff --git a/code/cgame/cg_servercmds_filter.h b/code/cgame/cg_servercmds_filter.h new file mode 100644 index 00000000..f8351028 --- /dev/null +++ b/code/cgame/cg_servercmds_filter.h @@ -0,0 +1,30 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// DESCRIPTION: +// cg_servercmds_filter.h -- filtered server commands + +#pragma once + +#include "cg_local.h" + +qboolean CG_IsStatementFiltered(char *cmd); \ No newline at end of file diff --git a/code/cgame/cg_snapshot.c b/code/cgame/cg_snapshot.c index 1c64061d..06b6d67d 100644 --- a/code/cgame/cg_snapshot.c +++ b/code/cgame/cg_snapshot.c @@ -23,8 +23,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // DESCRIPTION: // things that happen on snapshot transition, not necessarily every // single frame +// +// ADDITIONS: +// - CG_TransitionSnapshot() footer: set ps.walking to true if the ps has a ground entity #include "cg_local.h" +#include "cg_radar.h" #include "tiki.h" /* @@ -69,10 +73,10 @@ static void CG_ResetEntity(centity_t *cent) CG_RemoveClientEntity(cent->currentState.number, tiki, cent); // reset the animation for the entities - if (tiki && tiki->a->bIsCharacter) { + if (tiki) { for (i = 0; i < MAX_FRAMEINFOS; i++) { - cent->animLast[i] = cent->currentState.frameInfo[i].index; - cent->animLastTimes[i] = cent->currentState.frameInfo[i].time; + cent->animLast[i] = -1; + cent->animLastTimes[i] = -1; if (cent->currentState.frameInfo[i].weight) { cent->animLastWeight |= 1 << i; } else { @@ -83,7 +87,8 @@ static void CG_ResetEntity(centity_t *cent) } else { // clear all the last animations for (i = 0; i < MAX_FRAMEINFOS; i++) { - cent->animLast[i] = -1; + cent->animLast[i] = -1; + cent->animLastTimes[i] = 0.0; } cent->animLastWeight = 0; @@ -206,6 +211,9 @@ static void CG_TransitionSnapshot(qboolean differentServer) cent->teleported = qfalse; } CG_TransitionEntity(cent); + + // remember time of snapshot this entity was last updated in + cent->snapShotTime = cg.snap->serverTime; } for (i = 0; i < cg.snap->number_of_sounds; i++) { @@ -243,6 +251,15 @@ static void CG_TransitionSnapshot(qboolean differentServer) CG_TransitionPlayerState(ps, ops); } } + + if (differentServer) { + cgi.CL_RestoreSavedCgameState(); + } else { + cgi.CL_ClearSavedCgameState(); + } + + // this allows the view model to still look normal when the player is on ground + cg.snap->ps.walking = cg.snap->ps.groundEntityNum != ENTITYNUM_NONE; } /* @@ -330,8 +347,10 @@ static snapshot_t *CG_ReadNextSnapshot(void) snapshot_t *dest; if (cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000) { - cgi.Error( - ERR_DROP, "CG_ReadNextSnapshot: way out of range, %i > %i", cg.latestSnapshotNum, cgs.processedSnapshotNum + cgi.Printf( + "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i\n", + cg.latestSnapshotNum, + cgs.processedSnapshotNum ); } diff --git a/code/cgame/cg_specialfx.cpp b/code/cgame/cg_specialfx.cpp index 8f5abb61..48042803 100644 --- a/code/cgame/cg_specialfx.cpp +++ b/code/cgame/cg_specialfx.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -38,7 +38,8 @@ static vec3_t g_vLadderstepMaxs; ClientSpecialEffectsManager sfxManager; -Event EV_SFX_EffectDelay( +Event EV_SFX_EffectDelay +( "effectdelay", EV_DEFAULT, "iivvvvv", @@ -94,7 +95,7 @@ void ClientSpecialEffectsManager::LoadEffects() cgi.DPrintf("Loading Special Effects...\n"); AxisClear(axis); - for (i = 0; i < MAX_SPECIAL_EFFECTS; i++) { + for (i = 0; i < SFX_COUNT; i++) { switch (i) { case SFX_BHIT_PAPER_LITE: szEffectModel = "models/fx/bh_paper_lite.tik"; @@ -234,9 +235,15 @@ void ClientSpecialEffectsManager::LoadEffects() szEffectModel = "models/fx/bazookaexp_base.tik"; break; case SFX_EXP_HEAVYSHELL_BASE: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/heavyshellexp_base.tik"; break; case SFX_EXP_TANK_BASE: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/tankexp_base.tik"; break; case SFX_EXP_GREN_PAPER: @@ -285,30 +292,57 @@ void ClientSpecialEffectsManager::LoadEffects() szEffectModel = "models/fx/grenexp_carpet.tik"; break; case SFX_EXP_HEAVYSHELL_DIRT: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/heavyshellexp_dirt.tik"; break; case SFX_EXP_HEAVYSHELL_STONE: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/heavyshellexp_stone.tik"; break; case SFX_EXP_HEAVYSHELL_SNOW: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/heavyshellexp_snow.tik"; break; case SFX_EXP_TANK_DIRT: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/tankexp_dirt.tik"; break; case SFX_EXP_TANK_STONE: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/tankexp_stone.tik"; break; case SFX_EXP_TANK_SNOW: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/tankexp_snow.tik"; break; case SFX_EXP_BAZOOKA_DIRT: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/bazookaexp_dirt.tik"; break; case SFX_EXP_BAZOOKA_STONE: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/bazookaexp_stone.tik"; break; case SFX_EXP_BAZOOKA_SNOW: + if (cg_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + continue; + } szEffectModel = "models/fx/bazookaexp_snow.tik"; break; case SFX_WATER_RIPPLE_STILL: @@ -478,7 +512,7 @@ void ClientSpecialEffectsManager::ExecuteEffect( current_tiki = NULL; pCommand->emitter->cgd.origin = vPos; - if (pCommand->emitter->cgd.flags & T_ANGLES) { + if (!(pCommand->emitter->cgd.flags & T_ANGLES)) { pCommand->emitter->cgd.angles = vAngles; } @@ -486,7 +520,7 @@ void ClientSpecialEffectsManager::ExecuteEffect( AxisCopy(axis, pCommand->emitter->tag_axis); pCommand->emitter->cgd.createTime = cg.time; commandManager.SetSpawnthing(pCommand->emitter); - + (commandManager.*pCommand->endfcn)(); } } @@ -904,7 +938,144 @@ void CG_LandingSound(centity_t *ent, refEntity_t *pREnt, float volume, int iEqui void CG_BodyFallSound(centity_t *ent, refEntity_t *pREnt, float volume) { - // FIXME: unimplemented + int contents; + int surftype; + int iEffectNum = -1; + vec3_t vStart, vEnd; + vec3_t midlegs; + str sSoundName; + trace_t trace; + + VectorCopy(ent->lerpOrigin, vStart); + vStart[2] += 8; + + VectorCopy(vStart, vEnd); + vEnd[2] -= 64; + + if (ent->currentState.eType == ET_PLAYER) { + CG_Trace( + &trace, + vStart, + g_vFootstepMins, + g_vFootstepMaxs, + vEnd, + ent->currentState.number, + MASK_PLAYERSOLID, + qtrue, + qtrue, + "Player Landing" + ); + } else { + CG_Trace( + &trace, + vStart, + g_vFootstepMins, + g_vFootstepMaxs, + vEnd, + ent->currentState.number, + MASK_MONSTERSOLID, + qfalse, + qfalse, + "Monster Landing" + ); + } + + if (trace.fraction == 1) { + return; + } + + sSoundName = "snd_bodyfall_"; + contents = CG_PointContents(trace.endpos, -1); + if (contents & MASK_WATER) { + // take our ground position and trace upwards + VectorCopy(trace.endpos, midlegs); + midlegs[2] += WATER_NO_SPLASH_HEIGHT; + contents = CG_PointContents(midlegs, -1); + if (contents & MASK_WATER) { + sSoundName += "wade"; + } else { + sSoundName += "puddle"; + iEffectNum = SFX_FOOT_PUDDLE; + } + } else { + surftype = trace.surfaceFlags & MASK_SURF_TYPE; + switch (surftype) { + case SURF_FOLIAGE: + sSoundName += "foliage"; + iEffectNum = SFX_FOOT_GRASS; + break; + case SURF_SNOW: + sSoundName += "snow"; + iEffectNum = SFX_FOOT_SNOW; + break; + case SURF_CARPET: + sSoundName += "carpet"; + iEffectNum = SFX_FOOT_LIGHT_DUST; + break; + case SURF_SAND: + sSoundName += "sand"; + iEffectNum = SFX_FOOT_SAND; + break; + case SURF_PUDDLE: + sSoundName += "puddle"; + iEffectNum = SFX_FOOT_PUDDLE; + break; + case SURF_GLASS: + sSoundName += "glass"; + iEffectNum = SFX_FOOT_LIGHT_DUST; + break; + case SURF_GRAVEL: + sSoundName += "gravel"; + iEffectNum = SFX_FOOT_HEAVY_DUST; + break; + case SURF_MUD: + sSoundName += "mud"; + iEffectNum = SFX_FOOT_MUD; + break; + case SURF_DIRT: + sSoundName += "dirt"; + iEffectNum = SFX_FOOT_DIRT; + break; + case SURF_GRILL: + sSoundName += "grill"; + iEffectNum = SFX_FOOT_LIGHT_DUST; + break; + case SURF_GRASS: + sSoundName += "grass"; + iEffectNum = SFX_FOOT_GRASS; + break; + case SURF_ROCK: + sSoundName += "stone"; + iEffectNum = SFX_FOOT_HEAVY_DUST; + break; + case SURF_PAPER: + sSoundName += "paper"; + iEffectNum = SFX_FOOT_LIGHT_DUST; + break; + case SURF_WOOD: + sSoundName += "wood"; + iEffectNum = SFX_FOOT_LIGHT_DUST; + break; + case SURF_METAL: + sSoundName += "metal"; + iEffectNum = SFX_FOOT_LIGHT_DUST; + break; + default: + sSoundName += "stone"; + iEffectNum = SFX_FOOT_HEAVY_DUST; + break; + } + } + + if (cg_debugFootsteps->integer) { + cgi.DPrintf("BodyFall: %s volume: %.2f effect = %i\n", sSoundName.c_str(), volume, iEffectNum); + } + + commandManager.PlaySound(sSoundName, trace.endpos, -1, volume, -1, -1, 1); + + if (iEffectNum != -1) { + sfxManager.MakeEffect_Angles(iEffectNum, trace.endpos, Vector(270, 0, 0)); + } } /* @@ -1023,5 +1194,5 @@ qboolean ClientSpecialEffectsManager::EffectsPending() specialeffect_t *ClientSpecialEffectsManager::GetTestEffectPointer() { - return &m_effects[SPECIAL_EFFECT_TEST]; + return &m_effects[SFX_TEST_EFFECT]; } diff --git a/code/cgame/cg_specialfx.h b/code/cgame/cg_specialfx.h index 4a84e52c..9df6c06d 100644 --- a/code/cgame/cg_specialfx.h +++ b/code/cgame/cg_specialfx.h @@ -170,12 +170,9 @@ public: specialeffectcommand_t *AddNewCommand(); }; -#define MAX_SPECIAL_EFFECTS 99 -#define SPECIAL_EFFECT_TEST MAX_SPECIAL_EFFECTS - 1 - class ClientSpecialEffectsManager : public Listener { - specialeffect_t m_effects[99]; + specialeffect_t m_effects[SFX_COUNT]; qboolean m_bEffectsLoaded; int m_iNumPendingEvents; diff --git a/code/cgame/cg_tempmodels.cpp b/code/cgame/cg_tempmodels.cpp index 4fac5ac2..3ce3ab04 100644 --- a/code/cgame/cg_tempmodels.cpp +++ b/code/cgame/cg_tempmodels.cpp @@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tiki.h" cvar_t *cg_showtempmodels; +cvar_t *cg_max_tempmodels; +cvar_t *cg_reserve_tempmodels; cvar_t *cg_detail; cvar_t *cg_effectdetail; cvar_t *cg_effect_physicsrate; @@ -77,6 +79,11 @@ void ClientGameCommandManager::FreeTempModel(ctempmodel_t *p) RemoveClientEntity(p->number, p->cgd.tiki, NULL, p); + if (m_active_tempmodels.next == p) { + // use the next active temp model + m_active_tempmodels.next = p->next; + } + // remove from the doubly linked active list p->prev->next = p->next; p->next->prev = p->prev; @@ -84,8 +91,101 @@ void ClientGameCommandManager::FreeTempModel(ctempmodel_t *p) // the free list is only singly linked p->next = m_free_tempmodels; m_free_tempmodels = p; + + if (p->m_spawnthing) { + p->m_spawnthing->numtempmodels--; + // delete unused spawnthings + if (!p->m_spawnthing->numtempmodels) { + m_emitters.RemoveObject(p->m_spawnthing); + + if (p->m_spawnthing == m_spawnthing) { + m_spawnthing = NULL; + } + + delete p->m_spawnthing; + } + + p->m_spawnthing = NULL; + } } +//=============== +// FreeAllTempModels +//=============== +void ClientGameCommandManager::FreeAllTempModels(void) +{ + ctempmodel_t *p, *next; + + // Go through all the temp models and run the physics if necessary, + // then add them to the ref + p = m_active_tempmodels.prev; + for (; p != &m_active_tempmodels; p = next) { + // grab next now, so if the local entity is freed we still have it + next = p->prev; + FreeTempModel(p); + } +} + +//=============== +// FreeSomeTempModels +//=============== +void ClientGameCommandManager::FreeSomeTempModels(void) +{ + ctempmodel_t *model; + int count = 0; + unsigned int i; + unsigned int numToFree; + + if (!m_free_tempmodels) { + return; + } + + for (model = m_active_tempmodels.prev; model != &m_active_tempmodels; model = model->prev) { + count++; + } + + if (cg_reserve_tempmodels->integer <= (cg_max_tempmodels->integer - count)) { + // nothing to free + return; + } + + numToFree = cg_reserve_tempmodels->integer - (cg_max_tempmodels->integer - count); + + for (i = 0; i < numToFree; i++) { + FreeTempModel(m_active_tempmodels.prev); + } +} + +//=============== +// FreeSpawnthing +//=============== +void ClientGameCommandManager::FreeSpawnthing(spawnthing_t *sp) +{ + ctempmodel_t *model; + ctempmodel_t *prev; + + if (sp->numtempmodels) { + for (model = m_active_tempmodels.prev; model != &m_active_tempmodels; model = prev) { + prev = model->prev; + + if (model->m_spawnthing == sp) { + FreeTempModel(model); + } + } + } else { + m_emitters.RemoveObject(sp); + + if (sp == m_spawnthing) { + m_spawnthing = NULL; + } + + delete sp; + } +} + +//=============== +// ResetTempModels +//=============== void ClientGameCommandManager::ResetTempModels(void) { // Go through all the active tempmodels and free them @@ -99,6 +199,7 @@ void ClientGameCommandManager::ResetTempModels(void) } static int lastTempModelFrameTime = 0; +int next_tempmodel_warning = 0; void CG_ResetTempModels(void) { @@ -127,10 +228,29 @@ void ClientGameCommandManager::InitializeTempModels(void) void ClientGameCommandManager::InitializeTempModelCvars(void) { - cg_showtempmodels = cgi.Cvar_Get("cg_showtempmodels", "0", 0); - cg_detail = cgi.Cvar_Get("detail", "1", 1); - cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", 1); - cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", 1); + cg_showtempmodels = cgi.Cvar_Get("cg_showtempmodels", "0", 0); + cg_detail = cgi.Cvar_Get("detail", "1", CVAR_ARCHIVE); + + cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", CVAR_ARCHIVE); + cgi.Cvar_CheckRange(cg_effectdetail, 0.2, 1.0, qfalse); + + cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", CVAR_ARCHIVE); + cg_max_tempmodels = cgi.Cvar_Get("cg_max_tempmodels", "1100", CVAR_ARCHIVE); + cgi.Cvar_CheckRange(cg_max_tempmodels, 200, MAX_TEMPMODELS, qtrue); + + cg_reserve_tempmodels = cgi.Cvar_Get("cg_reserve_tempmodels", "200", CVAR_ARCHIVE); + + if (cg_max_tempmodels->integer > MAX_TEMPMODELS) { + // 2.40 sets the integer value directly rather than calling Cvar_Set() + //cg_max_tempmodels->integer = MAX_TEMPMODELS + cgi.Cvar_Set("cg_max_tempmodels", va("%i", MAX_TEMPMODELS)); + } + + if (cg_reserve_tempmodels->integer * 5 > cg_max_tempmodels->integer) { + // 2.40 sets the integer value directly rather than calling Cvar_Set() + //cg_reserve_tempmodels->integer = cg_max_tempmodels->integer / 5; + cgi.Cvar_Set("cg_reserve_tempmodels", va("%i", cg_max_tempmodels->integer / 5)); + } } //=============== @@ -138,9 +258,10 @@ void ClientGameCommandManager::InitializeTempModelCvars(void) //=============== void ClientGameCommandManager::AnimateTempModel(ctempmodel_t *p, Vector origin, refEntity_t *newEnt) { - int numframes; - int deltatime; - int frametime; + int numframes; + int deltatime; + int frametime; + float prev; // This code is for animating tempmodels that are spawned from the client // side @@ -165,10 +286,18 @@ void ClientGameCommandManager::AnimateTempModel(ctempmodel_t *p, Vector origin, // Go through all the frames, and process any commands associated with the // tempmodel as well + prev = deltatime; while (deltatime >= frametime) { + deltatime -= frametime; p->lastAnimTime += frametime; p->ent.wasframe = (p->ent.wasframe + 1) % numframes; CG_ProcessEntityCommands(p->ent.wasframe, p->ent.frameInfo[0].index, -1, &p->ent, NULL); + + if (deltatime == prev) { + break; + } + + prev = deltatime; } } @@ -208,9 +337,10 @@ void ClientGameCommandManager::UpdateSwarm(ctempmodel_t *p) } } -qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float dtime, float scale) +qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float scale) { float fade, fadein; + float dtime; byte tempColor[4]; if (p->cgd.flags & (T_FADE | T_SCALEUPDOWN)) { @@ -314,9 +444,11 @@ qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t *p, flo p->ent.shaderRGBA[0] = (int)((float)tempColor[0] * vLighting[0]); p->ent.shaderRGBA[1] = (int)((float)tempColor[1] * vLighting[1]); + p->ent.shaderRGBA[2] = (int)((float)tempColor[2] * vLighting[2]); } else { p->ent.shaderRGBA[0] = tempColor[0]; p->ent.shaderRGBA[1] = tempColor[1]; + p->ent.shaderRGBA[2] = tempColor[2]; } if (p->cgd.flags & T_FADEIN && (fadein < 1)) // Do the fadein effect @@ -362,9 +494,19 @@ void ClientGameCommandManager::OtherTempModelEffects(ctempmodel_t *p, Vector ori vec3_t axis[3]; if (p->number != -1) { + refEntity_t *old_entity; + dtiki_t *old_tiki; + int oldnum; + float oldscale; + // Set the axis AnglesToAxis(p->cgd.angles, axis); + old_entity = current_entity; + old_tiki = current_tiki; + oldnum = current_entity_number; + oldscale = current_scale; + current_scale = newEnt->scale; current_entity = newEnt; current_tiki = p->cgd.tiki; @@ -380,14 +522,23 @@ void ClientGameCommandManager::OtherTempModelEffects(ctempmodel_t *p, Vector ori commandManager.ProcessEvent(ev); } - current_entity_number = -1; - current_tiki = NULL; - current_entity = NULL; - current_scale = -1; + current_entity_number = oldnum; + current_tiki = old_tiki; + current_entity = old_entity; + current_scale = oldscale; + } + + if (p->cgd.flags2 & T2_ALIGNSTRETCH) { + Vector vDelta; + float fScale; + + vDelta = p->cgd.origin - p->cgd.oldorigin; + fScale = vDelta.length() * p->cgd.scale2; + VectorScale(newEnt->axis[0], fScale, newEnt->axis[0]); } } -qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime, float time2, float scale) +qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime, float scale) { int dtime; Vector parentOrigin(0, 0, 0); @@ -395,6 +546,7 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime Vector tempangles; trace_t trace; float dot; + int i; VectorCopy(p->ent.origin, p->lastEnt.origin); AxisCopy(p->ent.axis, p->lastEnt.axis); @@ -406,37 +558,40 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime // Update based on swarm if (p->cgd.flags & T_SWARM) { - p->cgd.origin += ftime * p->cgd.velocity * scale; + p->cgd.origin += p->cgd.velocity * ftime * scale; } - // Update the orign and the angles based on velocities first - if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) { - p->cgd.origin = p->cgd.origin + (p->cgd.velocity * ftime * scale) + (time2 * p->cgd.accel); + else if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) { + p->cgd.origin += p->cgd.velocity * ftime * scale; } // If linked to the parent or hardlinked, get the parent's origin if ((p->cgd.flags & (T_PARENTLINK | T_HARDLINK)) && (p->cgd.parent != ENTITYNUM_NONE)) { - centity_t *pc; + centity_t *pc; + refEntity_t *e; + pc = &cg_entities[p->cgd.parent]; - - if (pc->currentValid) { - refEntity_t *e; - - e = cgi.R_GetRenderEntity(p->cgd.parent); - - if (!e) { - return false; - } - - parentOrigin = e->origin; - vectoangles(e->axis[0], parentAngles); - } else { + if (!pc->currentValid) { return false; } + + e = cgi.R_GetRenderEntity(p->cgd.parent); + if (!e) { + return false; + } + + parentOrigin = e->origin; + vectoangles(e->axis[0], parentAngles); } else if (p->cgd.flags & T_SWARM) { p->cgd.parentOrigin = p->cgd.velocity + p->cgd.accel * ftime * scale; } + if (p->cgd.flags2 & T2_WATERONLY) { + if (!(cgi.CM_PointContents(p->cgd.origin, 0) & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA))) { + return false; + } + } + // Align the object along it's traveling vector if (p->cgd.flags & T_ALIGN) { p->cgd.angles = p->cgd.velocity.toAngles(); @@ -457,12 +612,12 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime p->cgd.angles[1] = AngleMod(p->cgd.angles[1]); p->cgd.angles[2] = AngleMod(p->cgd.angles[2]); - // Add in parent angles - tempangles = p->cgd.angles + parentAngles; - // Convert to axis if ((p->cgd.flags & (T_ALIGN | T_RANDOMROLL | T_PARENTLINK | T_HARDLINK | T_ANGLES)) || (p->cgd.flags2 & T2_AMOVE)) { + // Add in parent angles + tempangles = p->cgd.angles + parentAngles; + AnglesToAxis(tempangles, p->ent.axis); } @@ -503,70 +658,68 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime } if (p->cgd.flags2 & T2_CLAMP_VEL) { - if (p->cgd.velocity.x < p->cgd.minVel.x) { - p->cgd.velocity.x = p->cgd.minVel.x; - } - if (p->cgd.velocity.y < p->cgd.minVel.y) { - p->cgd.velocity.y = p->cgd.minVel.y; - } - if (p->cgd.velocity.z < p->cgd.minVel.z) { - p->cgd.velocity.z = p->cgd.minVel.z; - } - - if (p->cgd.velocity.x > p->cgd.maxVel.x) { - p->cgd.velocity.x = p->cgd.maxVel.x; - } - if (p->cgd.velocity.y > p->cgd.maxVel.y) { - p->cgd.velocity.y = p->cgd.maxVel.y; - } - if (p->cgd.velocity.z > p->cgd.maxVel.z) { - p->cgd.velocity.z = p->cgd.maxVel.z; - } - } - - if (p->cgd.flags2 & T2_CLAMP_VEL_AXIS) { + p->cgd.velocity.x = Q_clamp_float(p->cgd.velocity.x, p->cgd.minVel.x, p->cgd.maxVel.x); + p->cgd.velocity.y = Q_clamp_float(p->cgd.velocity.y, p->cgd.minVel.y, p->cgd.maxVel.y); + p->cgd.velocity.z = Q_clamp_float(p->cgd.velocity.z, p->cgd.minVel.z, p->cgd.maxVel.z); + } else if (p->cgd.flags2 & T2_CLAMP_VEL_AXIS) { Vector localVelocity; localVelocity.x = DotProduct(p->cgd.velocity, p->ent.axis[0]); localVelocity.y = DotProduct(p->cgd.velocity, p->ent.axis[1]); localVelocity.z = DotProduct(p->cgd.velocity, p->ent.axis[2]); - if (localVelocity.x < p->cgd.minVel.x) { - localVelocity.x = p->cgd.minVel.x; - } - if (localVelocity.y < p->cgd.minVel.y) { - localVelocity.y = p->cgd.minVel.y; - } - if (localVelocity.z < p->cgd.minVel.z) { - localVelocity.z = p->cgd.minVel.z; - } - - if (localVelocity.x > p->cgd.maxVel.x) { - localVelocity.x = p->cgd.maxVel.x; - } - if (localVelocity.y > p->cgd.maxVel.y) { - localVelocity.y = p->cgd.maxVel.y; - } - if (localVelocity.z > p->cgd.maxVel.z) { - localVelocity.z = p->cgd.maxVel.z; - } + localVelocity.x = Q_clamp_float(localVelocity.x, p->cgd.minVel.x, p->cgd.maxVel.x); + localVelocity.y = Q_clamp_float(localVelocity.y, p->cgd.minVel.y, p->cgd.maxVel.y); + localVelocity.z = Q_clamp_float(localVelocity.z, p->cgd.minVel.z, p->cgd.maxVel.z); p->cgd.velocity.x = DotProduct(localVelocity, p->ent.axis[0]); p->cgd.velocity.y = DotProduct(localVelocity, p->ent.axis[1]); p->cgd.velocity.z = DotProduct(localVelocity, p->ent.axis[2]); } - if (p->cgd.flags2 & T_ALIGN) { - // FIXME: vss wind + if (p->cgd.flags2 & T2_WIND_AFFECT) { + for (i = 0; i < 3; i++) { + float fWind; + + switch (i) { + case 0: + fWind = vss_wind_x->value; + break; + case 1: + fWind = vss_wind_y->value; + break; + case 2: + fWind = vss_wind_z->value; + break; + } + + if (fWind < 0) { + if (p->cgd.velocity[i] > fWind) { + p->cgd.velocity[i] -= ftime * vss_wind_strength->value; + if (p->cgd.velocity[i] > fWind) { + p->cgd.velocity[i] = fWind; + } + } else if (p->cgd.velocity[i] < fWind) { + p->cgd.velocity[i] += ftime * vss_movement_dampen->value; + if (p->cgd.velocity[i] < fWind) { + p->cgd.velocity[i] = fWind; + } + } + } else { + if (p->cgd.velocity[i] < fWind) { + p->cgd.velocity[i] += ftime * vss_wind_strength->value; + if (p->cgd.velocity[i] > fWind) { + p->cgd.velocity[i] = fWind; + } + } else if (p->cgd.velocity[i] > fWind) { + p->cgd.velocity[i] -= ftime * vss_wind_strength->value; + if (p->cgd.velocity[i] < fWind) { + p->cgd.velocity[i] = fWind; + } + } + } + } } } else { - if (p->touchfcn) { - p->touchfcn(p, &trace); - } - - if (p->cgd.flags & T_DIETOUCH) { - return false; - } - Vector normal; // Set the origin @@ -581,14 +734,14 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime trace.endpos, trace.plane.normal, p->cgd.decal_orientation, + p->cgd.decal_radius, p->cgd.color[0], p->cgd.color[1], p->cgd.color[2], p->cgd.alpha, p->cgd.flags & T_FADE, - p->cgd.decal_radius, p->cgd.flags2 & T2_TEMPORARY_DECAL, - p->cgd.lightstyle, + qtrue, p->cgd.flags & T_FADEIN ); @@ -610,9 +763,10 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime dot = p->cgd.velocity * normal; p->cgd.velocity = p->cgd.velocity + ((-2 * dot) * normal); p->cgd.velocity *= p->cgd.bouncefactor; + p->cgd.avelocity *= -p->cgd.bouncefactor; // check for stop - if (trace.plane.normal[2] > 0 && p->cgd.velocity[2] < 40) { + if (trace.plane.normal[2] > 0 && p->cgd.velocity[2] < 45) { p->cgd.velocity = Vector(0, 0, 0); p->cgd.avelocity = Vector(0, 0, 0); p->cgd.flags &= ~T_WAVE; @@ -685,7 +839,7 @@ qboolean ClientGameCommandManager::LerpTempModel(refEntity_t *newEnt, ctempmodel // Add the parent ent's origin to the local origin VectorAdd(newEnt->origin, parentOrigin, newEnt->origin); } else { - if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) { + if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL) || (p->cgd.flags & T_SWARM)) { // Lerp the ent's origin for (i = 0; i < 3; i++) { newEnt->origin[i] = p->lastEnt.origin[i] + frac * (p->ent.origin[i] - p->lastEnt.origin[i]); @@ -741,16 +895,18 @@ void ClientGameCommandManager::AddTempModels(void) refEntity_t *old_ent; // To counteract cg.time going backwards - if (lastTempModelFrameTime) { - if ((cg.time < lastTempModelFrameTime) || (cg.time - lastTempModelFrameTime > TOO_MUCH_TIME_PASSED)) { - p = m_active_tempmodels.prev; - for (; p != &m_active_tempmodels; p = next) { - next = p->prev; - p->lastPhysicsTime = cg.time; - } - lastTempModelFrameTime = cg.time; - return; + if (lastTempModelFrameTime + && ((cg.time < lastTempModelFrameTime) || (cg.time - lastTempModelFrameTime > TOO_MUCH_TIME_PASSED))) { + p = m_active_tempmodels.prev; + for (; p != &m_active_tempmodels; p = next) { + next = p->prev; + p->lastPhysicsTime = cg.time; } + lastTempModelFrameTime = cg.time; + return; + } + + if (lastTempModelFrameTime) { frameTime = cg.time - lastTempModelFrameTime; } else { frameTime = 0; @@ -763,6 +919,7 @@ void ClientGameCommandManager::AddTempModels(void) } memset(&newEnt, 0, sizeof(newEnt)); + newEnt.parentEntity = ENTITYNUM_NONE; // Set this frame time for the next one effectTime = (float)frameTime / 1000.0f; effectTime2 = effectTime * effectTime; @@ -793,7 +950,7 @@ void ClientGameCommandManager::AddTempModels(void) current_tiki = p->cgd.tiki; current_entity_number = p->number; - TempModelRealtimeEffects(p, effectTime, effectTime2, scale); + TempModelRealtimeEffects(p, effectTime, scale); if (p->lastPhysicsTime) { mstime = cg.time - p->lastPhysicsTime; @@ -808,8 +965,7 @@ void ClientGameCommandManager::AddTempModels(void) if ((mstime >= physics_rate) || (p->cgd.flags2 & T2_PHYSICS_EVERYFRAME)) { ftime = mstime / 1000.0f; - time2 = ftime * ftime; - ret = TempModelPhysics(p, ftime, time2, scale); + ret = TempModelPhysics(p, ftime, scale); if (!ret) { FreeTempModel(p); @@ -823,9 +979,8 @@ void ClientGameCommandManager::AddTempModels(void) // Calculate the lerp value based on the time passed since last physics // time of this tempmodel lerpfrac = (float)(cg.time - p->lastPhysicsTime) / (float)physics_rate; - // Clamp - if (lerpfrac > 1) { + if (lerpfrac > 1 || (p->cgd.flags2 & T2_PHYSICS_EVERYFRAME)) { lerpfrac = 1; } if (lerpfrac < 0) { @@ -843,11 +998,10 @@ void ClientGameCommandManager::AddTempModels(void) // Run physics if the lastEnt is not valid to get a valid lerp if (!p->lastEntValid) { - float t, t2; - t = physics_rate / 1000.0f; - t2 = t * t; + float t; + t = physics_rate / 1000.0f; - ret = TempModelPhysics(p, t, t2, scale); + ret = TempModelPhysics(p, t, scale); if (!ret) { FreeTempModel(p); continue; @@ -872,12 +1026,12 @@ void ClientGameCommandManager::AddTempModels(void) } if (p->cgd.flags & T_WAVE) { - Vector origin; + vec3_t origin; float axis[3][3]; - origin = Vector(p->m_spawnthing->linked_origin) + Vector(p->m_spawnthing->linked_axis[0]) * newEnt.origin[0] - + Vector(p->m_spawnthing->linked_axis[1]) * newEnt.origin[1] - + Vector(p->m_spawnthing->linked_axis[2]) * newEnt.origin[2]; + VectorMA(p->m_spawnthing->linked_origin, newEnt.origin[0], p->m_spawnthing->linked_axis[0], origin); + VectorMA(origin, newEnt.origin[1], p->m_spawnthing->linked_axis[1], origin); + VectorMA(origin, newEnt.origin[2], p->m_spawnthing->linked_axis[2], origin); VectorCopy(origin, newEnt.origin); @@ -891,7 +1045,10 @@ void ClientGameCommandManager::AddTempModels(void) newEnt.reType = p->ent.reType; newEnt.shaderTime = p->ent.shaderTime; - newEnt.frameInfo[0] = p->ent.frameInfo[0]; + newEnt.frameInfo[0].index = p->ent.frameInfo[0].index; + newEnt.frameInfo[0].weight = 1.0; + newEnt.frameInfo[0].time = 0.0; + newEnt.wasframe = p->ent.wasframe; newEnt.actionWeight = 1.0; newEnt.entityNumber = ENTITYNUM_NONE; @@ -901,6 +1058,9 @@ void ClientGameCommandManager::AddTempModels(void) OtherTempModelEffects(p, newEnt.origin, &newEnt); + VectorCopy(newEnt.origin, newEnt.lightingOrigin); + newEnt.radius = 4.0; + // Add to the ref if (p->cgd.flags & T_DLIGHT) { // Tempmodel is a Dynamic Light @@ -960,6 +1120,14 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) Vector delta; Vector start; Vector vForward, vLeft, vUp; + float fDist; + + delta = m_spawnthing->cgd.origin - cg.refdef.vieworg; + fDist = delta * delta * (cg.refdef.fov_x * cg.refdef.fov_x / 6400.0); + if (fDist >= m_spawnthing->fMaxRangeSquared || fDist < m_spawnthing->fMinRangeSquared) { + // don't draw above the distance + return; + } if (current_entity) { current_entity_scale = current_entity->scale; @@ -1003,7 +1171,11 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) p = AllocateTempModel(); if (!p) { - cgi.DPrintf("Out of tempmodels\n"); + if (cgi.Milliseconds() >= next_tempmodel_warning) { + // make sure to not spam the console with this message + cgi.DPrintf("Out of tempmodels\n"); + next_tempmodel_warning = cgi.Milliseconds() + 1000; + } return; } @@ -1013,7 +1185,7 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) if (m_spawnthing->cgd.flags & T_WAVE) { p->m_spawnthing = m_spawnthing; m_spawnthing->numtempmodels++; - start = Vector(0, 0, 0); + start = Vector(0, 0, 0); } else { p->m_spawnthing = NULL; start = m_spawnthing->cgd.origin; @@ -1027,15 +1199,23 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) // Set up the origin of the tempmodel if (m_spawnthing->cgd.flags & T_SPHERE) { - // Create a random forward vector so the particles burst out in a - // sphere - newForward = Vector(crandom(), crandom(), crandom()); + do { + // Create a random forward vector so the particles burst out in a + // sphere + newForward = Vector(crandom(), crandom(), crandom()); + } while (newForward * newForward > 1.0); } else if (m_spawnthing->cgd.flags & T_CIRCLE) { if (m_spawnthing->sphereRadius != 0) // Offset by the radius { Vector dst; // Create a circular shaped burst around the up vector - float angle = ((float)count / (float)m_spawnthing->count) * 360; // * M_PI * 2; + float angle; + + if (mcount == 1) { + angle = random() * 360; + } else { + angle = ((float)count / (float)m_spawnthing->count) * 360; // * M_PI * 2; + } Vector end = Vector(vLeft) * m_spawnthing->sphereRadius * current_entity_scale; RotatePointAroundVector(dst, Vector(vForward), end, angle); @@ -1044,12 +1224,14 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) newForward = p->cgd.origin - m_spawnthing->cgd.origin; newForward.normalize(); } - } else if (m_spawnthing->cgd.flags & T_SPHERE) { + } else if (m_spawnthing->cgd.flags & T_INWARDSPHERE) { // Project the origin along a random ray, and set the forward // vector pointing back to the origin Vector dir, end; - dir = Vector(crandom(), crandom(), crandom()); + do { + dir = Vector(crandom(), crandom(), crandom()); + } while (dir * dir > 1.0); end = m_spawnthing->cgd.origin + dir * m_spawnthing->sphereRadius * current_entity_scale; VectorCopy(end, p->cgd.origin); @@ -1078,10 +1260,9 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) cosa = cos(fAngle); p->cgd.origin = start + vForward * fHeight; - p->cgd.origin += start + vLeft * (cosa * fRadius); - p->cgd.origin += start + vUp * (sina * fRadius); - } else if (m_spawnthing->sphereRadius != 0) // Offset in a spherical pattern - { + p->cgd.origin += vLeft * (cosa * fRadius); + p->cgd.origin += vUp * (sina * fRadius); + } else if (m_spawnthing->sphereRadius != 0) { // Offset in a spherical pattern Vector dir, end; dir = Vector(crandom(), crandom(), crandom()); @@ -1092,7 +1273,7 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) VectorCopy(end, p->cgd.origin); newForward = dir; } else { - VectorCopy(m_spawnthing->cgd.origin, p->cgd.origin); + VectorCopy(start, p->cgd.origin); } if (m_spawnthing->cgd.flags & T_SWARM && !(m_spawnthing->cgd.flags & (T_HARDLINK | T_PARENTLINK))) { @@ -1287,7 +1468,7 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) p->cgd.avelocity[i] = m_spawnthing->avelocity_amplitude[i] * random() + m_spawnthing->avelocity_base[i]; // Randomize angles or set absolute - p->cgd.angles[i] += random() * m_spawnthing->angles_amplitude[i]; + p->cgd.angles[i] = m_spawnthing->angles_amplitude[i] * random() + m_spawnthing->cgd.angles[i]; } // If forward velocity is set, just use that otherwise use random @@ -1321,18 +1502,15 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) } } - // Calculate one tick of velocity based on time alive ( passed in ) - p->cgd.origin = p->cgd.origin + (p->cgd.velocity * ((float)p->aliveTime / 1000.0f) * current_entity_scale); - - if (p->cgd.flags2 & T2_ACCEL) { + if (m_spawnthing->cgd.flags2 & T2_RADIALVELOCITY) { float fLength; p->cgd.velocity = p->cgd.origin - start; fLength = p->cgd.velocity.length(); if (fLength) { - float fVel = m_spawnthing->cgd.velocity.x - + (m_spawnthing->cgd.velocity.y + m_spawnthing->cgd.velocity.z * crandom()) / fLength; + float fVel = m_spawnthing->cgd.velocity[0] + + (m_spawnthing->cgd.velocity[1] + m_spawnthing->cgd.velocity[2] * random()) / fLength; p->cgd.velocity *= fVel; } @@ -1343,20 +1521,22 @@ void ClientGameCommandManager::SpawnTempModel(int mcount) (m_spawnthing->randvel_base[i] + m_spawnthing->randvel_amplitude[i] * random()) * current_entity_scale; if (m_spawnthing->cgd.flags & T_RANDVELAXIS) { - p->cgd.velocity += fVel * Vector(m_spawnthing->tag_axis[i]); + if (p->cgd.flags2 & T2_NOTAGAXIS) { + p->cgd.velocity += fVel * Vector(m_spawnthing->axis[i]); + } else { + p->cgd.velocity += fVel * Vector(m_spawnthing->tag_axis[i]); + } } else { p->cgd.velocity[i] += fVel; } } if (p->cgd.flags & (T_ALIGN | T_DETAIL)) { - if (p->cgd.velocity.x && p->cgd.velocity.y) { - p->cgd.angles = p->cgd.velocity.toAngles(); - } - - p->cgd.origin += p->cgd.velocity * (p->aliveTime / 1000.0) * current_entity_scale; + p->cgd.angles = p->cgd.velocity.toAngles(); } + p->cgd.origin += p->cgd.velocity * (p->aliveTime / 1000.0) * current_entity_scale; + if (p->cgd.flags & T_AUTOCALCLIFE) { Vector end, delta; float length, speed; diff --git a/code/cgame/cg_testemitter.cpp b/code/cgame/cg_testemitter.cpp index 3fc360fe..760cd55f 100644 --- a/code/cgame/cg_testemitter.cpp +++ b/code/cgame/cg_testemitter.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2023-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -26,6 +26,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_commands.h" #include "cg_specialfx.h" +typedef enum te_mode_e { + TE_MODE_EMITTER, + TE_MODE_MODEL_ANIM, + TE_MODE_MODEL_INIT, + TE_MODE_SFX, +} te_mode_t; + cvar_t *cg_te_alpha; cvar_t *cg_te_dietouch; cvar_t *cg_te_bouncefactor; @@ -101,6 +108,7 @@ cvar_t *cg_te_radial_scale; cvar_t *cg_te_radial_min; cvar_t *cg_te_radial_max; cvar_t *cg_te_friction; +cvar_t *cg_te_spin; // Added in 2.0 cvar_t *cg_te_varycolor; cvar_t *cg_te_spritegridlighting; cvar_t *cg_te_cone_height; @@ -113,18 +121,22 @@ cvar_t *cg_te_tag; cvar_t *cg_te_xangles; cvar_t *cg_te_yangles; cvar_t *cg_te_zangles; -class specialeffect_t; -refEntity_t te_refEnt; -cvar_t *cg_te_emittermodel; -cvar_t *cg_te_mode; -cvar_t *cg_te_mode_name; -cvar_t *cg_te_currCommand; -cvar_t *cg_te_numCommands; -float te_vEmitterOrigin[3]; -int te_iNumCommands; -int te_iCurrCommand; +cvar_t *cg_te_emittermodel; +cvar_t *cg_te_mode; +cvar_t *cg_te_mode_name; +cvar_t *cg_te_currCommand; +cvar_t *cg_te_numCommands; + +refEntity_t te_refEnt; +float te_vEmitterOrigin[3]; +int te_iNumCommands; +int te_iCurrCommand; + specialeffect_t *pTesteffect; +specialeffectcommand_t *pCurrCommand; +spawnthing_t *pCurrSpawnthing; + #define MAX_TESTEMITTERS_SAVE 32 str cg_te_alphaG[MAX_TESTEMITTERS_SAVE]; @@ -202,6 +214,7 @@ str cg_te_radial_scaleG[MAX_TESTEMITTERS_SAVE]; str cg_te_radial_minG[MAX_TESTEMITTERS_SAVE]; str cg_te_radial_maxG[MAX_TESTEMITTERS_SAVE]; str cg_te_frictionG[MAX_TESTEMITTERS_SAVE]; +str cg_te_spinG[MAX_TESTEMITTERS_SAVE]; // Added in 2.0 str cg_te_varycolorG[MAX_TESTEMITTERS_SAVE]; str cg_te_spritegridlightingG[MAX_TESTEMITTERS_SAVE]; str cg_te_spawnrange_aG[MAX_TESTEMITTERS_SAVE]; @@ -291,6 +304,7 @@ void CG_SaveEffectCommandCvars(int iCommand) cg_te_radial_minG[iCommand] = cg_te_radial_min->string; cg_te_radial_maxG[iCommand] = cg_te_radial_max->string; cg_te_frictionG[iCommand] = cg_te_friction->string; + cg_te_spinG[iCommand] = cg_te_spin->string; // Added in 2.0 cg_te_varycolorG[iCommand] = cg_te_varycolor->string; cg_te_spritegridlightingG[iCommand] = cg_te_spritegridlighting->string; cg_te_spawnrange_aG[iCommand] = cg_te_spawnrange_a->string; @@ -302,77 +316,1674 @@ void CG_SaveEffectCommandCvars(int iCommand) cg_te_tagG[iCommand] = cg_te_tag->string; } +void CG_GetEffectCommandCvars(int iCommand) +{ + cgi.Cvar_Set("cg_te_alpha", cg_te_alphaG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_dietouch", cg_te_dietouchG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_bouncefactor", cg_te_bouncefactorG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_scale", cg_te_scaleG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_scalemin", cg_te_scaleminG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_scalemax", cg_te_scalemaxG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_model", cg_te_modelG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_life", cg_te_lifeG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_color_r", cg_te_color_rG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_color_g", cg_te_color_gG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_color_b", cg_te_color_bG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_accel_x", cg_te_accel_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_accel_y", cg_te_accel_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_accel_z", cg_te_accel_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_count", cg_te_countG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_fade", cg_te_fadeG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_fadedelay", cg_te_fadedelayG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_fadein", cg_te_fadeinG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_spawnrate", cg_te_spawnrateG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_offsbase_x", cg_te_offsbase_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_offsbase_y", cg_te_offsbase_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_offsbase_z", cg_te_offsbase_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_offsamp_x", cg_te_offsamp_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_offsamp_y", cg_te_offsamp_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_offsamp_z", cg_te_offsamp_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_scalerate", cg_te_scalerateG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_circle", cg_te_circleG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_sphere", cg_te_sphereG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_insphere", cg_te_insphereG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_radius", cg_te_radiusG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_align", cg_te_alignG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_flickeralpha", cg_te_flickeralphaG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_collision", cg_te_collisionG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randomroll", cg_te_randomrollG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_anglesbase_p", cg_te_anglesbase_pG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_anglesbase_y", cg_te_anglesbase_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_anglesbase_r", cg_te_anglesbase_rG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_anglesamp_p", cg_te_anglesamp_pG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_anglesamp_y", cg_te_anglesamp_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_anglesamp_r", cg_te_anglesamp_rG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_forwardvel", cg_te_forwardvelG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randvelbase_x", cg_te_randvelbase_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randvelbase_y", cg_te_randvelbase_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randvelbase_z", cg_te_randvelbase_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randvelamp_x", cg_te_randvelamp_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randvelamp_y", cg_te_randvelamp_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randvelamp_z", cg_te_randvelamp_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelmin_x", cg_te_clampvelmin_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelmax_x", cg_te_clampvelmax_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelmin_y", cg_te_clampvelmin_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelmax_y", cg_te_clampvelmax_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelmin_z", cg_te_clampvelmin_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelmax_z", cg_te_clampvelmax_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_clampvelaxis", cg_te_clampvelaxisG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_volumetric", cg_te_volumetricG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_randaxis", cg_te_randaxisG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_axisoffsbase_x", cg_te_axisoffsbase_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_axisoffsbase_y", cg_te_axisoffsbase_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_axisoffsbase_z", cg_te_axisoffsbase_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_axisoffsamp_x", cg_te_axisoffsamp_xG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_axisoffsamp_y", cg_te_axisoffsamp_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_axisoffsamp_z", cg_te_axisoffsamp_zG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_swarm_freq", cg_te_swarm_freqG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_swarm_maxspeed", cg_te_swarm_maxspeedG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_swarm_delta", cg_te_swarm_deltaG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_avelbase_p", cg_te_avelbase_pG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_avelbase_y", cg_te_avelbase_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_avelbase_r", cg_te_avelbase_rG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_avelamp_p", cg_te_avelamp_pG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_avelamp_y", cg_te_avelamp_yG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_avelamp_r", cg_te_avelamp_rG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_radial_scale", cg_te_radial_scaleG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_radial_min", cg_te_radial_minG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_radial_max", cg_te_radial_maxG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_friction", cg_te_frictionG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_spin", cg_te_spinG[iCommand].c_str()); // Added in 2.0 + cgi.Cvar_Set("cg_te_varycolor", cg_te_varycolorG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_spritegridlighting", cg_te_spritegridlightingG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_spawnrange_a", cg_te_spawnrange_aG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_spawnrnage_b", cg_te_spawnrange_bG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_cone_height", cg_te_cone_heightG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_alignstretch_scale", cg_te_alignstretch_scaleG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_command_time", cg_te_command_timeG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_singlelinecommand", cg_te_singlelinecommandG[iCommand].c_str()); + cgi.Cvar_Set("cg_te_tag", cg_te_tagG[iCommand].c_str()); +} + void CG_ResetEffectCommandCvars() { - // FIXME: unimplemented + cgi.Cvar_Set("cg_te_alpha", "1"); + cgi.Cvar_Set("cg_te_dietouch", "0"); + cgi.Cvar_Set("cg_te_bouncefactor", "0.3"); + cgi.Cvar_Set("cg_te_scale", "1"); + cgi.Cvar_Set("cg_te_scalemin", "0"); + cgi.Cvar_Set("cg_te_scalemax", "0"); + cgi.Cvar_Set("cg_te_model", "none"); + cgi.Cvar_Set("cg_te_life", "1"); + cgi.Cvar_Set("cg_te_color_r", "1"); + cgi.Cvar_Set("cg_te_color_g", "1"); + cgi.Cvar_Set("cg_te_color_b", "1"); + cgi.Cvar_Set("cg_te_accel_x", "0"); + cgi.Cvar_Set("cg_te_accel_y", "0"); + cgi.Cvar_Set("cg_te_accel_z", "0"); + cgi.Cvar_Set("cg_te_count", "1"); + cgi.Cvar_Set("cg_te_fade", "0"); + cgi.Cvar_Set("cg_te_fadedelay", "0"); + cgi.Cvar_Set("cg_te_fadein", "0"); + cgi.Cvar_Set("cg_te_spawnrate", "1"); + cgi.Cvar_Set("cg_te_offsbase_x", "0"); + cgi.Cvar_Set("cg_te_offsbase_y", "0"); + cgi.Cvar_Set("cg_te_offsbase_z", "0"); + cgi.Cvar_Set("cg_te_offsamp_x", "0"); + cgi.Cvar_Set("cg_te_offsamp_y", "0"); + cgi.Cvar_Set("cg_te_offsamp_z", "0"); + cgi.Cvar_Set("cg_te_scalerate", "0"); + cgi.Cvar_Set("cg_te_circle", "0"); + cgi.Cvar_Set("cg_te_sphere", "0"); + cgi.Cvar_Set("cg_te_insphere", "0"); + cgi.Cvar_Set("cg_te_radius", "0"); + cgi.Cvar_Set("cg_te_align", "0"); + cgi.Cvar_Set("cg_te_flickeralpha", "0"); + cgi.Cvar_Set("cg_te_collision", "0"); + cgi.Cvar_Set("cg_te_randomroll", "0"); + cgi.Cvar_Set("cg_te_anglesbase_p", "0"); + cgi.Cvar_Set("cg_te_anglesbase_y", "0"); + cgi.Cvar_Set("cg_te_anglesbase_r", "0"); + cgi.Cvar_Set("cg_te_anglesamp_p", "0"); + cgi.Cvar_Set("cg_te_anglesamp_y", "0"); + cgi.Cvar_Set("cg_te_anglesamp_r", "0"); + cgi.Cvar_Set("cg_te_forwardvel", "0"); + cgi.Cvar_Set("cg_te_randvelbase_x", "0"); + cgi.Cvar_Set("cg_te_randvelbase_y", "0"); + cgi.Cvar_Set("cg_te_randvelbase_z", "0"); + cgi.Cvar_Set("cg_te_randvelamp_x", "0"); + cgi.Cvar_Set("cg_te_randvelamp_y", "0"); + cgi.Cvar_Set("cg_te_randvelamp_z", "0"); + cgi.Cvar_Set("cg_te_clampvelmin_x", "-9999"); + cgi.Cvar_Set("cg_te_clampvelmax_x", "9999"); + cgi.Cvar_Set("cg_te_clampvelmin_y", "-9999"); + cgi.Cvar_Set("cg_te_clampvelmax_y", "9999"); + cgi.Cvar_Set("cg_te_clampvelmin_z", "-9999"); + cgi.Cvar_Set("cg_te_clampvelmax_z", "9999"); + cgi.Cvar_Set("cg_te_clampvelaxis", "0"); + cgi.Cvar_Set("cg_te_volumetric", "0"); + cgi.Cvar_Set("cg_te_randaxis", "0"); + cgi.Cvar_Set("cg_te_axisoffsbase_x", "0"); + cgi.Cvar_Set("cg_te_axisoffsbase_y", "0"); + cgi.Cvar_Set("cg_te_axisoffsbase_z", "0"); + cgi.Cvar_Set("cg_te_axisoffsamp_x", "0"); + cgi.Cvar_Set("cg_te_axisoffsamp_y", "0"); + cgi.Cvar_Set("cg_te_axisoffsamp_z", "0"); + cgi.Cvar_Set("cg_te_swarm_freq", "0"); + cgi.Cvar_Set("cg_te_swarm_maxspeed", "0"); + cgi.Cvar_Set("cg_te_swarm_delta", "0"); + cgi.Cvar_Set("cg_te_avelbase_p", "0"); + cgi.Cvar_Set("cg_te_avelbase_y", "0"); + cgi.Cvar_Set("cg_te_avelbase_r", "0"); + cgi.Cvar_Set("cg_te_avelamp_p", "0"); + cgi.Cvar_Set("cg_te_avelamp_y", "0"); + cgi.Cvar_Set("cg_te_avelamp_r", "0"); + cgi.Cvar_Set("cg_te_radial_scale", "0"); + cgi.Cvar_Set("cg_te_radial_min", "0"); + cgi.Cvar_Set("cg_te_radial_max", "0"); + cgi.Cvar_Set("cg_te_friction", "0"); + cgi.Cvar_Set("cg_te_spin", "0"); // Added in 2.0 + cgi.Cvar_Set("cg_te_varycolor", "0"); + cgi.Cvar_Set("cg_te_spritegridlighting", "0"); + cgi.Cvar_Set("cg_te_spawnrange_a", "0"); + cgi.Cvar_Set("cg_te_spawnrange_b", "0"); + cgi.Cvar_Set("cg_te_cone_height", "0"); + cgi.Cvar_Set("cg_te_alignstretch_scale", "0"); + cgi.Cvar_Set("cg_te_command_time", "0"); + cgi.Cvar_Set("cg_te_singlelinecommand", ""); + cgi.Cvar_Set("cg_te_tag", ""); } void CG_SetTestEmitterValues() { - // FIXME: unimplemented + int i; + int iTagNum; + vec3_t vAngles; + vec3_t vOrigin; + vec3_t axis[3]; + + pCurrSpawnthing->cgd.flags2 |= T2_ACCEL | T2_AMOVE | T2_MOVE; + + if (te_refEnt.scale > 0 && Q_stricmp(cg_te_tag->string, "") && cg_te_mode->integer != TE_MODE_SFX) { + iTagNum = cgi.Tag_NumForName(te_refEnt.tiki, cg_te_tag->string); + } else { + iTagNum = -1; + } + + VectorCopy(te_vEmitterOrigin, vOrigin); + + if (iTagNum != -1) { + orientation_t oTag; + + oTag = cgi.TIKI_Orientation(&te_refEnt, iTagNum); + for (i = 0; i < 3; ++i) { + VectorMA(vOrigin, oTag.origin[i], te_refEnt.axis[i], vOrigin); + } + + R_ConcatRotations(oTag.axis, te_refEnt.axis, axis); + } else { + vAngles[0] = cg_te_xangles->value; + vAngles[1] = cg_te_yangles->value; + vAngles[2] = cg_te_zangles->value; + AnglesToAxis(vAngles, axis); + } + + VectorCopy(vOrigin, pCurrSpawnthing->cgd.origin); + pCurrSpawnthing->SetModel(cg_te_model->string); + + AxisCopy(axis, pCurrSpawnthing->axis); + + pCurrSpawnthing->cgd.alpha = cg_te_alpha->value; + pCurrSpawnthing->cgd.color[3] = cg_te_alpha->value; + pCurrSpawnthing->cgd.bouncefactor = cg_te_bouncefactor->value; + pCurrSpawnthing->cgd.scale = cg_te_scale->value; + pCurrSpawnthing->cgd.life = cg_te_life->value * 1000.0; + pCurrSpawnthing->cgd.color[0] = cg_te_color_r->value; + pCurrSpawnthing->cgd.color[1] = cg_te_color_g->value; + pCurrSpawnthing->cgd.color[2] = cg_te_color_b->value; + + if (cg_te_varycolor->integer) { + pCurrSpawnthing->cgd.flags2 |= T2_VARYCOLOR; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_VARYCOLOR; + } + + if (cg_te_spritegridlighting->integer) { + pCurrSpawnthing->cgd.flags2 |= T2_SPRITEGRIDLIGHTING; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_SPRITEGRIDLIGHTING; + } + + pCurrSpawnthing->cgd.accel[0] = cg_te_accel_x->value; + pCurrSpawnthing->cgd.accel[1] = cg_te_accel_y->value; + pCurrSpawnthing->cgd.accel[2] = cg_te_accel_z->value; + + pCurrSpawnthing->count = cg_te_count->value; + pCurrSpawnthing->spawnRate = 1.0 / cg_te_spawnrate->value * 1000.0; + + if (cg_te_spawnrange_a->value || cg_te_spawnrange_b->value) { + vAngles[0] = Square(cg_te_spawnrange_a->value); + vAngles[1] = Square(cg_te_spawnrange_b->value); + + if (vAngles[0] > vAngles[1]) { + pCurrSpawnthing->fMaxRangeSquared = vAngles[0]; + pCurrSpawnthing->fMinRangeSquared = vAngles[1]; + } else { + pCurrSpawnthing->fMinRangeSquared = vAngles[0]; + pCurrSpawnthing->fMaxRangeSquared = vAngles[2]; + } + } else { + pCurrSpawnthing->fMinRangeSquared = 0.0; + pCurrSpawnthing->fMaxRangeSquared = 9.9999997e37f; + } + + pCurrSpawnthing->cgd.scaleRate = cg_te_scalerate->value; + pCurrSpawnthing->sphereRadius = cg_te_radius->value; + + if (cg_te_cone_height->value) { + pCurrSpawnthing->cgd.flags2 |= T2_CONE; + pCurrSpawnthing->coneHeight = cg_te_cone_height->value; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_CONE; + } + + pCurrSpawnthing->forwardVelocity = cg_te_forwardvel->value; + if (cg_te_friction->value) { + pCurrSpawnthing->cgd.flags2 |= T2_FRICTION; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_FRICTION; + } + + // + // Added in 2.0 + // + if (cg_te_spin->value) { + pCurrSpawnthing->cgd.flags2 |= T2_SPIN; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_SPIN; + } + + pCurrSpawnthing->origin_offset_base[0] = cg_te_offsbase_x->value; + pCurrSpawnthing->origin_offset_base[1] = cg_te_offsbase_y->value; + pCurrSpawnthing->origin_offset_base[2] = cg_te_offsbase_z->value; + pCurrSpawnthing->origin_offset_amplitude[0] = cg_te_offsamp_x->value; + pCurrSpawnthing->origin_offset_amplitude[1] = cg_te_offsamp_y->value; + pCurrSpawnthing->origin_offset_amplitude[2] = cg_te_offsamp_z->value; + + pCurrSpawnthing->axis_offset_base[0] = cg_te_axisoffsbase_x->value; + pCurrSpawnthing->axis_offset_base[1] = cg_te_axisoffsbase_y->value; + pCurrSpawnthing->axis_offset_base[2] = cg_te_axisoffsbase_z->value; + pCurrSpawnthing->axis_offset_amplitude[0] = cg_te_axisoffsamp_x->value; + pCurrSpawnthing->axis_offset_amplitude[1] = cg_te_axisoffsamp_y->value; + pCurrSpawnthing->axis_offset_amplitude[2] = cg_te_axisoffsamp_z->value; + + pCurrSpawnthing->cgd.angles[0] = cg_te_anglesbase_p->value; + pCurrSpawnthing->cgd.angles[1] = cg_te_anglesbase_y->value; + pCurrSpawnthing->cgd.angles[2] = cg_te_anglesbase_r->value; + pCurrSpawnthing->angles_amplitude[0] = cg_te_anglesamp_p->value; + pCurrSpawnthing->angles_amplitude[1] = cg_te_anglesamp_y->value; + pCurrSpawnthing->angles_amplitude[2] = cg_te_anglesamp_r->value; + + if (!VectorCompare(pCurrSpawnthing->cgd.angles, vec_zero) + || !VectorCompare(pCurrSpawnthing->angles_amplitude, vec_zero)) { + pCurrSpawnthing->cgd.flags |= T_ANGLES; + } else { + pCurrSpawnthing->cgd.flags &= ~T_ANGLES; + } + + pCurrSpawnthing->avelocity_base[0] = cg_te_avelbase_p->value; + pCurrSpawnthing->avelocity_base[1] = cg_te_avelbase_y->value; + pCurrSpawnthing->avelocity_base[2] = cg_te_avelbase_r->value; + pCurrSpawnthing->avelocity_amplitude[0] = cg_te_avelamp_p->value; + pCurrSpawnthing->avelocity_amplitude[1] = cg_te_avelamp_y->value; + pCurrSpawnthing->avelocity_amplitude[2] = cg_te_avelamp_r->value; + + pCurrSpawnthing->randvel_base[0] = cg_te_randvelbase_x->value; + pCurrSpawnthing->randvel_base[1] = cg_te_randvelbase_y->value; + pCurrSpawnthing->randvel_base[2] = cg_te_randvelbase_z->value; + pCurrSpawnthing->randvel_amplitude[0] = cg_te_randvelamp_x->value; + pCurrSpawnthing->randvel_amplitude[1] = cg_te_randvelamp_y->value; + pCurrSpawnthing->randvel_amplitude[2] = cg_te_randvelamp_z->value; + + if (cg_te_randaxis->integer) { + pCurrSpawnthing->cgd.flags |= T_RANDVELAXIS; + } else { + pCurrSpawnthing->cgd.flags &= ~T_RANDVELAXIS; + } + + if (cg_te_radial_scale->value || cg_te_radial_min->value || cg_te_radial_max->value) { + pCurrSpawnthing->cgd.velocity[0] = cg_te_radial_scale->value; + pCurrSpawnthing->cgd.velocity[1] = cg_te_radial_min->value; + pCurrSpawnthing->cgd.velocity[2] = cg_te_radial_max->value; + pCurrSpawnthing->cgd.velocity[2] -= pCurrSpawnthing->cgd.velocity[1]; + + pCurrSpawnthing->cgd.flags2 |= T2_RADIALVELOCITY; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_RADIALVELOCITY; + } + + pCurrSpawnthing->cgd.minVel[0] = cg_te_clampvelmin_x->value; + pCurrSpawnthing->cgd.maxVel[0] = cg_te_clampvelmax_x->value; + pCurrSpawnthing->cgd.minVel[1] = cg_te_clampvelmin_y->value; + pCurrSpawnthing->cgd.maxVel[1] = cg_te_clampvelmax_y->value; + pCurrSpawnthing->cgd.minVel[2] = cg_te_clampvelmin_z->value; + pCurrSpawnthing->cgd.maxVel[2] = cg_te_clampvelmax_z->value; + pCurrSpawnthing->cgd.flags &= ~(T_GLOBALFADEIN | T_GLOBALFADEOUT); + + if (pCurrSpawnthing->cgd.minVel[0] > -9999 || pCurrSpawnthing->cgd.minVel[1] > -9999 + || pCurrSpawnthing->cgd.minVel[2] > -9999 || pCurrSpawnthing->cgd.maxVel[0] < 9999 + || pCurrSpawnthing->cgd.maxVel[1] < 9999 || pCurrSpawnthing->cgd.maxVel[2] < 9999) { + if (cg_te_clampvelaxis->value) { + pCurrSpawnthing->cgd.flags |= T_GLOBALFADEOUT; + } else { + pCurrSpawnthing->cgd.flags |= T_GLOBALFADEIN; + } + } + + pCurrSpawnthing->cgd.scalemin = cg_te_scalemin->value; + pCurrSpawnthing->cgd.scalemax = cg_te_scalemax->value; + if (pCurrSpawnthing->cgd.scalemin || pCurrSpawnthing->cgd.scalemax) { + pCurrSpawnthing->cgd.flags |= T_RANDSCALE; + } else { + pCurrSpawnthing->cgd.flags &= ~T_RANDSCALE; + } + + if (cg_te_dietouch->integer) { + pCurrSpawnthing->cgd.flags |= T_DIETOUCH; + } else { + pCurrSpawnthing->cgd.flags &= ~T_DIETOUCH; + } + + if (cg_te_fade->integer) { + pCurrSpawnthing->cgd.flags |= T_FADE; + } else { + pCurrSpawnthing->cgd.flags &= ~T_FADE; + } + + if (cg_te_fadedelay->integer > 0) { + pCurrSpawnthing->cgd.flags |= T_FADE; + pCurrSpawnthing->cgd.fadedelay = cg_te_fadedelay->value * 1000.0; + } + + if (cg_te_fadein->integer > 0) { + pCurrSpawnthing->cgd.flags |= T_FADEIN; + pCurrSpawnthing->cgd.fadeintime = cg_te_fadein->value * 1000.0; + } else { + pCurrSpawnthing->cgd.flags &= ~T_FADEIN; + } + + if (cg_te_circle->integer) { + pCurrSpawnthing->cgd.flags |= T_CIRCLE; + } else { + pCurrSpawnthing->cgd.flags &= ~T_CIRCLE; + } + + if (cg_te_sphere->integer) { + pCurrSpawnthing->cgd.flags |= T_SPHERE; + } else { + pCurrSpawnthing->cgd.flags &= ~T_SPHERE; + } + + if (cg_te_insphere->integer) { + pCurrSpawnthing->cgd.flags |= T_INWARDSPHERE; + } else { + pCurrSpawnthing->cgd.flags &= ~T_INWARDSPHERE; + } + + if (cg_te_align->integer) { + pCurrSpawnthing->cgd.flags |= T_ALIGN; + } else { + pCurrSpawnthing->cgd.flags &= ~T_ALIGN; + } + + if (cg_te_alignstretch_scale->integer) { + pCurrSpawnthing->cgd.flags |= T_ALIGN; + pCurrSpawnthing->cgd.flags2 |= T2_ALIGNSTRETCH; + pCurrSpawnthing->cgd.scale2 = cg_te_alignstretch_scale->value; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_ALIGNSTRETCH; + } + + if (cg_te_flickeralpha->integer) { + pCurrSpawnthing->cgd.flags |= T_FLICKERALPHA; + } else { + pCurrSpawnthing->cgd.flags &= ~T_FLICKERALPHA; + } + + if (cg_te_randomroll->integer) { + pCurrSpawnthing->cgd.flags |= T_RANDOMROLL; + } else { + pCurrSpawnthing->cgd.flags &= ~T_RANDOMROLL; + } + + if (cg_te_volumetric->integer) { + pCurrSpawnthing->cgd.flags2 |= T2_VOLUMETRIC; + } else { + pCurrSpawnthing->cgd.flags2 &= ~T2_VOLUMETRIC; + } + + if (cg_te_collision->integer == 2) { + pCurrSpawnthing->cgd.flags |= T_COLLISION; + pCurrSpawnthing->cgd.collisionmask = CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_WATER | CONTENTS_SOLID; + } else if (cg_te_collision->integer == 1 || (pCurrSpawnthing->cgd.flags & T_DIETOUCH)) { + pCurrSpawnthing->cgd.flags &= ~T_COLLISION; + pCurrSpawnthing->cgd.collisionmask = CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_SOLID; + } else { + pCurrSpawnthing->cgd.flags &= ~T_COLLISION; + pCurrSpawnthing->cgd.collisionmask = 0; + } + + if (cg_te_swarm_freq->integer > 0 && cg_te_swarm_maxspeed->value > 0 && cg_te_swarm_delta->value > 0) { + pCurrSpawnthing->cgd.swarmfreq = cg_te_swarm_freq->integer; + pCurrSpawnthing->cgd.swarmmaxspeed = cg_te_swarm_maxspeed->value; + pCurrSpawnthing->cgd.swarmdelta = cg_te_swarm_delta->value; + pCurrSpawnthing->cgd.flags |= T_SWARM; + pCurrSpawnthing->cgd.flags &= ~T_SPHERE; + } + + if (pCurrCommand) { + Event *pEvent; + int argcount; + + pCurrCommand->fCommandTime = cg_te_command_time->value; + pCurrCommand->endfcn = &ClientGameCommandManager::TestEffectEndFunc; + + if (pCurrCommand->pEvent) { + delete pCurrCommand->pEvent; + pCurrCommand->pEvent = NULL; + } + + if (Q_stricmp(cg_te_singlelinecommand->string, "")) { + cgi.Cmd_TokenizeString(cg_te_singlelinecommand->string); + + pEvent = new Event(cgi.Argv(0)); + + argcount = cgi.Argc(); + for (i = 1; i < argcount; i++) { + pEvent->AddToken(cgi.Argv(i)); + } + + pCurrCommand->pEvent = pEvent; + } + } } void CG_UpdateTestEmitter(void) { - // FIXME: unimplemented + int count; + Vector vAng; + Vector delta; + Vector end, end2; + Vector axis[3]; + emittertime_t *et = NULL; + + if (VectorCompare(te_vEmitterOrigin, vec_zero) || te_iNumCommands < 1) { + if (Q_stricmp(cg_te_mode_name->string, "Temp Emitter Off")) { + cgi.Cvar_Set("cg_te_mode_name", "Temp Emitter Off"); + } + return; + } + + cgi.Cvar_Set("cg_te_currCommand", va("%i", te_iCurrCommand + 1)); + cgi.Cvar_Set("cg_te_numCommands", va("%i", te_iNumCommands)); + + switch (cg_te_mode->integer) { + case TE_MODE_MODEL_ANIM: + cgi.Cvar_Set("cg_te_mode_name", "Model Anim Mode"); + break; + case TE_MODE_MODEL_INIT: + cgi.Cvar_Set("cg_te_mode_name", "Model Init Mode"); + break; + case TE_MODE_SFX: + cgi.Cvar_Set("cg_te_mode_name", "SFX Mode"); + break; + default: + cgi.Cvar_Set("cg_te_mode_name", "Emitter Mode"); + break; + } + + vAng[0] = cg_te_xangles->value; + vAng[1] = cg_te_yangles->value; + vAng[2] = cg_te_zangles->value; + AnglesToAxis(vAng, (vec3_t *)axis); + + end = te_vEmitterOrigin + axis[0] * 50; + cgi.R_DebugLine(te_vEmitterOrigin, end, 1.0, 0.0, 0.0, 1.0); + + end2 = end + axis[1] * 16 + axis[0] * -16; + cgi.R_DebugLine(end, end2, 1.0, 0.0, 0.0, 1.0); + + end2 = end + axis[1] * -16 + axis[0] * -16; + cgi.R_DebugLine(end, end2, 1.0, 0.0, 0.0, 1.0); + + if (cg_te_emittermodel->string[0]) { + // + // Initialize the entity + // + + memset(&te_refEnt, 0, sizeof(te_refEnt)); + te_refEnt.parentEntity = ENTITYNUM_NONE; + te_refEnt.scale = 1.0; + te_refEnt.shaderRGBA[0] = -1; + te_refEnt.shaderRGBA[1] = -1; + te_refEnt.shaderRGBA[2] = -1; + te_refEnt.shaderRGBA[3] = -1; + + // + // Setup transforms + // + + AxisCopy((const vec3_t *)axis, te_refEnt.axis); + VectorCopy(te_vEmitterOrigin, te_refEnt.origin); + VectorCopy(te_vEmitterOrigin, te_refEnt.lightingOrigin); + + // + // Setup the model + // + + te_refEnt.radius = 4.0; + te_refEnt.hModel = cgi.R_RegisterModel(cg_te_emittermodel->string); + te_refEnt.tiki = cgi.R_Model_GetHandle(te_refEnt.hModel); + + // + // Setup the shader + // + + if (!Q_stricmp(cg_te_emittermodel->string, "*beam")) { + te_refEnt.reType = RT_BEAM; + te_refEnt.customShader = cgi.R_RegisterShader("beamshader"); + } else if (strstr(cg_te_emittermodel->string, ".spr")) { + te_refEnt.reType = RT_SPRITE; + } else { + te_refEnt.reType = RT_MODEL; + } + + // + // Setup the animation + // + + te_refEnt.frameInfo[0].index = cgi.Anim_NumForName(te_refEnt.tiki, "idle"); + ; + if (te_refEnt.frameInfo[0].index < 0) { + te_refEnt.frameInfo[0].index = 0; + } + te_refEnt.frameInfo[0].weight = 1.0; + te_refEnt.frameInfo[0].time = 0.0; + te_refEnt.actionWeight = 1.0; + te_refEnt.entityNumber = ENTITYNUM_NONE; + + if (te_refEnt.reType == RT_SPRITE) { + cgi.R_AddRefSpriteToScene(&te_refEnt); + } else { + cgi.R_AddRefEntityToScene(&te_refEnt, ENTITYNUM_NONE); + } + } else { + te_refEnt.scale = 0.0; + } + + cg_te_currCommand = cgi.Cvar_Get("cg_te_currCommand", "0", 0); + cg_te_numCommands = cgi.Cvar_Get("cg_te_numCommands", "0", 0); + + if (cg_te_mode->integer != TE_MODE_EMITTER) { + return; + } + + pCurrCommand = pTesteffect->m_commands[te_iCurrCommand]; + if (!pCurrCommand) { + return; + } + + pCurrSpawnthing = pCurrCommand->emitter; + if (!pCurrSpawnthing) { + return; + } + + CG_SetTestEmitterValues(); + + et = pCurrSpawnthing->GetEmitTime(1); + if (!et->active) { + return; + } + + pCurrSpawnthing->cgd.createTime = cg.time; + + if (et->last_emit_time > 0 && pCurrSpawnthing->spawnRate != 0) { + float dtime; + float lerp; + float lerpfrac; + + dtime = cg.time - et->last_emit_time; + count = dtime / pCurrSpawnthing->spawnRate; + if (!count) { + return; + } + + if (count == 1) { + commandManager.SpawnEffect(1, pCurrSpawnthing); + et->last_emit_time = cg.time; + } else { + lerpfrac = 1.0 / count; + for (lerp = 0.0;; lerp = lerp + lerpfrac) { + if (dtime <= pCurrSpawnthing->spawnRate) { + break; + } + + et->last_emit_time = cg.time; + dtime = dtime - pCurrSpawnthing->spawnRate; + if (et->lerp_emitter) { + pCurrSpawnthing->cgd.origin = et->oldorigin + delta * lerp; + } + + commandManager.SpawnEffect(1, pCurrSpawnthing); + } + } + } else { + et->last_emit_time = cg.time; + } + + pCurrCommand = NULL; + pCurrSpawnthing = NULL; } void CG_SortEffectCommands() { - // FIXME: unimplemented + int j, k; + + for (j = 1; j < pTesteffect->m_iCommandCount; j++) { + for (k = 0; k < j; k++) { + if (pTesteffect->m_commands[k] > pTesteffect->m_commands[k + 1]) { + specialeffectcommand_t *command = pTesteffect->m_commands[k]; + + pTesteffect->m_commands[k] = pTesteffect->m_commands[k + 1]; + pTesteffect->m_commands[k + 1] = command; + } + } + } } void CG_TriggerTestEmitter_f(void) { - // FIXME: unimplemented + int i; + vec3_t axis[3]; + + if (!cg_te_mode->integer) { + return; + } + + if (!te_iNumCommands) { + return; + } + + CG_SaveEffectCommandCvars(te_iCurrCommand); + + for (i = 0; i < te_iNumCommands; ++i) { + pCurrCommand = pTesteffect->m_commands[i]; + if (!pCurrCommand) { + return; + } + + pCurrSpawnthing = pCurrCommand->emitter; + if (!pCurrSpawnthing) { + return; + } + + CG_GetEffectCommandCvars(i); + CG_SetTestEmitterValues(); + } + + CG_GetEffectCommandCvars(te_iCurrCommand); + CG_SortEffectCommands(); + + pCurrCommand = pTesteffect->m_commands[0]; + pCurrSpawnthing = pCurrCommand->emitter; + AxisCopy(pCurrSpawnthing->axis, axis); + + // Spawn the effect + sfxManager.MakeEffect_Axis(SFX_TEST_EFFECT, pCurrSpawnthing->cgd.origin, axis); + + pCurrCommand = NULL; + pCurrSpawnthing = NULL; } -void CG_DumpBaseAndAmplitude(str *buff, char *prefix, Vector *base, Vector *amplitude) +void CG_DumpBaseAndAmplitude(str *buff, const char *prefix, Vector *base, Vector *amplitude) { - // FIXME: unimplemented + int i; + + if ((*amplitude)[0] || (*amplitude)[1] || (*amplitude)[2]) { + *buff += prefix; + + for (i = 0; i < 3; i++) { + if (!(*amplitude)[i]) { + *buff += va(" %g", (*base)[i]); + } else if (!(*base)[i]) { + *buff += va(" random %g", (*amplitude)[i]); + } else if (-(*base)[i] == (*base)[i] + (*amplitude)[i]) { + *buff += va(" crandom %g", (*amplitude)[i] * 0.5); + } else { + *buff += va(" range %g %g", (*base)[i], (*amplitude)[i]); + } + } + + *buff += "\n"; + } else if ((*base)[0] || (*base)[1] || (*base)[2]) { + *buff += prefix; + *buff += va(" %g %g %g\n", (*base)[0], (*base)[1], (*base)[2]); + } } void CG_DumpEmitter_f(void) { - // FIXME: unimplemented + cvar_t *filename; + str buff; + str sTabbing; + str old_buff; + int iCurrCommand; + int iTagNum; + + if (te_iNumCommands < 1) { + return; + } + + filename = cgi.Cvar_Get("cg_te_filename", "dump/emitter.txt", 0); + switch (cg_te_mode->integer) { + case TE_MODE_MODEL_ANIM: + sTabbing = "\t\t\t"; + break; + case TE_MODE_MODEL_INIT: + sTabbing = "\t\t"; + break; + case TE_MODE_SFX: + sTabbing = "\t\t"; + break; + default: + sTabbing = "\t\t"; + break; + } + CG_SaveEffectCommandCvars(te_iCurrCommand); + + if (cg_te_mode->integer == TE_MODE_EMITTER) { + iCurrCommand = te_iCurrCommand; + } else { + iCurrCommand = 0; + } + + do { + pCurrCommand = pTesteffect->m_commands[iCurrCommand]; + if (!pCurrCommand) { + return; + } + + pCurrSpawnthing = pCurrCommand->emitter; + if (!pCurrSpawnthing) { + return; + } + + CG_GetEffectCommandCvars(iCurrCommand); + CG_SetTestEmitterValues(); + + if (te_refEnt.scale > 0 && Q_stricmp(cg_te_tag->string, "") && cg_te_mode->integer != TE_MODE_SFX) { + iTagNum = cgi.Tag_NumForName(te_refEnt.tiki, cg_te_tag->string); + } else { + iTagNum = -1; + } + + switch (cg_te_mode->integer) { + case TE_MODE_MODEL_ANIM: + buff += va("%s0", sTabbing.c_str()); + + if (pCurrCommand->fCommandTime > 0) { + buff += va("commanddelay %g ", pCurrCommand->fCommandTime); + } + + if (iTagNum != -1) { + buff += va("tagspawn %s\n", cg_te_tag->string); + } else { + buff += "originspawn\n"; + } + break; + case TE_MODE_MODEL_INIT: + buff += sTabbing; + + if (pCurrCommand->fCommandTime > 0) { + buff += va("commanddelay %g ", pCurrCommand->fCommandTime); + } + + if (iTagNum != -1) { + buff += va("tagspawn %s\n", cg_te_tag->string); + } else { + buff += "originspawn\n"; + } + break; + case TE_MODE_SFX: + buff += sTabbing; + + if (pCurrCommand->fCommandTime > 0) { + buff += va("delayedsfx %.3g originspawn\n", pCurrCommand->fCommandTime); + } else { + buff += "sfx originspawn\n"; + } + break; + default: + if (iTagNum != -1) { + buff += va("%stagemitter %s name%i\n", sTabbing.c_str(), cg_te_tag->string, iCurrCommand + 1); + } else { + buff += va("%soriginemitter name%i\n", sTabbing.c_str(), iCurrCommand + 1); + } + break; + } + + buff += sTabbing + "(\n"; + + if (pCurrSpawnthing->fMinRangeSquared > 0) { + buff += + va("%s\tspawnrange %i %i\n", + sTabbing.c_str(), + (int)sqrt(pCurrSpawnthing->fMinRangeSquared), + (int)sqrt(pCurrSpawnthing->fMaxRangeSquared)); + } else if (pCurrSpawnthing->fMaxRangeSquared > 0) { + buff += va("%s\tspawnrange %i\n", sTabbing.c_str(), (int)sqrt(pCurrSpawnthing->fMaxRangeSquared)); + } + + if (pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) { + buff += sTabbing + "\tvolumetric\n"; + } + + buff += va("%s\tspawnrate %g\n", sTabbing.c_str(), cg_te_spawnrate->value); + buff += va("%s\tmodel %s\n", sTabbing.c_str(), pCurrSpawnthing->m_modellist.ObjectAt(1).c_str()); + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) && pCurrSpawnthing->count > 1) { + buff += va("%s\tcount %i\n", sTabbing.c_str(), pCurrSpawnthing->count); + } + + if (pCurrSpawnthing->cgd.alpha != 1.0) { + buff += va("%s\talpha %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.alpha); + } + + buff += + va("%s\tcolor %g %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.color[0], + pCurrSpawnthing->cgd.color[1], + pCurrSpawnthing->cgd.color[2]); + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC)) { + if (pCurrSpawnthing->cgd.flags2 & T2_VARYCOLOR) { + buff += sTabbing + "\tvarycolor\n"; + } + if (pCurrSpawnthing->cgd.flags2 & T2_SPRITEGRIDLIGHTING) { + buff += sTabbing + "\tspritegridlighting\n"; + } + } + + if (pCurrSpawnthing->cgd.flags & T_COLLISION) { + if (pCurrSpawnthing->cgd.collisionmask & CONTENTS_WATER) { + buff += sTabbing + "\tcollision water\n"; + } else { + buff += sTabbing + "\tcollision\n"; + } + } + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) && (pCurrSpawnthing->cgd.flags & T_COLLISION)) { + buff += va("%s\tbouncefactor %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.bouncefactor); + } + + if (pCurrSpawnthing->cgd.scale != 1.0) { + buff += va("%s\tscale %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.scale); + } + + buff += va("%s\tlife %g\n", sTabbing.c_str(), cg_te_life->value); + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) && pCurrSpawnthing->cgd.scaleRate) { + buff + va("%s\tscalerate %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.scaleRate); + } + + if (pCurrSpawnthing->sphereRadius) { + if (cg_te_cone_height->value) { + buff += + va("%s\tcone %g %g\n", sTabbing.c_str(), pCurrSpawnthing->coneHeight, pCurrSpawnthing->sphereRadius + ); + } else { + buff += va("%s\tradius %g\n", sTabbing.c_str(), pCurrSpawnthing->sphereRadius); + } + } + + if (pCurrSpawnthing->forwardVelocity) { + buff += va("%s\tvelocity %g\n", sTabbing.c_str(), pCurrSpawnthing->forwardVelocity); + } + + if (pCurrSpawnthing->cgd.flags2 & T2_RADIALVELOCITY) { + buff += + va("%s\tradialvelocity %g %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.velocity[0], + pCurrSpawnthing->cgd.velocity[1], + pCurrSpawnthing->cgd.velocity[2]); + } + + if (pCurrSpawnthing->cgd.flags & T_RANDVELAXIS) { + CG_DumpBaseAndAmplitude( + &buff, + va("%s\trandvelaxis", sTabbing.c_str()), + &pCurrSpawnthing->randvel_base, + &pCurrSpawnthing->randvel_amplitude + ); + } else { + CG_DumpBaseAndAmplitude( + &buff, + va("%s\trandvel", sTabbing.c_str()), + &pCurrSpawnthing->randvel_base, + &pCurrSpawnthing->randvel_amplitude + ); + } + + if (pCurrSpawnthing->cgd.flags2 & T2_CLAMP_VEL) { + buff += + va("%s\tclampvel %g %g %g %g %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.minVel[0], + pCurrSpawnthing->cgd.maxVel[0], + pCurrSpawnthing->cgd.minVel[1], + pCurrSpawnthing->cgd.maxVel[1], + pCurrSpawnthing->cgd.minVel[2], + pCurrSpawnthing->cgd.maxVel[2]); + } else if (pCurrSpawnthing->cgd.flags2 & T2_CLAMP_VEL_AXIS) { + buff += + va("%s\tclampvelaxis %g %g %g %g %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.minVel[0], + pCurrSpawnthing->cgd.maxVel[0], + pCurrSpawnthing->cgd.minVel[1], + pCurrSpawnthing->cgd.maxVel[1], + pCurrSpawnthing->cgd.minVel[2], + pCurrSpawnthing->cgd.maxVel[2]); + } + + if (pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) { + if (pCurrSpawnthing->cgd.accel[0] || pCurrSpawnthing->cgd.accel[1] || pCurrSpawnthing->cgd.accel[2]) { + buff += + va("%s\tsmokeparms %g %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.accel[0], + pCurrSpawnthing->cgd.accel[1], + pCurrSpawnthing->cgd.accel[2]); + } + } else { + if (pCurrSpawnthing->cgd.accel[0] || pCurrSpawnthing->cgd.accel[1] || pCurrSpawnthing->cgd.accel[2]) { + buff += + va("%s\taccel %g %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.accel[0], + pCurrSpawnthing->cgd.accel[1], + pCurrSpawnthing->cgd.accel[2]); + } + } + + if (pCurrSpawnthing->cgd.flags2 & T2_FRICTION) { + buff += va("%s\tfriction %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.friction); + } + + if (pCurrSpawnthing->cgd.flags2 & T2_SPIN) { + buff += va("%s\tfriction %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.spin_rotation); + } + + CG_DumpBaseAndAmplitude( + &buff, + va("%s\toffset", sTabbing.c_str()), + &pCurrSpawnthing->origin_offset_base, + &pCurrSpawnthing->origin_offset_amplitude + ); + CG_DumpBaseAndAmplitude( + &buff, + va("%s\toffsetalongaxis", sTabbing.c_str()), + &pCurrSpawnthing->axis_offset_base, + &pCurrSpawnthing->axis_offset_amplitude + ); + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) && (pCurrSpawnthing->cgd.flags & T_ANGLES)) { + CG_DumpBaseAndAmplitude( + &buff, + va("%s\tangles", sTabbing.c_str()), + &pCurrSpawnthing->cgd.angles, + &pCurrSpawnthing->angles_amplitude + ); + } + + if (pCurrSpawnthing->cgd.flags2 & T2_AMOVE) { + CG_DumpBaseAndAmplitude( + &buff, + va("%s\tavelocity", sTabbing.c_str()), + &pCurrSpawnthing->avelocity_base, + &pCurrSpawnthing->avelocity_amplitude + ); + } + + if (pCurrSpawnthing->cgd.scalemin) { + buff += va("%s\tscalemin %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.scalemin); + } + if (pCurrSpawnthing->cgd.scalemax) { + buff += va("%s\tscalemax %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.scalemax); + } + + if (pCurrSpawnthing->cgd.flags & T_DIETOUCH) { + buff += sTabbing + "\tdietouch\n"; + } + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC)) { + if (pCurrSpawnthing->cgd.fadedelay > 0) { + buff += va("%s\tfadedelay %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.fadedelay / 1000.0); + } else if (pCurrSpawnthing->cgd.flags & T_FADE) { + buff += sTabbing + "\tfade\n"; + } + + if (pCurrSpawnthing->cgd.flags & T_FADEIN) { + buff += va("%s\tfadein %g\n", sTabbing.c_str(), pCurrSpawnthing->cgd.fadeintime / 1000.0); + } + } + + if (pCurrSpawnthing->cgd.flags & T_CIRCLE) { + buff += sTabbing + "\tcircle\n"; + } + if (pCurrSpawnthing->cgd.flags & T_SPHERE) { + buff += sTabbing + "\tsphere\n"; + } + if (pCurrSpawnthing->cgd.flags & T_INWARDSPHERE) { + buff += sTabbing + "\tinwardsphere\n"; + } + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC)) { + if (pCurrSpawnthing->cgd.flags2 & T2_ALIGNSTRETCH) { + buff += va("%s\talignstretch %g", sTabbing.c_str(), pCurrSpawnthing->cgd.scale2); + } else if (pCurrSpawnthing->cgd.flags & T_ALIGN) { + buff += sTabbing + "\talign\n"; + } + + if (pCurrSpawnthing->cgd.flags & T_FLICKERALPHA) { + buff += sTabbing + "\tflickeralpha\n"; + } + } + + if (pCurrSpawnthing->cgd.flags & T_RANDOMROLL) { + buff += sTabbing + "\trandomroll\n"; + } + + if (!(pCurrSpawnthing->cgd.flags2 & T2_VOLUMETRIC) && (pCurrSpawnthing->cgd.flags & T_SWARM)) { + buff += + va("%s\tswarm %i %g %g\n", + sTabbing.c_str(), + pCurrSpawnthing->cgd.swarmfreq, + pCurrSpawnthing->cgd.swarmmaxspeed, + pCurrSpawnthing->cgd.swarmdelta); + } + + buff += sTabbing + ")\n\n"; + + iCurrCommand++; + } while (iCurrCommand < te_iNumCommands && cg_te_mode->integer != TE_MODE_EMITTER); + + char *buffer; + str szTmp; + int iLen; + + iLen = cgi.FS_ReadFile(filename->string, (void **)&buffer, qfalse); + if (iLen != -1) { + char FBuf[512]; + + COM_StripExtension(filename->string, FBuf, sizeof(FBuf)); + szTmp = FBuf; + szTmp += ".old"; + + cgi.FS_WriteFile(szTmp.c_str(), buffer, iLen); + } + + cgi.FS_WriteTextFile(filename->string, buff.c_str(), buff.length()); + + pCurrSpawnthing = NULL; + + CG_GetEffectCommandCvars(te_iCurrCommand); } void CG_LoadBaseAndAmplitude( - char **pBufer, char *szCvarX, char *szCvarY, char *szCvarZ, char *szCvarXAmp, char *szCvarYAmp, char *szCvarZAmp + char **pBufer, + const char *szCvarX, + const char *szCvarY, + const char *szCvarZ, + const char *szCvarXAmp, + const char *szCvarYAmp, + const char *szCvarZAmp ) { - // FIXME: unimplemented + char com_token[MAX_TOKEN_CHARS]; + + const char *szCvarList[] = {szCvarX, szCvarY, szCvarZ}; + const char *szCvarAmpList[] = {szCvarXAmp, szCvarYAmp, szCvarZAmp}; + int i; + + // Fixed in OPM + // Use a loop rather than a copy-paste + + for (i = 0; i < 3; i++) { + Q_strncpyz(com_token, COM_ParseExt(pBufer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + return; + } + + if (!Q_stricmp(com_token, "random")) { + Q_strncpyz(com_token, COM_ParseExt(pBufer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + return; + } + + cgi.Cvar_Set(szCvarAmpList[i], com_token); + } else if (!Q_stricmp(com_token, "crandom")) { + float fTmp; + + Q_strncpyz(com_token, COM_ParseExt(pBufer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + return; + } + + fTmp = atof(com_token); + cgi.Cvar_Set(szCvarList[i], va("%g", -fTmp)); + cgi.Cvar_Set(szCvarAmpList[i], va("%g", fTmp * 2.0)); + } else if (!Q_stricmp(com_token, "range")) { + Q_strncpyz(com_token, COM_ParseExt(pBufer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + return; + } + cgi.Cvar_Set(szCvarList[i], com_token); + + Q_strncpyz(com_token, COM_ParseExt(pBufer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + return; + } + cgi.Cvar_Set(szCvarAmpList[i], com_token); + } + } } void CG_LoadEmitter_f(void) { - // FIXME: unimplemented + int iCommandCount; + char *buffer; + char *bufstart; + char com_token[MAX_TOKEN_CHARS]; + cvar_t *filename; + + if (te_iNumCommands <= 0) { + CG_TestEmitter_f(); + } else { + CG_SaveEffectCommandCvars(te_iCurrCommand); + } + filename = cgi.Cvar_Get("cg_te_filename", "dump/emitter.txt", 0); + + if (cgi.FS_ReadFile(filename->string, (void **)&buffer, qfalse) == -1) { + return; + } + + Com_Printf("Loading emitter dump '%s'\n", filename->string); + bufstart = buffer; + iCommandCount = 0; + + while ((Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token))), com_token[0]) { + iCommandCount++; + if (te_iNumCommands < iCommandCount) { + CG_NewEmitterCommand_f(); + } + + te_iCurrCommand = iCommandCount - 1; + pCurrCommand = pTesteffect->m_commands[iCommandCount - 1]; + if (!pCurrCommand) { + Com_Printf("Error loading effect dump\n"); + break; + } + + pCurrSpawnthing = pCurrCommand->emitter; + commandManager.InitializeSpawnthing(pCurrSpawnthing); + pCurrCommand->fCommandTime = 0.0; + CG_ResetEffectCommandCvars(); + + if (com_token[0] == '0') { + cgi.Cvar_Set("cg_te_mode", va("%i", 1)); + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + } else if (!Q_stricmp(com_token, "delayedsfx") || !Q_stricmp(com_token, "sfx")) { + cgi.Cvar_Set("cg_te_mode", va("%i", 3)); + if (!Q_stricmp(com_token, "delayedsfx")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + cgi.Cvar_Set("cg_te_command_time", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + } + } else if (!Q_stricmp(com_token, "tagemitter") || !Q_stricmp(com_token, "originemitter")) { + cgi.Cvar_Set("cg_te_mode", va("%i", 0)); + } else { + cgi.Cvar_Set("cg_te_mode", va("%i", 2)); + } + + if (!Q_stricmp(com_token, "commanddelay")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + cgi.Cvar_Set("cg_te_command_time", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + } + + if (!Q_stricmpn(com_token, "tag", 3)) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + cgi.Cvar_Set("cg_te_tag", com_token); + } + + while (COM_ParseExt(&buffer, qfalse)) {} + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); + if (Q_stricmp(com_token, "(")) { + Com_Printf("Error loading effect dump\n"); + break; + } + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); + if (!com_token[0]) { + Com_Printf("Error loading effect dump\n"); + break; + } + + while (Q_stricmp(com_token, ")")) { + if (!Q_stricmp(com_token, "spawnrange")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_spawnrange_a", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_spawnrange_b", com_token); + } + } + } else if (!Q_stricmp(com_token, "volumetric")) { + cgi.Cvar_Set("cg_te_volumetric", "1"); + } else if (!Q_stricmp(com_token, "spawnrate")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_spawnrate", com_token); + } + } else if (!Q_stricmp(com_token, "model")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_model", com_token); + } + } else if (!Q_stricmp(com_token, "count")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_count", com_token); + } + } else if (!Q_stricmp(com_token, "alpha")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_alpha", com_token); + } + } else if (!Q_stricmp(com_token, "color")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_color_r", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_color_g", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_color_b", com_token); + } + } + } + } else if (!Q_stricmp(com_token, "varycolor")) { + cgi.Cvar_Set("cg_te_varycolor", "1"); + } else if (!Q_stricmp(com_token, "spritegridlighting")) { + cgi.Cvar_Set("cg_te_spritegridlighting", "1"); + } else if (!Q_stricmp(com_token, "collision")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_collision", "1"); + } else { + cgi.Cvar_Set("cg_te_collision", "1"); + } + } else if (!Q_stricmp(com_token, "bouncefactor")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_alpha", com_token); + } + } else if (!Q_stricmp(com_token, "scale")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_alpha", com_token); + } + } else if (!Q_stricmp(com_token, "life")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_life", com_token); + } + } else if (!Q_stricmp(com_token, "scalerate")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_scalerate", com_token); + } + } else if (!Q_stricmp(com_token, "radius")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_radius", com_token); + } + } else if (!Q_stricmp(com_token, "cone")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_cone_height", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_radius", com_token); + } + } + } else if (!Q_stricmp(com_token, "velocity")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_forwardvel", com_token); + } + } else if (!Q_stricmp(com_token, "radialvelocity")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_radial_scale", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_radial_min", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_radial_max", com_token); + } + } + } + } else if (!Q_stricmp(com_token, "randvelaxis") || !Q_stricmp(com_token, "randvel")) { + if (!Q_stricmp(com_token, "randvelaxis")) { + cgi.Cvar_Set("cg_te_randaxis", "1"); + + CG_LoadBaseAndAmplitude( + &buffer, + "cg_te_randvelbase_x", + "cg_te_randvelbase_y", + "cg_te_randvelbase_z", + "cg_te_randvelamp_x", + "cg_te_randvelamp_y", + "cg_te_randvelamp_z" + ); + } + } else if (!Q_stricmp(com_token, "clampvel") || !Q_stricmp(com_token, "clampvelaxis")) { + if (!Q_stricmp(com_token, "clampvelaxis")) { + cgi.Cvar_Set("cg_te_clampvelaxis", "1"); + } + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_clampvelmin_x", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_clampvelmax_x", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_clampvelmin_y", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_clampvelmax_y", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_clampvelmin_z", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_clampvelmax_z", com_token); + } + } + } + } + } + } + } else if (!Q_stricmp(com_token, "accel") || !Q_stricmp(com_token, "smokeparms")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_accel_x", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_accel_y", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_accel_z", com_token); + } + } + } + } else if (!Q_stricmp(com_token, "friction")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_friction", com_token); + } + // Added in 2.0 + // spin + } else if (!Q_stricmp(com_token, "spin")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_spin", com_token); + } + } else if (!Q_stricmp(com_token, "offset")) { + CG_LoadBaseAndAmplitude( + &buffer, + "cg_te_offsbase_x", + "cg_te_offsbase_y", + "cg_te_offsbase_z", + "cg_te_offsamp_x", + "cg_te_offsamp_y", + "cg_te_offsamp_z" + ); + } else if (!Q_stricmp(com_token, "offsetalongaxis")) { + CG_LoadBaseAndAmplitude( + &buffer, + "cg_te_axisoffsbase_x", + "cg_te_axisoffsbase_y", + "cg_te_axisoffsbase_z", + "cg_te_axisoffsamp_x", + "cg_te_axisoffsamp_y", + "cg_te_axisoffsamp_z" + ); + } else if (!Q_stricmp(com_token, "angles")) { + CG_LoadBaseAndAmplitude( + &buffer, + "cg_te_anglesbase_p", + "cg_te_anglesbase_y", + "cg_te_anglesbase_r", + "cg_te_anglesamp_p", + "cg_te_anglesamp_y", + "cg_te_anglesamp_r" + ); + } else if (!Q_stricmp(com_token, "avelocity")) { + CG_LoadBaseAndAmplitude( + &buffer, + "cg_te_avelbase_p", + "cg_te_avelbase_y", + "cg_te_avelbase_r", + "cg_te_avelamp_p", + "cg_te_avelamp_y", + "cg_te_avelamp_r" + ); + } else if (!Q_stricmp(com_token, "scalemin")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_scalemin", com_token); + } + } else if (!Q_stricmp(com_token, "scalemax")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_scalemax", com_token); + } + } else if (!Q_stricmp(com_token, "dietouch")) { + cgi.Cvar_Set("cg_te_dietouch", "1"); + } else if (!Q_stricmp(com_token, "fade")) { + cgi.Cvar_Set("cg_te_fade", "1"); + } else if (!Q_stricmp(com_token, "fadedelay")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_fadedelay", com_token); + } + } else if (!Q_stricmp(com_token, "fadein")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_fadein", com_token); + } + } else if (!Q_stricmp(com_token, "circle")) { + cgi.Cvar_Set("cg_te_circle", "1"); + } else if (!Q_stricmp(com_token, "sphere")) { + cgi.Cvar_Set("cg_te_sphere", "1"); + } else if (!Q_stricmp(com_token, "inwardsphere")) { + cgi.Cvar_Set("cg_te_insphere", "1"); + } else if (!Q_stricmp(com_token, "align")) { + cgi.Cvar_Set("cg_te_align", "1"); + } else if (!Q_stricmp(com_token, "alignstretch")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_alignstretch_scale", com_token); + } + } else if (!Q_stricmp(com_token, "flickeralpha")) { + cgi.Cvar_Set("cg_te_flickeralpha", "1"); + } else if (!Q_stricmp(com_token, "randomroll")) { + cgi.Cvar_Set("cg_te_randomroll", "1"); + } else if (!Q_stricmp(com_token, "swarm")) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_swarm_freq", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_swarm_maxspeed", com_token); + + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (com_token[0]) { + cgi.Cvar_Set("cg_te_swarm_delta", com_token); + } + } + } + } + } + + CG_SaveEffectCommandCvars(te_iCurrCommand); + } + + cgi.FS_FreeFile(bufstart); + return; } void CG_TestEmitter_f(void) { - // FIXME: unimplemented + vec3_t angles; + + if (!pTesteffect->m_iCommandCount) { + pCurrCommand = pTesteffect->AddNewCommand(); + if (!pCurrCommand) { + return; + } + + pCurrSpawnthing = new spawnthing_t(); + pCurrCommand->emitter = pCurrSpawnthing; + commandManager.InitializeSpawnthing(pCurrSpawnthing); + + te_iNumCommands++; + } + + assert(pCurrSpawnthing); + + VectorMA(cg.refdef.vieworg, 100.0, cg.refdef.viewaxis[0], te_vEmitterOrigin); + VectorSet(angles, 0, cg.refdefViewAngles[1], 0); + AnglesToAxis(angles, pCurrSpawnthing->axis); + + pCurrSpawnthing->cgd.tiki = NULL; + CG_SetTestEmitterValues(); + + pCurrCommand = NULL; + pCurrSpawnthing = NULL; } void CG_PrevEmitterCommand_f(void) { - // FIXME: unimplemented + CG_SaveEffectCommandCvars(te_iCurrCommand); + + te_iCurrCommand--; + if (te_iCurrCommand < 0) { + te_iCurrCommand = te_iNumCommands - 1; + } + + CG_GetEffectCommandCvars(te_iCurrCommand); } void CG_NextEmitterCommand_f(void) { - // FIXME: unimplemented + CG_SaveEffectCommandCvars(te_iCurrCommand); + + te_iCurrCommand++; + if (te_iCurrCommand >= te_iNumCommands) { + te_iCurrCommand = 0; + } + + CG_GetEffectCommandCvars(te_iCurrCommand); } void CG_NewEmitterCommand_f(void) { - // FIXME: unimplemented + if (te_iNumCommands >= MAX_TESTEMITTERS_SAVE) { + Com_Printf("Test effect can not have more than %i effect commands\n", MAX_TESTEMITTERS_SAVE); + return; + } + + pCurrCommand = pTesteffect->AddNewCommand(); + if (!pCurrCommand) { + return; + } + + pCurrSpawnthing = new spawnthing_t(); + pCurrCommand->emitter = pCurrSpawnthing; + commandManager.InitializeSpawnthing(pCurrSpawnthing); + + te_iNumCommands++; + CG_SaveEffectCommandCvars(te_iCurrCommand); + + te_iCurrCommand = te_iNumCommands - 1; + CG_GetEffectCommandCvars(te_iCurrCommand); + + Com_Printf("Test effect now has %i effect commands\n", te_iNumCommands); } -void CG_DeleteEmitterCommand_f(void) -{ - // FIXME: unimplemented -} +void CG_DeleteEmitterCommand_f(void) {} void CG_InitTestEmitter(void) { @@ -452,6 +2063,7 @@ void CG_InitTestEmitter(void) cg_te_radial_min = cgi.Cvar_Get("cg_te_radial_min", "0", 0); cg_te_radial_max = cgi.Cvar_Get("cg_te_radial_max", "0", 0); cg_te_friction = cgi.Cvar_Get("cg_te_friction", "0", 0); + cg_te_spin = cgi.Cvar_Get("cg_te_spin", "0", 0); // Added in 2.0 cg_te_varycolor = cgi.Cvar_Get("cg_te_varycolor", "0", 0); cg_te_spritegridlighting = cgi.Cvar_Get("cg_te_spritegridlighting", "0", 0); cg_te_spawnrange_a = cgi.Cvar_Get("cg_te_spawnrange_a", "0", 0); @@ -473,14 +2085,12 @@ void CG_InitTestEmitter(void) cg_te_mode = cgi.Cvar_Get("cg_te_mode", "0", 0); cg_te_mode_name = cgi.Cvar_Get("cg_te_mode_name", "Emitter Mode", 0); cg_te_currCommand = cgi.Cvar_Get("cg_te_currCommand", "0", 0); + cg_te_numCommands = cgi.Cvar_Get("cg_te_numCommands", "0", 0); - te_vEmitterOrigin[2] = 0.0; - te_vEmitterOrigin[1] = 0.0; - te_vEmitterOrigin[0] = 0.0; - te_refEnt.scale = 0.0; - cg_te_numCommands = cgi.Cvar_Get("cg_te_numCommands", "0", 0); - te_iNumCommands = 0; - te_iCurrCommand = 0; + VectorClear(te_vEmitterOrigin); + te_refEnt.scale = 0.0; + te_iNumCommands = 0; + te_iCurrCommand = 0; pTesteffect = sfxManager.GetTestEffectPointer(); } diff --git a/code/cgame/cg_ui.cpp b/code/cgame/cg_ui.cpp index aec50df4..c884fc97 100644 --- a/code/cgame/cg_ui.cpp +++ b/code/cgame/cg_ui.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_local.h" #include "str.h" +#include "../client/keycodes.h" void CG_MessageMode_f(void) { @@ -61,8 +62,8 @@ void CG_MessageMode_Private_f(void) return; } - clientNum = atoi(cgi.Argv(1)) - 1; - if (clientNum < 0 || clientNum >= MAX_CLIENTS) { + clientNum = atoi(cgi.Argv(1)); + if (clientNum < 1 || clientNum >= MAX_CLIENTS) { cgi.Printf(HUD_MESSAGE_CHAT_WHITE "Message Error: %s is a bad client number\n", cgi.Argv(1)); return; } @@ -119,7 +120,7 @@ void CG_MessageSingleClient_f(void) // copy the rest for (i = 2; i < cgi.Argc(); i++) { - sString += va("%s", cgi.Argv(i)); + sString += va(" %s", cgi.Argv(i)); } sString += "\n"; @@ -189,11 +190,39 @@ void CG_InstaMessageGroupE_f(void) void CG_HudPrint_f(void) { - cgi.Printf("\x1%s", cgi.Argv(0)); + cgi.Printf("\x1%s", cgi.Argv(1)); } -int CG_CheckCaptureKey(int key, qboolean down, unsigned int time) +qboolean CG_CheckCaptureKey(int key, qboolean down, unsigned int time) { - // FIXME: unimplemented - return 0; + char minKey = '1', maxKey = '9'; + + if (!cg.iInstaMessageMenu || !down) { + return qfalse; + } + + if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + maxKey = '8'; + } + + if (key < minKey || key > maxKey) { + if (key == K_ESCAPE || key == '0') { + cg.iInstaMessageMenu = 0; + return qtrue; + } + return qfalse; + } + + if (cg.iInstaMessageMenu == -1) { + if (key > '6') { + cg.iInstaMessageMenu = 0; + } else { + cg.iInstaMessageMenu = key - '0'; + } + } else if (cg.iInstaMessageMenu > 0) { + cgi.SendClientCommand(va("dmmessage 0 *%i%i\n", cg.iInstaMessageMenu, key - '0')); + cg.iInstaMessageMenu = 0; + } + + return qtrue; } diff --git a/code/cgame/cg_view.c b/code/cgame/cg_view.c index ec2ce010..8da21cac 100644 --- a/code/cgame/cg_view.c +++ b/code/cgame/cg_view.c @@ -242,6 +242,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition) float mat[3][3]; vec3_t vOldOrigin; vec3_t vStart, vEnd, vMins, vMaxs; + vec3_t vVelocity; trace_t trace; VectorSet(vMins, -6, -6, -6); @@ -297,6 +298,15 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition) VectorCopy(origin, vOldOrigin); + if (!cg.predicted_player_state.walking || (!(cg.predicted_player_state.pm_flags & PMF_FROZEN) && !(cg.predicted_player_state.pm_flags & PMF_NO_MOVE))) { + VectorCopy(cg.predicted_player_state.velocity, vVelocity); + } else { + // + // Added in OPM + // When frozen, there must be no movement at all + VectorClear(vVelocity); + } + if (bUseWorldPosition) { iMask = MASK_VIEWSOLID; } else { @@ -367,7 +377,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition) } if (cg.predicted_player_state.walking) { - fVel = VectorLength(cg.predicted_player_state.velocity); + fVel = VectorLength(vVelocity); fPhase = fVel * 0.0015 + 0.9; cg.fCurrentViewBobPhase += (cg.frametime / 1000.0 + cg.frametime / 1000.0) * M_PI * fPhase; @@ -446,7 +456,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition) AngleVectorsLeft(vDelta, mat[0], mat[1], mat[2]); CG_CalcViewModelMovement( - cg.fCurrentViewBobPhase, cg.fCurrentViewBobAmp, cg.predicted_player_state.velocity, vDelta + cg.fCurrentViewBobPhase, cg.fCurrentViewBobAmp, vVelocity, vDelta ); VectorMA(pREnt->origin, vDelta[0], mat[0], pREnt->origin); @@ -475,9 +485,16 @@ static int CG_CalcFov(void) int contents; float fov_x, fov_y; int inwater; + float fov_ratio; - fov_x = cg.camera_fov; - x = cg.refdef.width / tan(fov_x / 360 * M_PI); + fov_ratio = (float)cg.refdef.width / (float)cg.refdef.height * (3.0 / 4.0); + if (fov_ratio == 1) { + fov_x = cg.camera_fov; + } else { + fov_x = RAD2DEG(atan(tan(DEG2RAD(cg.camera_fov / 2.0)) * fov_ratio)) * 2.0; + } + + x = cg.refdef.width / tan(fov_x / 360 * M_PI); fov_y = atan2(cg.refdef.height, x); fov_y = fov_y * 360 / M_PI; @@ -504,6 +521,44 @@ static int CG_CalcFov(void) return inwater; } +/* +=============== +CG_SetupFog + +Prepares fog values for rendering +=============== +*/ +void CG_SetupFog() { + cg.refdef.farplane_distance = cg.farplane_distance; + cg.refdef.farplane_bias = cg.farplane_bias; + cg.refdef.farplane_color[0] = cg.farplane_color[0]; + cg.refdef.farplane_color[1] = cg.farplane_color[1]; + cg.refdef.farplane_color[2] = cg.farplane_color[2]; + cg.refdef.farplane_cull = cg.farplane_cull; + cg.refdef.skybox_farplane = cg.skyboxFarplane; + cg.refdef.renderTerrain = cg.renderTerrain; + cg.refdef.farclipOverride = cg.farclipOverride; + cg.refdef.farplaneColorOverride[0] = cg.farplaneColorOverride[0]; + cg.refdef.farplaneColorOverride[1] = cg.farplaneColorOverride[1]; + cg.refdef.farplaneColorOverride[2] = cg.farplaneColorOverride[2]; +} + +/* +=============== +CG_SetupPortalSky + +Sets portalsky values for rendering +=============== +*/ +void CG_SetupPortalSky() { + cg.refdef.sky_alpha = cg.sky_alpha; + cg.refdef.sky_portal = cg.sky_portal; + VectorCopy(cg.sky_axis[0], cg.refdef.sky_axis[0]); + VectorCopy(cg.sky_axis[1], cg.refdef.sky_axis[1]); + VectorCopy(cg.sky_axis[2], cg.refdef.sky_axis[2]); + VectorMA(cg.sky_origin, cg.skyboxSpeed, cg.refdef.vieworg, cg.refdef.sky_origin); +} + /* =============== CG_CalcViewValues @@ -520,17 +575,7 @@ static int CG_CalcViewValues(void) // calculate size of 3D view CG_CalcVrect(); - - // setup fog and far clipping plane - cg.refdef.farplane_distance = cg.farplane_distance; - VectorCopy(cg.farplane_color, cg.refdef.farplane_color); - cg.refdef.farplane_cull = cg.farplane_cull; - - // setup portal sky - cg.refdef.sky_alpha = cg.sky_alpha; - cg.refdef.sky_portal = cg.sky_portal; - memcpy(cg.refdef.sky_axis, cg.sky_axis, sizeof(cg.sky_axis)); - VectorCopy(cg.sky_origin, cg.refdef.sky_origin); + CG_SetupFog(); ps = &cg.predicted_player_state; @@ -604,7 +649,9 @@ static int CG_CalcViewValues(void) // Set the aural axis of the player VectorCopy(cg.refdefViewAngles, SoundAngles); // yaw is purposely inverted because of the miles sound system - SoundAngles[YAW] = -SoundAngles[YAW]; + // Commented out in OPM + // Useless as SDL audio/AL is used + //SoundAngles[YAW] = -SoundAngles[YAW]; AnglesToAxis(SoundAngles, cg.SoundAxis); // decide on third person view @@ -623,6 +670,11 @@ static int CG_CalcViewValues(void) // Set the aural axis to the camera's angles VectorCopy(cg.camera_angles, cg.refdefViewAngles); + if (cg_protocol >= PROTOCOL_MOHTA_MIN && (ps->pm_flags & PMF_DAMAGE_ANGLES)) { + // Handle camera shake + VectorSubtract(cg.refdefViewAngles, cg.predicted_player_state.damage_angles, cg.refdefViewAngles); + } + if (ps->camera_posofs[0] || ps->camera_posofs[1] || ps->camera_posofs[2]) { vec3_t vAxis[3], vOrg; AnglesToAxis(cg.refdefViewAngles, vAxis); @@ -633,6 +685,9 @@ static int CG_CalcViewValues(void) // copy view values VectorCopy(cg.refdef.vieworg, cg.currentViewPos); VectorCopy(cg.refdefViewAngles, cg.currentViewAngles); + // since 2.0: also copy location data for sound + VectorCopy(cg.refdef.vieworg, cg.SoundOrg); + AnglesToAxis(cg.refdefViewAngles, cg.SoundAxis); } // position eye reletive to origin @@ -674,7 +729,37 @@ float CG_SensitivityScale() void CG_AddLightShow() { - // FIXME: unimplemented + int i; + float fSlopeY, fSlopeZ; + float x, y, z; + vec3_t vOrg; + float r, g, b; + float fMax; + + fSlopeY = tan(cg.refdef.fov_x * 0.5); + fSlopeZ = tan(cg.refdef.fov_y * 0.5); + + for (i = 0; i < cg_acidtrip->integer; i++) { + x = pow(random(), 1.0 / 3.0) * 2048.0; + y = crandom() * x * fSlopeY; + z = crandom() * x * fSlopeZ; + + VectorCopy(cg.refdef.vieworg, vOrg); + VectorMA(vOrg, x, cg.refdef.viewaxis[0], vOrg); + VectorMA(vOrg, y, cg.refdef.viewaxis[1], vOrg); + VectorMA(vOrg, z, cg.refdef.viewaxis[2], vOrg); + + r = random(); + g = random(); + b = random(); + + fMax = Q_max(r, Q_max(g, b)); + r /= fMax; + g /= fMax; + b /= fMax; + + cgi.R_AddLightToScene(vOrg, (rand() & 0x1FF) + 0x80, r, g, b, 0); + } } qboolean CG_FrustumCullSphere(const vec3_t vPos, float fRadius) { @@ -762,6 +847,15 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, // no entities should be marked as interpolating } + // + // Added in OPM + // Clamp the fov to avoid artifacts + if (cg_fov->value < 65) { + cgi.Cvar_Set("cg_fov", "65"); + } else if (cg_fov->value > 120) { + cgi.Cvar_Set("cg_fov", "120"); + } + // update cg.predicted_player_state CG_PredictPlayerState(); @@ -774,10 +868,46 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, CG_ScoresDown_f(); } else if (cg.bIntermissionDisplay) { if (cg.nextSnap) { - if (cgi.Cvar_Get("g_success", "", 0)->integer) { - cgi.UI_ShowMenu("StatsScreen_Success", qfalse); + if (cg_protocol >= PROTOCOL_MOHTA_MIN) { + cvar_t* pMission = cgi.Cvar_Get("g_mission", "", CVAR_ARCHIVE); + + if (cgi.Cvar_Get("g_success", "", 0)->integer) { + switch (pMission->integer) + { + default: + case 0: + cgi.UI_ShowMenu("mission_success_1", 0); + cgi.Cvar_Set("g_t2l1", "1"); + break; + case 2: + cgi.UI_ShowMenu("mission_success_2", 0); + cgi.Cvar_Set("g_t3l1", "1"); + break; + case 3: + cgi.UI_ShowMenu("mission_success_3", 0); + break; + } + } else { + switch (pMission->integer) + { + default: + case 0: + cgi.UI_ShowMenu("mission_failed_1", 0); + break; + case 2: + cgi.UI_ShowMenu("mission_failed_2", 0); + break; + case 3: + cgi.UI_ShowMenu("mission_failed_3", 0); + break; + } + } } else { - cgi.UI_ShowMenu("StatsScreen_Failed", qfalse); + if (cgi.Cvar_Get("g_success", "", 0)->integer) { + cgi.UI_ShowMenu("StatsScreen_Success", qfalse); + } else { + cgi.UI_ShowMenu("StatsScreen_Failed", qfalse); + } } } } else { @@ -789,16 +919,53 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, if (cgs.gametype != GT_SINGLE_PLAYER) { CG_ScoresUp_f(); } else { - if (cgi.Cvar_Get("g_success", "", 0)->integer) { - cgi.UI_ShowMenu("StatsScreen_Success", qfalse); + if (cg_protocol >= PROTOCOL_MOHTA_MIN) { + cvar_t* pMission = cgi.Cvar_Get("g_mission", "", CVAR_ARCHIVE); + + if (cgi.Cvar_Get("g_success", "", 0)->integer) { + switch (pMission->integer) + { + default: + case 0: + cgi.UI_HideMenu("mission_success_1", qtrue); + break; + case 2: + cgi.UI_HideMenu("mission_success_2", qtrue); + break; + case 3: + cgi.UI_HideMenu("mission_success_3", qtrue); + break; + } + } else { + switch (pMission->integer) + { + default: + case 0: + cgi.UI_HideMenu("mission_failed_1", qtrue); + break; + case 2: + cgi.UI_HideMenu("mission_failed_2", qtrue); + break; + case 3: + cgi.UI_HideMenu("mission_failed_3", qtrue); + break; + } + } } else { - cgi.UI_ShowMenu("StatsScreen_Failed", qfalse); + if (cgi.Cvar_Get("g_success", "", 0)->integer) { + cgi.UI_HideMenu("StatsScreen_Success", qtrue); + } else { + cgi.UI_HideMenu("StatsScreen_Failed", qtrue); + } } } cg.bIntermissionDisplay = qfalse; } + // Added in OPM + CG_ProcessPlayerModel(); + // build the render lists if (!cg.hyperspace) { CG_AddPacketEntities(); // after calcViewValues, so predicted player state is correct @@ -806,6 +973,7 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, } // finish up the rest of the refdef + CG_SetupPortalSky(); cg.refdef.time = cg.time; memcpy(cg.refdef.areamask, cg.snap->areamask, sizeof(cg.refdef.areamask)); diff --git a/code/cgame/cg_viewmodelanim.c b/code/cgame/cg_viewmodelanim.c index e53fe7ef..c3bb9f73 100644 --- a/code/cgame/cg_viewmodelanim.c +++ b/code/cgame/cg_viewmodelanim.c @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static const char *AnimPrefixList[] = { "", + "unarmed", "papers", "colt45", "p38", @@ -45,7 +46,6 @@ static const char *AnimPrefixList[] = { "bazooka", "panzerschreck", "shotgun", - "unarmed", // // Team Assault and Team Tactics weapons "mg42portable", @@ -82,6 +82,7 @@ static const char *AnimPrefixList[] = { enum animPrefix_e { WPREFIX_NONE, + WPREFIX_UNARMED, WPREFIX_PAPERS, WPREFIX_COLT45, WPREFIX_P38, @@ -99,7 +100,6 @@ enum animPrefix_e { WPREFIX_BAZOOKA, WPREFIX_PANZERSCHRECK, WPREFIX_SHOTGUN, - WPREFIX_UNARMED, // // Team Assault and Team Tactics weapons WPREFIX_MG42_PORTABLE, @@ -308,6 +308,9 @@ int CG_GetVMAnimPrefixIndex() if (!Q_stricmp(szWeaponName, "Panzerschreck")) { return WPREFIX_PANZERSCHRECK; } + if (!Q_stricmp(szWeaponName, "Gewehrgranate")) { + return WPREFIX_KAR98_MORTAR; + } if (!Q_stricmp(szWeaponName, "Shotgun")) { return WPREFIX_SHOTGUN; } @@ -335,9 +338,11 @@ void CG_ViewModelAnimation(refEntity_t *pModel) char szAnimName[MAX_QPATH]; dtiki_t *pTiki; qboolean bAnimChanged; + qboolean bWeaponChanged; fCrossblendFrac = 0.0; - bAnimChanged = 0; + bAnimChanged = qfalse; + bWeaponChanged = qfalse; // Added in OPM pTiki = pModel->tiki; if (cgi.anim->g_iLastEquippedWeaponStat == cg.snap->ps.stats[STAT_EQUIPPED_WEAPON] @@ -346,13 +351,15 @@ void CG_ViewModelAnimation(refEntity_t *pModel) } else { iAnimPrefixIndex = CG_GetVMAnimPrefixIndex(); cgi.anim->g_iLastEquippedWeaponStat = cg.snap->ps.stats[STAT_EQUIPPED_WEAPON]; - strcpy(cgi.anim->g_szLastActiveItem, CG_ConfigString(CS_WEAPONS + cg.snap->ps.activeItems[1])); + Q_strncpyz(cgi.anim->g_szLastActiveItem, CG_ConfigString(CS_WEAPONS + cg.snap->ps.activeItems[1]), sizeof(cgi.anim->g_szLastActiveItem)); cgi.anim->g_iLastAnimPrefixIndex = iAnimPrefixIndex; - bAnimChanged = qtrue; + + bAnimChanged = qtrue; + bWeaponChanged = qtrue; } if (cgi.anim->g_iLastVMAnim == -1) { - sprintf(szAnimName, "%s_idle", AnimPrefixList[iAnimPrefixIndex]); + Com_sprintf(szAnimName, sizeof(szAnimName), "%s_idle", AnimPrefixList[iAnimPrefixIndex]); cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index = cgi.Anim_NumForName(pTiki, szAnimName); if (cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index == -1) { @@ -421,21 +428,28 @@ void CG_ViewModelAnimation(refEntity_t *pModel) break; } - sprintf(szAnimName, "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix); - fCrossblendTime = cgi.Anim_CrossblendTime(pTiki, cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index); - fCrossblendAmount = cgi.anim->g_iCurrentVMDuration / 1000.0; + Com_sprintf(szAnimName, sizeof(szAnimName), "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix); + if (!bWeaponChanged) { + fCrossblendTime = + cgi.Anim_CrossblendTime(pTiki, cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index); + fCrossblendAmount = cgi.anim->g_iCurrentVMDuration / 1000.0; - if (fCrossblendAmount < fCrossblendTime && fCrossblendAmount > 0.0) { - fCrossblendFrac = fCrossblendAmount / fCrossblendTime; - for (i = 0; i < MAX_FRAMEINFOS; ++i) { - if (cgi.anim->g_VMFrameInfo[i].weight) { - if (i == cgi.anim->g_iCurrentVMAnimSlot) { - cgi.anim->g_VMFrameInfo[i].weight = fCrossblendFrac; - } else { - cgi.anim->g_VMFrameInfo[i].weight *= (1.0 - fCrossblendFrac); + if (fCrossblendAmount < fCrossblendTime && fCrossblendAmount > 0.0) { + fCrossblendFrac = fCrossblendAmount / fCrossblendTime; + for (i = 0; i < MAX_FRAMEINFOS; ++i) { + if (cgi.anim->g_VMFrameInfo[i].weight) { + if (i == cgi.anim->g_iCurrentVMAnimSlot) { + cgi.anim->g_VMFrameInfo[i].weight = fCrossblendFrac; + } else { + cgi.anim->g_VMFrameInfo[i].weight *= (1.0 - fCrossblendFrac); + } } } } + } else { + fCrossblendTime = 0; + fCrossblendAmount = 0; + fCrossblendFrac = 0; } cgi.anim->g_iCurrentVMAnimSlot = (cgi.anim->g_iCurrentVMAnimSlot + 1) % MAX_FRAMEINFOS; @@ -450,17 +464,31 @@ void CG_ViewModelAnimation(refEntity_t *pModel) cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].weight = 1.0; cgi.anim->g_iCurrentVMDuration = 0; - fCrossblendTime = cgi.Anim_CrossblendTime(pTiki, cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index); - if (!fCrossblendTime) { + if (!bWeaponChanged) { + fCrossblendTime = + cgi.Anim_CrossblendTime(pTiki, cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index); + if (!fCrossblendTime) { + for (i = 0; i < MAX_FRAMEINFOS; ++i) { + if (i != cgi.anim->g_iCurrentVMAnimSlot) { + cgi.anim->g_VMFrameInfo[i].weight = 0.0; + } + } + + cgi.anim->g_bCrossblending = qfalse; + } else { + cgi.anim->g_bCrossblending = qtrue; + } + } else { + // Added in OPM + // If there is a new weapon, don't do any crossblend + cgi.anim->g_bCrossblending = qfalse; + + // clear crossblend values for (i = 0; i < MAX_FRAMEINFOS; ++i) { if (i != cgi.anim->g_iCurrentVMAnimSlot) { cgi.anim->g_VMFrameInfo[i].weight = 0.0; } } - - cgi.anim->g_bCrossblending = qfalse; - } else { - cgi.anim->g_bCrossblending = qtrue; } } diff --git a/code/cgame/cg_volumetricsmoke.cpp b/code/cgame/cg_volumetricsmoke.cpp index 758b0881..eeb6a3ce 100644 --- a/code/cgame/cg_volumetricsmoke.cpp +++ b/code/cgame/cg_volumetricsmoke.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_local.h" #include "cg_commands.h" +#include "memarchiver.h" const char *cg_vsstypes[] = { "default", @@ -41,7 +42,9 @@ const char *cg_vsstypes[] = { "debris" }; -cvssource_t *vss_sorttable[16384]; +#define MAX_VSS_SORTS 16384 + +cvssource_t *vss_sorttable[MAX_VSS_SORTS]; static int lastVSSFrameTime; static constexpr float MAX_VSS_COORDS = 8096.0; @@ -77,56 +80,57 @@ void VSS_AddRepulsion(cvssource_t *pA, cvssource_t *pB) VectorSubtract(pA->newOrigin, pB->newOrigin, vPush); - if (vPush[0] || vPush[1] || vPush[2]) { - fDist = VectorNormalize(vPush); - f = fDist - pB->newRadius; - - if (f > 0.0) { - f *= pA->ooRadius; - if (f > 1.49) { - f = 0.0; - } else { - f = f * (f * 0.0161 + -0.3104) + 1.2887; - } - - if (f < 0.0) { - f = f * 1.1; - } - - fForce = f; - } else { - fForce = 1.0; - } - - f = fDist - pA->newRadius; - if (f > 0.0) { - f *= pB->ooRadius; - if (f > 1.49) { - f = 0.0; - } else { - f = f * (f * 0.0161 + -0.3104) + 1.2887; - } - - if (f < 0.0) { - f = f * 1.1; - } - - fForce += f; - } else { - fForce += 1.0; - } - - if (fForce <= -0.05 && fForce >= 0.05) { - fForce = (pA->newRadius + pB->newRadius) * 0.03 * fForce; - VectorScale(vPush, fForce, vPush); - - VectorAdd(pA->repulsion, vPush, pA->repulsion); - VectorSubtract(pB->repulsion, vPush, pB->repulsion); - } - } else { + if (!vPush[0] && !vPush[1] && !vPush[2]) { VectorSet(vPush, crandom(), crandom(), crandom()); VectorAdd(pA->repulsion, vPush, pA->repulsion); VectorSubtract(pB->repulsion, vPush, pB->repulsion); + return; + } + + fDist = VectorNormalize(vPush); + f = fDist - pB->newRadius; + + if (f > 0.0f) { + f *= pA->ooRadius; + if (f > 1.49f) { + f = 0.0f; + } else { + f = f * (f * 0.0161f + -0.3104f) + 1.2887f; + } + + if (f < 0.0) { + f *= 1.1f; + } + + fForce = f; + } else { + fForce = 1.0; + } + + f = fDist - pA->newRadius; + if (f > 0.0) { + f *= pB->ooRadius; + if (f > 1.49f) { + f = 0.0f; + } else { + f = f * (f * 0.0161f + -0.3104f) + 1.2887f; + } + + if (f < 0.0) { + f *= 1.1f; + } + + fForce += f; + } else { + fForce += 1.0f; + } + + if (fForce <= -0.05f || fForce >= 0.05f) { + fForce = (pA->newRadius + pB->newRadius) * 0.03f * fForce; + VectorScale(vPush, fForce, vPush); + + VectorAdd(pA->repulsion, vPush, pA->repulsion); + VectorSubtract(pB->repulsion, vPush, pB->repulsion); } } @@ -205,7 +209,7 @@ void ClientGameCommandManager::ResetVSSSources() void ClientGameCommandManager::ResetVSSSources(Event *ev) { - // FIXME: stub?? + ResetVSSSources(); } void CG_ResetVSSSources() @@ -214,6 +218,11 @@ void CG_ResetVSSSources() lastVSSFrameTime = cg.time; } +void CG_ArchiveVSSGlobals(MemArchiver& archiver) +{ + archiver.ArchiveTime(&lastVSSFrameTime); +} + void ClientGameCommandManager::InitializeVSSSources() { int i; @@ -280,13 +289,13 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime) fWind = 0.0; - if ((pSource->flags2 & 5) != 0) { + if ((pSource->flags2 & (T2_ACCEL | T2_MOVE)) != 0) { VectorMA(pSource->velocity, ftime, pSource->repulsion, pSource->velocity); } pSource->lastOrigin = pSource->newOrigin; - if (pSource->flags & 0x800) { + if (pSource->flags & T_COLLISION) { trace.allsolid = qfalse; CG_ClipMoveToEntities( pSource->newOrigin, vec3_origin, vec3_origin, pSource->newOrigin, -1, MASK_VOLUMETRIC_SMOKE, &trace, qfalse @@ -306,11 +315,11 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime) } } - if (pSource->flags2 & 5) { + if (pSource->flags2 & (T2_ACCEL | T2_MOVE)) { VectorMA(pSource->newOrigin, ftime, pSource->velocity, pSource->newOrigin); } - if (pSource->flags & 0x800) { + if (pSource->flags & T_COLLISION) { CG_Trace( &trace, pSource->lastOrigin, @@ -328,6 +337,8 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime) float fDot; vec3_t vNorm; + VectorCopy(trace.plane.normal, vNorm); + VectorAdd(trace.endpos, trace.plane.normal, pSource->newOrigin); fDot = DotProduct(vNorm, pSource->velocity); VectorMA(pSource->velocity, fDot, vNorm, pSource->velocity); @@ -352,7 +363,7 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime) } iSmokeType = abs(pSource->smokeType); - if (pSource->flags2 & 5) { + if (pSource->flags2 & (T2_ACCEL | T2_MOVE)) { VectorCopy(pSource->velocity, vVel); for (i = 0; i < 3; i++) { @@ -613,7 +624,7 @@ qboolean VSS_LerpSource(cvssource_t *pCurrent, cvssourcestate_t *pState, float f { int i; - if (pCurrent->flags & 0xA0000) { + if (pCurrent->flags & (T_HARDLINK | T_PARENTLINK)) { Vector parentOrigin; for (i = 0; i < 3; i++) { @@ -632,7 +643,7 @@ qboolean VSS_LerpSource(cvssource_t *pCurrent, cvssourcestate_t *pState, float f parentOrigin = e->origin; VectorAdd(pState->origin, parentOrigin, pState->origin); - } else if (pCurrent->flags2 & 5) { + } else if (pCurrent->flags2 & (T2_ACCEL | T2_MOVE)) { for (i = 0; i < 3; i++) { pState->origin[i] = (pCurrent->newOrigin[i] - pCurrent->lastOrigin[i]) * fLerpFrac + pCurrent->lastOrigin[i]; @@ -735,9 +746,8 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) pSource->startAlpha = (random() * 0.15 + 0.85) * fDensity; pSource->newDensity = 0.0; - if (m_spawnthing->cgd.flags & 1) { + if (m_spawnthing->cgd.flags & T_RANDSCALE) { pSource->newRadius = RandomizeRange(m_spawnthing->cgd.scalemin, m_spawnthing->cgd.scalemax); - ; if (pSource->newRadius > 32.0) { pSource->newRadius = 32.0; } @@ -766,16 +776,16 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) pSource->roll = anglemod(fAngle); if (random() < 0.5) { - pSource->flags |= 0x40000; + pSource->flags |= T_RANDOMROLL; } VectorCopy(m_spawnthing->axis[0], vNewForward); - if (m_spawnthing->cgd.flags & 4) { + if (m_spawnthing->cgd.flags & T_SPHERE) { VectorCopy(m_spawnthing->cgd.origin, pSource->newOrigin); do { vNewForward = Vector(crandom(), crandom(), crandom()); } while (Vector::Dot(vNewForward, vNewForward) < 1.0); - } else if (m_spawnthing->cgd.flags & 0x10) { + } else if (m_spawnthing->cgd.flags & T_CIRCLE) { if (m_spawnthing->sphereRadius != 0.0) { Vector dst, end; @@ -788,7 +798,7 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) fAngle += fAngleStep; } - } else if (m_spawnthing->cgd.flags & 8) { + } else if (m_spawnthing->cgd.flags & T_INWARDSPHERE) { Vector dir, end; do { dir = Vector(crandom(), crandom(), crandom()); @@ -797,7 +807,7 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) end = m_spawnthing->cgd.origin + dir * m_spawnthing->sphereRadius; VectorCopy(end, pSource->newOrigin); vNewForward = dir * -1.0; - } else if (m_spawnthing->cgd.flags2 & 0x20000) { + } else if (m_spawnthing->cgd.flags2 & T2_CONE) { float fHeight, fRadius; float fAngle; float sina, cosa; @@ -819,8 +829,6 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) VectorMA(m_spawnthing->cgd.origin, fRadius * cosa, m_spawnthing->axis[1], pSource->newOrigin); VectorMA(m_spawnthing->cgd.origin, fRadius * sina, m_spawnthing->axis[2], pSource->newOrigin); } else if (m_spawnthing->sphereRadius) { - VectorCopy(m_spawnthing->cgd.origin, pSource->newOrigin); - } else { Vector dir, end; do { dir = Vector(crandom(), crandom(), crandom()); @@ -830,6 +838,8 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) end = m_spawnthing->cgd.origin + dir * m_spawnthing->sphereRadius; VectorCopy(end, pSource->newOrigin); vNewForward = dir; + } else { + VectorCopy(m_spawnthing->cgd.origin, pSource->newOrigin); } for (i = 0; i < 3; i++) { @@ -863,15 +873,14 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive) for (i = 0; i < 3; ++i) { float fDist = m_spawnthing->axis_offset_base[i] + random() * m_spawnthing->axis_offset_amplitude[i]; - if (pSource->flags2 & 0x80) { + if (pSource->flags2 & T2_PARALLEL) { pSource->newOrigin += Vector(m_spawnthing->axis[i]) * fDist; } else { pSource->newOrigin += Vector(m_spawnthing->tag_axis[i]) * fDist; } } - pSource->velocity *= pSource->lifeTime / 1000.0; - pSource->newOrigin += pSource->velocity; + pSource->newOrigin += pSource->velocity * (pSource->lifeTime / 1000.0); if (vss_lighting_fps->integer) { cgi.R_GetLightingForSmoke(pSource->newLighting, pSource->newOrigin); } @@ -884,251 +893,249 @@ void VSS_CalcRepulsionForces(cvssource_t *pActiveSources) { cvssource_t *pCurrent; cvssource_t *pComp; + qboolean bXUp, bXDown; + qboolean bYUp, bYDown; + qboolean bZDown; + int i; + int iIndex; + int iX, iY, iZ; + int iMinX, iMinY, iMinZ; + int iMaxX, iMaxY, iMaxZ; + float fOfs; + cvssource_t *pSTLatch; pCurrent = pActiveSources->prev; - if (pCurrent != pActiveSources) { - qboolean bXUp, bXDown; - qboolean bYUp, bYDown; - qboolean bZDown; - int i; - int iIndex; - int iX, iY, iZ; - int iMinX, iMinY, iMinZ; - int iMaxX, iMaxY, iMaxZ; - float fOfs; - cvssource_t *pSTLatch; + if (pCurrent == pActiveSources) { + return; + } - memset(vss_sorttable, 0, sizeof(vss_sorttable)); + memset(vss_sorttable, 0, sizeof(vss_sorttable)); - while (pCurrent != pActiveSources) { - VectorClear(pCurrent->repulsion); + for (pCurrent = pActiveSources->prev; pCurrent != pActiveSources; pCurrent = pCurrent->prev) { + VectorClear(pCurrent->repulsion); - iIndex = ((int)floor(pCurrent->newOrigin[0] + 8192.0 + 0.5) / 96) % 32; - iIndex |= ((int)floor(pCurrent->newOrigin[1] + 8192.0 + 0.5) / 96) % 32; - iIndex |= (((int)floor(pCurrent->newOrigin[2] + 8192.0 + 0.5) / 96) % 16) << 10; + iIndex = ((int)floor(pCurrent->newOrigin[0] + 8192.0 + 0.5) / 96) % 32; + iIndex |= (((int)floor(pCurrent->newOrigin[1] + 8192.0 + 0.5) / 96) % 32) << 5; + iIndex |= (((int)floor(pCurrent->newOrigin[2] + 8192.0 + 0.5) / 96) % 16) << 10; - pCurrent->stnext = vss_sorttable[iIndex]; - vss_sorttable[iIndex] = pCurrent; - pCurrent->stindex = iIndex; - pCurrent = pCurrent->prev; + pCurrent->stnext = vss_sorttable[iIndex]; + vss_sorttable[iIndex] = pCurrent; + pCurrent->stindex = iIndex; + } + + for (pCurrent = pActiveSources->prev; pCurrent != pActiveSources; pCurrent = pCurrent->prev) { + if (vss_sorttable[pCurrent->stindex] == pCurrent) { + pSTLatch = (cvssource_t *)-1; + pComp = pCurrent->stnext; + } else { + pSTLatch = 0; + pComp = vss_sorttable[pCurrent->stindex]; } - for (pCurrent = pActiveSources->prev; pCurrent != pActiveSources; pCurrent = pCurrent->prev) { - if (vss_sorttable[pCurrent->stindex] == pCurrent) { - pSTLatch = (cvssource_t *)-1; - pComp = pCurrent->stnext; - } else { - pSTLatch = 0; - pComp = vss_sorttable[pCurrent->stindex]; + for(; pComp; pComp = pComp->stnext) { + VSS_AddRepulsion(pCurrent, pComp); + if (!pSTLatch && pComp->stnext == pCurrent) { + pSTLatch = pComp; + // skip current + pComp = pComp->stnext; + } + } + + iX = ((int)floor(pCurrent->newOrigin[0] + 8192.0 + 0.5) / 96) % 32; + iY = (((int)floor(pCurrent->newOrigin[1] + 8192.0 + 0.5) / 96) % 32) << 5; + iZ = (((int)floor(pCurrent->newOrigin[2] + 8192.0 + 0.5) / 96) % 16) << 10; + + fOfs = pCurrent->newRadius + 1.49 + 48.0; + iMaxX = ((int)floor(pCurrent->newOrigin[0] + fOfs + 8192.0 + 0.5) / 96) % 32; + iMaxY = (((int)floor(pCurrent->newOrigin[1] + fOfs + 8192.0 + 0.5) / 96) % 32) << 5; + iMaxZ = (((int)floor(pCurrent->newOrigin[2] + fOfs + 8192.0 + 0.5) / 96) % 16) << 10; + + iMinX = ((int)floor(pCurrent->newOrigin[0] - fOfs + 8192.0 + 0.5) / 96) % 32; + iMinY = (((int)floor(pCurrent->newOrigin[1] - fOfs + 8192.0 + 0.5) / 96) % 32) << 5; + iMinZ = (((int)floor(pCurrent->newOrigin[2] - fOfs + 8192.0 + 0.5) / 96) % 16) << 10; + + bXUp = (iMaxX | (pCurrent->stindex & 0xFFFFFFE0)) != pCurrent->stindex; + bXDown = (iMinX | (pCurrent->stindex & 0xFFFFFFE0)) != pCurrent->stindex; + bYUp = (iMaxY | (pCurrent->stindex & 0xFFFFFC1F)) != pCurrent->stindex; + bYDown = (iMinY | (pCurrent->stindex & 0xFFFFFC1F)) != pCurrent->stindex; + + iIndex = iMinZ | (pCurrent->stindex & 0xFFFFC3FF); + bZDown = iIndex != pCurrent->stindex; + + if (iIndex == pCurrent->stindex) { + iIndex = iMaxY | (pCurrent->stindex & 0xFFFFFC1F); + + i = 9; + } else { + i = 0; + } + + for (; i < (bZDown ? 26 : 17); i++) { + switch (i) { + case 0: + iIndex = iMaxZ | (pCurrent->stindex & 0xFFFFC3FF); + break; + case 1: + iIndex = iMaxX | (iIndex & 0xFFFFFFE0); + if (bXUp) { + break; + } + continue; + case 2: + iIndex = iMaxY | (iIndex & 0xFFFFFC1F); + if (bXUp && bYUp) { + break; + } + continue; + case 3: + iIndex = iMinY | (iIndex & 0xFFFFFC1F); + if (bXUp && bYDown) { + break; + } + continue; + case 4: + iIndex = iMinY | (iIndex & 0xFFFFFFE0); + if (bYDown) { + break; + } + continue; + case 5: + iIndex = iMinX | (iIndex & 0xFFFFFFE0); + if (bXDown && bYDown) { + break; + } + continue; + case 6: + iIndex = iY | (iIndex & 0xFFFFFC1F); + if (bXDown) { + break; + } + continue; + case 7: + iIndex = iMaxY | (iIndex & 0xFFFFFC1F); + if (bXDown && bYUp) { + break; + } + continue; + case 8: + iIndex = iX | (iIndex & 0xFFFFFFE0); + if (bYUp) { + break; + } + continue; + case 9: + iIndex = iZ | (iIndex & 0xFFFFFFC3); + if (bYUp) { + break; + } + continue; + case 10: + iIndex = iMaxX | (iIndex & 0xFFFFFFE0); + if (bXUp && bYUp) { + break; + } + continue; + case 11: + iIndex = iMinX | (iIndex & 0xFFFFFFE0); + if (bXDown && bYUp) { + break; + } + continue; + case 12: + iIndex = iY | (iIndex & 0xFFFFFC1F); + if (bXDown) { + break; + } + continue; + case 13: + iIndex = iMinY | (iIndex & 0xFFFFFC1F); + if (bXDown && bYDown) { + break; + } + continue; + case 14: + iIndex = iX | (iIndex & 0xFFFFFFE0); + if (bYDown) { + break; + } + continue; + case 15: + iIndex = iMaxX | (iIndex & 0xFFFFFFE0); + if (bXUp && bYDown) { + break; + } + continue; + case 16: + iIndex = iY | (iIndex & 0xFFFFFC1F); + if (bXUp) { + break; + } + continue; + case 17: + iIndex = iMinZ | (iIndex & 0xFFFFFCC3); + if (bXUp) { + break; + } + continue; + case 18: + iIndex = iMaxY | (iIndex & 0xFFFFFC1F); + if (bXUp && bYUp) { + break; + } + continue; + case 19: + iIndex = iMinY | (iIndex & 0xFFFFFC1F); + if (bXUp && bYDown) { + break; + } + continue; + case 20: + iIndex = iX | (iIndex & 0xFFFFFFE0); + if (bYDown) { + break; + } + continue; + case 21: + iIndex = iMinX | (iIndex & 0xFFFFFFE0); + if (bXDown && bYDown) { + break; + } + continue; + case 22: + iIndex = iY | (iIndex & 0xFFFFFC1F); + if (bXDown) { + break; + } + continue; + case 23: + iIndex = iMaxY | (iIndex & 0xFFFFFC1F); + if (bXDown && bYUp) { + break; + } + continue; + case 24: + iIndex = iX | (iIndex & 0xFFFFFFE0); + if (bYUp) { + break; + } + continue; + case 25: + iIndex = iY | (iIndex & 0xFFFFFC1F); + break; + default: + assert(0); // This can't happen + break; } - while (pComp) { + for (pComp = vss_sorttable[iIndex]; pComp; pComp = pComp->stnext) { VSS_AddRepulsion(pCurrent, pComp); - if (!pSTLatch && pComp->stnext == pCurrent) { - pSTLatch = pComp; - pComp = pComp->stnext; - } - - pComp = pComp->stnext; } - iX = ((int)floor(pCurrent->newOrigin[0] + 8192.0 + 0.5) / 96) % 32; - iY = ((int)floor(pCurrent->newOrigin[1] + 8192.0 + 0.5) / 96) % 32; - iY *= 2; - iZ = ((int)floor(pCurrent->newOrigin[2] + 8192.0 + 0.5) / 96) % 16; - iZ <<= 10; + } - fOfs = pCurrent->newRadius + 1.49 + 48.0; - iMaxX = ((int)floor(pCurrent->newOrigin[0] + 8192.0 + 0.5 + fOfs) / 96) % 32; - iMaxY = ((int)floor(pCurrent->newOrigin[1] + 8192.0 + 0.5 + fOfs) / 96) % 32; - iMaxY *= 2; - iMaxZ = ((int)floor(pCurrent->newOrigin[2] + 8192.0 + 0.5 + fOfs) / 96) % 16; - iMaxZ <<= 10; - - iMinX = ((int)floor(pCurrent->newOrigin[0] + 8192.0 + 0.5 - fOfs) / 96) % 32; - iMinY = ((int)floor(pCurrent->newOrigin[1] + 8192.0 + 0.5 - fOfs) / 96) % 32; - iMinY *= 2; - iMinZ = ((int)floor(pCurrent->newOrigin[2] + 8192.0 + 0.5 - fOfs) / 96) % 16; - iMinZ <<= 10; - - bXUp = (iMaxX | (pCurrent->stindex & 0xFFFFFFE0)) != pCurrent->stindex; - bXDown = (iMinX | (pCurrent->stindex & 0xFFFFFFE0)) != pCurrent->stindex; - bYUp = (iMaxY | (pCurrent->stindex & 0xFFFFFC1F)) != pCurrent->stindex; - bYDown = (iMinY | (pCurrent->stindex & 0xFFFFFC1F)) != pCurrent->stindex; - - iIndex = iMinZ | (pCurrent->stindex & 0xFFFFFCC3); - bZDown = iIndex != pCurrent->stindex; - - if (iIndex == pCurrent->stindex) { - iIndex = iMaxY | pCurrent->stindex & 0xFFFFFC1F; - i = 9; - } else { - i = 0; - } - - for(; i < (bZDown ? 26 : 17); i++) { - switch (i) { - case 0: - iIndex = iMaxZ | (pCurrent->stindex & 0xFFFFFCC3); - break; - case 1: - iIndex = iMaxX | (iIndex & 0xFFFFFFE0); - if (bXUp) { - break; - } - continue; - case 2: - iIndex = iMaxY | (iIndex & 0xFFFFFC1F); - if (bXUp && bYUp) { - break; - } - continue; - case 3: - iIndex = iMinY | (iIndex & 0xFFFFFC1F); - if (bXUp && bYDown) { - break; - } - continue; - case 4: - iIndex = iMinY | (iIndex & 0xFFFFFFE0); - if (bYDown) { - break; - } - continue; - case 5: - iIndex = iMinX | (iIndex & 0xFFFFFFE0); - if (bXDown && bYDown) { - break; - } - continue; - case 6: - iIndex = iY | (iIndex & 0xFFFFFC1F); - if (bXDown) { - break; - } - continue; - case 7: - iIndex = iMaxY | (iIndex & 0xFFFFFC1F); - if (bXDown && bYUp) { - break; - } - continue; - case 8: - iIndex = iX | (iIndex & 0xFFFFFFE0); - if (bYUp) { - break; - } - continue; - case 9: - iIndex = iZ | (iIndex & 0xFFFFFFC3); - if (bYUp) { - break; - } - continue; - case 10: - iIndex = iMaxX | (iIndex & 0xFFFFFFE0); - if (bXUp && bYUp) { - break; - } - continue; - case 11: - iIndex = iMinX | (iIndex & 0xFFFFFFE0); - if (bXDown && bYUp) { - break; - } - continue; - case 12: - iIndex = iY | (iIndex & 0xFFFFFC1F); - if (bXDown) { - break; - } - continue; - case 13: - iIndex = iMinY | (iIndex & 0xFFFFFC1F); - if (bXDown && bYDown) { - break; - } - continue; - case 14: - iIndex = iX | (iIndex & 0xFFFFFFE0); - if (bYDown) { - break; - } - continue; - case 15: - iIndex = iMaxX | (iIndex & 0xFFFFFFE0); - if (bXUp && bYDown) { - break; - } - continue; - case 16: - iIndex = iY | (iIndex & 0xFFFFFC1F); - if (bXUp) { - break; - } - continue; - case 17: - iIndex = iMinZ | (iIndex & 0xFFFFFCC3); - if (bXUp) { - break; - } - continue; - case 18: - iIndex = iMaxY | (iIndex & 0xFFFFFC1F); - if (bXUp && bYUp) { - break; - } - continue; - case 19: - iIndex = iMinY | (iIndex & 0xFFFFFC1F); - if (bXUp && bYDown) { - break; - } - continue; - case 20: - iIndex = iX | (iIndex & 0xFFFFFFE0); - if (bYDown) { - break; - } - continue; - case 21: - iIndex = iMinX | (iIndex & 0xFFFFFFE0); - if (bXDown && bYDown) { - break; - } - continue; - case 22: - iIndex = iY | (iIndex & 0xFFFFFC1F); - if (bXDown) { - break; - } - continue; - case 23: - iIndex = iMaxY | (iIndex & 0xFFFFFC1F); - if (bXDown && bYUp) { - break; - } - continue; - case 24: - iIndex = iX | (iIndex & 0xFFFFFFE0); - if (bYUp) { - break; - } - continue; - case 25: - iIndex = iY | (iIndex & 0xFFFFFC1F); - break; - } - - for (pComp = vss_sorttable[iIndex]; pComp; pComp = pComp->stnext) { - VSS_AddRepulsion(pCurrent, pComp); - } - } - - if (pSTLatch == (cvssource_t *)-1) { - vss_sorttable[pCurrent->stindex] = pCurrent->stnext; - } else { - pSTLatch->stnext = pCurrent->stnext; - } + if (pSTLatch == (cvssource_t *)-1) { + vss_sorttable[pCurrent->stindex] = pCurrent->stnext; + } else { + pSTLatch->stnext = pCurrent->stnext; } } } @@ -1216,13 +1223,13 @@ void ClientGameCommandManager::AddVSSSources() pComp = pCurrent->prev; newEnt.renderfx = 0; - if (pCurrent->flags < 0 && !cg_detail->integer) { + if ((pCurrent->flags & T_DETAIL) && !cg_detail->integer) { FreeVSSSource(pCurrent); continue; } - if ((pCurrent->flags2 & 0x4000) != 0) { - newEnt.renderfx = 0x4000000; + if ((pCurrent->flags2 & T2_ALWAYSDRAW) != 0) { + newEnt.renderfx = RF_ALWAYSDRAW; } if (pCurrent->lastPhysicsTime) { @@ -1231,8 +1238,8 @@ void ClientGameCommandManager::AddVSSSources() mstime = physics_rate; } - if (mstime >= physics_rate || (pCurrent->flags2 & 0x10) != 0) { - if (!VSS_SourcePhysics(pCurrent, (float)mstime * 0.001)) { + if (mstime >= physics_rate || (pCurrent->flags2 & T2_PHYSICS_EVERYFRAME) != 0) { + if (!VSS_SourcePhysics(pCurrent, (float)mstime / 1000.0)) { FreeVSSSource(pCurrent); continue; } @@ -1256,26 +1263,18 @@ void ClientGameCommandManager::AddVSSSources() } } - fLerpFrac = (cg.time - pCurrent->lastPhysicsTime) / physics_rate; - if (fLerpFrac > 1.0) { - fLerpFrac = 1.0; - } else if (fLerpFrac < 0.0) { - fLerpFrac = 0.0; - } + fLerpFrac = (float)(cg.time - pCurrent->lastPhysicsTime) / (float)physics_rate; + fLerpFrac = Q_clamp_float(fLerpFrac, 0, 1); - fLightingFrac = (cg.time - pCurrent->lastLightingTime) / lighting_rate; - if (fLightingFrac > 1.0) { - fLightingFrac = 1.0; - } else if (fLightingFrac < 0.0) { - fLightingFrac = 0.0; - } + fLightingFrac = (float)(cg.time - pCurrent->lastLightingTime) / (float)lighting_rate; + fLightingFrac = Q_clamp_float(fLightingFrac, 0, 1); if (lastVSSFrameTime) { pCurrent->lifeTime += frameTime; } if (!pCurrent->lastValid) { - if (!VSS_SourcePhysics(pCurrent, (float)physics_rate * 0.001)) { + if (!VSS_SourcePhysics(pCurrent, (float)physics_rate / 1000)) { ClientGameCommandManager::FreeVSSSource(pCurrent); continue; } @@ -1329,12 +1328,12 @@ void ClientGameCommandManager::AddVSSSources() pCurrent->roll -= j; } - if ((pCurrent->flags & 0x40000) != 0) { + if ((pCurrent->flags & T_RANDOMROLL) != 0) { newEnt.hModel = hModel; } else { newEnt.hModel = hModel2; } - } else if ((pCurrent->flags & 0x40000) != 0) { + } else if ((pCurrent->flags & T_RANDOMROLL) != 0) { newEnt.hModel = hModel; } else { newEnt.hModel = hModel2; diff --git a/code/cgame/memarchiver.cpp b/code/cgame/memarchiver.cpp new file mode 100644 index 00000000..a07c4211 --- /dev/null +++ b/code/cgame/memarchiver.cpp @@ -0,0 +1,241 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cg_local.h" +#include "memarchiver.h" +#include "../qcommon/vector.h" +#include "../qcommon/str.h" + +MemArchiver::MemArchiver() +{ + state = MEMARC_WRITING; + buffer = 0; + allocatedSize = 0; + bufferSize = 0; +} + +MemArchiver::~MemArchiver() +{ + if (state == MEMARC_WRITING && buffer) { + cgi.Free(buffer); + } +} + +void MemArchiver::SetupForWriting(size_t initialSize) +{ + this->state = MEMARC_WRITING; + this->buffer = (byte*)cgi.Malloc(initialSize); + this->allocatedSize = initialSize; + this->bufferSize = 0; +} + +void MemArchiver::SetupForReading(byte* buffer, size_t size) +{ + this->state = MEMARC_READING; + this->buffer = buffer; + this->allocatedSize = size; + this->bufferSize = 0; +} + +void MemArchiver::SetBaseTime(unsigned int time) +{ + this->svsTime = time; +} + +size_t MemArchiver::BufferSize() const +{ + return bufferSize; +} + +byte* MemArchiver::ConfiscateBuffer() +{ + byte* confiscatedBuffer = buffer; + + buffer = NULL; + allocatedSize = 0; + bufferSize = 0; + + return confiscatedBuffer; +} + +bool MemArchiver::IsReading() const +{ + return !IsWriting(); +} + +bool MemArchiver::IsWriting() const +{ + return state == MEMARC_WRITING; +} + +bool MemArchiver::FinishedReading() const +{ + return bufferSize == allocatedSize; +} + +void MemArchiver::ArchiveByte(byte* value) +{ + ArchiveRaw(value, sizeof(byte)); +} + +void MemArchiver::ArchiveBoolean(qboolean* value) +{ + ArchiveRaw(value, sizeof(qboolean)); +} + +void MemArchiver::ArchiveChar(char* value) +{ + ArchiveRaw(value, sizeof(char)); +} + +void MemArchiver::ArchiveUChar(unsigned char* value) +{ + ArchiveRaw(value, sizeof(unsigned char)); +} + +void MemArchiver::ArchiveShort(short* value) +{ + ArchiveRaw(value, sizeof(short)); +} + +void MemArchiver::ArchiveInteger(int* value) +{ + ArchiveRaw(value, sizeof(int)); +} + +void MemArchiver::ArchiveSize(size_t* value) +{ + ArchiveRaw(value, sizeof(size_t)); +} + +void MemArchiver::ArchiveFloat(float* value) +{ + ArchiveRaw(value, sizeof(float)); +} + +void MemArchiver::ArchiveVec3(vec3_t value) +{ + ArchiveRaw(value, sizeof(vec3_t)); +} + +void MemArchiver::ArchiveVector(Vector* value) +{ + ArchiveFloat(&value->x); + ArchiveFloat(&value->y); + ArchiveFloat(&value->z); +} + +void MemArchiver::ArchiveString(str* value) +{ + char tmp[4096]; + int current = 0; + + if (IsReading()) { + for (current = 0; current < 4096; current++) { + ArchiveReadRaw(&tmp[current], sizeof(char)); + if (!tmp[current]) { + break; + } + } + + if (current == 4096) { + tmp[current - 1] = 0; + } + + *value = tmp; + } else { + ArchiveWriteRaw(value->c_str(), value->length() + 1); + } +} + +void MemArchiver::ArchiveTime(int* value) +{ + int time; + + if (IsReading()) { + ArchiveReadRaw(&time, sizeof(time)); + + if (time) { + time += svsTime; + } + + *value = time; + } else { + time = *value; + if (time) { + time -= svsTime; + } + + ArchiveWriteRaw(&time, sizeof(time)); + } +} + +void MemArchiver::ArchiveRaw(void* buffer, size_t size) +{ + if (IsReading()) { + ArchiveReadRaw(buffer, size); + } else { + ArchiveWriteRaw(buffer, size); + } +} + +void MemArchiver::ArchiveReadRaw(void* buffer, size_t size) +{ + if (!size) { + return; + } + + if (size + this->bufferSize > this->allocatedSize) { + Com_Error(ERR_DROP, "MemArchiver: tried to read past end of buffer"); + } + + memcpy(buffer, this->buffer + this->bufferSize, size); + this->bufferSize += size; +} + +void MemArchiver::ArchiveWriteRaw(const void* buffer, size_t size) +{ + if (!size) { + return; + } + + if (size + this->bufferSize > this->allocatedSize) { + if (!this->allocatedSize) { + this->allocatedSize = 1024; + this->buffer = (byte*)cgi.Malloc(this->allocatedSize); + } else { + byte* newBuffer; + + do { + this->allocatedSize *= 2; + } while (size + this->bufferSize > this->allocatedSize); + + newBuffer = (byte*)cgi.Malloc(this->allocatedSize); + memcpy(newBuffer, this->buffer, this->bufferSize); + cgi.Free(this->buffer); + this->buffer = newBuffer; + } + } + + memcpy(this->buffer + this->bufferSize, buffer, size); + this->bufferSize += size; +} diff --git a/code/cgame/memarchiver.h b/code/cgame/memarchiver.h new file mode 100644 index 00000000..87c2ae36 --- /dev/null +++ b/code/cgame/memarchiver.h @@ -0,0 +1,72 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// DESCRIPTION: +// In-memory archiver + +#include "cg_local.h" + +class Vector; +class str; + +typedef enum { + MEMARC_WRITING, + MEMARC_READING +} archiverState_e; + +class MemArchiver { +public: + MemArchiver(); + ~MemArchiver(); + + void SetupForWriting(size_t initialSize); + void SetupForReading(byte* buffer, size_t size); + void SetBaseTime(unsigned int time); + size_t BufferSize() const; + byte* ConfiscateBuffer(); + bool IsReading() const; + bool IsWriting() const; + bool FinishedReading() const; + + void ArchiveByte(byte* value); + void ArchiveBoolean(qboolean* value); + void ArchiveChar(char* value); + void ArchiveUChar(unsigned char* value); + void ArchiveShort(short* value); + void ArchiveInteger(int* value); + void ArchiveSize(size_t* value); + void ArchiveFloat(float* value); + void ArchiveVec3(vec3_t value); + void ArchiveVector(Vector* value); + void ArchiveString(str* value); + void ArchiveTime(int* value); + void ArchiveRaw(void* buffer, size_t size); + void ArchiveReadRaw(void* buffer, size_t size); + void ArchiveWriteRaw(const void* buffer, size_t size); + +private: + archiverState_e state; + byte* buffer; + size_t bufferSize; + size_t allocatedSize; + int svsTime; +}; diff --git a/code/client/CMakeLists.txt b/code/client/CMakeLists.txt index 8ba2b753..259e055b 100644 --- a/code/client/CMakeLists.txt +++ b/code/client/CMakeLists.txt @@ -1,22 +1,84 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) + project(omohclient) add_subdirectory("../cgame" "./cgame") -file(GLOB_RECURSE SOURCES_CLIENT "./*.c*") +file(GLOB SOURCES_CLIENT "./*.c*") file(GLOB_RECURSE SOURCES_UILIB "../uilib/*.c*") +set(SOURCES_CLIENT ${SOURCES_CLIENT} + # Gamespy + "${CMAKE_SOURCE_DIR}/code/gamespy/cl_gamespy.c" +) + # Made as an interface and not static, as static only links used methods add_library(omohclient INTERFACE) -target_sources(omohclient INTERFACE ${SOURCES_CLIENT} ${SOURCES_UILIB}) target_compile_definitions(omohclient INTERFACE APP_MODULE) target_compile_features(omohclient INTERFACE cxx_nullptr) target_compile_features(omohclient INTERFACE c_variadic_macros) -target_link_libraries(omohclient INTERFACE omohsdl) +target_link_libraries(omohclient INTERFACE omohsdl_client) target_link_libraries(omohclient INTERFACE gcd) # Sound stuff target_compile_definitions(omohclient INTERFACE USE_CODEC_MP3) -add_subdirectory("../libmad-0.15.1b" "./libmad") -target_link_libraries(omohclient INTERFACE libmad) \ No newline at end of file +if (NOT NO_MODERN_DMA) + # Use OpenAL + find_package(OpenAL REQUIRED) + + if (OPENAL_FOUND) + target_compile_definitions(omohclient INTERFACE USE_OPENAL=1 NO_MODERN_DMA=0) + if (MSVC) + target_include_directories(omohclient INTERFACE ${OPENAL_INCLUDE_DIR}/AL) + else() + target_include_directories(omohclient INTERFACE ${OPENAL_INCLUDE_DIR}) + endif() + + if(NOT USE_SYSTEM_LIBS) + target_compile_definitions(omohclient INTERFACE USE_OPENAL_DLOPEN=1) + else() + # Link against system OpenAL + target_link_libraries(omohclient INTERFACE OpenAL::OpenAL) + endif() + endif() + + list(FILTER SOURCES_CLIENT EXCLUDE REGEX "./snd_([a-zA-Z0-9_]+)\.c$") + file(GLOB SOURCES_CLIENT_SND "./snd_*_new.c*" "./snd_codec*.c*") + list(APPEND SOURCES_CLIENT ${SOURCES_CLIENT_SND}) +else() + # + # Fallback to old DMA sound system + # + message(NOTICE "OpenAL was explicitly disabled - fallback to old SDL sound system") + target_compile_definitions(omohclient INTERFACE NO_MODERN_DMA=1) + set(NO_MODERN_DMA TRUE) + + list(FILTER SOURCES_CLIENT EXCLUDE REGEX "./snd_([a-zA-Z0-9_]+)\.cpp$") + file(GLOB_RECURSE SOURCES_CLIENT_SND "./new/*.c*") + list(APPEND SOURCES_CLIENT ${SOURCES_CLIENT_SND}) +endif() + +set(OLD_VALUE ${BUILD_SHARED_LIBS}) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +if(USE_INTERNAL_MAD) + add_subdirectory("../libmad" "./libmad" EXCLUDE_FROM_ALL) + target_link_libraries(omohclient INTERFACE mad) +else() + include(FindPackageHandleStandardArgs) + find_path(LIBMAD_INCLUDE_DIRS mad.h) + find_library(LIBMAD_LIBRARIES mad) + find_package_handle_standard_args( + LibMad + DEFAULT_MSG + LIBMAD_LIBRARIES + LIBMAD_INCLUDE_DIRS + ) + target_include_directories(omohclient INTERFACE ${LIBMAD_INCLUDE_DIRS}) + target_link_libraries(omohclient INTERFACE ${LIBMAD_LIBRARIES}) +endif() + +set(BUILD_SHARED_LIBS ${OLD_VALUE} CACHE BOOL "" FORCE) + +target_sources(omohclient INTERFACE ${SOURCES_CLIENT} ${SOURCES_UILIB}) diff --git a/code/client/cl_avi.cpp b/code/client/cl_avi.cpp index a6e018f0..051599a3 100644 --- a/code/client/cl_avi.cpp +++ b/code/client/cl_avi.cpp @@ -334,6 +334,9 @@ writing the actual data can begin */ qboolean CL_OpenAVIForWriting( const char *fileName ) { + return qfalse; + // Removed in OPM +#if 0 if( afd.fileOpen ) return qfalse; @@ -425,6 +428,7 @@ qboolean CL_OpenAVIForWriting( const char *fileName ) afd.fileOpen = qtrue; return qtrue; +#endif } /* diff --git a/code/client/cl_cgame.cpp b/code/client/cl_cgame.cpp index 6cd2f97c..e6737760 100644 --- a/code/client/cl_cgame.cpp +++ b/code/client/cl_cgame.cpp @@ -211,20 +211,20 @@ qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) { } snapshot->numEntities = 0; - for ( i = 0 ; i < count ; i++ ) { + for(i = 0; i < MAX_ENTITIES_IN_SNAPSHOT; i++) { + parents[i] = -1; + } + + for (i = 0; i < count; i++) { s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)]; pnum = s1->parent; if (pnum == ENTITYNUM_NONE) { parents[s1->number] = -2; - } - else - { + } else { if (parents[pnum] == -2) { parents[s1->number] = -2; - } - else - { + } else { // add it later parents[s1->number] = pnum; continue; @@ -234,33 +234,37 @@ qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) { snapshot->entities[snapshot->numEntities++] = *s1; } - for(pcount = 0; pcount < 8 && snapshot->numEntities != count; pcount++) - { - for (i = 0; i < count; i++) - { + for(pcount = 0; pcount < 8 && snapshot->numEntities != count; pcount++) { + for (i = 0; i < count; i++) { s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)]; pnum = parents[s1->number]; if (pnum >= 0 && parents[pnum] == -2) { + parents[s1->number] = -2; snapshot->entities[snapshot->numEntities++] = *s1; } } } - if (pcount >= 8) - { - for (i = count; i < snapshot->numEntities; i++) + if (snapshot->numEntities != count) { + Com_DPrintf("CL_GetSnapshot: Not all children could find their parents.\n"); + + for (i = snapshot->numEntities; i < count; i++) { - s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)]; - if (parents[s1->number] >= 0) { - Com_DPrintf( - "CL_GetSnapshot: entity %d with parent %d and model '%s' at %.2f %.2f %.2f, could not find parent.\n", - s1->number, - s1->parent, - CL_ConfigString(CS_MODELS + s1->modelindex), - s1->origin[0], - s1->origin[1], - s1->origin[2] - ); + for (pnum = 0; pnum < count; pnum++) { + s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + pnum) & (MAX_PARSE_ENTITIES - 1)]; + if (parents[s1->number] >= 0) { + Com_DPrintf( + "CL_GetSnapshot: entity %d with parent %d and model '%s' at %.2f %.2f %.2f, could not find parent.\n", + s1->number, + s1->parent, + CL_ConfigString(CS_MODELS + s1->modelindex), + s1->origin[0], + s1->origin[1], + s1->origin[2] + ); + + parents[s1->number] = -2; + } } } } @@ -358,7 +362,9 @@ qboolean CL_ProcessServerCommand(const char* origString, const char* cmd, qboole // because this function might be called from a module that would be unloaded // inside Com_Error UI_ForceMenuOff(1); - Cbuf_AddText("disconnect;pushmenu disconnected"); + // Fixed in OPM + // Added a newline for next commands + Cbuf_AddText("disconnect;pushmenu disconnected\n"); return qtrue; } @@ -395,8 +401,8 @@ Set up argc/argv for the given command =================== */ qboolean CL_GetServerCommand( int serverCommandNumber, qboolean differentServer ) { - char *s; - char *cmd; + char *s; + char *cmd; static char bigConfigString[BIG_INFO_STRING]; // if we have irretrievably lost a reliable command, drop the connection @@ -421,9 +427,39 @@ qboolean CL_GetServerCommand( int serverCommandNumber, qboolean differentServer Com_DPrintf( "serverCommand: %i : %s\n", serverCommandNumber, s ); } - Cmd_TokenizeString( s ); + Cmd_TokenizeString(s); cmd = Cmd_Argv(0); + // Readded in OPM (from ioquake) + // Configstring big buffer + if (!strcmp(cmd, "bcs0")) { + Com_sprintf(bigConfigString, BIG_INFO_STRING, "cs %s \"%s", Cmd_Argv(1), Cmd_Argv(2)); + return qfalse; + } + + if (!strcmp(cmd, "bcs1")) { + s = Cmd_Argv(2); + if (strlen(bigConfigString) + strlen(s) >= BIG_INFO_STRING) { + Com_Error(ERR_DROP, "bcs exceeded BIG_INFO_STRING"); + } + strcat(bigConfigString, s); + return qfalse; + } + + if (!strcmp(cmd, "bcs2")) { + s = Cmd_Argv(2); + if (strlen(bigConfigString) + strlen(s) + 1 >= BIG_INFO_STRING) { + Com_Error(ERR_DROP, "bcs exceeded BIG_INFO_STRING"); + } + strcat(bigConfigString, s); + strcat(bigConfigString, "\""); + s = bigConfigString; + + // reparse + Cmd_TokenizeString(s); + cmd = Cmd_Argv(0); + } + return CL_ProcessServerCommand(s, cmd, differentServer); } @@ -435,10 +471,10 @@ CL_CM_LoadMap Just adds default parameters that cgame doesn't need to know about ==================== */ -void CL_CM_LoadMap( const char *mapname ) { - int checksum; - - CM_LoadMap( mapname, qtrue, &checksum ); +void CL_CM_LoadMap( const char *mapname, int *checksum ) { + CM_LoadMap( mapname, qtrue, checksum ); + // prepare world vis data + re.SetWorldVisData(CM_VisibilityPointer()); } /* @@ -548,7 +584,7 @@ CL_RestoreSavedCgameState */ void CL_RestoreSavedCgameState() { if (cls.savedCgameState) { - cge->CG_LoadStateToBuffer(&cls.savedCgameState, cls.savedCgameStateSize, cl.snap.serverTime); + cge->CG_LoadStateToBuffer(cls.savedCgameState, cls.savedCgameStateSize, cl.snap.serverTime); } } @@ -580,6 +616,7 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) { cgi->Printf = Com_Printf; cgi->DPrintf = Com_DPrintf; + cgi->DebugPrintf = Com_DebugPrintf; cgi->Malloc = CL_CG_Malloc; cgi->Free = CL_CG_Free; @@ -590,7 +627,9 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) { cgi->LV_ConvertString = Sys_LV_CL_ConvertString; cgi->Cvar_Get = Cvar_Get; + cgi->Cvar_Find = Cvar_FindVar; cgi->Cvar_Set = Cvar_Set; + cgi->Cvar_CheckRange = Cvar_CheckRange; cgi->Argc = Cmd_Argc; cgi->Args = Cmd_Args; @@ -605,6 +644,8 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) { cgi->FS_FreeFile = FS_FreeFile; cgi->FS_WriteFile = FS_WriteFile; cgi->FS_WriteTextFile = FS_WriteTextFile; + cgi->FS_ListFilteredFiles = FS_ListFilteredFiles; + cgi->FS_FreeFileList = FS_FreeFileList; cgi->SendConsoleCommand = Cbuf_AddText; @@ -676,9 +717,11 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) { cgi->R_RegisterModel = re.RegisterModel; cgi->R_SpawnEffectModel = re.SpawnEffectModel; cgi->R_RegisterServerModel = re.RegisterServerModel; + cgi->R_GetModelName = re.GetModelName; cgi->R_UnregisterServerModel = re.UnregisterServerModel; cgi->R_RegisterShader = re.RegisterShader; cgi->R_RegisterShaderNoMip = re.RegisterShaderNoMip; + cgi->R_GetShaderName = re.GetShaderName; cgi->R_AddRefEntityToScene = re.AddRefEntityToScene; cgi->R_AddRefSpriteToScene = re.AddRefSpriteToScene; @@ -730,7 +773,9 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) { cgi->UI_ShowMenu = UI_ShowMenu; cgi->UI_HideMenu = UI_HideMenu; - cgi->UI_FontStringWidth = uie.FontStringWidth; + cgi->UI_FontStringWidth = CL_FontStringWidth; + cgi->UI_GetObjectivesTop = UI_GetObjectivesTop; + cgi->UI_GetHighResolutionScale = UI_GetHighResolutionScale; cgi->Key_StringToKeynum = Key_StringToKeynum; cgi->Key_KeynumToBindString = Key_KeynumToBindString; cgi->Key_GetKeysForCommand = Key_GetKeysForCommand; @@ -778,6 +823,8 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) { cgi->CL_RestoreSavedCgameState = CL_RestoreSavedCgameState; cgi->CL_ClearSavedCgameState = CL_ClearSavedCgameState; + cgi->getConfigStringIdNormalized = CPT_NormalizeConfigstring; + cgi->fsDebug = fs_debug; cgi->HudDrawElements = cls.HudDrawElements; cgi->anim = &cls.anim; @@ -877,7 +924,13 @@ void CL_InitCGame( void ) { // find the current mapname info = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SERVERINFO ]; mapname = Info_ValueForKey( info, "mapname" ); - Com_sprintf( cl.mapname, sizeof( cl.mapname ), "maps/%s.bsp", mapname ); + + if (CL_UseLargeLightmap(mapname)) { + Com_sprintf(cl.mapname, sizeof(cl.mapname), "maps/%s.bsp", mapname); + } else { + // Added in 2.0 + Com_sprintf(cl.mapname, sizeof(cl.mapname), "maps/%s_sml.bsp", mapname); + } S_BeginRegistration(); CL_ShutdownCGame(); @@ -892,10 +945,17 @@ void CL_InitCGame( void ) { CL_InitClientSavedData(); } - // init for this gamestate - // use the lastExecutedServerCommand instead of the serverCommandSequence - // otherwise server commands sent just before a gamestate are dropped - cge->CG_Init( &cgi, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum ); + if (cl.snap.valid) { + // init for this gamestate + // use the lastExecutedServerCommand instead of the serverCommandSequence + // otherwise server commands sent just before a gamestate are dropped + cge->CG_Init(&cgi, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum); + } else { + // executing client commands from previous map/server might be an issue, some commands might be cs commands, + // like old CS_SYSTEMINFO configstrings which still contain the sv_serverId from previous map. + // It would cause the client to lose the game state number + cge->CG_Init(&cgi, clc.serverMessageSequence, clc.serverCommandSequence, clc.clientNum); + } ClearNewConfigFlag(); TIKI_FinishLoad(); @@ -1070,6 +1130,42 @@ void CL_FirstSnapshot( void ) { Cbuf_AddText( cl_activeAction->string ); Cvar_Set( "activeAction", "" ); } + +#ifdef USE_MUMBLE + if ((cl_useMumble->integer) && !mumble_islinked()) { + int ret = mumble_link(CLIENT_WINDOW_TITLE); + Com_Printf("Mumble: Linking to Mumble application %s\n", ret==0?"ok":"failed"); + } +#endif + +#ifdef USE_VOIP + if (!clc.voipCodecInitialized) { + int i; + int error; + + clc.opusEncoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, &error); + + if ( error ) { + Com_DPrintf("VoIP: Error opus_encoder_create %d\n", error); + return; + } + + for (i = 0; i < MAX_CLIENTS; i++) { + clc.opusDecoder[i] = opus_decoder_create(48000, 1, &error); + if ( error ) { + Com_DPrintf("VoIP: Error opus_decoder_create(%d) %d\n", i, error); + return; + } + clc.voipIgnore[i] = qfalse; + clc.voipGain[i] = 1.0f; + } + clc.voipCodecInitialized = qtrue; + clc.voipMuteAll = qfalse; + Cmd_AddCommand ("voip", CL_Voip_f); + Cvar_Set("cl_voipSendTarget", "spatial"); + Com_Memset(clc.voipTargets, ~0, sizeof(clc.voipTargets)); + } +#endif } static int lastSnapFlags; @@ -1120,7 +1216,12 @@ void CL_SetCGameTime( void ) { // allow pause in single player if ( paused->integer && com_sv_running->integer ) { // paused - CL_AdjustTimeDelta(); + //CL_AdjustTimeDelta(); + // Fixed in OPM + // Keep in sync with the server time. + // In OG, the game could lag for a short time + // when pausing and unpausing frequently + cl.serverTimeDelta = cl.snap.serverTime - cls.realtime; return; } diff --git a/code/client/cl_cin.cpp b/code/client/cl_cin.cpp index fc3ada32..667a7ef2 100644 --- a/code/client/cl_cin.cpp +++ b/code/client/cl_cin.cpp @@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../uilib/ui_public.h" #include "snd_local.h" +#include "cl_ui.h" + #define MAXSIZE 8 #define MINSIZE 4 @@ -55,6 +57,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static void RoQ_init( void ); +static void CL_FinishedCinematic(); /****************************************************************************** * @@ -126,6 +129,10 @@ typedef struct { int playonwalls; byte* buf; long drawX, drawY; + + long realTime; + long currTime; + long soundTime; } cin_cache; static cinematics_t cin; @@ -133,6 +140,10 @@ static cin_cache cinTable[MAX_VIDEO_HANDLES]; static int currentHandle = -1; static int CL_handle = -1; +static connstate_t oldClientState; + +static int audioStartTime = 0; + extern "C" int s_soundtime; // sample PAIRS @@ -160,7 +171,7 @@ static int CIN_HandleForVideo(void) { } -extern "C" int CL_ScaledMilliseconds(void); +extern "C" int Com_Milliseconds(void); //----------------------------------------------------------------------------- // RllSetupTable @@ -1142,24 +1153,20 @@ redump: case ZA_SOUND_MONO: if (!cinTable[currentHandle].silent) { ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags); - S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1); + // S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1); } break; case ZA_SOUND_STEREO: if (!cinTable[currentHandle].silent) { - if (cinTable[currentHandle].numQuads == -1) { - S_Update(); - s_rawend[0] = s_soundtime; - } ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags); - S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1); + // S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1); } break; case ROQ_QUAD_INFO: if (cinTable[currentHandle].numQuads == -1) { readQuadInfo( framedata ); setupQuad( 0, 0 ); - cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds(); + cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = Com_Milliseconds(); } if (cinTable[currentHandle].numQuads != 1) cinTable[currentHandle].numQuads = 0; break; @@ -1226,7 +1233,10 @@ redump: static void RoQ_init( void ) { - cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds(); + cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = Com_Milliseconds(); + cinTable[currentHandle].realTime = Com_Milliseconds(); + cinTable[currentHandle].currTime = 0; + cinTable[currentHandle].soundTime = 0; cinTable[currentHandle].RoQPlayed = 24; @@ -1273,8 +1283,10 @@ static void RoQShutdown( void ) { cinTable[currentHandle].iFile = 0; } + S_StopMovieAudio(); + if (cinTable[currentHandle].alterGameState) { - clc.state = CA_DISCONNECTED; + clc.state = oldClientState; // we can't just do a vstr nextmap, because // if we are aborting the intro cinematic with // a devmap command, nextmap would be valid by @@ -1286,8 +1298,29 @@ static void RoQShutdown( void ) { } CL_handle = -1; } + cinTable[currentHandle].fileName[0] = 0; currentHandle = -1; + + CL_FinishedCinematic(); +} + +static void CL_FinishedCinematic() +{ + const char* s; + + if (!CL_FinishedIntro()) + { + CL_FinishedStartStage(); + return; + } + + s = Cvar_VariableString("nextmap"); + if (*s) + { + Cbuf_ExecuteText(EXEC_APPEND, va("%s\n", s)); + Cvar_Set("nextmap", ""); + } } /* @@ -1328,8 +1361,11 @@ Fetch and decompress the pending frame e_status CIN_RunCinematic (int handle) { - int start = 0; - int thisTime = 0; + int deltaTime; + int frameTime; + int soundTime; + int newTime; + long tfps; if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return FMV_EOF; @@ -1357,24 +1393,46 @@ e_status CIN_RunCinematic (int handle) return cinTable[currentHandle].status; } - thisTime = CL_ScaledMilliseconds(); - if (cinTable[currentHandle].shader && (abs(thisTime - cinTable[currentHandle].lastTime))>100) { - cinTable[currentHandle].startTime += thisTime - cinTable[currentHandle].lastTime; + frameTime = Com_Milliseconds(); + deltaTime = frameTime - cinTable[currentHandle].realTime; + if (deltaTime > 100) { + deltaTime = 100; } - cinTable[currentHandle].tfps = (((CL_ScaledMilliseconds() - cinTable[currentHandle].startTime)*3)/100); - start = cinTable[currentHandle].startTime; - while( (cinTable[currentHandle].tfps != cinTable[currentHandle].numQuads) + newTime = cinTable[currentHandle].currTime + deltaTime; + if (cl_movieaudio->integer) { + soundTime = S_CurrentMoviePosition(); + if (soundTime > cinTable[currentHandle].currTime || soundTime > cinTable[currentHandle].soundTime) { + cinTable[currentHandle].currTime = newTime + (deltaTime * (soundTime - newTime)) / 100; + } + else { + cinTable[currentHandle].currTime = newTime; + } + + cinTable[currentHandle].soundTime = soundTime; + } else { + // + // Fixed in OPM + // + cinTable[currentHandle].currTime = newTime; + } + + cinTable[currentHandle].realTime = frameTime; + + tfps = (cinTable[currentHandle].currTime * 3) / 100; + + while( (tfps != cinTable[currentHandle].numQuads) && (cinTable[currentHandle].status == FMV_PLAY) ) { RoQInterrupt(); - if (start != cinTable[currentHandle].startTime) { - cinTable[currentHandle].tfps = (((CL_ScaledMilliseconds() - cinTable[currentHandle].startTime)*3)/100); - start = cinTable[currentHandle].startTime; + + cinTable[currentHandle].realTime = Com_Milliseconds(); + if (cinTable[currentHandle].realTime > frameTime + 66) { + break; } } - cinTable[currentHandle].lastTime = thisTime; + cinTable[currentHandle].lastTime = frameTime; if (cinTable[currentHandle].status == FMV_LOOPED) { cinTable[currentHandle].status = FMV_PLAY; @@ -1422,7 +1480,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi cin.currentHandle = currentHandle; - strcpy(cinTable[currentHandle].fileName, name); + Q_strncpyz(cinTable[currentHandle].fileName, name, sizeof(cinTable[currentHandle].fileName)); cinTable[currentHandle].ROQSize = 0; cinTable[currentHandle].ROQSize = FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue, qtrue); @@ -1468,10 +1526,6 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi clc.state = CA_CINEMATIC; } - if (!cinTable[currentHandle].silent) { - s_rawend[0] = s_soundtime; - } - return currentHandle; } Com_DPrintf("trFMV::play(), invalid RoQ ID\n"); @@ -1593,33 +1647,96 @@ void CIN_DrawCinematic (int handle) { cinTable[handle].dirty = qfalse; } +static unsigned short CL_PlayRoQ(const char* name, const char* arg, const char* s) { + unsigned short RoQID; + + Com_Memset(&cin, 0, sizeof(cinematics_t) ); + currentHandle = CIN_HandleForVideo(); + + cin.currentHandle = currentHandle; + + Q_strncpyz(cinTable[currentHandle].fileName, name, sizeof(cinTable[currentHandle].fileName)); + + cinTable[currentHandle].ROQSize = 0; + cinTable[currentHandle].ROQSize = FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue, qtrue); + + if (cinTable[currentHandle].ROQSize<=0) { + Com_DPrintf("Can not find RoQ cinematic '%s'\n", name); + CL_FinishedCinematic(); + return -1; + } + + if ((s && s[0] == '1') || Q_stricmp(arg,"demoend.roq")==0 || Q_stricmp(arg,"end.roq")==0) { + cinTable[currentHandle].holdAtEnd = qtrue; + } + + CIN_SetExtents(currentHandle, 0, 0, 640, 480); + cinTable[currentHandle].alterGameState = qtrue; + + initRoQ(); + + FS_Read (cin.file, 16, cinTable[currentHandle].iFile); + + RoQID = (unsigned short)(cin.file[0]) + (unsigned short)(cin.file[1])*256; + if (RoQID == 0x1084) + { + RoQ_init(); +// FS_Read (cin.file, cinTable[currentHandle].RoQFrameSize+8, cinTable[currentHandle].iFile); + + cinTable[currentHandle].status = FMV_PLAY; + Com_DPrintf("trFMV::play(), playing %s\n", arg); + + if (cl_movieaudio->integer) { + audioStartTime = Com_Milliseconds(); + S_SetupMovieAudio(name); + } + + oldClientState = clc.state; + clc.state = CA_CINEMATIC; + + if (cls.glconfig.maxTextureSize <= 256 || s && *s == '2') { + //cinTable[currentHandle].interlaced = qtrue; + } + + CL_handle = currentHandle; + + do { + SCR_RunCinematic(); + } while (!cinTable[currentHandle].buf && cinTable[currentHandle].status == FMV_PLAY); + + UI_CloseConsole(); + + return currentHandle; + } + Com_DPrintf("trFMV::play(), invalid RoQ ID\n"); + + RoQShutdown(); + return -1; +} + void CL_PlayCinematic_f(void) { char *arg, *s; - int bits = CIN_system; + char name[256]; - Com_DPrintf("CL_PlayCinematic_f\n"); if (clc.state == CA_CINEMATIC) { SCR_StopCinematic(); } arg = Cmd_Argv( 1 ); + Com_DPrintf("CL_PlayCinematic( %s )\n", arg); s = Cmd_Argv(2); - if ((s && s[0] == '1') || Q_stricmp(arg,"demoend.roq")==0 || Q_stricmp(arg,"end.roq")==0) { - bits |= CIN_hold; - } - if (s && s[0] == '2') { - bits |= CIN_loop; + CL_StartHunkUsers(qfalse); + S_StopAllSounds2(qtrue); + + Com_sprintf(name, sizeof(name), "video/%s", arg); + + if (Q_stricmp(&name[strlen(name) - 4], ".roq")) { + Com_Printf("Bad or missing cinematic extension.\n"); + return; } - S_StopAllSounds( qtrue ); - - CL_handle = CIN_PlayCinematic( arg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, bits ); - if (CL_handle >= 0) { - do { - SCR_RunCinematic(); - } while (cinTable[currentHandle].buf == NULL && cinTable[currentHandle].status == FMV_PLAY); // wait for first frame (load codebook and sound) - } + CL_PlayRoQ(name, arg, s); } @@ -1639,7 +1756,5 @@ void SCR_RunCinematic (void) void SCR_StopCinematic(void) { if (CL_handle >= 0 && CL_handle < MAX_VIDEO_HANDLES) { CIN_StopCinematic(CL_handle); - S_StopAllSounds( qtrue ); - CL_handle = -1; } } diff --git a/code/client/cl_input.cpp b/code/client/cl_input.cpp index b2eb30e8..e2f89d1f 100644 --- a/code/client/cl_input.cpp +++ b/code/client/cl_input.cpp @@ -56,6 +56,10 @@ qboolean in_guimouse; kbutton_t in_up, in_down; +#ifdef USE_VOIP +kbutton_t in_voiprecord; +#endif + kbutton_t in_buttons[16]; qboolean in_mlooking; @@ -258,6 +262,20 @@ void IN_SpeedUp(void) {IN_KeyUp(&in_speed);} void IN_StrafeDown(void) {IN_KeyDown(&in_strafe);} void IN_StrafeUp(void) {IN_KeyUp(&in_strafe);} +#ifdef USE_VOIP +void IN_VoipRecordDown(void) +{ + IN_KeyDown(&in_voiprecord); + Cvar_Set("cl_voipSend", "1"); +} + +void IN_VoipRecordUp(void) +{ + IN_KeyUp(&in_voiprecord); + Cvar_Set("cl_voipSend", "0"); +} +#endif + void IN_Button0Down(void) {IN_KeyDown(&in_buttons[0]);} void IN_Button0Up(void) {IN_KeyUp(&in_buttons[0]);} void IN_Button1Down(void) {IN_KeyDown(&in_buttons[1]);} @@ -432,7 +450,7 @@ void CL_MouseEvent( int dx, int dy, int time ) { if( cl.mousey > cls.glconfig.vidHeight ) cl.mousey = cls.glconfig.vidHeight; } - else + else if ( !paused->integer ) { cl.mouseDx[cl.mouseIndex] += dx; cl.mouseDy[cl.mouseIndex] += dy; @@ -461,6 +479,16 @@ CL_JoystickMove void CL_JoystickMove( usercmd_t *cmd ) { float anglespeed; + float yaw = j_yaw->value * cl.joystickAxis[j_yaw_axis->integer]; + float right = j_side->value * cl.joystickAxis[j_side_axis->integer]; + float forward = j_forward->value * cl.joystickAxis[j_forward_axis->integer]; + float pitch = j_pitch->value * cl.joystickAxis[j_pitch_axis->integer]; + float up = j_up->value * cl.joystickAxis[j_up_axis->integer]; + + if ( in_speed.active ^ cl_run->integer ) { + cmd->buttons |= BUTTON_RUN; + } + if ( in_speed.active ) { anglespeed = 0.001 * cls.frametime * cl_anglespeedkey->value; } else { @@ -468,18 +496,22 @@ void CL_JoystickMove( usercmd_t *cmd ) { } if ( !in_strafe.active ) { - cl.viewangles[YAW] += anglespeed * cl_yawspeed->value * cl.joystickAxis[AXIS_SIDE]; + cl.viewangles[YAW] += anglespeed * yaw; + cmd->rightmove = ClampChar( cmd->rightmove + (int)right ); } else { - cmd->rightmove = ClampChar( cmd->rightmove + cl.joystickAxis[AXIS_SIDE] ); + cl.viewangles[YAW] += anglespeed * right; + cmd->rightmove = ClampChar( cmd->rightmove + (int)yaw ); } if ( in_mlooking ) { - cl.viewangles[PITCH] += anglespeed * cl_pitchspeed->value * cl.joystickAxis[AXIS_FORWARD]; + cl.viewangles[PITCH] += anglespeed * forward; + cmd->forwardmove = ClampChar( cmd->forwardmove + (int)pitch ); } else { - cmd->forwardmove = ClampChar( cmd->forwardmove + cl.joystickAxis[AXIS_FORWARD] ); + cl.viewangles[PITCH] += anglespeed * pitch; + cmd->forwardmove = ClampChar( cmd->forwardmove + (int)forward ); } - cmd->upmove = ClampChar( cmd->upmove + cl.joystickAxis[AXIS_UP] ); + cmd->upmove = ClampChar( cmd->upmove + (int)up ); } /* @@ -565,6 +597,8 @@ void CL_MouseMove( usercmd_t *cmd ) { mx *= cgameSensitivity; my *= cgameSensitivity; + cmd->buttons |= BUTTON_ANY; + // add mouse X/Y movement to cmd if(in_strafe.active) cmd->rightmove = ClampChar(cmd->rightmove + m_side->value * mx); @@ -575,6 +609,14 @@ void CL_MouseMove( usercmd_t *cmd ) { cl.viewangles[PITCH] += m_pitch->value * my; else cmd->forwardmove = ClampChar(cmd->forwardmove - m_forward->value * my); + + if (!isfinite(cl.viewangles[PITCH]) || !isfinite(cl.viewangles[YAW])) { + Com_DPrintf("Invalid client viewangles encountered (view pitch: %f, view yaw: %f)!\n", cl.viewangles[PITCH], cl.viewangles[YAW]); + Com_DPrintf("cgameSensitivity: %f | mx: %f | my: %f | m_pitch: %f | m_yaw: %f\n", cgameSensitivity, mx, my, m_pitch->value, m_yaw->value); + Com_DPrintf("Resetting client viewangles\n"); + cl.viewangles[PITCH] = 0; + cl.viewangles[YAW] = 0; + } } /* @@ -609,8 +651,8 @@ void CL_CmdButtons( usercmd_t *cmd ) { if (UI_MenuActive() || UI_ConsoleIsOpen()) { cmd->buttons |= BUTTON_TALK; } - - if (in_speed.active == !cl_run->integer) { + + if ( in_speed.active ^ cl_run->integer ) { cmd->buttons |= BUTTON_RUN; } @@ -718,6 +760,12 @@ void CL_CreateNewCommands( void ) { frame_msec = com_frameTime - old_com_frameTime; + // if running over 1000fps, act as if each frame is 1ms + // prevents divisions by zero + if ( frame_msec < 1 ) { + frame_msec = 1; + } + // if running less than 5fps, truncate the extra time to prevent // unexpected moves after a hitch if ( frame_msec > 200 ) { @@ -818,8 +866,8 @@ qboolean CL_ReadyToSendPacket( void ) { } // check for exceeding cl_maxpackets - if ( cl_maxpackets->integer < 15 ) { - Cvar_Set( "cl_maxpackets", "15" ); + if ( cl_maxpackets->integer < 30 ) { + Cvar_Set( "cl_maxpackets", "30" ); } else if ( cl_maxpackets->integer > 125 ) { Cvar_Set( "cl_maxpackets", "125" ); } @@ -909,6 +957,58 @@ void CL_WritePacket( void ) { count = MAX_PACKET_USERCMDS; Com_Printf("MAX_PACKET_USERCMDS\n"); } + +#ifdef USE_VOIP + if (clc.voipOutgoingDataSize > 0) + { + if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1)) + { + MSG_WriteByte (&buf, clc_voipOpus); + MSG_WriteByte (&buf, clc.voipOutgoingGeneration); + MSG_WriteLong (&buf, clc.voipOutgoingSequence); + MSG_WriteByte (&buf, clc.voipOutgoingDataFrames); + MSG_WriteData (&buf, clc.voipTargets, sizeof(clc.voipTargets)); + MSG_WriteByte(&buf, clc.voipFlags); + MSG_WriteShort (&buf, clc.voipOutgoingDataSize); + MSG_WriteData (&buf, clc.voipOutgoingData, clc.voipOutgoingDataSize); + + // If we're recording a demo, we have to fake a server packet with + // this VoIP data so it gets to disk; the server doesn't send it + // back to us, and we might as well eliminate concerns about dropped + // and misordered packets here. + if(clc.demorecording && !clc.demowaiting) + { + const int voipSize = clc.voipOutgoingDataSize; + msg_t fakemsg; + byte fakedata[MAX_MSGLEN]; + MSG_Init (&fakemsg, fakedata, sizeof (fakedata)); + MSG_Bitstream (&fakemsg); + MSG_WriteLong (&fakemsg, clc.reliableAcknowledge); + MSG_WriteByte (&fakemsg, svc_voipOpus); + MSG_WriteShort (&fakemsg, clc.clientNum); + MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration); + MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence); + MSG_WriteByte (&fakemsg, clc.voipOutgoingDataFrames); + MSG_WriteShort (&fakemsg, clc.voipOutgoingDataSize ); + MSG_WriteBits (&fakemsg, clc.voipFlags, VOIP_FLAGCNT); + MSG_WriteData (&fakemsg, clc.voipOutgoingData, voipSize); + MSG_WriteByte (&fakemsg, svc_EOF); + CL_WriteDemoMessage (&fakemsg, 0); + } + + clc.voipOutgoingSequence += clc.voipOutgoingDataFrames; + clc.voipOutgoingDataSize = 0; + clc.voipOutgoingDataFrames = 0; + } + else + { + // We have data, but no targets. Silently discard all data + clc.voipOutgoingDataSize = 0; + clc.voipOutgoingDataFrames = 0; + } + } +#endif + if ( count >= 1 ) { if ( cl_showSend->integer ) { Com_Printf( "(%i)", count ); @@ -965,16 +1065,6 @@ void CL_WritePacket( void ) { } CL_Netchan_Transmit (&clc.netchan, &buf); - - // clients never really should have messages large enough - // to fragment, but in case they do, fire them all off - // at once - // TTimo: this causes a packet burst, which is bad karma for winsock - // added a WARNING message, we'll see if there are legit situations where this happens - while ( clc.netchan.unsentFragments ) { - Com_DPrintf( "WARNING: #462 unsent fragments (not supposed to happen!)\n" ); - CL_Netchan_TransmitNextFragment( &clc.netchan ); - } } /* @@ -991,7 +1081,7 @@ void CL_SendCmd( void ) { } // don't send commands if paused - if ( com_sv_running->integer && paused->integer && paused->integer ) { + if ( com_sv_running->integer && paused->integer ) { return; } @@ -1086,6 +1176,85 @@ void CL_InitInput( void ) { Cmd_AddCommand("+mlook", IN_MLookDown); Cmd_AddCommand("-mlook", IN_MLookUp); +#ifdef USE_VOIP + Cmd_AddCommand ("+voiprecord", IN_VoipRecordDown); + Cmd_AddCommand ("-voiprecord", IN_VoipRecordUp); +#endif + cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0); cl_debugMove = Cvar_Get ("cl_debugMove", "0", 0); } + +/* +============ +CL_ShutdownInput +============ +*/ +void CL_ShutdownInput(void) +{ + Cmd_RemoveCommand("centerview"); + + Cmd_RemoveCommand("+moveup"); + Cmd_RemoveCommand("-moveup"); + Cmd_RemoveCommand("+movedown"); + Cmd_RemoveCommand("-movedown"); + Cmd_RemoveCommand("+left"); + Cmd_RemoveCommand("-left"); + Cmd_RemoveCommand("+right"); + Cmd_RemoveCommand("-right"); + Cmd_RemoveCommand("+forward"); + Cmd_RemoveCommand("-forward"); + Cmd_RemoveCommand("+back"); + Cmd_RemoveCommand("-back"); + Cmd_RemoveCommand("+lookup"); + Cmd_RemoveCommand("-lookup"); + Cmd_RemoveCommand("+lookdown"); + Cmd_RemoveCommand("-lookdown"); + Cmd_RemoveCommand("+strafe"); + Cmd_RemoveCommand("-strafe"); + Cmd_RemoveCommand("+moveleft"); + Cmd_RemoveCommand("-moveleft"); + Cmd_RemoveCommand("+moveright"); + Cmd_RemoveCommand("-moveright"); + Cmd_RemoveCommand("+speed"); + Cmd_RemoveCommand("-speed"); + Cmd_RemoveCommand("+attack"); + Cmd_RemoveCommand("-attack"); + Cmd_RemoveCommand("+button0"); + Cmd_RemoveCommand("-button0"); + Cmd_RemoveCommand("+button1"); + Cmd_RemoveCommand("-button1"); + Cmd_RemoveCommand("+button2"); + Cmd_RemoveCommand("-button2"); + Cmd_RemoveCommand("+button3"); + Cmd_RemoveCommand("-button3"); + Cmd_RemoveCommand("+button4"); + Cmd_RemoveCommand("-button4"); + Cmd_RemoveCommand("+button5"); + Cmd_RemoveCommand("-button5"); + Cmd_RemoveCommand("+button6"); + Cmd_RemoveCommand("-button6"); + Cmd_RemoveCommand("+button7"); + Cmd_RemoveCommand("-button7"); + Cmd_RemoveCommand("+button8"); + Cmd_RemoveCommand("-button8"); + Cmd_RemoveCommand("+button9"); + Cmd_RemoveCommand("-button9"); + Cmd_RemoveCommand("+button10"); + Cmd_RemoveCommand("-button10"); + Cmd_RemoveCommand("+button11"); + Cmd_RemoveCommand("-button11"); + Cmd_RemoveCommand("+button12"); + Cmd_RemoveCommand("-button12"); + Cmd_RemoveCommand("+button13"); + Cmd_RemoveCommand("-button13"); + Cmd_RemoveCommand("+button14"); + Cmd_RemoveCommand("-button14"); + Cmd_RemoveCommand("+mlook"); + Cmd_RemoveCommand("-mlook"); + +#ifdef USE_VOIP + Cmd_RemoveCommand("+voiprecord"); + Cmd_RemoveCommand("-voiprecord"); +#endif +} diff --git a/code/client/cl_instantAction.cpp b/code/client/cl_instantAction.cpp new file mode 100644 index 00000000..1501121a --- /dev/null +++ b/code/client/cl_instantAction.cpp @@ -0,0 +1,640 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cl_ui.h" +#include "cl_instantAction.h" +#include "cl_uiserverlist.h" +#include "../gamespy/sv_gamespy.h" + +Event EV_UIInstantAction_AcceptServer +( + "acceptserver", + EV_DEFAULT, + NULL, + NULL, + "Connect to the current server" +); + +Event EV_UIInstantAction_RejectServer +( + "rejectserver", + EV_DEFAULT, + NULL, + NULL, + "Reject the current server" +); + +Event EV_UIInstantAction_Cancel +( + "ia_cancel", + EV_DEFAULT, + NULL, + NULL, + "cancel the server update" +); + +Event EV_UIInstantAction_Refresh +( + "ia_refresh", + EV_DEFAULT, + NULL, + NULL, + "Refresh the server list" +); + +CLASS_DECLARATION(UIWidget, UIInstantAction, NULL) { + {&EV_UIInstantAction_AcceptServer, &UIInstantAction::Connect }, + {&EV_UIInstantAction_RejectServer, &UIInstantAction::Reject }, + {&EV_UIInstantAction_Cancel, &UIInstantAction::CancelRefresh}, + {&EV_UIInstantAction_Refresh, &UIInstantAction::Refresh }, + {NULL, NULL } +}; + +struct ServerListInstance { + int iServerType; + UIInstantAction *pServerList; +}; + +ServerListInstance g_IAServerListInst[2]; + +UIInstantAction::UIInstantAction() +{ + state = IA_INITIALIZE; + numFoundServers = 0; + numServers = 0; + minPlayers = 3; + startingMaxPing = 100; + endingMaxPing = 1500; + maxServers = -1; + servers = NULL; + doneList[0] = false; + doneList[1] = false; + serverList[0] = NULL; + serverList[1] = NULL; + + ReadIniFile(); + EnableServerInfo(false); + + menuManager.PassEventToWidget("ia_cancel_button", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_refresh_button", new Event(EV_Widget_Disable)); +} + +UIInstantAction::~UIInstantAction() +{ + CleanUp(); +} + +void UIInstantAction::CleanUp() +{ + if (serverList[0]) { + ServerListFree(serverList[0]); + serverList[0] = NULL; + } + + if (serverList[1]) { + ServerListFree(serverList[1]); + serverList[1] = NULL; + } + + if (servers) { + delete[] servers; + servers = NULL; + } +} + +void UIInstantAction::Init() +{ + const char *secret_key; + const char *game_name; + + static const unsigned int iNumConcurrent = 10; + + numFoundServers = 0; + numServers = 0; + doneList[0] = false; + doneList[1] = false; + + EnableServerInfo(false); + + menuManager.PassEventToWidget("ia_cancel_button", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_refresh_button", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_noserverfound", new Event(EV_Widget_Disable)); + + Cvar_Set("ia_search_percentage", va("%d %%", 0)); + + if (com_target_game->integer < target_game_e::TG_MOHTT) { + g_IAServerListInst[0].iServerType = com_target_game->integer; + g_IAServerListInst[0].pServerList = this; + + game_name = GS_GetGameName(com_target_game->integer); + secret_key = GS_GetGameKey(com_target_game->integer); + + serverList[0] = ServerListNew( + game_name, + game_name, + secret_key, + iNumConcurrent, + (void *)&IAServerListCallBack, + 1, + (void *)&g_IAServerListInst[0] + ); + + ServerListClear(serverList[0]); + } else { + g_IAServerListInst[0].iServerType = target_game_e::TG_MOHTT; + g_IAServerListInst[0].pServerList = this; + + game_name = GS_GetGameName(target_game_e::TG_MOHTT); + secret_key = GS_GetGameKey(target_game_e::TG_MOHTT); + + serverList[0] = ServerListNew( + game_name, + game_name, + secret_key, + iNumConcurrent, + (void *)&IAServerListCallBack, + 1, + (void *)&g_IAServerListInst[0] + ); + + ServerListClear(serverList[0]); + + g_IAServerListInst[1].iServerType = target_game_e::TG_MOHTA; + g_IAServerListInst[1].pServerList = this; + + game_name = GS_GetGameName(target_game_e::TG_MOHTA); + secret_key = GS_GetGameKey(target_game_e::TG_MOHTA); + + serverList[1] = ServerListNew( + game_name, + game_name, + secret_key, + iNumConcurrent, + (void *)&IAServerListCallBack, + 1, + (void *)&g_IAServerListInst[1] + ); + + ServerListClear(serverList[1]); + } + + state = IA_WAITING; + numFoundServers = 0; + + ServerListUpdate(serverList[0], true); + + if (serverList[1]) { + ServerListUpdate(serverList[1], true); + } + + menuManager.PassEventToWidget("ia_cancel_button", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("searchstatus", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("searchstatuslable", new Event(EV_Widget_Enable)); +} + +int UIInstantAction::GetServerIndex(int maxPing, int gameType) +{ + int bestPing = 1500; + int bestServer = -1; + int i; + + for (i = 0; i < numFoundServers; i++) { + const IAServer_t& IAServer = servers[i]; + + char *gameVer; + float fGameVer; + int ping; + int numPlayers; + + if (IAServer.rejected) { + continue; + } + + // Skip servers that don't match the provided game type + if (ServerGetIntValue(IAServer.server, "g_gametype_i", 1) != gameType) { + continue; + } + + // Skip servers with high ping + ping = ServerGetPing(IAServer.server); + if (ping > maxPing) { + continue; + } + + gameVer = ServerGetStringValue(IAServer.server, "gamever", "1.00"); + if (com_target_demo->integer && *gameVer != 'd') { + // Skip retail servers on demo game + continue; + } else if (!com_target_demo->integer && *gameVer == 'd') { + // Skip demo servers on retail game + continue; + } + + // Skip incompatible servers + fGameVer = atof(gameVer); + if (com_target_game->integer >= target_game_e::TG_MOHTT) { + if (IAServer.serverGame.serverType == target_game_e::TG_MOHTT) { + if (fabs(fGameVer) < 2.3f) { + continue; + } + } else { + if (fabs(fGameVer) < 2.1f) { + continue; + } + } + } else { + if (fabs(fGameVer - com_target_version->value) > 0.1f) { + continue; + } + } + + // Skip servers with a password + if (ServerGetIntValue(IAServer.server, "password", 0)) { + continue; + } + + // Skip servers that don't match the minimum number of players + numPlayers = ServerGetIntValue(IAServer.server, "numplayers", 0); + if (numPlayers < minPlayers) { + continue; + } + + // Skip full servers + if (numPlayers == ServerGetIntValue(IAServer.server, "maxplayers", 0)) { + continue; + } + + // Skip servers with an higher ping than the best one + if (ping >= bestPing) { + continue; + } + + // + // Found a potential server + // + + bestPing = ping; + bestServer = i; + } + + return bestServer; +} + +void UIInstantAction::ReadIniFile() +{ + char *buffer; + const char *p; + const char *pVal; + int intValue; + char value[32]; + + if (!FS_ReadFileEx("iaction.ini", (void **)&buffer, qtrue)) { + return; + } + + for (p = buffer; p; p = strstr(pVal, "\n")) { + if (sscanf(p, "%31s", value) != 1) { + break; + } + + pVal = strstr(p, "="); + if (!pVal) { + break; + } + + pVal++; + + if (sscanf(pVal, "%d", &intValue) != 1) { + break; + } + + if (!Q_stricmpn(value, "MinPlayers", 10)) { + minPlayers = intValue; + } + + if (!Q_stricmpn(value, "StartingMaxPing", 15)) { + startingMaxPing = intValue; + } + + if (!Q_stricmpn(value, "EndingMaxPing", 13)) { + endingMaxPing = intValue; + } + + if (!Q_stricmpn(value, "MaxServers", 10)) { + maxServers = intValue; + } + } +} + +void UIInstantAction::FindServer() +{ + int ping; + int i; + + currentServer = -1; + state = IA_NONE; + + for (ping = startingMaxPing; ping < endingMaxPing; ping += 100) { + // + // Find the best server starting from FFA gametype first + // + for (i = 1; i < 7; i++) { + currentServer = GetServerIndex(ping, i); + if (currentServer >= 0) { + break; + } + } + + if (currentServer >= 0) { + break; + } + } + + menuManager.PassEventToWidget("ia_refresh_button", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_cancel_button", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("searchstatus", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("searchstatuslable", new Event(EV_Widget_Disable)); + + if (currentServer < 0) { + EnableServerInfo(false); + + menuManager.PassEventToWidget("ia_noserverfound", new Event(EV_Widget_Enable)); + return; + } + + const IAServer_t& IAServer = servers[currentServer]; + const char *hostname = ServerGetStringValue(IAServer.server, "hostname", "(NONE)"); + const char *gametype = ServerGetStringValue(IAServer.server, "gametype", "(NONE)"); + int numplayers = ServerGetIntValue(IAServer.server, "numplayers", 0); + int maxplayers = ServerGetIntValue(IAServer.server, "maxplayers", 0); + ping = ServerGetPing(IAServer.server); + + Cvar_Set("ia_servername", va(" %s", hostname)); + Cvar_Set("ia_ping", va("%d", ping)); + Cvar_Set("ia_gametype", va("%s", gametype)); + Cvar_Set("ia_players", va("%d", numplayers)); + Cvar_Set("ia_maxplayers", va("%d", maxplayers)); + + EnableServerInfo(true); +} + +void UIInstantAction::Connect(Event *ev) +{ + char *gameVer; + float fGameVer; + bool bDiffVersion; + char command[256]; + + if (currentServer < 0 || currentServer < numServers) { + return; + } + + const IAServer_t& IAServer = servers[currentServer]; + + gameVer = ServerGetStringValue(IAServer.server, "gamever", "1.00"); + if (gameVer[0] == 'd') { + gameVer++; + } + + // Skip incompatible servers + fGameVer = atof(gameVer); + bDiffVersion = false; + if (com_target_game->integer >= target_game_e::TG_MOHTT) { + if (IAServer.serverGame.serverType == target_game_e::TG_MOHTT) { + if (fabs(fGameVer) < 2.3f) { + bDiffVersion = true; + } + } else { + if (fabs(fGameVer) < 2.1f) { + bDiffVersion = true; + } + } + } else { + if (fabs(fGameVer - com_target_version->value) > 0.1f) { + bDiffVersion = true; + } + } + + if (bDiffVersion) { + if (fGameVer - com_target_version->value > 0) { + // Older version + UI_SetReturnMenuToCurrent(); + Cvar_Set("com_errormessage", va("Server is version %s, you are using %s", gameVer, "2.40")); + UI_PushMenu("wrongversion"); + } else { + // Server version is newer + Cvar_Set("dm_serverstatus", va("Can not connect to v%s server, you are using v%s", gameVer, "2.40")); + } + } + + UI_SetReturnMenuToCurrent(); + Cvar_Set("g_servertype", va("%d", servers[currentServer].serverGame.serverType)); + + Com_sprintf( + command, + sizeof(command), + "connect %s:%i\n", + ServerGetAddress(IAServer.server), + ServerGetIntValue(IAServer.server, "hostport", PORT_SERVER) + ); + Cbuf_AddText(command); +} + +void UIInstantAction::Reject(Event *ev) +{ + servers[currentServer].rejected = 1; + FindServer(); +} + +void UIInstantAction::Draw() +{ + switch (state) { + case IA_INITIALIZE: + Init(); + break; + case IA_UPDATE: + Update(); + break; + case IA_FINISHED: + FindServer(); + break; + default: + break; + } + + if (serverList[0]) { + ServerListThink(serverList[0]); + } + + if (serverList[1]) { + ServerListThink(serverList[1]); + } +} + +void UIInstantAction::Update() +{ + numFoundServers = 0; + + // count the total number of servers from both server list + numServers = ServerListCount(serverList[0]); + if (serverList[1]) { + numServers += ServerListCount(serverList[1]); + } + + state = IA_FINISHED; + servers = new IAServer_t[numServers]; + + ServerListHalt(serverList[0]); + if (serverList[1]) { + ServerListHalt(serverList[1]); + } + + ServerListThink(serverList[0]); + if (serverList[1]) { + ServerListThink(serverList[1]); + } + + state = IA_SEARCHING; + + // Start updating the first list + doneList[0] = false; + ServerListClear(serverList[0]); + ServerListUpdate(serverList[0], true); + + // Update the second optional list + if (serverList[1]) { + doneList[1] = false; + ServerListClear(serverList[1]); + ServerListUpdate(serverList[1], true); + } +} + +int UIInstantAction::AddServer(GServer server, const ServerGame_t& serverGame) +{ + servers[numFoundServers].server = server; + servers[numFoundServers].serverGame = serverGame; + servers[numFoundServers].rejected = false; + numFoundServers++; + + return numFoundServers; +} + +void UIInstantAction::CancelRefresh(Event *ev) +{ + state = IA_FINISHED; + ServerListHalt(serverList[0]); + ServerListHalt(serverList[1]); +} + +void UIInstantAction::Refresh(Event *ev) +{ + state = IA_INITIALIZE; +} + +void UIInstantAction::EnableServerInfo(bool enable) +{ + if (enable) { + menuManager.PassEventToWidget("iaservername_label", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_servername_field", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_ping_label", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_ping_field", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_gametype_label", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_gametype_field", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_players_label", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_players_field", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_maxplayers_label", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("ia_maxplayers_field", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("acceptserver", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("rejectserver", new Event(EV_Widget_Enable)); + } else { + menuManager.PassEventToWidget("iaservername_label", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_servername_field", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_ping_label", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_ping_field", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_gametype_label", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_gametype_field", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_players_label", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_players_field", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_maxplayers_label", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("ia_maxplayers_field", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("acceptserver", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("rejectserver", new Event(EV_Widget_Disable)); + } +} + +void UIInstantAction::IAServerListCallBack(GServerList serverlist, int msg, void *instance, void *param1, void *param2) +{ + const ServerListInstance *pInstance = (const ServerListInstance *)instance; + UIInstantAction *pServerList = pInstance->pServerList; + + if (msg == LIST_PROGRESS) { + if (pServerList->state == IA_WAITING) { + if (pInstance->iServerType == com_target_game->integer) { + pServerList->doneList[0] = true; + } + + if (com_target_game->integer >= target_game_e::TG_MOHTT && pInstance->iServerType == target_game_e::TG_MOHTA) { + pServerList->doneList[1] = true; + } + + if (pServerList->doneList[0] && (!pServerList->serverList[1] || pServerList->doneList[1])) { + pServerList->state = IA_UPDATE; + } + } else if (pServerList->state == IA_SEARCHING) { + ServerGame_t serverGame; + serverGame.serverType = pInstance->iServerType; + const int serverIndex = pServerList->AddServer((GServer)param1, serverGame); + + Cvar_Set("ia_search_percentage", va("%d %%", 100 * serverIndex / pServerList->numServers)); + + if (pServerList->maxServers >= 0 && serverIndex >= pServerList->maxServers) { + // Reached the maximum number of servers, stop there + pServerList->doneList[0] = true; + ServerListHalt(pServerList->serverList[0]); + + if (pServerList->serverList[1]) { + pServerList->doneList[1] = true; + ServerListHalt(pServerList->serverList[1]); + } + + pServerList->state = IA_FINISHED; + } + } + } else if (msg == LIST_STATECHANGED && ServerListState(serverlist) == GServerListState::sl_idle) { + if (pInstance->iServerType == com_target_game->integer) { + pServerList->doneList[0] = true; + } + + if (com_target_game->integer >= target_game_e::TG_MOHTT && pInstance->iServerType == target_game_e::TG_MOHTA) { + pServerList->doneList[1] = true; + } + + if (pServerList->doneList[0] && (!pServerList->serverList[1] || pServerList->doneList[1])) { + if (pServerList->state == IA_WAITING) { + pServerList->state = IA_UPDATE; + } + if (pServerList->state == IA_SEARCHING) { + pServerList->state = IA_FINISHED; + } + } + } +} diff --git a/code/client/cl_instantAction.h b/code/client/cl_instantAction.h new file mode 100644 index 00000000..9a838dc5 --- /dev/null +++ b/code/client/cl_instantAction.h @@ -0,0 +1,103 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// Added in 2.30 +// Instantly find a server matching common criterias + +#pragma once + +#include "../gamespy/goaceng.h" + +typedef struct { + int serverType; +} ServerGame_t; + +typedef struct { + GServer server; + ServerGame_t serverGame; + bool rejected; +} IAServer_t; + +enum IAState_e { + IA_NONE, + IA_INITIALIZE, + IA_WAITING, + IA_UPDATE, + IA_SEARCHING, + IA_FINISHED +}; + +class UIInstantAction : public UIWidget +{ +public: + CLASS_PROTOTYPE(UIInstantAction); + +public: + UIInstantAction(); + ~UIInstantAction() override; + + void CleanUp(); + void Init(); + + int GetServerIndex(int maxPing, int gameType); + void ReadIniFile(); + void FindServer(); + void Connect(Event *ev); + void Reject(Event *ev); + void Draw(); + void Update(); + int AddServer(GServer server, const ServerGame_t& serverGame); + void CancelRefresh(Event *ev); + void Refresh(Event *ev); + void EnableServerInfo(bool enable); + +private: + static void IAServerListCallBack(GServerList serverlist, int msg, void *instance, void *param1, void *param2); + +private: + // + // List + // + bool doneList[2]; + GServerList serverList[2]; + int maxServers; + + // + // Current states + // + IAState_e state; + int numServers; + int numFoundServers; + + // + // Filters + // + int minPlayers; + int startingMaxPing; + int endingMaxPing; + + // + // Servers + // + IAServer_t *servers; + int currentServer; +}; diff --git a/code/client/cl_inv.cpp b/code/client/cl_inv.cpp index 1fbdda1a..850d766d 100644 --- a/code/client/cl_inv.cpp +++ b/code/client/cl_inv.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,316 +22,1159 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" -CLASS_DECLARATION( Listener, invlistener, NULL ) -{ - { NULL, NULL } +typedef struct { + const char *string; + int value; +} equipment_event_table_t; + +static equipment_event_table_t s_equipTable[] = { + {"left", 1 }, + {"right", 2 }, + {"dual", 4 }, + {"use", 8 }, + {"none", 16}, + {NULL, 0 } }; -invlistener::invlistener( inventory_t *i ) +Event evi_inv_changesound +( + "inv_changesound", + EV_DEFAULT, + "s", + "soundname", + "Set the sound to play when the inventory changes items" +); +Event evi_inv_selectsound +( + "inv_selectsound", + EV_DEFAULT, + "s", + "soundname", + "Set the sound to play when an inventory item is selected" +); +Event evi_inv_rejectsound +( + "inv_rejectsound", + EV_DEFAULT, + "s", + "soundname", + "Set the sound to play when an invalid inventory item is selected" +); +Event evi_inv_width +( + "inv_width", + EV_DEFAULT, + "i", + "width", + "Specifies the width of each of the main inv buttons" +); +Event evi_inv_height +( + "inv_height", + EV_DEFAULT, + "i", + "height", + "Specifies the height of each of the main inv buttons" +); +Event evi_inv_vertical_offset +( + "inv_vert_offset", + EV_DEFAULT, + "i", + "offset", + "Specifies the vertical offset from the top of the screen for the inventory" +); +Event evi_inv_horizontal_offset +( + "inv_horiz_offset", + EV_DEFAULT, + "i", + "offset", + "Specifies the horizontal offset from the right of the screen for the inventory" +); +Event evi_inv_align +( + "inv_align", + EV_DEFAULT, + "s", + "side", + "Specifies the horizontal offset from the right of the screen for the inventory" +); +Event evi_inv_cascade +( + "inv_cascade", + EV_DEFAULT, + "s", + "side", + "Specifies the side which to cascade inventory items" +); +Event evi_typedef +( + "typedef", + EV_DEFAULT, + "s", + "type", + "Specifies which class of item you're editing" +); +Event evi_openbrace +( + "{", EV_DEFAULT, + NULL, + NULL, + "Open brace, useless" +); +Event evi_closebrace +( + "}", EV_DEFAULT, + NULL, + NULL, + "Close brace, useless" +); +Event evi_button_shader +( + "button_shader", + EV_DEFAULT, + "s", + "shader", + "The shader for the class button" +); +Event evi_hover_shader +( + "hover_shader", + EV_DEFAULT, + "s", + "shader", + "The shader for the class button when hovering" +); +Event evi_sel_shader +( + "sel_shader", + EV_DEFAULT, + "s", + "shader", + "The shader for the class button when selected" +); +Event evi_bg +( + "bg", + EV_DEFAULT, + "s", + "shader", + "Shader for the background of the class submenu" +); +Event evi_bg_tile +( + "bg_tile", + EV_DEFAULT, + NULL, + NULL, + "Specifies to tile the background of the class submenu" +); +Event evi_width +( + "width", + EV_DEFAULT, + "i", + "width", + "The width of the current item, or default width of all items depending on context" +); +Event evi_height +( + "height", + EV_DEFAULT, + "i", + "height", + "The height of the current item, or default width of all items depending on context" +); +Event evi_barwidth +( + "barwidth", + EV_DEFAULT, + "i", + "width", + "The width of the current item's ammo bar or default width of all items bar's depending on context" +); +Event evi_barheight( + "barheight", + EV_DEFAULT, + "i", + "barheight", + "The height of the current item's ammo bar, or default width of all items bar's depending on context" +); +Event evi_baroffsetx +( + "baroffsetx", + EV_DEFAULT, + "i", + "width", + "The x offset used to calculate ammo bar" +); +Event evi_baroffsety +( + "baroffsety", + EV_DEFAULT, + "i", + "width", + "The y offset used to calculate ammo bar" +); +Event evi_item +( + "item", + EV_DEFAULT, + "s", + "item_name", + "The name of the current item" +); +Event evi_ammo +( + "ammo", + EV_DEFAULT, + "s", + "ammo_name", + "The name of the current item's ammo" +); +Event evi_equip +( + "equip", + EV_DEFAULT, + "sSSSSSSSSS", + "use use use use use use use use use use", + "Which ways you can use this item" +); +Event evi_checkammo +( + "checkammo", + EV_DEFAULT, + "b", + "bool", + "Check if the weapon has ammo before using it" +); +Event evi_command +( + "command", + EV_DEFAULT, + "s", + "command", + "Command to execute" +); +Event evi_model +( + "invmodel", + EV_DEFAULT, + "s", + "name", + "Which model this item is" +); +Event evi_anim +( + "invanim", + EV_DEFAULT, + "s", + "anim", + "Which anim this item uses" +); +Event evi_scale +( + "invscale", + EV_DEFAULT, + "f", + "scale", + "How much to scale the model" +); +Event evi_angles +( + "invangles", + EV_DEFAULT, + "v", + "angles", + "The orientation of the model" +); +Event evi_angledeltas +( + "invangledeltas", + EV_DEFAULT, + "v", + "angles", + "How to spin or bob the model" +); +Event evi_move +( + "invmove", + EV_DEFAULT, + "s", + "movetype", + "How to move the model when selected.\n either bob or spin" +); +Event evi_rotateoffset +( + "invrotateoffset", + EV_DEFAULT, + "v", + "offset", + "Offsets the origin of the model for rotation" +); +Event evi_offset +( + "invoffset", + EV_DEFAULT, + "v", + "offset", + "Offsets the origin of the model for moving" +); +Event evi_hudmodel +( + "hudmodel", + EV_DEFAULT, + "s", + "name", + "Which model this item is" +); +Event evi_hudanim +( + "hudanim", + EV_DEFAULT, + "s", + "anim", + "Which anim this item uses" +); +Event evi_hudscale +( + "hudscale", + EV_DEFAULT, + "f", + "scale", + "How much to scale the model" +); +Event evi_hudangles +( + "hudangles", + EV_DEFAULT, + "v", + "angles", + "The orientation of the model" +); +Event evi_hudangledeltas +( + "hudangledeltas", + EV_DEFAULT, + "v", + "angles", + "How to spin or bob the model" +); +Event evi_hudmove +( + "hudmove", + EV_DEFAULT, + "s", + "movetype", + "How to move the model when selected.\n either bob or spin" +); +Event evi_hudcompassangles +( + "hudcompassangles", + EV_DEFAULT, + NULL, + NULL, + "Applies the special case compass angles to the model\n" +); +Event evi_hudcompassneedleangles +( + "hudcompassneedleangles", + EV_DEFAULT, + NULL, + NULL, + "Applies the special case compass needle angles to the model\n" +); +Event evi_hudrotateoffset +( + "hudrotateoffset", + EV_DEFAULT, + "v", + "offset", + "Offsets the origin of the model for rotation" +); +Event evi_hudoffset +( + "hudoffset", + EV_DEFAULT, + "v", + "offset", + "Offsets the origin of the model for moving" +); +Event evi_bgshader +( + "bgshader", + EV_DEFAULT, + "s", + "shader", + "Shader to draw on the background of the item widget" +); +Event evi_barshader +( + "barshader", + EV_DEFAULT, + "s", + "shader", + "Shader to draw on the background of the item widget to display ammo counts" +); +Event evi_selitemshader +( + "selitem_shader", + EV_DEFAULT, + "s", + "shader", + "The shader for an item that is currently selected in the class submenu" +); +Event evi_selitemshaderontop +( + "selitem_shaderontop", + EV_DEFAULT, + NULL, + NULL, + "Whether the sel shader should be rendered after the model" +); +Event evi_modelwindow +( + "modelwindow", + EV_DEFAULT, + "ffff", + "x y width height", + "Specifies the dimensions of the model window for the inventory in normalized coordinates" +); + +CLASS_DECLARATION(Listener, invlistener, NULL) { + {&evi_inv_width, &invlistener::InvWidth }, + {&evi_inv_height, &invlistener::InvHeight }, + {&evi_inv_vertical_offset, &invlistener::InvVertOffset }, + {&evi_inv_horizontal_offset, &invlistener::InvHorizOffset }, + {&evi_inv_selectsound, &invlistener::InvSelectSound }, + {&evi_inv_rejectsound, &invlistener::InvRejectSound }, + {&evi_inv_changesound, &invlistener::InvChangeSound }, + {&evi_inv_align, &invlistener::InvAlign }, + {&evi_inv_cascade, &invlistener::InvCascade }, + {&evi_typedef, &invlistener::Typedef }, + {&evi_openbrace, &invlistener::OpenBrace }, + {&evi_closebrace, &invlistener::CloseBrace }, + {&evi_button_shader, &invlistener::ButtonShader }, + {&evi_hover_shader, &invlistener::HoverShader }, + {&evi_sel_shader, &invlistener::SelShader }, + {&evi_bg, &invlistener::Background }, + {&evi_bg_tile, &invlistener::BackgroundTile }, + {&evi_width, &invlistener::Width }, + {&evi_height, &invlistener::Height }, + {&evi_barwidth, &invlistener::BarWidth }, + {&evi_barheight, &invlistener::BarHeight }, + {&evi_baroffsetx, &invlistener::BarOffsetX }, + {&evi_baroffsety, &invlistener::BarOffsetY }, + {&evi_item, &invlistener::Item }, + {&evi_ammo, &invlistener::Ammo }, + {&evi_equip, &invlistener::Equip }, + {&evi_checkammo, &invlistener::CheckAmmo }, + {&evi_command, &invlistener::Command }, + {&evi_bgshader, &invlistener::BGShader }, + {&evi_barshader, &invlistener::BarShader }, + {&evi_selitemshader, &invlistener::SelItemShader }, + {&evi_selitemshaderontop, &invlistener::SelItemShaderOnTop }, + {&evi_modelwindow, &invlistener::ModelWindow }, + {&evi_model, &invlistener::Model }, + {&evi_anim, &invlistener::Anim }, + {&evi_move, &invlistener::Move }, + {&evi_rotateoffset, &invlistener::RotateOffset }, + {&evi_offset, &invlistener::Offset }, + {&evi_scale, &invlistener::Scale }, + {&evi_angles, &invlistener::Angles }, + {&evi_angledeltas, &invlistener::AngleDeltas }, + {&evi_hudmodel, &invlistener::HudModel }, + {&evi_hudanim, &invlistener::HudAnim }, + {&evi_hudmove, &invlistener::HudMove }, + {&evi_hudcompassangles, &invlistener::HudCompassAngles }, + {&evi_hudcompassneedleangles, &invlistener::HudCompassNeedleAngles}, + {&evi_hudrotateoffset, &invlistener::HudRotateOffset }, + {&evi_hudoffset, &invlistener::HudOffset }, + {&evi_hudscale, &invlistener::HudScale }, + {&evi_hudangles, &invlistener::HudAngles }, + {&evi_hudangledeltas, &invlistener::HudAngleDeltas }, + {NULL, NULL } +}; + +invlistener::invlistener(inventory_t *i) { - // FIXME: stub + inv = i; + curtype = 0; } -invlistener::invlistener() +invlistener::invlistener() {} + +void invlistener::verify_curitem(void) { - // FIXME: stub + if (!curitem) { + throw "no current item"; + } } -void invlistener::verify_curitem( void ) +void invlistener::verify_curtype(void) { - // FIXME: stub + if (!curtype) { + throw "no current type"; + } } -void invlistener::verify_curtype( void ) +void invlistener::verify_one_arg(Event *ev) { - // FIXME: stub + if (ev->NumArgs() != 1) { + throw "bad arg count"; + } } -void invlistener::verify_one_arg( Event *ev ) +bool invlistener::Load(Script& script) { - // FIXME: stub + str token; + str errortext; + + while (script.TokenAvailable(true)) { + token = script.GetToken(true); + + if (!token.length() || !ValidEvent(token)) { + throw "invalid token"; + } + + Event *event = new Event(token); + + while (script.TokenAvailable(false)) { + event->AddToken(script.GetToken(false)); + } + + ProcessEvent(event); + } + + return true; } -bool invlistener::Load( Script& script ) +bool CL_LoadInventory(const char *filename, inventory_t *inv) { - // FIXME: stub - return false; + Script script; + + Com_Printf("Loading inventory...\n"); + + inv->Clear(); + invlistener listener(inv); + + // Load the inventory file + script.LoadFile(filename); + return listener.Load(script); } -void invlistener::InvSelectSound( Event *ev ) +inventory_t::inventory_t() { - // FIXME: stub + typewidth = 64; + typeheight = 64; + horizoffset = 0; + vertoffset = 0; + align = INV_ALIGN_RIGHT; + cascade = INV_CASCADE_LEFT; } -void invlistener::InvRejectSound( Event *ev ) +inventory_t::~inventory_t() { - // FIXME: stub + Clear(); } -void invlistener::InvChangeSound( Event *ev ) +inventory_t::inventory_t(const inventory_t& other) { - // FIXME: stub + typewidth = other.typewidth; + typeheight = other.typeheight; + horizoffset = other.horizoffset; + vertoffset = other.vertoffset; + align = other.align; + cascade = other.cascade; + rejectsound = other.rejectsound; + selectsound = other.selectsound; + changesound = other.changesound; + types = other.types; } -void invlistener::InvWidth( Event *ev ) +inventory_t& inventory_t::operator=(const inventory_t& other) { - // FIXME: stub + Clear(); + + typewidth = other.typewidth; + typeheight = other.typeheight; + horizoffset = other.horizoffset; + vertoffset = other.vertoffset; + align = other.align; + cascade = other.cascade; + rejectsound = other.rejectsound; + selectsound = other.selectsound; + changesound = other.changesound; + types = other.types; + + return *this; } -void invlistener::InvHeight( Event *ev ) +void inventory_t::Clear() { - // FIXME: stub + types.ClearObjectList(); } -void invlistener::InvHorizOffset( Event *ev ) +void invlistener::InvAlign(Event *ev) { - // FIXME: stub + str side; + + verify_one_arg(ev); + + side = ev->GetString(1); + + if (!str::icmp(side, "left")) { + inv->align = INV_ALIGN_LEFT; + } else if (!str::icmp(side, "right")) { + inv->align = INV_ALIGN_RIGHT; + } else { + warning(__FUNCTION__, "Invalid align side '%s'\n", side.c_str()); + } } -void invlistener::InvVertOffset( Event *ev ) +void invlistener::InvCascade(Event *ev) { - // FIXME: stub + str side; + + verify_one_arg(ev); + + side = ev->GetString(1); + + if (!str::icmp(side, "left")) { + inv->cascade = INV_CASCADE_LEFT; + } else if (!str::icmp(side, "right")) { + inv->cascade = INV_CASCADE_RIGHT; + } else { + warning(__FUNCTION__, "Invalid cascade side '%s'\n", side.c_str()); + } } -void invlistener::InvAlign( Event *ev ) +void invlistener::InvWidth(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->typewidth = ev->GetInteger(1); } -void invlistener::InvCascade( Event *ev ) +void invlistener::InvHeight(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->typeheight = ev->GetInteger(1); } -void invlistener::Typedef( Event *ev ) +void invlistener::InvVertOffset(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->vertoffset = ev->GetInteger(1); } -void invlistener::OpenBrace( Event *ev ) +void invlistener::InvHorizOffset(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->horizoffset = ev->GetInteger(1); } -void invlistener::CloseBrace( Event *ev ) +void invlistener::InvSelectSound(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->selectsound = ev->GetString(1); } -void invlistener::ButtonShader( Event *ev ) +void invlistener::InvRejectSound(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->rejectsound = ev->GetString(1); } -void invlistener::HoverShader( Event *ev ) +void invlistener::InvChangeSound(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + inv->changesound = ev->GetString(1); } -void invlistener::SelShader( Event *ev ) +void invlistener::Typedef(Event *ev) { - // FIXME: stub + str type; + inventory_type_t *t; + + verify_one_arg(ev); + + type = ev->GetString(1); + + t = new inventory_type_t(); + t->name = type; + t->bg_tile = false; + + curtype = t; + curitem = NULL; + defaultWidth = 0; + defaultHeight = 0; + defaultBarWidth = 0; + defaultBarHeight = 0; + defaultBarOffsetX = 0; + defaultBarOffsetY = 0; + + inv->types.AddObject(t); } -void invlistener::Background( Event *ev ) +void invlistener::OpenBrace(Event *ev) {} + +void invlistener::CloseBrace(Event *ev) {} + +void invlistener::ButtonShader(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curtype(); + + curtype->texture = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::BackgroundTile( Event *ev ) +void invlistener::HoverShader(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curtype(); + + curtype->hoverTexture = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::Width( Event *ev ) +void invlistener::SelShader(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curtype(); + + curtype->selTexture = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::Height( Event *ev ) +void invlistener::Background(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curtype(); + + curtype->bg = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::BarWidth( Event *ev ) +void invlistener::BackgroundTile(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curtype(); + + curtype->bg = uWinMan.RegisterShader(ev->GetString(1)); + curtype->bg_tile = true; } -void invlistener::BarHeight( Event *ev ) +void invlistener::BGShader(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->bgshader = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::BarOffsetX( Event *ev ) +void invlistener::SelItemShader(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->selshader = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::BarOffsetY( Event *ev ) +void invlistener::SelItemShaderOnTop(Event *ev) { - // FIXME: stub + verify_curitem(); + + curitem->selShaderOnTop = true; } -void invlistener::Item( Event *ev ) +void invlistener::BarShader(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->barshader = uWinMan.RegisterShader(ev->GetString(1)); } -void invlistener::Ammo( Event *ev ) +void invlistener::Width(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + if (curitem) { + curitem->width = ev->GetInteger(1); + } else { + defaultWidth = ev->GetInteger(1); + } } -void invlistener::Equip( Event *ev ) +void invlistener::Height(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + if (curitem) { + curitem->height = ev->GetInteger(1); + } else { + defaultHeight = ev->GetInteger(1); + } } -void invlistener::CheckAmmo( Event *ev ) +void invlistener::BarWidth(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + if (curitem) { + curitem->barwidth = ev->GetInteger(1); + } else { + defaultBarWidth = ev->GetInteger(1); + } } -void invlistener::Command( Event *ev ) +void invlistener::BarHeight(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + if (curitem) { + curitem->barheight = ev->GetInteger(1); + } else { + defaultBarHeight = ev->GetInteger(1); + } } -void invlistener::BGShader( Event *ev ) +void invlistener::BarOffsetY(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + if (curitem) { + curitem->baroffsetY = ev->GetInteger(1); + } else { + defaultBarOffsetY = ev->GetInteger(1); + } } -void invlistener::BarShader( Event *ev ) +void invlistener::BarOffsetX(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + if (curitem) { + curitem->baroffsetX = ev->GetInteger(1); + } else { + defaultBarOffsetX = ev->GetInteger(1); + } } -void invlistener::SelItemShader( Event *ev ) +void invlistener::Item(Event *ev) { - // FIXME: stub + str type; + inventory_item_t *item; + + verify_one_arg(ev); + verify_curtype(); + + item = new inventory_item_t(); + item->name = ev->GetString(1); + + item->width = defaultWidth; + item->height = defaultHeight; + item->barwidth = defaultBarWidth; + item->barheight = defaultBarHeight; + item->baroffsetX = defaultBarOffsetX; + item->baroffsetY = defaultBarOffsetY; + item->equip = 8; + + curtype->items.AddObject(item); + curitem = curtype->items.ObjectAt(curtype->items.NumObjects()); } -void invlistener::SelItemShaderOnTop( Event *ev ) +void invlistener::Ammo(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->ammoname = ev->GetString(1); } -void invlistener::RotateOffset( Event *ev ) +void invlistener::RotateOffset(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.rotateoffset = ev->GetVector(1); } -void invlistener::Offset( Event *ev ) +void invlistener::HudRotateOffset(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.rotateoffset = ev->GetVector(1); } -void invlistener::Model( Event *ev ) +void invlistener::Offset(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.offset = ev->GetVector(1); } -void invlistener::Anim( Event *ev ) +void invlistener::HudOffset(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.offset = ev->GetVector(1); } -void invlistener::Scale( Event *ev ) +void invlistener::Command(Event *ev) { - // FIXME: stub + verify_curitem(); + + if (ev->NumArgs() <= 0) { + throw "command needs one or more args"; + } + + curitem->command = ev->GetString(1); } -void invlistener::Angles( Event *ev ) +void invlistener::CheckAmmo(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + curitem->checkammo = ev->GetBoolean(1); } -void invlistener::AngleDeltas( Event *ev ) +void invlistener::Equip(Event *ev) { - // FIXME: stub + int i; + + verify_curitem(); + + if (ev->NumArgs() <= 0) { + throw "command needs one or more args"; + } + + curitem->equip = 0; + + for (i = 1; i <= ev->NumArgs(); i++) { + str equipstr = ev->GetString(i); + int tab; + + for (tab = 0; s_equipTable[tab].string; tab++) { + if (equipstr == s_equipTable[tab].string) { + curitem->equip |= s_equipTable[tab].value; + break; + } + } + + if (!s_equipTable[tab].string) { + throw "bad equip arguments"; + } + } } -void invlistener::Move( Event *ev ) +void invlistener::Model(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.model = ev->GetString(1); } -void invlistener::ModelWindow( Event *ev ) +void invlistener::ModelWindow(Event *ev) { - // FIXME: stub + if (ev->NumArgs() != 4) { + throw "ModelWindow: bad arg count"; + } + + verify_curitem(); + + curitem->modelWindowX = ev->GetFloat(1); + curitem->modelWindowY = ev->GetFloat(2); + curitem->modelWindowWidth = ev->GetFloat(3); + curitem->modelWindowHeight = ev->GetFloat(4); } -void invlistener::HudRotateOffset( Event *ev ) +void invlistener::HudModel(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.model = ev->GetString(1); } -void invlistener::HudOffset( Event *ev ) +void invlistener::Anim(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.anim = ev->GetString(1); } -void invlistener::HudModel( Event *ev ) +void invlistener::HudAnim(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.anim = ev->GetString(1); } -void invlistener::HudAnim( Event *ev ) +void invlistener::Scale(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.scale = ev->GetFloat(1); } -void invlistener::HudScale( Event *ev ) +void invlistener::HudScale(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.scale = ev->GetFloat(1); } -void invlistener::HudAngles( Event *ev ) +void invlistener::Angles(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.angles = ev->GetVector(1); } -void invlistener::HudAngleDeltas( Event *ev ) +void invlistener::HudAngles(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.angles = ev->GetVector(1); } -void invlistener::HudMove( Event *ev ) +void invlistener::AngleDeltas(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->invprops.angledeltas = ev->GetVector(1); } -void invlistener::HudCompassAngles( Event *ev ) +void invlistener::HudAngleDeltas(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + curitem->hudprops.angledeltas = ev->GetVector(1); } -void invlistener::HudCompassNeedleAngles( Event *ev ) +void invlistener::Move(Event *ev) { - // FIXME: stub + verify_one_arg(ev); + verify_curitem(); + + str arg = ev->GetString(1); + + if (arg == "bob") { + curitem->invprops.move = INV_MOVE_BOB; + } else if (arg == "spin") { + curitem->invprops.move = INV_MOVE_SPIN; + } else { + throw "bad move arguments"; + } } -bool CL_LoadInventory( const char *filename, inventory_t *inv ) +void invlistener::HudMove(Event *ev) { - // FIXME: stub - return false; + verify_one_arg(ev); + verify_curitem(); + + str arg = ev->GetString(1); + + if (arg == "bob") { + curitem->hudprops.move = INV_MOVE_BOB; + } else if (arg == "spin") { + curitem->hudprops.move = INV_MOVE_SPIN; + } else { + throw "bad move arguments"; + } } -inventory_item_t *CL_GetInvItemByName( inventory_t *inv, const char *name ) +void invlistener::HudCompassAngles(Event *ev) { - // FIXME: stub - return NULL; + verify_curitem(); + + curitem->anglesType = INV_HUDANGLES_COMPASS; } -qboolean CL_HasInventoryItem( const char *name ) +void invlistener::HudCompassNeedleAngles(Event *ev) { - // FIXME: stub - return qfalse; + verify_curitem(); + + curitem->anglesType = INV_HUDANGLES_COMPASS_NEEDLE; } -void CL_AmmoCount( const char *name, int *ammo_count, int *max_ammo_count ) +inventory_item_t *CL_GetInvItemByName(inventory_t *inv, const char *name) { - // FIXME: stub + if (!inv) { + return NULL; + } + + for (int i = 1; i <= inv->types.NumObjects(); i++) { + const inventory_type_t *type = inv->types.ObjectAt(i); + + for (int ii = 1; ii <= type->items.NumObjects(); ii++) { + inventory_item_t *item = type->items.ObjectAt(i); + + if (!item) { + return NULL; + } + + if (!str::icmp(item->name, name)) { + return item; + } + } + } + + return NULL; +} + +qboolean CL_HasInventoryItem(const char *name) +{ + int i; + + for (i = 2; i < 6; i++) { + int index = cl.snap.ps.activeItems[i]; + + if (index > 0) { + if (!str::icmp(name, CL_ConfigString(CS_WEAPONS + index))) { + return true; + } + } + } + + return false; +} + +void CL_AmmoCount(const char *name, int *ammo_count, int *max_ammo_count) +{ + int i; + + *ammo_count = 0; + *max_ammo_count = 0; + + for (i = 0; i < ARRAY_LEN(cl.snap.ps.ammo_name_index); i++) { + int index = cl.snap.ps.ammo_name_index[i]; + if (index) { + if (!str::icmp(name, CL_ConfigString(CS_WEAPONS + index))) { + *ammo_count = cl.snap.ps.ammo_amount[i]; + *max_ammo_count = cl.snap.ps.max_ammo_amount[i]; + break; + } + } + } } diff --git a/code/client/cl_inv.h b/code/client/cl_inv.h index fef74f34..45cf58af 100644 --- a/code/client/cl_inv.h +++ b/code/client/cl_inv.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,175 +20,198 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_INV_H__ -#define __CL_INV_H__ +#pragma once -typedef enum { INV_MOVE_NONE, INV_MOVE_BOB, INV_MOVE_SPIN } inv_move_type; -typedef enum { INV_CASCADE_LEFT, INV_CASCADE_RIGHT } inv_cascade_type; -typedef enum { INV_HUDANGLES_BASE, INV_HUDANGLES_COMPASS, INV_HUDANGLES_COMPASS_NEEDLE } inv_hudangles_type; +typedef enum { + INV_MOVE_NONE, + INV_MOVE_BOB, + INV_MOVE_SPIN +} inv_move_type; -class item_properties_t : public Class { -public: - float scale; - Vector angles; - Vector angledeltas; - Vector rotateoffset; - Vector offset; - inv_move_type move; - str model; - str anim; -}; +typedef enum { + INV_ALIGN_NONE, + INV_ALIGN_LEFT, + INV_ALIGN_RIGHT +} inv_align_type; -class inventory_item_t : public Class { -public: - str name; - str ammoname; - int equip; - int width; - int height; - int barwidth; - int barheight; - int baroffsetY; - int baroffsetX; - float modelWindowX; - float modelWindowY; - float modelWindowWidth; - float modelWindowHeight; - bool selShaderOnTop; - bool checkammo; - str command; - inv_hudangles_type anglesType; - item_properties_t hudprops; - item_properties_t invprops; - UIReggedMaterial *bgshader; - UIReggedMaterial *barshader; - UIReggedMaterial *selshader; -}; +typedef enum { + INV_CASCADE_LEFT, + INV_CASCADE_RIGHT +} inv_cascade_type; -class inventory_type_t { -public: - str name; - bool bg_tile; - UIReggedMaterial *texture; - UIReggedMaterial *bg; - UIReggedMaterial *hoverTexture; - UIReggedMaterial *selTexture; - Container items; +typedef enum { + INV_HUDANGLES_BASE, + INV_HUDANGLES_COMPASS, + INV_HUDANGLES_COMPASS_NEEDLE +} inv_hudangles_type; - int IndexOfItemPtr( inventory_item_t *item ); -}; - -inline -int inventory_type_t::IndexOfItemPtr( inventory_item_t *item ) +class item_properties_t : public Class { - for( int i = items.NumObjects(); i > 0; i-- ) - { - if( items.ObjectAt( i ) == item ) - { - return i; - } - } +public: + float scale; + Vector angles; + Vector angledeltas; + Vector rotateoffset; + Vector offset; + inv_move_type move; + str model; + str anim; +}; - return 0; +class inventory_item_t : public Class +{ +public: + str name; + str ammoname; + int equip; + int width; + int height; + int barwidth; + int barheight; + int baroffsetY; + int baroffsetX; + float modelWindowX; + float modelWindowY; + float modelWindowWidth; + float modelWindowHeight; + bool selShaderOnTop; + bool checkammo; + str command; + inv_hudangles_type anglesType; + item_properties_t hudprops; + item_properties_t invprops; + UIReggedMaterial *bgshader; + UIReggedMaterial *barshader; + UIReggedMaterial *selshader; +}; + +class inventory_type_t +{ +public: + str name; + bool bg_tile; + UIReggedMaterial *texture; + UIReggedMaterial *bg; + UIReggedMaterial *hoverTexture; + UIReggedMaterial *selTexture; + Container items; + + int IndexOfItemPtr(inventory_item_t *item); +}; + +inline int inventory_type_t::IndexOfItemPtr(inventory_item_t *item) +{ + for (int i = items.NumObjects(); i > 0; i--) { + if (items.ObjectAt(i) == item) { + return i; + } + } + + return 0; } -class inventory_t { +class inventory_t +{ public: - int typewidth; - int typeheight; - int horizoffset; - int vertoffset; - int align; - inv_cascade_type cascade; - str selectsound; - str rejectsound; - str changesound; - Container types; + int typewidth; + int typeheight; + int horizoffset; + int vertoffset; + inv_align_type align; + inv_cascade_type cascade; + str selectsound; + str rejectsound; + str changesound; + Container types; - void Clear() { types.ClearObjectList(); } +public: + inventory_t(); + ~inventory_t(); + inventory_t(const inventory_t& other); + inventory_t& operator=(const inventory_t& other); + void Clear(); }; -class invlistener : public Listener { +class invlistener : public Listener +{ protected: - inventory_t *inv; - inventory_type_t *curtype; - inventory_item_t *curitem; - int defaultWidth; - int defaultHeight; - int defaultBarWidth; - int defaultBarHeight; - int defaultBarOffsetX; - int defaultBarOffsetY; + inventory_t *inv; + inventory_type_t *curtype; + inventory_item_t *curitem; + int defaultWidth; + int defaultHeight; + int defaultBarWidth; + int defaultBarHeight; + int defaultBarOffsetX; + int defaultBarOffsetY; public: - CLASS_PROTOTYPE( invlistener ); + CLASS_PROTOTYPE(invlistener); protected: - void verify_curitem( void ); - void verify_curtype( void ); - void verify_one_arg( Event *ev ); + void verify_curitem(void); + void verify_curtype(void); + void verify_one_arg(Event *ev); public: - invlistener( inventory_t *i ); - invlistener(); + invlistener(inventory_t *i); + invlistener(); - bool Load( Script& script ); - void InvSelectSound( Event *ev ); - void InvRejectSound( Event *ev ); - void InvChangeSound( Event *ev ); - void InvWidth( Event *ev ); - void InvHeight( Event *ev ); - void InvHorizOffset( Event *ev ); - void InvVertOffset( Event *ev ); - void InvAlign( Event *ev ); - void InvCascade( Event *ev ); - void Typedef( Event *ev ); - void OpenBrace( Event *ev ); - void CloseBrace( Event *ev ); - void ButtonShader( Event *ev ); - void HoverShader( Event *ev ); - void SelShader( Event *ev ); - void Background( Event *ev ); - void BackgroundTile( Event *ev ); - void Width( Event *ev ); - void Height( Event *ev ); - void BarWidth( Event *ev ); - void BarHeight( Event *ev ); - void BarOffsetX( Event *ev ); - void BarOffsetY( Event *ev ); - void Item( Event *ev ); - void Ammo( Event *ev ); - void Equip( Event *ev ); - void CheckAmmo( Event *ev ); - void Command( Event *ev ); - void BGShader( Event *ev ); - void BarShader( Event *ev ); - void SelItemShader( Event *ev ); - void SelItemShaderOnTop( Event *ev ); - void RotateOffset( Event *ev ); - void Offset( Event *ev ); - void Model( Event *ev ); - void Anim( Event *ev ); - void Scale( Event *ev ); - void Angles( Event *ev ); - void AngleDeltas( Event *ev ); - void Move( Event *ev ); - void ModelWindow( Event *ev ); - void HudRotateOffset( Event *ev ); - void HudOffset( Event *ev ); - void HudModel( Event *ev ); - void HudAnim( Event *ev ); - void HudScale( Event *ev ); - void HudAngles( Event *ev ); - void HudAngleDeltas( Event *ev ); - void HudMove( Event *ev ); - void HudCompassAngles( Event *ev ); - void HudCompassNeedleAngles( Event *ev ); + bool Load(Script& script); + void InvSelectSound(Event *ev); + void InvRejectSound(Event *ev); + void InvChangeSound(Event *ev); + void InvWidth(Event *ev); + void InvHeight(Event *ev); + void InvHorizOffset(Event *ev); + void InvVertOffset(Event *ev); + void InvAlign(Event *ev); + void InvCascade(Event *ev); + void Typedef(Event *ev); + void OpenBrace(Event *ev); + void CloseBrace(Event *ev); + void ButtonShader(Event *ev); + void HoverShader(Event *ev); + void SelShader(Event *ev); + void Background(Event *ev); + void BackgroundTile(Event *ev); + void Width(Event *ev); + void Height(Event *ev); + void BarWidth(Event *ev); + void BarHeight(Event *ev); + void BarOffsetX(Event *ev); + void BarOffsetY(Event *ev); + void Item(Event *ev); + void Ammo(Event *ev); + void Equip(Event *ev); + void CheckAmmo(Event *ev); + void Command(Event *ev); + void BGShader(Event *ev); + void BarShader(Event *ev); + void SelItemShader(Event *ev); + void SelItemShaderOnTop(Event *ev); + void RotateOffset(Event *ev); + void Offset(Event *ev); + void Model(Event *ev); + void Anim(Event *ev); + void Scale(Event *ev); + void Angles(Event *ev); + void AngleDeltas(Event *ev); + void Move(Event *ev); + void ModelWindow(Event *ev); + void HudRotateOffset(Event *ev); + void HudOffset(Event *ev); + void HudModel(Event *ev); + void HudAnim(Event *ev); + void HudScale(Event *ev); + void HudAngles(Event *ev); + void HudAngleDeltas(Event *ev); + void HudMove(Event *ev); + void HudCompassAngles(Event *ev); + void HudCompassNeedleAngles(Event *ev); }; -bool CL_LoadInventory( const char *filename, inventory_t *inv ); -inventory_item_t *CL_GetInvItemByName( inventory_t *inv, const char *name ); -qboolean CL_HasInventoryItem( const char *name ); -void CL_AmmoCount( const char *name, int *ammo_count, int *max_ammo_count ); - -#endif // __CL_INV_H__ +bool CL_LoadInventory(const char *filename, inventory_t *inv); +inventory_item_t *CL_GetInvItemByName(inventory_t *inv, const char *name); +qboolean CL_HasInventoryItem(const char *name); +void CL_AmmoCount(const char *name, int *ammo_count, int *max_ammo_count); diff --git a/code/client/cl_invrender.cpp b/code/client/cl_invrender.cpp index bcb5125b..cfbdb3f1 100644 --- a/code/client/cl_invrender.cpp +++ b/code/client/cl_invrender.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,204 +21,1037 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/tiki.h" -CLASS_DECLARATION( UIWidget, FakkItemList, NULL ) -{ - { NULL, NULL } +static inventory_t s_processed_inv; +static SafePtr s_main_inv; + +Event FakkInventory_Timeout("_timeout", EV_DEFAULT, NULL, NULL, "Timeout of the menu from inactivity"); + +CLASS_DECLARATION(UIWidget, FakkInventory, NULL) { + {&W_MouseMoved, &FakkInventory::OnMouseMove }, + {&W_MouseEntered, &FakkInventory::OnMouseEnter}, + {&W_MouseExited, &FakkInventory::OnMouseLeave}, + {&W_LeftMouseDown, &FakkInventory::OnMouseDown }, + {&W_RightMouseDown, &FakkInventory::OnMouseDown }, + {&FakkInventory_Timeout, &FakkInventory::Timeout }, + {NULL, NULL } }; -FakkItemList::FakkItemList() -{ - // FIXME: stub -} - -FakkItemList::~FakkItemList() -{ - // FIXME: stub -} - -void FakkItemList::VerifyItemUp( inventory_item_t *item, qboolean warpmouse ) -{ - // FIXME: stub -} - -void FakkItemList::setType( inventory_type_t *t ) -{ - // FIXME: stub -} - -void FakkItemList::Create( float x, float y, FakkInventory *parent ) -{ - // FIXME: stub -} - -bool FakkItemList::HasAnyItems( void ) -{ - // FIXME: stub - return false; -} - -void FakkItemList::Draw( void ) -{ - // FIXME: stub -} - -void FakkItemList::OnLeftMouseDown( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnRightMouseDown( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnLeftMouseUp( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnRightMouseUp( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnMouseMove( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnMouseEnter( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnMouseLeave( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::OnMenuKilled( Event *ev ) -{ - // FIXME: stub -} - -void FakkItemList::EquipItem( Event *ev ) -{ - // FIXME: stub -} - -CLASS_DECLARATION( UIWidget, FakkInventory, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(UIWidget, FakkItemList, NULL) { + {&W_LeftMouseDown, &FakkItemList::OnLeftMouseDown }, + {&W_RightMouseDown, &FakkItemList::OnRightMouseDown}, + {&W_LeftMouseUp, &FakkItemList::OnLeftMouseUp }, + {&W_RightMouseUp, &FakkItemList::OnRightMouseUp }, + {&W_MouseMoved, &FakkItemList::OnMouseMove }, + {&W_MouseEntered, &FakkItemList::OnMouseEnter }, + {&W_MouseExited, &FakkItemList::OnMouseLeave }, + {&W_Destroyed, &FakkItemList::OnMenuKilled }, + {NULL, NULL } }; +void CL_Draw3DModel( + float x, + float y, + float w, + float h, + qhandle_t model, + vec3_t origin, + vec3_t rotateoffset, + vec3_t offset, + vec3_t angle, + vec3_t color, + str anim +) +{ + refdef_t inv_refdef {}; + refEntity_t ent {}; + vec3_t unprojoffset; + vec3_t entaxis[3]; + + inv_refdef.fov_x = 30; + inv_refdef.fov_y = 30; + inv_refdef.x = x; + inv_refdef.y = y; + inv_refdef.width = w; + inv_refdef.rdflags = RDF_HUD | RDF_NOWORLDMODEL; + inv_refdef.height = h; + inv_refdef.time = cl.serverTime; + re.ClearScene(); + + AnglesToAxis(angle, entaxis); + + MatrixTransformVector(rotateoffset, entaxis, unprojoffset); + + ent.scale = 1.0; + ent.hModel = model; + ent.entityNumber = 1023; + VectorAdd(origin, offset, ent.origin); + VectorAdd(ent.origin, unprojoffset, ent.origin); + + ent.tiki = re.R_Model_GetHandle(model); + if (!ent.tiki) { + return; + } + + if (anim.length()) { + static qboolean bInited = false; + static int hModel[8]; + static int iUpdateTime[8]; + static int iIndex[8]; + static float fAnimTime[8]; + static char szAnimName[8][256]; + int i; + int iCurrNum; + + if (!bInited) { + for (i = 0; i < ARRAY_LEN(hModel); i++) { + iUpdateTime[i] = 0; + iIndex[i] = -1; + hModel[i] = -1; + } + bInited = true; + } + + for (i = 0; i < ARRAY_LEN(hModel); i++) { + if (hModel[i] == model) { + break; + } + } + + if (i == ARRAY_LEN(hModel)) { + iCurrNum = 0; + + // Find a free slot + for (i = 0; i < ARRAY_LEN(hModel); i++) { + if (hModel[i] == -1) { + iCurrNum = i; + break; + } + } + + if (i == ARRAY_LEN(hModel)) { + int iOldestNum, iOldestTime; + + iOldestTime = iUpdateTime[0]; + iOldestNum = 0; + + for (i = 1; i < ARRAY_LEN(hModel); i++) { + if (iUpdateTime[i] < iOldestTime) { + iOldestNum = i; + iOldestTime = iUpdateTime[i]; + } + } + + iCurrNum = iOldestNum; + } + + hModel[iCurrNum] = model; + iIndex[iCurrNum] = -1; + Q_strncpyz(szAnimName[iCurrNum], anim, sizeof(szAnimName[iCurrNum])); + } else { + iCurrNum = i; + + if (!Q_stricmp(szAnimName[iCurrNum], anim)) { + fAnimTime[iCurrNum] += (cls.realtime - iUpdateTime[i]) * 0.001f; + iUpdateTime[iCurrNum] = cls.realtime; + + if (TIKI_Anim_Time(ent.tiki, iIndex[iCurrNum]) < fAnimTime[iCurrNum]) { + // Added in 2.0 + // Clear tunak easter egg + Cvar_Set("tunak", "0"); + iIndex[iCurrNum] = -1; + } + } else { + iIndex[iCurrNum] = -1; + Q_strncpyz(szAnimName[iCurrNum], anim, sizeof(szAnimName[iCurrNum])); + } + } + + if (iIndex[iCurrNum] == -1) { + iIndex[iCurrNum] = TIKI_Anim_NumForName(ent.tiki, szAnimName[iCurrNum]); + fAnimTime[iCurrNum] = 0; + iUpdateTime[iCurrNum] = cls.realtime; + } + + ent.frameInfo[0].index = iIndex[iCurrNum]; + ent.frameInfo[0].time = fAnimTime[iCurrNum]; + ent.frameInfo[0].weight = 1.f; + ent.actionWeight = 1.f; + } + + ent.shaderRGBA[0] = color[0] * 255; + ent.shaderRGBA[1] = color[1] * 255; + ent.shaderRGBA[2] = color[2] * 255; + ent.shaderRGBA[3] = color[3] * 255; + + if (cge) { + vec3_t vViewAngles; + + cge->CG_EyePosition(&inv_refdef.vieworg); + cge->CG_EyeAngles(&vViewAngles); + AnglesToAxis(vViewAngles, inv_refdef.viewaxis); + + VectorCopy(ent.origin, unprojoffset); + MatrixTransformVector(unprojoffset, inv_refdef.viewaxis, ent.origin); + MatrixMultiply(entaxis, inv_refdef.viewaxis, ent.axis); + VectorAdd(ent.origin, inv_refdef.vieworg, ent.origin); + } else { + AnglesToAxis(angle, ent.axis); + AxisClear(inv_refdef.viewaxis); + } + + re.AddRefEntityToScene(&ent, ENTITYNUM_NONE); + re.RenderScene(&inv_refdef); +} + +bool CL_DoIHaveThisItem(const char *name) +{ + return true; +} + +static void ProcessType(inventory_type_t *type) +{ + for (int i = 1; i < type->items.NumObjects(); i++) { + const inventory_item_t *item = type->items.ObjectAt(i); + + if (!CL_DoIHaveThisItem(item->name)) { + type->items.RemoveObjectAt(i--); + } + } +} + +static void ProcessInventory() +{ + for (int i = 1; i <= s_processed_inv.types.NumObjects(); i++) { + inventory_type_t *type = s_processed_inv.types.ObjectAt(i); + + ProcessType(type); + if (!type->items.NumObjects()) { + delete type; + s_processed_inv.types.RemoveObjectAt(i--); + } + } +} + +void UI_NextInventory() +{ + UI_DoInventory(false); + + if (s_main_inv) { + s_main_inv->WarpTo(1); + s_main_inv->NextItem(); + } +} + +void UI_PrevInventory() +{ + UI_DoInventory(false); + + if (s_main_inv) { + s_main_inv->WarpTo(1); + s_main_inv->PrevItem(); + } +} + +void UI_WarpInventory() +{ + UI_DoInventory(0); + + if (Cmd_Argc() != 2) { + Com_Printf("Usage: warpinv "); + } + + if (s_main_inv) { + s_main_inv->WarpTo(Cmd_Argv(1)); + } +} + +void UI_DoInventory_f() +{ + UI_DoInventory(1); + + if (s_main_inv) { + s_main_inv->WarpTo(1); + } +} + +void UI_DoInventory(qboolean activate_mouse) +{ + if ((cl.snap.ps.stats[STAT_CINEMATIC] & 1) || s_main_inv) { + return; + } + + ProcessInventory(); + + if (!s_processed_inv.types.NumObjects()) { + UI_UpdateCenterPrint("- No inventory -", 1); + return; + } + + s_main_inv = new FakkInventory(); + s_main_inv->setInventory(&s_processed_inv); + + if (client_inv.align == INV_ALIGN_RIGHT) { + s_main_inv->InitFrame( + NULL, + client_inv.horizoffset + uid.vidWidth - client_inv.typewidth, + client_inv.vertoffset, + client_inv.typewidth, + client_inv.typeheight * client_inv.types.NumObjects(), + 0 + ); + } else if (client_inv.align == INV_ALIGN_LEFT) { + s_main_inv->InitFrame( + NULL, + client_inv.horizoffset, + client_inv.vertoffset, + client_inv.typewidth, + client_inv.typeheight * client_inv.types.NumObjects(), + 0 + ); + } + + uWinMan.ActivateControl(s_main_inv); + + if (activate_mouse) { + IN_MouseOn(); + } + + s_main_inv->m_mouse_active = true; +} + +qboolean UI_CloseInventory() +{ + menuManager.PassEventToAllWidgets(EV_ClearInvItemReference); + + if (!s_main_inv || s_main_inv->isDying()) { + return false; + } + + delete s_main_inv; + + UI_FocusMenuIfExists(); + return true; +} FakkInventory::FakkInventory() { - // FIXME: stub + m_currenttype = NULL; + AllowActivate(false); + UIWidget::setBackgroundColor(UColor(), true); } FakkInventory::~FakkInventory() { - // FIXME: stub + if (!uWinMan.IsDead()) { + VerifyTypeUp(NULL, false); + } } -void FakkInventory::VerifyItemUp( inventory_item_t *item, qboolean warpmouse ) +int FakkInventory::FindFirstItem(int itemindex, int sign) { - // FIXME: stub + int i; + + for (i = itemindex; i > 0 && i <= m_currenttype->items.NumObjects(); i += sign) { + const inventory_item_t *item = m_currenttype->items.ObjectAt(i); + + if (CL_HasInventoryItem(item->name)) { + break; + } + } + + return i; } -void FakkInventory::setInventory( inventory_t *i ) +void FakkInventory::ChangeItem(int sign) { - // FIXME: stub + int itemindex; + int groupindex; + inventory_item_t *selitem; + + if (!m_currenttype && !m_currentlist) { + WarpTo(1); + } + + itemindex = m_currenttype->IndexOfItemPtr(m_currentlist->getHoverItem()); + if (itemindex) { + itemindex = FindFirstItem(itemindex + sign, sign); + if (itemindex <= 0 || itemindex > m_currenttype->items.NumObjects()) { + groupindex = m_inv->types.IndexOfObject(m_currenttype); + if (groupindex) { + groupindex += sign; + if (groupindex > m_inv->types.NumObjects()) { + groupindex = 1; + } else if (groupindex < 1) { + groupindex = m_inv->types.NumObjects(); + } + + VerifyTypeUp(m_inv->types.ObjectAt(groupindex), false); + + if (sign > 0) { + itemindex = FindFirstItem(1, sign); + } else { + itemindex = FindFirstItem(m_inv->types.ObjectAt(groupindex)->items.NumObjects(), sign); + } + + if (itemindex > m_inv->types.ObjectAt(groupindex)->items.NumObjects()) { + itemindex = 1; + } + } else { + VerifyTypeUp(m_inv->types.ObjectAt(1), false); + itemindex = FindFirstItem(1, sign); + } + } + } else { + itemindex = 1; + } + + selitem = m_currenttype->items.ObjectAt(itemindex); + return m_currentlist->VerifyItemUp(selitem, false); } -void FakkInventory::Draw( void ) +void FakkInventory::NextItem(void) { - // FIXME: stub + ChangeItem(1); } -void FakkInventory::OnMouseMove( Event *ev ) +void FakkInventory::PrevItem(void) { - // FIXME: stub + ChangeItem(-1); } -void FakkInventory::OnMouseLeave( Event *ev ) +void FakkInventory::Timeout(Event *ev) { - // FIXME: stub + UI_CloseInventory(); } -void FakkInventory::OnMouseEnter( Event *ev ) +void FakkInventory::PlaySound(invsound_t type) { - // FIXME: stub + switch (type) { + case invsound_t::selectsound: + S_StartLocalSound(m_inv->selectsound, qfalse); + break; + case invsound_t::rejectsound: + S_StartLocalSound(m_inv->rejectsound, qfalse); + break; + case invsound_t::changesound: + S_StartLocalSound(m_inv->changesound, qfalse); + break; + default: + break; + } } -void FakkInventory::OnMouseDown( Event *ev ) +void FakkInventory::Draw(void) { - // FIXME: stub + int i; + bool mouse_in; + UIPoint2D clientPoint; + + if (!m_inv) { + return; + } + + clientPoint = UIPoint2D(uid.mouseX, uid.mouseY); + mouse_in = uWinMan.FindResponder(clientPoint) == this; + clientPoint = getLocalPoint(clientPoint); + + for (i = 1; i <= m_inv->types.NumObjects(); i++) { + inventory_type_t *type; + float top; + UIReggedMaterial *torender; + + type = m_inv->types.ObjectAt(i); + top = m_inv->typeheight * (i - 1); + if (type == m_currenttype) { + if (mouse_in) { + torender = type->hoverTexture; + } else { + torender = type->selTexture; + } + } else { + torender = type->texture; + } + + if (torender) { + uii.Rend_DrawPicStretched( + 0, top, m_inv->typewidth, m_inv->typeheight, 0, 0, 1.f, 1.f, torender->GetMaterial() + ); + } + } } -void FakkInventory::WarpTo( const char *name ) +void FakkInventory::OnMouseDown(Event *ev) { - // FIXME: stub + inventory_type_t *oldtype; + UIPoint2D p; + int i; + + p = MouseEventToClientPoint(ev); + i = (int)(p.y / m_inv->typeheight); + + if (i + 1 > m_inv->types.NumObjects()) { + return; + } + + oldtype = m_currenttype; + VerifyTypeUp(m_inv->types.ObjectAt(i + 1), true); + + if (m_currentlist && m_currenttype == oldtype) { + m_currentlist->VerifyItemUp(m_currenttype->items.ObjectAt(1), true); + } } -void FakkInventory::WarpTo( int slotnum ) +void FakkInventory::OnMouseMove(Event *ev) {} + +void FakkInventory::OnMouseLeave(Event *ev) {} + +void FakkInventory::OnMouseEnter(Event *ev) { - // FIXME: stub + SetHovermaterialActive(true); } -void FakkInventory::NextItem( void ) +void FakkInventory::VerifyTypeUp(inventory_type_t *t, qboolean warpmouse) { - // FIXME: stub + CancelEventsOfType(FakkInventory_Timeout); + PostEvent(new Event(FakkInventory_Timeout), 5); + + if (m_currenttype != t) { + if (m_currenttype) { + delete m_currenttype; + } + + m_currenttype = t; + if (t) { + m_currentlist = new FakkItemList(); + m_currentlist->setType(m_currenttype); + + switch (m_inv->cascade) { + case INV_CASCADE_LEFT: + m_currentlist->Create(m_screenframe.pos.x, m_screenframe.pos.y, this); + break; + case INV_CASCADE_RIGHT: + m_currentlist->Create(m_screenframe.pos.x + m_screenframe.size.width, m_screenframe.pos.y, this); + break; + default: + break; + } + } + + if (m_currenttype) { + PlaySound(invsound_t::changesound); + } + } + + if (warpmouse && m_currentlist) { + int i; + int height = 0; + + for (i = 1; i <= m_inv->types.NumObjects() && m_inv->types.ObjectAt(i) != t; i++) { + height += m_inv->typeheight; + } + + CL_SetMousePos( + (int)((m_inv->typewidth / 2) + m_screenframe.pos.x), + (int)((m_inv->typeheight / 2 + height) + m_screenframe.pos.y) + ); + } } -void FakkInventory::PrevItem( void ) +void FakkInventory::WarpTo(int slotnum) { - // FIXME: stub + int i; + + for (i = slotnum; i > 0 && i <= m_inv->types.NumObjects(); i++) { + inventory_type_t *t = m_inv->types.ObjectAt(i); + if (t) { + VerifyTypeUp(t, true); + } + } } -qboolean FakkInventory::isDying( void ) +void FakkInventory::WarpTo(const char *name) { - // FIXME: stub - return qfalse; + int i; + int count; + + count = m_inv->types.NumObjects(); + for (i = 1; i <= count; i++) { + inventory_type_t *t = m_inv->types.ObjectAt(i); + + if (name && str::icmp(t->name, name)) { + continue; + } + + VerifyTypeUp(t, true); + if (name && m_currentlist && m_currenttype) { + m_currentlist->VerifyItemUp(m_currenttype->items.ObjectAt(1), true); + } + } } -qboolean FakkInventory::KeyEvent( int key, unsigned int time ) +void FakkInventory::setInventory(inventory_t *i) { - // FIXME: stub - return qfalse; + m_inv = i; } -void FakkInventory::PlaySound( invsound_t type ) +qboolean FakkInventory::KeyEvent(int key, unsigned int time) { - // FIXME: stub + char bind[1024]; + const char *cmd; + const char *name; + int index; + bool actionitemlist; + str command; + + if (cl.snap.ps.stats[STAT_CINEMATIC] & 1) { + UI_CloseInventory(); + return false; + } + + if (!m_inv->types.NumObjects()) { + return true; + } + + actionitemlist = m_currenttype && m_currentlist && m_currentlist->getHoverItem() != NULL; + + cmd = Key_GetBinding(key); + if (cmd) { + Q_strncpyz(bind, cmd, sizeof(bind)); + } else { + bind[0] = 0; + } + + if (bind[0]) { + name = strtok(bind, " "); + if (!str::icmp(name, "+attackleft")) { + command = "attackleft"; + } else if (!str::icmp(name, "+attackright")) { + command = "attackright"; + } else if (!str::icmp(name, "warpinv")) { + name = strtok(NULL, " "); + } else { + if (!str::icmp(name, "inventory")) { + UI_CloseInventory(); + return qtrue; + } else if (!str::icmp(name, "nextinv")) { + NextItem(); + return true; + } else if (!str::icmp(name, "previnv")) { + PrevItem(); + return true; + } + name = NULL; + } + } + + if (actionitemlist) { + if (m_mouse_active && (key == K_UPARROW || key == K_DOWNARROW) || (key == K_MWHEELUP || key == K_MWHEELDOWN) + || (name && !str::icmp(name, m_currenttype->name))) { + inventory_item_t *hoverItem = m_currentlist->getHoverItem(); + + if (m_currenttype->items.NumObjects()) { + index = m_currenttype->IndexOfItemPtr(hoverItem); + + if (!index) { + index = 1; + } else if (key == K_UPARROW || key == K_MWHEELUP) { + index--; + if (index < 1) { + index = m_currenttype->items.NumObjects(); + } + } else { + index++; + if (index > m_currenttype->items.NumObjects()) { + index = 1; + } + } + + m_currentlist->VerifyItemUp(m_currenttype->items.ObjectAt(index), true); + return true; + } + } else { + if (command.length()) { + if (!str::icmp(command, "attackleft")) { + if (m_currentlist) { + m_currentlist->OnLeftMouseDown(NULL); + } + } else if (!str::icmp(command, "attackright")) { + if (m_currentlist) { + m_currentlist->OnRightMouseDown(NULL); + } + } + + PostponeEvent(FakkInventory_Timeout, 5.f); + return true; + } + + if (name) { + WarpTo(name); + PostponeEvent(FakkInventory_Timeout, 5.f); + return true; + } + + CL_Key_ForceCommand(key, time); + return true; + } + } + + if (m_mouse_active && (key == K_UPARROW || key == K_DOWNARROW) || (key == K_MWHEELUP || key == K_MWHEELDOWN)) { + index = m_inv->types.IndexOfObject(m_currenttype); + if (!index) { + index = 1; + } else if (key == K_UPARROW || key == K_MWHEELUP) { + index--; + if (index < 1) { + index = m_inv->types.NumObjects(); + } + } else { + index++; + if (index > m_inv->types.NumObjects()) { + index = 1; + } + } + + VerifyTypeUp(m_inv->types.ObjectAt(index), true); + return qtrue; + } + + if (m_mouse_active && (key == K_RIGHTARROW || key == K_LEFTARROW)) { + if (!m_currenttype || !m_currentlist) { + return qtrue; + } + + if ((m_inv->cascade == INV_CASCADE_LEFT && key == K_LEFTARROW) + || (m_inv->cascade == INV_CASCADE_RIGHT && key == K_RIGHTARROW)) { + m_currentlist->VerifyItemUp(m_currenttype->items.ObjectAt(1), true); + return qtrue; + } + + PostponeEvent(FakkInventory_Timeout, 5.f); + return true; + } + + if (!name) { + PostponeEvent(FakkInventory_Timeout, 5.f); + return true; + } + + WarpTo(name); + PostponeEvent(FakkInventory_Timeout, 5.f); + return true; } -void FakkInventory::Timeout( Event *ev ) +qboolean FakkInventory::isDying(void) { - // FIXME: stub + return m_dying; } -void FakkInventory::ChangeItem( int sign ) +FakkItemList::FakkItemList() { - // FIXME: stub + m_hoveritem = NULL; + m_lastmenuitem = NULL; + m_parent = NULL; + UIWidget::setBackgroundColor(UColor(), true); } -int FakkInventory::FindFirstItem( int itemindex, int sign ) +FakkItemList::~FakkItemList() {} + +void FakkItemList::Create(float x, float y, FakkInventory *parent) { - // FIXME: stub - return 0; + UIRect2D rect; + int i; + float maxWidth = 0; + + for (i = 1; i <= type->items.NumObjects(); i++) { + inventory_item_t *item = type->items.ObjectAt(i); + if (maxWidth <= item->width) { + maxWidth = item->width; + } + + rect.size.height += item->height; + } + + if (client_inv.cascade == INV_CASCADE_RIGHT) { + rect.pos.x = x; + rect.pos.y = y; + rect.size.width = maxWidth; + + InitFrame(NULL, rect, 0); + } else if (client_inv.cascade == INV_CASCADE_LEFT) { + rect.pos.x = x - maxWidth; + rect.pos.y = y; + rect.size.width = maxWidth; + + InitFrame(NULL, rect, 0); + } + + Com_DPrintf("FakkItemList::Create : Invalid cascade for inventory list\n"); + if (parent) { + m_parent = parent; + } } -void CL_Draw3DModel( float x, float y, float w, float h, qhandle_t model, vec3_t origin, vec3_t rotateoffset, vec3_t offset, vec3_t angle, vec3_t color, str anim ) +bool FakkItemList::HasAnyItems(void) { - // FIXME: stub + int i; + + for (i = 1; i <= type->items.NumObjects(); i++) { + inventory_item_t *item = type->items.ObjectAt(i); + + if (CL_HasInventoryItem(item->name)) { + return true; + } + } + + return false; } -qboolean UI_CloseInventory( void ) +void FakkItemList::Draw(void) {} + +void FakkItemList::OnMouseEnter(Event *ev) { - // FIXME/ stub - return qfalse; + SetHovermaterialActive(true); +} + +void FakkItemList::OnLeftMouseDown(Event *ev) +{ + char bind[1024]; + const char *cmd; + const char *name; + + if ((cl.snap.ps.stats[STAT_CINEMATIC] & 1)) { + return; + } + + if (m_parent) { + m_parent->CancelEventsOfType(FakkInventory_Timeout); + m_parent->PostEvent(new Event(FakkInventory_Timeout), 5); + } + + if (ev) { + cmd = Key_GetBinding(K_MOUSE1); + if (cmd) { + Q_strncpyz(bind, cmd, sizeof(bind)); + } else { + bind[0] = 0; + } + + if (bind[0]) { + name = strtok(bind, " "); + if (str::icmp(name, "+attackleft")) { + if (!str::icmp(name, "+attackright")) { + OnRightMouseDown(NULL); + } + return; + } + } + } + + if (!CL_HasInventoryItem(m_lastmenuitem->name) || (m_lastmenuitem->equip & 16)) { + if (m_parent) { + m_parent->PlaySound(invsound_t::rejectsound); + } + return; + } + + if (m_lastmenuitem->checkammo) { + int count; + int max; + + CL_AmmoCount(m_lastmenuitem->ammoname, &count, &max); + + if (!count) { + if (m_parent) { + m_parent->PlaySound(invsound_t::rejectsound); + } + return; + } + } + + if (m_lastmenuitem->command.length()) { + uii.Cmd_Stuff(va("%s\n", m_lastmenuitem->command.c_str())); + } else if (m_lastmenuitem->equip & 4) { + uii.Cmd_Stuff(va("use \"%s\" dualhand\n", m_lastmenuitem->name.c_str())); + } else if (m_lastmenuitem->equip & 1) { + uii.Cmd_Stuff(va("use \"%s\" lefthand\n", m_lastmenuitem->name.c_str())); + } else if (m_lastmenuitem->equip & 8) { + uii.Cmd_Stuff(va("use \"%s\"\n", m_lastmenuitem->name.c_str())); + } else { + if (m_parent) { + m_parent->PlaySound(invsound_t::rejectsound); + } + } + + if (m_parent) { + m_parent->PlaySound(invsound_t::selectsound); + } + + if (m_parent && !m_parent->m_mouse_active) { + UI_CloseInventory(); + } +} + +void FakkItemList::OnRightMouseDown(Event *ev) +{ + char bind[1024]; + const char *cmd; + const char *name; + + if ((cl.snap.ps.stats[STAT_CINEMATIC] & 1)) { + return; + } + + if (m_parent) { + m_parent->CancelEventsOfType(FakkInventory_Timeout); + m_parent->PostEvent(new Event(FakkInventory_Timeout), 5); + } + + if (ev) { + cmd = Key_GetBinding(K_MOUSE2); + if (cmd) { + Q_strncpyz(bind, cmd, sizeof(bind)); + } else { + bind[0] = 0; + } + + if (bind[0]) { + name = strtok(bind, " "); + if (str::icmp(name, "+attackright")) { + if (!str::icmp(name, "+attackleft")) { + OnLeftMouseDown(NULL); + } + return; + } + } + } + + if (!CL_HasInventoryItem(m_lastmenuitem->name) || (m_lastmenuitem->equip & 16)) { + if (m_parent) { + m_parent->PlaySound(invsound_t::rejectsound); + } + return; + } + + if (m_lastmenuitem->checkammo) { + int count; + int max; + + CL_AmmoCount(m_lastmenuitem->ammoname, &count, &max); + + if (!count) { + if (m_parent) { + m_parent->PlaySound(invsound_t::rejectsound); + } + return; + } + } + + if (m_lastmenuitem->command.length()) { + uii.Cmd_Stuff(va("%s\n", m_lastmenuitem->command.c_str())); + } else if (m_lastmenuitem->equip & 4) { + uii.Cmd_Stuff(va("use \"%s\" dualhand\n", m_lastmenuitem->name.c_str())); + } else if (m_lastmenuitem->equip & 1) { + uii.Cmd_Stuff(va("use \"%s\" righthand\n", m_lastmenuitem->name.c_str())); + } else if (m_lastmenuitem->equip & 8) { + uii.Cmd_Stuff(va("use \"%s\"\n", m_lastmenuitem->name.c_str())); + } else { + if (m_parent) { + m_parent->PlaySound(invsound_t::rejectsound); + } + } + + if (m_parent) { + m_parent->PlaySound(invsound_t::selectsound); + } + + if (m_parent && !m_parent->m_mouse_active) { + UI_CloseInventory(); + } +} + +void FakkItemList::OnLeftMouseUp(Event *ev) {} + +void FakkItemList::OnRightMouseUp(Event *ev) {} + +void FakkItemList::OnMouseLeave(Event *ev) {} + +void FakkItemList::VerifyItemUp(inventory_item_t *item, qboolean warpmouse) +{ + int i; + int height = 0; + inventory_item_t *ii = NULL; + + if (m_parent) { + m_parent->CancelEventsOfType(FakkInventory_Timeout); + m_parent->PostEvent(new Event(FakkInventory_Timeout), 5); + } + + m_hoveritem = item; + m_lastmenuitem = item; + + if (m_parent) { + m_parent->PlaySound(changesound); + } + + if (warpmouse) { + for (i = 1; i <= type->items.NumObjects(); i++) { + ii = type->items.ObjectAt(i); + if (ii == item) { + break; + } + + height += ii->height; + } + + if (ii) { + CL_SetMousePos( + (int)((ii->width / 2) + m_screenframe.pos.x), (int)((ii->height / 2 + height) + m_screenframe.pos.y) + ); + } + } +} + +void FakkItemList::OnMouseMove(Event *ev) +{ + int i; + float top; + inventory_item_t *newitem; + UIPoint2D p; + + top = 0; + newitem = NULL; + p = MouseEventToClientPoint(ev); + + for (i = 1; i <= type->items.NumObjects(); i++) { + inventory_item_t *item = type->items.ObjectAt(i); + if (p.x >= 0 && item->width > p.x && p.y >= top && item->height + top > p.y) { + newitem = item; + break; + } + + top += item->height; + } + + if (newitem != m_hoveritem) { + VerifyItemUp(newitem, false); + } +} + +void FakkItemList::OnMenuKilled(Event *ev) +{ + VerifyItemUp(NULL, false); +} + +void FakkItemList::setType(inventory_type_t *t) +{ + type = t; +} + +void FakkItemList::EquipItem(Event *ev) {} + +inventory_item_t *FakkItemList::getHoverItem() const +{ + return m_hoveritem; } diff --git a/code/client/cl_invrender.h b/code/client/cl_invrender.h index 643c4481..b7d09c66 100644 --- a/code/client/cl_invrender.h +++ b/code/client/cl_invrender.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,79 +20,102 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_INVRENDER_H__ -#define __CL_INVRENDER_H__ +#pragma once class FakkInventory; -typedef enum { selectsound, rejectsound, changesound } invsound_t; -class FakkItemList : public UIWidget { +typedef enum { + selectsound, + rejectsound, + changesound +} invsound_t; + +class FakkItemList : public UIWidget +{ protected: - inventory_type_t *type; - uipopup_describe m_describe[ 10 ]; - inventory_item_t *m_hoveritem; - inventory_item_t *m_lastmenuitem; - FakkInventory *m_parent; - float m_hovertop; + inventory_type_t *type; + uipopup_describe m_describe[10]; + inventory_item_t *m_hoveritem; + inventory_item_t *m_lastmenuitem; + FakkInventory *m_parent; + float m_hovertop; public: - CLASS_PROTOTYPE( FakkItemList ); + CLASS_PROTOTYPE(FakkItemList); - FakkItemList(); - ~FakkItemList(); + FakkItemList(); + ~FakkItemList(); - void VerifyItemUp( inventory_item_t *item, qboolean warpmouse ); - void setType( inventory_type_t *t ); - void Create( float x, float y, FakkInventory *parent ); - bool HasAnyItems( void ); - void Draw( void ) override; - void OnLeftMouseDown( Event *ev ); - void OnRightMouseDown( Event *ev ); - void OnLeftMouseUp( Event *ev ); - void OnRightMouseUp( Event *ev ); - void OnMouseMove( Event *ev ); - void OnMouseEnter( Event *ev ); - void OnMouseLeave( Event *ev ); - void OnMenuKilled( Event *ev ); - void EquipItem( Event *ev ); + void VerifyItemUp(inventory_item_t *item, qboolean warpmouse); + void setType(inventory_type_t *t); + void Create(float x, float y, FakkInventory *parent); + bool HasAnyItems(void); + void Draw(void) override; + void OnLeftMouseDown(Event *ev); + void OnRightMouseDown(Event *ev); + void OnLeftMouseUp(Event *ev); + void OnRightMouseUp(Event *ev); + void OnMouseMove(Event *ev); + void OnMouseEnter(Event *ev); + void OnMouseLeave(Event *ev); + void OnMenuKilled(Event *ev); + void EquipItem(Event *ev); + + inventory_item_t *getHoverItem() const; }; -class FakkInventory : public UIWidget { +class FakkInventory : public UIWidget +{ protected: - inventory_t *m_inv; - SafePtr m_currentlist; - inventory_type_t *m_currenttype; - int m_currentitemnum; + inventory_t *m_inv; + SafePtr m_currentlist; + inventory_type_t *m_currenttype; + int m_currentitemnum; public: - CLASS_PROTOTYPE( FakkInventory ); - -protected: - void VerifyItemUp( inventory_item_t *item, qboolean warpmouse ); + CLASS_PROTOTYPE(FakkInventory); public: - FakkInventory(); - ~FakkInventory(); + qboolean m_mouse_active; - void setInventory( inventory_t *i ); - void Draw( void ) override; - void OnMouseMove( Event *ev ); - void OnMouseLeave( Event *ev ); - void OnMouseEnter( Event *ev ); - void OnMouseDown( Event *ev ); - void WarpTo( const char *name ); - void WarpTo( int slotnum ); - void NextItem( void ); - void PrevItem( void ); - qboolean isDying( void ); - qboolean KeyEvent( int key, unsigned int time ) override; - void PlaySound( invsound_t type ); - void Timeout( Event *ev ); - void ChangeItem( int sign ); - int FindFirstItem( int itemindex, int sign ); +protected: + void VerifyTypeUp(inventory_type_t *t, qboolean warpmouse); + +public: + FakkInventory(); + ~FakkInventory(); + + void setInventory(inventory_t *i); + void Draw(void) override; + void OnMouseMove(Event *ev); + void OnMouseLeave(Event *ev); + void OnMouseEnter(Event *ev); + void OnMouseDown(Event *ev); + void WarpTo(const char *name); + void WarpTo(int slotnum); + void NextItem(void); + void PrevItem(void); + qboolean isDying(void); + qboolean KeyEvent(int key, unsigned int time) override; + void PlaySound(invsound_t type); + void Timeout(Event *ev); + void ChangeItem(int sign); + int FindFirstItem(int itemindex, int sign); }; -void CL_Draw3DModel( float x, float y, float w, float h, qhandle_t model, vec3_t origin, vec3_t rotateoffset, vec3_t offset, vec3_t angle, vec3_t color, str anim ); -qboolean UI_CloseInventory( void ); +void CL_Draw3DModel( + float x, + float y, + float w, + float h, + qhandle_t model, + vec3_t origin, + vec3_t rotateoffset, + vec3_t offset, + vec3_t angle, + vec3_t color, + str anim +); -#endif // __CL_INVRENDER_H__ +void UI_DoInventory(qboolean activate_mouse); +qboolean UI_CloseInventory(void); diff --git a/code/client/cl_keys.cpp b/code/client/cl_keys.cpp index 39062da9..39474cb9 100644 --- a/code/client/cl_keys.cpp +++ b/code/client/cl_keys.cpp @@ -29,21 +29,20 @@ key up events are sent even if in console mode */ -int nextHistoryLine; // the last line in the history buffer, not masked -int historyLine; // the line being displayed from history buffer - // will be <= nextHistoryLine +int nextHistoryLine; // the last line in the history buffer, not masked +int historyLine; // the line being displayed from history buffer + // will be <= nextHistoryLine -qboolean chat_team; +qboolean chat_team; -int chat_playerNum; +int chat_playerNum; +qboolean key_overstrikeMode; -qboolean key_overstrikeMode; - -int anykeydown; -qkey_t keys[MAX_KEYS]; -qkey_t altkeys[MAX_KEYS]; -qkey_t ctrlkeys[MAX_KEYS]; +int anykeydown; +qkey_t keys[MAX_KEYS]; +qkey_t altkeys[MAX_KEYS]; +qkey_t ctrlkeys[MAX_KEYS]; qboolean menubound[MAX_KEYS]; @@ -51,289 +50,287 @@ qboolean alt_down; qboolean ctrl_down; typedef struct { - const char *name; - int keynum; + const char *name; + int keynum; } keyname_t; // names not in this list can either be lowercase ascii, or '0xnn' hex sequences -keyname_t keynames[] = -{ - {"TAB", K_TAB}, - {"ENTER", K_ENTER}, - {"ESCAPE", K_ESCAPE}, - {"SPACE", K_SPACE}, - {"BACKSPACE", K_BACKSPACE}, - {"UPARROW", K_UPARROW}, - {"DOWNARROW", K_DOWNARROW}, - {"LEFTARROW", K_LEFTARROW}, - {"RIGHTARROW", K_RIGHTARROW}, +keyname_t keynames[] = { + {"TAB", K_TAB }, + {"ENTER", K_ENTER }, + {"ESCAPE", K_ESCAPE }, + {"SPACE", K_SPACE }, + {"BACKSPACE", K_BACKSPACE }, + {"UPARROW", K_UPARROW }, + {"DOWNARROW", K_DOWNARROW }, + {"LEFTARROW", K_LEFTARROW }, + {"RIGHTARROW", K_RIGHTARROW }, - {"ALT", K_ALT}, - {"CTRL", K_CTRL}, - {"SHIFT", K_SHIFT}, + {"ALT", K_ALT }, + {"CTRL", K_CTRL }, + {"SHIFT", K_SHIFT }, - {"COMMAND", K_COMMAND}, + {"COMMAND", K_COMMAND }, - {"CAPSLOCK", K_CAPSLOCK}, + {"CAPSLOCK", K_CAPSLOCK }, - - {"F1", K_F1}, - {"F2", K_F2}, - {"F3", K_F3}, - {"F4", K_F4}, - {"F5", K_F5}, - {"F6", K_F6}, - {"F7", K_F7}, - {"F8", K_F8}, - {"F9", K_F9}, - {"F10", K_F10}, - {"F11", K_F11}, - {"F12", K_F12}, - {"F13", K_F13}, - {"F14", K_F14}, - {"F15", K_F15}, + {"F1", K_F1 }, + {"F2", K_F2 }, + {"F3", K_F3 }, + {"F4", K_F4 }, + {"F5", K_F5 }, + {"F6", K_F6 }, + {"F7", K_F7 }, + {"F8", K_F8 }, + {"F9", K_F9 }, + {"F10", K_F10 }, + {"F11", K_F11 }, + {"F12", K_F12 }, + {"F13", K_F13 }, + {"F14", K_F14 }, + {"F15", K_F15 }, - {"INS", K_INS}, - {"DEL", K_DEL}, - {"PGDN", K_PGDN}, - {"PGUP", K_PGUP}, - {"HOME", K_HOME}, - {"END", K_END}, + {"INS", K_INS }, + {"DEL", K_DEL }, + {"PGDN", K_PGDN }, + {"PGUP", K_PGUP }, + {"HOME", K_HOME }, + {"END", K_END }, - {"MOUSE1", K_MOUSE1}, - {"MOUSE2", K_MOUSE2}, - {"MOUSE3", K_MOUSE3}, - {"MOUSE4", K_MOUSE4}, - {"MOUSE5", K_MOUSE5}, + {"MOUSE1", K_MOUSE1 }, + {"MOUSE2", K_MOUSE2 }, + {"MOUSE3", K_MOUSE3 }, + {"MOUSE4", K_MOUSE4 }, + {"MOUSE5", K_MOUSE5 }, - {"MWHEELUP", K_MWHEELUP }, - {"MWHEELDOWN", K_MWHEELDOWN }, + {"MWHEELUP", K_MWHEELUP }, + {"MWHEELDOWN", K_MWHEELDOWN }, - {"JOY1", K_JOY1}, - {"JOY2", K_JOY2}, - {"JOY3", K_JOY3}, - {"JOY4", K_JOY4}, - {"JOY5", K_JOY5}, - {"JOY6", K_JOY6}, - {"JOY7", K_JOY7}, - {"JOY8", K_JOY8}, - {"JOY9", K_JOY9}, - {"JOY10", K_JOY10}, - {"JOY11", K_JOY11}, - {"JOY12", K_JOY12}, - {"JOY13", K_JOY13}, - {"JOY14", K_JOY14}, - {"JOY15", K_JOY15}, - {"JOY16", K_JOY16}, - {"JOY17", K_JOY17}, - {"JOY18", K_JOY18}, - {"JOY19", K_JOY19}, - {"JOY20", K_JOY20}, - {"JOY21", K_JOY21}, - {"JOY22", K_JOY22}, - {"JOY23", K_JOY23}, - {"JOY24", K_JOY24}, - {"JOY25", K_JOY25}, - {"JOY26", K_JOY26}, - {"JOY27", K_JOY27}, - {"JOY28", K_JOY28}, - {"JOY29", K_JOY29}, - {"JOY30", K_JOY30}, - {"JOY31", K_JOY31}, - {"JOY32", K_JOY32}, + {"JOY1", K_JOY1 }, + {"JOY2", K_JOY2 }, + {"JOY3", K_JOY3 }, + {"JOY4", K_JOY4 }, + {"JOY5", K_JOY5 }, + {"JOY6", K_JOY6 }, + {"JOY7", K_JOY7 }, + {"JOY8", K_JOY8 }, + {"JOY9", K_JOY9 }, + {"JOY10", K_JOY10 }, + {"JOY11", K_JOY11 }, + {"JOY12", K_JOY12 }, + {"JOY13", K_JOY13 }, + {"JOY14", K_JOY14 }, + {"JOY15", K_JOY15 }, + {"JOY16", K_JOY16 }, + {"JOY17", K_JOY17 }, + {"JOY18", K_JOY18 }, + {"JOY19", K_JOY19 }, + {"JOY20", K_JOY20 }, + {"JOY21", K_JOY21 }, + {"JOY22", K_JOY22 }, + {"JOY23", K_JOY23 }, + {"JOY24", K_JOY24 }, + {"JOY25", K_JOY25 }, + {"JOY26", K_JOY26 }, + {"JOY27", K_JOY27 }, + {"JOY28", K_JOY28 }, + {"JOY29", K_JOY29 }, + {"JOY30", K_JOY30 }, + {"JOY31", K_JOY31 }, + {"JOY32", K_JOY32 }, - {"AUX1", K_AUX1}, - {"AUX2", K_AUX2}, - {"AUX3", K_AUX3}, - {"AUX4", K_AUX4}, - {"AUX5", K_AUX5}, - {"AUX6", K_AUX6}, - {"AUX7", K_AUX7}, - {"AUX8", K_AUX8}, - {"AUX9", K_AUX9}, - {"AUX10", K_AUX10}, - {"AUX11", K_AUX11}, - {"AUX12", K_AUX12}, - {"AUX13", K_AUX13}, - {"AUX14", K_AUX14}, - {"AUX15", K_AUX15}, - {"AUX16", K_AUX16}, + {"AUX1", K_AUX1 }, + {"AUX2", K_AUX2 }, + {"AUX3", K_AUX3 }, + {"AUX4", K_AUX4 }, + {"AUX5", K_AUX5 }, + {"AUX6", K_AUX6 }, + {"AUX7", K_AUX7 }, + {"AUX8", K_AUX8 }, + {"AUX9", K_AUX9 }, + {"AUX10", K_AUX10 }, + {"AUX11", K_AUX11 }, + {"AUX12", K_AUX12 }, + {"AUX13", K_AUX13 }, + {"AUX14", K_AUX14 }, + {"AUX15", K_AUX15 }, + {"AUX16", K_AUX16 }, - {"KP_HOME", K_KP_HOME }, - {"KP_UPARROW", K_KP_UPARROW }, - {"KP_PGUP", K_KP_PGUP }, - {"KP_LEFTARROW", K_KP_LEFTARROW }, - {"KP_5", K_KP_5 }, - {"KP_RIGHTARROW", K_KP_RIGHTARROW }, - {"KP_END", K_KP_END }, - {"KP_DOWNARROW", K_KP_DOWNARROW }, - {"KP_PGDN", K_KP_PGDN }, - {"KP_ENTER", K_KP_ENTER }, - {"KP_INS", K_KP_INS }, - {"KP_DEL", K_KP_DEL }, - {"KP_SLASH", K_KP_SLASH }, - {"KP_MINUS", K_KP_MINUS }, - {"KP_PLUS", K_KP_PLUS }, - {"KP_NUMLOCK", K_KP_NUMLOCK }, - {"KP_STAR", K_KP_STAR }, - {"KP_EQUALS", K_KP_EQUALS }, + {"KP_HOME", K_KP_HOME }, + {"KP_UPARROW", K_KP_UPARROW }, + {"KP_PGUP", K_KP_PGUP }, + {"KP_LEFTARROW", K_KP_LEFTARROW }, + {"KP_5", K_KP_5 }, + {"KP_RIGHTARROW", K_KP_RIGHTARROW }, + {"KP_END", K_KP_END }, + {"KP_DOWNARROW", K_KP_DOWNARROW }, + {"KP_PGDN", K_KP_PGDN }, + {"KP_ENTER", K_KP_ENTER }, + {"KP_INS", K_KP_INS }, + {"KP_DEL", K_KP_DEL }, + {"KP_SLASH", K_KP_SLASH }, + {"KP_MINUS", K_KP_MINUS }, + {"KP_PLUS", K_KP_PLUS }, + {"KP_NUMLOCK", K_KP_NUMLOCK }, + {"KP_STAR", K_KP_STAR }, + {"KP_EQUALS", K_KP_EQUALS }, - {"PAUSE", K_PAUSE}, - - {"SEMICOLON", ';'}, // because a raw semicolon separates commands + {"PAUSE", K_PAUSE }, - {"WORLD_0", K_WORLD_0}, - {"WORLD_1", K_WORLD_1}, - {"WORLD_2", K_WORLD_2}, - {"WORLD_3", K_WORLD_3}, - {"WORLD_4", K_WORLD_4}, - {"WORLD_5", K_WORLD_5}, - {"WORLD_6", K_WORLD_6}, - {"WORLD_7", K_WORLD_7}, - {"WORLD_8", K_WORLD_8}, - {"WORLD_9", K_WORLD_9}, - {"WORLD_10", K_WORLD_10}, - {"WORLD_11", K_WORLD_11}, - {"WORLD_12", K_WORLD_12}, - {"WORLD_13", K_WORLD_13}, - {"WORLD_14", K_WORLD_14}, - {"WORLD_15", K_WORLD_15}, - {"WORLD_16", K_WORLD_16}, - {"WORLD_17", K_WORLD_17}, - {"WORLD_18", K_WORLD_18}, - {"WORLD_19", K_WORLD_19}, - {"WORLD_20", K_WORLD_20}, - {"WORLD_21", K_WORLD_21}, - {"WORLD_22", K_WORLD_22}, - {"WORLD_23", K_WORLD_23}, - {"WORLD_24", K_WORLD_24}, - {"WORLD_25", K_WORLD_25}, - {"WORLD_26", K_WORLD_26}, - {"WORLD_27", K_WORLD_27}, - {"WORLD_28", K_WORLD_28}, - {"WORLD_29", K_WORLD_29}, - {"WORLD_30", K_WORLD_30}, - {"WORLD_31", K_WORLD_31}, - {"WORLD_32", K_WORLD_32}, - {"WORLD_33", K_WORLD_33}, - {"WORLD_34", K_WORLD_34}, - {"WORLD_35", K_WORLD_35}, - {"WORLD_36", K_WORLD_36}, - {"WORLD_37", K_WORLD_37}, - {"WORLD_38", K_WORLD_38}, - {"WORLD_39", K_WORLD_39}, - {"WORLD_40", K_WORLD_40}, - {"WORLD_41", K_WORLD_41}, - {"WORLD_42", K_WORLD_42}, - {"WORLD_43", K_WORLD_43}, - {"WORLD_44", K_WORLD_44}, - {"WORLD_45", K_WORLD_45}, - {"WORLD_46", K_WORLD_46}, - {"WORLD_47", K_WORLD_47}, - {"WORLD_48", K_WORLD_48}, - {"WORLD_49", K_WORLD_49}, - {"WORLD_50", K_WORLD_50}, - {"WORLD_51", K_WORLD_51}, - {"WORLD_52", K_WORLD_52}, - {"WORLD_53", K_WORLD_53}, - {"WORLD_54", K_WORLD_54}, - {"WORLD_55", K_WORLD_55}, - {"WORLD_56", K_WORLD_56}, - {"WORLD_57", K_WORLD_57}, - {"WORLD_58", K_WORLD_58}, - {"WORLD_59", K_WORLD_59}, - {"WORLD_60", K_WORLD_60}, - {"WORLD_61", K_WORLD_61}, - {"WORLD_62", K_WORLD_62}, - {"WORLD_63", K_WORLD_63}, - {"WORLD_64", K_WORLD_64}, - {"WORLD_65", K_WORLD_65}, - {"WORLD_66", K_WORLD_66}, - {"WORLD_67", K_WORLD_67}, - {"WORLD_68", K_WORLD_68}, - {"WORLD_69", K_WORLD_69}, - {"WORLD_70", K_WORLD_70}, - {"WORLD_71", K_WORLD_71}, - {"WORLD_72", K_WORLD_72}, - {"WORLD_73", K_WORLD_73}, - {"WORLD_74", K_WORLD_74}, - {"WORLD_75", K_WORLD_75}, - {"WORLD_76", K_WORLD_76}, - {"WORLD_77", K_WORLD_77}, - {"WORLD_78", K_WORLD_78}, - {"WORLD_79", K_WORLD_79}, - {"WORLD_80", K_WORLD_80}, - {"WORLD_81", K_WORLD_81}, - {"WORLD_82", K_WORLD_82}, - {"WORLD_83", K_WORLD_83}, - {"WORLD_84", K_WORLD_84}, - {"WORLD_85", K_WORLD_85}, - {"WORLD_86", K_WORLD_86}, - {"WORLD_87", K_WORLD_87}, - {"WORLD_88", K_WORLD_88}, - {"WORLD_89", K_WORLD_89}, - {"WORLD_90", K_WORLD_90}, - {"WORLD_91", K_WORLD_91}, - {"WORLD_92", K_WORLD_92}, - {"WORLD_93", K_WORLD_93}, - {"WORLD_94", K_WORLD_94}, - {"WORLD_95", K_WORLD_95}, + {"SEMICOLON", ';' }, // because a raw semicolon separates commands - {"WINDOWS", K_SUPER}, - {"COMPOSE", K_COMPOSE}, - {"MODE", K_MODE}, - {"HELP", K_HELP}, - {"PRINT", K_PRINT}, - {"SYSREQ", K_SYSREQ}, - {"SCROLLOCK", K_SCROLLOCK }, - {"BREAK", K_BREAK}, - {"MENU", K_MENU}, - {"POWER", K_POWER}, - {"EURO", K_EURO}, - {"UNDO", K_UNDO}, + {"WORLD_0", K_WORLD_0 }, + {"WORLD_1", K_WORLD_1 }, + {"WORLD_2", K_WORLD_2 }, + {"WORLD_3", K_WORLD_3 }, + {"WORLD_4", K_WORLD_4 }, + {"WORLD_5", K_WORLD_5 }, + {"WORLD_6", K_WORLD_6 }, + {"WORLD_7", K_WORLD_7 }, + {"WORLD_8", K_WORLD_8 }, + {"WORLD_9", K_WORLD_9 }, + {"WORLD_10", K_WORLD_10 }, + {"WORLD_11", K_WORLD_11 }, + {"WORLD_12", K_WORLD_12 }, + {"WORLD_13", K_WORLD_13 }, + {"WORLD_14", K_WORLD_14 }, + {"WORLD_15", K_WORLD_15 }, + {"WORLD_16", K_WORLD_16 }, + {"WORLD_17", K_WORLD_17 }, + {"WORLD_18", K_WORLD_18 }, + {"WORLD_19", K_WORLD_19 }, + {"WORLD_20", K_WORLD_20 }, + {"WORLD_21", K_WORLD_21 }, + {"WORLD_22", K_WORLD_22 }, + {"WORLD_23", K_WORLD_23 }, + {"WORLD_24", K_WORLD_24 }, + {"WORLD_25", K_WORLD_25 }, + {"WORLD_26", K_WORLD_26 }, + {"WORLD_27", K_WORLD_27 }, + {"WORLD_28", K_WORLD_28 }, + {"WORLD_29", K_WORLD_29 }, + {"WORLD_30", K_WORLD_30 }, + {"WORLD_31", K_WORLD_31 }, + {"WORLD_32", K_WORLD_32 }, + {"WORLD_33", K_WORLD_33 }, + {"WORLD_34", K_WORLD_34 }, + {"WORLD_35", K_WORLD_35 }, + {"WORLD_36", K_WORLD_36 }, + {"WORLD_37", K_WORLD_37 }, + {"WORLD_38", K_WORLD_38 }, + {"WORLD_39", K_WORLD_39 }, + {"WORLD_40", K_WORLD_40 }, + {"WORLD_41", K_WORLD_41 }, + {"WORLD_42", K_WORLD_42 }, + {"WORLD_43", K_WORLD_43 }, + {"WORLD_44", K_WORLD_44 }, + {"WORLD_45", K_WORLD_45 }, + {"WORLD_46", K_WORLD_46 }, + {"WORLD_47", K_WORLD_47 }, + {"WORLD_48", K_WORLD_48 }, + {"WORLD_49", K_WORLD_49 }, + {"WORLD_50", K_WORLD_50 }, + {"WORLD_51", K_WORLD_51 }, + {"WORLD_52", K_WORLD_52 }, + {"WORLD_53", K_WORLD_53 }, + {"WORLD_54", K_WORLD_54 }, + {"WORLD_55", K_WORLD_55 }, + {"WORLD_56", K_WORLD_56 }, + {"WORLD_57", K_WORLD_57 }, + {"WORLD_58", K_WORLD_58 }, + {"WORLD_59", K_WORLD_59 }, + {"WORLD_60", K_WORLD_60 }, + {"WORLD_61", K_WORLD_61 }, + {"WORLD_62", K_WORLD_62 }, + {"WORLD_63", K_WORLD_63 }, + {"WORLD_64", K_WORLD_64 }, + {"WORLD_65", K_WORLD_65 }, + {"WORLD_66", K_WORLD_66 }, + {"WORLD_67", K_WORLD_67 }, + {"WORLD_68", K_WORLD_68 }, + {"WORLD_69", K_WORLD_69 }, + {"WORLD_70", K_WORLD_70 }, + {"WORLD_71", K_WORLD_71 }, + {"WORLD_72", K_WORLD_72 }, + {"WORLD_73", K_WORLD_73 }, + {"WORLD_74", K_WORLD_74 }, + {"WORLD_75", K_WORLD_75 }, + {"WORLD_76", K_WORLD_76 }, + {"WORLD_77", K_WORLD_77 }, + {"WORLD_78", K_WORLD_78 }, + {"WORLD_79", K_WORLD_79 }, + {"WORLD_80", K_WORLD_80 }, + {"WORLD_81", K_WORLD_81 }, + {"WORLD_82", K_WORLD_82 }, + {"WORLD_83", K_WORLD_83 }, + {"WORLD_84", K_WORLD_84 }, + {"WORLD_85", K_WORLD_85 }, + {"WORLD_86", K_WORLD_86 }, + {"WORLD_87", K_WORLD_87 }, + {"WORLD_88", K_WORLD_88 }, + {"WORLD_89", K_WORLD_89 }, + {"WORLD_90", K_WORLD_90 }, + {"WORLD_91", K_WORLD_91 }, + {"WORLD_92", K_WORLD_92 }, + {"WORLD_93", K_WORLD_93 }, + {"WORLD_94", K_WORLD_94 }, + {"WORLD_95", K_WORLD_95 }, - {"PAD0_A", K_PAD0_A }, - {"PAD0_B", K_PAD0_B }, - {"PAD0_X", K_PAD0_X }, - {"PAD0_Y", K_PAD0_Y }, - {"PAD0_BACK", K_PAD0_BACK }, - {"PAD0_GUIDE", K_PAD0_GUIDE }, - {"PAD0_START", K_PAD0_START }, - {"PAD0_LEFTSTICK_CLICK", K_PAD0_LEFTSTICK_CLICK }, - {"PAD0_RIGHTSTICK_CLICK", K_PAD0_RIGHTSTICK_CLICK }, - {"PAD0_LEFTSHOULDER", K_PAD0_LEFTSHOULDER }, - {"PAD0_RIGHTSHOULDER", K_PAD0_RIGHTSHOULDER }, - {"PAD0_DPAD_UP", K_PAD0_DPAD_UP }, - {"PAD0_DPAD_DOWN", K_PAD0_DPAD_DOWN }, - {"PAD0_DPAD_LEFT", K_PAD0_DPAD_LEFT }, - {"PAD0_DPAD_RIGHT", K_PAD0_DPAD_RIGHT }, + {"WINDOWS", K_SUPER }, + {"COMPOSE", K_COMPOSE }, + {"MODE", K_MODE }, + {"HELP", K_HELP }, + {"PRINT", K_PRINT }, + {"SYSREQ", K_SYSREQ }, + {"SCROLLOCK", K_SCROLLOCK }, + {"BREAK", K_BREAK }, + {"MENU", K_MENU }, + {"POWER", K_POWER }, + {"EURO", K_EURO }, + {"UNDO", K_UNDO }, - {"PAD0_LEFTSTICK_LEFT", K_PAD0_LEFTSTICK_LEFT }, - {"PAD0_LEFTSTICK_RIGHT", K_PAD0_LEFTSTICK_RIGHT }, - {"PAD0_LEFTSTICK_UP", K_PAD0_LEFTSTICK_UP }, - {"PAD0_LEFTSTICK_DOWN", K_PAD0_LEFTSTICK_DOWN }, - {"PAD0_RIGHTSTICK_LEFT", K_PAD0_RIGHTSTICK_LEFT }, - {"PAD0_RIGHTSTICK_RIGHT", K_PAD0_RIGHTSTICK_RIGHT }, - {"PAD0_RIGHTSTICK_UP", K_PAD0_RIGHTSTICK_UP }, - {"PAD0_RIGHTSTICK_DOWN", K_PAD0_RIGHTSTICK_DOWN }, - {"PAD0_LEFTTRIGGER", K_PAD0_LEFTTRIGGER }, - {"PAD0_RIGHTTRIGGER", K_PAD0_RIGHTTRIGGER }, + {"PAD0_A", K_PAD0_A }, + {"PAD0_B", K_PAD0_B }, + {"PAD0_X", K_PAD0_X }, + {"PAD0_Y", K_PAD0_Y }, + {"PAD0_BACK", K_PAD0_BACK }, + {"PAD0_GUIDE", K_PAD0_GUIDE }, + {"PAD0_START", K_PAD0_START }, + {"PAD0_LEFTSTICK_CLICK", K_PAD0_LEFTSTICK_CLICK }, + {"PAD0_RIGHTSTICK_CLICK", K_PAD0_RIGHTSTICK_CLICK}, + {"PAD0_LEFTSHOULDER", K_PAD0_LEFTSHOULDER }, + {"PAD0_RIGHTSHOULDER", K_PAD0_RIGHTSHOULDER }, + {"PAD0_DPAD_UP", K_PAD0_DPAD_UP }, + {"PAD0_DPAD_DOWN", K_PAD0_DPAD_DOWN }, + {"PAD0_DPAD_LEFT", K_PAD0_DPAD_LEFT }, + {"PAD0_DPAD_RIGHT", K_PAD0_DPAD_RIGHT }, - {"PAD0_MISC1", K_PAD0_MISC1 }, - {"PAD0_PADDLE1", K_PAD0_PADDLE1 }, - {"PAD0_PADDLE2", K_PAD0_PADDLE2 }, - {"PAD0_PADDLE3", K_PAD0_PADDLE3 }, - {"PAD0_PADDLE4", K_PAD0_PADDLE4 }, - {"PAD0_TOUCHPAD", K_PAD0_TOUCHPAD }, + {"PAD0_LEFTSTICK_LEFT", K_PAD0_LEFTSTICK_LEFT }, + {"PAD0_LEFTSTICK_RIGHT", K_PAD0_LEFTSTICK_RIGHT }, + {"PAD0_LEFTSTICK_UP", K_PAD0_LEFTSTICK_UP }, + {"PAD0_LEFTSTICK_DOWN", K_PAD0_LEFTSTICK_DOWN }, + {"PAD0_RIGHTSTICK_LEFT", K_PAD0_RIGHTSTICK_LEFT }, + {"PAD0_RIGHTSTICK_RIGHT", K_PAD0_RIGHTSTICK_RIGHT}, + {"PAD0_RIGHTSTICK_UP", K_PAD0_RIGHTSTICK_UP }, + {"PAD0_RIGHTSTICK_DOWN", K_PAD0_RIGHTSTICK_DOWN }, + {"PAD0_LEFTTRIGGER", K_PAD0_LEFTTRIGGER }, + {"PAD0_RIGHTTRIGGER", K_PAD0_RIGHTTRIGGER }, - // - // non-ioq3 - // - {"LALT", K_ALT}, - {"LCTRL", K_CTRL}, - {"LSHIFT", K_SHIFT}, + {"PAD0_MISC1", K_PAD0_MISC1 }, + {"PAD0_PADDLE1", K_PAD0_PADDLE1 }, + {"PAD0_PADDLE2", K_PAD0_PADDLE2 }, + {"PAD0_PADDLE3", K_PAD0_PADDLE3 }, + {"PAD0_PADDLE4", K_PAD0_PADDLE4 }, + {"PAD0_TOUCHPAD", K_PAD0_TOUCHPAD }, - {NULL,0} + // + // non-ioq3 + // + {"LALT", K_ALT }, + {"LCTRL", K_CTRL }, + {"LSHIFT", K_SHIFT }, + + {NULL, 0 } }; /* @@ -343,46 +340,45 @@ Message_Key In game talk message ================ */ -void Message_Key( int key ) { - if (key == K_ESCAPE) { - Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_MESSAGE ); - return; - } +void Message_Key(int key) +{ + if (key == K_ESCAPE) { + Key_SetCatcher(Key_GetCatcher() & ~KEYCATCH_MESSAGE); + return; + } - if ( key == K_ENTER || key == K_KP_ENTER ) - { - Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_MESSAGE ); - return; - } + if (key == K_ENTER || key == K_KP_ENTER) { + Key_SetCatcher(Key_GetCatcher() & ~KEYCATCH_MESSAGE); + return; + } } //============================================================================ - -qboolean Key_GetOverstrikeMode( void ) { - return key_overstrikeMode; +qboolean Key_GetOverstrikeMode(void) +{ + return key_overstrikeMode; } - -void Key_SetOverstrikeMode( qboolean state ) { - key_overstrikeMode = state; +void Key_SetOverstrikeMode(qboolean state) +{ + key_overstrikeMode = state; } - /* =================== Key_IsDown =================== */ -qboolean Key_IsDown( int keynum ) { - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return qfalse; - } +qboolean Key_IsDown(int keynum) +{ + if (keynum < 0 || keynum >= MAX_KEYS) { + return qfalse; + } - return keys[keynum].down; + return keys[keynum].down; } - /* =================== Key_StringToKeynum @@ -396,48 +392,50 @@ the K_* names are matched up. to be configured even if they don't have defined names. =================== */ -int Key_StringToKeynum( const char *str ) { - keyname_t *kn; +int Key_StringToKeynum(const char *str) +{ + keyname_t *kn; - if ( !str || !str[0] ) { - return -1; - } - if ( !str[1] ) { - return str[0]; - } + if (!str || !str[0]) { + return -1; + } + if (!str[1]) { + return str[0]; + } - // check for hex code - if ( str[0] == '0' && str[1] == 'x' && strlen( str ) == 4) { - int n1, n2; + // check for hex code + if (str[0] == '0' && str[1] == 'x' && strlen(str) == 4) { + int n1, n2; - n1 = str[2]; - if ( n1 >= '0' && n1 <= '9' ) { - n1 -= '0'; - } else if ( n1 >= 'a' && n1 <= 'f' ) { - n1 = n1 - 'a' + 10; - } else { - n1 = 0; - } + n1 = str[2]; + if (n1 >= '0' && n1 <= '9') { + n1 -= '0'; + } else if (n1 >= 'a' && n1 <= 'f') { + n1 = n1 - 'a' + 10; + } else { + n1 = 0; + } - n2 = str[3]; - if ( n2 >= '0' && n2 <= '9' ) { - n2 -= '0'; - } else if ( n2 >= 'a' && n2 <= 'f' ) { - n2 = n2 - 'a' + 10; - } else { - n2 = 0; - } + n2 = str[3]; + if (n2 >= '0' && n2 <= '9') { + n2 -= '0'; + } else if (n2 >= 'a' && n2 <= 'f') { + n2 = n2 - 'a' + 10; + } else { + n2 = 0; + } - return n1 * 16 + n2; - } + return n1 * 16 + n2; + } - // scan for a text match - for ( kn=keynames ; kn->name ; kn++ ) { - if ( !Q_stricmp( str,kn->name ) ) - return kn->keynum; - } + // scan for a text match + for (kn = keynames; kn->name; kn++) { + if (!Q_stricmp(str, kn->name)) { + return kn->keynum; + } + } - return -1; + return -1; } /* @@ -448,44 +446,45 @@ Returns a string (either a single ascii char, a K_* name, or a 0x11 hex string) given keynum. =================== */ -const char *Key_KeynumToString( int keynum ) { - keyname_t *kn; - static char tinystr[5]; - int i, j; +const char *Key_KeynumToString(int keynum) +{ + keyname_t *kn; + static char tinystr[5]; + int i, j; - if ( keynum == -1 ) { - return ""; - } + if (keynum == -1) { + return ""; + } - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return ""; - } + if (keynum < 0 || keynum >= MAX_KEYS) { + return ""; + } - // check for printable ascii (don't use quote) - if ( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' ) { - tinystr[0] = keynum; - tinystr[1] = 0; - return tinystr; - } + // check for printable ascii (don't use quote) + if (keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';') { + tinystr[0] = keynum; + tinystr[1] = 0; + return tinystr; + } - // check for a key string - for ( kn=keynames ; kn->name ; kn++ ) { - if (keynum == kn->keynum) { - return kn->name; - } - } + // check for a key string + for (kn = keynames; kn->name; kn++) { + if (keynum == kn->keynum) { + return kn->name; + } + } - // make a hex string - i = keynum >> 4; - j = keynum & 15; + // make a hex string + i = keynum >> 4; + j = keynum & 15; - tinystr[0] = '0'; - tinystr[1] = 'x'; - tinystr[2] = i > 9 ? i - 10 + 'a' : i + '0'; - tinystr[3] = j > 9 ? j - 10 + 'a' : j + '0'; - tinystr[4] = 0; + tinystr[0] = '0'; + tinystr[1] = 'x'; + tinystr[2] = i > 9 ? i - 10 + 'a' : i + '0'; + tinystr[3] = j > 9 ? j - 10 + 'a' : j + '0'; + tinystr[4] = 0; - return tinystr; + return tinystr; } /* @@ -496,57 +495,58 @@ Returns a string (either a single ascii char, a K_* name, or a 0x11 hex string) given keynum. =================== */ -const char *Key_KeynumToBindString( int keynum ) { - keyname_t *kn; - static char tinystr[5]; +const char *Key_KeynumToBindString(int keynum) +{ + keyname_t *kn; + static char tinystr[5]; - if ( keynum == -1 ) { - return "Not Bound"; - } + if (keynum == -1) { + return "Not Bound"; + } - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return "Out of Range"; - } + if (keynum < 0 || keynum >= MAX_KEYS) { + return "Out of Range"; + } - // check for printable ascii (don't use quote) - if ( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' ) { - tinystr[0] = keynum; - tinystr[1] = 0; - return tinystr; - } + // check for printable ascii (don't use quote) + if (keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';') { + tinystr[0] = keynum; + tinystr[1] = 0; + return tinystr; + } - // check for a key string - for ( kn=keynames ; kn->name ; kn++ ) { - if (keynum == kn->keynum) { - return kn->name; - } - } + // check for a key string + for (kn = keynames; kn->name; kn++) { + if (keynum == kn->keynum) { + return kn->name; + } + } - return "Unknown Key"; + return "Unknown Key"; } - /* =================== Key_SetBinding =================== */ -void Key_SetBinding( int keynum, const char *binding ) { - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return; - } +void Key_SetBinding(int keynum, const char *binding) +{ + if (keynum < 0 || keynum >= MAX_KEYS) { + return; + } - // free old bindings - if ( keys[ keynum ].binding ) { - Z_Free( keys[ keynum ].binding ); - } + // free old bindings + if (keys[keynum].binding) { + Z_Free(keys[keynum].binding); + } - // allocate memory for new binding - keys[keynum].binding = CopyString( binding ); + // allocate memory for new binding + keys[keynum].binding = CopyString(binding); - // consider this like modifying an archived cvar, so the - // file write will be triggered at the next oportunity - cvar_modifiedFlags |= CVAR_ARCHIVE; + // consider this like modifying an archived cvar, so the + // file write will be triggered at the next oportunity + cvar_modifiedFlags |= CVAR_ARCHIVE; } /* @@ -554,22 +554,23 @@ void Key_SetBinding( int keynum, const char *binding ) { Key_SetAltBinding =================== */ -void Key_SetAltBinding( int keynum, const char *binding ) { - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return; - } +void Key_SetAltBinding(int keynum, const char *binding) +{ + if (keynum < 0 || keynum >= MAX_KEYS) { + return; + } - // free old bindings - if ( altkeys[ keynum ].binding ) { - Z_Free( altkeys[ keynum ].binding ); - } + // free old bindings + if (altkeys[keynum].binding) { + Z_Free(altkeys[keynum].binding); + } - // allocate memory for new binding - altkeys[keynum].binding = CopyString( binding ); + // allocate memory for new binding + altkeys[keynum].binding = CopyString(binding); - // consider this like modifying an archived cvar, so the - // file write will be triggered at the next oportunity - cvar_modifiedFlags |= CVAR_ARCHIVE; + // consider this like modifying an archived cvar, so the + // file write will be triggered at the next oportunity + cvar_modifiedFlags |= CVAR_ARCHIVE; } /* @@ -577,36 +578,37 @@ void Key_SetAltBinding( int keynum, const char *binding ) { Key_SetCtrlBinding =================== */ -void Key_SetCtrlBinding( int keynum, const char *binding ) { - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return; - } +void Key_SetCtrlBinding(int keynum, const char *binding) +{ + if (keynum < 0 || keynum >= MAX_KEYS) { + return; + } - // free old bindings - if ( ctrlkeys[ keynum ].binding ) { - Z_Free( ctrlkeys[ keynum ].binding ); - } + // free old bindings + if (ctrlkeys[keynum].binding) { + Z_Free(ctrlkeys[keynum].binding); + } - // allocate memory for new binding - ctrlkeys[ keynum ].binding = CopyString( binding ); + // allocate memory for new binding + ctrlkeys[keynum].binding = CopyString(binding); - // consider this like modifying an archived cvar, so the - // file write will be triggered at the next oportunity - cvar_modifiedFlags |= CVAR_ARCHIVE; + // consider this like modifying an archived cvar, so the + // file write will be triggered at the next oportunity + cvar_modifiedFlags |= CVAR_ARCHIVE; } - /* =================== Key_GetBinding =================== */ -const char *Key_GetBinding( int keynum ) { - if ( keynum < 0 || keynum >= MAX_KEYS ) { - return ""; - } +const char *Key_GetBinding(int keynum) +{ + if (keynum < 0 || keynum >= MAX_KEYS) { + return ""; + } - return keys[ keynum ].binding; + return keys[keynum].binding; } /* @@ -615,17 +617,18 @@ Key_GetKey =================== */ -int Key_GetKey(const char *binding) { - int i; +int Key_GetKey(const char *binding) +{ + int i; - if (binding) { - for (i=0 ; i < MAX_KEYS ; i++) { - if (keys[i].binding && Q_stricmp(binding, keys[i].binding) == 0) { - return i; - } + if (binding) { + for (i = 0; i < MAX_KEYS; i++) { + if (keys[i].binding && Q_stricmp(binding, keys[i].binding) == 0) { + return i; + } + } } - } - return -1; + return -1; } /* @@ -633,19 +636,20 @@ int Key_GetKey(const char *binding) { Key_GetKeynameForCommand =================== */ -const char *Key_GetKeynameForCommand( const char *command ) { - int i; +const char *Key_GetKeynameForCommand(const char *command) +{ + int i; - for( i = 0; i < MAX_KEYS; i++ ) { - if( !keys[ i ].binding ) { - continue; - } - if( keys[ i ].down && !stricmp( command, keys[ i ].binding ) ) { - return Key_KeynumToString( i ); - } - } + for (i = 0; i < MAX_KEYS; i++) { + if (!keys[i].binding) { + continue; + } + if (keys[i].down && !stricmp(command, keys[i].binding)) { + return Key_KeynumToString(i); + } + } - return "Unknown Command"; + return "Unknown Command"; } /* @@ -653,24 +657,25 @@ const char *Key_GetKeynameForCommand( const char *command ) { Key_GetKeysForCommand =================== */ -void Key_GetKeysForCommand( const char *command, int *key1, int *key2 ) { - int i; +void Key_GetKeysForCommand(const char *command, int *key1, int *key2) +{ + int i; - *key1 = *key2 = -1; + *key1 = *key2 = -1; - for( i = 0; i < MAX_KEYS; i++ ) { - if( !keys[ i ].binding ) { - continue; - } - if( !stricmp( command, keys[ i ].binding ) ) { - if( *key1 == -1 ) { - *key1 = i; - } else { - *key2 = i; - return; - } - } - } + for (i = 0; i < MAX_KEYS; i++) { + if (!keys[i].binding) { + continue; + } + if (!stricmp(command, keys[i].binding)) { + if (*key1 == -1) { + *key1 = i; + } else { + *key2 = i; + return; + } + } + } } /* @@ -678,24 +683,22 @@ void Key_GetKeysForCommand( const char *command, int *key1, int *key2 ) { Key_Unbind_f =================== */ -void Key_Unbind_f (void) +void Key_Unbind_f(void) { - int b; + int b; - if (Cmd_Argc() != 2) - { - Com_Printf ("unbind : remove commands from a key\n"); - return; - } + if (Cmd_Argc() != 2) { + Com_Printf("unbind : remove commands from a key\n"); + return; + } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Com_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } + b = Key_StringToKeynum(Cmd_Argv(1)); + if (b == -1) { + Com_Printf("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } - Key_SetBinding (b, ""); + Key_SetBinding(b, ""); } /* @@ -703,24 +706,22 @@ void Key_Unbind_f (void) Key_Unaltbind_f =================== */ -void Key_Unaltbind_f (void) +void Key_Unaltbind_f(void) { - int b; + int b; - if (Cmd_Argc() != 2) - { - Com_Printf ("unaltbind : remove commands from a key\n"); - return; - } + if (Cmd_Argc() != 2) { + Com_Printf("unaltbind : remove commands from a key\n"); + return; + } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Com_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } + b = Key_StringToKeynum(Cmd_Argv(1)); + if (b == -1) { + Com_Printf("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } - Key_SetAltBinding (b, ""); + Key_SetAltBinding(b, ""); } /* @@ -728,24 +729,22 @@ void Key_Unaltbind_f (void) Key_Unctrlbind_f =================== */ -void Key_Unctrlbind_f (void) +void Key_Unctrlbind_f(void) { - int b; + int b; - if (Cmd_Argc() != 2) - { - Com_Printf ("unctrlbind : remove commands from a key\n"); - return; - } + if (Cmd_Argc() != 2) { + Com_Printf("unctrlbind : remove commands from a key\n"); + return; + } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Com_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } + b = Key_StringToKeynum(Cmd_Argv(1)); + if (b == -1) { + Com_Printf("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } - Key_SetCtrlBinding (b, ""); + Key_SetCtrlBinding(b, ""); } /* @@ -753,59 +752,58 @@ void Key_Unctrlbind_f (void) Key_Unbindall_f =================== */ -void Key_Unbindall_f (void) +void Key_Unbindall_f(void) { - int i; + int i; - for (i=0 ; i < MAX_KEYS; i++) - if (keys[i].binding) - Key_SetBinding (i, ""); + for (i = 0; i < MAX_KEYS; i++) { + if (keys[i].binding) { + Key_SetBinding(i, ""); + } + } } - /* =================== Key_Bind_f =================== */ -void Key_Bind_f (void) +void Key_Bind_f(void) { - int i, c, b; - char cmd[1024]; + int i, c, b; + char cmd[1024]; - c = Cmd_Argc(); + c = Cmd_Argc(); - if (c < 2) - { - Com_Printf ("bind [command] : attach a command to a key\n"); - return; - } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Com_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } + if (c < 2) { + Com_Printf("bind [command] : attach a command to a key\n"); + return; + } + b = Key_StringToKeynum(Cmd_Argv(1)); + if (b == -1) { + Com_Printf("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } - if (c == 2) - { - if (keys[b].binding) - Com_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keys[b].binding ); - else - Com_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); - return; - } + if (c == 2) { + if (keys[b].binding) { + Com_Printf("\"%s\" = \"%s\"\n", Cmd_Argv(1), keys[b].binding); + } else { + Com_Printf("\"%s\" is not bound\n", Cmd_Argv(1)); + } + return; + } -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - for (i=2 ; i< c ; i++) - { - strcat (cmd, Cmd_Argv(i)); - if (i != (c-1)) - strcat (cmd, " "); - } + // copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i = 2; i < c; i++) { + strcat(cmd, Cmd_Argv(i)); + if (i != (c - 1)) { + strcat(cmd, " "); + } + } - Key_SetBinding (b, cmd); + Key_SetBinding(b, cmd); } /* @@ -813,44 +811,42 @@ void Key_Bind_f (void) Key_AltBind_f =================== */ -void Key_AltBind_f (void) +void Key_AltBind_f(void) { - int i, c, b; - char cmd[1024]; + int i, c, b; + char cmd[1024]; - c = Cmd_Argc(); + c = Cmd_Argc(); - if (c < 2) - { - Com_Printf ("altbind [command] : attach a command to a key\n"); - return; - } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Com_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } + if (c < 2) { + Com_Printf("altbind [command] : attach a command to a key\n"); + return; + } + b = Key_StringToKeynum(Cmd_Argv(1)); + if (b == -1) { + Com_Printf("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } - if (c == 2) - { - if (altkeys[b].binding) - Com_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), altkeys[b].binding ); - else - Com_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); - return; - } + if (c == 2) { + if (altkeys[b].binding) { + Com_Printf("\"%s\" = \"%s\"\n", Cmd_Argv(1), altkeys[b].binding); + } else { + Com_Printf("\"%s\" is not bound\n", Cmd_Argv(1)); + } + return; + } -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - for (i=2 ; i< c ; i++) - { - strcat (cmd, Cmd_Argv(i)); - if (i != (c-1)) - strcat (cmd, " "); - } + // copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i = 2; i < c; i++) { + strcat(cmd, Cmd_Argv(i)); + if (i != (c - 1)) { + strcat(cmd, " "); + } + } - Key_SetAltBinding (b, cmd); + Key_SetAltBinding(b, cmd); } /* @@ -858,44 +854,42 @@ void Key_AltBind_f (void) Key_AltBind_f =================== */ -void Key_CtrlBind_f (void) +void Key_CtrlBind_f(void) { - int i, c, b; - char cmd[1024]; + int i, c, b; + char cmd[1024]; - c = Cmd_Argc(); + c = Cmd_Argc(); - if (c < 2) - { - Com_Printf ("ctrlbind [command] : attach a command to a key\n"); - return; - } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Com_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } + if (c < 2) { + Com_Printf("ctrlbind [command] : attach a command to a key\n"); + return; + } + b = Key_StringToKeynum(Cmd_Argv(1)); + if (b == -1) { + Com_Printf("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } - if (c == 2) - { - if (ctrlkeys[b].binding) - Com_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), ctrlkeys[b].binding ); - else - Com_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); - return; - } + if (c == 2) { + if (ctrlkeys[b].binding) { + Com_Printf("\"%s\" = \"%s\"\n", Cmd_Argv(1), ctrlkeys[b].binding); + } else { + Com_Printf("\"%s\" is not bound\n", Cmd_Argv(1)); + } + return; + } -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - for (i=2 ; i< c ; i++) - { - strcat (cmd, Cmd_Argv(i)); - if (i != (c-1)) - strcat (cmd, " "); - } + // copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i = 2; i < c; i++) { + strcat(cmd, Cmd_Argv(i)); + if (i != (c - 1)) { + strcat(cmd, " "); + } + } - Key_SetCtrlBinding (b, cmd); + Key_SetCtrlBinding(b, cmd); } /* @@ -905,35 +899,34 @@ Key_WriteBindings Writes lines containing "bind key value" ============ */ -void Key_WriteBindings( fileHandle_t f ) { - int i; +void Key_WriteBindings(fileHandle_t f) +{ + int i; - FS_Printf (f, "unbindall\n" ); + FS_Printf(f, "unbindall\n"); - for (i=0 ; iinteger ) { - alt_down = down; - } + if ((key == K_ALT || key == K_INS) && cl_altbindings->integer) { + alt_down = down; + } - if( ( key == K_CTRL || key == K_DEL ) && cl_ctrlbindings->integer ) { - ctrl_down = down; - } + if ((key == K_CTRL || key == K_DEL) && cl_ctrlbindings->integer) { + ctrl_down = down; + } - if (down && !CL_FinishedIntro()) - { - UI_StartStageKeyEvent(); - return; - } + if (down && !CL_FinishedIntro()) { + UI_StartStageKeyEvent(); + return; + } - if( clc.state > CA_DISCONNECTED && cge && !Key_GetCatcher() && cge->CG_CheckCaptureKey( key, down, time ) && key != K_ESCAPE ) - { - if (key == K_CONSOLE || (keys[K_SHIFT].down && key == K_ESCAPE)) - return; - } + if (clc.state > CA_DISCONNECTED && cge && !Key_GetCatcher() && cge->CG_CheckCaptureKey(key, down, time) + && key != K_ESCAPE) { + if (key != K_CONSOLE && (!keys[K_SHIFT].down || key != K_ESCAPE)) { + return; + } + } - if (key == K_CONSOLE || (keys[K_SHIFT].down && key == K_ESCAPE)) - { - if( !down ) { - return; - } + if (key == K_CONSOLE || (keys[K_SHIFT].down && key == K_ESCAPE)) { + if (!down) { + return; + } - if( Cvar_VariableIntegerValue( "ui_console" ) ) - { - UI_ToggleConsole(); - } - else if( clc.state == CA_ACTIVE ) - { - if( cg_gametype->integer ) { - UI_ToggleDMConsole( 300 ); - } - } - return; - } + if (Cvar_VariableIntegerValue("ui_console")) { + UI_ToggleConsole(); + } else if (clc.state == CA_ACTIVE) { + if (cg_gametype->integer) { + UI_ToggleDMConsole(300); + } + } + return; + } - if( down ) - { - if( alt_down && key != K_ALT && key != K_INS ) { - altkeys[ key ].down = down; - } - if( down && ctrl_down && key != K_CTRL ) { - ctrlkeys[ key ].down = down; - } - } + if (down) { + if (alt_down && key != K_ALT && key != K_INS) { + altkeys[key].down = down; + } + if (down && ctrl_down && key != K_CTRL) { + ctrlkeys[key].down = down; + } + } - if( key != K_DEL ) { - ctrlkeys[ key ].down = down; - } + if (key != K_DEL) { + ctrlkeys[key].down = down; + } - if (key == K_ENTER) - { - if (down) - { - if (keys[K_ALT].down) - { - Key_ClearStates(); - Cvar_SetValue( "r_fullscreen", - !Cvar_VariableIntegerValue( "r_fullscreen" ) ); - return; - } - } - } + if (key == K_ENTER) { + if (down) { + if (keys[K_ALT].down) { + Key_ClearStates(); + Cvar_SetValue("r_fullscreen", !Cvar_VariableIntegerValue("r_fullscreen")); + return; + } + } + } + if (key >= K_MOUSE1 && key <= K_MOUSE5) { + if (down) { + cl.mouseButtons |= (1 << (key - K_MOUSE1)); + } else { + cl.mouseButtons &= ~(1 << (key - K_MOUSE1)); + } - if( key == K_MOUSE1 || key == K_MOUSE2 - || key == K_MOUSE3 || key == K_MOUSE4 - || key == K_MOUSE5 ) - { - if( down ) { - cl.mouseButtons |= ( 1 << ( key + (256 - K_MOUSE1) ) ); - } else { - cl.mouseButtons &= ~( 1 << ( key + (256 - K_MOUSE1)) ); - } - } + if (in_guimouse) { + return; + } + } - if (!in_guimouse || key <= K_MWHEELUP || key > K_JOY1) - { - // keys can still be used for bound actions - if (down && (key <= K_BACKSPACE || key == K_MOUSE4) && - ( clc.demoplaying || clc.state == CA_CINEMATIC ) && Key_GetCatcher() == 0 ) { - Cvar_Set( "nextdemo", "" ); - key = K_ESCAPE; - } + // keys can still be used for bound actions + if (down && (key <= K_BACKSPACE || key == K_MOUSE4) && (clc.demoplaying || clc.state == CA_CINEMATIC) + && Key_GetCatcher() == 0) { + Cvar_Set("nextdemo", ""); + key = K_ESCAPE; + } - // escape is always handled special - if( key == K_ESCAPE ) { - if( down ) { - qboolean wasup = UI_MenuUp(); - UI_DeactiveFloatingWindows(); + // escape is always handled special + if (key == K_ESCAPE) { + if (down) { + qboolean wasup = UI_MenuUp(); + UI_DeactiveFloatingWindows(); - if( clc.state == CA_CINEMATIC ) - { - SCR_StopCinematic(); - return; - } + if (clc.state == CA_CINEMATIC) { + SCR_StopCinematic(); + return; + } - if( cls.realFrametime - last_escape_time <= 1000 ) { - UI_MenuEscape( "main" ); - return; - } + if (cls.realFrametime - last_escape_time <= 1000) { + UI_MenuEscape("main"); + return; + } - if( wasup ) { - UI_MenuEscape( "main" ); - return; - } + if (wasup) { + UI_MenuEscape("main"); + return; + } - if( cl.snap.ps.stats[ STAT_CINEMATIC ] & 1 && clc.state == CA_ACTIVE ) { - Cbuf_AddText( "skipcinematic\n" ); - return; - } + if (cl.snap.ps.stats[STAT_CINEMATIC] & 1 && clc.state == CA_ACTIVE) { + Cbuf_AddText("skipcinematic\n"); + return; + } - if( clc.state <= CA_DISCONNECTED || clc.state == CA_ACTIVE ) { - UI_MenuEscape( "main" ); - } - return; - } - } else if( down ) { - if ( ( Key_GetCatcher( ) & KEYCATCH_UI && !menubound[ key ] ) || UI_BindActive() ) { - UI_KeyEvent( key, time ); - } else if( cls.loading & KEYCATCH_MESSAGE ) { - Message_Key( key ); - } else if( clc.state != CA_DISCONNECTED || menubound[key]) { - // send the bound action - kb = altkeys[ key ].binding; - if( !kb || !altkeys[ key ].down ) { - kb = ctrlkeys[ key ].binding; - if( !kb || !ctrlkeys[ key ].down ) { - kb = keys[ key ].binding; - } - } - if( !kb ) { - if( key >= 200 ) { - Com_Printf( "%s is unbound, use controls menu to set.\n" - , Key_KeynumToString( key ) ); - } - } else if( kb[ 0 ] == '+' ) { - int i; - char button[ 1024 ], *buttonPtr; - buttonPtr = button; - for( i = 0;; i++ ) { - if( kb[ i ] == ';' || !kb[ i ] ) { - *buttonPtr = '\0'; - if( button[ 0 ] == '+' ) { - // button commands add keynum and time as parms so that multiple - // sources can be discriminated and subframe corrected - Com_sprintf( cmd, sizeof( cmd ), "%s %i %i\n", button, key, time ); - Cbuf_AddText( cmd ); - } - else { - // down-only command - Cbuf_AddText( button ); - Cbuf_AddText( "\n" ); - } - buttonPtr = button; - while( ( kb[ i ] <= ' ' || kb[ i ] == ';' ) && kb[ i ] != 0 ) { - i++; - } - } - *buttonPtr++ = kb[ i ]; - if( !kb[ i ] ) { - break; - } - } - } else { - // down-only command - Cbuf_AddText( kb ); - Cbuf_AddText( "\n" ); - } - } - return; - } + if (clc.state <= CA_DISCONNECTED || clc.state == CA_ACTIVE) { + UI_MenuEscape("main"); + } + return; + } + } else if (down) { + if ((Key_GetCatcher() & KEYCATCH_UI && !menubound[key]) || UI_BindActive()) { + UI_KeyEvent(key, time); + } else if (cls.loading & KEYCATCH_MESSAGE) { + Message_Key(key); + } else if (clc.state != CA_DISCONNECTED || menubound[key]) { + // send the bound action + kb = altkeys[key].binding; + if (!kb || !altkeys[key].down) { + kb = ctrlkeys[key].binding; + if (!kb || !ctrlkeys[key].down) { + kb = keys[key].binding; + } + } + if (!kb) { + if (key >= 200) { + Com_Printf("%s is unbound, use controls menu to set.\n", Key_KeynumToString(key)); + } + } else if (kb[0] == '+') { + int i; + char button[1024], *buttonPtr; + buttonPtr = button; + for (i = 0;; i++) { + if (kb[i] == ';' || !kb[i]) { + *buttonPtr = '\0'; + if (button[0] == '+') { + // button commands add keynum and time as parms so that multiple + // sources can be discriminated and subframe corrected + Com_sprintf(cmd, sizeof(cmd), "%s %i %i\n", button, key, time); + Cbuf_AddText(cmd); + } else { + // down-only command + Cbuf_AddText(button); + Cbuf_AddText("\n"); + } + buttonPtr = button; + while ((kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0) { + i++; + } + } + *buttonPtr++ = kb[i]; + if (!kb[i]) { + break; + } + } + } else { + // down-only command + Cbuf_AddText(kb); + Cbuf_AddText("\n"); + } + } + return; + } - if( altkeys[ key ].down ) { - kb = altkeys[ key ].binding; - altkeys[ key ].down = false; - CL_AddKeyUpCommands( key, kb, time ); - } - if( ctrlkeys[ key ].down ) { - kb = ctrlkeys[ key ].binding; - ctrlkeys[ key ].down = false; - CL_AddKeyUpCommands( key, kb, time ); - } + if (altkeys[key].down) { + kb = altkeys[key].binding; + altkeys[key].down = false; + CL_AddKeyUpCommands(key, kb, time); + } + if (ctrlkeys[key].down) { + kb = ctrlkeys[key].binding; + ctrlkeys[key].down = false; + CL_AddKeyUpCommands(key, kb, time); + } - CL_AddKeyUpCommands( key, keys[ key ].binding, time ); - } + CL_AddKeyUpCommands(key, keys[key].binding, time); } +/* +=================== +CL_Key_ForceCommand +=================== +*/ +void CL_Key_ForceCommand(int key, unsigned int time) +{ + const char *kb; + char cmd[1024]; + + if (clc.state == CA_DISCONNECTED) { + return; + } + + kb = keys[key].binding; + if (kb) { + if (*kb == '+') { + Com_sprintf(cmd, sizeof(cmd), "%s %i %i\n", kb, key, time); + } else { + Cbuf_AddText(keys[key].binding); + Cbuf_AddText("\n"); + } + } else if (key > K_JOY12) { + Com_Printf("%s is unbound, use controls menu to set.\n", Key_KeynumToString(key)); + } +} /* =================== @@ -1273,48 +1290,47 @@ CL_CharEvent Normal keyboard characters, already shifted / capslocked / etc =================== */ -void CL_CharEvent( int key ) { - // the console key should never be used as a char - if ( key == '`' || key == '~' ) { - return; - } +void CL_CharEvent(int key) +{ + // the console key should never be used as a char + if (key == '`' || key == '~') { + return; + } - // delete is not a printable character and is - // otherwise handled by Field_KeyDownEvent - if ( key == 127 ) { - return; - } + // delete is not a printable character and is + // otherwise handled by Field_KeyDownEvent + if (key == 127) { + return; + } - // distribute the key down event to the apropriate handler - if ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) { - return; - } + // distribute the key down event to the apropriate handler + if (Key_GetCatcher() & KEYCATCH_CONSOLE) { + return; + } - if ( Key_GetCatcher( ) & KEYCATCH_UI ) { - UI_CharEvent( key ); - } + if (Key_GetCatcher() & KEYCATCH_UI) { + UI_CharEvent(key); + } } - /* =================== Key_ClearStates =================== */ -void Key_ClearStates (void) +void Key_ClearStates(void) { - int i; + int i; - anykeydown = 0; + anykeydown = 0; - for ( i=0 ; i < MAX_KEYS ; i++ ) { - if ( keys[i].down ) { - CL_KeyEvent( i, qfalse, 0 ); - - } - keys[i].down = 0; - keys[i].repeats = 0; - } + for (i = 0; i < MAX_KEYS; i++) { + if (keys[i].down) { + CL_KeyEvent(i, qfalse, 0); + } + keys[i].down = 0; + keys[i].repeats = 0; + } } static int keyCatchers = 0; @@ -1324,8 +1340,9 @@ static int keyCatchers = 0; Key_GetCatcher ==================== */ -int Key_GetCatcher( void ) { - return cls.keyCatchers; +int Key_GetCatcher(void) +{ + return cls.keyCatchers; } /* @@ -1333,6 +1350,7 @@ int Key_GetCatcher( void ) { Key_SetCatcher ==================== */ -void Key_SetCatcher( int catcher ) { - keyCatchers = catcher; +void Key_SetCatcher(int catcher) +{ + cls.keyCatchers = catcher; } diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp index 59f84516..dd4ff10c 100644 --- a/code/client/cl_main.cpp +++ b/code/client/cl_main.cpp @@ -29,14 +29,21 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/localization.h" #include "../qcommon/bg_compat.h" #include "../sys/sys_local.h" -#ifdef USE_RENDERER_DLL -#include "../sys/sys_loadlib.h" -#endif +#include "../sys/sys_update_checker.h" +#include "../uilib/uimessage.h" + +extern "C" { + #include "../sys/sys_loadlib.h" +} #include "../gamespy/gcdkey/gcdkeyc.h" #include +#ifdef USE_RENDERER_DLOPEN +cvar_t* cl_renderer; +#endif + cvar_t *cl_nodelta; cvar_t *cl_debugMove; @@ -56,6 +63,8 @@ cvar_t *cl_showTimeDelta; cvar_t *cl_freezeDemo; cvar_t *cl_shownet; +cvar_t *cl_netprofile; +cvar_t *cl_netprofileoverlay; cvar_t *cl_showSend; cvar_t *cl_timedemo; cvar_t *cl_timedemoLog; @@ -118,6 +127,7 @@ cvar_t *cl_r_fullscreen; cvar_t *cl_consoleKeys; cvar_t *name; +cvar_t *cl_rate; clientActive_t cl; clientConnection_t clc; @@ -127,19 +137,14 @@ clientGameExport_t *cge; // Structure containing functions exported from refresh DLL refexport_t re; +#ifdef USE_RENDERER_DLOPEN +static void *rendererLib = NULL; +#endif qboolean camera_reset; qboolean camera_active; vec3_t camera_offset; -#ifdef USE_RENDERER_DLL -// su44: for plugable renderer system -refexport_t* (*DGetRefAPI)(int apiVersion, refimport_t * rimp) = NULL; -static cvar_t *cl_renderer = NULL; -static void *rendererLib = NULL; -#endif // USE_RENDERER_DLL - - ping_t cl_pinglist[MAX_PINGREQUESTS]; typedef struct serverStatus_s @@ -167,9 +172,28 @@ void CL_ShowIP_f(void); void CL_ServerStatus_f(void); void CL_ServerStatusResponse( netadr_t from, msg_t *msg ); -void CL_GamespyServers_f( void ); - static qboolean cl_bCLSystemStarted = qfalse; +static qboolean cl_updateNotified = qfalse; + +/* +=============== +CL_UseLargeLightmap + +Added in 2.0 +Returns true if the standard BSP file should be used, false if the smaller lightmap BSP file should be used +=============== +*/ +qboolean CL_UseLargeLightmap(const char* mapName) { + char buffer[MAX_QPATH]; + + Com_sprintf(buffer, sizeof(buffer), "maps/%s_sml.bsp", mapName); + + if (FS_ReadFileEx(buffer, NULL, qtrue) == -1) { + return qtrue; + } + + return Cvar_Get("r_largemap", "0", 0)->integer; +} /* =============== @@ -706,7 +730,7 @@ void CL_PlayDemo_f( void ) { clc.state = CA_CONNECTED; clc.demoplaying = qtrue; - Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) ); + Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) ); // read demo messages until connected while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) { @@ -769,7 +793,9 @@ void CL_ShutdownAll(qboolean shutdownRef) { CL_cURL_Shutdown(); #endif // clear sounds +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA S_DisableSounds(); +#endif // shutdown CGame CL_ShutdownCGame(); // shutdown UI @@ -779,9 +805,10 @@ void CL_ShutdownAll(qboolean shutdownRef) { TIKI_FreeAll(); // shutdown the renderer - if ( re.Shutdown ) { - re.Shutdown( qfalse ); // don't destroy window or context - } + if(shutdownRef) + CL_ShutdownRef(); + else if(re.Shutdown) + re.Shutdown(qfalse); // don't destroy window or context cls.uiStarted = qfalse; cls.cgameStarted = qfalse; @@ -801,7 +828,7 @@ void CL_FlushMemory( void ) { // shutdown all the client stuff CL_ShutdownCGame(); - S_StopAllSounds( qtrue ); + S_StopAllSounds2( qtrue ); UI_ClearState(); cls.rendererRegistered = qfalse; } @@ -830,7 +857,7 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) { if (pszMapName) { // if we are already connected to the local host, stay connected - if (clc.state >= CA_CONNECTED && !Q_stricmp(cls.servername, "localhost")) { + if (clc.state >= CA_CONNECTED && !Q_stricmp(clc.servername, "localhost")) { clc.state = CA_CONNECTED; // so the connect screen is drawn Com_Memset(cls.updateInfoString, 0, sizeof(cls.updateInfoString)); Com_Memset(clc.serverMessage, 0, sizeof(clc.serverMessage)); @@ -841,11 +868,11 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) { // clear nextmap so the cinematic shutdown doesn't execute it Cvar_Set("nextmap", ""); CL_Disconnect(); - Q_strncpyz(cls.servername, "localhost", sizeof(cls.servername)); + Q_strncpyz(clc.servername, "localhost", sizeof(clc.servername)); clc.state = CA_CHALLENGING; // so the connect screen is drawn clc.connectStartTime = cls.realtime; clc.connectTime = -RETRANSMIT_TIMEOUT; - NET_StringToAdr(cls.servername, &clc.serverAddress, NA_UNSPEC); + NET_StringToAdr(clc.servername, &clc.serverAddress, NA_UNSPEC); // we don't need a challenge on the localhost CL_CheckForResend(); @@ -868,7 +895,7 @@ void CL_ClearState( void ) CL_ShutdownCGame(); if( !com_sv_running->integer ) { - S_StopAllSounds( qtrue ); + S_StopAllSounds2( qtrue ); } UI_ClearState(); @@ -883,7 +910,7 @@ CL_UpdateGUID update cl_guid using QKEY_FILE and optional prefix ==================== */ -static void CL_UpdateGUID( char *prefix, int prefix_len ) +static void CL_UpdateGUID( const char *prefix, int prefix_len ) { fileHandle_t f; int len; @@ -910,6 +937,8 @@ This is also called on Com_Error and Com_Quit, so it shouldn't cause any errors ===================== */ void CL_Disconnect() { + int mouseX, mouseY; + if ( !com_cl_running || !com_cl_running->integer ) { return; } @@ -945,8 +974,16 @@ void CL_Disconnect() { CL_WritePacket(); } + // Fixed in OPM + // Don't reset the mouse every time the client disconnects + mouseX = cl.mousex; + mouseY = cl.mousey; + CL_ClearState (); + cl.mousex = mouseX; + cl.mousey = mouseY; + // wipe the client connection Com_Memset( &clc, 0, sizeof( clientConnection_t ) ); @@ -1047,7 +1084,7 @@ void CL_RequestMotd( void ) { Info_SetValueForKey( info, "renderer", cls.glconfig.renderer_string ); Info_SetValueForKey( info, "version", com_version->string ); - NET_OutOfBandPrint( NS_CLIENT, cls.updateServer, "getmotd \"%s\"\n", info ); + CL_NET_OutOfBandPrint( cls.updateServer, "getmotd \"%s\"\n", info ); } /* @@ -1130,7 +1167,7 @@ void CL_RequestAuthorization( void ) { fs = Cvar_Get ("cl_anonymous", "0", CVAR_INIT|CVAR_SYSTEMINFO ); - NET_OutOfBandPrint(NS_CLIENT, cls.authorizeServer, "getKeyAuthorize %i %s", fs->integer, nums ); + CL_NET_OutOfBandPrint(cls.authorizeServer, "getKeyAuthorize %i %s", fs->integer, nums ); } /* @@ -1172,12 +1209,12 @@ void CL_Setenv_f( void ) { char buffer[1024]; int i; - strcpy( buffer, Cmd_Argv(1) ); - strcat( buffer, "=" ); + Q_strncpyz( buffer, Cmd_Argv(1), sizeof( buffer ) ); + Q_strcat( buffer, sizeof( buffer ), "=" ); for ( i = 2; i < argc; i++ ) { - strcat( buffer, Cmd_Argv( i ) ); - strcat( buffer, " " ); + Q_strcat( buffer, sizeof( buffer ), Cmd_Argv( i ) ); + Q_strcat( buffer, sizeof( buffer ), " " ); } putenv( buffer ); @@ -1199,28 +1236,32 @@ CL_Disconnect_f ================== */ void CL_Disconnect_f( void ) { - if ( clc.state != CA_DISCONNECTED ) { - qboolean bConsoleState = UI_ConsoleIsOpen(); + qboolean bConsoleState; - Com_Printf("\nDisconnected from server\n"); - SV_Shutdown("Disconnected from server\n"); + if ( clc.state == CA_DISCONNECTED ) { + return; + } - if (com_cl_running && com_cl_running->integer) - { - CL_AbnormalDisconnect(); - CL_FlushMemory(); - CL_StartHunkUsers(qfalse); - S_StopAllSounds(1); - S_TriggeredMusic_PlayIntroMusic(); - } + bConsoleState = UI_ConsoleIsOpen(); - UI_FocusMenuIfExists(); + Com_Printf("\nDisconnected from server\n"); + SV_Shutdown("Disconnected from server\n"); - if (bConsoleState) { - UI_OpenConsole(); - } else { - UI_CloseConsole(); - } + if (com_cl_running && com_cl_running->integer) + { + CL_AbnormalDisconnect(); + CL_FlushMemory(); + CL_StartHunkUsers(qfalse); + S_StopAllSounds2(1); + S_TriggeredMusic_PlayIntroMusic(); + } + + UI_FocusMenuIfExists(); + + if (bConsoleState) { + UI_OpenConsole(); + } else { + UI_CloseConsole(); } } @@ -1232,22 +1273,22 @@ CL_Reconnect_f ================ */ void CL_Reconnect_f( void ) { - if ( !strlen( cls.servername ) || !strcmp( cls.servername, "localhost" ) ) { + if ( !strlen( clc.servername ) || !strcmp( clc.servername, "localhost" ) ) { Com_Printf( "Can't reconnect to localhost.\n" ); return; } Cvar_Set("ui_singlePlayerActive", "0"); - Cbuf_AddText( va("connect %s\n", cls.servername ) ); + Cbuf_AddText( va("connect %s\n", clc.servername ) ); } /* ================ -CL_Connect_f +CL_Connect ================ */ -void CL_Connect( const char *server ) { - char serverString[ 22 ]; +void CL_Connect( const char *server, netadrtype_t family ) { + const char *serverString; Cvar_Set( "ui_singlePlayerActive", "0" ); @@ -1273,22 +1314,25 @@ void CL_Connect( const char *server ) { CL_FlushMemory( ); */ - Q_strncpyz( cls.servername, server, sizeof( cls.servername ) ); + Q_strncpyz( clc.servername, server, sizeof( clc.servername ) ); - if( !NET_StringToAdr( cls.servername, &clc.serverAddress, NA_IP ) ) { + if( !NET_StringToAdr( clc.servername, &clc.serverAddress, family ) ) { Com_Printf( "Bad server address\n" ); clc.state = CA_DISCONNECTED; + UI_PushMenu("badserveraddy"); return; } if( clc.serverAddress.port == 0 ) { clc.serverAddress.port = BigShort( PORT_SERVER ); } - Com_sprintf( serverString, sizeof( serverString ), "%i.%i.%i.%i:%i", - clc.serverAddress.ip[ 0 ], clc.serverAddress.ip[ 1 ], - clc.serverAddress.ip[ 2 ], clc.serverAddress.ip[ 3 ], - BigShort( clc.serverAddress.port ) ); + serverString = NET_AdrToStringwPort(clc.serverAddress); - Com_Printf( "%s resolved to %s\n", cls.servername, serverString ); + Com_Printf( "%s resolved to %s\n", clc.servername, serverString ); + + if (cl_guidServerUniq->integer) + CL_UpdateGUID(serverString, strlen(serverString)); + else + CL_UpdateGUID(NULL, 0); // if we aren't playing on a lan, we need to authenticate // with the cd key @@ -1298,11 +1342,14 @@ void CL_Connect( const char *server ) { } else { clc.state = CA_CONNECTING; + + // Set a client challenge number that ideally is mirrored back by the server. + clc.challenge = (((unsigned int)rand() << 16) ^ (unsigned int)rand()) ^ Com_Milliseconds(); } clc.connectTime = -99999; // CL_CheckForResend() will fire immediately clc.connectPacketCount = 0; - clc.connectStartTime = 0; + clc.connectStartTime = cls.realtime; // server connection string Cvar_Set( "cl_currentServerAddress", server ); @@ -1315,17 +1362,36 @@ CL_Connect_f ================ */ // we have our own server provided to us by mohaaaa.co.uk -void CL_Connect_f( void ) { - char *server; +void CL_Connect_f(void) { + const char *server; + int argc = Cmd_Argc(); + netadrtype_t family = NA_UNSPEC; if ( Cmd_Argc() != 2 ) { Com_Printf( "usage: connect [server]\n"); return; } - - server = Cmd_Argv (1); - CL_Connect( server ); + if (argc != 2 && argc != 3) { + Com_Printf("usage: connect [-4|-6] server\n"); + return; + } + + if (argc == 2) + server = Cmd_Argv(1); + else + { + if (!strcmp(Cmd_Argv(1), "-4")) + family = NA_IP; + else if (!strcmp(Cmd_Argv(1), "-6")) + family = NA_IP6; + else + Com_Printf("warning: only -4 or -6 as address type understood.\n"); + + server = Cmd_Argv(2); + } + + CL_Connect( server, family ); } /* @@ -1343,7 +1409,7 @@ void CL_MenuConnect_f( void ) { server = Cmd_Argv( 1 ); - CL_Connect( Cvar_VariableString( server ) ); + CL_Connect( Cvar_VariableString( server ), NA_UNSPEC ); } /* @@ -1363,7 +1429,7 @@ void CL_FastConnect_f( void ) { Com_Printf( "Server %i - '%s'\n", i, NET_AdrToString( cls.localServers[ i ].adr ) ); } - CL_Connect( cls.localServers[ 0 ].hostName ); + CL_Connect( cls.localServers[ 0 ].hostName, NA_UNSPEC ); Cbuf_AddText( "popmenu 0 ; wait 500 ; popmenu 0 ; wait 500 ; popmenu 0\n" ); endTime = 123456789; } @@ -1437,7 +1503,11 @@ void CL_Rcon_f( void ) { } } - NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to); + NET_SendPacket (NS_CLIENT, strlen(message) + 1, message, to); + + if (cl_netprofile->integer) { + NetProfileAddPacket(&cls.netprofile.inPackets, strlen(message) + 1, NETPROF_PACKET_MESSAGE); + } } /* @@ -1456,10 +1526,9 @@ void CL_SendPureChecksums( void ) { // "cp" // "Yf" Com_sprintf(cMsg, sizeof(cMsg), "Yf "); - Q_strcat(cMsg, sizeof(cMsg), va("%d ", cl.serverId) ); Q_strcat(cMsg, sizeof(cMsg), pChecksums); for (i = 0; i < 2; i++) { - cMsg[i] += 10; + cMsg[i] += '\n'; } CL_AddReliableCommand( cMsg, qfalse ); } @@ -1488,6 +1557,12 @@ because the renderer doesn't know what graphics to reload ================= */ void CL_Vid_Restart_f( void ) { + soundsystemsavegame_t save; + char tm_filename[MAX_RES_NAME]; + int tm_loopcount; + int tm_offset; + char current_soundtrack[128]; + if (!CL_Allowed_Vid_Restart()) { return; } @@ -1495,32 +1570,65 @@ void CL_Vid_Restart_f( void ) { Com_Printf("-------- CL_Vid_Restart_f --------\n"); cls.vid_restart = qtrue; - // don't let them loop during the restart - S_StopAllSounds(qtrue); + // + // Save the current music + // + Q_strncpyz(tm_filename, S_GetMusicFilename(), sizeof(tm_filename)); + tm_loopcount = S_GetMusicLoopCount(); + tm_offset = S_GetMusicOffset(); SV_ClearSvsTimeFixups(); + S_SaveData(&save); + Q_strncpyz(current_soundtrack, S_CurrentSoundtrack(), sizeof(current_soundtrack)); + S_BeginRegistration(); + // shutdown the UI + //CL_ShutdownUI(); // shutdown the renderer and clear the renderer interface - CL_ShutdownRef(); + CL_ShutdownRef(); + + cls.rendererRegistered = qfalse; + // shutdown the CGame CL_ShutdownCGame(); // initialize the renderer interface CL_InitRef(); + // initialize the UI + //CL_InitializeUI(); // initialize the ui library UI_ResolutionChange(); - - cls.rendererRegistered = qfalse; + // clear aliases + Alias_Clear(); // unpause so the cgame definately gets a snapshot and renders a frame Com_Unpause(); CL_StartHunkUsers(qfalse); +#if !defined(NO_MODERN_DMA) || !NO_MODERN_DMA + s_bSoundPaused = true; + S_LoadData(&save); +#else + S_Init(); +#endif + SV_FinishSvsTimeFixups(); - S_Init(); + S_ReLoad(&save); + + if (tm_filename[0]) { + S_TriggeredMusic_SetupHandle(tm_filename, tm_loopcount, tm_offset, 0); + } + + MUSIC_NewSoundtrack(current_soundtrack); + + if (clc.state > CA_CONNECTED && clc.state != CA_CINEMATIC) + { + // send pure checksums + CL_SendPureChecksums(); + } cls.vid_restart = qfalse; Com_Printf("----- finished CL_Vid_Restart_f ----\n"); @@ -1536,10 +1644,52 @@ handles will be invalid ================= */ void CL_Snd_Restart_f( void ) { +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA S_Shutdown(); S_Init(); + CL_Vid_Restart_f(); +#else + qboolean full; + soundsystemsavegame_t save; + char tm_filename[MAX_RES_NAME]; + int tm_loopcount; + int tm_offset; + char current_soundtrack[128]; - CL_Vid_Restart_f(); + full = S_NeedFullRestart(); + + // + // Save the current music + // + Q_strncpyz(tm_filename, S_GetMusicFilename(), sizeof(tm_filename)); + tm_loopcount = S_GetMusicLoopCount(); + tm_offset = S_GetMusicOffset(); + + SV_ClearSvsTimeFixups(); + + S_SaveData(&save); + Q_strncpyz(current_soundtrack, S_CurrentSoundtrack(), sizeof(current_soundtrack)); + + S_Shutdown(qfalse); + S_Init(qfalse); + + s_bSoundPaused = true; + + S_LoadData(&save); + + SV_FinishSvsTimeFixups(); + S_ReLoad(&save); + + if (tm_filename[0]) { + S_TriggeredMusic_SetupHandle(tm_filename, tm_loopcount, tm_offset, 0); + } + + MUSIC_NewSoundtrack(current_soundtrack); + + if (full) { + CL_Vid_Restart_f(); + } +#endif } @@ -1604,7 +1754,7 @@ CL_Clientinfo_f void CL_Clientinfo_f( void ) { Com_Printf( "--------- Client Information ---------\n" ); Com_Printf( "state: %i\n", clc.state ); - Com_Printf( "Server: %s\n", cls.servername ); + Com_Printf( "Server: %s\n", clc.servername ); Com_Printf ("User info settings:\n"); Info_Print( Cvar_InfoString( CVAR_USERINFO ) ); Com_Printf( "--------------------------------------\n" ); @@ -1661,6 +1811,13 @@ void CL_DownloadsComplete( void ) { Com_EventLoop(); CL_StartHunkUsers(qfalse); + + // set pure checksums + CL_SendPureChecksums(); + + CL_WritePacket(); + CL_WritePacket(); + CL_WritePacket(); } /* @@ -1798,7 +1955,7 @@ void CL_InitDownloads(void) { if (FS_ComparePaks( missingfiles, sizeof( missingfiles ), qfalse ) ) { // NOTE TTimo I would rather have that printed as a modal message box - // but at this point while joining the game we don't know wether we will successfully join or not + // but at this point while joining the game we don't know whether we will successfully join or not Com_Printf( "\nWARNING: You are missing some files referenced by the server:\n%s" "You might not be able to join the game\n" "Go to the setting menu to turn on autodownload, or get the file elsewhere\n\n", missingfiles ); @@ -1857,12 +2014,12 @@ void CL_CheckForResend( void ) { // if ( !Sys_IsLANAddress( clc.serverAddress ) ) { // CL_RequestAuthorization(); // } - NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge"); + CL_NET_OutOfBandPrint(clc.serverAddress, "getchallenge"); break; case CA_AUTHORIZING: // resend the cd key authorization gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_REAUTH); - NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "authorizeThis %s", cls.gcdResponse); + CL_NET_OutOfBandPrint(clc.serverAddress, "authorizeThis %s", cls.gcdResponse); break; case CA_CHALLENGING: /* @@ -1886,13 +2043,13 @@ wombat: sending conect here: an example connect string from MOHAA looks like thi Info_SetValueForKey(info, "protocol", va("%i", com_protocol->integer)); Info_SetValueForKey( info, "qport", va("%i", port ) ); Info_SetValueForKey(info, "challenge", va("%i", clc.challenge)); - Info_SetValueForKey(info, "version", com_shortversion->string); + Info_SetValueForKey(info, "version", com_target_version->string); if (com_target_game->integer == target_game_e::TG_MOHTT) { // only send if maintt is loaded Info_SetValueForKey(info, "clientType", "Breakthrough"); } - strcpy(data, "connect "); + Q_strncpyz(data, "connect ", sizeof(data)); // TTimo adding " " around the userinfo string to avoid truncated userinfo on the server // (Com_TokenizeString tokenizes around spaces) data[8] = '"'; @@ -1977,13 +2134,8 @@ void CL_MotdPacket( netadr_t from ) { CL_InitServerInfo =================== */ -void CL_InitServerInfo( serverInfo_t *server, serverAddress_t *address ) { - server->adr.type = NA_IP; - server->adr.ip[0] = address->ip[0]; - server->adr.ip[1] = address->ip[1]; - server->adr.ip[2] = address->ip[2]; - server->adr.ip[3] = address->ip[3]; - server->adr.port = address->port; +void CL_InitServerInfo( serverInfo_t *server, netadr_t *address ) { + server->adr = *address; server->clients = 0; server->hostName[0] = '\0'; server->mapName[0] = '\0'; @@ -2003,14 +2155,14 @@ void CL_InitServerInfo( serverInfo_t *server, serverAddress_t *address ) { CL_ServersResponsePacket =================== */ -void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) { - int i, count, max, total; - serverAddress_t addresses[MAX_SERVERSPERPACKET]; +void CL_ServersResponsePacket( const netadr_t* from, msg_t *msg, qboolean extended ) { + int i, j, count, total; + netadr_t addresses[MAX_SERVERSPERPACKET]; int numservers; byte* buffptr; byte* buffend; - - Com_Printf("CL_ServersResponsePacket\n"); + + Com_Printf("CL_ServersResponsePacket from %s\n", NET_AdrToStringwPort(*from)); if (cls.numglobalservers == -1) { // state to detect lack of servers or lack of response @@ -2018,71 +2170,84 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) { cls.numGlobalServerAddresses = 0; } - if (cls.nummplayerservers == -1) { - cls.nummplayerservers = 0; - } - // parse through server response string numservers = 0; buffptr = msg->data; buffend = buffptr + msg->cursize; - while (buffptr+1 < buffend) { - // advance to initial token - do { - if (*buffptr++ == '\\') - break; - } - while (buffptr < buffend); - if ( buffptr >= buffend - 6 ) { + // advance to initial token + do + { + if(*buffptr == '\\' || (extended && *buffptr == '/')) break; + + buffptr++; + } while (buffptr < buffend); + + while (buffptr + 1 < buffend) + { + // IPv4 address + if (*buffptr == '\\') + { + buffptr++; + + if (buffend - buffptr < sizeof(addresses[numservers].ip) + sizeof(addresses[numservers].port) + 1) + break; + + for(i = 0; i < sizeof(addresses[numservers].ip); i++) + addresses[numservers].ip[i] = *buffptr++; + + addresses[numservers].type = NA_IP; } + // IPv6 address, if it's an extended response + else if (extended && *buffptr == '/') + { + buffptr++; - // parse out ip - addresses[numservers].ip[0] = *buffptr++; - addresses[numservers].ip[1] = *buffptr++; - addresses[numservers].ip[2] = *buffptr++; - addresses[numservers].ip[3] = *buffptr++; - + if (buffend - buffptr < sizeof(addresses[numservers].ip6) + sizeof(addresses[numservers].port) + 1) + break; + + for(i = 0; i < sizeof(addresses[numservers].ip6); i++) + addresses[numservers].ip6[i] = *buffptr++; + + addresses[numservers].type = NA_IP6; + addresses[numservers].scope_id = from->scope_id; + } + else + // syntax error! + break; + // parse out port - addresses[numservers].port = (*buffptr++)<<8; + addresses[numservers].port = (*buffptr++) << 8; addresses[numservers].port += *buffptr++; addresses[numservers].port = BigShort( addresses[numservers].port ); // syntax check - if (*buffptr != '\\') { + if (*buffptr != '\\' && *buffptr != '/') break; - } - - Com_DPrintf( "server: %d ip: %d.%d.%d.%d:%d\n",numservers, - addresses[numservers].ip[0], - addresses[numservers].ip[1], - addresses[numservers].ip[2], - addresses[numservers].ip[3], - addresses[numservers].port ); - + numservers++; - if (numservers >= MAX_SERVERSPERPACKET) { + if (numservers >= MAX_SERVERSPERPACKET) break; - } - - // parse out EOT - if (buffptr[1] == 'E' && buffptr[2] == 'O' && buffptr[3] == 'T') { - break; - } } - if (cls.masterNum == 0) { - count = cls.numglobalservers; - max = MAX_GLOBAL_SERVERS; - } else { - count = cls.nummplayerservers; - max = MAX_OTHER_SERVERS; - } + count = cls.numglobalservers; - for (i = 0; i < numservers && count < max; i++) { + for (i = 0; i < numservers && count < MAX_GLOBAL_SERVERS; i++) { // build net address - serverInfo_t *server = (cls.masterNum == 0) ? &cls.globalServers[count] : &cls.mplayerServers[count]; + serverInfo_t *server = &cls.globalServers[count]; + + // Tequila: It's possible to have sent many master server requests. Then + // we may receive many times the same addresses from the master server. + // We just avoid to add a server if it is still in the global servers list. + for (j = 0; j < count; j++) + { + if (NET_CompareAdr(cls.globalServers[j].adr, addresses[i])) + break; + } + + if (j < count) + continue; CL_InitServerInfo( server, &addresses[i] ); // advance to next slot @@ -2090,29 +2255,18 @@ void CL_ServersResponsePacket( netadr_t from, msg_t *msg ) { } // if getting the global list - if (cls.masterNum == 0) { - if ( cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) { - // if we couldn't store the servers in the main list anymore - for (; i < numservers && count >= max; i++) { - serverAddress_t *addr; - // just store the addresses in an additional list - addr = &cls.globalServerAddresses[cls.numGlobalServerAddresses++]; - addr->ip[0] = addresses[i].ip[0]; - addr->ip[1] = addresses[i].ip[1]; - addr->ip[2] = addresses[i].ip[2]; - addr->ip[3] = addresses[i].ip[3]; - addr->port = addresses[i].port; - } + if ( count >= MAX_GLOBAL_SERVERS && cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) + { + // if we couldn't store the servers in the main list anymore + for (; i < numservers && cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS; i++) + { + // just store the addresses in an additional list + cls.globalServerAddresses[cls.numGlobalServerAddresses++] = addresses[i]; } } - if (cls.masterNum == 0) { - cls.numglobalservers = count; - total = count + cls.numGlobalServerAddresses; - } else { - cls.nummplayerservers = count; - total = count; - } + cls.numglobalservers = count; + total = count + cls.numGlobalServerAddresses; Com_Printf("%d servers parsed (total %d)\n", numservers, total); } @@ -2128,6 +2282,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { char *s; char *c; const char *reason; + + if (cl_netprofile->integer) { + NetProfileAddPacket(&cls.netprofile.inPackets, msg->cursize, NETPROF_PACKET_MESSAGE); + } MSG_BeginReadingOOB( msg ); MSG_ReadLong( msg ); // skip the -1 @@ -2212,7 +2370,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { // echo request from server if ( !Q_stricmp(c, "echo") ) { - NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) ); + CL_NET_OutOfBandPrint(from, "%s", Cmd_Argv(1) ); return; } @@ -2220,7 +2378,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { if ( !Q_stricmp(c, "getKey") ) { clc.state = CA_AUTHORIZING; gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_NEWAUTH); - NET_OutOfBandPrint(NS_CLIENT, from, "authorizeThis %s", cls.gcdResponse); + CL_NET_OutOfBandPrint(from, "authorizeThis %s", cls.gcdResponse); return; } @@ -2240,7 +2398,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { // echo request from server if ( !Q_strncmp(c, "getserversResponse", 18) ) { - CL_ServersResponsePacket( from, msg ); + CL_ServersResponsePacket( &from, msg, qfalse ); return; } @@ -2335,6 +2493,13 @@ CL_CheckTimeout ================== */ void CL_CheckTimeout( void ) { + if (com_sv_running->integer) { + // Added in OPM + // Timeout should not be possible if the client is hosting the game + // (like in single-player mode) + return; + } + // // check timeout // @@ -2342,10 +2507,37 @@ void CL_CheckTimeout( void ) { && clc.state >= CA_CONNECTED && clc.state != CA_CINEMATIC && cls.realtime - clc.lastPacketTime > cl_timeout->value*1000) { if (++cl.timeoutcount > 5) { // timeoutcount saves debugger - Com_Printf ("\nServer connection timed out.\n"); - Cbuf_AddText( "pushmenu servertimeout\n" ); - CL_Disconnect(); - return; + const char* info; + const char* maxclients; + + info = &cl.gameState.stringData[cl.gameState.stringOffsets[CS_SERVERINFO]]; + maxclients = Info_ValueForKey(info, "maxclients"); + // + // Disconnect if the player isn't alone (single-player mode) + // + if (!maxclients || atoi(maxclients) != 1) { + qboolean bConsoleState; + + bConsoleState = UI_ConsoleIsOpen(); + + Com_Printf("\nServer connection timed out.\n"); + SV_Shutdown("\nServer connection timed out\n"); + + if (com_cl_running && com_cl_running->integer) { + CL_AbnormalDisconnect(); + CL_FlushMemory(); + CL_StartHunkUsers(qfalse); + } + + UI_ForceMenuOff(qtrue); + UI_PushMenu("servertimeout"); + + if (bConsoleState) { + UI_OpenConsole(); + } else { + UI_CloseConsole(); + } + } } } else { cl.timeoutcount = 0; @@ -2391,7 +2583,7 @@ void CL_CheckUserinfo( void ) { // send a reliable userinfo update if needed if(cvar_modifiedFlags & CVAR_USERINFO) { - if (Com_SanitizeName(name->string, szSanitizedName)) { + if (Com_SanitizeName(name->string, szSanitizedName, sizeof(szSanitizedName))) { Cvar_Set("name", szSanitizedName); } @@ -2401,9 +2593,43 @@ void CL_CheckUserinfo( void ) { } void CL_SetFrameNumber(int frameNumber) { + if (!re.SetFrameNumber) { + return; + } + re.SetFrameNumber(frameNumber); } +/* +================== +CL_VerifyUpdate + +Check for a new version and display a message box +when a new version is available +================== +*/ +void CL_VerifyUpdate() { + if (cl_updateNotified) { + return; + } + + int lastMajor, lastMinor, lastPatch; + if (updateChecker.CheckNewVersion(lastMajor, lastMinor, lastPatch)) { + cl_updateNotified = true; + + const char *updateText = + va("A new update is available!\n" + "The latest version is v%d.%d.%d (you are running v%s).\n" + "Check https://github.com/openmoh/openmohaa for more.", + lastMajor, + lastMinor, + lastPatch, + PRODUCT_VERSION_NUMBER_STRING); + + UIMessageDialog::ShowMessageBox("Update available", updateText); + } +} + /* ================== CL_Frame @@ -2434,11 +2660,19 @@ void CL_Frame ( int msec ) { } #endif - if ( clc.state == CA_DISCONNECTED && !UI_MenuActive() - && !com_sv_running->integer ) { - // if disconnected, bring up the menu - S_StopAllSounds( qtrue ); - UI_MenuEscape( "main" ); + if (CL_FinishedIntro()) { + if (clc.state == CA_DISCONNECTED) { + if (!UI_MenuActive() && !com_sv_running->integer) { + // if disconnected, bring up the menu + S_StopAllSounds2(qtrue); + S_TriggeredMusic_PlayIntroMusic(); + UI_MenuEscape("main"); + } + + CL_VerifyUpdate(); + } else if (clc.state == CA_CINEMATIC) { + UI_ForceMenuOff(qtrue); + } } // if recording an avi, lock to a fixed fps @@ -2473,7 +2707,7 @@ void CL_Frame ( int msec ) { now.tm_min, now.tm_sec ); - Q_strncpyz( serverName, cls.servername, MAX_OSPATH ); + Q_strncpyz( serverName, clc.servername, MAX_OSPATH ); // Replace the ":" in the address as it is not a valid // file name character p = strstr( serverName, ":" ); @@ -2507,6 +2741,31 @@ void CL_Frame ( int msec ) { cls.timeScaled = com_timescale->integer != 1; + // + // Added in 2.0: network profiling + // + if (cl_netprofile->integer) { + if (!cls.netprofile.initialized) { + memset(&cls.netprofile, 0, sizeof(cls.netprofile)); + cls.netprofile.initialized = qtrue; + } + + if (cls.netprofile.rate != cl_rate->integer) { + cls.netprofile.rate = cl_rate->integer; + + if (cls.netprofile.rate < 1000) { + cls.netprofile.rate = 1000; + } else if (cls.netprofile.rate > 90000) { + cls.netprofile.rate = 90000; + } + } + + cls.netprofile.outPackets.updateTime = Com_Milliseconds(); + cls.netprofile.inPackets.updateTime = cls.netprofile.outPackets.updateTime; + } else { + cls.netprofile.initialized = qfalse; + } + // see if we need to update any userinfo CL_CheckUserinfo(); @@ -2595,15 +2854,15 @@ CL_ShutdownRef ============ */ void CL_ShutdownRef( void ) { - if ( !re.Shutdown ) { - return; + if ( re.Shutdown ) { + re.Shutdown( qtrue ); } - re.Shutdown( qtrue ); + Com_Memset( &re, 0, sizeof( re ) ); -#ifdef USE_RENDERER_DLL - // su44: remember to unload renderer library - if(rendererLib) { - Sys_UnloadLibrary(rendererLib); + +#ifdef USE_RENDERER_DLOPEN + if ( rendererLib ) { + Sys_UnloadLibrary( rendererLib ); rendererLib = NULL; } #endif @@ -2653,6 +2912,15 @@ void *CL_RefMalloc(int size) { return Z_TagMalloc( size, TAG_RENDERER ); } +/* +============ +CL_RefFree +============ +*/ +void CL_RefFree(void* ptr) { + Z_Free(ptr); +} + /* ============ CL_RefClear @@ -2708,7 +2976,7 @@ void CL_RefStaticClear( void ) { CL_CG_PermanentMark ============ */ -int CL_CG_PermanentMark(const vec3_t origin, const vec3_t dir, float orientation, +int CL_CG_PermanentMark(vec3_t origin, vec3_t dir, float orientation, float fSScale, float fTScale, float red, float green, float blue, float alpha, qboolean dolighting, float fSCenter, float fTCenter, markFragment_t *pMarkFragments, void *pPolyVerts ) @@ -2771,22 +3039,105 @@ void CL_CG_EndTiki( dtiki_t *tiki ) { } } +/* +============ +CL_CG_EndTiki +============ +*/ extern "C" int CL_ScaledMilliseconds(void) { return Sys_Milliseconds()*com_timescale->value; } +/* +============ +CL_RefFS_WriteFile +============ +*/ void CL_RefFS_WriteFile(const char* qpath, const void* buffer, int size) { FS_WriteFile(qpath, buffer, size); } +/* +============ +CL_RefFS_ListFiles +============ +*/ char** CL_RefFS_ListFiles(const char* name, const char* extension, int* numfilesfound) { return FS_ListFiles(name, extension, qtrue, numfilesfound); } +/* +============ +CL_RefCIN_UploadCinematic +============ +*/ void CL_RefCIN_UploadCinematic(int handle) { } +/* +============ +CL_RefTIKI_GetNumChannels +============ +*/ +int CL_RefTIKI_GetNumChannels(dtiki_t* tiki) { + return tiki->m_boneList.NumChannels(); +} + +/* +============ +CL_RefTIKI_GetLocalChannel +============ +*/ +int CL_RefTIKI_GetLocalChannel(dtiki_t* tiki, int channel) { + return tiki->m_boneList.LocalChannel(channel); +} + +/* +============ +CL_RefTIKI_GetLocalFromGlobal +============ +*/ +int CL_RefTIKI_GetLocalFromGlobal(dtiki_t* tiki, int channel) { + return tiki->m_boneList.GetLocalFromGlobal(channel); +} + +/* +============ +CL_RefSKEL_GetMorphWeightFrame +============ +*/ +int CL_RefSKEL_GetMorphWeightFrame(void* skeletor, int index, float time, int* data) { + return ((skeletor_c*)skeletor)->GetMorphWeightFrame(index, time, data); +} + +/* +============ +CL_RefSKEL_GetBoneParent +============ +*/ +int CL_RefSKEL_GetBoneParent(void* skeletor, int boneIndex) { + return ((skeletor_c*)skeletor)->GetBoneParent(boneIndex); +} + +/* +============ +CL_GetRefSequence +============ +*/ +int CL_GetRefSequence(void) { + return cls.refSequence; +} + +/* +============ +CL_IsRendererLoaded +============ +*/ +qboolean CL_IsRendererLoaded(void) { + return re.Shutdown != NULL; +} + /* ============ CL_InitRef @@ -2795,12 +3146,40 @@ CL_InitRef void CL_InitRef( void ) { refimport_t ri; refexport_t *ret; -#ifdef USE_RENDERER_DLL - char dllName[256]; +#ifdef USE_RENDERER_DLOPEN + GetRefAPI_t GetRefAPI; + char dllName[MAX_OSPATH]; #endif Com_Printf( "----- Initializing Renderer ----\n" ); +#ifdef USE_RENDERER_DLOPEN + cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH); + + Com_sprintf(dllName, sizeof(dllName), "renderer_%s" ARCH_SUFFIX DLL_SUFFIX DLL_EXT, cl_renderer->string); + + if(!(rendererLib = Sys_LoadDll(dllName, qfalse)) && strcmp(cl_renderer->string, cl_renderer->resetString)) + { + Com_Printf("failed:\n\"%s\"\n", Sys_LibraryError()); + Cvar_ForceReset("cl_renderer"); + + Com_sprintf(dllName, sizeof(dllName), "renderer_opengl1" ARCH_SUFFIX DLL_SUFFIX DLL_EXT); + rendererLib = Sys_LoadDll(dllName, qfalse); + } + + if(!rendererLib) + { + Com_Printf("failed:\n\"%s\"\n", Sys_LibraryError()); + Com_Error(ERR_FATAL, "Failed to load renderer"); + } + + GetRefAPI = (GetRefAPI_t)Sys_LoadFunction(rendererLib, "GetRefAPI"); + if(!GetRefAPI) + { + Com_Error(ERR_FATAL, "Can't load symbol GetRefAPI: '%s'", Sys_LibraryError()); + } +#endif + ri.Cmd_AddCommand = Cmd_AddCommand; ri.Cmd_RemoveCommand = Cmd_RemoveCommand; ri.Cmd_Argc = Cmd_Argc; @@ -2811,7 +3190,7 @@ void CL_InitRef( void ) { ri.Milliseconds = CL_ScaledMilliseconds; ri.LV_ConvertString = Sys_LV_CL_ConvertString; ri.Malloc = CL_RefMalloc; - ri.Free = Z_Free; + ri.Free = CL_RefFree; ri.Clear = CL_RefClear; ri.Hunk_Clear = CL_RefStaticClear; #ifdef HUNK_DEBUG @@ -2824,8 +3203,10 @@ void CL_InitRef( void ) { ri.CM_DrawDebugSurface = CM_DrawDebugSurface; ri.FS_OpenFile = FS_FOpenFileRead; + ri.FS_OpenFileWrite = FS_FOpenFileWrite; ri.FS_CloseFile = FS_FCloseFile; ri.FS_Read = FS_Read; + ri.FS_Write = FS_Write; ri.FS_Seek = FS_Seek; ri.FS_ReadFile = FS_ReadFile; ri.FS_ReadFileEx = FS_ReadFileEx; @@ -2835,8 +3216,10 @@ void CL_InitRef( void ) { ri.FS_ListFiles = CL_RefFS_ListFiles; ri.FS_FileIsInPAK = FS_FileIsInPAK; ri.FS_FileExists = FS_FileExists; + ri.FS_CanonicalFilename = FS_CanonicalFilename; ri.Cvar_Get = Cvar_Get; ri.Cvar_Set = Cvar_Set; + ri.Cvar_SetValue = Cvar_SetValue; ri.Cvar_SetDefault = Cvar_SetDefault; ri.CM_EntityString = CM_EntityString; @@ -2885,40 +3268,30 @@ void CL_InitRef( void ) { ri.Sys_GLimpInit = Sys_GLimpInit; ri.Sys_LowPhysicalMemory = Sys_LowPhysicalMemory; -#ifdef USE_RENDERER_DLL - // su44: load renderer dll - cl_renderer = Cvar_Get("cl_renderer", "glom", CVAR_ARCHIVE); - Q_snprintf(dllName, sizeof(dllName), "renderer_%s" ARCH_STRING DLL_EXT, cl_renderer->string); - Com_Printf("Loading \"%s\"...", dllName); - if((rendererLib = Sys_LoadLibrary(dllName)) == 0) { -#ifdef _WIN32 - Com_Error(ERR_FATAL, "failed:\n\"%s\"\n", Sys_LibraryError()); -#else - char fn[1024]; + // + // Added in OPM + // + ri.UI_LoadResource = UI_LoadResource; + ri.CM_PointLeafnum = CM_PointLeafnum; + ri.CM_LeafCluster = CM_LeafCluster; - Q_strncpyz(fn, Sys_Cwd(), sizeof(fn)); - strncat(fn, "/", sizeof(fn) - strlen(fn) - 1); - strncat(fn, dllName, sizeof(fn) - strlen(fn) - 1); + ri.TIKI_CalcLodConsts = TIKI_CalcLodConsts; + ri.TIKI_CalculateBounds = TIKI_CalculateBounds; + ri.TIKI_FindTiki = TIKI_FindTiki; + ri.TIKI_RegisterTikiFlags = TIKI_RegisterTikiFlags; + ri.TIKI_GetSkeletor = TIKI_GetSkeletor; + ri.TIKI_GetSkel = TIKI_GetSkel; + ri.TIKI_GetSkelAnimFrame = TIKI_GetSkelAnimFrame; + ri.TIKI_GlobalRadius = TIKI_GlobalRadius; + ri.TIKI_FindSkelByHeader = TIKI_FindSkelByHeader; + ri.TIKI_GetNumChannels = CL_RefTIKI_GetNumChannels; + ri.TIKI_GetLocalChannel = CL_RefTIKI_GetLocalChannel; + ri.TIKI_GetLocalFromGlobal = CL_RefTIKI_GetLocalFromGlobal; - Com_Printf("Loading \"%s\"...", fn); - if((rendererLib = Sys_LoadLibrary(fn)) == 0) - { - Com_Error(ERR_FATAL, "failed:\n\"%s\"", Sys_LibraryError()); - } -#endif /* _WIN32 */ - } + ri.SKEL_GetBoneParent = CL_RefSKEL_GetBoneParent; + ri.SKEL_GetMorphWeightFrame = CL_RefSKEL_GetMorphWeightFrame; - Com_Printf("done\n"); - - DGetRefAPI = Sys_LoadFunction(rendererLib, "GetRefAPI"); - if(!DGetRefAPI) - { - Com_Error(ERR_FATAL, "Can't load symbol GetRefAPI: '%s'", Sys_LibraryError()); - } - ret = DGetRefAPI( REF_API_VERSION, &ri ); -#else ret = GetRefAPI( REF_API_VERSION, &ri ); -#endif #if defined __USEA3D && defined __A3D_GEOM hA3Dg_ExportRenderGeom (ret); @@ -2934,6 +3307,8 @@ void CL_InitRef( void ) { // unpause so the cgame definately gets a snapshot and renders a frame Cvar_Set( "cl_paused", "0" ); + + cls.refSequence++; } @@ -2972,7 +3347,7 @@ void CL_VidMode_f( void ) { mode = atoi( Cmd_Argv( 1 ) ); if( CL_SetVidMode( mode ) ) { - sprintf( text, "%d", mode ); + Com_sprintf( text, sizeof( text ), "%d", mode ); Cvar_Set( "r_mode", text ); } } @@ -2991,10 +3366,10 @@ void CL_TikiInfoCommand_f( void ) { name = Cmd_Argv( 1 ); if( strchr( name, '/' ) ) { - strcpy( modelname, name ); + Q_strncpyz( modelname, name, sizeof( modelname ) ); } else { - strcpy( modelname, "models/" ); - strcat( modelname, name ); + Q_strncpyz( modelname, "models/", sizeof( modelname ) ); + Q_strcat( modelname, sizeof( modelname ), name ); } COM_DefaultExtension( modelname, sizeof( modelname ), ".tik" ); @@ -3086,8 +3461,6 @@ it by filling it with 2048 bytes of random data. */ static void CL_GenerateQKey(void) { - // FIXME: unimplemented - /* int len = 0; unsigned char buff[ QKEY_SIZE ]; fileHandle_t f; @@ -3117,7 +3490,6 @@ static void CL_GenerateQKey(void) FS_FCloseFile( f ); Com_Printf( "QKEY generated\n" ); } - */ } /* @@ -3139,7 +3511,7 @@ void CL_Init( void ) { start = Sys_Milliseconds(); CL_ClearState (); - S_StopAllSounds( qtrue ); + S_StopAllSounds2( qtrue ); clc.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED Key_SetCatcher(KEYCATCH_UI); @@ -3165,6 +3537,8 @@ void CL_Init( void ) { cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE); cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP ); cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP ); + cl_netprofile = Cvar_Get("cl_netprofile", "0", CVAR_TEMP); + cl_netprofileoverlay = Cvar_Get("cl_netprofileoverlay", "0", CVAR_TEMP); cl_showSend = Cvar_Get ("cl_showSend", "0", CVAR_TEMP ); cl_showTimeDelta = Cvar_Get ("cl_showTimeDelta", "0", CVAR_TEMP ); cl_freezeDemo = Cvar_Get ("cl_freezeDemo", "0", CVAR_TEMP ); @@ -3279,21 +3653,13 @@ void CL_Init( void ) { cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE ); // userinfo - name = Cvar_Get ("name", "UnnamedSoldier", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("rate", "5000", CVAR_USERINFO | CVAR_ARCHIVE ); + name = Cvar_Get ("name", va("UnnamedSoldier#%d", rand() % 100000), CVAR_USERINFO | CVAR_ARCHIVE); + cl_rate = Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("password", "", CVAR_USERINFO); Cvar_Get ("dm_playermodel", "american_army", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("dm_playergermanmodel", "german_wehrmacht_soldier", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("cg_predictItems", "1", CVAR_USERINFO | CVAR_ARCHIVE ); - - - // cgame might not be initialized before menu is used - Cvar_Get ("cg_viewsize", "100", CVAR_ARCHIVE ); - - Cvar_Get ("cg_running", "0", CVAR_ROM ); - // // register our commands // @@ -3312,7 +3678,6 @@ void CL_Init( void ) { Cmd_AddCommand ("reconnect", CL_Reconnect_f); Cmd_AddCommand ("localservers", CL_LocalServers_f); Cmd_AddCommand ("globalservers", CL_GlobalServers_f); - Cmd_AddCommand ("refreshserverlist", CL_GamespyServers_f); // wombat: gamespy query Cmd_AddCommand ("rcon", CL_Rcon_f); Cmd_AddCommand ("setenv", CL_Setenv_f ); Cmd_AddCommand ("ping", CL_Ping_f ); @@ -3341,10 +3706,12 @@ void CL_Init( void ) { Cvar_Set( "cl_running", "1" ); - NET_Init(); +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA S_Init2(); +#else + S_Init(qtrue); +#endif - // fixme: should we leave it? CL_GenerateQKey(); Cvar_Get( "cl_guid", "", CVAR_USERINFO | CVAR_ROM ); CL_UpdateGUID( NULL, 0 ); @@ -3353,6 +3720,12 @@ void CL_Init( void ) { end = Sys_Milliseconds(); + if (com_gotOriginalConfig) { + // Added in OPM + // Apply config tweaks after loading the original config + CL_ApplyOriginalConfigTweaks(); + } + Com_Printf( "----- Client Initialization Complete ----- %i ms\n", start - end ); } @@ -3383,7 +3756,11 @@ void CL_Shutdown(const char* finalmsg, qboolean disconnect, qboolean quit) { if(disconnect) CL_Disconnect(); +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA S_Shutdown(); +#else + S_Shutdown(qtrue); +#endif CL_ShutdownRef(); CL_ShutdownUI(); @@ -3411,6 +3788,8 @@ void CL_Shutdown(const char* finalmsg, qboolean disconnect, qboolean quit) { Cmd_RemoveCommand ("video"); Cmd_RemoveCommand ("stopvideo"); + CL_ShutdownInput(); + Cvar_Set( "cl_running", "0" ); recursive = qfalse; @@ -3430,6 +3809,7 @@ static void CL_SetServerInfo(serverInfo_t *server, const char *info, int ping) { server->maxClients = atoi(Info_ValueForKey(info, "sv_maxclients")); Q_strncpyz(server->game,Info_ValueForKey(info, "game"), MAX_NAME_LENGTH); server->gameType = atoi(Info_ValueForKey(info, "gametype")); + Q_strncpyz(server->gameTypeString, Info_ValueForKey(info, "gametypestring"), sizeof(server->gameTypeString)); server->netType = atoi(Info_ValueForKey(info, "nettype")); server->minPing = atoi(Info_ValueForKey(info, "minping")); server->maxPing = atoi(Info_ValueForKey(info, "maxping")); @@ -3475,26 +3855,82 @@ CL_ServerInfoPacket void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { int i, type; char info[MAX_INFO_STRING]; - const char* str; char *infoString; int prot; + char *gamename; + char *pszVersion; + char *pszServerType; + qboolean gameMismatch; infoString = MSG_ReadString( msg ); + // if this isn't the correct gamename, ignore it + gamename = Info_ValueForKey( infoString, "gamename" ); + +#ifdef LEGACY_PROTOCOL + // gamename is optional for legacy protocol + if (com_legacyprotocol->integer && !*gamename) + gameMismatch = qfalse; + else +#endif + gameMismatch = !*gamename || strcmp(gamename, com_gamename->string) != 0; + + if (gameMismatch) + { + Com_DPrintf( "Game mismatch in info packet: %s\n", infoString ); + return; + } + // if this isn't the correct protocol version, ignore it prot = atoi( Info_ValueForKey( infoString, "protocol" ) ); - if ( prot != PROTOCOL_VERSION ) { + + if(prot != com_protocol->integer +#ifdef LEGACY_PROTOCOL + && prot != com_legacyprotocol->integer +#endif + && (com_target_demo->integer || prot != protocol_version_demo) + ) + { Com_DPrintf( "Different protocol info packet: %s\n", infoString ); return; } + if (!com_target_demo->integer && protocol_version_demo != protocol_version_full && prot == protocol_version_demo) { + Com_DPrintf("Full version found compatible demo protocol version. %s\n", infoString); + } + + pszVersion = Info_ValueForKey(infoString, "gamever"); + pszServerType = Info_ValueForKey(infoString, "serverType"); + + if (*pszVersion) { + if (*pszVersion == 'd') { + pszVersion++; + } + + if (com_target_game->integer >= target_game_e::TG_MOHTT) { + if (atoi(pszServerType) == target_game_e::TG_MOHTT) { + if (fabs(atof(pszVersion)) < 2.3f) { + return; + } + } else { + if (fabs(atof(pszVersion)) < 2.1f) { + return; + } + } + } else { + if (fabs(atof(pszVersion) - com_target_version->value) > 0.1f) { + return; + } + } + } + // iterate servers waiting for ping response for (i=0; iaddress) ) { - // if we recieved an response for this server status request + // if we received a response for this server status request if (!serverStatus->pending) { Q_strncpyz(serverStatusString, serverStatus->string, maxLen); serverStatus->retrieved = qtrue; @@ -3647,7 +4069,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma serverStatus->retrieved = qfalse; serverStatus->time = 0; serverStatus->startTime = Com_Milliseconds(); - NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" ); + CL_NET_OutOfBandPrint(to, "getstatus" ); return qfalse; } } @@ -3659,7 +4081,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma serverStatus->retrieved = qfalse; serverStatus->startTime = Com_Milliseconds(); serverStatus->time = 0; - NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" ); + CL_NET_OutOfBandPrint(to, "getstatus" ); return qfalse; } return qfalse; @@ -3672,9 +4094,9 @@ CL_ServerStatusResponse */ void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) { const char *s; - char info[MAX_INFO_STRING]; - int i, l, score, ping; - size_t len; + char info[MAX_INFO_STRING]; + int i, l, ping; + int len; serverStatus_t *serverStatus; serverStatus = NULL; @@ -3727,7 +4149,7 @@ void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) { if (serverStatus->print) { Com_Printf("\nPlayers:\n"); - Com_Printf("num: score: ping: name:\n"); + Com_Printf("num: ping: name:\n"); } for (i = 0, s = MSG_ReadStringLine( msg ); *s; s = MSG_ReadStringLine( msg ), i++) { @@ -3735,16 +4157,14 @@ void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) { Com_sprintf(&serverStatus->string[len], sizeof(serverStatus->string)-len, "\\%s", s); if (serverStatus->print) { - score = ping = 0; - sscanf(s, "%d %d", &score, &ping); + ping = 0; + sscanf(s, "%d", &ping); s = strchr(s, ' '); - if (s) - s = strchr(s+1, ' '); if (s) s++; else s = "unknown"; - Com_Printf("%-2d %-3d %-3d %s\n", i, score, ping, s ); + Com_Printf("%-2d %-3d %s\n", i, ping, s ); } } len = strlen(serverStatus->string); @@ -3773,6 +4193,7 @@ void CL_LocalServers_f( void ) { // reset the list, waiting for response cls.numlocalservers = 0; + cls.bNewLocalServerInfo = true; cls.pingUpdateSource = AS_LOCAL; for (i = 0; i < MAX_OTHER_SERVERS; i++) { @@ -3797,176 +4218,122 @@ void CL_LocalServers_f( void ) { to.type = NA_BROADCAST; NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); + + if (cl_netprofile->integer) { + NetProfileAddPacket(&cls.netprofile.inPackets, strlen( message ), NETPROF_PACKET_MESSAGE); + } + + // Added in OPM (from ioquake3) + to.type = NA_MULTICAST6; + NET_SendPacket( NS_CLIENT, strlen( message ), message, to ); + + if (cl_netprofile->integer) { + NetProfileAddPacket(&cls.netprofile.inPackets, strlen(message), NETPROF_PACKET_MESSAGE); + } } } } -/* -================== -CL_GamespyServers_f -================== -*/ -// currently about 1000 mohaa servers at a time. when set higher, buffer must be increased! -#define MAX_GAMESPYSERVERS 16 - -void CL_GamespyServers_f( void ) { - // FIXME: unimplemented -#if 0 - char buffer[10240]; - int bytesRead; - - int i, count, max, total; - serverAddress_t addresses[MAX_GAMESPYSERVERS]; - int numservers; - byte* buffptr; - byte* buffend; - -// if ( Cmd_Argc() < 1) { -// Com_Printf( "usage: gamespyservers [keywords]\n"); -// return; -// } - - Com_Printf( "Requesting servers from the GameSpy master...\n" ); - Cvar_Set( "dm_serverstatus", "Getting List."); - - - if (!NETGS_CreateMasterSocket()) { - Com_Printf( "CL_GamespyServers_f: could not create socket.\n" ); - return; - } - if (!NETGS_SendMasterRequest()) { - Com_Printf( "CL_GamespyServers_f: could not send master request.\n" ); - return; - } - bytesRead = NETGS_ReceiveMasterResponse( buffer, sizeof(buffer) ); - if (!bytesRead) { - Com_Printf( "CL_GamespyServers_f: Error in Response.\n" ); - return; - } - - // parse through server response string - numservers = 0; - buffptr = ( byte * )buffer; - buffend = buffptr + bytesRead; - - while (buffptr+1 < buffend) { - if ( buffptr >= buffend - 6 ) { - break; - } - - // parse out ip - addresses[numservers].ip[0] = *buffptr++; - addresses[numservers].ip[1] = *buffptr++; - addresses[numservers].ip[2] = *buffptr++; - addresses[numservers].ip[3] = *buffptr++; - - // parse out port - addresses[numservers].port = *buffptr++; - addresses[numservers].port += (*buffptr++) << 8; - - Com_DPrintf( "server: %d ip: %d.%d.%d.%d:%d\n",numservers, - addresses[numservers].ip[0], - addresses[numservers].ip[1], - addresses[numservers].ip[2], - addresses[numservers].ip[3], - BigShort(addresses[numservers].port) ); - - numservers++; - if (numservers >= MAX_GAMESPYSERVERS) { - break; - } - - // parse out "\\final\\" - if (buffptr[0] == '\\' && buffptr[1] == 'f' && buffptr[2] == 'i' && buffptr[3] == 'n' && buffptr[4] == 'a' && buffptr[6] == 'l' && buffptr[6] == '\\') { - break; - } - } - - cls.numglobalservers = 0; - cls.numGlobalServerAddresses = 0; - - count = cls.numglobalservers; - max = MAX_GLOBAL_SERVERS; - for (i = 0; i < numservers && count < max; i++) { - // build net address - serverInfo_t *server = &cls.globalServers[count]; - - CL_InitServerInfo( server, &addresses[i] ); - // advance to next slot - count++; - } - - - if ( cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) { - // if we couldn't store the servers in the main list anymore - for (; i < numservers && count >= max; i++) { - serverAddress_t *addr; - // just store the addresses in an additional list - addr = &cls.globalServerAddresses[cls.numGlobalServerAddresses++]; - addr->ip[0] = addresses[i].ip[0]; - addr->ip[1] = addresses[i].ip[1]; - addr->ip[2] = addresses[i].ip[2]; - addr->ip[3] = addresses[i].ip[3]; - addr->port = addresses[i].port; - } - } - - cls.numglobalservers = count; - total = count + cls.numGlobalServerAddresses; - - Com_Printf("%d servers parsed (total %d)\n", numservers, total); - Cvar_Set( "dm_serverstatus", "Server List Received."); - Cvar_SetValue( "dm_servercount", total ); -#endif -} - - /* ================== CL_GlobalServers_f + +Originally master 0 was Internet and master 1 was MPlayer. +ioquake3 2008; added support for requesting five separate master servers using 0-4. +ioquake3 2017; made master 0 fetch all master servers and 1-5 request a single master server. ================== */ void CL_GlobalServers_f( void ) { netadr_t to; - int i; - int count; - char *buffptr; - char command[1024]; + int count, i, masterNum; + char command[1024], *masteraddress; + + if ((count = Cmd_Argc()) < 3 || (masterNum = atoi(Cmd_Argv(1))) < 0 || masterNum > MAX_MASTER_SERVERS) + { + Com_Printf("usage: globalservers [keywords]\n", MAX_MASTER_SERVERS); + return; + } - if ( Cmd_Argc() < 3) { - Com_Printf( "usage: globalservers [keywords]\n"); + // request from all master servers + if ( masterNum == 0 ) { + int numAddress = 0; + + for ( i = 1; i <= MAX_MASTER_SERVERS; i++ ) { + Com_sprintf(command, sizeof(command), "sv_master%d", i); + masteraddress = Cvar_VariableString(command); + + if(!*masteraddress) + continue; + + numAddress++; + + Com_sprintf(command, sizeof(command), "globalservers %d %s %s\n", i, Cmd_Argv(2), Cmd_ArgsFrom(3)); + Cbuf_AddText(command); + } + + if ( !numAddress ) { + Com_Printf( "CL_GlobalServers_f: Error: No master server addresses.\n"); + } return; } - cls.masterNum = atoi( Cmd_Argv(1) ); - - Com_Printf( "Requesting servers from the master...\n"); + Com_sprintf(command, sizeof(command), "sv_master%d", masterNum); + masteraddress = Cvar_VariableString(command); + + if(!*masteraddress) + { + Com_Printf( "CL_GlobalServers_f: Error: No master server address given.\n"); + return; + } // reset the list, waiting for response // -1 is used to distinguish a "no response" - NET_StringToAdr( cl_master->string, &to, NA_IP ); - - if( cls.masterNum == 1 ) { - cls.nummplayerservers = -1; - cls.pingUpdateSource = AS_MPLAYER; + i = NET_StringToAdr(masteraddress, &to, NA_UNSPEC); + + if(!i) + { + Com_Printf( "CL_GlobalServers_f: Error: could not resolve address of master %s\n", masteraddress); + return; } - else { - cls.numglobalservers = -1; - cls.pingUpdateSource = AS_GLOBAL; + else if(i == 2) + to.port = BigShort(PORT_MASTER); + + Com_Printf("Requesting servers from %s (%s)...\n", masteraddress, NET_AdrToStringwPort(to)); + + cls.numglobalservers = -1; + cls.pingUpdateSource = AS_GLOBAL; + + // Use the extended query for IPv6 masters + if (to.type == NA_IP6 || to.type == NA_MULTICAST6) + { + int v4enabled = Cvar_VariableIntegerValue("net_enabled") & NET_ENABLEV4; + + if(v4enabled) + { + Com_sprintf(command, sizeof(command), "getserversExt %s %s", + com_gamename->string, Cmd_Argv(2)); + } + else + { + Com_sprintf(command, sizeof(command), "getserversExt %s %s ipv6", + com_gamename->string, Cmd_Argv(2)); + } } - to.type = NA_IP; - to.port = BigShort(PORT_MASTER); + //else if ( !Q_stricmp( com_gamename->string, LEGACY_MASTER_GAMENAME ) ) + // Com_sprintf(command, sizeof(command), "getservers %s", + // Cmd_Argv(2)); + else + Com_sprintf(command, sizeof(command), "getservers %s %s", + com_gamename->string, Cmd_Argv(2)); - sprintf( command, "getservers %s", Cmd_Argv(2) ); + for (i=3; i < count; i++) + { + Q_strcat(command, sizeof(command), " "); + Q_strcat(command, sizeof(command), Cmd_Argv(i)); + } - // tack on keywords - buffptr = command + strlen( command ); - count = Cmd_Argc(); - for (i=3; i= MAX_PINGREQUESTS || !cl_pinglist[n].adr.port) { - // empty slot + // empty or invalid slot buf[0] = '\0'; *pingtime = 0; return; } - str = NET_AdrToString( cl_pinglist[n].adr ); + str = NET_AdrToStringwPort( cl_pinglist[n].adr ); Q_strncpyz( buf, str, buflen ); time = cl_pinglist[n].time; if (!time) { // check for timeout - time = cls.realtime - cl_pinglist[n].start; + time = Sys_Milliseconds() - cl_pinglist[n].start; maxPing = Cvar_VariableIntegerValue( "cl_maxPing" ); if( maxPing < 100 ) { maxPing = 100; @@ -4035,9 +4402,9 @@ CL_GetPingInfo */ void CL_GetPingInfo( int n, char *buf, int buflen ) { - if (!cl_pinglist[n].adr.port) + if (n < 0 || n >= MAX_PINGREQUESTS || !cl_pinglist[n].adr.port) { - // empty slot + // empty or invalid slot if (buflen) buf[0] = '\0'; return; @@ -4090,7 +4457,7 @@ CL_GetFreePing ping_t* CL_GetFreePing( void ) { ping_t* pingptr; - ping_t* best; + ping_t* best; int oldest; int i; int time; @@ -4103,7 +4470,7 @@ ping_t* CL_GetFreePing( void ) { if (!pingptr->time) { - if (cls.realtime - pingptr->start < 500) + if (Sys_Milliseconds() - pingptr->start < 500) { // still waiting for response continue; @@ -4128,7 +4495,7 @@ ping_t* CL_GetFreePing( void ) for (i=0; istart; + time = Sys_Milliseconds() - pingptr->start; if (time > oldest) { oldest = time; @@ -4148,29 +4515,45 @@ void CL_Ping_f( void ) { netadr_t to; ping_t* pingptr; char* server; + int argc; + netadrtype_t family = NA_UNSPEC; - if ( Cmd_Argc() != 2 ) { - Com_Printf( "usage: ping [server]\n"); - return; + argc = Cmd_Argc(); + + if ( argc != 2 && argc != 3 ) { + Com_Printf( "usage: ping [-4|-6] server\n"); + return; + } + + if(argc == 2) + server = Cmd_Argv(1); + else + { + if(!strcmp(Cmd_Argv(1), "-4")) + family = NA_IP; + else if(!strcmp(Cmd_Argv(1), "-6")) + family = NA_IP6; + else + Com_Printf( "warning: only -4 or -6 as address type understood.\n"); + + server = Cmd_Argv(2); } Com_Memset( &to, 0, sizeof(netadr_t) ); - server = Cmd_Argv(1); - - if ( !NET_StringToAdr( server, &to, NA_IP ) ) { + if ( !NET_StringToAdr( server, &to, family ) ) { return; } pingptr = CL_GetFreePing(); memcpy( &pingptr->adr, &to, sizeof (netadr_t) ); - pingptr->start = cls.realtime; + pingptr->start = Sys_Milliseconds(); pingptr->time = 0; CL_SetServerInfoByAddress(pingptr->adr, NULL, 0); - - NET_OutOfBandPrint( NS_CLIENT, to, "\x02getinfo" ); + + CL_NET_OutOfBandPrint( to, "\x02getinfo xxx" ); } /* @@ -4223,10 +4606,10 @@ void CL_Dialog_f( void ) { return; } - strcpy( title, Cmd_Argv( 1 ) ); - strcpy( cvar, Cmd_Argv( 2 ) ); - strcpy( command, Cmd_Argv( 3 ) ); - strcpy( cancelCommand, Cmd_Argv( 4 ) ); + Q_strncpyz( title, Cmd_Argv( 1 ), sizeof( title ) ); + Q_strncpyz( cvar, Cmd_Argv( 2 ), sizeof( cvar ) ); + Q_strncpyz( command, Cmd_Argv( 3 ), sizeof( command ) ); + Q_strncpyz( cancelCommand, Cmd_Argv( 4 ), sizeof( cancelCommand ) ); if( Cmd_Argc() > 5 ) { width = atoi( Cmd_Argv( 5 ) ); @@ -4240,17 +4623,17 @@ void CL_Dialog_f( void ) { } if( Cmd_Argc() > 7 ) { - strcpy( shader, Cmd_Argv( 7 ) ); + Q_strncpyz( shader, Cmd_Argv( 7 ), sizeof( shader ) ); } else { shader[ 0 ] = 0; } if( Cmd_Argc() > 8 ) { - strcpy( okshader, Cmd_Argv( 8 ) ); + Q_strncpyz( okshader, Cmd_Argv( 8 ), sizeof(okshader) ); } else { okshader[ 0 ] = 0; } if( Cmd_Argc() > 9 ) { - strcpy( cancelshader, Cmd_Argv( 9 ) ); + Q_strncpyz( cancelshader, Cmd_Argv( 9 ), sizeof(cancelshader) ); } else { cancelshader[ 0 ] = 0; } @@ -4264,7 +4647,10 @@ CL_ServerRestarted ================== */ void CL_ServerRestarted( void ) { - S_StopAllSounds( qfalse ); + //S_StopAllSounds2( qfalse ); + // Fixed in OPM + // Also stop the music + S_StopAllSounds2( qtrue ); UI_ServerLoaded(); UI_ClearState(); @@ -4294,16 +4680,11 @@ qboolean CL_UpdateVisiblePings_f(int source) { if (slots < MAX_PINGREQUESTS) { serverInfo_t *server = NULL; - max = (source == AS_GLOBAL) ? MAX_GLOBAL_SERVERS : MAX_OTHER_SERVERS; switch (source) { case AS_LOCAL : server = &cls.localServers[0]; max = cls.numlocalservers; break; - case AS_MPLAYER : - server = &cls.mplayerServers[0]; - max = cls.nummplayerservers; - break; case AS_GLOBAL : server = &cls.globalServers[0]; max = cls.numglobalservers; @@ -4312,6 +4693,8 @@ qboolean CL_UpdateVisiblePings_f(int source) { server = &cls.favoriteServers[0]; max = cls.numfavoriteservers; break; + default: + return qfalse; } for (i = 0; i < max; i++) { if (server[i].visible) { @@ -4338,9 +4721,9 @@ qboolean CL_UpdateVisiblePings_f(int source) { } } memcpy(&cl_pinglist[j].adr, &server[i].adr, sizeof(netadr_t)); - cl_pinglist[j].start = cls.realtime; + cl_pinglist[j].start = Sys_Milliseconds(); cl_pinglist[j].time = 0; - NET_OutOfBandPrint( NS_CLIENT, cl_pinglist[j].adr, "getinfo xxx" ); + CL_NET_OutOfBandPrint( cl_pinglist[j].adr, "getinfo xxx" ); slots++; } } @@ -4360,7 +4743,7 @@ qboolean CL_UpdateVisiblePings_f(int source) { } } } - } + } if (slots) { status = qtrue; @@ -4385,32 +4768,53 @@ CL_ServerStatus_f ================== */ void CL_ServerStatus_f(void) { - netadr_t to; + netadr_t to, *toptr = NULL; char *server; serverStatus_t *serverStatus; + int argc; + netadrtype_t family = NA_UNSPEC; - Com_Memset( &to, 0, sizeof(netadr_t) ); + argc = Cmd_Argc(); - if ( Cmd_Argc() != 2 ) { - if ( clc.state != CA_ACTIVE || clc.demoplaying ) { + if ( argc != 2 && argc != 3 ) + { + if (clc.state != CA_ACTIVE || clc.demoplaying) + { Com_Printf ("Not connected to a server.\n"); - Com_Printf( "Usage: serverstatus [server]\n"); + Com_Printf( "usage: serverstatus [-4|-6] server\n"); return; } - server = cls.servername; + + toptr = &clc.serverAddress; } - else { - server = Cmd_Argv(1); + + if(!toptr) + { + Com_Memset( &to, 0, sizeof(netadr_t) ); + + if(argc == 2) + server = Cmd_Argv(1); + else + { + if(!strcmp(Cmd_Argv(1), "-4")) + family = NA_IP; + else if(!strcmp(Cmd_Argv(1), "-6")) + family = NA_IP6; + else + Com_Printf( "warning: only -4 or -6 as address type understood.\n"); + + server = Cmd_Argv(2); + } + + toptr = &to; + if ( !NET_StringToAdr( server, toptr, family ) ) + return; } - if ( !NET_StringToAdr( server, &to, NA_IP ) ) { - return; - } + CL_NET_OutOfBandPrint( *toptr, "getstatus" ); - NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" ); - - serverStatus = CL_GetServerStatus( to ); - serverStatus->address = to; + serverStatus = CL_GetServerStatus( *toptr ); + serverStatus->address = *toptr; serverStatus->print = qtrue; serverStatus->pending = qtrue; } @@ -4476,7 +4880,7 @@ qboolean CL_CDKeyValidate( const char *key, const char *checksum ) { } } - sprintf(chs, "%02x", sum); + Com_sprintf(chs, sizeof(chs), "%02x", sum); if (checksum && !Q_stricmp(chs, checksum)) { return qtrue; @@ -4498,3 +4902,15 @@ void TIKI_CG_Command_ProcessFile(char* filename, qboolean quiet, dtiki_t* curTik Com_Printf("NO CGE \n"); } + +void CL_ApplyOriginalConfigTweaks() +{ + cvar_t* snaps = Cvar_Get("snaps", "", 0); + + // Those variables are not editable via UI so reset them + // snaps/maxpackets can also have wrong values due to them being changed + // via stufftext + + Cvar_Set("snaps", snaps->resetString); + Cvar_Set("cl_maxpackets", cl_maxpackets->resetString); +} diff --git a/code/client/cl_net_chan.cpp b/code/client/cl_net_chan.cpp index 1433c434..102d5524 100644 --- a/code/client/cl_net_chan.cpp +++ b/code/client/cl_net_chan.cpp @@ -132,7 +132,7 @@ CL_Netchan_TransmitNextFragment ================= */ void CL_Netchan_TransmitNextFragment( netchan_t *chan ) { - Netchan_TransmitNextFragment( chan ); + Netchan_TransmitNextFragment( chan, cl_netprofile->integer ? &cls.netprofile.inPackets : NULL ); } /* @@ -144,7 +144,7 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) { MSG_WriteByte( msg, clc_EOF ); CL_Netchan_Encode( msg ); - Netchan_Transmit( chan, msg->cursize, msg->data ); + Netchan_Transmit( chan, msg->cursize, msg->data, cl_netprofile->integer ? &cls.netprofile.inPackets : NULL ); } extern int oldsize; @@ -158,10 +158,30 @@ CL_Netchan_Process qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; - ret = Netchan_Process( chan, msg ); + ret = Netchan_Process( chan, msg, cl_netprofile->integer ? &cls.netprofile.outPackets : NULL ); if (!ret) return qfalse; CL_Netchan_Decode( msg ); newsize += msg->cursize; return qtrue; } + +/* +================= +CL_NET_OutOfBandPrint +================= +*/ +void CL_NET_OutOfBandPrint(netadr_t adr, const char* format, ...) { + va_list argptr; + char string[MAX_MSGLEN]; + + va_start(argptr, format); + Q_vsnprintf(string, sizeof(string), format, argptr); + va_end(argptr); + + NET_OutOfBandPrint(NS_CLIENT, adr, "%s", string); + + if (cl_netprofile->integer) { + NetProfileAddPacket(&cls.netprofile.inPackets, strlen(string), NETPROF_PACKET_MESSAGE); + } +} diff --git a/code/client/cl_parse.cpp b/code/client/cl_parse.cpp index 76a17cf4..68a9cc7e 100644 --- a/code/client/cl_parse.cpp +++ b/code/client/cl_parse.cpp @@ -223,13 +223,13 @@ qboolean CL_UnpackNonPVSClient(int* packed, radarUnpacked_t* unpacked) { range = 0; } - unpacked->x = x * range / 63.f; - unpacked->y = y * range / 63.f; + unpacked->x = x * range / (MAX_CLIENTS - 1); + unpacked->y = y * range / (MAX_CLIENTS - 1); if (!bValid) { - unpacked->x = x * range / 63.f * 1024; - unpacked->y = y * range / 63.f * 1024; + unpacked->x = x * range / (MAX_CLIENTS - 1) * 1024.0; + unpacked->y = y * range / (MAX_CLIENTS - 1) * 1024.0; } unpacked->yaw = yaw * 11.25f; @@ -429,12 +429,24 @@ void CL_SystemInfoChanged( void ) { // in some cases, outdated cp commands might get sent with this news serverId cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) ); +#ifdef USE_VOIP +#ifdef LEGACY_PROTOCOL + if(clc.compat) + clc.voipEnabled = qfalse; + else +#endif + { + s = Info_ValueForKey( systemInfo, "sv_voipProtocol" ); + clc.voipEnabled = !Q_stricmp(s, "opus"); + } +#endif + // don't set any vars when playing a demo if ( clc.demoplaying ) { return; } - s = Info_ValueForKey( systemInfo, "sv_cheats" ); + s = Info_ValueForKey( systemInfo, "cheats" ); cl_connectedToCheatServer = atoi( s ); if ( !cl_connectedToCheatServer ) { Cvar_SetCheatState(); @@ -556,6 +568,7 @@ void CL_ParseGamestate( msg_t *msg ) { csNum = CPT_NormalizeConfigstring(i); if (csNum < 0 || csNum >= MAX_CONFIGSTRINGS) { Com_Error(ERR_DROP, "configstring > MAX_CONFIGSTRINGS"); + return; } s = MSG_ReadScrambledBigString(msg); len = strlen(s); @@ -576,8 +589,7 @@ void CL_ParseGamestate( msg_t *msg ) { //Com_Memset (&nullstate, 0, sizeof(nullstate)); MSG_GetNullEntityState(&nullstate); es = &cl.entityBaselines[ newnum ]; - // FIXME: frametime - MSG_ReadDeltaEntity( msg, &nullstate, es, newnum, 0.0); + MSG_ReadDeltaEntity( msg, &nullstate, es, newnum, cls.serverFrameTime); } else { Com_Error( ERR_DROP, "CL_ParseGamestate: bad command byte %i", cmd ); } @@ -594,16 +606,25 @@ void CL_ParseGamestate( msg_t *msg ) { // stop recording now so the demo won't have an unnecessary level load at the end. if(cl_autoRecordDemo->integer && clc.demorecording) CL_StopRecord_f(); - - // reinitialize the filesystem if the game directory has changed - FS_ConditionalRestart( clc.checksumFeed, qfalse ); + + if (clc.state == CA_CONNECTED && !Cvar_Get("sv_paks", "", 0)->string[0]) { + // Added in 2.30 + FS_Restart(clc.checksumFeed); + } else { + // reinitialize the filesystem if the game directory has changed + FS_ConditionalRestart(clc.checksumFeed, qfalse); + } clc.state = CA_LOADING; if (!com_sv_running->integer) { const char *info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO]; - UI_ClearState(); - UI_BeginLoad(Info_ValueForKey(info, "mapname")); + const char *mapname = Info_ValueForKey(info, "mapname"); + // Added in 2.0 + Cvar_Set("mapname", mapname); + + UI_ClearState(); + UI_BeginLoad(mapname); } // This used to call CL_StartHunkUsers, but now we enter the download state before loading the @@ -784,6 +805,178 @@ void CL_ParseDownload ( msg_t *msg ) { } } +#ifdef USE_VOIP +static +qboolean CL_ShouldIgnoreVoipSender(int sender) +{ + if (!cl_voip->integer) + return qtrue; // VoIP is disabled. + else if ((sender == clc.clientNum) && (!clc.demoplaying)) + return qtrue; // ignore own voice (unless playing back a demo). + else if (clc.voipMuteAll) + return qtrue; // all channels are muted with extreme prejudice. + else if (clc.voipIgnore[sender]) + return qtrue; // just ignoring this guy. + else if (clc.voipGain[sender] == 0.0f) + return qtrue; // too quiet to play. + + return qfalse; +} + +/* +===================== +CL_PlayVoip + +Play raw data +===================== +*/ + +static void CL_PlayVoip(int sender, int samplecnt, const byte *data, int flags) +{ + if(flags & VOIP_DIRECT) + { + S_RawSamples(sender + 1, samplecnt, 48000, 2, 1, + data, clc.voipGain[sender], -1); + } + + if(flags & VOIP_SPATIAL) + { + S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, 48000, 2, 1, + data, 1.0f, sender); + } +} + +/* +===================== +CL_ParseVoip + +A VoIP message has been received from the server +===================== +*/ +static +void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) { + static short decoded[VOIP_MAX_PACKET_SAMPLES*4]; // !!! FIXME: don't hard code + + const int sender = MSG_ReadShort(msg); + const int generation = MSG_ReadByte(msg); + const int sequence = MSG_ReadLong(msg); + const int frames = MSG_ReadByte(msg); + const int packetsize = MSG_ReadShort(msg); + const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT); + unsigned char encoded[4000]; + int numSamples; + int seqdiff; + int written = 0; + int i; + + Com_DPrintf("VoIP: %d-byte packet from client %d\n", packetsize, sender); + + if (sender < 0) + return; // short/invalid packet, bail. + else if (generation < 0) + return; // short/invalid packet, bail. + else if (sequence < 0) + return; // short/invalid packet, bail. + else if (frames < 0) + return; // short/invalid packet, bail. + else if (packetsize < 0) + return; // short/invalid packet, bail. + + if (packetsize > sizeof (encoded)) { // overlarge packet? + int bytesleft = packetsize; + while (bytesleft) { + int br = bytesleft; + if (br > sizeof (encoded)) + br = sizeof (encoded); + MSG_ReadData(msg, encoded, br); + bytesleft -= br; + } + return; // overlarge packet, bail. + } + + MSG_ReadData(msg, encoded, packetsize); + + if (ignoreData) { + return; // just ignore legacy speex voip data + } else if (!clc.voipCodecInitialized) { + return; // can't handle VoIP without libopus! + } else if (sender >= MAX_CLIENTS) { + return; // bogus sender. + } else if (CL_ShouldIgnoreVoipSender(sender)) { + return; // Channel is muted, bail. + } + + // !!! FIXME: make sure data is narrowband? Does decoder handle this? + + Com_DPrintf("VoIP: packet accepted!\n"); + + seqdiff = sequence - clc.voipIncomingSequence[sender]; + + // This is a new "generation" ... a new recording started, reset the bits. + if (generation != clc.voipIncomingGeneration[sender]) { + Com_DPrintf("VoIP: new generation %d!\n", generation); + opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE); + clc.voipIncomingGeneration[sender] = generation; + seqdiff = 0; + } else if (seqdiff < 0) { // we're ahead of the sequence?! + // This shouldn't happen unless the packet is corrupted or something. + Com_DPrintf("VoIP: misordered sequence! %d < %d!\n", + sequence, clc.voipIncomingSequence[sender]); + // reset the decoder just in case. + opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE); + seqdiff = 0; + } else if (seqdiff * VOIP_MAX_PACKET_SAMPLES*2 >= sizeof (decoded)) { // dropped more than we can handle? + // just start over. + Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n", + seqdiff, sender); + opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE); + seqdiff = 0; + } + + if (seqdiff != 0) { + Com_DPrintf("VoIP: Dropped %d frames from client #%d\n", + seqdiff, sender); + // tell opus that we're missing frames... + for (i = 0; i < seqdiff; i++) { + assert((written + VOIP_MAX_PACKET_SAMPLES) * 2 < sizeof (decoded)); + numSamples = opus_decode(clc.opusDecoder[sender], NULL, 0, decoded + written, VOIP_MAX_PACKET_SAMPLES, 0); + if ( numSamples <= 0 ) { + Com_DPrintf("VoIP: Error decoding frame %d from client #%d\n", i, sender); + continue; + } + written += numSamples; + } + } + + numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, ARRAY_LEN(decoded) - written, 0); + + if ( numSamples <= 0 ) { + Com_DPrintf("VoIP: Error decoding voip data from client #%d\n", sender); + numSamples = 0; + } + + #if 0 + static FILE *encio = NULL; + if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb"); + if (encio != NULL) { fwrite(encoded, packetsize, 1, encio); fflush(encio); } + static FILE *decio = NULL; + if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb"); + if (decio != NULL) { fwrite(decoded+written, numSamples*2, 1, decio); fflush(decio); } + #endif + + written += numSamples; + + Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n", + written * 2, written, frames); + + if(written > 0) + CL_PlayVoip(sender, written, (const byte *) decoded, flags); + + clc.voipIncomingSequence[sender] = sequence + frames; +} +#endif + + /* ===================== CL_ParseCommandString @@ -932,8 +1125,16 @@ void CL_ParseServerMessage( msg_t *msg ) { } CL_ParseCGMessage( msg ); break; + case svc_voipSpeex: +#ifdef USE_VOIP + CL_ParseVoip( msg, qtrue ); +#endif + break; + case svc_voipOpus: +#ifdef USE_VOIP + CL_ParseVoip( msg, !clc.voipEnabled ); +#endif + break; } } } - - diff --git a/code/client/cl_scrn.cpp b/code/client/cl_scrn.cpp index 0f97ef05..a14769a1 100644 --- a/code/client/cl_scrn.cpp +++ b/code/client/cl_scrn.cpp @@ -343,7 +343,7 @@ void SCR_DrawDemoRecording( void ) { } pos = FS_FTell( clc.demofile ); - sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); + Com_sprintf( string, sizeof( string ), "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue, qfalse ); } @@ -520,16 +520,18 @@ text to the screen. ================== */ void SCR_UpdateScreen( void ) { - static int recursive; + static qboolean screen_recursive; if ( !scr_initialized ) { return; // not initialized yet } - if ( ++recursive > 2 ) { - Com_Error( ERR_FATAL, "SCR_UpdateScreen: recursively called" ); + if (screen_recursive) { + // already called + return; } - recursive = 1; + + screen_recursive = qtrue; CL_StartHunkUsers(qfalse); SCR_SimpleUpdateScreen(); @@ -553,6 +555,6 @@ void SCR_UpdateScreen( void ) { } } - recursive = 0; + screen_recursive = qfalse; } diff --git a/code/client/cl_ui.cpp b/code/client/cl_ui.cpp index c061dca6..e8cef7f9 100644 --- a/code/client/cl_ui.cpp +++ b/code/client/cl_ui.cpp @@ -1,21 +1,21 @@ /* =========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2024 the OpenMoHAA team -This file is part of Quake III Arena source code. +This file is part of OpenMoHAA source code. -Quake III Arena source code is free software; you can redistribute it +OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. -Quake III Arena source code is distributed in the hope that it will be +OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software +along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ @@ -29,159 +29,167 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/q_version.h" #include "cl_ui.h" +#include "cl_uigamespy.h" #include typedef struct { - float fadetime; - float starttime; - float endtime; - float alpha_start; - float alpha_end; - UIReggedMaterial *material; + float fadetime; + float starttime; + float endtime; + float alpha_start; + float alpha_end; + UIReggedMaterial *material; } intro_stage_t; -static qboolean ui_hud; -static class UIFont *globalFont; -static UIFloatingConsole *fakk_console; +static qboolean ui_hud; +static class UIFont *globalFont; +static UIFloatingConsole *fakk_console; static UIFloatingDMConsole *dm_console; -static UIFloatingConsole *developer_console; -static FakkMiniconsole *mini_console; -static UIGMBox *gmbox; -static UIDMBox *dmbox; -static View3D *view3d; -static Menu *mainmenu; -static Menu *hud_weapons; -static Menu *hud_items; -static Menu *hud_health; -static Menu *hud_ammo; -static Menu *hud_compass; -static Menu *hud_boss; -static Menu *crosshairhud; -static Menu *missionLog; -qboolean server_loading; -static qboolean server_loading_waiting; -static str *s_intermediateconsole; -static int ui_lastWeapHudState_Owned; -static int ui_lastWeapHudState_Equipped = 0xFFFF; -static int ui_weapHudTime; -static int ui_itemHudTime; -Menu *ui_pLoadingMenu; -static Menu *ui_pConnectingMenu; +static UIFloatingConsole *developer_console; +static FakkMiniconsole *mini_console; +static UIGMBox *gmbox; +static UIDMBox *dmbox; +static View3D *view3d; +static Menu *mainmenu; +static Menu *hud_weapons; +static Menu *hud_items; +static Menu *hud_health; +static Menu *hud_ammo; +static Menu *hud_compass; +static Menu *hud_boss; +static Menu *crosshairhud; +static Menu *missionLog; +qboolean server_loading; +static qboolean server_loading_waiting; +static str *s_intermediateconsole; +static int ui_lastWeapHudState_Owned; +static int ui_lastWeapHudState_Equipped = 0xFFFF; +static int ui_weapHudTime; +static int ui_itemHudTime; +Menu *ui_pLoadingMenu; +static Menu *ui_pConnectingMenu; static_media_t ui_static_materials; -cvar_t *cl_greenfps; -cvar_t *ui_GunneryEvaluation; -cvar_t *ui_GroinShots; -cvar_t *ui_RightArmShots; -cvar_t *ui_LeftArmShots; -cvar_t *ui_RightLegShots; -cvar_t *ui_LeftLegShots; -cvar_t *ui_TorsoShots; -cvar_t *ui_HeadShots; -cvar_t *ui_NumEnemysKilled; -cvar_t *ui_NumObjectsDestroyed; -cvar_t *ui_NumHitsTaken; -cvar_t *ui_PreferredWeapon; -cvar_t *ui_Accuracy; -cvar_t *ui_NumObjectives; -cvar_t *ui_NumComplete; -cvar_t *ui_NumHits; -cvar_t *ui_NumShotsFired; -cvar_t *ui_gotmedal; -cvar_t *ui_success; -cvar_t *ui_failed; -cvar_t *ui_returnmenu; -cvar_t *ui_skip_eamovie; -cvar_t *ui_skip_titlescreen; -cvar_t *ui_skip_legalscreen; -cvar_t *ui_titlescreen_fadein; -cvar_t *ui_titlescreen_fadeout; -cvar_t *ui_titlescreen_stay; -cvar_t *ui_legalscreen_fadein; -cvar_t *ui_legalscreen_fadeout; -cvar_t *ui_legalscreen_stay; -cvar_t *ui_drawcoords; -cvar_t *ui_minicon; -cvar_t *ui_gmbox; -cvar_t *ui_consoleposition; -cvar_t *ui_inventoryfile; -cvar_t *ui_console; -cvar_t *ui_newvidmode; -cvar_t *ui_crosshair; -cvar_t *ui_compass; -cvar_t *ui_weaponsbar; -cvar_t *ui_weaponsbartime; -cvar_t *ui_itemsbar; -cvar_t *ui_health_start; -cvar_t *ui_health_end; -cvar_t *ui_gmboxspam; -cvar_t *ui_debugload; -cvar_t *sound_overlay; -cvar_t *ui_compass_scale; +cvar_t *cl_greenfps; +cvar_t *ui_GunneryEvaluation; +cvar_t *ui_GroinShots; +cvar_t *ui_RightArmShots; +cvar_t *ui_LeftArmShots; +cvar_t *ui_RightLegShots; +cvar_t *ui_LeftLegShots; +cvar_t *ui_TorsoShots; +cvar_t *ui_HeadShots; +cvar_t *ui_NumEnemysKilled; +cvar_t *ui_NumObjectsDestroyed; +cvar_t *ui_NumHitsTaken; +cvar_t *ui_PreferredWeapon; +cvar_t *ui_Accuracy; +cvar_t *ui_NumObjectives; +cvar_t *ui_NumComplete; +cvar_t *ui_NumHits; +cvar_t *ui_NumShotsFired; +cvar_t *ui_gotmedal; +cvar_t *ui_success; +cvar_t *ui_failed; +cvar_t *ui_returnmenu; +cvar_t *ui_skip_eamovie; +cvar_t *ui_skip_titlescreen; +cvar_t *ui_skip_legalscreen; +cvar_t *ui_titlescreen_fadein; +cvar_t *ui_titlescreen_fadeout; +cvar_t *ui_titlescreen_stay; +cvar_t *ui_legalscreen_fadein; +cvar_t *ui_legalscreen_fadeout; +cvar_t *ui_legalscreen_stay; +cvar_t *ui_drawcoords; +cvar_t *ui_minicon; +cvar_t *ui_gmbox; +cvar_t *ui_consoleposition; +cvar_t *ui_inventoryfile; +cvar_t *ui_console; +cvar_t *ui_newvidmode; +cvar_t *ui_crosshair; +cvar_t *ui_compass; +cvar_t *ui_weaponsbar; +cvar_t *ui_weaponsbartime; +cvar_t *ui_itemsbar; +cvar_t *ui_health_start; +cvar_t *ui_health_end; +cvar_t *ui_gmboxspam; +cvar_t *ui_debugload; +cvar_t *sound_overlay; +cvar_t *ui_compass_scale; static intro_stage_t intro_stage; -static char server_mapname[ 64 ]; -static UIListCtrl *scoreboardlist; -static Menu *scoreboard_menu; -static float scoreboard_x; -static float scoreboard_y; -static float scoreboard_w; -static float scoreboard_h; -static qboolean scoreboard_header; -cvar_t *cl_playintro; -cvar_t *cl_movieaudio; -static unsigned int startCountLow; -static unsigned int startCountHigh; -static unsigned int loadCountLow; -static unsigned int loadCountHigh; -static unsigned int loadCount; -static unsigned int lastTime; -static unsigned int loadNumber; -static unsigned int totalLoadTime; -static unsigned int currentLoadTime; -unsigned char UIListCtrlItem[ 8 ]; +static char server_mapname[64]; +static UIListCtrl *scoreboardlist; +static Menu *scoreboard_menu; +static float scoreboard_x; +static float scoreboard_y; +static float scoreboard_w; +static float scoreboard_h; +static qboolean scoreboard_header; +cvar_t *cl_playintro; +cvar_t *cl_movieaudio; +static unsigned int startCountLow; +static unsigned int startCountHigh; +static unsigned int loadCountLow; +static unsigned int loadCountHigh; +static unsigned int loadCount; +static unsigned int lastTime = 0; +static unsigned int updateTime = 0; +static unsigned int loadNumber; +static unsigned int totalLoadTime; +static unsigned int currentLoadTime; +unsigned char UIListCtrlItem[8]; -inventory_t client_inv; -bind_t client_bind; -static str scoreboard_menuname; -static str ui_sCurrentLoadingMenu; +static const float maxWidthRes = 1920; +static const float maxHeightRes = 1080; + +inventory_t client_inv; +bind_t client_bind; +static str scoreboard_menuname; +static str ui_sCurrentLoadingMenu; static Container hudList; +const UColor UWhiteChatMessageColor(0.75, 0.75, 0.75); +const UColor URedChatMessageColor(1.0, 0.25, 0.25); +const UColor UGreenChatMessageColor(0.0, 1.0, 0.25, 1.0); + void UI_MultiplayerMenuWidgetsUpdate(void); +void UI_MultiplayerMainMenuWidgetsUpdate(void); void UI_MainMenuWidgetsUpdate(void); static UIRect2D getDefaultGMBoxRectangle(void); static UIRect2D getDefaultDMBoxRectangle(void); -class ConsoleHider : public Listener { +class ConsoleHider : public Listener +{ public: - CLASS_PROTOTYPE( ConsoleHider ); + CLASS_PROTOTYPE(ConsoleHider); - void HideConsole( Event *ev ); - void DeadConsole( Event *ev ); + void HideConsole(Event *ev); + void DeadConsole(Event *ev); }; - -CLASS_DECLARATION( Listener, ConsoleHider, NULL ) -{ - { &UIFloatingWindow::W_ClosePressed, &ConsoleHider::HideConsole }, - { &W_Destroyed, &ConsoleHider::DeadConsole }, - { NULL, NULL } +CLASS_DECLARATION(Listener, ConsoleHider, NULL) { + {&UIFloatingWindow::W_ClosePressed, &ConsoleHider::HideConsole}, + {&W_Destroyed, &ConsoleHider::DeadConsole}, + {NULL, NULL } }; -void ConsoleHider::HideConsole( Event *ev ) +void ConsoleHider::HideConsole(Event *ev) { - UI_CloseConsole(); + UI_CloseConsole(); } -void ConsoleHider::DeadConsole( Event *ev ) +void ConsoleHider::DeadConsole(Event *ev) { - if( fakk_console && !fakk_console->IsDying() ) - { - delete fakk_console; - fakk_console = NULL; - } + if (fakk_console && !fakk_console->IsDying()) { + delete fakk_console; + fakk_console = NULL; + } } static ConsoleHider s_consolehider; @@ -191,8 +199,9 @@ static ConsoleHider s_consolehider; ConsoleCommandHandler ==================== */ -static void ConsoleCommandHandler( const char *txt ) { - Cbuf_AddText( txt ); +static void ConsoleCommandHandler(const char *txt) +{ + Cbuf_AddText(txt); } /* @@ -200,61 +209,58 @@ static void ConsoleCommandHandler( const char *txt ) { getDefaultConsoleRectangle ==================== */ -static UIRect2D getDefaultConsoleRectangle( void ) { - float f[ 4 ]; - int i; - UIRect2D rect; +static UIRect2D getDefaultConsoleRectangle(void) +{ + float f[4]; + int i; + UIRect2D rect; - if( sscanf( ui_consoleposition->string, "%f %f %f %f", &f[ 0 ], &f[ 1 ], &f[ 2 ], &f[ 3 ] ) == 4 ) - { - for( i = 0; i < 4; i++ ) { - f[ i ] = floor( f[ i ] ); - } + if (sscanf(ui_consoleposition->string, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]) == 4) { + for (i = 0; i < 4; i++) { + f[i] = floor(f[i]); + } - rect.pos.x = f[ 0 ] - cls.glconfig.vidWidth; - rect.pos.y = f[ 1 ] - cls.glconfig.vidHeight; - rect.size.width = f[ 2 ] + 50.0; - rect.size.height = f[ 3 ] + 50.0; - } - else - { - rect.pos.x = 25.0; - rect.pos.y = 25.0; - rect.size.width = ( cls.glconfig.vidWidth - 50 ); - rect.size.height = ( cls.glconfig.vidHeight / 2 ); - } + rect.pos.x = f[0] - uid.vidWidth; + rect.pos.y = f[1] - uid.vidHeight; + rect.size.width = f[2] + 50.0; + rect.size.height = f[3] + 50.0; + } else { + rect.pos.x = 25.0; + rect.pos.y = 25.0; + rect.size.width = (uid.vidWidth - 50); + rect.size.height = (uid.vidHeight / 2); + } - return rect; + return rect; } -class DMConsoleHider : public Listener { +class DMConsoleHider : public Listener +{ public: - CLASS_PROTOTYPE( DMConsoleHider ); + CLASS_PROTOTYPE(DMConsoleHider); - void HideDMConsole( Event *ev ); - void DeadDMConsole( Event *ev ); + void HideDMConsole(Event *ev); + void DeadDMConsole(Event *ev); }; -CLASS_DECLARATION( Listener, DMConsoleHider, NULL ) -{ - { &UIFloatingWindow::W_ClosePressed, &DMConsoleHider::HideDMConsole }, - { &W_Deactivated, &DMConsoleHider::HideDMConsole }, - { &W_Destroyed, &DMConsoleHider::DeadDMConsole }, - { NULL, NULL } +CLASS_DECLARATION(Listener, DMConsoleHider, NULL) { + {&UIFloatingWindow::W_ClosePressed, &DMConsoleHider::HideDMConsole}, + {&W_Deactivated, &DMConsoleHider::HideDMConsole}, + {&W_Destroyed, &DMConsoleHider::DeadDMConsole}, + {NULL, NULL } }; -void DMConsoleHider::HideDMConsole( Event *ev ) +void DMConsoleHider::HideDMConsole(Event *ev) { - UI_CloseDMConsole(); + UI_CloseDMConsole(); } -void DMConsoleHider::DeadDMConsole( Event *ev ) +void DMConsoleHider::DeadDMConsole(Event *ev) { - if( dm_console && !dm_console->IsDying() ) - { - delete dm_console; - dm_console = NULL; - } + if (dm_console && !dm_console->IsDying()) { + delete dm_console; + dm_console = NULL; + } } static DMConsoleHider s_dmconsolehider; @@ -264,13 +270,14 @@ static DMConsoleHider s_dmconsolehider; GetClientState ==================== */ -static void GetClientState( uiClientState_t *state ) { - state->connectPacketCount = clc.connectPacketCount; - state->connState = clc.state; - Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) ); - Q_strncpyz( state->updateInfoString, cls.updateInfoString, sizeof( state->updateInfoString ) ); - Q_strncpyz( state->messageString, clc.serverMessage, sizeof( state->messageString ) ); - state->clientNum = cl.snap.ps.clientNum; +static void GetClientState(uiClientState_t *state) +{ + state->connectPacketCount = clc.connectPacketCount; + state->connState = clc.state; + Q_strncpyz(state->servername, clc.servername, sizeof(state->servername)); + Q_strncpyz(state->updateInfoString, cls.updateInfoString, sizeof(state->updateInfoString)); + Q_strncpyz(state->messageString, clc.serverMessage, sizeof(state->messageString)); + state->clientNum = cl.snap.ps.clientNum; } /* @@ -278,26 +285,27 @@ static void GetClientState( uiClientState_t *state ) { LAN_LoadCachedServers ==================== */ -void LAN_LoadCachedServers( void ) { - int size; - fileHandle_t fileIn; - cls.numglobalservers = cls.nummplayerservers = cls.numfavoriteservers = 0; - cls.numGlobalServerAddresses = 0; - if (FS_SV_FOpenFileRead("servercache.dat", &fileIn)) { - FS_Read(&cls.numglobalservers, sizeof(int), fileIn); - FS_Read(&cls.nummplayerservers, sizeof(int), fileIn); - FS_Read(&cls.numfavoriteservers, sizeof(int), fileIn); - FS_Read(&size, sizeof(int), fileIn); - if (size == sizeof(cls.globalServers) + sizeof(cls.favoriteServers) + sizeof(cls.mplayerServers)) { - FS_Read(&cls.globalServers, sizeof(cls.globalServers), fileIn); - FS_Read(&cls.mplayerServers, sizeof(cls.mplayerServers), fileIn); - FS_Read(&cls.favoriteServers, sizeof(cls.favoriteServers), fileIn); - } else { - cls.numglobalservers = cls.nummplayerservers = cls.numfavoriteservers = 0; - cls.numGlobalServerAddresses = 0; - } - FS_FCloseFile(fileIn); - } +void LAN_LoadCachedServers(void) +{ + int size; + fileHandle_t fileIn; + cls.numglobalservers = cls.nummplayerservers = cls.numfavoriteservers = 0; + cls.numGlobalServerAddresses = 0; + if (FS_SV_FOpenFileRead("servercache.dat", &fileIn)) { + FS_Read(&cls.numglobalservers, sizeof(int), fileIn); + FS_Read(&cls.nummplayerservers, sizeof(int), fileIn); + FS_Read(&cls.numfavoriteservers, sizeof(int), fileIn); + FS_Read(&size, sizeof(int), fileIn); + if (size == sizeof(cls.globalServers) + sizeof(cls.favoriteServers) + sizeof(cls.mplayerServers)) { + FS_Read(&cls.globalServers, sizeof(cls.globalServers), fileIn); + FS_Read(&cls.mplayerServers, sizeof(cls.mplayerServers), fileIn); + FS_Read(&cls.favoriteServers, sizeof(cls.favoriteServers), fileIn); + } else { + cls.numglobalservers = cls.nummplayerservers = cls.numfavoriteservers = 0; + cls.numGlobalServerAddresses = 0; + } + FS_FCloseFile(fileIn); + } } /* @@ -305,54 +313,55 @@ void LAN_LoadCachedServers( void ) { LAN_SaveServersToCache ==================== */ -void LAN_SaveServersToCache( void ) { - int size; - fileHandle_t fileOut = FS_SV_FOpenFileWrite("servercache.dat"); - FS_Write(&cls.numglobalservers, sizeof(int), fileOut); - FS_Write(&cls.nummplayerservers, sizeof(int), fileOut); - FS_Write(&cls.numfavoriteservers, sizeof(int), fileOut); - size = sizeof(cls.globalServers) + sizeof(cls.favoriteServers) + sizeof(cls.mplayerServers); - FS_Write(&size, sizeof(int), fileOut); - FS_Write(&cls.globalServers, sizeof(cls.globalServers), fileOut); - FS_Write(&cls.mplayerServers, sizeof(cls.mplayerServers), fileOut); - FS_Write(&cls.favoriteServers, sizeof(cls.favoriteServers), fileOut); - FS_FCloseFile(fileOut); +void LAN_SaveServersToCache(void) +{ + int size; + fileHandle_t fileOut = FS_SV_FOpenFileWrite("servercache.dat"); + FS_Write(&cls.numglobalservers, sizeof(int), fileOut); + FS_Write(&cls.nummplayerservers, sizeof(int), fileOut); + FS_Write(&cls.numfavoriteservers, sizeof(int), fileOut); + size = sizeof(cls.globalServers) + sizeof(cls.favoriteServers) + sizeof(cls.mplayerServers); + FS_Write(&size, sizeof(int), fileOut); + FS_Write(&cls.globalServers, sizeof(cls.globalServers), fileOut); + FS_Write(&cls.mplayerServers, sizeof(cls.mplayerServers), fileOut); + FS_Write(&cls.favoriteServers, sizeof(cls.favoriteServers), fileOut); + FS_FCloseFile(fileOut); } - /* ==================== LAN_ResetPings ==================== */ -static void LAN_ResetPings(int source) { - int count,i; - serverInfo_t *servers = NULL; - count = 0; +static void LAN_ResetPings(int source) +{ + int count, i; + serverInfo_t *servers = NULL; + count = 0; - switch (source) { - case AS_LOCAL : - servers = &cls.localServers[0]; - count = MAX_OTHER_SERVERS; - break; - case AS_MPLAYER : - servers = &cls.mplayerServers[0]; - count = MAX_OTHER_SERVERS; - break; - case AS_GLOBAL : - servers = &cls.globalServers[0]; - count = MAX_GLOBAL_SERVERS; - break; - case AS_FAVORITES : - servers = &cls.favoriteServers[0]; - count = MAX_OTHER_SERVERS; - break; - } - if (servers) { - for (i = 0; i < count; i++) { - servers[i].ping = -1; - } - } + switch (source) { + case AS_LOCAL: + servers = &cls.localServers[0]; + count = MAX_OTHER_SERVERS; + break; + case AS_MPLAYER: + servers = &cls.mplayerServers[0]; + count = MAX_OTHER_SERVERS; + break; + case AS_GLOBAL: + servers = &cls.globalServers[0]; + count = MAX_GLOBAL_SERVERS; + break; + case AS_FAVORITES: + servers = &cls.favoriteServers[0]; + count = MAX_OTHER_SERVERS; + break; + } + if (servers) { + for (i = 0; i < count; i++) { + servers[i].ping = -1; + } + } } /* @@ -360,49 +369,50 @@ static void LAN_ResetPings(int source) { LAN_AddServer ==================== */ -static int LAN_AddServer(int source, const char *name, const char *address) { - int max, *count, i; - netadr_t adr; - serverInfo_t *servers = NULL; - max = MAX_OTHER_SERVERS; - count = NULL; +static int LAN_AddServer(int source, const char *name, const char *address) +{ + int max, *count, i; + netadr_t adr; + serverInfo_t *servers = NULL; + max = MAX_OTHER_SERVERS; + count = NULL; - switch (source) { - case AS_LOCAL : - count = &cls.numlocalservers; - servers = &cls.localServers[0]; - break; - case AS_MPLAYER : - count = &cls.nummplayerservers; - servers = &cls.mplayerServers[0]; - break; - case AS_GLOBAL : - max = MAX_GLOBAL_SERVERS; - count = &cls.numglobalservers; - servers = &cls.globalServers[0]; - break; - case AS_FAVORITES : - count = &cls.numfavoriteservers; - servers = &cls.favoriteServers[0]; - break; - } - if (servers && *count < max) { - NET_StringToAdr( address, &adr, NA_IP ); - for ( i = 0; i < *count; i++ ) { - if (NET_CompareAdr(servers[i].adr, adr)) { - break; - } - } - if (i >= *count) { - servers[*count].adr = adr; - Q_strncpyz(servers[*count].hostName, name, sizeof(servers[*count].hostName)); - servers[*count].visible = qtrue; - (*count)++; - return 1; - } - return 0; - } - return -1; + switch (source) { + case AS_LOCAL: + count = &cls.numlocalservers; + servers = &cls.localServers[0]; + break; + case AS_MPLAYER: + count = &cls.nummplayerservers; + servers = &cls.mplayerServers[0]; + break; + case AS_GLOBAL: + max = MAX_GLOBAL_SERVERS; + count = &cls.numglobalservers; + servers = &cls.globalServers[0]; + break; + case AS_FAVORITES: + count = &cls.numfavoriteservers; + servers = &cls.favoriteServers[0]; + break; + } + if (servers && *count < max) { + NET_StringToAdr(address, &adr, NA_IP); + for (i = 0; i < *count; i++) { + if (NET_CompareAdr(servers[i].adr, adr)) { + break; + } + } + if (i >= *count) { + servers[*count].adr = adr; + Q_strncpyz(servers[*count].hostName, name, sizeof(servers[*count].hostName)); + servers[*count].visible = qtrue; + (*count)++; + return 1; + } + return 0; + } + return -1; } /* @@ -410,67 +420,68 @@ static int LAN_AddServer(int source, const char *name, const char *address) { LAN_RemoveServer ==================== */ -static void LAN_RemoveServer(int source, const char *addr) { - int *count, i; - serverInfo_t *servers = NULL; - count = NULL; - switch (source) { - case AS_LOCAL : - count = &cls.numlocalservers; - servers = &cls.localServers[0]; - break; - case AS_MPLAYER : - count = &cls.nummplayerservers; - servers = &cls.mplayerServers[0]; - break; - case AS_GLOBAL : - count = &cls.numglobalservers; - servers = &cls.globalServers[0]; - break; - case AS_FAVORITES : - count = &cls.numfavoriteservers; - servers = &cls.favoriteServers[0]; - break; - } - if (servers) { - netadr_t comp; - NET_StringToAdr( addr, &comp, NA_IP ); - for (i = 0; i < *count; i++) { - if (NET_CompareAdr( comp, servers[i].adr)) { - int j = i; - while (j < *count - 1) { - Com_Memcpy(&servers[j], &servers[j+1], sizeof(servers[j])); - j++; - } - (*count)--; - break; - } - } - } +static void LAN_RemoveServer(int source, const char *addr) +{ + int *count, i; + serverInfo_t *servers = NULL; + count = NULL; + switch (source) { + case AS_LOCAL: + count = &cls.numlocalservers; + servers = &cls.localServers[0]; + break; + case AS_MPLAYER: + count = &cls.nummplayerservers; + servers = &cls.mplayerServers[0]; + break; + case AS_GLOBAL: + count = &cls.numglobalservers; + servers = &cls.globalServers[0]; + break; + case AS_FAVORITES: + count = &cls.numfavoriteservers; + servers = &cls.favoriteServers[0]; + break; + } + if (servers) { + netadr_t comp; + NET_StringToAdr(addr, &comp, NA_IP); + for (i = 0; i < *count; i++) { + if (NET_CompareAdr(comp, servers[i].adr)) { + int j = i; + while (j < *count - 1) { + Com_Memcpy(&servers[j], &servers[j + 1], sizeof(servers[j])); + j++; + } + (*count)--; + break; + } + } + } } - /* ==================== LAN_GetServerCount ==================== */ -static int LAN_GetServerCount( int source ) { - switch (source) { - case AS_LOCAL : - return cls.numlocalservers; - break; - case AS_MPLAYER : - return cls.nummplayerservers; - break; - case AS_GLOBAL : - return cls.numglobalservers; - break; - case AS_FAVORITES : - return cls.numfavoriteservers; - break; - } - return 0; +static int LAN_GetServerCount(int source) +{ + switch (source) { + case AS_LOCAL: + return cls.numlocalservers; + break; + case AS_MPLAYER: + return cls.nummplayerservers; + break; + case AS_GLOBAL: + return cls.numglobalservers; + break; + case AS_FAVORITES: + return cls.numfavoriteservers; + break; + } + return 0; } /* @@ -478,34 +489,35 @@ static int LAN_GetServerCount( int source ) { LAN_GetLocalServerAddressString ==================== */ -static void LAN_GetServerAddressString( int source, int n, char *buf, int buflen ) { - switch (source) { - case AS_LOCAL : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - Q_strncpyz(buf, NET_AdrToString( cls.localServers[n].adr) , buflen ); - return; - } - break; - case AS_MPLAYER : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - Q_strncpyz(buf, NET_AdrToString( cls.mplayerServers[n].adr) , buflen ); - return; - } - break; - case AS_GLOBAL : - if (n >= 0 && n < MAX_GLOBAL_SERVERS) { - Q_strncpyz(buf, NET_AdrToString( cls.globalServers[n].adr) , buflen ); - return; - } - break; - case AS_FAVORITES : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - Q_strncpyz(buf, NET_AdrToString( cls.favoriteServers[n].adr) , buflen ); - return; - } - break; - } - buf[0] = '\0'; +static void LAN_GetServerAddressString(int source, int n, char *buf, int buflen) +{ + switch (source) { + case AS_LOCAL: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + Q_strncpyz(buf, NET_AdrToString(cls.localServers[n].adr), buflen); + return; + } + break; + case AS_MPLAYER: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + Q_strncpyz(buf, NET_AdrToString(cls.mplayerServers[n].adr), buflen); + return; + } + break; + case AS_GLOBAL: + if (n >= 0 && n < MAX_GLOBAL_SERVERS) { + Q_strncpyz(buf, NET_AdrToString(cls.globalServers[n].adr), buflen); + return; + } + break; + case AS_FAVORITES: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + Q_strncpyz(buf, NET_AdrToString(cls.favoriteServers[n].adr), buflen); + return; + } + break; + } + buf[0] = '\0'; } /* @@ -513,51 +525,52 @@ static void LAN_GetServerAddressString( int source, int n, char *buf, int buflen LAN_GetServerInfo ==================== */ -static void LAN_GetServerInfo( int source, int n, char *buf, int buflen ) { - char info[MAX_STRING_CHARS]; - serverInfo_t *server = NULL; - info[0] = '\0'; - switch (source) { - case AS_LOCAL : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - server = &cls.localServers[n]; - } - break; - case AS_MPLAYER : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - server = &cls.mplayerServers[n]; - } - break; - case AS_GLOBAL : - if (n >= 0 && n < MAX_GLOBAL_SERVERS) { - server = &cls.globalServers[n]; - } - break; - case AS_FAVORITES : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - server = &cls.favoriteServers[n]; - } - break; - } - if (server && buf) { - buf[0] = '\0'; - Info_SetValueForKey( info, "hostname", server->hostName); - Info_SetValueForKey( info, "mapname", server->mapName); - Info_SetValueForKey( info, "clients", va("%i",server->clients)); - Info_SetValueForKey( info, "sv_maxclients", va("%i",server->maxClients)); - Info_SetValueForKey( info, "ping", va("%i",server->ping)); - Info_SetValueForKey( info, "minping", va("%i",server->minPing)); - Info_SetValueForKey( info, "maxping", va("%i",server->maxPing)); - Info_SetValueForKey( info, "game", server->game); - Info_SetValueForKey( info, "gametype", va("%i",server->gameType)); - Info_SetValueForKey( info, "nettype", va("%i",server->netType)); - Info_SetValueForKey( info, "addr", NET_AdrToString(server->adr)); - Q_strncpyz(buf, info, buflen); - } else { - if (buf) { - buf[0] = '\0'; - } - } +static void LAN_GetServerInfo(int source, int n, char *buf, int buflen) +{ + char info[MAX_STRING_CHARS]; + serverInfo_t *server = NULL; + info[0] = '\0'; + switch (source) { + case AS_LOCAL: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + server = &cls.localServers[n]; + } + break; + case AS_MPLAYER: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + server = &cls.mplayerServers[n]; + } + break; + case AS_GLOBAL: + if (n >= 0 && n < MAX_GLOBAL_SERVERS) { + server = &cls.globalServers[n]; + } + break; + case AS_FAVORITES: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + server = &cls.favoriteServers[n]; + } + break; + } + if (server && buf) { + buf[0] = '\0'; + Info_SetValueForKey(info, "hostname", server->hostName); + Info_SetValueForKey(info, "mapname", server->mapName); + Info_SetValueForKey(info, "clients", va("%i", server->clients)); + Info_SetValueForKey(info, "sv_maxclients", va("%i", server->maxClients)); + Info_SetValueForKey(info, "ping", va("%i", server->ping)); + Info_SetValueForKey(info, "minping", va("%i", server->minPing)); + Info_SetValueForKey(info, "maxping", va("%i", server->maxPing)); + Info_SetValueForKey(info, "game", server->game); + Info_SetValueForKey(info, "gametype", va("%i", server->gameType)); + Info_SetValueForKey(info, "nettype", va("%i", server->netType)); + Info_SetValueForKey(info, "addr", NET_AdrToString(server->adr)); + Q_strncpyz(buf, info, buflen); + } else { + if (buf) { + buf[0] = '\0'; + } + } } /* @@ -565,34 +578,35 @@ static void LAN_GetServerInfo( int source, int n, char *buf, int buflen ) { LAN_GetServerPing ==================== */ -static int LAN_GetServerPing( int source, int n ) { - serverInfo_t *server = NULL; - switch (source) { - case AS_LOCAL : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - server = &cls.localServers[n]; - } - break; - case AS_MPLAYER : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - server = &cls.mplayerServers[n]; - } - break; - case AS_GLOBAL : - if (n >= 0 && n < MAX_GLOBAL_SERVERS) { - server = &cls.globalServers[n]; - } - break; - case AS_FAVORITES : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - server = &cls.favoriteServers[n]; - } - break; - } - if (server) { - return server->ping; - } - return -1; +static int LAN_GetServerPing(int source, int n) +{ + serverInfo_t *server = NULL; + switch (source) { + case AS_LOCAL: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + server = &cls.localServers[n]; + } + break; + case AS_MPLAYER: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + server = &cls.mplayerServers[n]; + } + break; + case AS_GLOBAL: + if (n >= 0 && n < MAX_GLOBAL_SERVERS) { + server = &cls.globalServers[n]; + } + break; + case AS_FAVORITES: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + server = &cls.favoriteServers[n]; + } + break; + } + if (server) { + return server->ping; + } + return -1; } /* @@ -600,30 +614,31 @@ static int LAN_GetServerPing( int source, int n ) { LAN_GetServerPtr ==================== */ -static serverInfo_t *LAN_GetServerPtr( int source, int n ) { - switch (source) { - case AS_LOCAL : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - return &cls.localServers[n]; - } - break; - case AS_MPLAYER : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - return &cls.mplayerServers[n]; - } - break; - case AS_GLOBAL : - if (n >= 0 && n < MAX_GLOBAL_SERVERS) { - return &cls.globalServers[n]; - } - break; - case AS_FAVORITES : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - return &cls.favoriteServers[n]; - } - break; - } - return NULL; +static serverInfo_t *LAN_GetServerPtr(int source, int n) +{ + switch (source) { + case AS_LOCAL: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + return &cls.localServers[n]; + } + break; + case AS_MPLAYER: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + return &cls.mplayerServers[n]; + } + break; + case AS_GLOBAL: + if (n >= 0 && n < MAX_GLOBAL_SERVERS) { + return &cls.globalServers[n]; + } + break; + case AS_FAVORITES: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + return &cls.favoriteServers[n]; + } + break; + } + return NULL; } /* @@ -631,68 +646,65 @@ static serverInfo_t *LAN_GetServerPtr( int source, int n ) { LAN_CompareServers ==================== */ -static int LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int s2 ) { - int res; - serverInfo_t *server1, *server2; +static int LAN_CompareServers(int source, int sortKey, int sortDir, int s1, int s2) +{ + int res; + serverInfo_t *server1, *server2; - server1 = LAN_GetServerPtr(source, s1); - server2 = LAN_GetServerPtr(source, s2); - if (!server1 || !server2) { - return 0; - } + server1 = LAN_GetServerPtr(source, s1); + server2 = LAN_GetServerPtr(source, s2); + if (!server1 || !server2) { + return 0; + } - res = 0; - switch( sortKey ) { - case SORT_HOST: - res = Q_stricmp( server1->hostName, server2->hostName ); - break; + res = 0; + switch (sortKey) { + case SORT_HOST: + res = Q_stricmp(server1->hostName, server2->hostName); + break; - case SORT_MAP: - res = Q_stricmp( server1->mapName, server2->mapName ); - break; - case SORT_CLIENTS: - if (server1->clients < server2->clients) { - res = -1; - } - else if (server1->clients > server2->clients) { - res = 1; - } - else { - res = 0; - } - break; - case SORT_GAME: - if (server1->gameType < server2->gameType) { - res = -1; - } - else if (server1->gameType > server2->gameType) { - res = 1; - } - else { - res = 0; - } - break; - case SORT_PING: - if (server1->ping < server2->ping) { - res = -1; - } - else if (server1->ping > server2->ping) { - res = 1; - } - else { - res = 0; - } - break; - } + case SORT_MAP: + res = Q_stricmp(server1->mapName, server2->mapName); + break; + case SORT_CLIENTS: + if (server1->clients < server2->clients) { + res = -1; + } else if (server1->clients > server2->clients) { + res = 1; + } else { + res = 0; + } + break; + case SORT_GAME: + if (server1->gameType < server2->gameType) { + res = -1; + } else if (server1->gameType > server2->gameType) { + res = 1; + } else { + res = 0; + } + break; + case SORT_PING: + if (server1->ping < server2->ping) { + res = -1; + } else if (server1->ping > server2->ping) { + res = 1; + } else { + res = 0; + } + break; + } - if (sortDir) { - if (res < 0) - return 1; - if (res > 0) - return -1; - return 0; - } - return res; + if (sortDir) { + if (res < 0) { + return 1; + } + if (res > 0) { + return -1; + } + return 0; + } + return res; } /* @@ -700,8 +712,9 @@ static int LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int LAN_GetPingQueueCount ==================== */ -static int LAN_GetPingQueueCount( void ) { - return (CL_GetPingQueueCount()); +static int LAN_GetPingQueueCount(void) +{ + return (CL_GetPingQueueCount()); } /* @@ -709,8 +722,9 @@ static int LAN_GetPingQueueCount( void ) { LAN_ClearPing ==================== */ -static void LAN_ClearPing( int n ) { - CL_ClearPing( n ); +static void LAN_ClearPing(int n) +{ + CL_ClearPing(n); } /* @@ -718,8 +732,9 @@ static void LAN_ClearPing( int n ) { LAN_GetPing ==================== */ -static void LAN_GetPing( int n, char *buf, int buflen, int *pingtime ) { - CL_GetPing( n, buf, buflen, pingtime ); +static void LAN_GetPing(int n, char *buf, int buflen, int *pingtime) +{ + CL_GetPing(n, buf, buflen, pingtime); } /* @@ -727,8 +742,9 @@ static void LAN_GetPing( int n, char *buf, int buflen, int *pingtime ) { LAN_GetPingInfo ==================== */ -static void LAN_GetPingInfo( int n, char *buf, int buflen ) { - CL_GetPingInfo( n, buf, buflen ); +static void LAN_GetPingInfo(int n, char *buf, int buflen) +{ + CL_GetPingInfo(n, buf, buflen); } /* @@ -736,87 +752,88 @@ static void LAN_GetPingInfo( int n, char *buf, int buflen ) { LAN_MarkServerVisible ==================== */ -static void LAN_MarkServerVisible(int source, int n, qboolean visible ) { - if (n == -1) { - int count = MAX_OTHER_SERVERS; - serverInfo_t *server = NULL; - switch (source) { - case AS_LOCAL : - server = &cls.localServers[0]; - break; - case AS_MPLAYER : - server = &cls.mplayerServers[0]; - break; - case AS_GLOBAL : - server = &cls.globalServers[0]; - count = MAX_GLOBAL_SERVERS; - break; - case AS_FAVORITES : - server = &cls.favoriteServers[0]; - break; - } - if (server) { - for (n = 0; n < count; n++) { - server[n].visible = visible; - } - } +static void LAN_MarkServerVisible(int source, int n, qboolean visible) +{ + if (n == -1) { + int count = MAX_OTHER_SERVERS; + serverInfo_t *server = NULL; + switch (source) { + case AS_LOCAL: + server = &cls.localServers[0]; + break; + case AS_MPLAYER: + server = &cls.mplayerServers[0]; + break; + case AS_GLOBAL: + server = &cls.globalServers[0]; + count = MAX_GLOBAL_SERVERS; + break; + case AS_FAVORITES: + server = &cls.favoriteServers[0]; + break; + } + if (server) { + for (n = 0; n < count; n++) { + server[n].visible = visible; + } + } - } else { - switch (source) { - case AS_LOCAL : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - cls.localServers[n].visible = visible; - } - break; - case AS_MPLAYER : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - cls.mplayerServers[n].visible = visible; - } - break; - case AS_GLOBAL : - if (n >= 0 && n < MAX_GLOBAL_SERVERS) { - cls.globalServers[n].visible = visible; - } - break; - case AS_FAVORITES : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - cls.favoriteServers[n].visible = visible; - } - break; - } - } + } else { + switch (source) { + case AS_LOCAL: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + cls.localServers[n].visible = visible; + } + break; + case AS_MPLAYER: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + cls.mplayerServers[n].visible = visible; + } + break; + case AS_GLOBAL: + if (n >= 0 && n < MAX_GLOBAL_SERVERS) { + cls.globalServers[n].visible = visible; + } + break; + case AS_FAVORITES: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + cls.favoriteServers[n].visible = visible; + } + break; + } + } } - /* ======================= LAN_ServerIsVisible ======================= */ -static int LAN_ServerIsVisible(int source, int n ) { - switch (source) { - case AS_LOCAL : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - return cls.localServers[n].visible; - } - break; - case AS_MPLAYER : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - return cls.mplayerServers[n].visible; - } - break; - case AS_GLOBAL : - if (n >= 0 && n < MAX_GLOBAL_SERVERS) { - return cls.globalServers[n].visible; - } - break; - case AS_FAVORITES : - if (n >= 0 && n < MAX_OTHER_SERVERS) { - return cls.favoriteServers[n].visible; - } - break; - } - return qfalse; +static int LAN_ServerIsVisible(int source, int n) +{ + switch (source) { + case AS_LOCAL: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + return cls.localServers[n].visible; + } + break; + case AS_MPLAYER: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + return cls.mplayerServers[n].visible; + } + break; + case AS_GLOBAL: + if (n >= 0 && n < MAX_GLOBAL_SERVERS) { + return cls.globalServers[n].visible; + } + break; + case AS_FAVORITES: + if (n >= 0 && n < MAX_OTHER_SERVERS) { + return cls.favoriteServers[n].visible; + } + break; + } + return qfalse; } /* @@ -824,8 +841,9 @@ static int LAN_ServerIsVisible(int source, int n ) { LAN_UpdateVisiblePings ======================= */ -qboolean LAN_UpdateVisiblePings(int source ) { - return CL_UpdateVisiblePings_f(source); +qboolean LAN_UpdateVisiblePings(int source) +{ + return CL_UpdateVisiblePings_f(source); } /* @@ -833,8 +851,9 @@ qboolean LAN_UpdateVisiblePings(int source ) { LAN_GetServerStatus ==================== */ -int LAN_GetServerStatus( const char *serverAddress, char *serverStatus, int maxLen ) { - return CL_ServerStatus( serverAddress, serverStatus, maxLen ); +int LAN_GetServerStatus(const char *serverAddress, char *serverStatus, int maxLen) +{ + return CL_ServerStatus(serverAddress, serverStatus, maxLen); } /* @@ -842,8 +861,9 @@ int LAN_GetServerStatus( const char *serverAddress, char *serverStatus, int maxL CL_GetGlConfig ==================== */ -static void CL_GetGlconfig( glconfig_t *config ) { - *config = cls.glconfig; +static void CL_GetGlconfig(glconfig_t *config) +{ + *config = cls.glconfig; } /* @@ -851,19 +871,20 @@ static void CL_GetGlconfig( glconfig_t *config ) { CL_GetClipboardData ==================== */ -static void CL_GetClipboardData( char *buf, int buflen ) { - char *cbd; +static void CL_GetClipboardData(char *buf, int buflen) +{ + char *cbd; - cbd = Sys_GetClipboardData(); + cbd = Sys_GetClipboardData(); - if ( !cbd ) { - *buf = 0; - return; - } + if (!cbd) { + *buf = 0; + return; + } - Q_strncpyz( buf, cbd, buflen ); + Q_strncpyz(buf, cbd, buflen); - Z_Free( cbd ); + Z_Free(cbd); } /* @@ -871,8 +892,9 @@ static void CL_GetClipboardData( char *buf, int buflen ) { Key_KeynumToStringBuf ==================== */ -static void Key_KeynumToStringBuf( int keynum, char *buf, int buflen ) { - Q_strncpyz( buf, Key_KeynumToString( keynum ), buflen ); +static void Key_KeynumToStringBuf(int keynum, char *buf, int buflen) +{ + Q_strncpyz(buf, Key_KeynumToString(keynum), buflen); } /* @@ -880,16 +902,16 @@ static void Key_KeynumToStringBuf( int keynum, char *buf, int buflen ) { Key_GetBindingBuf ==================== */ -static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) { - const char *value; +static void Key_GetBindingBuf(int keynum, char *buf, int buflen) +{ + const char *value; - value = Key_GetBinding( keynum ); - if ( value ) { - Q_strncpyz( buf, value, buflen ); - } - else { - *buf = 0; - } + value = Key_GetBinding(keynum); + if (value) { + Q_strncpyz(buf, value, buflen); + } else { + *buf = 0; + } } /* @@ -899,22 +921,23 @@ GetConfigString */ static int GetConfigString(int index, char *buf, int size) { - int offset; + int offset; - if (index < 0 || index >= MAX_CONFIGSTRINGS) - return qfalse; + if (index < 0 || index >= MAX_CONFIGSTRINGS) { + return qfalse; + } - offset = cl.gameState.stringOffsets[index]; - if (!offset) { - if( size ) { - buf[0] = 0; - } - return qfalse; - } + offset = cl.gameState.stringOffsets[index]; + if (!offset) { + if (size) { + buf[0] = 0; + } + return qfalse; + } - Q_strncpyz( buf, cl.gameState.stringData+offset, size); + Q_strncpyz(buf, cl.gameState.stringData + offset, size); - return qtrue; + return qtrue; } /* @@ -922,16 +945,18 @@ static int GetConfigString(int index, char *buf, int size) FloatAsInt ==================== */ -static int FloatAsInt( float f ) { - int temp; +static int FloatAsInt(float f) +{ + int temp; - *(float *)&temp = f; + *(float *)&temp = f; - return temp; + return temp; } -qboolean UI_usesUniqueCDKey( void ) { - return qfalse; +qboolean UI_usesUniqueCDKey(void) +{ + return qfalse; } /* @@ -939,31 +964,29 @@ qboolean UI_usesUniqueCDKey( void ) { getDefaultConsoleRectangle ==================== */ -static UIRect2D getDefaultDMConsoleRectangle( void ) { - float f[ 4 ]; - int i; - UIRect2D rect; +static UIRect2D getDefaultDMConsoleRectangle(void) +{ + float f[4]; + int i; + UIRect2D rect; - if( sscanf( ui_consoleposition->string, "%f %f %f %f", &f[ 0 ], &f[ 1 ], &f[ 2 ], &f[ 3 ] ) == 4 ) - { - for( i = 0; i < 4; i++ ) { - f[ i ] = floor( f[ i ] ); - } + if (sscanf(ui_consoleposition->string, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]) == 4) { + for (i = 0; i < 4; i++) { + f[i] = floor(f[i]); + } - rect.pos.x = f[ 0 ] - cls.glconfig.vidWidth; - rect.pos.y = f[ 1 ] - cls.glconfig.vidHeight; - rect.size.width = f[ 2 ] + 50.0; - rect.size.height = f[ 3 ] + 50.0; - } - else - { - rect.pos.x = 0; - rect.pos.y = cls.glconfig.vidHeight * 0.58; - rect.size.width = cls.glconfig.vidWidth; - rect.size.height = cls.glconfig.vidHeight * 0.415; - } + rect.pos.x = f[0] - uid.vidWidth; + rect.pos.y = f[1] - uid.vidHeight; + rect.size.width = f[2] + 50.0; + rect.size.height = f[3] + 50.0; + } else { + rect.pos.x = 0; + rect.pos.y = uid.vidHeight * 0.58; + rect.size.width = uid.vidWidth; + rect.size.height = uid.vidHeight * 0.415; + } - return rect; + return rect; } /* @@ -971,31 +994,33 @@ static UIRect2D getDefaultDMConsoleRectangle( void ) { getDefaultConsoleRectangle ==================== */ -static UIRect2D getQuickMessageDMConsoleRectangle( void ) { - float f[ 4 ]; - int i; - UIRect2D rect; +static UIRect2D getQuickMessageDMConsoleRectangle(void) +{ + float f[4]; + int i; + UIRect2D rect; - if( sscanf( ui_consoleposition->string, "%f %f %f %f", &f[ 0 ], &f[ 1 ], &f[ 2 ], &f[ 3 ] ) == 4 ) - { - for( i = 0; i < 4; i++ ) { - f[ i ] = floor( f[ i ] ); - } + if (sscanf(ui_consoleposition->string, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]) == 4) { + for (i = 0; i < 4; i++) { + f[i] = floor(f[i]); + } - rect.pos.x = f[ 0 ] - cls.glconfig.vidWidth; - rect.pos.y = f[ 1 ] - cls.glconfig.vidHeight; - rect.size.width = f[ 2 ] + 50.0; - rect.size.height = f[ 3 ] + 50.0; - } - else - { - rect.pos.x = 0; - rect.pos.y = cls.glconfig.vidHeight * 0.65; - rect.size.width = cls.glconfig.vidWidth; - rect.size.height = 38.0; - } + rect.pos.x = f[0] - uid.vidWidth; + rect.pos.y = f[1] - uid.vidHeight; + rect.size.width = f[2] + 50.0; + rect.size.height = f[3] + 50.0; + } else { + rect.pos.x = 0; + rect.pos.y = uid.vidHeight * 0.66; + rect.size.width = uid.vidWidth; + // Fixed in 2.0 + // Was 38.0 in 1.11 and below + // This prevents characters to be seen from the DM console + // in the quick message console + rect.size.height = 36.0 * uid.scaleRes[1]; + } - return rect; + return rect; } /* @@ -1003,25 +1028,24 @@ static UIRect2D getQuickMessageDMConsoleRectangle( void ) { UI_DMMessageModesMatch ==================== */ -static qboolean UI_DMMessageModesMatch( int iMode ) { - qboolean bQuickMessage; +static qboolean UI_DMMessageModesMatch(int iMode) +{ + qboolean bQuickMessage = qfalse; - if( iMode && ( iMode != 300 || dm_console->GetQuickMessageMode() ) ) - { - if( iMode < 0 ) - { - bQuickMessage = qtrue; - iMode = -iMode; - } + if (iMode && (iMode != 300 || dm_console->GetQuickMessageMode())) { + if (iMode < 0) { + bQuickMessage = qtrue; + iMode = -iMode; + } - if( dm_console->GetQuickMessageMode() == bQuickMessage ) { - return dm_console->GetMessageMode() == iMode; - } else { - return qfalse; - } - } else { - return qtrue; - } + if (dm_console->GetQuickMessageMode() == bQuickMessage) { + return dm_console->GetMessageMode() == iMode; + } else { + return qfalse; + } + } else { + return qtrue; + } } /* @@ -1029,92 +1053,101 @@ static qboolean UI_DMMessageModesMatch( int iMode ) { UI_SetDMConsoleMode ==================== */ -static void UI_SetDMConsoleMode( int iMode ) { - qboolean bQuickMessage; +static void UI_SetDMConsoleMode(int iMode) +{ + qboolean bQuickMessage; - if( UI_DMMessageModesMatch( iMode ) ) { - return; - } + if (UI_DMMessageModesMatch(iMode)) { + return; + } - if( iMode < 0 ) - { - bQuickMessage = qtrue; - iMode = -iMode; - } + bQuickMessage = qfalse; - if( iMode == 300 ) { - bQuickMessage = dm_console->GetMessageMode(); - } + if (iMode < 0) { + bQuickMessage = qtrue; + iMode = -iMode; + } - if( dm_console->GetQuickMessageMode() ) - { - if( !bQuickMessage ) - { - dm_console->setFrame( getDefaultDMConsoleRectangle() ); - dm_console->SetQuickMessageMode( qfalse ); - } - } - else - { - if( bQuickMessage ) - { - dm_console->setFrame( getDefaultDMConsoleRectangle() ); - dm_console->SetQuickMessageMode( qfalse ); - } - } + if (iMode == 300) { + iMode = dm_console->GetMessageMode(); + } - dm_console->SetMessageMode( iMode ); + if (dm_console->GetQuickMessageMode()) { + if (!bQuickMessage) { + dm_console->setFrame(getDefaultDMConsoleRectangle()); + dm_console->SetQuickMessageMode(qfalse); + } + } else { + if (bQuickMessage) { + dm_console->setFrame(getQuickMessageDMConsoleRectangle()); + dm_console->SetQuickMessageMode(bQuickMessage); + } + } - if( bQuickMessage ) - { - if( iMode == 100 ) - { - dm_console->setTitle( Sys_LV_CL_ConvertString( "Quick Chat (Press Enter to send) : Messaging to All" ) ); - } - else if( iMode == 200 ) - { - dm_console->setTitle( Sys_LV_CL_ConvertString( "Quick Chat (Press Enter to send) : Messaging to Team" ) ); - } - else - { - dm_console->setTitle( va( "%s %i", Sys_LV_CL_ConvertString( "Quick Chat (Press Enter to send) : Messaging to Client" ), iMode ) ); - } - } - else - { - if( iMode == 100 ) - { - dm_console->setTitle( Sys_LV_CL_ConvertString( "Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to All" ) ); - } - else if( iMode == 100 ) - { - dm_console->setTitle( Sys_LV_CL_ConvertString( "Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to Team" ) ); - } - else - { - dm_console->setTitle( va( "%s %i", Sys_LV_CL_ConvertString( "Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to Client" ), iMode ) ); - } - } + dm_console->SetMessageMode(iMode); + + if (bQuickMessage) { + if (iMode == 100) { + dm_console->setTitle(Sys_LV_CL_ConvertString("Quick Chat (Press Enter to send) : Messaging to All")); + } else if (iMode == 200) { + dm_console->setTitle(Sys_LV_CL_ConvertString("Quick Chat (Press Enter to send) : Messaging to Team")); + } else { + dm_console->setTitle( + va("%s %i", Sys_LV_CL_ConvertString("Quick Chat (Press Enter to send) : Messaging to Client"), iMode) + ); + } + } else { + if (iMode == 100) { + dm_console->setTitle(Sys_LV_CL_ConvertString( + "Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to All" + )); + } else if (iMode == 200) { + dm_console->setTitle(Sys_LV_CL_ConvertString( + "Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to Team" + )); + } else { + dm_console->setTitle( + va("%s %i", + Sys_LV_CL_ConvertString( + "Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to Client" + ), + iMode) + ); + } + } } -static void DMConsoleCommandHandler( const char *txt ) { - int iMode; - char szStringOut[1024]; +static void DMConsoleCommandHandler(const char *txt) +{ + int iMode; + char szStringOut[1024]; - iMode = 0; + iMode = 0; - if (dm_console->GetMessageMode() != 100) - { - if (dm_console->GetMessageMode() == 200) { - iMode = -1; - } - else { - iMode = dm_console->GetMessageMode(); - } - } + if (dm_console->GetMessageMode() != 100) { + if (dm_console->GetMessageMode() == 200) { + iMode = -1; + } else { + iMode = dm_console->GetMessageMode(); + } + } - Com_sprintf(szStringOut, sizeof(szStringOut), "dmmessage %i %s\n", iMode, txt); - CL_AddReliableCommand(szStringOut, qfalse); + Com_sprintf(szStringOut, sizeof(szStringOut), "dmmessage %i %s\n", iMode, txt); + CL_AddReliableCommand(szStringOut, qfalse); +} + +/* +==================== +getScreenWidth +==================== +*/ +static float getScreenWidth() +{ + if (uid.bHighResScaling) { + return maxWidthRes; + } else { + return uid.vidWidth; + } } /* @@ -1122,18 +1155,19 @@ static void DMConsoleCommandHandler( const char *txt ) { getNewConsole ==================== */ -UIFloatingConsole* getNewConsole() { - const char* consoleName = va("%s console version %s", PRODUCT_NAME, PRODUCT_VERSION); +UIFloatingConsole *getNewConsole() +{ + const char *consoleName = va("%s console version %s", PRODUCT_NAME, PRODUCT_VERSION); - UIFloatingConsole* console = new UIFloatingConsole; - console->Create(NULL, getDefaultConsoleRectangle(), consoleName, UWindowColor, UHudColor); - console->setConsoleHandler(ConsoleCommandHandler); - console->setConsoleBackground(UBlack, 0.8f); - console->setShow(false); - console->Connect(&s_consolehider, UIFloatingWindow::W_ClosePressed, UIFloatingWindow::W_ClosePressed); - console->Connect(&s_consolehider, W_Destroyed, W_Destroyed); + UIFloatingConsole *console = new UIFloatingConsole; + console->Create(NULL, getDefaultConsoleRectangle(), consoleName, UWindowColor, UHudColor); + console->setConsoleHandler(ConsoleCommandHandler); + console->setConsoleBackground(UBlack, 0.8f); + console->setShow(false); + console->Connect(&s_consolehider, UIFloatingWindow::W_ClosePressed, UIFloatingWindow::W_ClosePressed); + console->Connect(&s_consolehider, W_Destroyed, W_Destroyed); - return console; + return console; } /* @@ -1141,27 +1175,32 @@ UIFloatingConsole* getNewConsole() { getNewDMConsole ==================== */ -UIFloatingDMConsole *getNewDMConsole() { - UIFloatingDMConsole *console = new UIFloatingDMConsole; - Event *event; +UIFloatingDMConsole *getNewDMConsole() +{ + UIFloatingDMConsole *console = new UIFloatingDMConsole; + Event *event; - console->Create( NULL, getDefaultDMConsoleRectangle(), - "Chat Window (Enter to send/close) (all|team|private to change message mode) : Messaging to All", - UWindowColor, UHudColor ); + console->Create( + NULL, + getDefaultDMConsoleRectangle(), + "Chat Window (Enter to send/close) (all|team|private to change message mode) : Messaging to All", + UWindowColor, + UHudColor + ); - console->setConsoleHandler( DMConsoleCommandHandler ); - console->setConsoleBackground( UBlack, 0.8f ); - console->setShow( false ); - console->Connect( &s_dmconsolehider, UIFloatingWindow::W_ClosePressed, UIFloatingWindow::W_ClosePressed ); - console->Connect( &s_dmconsolehider, W_Destroyed, W_Destroyed ); + console->setConsoleHandler(DMConsoleCommandHandler); + console->setConsoleBackground(UBlack, 0.8f); + console->setShow(false); + console->Connect(&s_dmconsolehider, UIFloatingWindow::W_ClosePressed, UIFloatingWindow::W_ClosePressed); + console->Connect(&s_dmconsolehider, W_Destroyed, W_Destroyed); - event = new Event( EV_Widget_Disable ); - console->PassEventToWidget( "closebutton", event ); + event = new Event(EV_Widget_Disable); + console->PassEventToWidget("closebutton", event); - event = new Event( EV_Widget_Disable ); - console->PassEventToWidget( "minimizebutton", event ); + event = new Event(EV_Widget_Disable); + console->PassEventToWidget("minimizebutton", event); - return console; + return console; } /* @@ -1169,21 +1208,17 @@ UIFloatingDMConsole *getNewDMConsole() { getDefaultGMBoxRectangle ==================== */ -static UIRect2D getDefaultGMBoxRectangle(void) { +static UIRect2D getDefaultGMBoxRectangle(void) +{ UIRect2D dmRect = getDefaultDMBoxRectangle(); - float height = cls.glconfig.vidHeight * ui_compass_scale->value * 0.25f; - float y = dmRect.size.height + dmRect.pos.y; + float height = uid.vidHeight * ui_compass_scale->value * 0.25f; + float y = dmRect.size.height + dmRect.pos.y; if (height < y) { - height = y; + height = y; } - return UIRect2D( - 20.0f, - height, - cls.glconfig.vidWidth - 20, - 128.0f - ); + return UIRect2D(20.0f, height, (getScreenWidth() - 20) * uid.scaleRes[0], 128.0f * uid.scaleRes[1]); } /* @@ -1191,15 +1226,39 @@ static UIRect2D getDefaultGMBoxRectangle(void) { getDefaultDMBoxRectangle ==================== */ -static UIRect2D getDefaultDMBoxRectangle(void) { - float width = cls.glconfig.vidWidth * ui_compass_scale->value * 0.2f; +static UIRect2D getDefaultDMBoxRectangle(void) +{ + float width; + float screenWidth = getScreenWidth(); + + width = screenWidth * uid.scaleRes[0] * ui_compass_scale->value * 0.2f; - return UIRect2D( - width, - 0, - cls.glconfig.vidWidth - (width + 192.0f), - 120.0f - ); + return UIRect2D(width, 0, (screenWidth - (width + 192.0f)) * uid.scaleRes[0], 120.0f * uid.scaleRes[1]); +} + +/* +==================== +UI_GetObjectivesTop +==================== +*/ +float UI_GetObjectivesTop(void) +{ + return getDefaultGMBoxRectangle().pos.y; +} + +/* +==================== +UI_GetObjectivesTop +==================== +*/ +void UI_GetHighResolutionScale(vec2_t scale) +{ + if (uid.bHighResScaling) { + scale[0] = uid.scaleRes[0]; + scale[1] = uid.scaleRes[1]; + } else { + scale[0] = scale[1] = 1.0; + } } /* @@ -1207,11 +1266,11 @@ static UIRect2D getDefaultDMBoxRectangle(void) { UI_ShowHudList ==================== */ -void UI_ShowHudList( void ) { - for( int i = 1; i <= hudList.NumObjects(); i++ ) - { - hudList.ObjectAt( i )->ForceShow(); - } +void UI_ShowHudList(void) +{ + for (int i = 1; i <= hudList.NumObjects(); i++) { + hudList.ObjectAt(i)->ForceShow(); + } } /* @@ -1219,11 +1278,11 @@ void UI_ShowHudList( void ) { UI_HideHudList ==================== */ -void UI_HideHudList( void ) { - for( int i = 1; i <= hudList.NumObjects(); i++ ) - { - hudList.ObjectAt( i )->ForceHide(); - } +void UI_HideHudList(void) +{ + for (int i = 1; i <= hudList.NumObjects(); i++) { + hudList.ObjectAt(i)->ForceHide(); + } } /* @@ -1231,15 +1290,15 @@ void UI_HideHudList( void ) { UI_DisplayHudList ==================== */ -void UI_DisplayHudList( void ) { - for( int i = 1; i <= hudList.NumObjects(); i++ ) - { - Menu *pMenu = hudList.ObjectAt( i ); - UIWidget *pWidget = pMenu->GetContainerWidget(); +void UI_DisplayHudList(void) +{ + for (int i = 1; i <= hudList.NumObjects(); i++) { + Menu *pMenu = hudList.ObjectAt(i); + UIWidget *pWidget = pMenu->GetContainerWidget(); - pMenu->ForceShow(); - pWidget->Display( uWinMan.getFrame(), 1.0 ); - } + pMenu->ForceShow(); + pWidget->Display(uWinMan.getFrame(), 1.0); + } } /* @@ -1247,139 +1306,129 @@ void UI_DisplayHudList( void ) { UI_PrintConsole ==================== */ -void UI_PrintConsole( const char *msg ) +void UI_PrintConsole(const char *msg) { - UColor *pColor = NULL; - char szString[ 1024 ]; - char szBlah[ 1024 ]; + const UColor *pColor = NULL; + const char *pszString; + char szString[1024]; + char szBlah[1024]; + qboolean bPrintedDMBox = qfalse; - memcpy( szString, msg, sizeof( szString ) ); + pszString = msg; + strncpy(szString, msg, 1024); - if( *szString < MESSAGE_MAX ) - { - qboolean bNormalMessage = qfalse; - qboolean bDMMessage = qfalse; - qboolean bBold = qfalse; - qboolean bDeathMessage = qfalse; + if (*pszString < MESSAGE_MAX) { + qboolean bNormalMessage = qfalse; + qboolean bDMMessage = qfalse; + qboolean bBold = qfalse; + qboolean bDeathMessage = qfalse; - switch( *szString ) - { - case MESSAGE_YELLOW: - bNormalMessage = qtrue; - pColor = &UHudColor; - break; - case MESSAGE_CHAT_WHITE: - bDMMessage = qtrue; - pColor = &UGrey; - break; - case MESSAGE_WHITE: - bBold = qtrue; - pColor = &UWhite; - break; - case MESSAGE_CHAT_RED: - bDeathMessage = qtrue; - pColor = &ULightRed; - break; - case MESSAGE_CHAT_GREEN: - bDeathMessage = qtrue; - pColor = &UGreen; - break; - } + switch (*pszString) { + case MESSAGE_YELLOW: + bNormalMessage = qtrue; + pColor = &UHudColor; + break; + case MESSAGE_CHAT_WHITE: + bDMMessage = qtrue; + pColor = &UWhiteChatMessageColor; + break; + case MESSAGE_WHITE: + bBold = qtrue; + pColor = &UWhite; + break; + case MESSAGE_CHAT_RED: + bDeathMessage = MESSAGE_CHAT_RED; + pColor = &URedChatMessageColor; + break; + case MESSAGE_CHAT_GREEN: + bDeathMessage = MESSAGE_CHAT_GREEN; + pColor = &UGreenChatMessageColor; + break; + } - msg++; + if (*pszString != 0) { + pszString++; + } - // - // print to the deathmatch console - // - if( dm_console && !bNormalMessage ) - { - if( bDMMessage ) - { - dm_console->AddDMMessageText( szString + 1, pColor ); - } - else - { - dm_console->AddText( szString + 1, pColor ); - } - } + // + // print to the deathmatch console + // + if (dm_console && !bNormalMessage) { + if (bDMMessage) { + dm_console->AddDMMessageText(szString + 1, pColor); + } else { + dm_console->AddText(szString + 1, pColor); + } + } - // - // print to the deathmatch message box - // - if( dmbox ) - { - if( bDMMessage ) - { - *szString = MESSAGE_CHAT_WHITE; - dmbox->Print( szString ); - return; - } - else if( bDeathMessage ) - { - dmbox->Print( szString ); - *szString = MESSAGE_CHAT_RED; - return; - } - } + // + // print to the deathmatch message box + // + if (dmbox) { + if (bDMMessage) { + *szString = MESSAGE_CHAT_WHITE; + dmbox->Print(szString); + pszString = msg + 1; + bPrintedDMBox = qtrue; + } else if (bDeathMessage) { + dmbox->Print(szString); + *szString = bDeathMessage; + bPrintedDMBox = qtrue; + } + } - // - // print to the game message box - // - if( gmbox ) - { - if( bBold ) - { - *szString = MESSAGE_WHITE; - gmbox->Print( szString ); - uii.Snd_PlaySound( "objective_text" ); - } - else - { - gmbox->Print( szString + 1 ); - } + // + // print to the game message box + // + if (gmbox && !bPrintedDMBox) { + if (bBold) { + *szString = MESSAGE_WHITE; + gmbox->Print(szString); + uii.Snd_PlaySound("objective_text"); + pszString = msg + 1; + } else { + gmbox->Print(szString + 1); + } - if( !ui_gmboxspam->integer ) { - return; - } + if (!ui_gmboxspam->integer) { + return; + } - memcpy( szBlah, "Game Message: ", 15 ); - strcat( szBlah, szString + 1 ); - } - } + if (!bDMMessage) { + memcpy(szBlah, "Game Message: ", 15); + Q_strcat(szBlah, sizeof(szBlah), pszString); + pszString = szBlah; + } + } + } - if( *msg == 7 ) - { - msg++; - if( mini_console ) - { - mini_console->Print( msg + 1 ); - return; - } - } + if (*pszString == '\a') { + pszString++; + if (mini_console) { + mini_console->Print(pszString); + return; + } + } - if( fakk_console ) - { - if( s_intermediateconsole ) - { - fakk_console->AddText( *s_intermediateconsole, NULL ); - delete s_intermediateconsole; - s_intermediateconsole = NULL; - } + if (fakk_console) { + if (s_intermediateconsole) { + fakk_console->AddText(*s_intermediateconsole, NULL); + delete s_intermediateconsole; + s_intermediateconsole = NULL; + } - fakk_console->AddText( msg, pColor ); + fakk_console->AddText(pszString, pColor); - if( mini_console ) { - mini_console->Print( msg ); - } - } - else - { - if( !s_intermediateconsole ) { - s_intermediateconsole = new str; - } + if (mini_console) { + mini_console->Print(pszString); + } + } else { + if (!s_intermediateconsole) { + s_intermediateconsole = new str; + } - *s_intermediateconsole = msg; - } + *s_intermediateconsole = msg; + } } /* @@ -1387,13 +1436,13 @@ void UI_PrintConsole( const char *msg ) UI_PrintDeveloperConsole ==================== */ -void UI_PrintDeveloperConsole( const char *msg ) +void UI_PrintDeveloperConsole(const char *msg) { - if( !developer_console ) { - return; - } + if (!developer_console) { + return; + } - developer_console->AddText( msg, NULL ); + developer_console->AddText(msg, NULL); } /* @@ -1401,39 +1450,38 @@ void UI_PrintDeveloperConsole( const char *msg ) UI_UpdateContinueGame ==================== */ -void UI_UpdateContinueGame( void ) { - cvar_t *var; - const char *name; - const char *archive_name; - int length; - Event *event; +void UI_UpdateContinueGame(void) +{ + cvar_t *var; + const char *name; + const char *archive_name; + int length; + Event *event; - var = Cvar_Get( "g_lastsave", "", 0 ); - name = var->string; + var = Cvar_Get("g_lastsave", "", 0); + name = var->string; - if( *name ) - { - archive_name = Com_GetArchiveFileName( name, "sav" ); - length = FS_ReadFileEx( archive_name, NULL, qtrue ); + if (*name) { + archive_name = Com_GetArchiveFileName(name, "sav"); + length = FS_ReadFileEx(archive_name, NULL, qtrue); - if( length != -1 ) - { - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "continue game", event ); + if (length != -1) { + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("continue game", event); - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "new game", event ); - return; - } + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("new game", event); + return; + } - Cvar_Set( "g_lastsave", "" ); - } + Cvar_Set("g_lastsave", ""); + } - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "continue game", event ); + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("continue game", event); - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "new game", event ); + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("new game", event); } /* @@ -1441,8 +1489,9 @@ void UI_UpdateContinueGame( void ) { UI_MenuActive ==================== */ -qboolean UI_MenuActive( void ) { - return menuManager.CurrentMenu() != NULL; +qboolean UI_MenuActive(void) +{ + return menuManager.CurrentMenu() != NULL; } /* @@ -1450,35 +1499,32 @@ qboolean UI_MenuActive( void ) { UI_FocusMenuIfExists ==================== */ -void UI_FocusMenuIfExists( void ) { - Menu *currentMenu; - int r_mode; +void UI_FocusMenuIfExists(void) +{ + Menu *currentMenu; + int r_mode; - currentMenu = menuManager.CurrentMenu(); - r_mode = Cvar_VariableValue( "r_mode" ); + currentMenu = menuManager.CurrentMenu(); + r_mode = Cvar_VariableValue("r_mode"); - if( currentMenu ) - { - IN_MouseOn(); + if (currentMenu) { + IN_MouseOn(); - if( view3d->IsActive() ) { - uWinMan.DeactivateCurrentControl(); - } + if (view3d->IsActive()) { + uWinMan.DeactivateCurrentControl(); + } - currentMenu->ActivateMenu(); + currentMenu->ActivateMenu(); - if( ui_newvidmode->integer == -1 ) - { - Cvar_Get( "ui_newvidmode", va( "%d", r_mode ), CVAR_SERVER_CREATED ); - Cvar_SetValue( "ui_newvidmode", r_mode ); - } - } - else - { - UI_ActivateView3D(); - IN_MouseOff(); - Cvar_SetValue( "ui_newvidmode", -1 ); - } + if (ui_newvidmode->integer == -1) { + Cvar_Get("ui_newvidmode", va("%d", r_mode), CVAR_RESETSTRING); + Cvar_SetValue("ui_newvidmode", r_mode); + } + } else { + UI_ActivateView3D(); + IN_MouseOff(); + Cvar_SetValue("ui_newvidmode", -1); + } } /* @@ -1486,14 +1532,15 @@ void UI_FocusMenuIfExists( void ) { UI_OpenConsole ==================== */ -void UI_OpenConsole( void ) { - if( !fakk_console ) { - return; - } +void UI_OpenConsole(void) +{ + if (!fakk_console) { + return; + } - fakk_console->setShow( true ); - uWinMan.ActivateControl( fakk_console ); - IN_MouseOn(); + fakk_console->setShow(true); + uWinMan.ActivateControl(fakk_console); + IN_MouseOn(); } /* @@ -1501,8 +1548,9 @@ void UI_OpenConsole( void ) { UI_OpenConsole ==================== */ -qboolean UI_ConsoleIsVisible( void ) { - return fakk_console && fakk_console->IsVisible(); +qboolean UI_ConsoleIsVisible(void) +{ + return fakk_console && fakk_console->IsVisible(); } /* @@ -1510,8 +1558,9 @@ qboolean UI_ConsoleIsVisible( void ) { UI_ConsoleIsOpen ==================== */ -qboolean UI_ConsoleIsOpen( void ) { - return fakk_console && fakk_console->IsVisible() && fakk_console->IsActive(); +qboolean UI_ConsoleIsOpen(void) +{ + return fakk_console && fakk_console->IsVisible() && fakk_console->IsActive(); } /* @@ -1519,11 +1568,12 @@ qboolean UI_ConsoleIsOpen( void ) { UI_CloseConsole ==================== */ -void UI_CloseConsole( void ) { - if( fakk_console && fakk_console->getShow() ) { - fakk_console->setShow( false ); - } - UI_FocusMenuIfExists(); +void UI_CloseConsole(void) +{ + if (fakk_console && fakk_console->getShow()) { + fakk_console->setShow(false); + } + UI_FocusMenuIfExists(); } /* @@ -1531,16 +1581,17 @@ void UI_CloseConsole( void ) { UI_ToggleConsole ==================== */ -void UI_ToggleConsole( void ) { - if( !fakk_console ) { - return; - } +void UI_ToggleConsole(void) +{ + if (!fakk_console) { + return; + } - if( fakk_console->IsVisible() ) { - UI_CloseConsole(); - } else { - UI_OpenConsole(); - } + if (fakk_console->IsVisible()) { + UI_CloseConsole(); + } else { + UI_OpenConsole(); + } } /* @@ -1548,15 +1599,16 @@ void UI_ToggleConsole( void ) { UI_OpenDMConsole ==================== */ -void UI_OpenDMConsole( int iMode ) { - if( !dm_console ) { - return; - } +void UI_OpenDMConsole(int iMode) +{ + if (!dm_console) { + return; + } - UI_SetDMConsoleMode( iMode ); - dm_console->setShow( true ); - uWinMan.ActivateControl( dm_console ); - IN_MouseOff(); + UI_SetDMConsoleMode(iMode); + dm_console->setShow(true); + uWinMan.ActivateControl(dm_console); + IN_MouseOff(); } /* @@ -1564,11 +1616,12 @@ void UI_OpenDMConsole( int iMode ) { UI_CloseDMConsole ==================== */ -void UI_CloseDMConsole( void ) { - if( dm_console && dm_console->getShow() ) { - dm_console->setShow( false ); - } - UI_FocusMenuIfExists(); +void UI_CloseDMConsole(void) +{ + if (dm_console && dm_console->getShow()) { + dm_console->setShow(false); + } + UI_FocusMenuIfExists(); } /* @@ -1576,23 +1629,21 @@ void UI_CloseDMConsole( void ) { UI_ToggleDMConsole ==================== */ -void UI_ToggleDMConsole( int iMode ) { - if( !dm_console ) { - return; - } +void UI_ToggleDMConsole(int iMode) +{ + if (!dm_console) { + return; + } - if( dm_console->IsVisible() ) - { - if( UI_DMMessageModesMatch( iMode ) ) { - UI_CloseDMConsole(); - } else { - UI_OpenDMConsole( iMode ); - } - } - else - { - UI_OpenDMConsole( iMode ); - } + if (dm_console->IsVisible()) { + if (UI_DMMessageModesMatch(iMode)) { + UI_CloseDMConsole(); + } else { + UI_OpenDMConsole(iMode); + } + } else { + UI_OpenDMConsole(iMode); + } } /* @@ -1600,14 +1651,15 @@ void UI_ToggleDMConsole( int iMode ) { UI_OpenDeveloperConsole ==================== */ -void UI_OpenDeveloperConsole( void ) { - if( !developer_console ) { - return; - } +void UI_OpenDeveloperConsole(void) +{ + if (!developer_console) { + return; + } - developer_console->setShow( true ); - uWinMan.ActivateControl( developer_console ); - IN_MouseOn(); + developer_console->setShow(true); + uWinMan.ActivateControl(developer_console); + IN_MouseOn(); } /* @@ -1615,11 +1667,12 @@ void UI_OpenDeveloperConsole( void ) { UI_CloseDeveloperConsole ==================== */ -void UI_CloseDeveloperConsole( void ) { - if( developer_console && developer_console->getShow() ) { - developer_console->setShow( false ); - } - UI_FocusMenuIfExists(); +void UI_CloseDeveloperConsole(void) +{ + if (developer_console && developer_console->getShow()) { + developer_console->setShow(false); + } + UI_FocusMenuIfExists(); } /* @@ -1627,16 +1680,17 @@ void UI_CloseDeveloperConsole( void ) { UI_ToggleDeveloperConsole_f ==================== */ -void UI_ToggleDeveloperConsole_f( void ) { - if( !developer_console ) { - return; - } +void UI_ToggleDeveloperConsole_f(void) +{ + if (!developer_console) { + return; + } - if( developer_console->IsThisOrChildActive() ) { - UI_CloseDeveloperConsole(); - } else { - UI_OpenDeveloperConsole(); - } + if (developer_console->IsThisOrChildActive()) { + UI_CloseDeveloperConsole(); + } else { + UI_OpenDeveloperConsole(); + } } /* @@ -1644,8 +1698,9 @@ void UI_ToggleDeveloperConsole_f( void ) { UI_KeyEvent ==================== */ -void UI_KeyEvent( int key, unsigned int time ) { - uWinMan.KeyEvent( key, time ); +void UI_KeyEvent(int key, unsigned int time) +{ + uWinMan.KeyEvent(key, time); } /* @@ -1653,8 +1708,9 @@ void UI_KeyEvent( int key, unsigned int time ) { UI_CharEvent ==================== */ -void UI_CharEvent( int ch ) { - uWinMan.CharEvent( ch ); +void UI_CharEvent(int ch) +{ + uWinMan.CharEvent(ch); } /* @@ -1662,12 +1718,15 @@ void UI_CharEvent( int ch ) { UI_ClearBackground ==================== */ -void UI_ClearBackground( void ) { - re.Set2DWindow( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, -1, -1 ); - re.Scissor( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight ); - re.SetColor( g_color_table[ 0 ] ); - re.DrawBox( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight ); - re.SetColor( NULL ); +void UI_ClearBackground(void) +{ + re.Set2DWindow( + 0, 0, uid.vidWidth, uid.vidHeight, 0, uid.vidWidth, uid.vidHeight, 0, -1, 1 + ); + re.Scissor(0, 0, uid.vidWidth, uid.vidHeight); + re.SetColor(g_color_table[0]); + re.DrawBox(0, 0, uid.vidWidth, uid.vidHeight); + re.SetColor(NULL); } /* @@ -1675,13 +1734,14 @@ void UI_ClearBackground( void ) { UI_ActivateView3D ==================== */ -void UI_ActivateView3D( void ) { - if( !view3d ) { - return; - } +void UI_ActivateView3D(void) +{ + if (!view3d) { + return; + } - view3d->setShow( true ); - uWinMan.ActivateControl( view3d ); + view3d->setShow(true); + uWinMan.ActivateControl(view3d); } /* @@ -1689,17 +1749,46 @@ void UI_ActivateView3D( void ) { UI_DrawIntro ==================== */ -void UI_DrawIntro( void ) { - if( clc.state == CA_CINEMATIC ) - { - view3d->setShow( true ); - return; - } +void UI_DrawIntro(void) +{ + if (clc.state == CA_CINEMATIC) { + view3d->setShow(true); + return; + } - view3d->setShow( false ); - UI_ClearBackground(); + view3d->setShow(false); + UI_ClearBackground(); - // FIXME: draw intro + if (cls.startStage < 3 || cls.startStage >= 12) { + return; + } + + if (intro_stage.material->GetMaterial()) { + float swidth; + float sheight; + vec4_t color; + + VectorSet4(color, 1, 1, 1, 1); + if (intro_stage.fadetime) { + float frac; + + frac = Q_clamp_float((cls.realtime - intro_stage.starttime) / intro_stage.fadetime, 0, 1); + color[0] = color[1] = color[2] = + intro_stage.alpha_start + frac * (intro_stage.alpha_end - intro_stage.alpha_start); + } + + swidth = view3d->getFrame().getMaxX(); + sheight = view3d->getFrame().getMaxY(); + + re.SetColor(color); + + re.DrawStretchPic(0.0, 0.0, swidth, sheight, 0.0, 0.0, 1.0, 1.0, intro_stage.material->GetMaterial()); + re.SetColor(NULL); + } + + if (cls.realtime >= intro_stage.endtime) { + CL_FinishedStartStage(); + } } /* @@ -1707,8 +1796,9 @@ void UI_DrawIntro( void ) { UI_MenuUp ==================== */ -qboolean UI_MenuUp() { - return menuManager.CurrentMenu() != NULL; +qboolean UI_MenuUp() +{ + return menuManager.CurrentMenu() != NULL; } /* @@ -1718,13 +1808,13 @@ UI_FullscreenMenuUp */ qboolean UI_FullscreenMenuUp() { - Menu *currentMenu = menuManager.CurrentMenu(); + Menu *currentMenu = menuManager.CurrentMenu(); - if( currentMenu ) { - return currentMenu->isFullscreen(); - } + if (currentMenu) { + return currentMenu->isFullscreen(); + } - return qfalse; + return qfalse; } /* @@ -1734,758 +1824,582 @@ UI_Update Updates the UI. ==================== */ -void UI_Update(void) { - Menu* currentMenu; - UIRect2D frame; +void UI_Update(void) +{ + Menu *currentMenu; + UIRect2D frame; - re.SetRenderTime(cls.realtime); - CL_FillUIDef(); - uWinMan.ServiceEvents(); + re.SetRenderTime(cls.realtime); + CL_FillUIDef(); + uWinMan.ServiceEvents(); - // - // draw the base HUD when in-game - // - if (cls.no_menus && clc.state == CA_ACTIVE) - { - view3d->setShow(true); - frame = uWinMan.getFrame(); - view3d->Display(frame, 1.0); + // + // draw the base HUD when in-game + // + if (cls.no_menus && clc.state == CA_ACTIVE) { + view3d->setShow(true); + frame = uWinMan.getFrame(); + view3d->Display(frame, 1.0); - if (ui_hud && !view3d->LetterboxActive()) - { - // draw the health hud - if (hud_health) - { - hud_health->ForceShow(); - frame = uWinMan.getFrame(); - hud_health->GetContainerWidget()->Display(frame, 1.0); - } + if (ui_hud && !view3d->LetterboxActive()) { + // draw the health hud + if (hud_health) { + hud_health->ForceShow(); + frame = uWinMan.getFrame(); + hud_health->GetContainerWidget()->Display(frame, 1.0); + } - // draw the ammo hud - if (hud_ammo) - { - hud_ammo->ForceShow(); - frame = uWinMan.getFrame(); - hud_ammo->GetContainerWidget()->Display(frame, 1.0); - } + // draw the ammo hud + if (hud_ammo) { + hud_ammo->ForceShow(); + frame = uWinMan.getFrame(); + hud_ammo->GetContainerWidget()->Display(frame, 1.0); + } - // draw the compass hud - if (hud_compass) - { - hud_compass->ForceShow(); - frame = uWinMan.getFrame(); - hud_compass->GetContainerWidget()->Display(frame, 1.0); - } - } - } + // draw the compass hud + if (hud_compass) { + hud_compass->ForceShow(); + frame = uWinMan.getFrame(); + hud_compass->GetContainerWidget()->Display(frame, 1.0); + } + } - if (fakk_console) - { - if (ui_minicon->integer) - { - // toggle the mini-console - if (mini_console) { - mini_console->setRealShow(fakk_console->getShow() ^ 1); - } - } - else if (mini_console) { - mini_console->setRealShow(false); - } - } + return; + } - if (gmbox) { - gmbox->setRealShow(true); - } + if (fakk_console) { + if (ui_minicon->integer) { + // toggle the mini-console + if (mini_console) { + mini_console->setRealShow(fakk_console->getShow() ^ 1); + } + } else if (mini_console) { + mini_console->setRealShow(false); + } + } - if (dmbox) { - dmbox->setRealShow(true); - } + if (gmbox) { + gmbox->setRealShow(true); + } - currentMenu = menuManager.CurrentMenu(); + if (dmbox) { + dmbox->setRealShow(true); + } - if (currentMenu == menuManager.FindMenu("main")) { - UI_MainMenuWidgetsUpdate(); - } + currentMenu = menuManager.CurrentMenu(); - // don't care about the intro - /* - if( CL_FinishedIntro() ) - { - } - else - { - UI_DrawIntro(); - } - */ + if (currentMenu == menuManager.FindMenu("main")) { + UI_MainMenuWidgetsUpdate(); + } else if (currentMenu == menuManager.FindMenu("dm_main")) { + UI_MultiplayerMainMenuWidgetsUpdate(); + } - if (!server_loading && (clc.state == CA_CONNECTING || clc.state == CA_CHALLENGING) && ui_pConnectingMenu) - { - view3d->setShow(false); - UI_ClearBackground(); + // don't care about the intro + if (!CL_FinishedIntro()) { + UI_DrawIntro(); + } else if (!server_loading && (clc.state == CA_CONNECTING || clc.state == CA_CHALLENGING) && ui_pConnectingMenu) { + view3d->setShow(false); + UI_ClearBackground(); - if (UI_BindActive()) - { - Menu* bindMenu = menuManager.FindMenu("controls"); + if (UI_BindActive()) { + Menu *bindMenu = menuManager.FindMenu("controls"); - if (bindMenu) - { - Event* event = new Event(EV_UIFakkBindList_StopBind); - bindMenu->PassEventToWidget("bindlist", event); - } - else - { - uWinMan.SetBindActive(NULL); - } - } + if (bindMenu) { + Event *event = new Event(EV_UIFakkBindList_StopBind); + bindMenu->PassEventToWidget("bindlist", event); + } else { + uWinMan.SetBindActive(NULL); + } + } - if (clc.connectTime >= cls.realtime - 1000 * cl_connect_timeout->integer) - { - if (currentMenu != ui_pConnectingMenu) - { - UI_ForceMenuOff(true); - UI_DeactiveFloatingWindows(); - UI_ForceMenu("connecting"); - uWinMan.showCursor(true); - } - } - else - { - Com_Printf("\nConnect to server timed out\n"); - UI_ForceMenuOff(true); - Cbuf_AddText("disconnect;pushmenu servertimeout"); - } - } - else - { - if (currentMenu && currentMenu->isFullscreen() && (!server_loading || !ui_pLoadingMenu)) - { - if (com_sv_running->integer && clc.state == CA_ACTIVE) { - Com_FakePause(); - } + if (clc.connectStartTime >= cls.realtime - 1000 * cl_connect_timeout->integer) { + if (currentMenu != ui_pConnectingMenu) { + UI_ForceMenuOff(true); + UI_DeactiveFloatingWindows(); + UI_ForceMenu("connecting"); + uWinMan.showCursor(true); + } + } else { + Com_Printf("\nConnect to server timed out\n"); + UI_ForceMenuOff(true); + Cbuf_AddText("disconnect;pushmenu servertimeout"); + } + } else { + if (currentMenu && currentMenu->isFullscreen() && (!server_loading || !ui_pLoadingMenu)) { + if (com_sv_running->integer && clc.state == CA_ACTIVE) { + Com_FakePause(); + } - view3d->setShow(false); - } - else if (!server_loading) - { - if (clc.state <= CA_PRIMED) - { - view3d->setShow(false); - UI_ClearBackground(); - } - else if (clc.state == CA_PRIMED || clc.state == CA_ACTIVE) - { - Com_FakeUnpause(); - view3d->setShow(true); - } - else - { - UI_ClearBackground(); - view3d->setShow(false); - } - } - else - { - view3d->setShow(false); - UI_ClearBackground(); + view3d->setShow(false); + } else if (!server_loading) { + if (clc.state <= CA_PRIMED) { + view3d->setShow(false); + UI_ClearBackground(); + } else if (clc.state == CA_ACTIVE || clc.state == CA_CINEMATIC) { + Com_FakeUnpause(); + view3d->setShow(true); + } else { + UI_ClearBackground(); + view3d->setShow(false); + } + } else { + view3d->setShow(false); + UI_ClearBackground(); - if (UI_BindActive()) - { - Menu* bindMenu = menuManager.FindMenu("controls"); + if (UI_BindActive()) { + Menu *bindMenu = menuManager.FindMenu("controls"); - if (bindMenu) - { - Event* event = new Event(EV_UIFakkBindList_StopBind); - bindMenu->PassEventToWidget("bindlist", event); - } - } - else - { - uWinMan.SetBindActive(NULL); - } + if (bindMenu) { + Event *event = new Event(EV_UIFakkBindList_StopBind); + bindMenu->PassEventToWidget("bindlist", event); + } + } else { + uWinMan.SetBindActive(NULL); + } - if (ui_pLoadingMenu) - { - if (currentMenu != ui_pLoadingMenu) - { - UI_ForceMenuOff(true); - UI_DeactiveFloatingWindows(); - UI_ForceMenu(ui_sCurrentLoadingMenu); - uWinMan.showCursor(false); - } + if (ui_pLoadingMenu) { + if (currentMenu != ui_pLoadingMenu) { + UI_ForceMenuOff(true); + UI_DeactiveFloatingWindows(); + UI_ForceMenu(ui_sCurrentLoadingMenu); + uWinMan.showCursor(false); + } - if (!developer->integer && UI_ConsoleIsVisible()) { - UI_CloseConsole(); - } - } - else if (ui_static_materials.loading) - { - ui_static_materials.loading->ReregisterMaterial(); - } - } - } + if (!developer->integer && UI_ConsoleIsVisible()) { + UI_CloseConsole(); + } + } else if (ui_static_materials.loading) { + ui_static_materials.loading->GetMaterial(); + } + } + } - // Hide the HUD when necessary - if (!ui_hud || clc.state != CA_ACTIVE || view3d->LetterboxActive() - || (currentMenu && currentMenu->isFullscreen()) - || server_loading - || ((cl.snap.ps.pm_flags & PMF_NO_HUD) || (cl.snap.ps.pm_flags & PMF_SPECTATE_FOLLOW))) - { - if (crosshairhud) - { - crosshairhud->ForceHide(); - } - if (hud_weapons) - { - hud_weapons->ForceHide(); - ui_weapHudTime = 0; - } - if (hud_items) - { - hud_items->ForceHide(); - ui_itemHudTime = 0; - } - if (hud_health) - { - hud_health->ForceHide(); - } - if (hud_ammo) - { - hud_ammo->ForceHide(); - } - if (hud_compass) - { - hud_compass->ForceHide(); - } - if (hud_boss) - { - hud_boss->ForceHide(); - } + // Hide the HUD when necessary + if (!ui_hud || clc.state != CA_ACTIVE || view3d->LetterboxActive() || (currentMenu && currentMenu->isFullscreen()) + || server_loading || ((cl.snap.ps.pm_flags & PMF_NO_HUD) || (cl.snap.ps.pm_flags & PMF_INTERMISSION))) { + if (crosshairhud) { + crosshairhud->ForceHide(); + } + if (hud_weapons) { + hud_weapons->ForceHide(); + ui_weapHudTime = 0; + } + if (hud_items) { + hud_items->ForceHide(); + ui_itemHudTime = 0; + } + if (hud_health) { + hud_health->ForceHide(); + } + if (hud_ammo) { + hud_ammo->ForceHide(); + } + if (hud_compass) { + hud_compass->ForceHide(); + } + if (hud_boss) { + hud_boss->ForceHide(); + } - UI_HideHudList(); - } - else - { - if (crosshairhud) - { - if (ui_crosshair->integer && cl.snap.ps.stats[STAT_CROSSHAIR]) { - crosshairhud->ForceShow(); - } - else { - crosshairhud->ForceHide(); - } - } + UI_HideHudList(); + } else { + if (crosshairhud) { + if (ui_crosshair->integer && cl.snap.ps.stats[STAT_CROSSHAIR]) { + crosshairhud->ForceShow(); + } else { + crosshairhud->ForceHide(); + } + } - // - // show and highlight all weapons that the player holds - // + // + // show and highlight all weapons that the player holds + // - // - // try to show the weapons bar - // - if (hud_weapons) - { - if (ui_weaponsbar->integer) - { - int iEquippedDiff = 0; - int iOwnedDiff = 0; + // + // try to show the weapons bar + // + if (hud_weapons) { + if (ui_weaponsbar->integer) { + int iEquippedDiff = 0; + int iOwnedDiff = 0; - if (ui_weaponsbar->integer == 2) { - ui_weapHudTime = cls.realtime + ui_weaponsbartime->value; - } - else if (ui_weaponsbar->integer != 3 && ui_itemHudTime && hud_items->isVisible()) { - ui_weapHudTime = 0; - } + if (ui_weaponsbar->integer == 2) { + ui_weapHudTime = cls.realtime + ui_weaponsbartime->value; + } else if (ui_weaponsbar->integer != 3 && ui_itemHudTime && hud_items->isVisible()) { + ui_weapHudTime = 0; + } - if (ui_lastWeapHudState_Owned != cl.snap.ps.stats[STAT_WEAPONS] - || ui_lastWeapHudState_Equipped != cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) - { - iOwnedDiff = cl.snap.ps.stats[STAT_WEAPONS] ^ ui_lastWeapHudState_Owned & 0x3F; - iEquippedDiff = (ui_lastWeapHudState_Equipped ^ cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) & 0x3F; + if (ui_lastWeapHudState_Owned != cl.snap.ps.stats[STAT_WEAPONS] + || ui_lastWeapHudState_Equipped != cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) { + iOwnedDiff = cl.snap.ps.stats[STAT_WEAPONS] ^ ui_lastWeapHudState_Owned & 0x3F; + iEquippedDiff = (ui_lastWeapHudState_Equipped ^ cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) & 0x3F; - // if we have different equipment, reset the weapons hud time - if (iOwnedDiff || iEquippedDiff) { - ui_weapHudTime = cls.realtime + ui_weaponsbartime->integer; - } - } + // if we have different equipment, reset the weapons hud time + if (iOwnedDiff || iEquippedDiff) { + ui_weapHudTime = cls.realtime + ui_weaponsbartime->integer; + } + } - // - // show weapons that the player holds - // - if (iOwnedDiff) - { - if (iOwnedDiff & 1) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 1) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("pistol_empty", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("pistol_empty", event); - } - } - if (iOwnedDiff & 2) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 2) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("rifle_empty", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("rifle_empty", event); - } - } - if (iOwnedDiff & 4) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 4) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("smg_empty", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("smg_empty", event); - } - } - if (iOwnedDiff & 8) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 8) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("mg_empty", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("mg_empty", event); - } - } - if (iOwnedDiff & 16) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 16) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("grenade_empty", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("grenade_empty", event); - } - } - if (iOwnedDiff & 32) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 32) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("heavy_empty", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("heavy_empty", event); - } - } - ui_lastWeapHudState_Owned = cl.snap.ps.stats[STAT_WEAPONS] & 0x3F | ui_lastWeapHudState_Owned & ~0x3F; - } - // - // highlight currently equipped weapons - // - if (iEquippedDiff) - { - if (iEquippedDiff & 1) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 1) - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("pistol_equipped", event); - } - else - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("pistol_equipped", event); - } - } - if (iEquippedDiff & 2) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 2) - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("rifle_equipped", event); - } - else - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("rifle_equipped", event); - } - } - if (iEquippedDiff & 4) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 4) - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("smg_equipped", event); - } - else - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("smg_equipped", event); - } - } - if (iEquippedDiff & 8) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 8) - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("mg_equipped", event); - } - else - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("mg_equipped", event); - } - } - if (iEquippedDiff & 16) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 16) - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("grenade_equipped", event); - } - else - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("grenade_equipped", event); - } - } - if (iEquippedDiff & 32) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 32) - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("heavy_equipped", event); - } - else - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("heavy_equipped", event); - } - } - ui_lastWeapHudState_Equipped = cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 0x3F | ui_lastWeapHudState_Equipped & ~0x3F; - } + // + // show weapons that the player holds + // + if (iOwnedDiff) { + if (iOwnedDiff & 1) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 1) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("pistol_empty", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("pistol_empty", event); + } + } + if (iOwnedDiff & 2) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 2) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("rifle_empty", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("rifle_empty", event); + } + } + if (iOwnedDiff & 4) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 4) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("smg_empty", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("smg_empty", event); + } + } + if (iOwnedDiff & 8) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 8) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("mg_empty", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("mg_empty", event); + } + } + if (iOwnedDiff & 16) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 16) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("grenade_empty", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("grenade_empty", event); + } + } + if (iOwnedDiff & 32) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 32) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("heavy_empty", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("heavy_empty", event); + } + } + ui_lastWeapHudState_Owned = + cl.snap.ps.stats[STAT_WEAPONS] & 0x3F | ui_lastWeapHudState_Owned & ~0x3F; + } + // + // highlight currently equipped weapons + // + if (iEquippedDiff) { + if (iEquippedDiff & 1) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 1) { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("pistol_equipped", event); + } else { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("pistol_equipped", event); + } + } + if (iEquippedDiff & 2) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 2) { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("rifle_equipped", event); + } else { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("rifle_equipped", event); + } + } + if (iEquippedDiff & 4) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 4) { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("smg_equipped", event); + } else { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("smg_equipped", event); + } + } + if (iEquippedDiff & 8) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 8) { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("mg_equipped", event); + } else { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("mg_equipped", event); + } + } + if (iEquippedDiff & 16) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 16) { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("grenade_equipped", event); + } else { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("grenade_equipped", event); + } + } + if (iEquippedDiff & 32) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 32) { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("heavy_equipped", event); + } else { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("heavy_equipped", event); + } + } + ui_lastWeapHudState_Equipped = + cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 0x3F | ui_lastWeapHudState_Equipped & ~0x3F; + } - if (!ui_weapHudTime) - { - if (hud_weapons->isVisible()) { - hud_weapons->ProcessEvent(EV_HideMenu); - } - } - else if (ui_weapHudTime < cls.realtime || ui_itemHudTime > ui_weapHudTime) - { - ui_weapHudTime = 0; + if (!ui_weapHudTime) { + if (hud_weapons->isVisible()) { + hud_weapons->ProcessEvent(EV_HideMenu); + } + } else if (ui_weapHudTime < cls.realtime || ui_itemHudTime > ui_weapHudTime) { + ui_weapHudTime = 0; - if (hud_weapons->isVisible()) { - hud_weapons->ProcessEvent(EV_HideMenu); - } - } - else if (!hud_weapons->isVisible()) - { - Event* event = new Event(EV_ShowMenu); - event->AddInteger(false); - hud_weapons->ProcessEvent(event); + if (hud_weapons->isVisible()) { + hud_weapons->ProcessEvent(EV_HideMenu); + } + } else if (!hud_weapons->isVisible()) { + Event *event = new Event(EV_ShowMenu); + event->AddInteger(false); + hud_weapons->ProcessEvent(event); - if (hud_items->isVisible()) { - hud_items->ProcessEvent(EV_HideMenu); - } - } - } - else - { - hud_weapons->ForceHide(); - ui_weapHudTime = 0; - } - } + if (hud_items->isVisible()) { + hud_items->ProcessEvent(EV_HideMenu); + } + } + } else { + hud_weapons->ForceHide(); + ui_weapHudTime = 0; + } + } - // - // try to show the item bar - // - if (hud_items) - { - if (ui_weaponsbar->integer && ui_itemsbar->integer) - { - int iEquippedDiff = 0; - int iOwnedDiff = 0; + // + // try to show the item bar + // + if (hud_items) { + if (ui_weaponsbar->integer && ui_itemsbar->integer) { + int iEquippedDiff = 0; + int iOwnedDiff = 0; - if (ui_weaponsbar->integer == 3) - { - ui_itemHudTime = cls.realtime + ui_weaponsbartime->integer; + if (ui_weaponsbar->integer == 3) { + ui_itemHudTime = cls.realtime + ui_weaponsbartime->integer; - if (ui_weapHudTime && hud_weapons->isVisible()) { - ui_itemHudTime = 0; - } - } + if (ui_weapHudTime && hud_weapons->isVisible()) { + ui_itemHudTime = 0; + } + } - if (ui_lastWeapHudState_Owned != cl.snap.ps.stats[STAT_WEAPONS] - || ui_lastWeapHudState_Equipped != cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) - { - iOwnedDiff = cl.snap.ps.stats[STAT_WEAPONS] ^ ui_lastWeapHudState_Owned & 0xF00; - iEquippedDiff = (ui_lastWeapHudState_Equipped ^ cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) & 0xF00; + if (ui_lastWeapHudState_Owned != cl.snap.ps.stats[STAT_WEAPONS] + || ui_lastWeapHudState_Equipped != cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) { + iOwnedDiff = cl.snap.ps.stats[STAT_WEAPONS] ^ ui_lastWeapHudState_Owned & 0xF00; + iEquippedDiff = (ui_lastWeapHudState_Equipped ^ cl.snap.ps.stats[STAT_EQUIPPED_WEAPON]) & 0xF00; - // if we have different equipment, reset the weapons hud time - if (iOwnedDiff || iEquippedDiff) { - ui_weapHudTime = cls.realtime + ui_weaponsbartime->integer; - } - } + // if we have different equipment, reset the weapons hud time + if (iOwnedDiff || iEquippedDiff) { + ui_weapHudTime = cls.realtime + ui_weaponsbartime->integer; + } + } - // - // show items that the player holds - // - if (iOwnedDiff) - { - if (iOwnedDiff & 0x100) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 1) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot1_icon", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot1_icon", event); - } - } - if (iOwnedDiff & 0x200) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 2) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot2_icon", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot2_icon", event); - } - } - if (iOwnedDiff & 0x400) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 4) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot3_icon", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot3_icon", event); - } - } - if (iOwnedDiff & 0x800) - { - if (cl.snap.ps.stats[STAT_WEAPONS] & 8) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot4_icon", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot4_icon", event); - } - } - ui_lastWeapHudState_Owned = cl.snap.ps.stats[STAT_WEAPONS] & 0xF00 | (ui_lastWeapHudState_Owned & 0xF0); - } - // - // highlight currently equipped weapons - // - else if (iEquippedDiff) - { - if (iEquippedDiff & 0x100) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 1) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot1_highlight", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot1_highlight", event); - } - } - else if (iEquippedDiff & 0x200) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 2) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot2_highlight", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot2_highlight", event); - } - } - else if (iEquippedDiff & 0x400) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 4) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot3_highlight", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot3_highlight", event); - } - } - else if (iEquippedDiff & 0x800) - { - if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 8) - { - Event* event = new Event(EV_Widget_Disable); - hud_weapons->PassEventToWidget("slot4_highlight", event); - } - else - { - Event* event = new Event(EV_Widget_Enable); - hud_weapons->PassEventToWidget("slot4_highlight", event); - } - } - else - { - ui_lastWeapHudState_Equipped = cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 0xF00 | (ui_lastWeapHudState_Equipped & 0xF0); - } - } + // + // show items that the player holds + // + if (iOwnedDiff) { + if (iOwnedDiff & 0x100) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 1) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot1_icon", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot1_icon", event); + } + } + if (iOwnedDiff & 0x200) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 2) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot2_icon", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot2_icon", event); + } + } + if (iOwnedDiff & 0x400) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 4) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot3_icon", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot3_icon", event); + } + } + if (iOwnedDiff & 0x800) { + if (cl.snap.ps.stats[STAT_WEAPONS] & 8) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot4_icon", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot4_icon", event); + } + } + ui_lastWeapHudState_Owned = + cl.snap.ps.stats[STAT_WEAPONS] & 0xF00 | (ui_lastWeapHudState_Owned & 0xF0); + } + // + // highlight currently equipped weapons + // + else if (iEquippedDiff) { + if (iEquippedDiff & 0x100) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 1) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot1_highlight", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot1_highlight", event); + } + } else if (iEquippedDiff & 0x200) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 2) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot2_highlight", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot2_highlight", event); + } + } else if (iEquippedDiff & 0x400) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 4) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot3_highlight", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot3_highlight", event); + } + } else if (iEquippedDiff & 0x800) { + if (cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 8) { + Event *event = new Event(EV_Widget_Disable); + hud_weapons->PassEventToWidget("slot4_highlight", event); + } else { + Event *event = new Event(EV_Widget_Enable); + hud_weapons->PassEventToWidget("slot4_highlight", event); + } + } else { + ui_lastWeapHudState_Equipped = + cl.snap.ps.stats[STAT_EQUIPPED_WEAPON] & 0xF00 | (ui_lastWeapHudState_Equipped & 0xF0); + } + } - if (!ui_itemHudTime) - { - if (hud_items->isVisible()) { - hud_items->ProcessEvent(EV_HideMenu); - } - } - else if (ui_itemHudTime < cls.realtime || ui_weapHudTime > ui_itemHudTime) - { - ui_itemHudTime = 0; + if (!ui_itemHudTime) { + if (hud_items->isVisible()) { + hud_items->ProcessEvent(EV_HideMenu); + } + } else if (ui_itemHudTime < cls.realtime || ui_weapHudTime > ui_itemHudTime) { + ui_itemHudTime = 0; - if (hud_items->isVisible()) { - hud_items->ProcessEvent(EV_HideMenu); - } - } - else if (!hud_items->isVisible()) - { - Event* event = new Event(EV_ShowMenu); - event->AddInteger(false); - hud_items->ProcessEvent(event); + if (hud_items->isVisible()) { + hud_items->ProcessEvent(EV_HideMenu); + } + } else if (!hud_items->isVisible()) { + Event *event = new Event(EV_ShowMenu); + event->AddInteger(false); + hud_items->ProcessEvent(event); - if (hud_weapons->isVisible()) { - hud_weapons->ProcessEvent(EV_HideMenu); - } - } - } - else - { - hud_items->ForceHide(); - ui_itemHudTime = 0; - } - } + if (hud_weapons->isVisible()) { + hud_weapons->ProcessEvent(EV_HideMenu); + } + } + } else { + hud_items->ForceHide(); + ui_itemHudTime = 0; + } + } - if (hud_health) { - hud_health->ForceShow(); - } + if (hud_health) { + hud_health->ForceShow(); + } - // - // show the ammo hud - // - str ammo = "hud_ammo_"; - ammo += CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[ITEM_WEAPON]); + // + // show the ammo hud + // + str ammo = "hud_ammo_"; + ammo += CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[ITEM_WEAPON]); - if (!hud_ammo || hud_ammo->m_name.icmp(ammo)) - { - Menu* ammoMenu = menuManager.FindMenu(ammo); - if (ammoMenu) - { - if (ammoMenu != hud_ammo) - { - if (hud_ammo) { - hud_ammo->ForceHide(); - } - hud_ammo = ammoMenu; - } - } - else - { - ammoMenu = menuManager.FindMenu("hud_ammo_"); - if (ammoMenu) - { - if (ammoMenu != hud_ammo) - { - if (hud_ammo) { - hud_ammo->ForceHide(); - } - hud_ammo = ammoMenu; - } - } - } - } + if (!hud_ammo || hud_ammo->m_name.icmp(ammo)) { + Menu *ammoMenu = menuManager.FindMenu(ammo); + if (ammoMenu) { + if (ammoMenu != hud_ammo) { + if (hud_ammo) { + hud_ammo->ForceHide(); + } + hud_ammo = ammoMenu; + } + } else { + ammoMenu = menuManager.FindMenu("hud_ammo_"); + if (ammoMenu) { + if (ammoMenu != hud_ammo) { + if (hud_ammo) { + hud_ammo->ForceHide(); + } + hud_ammo = ammoMenu; + } + } + } + } - if (hud_ammo) { - hud_ammo->ForceShow(); - } + if (hud_ammo) { + hud_ammo->ForceShow(); + } - // - // show the compass - // - if (hud_compass) - { - if (ui_compass->integer) { - hud_compass->ForceShow(); - } - else { - hud_compass->ForceHide(); - } - } + // + // show the compass + // + if (hud_compass) { + if (ui_compass->integer) { + hud_compass->ForceShow(); + } else { + hud_compass->ForceHide(); + } + } - // - // show the boss health - // - if (hud_boss) - { - if (cl.snap.ps.stats[STAT_BOSSHEALTH] > 0 && !hud_boss->isVisible()) - { - Event* event = new Event(EV_ShowMenu); - event->AddInteger(false); - hud_boss->ProcessEvent(event); - } - else if (hud_boss->isVisible()) - { - hud_boss->ProcessEvent(EV_HideMenu); - } - } + // + // show the boss health + // + if (hud_boss) { + if (cl.snap.ps.stats[STAT_BOSSHEALTH] > 0 && !hud_boss->isVisible()) { + Event *event = new Event(EV_ShowMenu); + event->AddInteger(false); + hud_boss->ProcessEvent(event); + } else if (hud_boss->isVisible()) { + hud_boss->ProcessEvent(EV_HideMenu); + } + } - UI_ShowHudList(); - } + UI_ShowHudList(); + } - // - // show the scoreboard - // - if (scoreboard_menu) - { - if (scoreboardlist && scoreboardlist->IsVisible()) { - scoreboard_menu->ForceShow(); - } - else { - scoreboard_menu->ForceHide(); - } - } + // + // show the scoreboard + // + if (scoreboard_menu) { + if (scoreboardlist && scoreboardlist->IsVisible()) { + scoreboard_menu->ForceShow(); + } else { + scoreboard_menu->ForceHide(); + } + } - uWinMan.UpdateViews(); + uWinMan.UpdateViews(); } /* @@ -2493,64 +2407,53 @@ void UI_Update(void) { UI_MultiplayerMenuWidgetsUpdate ==================== */ -void UI_MultiplayerMenuWidgetsUpdate( void ) { - Event *event; +void UI_MultiplayerMenuWidgetsUpdate(void) +{ + Event *event; - // allow the map change widget when running in-game - if( com_sv_running->integer ) - { - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "startnew", event ); + // allow the map change widget when running in-game + if (com_sv_running->integer) { + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("startnew", event); - if( clc.state > CA_PRIMED && !cg_gametype->integer ) - { - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "changemap", event ); - } - else - { - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "changemap", event ); - } - } - else - { - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "changemap", event ); + if (clc.state > CA_PRIMED && !cg_gametype->integer) { + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("changemap", event); + } else { + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("changemap", event); + } + } else { + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("changemap", event); - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "startnew", event ); - } + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("startnew", event); + } - // allow the disconnect widget when in-game - if( clc.state > CA_PRIMED ) - { - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "disconnect", event ); - } - else - { - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "disconnect", event ); - } + // allow the disconnect widget when in-game + if (clc.state > CA_PRIMED) { + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("disconnect", event); + } else { + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("disconnect", event); + } - // allow the join widget when in-game - if( com_sv_running->integer || clc.state > CA_PRIMED ) - { - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "joinlan", event ); + // allow the join widget when in-game + if (com_sv_running->integer || clc.state > CA_PRIMED) { + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("joinlan", event); - event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "joininternet", event ); - } - else - { - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "joinlan", event ); + event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("joininternet", event); + } else { + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("joinlan", event); - event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "joininternet", event ); - } + event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("joininternet", event); + } } /* @@ -2558,19 +2461,55 @@ void UI_MultiplayerMenuWidgetsUpdate( void ) { UI_MainMenuWidgetsUpdate ==================== */ -void UI_MainMenuWidgetsUpdate( void ) { - if( clc.state > CA_PRIMED ) - { - Event *event = new Event( EV_Widget_Enable ); - menuManager.PassEventToWidget( "backtogame", event ); - } - else - { - Event *event = new Event( EV_Widget_Disable ); - menuManager.PassEventToWidget( "backtogame", event ); - } +void UI_MainMenuWidgetsUpdate(void) +{ + if (clc.state > CA_PRIMED) { + Event *event = new Event(EV_Widget_Enable); + menuManager.PassEventToWidget("backtogame", event); + } else { + Event *event = new Event(EV_Widget_Disable); + menuManager.PassEventToWidget("backtogame", event); + } - UI_UpdateContinueGame(); + UI_UpdateContinueGame(); +} + +/* +==================== +UI_MultiplayerMainMenuWidgetsUpdate +==================== +*/ +// Added in 2.0 +void UI_MultiplayerMainMenuWidgetsUpdate(void) +{ + static const cvar_t *cg_allowvote = Cvar_Get("cg_allowvote", "1", 0); + + if (cg_allowvote->integer) { + menuManager.PassEventToWidget("cantvote", new Event(EV_Widget_Disable)); + + if (atoi(CL_ConfigString(CS_VOTE_TIME))) { + menuManager.PassEventToWidget("callvotebutton", new Event(EV_Widget_Disable)); + + if (cl.snap.ps.voted) { + menuManager.PassEventToWidget("votebutton", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("alreadyvoted", new Event(EV_Widget_Enable)); + } else { + menuManager.PassEventToWidget("votebutton", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("alreadyvoted", new Event(EV_Widget_Disable)); + } + } else { + menuManager.PassEventToWidget("callvotebutton", new Event(EV_Widget_Enable)); + menuManager.PassEventToWidget("votebutton", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("alreadyvoted", new Event(EV_Widget_Disable)); + } + } else { + menuManager.PassEventToWidget("callvotebutton", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("votebutton", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("alreadyvoted", new Event(EV_Widget_Disable)); + menuManager.PassEventToWidget("cantvote", new Event(EV_Widget_Enable)); + } + + UI_UpdateContinueGame(); } /* @@ -2580,26 +2519,23 @@ UI_ToggleMenu Toggle a menu ==================== */ -void UI_ToggleMenu( str name ) { - Menu *menu; +void UI_ToggleMenu(str name) +{ + Menu *menu; - menu = menuManager.CurrentMenu(); + menu = menuManager.CurrentMenu(); - if( menu ) - { - UI_ForceMenuOff( false ); + if (menu) { + UI_ForceMenuOff(false); - if( menu->m_name != name ) - { - UI_PushMenu( name ); - } - } - else - { - UI_PushMenu( name ); - } + if (menu->m_name != name) { + UI_PushMenu(name); + } + } else { + UI_PushMenu(name); + } - UI_FocusMenuIfExists(); + UI_FocusMenuIfExists(); } /* @@ -2607,13 +2543,14 @@ void UI_ToggleMenu( str name ) { UI_ToggleMenu_f ==================== */ -void UI_ToggleMenu_f() { - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: togglemenu \n" ); - return; - } +void UI_ToggleMenu_f() +{ + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: togglemenu \n"); + return; + } - UI_ToggleMenu( Cmd_Argv( 1 ) ); + UI_ToggleMenu(Cmd_Argv(1)); } /* @@ -2621,33 +2558,32 @@ void UI_ToggleMenu_f() { UI_PopMenu ==================== */ -void UI_PopMenu( qboolean restore_cvars ) { - Menu *menu; +void UI_PopMenu(qboolean restore_cvars) +{ + Menu *menu; - if( uWinMan.DialogExists() ) { - uWinMan.RemoveAllDialogBoxes(); - return; - } + if (uWinMan.DialogExists()) { + uWinMan.RemoveAllDialogBoxes(); + return; + } - if( menuManager.CurrentMenu() ) { - menuManager.PopMenu( restore_cvars ); - } + if (menuManager.CurrentMenu()) { + menuManager.PopMenu(restore_cvars); + } - UI_FocusMenuIfExists(); + UI_FocusMenuIfExists(); - menu = menuManager.CurrentMenu(); + menu = menuManager.CurrentMenu(); - if( menu ) - { - if( !memcmp( menu->m_name.c_str(), "main", 5 ) ) - { - UI_MainMenuWidgetsUpdate(); - } - else if( !memcmp(menu->m_name.c_str(), "multiplayer", 12 ) ) - { - UI_MultiplayerMenuWidgetsUpdate(); - } - } + if (menu) { + if (!str::cmp(menu->m_name, "main")) { + UI_MainMenuWidgetsUpdate(); + } else if (!str::cmp(menu->m_name, "dm_main")) { + UI_MultiplayerMainMenuWidgetsUpdate(); + } else if (!str::cmp(menu->m_name, "multiplayer")) { + UI_MultiplayerMenuWidgetsUpdate(); + } + } } /* @@ -2655,8 +2591,9 @@ void UI_PopMenu( qboolean restore_cvars ) { UI_DeactiveFloatingWindows ==================== */ -void UI_DeactiveFloatingWindows( void ) { - uWinMan.DeactiveFloatingWindows(); +void UI_DeactiveFloatingWindows(void) +{ + uWinMan.DeactiveFloatingWindows(); } /* @@ -2664,30 +2601,28 @@ void UI_DeactiveFloatingWindows( void ) { UI_PushMenu ==================== */ -void UI_PushMenu( const char *name ) { - Menu *menu = menuManager.CurrentMenu(); - qboolean bDiff = qfalse; +void UI_PushMenu(const char *name) +{ + Menu *menu = menuManager.CurrentMenu(); + qboolean bDiff = qfalse; - if( menu ) - { - bDiff = strcmp( menu->m_name, name ) != 0; - } + if (menu) { + bDiff = strcmp(menu->m_name, name) != 0; + } - if( !bDiff || !ui_pLoadingMenu || menu != ui_pLoadingMenu ) - { - menuManager.PushMenu( name ); - } + if (!bDiff || !ui_pLoadingMenu || menu != ui_pLoadingMenu) { + menuManager.PushMenu(name); + } - UI_FocusMenuIfExists(); + UI_FocusMenuIfExists(); - if( !memcmp( name, "main", 5 ) ) - { - UI_MainMenuWidgetsUpdate(); - } - else if( !memcmp( name, "multiplayer", 12 ) ) - { - UI_MultiplayerMenuWidgetsUpdate(); - } + if (!str::cmp(name, "main")) { + UI_MainMenuWidgetsUpdate(); + } else if (!str::cmp(name, "dm_main")) { + UI_MultiplayerMainMenuWidgetsUpdate(); + } else if (!str::cmp(name, "multiplayer")) { + UI_MultiplayerMenuWidgetsUpdate(); + } } /* @@ -2695,21 +2630,20 @@ void UI_PushMenu( const char *name ) { UI_ForceMenu ==================== */ -void UI_ForceMenu( const char *name ) { - Menu *menu = menuManager.CurrentMenu(); - qboolean bDiff = qfalse; +void UI_ForceMenu(const char *name) +{ + Menu *menu = menuManager.CurrentMenu(); + qboolean bDiff = qfalse; - if( menu ) - { - bDiff = strcmp( menu->m_name, name ) != 0; - } + if (menu) { + bDiff = strcmp(menu->m_name, name) != 0; + } - if( !menu || bDiff ) - { - menuManager.ForceMenu( name ); - } + if (!menu || bDiff) { + menuManager.ForceMenu(name); + } - UI_FocusMenuIfExists(); + UI_FocusMenuIfExists(); } /* @@ -2717,21 +2651,21 @@ void UI_ForceMenu( const char *name ) { UI_ShowMenu ==================== */ -void UI_ShowMenu( const char *name, qboolean bForce ) { - Menu *pMenu; +void UI_ShowMenu(const char *name, qboolean bForce) +{ + Menu *pMenu; - pMenu = menuManager.FindMenu( name ); + pMenu = menuManager.FindMenu(name); - if( pMenu ) - { - if( bForce ) { - pMenu->ForceShow(); - } else if( !pMenu->isVisible() ) { - Event *event = new Event( EV_ShowMenu ); - event->AddInteger( false ); - pMenu->ProcessEvent( event ); - } - } + if (pMenu) { + if (bForce) { + pMenu->ForceShow(); + } else if (!pMenu->isVisible()) { + Event *event = new Event(EV_ShowMenu); + event->AddInteger(false); + pMenu->ProcessEvent(event); + } + } } /* @@ -2739,19 +2673,19 @@ void UI_ShowMenu( const char *name, qboolean bForce ) { UI_HideMenu ==================== */ -void UI_HideMenu( const char *name, qboolean bForce ) { - Menu *pMenu; +void UI_HideMenu(const char *name, qboolean bForce) +{ + Menu *pMenu; - pMenu = menuManager.FindMenu( name ); + pMenu = menuManager.FindMenu(name); - if( pMenu ) - { - if( bForce ) { - pMenu->ForceHide(); - } else if( pMenu->isVisible() ) { - pMenu->ProcessEvent( EV_HideMenu ); - } - } + if (pMenu) { + if (bForce) { + pMenu->ForceHide(); + } else if (pMenu->isVisible()) { + pMenu->ProcessEvent(EV_HideMenu); + } + } } /* @@ -2759,13 +2693,14 @@ void UI_HideMenu( const char *name, qboolean bForce ) { UI_PushMenu_f ==================== */ -void UI_PushMenu_f( void ) { - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: pushmenu \n" ); - return; - } +void UI_PushMenu_f(void) +{ + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: pushmenu \n"); + return; + } - UI_PushMenu( Cmd_Argv( 1 ) ); + UI_PushMenu(Cmd_Argv(1)); } /* @@ -2773,59 +2708,56 @@ void UI_PushMenu_f( void ) { UI_PushMenuSP_f ==================== */ -void UI_PushMenuSP_f( void ) { - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: pushmenu_sp \n" ); - return; - } +void UI_PushMenuSP_f(void) +{ + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: pushmenu_sp \n"); + return; + } - if( ( !com_cl_running || !com_cl_running->integer - || clc.state == CA_DISCONNECTED || !cg_gametype->integer ) - && ( !com_sv_running || !com_sv_running->integer || !g_gametype->integer ) ) - { - UI_PushMenu( Cmd_Argv( 1 ) ); - } + if ((!com_cl_running || !com_cl_running->integer || clc.state == CA_DISCONNECTED || !cg_gametype->integer) + && (!com_sv_running || !com_sv_running->integer || g_gametype->integer == GT_SINGLE_PLAYER)) { + UI_PushMenu(Cmd_Argv(1)); + } } + /* ==================== UI_PushMenuMP_f ==================== */ -void UI_PushMenuMP_f( void ) { - const char *cmd; +void UI_PushMenuMP_f(void) +{ + const char *cmd; - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: pushmenu_mp \n" ); - return; - } + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: pushmenu_mp \n"); + return; + } - if( com_cl_running && com_cl_running->integer - && clc.state != CA_DISCONNECTED && cg_gametype->integer - && com_sv_running && com_sv_running->integer && g_gametype->integer ) - { - cmd = Cmd_Argv( 1 ); + if (com_cl_running && com_cl_running->integer && clc.state != CA_DISCONNECTED && cg_gametype->integer + && com_sv_running && com_sv_running->integer && g_gametype->integer != GT_SINGLE_PLAYER) { + cmd = Cmd_Argv(1); - // - // Push the right menu depending on the gametype - // - if( !Q_stricmp( cmd, "SelectTeam" ) ) - { - switch( cg_gametype->integer ) - { - case GT_FFA: - UI_PushMenu( "SelectFFAModel" ); - break; - case GT_OBJECTIVE: - UI_PushMenu( "ObjSelectTeam" ); - break; - default: - UI_PushMenu( "SelectTeam" ); - } - } else { - UI_PushMenu( cmd ); - } - } + // + // Push the right menu depending on the gametype + // + if (!Q_stricmp(cmd, "SelectTeam")) { + switch (cg_gametype->integer) { + case GT_FFA: + UI_PushMenu("SelectFFAModel"); + break; + case GT_OBJECTIVE: + UI_PushMenu("ObjSelectTeam"); + break; + default: + UI_PushMenu("SelectTeam"); + } + } else { + UI_PushMenu(cmd); + } + } } /* @@ -2833,13 +2765,14 @@ void UI_PushMenuMP_f( void ) { UI_ForceMenu_f ==================== */ -void UI_ForceMenu_f( void ) { - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: forcemenu \n" ); - return; - } +void UI_ForceMenu_f(void) +{ + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: forcemenu \n"); + return; + } - UI_ForceMenu( Cmd_Argv( 1 ) ); + UI_ForceMenu(Cmd_Argv(1)); } /* @@ -2847,13 +2780,14 @@ void UI_ForceMenu_f( void ) { UI_PopMenu_f ==================== */ -void UI_PopMenu_f( void ) { - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: popmenu " ); - return; - } +void UI_PopMenu_f(void) +{ + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: popmenu "); + return; + } - UI_PopMenu( atoi( Cmd_Argv( 1 ) ) ); + UI_PopMenu(atoi(Cmd_Argv(1))); } /* @@ -2861,24 +2795,25 @@ void UI_PopMenu_f( void ) { UI_ShowMenu_f ==================== */ -void UI_ShowMenu_f( void ) { - qboolean bForce; - const char *name; +void UI_ShowMenu_f(void) +{ + qboolean bForce; + const char *name; - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: showmenu \n" ); - return; - } + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: showmenu \n"); + return; + } - name = Cmd_Argv( 1 ); + name = Cmd_Argv(1); - if( Cmd_Argc() > 2 ) { - bForce = atoi( Cmd_Argv( 2 ) ); - } else { - bForce = qfalse; - } + if (Cmd_Argc() > 2) { + bForce = atoi(Cmd_Argv(2)); + } else { + bForce = qfalse; + } - UI_ShowMenu( name, bForce ); + UI_ShowMenu(name, bForce); } /* @@ -2886,24 +2821,25 @@ void UI_ShowMenu_f( void ) { UI_HideMenu_f ==================== */ -void UI_HideMenu_f( void ) { - qboolean bForce; - const char *name; +void UI_HideMenu_f(void) +{ + qboolean bForce; + const char *name; - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: hidemenu \n" ); - return; - } + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: hidemenu \n"); + return; + } - name = Cmd_Argv( 1 ); + name = Cmd_Argv(1); - if( Cmd_Argc() > 2 ) { - bForce = atoi( Cmd_Argv( 2 ) ); - } else { - bForce = qfalse; - } + if (Cmd_Argc() > 2) { + bForce = atoi(Cmd_Argv(2)); + } else { + bForce = qfalse; + } - UI_HideMenu( name, bForce ); + UI_HideMenu(name, bForce); } /* @@ -2911,25 +2847,25 @@ void UI_HideMenu_f( void ) { UI_WidgetCommand_f ==================== */ -void UI_WidgetCommand_f( void ) { - str name; - str commandstring; +void UI_WidgetCommand_f(void) +{ + str name; + str commandstring; - if( Cmd_Argc() <= 2 ) { - Com_Printf( "Usage: widgetcommand \n" ); - return; - } + if (Cmd_Argc() <= 2) { + Com_Printf("Usage: widgetcommand \n"); + return; + } - name = Cmd_Argv( 1 ); - commandstring = Cmd_Argv( 2 ); - Event *event = new Event( commandstring ); + name = Cmd_Argv(1); + commandstring = Cmd_Argv(2); + Event *event = new Event(commandstring); - for( int i = 3; i < Cmd_Argc(); i++ ) - { - event->AddToken( Cmd_Argv( i ) ); - } + for (int i = 3; i < Cmd_Argc(); i++) { + event->AddToken(Cmd_Argv(i)); + } - menuManager.PassEventToWidget( name, event ); + menuManager.PassEventToWidget(name, event); } /* @@ -2937,25 +2873,25 @@ void UI_WidgetCommand_f( void ) { UI_GlobalWidgetCommand_f ==================== */ -void UI_GlobalWidgetCommand_f( void ) { - str name; - str commandstring; +void UI_GlobalWidgetCommand_f(void) +{ + str name; + str commandstring; - if( Cmd_Argc() <= 2 ) { - Com_Printf( "Usage: globalwidgetcommand \n" ); - return; - } + if (Cmd_Argc() <= 2) { + Com_Printf("Usage: globalwidgetcommand \n"); + return; + } - name = Cmd_Argv( 1 ); - commandstring = Cmd_Argv( 2 ); - Event *event = new Event( commandstring ); + name = Cmd_Argv(1); + commandstring = Cmd_Argv(2); + Event *event = new Event(commandstring); - for( int i = 3; i < Cmd_Argc(); i++ ) - { - event->AddToken( Cmd_Argv( i ) ); - } + for (int i = 3; i < Cmd_Argc(); i++) { + event->AddToken(Cmd_Argv(i)); + } - uWinMan.PassEventToWidget( name, event ); + uWinMan.PassEventToWidget(name, event); } /* @@ -2963,8 +2899,9 @@ void UI_GlobalWidgetCommand_f( void ) { UI_ListMenus_f ==================== */ -void UI_ListMenus_f() { - menuManager.ListMenus(); +void UI_ListMenus_f() +{ + menuManager.ListMenus(); } /* @@ -2972,8 +2909,9 @@ void UI_ListMenus_f() { UI_BindActive ==================== */ -qboolean UI_BindActive( void ) { - return uWinMan.BindActive() != NULL; +qboolean UI_BindActive(void) +{ + return uWinMan.BindActive() != NULL; } /* @@ -2981,14 +2919,15 @@ qboolean UI_BindActive( void ) { UI_SetReturnMenuToCurrent ==================== */ -void UI_SetReturnMenuToCurrent( void ) { - Menu *currentMenu = menuManager.CurrentMenu(); +void UI_SetReturnMenuToCurrent(void) +{ + Menu *currentMenu = menuManager.CurrentMenu(); - if( currentMenu ) { - Cvar_Set( "ui_returnmenu", currentMenu->m_name ); - } else { - Cvar_Set( "ui_returnmenu", "" ); - } + if (currentMenu) { + Cvar_Set("ui_returnmenu", currentMenu->m_name); + } else { + Cvar_Set("ui_returnmenu", ""); + } } /* @@ -2996,33 +2935,33 @@ void UI_SetReturnMenuToCurrent( void ) { UI_PushReturnMenu ==================== */ -qboolean UI_PushReturnMenu() { - str sMenuName; +qboolean UI_PushReturnMenu() +{ + str sMenuName; - if( !ui_returnmenu->string || !*ui_returnmenu->string ) { - return qfalse; - } + if (!ui_returnmenu->string || !*ui_returnmenu->string) { + return qfalse; + } - sMenuName = ui_returnmenu->string; + sMenuName = ui_returnmenu->string; - UI_PushMenu( sMenuName ); - Cvar_Set( "ui_returnmenu", "" ); - UI_FocusMenuIfExists(); + UI_PushMenu(sMenuName); + Cvar_Set("ui_returnmenu", ""); + UI_FocusMenuIfExists(); - if( !menuManager.CurrentMenu() ) { - return qfalse; - } + if (!menuManager.CurrentMenu()) { + return qfalse; + } - if( !memcmp( sMenuName.c_str(), "main", 5 ) ) - { - UI_MainMenuWidgetsUpdate(); - } - else if( !memcmp( sMenuName.c_str(), "multiplayer", 12 ) ) - { - UI_MultiplayerMenuWidgetsUpdate(); - } + if (!str::cmp(sMenuName, "main")) { + UI_MainMenuWidgetsUpdate(); + } else if (!str::cmp(sMenuName, "dm_main")) { + UI_MultiplayerMainMenuWidgetsUpdate(); + } else if (!str::cmp(sMenuName, "multiplayer")) { + UI_MultiplayerMenuWidgetsUpdate(); + } - return qtrue; + return qtrue; } /* @@ -3030,8 +2969,9 @@ qboolean UI_PushReturnMenu() { UI_PushReturnMenu_f ==================== */ -void UI_PushReturnMenu_f( void ) { - UI_PushReturnMenu(); +void UI_PushReturnMenu_f(void) +{ + UI_PushReturnMenu(); } /* @@ -3039,59 +2979,54 @@ void UI_PushReturnMenu_f( void ) { UI_MenuEscape ==================== */ -void UI_MenuEscape( const char *name ) { - if( server_loading ) { - return; - } +void UI_MenuEscape(const char *name) +{ + if (server_loading) { + return; + } - if( uWinMan.BindActive() ) - { - UI_KeyEvent( K_ESCAPE, qfalse ); - } - else if( menuManager.CurrentMenu() != mainmenu || clc.state != CA_DISCONNECTED ) - { - if( uWinMan.DialogExists() ) - { - uWinMan.RemoveAllDialogBoxes(); - } - else - { - if( menuManager.CurrentMenu() ) - { - menuManager.PopMenu( qtrue ); - } - else if( !Q_stricmp( name, "main" ) && clc.state > CA_PRIMED && cg_gametype->integer > 0 ) - { - UI_PushMenu( "dm_main" ); - } - else - { - UI_PushMenu( name ); - } + if (uWinMan.BindActive()) { + UI_KeyEvent(K_ESCAPE, qfalse); + return; + } - UI_FocusMenuIfExists(); + if (menuManager.CurrentMenu() == mainmenu && clc.state == CA_DISCONNECTED) { + if (developer->integer) { + if (UI_ConsoleIsVisible()) { + UI_CloseConsole(); + } else { + UI_OpenConsole(); + } + } + return; + } - if( menuManager.CurrentMenu() ) - { - if( !memcmp( name, "main", 5 ) ) - { - UI_MainMenuWidgetsUpdate(); - } - else if( !memcmp( name, "multiplayer", 12 ) ) - { - UI_MultiplayerMenuWidgetsUpdate(); - } - } - } - } - else if( developer->integer ) - { - if( UI_ConsoleIsVisible() ) { - UI_CloseConsole(); - } else { - UI_OpenConsole(); - } - } + if (uWinMan.DialogExists()) { + uWinMan.RemoveAllDialogBoxes(); + return; + } + + if (menuManager.CurrentMenu()) { + menuManager.PopMenu(qtrue); + } else if (!Q_stricmp(name, "main") && clc.state > CA_PRIMED && cg_gametype->integer > 0) { + // multiplayer + UI_PushMenu("dm_main"); + } else { + // single-player + UI_PushMenu(name); + } + + UI_FocusMenuIfExists(); + + if (menuManager.CurrentMenu()) { + if (!str::cmp(name, "main")) { + UI_MainMenuWidgetsUpdate(); + } else if (!str::cmp(name, "dm_main")) { + UI_MultiplayerMainMenuWidgetsUpdate(); + } else if (!str::cmp(name, "multiplayer")) { + UI_MultiplayerMenuWidgetsUpdate(); + } + } } /* @@ -3099,9 +3034,10 @@ void UI_MenuEscape( const char *name ) { UI_ForceMenuOff ==================== */ -void UI_ForceMenuOff( bool force ) { - menuManager.ClearMenus( force ); - UI_FocusMenuIfExists(); +void UI_ForceMenuOff(bool force) +{ + menuManager.ClearMenus(force); + UI_FocusMenuIfExists(); } /* @@ -3109,34 +3045,30 @@ void UI_ForceMenuOff( bool force ) { UI_UpdateConnectionString ==================== */ -void UI_UpdateConnectionString( void ) { -} +void UI_UpdateConnectionString(void) {} /* ==================== UI_ParseServerInfoMessage ==================== */ -void UI_ParseServerInfoMessage( msg_t *msg ) { - -} +void UI_ParseServerInfoMessage(msg_t *msg) {} /* ==================== UI_DrawConnectText ==================== */ -void UI_DrawConnectText( void ) { - -} +void UI_DrawConnectText(void) {} /* ==================== UI_DrawConnect ==================== */ -void UI_DrawConnect( void ) { - Com_Printf( "UI_DrawConnect called\n" ); +void UI_DrawConnect(void) +{ + Com_Printf("UI_DrawConnect called\n"); } /* @@ -3144,55 +3076,49 @@ void UI_DrawConnect( void ) { CL_PingServers_f ==================== */ -void CL_PingServers_f( void ) { - int i; - netadr_t adr; - char name[ 32 ]; - const char *adrstring; - cvar_t *noudp; - cvar_t *noipx; +void CL_PingServers_f(void) +{ + int i; + netadr_t adr; + char name[32]; + const char *adrstring; + cvar_t *noudp; + cvar_t *noipx; - Com_Printf( "pinging broadcast...\n" ); + Com_Printf("pinging broadcast...\n"); - noudp = Cvar_Get( "noudp", "0", CVAR_INIT ); - if( !noudp->integer ) - { - adr.type = NA_BROADCAST; - adr.port = BigShort( 12203 ); - NET_OutOfBandPrint( NS_SERVER, adr, "info %i", 8 ); - } + noudp = Cvar_Get("noudp", "0", CVAR_INIT); + if (!noudp->integer) { + adr.type = NA_BROADCAST; + adr.port = BigShort(12203); + CL_NET_OutOfBandPrint(adr, "info %i", 8); + } - noipx = Cvar_Get( "noipx", "0", CVAR_INIT ); - if( !noipx->integer ) - { - adr.type = NA_BROADCAST_IPX; - adr.port = BigShort( 12203 ); - NET_OutOfBandPrint( NS_SERVER, adr, "info %i", 8 ); - } + noipx = Cvar_Get("noipx", "0", CVAR_INIT); + if (!noipx->integer) { + adr.type = NA_BROADCAST_IPX; + adr.port = BigShort(12203); + CL_NET_OutOfBandPrint(adr, "info %i", 8); + } - for( i = 0; i < 16; i++ ) - { - Com_sprintf( name, sizeof( name ), "adr%i", i ); - adrstring = Cvar_VariableString( name ); + for (i = 0; i < 16; i++) { + Com_sprintf(name, sizeof(name), "adr%i", i); + adrstring = Cvar_VariableString(name); - if( adrstring && *adrstring ) - { - Com_Printf( "pinging %s...\n", adrstring ); + if (adrstring && *adrstring) { + Com_Printf("pinging %s...\n", adrstring); - if( NET_StringToAdr( adrstring, &adr, NA_IP ) ) - { - if( !adr.port ) { - adr.port = BigShort( 12203 ); - } + if (NET_StringToAdr(adrstring, &adr, NA_IP)) { + if (!adr.port) { + adr.port = BigShort(12203); + } - NET_OutOfBandPrint( NS_SERVER, adr, "info %i", 8 ); - } - else - { - Com_Printf( "Bad address: %s\n", adrstring ); - } - } - } + CL_NET_OutOfBandPrint(adr, "info %i", 8); + } else { + Com_Printf("Bad address: %s\n", adrstring); + } + } + } } /* @@ -3200,19 +3126,19 @@ void CL_PingServers_f( void ) { UI_MapList_f ==================== */ -void UI_MapList_f( void ) { - str mappath = "maps"; +void UI_MapList_f(void) +{ + str mappath = "maps"; - if( Cmd_Argc() == 2 ) - { - mappath += "/"; - mappath += Cmd_Argv( 1 ); - } + if (Cmd_Argc() == 2) { + mappath += "/"; + mappath += Cmd_Argv(1); + } - MapRunnerClass *map = new MapRunnerClass; - map->Setup( "maps", mappath, ".bsp" ); + MapRunnerClass *map = new MapRunnerClass; + map->Setup("maps", mappath, ".bsp", "_sml"); - CL_SetMousePos( cls.glconfig.vidWidth / 2, cls.glconfig.vidHeight / 2 ); + CL_SetMousePos(uid.vidWidth / 2, uid.vidHeight / 2); } /* @@ -3220,26 +3146,39 @@ void UI_MapList_f( void ) { UI_DMMapSelect_f ==================== */ -void UI_DMMapSelect_f( void ) { - str basepath = "maps"; - str mappath = "maps"; +void UI_DMMapSelect_f(void) +{ + str basepath = "maps"; + str mappath; + str gametype; - if( Cmd_Argc() > 1 ) - { - mappath += "/"; - mappath += Cmd_Argv( 1 ); - } + if (Cmd_Argc() > 1) { + const char *path; - if( Cmd_Argc() > 2 ) - { - basepath += "/"; - basepath += Cmd_Argv( 2 ); - } + path = Cmd_Argv(1); - MpMapPickerClass *map = new MpMapPickerClass; - map->Setup( basepath, mappath ); + if (strcmp(path, ".")) { + basepath += "/"; + basepath += path; + } - CL_SetMousePos( cls.glconfig.vidWidth / 2, cls.glconfig.vidHeight / 2 ); + if (Cmd_Argc() > 2) { + path = Cmd_Argv(2); + if (strcmp(path, ".")) { + mappath += "maps/"; + mappath += path; + } + } + + if (Cmd_Argc() > 3) { + gametype = Cmd_Argv(3); + } + } + + MpMapPickerClass *map = new MpMapPickerClass; + map->Setup(basepath, mappath, gametype); + + CL_SetMousePos(uid.vidWidth / 2, uid.vidHeight / 2); } /* @@ -3247,147 +3186,156 @@ void UI_DMMapSelect_f( void ) { UI_StartDMMap_f ==================== */ -void UI_StartDMMap_f( void ) { - int iDedicated; - int iMaxClients; - int iUseGameSpy; - int iGameType = GT_FFA; - int iFragLimit; - int iTimeLimit; - int iTeamDamage; - int iInactiveSpectate; - int iInactiveKick; - const char *pszTemp; - const char *pszGameTypeString = "Free-For-All"; - const char *pszMapName; - const char *pszMapListCvar = "sv_maplist"; - const char *pszMapListString; - char szHostName[ 32 ]; +void UI_StartDMMap_f(void) +{ + int iDedicated; + int iMaxClients; + int iUseGameSpy; + int iGameType = GT_FFA; + int iFragLimit; + int iTimeLimit; + int iTeamDamage; + int iInactiveSpectate; + int iInactiveKick; + const char *pszTemp; + const char *pszGameTypeString = "Free-For-All"; + const char *pszMapName; + const char *pszMapListCvar = "sv_maplist"; + const char *pszMapListString; + char szHostName[32]; - if( Cmd_Argc() > 1 ) - { - iGameType = atoi( Cmd_Argv( 1 ) ); - if( Cmd_Argc() > 2 ) { - pszGameTypeString = Cmd_Argv( 2 ); + if (Cmd_Argc() > 1) { + iGameType = atoi(Cmd_Argv(1)); + if (Cmd_Argc() > 2) { + pszGameTypeString = Cmd_Argv(2); - if( Cmd_Argc() > 3 ) { - pszMapListCvar = Cmd_Argv( 3 ); - } - } - } + if (Cmd_Argc() > 3) { + pszMapListCvar = Cmd_Argv(3); + } + } + } - pszMapName = CvarGetForUI( "ui_dmmap", "" ); + pszMapName = CvarGetForUI("ui_dmmap", ""); - if( !*pszMapName ) { - return; - } + if (!*pszMapName) { + return; + } - iDedicated = atoi( CvarGetForUI( "ui_dedicated", "0" ) ); + iDedicated = atoi(CvarGetForUI("ui_dedicated", "0")); - if( iDedicated < 0 ) { - iDedicated = 0; - } else if( iDedicated > 1 ) { - iDedicated = 1; - } + if (iDedicated < 0) { + iDedicated = 0; + } else if (iDedicated > 1) { + iDedicated = 1; + } - Cvar_SetValue( "ui_dedicated", iDedicated ); + Cvar_SetValue("ui_dedicated", iDedicated); - iMaxClients = atoi( CvarGetForUI( "ui_maxclients", "0" ) ); + iMaxClients = atoi(CvarGetForUI("ui_maxclients", "0")); - if( iMaxClients < 1 ) { - iMaxClients = 1; - } else if( iMaxClients > MAX_CLIENTS ) { - iMaxClients = MAX_CLIENTS; - } + if (iMaxClients < 1) { + iMaxClients = 1; + } else if (iMaxClients > MAX_CLIENTS) { + iMaxClients = MAX_CLIENTS; + } - Cvar_SetValue( "ui_maxclients", iMaxClients ); + Cvar_SetValue("ui_maxclients", iMaxClients); - iUseGameSpy = atoi( CvarGetForUI( "ui_gamespy", "0" ) ); + iUseGameSpy = atoi(CvarGetForUI("ui_gamespy", "0")); - if( iUseGameSpy < 0 ) { - iUseGameSpy = 0; - } else if( iUseGameSpy > 1 ) { - iUseGameSpy = 1; - } + if (iUseGameSpy < 0) { + iUseGameSpy = 0; + } else if (iUseGameSpy > 1) { + iUseGameSpy = 1; + } - Cvar_SetValue( "ui_gamespy", iUseGameSpy ); + Cvar_SetValue("ui_gamespy", iUseGameSpy); - iFragLimit = atoi( CvarGetForUI( "ui_fraglimit", "0" ) ); + iFragLimit = atoi(CvarGetForUI("ui_fraglimit", "0")); - if( iFragLimit < 0 ) { - iFragLimit = 0; - } + if (iFragLimit < 0) { + iFragLimit = 0; + } - Cvar_SetValue( "ui_fraglimit", iFragLimit ); + Cvar_SetValue("ui_fraglimit", iFragLimit); - iTimeLimit = atoi( CvarGetForUI( "ui_timelimit", "0" ) ); + iTimeLimit = atoi(CvarGetForUI("ui_timelimit", "0")); - if( iTimeLimit < 0 ) { - iTimeLimit = 0; - } + if (iTimeLimit < 0) { + iTimeLimit = 0; + } - Cvar_SetValue( "ui_timelimit", iTimeLimit ); + Cvar_SetValue("ui_timelimit", iTimeLimit); - iTeamDamage = atoi( CvarGetForUI( "ui_teamdamage", "0" ) ); + iTeamDamage = atoi(CvarGetForUI("ui_teamdamage", "0")); - if( iTeamDamage < 0 ) { - iTeamDamage = 0; - } else if( iTeamDamage > 1 ) { - iTeamDamage = 1; - } + if (iTeamDamage < 0) { + iTeamDamage = 0; + } else if (iTeamDamage > 1) { + iTeamDamage = 1; + } - Cvar_SetValue( "ui_teamdamage", iTeamDamage ); + Cvar_SetValue("ui_teamdamage", iTeamDamage); - iInactiveSpectate = atoi( CvarGetForUI( "ui_inactivespectate", "0" ) ); + iInactiveSpectate = atoi(CvarGetForUI("ui_inactivespectate", "0")); - if( iInactiveSpectate < 0 ) { - iInactiveSpectate = 0; - } + if (iInactiveSpectate < 0) { + iInactiveSpectate = 0; + } - Cvar_SetValue( "ui_inactivespectate", iInactiveSpectate ); + Cvar_SetValue("ui_inactivespectate", iInactiveSpectate); - iInactiveKick = atoi( CvarGetForUI( "ui_inactivekick", "0" ) ); + iInactiveKick = atoi(CvarGetForUI("ui_inactivekick", "0")); - if( iInactiveKick < 0 ) { - iInactiveKick = 0; - } + if (iInactiveKick < 0) { + iInactiveKick = 0; + } - Cvar_SetValue( "ui_inactivekick", iInactiveKick ); + Cvar_SetValue("ui_inactivekick", iInactiveKick); - pszMapListString = CvarGetForUI( pszMapListCvar, "" ); + pszMapListString = CvarGetForUI(pszMapListCvar, ""); - pszTemp = CvarGetForUI( "ui_hostname", "Nameless Battle" ); - Q_strncpyz( szHostName, pszTemp, sizeof( szHostName ) ); + pszTemp = CvarGetForUI("ui_hostname", "Nameless Battle"); + Q_strncpyz(szHostName, pszTemp, sizeof(szHostName)); - for( int i = 0; i < sizeof( szHostName ); i++ ) - { - if( szHostName[ i ] == ';' || szHostName[ i ] == '"' || szHostName[ i ] == '\\' ) { - szHostName[ i ] = '_'; - } - } + for (int i = 0; i < sizeof(szHostName); i++) { + if (szHostName[i] == ';' || szHostName[i] == '"' || szHostName[i] == '\\') { + szHostName[i] = '_'; + } + } - Cvar_Set( "ui_hostname", szHostName ); + Cvar_Set("ui_hostname", szHostName); - Cbuf_AddText( - va( "set dedicated %i;" - "set sv_maxclients %i;" - "set sv_gamespy %i;" - "set g_gametype %i;" - "set g_gametypestring \"%s\";" - "set fraglimit %i;" - "set timelimit %i;" - "set g_teamdamage %i;" - "set g_inactivespectate %i;" - "set g_inactivekick %i;" - "set sv_maplist \"%s\";" - "set sv_hostname \"%s\";" - "set cheats 0;" - "wait;" - "map \"%s\"\n", - iDedicated, iMaxClients, iUseGameSpy, iGameType, pszGameTypeString, - iFragLimit, iTimeLimit, iTeamDamage, - iInactiveSpectate, iInactiveKick, - pszMapListString, szHostName, pszMapName ) ); + Cbuf_AddText( + va("set dedicated %i;" + "set sv_maxclients %i;" + "set sv_gamespy %i;" + "set g_gametype %i;" + "set g_gametypestring \"%s\";" + "set fraglimit %i;" + "set timelimit %i;" + "set g_teamdamage %i;" + "set g_inactivespectate %i;" + "set g_inactivekick %i;" + "set sv_maplist \"%s\";" + "set sv_hostname \"%s\";" + "set cheats 0;" + "wait;" + "map \"%s\"\n", + iDedicated, + iMaxClients, + iUseGameSpy, + iGameType, + pszGameTypeString, + iFragLimit, + iTimeLimit, + iTeamDamage, + iInactiveSpectate, + iInactiveKick, + pszMapListString, + szHostName, + pszMapName) + ); } /* @@ -3395,25 +3343,26 @@ void UI_StartDMMap_f( void ) { UI_PlayerModel_f ==================== */ -void UI_PlayerModel_f( void ) { - qboolean bGermanModel; - str modelpath = "models/player"; +void UI_PlayerModel_f(void) +{ + qboolean bGermanModel; + str modelpath = "models/player"; - bGermanModel = qfalse; + bGermanModel = qfalse; - if( Cmd_Argc() > 1 ) - { - bGermanModel = atoi( Cmd_Argv( 1 ) ) ? qtrue : qfalse; + if (Cmd_Argc() > 1) { + bGermanModel = atoi(Cmd_Argv(1)) ? qtrue : qfalse; - if( Cmd_Argc() == 3 ) - { - modelpath += "/"; - modelpath += Cmd_Argv( 2 ); - } - } + if (Cmd_Argc() == 3) { + modelpath += "/"; + modelpath += Cmd_Argv(2); + } + } - PlayerModelPickerClass *picker = new PlayerModelPickerClass; - picker->Setup( "models/player", modelpath, bGermanModel ); + PlayerModelPickerClass *picker = new PlayerModelPickerClass; + picker->Setup("models/player", modelpath, bGermanModel); + + CL_SetMousePos(uid.vidWidth / 2, uid.vidHeight / 2); } /* @@ -3421,16 +3370,23 @@ void UI_PlayerModel_f( void ) { UI_ApplyPlayerModel_f ==================== */ -void UI_ApplyPlayerModel_f( void ) { - const char *pszUIPlayerModel; +void UI_ApplyPlayerModel_f(void) +{ + const char *pszUIPlayerModel; + char donotshowssindeorfr[64]; - pszUIPlayerModel = CvarGetForUI( "ui_dm_playermodel", "american_army" ); - Cvar_Set( "dm_playermodel", pszUIPlayerModel ); + pszUIPlayerModel = CvarGetForUI("ui_dm_playermodel_set", "american_army"); + Cvar_Set("dm_playermodel", pszUIPlayerModel); - pszUIPlayerModel = CvarGetForUI( "ui_dm_playergermanmodel", "german_wehrmacht_soldier" ); - Cvar_Set( "ui_dm_playergermanmodel", pszUIPlayerModel ); + pszUIPlayerModel = CvarGetForUI("ui_dm_playergermanmodel_set", "german_wehrmacht_soldier"); + if (!Q_stricmpn(pszUIPlayerModel, "german_waffen", 14)) { + Q_strcat(donotshowssindeorfr, sizeof(donotshowssindeorfr), pszUIPlayerModel + 14); + Cvar_Set("dm_playergermanmodel", donotshowssindeorfr); + } else { + Cvar_Set("dm_playergermanmodel", pszUIPlayerModel); + } - Cvar_Set( "name", CvarGetForUI( "ui_name", "*** Blank Name ***" ) ); + Cvar_Set("name", CvarGetForUI("ui_name", "UnnamedSoldier")); } /* @@ -3438,31 +3394,35 @@ void UI_ApplyPlayerModel_f( void ) { UI_GetPlayerModel_f ==================== */ -void UI_GetPlayerModel_f( void ) { - const char *pszUIPlayerModel; - char donotshowssindeorfr[ 64 ]; +void UI_GetPlayerModel_f(void) +{ + const char *pszUIPlayerModel; + char donotshowssindeorfr[64]; - pszUIPlayerModel = CvarGetForUI( "dm_playermodel", "american_army" ); - Cvar_Set( "ui_dm_playermodel", pszUIPlayerModel ); + // + // Allies + // + pszUIPlayerModel = CvarGetForUI("dm_playermodel", "american_army"); + Cvar_Set("ui_dm_playermodel", PM_FilenameToDisplayname(pszUIPlayerModel)); + Cvar_Set("ui_dm_playermodel_set", pszUIPlayerModel); + Cvar_Set("ui_disp_playermodel", va("models/player/%s.tik", pszUIPlayerModel)); - Cvar_Set( "ui_disp_playermodel", va( "models/player/%s.tik", pszUIPlayerModel ) ); + // + // Axis + // + pszUIPlayerModel = CvarGetForUI("dm_playergermanmodel", "german_wehrmacht_soldier"); + Cvar_Set("ui_dm_playergermanmodel", PM_FilenameToDisplayname(pszUIPlayerModel)); + Cvar_Set("ui_dm_playergermanmodel_set", pszUIPlayerModel); - pszUIPlayerModel = CvarGetForUI( "dm_playergermanmodel", "german_wehrmacht_soldier" ); - Cvar_Set( "ui_dm_playergermanmodel", pszUIPlayerModel ); + if (!strncmp(pszUIPlayerModel, "german_waffen_", 14)) { + Q_strncpyz(donotshowssindeorfr, "german_waffenss_", sizeof(donotshowssindeorfr)); + Q_strcat(donotshowssindeorfr, sizeof(donotshowssindeorfr), pszUIPlayerModel + 14); + Cvar_Set("ui_disp_playergermanmodel", va("models/player/%s.tik", donotshowssindeorfr)); + } else { + Cvar_Set("ui_disp_playergermanmodel", va("models/player/%s.tik", pszUIPlayerModel)); + } - if( !strncmp( pszUIPlayerModel, "german_waffen_", 14 ) ) - { - memcpy( donotshowssindeorfr, "german_waffenss_", 17 ); - strncat( donotshowssindeorfr, pszUIPlayerModel + 14, 48 ); - } - else - { - strncpy( donotshowssindeorfr, pszUIPlayerModel, sizeof( donotshowssindeorfr ) ); - } - - Cvar_Set( "ui_disp_playergermanmodel", va( "models/player/%s.tik", donotshowssindeorfr ) ); - - Cvar_Set( "ui_name", CvarGetForUI( "name", "*** Blank Name ***" ) ); + Cvar_Set("ui_name", CvarGetForUI("name", "UnnamedSoldier")); } /* @@ -3470,8 +3430,9 @@ void UI_GetPlayerModel_f( void ) { UI_SoundPicker_f ==================== */ -void UI_SoundPicker_f( void ) { - new SoundPickerClass; +void UI_SoundPicker_f(void) +{ + new SoundPickerClass; } /* @@ -3479,11 +3440,12 @@ void UI_SoundPicker_f( void ) { UI_ViewSpawnList_f ==================== */ -void UI_ViewSpawnList_f( void ) { - str modelpath = "models"; +void UI_ViewSpawnList_f(void) +{ + str modelpath = "models"; - ViewSpawnerClass *picker = new ViewSpawnerClass; - picker->Setup( "models", modelpath, ".tik" ); + ViewSpawnerClass *picker = new ViewSpawnerClass; + picker->Setup("models", modelpath, ".tik"); } /* @@ -3491,11 +3453,12 @@ void UI_ViewSpawnList_f( void ) { UI_LODSpawnList_f ==================== */ -void UI_LODSpawnList_f( void ) { - str modelpath = "models"; +void UI_LODSpawnList_f(void) +{ + str modelpath = "models"; - LODSpawnerClass *picker = new LODSpawnerClass; - picker->Setup( "models", modelpath, ".tik" ); + LODSpawnerClass *picker = new LODSpawnerClass; + picker->Setup("models", modelpath, ".tik"); } /* @@ -3503,12 +3466,13 @@ void UI_LODSpawnList_f( void ) { UI_Notepad_f ==================== */ -void UI_Notepad_f( void ) { - if( Cmd_Argc() > 1 ) { - UI_LoadNotepadFile( Cmd_Argv( 1 ) ); - } else { - UI_LoadNotepadFile( NULL ); - } +void UI_Notepad_f(void) +{ + if (Cmd_Argc() > 1) { + UI_LoadNotepadFile(Cmd_Argv(1)); + } else { + UI_LoadNotepadFile(NULL); + } } /* @@ -3516,41 +3480,39 @@ void UI_Notepad_f( void ) { UI_EditScript_f ==================== */ -void UI_EditScript_f( void ) { - const char *info; - const char *mname; - str mapname; - str mappath; +void UI_EditScript_f(void) +{ + const char *info; + const char *mname; + str mapname; + str mappath; - // editscript only works in-game - if( clc.state != CA_ACTIVE ) - { - Com_Printf( "You need to load a map to edit its script\n" ); - return; - } + // editscript only works in-game + if (clc.state != CA_ACTIVE) { + Com_Printf("You need to load a map to edit its script\n"); + return; + } - mname = Info_ValueForKey( &cl.gameState.stringData[ cl.gameState.stringOffsets[ CS_SERVERINFO ] ], "mapname" ); - mapname = mname; + mname = Info_ValueForKey(&cl.gameState.stringData[cl.gameState.stringOffsets[CS_SERVERINFO]], "mapname"); + mapname = mname; - // remove the spawnpoint name - if( strchr( mname, '$' ) ) - { - info = strchr( mname, '$' ); - mapname[ info - mname ] = 0; - } + // remove the spawnpoint name + if (strchr(mname, '$')) { + info = strchr(mname, '$'); + mapname[info - mname] = 0; + } - // make sure the map is loaded - if( !strcmp( mapname, "" ) ) - { - Com_Printf( "No map loaded?\n" ); - return; - } + // make sure the map is loaded + if (!strcmp(mapname, "")) { + Com_Printf("No map loaded?\n"); + return; + } - mappath = "maps/" + mapname + ".scr"; + mappath = "maps/" + mapname + ".scr"; - if( !UI_LoadNotepadFile( mappath ) ) { - Com_Printf( "Couldn't load/find script file for %s\n", mappath.c_str() ); - } + if (!UI_LoadNotepadFile(mappath)) { + Com_Printf("Couldn't load/find script file for %s\n", mappath.c_str()); + } } /* @@ -3558,19 +3520,20 @@ void UI_EditScript_f( void ) { UI_EditShader_f ==================== */ -void UI_EditShader_f( void ) { - str shaderpath; +void UI_EditShader_f(void) +{ + str shaderpath; - if( Cmd_Argc() != 2 ) { - Com_Printf( "Usage: Editshader \n" ); - return; - } + if (Cmd_Argc() != 2) { + Com_Printf("Usage: Editshader \n"); + return; + } - shaderpath = "scripts/" + str( Cmd_Argv( 1 ) ) + ".shader"; + shaderpath = "scripts/" + str(Cmd_Argv(1)) + ".shader"; - if( !UI_LoadNotepadFile( shaderpath ) ) { - Com_Printf( "Couldn't open shader named %s\n", shaderpath.c_str() ); - } + if (!UI_LoadNotepadFile(shaderpath)) { + Com_Printf("Couldn't open shader named %s\n", shaderpath.c_str()); + } } /* @@ -3578,24 +3541,24 @@ void UI_EditShader_f( void ) { UI_EditSpecificShader_f ==================== */ -void UI_EditSpecificShader_f( void ) { -} +void UI_EditSpecificShader_f(void) {} /* ==================== UI_LoadMenu ==================== */ -void UI_LoadMenu( const char *name ) { - char buffer[ 256 ]; +void UI_LoadMenu(const char *name) +{ + char buffer[256]; - Com_sprintf( buffer, sizeof( buffer ), "ui/%s", name ); - COM_StripExtension( buffer, buffer, sizeof( buffer ) ); - Q_strcat( buffer, 256, ".urc" ); + Com_sprintf(buffer, sizeof(buffer), "ui/%s", name); + COM_StripExtension(buffer, buffer, sizeof(buffer)); + Q_strcat(buffer, 256, ".urc"); - new UILayout( buffer ); - uWinMan.CreateMenus(); - UI_FocusMenuIfExists(); + new UILayout(buffer); + uWinMan.CreateMenus(); + UI_FocusMenuIfExists(); } /* @@ -3603,8 +3566,9 @@ void UI_LoadMenu( const char *name ) { UI_LoadMenu_f ==================== */ -void UI_LoadMenu_f( void ) { - UI_LoadMenu( Cmd_Argv( 1 ) ); +void UI_LoadMenu_f(void) +{ + UI_LoadMenu(Cmd_Argv(1)); } /* @@ -3612,20 +3576,19 @@ void UI_LoadMenu_f( void ) { CvarGetForUI ==================== */ -const char *CvarGetForUI( const char *name, const char *defval ) { - cvar_t *cvar = Cvar_FindVar( name ); +const char *CvarGetForUI(const char *name, const char *defval) +{ + cvar_t *cvar = Cvar_FindVar(name); - if( cvar ) { - if( cvar->latchedString && *cvar->latchedString ) { - return cvar->latchedString; - } else { - return cvar->string; - } - } - else - { - return defval; - } + if (cvar) { + if (cvar->latchedString && *cvar->latchedString) { + return cvar->latchedString; + } else { + return cvar->string; + } + } else { + return defval; + } } /* @@ -3633,18 +3596,18 @@ const char *CvarGetForUI( const char *name, const char *defval ) { ListFilesForUI ==================== */ -void ListFilesForUI( const char *filespec ) +void ListFilesForUI(const char *filespec) { - int nfiles; - char **filenames; + int nfiles; + char **filenames; - filenames = FS_ListFiles( "", filespec, qfalse, &nfiles ); + filenames = FS_ListFiles("", filespec, qfalse, &nfiles); - for( int i = 0; i < nfiles; i++ ) { - uie.AddFileToList( filenames[ i ] ); - } + for (int i = 0; i < nfiles; i++) { + uie.AddFileToList(filenames[i]); + } - FS_FreeFileList( filenames ); + FS_FreeFileList(filenames); } /* @@ -3652,8 +3615,9 @@ void ListFilesForUI( const char *filespec ) IsKeyDown ==================== */ -int IsKeyDown( int key ) { - return keys[ key ].down; +int IsKeyDown(int key) +{ + return keys[key].down; } /* @@ -3661,19 +3625,19 @@ int IsKeyDown( int key ) { UI_WantsKeyboard ==================== */ -void UI_WantsKeyboard() { - cls.keyCatchers |= KEYCATCH_UI; +void UI_WantsKeyboard() +{ + Key_SetCatcher(Key_GetCatcher() | KEYCATCH_UI); } struct widgettrans_s { - const char *src; - const char *dst; + const char *src; + const char *dst; }; -static widgettrans_s s_widgettrans[ 2 ] = -{ - { "Label", "FakkLabel" }, - { NULL, NULL } +static widgettrans_s s_widgettrans[2] = { + {"Label", "FakkLabel"}, + {NULL, NULL } }; /* @@ -3681,17 +3645,17 @@ static widgettrans_s s_widgettrans[ 2 ] = TranslateWidgetName ==================== */ -const char *TranslateWidgetName( const char *widget ) { - widgettrans_s *trans = &s_widgettrans[ 0 ]; +const char *TranslateWidgetName(const char *widget) +{ + widgettrans_s *trans = &s_widgettrans[0]; - for( int i = 0; trans->src != NULL; i++, trans++ ) - { - if( !strcmp( trans->src, widget ) ) { - return trans->dst; - } - } + for (int i = 0; trans->src != NULL; i++, trans++) { + if (!strcmp(trans->src, widget)) { + return trans->dst; + } + } - return NULL; + return NULL; } /* @@ -3699,8 +3663,9 @@ const char *TranslateWidgetName( const char *widget ) { UI_Cvar_Set ==================== */ -void UI_Cvar_Set( const char *var_name, const char *value ) { - Cvar_Set2( var_name, value, qfalse ); +void UI_Cvar_Set(const char *var_name, const char *value) +{ + Cvar_Set2(var_name, value, qfalse); } /* @@ -3708,20 +3673,63 @@ void UI_Cvar_Set( const char *var_name, const char *value ) { CL_FillUIDef ==================== */ -void CL_FillUIDef( void ) { - CL_GetMouseState( &uid.mouseX, &uid.mouseY, &uid.mouseFlags ); - uid.time = cls.realtime; - uid.vidHeight = cls.glconfig.vidHeight; - uid.vidWidth = cls.glconfig.vidWidth; - uid.uiHasMouse = in_guimouse != qfalse; +void CL_FillUIDef(void) +{ + CL_GetMouseState(&uid.mouseX, &uid.mouseY, &uid.mouseFlags); + uid.time = cls.realtime; + uid.vidHeight = cls.glconfig.vidHeight; + uid.vidWidth = cls.glconfig.vidWidth; + uid.uiHasMouse = in_guimouse != qfalse; } -sfxHandle_t UI_RegisterSound( const char *sample, qboolean streamed ) { - return S_RegisterSound( sample, streamed, qfalse ); +/* +==================== +UI_RegisterSound +==================== +*/ +sfxHandle_t UI_RegisterSound(const char *sample, qboolean streamed) +{ + return S_RegisterSound(sample, streamed, qfalse); } -void UI_StartLocalSound( const char *sound_name ) { - S_StartLocalSound( sound_name, qtrue ); +/* +==================== +UI_FadeSound +==================== +*/ +void UI_FadeSound(float fTime) +{ + S_FadeSound(fTime); +} + +/* +==================== +UI_StopAll +==================== +*/ +void UI_StopAll() +{ + S_StopAllSounds2(qtrue); +} + +/* +==================== +UI_StartLocalSound +==================== +*/ +void UI_StartLocalSound(const char *sound_name) +{ + S_StartLocalSound(sound_name, qtrue); +} + +/* +==================== +UI_StartLocalSoundDialog +==================== +*/ +void UI_StartLocalSoundDialog(const char *sound_name) +{ + S_StartLocalSoundChannel(sound_name, qtrue, CHAN_DIALOG); } /* @@ -3729,164 +3737,75 @@ void UI_StartLocalSound( const char *sound_name ) { CL_FillUIImports ==================== */ -void CL_FillUIImports( void ) { - uii.Rend_DrawBox = re.DrawBox; - uii.Rend_DrawPicStretched = re.DrawStretchPic; - uii.Rend_DrawPicStretched2 = re.DrawStretchPic2; - uii.Rend_DrawPicTiled = re.DrawTilePic; - uii.Rend_GetShaderHeight = re.GetShaderHeight; - uii.Rend_GetShaderWidth = re.GetShaderWidth; - uii.Rend_DrawString = re.DrawString; - uii.Rend_LoadFont = re.LoadFont; - uii.Rend_RegisterMaterial = re.RegisterShaderNoMip; - uii.Rend_RefreshMaterial = re.RefreshShaderNoMip; - uii.Rend_Scissor = re.Scissor; - uii.Rend_Set2D = re.Set2DWindow; - uii.Rend_SetColor = re.SetColor; +void CL_FillUIImports(void) +{ + uii.Rend_DrawBox = re.DrawBox; + uii.Rend_DrawPicStretched = re.DrawStretchPic; + uii.Rend_DrawPicStretched2 = re.DrawStretchPic2; + uii.Rend_DrawPicTiled = re.DrawTilePic; + uii.Rend_GetShaderHeight = re.GetShaderHeight; + uii.Rend_GetShaderWidth = re.GetShaderWidth; + uii.Rend_DrawString = re.DrawString; + uii.Rend_LoadFont = re.LoadFont; + uii.Rend_RegisterMaterial = re.RegisterShaderNoMip; + uii.Rend_RefreshMaterial = re.RefreshShaderNoMip; + uii.Rend_Scissor = re.Scissor; + uii.Rend_Set2D = re.Set2DWindow; + uii.Rend_SetColor = re.SetColor; + uii.Rend_ImageExists = re.ImageExists; - uii.Cmd_Stuff = Cbuf_AddText; - uii.Cvar_GetString = CvarGetForUI; - uii.Cvar_Reset = Cvar_Reset; - uii.Cvar_Find = Cvar_FindVar; - uii.Cvar_Set = Cvar_Set; - uii.File_PickFile = PickFile; - uii.File_FreeFile = FS_FreeFile; - uii.File_ListFiles = ListFilesForUI; - uii.File_OpenFile = FS_ReadFile; - uii.File_WriteFile = FS_WriteTextFile; - uii.Snd_PlaySound = UI_StartLocalSound; - uii.Snd_RegisterSound = UI_RegisterSound; - uii.Alias_Add = Alias_Add; - uii.Alias_FindRandom = Alias_FindRandom; - uii.Sys_Error = Com_Error; - uii.Sys_IsKeyDown = IsKeyDown; - uii.Sys_Milliseconds = Sys_Milliseconds; - uii.Sys_Printf = Com_Printf; - uii.Sys_DPrintf = Com_DPrintf; - uii.Sys_GetClipboard = Sys_GetWholeClipboard; - uii.Sys_SetClipboard = Sys_SetClipboard; - uii.Cmd_CompleteCommandByNumber = Cmd_CompleteCommandByNumber; - uii.Cvar_CompleteCvarByNumber = Cvar_CompleteVariableByNumber; - uii.UI_WantsKeyboard = UI_WantsKeyboard; - uii.Client_TranslateWidgetName = TranslateWidgetName; - uii.Connect = CL_Connect; - uii.Key_GetKeynameForCommand = Key_GetKeynameForCommand; - uii.Key_GetCommandForKey = Key_GetBinding; - uii.Key_SetBinding = Key_SetBinding; - uii.Key_GetKeysForCommand = Key_GetKeysForCommand; - uii.Key_KeynumToString = Key_KeynumToBindString; + uii.Cmd_Stuff = Cbuf_AddText; + uii.Cvar_GetString = CvarGetForUI; + uii.Cvar_Reset = Cvar_Reset; + uii.Cvar_Find = Cvar_FindVar; + uii.Cvar_Set = UI_Cvar_Set; + uii.File_PickFile = PickFile; + uii.File_FreeFile = FS_FreeFile; + uii.File_ListFiles = ListFilesForUI; + uii.File_OpenFile = FS_ReadFile; + uii.File_WriteFile = FS_WriteTextFile; + uii.Snd_PlaySound = UI_StartLocalSound; + uii.Snd_PlaySoundDialog = UI_StartLocalSoundDialog; + uii.Snd_RegisterSound = UI_RegisterSound; + uii.Snd_FadeSound = UI_FadeSound; + uii.Snd_StopAllSound = UI_StopAll; + uii.Alias_Add = Alias_Add; + uii.Alias_FindRandom = Alias_FindRandom; + uii.Sys_Error = Com_Error; + uii.Sys_IsKeyDown = IsKeyDown; + uii.Sys_Milliseconds = Sys_Milliseconds; + uii.Sys_Printf = Com_Printf; + uii.Sys_DPrintf = Com_DPrintf; + uii.Sys_GetClipboard = Sys_GetWholeClipboard; + uii.Sys_SetClipboard = Sys_SetClipboard; + uii.Cmd_CompleteCommandByNumber = Cmd_CompleteCommandByNumber; + uii.Cvar_CompleteCvarByNumber = Cvar_CompleteVariableByNumber; + uii.UI_WantsKeyboard = UI_WantsKeyboard; + uii.Client_TranslateWidgetName = TranslateWidgetName; + uii.Connect = CL_Connect; + uii.Key_GetKeynameForCommand = Key_GetKeynameForCommand; + uii.Key_GetCommandForKey = Key_GetBinding; + uii.Key_SetBinding = Key_SetBinding; + uii.Key_GetKeysForCommand = Key_GetKeysForCommand; + uii.Key_KeynumToString = Key_KeynumToBindString; - uii.GetConfigstring = CL_ConfigString; - uii.UI_CloseDMConsole = UI_CloseDMConsole; + uii.GetConfigstring = CL_ConfigString; + uii.UI_CloseDMConsole = UI_CloseDMConsole; -#if 0 - uii.TIKI_RegisterModel = TIKI_RegisterTiki; - - uii.Cvar_Get = Cvar_Get; - uii.Argc = Cmd_Argc; - uii.Argv = Cmd_Argv; - uii.Cmd_ExecuteText = Cbuf_ExecuteText; - uii.FS_FOpenFile = FS_FOpenFileByMode; - uii.FS_Read = FS_Read; - uii.FS_Write = FS_Write; - uii.FS_FCloseFile = FS_FCloseFile; - uii.FS_GetFileList = FS_GetFileList; - uii.FS_Seek = FS_Seek; - uii.R_RegisterModel = re.RegisterModel; - uii.R_RegisterSkin = re.RegisterShader; - uii.R_RegisterShader = re.RegisterShader; - uii.R_RegisterShaderNoMip = re.RegisterShaderNoMip; - uii.R_ClearScene = re.ClearScene; - uii.R_AddRefEntityToScene = re.AddRefEntityToScene; - uii.R_AddPolyToScene = re.AddPolyToScene; - uii.R_AddLightToScene = re.AddLightToScene; - uii.R_RenderScene = re.RenderScene; - uii.R_SetColor = re.SetColor; - uii.R_DrawStretchPic = re.DrawStretchPic; - uii.UpdateScreen = SCR_UpdateScreen; - uii.S_StartLocalSound = S_StartLocalSound; - uii.S_RegisterSound = S_RegisterSound; - uii.Key_KeynumToStringBuf = Key_KeynumToStringBuf; - uii.Key_KeynumToString = Key_KeynumToString; - uii.Key_GetBindingBuf = Key_GetBindingBuf; - uii.Key_IsDown = Key_IsDown; - uii.Key_GetOverstrikeMode = Key_GetOverstrikeMode; - uii.Key_SetOverstrikeMode = Key_SetOverstrikeMode; - uii.Key_ClearStates = Key_ClearStates; - uii.Key_GetCatcher = Key_GetCatcher; - uii.Key_SetCatcher = Key_SetCatcher; - uii.GetClipboardData = CL_GetClipboardData; - uii.GetClientState = GetClientState; - uii.GetGlconfig = CL_GetGlconfig; - uii.GetConfigString = GetConfigString; - uii.LAN_GetServerCount = LAN_GetServerCount; - uii.LAN_GetServerAddressString = LAN_GetServerAddressString; - uii.LAN_GetServerInfo = LAN_GetServerInfo; - uii.LAN_GetPingQueueCount = LAN_GetPingQueueCount; - uii.LAN_ServerStatus = LAN_GetServerStatus; - uii.LAN_ClearPing = LAN_ClearPing; - uii.LAN_GetPing = LAN_GetPing; - uii.LAN_GetPingInfo = LAN_GetPingInfo; - uii.LAN_GetServerPing = LAN_GetServerPing; - uii.LAN_MarkServerVisible = LAN_MarkServerVisible; - uii.LAN_UpdateVisiblePings = LAN_UpdateVisiblePings; - uii.GetCDKey = CLUI_GetCDKey; - uii.SetCDKey = CLUI_SetCDKey; - uii.R_RegisterFont = re.RegisterFont; - uii.R_Text_Width = re.Text_Width; - uii.R_Text_Height = re.Text_Height; - uii.R_Text_Paint = re.Text_Paint; - uii.R_Text_PaintChar = re.Text_PaintChar; - uii.R_GetShaderName = re.GetShaderName; - - uii.Cmd_Stuff = Cbuf_AddText; - uii.Cvar_GetString = CvarGetForUI; - uii.Cvar_Reset = Cvar_Reset; - uii.Cvar_Find = Cvar_FindVar; - uii.Cvar_Set = UI_Cvar_Set; - uii.File_PickFile = PickFile; - uii.File_FreeFile = FS_FreeFile; - uii.File_ListFiles = ListFilesForUI; - uii.File_OpenFile = FS_ReadFile; - uii.File_WriteFile = FS_WriteTextFile; - uii.Rend_SetColor = re.SetColor; - uii.Snd_PlaySound = UI_StartLocalSound; - uii.Snd_RegisterSound = UI_RegisterSound; - uii.Alias_Add = Alias_Add; - uii.Alias_FindRandom = Alias_FindRandom; - uii.Sys_Error = Com_Error; - uii.Sys_IsKeyDown = IsKeyDown; - uii.Sys_Milliseconds = Sys_Milliseconds; - uii.Sys_Printf = Com_Printf; - uii.Sys_DPrintf = Com_DPrintf; - uii.Sys_GetClipboard = Sys_GetWholeClipboard; - uii.Sys_SetClipboard = Sys_SetClipboard; - uii.Cmd_CompleteCommandByNumber = Cmd_CompleteCommandByNumber; - uii.Cvar_CompleteCvarByNumber = Cvar_CompleteVariableByNumber; - uii.UI_WantsKeyboard = UI_WantsKeyboard; - uii.Client_TranslateWidgetName = TranslateWidgetName; - uii.Connect = CL_Connect; - uii.Key_GetKeynameForCommand = Key_GetKeynameForCommand; - uii.Key_GetCommandForKey = Key_GetBinding; - uii.Key_SetBinding = Key_SetBinding; - uii.Key_GetKeysForCommand = Key_GetKeysForCommand; - uii.Key_KeynumToString = Key_KeynumToBindString; - uii.GetConfigstring = CL_ConfigString; - uii.UI_CloseDMConsole = UI_CloseDMConsole; -#endif + uii.GetRefSequence = CL_GetRefSequence; + uii.IsRendererLoaded = CL_IsRendererLoaded; } - /* ==================== CL_BeginRegistration ==================== */ -void CL_BeginRegistration( void ) +void CL_BeginRegistration(void) { - // init console stuff - re.BeginRegistration( &cls.glconfig ); - uWinMan.CleanupShadersFromList(); + // init console stuff + re.BeginRegistration(&cls.glconfig); + uWinMan.CleanupShadersFromList(); } /* @@ -3894,22 +3813,22 @@ void CL_BeginRegistration( void ) CL_EndRegistration ==================== */ -void CL_EndRegistration( void ) +void CL_EndRegistration(void) { - int start, end; + int start, end; - start = Sys_Milliseconds(); + start = Sys_Milliseconds(); - S_EndRegistration(); - re.EndRegistration(); + S_EndRegistration(); + re.EndRegistration(); - if( !Sys_LowPhysicalMemory() ) { - Com_TouchMemory(); - } + if (!Sys_LowPhysicalMemory()) { + Com_TouchMemory(); + } - end = Sys_Milliseconds(); + end = Sys_Milliseconds(); - Com_Printf( "CL_EndRegistration: %5.2f seconds\n", ( float )( start - end ) / 1000.0 ); + Com_Printf("CL_EndRegistration: %5.2f seconds\n", (float)(start - end) / 1000.0); } /* @@ -3917,23 +3836,35 @@ void CL_EndRegistration( void ) UI_CreateDialog ==================== */ -void UI_CreateDialog( const char *title, char *cvarname, const char *command, const char *cancelCommand, int width, int height, const char *shader, const char *okshader, const char *cancelshader ) { - UIDialog *dlg = new UIDialog; - UIRect2D rect = UIRect2D( ( cls.glconfig.vidWidth - width ) >> 1, ( cls.glconfig.vidHeight - height ) >> 1, width, height ); - UColor bgColor = UWindowColor; +void UI_CreateDialog( + const char *title, + char *cvarname, + const char *command, + const char *cancelCommand, + int width, + int height, + const char *shader, + const char *okshader, + const char *cancelshader +) +{ + UIDialog *dlg = new UIDialog; + UIRect2D rect = + UIRect2D((uid.vidWidth - width) / 2, (uid.vidHeight - height) / 2, width, height); + UColor bgColor = UWindowColor; - dlg->Create( NULL, rect, title, bgColor, UHudColor ); - dlg->LinkCvar( cvarname ); - dlg->SetOKCommand( command ); - dlg->SetCancelCommand( command ); - dlg->SetLabelMaterial( uWinMan.RegisterShader( shader ) ); - dlg->SetOkMaterial( uWinMan.RegisterShader( okshader ) ); + dlg->Create(NULL, rect, title, bgColor, UHudColor); + dlg->LinkCvar(cvarname); + dlg->SetOKCommand(command); + dlg->SetCancelCommand(cancelCommand); + dlg->SetLabelMaterial(uWinMan.RegisterShader(shader)); + dlg->SetOkMaterial(uWinMan.RegisterShader(okshader)); - if( cancelshader ) { - dlg->SetCancelMaterial( uWinMan.RegisterShader( cancelshader ) ); - } + if (cancelshader) { + dlg->SetCancelMaterial(uWinMan.RegisterShader(cancelshader)); + } - uWinMan.ActivateControl( dlg ); + uWinMan.ActivateControl(dlg); } /* @@ -3941,67 +3872,83 @@ void UI_CreateDialog( const char *title, char *cvarname, const char *command, co UI_ResolutionChange ==================== */ -void UI_ResolutionChange( void ) { - UIRect2D frame; +void UI_ResolutionChange(void) +{ + UIRect2D frame; - ui_compass_scale = Cvar_Get("ui_compass_scale", "0.75", CVAR_ARCHIVE | CVAR_LATCH); - CL_FillUIImports(); - CL_FillUIDef(); + if (com_target_game->integer >= TG_MOHTA) { + ui_compass_scale = Cvar_Get("ui_compass_scale", "0.75", CVAR_ARCHIVE | CVAR_LATCH); + } else { + // Older version doesn't have an adjustable compass, so assume 0.5 by default + ui_compass_scale = Cvar_Get("ui_compass_scale", "0.55", CVAR_ARCHIVE | CVAR_LATCH); + } - if( !uie.ResolutionChange ) { - return; - } + CL_FillUIImports(); + CL_FillUIDef(); - if( fakk_console ) - { - frame = getDefaultConsoleRectangle(); - fakk_console->setFrame( frame ); - } + // Added in OPM + // Scaling for high resolutions + if (uid.vidWidth > maxWidthRes && uid.vidHeight > maxHeightRes) { + const float vidRatio = (float)uid.vidWidth / (float)uid.vidHeight; - if( dm_console ) - { - if( dm_console->GetQuickMessageMode() ) { - frame = getQuickMessageDMConsoleRectangle(); - } else { - frame = getDefaultDMConsoleRectangle(); - } + uid.scaleRes[0] = (float)uid.vidWidth / (maxHeightRes * vidRatio); + uid.scaleRes[1] = (float)uid.vidHeight / maxHeightRes; + //uid.scaleRes[0] = (float)uid.vidWidth / maxWidthRes; + //uid.scaleRes[1] = (float)uid.vidHeight / maxHeightRes; + uid.bHighResScaling = qtrue; + } else { + uid.scaleRes[0] = 1; + uid.scaleRes[1] = 1; + uid.bHighResScaling = qfalse; + } - dm_console->setFrame( frame ); - } + if (!uie.ResolutionChange) { + return; + } - if( developer_console ) - { - frame = getDefaultConsoleRectangle(); - developer_console->setFrame( frame ); - } + if (fakk_console) { + frame = getDefaultConsoleRectangle(); + fakk_console->setFrame(frame); + } - if( scoreboardlist ) - { - delete scoreboardlist; - scoreboardlist = NULL; - UI_CreateScoreboard(); - } + if (dm_console) { + if (dm_console->GetQuickMessageMode()) { + frame = getQuickMessageDMConsoleRectangle(); + } else { + frame = getDefaultDMConsoleRectangle(); + } - uie.ResolutionChange(); - menuManager.RealignMenus(); + dm_console->setFrame(frame); + } - if( view3d ) - { - frame = UIRect2D( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight ); - view3d->setFrame( frame ); - } + if (developer_console) { + frame = getDefaultConsoleRectangle(); + developer_console->setFrame(frame); + } - if( gmbox ) - { - frame = getDefaultGMBoxRectangle(); - gmbox->setFrame( frame ); - } + if (scoreboardlist) { + delete scoreboardlist; + scoreboardlist = NULL; + UI_CreateScoreboard(); + } - if( dmbox ) - { - frame = getDefaultDMBoxRectangle(); - dmbox->setFrame( frame ); - } + uie.ResolutionChange(); + menuManager.RealignMenus(); + + if (view3d) { + frame = UIRect2D(0, 0, uid.vidWidth, uid.vidHeight); + view3d->setFrame(frame); + } + + if (gmbox) { + frame = getDefaultGMBoxRectangle(); + gmbox->setFrame(frame); + } + + if (dmbox) { + frame = getDefaultDMBoxRectangle(); + dmbox->setFrame(frame); + } } /* @@ -4009,16 +3956,17 @@ void UI_ResolutionChange( void ) { UI_FinishLoadingScreen_f ==================== */ -void UI_FinishLoadingScreen_f( void ) { - Com_Unpause(); - UI_ForceMenuOff( qtrue ); +void UI_FinishLoadingScreen_f(void) +{ + Com_Unpause(); + UI_ForceMenuOff(qtrue); - ui_pLoadingMenu = NULL; - ui_sCurrentLoadingMenu = ""; - server_loading = qfalse; - server_loading_waiting = qfalse; + ui_pLoadingMenu = NULL; + ui_sCurrentLoadingMenu = ""; + server_loading = qfalse; + server_loading_waiting = qfalse; - UI_ActivateView3D(); + UI_ActivateView3D(); } /* @@ -4026,22 +3974,23 @@ void UI_FinishLoadingScreen_f( void ) { S_ServerLoaded ==================== */ -void S_ServerLoaded( void ) { - if( !svs.soundsNeedLoad ) { - return; - } - svs.soundsNeedLoad = qfalse; +void S_ServerLoaded(void) +{ + if (!svs.soundsNeedLoad) { + return; + } + svs.soundsNeedLoad = qfalse; - Com_DPrintf( "Loading Previous Sound State.\n" ); - S_StopAllSounds( qfalse ); - - //S_TriggeredMusic_Stop(); - //s_bSoundPaused = qtrue; - //S_ReLoad( &svs.soundSystem ); - // - //if( svs.tm_filename[ 0 ] ) { - // S_TriggeredMusic_SetupHandle( svs.tm_filename, svs.tm_loopcount, svs.tm_offset, 0 ); - //} + Com_DPrintf("Loading Previous Sound State.\n"); + S_StopAllSounds2(qfalse); + + S_TriggeredMusic_Stop(); + s_bSoundPaused = qtrue; + S_ReLoad(&svs.soundSystem); + + if (svs.tm_filename[0]) { + S_TriggeredMusic_SetupHandle(svs.tm_filename, svs.tm_loopcount, svs.tm_offset, 0); + } } /* @@ -4049,64 +3998,66 @@ void S_ServerLoaded( void ) { UI_ServerLoaded ==================== */ -void UI_ServerLoaded( void ) { - Menu *pCurrentMenu; - cvar_t *pMaxClients; - Event *event; +void UI_ServerLoaded(void) +{ + Menu *pCurrentMenu; + cvar_t *pMaxClients; + Event *event; - CL_UpdateSnapFlags(); - SV_ServerLoaded(); - S_FadeSound( 0 ); - S_ServerLoaded(); + CL_UpdateSnapFlags(); + SV_ServerLoaded(); + S_FadeSound(0); + S_ServerLoaded(); - if( !server_loading ) { - return; - } + if (!server_loading) { + return; + } - UI_EndLoad(); - pMaxClients = Cvar_Get( "sv_maxclients", "1", 0 ); + UI_EndLoad(); + pMaxClients = Cvar_Get("sv_maxclients", "1", 0); - if( com_sv_running->integer && pMaxClients->integer > 1 ) { - SV_Heartbeat_f(); - } + if (com_sv_running->integer && pMaxClients->integer > 1) { + SV_Heartbeat_f(); + } - uWinMan.showCursor( true ); + uWinMan.showCursor(true); - if( !ui_pLoadingMenu ) - { - UI_FinishLoadingScreen_f(); - return; - } + if (!ui_pLoadingMenu) { + UI_FinishLoadingScreen_f(); + return; + } - pCurrentMenu = menuManager.CurrentMenu(); + pCurrentMenu = menuManager.CurrentMenu(); - if( pCurrentMenu != ui_pLoadingMenu - || !pCurrentMenu->GetNamedWidget( "continuebutton" ) - || !com_sv_running->integer - || pMaxClients->integer > 1 ) - { - UI_FinishLoadingScreen_f(); - return; - } + if (pCurrentMenu != ui_pLoadingMenu || !pCurrentMenu->GetNamedWidget("continuebutton") || !com_sv_running->integer + || pMaxClients->integer > 1) { + UI_FinishLoadingScreen_f(); + return; + } - server_loading_waiting = qtrue; + if (ui_sCurrentLoadingMenu == "loading_default") { + UI_FinishLoadingScreen_f(); + return; + } - event = new Event( EV_Widget_Enable ); - ui_pLoadingMenu->PassEventToWidget( "continuebutton", event ); + server_loading_waiting = qtrue; - event = new Event( EV_Widget_Disable ); - ui_pLoadingMenu->PassEventToWidget( "loadingflasher", event ); + event = new Event(EV_Widget_Enable); + ui_pLoadingMenu->PassEventToWidget("continuebutton", event); - event = new Event( EV_Widget_Disable ); - ui_pLoadingMenu->PassEventToWidget( "loadingbar", event ); + event = new Event(EV_Widget_Disable); + ui_pLoadingMenu->PassEventToWidget("loadingflasher", event); - event = new Event( EV_Widget_Disable ); - ui_pLoadingMenu->PassEventToWidget( "loadingbar_border", event ); + event = new Event(EV_Widget_Disable); + ui_pLoadingMenu->PassEventToWidget("loadingbar", event); - event = new Event( EV_Widget_Activate ); - ui_pLoadingMenu->PassEventToWidget( "continuebutton", event ); + event = new Event(EV_Widget_Disable); + ui_pLoadingMenu->PassEventToWidget("loadingbar_border", event); - Com_FakePause(); + event = new Event(EV_Widget_Activate); + ui_pLoadingMenu->PassEventToWidget("continuebutton", event); + + Com_FakePause(); } /* @@ -4114,10 +4065,11 @@ void UI_ServerLoaded( void ) { UI_ClearCenterPrint ==================== */ -void UI_ClearCenterPrint( void ) { - if( view3d ) { - view3d->ClearCenterPrint(); - } +void UI_ClearCenterPrint(void) +{ + if (view3d) { + view3d->ClearCenterPrint(); + } } /* @@ -4125,8 +4077,9 @@ void UI_ClearCenterPrint( void ) { UI_UpdateCenterPrint ==================== */ -void UI_UpdateCenterPrint( const char *s, float alpha ) { - view3d->UpdateCenterPrint( s, alpha ); +void UI_UpdateCenterPrint(const char *s, float alpha) +{ + view3d->UpdateCenterPrint(s, alpha); } /* @@ -4134,8 +4087,9 @@ void UI_UpdateCenterPrint( const char *s, float alpha ) { UI_UpdateLocationPrint ==================== */ -void UI_UpdateLocationPrint( int x, int y, const char *s, float alpha ) { - view3d->UpdateLocationPrint( x, y, s, alpha ); +void UI_UpdateLocationPrint(int x, int y, const char *s, float alpha) +{ + view3d->UpdateLocationPrint(x, y, s, alpha); } /* @@ -4143,25 +4097,25 @@ void UI_UpdateLocationPrint( int x, int y, const char *s, float alpha ) { UI_CenterPrint_f ==================== */ -void UI_CenterPrint_f( void ) { - const char *s; - float alpha; +void UI_CenterPrint_f(void) +{ + const char *s; + float alpha; - if( Cmd_Argc() <= 1 ) { - Com_Printf( "Usage: centerprintf string [alpha]\n" ); - return; - } + if (Cmd_Argc() <= 1) { + Com_Printf("Usage: centerprintf string [alpha]\n"); + return; + } - s = Cmd_Argv( 1 ); + s = Cmd_Argv(1); - if( Cmd_Argc() > 2 ) { - alpha = atof( Cmd_Argv( 2 ) ); - } else { - alpha = 1.0; - } + if (Cmd_Argc() > 2) { + alpha = atof(Cmd_Argv(2)); + } else { + alpha = 1.0; + } - - UI_UpdateCenterPrint( s, alpha ); + UI_UpdateCenterPrint(s, alpha); } /* @@ -4169,29 +4123,29 @@ void UI_CenterPrint_f( void ) { UI_LocationPrint_f ==================== */ -void UI_LocationPrint_f( void ) { - int x, y; - const char *s; - float alpha; +void UI_LocationPrint_f(void) +{ + int x, y; + const char *s; + float alpha; - if( Cmd_Argc() <= 3 ) { - Com_Printf( "Usage: locatinprint x y string [alpha]\n" ); - return; - } + if (Cmd_Argc() <= 3) { + Com_Printf("Usage: locatinprint x y string [alpha]\n"); + return; + } - x = atoi( Cmd_Argv( 1 ) ); - y = atoi( Cmd_Argv( 2 ) ); + x = atoi(Cmd_Argv(1)); + y = atoi(Cmd_Argv(2)); - s = Cmd_Argv( 3 ); + s = Cmd_Argv(3); - if( Cmd_Argc() > 4 ) { - alpha = atof( Cmd_Argv( 4 ) ); - } else { - alpha = 1.0; - } + if (Cmd_Argc() > 4) { + alpha = atof(Cmd_Argv(4)); + } else { + alpha = 1.0; + } - - UI_UpdateLocationPrint( x, y, s, alpha ); + UI_UpdateLocationPrint(x, y, s, alpha); } /* @@ -4199,9 +4153,10 @@ void UI_LocationPrint_f( void ) { UI_LoadInventory_f ==================== */ -void UI_LoadInventory_f( void ) { - UI_CloseInventory(); - CL_LoadInventory( ui_inventoryfile->string, &client_inv ); +void UI_LoadInventory_f(void) +{ + UI_CloseInventory(); + CL_LoadInventory(ui_inventoryfile->string, &client_inv); } /* @@ -4209,17 +4164,18 @@ void UI_LoadInventory_f( void ) { UI_ClearState ==================== */ -void UI_ClearState( void ) { - S_FadeSound( 0.0 ); - UI_ClearCenterPrint(); +void UI_ClearState(void) +{ + S_FadeSound(0.0); + UI_ClearCenterPrint(); - if( gmbox ) { - gmbox->Clear(); - } + if (gmbox) { + gmbox->Clear(); + } - if( dmbox ) { - dmbox->Clear(); - } + if (dmbox) { + dmbox->Clear(); + } } /* @@ -4227,74 +4183,66 @@ void UI_ClearState( void ) { UI_CheckRestart ==================== */ -void UI_CheckRestart( void ) { - if( ui_console->integer && !fakk_console ) { - fakk_console = getNewConsole(); - } +void UI_CheckRestart(void) +{ + if (ui_console->integer && !fakk_console) { + fakk_console = getNewConsole(); + } - if( !dm_console ) { - dm_console = getNewDMConsole(); - } + if (!dm_console) { + dm_console = getNewDMConsole(); + } - if( !ui_console->integer && fakk_console ) { - fakk_console->SendSignal( W_Destroyed ); - } + if (!ui_console->integer && fakk_console) { + fakk_console->SendSignal(W_Destroyed); + } - if( ui_minicon->integer ) - { - if( !mini_console ) - { - UISize2D size; - UColor back = UColor( 0.0, 0.5, 1.0, 1.0 ); + if (ui_minicon->integer) { + if (!mini_console) { + UISize2D size; + UColor back = UColor(0.0, 0.5, 1.0, 1.0); - size.width = 500; - size.height = 100; + size.width = 500; + size.height = 100; - mini_console = new FakkMiniconsole; - mini_console->Create( size, UHudColor, back, 0.3f ); - mini_console->setAlwaysOnBottom( true ); - mini_console->setBorderStyle( border_none ); - } - } - else if( mini_console ) - { - delete mini_console; - mini_console = NULL; - } + mini_console = new FakkMiniconsole; + mini_console->Create(size, UHudColor, back, 0.3f); + mini_console->setAlwaysOnBottom(true); + mini_console->setBorderStyle(border_none); + } + } else if (mini_console) { + delete mini_console; + mini_console = NULL; + } - if( ui_gmbox->integer ) - { - if( !gmbox ) - { - UIRect2D frame; + if (ui_gmbox->integer) { + if (!gmbox) { + UIRect2D frame; - gmbox = new UIGMBox; - frame = getDefaultGMBoxRectangle(); + gmbox = new UIGMBox; + frame = getDefaultGMBoxRectangle(); - gmbox->Create( frame, UHudColor, UHudColor, 0 ); - gmbox->setAlwaysOnBottom( true ); - gmbox->setBorderStyle( border_none ); - } - } - else if( gmbox ) - { - delete gmbox; - gmbox = NULL; - } + gmbox->Create(frame, UHudColor, UHudColor, 0); + gmbox->setAlwaysOnBottom(true); + gmbox->setBorderStyle(border_none); + } + } else if (gmbox) { + delete gmbox; + gmbox = NULL; + } - if( !dmbox ) - { - UIRect2D frame; + if (!dmbox) { + UIRect2D frame; - dmbox = new UIDMBox; - frame = getDefaultDMBoxRectangle(); + dmbox = new UIDMBox; + frame = getDefaultDMBoxRectangle(); - dmbox->Create( frame, UHudColor, UHudColor, 0 ); - dmbox->setAlwaysOnBottom( true ); - dmbox->setBorderStyle( border_outline ); - } + dmbox->Create(frame, UHudColor, UHudColor, 0); + dmbox->setAlwaysOnBottom(true); + dmbox->setBorderStyle(border_outline); + } - menuManager.CheckRestart(); + menuManager.CheckRestart(); } /* @@ -4302,8 +4250,9 @@ void UI_CheckRestart( void ) { UI_ResetCvars ==================== */ -void UI_ResetCvars( void ) { - menuManager.ResetCVars(); +void UI_ResetCvars(void) +{ + menuManager.ResetCVars(); } /* @@ -4311,10 +4260,11 @@ void UI_ResetCvars( void ) { UI_ShowMouse_f ==================== */ -void UI_ShowMouse_f( void ) { - if( view3d->IsActive() ) { - uWinMan.DeactivateCurrentControl(); - } +void UI_ShowMouse_f(void) +{ + if (view3d->IsActive()) { + uWinMan.DeactivateCurrentControl(); + } } /* @@ -4322,23 +4272,24 @@ void UI_ShowMouse_f( void ) { UI_HideMouse_f ==================== */ -void UI_HideMouse_f( void ) { - if( !view3d->IsActive() ) - { - uWinMan.ActivateControl( view3d); - IN_MouseOff(); - } +void UI_HideMouse_f(void) +{ + if (!view3d->IsActive()) { + uWinMan.ActivateControl(view3d); + IN_MouseOff(); + } } -class TestListItem : public UIListCtrlItem { - str strings[ 3 ]; +class TestListItem : public UIListCtrlItem +{ + str strings[3]; public: - virtual griditemtype_t getListItemType( int which ) const; - virtual str getListItemString( int i ) const; - virtual int getListItemValue( int which ) const; - virtual void DrawListItem( int iColumn, const UIRect2D &drawRect, bool bSelected, UIFont *pFont ); - virtual qboolean IsHeaderEntry( void ) const; + virtual griditemtype_t getListItemType(int which) const; + virtual str getListItemString(int i) const; + virtual int getListItemValue(int which) const; + virtual void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont); + virtual qboolean IsHeaderEntry(void) const; }; /* @@ -4346,68 +4297,70 @@ public: UI_TestListCtrl_f ==================== */ -void UI_TestListCtrl_f( void ) { - UIFloatingWindow *wnd = new UIFloatingWindow; - UIListCtrl *control; - UIRect2D frame = UIRect2D( 20, 20, 400, 300 ); - TestListItem *i1, *i2, *i3; +void UI_TestListCtrl_f(void) +{ + UIFloatingWindow *wnd = new UIFloatingWindow; + UIListCtrl *control; + UIRect2D frame = UIRect2D(20, 20, 400, 300); + TestListItem *i1, *i2, *i3; - wnd->Create( NULL, frame, "Test list control", UWindowColor, UHudColor ); + wnd->Create(NULL, frame, "Test list control", UWindowColor, UHudColor); - control = new UIListCtrl; - control->InitFrame( wnd->getChildSpace(), frame.pos.x, frame.pos.y, frame.size.width, frame.size.height, border_none, "verdana-12" ); - control->setBackgroundColor( UWhite, true ); - control->AddColumn( "name", 0, 100, false, false ); - control->AddColumn( "ping", 1, 64, false, false ); - control->AddColumn( "IP", 2, 64, false, false ); + control = new UIListCtrl; + control->InitFrame( + wnd->getChildSpace(), frame.pos.x, frame.pos.y, frame.size.width, frame.size.height, border_none, "verdana-12" + ); + control->setBackgroundColor(UWhite, true); + control->AddColumn("name", 0, 100, false, false); + control->AddColumn("ping", 1, 64, false, false); + control->AddColumn("IP", 2, 64, false, false); - for( int i = 0; i < 100; i++ ) - { - i1 = new TestListItem; - control->AddItem( i1 ); + for (int i = 0; i < 100; i++) { + i1 = new TestListItem; + control->AddItem(i1); - i2 = new TestListItem; - control->AddItem( i2 ); + i2 = new TestListItem; + control->AddItem(i2); - i3 = new TestListItem; - control->AddItem( i3 ); - } + i3 = new TestListItem; + control->AddItem(i3); + } } -class StatsUpdater : public Listener { +class StatsUpdater : public Listener +{ public: - CLASS_PROTOTYPE( StatsUpdater ); + CLASS_PROTOTYPE(StatsUpdater); - void UpdateStats( Event *ev ); + void UpdateStats(Event *ev); }; -Event EV_StatsUpdater_UpdateStats; +Event EV_StatsUpdater_UpdateStats("updatestats", EV_DEFAULT, NULL, NULL, "Update the stats on the missionLog"); -CLASS_DECLARATION( Listener, StatsUpdater, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(Listener, StatsUpdater, NULL) { + {NULL, NULL} }; static StatsUpdater statsUpdater; -static str loadName; +static str loadName; -void StatsUpdater::UpdateStats( Event *ev ) +void StatsUpdater::UpdateStats(Event *ev) { - cvar_t *pMaxClients = Cvar_Get( "sv_maxclients", "1", 0 ); + cvar_t *pMaxClients = Cvar_Get("sv_maxclients", "1", 0); - if( !com_sv_running->integer || pMaxClients->integer > 1 ) { - return; - } + if (!com_sv_running->integer || pMaxClients->integer > 1) { + return; + } - if( paused && !paused->integer ) { - CL_AddReliableCommand( "stats", qfalse ); - } + if (paused && !paused->integer) { + CL_AddReliableCommand("stats", qfalse); + } - Event *event = new Event( EV_StatsUpdater_UpdateStats ); - PostEvent( event, 2.0 ); + Event *event = new Event(EV_StatsUpdater_UpdateStats); + PostEvent(event, 2.0); } -static int statsRequestTime; +static int statsRequestTime; static bool intermission_stats_up; static bool isMissionLogVisible; @@ -4416,56 +4369,45 @@ static bool isMissionLogVisible; UI_ShowScoreboard_f ==================== */ -void UI_ShowScoreboard_f( const char *pszMenuName ) { - if( pszMenuName ) - { - if( scoreboard_menuname.length() ) - { - if( str::icmp( scoreboard_menuname, pszMenuName ) ) { - scoreboard_menu->ForceHide(); - } - } +void UI_ShowScoreboard_f(const char *pszMenuName) +{ + if (pszMenuName) { + if (scoreboard_menuname.length() && str::icmp(scoreboard_menuname, pszMenuName) && scoreboard_menu) { + scoreboard_menu->ForceHide(); + } - scoreboard_menuname = pszMenuName; - } + scoreboard_menuname = pszMenuName; + } - if( UI_MenuActive() ) - { - if( scoreboard_menuname.length() ) - { - scoreboard_menu = menuManager.FindMenu( scoreboard_menuname ); + if (UI_MenuActive()) { + if (scoreboard_menuname.length()) { + scoreboard_menu = menuManager.FindMenu(scoreboard_menuname); - if( scoreboard_menu ) { - scoreboard_menu->ForceHide(); - } - } + if (scoreboard_menu) { + scoreboard_menu->ForceHide(); + } + } - if( scoreboardlist && scoreboardlist->IsVisible() ) - { - scoreboardlist->setShow( false ); - } - } - else - { - if( scoreboard_menuname.length() ) - { - scoreboard_menu = menuManager.FindMenu( scoreboard_menuname ); + if (scoreboardlist && scoreboardlist->IsVisible()) { + scoreboardlist->setShow(false); + } + } else { + if (scoreboard_menuname.length()) { + scoreboard_menu = menuManager.FindMenu(scoreboard_menuname); - if( scoreboard_menu ) - { - UIWidget *widget = scoreboard_menu->GetContainerWidget(); - if( widget ) { - widget->BringToFrontPropogated(); - } - scoreboard_menu->ForceShow(); - } - } + if (scoreboard_menu) { + UIWidget *widget = scoreboard_menu->GetContainerWidget(); + if (widget) { + widget->BringToFrontPropogated(); + } + scoreboard_menu->ForceShow(); + } + } - if( scoreboardlist && !scoreboardlist->IsVisible() ) - { - scoreboardlist->setShow( true ); - } - } + if (scoreboardlist && !scoreboardlist->IsVisible()) { + scoreboardlist->setShow(true); + } + } } /* @@ -4473,80 +4415,85 @@ void UI_ShowScoreboard_f( const char *pszMenuName ) { UI_HideScoreboard_f ==================== */ -void UI_HideScoreboard_f( void ) { - if( scoreboardlist ) - { - scoreboardlist->setShow( false ); - } +void UI_HideScoreboard_f(void) +{ + if (scoreboardlist) { + scoreboardlist->setShow(false); + } - if( scoreboard_menuname.length() ) - { - scoreboard_menu->ForceHide(); - } + if (scoreboard_menuname.length()) { + // Fixed in 2.30 (scoreboard_menu check) + if (scoreboard_menu) { + scoreboard_menu->ForceHide(); + } + } } -class ScoreboardListItem : public UIListCtrlItem { - str strings[ 8 ]; - qboolean bColorSet; - UColor backColor; - UColor textColor; - qboolean bTitleItem; +class ScoreboardListItem : public UIListCtrlItem +{ + str strings[8]; + qboolean bColorSet; + UColor backColor; + UColor textColor; + qboolean bTitleItem; public: - ScoreboardListItem(); + ScoreboardListItem(); - void SetListItemStrings( const char *string1, const char *string2, const char *string3, const char *string4, const char *string5, const char *string6, const char *string7, const char *string8 ); - virtual griditemtype_t getListItemType( int which ) const; - virtual str getListItemString( int i ) const; - virtual int getListItemValue( int which ) const; - virtual void DrawListItem( int iColumn, const UIRect2D &drawRect, bool bSelected, UIFont *pFont ); - void SetColors( const UColor& newTextColor, const UColor& newBackColor ); - void ClearColors( void ); - void SetTitleItem( qboolean bSet ); - virtual qboolean IsHeaderEntry( void ) const; + void SetListItemStrings( + const char *string1, + const char *string2, + const char *string3, + const char *string4, + const char *string5, + const char *string6, + const char *string7, + const char *string8 + ); + virtual griditemtype_t getListItemType(int which) const; + virtual str getListItemString(int i) const; + virtual int getListItemValue(int which) const; + virtual void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont); + void SetColors(const UColor& newTextColor, const UColor& newBackColor); + void ClearColors(void); + void SetTitleItem(qboolean bSet); + virtual qboolean IsHeaderEntry(void) const; }; ScoreboardListItem::ScoreboardListItem() { - bColorSet = false; - bTitleItem = false; + bColorSet = false; + bTitleItem = false; } -void ScoreboardListItem::DrawListItem( int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont ) +void ScoreboardListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) { - DrawBox( drawRect, backColor, 1.0 ); - pFont->setColor(textColor); - pFont->Print( - drawRect.pos.x + 1, - drawRect.pos.y, - Sys_LV_CL_ConvertString(getListItemString(iColumn)), - -1, - qfalse - ); + DrawBox(drawRect, backColor, 1.0); + pFont->setColor(textColor); + pFont->Print((drawRect.pos.x + 1) / uid.scaleRes[0], drawRect.pos.y / uid.scaleRes[1], Sys_LV_CL_ConvertString(getListItemString(iColumn)), -1, uid.scaleRes); - if( bTitleItem ) - { - UIRect2D lineRect; - UColor lineColor = backColor; + if (bTitleItem) { + UIRect2D lineRect; + UColor lineColor = backColor; - lineRect = drawRect; - lineRect.pos.y += lineRect.size.height - 2.0; - lineRect.size.height = 2.0; + lineRect = drawRect; + lineRect.pos.y += lineRect.size.height - 2.0; + lineRect.size.height = 2.0; - DrawBox( lineRect, lineColor, 1.0 ); - } + DrawBox(lineRect, lineColor, 1.0); + } } -void ScoreboardListItem::SetColors( const UColor& newTextColor, const UColor& newBackColor ) +void ScoreboardListItem::SetColors(const UColor& newTextColor, const UColor& newBackColor) { - textColor = newTextColor; - backColor = newBackColor; - bColorSet = true; + textColor = newTextColor; + backColor = newBackColor; + bColorSet = true; } -void ScoreboardListItem::ClearColors( void ) +void ScoreboardListItem::ClearColors(void) { - bColorSet = false; + bColorSet = false; } /* @@ -4554,52 +4501,52 @@ void ScoreboardListItem::ClearColors( void ) UI_CreateScoreboard ==================== */ -void UI_CreateScoreboard( void ) { - int i; - int iColumnWidth; - float w, h, x, y; - float fColumnScale; - float fR, fG, fB, fA; - float fFontR, fFontG, fFontB, fFontA; - const char *pszColumnName; +void UI_CreateScoreboard(void) +{ + int i; + int iColumnWidth; + float w, h, x, y; + float fColumnScale; + float fR, fG, fB, fA; + float fFontR, fFontG, fFontB, fFontA; + const char *pszColumnName; - if( !cge ) { - return; - } + if (!cge) { + return; + } - scoreboardlist = new UIListCtrl; - cge->CG_GetScoreBoardPosition( &x, &y, &w, &h ); - scoreboard_x = x; - scoreboard_y = y; - scoreboard_w = w; - scoreboard_h = h; + scoreboardlist = new UIListCtrl; + cge->CG_GetScoreBoardPosition(&x, &y, &w, &h); + scoreboard_x = x; + scoreboard_y = y; + scoreboard_w = w; + scoreboard_h = h; - SCR_AdjustFrom640( &x, &y, &w, &h ); - fColumnScale = cls.glconfig.vidWidth / 640.0; - cge->CG_GetScoreBoardColor( &fR, &fG, &fB, &fA ); - cge->CG_GetScoreBoardFontColor( &fFontR, &fFontG, &fFontB, &fFontA ); + SCR_AdjustFrom640(&x, &y, &w, &h); + fColumnScale = uid.vidWidth / 640.0; + cge->CG_GetScoreBoardColor(&fR, &fG, &fB, &fA); + cge->CG_GetScoreBoardFontColor(&fFontR, &fFontG, &fFontB, &fFontA); - scoreboardlist->InitFrame( NULL, x, y, w, h, -1, "verdana-12" ); - scoreboardlist->setBackgroundColor( UColor( fR, fG, fB, fA ), true ); - scoreboardlist->setForegroundColor( UColor( fFontR, fFontG, fFontB, fFontA ) ); + scoreboardlist->InitFrame(NULL, x, y, w, h, -1, "verdana-12"); + scoreboardlist->setBackgroundColor(UColor(fR, fG, fB, fA), true); + scoreboardlist->setForegroundColor(UColor(fFontR, fFontG, fFontB, fFontA)); - for( i = 0; i < 8; i++ ) - { - pszColumnName = cge->CG_GetColumnName( i, &iColumnWidth ); - if( !pszColumnName ) { - break; - } + for (i = 0; i < 8; i++) { + pszColumnName = cge->CG_GetColumnName(i, &iColumnWidth); + if (!pszColumnName) { + break; + } - scoreboardlist->AddColumn( pszColumnName, i, iColumnWidth * fColumnScale + 0.5, false, false ); - } + scoreboardlist->AddColumn(pszColumnName, i, iColumnWidth * fColumnScale + 0.5, false, false); + } - scoreboard_header = cge->CG_GetScoreBoardDrawHeader(); - scoreboardlist->setShow( false ); - scoreboardlist->AllowActivate( false ); - scoreboardlist->setAlwaysOnBottom( true ); - scoreboardlist->SetUseScrollBar( false ); - scoreboardlist->SetDrawHeader( scoreboard_header ); - scoreboardlist->setHeaderFont( "facfont-20" ); + scoreboard_header = cge->CG_GetScoreBoardDrawHeader(); + scoreboardlist->setShow(false); + scoreboardlist->AllowActivate(false); + scoreboardlist->setAlwaysOnBottom(true); + scoreboardlist->SetUseScrollBar(false); + scoreboardlist->SetDrawHeader(scoreboard_header); + scoreboardlist->setHeaderFont("facfont-20"); } /* @@ -4607,100 +4554,96 @@ void UI_CreateScoreboard( void ) { UI_SetScoreBoardItem ==================== */ -void UI_SetScoreBoardItem( int iItemNumber, - const char *pszData1, const char *pszData2, const char *pszData3, const char *pszData4, - const char *pszData5, const char *pszData6, const char *pszData7, const char *pszData8, - const vec4_t pTextColor, const vec4_t pBackColor, qboolean bIsHeader ) +void UI_SetScoreBoardItem( + int iItemNumber, + const char *pszData1, + const char *pszData2, + const char *pszData3, + const char *pszData4, + const char *pszData5, + const char *pszData6, + const char *pszData7, + const char *pszData8, + const vec4_t pTextColor, + const vec4_t pBackColor, + qboolean bIsHeader +) { - int i; - float x, y, w, h; - ScoreboardListItem *pItem; + int i; + float x, y, w, h; + ScoreboardListItem *pItem; - if( iItemNumber >= 64 ) { - return; - } + if (iItemNumber >= 64) { + return; + } - if( scoreboardlist ) - { - cge->CG_GetScoreBoardPosition( &x, &y, &w, &h ); + if (scoreboardlist) { + cge->CG_GetScoreBoardPosition(&x, &y, &w, &h); - // Recreate the scoreboard if it has different rect - if( scoreboard_x != x - || scoreboard_y != y - || scoreboard_w != w - || scoreboard_h != h - || scoreboard_header != cge->CG_GetScoreBoardDrawHeader() ) - { - delete scoreboardlist; - scoreboardlist = NULL; - UI_CreateScoreboard(); - } - } - else - { - UI_CreateScoreboard(); - } + // Recreate the scoreboard if it has different rect + if (scoreboard_x != x || scoreboard_y != y || scoreboard_w != w || scoreboard_h != h + || scoreboard_header != cge->CG_GetScoreBoardDrawHeader()) { + delete scoreboardlist; + scoreboardlist = NULL; + UI_CreateScoreboard(); + } + } else { + UI_CreateScoreboard(); + } - if( scoreboardlist ) - { - if (iItemNumber + 1 > scoreboardlist->getNumItems()) { - pItem = new ScoreboardListItem; - scoreboardlist->AddItem(pItem); - } - else { - pItem = (ScoreboardListItem*)scoreboardlist->GetItem(iItemNumber + 1); - } + if (scoreboardlist) { + if (iItemNumber + 1 > scoreboardlist->getNumItems()) { + pItem = new ScoreboardListItem; + scoreboardlist->AddItem(pItem); + } else { + pItem = (ScoreboardListItem *)scoreboardlist->GetItem(iItemNumber + 1); + } - if( pItem ) - { - if( !pszData1 ) { - pszData1 = ""; - } - if( !pszData2 ) { - pszData2 = ""; - } - if( !pszData3 ) { - pszData3 = ""; - } - if( !pszData4 ) { - pszData4 = ""; - } - if( !pszData5 ) { - pszData5 = ""; - } - if( !pszData6 ) { - pszData6 = ""; - } - if( !pszData7 ) { - pszData7 = ""; - } - if( !pszData8 ) { - pszData8 = ""; - } + if (pItem) { + if (!pszData1) { + pszData1 = ""; + } + if (!pszData2) { + pszData2 = ""; + } + if (!pszData3) { + pszData3 = ""; + } + if (!pszData4) { + pszData4 = ""; + } + if (!pszData5) { + pszData5 = ""; + } + if (!pszData6) { + pszData6 = ""; + } + if (!pszData7) { + pszData7 = ""; + } + if (!pszData8) { + pszData8 = ""; + } - pItem->SetListItemStrings( pszData1, pszData2, pszData3, pszData4, pszData5, pszData6, pszData7, pszData8 ); + pItem->SetListItemStrings(pszData1, pszData2, pszData3, pszData4, pszData5, pszData6, pszData7, pszData8); - if( pTextColor && pBackColor ) - { - UColor textColor, backColor; + if (pTextColor && pBackColor) { + UColor textColor, backColor; - textColor = UColor( pTextColor[ 0 ], pTextColor[ 1 ], pTextColor[ 2 ], pTextColor[ 3 ] ); - backColor = UColor( pBackColor[ 0 ], pBackColor[ 1 ], pBackColor[ 2 ], pBackColor[ 3 ] ); - pItem->SetColors( textColor, backColor ); - } - else - { - pItem->ClearColors(); - } + textColor = UColor(pTextColor[0], pTextColor[1], pTextColor[2], pTextColor[3]); + backColor = UColor(pBackColor[0], pBackColor[1], pBackColor[2], pBackColor[3]); + pItem->SetColors(textColor, backColor); + } else { + pItem->ClearColors(); + } - for( i = 0; i < 8; i++ ) - { - pItem->getListItemString( i ); - } + for (i = 0; i < 8; i++) { + pItem->getListItemString(i); + } - pItem->SetTitleItem( bIsHeader ); - } - } + pItem->SetTitleItem(bIsHeader); + } + } } /* @@ -4708,11 +4651,11 @@ void UI_SetScoreBoardItem( int iItemNumber, UI_DeleteScoreBoardItems ==================== */ -void UI_DeleteScoreBoardItems( int iMaxIndex ) { - while( iMaxIndex + 1 <= scoreboardlist->getNumItems() ) - { - scoreboardlist->DeleteItem( scoreboardlist->getNumItems() ); - } +void UI_DeleteScoreBoardItems(int iMaxIndex) +{ + while (iMaxIndex + 1 <= scoreboardlist->getNumItems()) { + scoreboardlist->DeleteItem(scoreboardlist->getNumItems()); + } } /* @@ -4720,65 +4663,61 @@ void UI_DeleteScoreBoardItems( int iMaxIndex ) { UI_Hud_f ==================== */ -void UI_Hud_f( void ) { - qboolean hide; +void UI_Hud_f(void) +{ + qboolean hide; - if( Cmd_Argc() != 2 ) { - Com_Printf( "Usage: ui_hud [1|0]" ); - return; - } + if (Cmd_Argc() != 2) { + Com_Printf("Usage: ui_hud [1|0]"); + return; + } - ui_hud = atoi( Cmd_Argv( 1 ) ); - hide = !ui_hud; + ui_hud = atoi(Cmd_Argv(1)); + hide = !ui_hud; - if( hud_weapons && hide ) - { - hud_weapons->ForceHide(); - ui_weapHudTime = 0; - } + if (hud_weapons && hide) { + hud_weapons->ForceHide(); + ui_weapHudTime = 0; + } - if( hud_items && hide ) - { - hud_items->ForceHide(); - ui_itemHudTime = 0; - } + if (hud_items && hide) { + hud_items->ForceHide(); + ui_itemHudTime = 0; + } - if( hud_health ) - { - if( hide ) { - hud_health->ForceHide(); - } else { - hud_health->ForceShow(); - } - } - if( hud_ammo ) - { - if( hide ) { - hud_ammo->ForceHide(); - } else { - hud_ammo->ForceShow(); - } - } - if( hud_compass ) - { - if( hide ) { - hud_compass->ForceHide(); - } else { - hud_compass->ForceShow(); - } - } + if (hud_health) { + if (hide) { + hud_health->ForceHide(); + } else { + hud_health->ForceShow(); + } + } + if (hud_ammo) { + if (hide) { + hud_ammo->ForceHide(); + } else { + hud_ammo->ForceShow(); + } + } + if (hud_compass) { + if (hide) { + hud_compass->ForceHide(); + } else { + hud_compass->ForceShow(); + } + } - if( hide ) { - UI_HideHudList(); - } else { - UI_ShowHudList(); - } + if (hide) { + UI_HideHudList(); + } else { + UI_ShowHudList(); + } - if( ui_hud ) { - Cvar_Set( "cg_hud", "1" ); - } else { - Cvar_Set( "cg_hud", "0" ); - } + if (ui_hud) { + Cvar_Set("cg_hud", "1"); + } else { + Cvar_Set("cg_hud", "0"); + } } /* @@ -4786,18 +4725,19 @@ void UI_Hud_f( void ) { UI_ClearConsole_f ==================== */ -void UI_ClearConsole_f( void ) { - if( fakk_console ) { - fakk_console->Clear(); - } +void UI_ClearConsole_f(void) +{ + if (fakk_console) { + fakk_console->Clear(); + } - if( dm_console ) { - dm_console->Clear(); - } + if (dm_console) { + dm_console->Clear(); + } - if( developer_console ) { - developer_console->Clear(); - } + if (developer_console) { + developer_console->Clear(); + } } /* @@ -4805,8 +4745,9 @@ void UI_ClearConsole_f( void ) { CL_FinishedIntro ==================== */ -qboolean CL_FinishedIntro( void ) { - return !cls.startStage; +qboolean CL_FinishedIntro(void) +{ + return cls.startStage == 0; } /* @@ -4814,8 +4755,89 @@ qboolean CL_FinishedIntro( void ) { CL_FinishedStartStage ==================== */ -void CL_FinishedStartStage( void ) { - // FIXME: stub +void CL_FinishedStartStage(void) +{ + int wait; + + switch (cls.startStage++) { + case 1: + Cbuf_ExecuteText(EXEC_NOW, "cinematic EAlogo.RoQ\n"); + break; + case 2: + intro_stage.alpha_start = 0.0; + intro_stage.alpha_end = 1.0; + + wait = ui_titlescreen_fadein->value * 1000.0; + intro_stage.fadetime = wait; + intro_stage.starttime = cls.realtime; + intro_stage.endtime = cls.realtime + wait; + + intro_stage.material = uWinMan.RegisterShader("mohaa_title"); + break; + case 3: + intro_stage.alpha_start = 1.0; + intro_stage.alpha_end = 1.0; + + wait = ui_legalscreen_stay->value * 1000.0; + intro_stage.fadetime = 0.0; + intro_stage.starttime = cls.realtime; + intro_stage.endtime = cls.realtime + wait; + break; + case 4: + intro_stage.alpha_start = 1.0; + intro_stage.alpha_end = 0.0; + + wait = ui_titlescreen_fadeout->value * 1000.0; + intro_stage.fadetime = wait; + intro_stage.starttime = cls.realtime; + intro_stage.endtime = cls.realtime + wait; + break; + case 5: + intro_stage.alpha_start = 0.0; + intro_stage.alpha_end = 1.0; + + wait = ui_legalscreen_fadein->value * 1000.0; + intro_stage.fadetime = wait; + intro_stage.starttime = cls.realtime; + intro_stage.endtime = cls.realtime + wait; + + intro_stage.material = uWinMan.RegisterShader("legal"); + break; + case 6: + intro_stage.alpha_start = 1.0; + intro_stage.alpha_end = 1.0; + + wait = ui_legalscreen_stay->value * 1000.0; + intro_stage.fadetime = 0.0; + intro_stage.starttime = cls.realtime; + intro_stage.endtime = cls.realtime + wait; + break; + case 7: + intro_stage.alpha_start = 1.0; + intro_stage.alpha_end = 0.0; + + wait = ui_legalscreen_fadeout->value * 1000.0; + intro_stage.fadetime = wait; + intro_stage.starttime = cls.realtime; + intro_stage.endtime = cls.realtime + wait; + break; + case 8: + if (com_target_game->integer >= target_game_e::TG_MOHTA) { + cls.startStage = 0; + return; + } + + Cbuf_ExecuteText(EXEC_NOW, "cinematic 2015intro.RoQ\n"); + break; + case 9: + Cbuf_ExecuteText(EXEC_NOW, "cinematic intro.RoQ\n"); + break; + case 10: + cls.startStage = 0; + break; + default: + break; + } } /* @@ -4823,45 +4845,37 @@ void CL_FinishedStartStage( void ) { UI_StartStageKeyEvent ==================== */ -void UI_StartStageKeyEvent( void ) { - switch( cls.startStage ) - { - case 2: - if( ui_skip_eamovie->integer ) { - SCR_StopCinematic(); - } - break; - case 12: - SCR_StopCinematic(); - break; - case 3: - case 4: - case 5: - if( ui_skip_titlescreen->integer ) - { - cls.startStage = 5; - CL_FinishedStartStage(); - } - break; - case 6: - case 7: - case 8: - if( ui_skip_legalscreen->integer ) - { - cls.startStage = 8; - CL_FinishedStartStage(); - } - break; - case 9: - case 10: - case 11: - if( ui_skip_legalscreen->integer ) - { - cls.startStage = 11; - CL_FinishedStartStage(); - } - break; - } +void UI_StartStageKeyEvent(void) +{ + switch (cls.startStage) { + case 2: + if (ui_skip_eamovie->integer) { + SCR_StopCinematic(); + } + break; + case 3: + case 4: + case 5: + if (ui_skip_titlescreen->integer) { + cls.startStage = 5; + CL_FinishedStartStage(); + } + break; + case 6: + case 7: + case 8: + if (ui_skip_legalscreen->integer) { + cls.startStage = 8; + CL_FinishedStartStage(); + } + break; + case 9: + case 10: + SCR_StopCinematic(); + break; + default: + break; + } } /* @@ -4869,10 +4883,11 @@ void UI_StartStageKeyEvent( void ) { UI_StartIntro_f ==================== */ -void UI_StartIntro_f( void ) { - cls.startStage = 1; - IN_MouseOff(); - CL_FinishedStartStage(); +void UI_StartIntro_f(void) +{ + cls.startStage = 1; + IN_MouseOff(); + CL_FinishedStartStage(); } /* @@ -4880,17 +4895,15 @@ void UI_StartIntro_f( void ) { CL_TryStartIntro ==================== */ -void CL_TryStartIntro( void ) { - if( developer->integer || !cl_playintro->integer ) - { - UI_ToggleConsole(); - } - else - { - // FIXME: no intro from now - //Cvar_Set( cl_playintro->name, "0" ); - //UI_StartIntro_f(); - } +void CL_TryStartIntro(void) +{ + if (developer->integer || !cl_playintro->integer) { + UI_ToggleConsole(); + } else { + // FIXME: no intro from now + Cvar_Set(cl_playintro->name, "0"); + UI_StartIntro_f(); + } } /* @@ -4898,29 +4911,32 @@ void CL_TryStartIntro( void ) { SaveConsoleRectangle ==================== */ -static void SaveConsoleRectangle( void ) { - bool wasMinimized; - UIRect2D r; +static void SaveConsoleRectangle(void) +{ + bool wasMinimized; + UIRect2D r; - if( !fakk_console ) { - return; - } + if (!fakk_console) { + return; + } - wasMinimized = fakk_console->IsMinimized(); + wasMinimized = fakk_console->IsMinimized(); - if( wasMinimized ) { - fakk_console->ProcessEvent( UIFloatingWindow::W_MinimizePressed ); - } + if (wasMinimized) { + fakk_console->ProcessEvent(UIFloatingWindow::W_MinimizePressed); + } - if( !fakk_console->IsMinimized() ) { - r = fakk_console->getFrame(); + if (!fakk_console->IsMinimized()) { + r = fakk_console->getFrame(); - Cvar_Set( "ui_consoleposition", va( "%d %d %d %d", (int)r.pos.x, (int)r.pos.y, (int)r.size.width, (int)r.size.height ) ); - - if( wasMinimized ) { - fakk_console->ProcessEvent( UIFloatingWindow::W_MinimizePressed ); - } - } + Cvar_Set( + "ui_consoleposition", va("%d %d %d %d", (int)r.pos.x, (int)r.pos.y, (int)r.size.width, (int)r.size.height) + ); + + if (wasMinimized) { + fakk_console->ProcessEvent(UIFloatingWindow::W_MinimizePressed); + } + } } /* @@ -4928,22 +4944,23 @@ static void SaveConsoleRectangle( void ) { LoadConsoleRectangle ==================== */ -static void LoadConsoleRectangle( void ) { - bool wasMinimized; +static void LoadConsoleRectangle(void) +{ + bool wasMinimized; - if( !fakk_console ) { - return; - } + if (!fakk_console) { + return; + } - wasMinimized = fakk_console->IsMinimized(); + wasMinimized = fakk_console->IsMinimized(); - if( wasMinimized ) { - fakk_console->ProcessEvent( UIFloatingWindow::W_MinimizePressed ); - } + if (wasMinimized) { + fakk_console->ProcessEvent(UIFloatingWindow::W_MinimizePressed); + } - if( !fakk_console->IsMinimized() && wasMinimized ) { - fakk_console->ProcessEvent( UIFloatingWindow::W_MinimizePressed ); - } + if (!fakk_console->IsMinimized() && wasMinimized) { + fakk_console->ProcessEvent(UIFloatingWindow::W_MinimizePressed); + } } /* @@ -4951,21 +4968,19 @@ static void LoadConsoleRectangle( void ) { UI_AddHud_f ==================== */ -void UI_AddHud_f( void ) { - Menu *hud = menuManager.FindMenu( Cmd_Argv( 1 ) ); +void UI_AddHud_f(void) +{ + Menu *hud = menuManager.FindMenu(Cmd_Argv(1)); - if( hud ) - { - if( !hudList.ObjectInList( hud ) ) { - hudList.AddObject( hud ); - } + if (hud) { + if (!hudList.ObjectInList(hud)) { + hudList.AddObject(hud); + } - hud->ShowMenu( NULL ); - } - else - { - Com_DPrintf( "Hud %s not found in menu system.\n", Cmd_Argv( 1 ) ); - } + hud->ShowMenu(NULL); + } else { + Com_DPrintf("Hud %s not found in menu system.\n", Cmd_Argv(1)); + } } /* @@ -4973,14 +4988,14 @@ void UI_AddHud_f( void ) { UI_RemoveHud_f ==================== */ -void UI_RemoveHud_f( void ) { - Menu *hud = menuManager.FindMenu( Cmd_Argv( 1 ) ); +void UI_RemoveHud_f(void) +{ + Menu *hud = menuManager.FindMenu(Cmd_Argv(1)); - if( hud && hudList.ObjectInList( hud ) ) - { - hud->ForceHide(); - hudList.RemoveObject( hud ); - } + if (hud && hudList.ObjectInList(hud)) { + hud->ForceHide(); + hudList.RemoveObject(hud); + } } /* @@ -4988,12 +5003,13 @@ void UI_RemoveHud_f( void ) { UI_StartServer_f ==================== */ -void UI_StartServer_f( void ) { - const char *map = Cmd_Argv( 1 ); +void UI_StartServer_f(void) +{ + const char *map = Cmd_Argv(1); - if( strlen( map ) ) { - Cbuf_AddText( va( "map %s\n", map ) ); - } + if (strlen(map)) { + Cbuf_AddText(va("map %s\n", map)); + } } /* @@ -5001,30 +5017,28 @@ void UI_StartServer_f( void ) { UI_ShowStatistics_f ==================== */ -void UI_ShowStatistics_f() { - cvar_t *pMaxClients = Cvar_Get( "sv_maxclients", "1", 0 ); +void UI_ShowStatistics_f() +{ + cvar_t *pMaxClients = Cvar_Get("sv_maxclients", "1", 0); - if( !com_sv_running->integer || pMaxClients->integer > 1 ) { - return; - } + if (!com_sv_running->integer || pMaxClients->integer > 1) { + return; + } - if( missionLog && !isMissionLogVisible ) - { - isMissionLogVisible = true; - missionLog->ShowMenu( NULL ); - IN_MouseOn(); - } + if (missionLog && !isMissionLogVisible) { + isMissionLogVisible = true; + missionLog->ShowMenu(NULL); + IN_MouseOn(); + } - if( statsRequestTime + 2000 <= cls.realtime ) - { - if( paused && !paused->integer ) - { - statsRequestTime = cls.realtime; - CL_AddReliableCommand( "stats", qfalse ); - Event *event = new Event( EV_StatsUpdater_UpdateStats ); - statsUpdater.PostEvent( event, 2.0 ); - } - } + if (statsRequestTime + 2000 <= cls.realtime) { + if (paused && !paused->integer) { + statsRequestTime = cls.realtime; + CL_AddReliableCommand("stats", qfalse); + Event *event = new Event(EV_StatsUpdater_UpdateStats); + statsUpdater.PostEvent(event, 2.0); + } + } } /* @@ -5032,170 +5046,177 @@ void UI_ShowStatistics_f() { UI_HideStatistics_f ==================== */ -void UI_HideStatistics_f() { - cvar_t *pMaxClients = Cvar_Get( "sv_maxclients", "1", 0 ); +void UI_HideStatistics_f() +{ + cvar_t *pMaxClients = Cvar_Get("sv_maxclients", "1", 0); - if( !com_sv_running->integer || pMaxClients->integer > 1 ) { - return; - } + if (!com_sv_running->integer || pMaxClients->integer > 1) { + return; + } - if( missionLog ) - { - isMissionLogVisible = false; - missionLog->HideMenu( &EV_HideMenu ); - IN_MouseOff(); - } + if (missionLog) { + isMissionLogVisible = false; + missionLog->HideMenu(&EV_HideMenu); + IN_MouseOff(); + } - statsUpdater.CancelEventsOfType( EV_StatsUpdater_UpdateStats ); + statsUpdater.CancelEventsOfType(EV_StatsUpdater_UpdateStats); } +/* +==================== +UI_SalesScreen_f +==================== +*/ +void UI_SalesScreen_f() +{ + if (random() > 0.5) { + Cbuf_AddText("pushmenu sales_splash1\n"); + } else { + Cbuf_AddText("pushmenu sales_splash2\n"); + } +} /* ==================== CL_ShutdownUI ==================== */ -void CL_ShutdownUI( void ) { - if( !cls.uiStarted ) { - return; - } +void CL_ShutdownUI(void) +{ + if (!cls.uiStarted) { + return; + } - if( s_intermediateconsole ) - { - delete s_intermediateconsole; - s_intermediateconsole = NULL; - } + if (s_intermediateconsole) { + delete s_intermediateconsole; + s_intermediateconsole = NULL; + } - // remove all UI commands - Cmd_RemoveCommand( "pushmenu" ); - Cmd_RemoveCommand( "forcemenu" ); - Cmd_RemoveCommand( "popmenu" ); - Cmd_RemoveCommand( "showmenu" ); - Cmd_RemoveCommand( "widgetcommand" ); - Cmd_RemoveCommand( "listmenus" ); - Cmd_RemoveCommand( "togglemenu" ); - Cmd_RemoveCommand( "loadmenu" ); - Cmd_RemoveCommand( "maplist" ); - Cmd_RemoveCommand( "dmmapselect" ); - Cmd_RemoveCommand( "ui_startdmmap" ); - Cmd_RemoveCommand( "viewspawnlist" ); - Cmd_RemoveCommand( "lod_spawnlist" ); - Cmd_RemoveCommand( "soundpicker" ); - Cmd_RemoveCommand( "notepad" ); - Cmd_RemoveCommand( "editscript" ); - Cmd_RemoveCommand( "editshader" ); - Cmd_RemoveCommand( "inv_restart" ); - Cmd_RemoveCommand( "ui_showmouse" ); - Cmd_RemoveCommand( "ui_hidemouse" ); - Cmd_RemoveCommand( "ui_saveconsolepos" ); - Cmd_RemoveCommand( "ui_loadconsolepos" ); - Cmd_RemoveCommand( "ui_testlist" ); - Cmd_RemoveCommand( "clear" ); - Cmd_RemoveCommand( "ui_hud" ); - Cmd_RemoveCommand( "ui_resetcvars" ); - Cmd_RemoveCommand( "ui_checkrestart" ); - Cmd_RemoveCommand( "ui_addhud" ); - Cmd_RemoveCommand( "ui_removehud" ); - Cmd_RemoveCommand( "centerprint" ); - Cmd_RemoveCommand( "locationprint" ); - Cmd_RemoveCommand( "startserver" ); - Cmd_RemoveCommand( "finishloadingscreen" ); - Cmd_RemoveCommand( "playermodel" ); - Cmd_RemoveCommand( "ui_applyplayermodel" ); - Cmd_RemoveCommand( "ui_getplayermodel" ); - Cmd_RemoveCommand( "devcon" ); - Cmd_RemoveCommand( "+statistics" ); - Cmd_RemoveCommand( "-statistics" ); + // remove all UI commands + Cmd_RemoveCommand("pushmenu"); + Cmd_RemoveCommand("forcemenu"); + Cmd_RemoveCommand("popmenu"); + Cmd_RemoveCommand("showmenu"); + Cmd_RemoveCommand("widgetcommand"); + Cmd_RemoveCommand("listmenus"); + Cmd_RemoveCommand("togglemenu"); + Cmd_RemoveCommand("loadmenu"); + Cmd_RemoveCommand("maplist"); + Cmd_RemoveCommand("dmmapselect"); + Cmd_RemoveCommand("ui_startdmmap"); + Cmd_RemoveCommand("viewspawnlist"); + Cmd_RemoveCommand("lod_spawnlist"); + Cmd_RemoveCommand("soundpicker"); + Cmd_RemoveCommand("notepad"); + Cmd_RemoveCommand("editscript"); + Cmd_RemoveCommand("editshader"); + Cmd_RemoveCommand("inv_restart"); + Cmd_RemoveCommand("ui_showmouse"); + Cmd_RemoveCommand("ui_hidemouse"); + Cmd_RemoveCommand("ui_saveconsolepos"); + Cmd_RemoveCommand("ui_loadconsolepos"); + Cmd_RemoveCommand("ui_testlist"); + Cmd_RemoveCommand("clear"); + Cmd_RemoveCommand("ui_hud"); + Cmd_RemoveCommand("ui_resetcvars"); + Cmd_RemoveCommand("ui_checkrestart"); + Cmd_RemoveCommand("ui_addhud"); + Cmd_RemoveCommand("ui_removehud"); + Cmd_RemoveCommand("centerprint"); + Cmd_RemoveCommand("locationprint"); + Cmd_RemoveCommand("startserver"); + Cmd_RemoveCommand("finishloadingscreen"); + Cmd_RemoveCommand("playermodel"); + Cmd_RemoveCommand("ui_applyplayermodel"); + Cmd_RemoveCommand("ui_getplayermodel"); + Cmd_RemoveCommand("devcon"); + Cmd_RemoveCommand("+statistics"); + Cmd_RemoveCommand("-statistics"); - for( int i = 0; i < hudList.NumObjects(); i++ ) { - hudList.RemoveObjectAt( i ); - } + for (int i = 0; i < hudList.NumObjects(); i++) { + hudList.RemoveObjectAt(i); + } - crosshairhud = menuManager.FindMenu( "crosshair" ); - hud_weapons = menuManager.FindMenu( "hud_weapons" ); - hud_items = menuManager.FindMenu( "hud_items" ); - hud_health = menuManager.FindMenu( "hud_health" ); - hud_compass = menuManager.FindMenu( "hud_compass" ); - hud_boss = menuManager.FindMenu( "hud_boss" ); - ui_pConnectingMenu = menuManager.FindMenu( "connecting" ); + // Removed in 2.0 + // Crosshair is now handled by the cgame module + //crosshairhud = menuManager.FindMenu("crosshair"); + hud_weapons = menuManager.FindMenu("hud_weapons"); + hud_items = menuManager.FindMenu("hud_items"); + hud_health = menuManager.FindMenu("hud_health"); + hud_compass = menuManager.FindMenu("hud_compass"); + hud_boss = menuManager.FindMenu("hud_boss"); + ui_pConnectingMenu = menuManager.FindMenu("connecting"); - // delete base hud - if( view3d ) - { - delete view3d; - view3d = NULL; - } - if( fakk_console ) - { - delete fakk_console; - fakk_console = NULL; - } - if( dm_console ) - { - delete dm_console; - dm_console = NULL; - } - if( developer_console ) - { - delete developer_console; - developer_console = NULL; - } - if( mini_console ) - { - delete mini_console; - mini_console = NULL; - } + // delete base hud + if (view3d) { + delete view3d; + view3d = NULL; + } + if (fakk_console) { + delete fakk_console; + fakk_console = NULL; + } + if (dm_console) { + delete dm_console; + dm_console = NULL; + } + if (developer_console) { + delete developer_console; + developer_console = NULL; + } + if (mini_console) { + delete mini_console; + mini_console = NULL; + } - // delete game hud - if( crosshairhud ) { - crosshairhud = NULL; - } - if( hud_weapons ) { - hud_weapons = NULL; - } - if( hud_items ) { - hud_items = NULL; - } - if( hud_health ) { - hud_health = NULL; - } - if( hud_ammo ) { - hud_ammo = NULL; - } - if( hud_compass ) { - hud_compass = NULL; - } - if( hud_boss ) { - hud_boss = NULL; - } + // delete game hud + if (crosshairhud) { + crosshairhud = NULL; + } + if (hud_weapons) { + hud_weapons = NULL; + } + if (hud_items) { + hud_items = NULL; + } + if (hud_health) { + hud_health = NULL; + } + if (hud_ammo) { + hud_ammo = NULL; + } + if (hud_compass) { + hud_compass = NULL; + } + if (hud_boss) { + hud_boss = NULL; + } - // delete informations hud - if( scoreboardlist ) - { - delete scoreboardlist; - scoreboardlist = NULL; - } - if( gmbox ) - { - delete gmbox; - gmbox = NULL; - } - if( dmbox ) - { - delete dmbox; - dmbox = NULL; - } + // delete informations hud + if (scoreboardlist) { + delete scoreboardlist; + scoreboardlist = NULL; + } + if (gmbox) { + delete gmbox; + gmbox = NULL; + } + if (dmbox) { + delete dmbox; + dmbox = NULL; + } - // clear inventory - client_inv.Clear(); + // clear inventory + client_inv.Clear(); - // shutdown the UI - uie.Shutdown(); + // shutdown the UI + uie.Shutdown(); - // delete all menus - menuManager.DeleteAllMenus(); + // delete all menus + menuManager.DeleteAllMenus(); - cls.uiStarted = false; + cls.uiStarted = false; } /* @@ -5203,266 +5224,271 @@ void CL_ShutdownUI( void ) { CL_InitUI ==================== */ -#define UI_OLD_API_VERSION 4 +#define UI_OLD_API_VERSION 4 -void CL_InitializeUI( void ) { - int nfiles; - char **filenames; - int i; +void CL_InitializeUI(void) +{ + int nfiles; + char **filenames; + int i; - // Register all variables - ui_minicon = Cvar_Get( "ui_minicon", "0", 1 ); - ui_gmbox = Cvar_Get( "ui_gmbox", "1", 1 ); - ui_consoleposition = Cvar_Get( "ui_consoleposition", "", 1 ); - ui_console = Cvar_Get("ui_console", "0", 1); - ui_crosshair = Cvar_Get("ui_crosshair", "1", 1); - ui_weaponsbar = Cvar_Get("ui_weaponsbar", "1", 1); - ui_weaponsbartime = Cvar_Get("ui_weaponsbartime", "2500", 1); - ui_itemsbar = Cvar_Get("ui_itemsbar", "0", 1); - sound_overlay = Cvar_Get("soundoverlay", "0", 0); - ui_debugload = Cvar_Get("ui_debugload", "0", 0); - Cvar_Get("ui_signshader", "", 0); - ui_compass = Cvar_Get("ui_compass", "1", 0); - ui_newvidmode = Cvar_Get("ui_newvidmode", "-1", 0); - ui_inventoryfile = Cvar_Get("ui_inventoryfile", "global/inventory.txt", 0); - ui_drawcoords = Cvar_Get("ui_drawcoords", "0", 0); - ui_health_start = Cvar_Get("ui_health_start", "0", 0); - ui_health_end = Cvar_Get("ui_health_end", "0", 0); - ui_GunneryEvaluation = Cvar_Get("ui_GunneryEvaluation", "0", 0); - ui_GroinShots = Cvar_Get("ui_GroinShots", "0", 0); - ui_RightArmShots = Cvar_Get("ui_RightArmShots", "0", 0); - ui_LeftArmShots = Cvar_Get("ui_LeftArmShots", "0", 0); - ui_RightLegShots = Cvar_Get("ui_RightLegShots", "0", 0); - ui_LeftLegShots = Cvar_Get("ui_LeftLegShots", "0", 0); - ui_TorsoShots = Cvar_Get("ui_TorsoShots", "0", 0); - ui_HeadShots = Cvar_Get("ui_HeadShots", "0", 0); - ui_NumEnemysKilled = Cvar_Get("ui_NumEnemysKilled", "0", 0); - ui_NumObjectsDestroyed = Cvar_Get("ui_NumObjectsDestroyed", "0", 0); - ui_NumHitsTaken = Cvar_Get("ui_NumHitsTaken", "0", 0); - ui_PreferredWeapon = Cvar_Get("ui_PreferredWeapon", "none", 0); - ui_Accuracy = Cvar_Get("ui_Accuracy", "0", 0); - ui_NumObjectives = Cvar_Get("ui_NumObjectives", "0", 0); - ui_NumComplete = Cvar_Get("ui_NumComplete", "0", 0); - ui_NumHits = Cvar_Get("ui_NumHits", "0", 0); - ui_NumShotsFired = Cvar_Get("ui_NumShotsFired", "0", 0); - ui_gmboxspam = Cvar_Get("ui_gmboxspam", "1", 0); - ui_gotmedal = Cvar_Get("ui_gotmedal", "0", 0); - ui_success = Cvar_Get("ui_success", "0", 0); - ui_failed = Cvar_Get("ui_failed", "0", 0); - ui_returnmenu = Cvar_Get("ui_returnmenu", "0", 0); - ui_skip_eamovie = Cvar_Get("ui_skip_eamovie", "0", 0); - ui_skip_titlescreen = Cvar_Get("ui_skip_titlescreen", "1", 0); - ui_skip_legalscreen = Cvar_Get("ui_skip_legalscreen", "1", 0); - ui_titlescreen_fadein = Cvar_Get("ui_titlescreen_fadein", "1", 0); - ui_titlescreen_fadeout = Cvar_Get( "ui_titlescreen_fadeout", "1", 0 ); - ui_titlescreen_stay = Cvar_Get( "ui_titlescreen_stay", "3", 0 ); - ui_legalscreen_fadein = Cvar_Get( "ui_legalscreen_fadein", "1", 0 ); - ui_legalscreen_fadeout = Cvar_Get( "ui_legalscreen_fadeout", "1", 0 ); - ui_legalscreen_stay = Cvar_Get( "ui_legalscreen_stay", "3", 0 ); - cl_greenfps = Cvar_Get( "cl_greenfps", "0", 1 ); - cl_playintro = Cvar_Get( "cl_playintro", "1", 0 ); - cl_movieaudio = Cvar_Get( "cl_movieaudio", "1", 0 ); - Cvar_Get( "ui_startmap", "", 1 ); - Cvar_Get( "dlg_badsave", "This save game is invalid", 0 ); + // Register all variables + ui_minicon = Cvar_Get("ui_minicon", "0", 1); + ui_gmbox = Cvar_Get("ui_gmbox", "1", 1); + ui_consoleposition = Cvar_Get("ui_consoleposition", "", 1); + ui_console = Cvar_Get("ui_console", "0", 1); + ui_crosshair = Cvar_Get("ui_crosshair", "1", 1); + ui_weaponsbar = Cvar_Get("ui_weaponsbar", "1", 1); + ui_weaponsbartime = Cvar_Get("ui_weaponsbartime", "2500", 1); + ui_itemsbar = Cvar_Get("ui_itemsbar", "0", 1); + sound_overlay = Cvar_Get("soundoverlay", "0", 0); + ui_debugload = Cvar_Get("ui_debugload", "0", 0); + Cvar_Get("ui_signshader", "", 0); + ui_compass = Cvar_Get("ui_compass", "1", 0); + ui_newvidmode = Cvar_Get("ui_newvidmode", "-1", 0); + ui_inventoryfile = Cvar_Get("ui_inventoryfile", "global/inventory.txt", 0); + ui_drawcoords = Cvar_Get("ui_drawcoords", "0", 0); + ui_health_start = Cvar_Get("ui_health_start", "0", 0); + ui_health_end = Cvar_Get("ui_health_end", "0", 0); + ui_GunneryEvaluation = Cvar_Get("ui_GunneryEvaluation", "0", 0); + ui_GroinShots = Cvar_Get("ui_GroinShots", "0", 0); + ui_RightArmShots = Cvar_Get("ui_RightArmShots", "0", 0); + ui_LeftArmShots = Cvar_Get("ui_LeftArmShots", "0", 0); + ui_RightLegShots = Cvar_Get("ui_RightLegShots", "0", 0); + ui_LeftLegShots = Cvar_Get("ui_LeftLegShots", "0", 0); + ui_TorsoShots = Cvar_Get("ui_TorsoShots", "0", 0); + ui_HeadShots = Cvar_Get("ui_HeadShots", "0", 0); + ui_NumEnemysKilled = Cvar_Get("ui_NumEnemysKilled", "0", 0); + ui_NumObjectsDestroyed = Cvar_Get("ui_NumObjectsDestroyed", "0", 0); + ui_NumHitsTaken = Cvar_Get("ui_NumHitsTaken", "0", 0); + ui_PreferredWeapon = Cvar_Get("ui_PreferredWeapon", "none", 0); + ui_Accuracy = Cvar_Get("ui_Accuracy", "0", 0); + ui_NumObjectives = Cvar_Get("ui_NumObjectives", "0", 0); + ui_NumComplete = Cvar_Get("ui_NumComplete", "0", 0); + ui_NumHits = Cvar_Get("ui_NumHits", "0", 0); + ui_NumShotsFired = Cvar_Get("ui_NumShotsFired", "0", 0); + ui_gmboxspam = Cvar_Get("ui_gmboxspam", "1", 0); + ui_gotmedal = Cvar_Get("ui_gotmedal", "0", 0); + ui_success = Cvar_Get("ui_success", "0", 0); + ui_failed = Cvar_Get("ui_failed", "0", 0); + ui_returnmenu = Cvar_Get("ui_returnmenu", "0", 0); + ui_skip_eamovie = Cvar_Get("ui_skip_eamovie", "1", 0); + ui_skip_titlescreen = Cvar_Get("ui_skip_titlescreen", "1", 0); + ui_skip_legalscreen = Cvar_Get("ui_skip_legalscreen", "1", 0); + ui_titlescreen_fadein = Cvar_Get("ui_titlescreen_fadein", "1", 0); + ui_titlescreen_fadeout = Cvar_Get("ui_titlescreen_fadeout", "1", 0); + ui_titlescreen_stay = Cvar_Get("ui_titlescreen_stay", "3", 0); + ui_legalscreen_fadein = Cvar_Get("ui_legalscreen_fadein", "1", 0); + ui_legalscreen_fadeout = Cvar_Get("ui_legalscreen_fadeout", "1", 0); + ui_legalscreen_stay = Cvar_Get("ui_legalscreen_stay", "3", 0); + cl_greenfps = Cvar_Get("cl_greenfps", "0", 1); + cl_playintro = Cvar_Get("cl_playintro", "1", 0); + cl_movieaudio = Cvar_Get("cl_movieaudio", "1", 0); + Cvar_Get("ui_startmap", "", 1); + Cvar_Get("dlg_badsave", "This save game is invalid", 0); - Cvar_Set( "cg_hud", ui_hud ? "1" : "0" ); + Cvar_Set("cg_hud", ui_hud ? "1" : "0"); - CL_FillUIDef(); - CL_FillUIImports(); - UI_InitExports(); - uie.Init(); + CL_FillUIDef(); + CL_FillUIImports(); + UI_InitExports(); + uie.Init(); - UI_LoadInventory_f(); - UI_CreateScoreboard(); + UI_LoadInventory_f(); + UI_CreateScoreboard(); - // New since mohta - // Version number - Cvar_Set("game_version", va("v%s", com_target_version->string)); + // New since mohta + // Version number + Cvar_Set("game_version", va("v%s", com_target_version->string)); - // Add all commands - Cmd_AddCommand( "pushmenu", UI_PushMenu_f ); - Cmd_AddCommand( "pushmenu_sp", UI_PushMenuSP_f ); - Cmd_AddCommand( "pushmenu_dm", UI_PushMenuMP_f ); - Cmd_AddCommand( "forcemenu", UI_ForceMenu_f ); - Cmd_AddCommand( "popmenu", UI_PopMenu_f ); - Cmd_AddCommand( "showmenu", UI_ShowMenu_f ); - Cmd_AddCommand( "hidemenu", UI_HideMenu_f ); - Cmd_AddCommand( "widgetcommand", UI_WidgetCommand_f ); - Cmd_AddCommand( "globalwidgetcommand", UI_GlobalWidgetCommand_f ); - Cmd_AddCommand( "listmenus", UI_ListMenus_f ); - Cmd_AddCommand( "togglemenu", UI_ToggleMenu_f ); - Cmd_AddCommand( "loadmenu", UI_LoadMenu_f ); - Cmd_AddCommand( "maplist", UI_MapList_f ); - Cmd_AddCommand( "dmmapselect", UI_DMMapSelect_f ); - Cmd_AddCommand( "ui_startdmmap", UI_StartDMMap_f ); - Cmd_AddCommand( "viewspawnlist", UI_ViewSpawnList_f ); - Cmd_AddCommand( "lod_spawnlist", UI_LODSpawnList_f ); - Cmd_AddCommand( "soundpicker", UI_SoundPicker_f ); - Cmd_AddCommand( "notepad", UI_Notepad_f ); - Cmd_AddCommand( "editscript", UI_EditScript_f ); - Cmd_AddCommand( "editshader", UI_EditShader_f ); - Cmd_AddCommand( "editspecificshader", UI_EditSpecificShader_f ); - Cmd_AddCommand( "inv_restart", UI_LoadInventory_f ); - Cmd_AddCommand( "ui_showmouse", UI_ShowMouse_f ); - Cmd_AddCommand( "ui_hidemouse", UI_HideMouse_f ); - Cmd_AddCommand( "ui_saveconsolepos", SaveConsoleRectangle ); - Cmd_AddCommand( "ui_loadconsolepos", LoadConsoleRectangle ); - Cmd_AddCommand( "ui_testlist", UI_TestListCtrl_f ); - Cmd_AddCommand( "clear", UI_ClearConsole_f ); - Cmd_AddCommand( "ui_hud", UI_Hud_f ); - Cmd_AddCommand( "ui_resetcvars", UI_ResetCvars ); - Cmd_AddCommand( "ui_checkrestart", UI_CheckRestart ); - Cmd_AddCommand( "centerprint", UI_CenterPrint_f ); - Cmd_AddCommand( "locationprint", UI_LocationPrint_f ); - Cmd_AddCommand( "ui_addhud", UI_AddHud_f ); - Cmd_AddCommand( "ui_removehud", UI_RemoveHud_f ); - Cmd_AddCommand( "startserver", UI_StartServer_f ); - Cmd_AddCommand( "finishloadingscreen", UI_FinishLoadingScreen_f ); - Cmd_AddCommand( "playermodel", UI_PlayerModel_f ); - Cmd_AddCommand( "ui_applyplayermodel", UI_ApplyPlayerModel_f ); - Cmd_AddCommand( "ui_getplayermodel", UI_GetPlayerModel_f ); - Cmd_AddCommand( "+statistics", UI_ShowStatistics_f ); - Cmd_AddCommand( "-statistics", UI_HideStatistics_f ); - Cmd_AddCommand( "setreturnmenu", UI_SetReturnMenuToCurrent ); - Cmd_AddCommand( "gotoreturnmenu", UI_PushReturnMenu_f ); + // Add all commands + Cmd_AddCommand("pushmenu", UI_PushMenu_f); + Cmd_AddCommand("pushmenu_sp", UI_PushMenuSP_f); + Cmd_AddCommand("pushmenu_dm", UI_PushMenuMP_f); + Cmd_AddCommand("forcemenu", UI_ForceMenu_f); + Cmd_AddCommand("popmenu", UI_PopMenu_f); + Cmd_AddCommand("showmenu", UI_ShowMenu_f); + Cmd_AddCommand("hidemenu", UI_HideMenu_f); + Cmd_AddCommand("widgetcommand", UI_WidgetCommand_f); + Cmd_AddCommand("globalwidgetcommand", UI_GlobalWidgetCommand_f); + Cmd_AddCommand("listmenus", UI_ListMenus_f); + Cmd_AddCommand("togglemenu", UI_ToggleMenu_f); + Cmd_AddCommand("loadmenu", UI_LoadMenu_f); + Cmd_AddCommand("maplist", UI_MapList_f); + Cmd_AddCommand("dmmapselect", UI_DMMapSelect_f); + Cmd_AddCommand("ui_startdmmap", UI_StartDMMap_f); + Cmd_AddCommand("viewspawnlist", UI_ViewSpawnList_f); + Cmd_AddCommand("lod_spawnlist", UI_LODSpawnList_f); + Cmd_AddCommand("soundpicker", UI_SoundPicker_f); + Cmd_AddCommand("notepad", UI_Notepad_f); + Cmd_AddCommand("editscript", UI_EditScript_f); + Cmd_AddCommand("editshader", UI_EditShader_f); + Cmd_AddCommand("editspecificshader", UI_EditSpecificShader_f); + Cmd_AddCommand("inv_restart", UI_LoadInventory_f); + Cmd_AddCommand("ui_showmouse", UI_ShowMouse_f); + Cmd_AddCommand("ui_hidemouse", UI_HideMouse_f); + Cmd_AddCommand("ui_saveconsolepos", SaveConsoleRectangle); + Cmd_AddCommand("ui_loadconsolepos", LoadConsoleRectangle); + Cmd_AddCommand("ui_testlist", UI_TestListCtrl_f); + Cmd_AddCommand("clear", UI_ClearConsole_f); + Cmd_AddCommand("ui_hud", UI_Hud_f); + Cmd_AddCommand("ui_resetcvars", UI_ResetCvars); + Cmd_AddCommand("ui_checkrestart", UI_CheckRestart); + Cmd_AddCommand("centerprint", UI_CenterPrint_f); + Cmd_AddCommand("locationprint", UI_LocationPrint_f); + Cmd_AddCommand("ui_addhud", UI_AddHud_f); + Cmd_AddCommand("ui_removehud", UI_RemoveHud_f); + Cmd_AddCommand("startserver", UI_StartServer_f); + Cmd_AddCommand("finishloadingscreen", UI_FinishLoadingScreen_f); + Cmd_AddCommand("playermodel", UI_PlayerModel_f); + Cmd_AddCommand("ui_applyplayermodel", UI_ApplyPlayerModel_f); + Cmd_AddCommand("ui_getplayermodel", UI_GetPlayerModel_f); + Cmd_AddCommand("+statistics", UI_ShowStatistics_f); + Cmd_AddCommand("-statistics", UI_HideStatistics_f); + Cmd_AddCommand("setreturnmenu", UI_SetReturnMenuToCurrent); + Cmd_AddCommand("gotoreturnmenu", UI_PushReturnMenu_f); + Cmd_AddCommand("salesscreen", UI_SalesScreen_f); + Cmd_AddCommand("launchgamespy", UI_LaunchGameSpy_f); - if( developer->integer ) - { - UColor bgColor; + if (developer->integer) { + UColor bgColor; - Cmd_AddCommand( "devcon", UI_ToggleDeveloperConsole_f ); + Cmd_AddCommand("devcon", UI_ToggleDeveloperConsole_f); - developer_console = new UIFloatingConsole; + developer_console = new UIFloatingConsole; - bgColor = UWindowColor; + bgColor = UWindowColor; - developer_console->Create( NULL, getDefaultConsoleRectangle(), "Developer Console", bgColor, UHudColor ); - developer_console->setConsoleHandler( ConsoleCommandHandler ); - developer_console->setConsoleBackground( UBlack, 0.800000011920929 ); - developer_console->setShow( false ); - developer_console->Connect( &s_consolehider, UIFloatingWindow::W_ClosePressed, UIFloatingWindow::W_ClosePressed ); - developer_console->Connect( &s_consolehider, W_Destroyed, W_Destroyed ); - } + developer_console->Create(NULL, getDefaultConsoleRectangle(), "Developer Console", bgColor, UHudColor); + developer_console->setConsoleHandler(ConsoleCommandHandler); + developer_console->setConsoleBackground(UBlack, 0.800000011920929); + developer_console->setShow(false); + developer_console->Connect(&s_consolehider, UIFloatingWindow::W_ClosePressed, UIFloatingWindow::W_ClosePressed); + developer_console->Connect(&s_consolehider, W_Destroyed, W_Destroyed); + } - // Create the 3D view - view3d = new View3D; - view3d->setAlwaysOnBottom( true ); - view3d->InitFrame( NULL, 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, -1, "facfont-20" ); - view3d->setName( "view3d" ); - view3d->InitSubtitle(); + // Create the 3D view + view3d = new View3D; + view3d->setAlwaysOnBottom(true); + view3d->InitFrame(NULL, 0, 0, uid.vidWidth, uid.vidHeight, -1, "facfont-20"); + view3d->setName("view3d"); + view3d->InitSubtitle(); - memset( &intro_stage, 0, sizeof( intro_stage ) ); + memset(&intro_stage, 0, sizeof(intro_stage)); - // Register the loading material - ui_static_materials.loading = uWinMan.RegisterShader( "textures/menu/loading" ); + // Register the loading material + ui_static_materials.loading = uWinMan.RegisterShader("textures/menu/loading"); - if( ui_console->integer || developer->integer > 0 ) - { - UColor bgColor = UWindowColor; + if (ui_console->integer || developer->integer > 0) { + UColor bgColor = UWindowColor; - // Create the console - fakk_console = getNewConsole(); + // Create the console + fakk_console = getNewConsole(); - bgColor = UColor( 0.0, 0.5, 1.0, 1.0 ); + bgColor = UColor(0.0, 0.5, 1.0, 1.0); - // Create the mini console - mini_console = new FakkMiniconsole; - mini_console->Create( UISize2D( 500, 100 ), UWhite, bgColor, 0.2f ); - mini_console->setAlwaysOnBottom( true ); - mini_console->setBorderStyle( border_none ); - } + // Create the mini console + mini_console = new FakkMiniconsole; + mini_console->Create(UISize2D(500, 100), UWhite, bgColor, 0.2f); + mini_console->setAlwaysOnBottom(true); + mini_console->setBorderStyle(border_none); + } - // Create the dm console - if( !dm_console ) { - dm_console = getNewDMConsole(); - } + // Create the dm console + if (!dm_console) { + dm_console = getNewDMConsole(); + } - // Create the game message box - if( ui_gmbox->integer && !gmbox ) - { - gmbox = new UIGMBox; - gmbox->Create( getDefaultGMBoxRectangle(), UHudColor, UHudColor, 0.0 ); - gmbox->setAlwaysOnBottom( true ); - gmbox->setBorderStyle( border_none ); - } + // Create the game message box + if (ui_gmbox->integer && !gmbox) { + gmbox = new UIGMBox; + gmbox->Create(getDefaultGMBoxRectangle(), UHudColor, UHudColor, 0.0); + gmbox->setAlwaysOnBottom(true); + gmbox->setBorderStyle(border_none); + } - // Create the deathmatch message box - if( !dmbox ) - { - dmbox = new UIDMBox; - dmbox->Create( getDefaultDMBoxRectangle(), UHudColor, UHudColor, 0.0 ); - dmbox->setAlwaysOnBottom( true ); - dmbox->setBorderStyle( border_outline ); - } + // Create the deathmatch message box + if (!dmbox) { + dmbox = new UIDMBox; + dmbox->Create(getDefaultDMBoxRectangle(), UHudColor, UHudColor, 0.0); + dmbox->setAlwaysOnBottom(true); + dmbox->setBorderStyle(border_outline); + } - // Load all urc files - filenames = FS_ListFiles( "ui/", "urc", qfalse, &nfiles ); + // Load all urc files + filenames = FS_ListFiles("ui/", "urc", qfalse, &nfiles); - for( i = 0; i < nfiles; i++ ) - { - char szFilename[ MAX_QPATH ]; + for (i = 0; i < nfiles; i++) { + char szFilename[MAX_QPATH]; - Com_sprintf( szFilename, sizeof( szFilename ), "ui/%s", filenames[ i ] ); - new UILayout( szFilename ); - } + Com_sprintf(szFilename, sizeof(szFilename), "ui/%s", filenames[i]); + new UILayout(szFilename); + } - FS_FreeFileList( filenames ); + FS_FreeFileList(filenames); - uWinMan.CreateMenus(); + uWinMan.CreateMenus(); - // find the crosshair - crosshairhud = menuManager.FindMenu( "crosshair" ); - // find weapons hud - hud_weapons = menuManager.FindMenu( "hud_weapons" ); - // find items hud - hud_items = menuManager.FindMenu( "hud_items" ); - // find the health hud - hud_health = menuManager.FindMenu( "hud_health" ); - // find the compass hud - hud_compass = menuManager.FindMenu( "hud_compass" ); - // find the boss health hud - hud_boss = menuManager.FindMenu( "hud_boss" ); - // find the stats screen - missionLog = menuManager.FindMenu( "StatsScreen" ); - // find the connection menu - ui_pConnectingMenu = menuManager.FindMenu( "connecting" ); + // find the crosshair + // Removed in 2.0 + // Crosshair is now handled by the cgame module + //crosshairhud = menuManager.FindMenu("crosshair"); + // find weapons hud + hud_weapons = menuManager.FindMenu("hud_weapons"); + // find items hud + hud_items = menuManager.FindMenu("hud_items"); + // find the health hud + hud_health = menuManager.FindMenu("hud_health"); + // find the compass hud + hud_compass = menuManager.FindMenu("hud_compass"); + // find the boss health hud + hud_boss = menuManager.FindMenu("hud_boss"); + // find the stats screen + missionLog = menuManager.FindMenu("StatsScreen"); + // find the connection menu + ui_pConnectingMenu = menuManager.FindMenu("connecting"); - if( crosshairhud ) { - crosshairhud->ShowMenu( NULL ); - } - if( hud_health ) { - hud_health->ShowMenu( NULL ); - } - if( hud_compass ) { - hud_compass->ShowMenu( NULL ); - } + if (crosshairhud) { + crosshairhud->ShowMenu(NULL); + } + if (hud_health) { + hud_health->ShowMenu(NULL); + } + if (hud_compass) { + hud_compass->ShowMenu(NULL); + } - // find the main menu - mainmenu = menuManager.FindMenu( "main" ); + // find the main menu + mainmenu = menuManager.FindMenu("main"); - IN_MouseOn(); + IN_MouseOn(); - // realign menus - menuManager.RealignMenus(); + // realign menus + menuManager.RealignMenus(); - // clear input - CL_ClearButtons(); + // clear input + CL_ClearButtons(); - cls.uiStarted = qtrue; + cls.uiStarted = qtrue; + + if (!com_dedicated->integer) { + CL_TryStartIntro(); + } } -static char **loadStrings; +static char **loadStrings; static unsigned int *loadTimes; -static char *loadStringsBuffer; +static char *loadStringsBuffer; -class LoadResourceInfo { +class LoadResourceInfo +{ public: - class LoadResourceInfo *next; - unsigned int loadCount; - char name[ 1 ]; + class LoadResourceInfo *next; + unsigned int loadCount; + char name[1]; public: - LoadResourceInfo(); + LoadResourceInfo(); }; static LoadResourceInfo *loadHead; @@ -5472,11 +5498,12 @@ static LoadResourceInfo *loadHead; UI_BeginLoadResource ==================== */ -void UI_BeginLoadResource( void ) { - clock_t time = clock(); +void UI_BeginLoadResource(void) +{ + clock_t time = clock(); - startCountHigh = time >> 32; - startCountLow = time; + startCountHigh = time >> 32; + startCountLow = time; } /* @@ -5484,7 +5511,15 @@ void UI_BeginLoadResource( void ) { UI_EndLoadResource ==================== */ -void UI_EndLoadResource( void ) { +void UI_EndLoadResource(void) +{ + clock_t time; + + time = clock() - (((clock_t)startCountHigh << 32) | startCountLow) + (((clock_t)loadCountHigh << 32) | loadCountLow); + + loadCountHigh = time >> 32; + loadCountLow = time; + loadCount = time >> 25; } /* @@ -5492,22 +5527,23 @@ void UI_EndLoadResource( void ) { UI_EndLoadResource ==================== */ -void UI_EndLoadResource( const char *name ) { - LoadResourceInfo *newLoadHead; +void UI_EndLoadResource(const char *name) +{ + LoadResourceInfo *newLoadHead; - if( !loadCount ) { - return; - } + if (!loadCount) { + return; + } - newLoadHead = ( LoadResourceInfo * )Z_Malloc( sizeof( LoadResourceInfo ) + strlen( name ) ); - newLoadHead->next = loadHead; - newLoadHead->loadCount = loadCount; - strcpy( newLoadHead->name, name ); - loadHead = newLoadHead; + newLoadHead = (LoadResourceInfo *)Z_Malloc(sizeof(LoadResourceInfo) + strlen(name)); + newLoadHead->next = loadHead; + newLoadHead->loadCount = loadCount; + strcpy(newLoadHead->name, name); + loadHead = newLoadHead; - loadNumber++; - loadCountLow = 0; - loadCountHigh = 0; + loadNumber++; + loadCountLow = 0; + loadCountHigh = 0; } /* @@ -5515,25 +5551,25 @@ void UI_EndLoadResource( const char *name ) { UI_IsResourceLoaded ==================== */ -qboolean UI_IsResourceLoaded( const char *name ) { - switch( *name ) - { - case 97: - case 98: - case 99: - case 100: - case 101: - case 104: - return TIKI_FindTikiAnim( name + 1 ) != NULL; - case 103: - return SkeletorCacheFindFilename( name + 1, NULL ); - case 107: - return S_IsSoundRegistered( name + 1 ); - case 110: - return R_ImageExists( name + 1 ); - default: - return qfalse; - } +qboolean UI_IsResourceLoaded(const char *name) +{ + switch (*name) { + case 97: + case 98: + case 99: + case 100: + case 101: + case 104: + return TIKI_FindTikiAnim(name + 1) != NULL; + case 103: + return SkeletorCacheFindFilename(name + 1, NULL); + case 107: + return S_IsSoundRegistered(name + 1); + case 110: + return uii.Rend_ImageExists(name + 1); + default: + return qfalse; + } } /* @@ -5541,34 +5577,28 @@ qboolean UI_IsResourceLoaded( const char *name ) { UI_RegisterLoadResource ==================== */ -void UI_RegisterLoadResource( const char *name ) { - int i, j; - int low, high; +void UI_RegisterLoadResource(const char *name) +{ + int i, j; + int low, high; - low = 0; - high = loadNumber - 1; + low = 0; + high = loadNumber - 1; - while( low <= high ) - { - i = ( high + low ) / 2; - j = strcmp( name, loadStrings[ i ] ); + while (low <= high) { + i = (low + high) / 2; + j = strcmp(name, loadStrings[i]); - if( j >= 0 ) - { - if( j <= 0 ) - { - currentLoadTime += loadTimes[ i ]; - loadTimes[ i ] = 0; - return; - } - - low = i + 1; - } - else - { - high = i - 1; - } - } + if (j < 0) { + high = i - 1; + } else if (j > 0) { + low = i + 1; + } else { + currentLoadTime += loadTimes[i]; + loadTimes[i] = 0; + break; + } + } } /* @@ -5576,15 +5606,22 @@ void UI_RegisterLoadResource( const char *name ) { UI_TestUpdateScreen ==================== */ -void UI_TestUpdateScreen( unsigned int timeout ) { - unsigned int newTime = Sys_Milliseconds(); +void UI_TestUpdateScreen(unsigned int timeout) +{ + unsigned int newTime = Sys_Milliseconds(); + unsigned int startRenderTime, endRenderTime; - if( newTime - lastTime >= timeout ) - { - lastTime = newTime; - Sys_PumpMessageLoop(); - SCR_UpdateScreen(); - } + if (timeout > 0 && (newTime - lastTime) < (timeout + updateTime)) { + return; + } + + startRenderTime = Sys_Milliseconds(); + Sys_PumpMessageLoop(); + SCR_UpdateScreen(); + endRenderTime = Sys_Milliseconds(); + + updateTime = Q_min(endRenderTime - startRenderTime, 1000); + lastTime = endRenderTime; } /* @@ -5592,13 +5629,14 @@ void UI_TestUpdateScreen( unsigned int timeout ) { UI_ClearResource ==================== */ -void UI_ClearResource( void ) { - if( cls.loading == SS_DEAD || cls.loading != SS_GAME ) { - return; - } +void UI_ClearResource(void) +{ + if (cls.loading == SS_DEAD || cls.loading != SS_GAME) { + return; + } - UI_BeginLoadResource(); - UI_TestUpdateScreen( 0 ); + UI_BeginLoadResource(); + UI_TestUpdateScreen(0); } /* @@ -5606,24 +5644,22 @@ void UI_ClearResource( void ) { UI_LoadResource ==================== */ -void UI_LoadResource( const char *name ) { - if (cls.loading == SS_DEAD) { - return; - } +void UI_LoadResource(const char *name) +{ + if (cls.loading == SS_DEAD) { + return; + } - if (cls.loading == SS_GAME) - { - UI_EndLoadResource(); - UI_EndLoadResource(name); - UI_BeginLoadResource(); - } - else if (cls.loading == SS_LOADING2) - { - UI_RegisterLoadResource(name); - Cvar_SetValue("loadingbar", (float)currentLoadTime / (float)totalLoadTime); - } + if (cls.loading == SS_GAME) { + UI_EndLoadResource(); + UI_EndLoadResource(name); + UI_BeginLoadResource(); + } else if (cls.loading == SS_LOADING2) { + UI_RegisterLoadResource(name); + Cvar_SetValue("loadingbar", (float)currentLoadTime / (float)totalLoadTime); + } - UI_TestUpdateScreen(333u); + UI_TestUpdateScreen(33); } /* @@ -5631,12 +5667,12 @@ void UI_LoadResource( const char *name ) { UI_FreeLoadStrings ==================== */ -void UI_FreeLoadStrings() { - if( loadStrings ) - { - Z_Free( loadStrings ); - loadStrings = NULL; - } +void UI_FreeLoadStrings() +{ + if (loadStrings) { + Z_Free(loadStrings); + loadStrings = NULL; + } } /* @@ -5644,15 +5680,15 @@ void UI_FreeLoadStrings() { UI_DeleteLoadInfo ==================== */ -void UI_DeleteLoadInfo() { - LoadResourceInfo *ptr; - LoadResourceInfo *nextPtr; +void UI_DeleteLoadInfo() +{ + LoadResourceInfo *ptr; + LoadResourceInfo *nextPtr; - for( ptr = loadHead; ptr != NULL; ptr = nextPtr ) - { - nextPtr = ptr->next; - Z_Free( ptr ); - } + for (ptr = loadHead; ptr != NULL; ptr = nextPtr) { + nextPtr = ptr->next; + Z_Free(ptr); + } } /* @@ -5660,59 +5696,55 @@ void UI_DeleteLoadInfo() { UI_ParseLoadMapinfo ==================== */ -bool UI_ParseLoadMapinfo(Script* scr) { - int size, index; - int allocLen; - char* pos; - const char* token; - char* newPos; - int time; +bool UI_ParseLoadMapinfo(Script *scr) +{ + int size, index; + int allocLen; + char *pos; + const char *token; + char *newPos; + int time; - loadNumber = scr->GetInteger(false); - size = scr->GetInteger(false); - scr->SkipWhiteSpace(true); + loadNumber = scr->GetInteger(false); + size = scr->GetInteger(false); + scr->SkipWhiteSpace(true); - allocLen = size + sizeof(loadStrings[0]) * loadNumber + sizeof(loadTimes[0]) * loadNumber; - loadStrings = (char**)Z_Malloc(allocLen); - loadTimes = (unsigned int*)(loadStrings + loadNumber); - loadStringsBuffer = (char*)(loadTimes + loadNumber); - pos = loadStringsBuffer; + allocLen = size + sizeof(loadStrings[0]) * loadNumber + sizeof(loadTimes[0]) * loadNumber; + loadStrings = (char **)Z_Malloc(allocLen); + loadTimes = (unsigned int *)(loadStrings + loadNumber); + loadStringsBuffer = (char *)(loadTimes + loadNumber); + pos = loadStringsBuffer; - totalLoadTime = 0; - index = 0; + totalLoadTime = 0; + index = 0; - do - { - token = scr->GetToken(true); - newPos = &pos[strlen(token) + 1]; - strcpy(pos, token); - loadStrings[index] = pos; + do { + token = scr->GetToken(true); + newPos = &pos[strlen(token) + 1]; + strcpy(pos, token); + loadStrings[index] = pos; - time = scr->GetInteger(true); + time = scr->GetInteger(true); - if (UI_IsResourceLoaded(pos)) - { - loadTimes[index] = 0; - } - else - { - loadTimes[index] = time; - totalLoadTime += time; - } + if (UI_IsResourceLoaded(pos)) { + loadTimes[index] = 0; + } else { + loadTimes[index] = time; + totalLoadTime += time; + } - pos = newPos; - index++; - } while (index != loadNumber); + pos = newPos; + index++; + } while (index != loadNumber); - assert(pos <= (char*)loadStrings + allocLen); + assert(pos <= (char *)loadStrings + allocLen); - if (newPos != loadStringsBuffer + size) - { - UI_FreeLoadStrings(); - return false; - } + if (newPos != loadStringsBuffer + size) { + UI_FreeLoadStrings(); + return false; + } - return true; + return true; } /* @@ -5720,35 +5752,35 @@ bool UI_ParseLoadMapinfo(Script* scr) { UI_ArchiveLoadMapinfo ==================== */ -bool UI_ArchiveLoadMapinfo( const char *mapname ) { - Script scr; - int version; - byte *tempbuf; - int length; - bool success; +bool UI_ArchiveLoadMapinfo(const char *mapname) +{ + Script scr; + int version; + byte *tempbuf; + int length; + bool success; - length = FS_ReadFile( loadName, ( void ** )&tempbuf ); + length = FS_ReadFile(loadName, (void **)&tempbuf); - if( length <= 0 ) { - return false; - } + if (length <= 0) { + return false; + } - scr.LoadFile( loadName, length, ( const char * )tempbuf ); - FS_FreeFile( tempbuf ); + scr.LoadFile(loadName, length, (const char *)tempbuf); + FS_FreeFile(tempbuf); - version = scr.GetInteger( false ); - scr.SkipWhiteSpace( true ); + version = scr.GetInteger(false); + scr.SkipWhiteSpace(true); - if( version == 3 ) - { - success = UI_ParseLoadMapinfo( &scr ); - } else { - Com_Printf( "Expecting version %d map info file. Map info is version %d.\n", 3, version ); - success = false; - } + if (version == 3) { + success = UI_ParseLoadMapinfo(&scr); + } else { + Com_Printf("Expecting version %d map info file. Map info is version %d.\n", 3, version); + success = false; + } - scr.Close(); - return success; + scr.Close(); + return success; } /* @@ -5756,109 +5788,107 @@ bool UI_ArchiveLoadMapinfo( const char *mapname ) { UI_BeginLoad ==================== */ -void UI_BeginLoad( const char *pszMapName ) { - str mapfile; +void UI_BeginLoad(const char *pszMapName) +{ + str mapfile; - if( cls.loading ) - { - if( cls.loading == SS_GAME ) { - UI_DeleteLoadInfo(); - } + if (cls.loading) { + if (cls.loading == SS_GAME) { + UI_DeleteLoadInfo(); + } - UI_FreeLoadStrings(); - cls.loading = SS_DEAD; - } + UI_FreeLoadStrings(); + cls.loading = SS_DEAD; + } - server_loading = qtrue; - server_loading_waiting = qfalse; - strcpy( server_mapname, pszMapName ); + server_loading = qtrue; + server_loading_waiting = qfalse; + strcpy(server_mapname, pszMapName); - if( str::icmp( ui_sCurrentLoadingMenu, server_mapname ) ) - { - ui_sCurrentLoadingMenu = server_mapname; - ui_pLoadingMenu = menuManager.FindMenu( ui_sCurrentLoadingMenu ); - } + if (str::icmp(ui_sCurrentLoadingMenu, server_mapname)) { + ui_sCurrentLoadingMenu = server_mapname; + ui_pLoadingMenu = menuManager.FindMenu(ui_sCurrentLoadingMenu); + } - if( !ui_pLoadingMenu ) - { - ui_sCurrentLoadingMenu = "loading_default"; - ui_pLoadingMenu = menuManager.FindMenu( ui_sCurrentLoadingMenu ); - } + if (!ui_pLoadingMenu) { + ui_sCurrentLoadingMenu = "loading_default"; + ui_pLoadingMenu = menuManager.FindMenu(ui_sCurrentLoadingMenu); + } - UI_ForceMenuOff( true ); - UI_DeactiveFloatingWindows(); + UI_ForceMenuOff(true); + UI_DeactiveFloatingWindows(); - if (ui_pLoadingMenu) - { - if (!developer->integer && UI_ConsoleIsVisible()) { - UI_CloseConsole(); - } + if (ui_pLoadingMenu) { + if (!developer->integer && UI_ConsoleIsVisible()) { + UI_CloseConsole(); + } - ui_pLoadingMenu->PassEventToWidget("continuebutton", new Event(EV_Widget_Disable)); + ui_pLoadingMenu->PassEventToWidget("continuebutton", new Event(EV_Widget_Disable)); - loadName = "maps/"; - loadName += pszMapName; - loadName += ".min"; - mapfile = loadName + ".bsp"; + loadName = "maps/"; + loadName += pszMapName; + mapfile = loadName; + loadName += ".min"; - if (UI_ArchiveLoadMapinfo(mapfile)) { - cls.loading = SS_LOADING2; - } - else { - cls.loading = SS_GAME; - } + if (CL_UseLargeLightmap(pszMapName)) { + mapfile += ".bsp"; + } else { + // Added in 2.0 + mapfile += "_sml.bsp"; + } - if (cls.loading == SS_LOADING2) - { - ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Disable)); - ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Enable)); - ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Enable)); + if (UI_ArchiveLoadMapinfo(mapfile)) { + cls.loading = SS_LOADING2; + } else { + cls.loading = SS_GAME; + } - currentLoadTime = 0; - Cvar_SetValue("loadingbar", 0); + if (cls.loading == SS_LOADING2) { + ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Disable)); + ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Enable)); + ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Enable)); - L_ProcessPendingEvents(); + currentLoadTime = 0; + Cvar_SetValue("loadingbar", 0); - lastTime = Sys_Milliseconds(); - if (com_sv_running->integer) { - SCR_UpdateScreen(); - } - } - else - { - ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Enable)); - ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Disable)); - ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Disable)); + L_ProcessPendingEvents(); - UI_BeginLoadResource(); - loadCountLow = 0; - loadCountHigh = 0; - loadHead = NULL; - loadNumber = 0; + lastTime = Sys_Milliseconds(); + if (com_sv_running->integer) { + SCR_UpdateScreen(); + } + } else { + ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Enable)); + ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Disable)); + ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Disable)); - cls.loading = SS_LOADING; + UI_BeginLoadResource(); + loadCountLow = 0; + loadCountHigh = 0; + loadHead = NULL; + loadNumber = 0; - L_ProcessPendingEvents(); - lastTime = Sys_Milliseconds(); + cls.loading = SS_LOADING; - if (com_sv_running->integer) { - SCR_UpdateScreen(); - } - } - } - else - { - cls.loading = SS_LOADING; + L_ProcessPendingEvents(); + lastTime = Sys_Milliseconds(); - // process all events - L_ProcessPendingEvents(); + if (com_sv_running->integer) { + SCR_UpdateScreen(); + } + } + } else { + cls.loading = SS_LOADING; - lastTime = Sys_Milliseconds(); + // process all events + L_ProcessPendingEvents(); - if (com_sv_running->integer) { - SCR_UpdateScreen(); - } - } + lastTime = Sys_Milliseconds(); + + if (com_sv_running->integer) { + SCR_UpdateScreen(); + } + } } /* @@ -5866,11 +5896,12 @@ void UI_BeginLoad( const char *pszMapName ) { UI_CompareLoadResources ==================== */ -int UI_CompareLoadResources( const void *elem1, const void *elem2 ) { - LoadResourceInfo *e1 = *( LoadResourceInfo ** )elem1; - LoadResourceInfo *e2 = *( LoadResourceInfo ** )elem2; +int UI_CompareLoadResources(const void *elem1, const void *elem2) +{ + LoadResourceInfo *e1 = *(LoadResourceInfo **)elem1; + LoadResourceInfo *e2 = *(LoadResourceInfo **)elem2; - return strcmp( e1->name, e2->name ); + return strcmp(e1->name, e2->name); } /* @@ -5878,79 +5909,72 @@ int UI_CompareLoadResources( const void *elem1, const void *elem2 ) { UI_EndLoad ==================== */ -void UI_EndLoad( void ) { - LoadResourceInfo *ptr; - LoadResourceInfo **base; - int i; - fileHandle_t file; - int size; - char buf[ 1024 ]; +void UI_EndLoad(void) +{ + LoadResourceInfo *ptr; + LoadResourceInfo **base; + int i; + fileHandle_t file; + int size; + char buf[1024]; - if( !cls.loading ) { - return; - } + if (!cls.loading) { + return; + } - UI_LoadResource( "*end" ); + UI_LoadResource("*end"); - if( cls.loading == SS_GAME ) - { - base = ( LoadResourceInfo ** )Z_Malloc( loadNumber * sizeof( LoadResourceInfo * ) ); + if (cls.loading == SS_GAME) { + base = (LoadResourceInfo **)Z_Malloc(loadNumber * sizeof(LoadResourceInfo *)); - i = 0; - for( ptr = loadHead; ptr != NULL; ptr = ptr->next ) - { - base[ i ] = ptr; - i++; - } + i = 0; + for (ptr = loadHead; ptr != NULL; ptr = ptr->next) { + base[i] = ptr; + i++; + } - qsort( base, loadNumber, sizeof( LoadResourceInfo * ), UI_CompareLoadResources ); + qsort(base, loadNumber, sizeof(LoadResourceInfo *), UI_CompareLoadResources); - size = 0; - for( i = 0; i < loadNumber; i++ ) - { - ptr = base[ i ]; - size += strlen( ptr->name ) + 1; - } + size = 0; + for (i = 0; i < loadNumber; i++) { + ptr = base[i]; + size += strlen(ptr->name) + 1; + } - file = FS_FOpenFileWrite( loadName ); - sprintf( buf, "%d\n%d %d\n", 3, loadNumber, size ); + file = FS_FOpenFileWrite(loadName); + Com_sprintf(buf, sizeof(buf), "%d\n%d %d\n", 3, loadNumber, size); - FS_Write( buf, strlen( buf ), file ); + FS_Write(buf, strlen(buf), file); - for( i = 0; i < loadNumber; i++ ) - { - sprintf( buf, "%s\n%d\n", base[ i ]->name, base[ i ]->loadCount ); - FS_Write( buf, strlen( buf ), file ); - } + for (i = 0; i < loadNumber; i++) { + Com_sprintf(buf, sizeof(buf), "%s\n%d\n", base[i]->name, base[i]->loadCount); + FS_Write(buf, strlen(buf), file); + } - FS_FCloseFile( file ); - Z_Free( base ); - UI_DeleteLoadInfo(); - } - else if( cls.loading == SS_LOADING2 ) - { - if( ui_debugload->integer ) { - Com_Printf( "Following resources not accounted for on load:\n" ); - } + FS_FCloseFile(file); + Z_Free(base); + UI_DeleteLoadInfo(); + } else if (cls.loading == SS_LOADING2) { + if (ui_debugload->integer) { + Com_Printf("Following resources not accounted for on load:\n"); + } - for( i = 0; i < loadNumber; i++ ) - { - if( loadTimes[ i ] ) - { - if( ui_debugload->integer ) { - Com_Printf( "%s\n", loadStrings[ i ] ); - } + for (i = 0; i < loadNumber; i++) { + if (loadTimes[i]) { + if (ui_debugload->integer) { + Com_Printf("%s\n", loadStrings[i]); + } - loadTimes[ i ] = 0; - } - } + loadTimes[i] = 0; + } + } - currentLoadTime = totalLoadTime; - } + currentLoadTime = totalLoadTime; + } - UI_FreeLoadStrings(); + UI_FreeLoadStrings(); - cls.loading = SS_DEAD; + cls.loading = SS_DEAD; } /* @@ -5958,14 +5982,14 @@ void UI_EndLoad( void ) { UI_AbortLoad ==================== */ -void UI_AbortLoad( void ) { - if( cls.loading ) - { - if( cls.loading == SS_GAME ) { - UI_DeleteLoadInfo(); - } - cls.loading = SS_DEAD; - } +void UI_AbortLoad(void) +{ + if (cls.loading) { + if (cls.loading == SS_GAME) { + UI_DeleteLoadInfo(); + } + cls.loading = SS_DEAD; + } } /* @@ -5973,67 +5997,75 @@ void UI_AbortLoad( void ) { CL_FontStringWidth ==================== */ -int CL_FontStringWidth( fontheader_t *pFont, const char *pszString, int iMaxLen ) { - return uie.FontStringWidth( pFont, pszString, iMaxLen ); +int CL_FontStringWidth(fontheader_t *pFont, const char *pszString, int iMaxLen) +{ + return uie.FontStringWidth(pFont, pszString, iMaxLen); } -griditemtype_t TestListItem::getListItemType( int which ) const +griditemtype_t TestListItem::getListItemType(int which) const { - return TYPE_STRING; + return TYPE_STRING; } -str TestListItem::getListItemString( int i ) const +str TestListItem::getListItemString(int i) const { - return strings[ i ]; + return strings[i]; } -int TestListItem::getListItemValue( int i ) const +int TestListItem::getListItemValue(int i) const { - return atoi( strings[ i ] ); + return atoi(strings[i]); } -void TestListItem::DrawListItem( int iColumn, const UIRect2D &drawRect, bool bSelected, UIFont *pFont ) +void TestListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} + +qboolean TestListItem::IsHeaderEntry(void) const { + return qfalse; } -qboolean TestListItem::IsHeaderEntry( void ) const +void ScoreboardListItem::SetListItemStrings( + const char *string1, + const char *string2, + const char *string3, + const char *string4, + const char *string5, + const char *string6, + const char *string7, + const char *string8 +) { - return qfalse; + strings[0] = string1; + strings[1] = string2; + strings[2] = string3; + strings[3] = string4; + strings[4] = string5; + strings[5] = string6; + strings[6] = string7; + strings[7] = string8; } -void ScoreboardListItem::SetListItemStrings( const char *string1, const char *string2, const char *string3, const char *string4, const char *string5, const char *string6, const char *string7, const char *string8 ) +griditemtype_t ScoreboardListItem::getListItemType(int i) const { - strings[ 0 ] = string1; - strings[ 1 ] = string2; - strings[ 2 ] = string3; - strings[ 3 ] = string4; - strings[ 4 ] = string5; - strings[ 5 ] = string6; - strings[ 6 ] = string7; - strings[ 7 ] = string8; + return bColorSet != 0 ? TYPE_OWNERDRAW : TYPE_STRING; } -griditemtype_t ScoreboardListItem::getListItemType( int i ) const +str ScoreboardListItem::getListItemString(int i) const { - return bColorSet != 0 ? TYPE_OWNERDRAW : TYPE_STRING; + return strings[i]; } -str ScoreboardListItem::getListItemString( int i ) const +int ScoreboardListItem::getListItemValue(int i) const { - return strings[ i ]; + return atoi(strings[i]); } -int ScoreboardListItem::getListItemValue( int i ) const +void ScoreboardListItem::SetTitleItem(qboolean bSet) { - return atoi( strings[ i ] ); + bTitleItem = bSet; } -void ScoreboardListItem::SetTitleItem( qboolean bSet ) +qboolean ScoreboardListItem::IsHeaderEntry(void) const { - bTitleItem = bSet; -} - -qboolean ScoreboardListItem::IsHeaderEntry( void ) const -{ - return bTitleItem; + return bTitleItem; } diff --git a/code/client/cl_ui.h b/code/client/cl_ui.h index 6b9afb07..ab3a001e 100644 --- a/code/client/cl_ui.h +++ b/code/client/cl_ui.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,112 +20,137 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UI_H__ -#define __CL_UI_H__ +#pragma once #include "../uilib/ui_extern.h" #include "../uilib/uiwidget.h" typedef struct { - UIReggedMaterial *loading; + UIReggedMaterial *loading; } static_media_t; // // cvars // -extern cvar_t* ui_health_start; -extern cvar_t* ui_health_end; -extern cvar_t* sound_overlay; +extern cvar_t *ui_health_start; +extern cvar_t *ui_health_end; +extern cvar_t *sound_overlay; +extern cvar_t *cl_movieaudio; // // initialization // -void CL_FillUIDef( void ); -void CL_InitializeUI( void ); -void CL_ShutdownUI( void ); +void CL_FillUIDef(void); +void CL_InitializeUI(void); +void CL_ShutdownUI(void); // // general ui stuff // -extern inventory_t client_inv; -extern bind_t client_bind; -extern cvar_t* cl_greenfps; +extern inventory_t client_inv; +extern bind_t client_bind; +extern cvar_t *cl_greenfps; +extern qboolean server_loading; +extern const UColor UWhiteChatMessageColor; +extern const UColor URedChatMessageColor; +extern const UColor UGreenChatMessageColor; -const char *CvarGetForUI( const char *name, const char *defval ); -void UI_ClearState( void ); -void CL_BeginRegistration( void ); -void CL_EndRegistration(void); +const char *CvarGetForUI(const char *name, const char *defval); +void UI_ClearState(void); +void CL_BeginRegistration(void); +void CL_EndRegistration(void); +float UI_GetObjectivesTop(void); +void UI_GetHighResolutionScale(vec2_t scale); // // menu // extern Menu *ui_pLoadingMenu; -void UI_ShowMenu( const char *name, qboolean bForce ); -void UI_HideMenu( const char *name, qboolean bForce ); -void UI_ForceMenuOff( bool force ); -void UI_PushMenu( const char *name ); -void UI_ForceMenu( const char *name ); -qboolean UI_BindActive( void ); -void UI_SetReturnMenuToCurrent(void); -void UI_ActivateView3D( void ); -void UI_MenuEscape( const char *name ); -void UI_CreateScoreboard( void ); -qboolean UI_MenuActive( void ); -qboolean UI_MenuUp( void ); -void UI_FocusMenuIfExists(void); -void UI_DrawConnect( void ); -void UI_CreateDialog( const char *title, char *cvarname, const char *command, const char *cancelCommand, int width, int height, const char *shader, const char *okshader, const char *cancelshader ); -void UI_ToggleDMConsole( int iMode ); -void UI_ShowScoreboard_f( const char *pszMenuName ); -void UI_HideScoreboard_f( void ); -void UI_SetScoreBoardItem( int iItemNumber, - const char *pszData1, const char *pszData2, const char *pszData3, const char *pszData4, - const char *pszData5, const char *pszData6, const char *pszData7, const char *pszData8, - const vec4_t pTextColor, const vec4_t pBackColor, qboolean bIsHeader ); -void UI_DeleteScoreBoardItems( int iMaxIndex ); +void UI_ShowMenu(const char *name, qboolean bForce); +void UI_HideMenu(const char *name, qboolean bForce); +void UI_ForceMenuOff(bool force); +void UI_PushMenu(const char *name); +void UI_ForceMenu(const char *name); +qboolean UI_BindActive(void); +void UI_SetReturnMenuToCurrent(void); +void UI_ActivateView3D(void); +void UI_MenuEscape(const char *name); +void UI_CreateScoreboard(void); +qboolean UI_MenuActive(void); +qboolean UI_MenuUp(void); +void UI_FocusMenuIfExists(void); +void UI_DrawConnect(void); +void UI_CreateDialog( + const char *title, + char *cvarname, + const char *command, + const char *cancelCommand, + int width, + int height, + const char *shader, + const char *okshader, + const char *cancelshader + ); +void UI_ToggleDMConsole(int iMode); +void UI_ShowScoreboard_f(const char *pszMenuName); +void UI_HideScoreboard_f(void); +void UI_SetScoreBoardItem( + int iItemNumber, + const char *pszData1, + const char *pszData2, + const char *pszData3, + const char *pszData4, + const char *pszData5, + const char *pszData6, + const char *pszData7, + const char *pszData8, + const vec4_t pTextColor, + const vec4_t pBackColor, + qboolean bIsHeader +); +void UI_DeleteScoreBoardItems(int iMaxIndex); // // ressources // -void UI_BeginLoad( const char *pszMapName ); -void UI_EndLoad( void ); -void UI_AbortLoad( void ); -void UI_BeginLoadResource( void ); -void UI_EndLoadResource( void ); -void UI_EndLoadResource( const char *name ); -qboolean UI_IsResourceLoaded( const char *name ); -void UI_RegisterLoadResource( const char *name ); -void UI_ClearResource( void ); -void UI_LoadResource( const char *name ); +void UI_BeginLoad(const char *pszMapName); +void UI_EndLoad(void); +void UI_AbortLoad(void); +int CL_FontStringWidth(fontheader_t* pFont, const char* pszString, int iMaxLen); +void UI_BeginLoadResource(void); +void UI_EndLoadResource(void); +void UI_EndLoadResource(const char *name); +qboolean UI_IsResourceLoaded(const char *name); +void UI_RegisterLoadResource(const char *name); +void UI_ClearResource(void); +void UI_LoadResource(const char *name); // // windows // -void UI_DeactiveFloatingWindows( void ); +void UI_DeactiveFloatingWindows(void); // // console // -void UI_OpenConsole( void ); -qboolean UI_ConsoleIsVisible( void ); -qboolean UI_ConsoleIsOpen( void ); -void UI_CloseConsole( void ); -void UI_ToggleConsole( void ); -void UI_OpenDMConsole( int iMode ); -void UI_CloseDMConsole( void ); -void UI_ToggleDMConsole( int iMode ); -void UI_OpenDeveloperConsole( void ); -void UI_CloseDeveloperConsole( void ); -void UI_PrintConsole(const char* msg); +void UI_OpenConsole(void); +qboolean UI_ConsoleIsVisible(void); +qboolean UI_ConsoleIsOpen(void); +void UI_CloseConsole(void); +void UI_ToggleConsole(void); +void UI_OpenDMConsole(int iMode); +void UI_CloseDMConsole(void); +void UI_ToggleDMConsole(int iMode); +void UI_OpenDeveloperConsole(void); +void UI_CloseDeveloperConsole(void); +void UI_PrintConsole(const char *msg); // // callbacks // -void UI_Update( void ); -void UI_ServerLoaded( void ); -void UI_ResolutionChange( void ); -void UI_KeyEvent( int key, unsigned int time ); -void UI_CharEvent( int ch ); - -#endif /* __CL_UI_H__ */ +void UI_Update(void); +void UI_ServerLoaded(void); +void UI_ResolutionChange(void); +void UI_KeyEvent(int key, unsigned int time); +void UI_CharEvent(int ch); diff --git a/code/client/cl_uibind.cpp b/code/client/cl_uibind.cpp index 22ae1e58..8db44142 100644 --- a/code/client/cl_uibind.cpp +++ b/code/client/cl_uibind.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,281 +24,529 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA bind_t::bind_t() { - // FIXME: stub + int i; + + commandwidth = 100; + commandheight = 20; + primarykeywidth = 100; + primarykeyheight = 20; + alternatekeywidth = 100; + alternatekeyheight = 20; + fillwidth = 16; + fillmaterial = NULL; + + for (i = 0; i < ARRAY_LEN(headermats); i++) { + headermats[i] = NULL; + } } bind_t::~bind_t() { - Clear(); + Clear(); } -void bind_t::Clear - ( - void - ) - +void bind_t::Clear(void) { - // FIXME: stub + for (int i = binds.NumObjects(); i > 0; i--) { + bind_item_t *bi; + + bi = binds.ObjectAt(i); + binds.RemoveObjectAt(i); + + if (bi) { + delete bi; + } + } } -CLASS_DECLARATION( Listener, bindlistener, NULL ) -{ - { NULL, NULL } +Event EV_Bind_Header +( + "header", + EV_DEFAULT, + "iss", + "column_num name material", + "Set the header of each column" +); +Event EV_Bind_Width +( + "bind_width", + EV_DEFAULT, + "i", + "width", + "Width of the bind menu" +); +Event EV_Bind_Height +( + "bind_height", + EV_DEFAULT, + "i", + "height", + "Height of the bind menu" +); +Event EV_Bind_FillWidth +( + "bind_fillwidth", + EV_DEFAULT, + "iS", + "width material", + "Width of the filling between widgets" +); +Event EV_Bind_CommandWidth +( + "bind_commandwidth", + EV_DEFAULT, + "i", + "width", + "Width of the command item" +); +Event EV_Bind_CommandHeight +( + "bind_commandheight", + EV_DEFAULT, + "i", + "height", + "Height of the command item" +); +Event EV_Bind_PrimaryKeyWidth +( + "bind_primarykeywidth", + EV_DEFAULT, + "i", + "width", + "Width of the primary key item" +); +Event EV_Bind_PrimaryKeyHeight +( + "bind_primarykeyheight", + EV_DEFAULT, + "i", + "height", + "Height of the primary key item" +); +Event EV_Bind_AlternateKeyWidth +( + "bind_alternatekeywidth", + EV_DEFAULT, + "i", + "width", + "Width of the alternate key item" +); +Event EV_Bind_AlternateKeyHeight +( + "bind_alternatekeyheight", + EV_DEFAULT, + "i", + "height", + "Height of the alternate key item" +); +Event EV_Bind_NewItem +( + "binditem", + EV_DEFAULT, + "ss", + "name command", + "Create a new bind item in the interface" +); +Event EV_Bind_Align +( + "align", + EV_DEFAULT, + "sSSSSS", + "arg1 arg2 arg3 arg4 arg5 arg6", + "Set the alignment on the bind menu" +); +Event EV_Bind_TitleForegroundColor +( + "titleforegroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the title foreground" +); +Event EV_Bind_TitleBackgroundColor +( + "titlebackgroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the title background" +); +Event EV_Bind_InactiveForegroundColor +( + "inactiveforegroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the inactive button foreground" +); +Event EV_Bind_InactiveBackgroundColor +( + "inactivebackgroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the inactive button background" +); +Event EV_Bind_ActiveForegroundColor +( + "activeforegroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the active button foreground" +); +Event EV_Bind_ActiveBackgroundColor +( + "activebackgroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the active button background" +); +Event EV_Bind_ActiveBorderColor +( + "activebordercolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the active button border" +); +Event EV_Bind_HighlightForegroundColor +( + "highlightforegroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the highlighted button foreground" +); +Event EV_Bind_HighlightBackgroundColor +( + "highlightbackgroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the highlighted button background" +); +Event EV_Bind_SelectForegroundColor +( + "selectforegroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the selected button foreground" +); +Event EV_Bind_SelectBackgroundColor +( + "selectbackgroundcolor", + EV_DEFAULT, + "ffff", + "r g b a", + "Set the color for the selected button background" +); +Event EV_Bind_ChangeSound +( + "changesound", + EV_DEFAULT, + "s", + "soundname", + "Set the name of the sound to play when the highlighted item changes" +); +Event EV_Bind_ActiveSound +( + "activesound", + EV_DEFAULT, + "s", + "soundname", + "Set the name of the sound to play when the item is made active" +); +Event EV_Bind_EnterSound +( + "entersound", + EV_DEFAULT, + "s", + "soundname", + "Set the name of the sound to play when the key is entered" +); + +CLASS_DECLARATION(Listener, bindlistener, NULL) { + {&EV_Bind_Width, &bindlistener::Width }, + {&EV_Bind_Height, &bindlistener::Height }, + {&EV_Bind_FillWidth, &bindlistener::FillWidth }, + {&EV_Bind_CommandWidth, &bindlistener::CommandWidth }, + {&EV_Bind_CommandHeight, &bindlistener::CommandHeight }, + {&EV_Bind_PrimaryKeyWidth, &bindlistener::PrimaryKeyWidth }, + {&EV_Bind_PrimaryKeyHeight, &bindlistener::PrimaryKeyHeight }, + {&EV_Bind_AlternateKeyWidth, &bindlistener::AlternateKeyWidth }, + {&EV_Bind_AlternateKeyHeight, &bindlistener::AlternateKeyHeight }, + {&EV_Bind_Header, &bindlistener::Header }, + {&EV_Bind_NewItem, &bindlistener::NewItem }, + {&EV_Bind_Align, &bindlistener::Align }, + {&EV_Bind_TitleForegroundColor, &bindlistener::TitleForegroundColor }, + {&EV_Bind_TitleBackgroundColor, &bindlistener::TitleBackgroundColor }, + {&EV_Bind_InactiveForegroundColor, &bindlistener::InactiveForegroundColor }, + {&EV_Bind_InactiveBackgroundColor, &bindlistener::InactiveBackgroundColor }, + {&EV_Bind_ActiveForegroundColor, &bindlistener::ActiveForegroundColor }, + {&EV_Bind_ActiveBackgroundColor, &bindlistener::ActiveBackgroundColor }, + {&EV_Bind_ActiveBorderColor, &bindlistener::ActiveBorderColor }, + {&EV_Bind_HighlightForegroundColor, &bindlistener::HighlightForegroundColor}, + {&EV_Bind_HighlightBackgroundColor, &bindlistener::HighlightBackgroundColor}, + {&EV_Bind_SelectForegroundColor, &bindlistener::SelectForegroundColor }, + {&EV_Bind_SelectBackgroundColor, &bindlistener::SelectBackgroundColor }, + {&EV_Bind_ChangeSound, &bindlistener::ChangeSound }, + {&EV_Bind_ActiveSound, &bindlistener::ActiveSound }, + {&EV_Bind_EnterSound, &bindlistener::EnterSound }, + {NULL, NULL } }; -bindlistener::bindlistener() +bindlistener::bindlistener() {} + +bindlistener::bindlistener(bind_t *b) { + bind = b; } -bindlistener::bindlistener - ( - bind_t *b - ) - +void bindlistener::Header(Event *ev) { - bind = b; + int num; + + num = ev->GetInteger(1) - 1; + if (num > ARRAY_LEN(bind_t::headers)) { + return; + } + + bind->headers[num] = ev->GetString(2); + if (ev->NumArgs() > 2) { + bind->headermats[num] = uWinMan.RegisterShader(ev->GetString(3)); + } } -bool bindlistener::Load - ( - Script& script - ) - +void bindlistener::ChangeSound(Event *ev) { - // FIXME: stub - return false; + bind->changesound = ev->GetString(1); } -void bindlistener::Header - ( - Event *ev - ) - +void bindlistener::ActiveSound(Event *ev) { - // FIXME: stub + bind->activesound = ev->GetString(1); } -void bindlistener::Width - ( - Event *ev - ) - +void bindlistener::EnterSound(Event *ev) { - // FIXME: stub + bind->entersound = ev->GetString(1); } -void bindlistener::FillWidth - ( - Event *ev - ) - +void bindlistener::SelectForegroundColor(Event *ev) { - // FIXME: stub + bind->selectfgcolor.r = ev->GetFloat(1); + bind->selectfgcolor.g = ev->GetFloat(2); + bind->selectfgcolor.b = ev->GetFloat(3); + bind->selectfgcolor.a = ev->GetFloat(4); } -void bindlistener::Height - ( - Event *ev - ) - +void bindlistener::SelectBackgroundColor(Event *ev) { - // FIXME: stub + bind->selectbgcolor.r = ev->GetFloat(1); + bind->selectbgcolor.g = ev->GetFloat(2); + bind->selectbgcolor.b = ev->GetFloat(3); + bind->selectbgcolor.a = ev->GetFloat(4); } -void bindlistener::CommandWidth - ( - Event *ev - ) - +void bindlistener::TitleForegroundColor(Event *ev) { - // FIXME: stub + bind->titlefgcolor.r = ev->GetFloat(1); + bind->titlefgcolor.g = ev->GetFloat(2); + bind->titlefgcolor.b = ev->GetFloat(3); + bind->titlefgcolor.a = ev->GetFloat(4); } -void bindlistener::CommandHeight - ( - Event *ev - ) - +void bindlistener::TitleBackgroundColor(Event *ev) { - // FIXME: stub + bind->titlebgcolor.r = ev->GetFloat(1); + bind->titlebgcolor.g = ev->GetFloat(2); + bind->titlebgcolor.b = ev->GetFloat(3); + bind->titlebgcolor.a = ev->GetFloat(4); } -void bindlistener::PrimaryKeyWidth - ( - Event *ev - ) - +void bindlistener::ActiveBorderColor(Event *ev) { - // FIXME: stub + bind->activebordercolor.r = ev->GetFloat(1); + bind->activebordercolor.g = ev->GetFloat(2); + bind->activebordercolor.b = ev->GetFloat(3); + bind->activebordercolor.a = ev->GetFloat(4); } -void bindlistener::PrimaryKeyHeight - ( - Event *ev - ) - +void bindlistener::ActiveForegroundColor(Event *ev) { - // FIXME: stub + bind->activefgcolor.r = ev->GetFloat(1); + bind->activefgcolor.g = ev->GetFloat(2); + bind->activefgcolor.b = ev->GetFloat(3); + bind->activefgcolor.a = ev->GetFloat(4); } -void bindlistener::AlternateKeyWidth - ( - Event *ev - ) - +void bindlistener::ActiveBackgroundColor(Event *ev) { - // FIXME: stub + bind->activebgcolor.r = ev->GetFloat(1); + bind->activebgcolor.g = ev->GetFloat(2); + bind->activebgcolor.b = ev->GetFloat(3); + bind->activebgcolor.a = ev->GetFloat(4); } -void bindlistener::AlternateKeyHeight - ( - Event *ev - ) - +void bindlistener::InactiveForegroundColor(Event *ev) { - // FIXME: stub + bind->inactivefgcolor.r = ev->GetFloat(1); + bind->inactivefgcolor.g = ev->GetFloat(2); + bind->inactivefgcolor.b = ev->GetFloat(3); + bind->inactivefgcolor.a = ev->GetFloat(4); } -void bindlistener::NewItem - ( - Event *ev - ) - +void bindlistener::InactiveBackgroundColor(Event *ev) { - // FIXME: stub + bind->inactivebgcolor.r = ev->GetFloat(1); + bind->inactivebgcolor.g = ev->GetFloat(2); + bind->inactivebgcolor.b = ev->GetFloat(3); + bind->inactivebgcolor.a = ev->GetFloat(4); } -void bindlistener::Align - ( - Event *ev - ) - +void bindlistener::HighlightForegroundColor(Event *ev) { - // FIXME: stub + bind->highlightfgcolor.r = ev->GetFloat(1); + bind->highlightfgcolor.g = ev->GetFloat(2); + bind->highlightfgcolor.b = ev->GetFloat(3); + bind->highlightfgcolor.a = ev->GetFloat(4); } -void bindlistener::TitleForegroundColor - ( - Event *ev - ) - +void bindlistener::HighlightBackgroundColor(Event *ev) { - // FIXME: stub + bind->highlightbgcolor.r = ev->GetFloat(1); + bind->highlightbgcolor.g = ev->GetFloat(2); + bind->highlightbgcolor.b = ev->GetFloat(3); + bind->highlightbgcolor.a = ev->GetFloat(4); } -void bindlistener::TitleBackgroundColor - ( - Event *ev - ) - +void bindlistener::Align(Event *ev) { - // FIXME: stub + int i; + + for (i = 1; i <= ev->NumArgs(); i++) { + str align = ev->GetString(i); + + if (!str::icmp(align, "left")) { + bind->align |= WA_LEFT; + } else if (!str::icmp(align, "right")) { + bind->align |= WA_RIGHT; + } else if (!str::icmp(align, "top")) { + bind->align |= WA_TOP; + } else if (!str::icmp(align, "bottom")) { + bind->align |= WA_BOTTOM; + } else if (!str::icmp(align, "centerx")) { + bind->align |= WA_CENTERX; + } else if (!str::icmp(align, "centery")) { + bind->align |= WA_CENTERY; + } + } } -void bindlistener::InactiveForegroundColor - ( - Event *ev - ) - +void bindlistener::NewItem(Event *ev) { - // FIXME: stub + bind_item_t *bt; + UIReggedMaterial *mat = NULL; + + if (ev->NumArgs() > 2) { + mat = uWinMan.RegisterShader(ev->GetString(3)); + } + + str n = ev->GetString(1); + str c = ev->GetString(2); + + bt = new bind_item_t; + bt->name = n; + bt->command = c; + bt->nameMaterial = mat; + + bind->binds.AddObject(bt); } -void bindlistener::InactiveBackgroundColor - ( - Event *ev - ) - +void bindlistener::Width(Event *ev) { - // FIXME: stub + bind->width = ev->GetInteger(1); } -void bindlistener::ActiveForegroundColor - ( - Event *ev - ) - +void bindlistener::Height(Event *ev) { - // FIXME: stub + bind->height = ev->GetInteger(1); } -void bindlistener::ActiveBackgroundColor - ( - Event *ev - ) - +void bindlistener::FillWidth(Event *ev) { - // FIXME: stub + bind->fillwidth = ev->GetInteger(1); + + if (ev->NumArgs() > 1) { + bind->fillmaterial = uWinMan.RegisterShader(ev->GetString(2)); + } } -void bindlistener::ActiveBorderColor - ( - Event *ev - ) - +void bindlistener::CommandWidth(Event *ev) { - // FIXME: stub + bind->commandwidth = ev->GetInteger(1); } -void bindlistener::HighlightForegroundColor - ( - Event *ev - ) - +void bindlistener::CommandHeight(Event *ev) { - // FIXME: stub + bind->commandheight = ev->GetInteger(1); } -void bindlistener::HighlightBackgroundColor - ( - Event *ev - ) - +void bindlistener::PrimaryKeyWidth(Event *ev) { - // FIXME: stub + bind->primarykeywidth = ev->GetInteger(1); } -void bindlistener::SelectForegroundColor - ( - Event *ev - ) - +void bindlistener::PrimaryKeyHeight(Event *ev) { - // FIXME: stub + bind->primarykeyheight = ev->GetInteger(1); } -void bindlistener::SelectBackgroundColor - ( - Event *ev - ) - +void bindlistener::AlternateKeyWidth(Event *ev) { - // FIXME: stub + bind->alternatekeywidth = ev->GetInteger(1); } -void bindlistener::ChangeSound - ( - Event *ev - ) - +void bindlistener::AlternateKeyHeight(Event *ev) { - // FIXME: stub + bind->alternatekeyheight = ev->GetInteger(1); } -void bindlistener::ActiveSound - ( - Event *ev - ) - +bool bindlistener::Load(Script& script) { - // FIXME: stub + str token; + str errortext; + + while (script.TokenAvailable(true)) { + token = script.GetToken(true); + + if (!token.length() || !ValidEvent(token)) { + throw "invalid token"; + } + + Event *event = new Event(token); + + while (script.TokenAvailable(false)) { + event->AddToken(script.GetToken(false)); + } + + ProcessEvent(event); + } + + return true; } -void bindlistener::EnterSound - ( - Event *ev - ) - +bool CL_LoadBind(const char *filename, bind_t *bind) { - // FIXME: stub + Script script; + + bind->Clear(); + + bindlistener listener(bind); + script.LoadFile(filename); + // Load the bind file + return listener.Load(script); } diff --git a/code/client/cl_uibind.h b/code/client/cl_uibind.h index a1a3a41b..25813bc5 100644 --- a/code/client/cl_uibind.h +++ b/code/client/cl_uibind.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,115 +20,109 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIBIND_H__ -#define __CL_UIBIND_H__ +#pragma once -class bind_item_t { +class bind_item_t +{ public: - str name; - str command; - UIReggedMaterial *nameMaterial; + str name; + str command; + UIReggedMaterial *nameMaterial; - bind_item_t(); - bind_item_t( str name, str command, UIReggedMaterial *nameMaterial ); + bind_item_t(); + bind_item_t(str name, str command, UIReggedMaterial *nameMaterial); }; -inline -bind_item_t::bind_item_t() +inline bind_item_t::bind_item_t() { - nameMaterial = NULL; + nameMaterial = NULL; } -inline -bind_item_t::bind_item_t - ( - str name, - str command, - UIReggedMaterial *nameMaterial - ) - +inline bind_item_t::bind_item_t(str name, str command, UIReggedMaterial *nameMaterial) { - this->name = name; - this->command = command; - this->nameMaterial = nameMaterial; + this->name = name; + this->command = command; + this->nameMaterial = nameMaterial; } -class bind_t { +class bind_t +{ public: - int width; - int height; - int fillwidth; - int commandwidth; - int commandheight; - int primarykeywidth; - int primarykeyheight; - int alternatekeywidth; - int alternatekeyheight; - int align; - UColor titlebgcolor; - UColor titlefgcolor; - UColor activefgcolor; - UColor activebgcolor; - UColor activebordercolor; - UColor inactivefgcolor; - UColor inactivebgcolor; - UColor highlightfgcolor; - UColor highlightbgcolor; - UColor selectfgcolor; - UColor selectbgcolor; - str changesound; - str activesound; - str entersound; - str headers[ 3 ]; - UIReggedMaterial *headermats[ 3 ]; - UIReggedMaterial *fillmaterial; - Container binds; + int width; + int height; + int fillwidth; + int commandwidth; + int commandheight; + int primarykeywidth; + int primarykeyheight; + int alternatekeywidth; + int alternatekeyheight; + int align; + UColor titlebgcolor; + UColor titlefgcolor; + UColor activefgcolor; + UColor activebgcolor; + UColor activebordercolor; + UColor inactivefgcolor; + UColor inactivebgcolor; + UColor highlightfgcolor; + UColor highlightbgcolor; + UColor selectfgcolor; + UColor selectbgcolor; + str changesound; + str activesound; + str entersound; + str headers[3]; + UIReggedMaterial *headermats[3]; + UIReggedMaterial *fillmaterial; + Container binds; public: - bind_t(); - ~bind_t(); + bind_t(); + ~bind_t(); - void Clear( void ); + void Clear(void); }; -class bindlistener : public Listener { +class bindlistener : public Listener +{ protected: - bind_t *bind; + bind_t *bind; public: - CLASS_PROTOTYPE( bindlistener ); + CLASS_PROTOTYPE(bindlistener); public: - bindlistener(); - bindlistener( bind_t *b ); + bindlistener(); + bindlistener(bind_t *b); - bool Load( Script& script ); - void Header( Event *ev ); - void Width( Event *ev ); - void FillWidth( Event *ev ); - void Height( Event *ev ); - void CommandWidth( Event *ev ); - void CommandHeight( Event *ev ); - void PrimaryKeyWidth( Event *ev ); - void PrimaryKeyHeight( Event *ev ); - void AlternateKeyWidth( Event *ev ); - void AlternateKeyHeight( Event *ev ); - void NewItem( Event *ev ); - void Align( Event *ev ); - void TitleForegroundColor( Event *ev ); - void TitleBackgroundColor( Event *ev ); - void InactiveForegroundColor( Event *ev ); - void InactiveBackgroundColor( Event *ev ); - void ActiveForegroundColor( Event *ev ); - void ActiveBackgroundColor( Event *ev ); - void ActiveBorderColor( Event *ev ); - void HighlightForegroundColor( Event *ev ); - void HighlightBackgroundColor( Event *ev ); - void SelectForegroundColor( Event *ev ); - void SelectBackgroundColor( Event *ev ); - void ChangeSound( Event *ev ); - void ActiveSound( Event *ev ); - void EnterSound( Event *ev ); + bool Load(Script& script); + void Header(Event *ev); + void Width(Event *ev); + void FillWidth(Event *ev); + void Height(Event *ev); + void CommandWidth(Event *ev); + void CommandHeight(Event *ev); + void PrimaryKeyWidth(Event *ev); + void PrimaryKeyHeight(Event *ev); + void AlternateKeyWidth(Event *ev); + void AlternateKeyHeight(Event *ev); + void NewItem(Event *ev); + void Align(Event *ev); + void TitleForegroundColor(Event *ev); + void TitleBackgroundColor(Event *ev); + void InactiveForegroundColor(Event *ev); + void InactiveBackgroundColor(Event *ev); + void ActiveForegroundColor(Event *ev); + void ActiveBackgroundColor(Event *ev); + void ActiveBorderColor(Event *ev); + void HighlightForegroundColor(Event *ev); + void HighlightBackgroundColor(Event *ev); + void SelectForegroundColor(Event *ev); + void SelectBackgroundColor(Event *ev); + void ChangeSound(Event *ev); + void ActiveSound(Event *ev); + void EnterSound(Event *ev); }; -#endif +bool CL_LoadBind(const char* filename, bind_t* bind); diff --git a/code/client/cl_uidmbox.cpp b/code/client/cl_uidmbox.cpp index 357d7571..c55afa08 100644 --- a/code/client/cl_uidmbox.cpp +++ b/code/client/cl_uidmbox.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/localization.h" Event EV_DMBox_Goin ( @@ -40,126 +41,116 @@ Event EV_DMBox_Decay "Event to make the dmbox console line decay" ); -static float s_dmboxWidth = 384.0; +static float s_dmboxWidth = 384.0; static float s_dmboxOffsetX = 3.0f; static float s_dmboxOffsetY = 8.0f; -CLASS_DECLARATION( UIWidget, UIDMBox, NULL ) -{ - { &W_SizeChanged, &UIDMBox::OnSizeChanged }, - { &EV_DMBox_Goin, &UIDMBox::MoveInEvent }, - { &EV_DMBox_Decay, &UIDMBox::DecayEvent }, - { NULL, NULL } +CLASS_DECLARATION(UIWidget, UIDMBox, NULL) { + {&W_SizeChanged, &UIDMBox::OnSizeChanged}, + {&EV_DMBox_Goin, &UIDMBox::MoveInEvent }, + {&EV_DMBox_Decay, &UIDMBox::DecayEvent }, + {NULL, NULL } }; UIDMBox::UIDMBox() { - m_numitems = 0; - m_reallyshown = true; - m_fontbold = NULL; - m_boxstate = boxstate_t::box_out; - m_iBeginDecay = 0; - m_boxtime = uid.time; - m_movespeed = 500; + m_numitems = 0; + m_reallyshown = true; + m_fontbold = NULL; + m_boxstate = boxstate_t::box_out; + m_iBeginDecay = 0; + m_boxtime = uid.time; + m_movespeed = 500; + m_drawoutline = com_target_game->integer >= target_game_e::TG_MOHTA; } -void UIDMBox::VerifyBoxOut( void ) +void UIDMBox::VerifyBoxOut(void) { - PostMoveinEvent(); - if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out) - { - ChangeBoxState(boxstate_t::box_moving_out); - } + PostMoveinEvent(); + if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out) { + ChangeBoxState(boxstate_t::box_moving_out); + } } -void UIDMBox::ChangeBoxState( boxstate_t state ) +void UIDMBox::ChangeBoxState(boxstate_t state) { - m_boxstate = state; - m_boxtime = uid.time; - setShowState(); + m_boxstate = state; + m_boxtime = uid.time; + setShowState(); - if (state == box_out) { - PostMoveinEvent(); - } + if (state == box_out) { + PostMoveinEvent(); + } } -void UIDMBox::HandleBoxMoving( void ) +void UIDMBox::HandleBoxMoving(void) { - int delta; - UIRect2D newRect; + int delta; + UIRect2D newRect; - if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) { - return; - } + if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) { + return; + } - delta = m_movespeed * (uid.time - m_boxtime) / 1000; - m_boxtime = 1000 * delta / m_movespeed + m_boxtime; - if (m_boxstate == boxstate_t::box_moving_out) - { - newRect.size.width = m_frame.size.width; - newRect.size.height = m_frame.size.height; - newRect.pos.x = m_frame.pos.x; - newRect.pos.y = delta + m_frame.pos.y; + delta = m_movespeed * (uid.time - m_boxtime) / 1000; + m_boxtime = 1000 * delta / m_movespeed + m_boxtime; + if (m_boxstate == boxstate_t::box_moving_out) { + newRect.size.width = m_frame.size.width; + newRect.size.height = m_frame.size.height; + newRect.pos.x = m_frame.pos.x; + newRect.pos.y = delta + m_frame.pos.y; - if (newRect.pos.y <= 0.0) - { - newRect.pos.y = 0.0; - ChangeBoxState(boxstate_t::box_out); - } - } - else if (m_boxstate == boxstate_t::box_moving_in) - { - newRect.size.width = m_frame.size.width; - newRect.size.height = m_frame.size.height; - newRect.pos.x = m_frame.pos.x; - newRect.pos.y = delta - m_frame.pos.y; + if (newRect.pos.y <= 0.0) { + newRect.pos.y = 0.0; + ChangeBoxState(boxstate_t::box_out); + } + } else if (m_boxstate == boxstate_t::box_moving_in) { + newRect.size.width = m_frame.size.width; + newRect.size.height = m_frame.size.height; + newRect.pos.x = m_frame.pos.x; + newRect.pos.y = delta - m_frame.pos.y; - if (newRect.pos.y <= -newRect.size.height) - { - newRect.pos.y = -newRect.size.height; - ChangeBoxState(boxstate_t::box_in); - } - } - else { - newRect = m_frame; - } + if (newRect.pos.y <= -newRect.size.height) { + newRect.pos.y = -newRect.size.height; + ChangeBoxState(boxstate_t::box_in); + } + } else { + newRect = m_frame; + } - setFrame(newRect); + setFrame(newRect); } -void UIDMBox::PostMoveinEvent( void ) +void UIDMBox::PostMoveinEvent(void) { - if (m_boxstate != boxstate_t::box_out) { - return; - } + if (m_boxstate != boxstate_t::box_out) { + return; + } - if (!EventPending(EV_DMBox_Goin)) { - PostEvent(EV_DMBox_Goin, 10.0); - } - else { - PostponeEvent(EV_DMBox_Goin, 10.0); - } + if (!EventPending(EV_DMBox_Goin)) { + PostEvent(EV_DMBox_Goin, 10.0); + } else { + PostponeEvent(EV_DMBox_Goin, 10.0); + } } -void UIDMBox::PostDecayEvent( void ) +void UIDMBox::PostDecayEvent(void) { - if (!EventPending(EV_DMBox_Decay)) - { - float fDelayTime; - int iNumLines; - int i; - const char* pszString = m_items[0].string.c_str(); + if (!EventPending(EV_DMBox_Decay)) { + float fDelayTime; + int iNumLines; + int i; + const char *pszString = m_items[0].string.c_str(); - // - // Calculate the number of lines - // - iNumLines = 1; - for (i = 0; pszString[i]; i++) - { - if (pszString[i] == '\n') { - iNumLines++; - } - } + // + // Calculate the number of lines + // + iNumLines = 1; + for (i = 0; pszString[i]; i++) { + if (pszString[i] == '\n') { + iNumLines++; + } + } if (m_items[0].flags & DMBOX_ITEM_FLAG_BOLD) { fDelayTime = iNumLines * 8.0; @@ -167,265 +158,268 @@ void UIDMBox::PostDecayEvent( void ) // // Bold as twice more decay // - else if (m_items[0].flags & DMBOX_ITEM_FLAG_DEATH) { - fDelayTime = iNumLines * 6.0; - } - else { - fDelayTime = iNumLines * 5.0; - } + else if (m_items[0].flags & DMBOX_ITEM_FLAG_DEATH) { + fDelayTime = iNumLines * 6.0; + } else { + fDelayTime = iNumLines * 5.0; + } - m_iBeginDecay = cls.realtime; - m_iEndDecay = (int)(fDelayTime * 1000.0); + m_iBeginDecay = cls.realtime; + m_iEndDecay = (int)(fDelayTime * 1000.0); - PostEvent(EV_DMBox_Decay, fDelayTime); - } + PostEvent(EV_DMBox_Decay, fDelayTime); + } } -void UIDMBox::setShowState( void ) +void UIDMBox::setShowState(void) { - if (m_reallyshown) { - setShow(m_boxstate != box_in); - } else { - setShow(false); - } + if (m_reallyshown) { + setShow(m_boxstate != box_in); + } else { + setShow(false); + } } -void UIDMBox::RemoveTopItem( void ) +void UIDMBox::RemoveTopItem(void) { - int i; + int i; - if (m_numitems > 0) { - for (i = 0; i < m_numitems - 1; i++) { - m_items[i] = m_items[i + 1]; - } + if (m_numitems > 0) { + for (i = 0; i < m_numitems - 1; i++) { + m_items[i] = m_items[i + 1]; + } - m_numitems--; - } + m_numitems--; + } } -str UIDMBox::CalculateBreaks( UIFont *font, str text, float max_width ) +str UIDMBox::CalculateBreaks(UIFont *font, str text, float max_width) { - str newText, sTmp; - int i; - float fX; - float fwX, fsX; + str newText; + float fX; + float fwX; + const char *current; + int count; - Cmd_TokenizeString(text.c_str()); - if (Cmd_Argc()) - { - fX = 0.0; - fsX = font->getCharWidth(' '); + current = text; + fX = 0.0; - for (i = 0; i < Cmd_Argc(); i++) - { - sTmp = Cmd_Argv(i); + for (count = font->DBCSGetWordBlockCount(current, -1); count; + current += count, count = font->DBCSGetWordBlockCount(current, -1)) { + fwX = font->getWidth(current, count); - fwX = font->getWidth(sTmp.c_str(), -1); - if (fwX + i <= max_width) - { - if (fwX + i + fX <= max_width) - { - newText += sTmp + " "; - } else { - newText += "\n" + sTmp + " "; - } - } - else - { - sTmp += "\n"; - fX = 0.0; - } - } - } else { - newText = ""; - } + if (fX + fwX > max_width) { + newText += "\n" + str(current, 0, count); + fX = 0; + } else { + newText += str(current, 0, count); + } - return newText; + fX += fwX; + } + + return newText; } -float UIDMBox::PrintWrap( UIFont *font, float x, float y, str text ) +float UIDMBox::PrintWrap(UIFont *font, float x, float y, str text) { - const char* p1, * p2; - size_t n, l; - float fY; + const char *p1, *p2; + size_t n, l; + float fY; - fY = y; - p1 = text.c_str(); - l = text.length(); + fY = y; + p1 = text.c_str(); + l = text.length(); - for (;;) - { - p2 = strchr(p1, '\n'); - if (!p2) { - break; - } + for (;;) { + p2 = strchr(p1, '\n'); + if (!p2) { + break; + } - n = p2 - p1; - if (n >= l) { - break; - } + n = p2 - p1; + if (n >= l) { + break; + } - font->Print(x, fY, p1, p2 - p1, qfalse); - p1 = p2 + 1; - l -= n; - fY += font->getHeight(qfalse); - } + font->Print(x, fY, p1, p2 - p1, getHighResScale()); + p1 = p2 + 1; + l -= n; + fY += font->getHeight(); + } - font->Print(x, fY, p1, l, qfalse); + if (*p1) { + font->Print(x, fY, p1, l, getHighResScale()); + fY += font->getHeight(); + } - return font->getHeight(qfalse) + (fY - y); + return fY - y; } -float UIDMBox::DrawItem( item_t *in, float x, float y, float alpha ) +float UIDMBox::DrawItem(item_t *in, float x, float y, float alpha) { - in->font->setColor(in->color); - in->font->setAlpha(alpha); + if (m_drawoutline) { + // + // Draw an outline + // - return PrintWrap(in->font, x, y, in->string); + in->font->setColor(UBlack); + in->font->setAlpha(alpha); + + PrintWrap(in->font, x + 1, y + 2, in->string); + PrintWrap(in->font, x + 2, y + 1, in->string); + PrintWrap(in->font, x - 1, y + 2, in->string); + PrintWrap(in->font, x - 2, y + 1, in->string); + PrintWrap(in->font, x - 1, y - 2, in->string); + PrintWrap(in->font, x - 2, y - 1, in->string); + PrintWrap(in->font, x + 1, y - 2, in->string); + PrintWrap(in->font, x + 2, y - 1, in->string); + PrintWrap(in->font, x + 2, y, in->string); + PrintWrap(in->font, x - 2, y, in->string); + PrintWrap(in->font, x, y + 2, in->string); + PrintWrap(in->font, x, y - 2, in->string); + } + + in->font->setColor(in->color); + in->font->setAlpha(alpha); + + return PrintWrap(in->font, x, y, in->string); } -void UIDMBox::Print( const char *text ) +void UIDMBox::Print(const char *text) { - const char* text1 = text; + const char *text1 = text; - if (m_numitems > 5) - { - // - // Overwrite an item - // - RemoveTopItem(); - } + if (m_numitems > 5) { + // + // Overwrite an item + // + RemoveTopItem(); + } - m_items[m_numitems].flags = 0; + m_items[m_numitems].flags = 0; - if (*text == MESSAGE_CHAT_WHITE) - { - m_items[m_numitems].color = UGrey; - m_items[m_numitems].font = m_fontbold; - m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD; + if (*text == MESSAGE_CHAT_WHITE) { + m_items[m_numitems].color = UWhiteChatMessageColor; + m_items[m_numitems].font = m_fontbold; + m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD; - text1 = text + 1; - } - else if (*text == MESSAGE_CHAT_RED) - { - m_items[m_numitems].color = ULightRed; - m_items[m_numitems].font = m_fontbold; - m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_DEATH; + text1 = text + 1; + } else if (*text == MESSAGE_CHAT_RED) { + m_items[m_numitems].color = URedChatMessageColor; + m_items[m_numitems].font = m_fontbold; + m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_DEATH; - text1 = text + 1; - } - else if (*text == MESSAGE_CHAT_GREEN) - { - m_items[m_numitems].color = UGreen; + text1 = text + 1; + } else if (*text == MESSAGE_CHAT_GREEN) { + m_items[m_numitems].color = UGreenChatMessageColor; m_items[m_numitems].font = m_fontbold; m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_DEATH; - text1 = text + 1; - } - else - { - m_items[m_numitems].color = m_foreground_color; - m_items[m_numitems].font = m_font; - } + text1 = text + 1; + } else { + m_items[m_numitems].color = m_foreground_color; + m_items[m_numitems].font = m_font; + } - m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, text1, s_dmboxWidth); + m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, Sys_LV_CL_ConvertString(text1), s_dmboxWidth); - m_numitems++; - VerifyBoxOut(); - PostDecayEvent(); + m_numitems++; + VerifyBoxOut(); + PostDecayEvent(); } -void UIDMBox::OnSizeChanged( Event *ev ) +void UIDMBox::OnSizeChanged(Event *ev) { - s_dmboxWidth = m_frame.size.width; + s_dmboxWidth = m_frame.size.width; } -void UIDMBox::Create( const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha ) +void UIDMBox::Create(const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha) { - InitFrame(NULL, rect, 0, "facfont-20"); + InitFrame(NULL, rect, 0, "facfont-20"); - if (!m_fontbold) { - m_fontbold = new UIFont("facfont-20"); - } + if (!m_fontbold) { + m_fontbold = new UIFont("facfont-20"); + } - m_fontbold->setColor(URed); - setBackgroundColor(back, true); - setForegroundColor(fore); - setBackgroundAlpha(alpha); + m_fontbold->setColor(URed); + setBackgroundColor(back, true); + setForegroundColor(fore); + setBackgroundAlpha(alpha); - Connect(this, W_SizeChanged, W_SizeChanged); - OnSizeChanged(NULL); + Connect(this, W_SizeChanged, W_SizeChanged); + OnSizeChanged(NULL); - m_movespeed = rect.size.height * 3.0; + m_movespeed = rect.size.height * 3.0; - setShowState(); + setShowState(); } -void UIDMBox::MoveInEvent( Event *ev ) +void UIDMBox::MoveInEvent(Event *ev) {} + +void UIDMBox::DecayEvent(Event *ev) { + RemoveTopItem(); + if (m_numitems) { + PostDecayEvent(); + } } -void UIDMBox::DecayEvent( Event *ev ) +void UIDMBox::Draw(void) { - RemoveTopItem(); - if (m_numitems) { - PostDecayEvent(); - } + float fsY; + int i; + float alpha; + float alphaScale; + + alphaScale = 0.8f; + HandleBoxMoving(); + + if (!m_numitems) { + // + // Nothing to show + // + return; + } + + m_font->setColor(m_foreground_color); + alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay; + if (alpha > 1.0) { + alpha = 1.0; + } + + alpha = (1.0 - alpha) * 4.0; + if (alpha > 1.0) { + alpha = 1.0; + } + + if (cge) { + alphaScale = 1.0 - cge->CG_GetObjectiveAlpha(); + } + + fsY = DrawItem(m_items, s_dmboxOffsetX, s_dmboxOffsetY, alpha * alphaScale); + fsY = alpha <= 0.2 ? s_dmboxOffsetY : fsY + s_dmboxOffsetY; + + for (i = 1; i < m_numitems; i++) { + fsY += DrawItem(&m_items[i], s_dmboxOffsetX, fsY, alphaScale); + if (fsY > m_frame.size.height) { + if (EventPending(EV_DMBox_Decay)) { + CancelEventsOfType(EV_DMBox_Decay); + } + + PostEvent(EV_DMBox_Decay, 0.0); + break; + } + } } -void UIDMBox::Draw( void ) +void UIDMBox::setRealShow(bool b) { - float fsY; - int i; - float alpha; - float alphaScale; - - alphaScale = 0.8f; - HandleBoxMoving(); - - if (!m_numitems) { - // - // Nothing to show - // - return; - } - - m_font->setColor(m_foreground_color); - alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay; - if (alpha > 1.0) alpha = 1.0; - - alpha = (1.0 - alpha) * 4.0; - if (alpha > 1.0) alpha = 1.0; - - if (cge) { - alphaScale = 1.0 - cge->CG_GetObjectiveAlpha(); - } - - fsY = DrawItem(m_items, s_dmboxOffsetX, s_dmboxOffsetY, alpha * alphaScale); - fsY = alpha <= 0.2 ? s_dmboxOffsetY : fsY + s_dmboxOffsetY; - - for (i = 1; i < m_numitems; i++) - { - fsY += DrawItem(&m_items[i], s_dmboxOffsetX, fsY, alphaScale); - if (fsY > m_frame.size.height) - { - if (EventPending(EV_DMBox_Decay)) { - CancelEventsOfType(EV_DMBox_Decay); - } - - PostEvent(EV_DMBox_Decay, 0.0); - break; - } - } + this->m_reallyshown = b; + setShowState(); } -void UIDMBox::setRealShow( bool b ) +void UIDMBox::Clear(void) { - this->m_reallyshown = b; - setShowState(); -} - -void UIDMBox::Clear( void ) -{ - m_numitems = 0; + m_numitems = 0; } diff --git a/code/client/cl_uidmbox.h b/code/client/cl_uidmbox.h index cf8660e1..a02dab84 100644 --- a/code/client/cl_uidmbox.h +++ b/code/client/cl_uidmbox.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2015-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIDMBOX_H__ -#define __CL_UIDMBOX_H__ +#pragma once static constexpr unsigned int DMBOX_ITEM_FLAG_BOLD = 2u; static constexpr unsigned int DMBOX_ITEM_FLAG_DEATH = 4u; @@ -47,6 +46,8 @@ protected: int m_movespeed; int m_iBeginDecay; int m_iEndDecay; + // Added in OPM + bool m_drawoutline; public: CLASS_PROTOTYPE( UIDMBox ); @@ -75,5 +76,3 @@ public: void setRealShow( bool b ); void Clear( void ); }; - -#endif /* __CL_UIDMBOX_H__ */ diff --git a/code/client/cl_uifilepicker.cpp b/code/client/cl_uifilepicker.cpp index 9ccadb61..ad8914c9 100644 --- a/code/client/cl_uifilepicker.cpp +++ b/code/client/cl_uifilepicker.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,72 +22,256 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" -CLASS_DECLARATION( USignal, FilePickerClass, NULL ) +class FilePickerItem : public UIListCtrlItem { - { NULL, NULL } + str strings[3]; + +public: + FilePickerItem(const str& fileName, const str& date, const str& size); + int getListItemValue(int which) const override; + griditemtype_t getListItemType(int which) const override; + str getListItemString(int which) const override; + void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; + qboolean IsHeaderEntry() const override; +}; + +CLASS_DECLARATION(USignal, FilePickerClass, NULL) { + {&EV_UIListBase_ItemSelected, &FilePickerClass::FileSelected }, + {&EV_UIListBase_ItemDoubleClicked, &FilePickerClass::FileChosen }, + {&W_Deactivated, &FilePickerClass::OnDeactivated}, + {NULL, NULL } }; FilePickerClass::FilePickerClass() { - // FIXME: stub + window = new UIFloatingWindow(); + window->Create( + NULL, + UIRect2D((uid.vidWidth - 400) / 2, (uid.vidHeight - 300) / 2, 400, 300), + "File Picker", + UColor(0.15f, 0.195f, 0.278f), + UHudColor + ); + window->Connect(this, W_Deactivated, W_Deactivated); + listbox = new UIListCtrl(); + listbox->InitFrame(window->getChildSpace(), window->getChildSpace()->getClientFrame(), 0); + listbox->setBackgroundColor(UColor(0.02f, 0.07f, 0.005f), true); + listbox->setForegroundColor(UHudColor); + listbox->AddColumn("File Name", 0, 175, false, false); + listbox->AddColumn("Date", 1, 125, false, false); + listbox->AddColumn("Size", 2, 100, true, false); + + listbox->Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); + listbox->Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); + listbox->AllowActivate(true); + + // Added in 2.0 + // Don't localize elements + listbox->SetDontLocalize(); } FilePickerClass::~FilePickerClass() { - // FIXME: stub + if (listbox) { + delete listbox; + listbox = NULL; + } + + if (window) { + delete window; + window = NULL; + } } -void FilePickerClass::SetupFiles( void ) +void FilePickerClass::Setup( + const char *root_directory, const char *current_directory, const char *ext, const char *ignore_files +) { - // FIXME: stub + Initialize(root_directory, current_directory, ext, ignore_files); } -void FilePickerClass::GotoParentDirectory( void ) +void FilePickerClass::Initialize( + const char *root_directory, const char *current_directory, const char *ext, const char *ignore_files +) { - // FIXME: stub + rootDirectory = root_directory; + if (rootDirectory.length() > 1 && rootDirectory[rootDirectory.length() - 1] != '/') { + rootDirectory += "/"; + } + + currentDirectory = current_directory; + if (currentDirectory.length() > 1 && currentDirectory[currentDirectory.length() - 1] != '/') { + currentDirectory += "/"; + } + + extension = ext; + if (ignore_files) { + ignoredFiles = ignore_files; + } + + SetupFiles(); } -void FilePickerClass::GotoSubDirectory( str subdir ) +void FilePickerClass::GotoParentDirectory(void) { - // FIXME: stub + int i; + + if (currentDirectory == rootDirectory) { + return; + } + + for (i = currentDirectory.length() - 2; i > 0; i--) { + if (currentDirectory[i] == '/') { + break; + } + } + + if (currentDirectory[i] == '/') { + i++; + } + + currentDirectory = str(currentDirectory, 0, i); + + // refresh files + SetupFiles(); } -void FilePickerClass::Initialize( const char *root_directory, const char *current_directory, const char *ext ) +void FilePickerClass::GotoSubDirectory(str subdir) { - // FIXME: stub + currentDirectory += subdir + "/"; + + // refresh files + SetupFiles(); } -void FilePickerClass::CloseWindow( void ) +void FilePickerClass::SetupFiles(void) { - // FIXME: stub + str mappath; + str work; + char **filenames; + int numfiles; + int i; + char date[128]; + char size[128]; + + listbox->DeleteAllItems(); + + if (currentDirectory != rootDirectory) { + // create the parent directory item + listbox->AddItem(new FilePickerItem("..", "", "")); + } + + // retrieve directories + filenames = FS_ListFiles(currentDirectory, "/", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + + if (filename[0] == '.' || !strlen(filename)) { + continue; + } + + work = "["; + work += filename; + work += "]"; + + FS_FileTime(currentDirectory + filename, date, size); + + listbox->AddItem(new FilePickerItem(work, date, size)); + } + + FS_FreeFileList(filenames); + + filenames = FS_ListFiles(currentDirectory, extension, qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + + if (ignoredFiles.length() && strstr(filename, ignoredFiles)) { + // Added in 2.0 + // Check for ignored files + continue; + } + + work = filename; + + FS_FileTime(currentDirectory + work, date, size); + + listbox->AddItem(new FilePickerItem(work, date, size)); + } + + FS_FreeFileList(filenames); + + window->setTitle(currentDirectory); } -void FilePickerClass::FileSelected( Event *ev ) +void FilePickerClass::FileSelected(const str& currentDirectory, const str& partialName, const str& fullname) {} + +void FilePickerClass::FileSelected(Event *ev) { - // FIXME: stub + str name = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0); + + if (*name != '[' && *name != '.') { + FileSelected(currentDirectory, name, currentDirectory + name); + } + + uii.Snd_PlaySound("sound/menu/scroll.wav"); } -void FilePickerClass::FileSelected( str ¤tDirectory, str &partialName, str &fullname ) +void FilePickerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) {} + +void FilePickerClass::FileChosen(Event *ev) { - // FIXME: stub + str filename = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0); + + if (*filename == '[') { + uii.Snd_PlaySound("sound/menu/scroll.wav"); + + GotoSubDirectory(str(filename, 1, filename.length() - 1)); + } else if (*filename == '.') { + GotoParentDirectory(); + } else { + uii.Snd_PlaySound("sound/menu/apply.wav"); + + FileChosen(currentDirectory, filename, currentDirectory + filename); + } } -void FilePickerClass::FileChosen( Event *ev ) +void FilePickerClass::CloseWindow(void) { - // FIXME: stub + PostEvent(EV_Remove, 0); } -void FilePickerClass::FileChosen( str ¤tDirectory, str &partialName, str &fullname ) +void FilePickerClass::OnDeactivated(Event *ev) { - // FIXME: stub + CloseWindow(); } -void FilePickerClass::OnDeactivated( Event *ev ) +FilePickerItem::FilePickerItem(const str& fileName, const str& date, const str& size) { - // FIXME: stub + strings[0] = fileName; + strings[1] = date; + strings[2] = size; } -void FilePickerClass::Setup( const char *root_directory, const char *current_directory, const char *ext ) +int FilePickerItem::getListItemValue(int which) const { - // FIXME: stub + return atoi(strings[which]); +} + +griditemtype_t FilePickerItem::getListItemType(int which) const +{ + return griditemtype_t::TYPE_STRING; +} + +str FilePickerItem::getListItemString(int which) const +{ + return strings[which]; +} + +void FilePickerItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} + +qboolean FilePickerItem::IsHeaderEntry() const +{ + return qfalse; } diff --git a/code/client/cl_uifilepicker.h b/code/client/cl_uifilepicker.h index db726ea4..9881d9ee 100644 --- a/code/client/cl_uifilepicker.h +++ b/code/client/cl_uifilepicker.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,40 +20,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIFILEPICKER_H__ -#define __CL_UIFILEPICKER_H__ +#pragma once class UIListCtrl; -class FilePickerClass : public USignal { - UIFloatingWindow *window; - UIListCtrl *listbox; - str currentDirectory; - str rootDirectory; - str extension; +class FilePickerClass : public USignal +{ + UIFloatingWindow *window; + UIListCtrl *listbox; + str currentDirectory; + str rootDirectory; + str extension; + // Added in 2.0 + str ignoredFiles; public: - CLASS_PROTOTYPE( FilePickerClass ); + CLASS_PROTOTYPE(FilePickerClass); private: - void SetupFiles( void ); - void GotoParentDirectory( void ); - void GotoSubDirectory( str subdir ); - void Initialize( const char *root_directory, const char *current_directory, const char *ext ); + void SetupFiles(void); + void GotoParentDirectory(void); + void GotoSubDirectory(str subdir); + // ignore_files parameter, added in 2.0 + void Initialize(const char *root_directory, const char *current_directory, const char *ext, const char* ignore_files); protected: - void CloseWindow( void ); - void FileSelected( Event *ev ); - virtual void FileSelected( str ¤tDirectory, str &partialName, str &fullname ); - void FileChosen( Event *ev ); - virtual void FileChosen( str ¤tDirectory, str &partialName, str &fullname ); - void OnDeactivated( Event *ev ); + void CloseWindow(void); + void FileSelected(Event *ev); + virtual void FileSelected(const str& currentDirectory, const str& partialName, const str& fullname); + void FileChosen(Event *ev); + virtual void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname); + void OnDeactivated(Event *ev); public: - FilePickerClass(); - ~FilePickerClass(); + FilePickerClass(); + ~FilePickerClass(); - void Setup( const char *root_directory, const char *current_directory, const char *ext ); + void Setup(const char *root_directory, const char *current_directory, const char *ext, const char* ignore_files = NULL); }; - -#endif /* __CL_UIFILEPICKER_H__ */ diff --git a/code/client/cl_uigamespy.cpp b/code/client/cl_uigamespy.cpp new file mode 100644 index 00000000..843ae75c --- /dev/null +++ b/code/client/cl_uigamespy.cpp @@ -0,0 +1,118 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// cl_uigamespy.cpp +#include "cl_uigamespy.h" + +CLASS_DECLARATION(UIFloatingWindow, GameSpyDialog, NULL) { + {&W_Deactivated, &UIFloatingWindow::ClosePressed}, + {NULL, NULL } +}; + +GameSpyDialog::GameSpyDialog() + : overlay(NULL) + , label(NULL) + , closeButton(NULL) +{ + AddFlag(WF_ALWAYS_TOP); +} + +GameSpyDialog::~GameSpyDialog() +{ + if (overlay) { + delete overlay; + overlay = NULL; + } + + if (label) { + delete label; + label = NULL; + } + + if (closeButton) { + delete closeButton; + closeButton = NULL; + } +} + +void GameSpyDialog::FrameInitialized(void) +{ + UIFloatingWindow::FrameInitialized(); + + label = new UILabel(); + + label->InitFrame(getChildSpace(), getChildSpace()->getClientFrame(), 0); + label->setTitle( + "GameSpy's multiplayer matchmaking\n" + "and server browsing services, which were\n" + "essential for online gaming in many classic\n" + "titles including Medal of Honor: Allied Assault,\n" + "were permanently shut down in 2014." + ); + label->setForegroundColor(UHudColor); + + closeButton = new UIButton(); + closeButton->InitFrame(getChildSpace(), UIRect2D(100, 150, 100, 30), 0); + closeButton->setTitle("Close"); + closeButton->AllowActivate(true); + closeButton->Connect(this, W_Button_Pressed, W_Deactivated); + + overlay = new UIButton(); + overlay->InitFrame(NULL, UIRect2D(0, 0, uid.vidWidth, uid.vidHeight), 0); + overlay->setBackgroundColor(UColor(0, 0, 0, 0.5f), true); + overlay->AllowActivate(true); + + overlay->Connect(this, W_Button_Pressed, W_Deactivated); +} + +void GameSpyDialog::Create( + UIWidget *parent, const UIRect2D& rect, const char *title, const UColor& bgColor, const UColor& fgColor +) +{ + // First call parent's Create + UIFloatingWindow::Create(parent, rect, title, bgColor, fgColor); + + // After creation, find minimize button by name and hide it + for (UIWidget *child = getFirstChild(); child; child = getNextChild(child)) { + if (strcmp(child->getName(), "minimizebutton") == 0) { + child->setShow(false); + break; + } + } +} + +void UI_LaunchGameSpy_f(void) +{ + GameSpyDialog *dialog = new GameSpyDialog(); + + dialog->Create( + NULL, + UIRect2D((uid.vidWidth - 300) / 2, (uid.vidHeight - 200) / 2, 300, 200), + "GameSpy", + UColor(0.15f, 0.195f, 0.278f), + UHudColor + ); + + uWinMan.ActivateControl(dialog); + + dialog->Connect(dialog, W_Deactivated, W_Deactivated); +} diff --git a/code/client/cl_uigamespy.h b/code/client/cl_uigamespy.h new file mode 100644 index 00000000..8d1117d4 --- /dev/null +++ b/code/client/cl_uigamespy.h @@ -0,0 +1,50 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// cl_gamespy.h +#ifndef __CL_GAMESPY_H__ +#define __CL_GAMESPY_H__ + +#include "cl_ui.h" +#include "keycodes.h" + +class GameSpyDialog : public UIFloatingWindow +{ +private: + UIButton *overlay; + UILabel *label; + UIButton *closeButton; + +protected: + void FrameInitialized(void) override; + +public: + GameSpyDialog(); + ~GameSpyDialog(); + void + Create(UIWidget *parent, const UIRect2D& rect, const char *title, const UColor& bgColor, const UColor& fgColor); + + CLASS_PROTOTYPE(GameSpyDialog); +}; + +void UI_LaunchGameSpy_f(void); +#endif diff --git a/code/client/cl_uigmbox.cpp b/code/client/cl_uigmbox.cpp index 82761c1b..18962d4a 100644 --- a/code/client/cl_uigmbox.cpp +++ b/code/client/cl_uigmbox.cpp @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/localization.h" Event EV_GMBox_Goin ( @@ -40,371 +41,370 @@ Event EV_GMBox_Decay "Event to make the gmbox console line decay" ); -static float s_gmboxWidth = 640.0; +static float s_gmboxWidth = 640.0; static float s_gmboxOffsetX = 3.0f; static float s_gmboxOffsetY = 0.0f; -CLASS_DECLARATION( UIWidget, UIGMBox, NULL ) -{ - { &W_SizeChanged, &UIGMBox::OnSizeChanged }, - { &EV_GMBox_Goin, &UIGMBox::MoveInEvent }, - { &EV_GMBox_Decay, &UIGMBox::DecayEvent }, - { NULL, NULL } +CLASS_DECLARATION(UIWidget, UIGMBox, NULL) { + {&W_SizeChanged, &UIGMBox::OnSizeChanged}, + {&EV_GMBox_Goin, &UIGMBox::MoveInEvent }, + {&EV_GMBox_Decay, &UIGMBox::DecayEvent }, + {NULL, NULL } }; UIGMBox::UIGMBox() { - m_numitems = 0; - m_reallyshown = true; - m_fontbold = NULL; - m_boxstate = boxstate_t::box_out; - m_iBeginDecay = 0; - m_boxtime = uid.time; - m_movespeed = 500; + m_numitems = 0; + m_reallyshown = true; + m_fontbold = NULL; + m_boxstate = boxstate_t::box_out; + m_iBeginDecay = 0; + m_boxtime = uid.time; + m_movespeed = 500; + m_drawoutline = com_target_game->integer >= target_game_e::TG_MOHTA; } -void UIGMBox::VerifyBoxOut( void ) +void UIGMBox::VerifyBoxOut(void) { - PostMoveinEvent(); - if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out) - { - ChangeBoxState(boxstate_t::box_moving_out); - } + PostMoveinEvent(); + if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out) { + ChangeBoxState(boxstate_t::box_moving_out); + } } -void UIGMBox::ChangeBoxState( boxstate_t state ) +void UIGMBox::ChangeBoxState(boxstate_t state) { - m_boxstate = state; - m_boxtime = uid.time; - setShowState(); + m_boxstate = state; + m_boxtime = uid.time; + setShowState(); - if (state == box_out) { - PostMoveinEvent(); - } + if (state == box_out) { + PostMoveinEvent(); + } } -void UIGMBox::HandleBoxMoving( void ) +void UIGMBox::HandleBoxMoving(void) { - int delta; - UIRect2D newRect; + int delta; + UIRect2D newRect; - if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) { - return; - } + if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) { + return; + } - delta = m_movespeed * (uid.time - m_boxtime) / 1000; - m_boxtime = 1000 * delta / m_movespeed + m_boxtime; - if (m_boxstate == boxstate_t::box_moving_out) - { - newRect.size.width = m_frame.size.width; - newRect.size.height = m_frame.size.height; - newRect.pos.x = m_frame.pos.x; - newRect.pos.y = delta + m_frame.pos.y; + delta = m_movespeed * (uid.time - m_boxtime) / 1000; + m_boxtime = 1000 * delta / m_movespeed + m_boxtime; + if (m_boxstate == boxstate_t::box_moving_out) { + newRect.size.width = m_frame.size.width; + newRect.size.height = m_frame.size.height; + newRect.pos.x = m_frame.pos.x; + newRect.pos.y = delta + m_frame.pos.y; - if (newRect.pos.y <= 0.0) - { - newRect.pos.y = 0.0; - ChangeBoxState(boxstate_t::box_out); - } - } - else if (m_boxstate == boxstate_t::box_moving_in) - { - newRect.size.width = m_frame.size.width; - newRect.size.height = m_frame.size.height; - newRect.pos.x = m_frame.pos.x; - newRect.pos.y = delta - m_frame.pos.y; + if (newRect.pos.y <= 0.0) { + newRect.pos.y = 0.0; + ChangeBoxState(boxstate_t::box_out); + } + } else if (m_boxstate == boxstate_t::box_moving_in) { + newRect.size.width = m_frame.size.width; + newRect.size.height = m_frame.size.height; + newRect.pos.x = m_frame.pos.x; + newRect.pos.y = delta - m_frame.pos.y; - if (newRect.pos.y <= -newRect.size.height) - { - newRect.pos.y = -newRect.size.height; - ChangeBoxState(boxstate_t::box_in); - } - } else { - newRect = m_frame; - } + if (newRect.pos.y <= -newRect.size.height) { + newRect.pos.y = -newRect.size.height; + ChangeBoxState(boxstate_t::box_in); + } + } else { + newRect = m_frame; + } - setFrame(newRect); + setFrame(newRect); } -void UIGMBox::PostMoveinEvent( void ) +void UIGMBox::PostMoveinEvent(void) { - if (m_boxstate != boxstate_t::box_out) { - return; - } + if (m_boxstate != boxstate_t::box_out) { + return; + } - if (!EventPending(EV_GMBox_Goin)) { - PostEvent(EV_GMBox_Goin, 10.0); - } else { - PostponeEvent(EV_GMBox_Goin, 10.0); - } + if (!EventPending(EV_GMBox_Goin)) { + PostEvent(EV_GMBox_Goin, 10.0); + } else { + PostponeEvent(EV_GMBox_Goin, 10.0); + } } -void UIGMBox::PostDecayEvent( void ) +void UIGMBox::PostDecayEvent(void) { - if (!EventPending(EV_GMBox_Decay)) - { - float fDelayTime; - int iNumLines; - int i; - const char* pszString = m_items[0].string.c_str(); + if (!EventPending(EV_GMBox_Decay)) { + float fDelayTime; + int iNumLines; + int i; + const char *pszString = m_items[0].string.c_str(); - // - // Calculate the number of lines - // - iNumLines = 1; - for (i = 0; pszString[i]; i++) - { - if (pszString[i] == '\n') { - iNumLines++; - } - } + // + // Calculate the number of lines + // + iNumLines = 1; + for (i = 0; pszString[i]; i++) { + if (pszString[i] == '\n') { + iNumLines++; + } + } - // - // Bold as twice more decay - // - if (m_items[0].flags & GMBOX_ITEM_FLAG_BOLD) { - fDelayTime = iNumLines * 10.0; - } else { - fDelayTime = iNumLines * 5.0; - } + // + // Bold as twice more decay + // + if (m_items[0].flags & GMBOX_ITEM_FLAG_BOLD) { + fDelayTime = iNumLines * 10.0; + } else { + fDelayTime = iNumLines * 5.0; + } - m_iBeginDecay = cls.realtime; - m_iEndDecay = (int)(fDelayTime * 1000.0); + m_iBeginDecay = cls.realtime; + m_iEndDecay = (int)(fDelayTime * 1000.0); - PostEvent(EV_GMBox_Decay, fDelayTime); - } + PostEvent(EV_GMBox_Decay, fDelayTime); + } } -void UIGMBox::setShowState( void ) +void UIGMBox::setShowState(void) { - if (m_reallyshown) { - setShow(m_boxstate != box_in); - } else { - setShow(false); - } + if (m_reallyshown) { + setShow(m_boxstate != box_in); + } else { + setShow(false); + } } -void UIGMBox::RemoveTopItem( void ) +void UIGMBox::RemoveTopItem(void) { - int i; + int i; - if (m_numitems > 0) { - for (i = 0; i < m_numitems - 1; i++) { - m_items[i] = m_items[i + 1]; - } + if (m_numitems > 0) { + for (i = 0; i < m_numitems - 1; i++) { + m_items[i] = m_items[i + 1]; + } - m_numitems--; - } + m_numitems--; + } } -str UIGMBox::CalculateBreaks( UIFont *font, str text, float max_width ) +str UIGMBox::CalculateBreaks(UIFont *font, str text, float max_width) { - str newText, sTmp; - int i; - float fX; - float fwX, fsX; + str newText; + float fX; + float fwX; + const char *current; + int count; - Cmd_TokenizeString(text.c_str()); - if (Cmd_Argc()) - { - fX = 0.0; - fsX = font->getCharWidth(' '); + current = text; + fX = 0.0; - for (i = 0; i < Cmd_Argc(); i++) - { - sTmp = Cmd_Argv(i); + for (count = font->DBCSGetWordBlockCount(current, -1); count; + current += count, count = font->DBCSGetWordBlockCount(current, -1)) { + fwX = font->getWidth(current, count); - fwX = font->getWidth(sTmp.c_str(), -1); - if (fwX + i <= max_width) - { - if (fwX + i + fX <= max_width) - { - newText += sTmp + " "; - } else { - newText += "\n" + sTmp + " "; - } - } - else - { - sTmp += "\n"; - fX = 0.0; - } - } - } else { - newText = ""; - } + if (fX + fwX > max_width) { + newText += "\n" + str(current, 0, count); + fX = 0; + } else { + newText += str(current, 0, count); + } - return newText; + fX += fwX; + } + + return newText; } -float UIGMBox::PrintWrap( UIFont *font, float x, float y, str text ) +float UIGMBox::PrintWrap(UIFont *font, float x, float y, str text) { - const char* p1, * p2; - size_t n, l; - float fY; + const char *p1, *p2; + size_t n, l; + float fY; - fY = y; - p1 = text.c_str(); - l = text.length(); + fY = y; + p1 = text.c_str(); + l = text.length(); - for (;;) - { - p2 = strchr(p1, '\n'); - if (!p2) { - break; - } + for (;;) { + p2 = strchr(p1, '\n'); + if (!p2) { + break; + } - n = p2 - p1; - if (n >= l) { - break; - } + n = p2 - p1; + if (n >= l) { + break; + } - font->Print(x, fY, p1, p2 - p1, qfalse); - p1 = p2 + 1; - l -= n; - fY += font->getHeight(qfalse); - } + font->Print(x, fY, p1, p2 - p1, getHighResScale()); + p1 = p2 + 1; + l -= n; + fY += font->getHeight(); + } - font->Print(x, fY, p1, l, qfalse); + if (*p1) { + font->Print(x, fY, p1, l, getHighResScale()); + fY += font->getHeight(); + } - return font->getHeight(qfalse) + (fY - y); + return fY - y; } -float UIGMBox::DrawItem( item_t *in, float x, float y, float alpha ) +float UIGMBox::DrawItem(item_t *in, float x, float y, float alpha) { - in->font->setColor(in->color); - in->font->setAlpha(alpha); + if (m_drawoutline) { + // + // Draw an outline + // - return PrintWrap(in->font, x, y, in->string); + in->font->setColor(UBlack); + in->font->setAlpha(alpha); + + PrintWrap(in->font, x + 1, y + 2, in->string); + PrintWrap(in->font, x + 2, y + 1, in->string); + PrintWrap(in->font, x - 1, y + 2, in->string); + PrintWrap(in->font, x - 2, y + 1, in->string); + PrintWrap(in->font, x - 1, y - 2, in->string); + PrintWrap(in->font, x - 2, y - 1, in->string); + PrintWrap(in->font, x + 1, y - 2, in->string); + PrintWrap(in->font, x + 2, y - 1, in->string); + PrintWrap(in->font, x + 2, y, in->string); + PrintWrap(in->font, x - 2, y, in->string); + PrintWrap(in->font, x, y + 2, in->string); + PrintWrap(in->font, x, y - 2, in->string); + } + + in->font->setColor(in->color); + in->font->setAlpha(alpha); + + return PrintWrap(in->font, x, y, in->string); } -void UIGMBox::Print( const char *text ) +void UIGMBox::Print(const char *text) { - const char* text1 = text; + const char *text1 = text; - if (m_numitems > 4) - { - // - // Overwrite an item - // - RemoveTopItem(); - } + if (m_numitems > 4) { + // + // Overwrite an item + // + RemoveTopItem(); + } - m_items[m_numitems].flags = 0; + m_items[m_numitems].flags = 0; - if (*text == 3) - { - m_items[m_numitems].color = UWhite; - m_items[m_numitems].font = m_fontbold; - m_items[m_numitems].flags |= GMBOX_ITEM_FLAG_BOLD; + if (*text == MESSAGE_WHITE) { + m_items[m_numitems].color = UWhite; + m_items[m_numitems].font = m_fontbold; + m_items[m_numitems].flags |= GMBOX_ITEM_FLAG_BOLD; - text1 = text + 1; - } - else - { - m_items[m_numitems].color = m_foreground_color; - m_items[m_numitems].font = m_font; - } + text1 = text + 1; + } else { + m_items[m_numitems].color = m_foreground_color; + m_items[m_numitems].font = m_font; + } - m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, text1, s_gmboxWidth); + m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, Sys_LV_CL_ConvertString(text1), s_gmboxWidth); - m_numitems++; - VerifyBoxOut(); - PostDecayEvent(); + m_numitems++; + VerifyBoxOut(); + PostDecayEvent(); } -void UIGMBox::OnSizeChanged( Event *ev ) +void UIGMBox::OnSizeChanged(Event *ev) { - s_gmboxWidth = m_frame.size.width; + s_gmboxWidth = m_frame.size.width; } -void UIGMBox::Create( const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha ) +void UIGMBox::Create(const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha) { - InitFrame(NULL, rect, 0, "facfont-20"); + InitFrame(NULL, rect, 0, "facfont-20"); - if (!m_fontbold) { - m_fontbold = new UIFont("facfont-20"); - } + if (!m_fontbold) { + m_fontbold = new UIFont("facfont-20"); + } - m_fontbold->setColor(URed); - setBackgroundColor(back, true); - setForegroundColor(fore); - setBackgroundAlpha(alpha); + m_fontbold->setColor(URed); + setBackgroundColor(back, true); + setForegroundColor(fore); + setBackgroundAlpha(alpha); - Connect(this, W_SizeChanged, W_SizeChanged); - OnSizeChanged(NULL); + Connect(this, W_SizeChanged, W_SizeChanged); + OnSizeChanged(NULL); - m_movespeed = rect.size.height * 3.0; + m_movespeed = rect.size.height * 3.0; - setShowState(); + setShowState(); } -void UIGMBox::MoveInEvent( Event *ev ) +void UIGMBox::MoveInEvent(Event *ev) {} + +void UIGMBox::DecayEvent(Event *ev) { + RemoveTopItem(); + if (m_numitems) { + PostDecayEvent(); + } } -void UIGMBox::DecayEvent( Event *ev ) +void UIGMBox::Draw(void) { - RemoveTopItem(); - if (m_numitems) { - PostDecayEvent(); - } + float fsY; + int i; + float alpha; + float alphaScale; + + alphaScale = 1.0; + HandleBoxMoving(); + + if (!m_numitems) { + // + // Nothing to show + // + return; + } + + m_font->setColor(m_foreground_color); + alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay; + if (alpha > 1.0) { + alpha = 1.0; + } + + alpha = (1.0 - alpha) * 4.0; + if (alpha > 1.0) { + alpha = 1.0; + } + + if (cge) { + alphaScale = 1.0 - cge->CG_GetObjectiveAlpha(); + } + + fsY = DrawItem(m_items, s_gmboxOffsetX, s_gmboxOffsetY, alpha * alphaScale); + fsY = alpha <= 0.2 ? s_gmboxOffsetY : fsY + s_gmboxOffsetY; + + for (i = 1; i < m_numitems; i++) { + fsY += DrawItem(&m_items[i], s_gmboxOffsetX, fsY, alphaScale); + if (fsY > m_frame.size.height) { + if (EventPending(EV_GMBox_Decay)) { + CancelEventsOfType(EV_GMBox_Decay); + } + + PostEvent(EV_GMBox_Decay, 0.0); + break; + } + } } -void UIGMBox::Draw( void ) +void UIGMBox::setRealShow(bool b) { - float fsY; - int i; - float alpha; - float alphaScale; - - alphaScale = 1.0; - HandleBoxMoving(); - - if (!m_numitems) { - // - // Nothing to show - // - return; - } - - m_font->setColor(m_foreground_color); - alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay; - if (alpha > 1.0) alpha = 1.0; - - alpha = (1.0 - alpha) * 4.0; - if (alpha > 1.0) alpha = 1.0; - - if (cge) { - alphaScale = 1.0 - cge->CG_GetObjectiveAlpha(); - } - - fsY = DrawItem(m_items, s_gmboxOffsetX, s_gmboxOffsetY, alpha * alphaScale); - fsY = alpha <= 0.2 ? s_gmboxOffsetY : fsY + s_gmboxOffsetY; - - for (i = 1; i < m_numitems; i++) - { - fsY += DrawItem(&m_items[i], s_gmboxOffsetX, fsY, alphaScale); - if (fsY > m_frame.size.height) - { - if (EventPending(EV_GMBox_Decay)) { - CancelEventsOfType(EV_GMBox_Decay); - } - - PostEvent(EV_GMBox_Decay, 0.0); - break; - } - } + this->m_reallyshown = b; + setShowState(); } -void UIGMBox::setRealShow( bool b ) +void UIGMBox::Clear(void) { - this->m_reallyshown = b; - setShowState(); + m_numitems = 0; } - -void UIGMBox::Clear( void ) -{ - m_numitems = 0; -} - diff --git a/code/client/cl_uigmbox.h b/code/client/cl_uigmbox.h index 6a904515..4090b45d 100644 --- a/code/client/cl_uigmbox.h +++ b/code/client/cl_uigmbox.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2015-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIGMBOX_H__ -#define __CL_UIGMBOX_H__ +#pragma once static constexpr unsigned int GMBOX_ITEM_FLAG_BOLD = 1u; @@ -44,6 +43,8 @@ protected: int m_movespeed; int m_iBeginDecay; int m_iEndDecay; + // Added in OPM + bool m_drawoutline; public: CLASS_PROTOTYPE( UIGMBox ); @@ -72,5 +73,3 @@ public: void setRealShow( bool b ); void Clear( void ); }; - -#endif diff --git a/code/client/cl_uilangame.cpp b/code/client/cl_uilangame.cpp index 70d788d2..e821a464 100644 --- a/code/client/cl_uilangame.cpp +++ b/code/client/cl_uilangame.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,44 +21,224 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/localization.h" -CLASS_DECLARATION( UIListCtrl, UILANGameClass, NULL ) +class LANGameItem : public UIListCtrlItem { - { NULL, NULL } + str strings[6]; + +public: + LANGameItem(); + LANGameItem( + const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping, const str& ipAddress + ); + + int getListItemValue(int which) const override; + griditemtype_t getListItemType(int which) const override; + str getListItemString(int which) const override; + void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; + qboolean IsHeaderEntry() const override; +}; + +Event EV_LANGame_JoinGame +( + "joingame", + EV_DEFAULT, + NULL, + NULL, + "Join the currently selected server" +); + +CLASS_DECLARATION(UIListCtrl, UILANGameClass, NULL) { + {&EV_UIListBase_ItemSelected, &UILANGameClass::SelectServer}, + {&EV_UIListBase_ItemDoubleClicked, &UILANGameClass::JoinServer }, + {&EV_LANGame_JoinGame, &UILANGameClass::JoinServer }, + {NULL, NULL } }; UILANGameClass::UILANGameClass() { - // FIXME: stub + Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); + Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); + AllowActivate(true); + setHeaderFont("facfont-20"); + + m_iLastUpdateTime = 0; + m_noservers_mat = uWinMan.RegisterShader("textures/menu/noservers"); + + // + // Added in OPM + // + m_bVirtual = false; } -void UILANGameClass::SetupServers( void ) +void UILANGameClass::Draw(void) { - // FIXME: stub + if (cls.bNewLocalServerInfo) { + SetupServers(); + } + + UIListCtrl::Draw(); + + if (!getNumItems() && m_noservers_mat) { + float x, y, w, h; + + w = re.GetShaderWidth(m_noservers_mat->GetMaterial()) * m_vVirtualScale[0]; + h = re.GetShaderHeight(m_noservers_mat->GetMaterial()) * m_vVirtualScale[1]; + + UIRect2D frame = getClientFrame(); + x = (frame.size.width - w) * 0.5f; + y = (frame.size.height - h) * 0.5f; + + re.DrawStretchPic(x, y, w, h, 0, 0, 1, 1, m_noservers_mat->GetMaterial()); + } + + if (m_iLastUpdateTime && m_iLastUpdateTime < cls.realtime) { + Cvar_Set("cl_langamerefreshstatus", "Ready"); + m_iLastUpdateTime = 0; + } } -void UILANGameClass::Draw( void ) +void UILANGameClass::UpdateUIElement(void) { - // FIXME: stub + float width; + + RemoveAllColumns(); + + width = getClientFrame().size.width - 16.f; + + AddColumn(Sys_LV_CL_ConvertString("Server Name"), 0, width * 0.27f, false, false); // was 0.4 + AddColumn(Sys_LV_CL_ConvertString("Map"), 1, width * 0.12f, false, false); // was 0.15 + AddColumn(Sys_LV_CL_ConvertString("Players"), 2, width * 0.08f, true, true); // was 0.165 + AddColumn(Sys_LV_CL_ConvertString("GameType"), 3, width * 0.118f, false, false); // was 0.22 + AddColumn(Sys_LV_CL_ConvertString("Ping"), 4, width * 0.052f, true, false); // was 0.065 + AddColumn(Sys_LV_CL_ConvertString("IP"), 5, width * 0.36f, false, false); // Added in OPM + + uWinMan.ActivateControl(this); + + SetupServers(); } -void UILANGameClass::SelectServer( Event *ev ) +void UILANGameClass::SetupServers(void) { - // FIXME: stub + int i; + LANGameItem *pItem; + const serverInfo_t *pServerInfo; + + for (i = 1; i <= cls.numlocalservers; i++) { + pServerInfo = &cls.localServers[i - 1]; + + if (i > getNumItems()) { + pItem = new LANGameItem(); + AddItem(pItem); + } else { + pItem = static_cast(GetItem(i)); + } + + *pItem = LANGameItem( + pServerInfo->hostName, + pServerInfo->mapName, + va("%02i/%02i", pServerInfo->clients, pServerInfo->maxClients), + pServerInfo->gameTypeString, + str(pServerInfo->ping), + // Added in OPM + NET_AdrToStringwPort(pServerInfo->adr) + ); + } + + while (cls.numlocalservers < getNumItems()) { + DeleteItem(getNumItems()); + } + + cls.bNewLocalServerInfo = false; + m_iLastUpdateTime = 0; } -void UILANGameClass::JoinServer( Event *ev ) +void UILANGameClass::SelectServer(Event *ev) { - // FIXME: stub + const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1]; + static const char info[] = "\xFF\xFF\xFF\xFF\x02getinfo xxx"; + + Com_Printf("Requesting updated info from server...\n"); + Cvar_Set("cl_langamerefreshstatus", "Requesting updated info from server..."); + + NET_SendPacket(NS_CLIENT, sizeof(info), info, serverInfo.adr); + m_iLastUpdateTime = cls.realtime + 3000; } -qboolean UILANGameClass::KeyEvent( int key, unsigned int time ) +void UILANGameClass::JoinServer(Event *ev) { - // FIXME: stub - return qfalse; + if (!getCurrentItem()) { + return; + } + + const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1]; + + UI_SetReturnMenuToCurrent(); + CL_Connect(NET_AdrToStringwPort(serverInfo.adr), netadrtype_t::NA_UNSPEC); } -void UILANGameClass::UpdateUIElement( void ) +qboolean UILANGameClass::KeyEvent(int key, unsigned int time) { - // FIXME: stub + switch (key) { + case K_ENTER: + case K_KP_ENTER: + JoinServer(NULL); + return true; + case K_UPARROW: + if (getCurrentItem() > 1) { + TrySelectItem(getCurrentItem() - 1); + SelectServer(NULL); + } + return false; + case K_DOWNARROW: + if (getCurrentItem() < getNumItems()) { + TrySelectItem(getCurrentItem() + 1); + SelectServer(NULL); + } + return false; + } + + return UIListBase::KeyEvent(key, time); +} + +LANGameItem::LANGameItem() {} + +LANGameItem::LANGameItem( + const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping, const str& ipAddress +) +{ + strings[0] = hostName; + strings[1] = mapName; + strings[2] = players; + strings[3] = gameTypeString; + strings[4] = ping; + + // + // Added in OPM + // + + strings[5] = ipAddress; +} + +int LANGameItem::getListItemValue(int which) const +{ + return atoi(strings[which]); +} + +griditemtype_t LANGameItem::getListItemType(int which) const +{ + return griditemtype_t::TYPE_STRING; +} + +str LANGameItem::getListItemString(int which) const +{ + return strings[which]; +} + +void LANGameItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} + +qboolean LANGameItem::IsHeaderEntry() const +{ + return qfalse; } diff --git a/code/client/cl_uilangame.h b/code/client/cl_uilangame.h index 2351a6c6..c374cb81 100644 --- a/code/client/cl_uilangame.h +++ b/code/client/cl_uilangame.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,29 +20,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UILANGAME_H__ -#define __CL_UILANGAME_H__ +#pragma once -class UILANGameClass : public UIListCtrl { +class UILANGameClass : public UIListCtrl +{ protected: - int m_iLastUpdateTime; - UIReggedMaterial *m_noservers_mat; + int m_iLastUpdateTime; + UIReggedMaterial *m_noservers_mat; public: - CLASS_PROTOTYPE( UILANGameClass ); + CLASS_PROTOTYPE(UILANGameClass); private: - void SetupServers( void ); + void SetupServers(void); protected: - void Draw( void ) override; - void SelectServer( Event *ev ); - void JoinServer( Event *ev ); - qboolean KeyEvent( int key, unsigned int time ) override; - void UpdateUIElement( void ) override; + void Draw(void) override; + void SelectServer(Event *ev); + void JoinServer(Event *ev); + qboolean KeyEvent(int key, unsigned int time) override; + void UpdateUIElement(void) override; public: - UILANGameClass(); + UILANGameClass(); }; - -#endif /* __CL_UILANGAME_H__ */ diff --git a/code/client/cl_uiloadsave.cpp b/code/client/cl_uiloadsave.cpp index f0e9c9f1..206bb38b 100644 --- a/code/client/cl_uiloadsave.cpp +++ b/code/client/cl_uiloadsave.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,63 +21,359 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/localization.h" -CLASS_DECLARATION( UIListCtrl, UIFAKKLoadGameClass, NULL ) +class FAKKLoadGameItem : public UIListCtrlItem { - { NULL, NULL } + str strings[4]; + +public: + FAKKLoadGameItem(const str& missionName, const str& elapsedTime, const str& dateTime, const str& fileName); + + int getListItemValue(int which) const override; + griditemtype_t getListItemType(int which) const override; + str getListItemString(int which) const override; + void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; + qboolean IsHeaderEntry() const override; +}; + +static UIFAKKLoadGameClass *loadgame_ui = NULL; + +Event EV_FAKKLoadGame_LoadGame +( + "loadgame", + EV_DEFAULT, + NULL, + NULL, + "Load the currently selected game" +); +Event EV_FAKKLoadGame_RemoveGame +( + "removegame", + EV_DEFAULT, + NULL, + NULL, + "Delete the currently selected game" +); +Event EV_FAKKLoadGame_DeleteGame +( + "deletegame", + EV_DEFAULT, + NULL, + NULL, + "Delete the currently selected game... for real" +); +Event EV_FAKKLoadGame_NoDeleteGame +( + "nodeletegame", + EV_DEFAULT, + NULL, + NULL, + "Delete the currently selected game... for real" +); +Event EV_FAKKLoadGame_SaveGame +( + "savegame", + EV_DEFAULT, + NULL, + NULL, + "Save the currently selected game" +); + +CLASS_DECLARATION(UIListCtrl, UIFAKKLoadGameClass, NULL) { + {&EV_UIListBase_ItemSelected, &UIFAKKLoadGameClass::SelectGame }, + {&EV_UIListBase_ItemDoubleClicked, &UIFAKKLoadGameClass::LoadGame }, + {&EV_FAKKLoadGame_RemoveGame, &UIFAKKLoadGameClass::RemoveGame }, + {&EV_FAKKLoadGame_DeleteGame, &UIFAKKLoadGameClass::DeleteGame }, + {&EV_FAKKLoadGame_NoDeleteGame, &UIFAKKLoadGameClass::NoDeleteGame}, + {&EV_FAKKLoadGame_LoadGame, &UIFAKKLoadGameClass::LoadGame }, + {&EV_FAKKLoadGame_SaveGame, &UIFAKKLoadGameClass::SaveGame }, + {NULL, NULL } }; UIFAKKLoadGameClass::UIFAKKLoadGameClass() { - // FIXME: stub + Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); + Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); + AllowActivate(true); + m_bRemovePending = false; + + setHeaderFont("facfont-20"); + loadgame_ui = this; } -void UIFAKKLoadGameClass::SelectGame( Event *ev ) +UIFAKKLoadGameClass::~UIFAKKLoadGameClass() { - // FIXME: stub + loadgame_ui = NULL; } -void UIFAKKLoadGameClass::LoadGame( Event *ev ) +void UIFAKKLoadGameClass::UpdateUIElement(void) { - // FIXME: stub + float width; + + RemoveAllColumns(); + + width = getClientFrame().size.width; + AddColumn(Sys_LV_CL_ConvertString("Mission"), 0, width * 0.555, false, false); + AddColumn(Sys_LV_CL_ConvertString("Elapsed Time"), 1, width * 0.17f, true, true); + AddColumn(Sys_LV_CL_ConvertString("Date & Time Logged"), 2, width * 0.275f, true, true); + + uWinMan.ActivateControl(this); + + SetupFiles(); } -void UIFAKKLoadGameClass::SaveGame( Event *ev ) +void UIFAKKLoadGameClass::SetupFiles(void) { - // FIXME: stub + char **filenames; + int numfiles; + int i; + const char *searchFolder = Com_GetArchiveFolder(); + + // cleanup + DeleteAllItems(); + + filenames = FS_ListFiles(searchFolder, "ssv", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename; + str work; + str gametime; + str date; + fileHandle_t f; + savegamestruct_t save; + + filename = filenames[i]; + work = searchFolder; + work += "/"; + work += filename; + + FS_FOpenFileRead(work, &f, qfalse, qtrue); + if (!f) { + continue; + } + + FS_Read(&save, sizeof(savegamestruct_t), f); + FS_FCloseFile(f); + Com_SwapSaveStruct(&save); + + if (save.version != SAVEGAME_STRUCT_VERSION) { + // wrong save game version + continue; + } + + if (save.type != com_target_game->integer) { + continue; + } + + gametime = (save.mapTime / 1000); + date = save.time; + + AddItem(new FAKKLoadGameItem(save.comment, gametime, date, save.saveName)); + } + + FS_FreeFileList(filenames); + + // sort by date + SortByColumn(2); + + // select the first item + TrySelectItem(1); + SelectGame(NULL); } -void UIFAKKLoadGameClass::RemoveGame( Event *ev ) +void UIFAKKLoadGameClass::SelectGame(Event *ev) { - // FIXME: stub + UIWidget *wid; + const char *shotName; + + if (getCurrentItem() > 0) { + shotName = Com_GetArchiveFileName(GetItem(getCurrentItem())->getListItemString(3), "tga"); + } else { + shotName = "textures/menu/no_saved_games.tga"; + } + + wid = findSibling("LoadSaveShot"); + if (!wid) { + return; + } + + wid->setMaterial(uWinMan.RefreshShader(shotName)); } -void UIFAKKLoadGameClass::DeleteGame( Event *ev ) +void UIFAKKLoadGameClass::RemoveGame(Event *ev) { - // FIXME: stub + if (m_bRemovePending || getCurrentItem() <= 0) { + return; + } + + Cbuf_ExecuteText( + EXEC_NOW, + "dialog \"\" \"\" \"widgetcommand LoadSaveList deletegame\" \"widgetcommand LoadSaveList nodeletegame\" 256 64 " + "confirm_delete menu_button_trans menu_button_trans\n" + ); + m_bRemovePending = true; } -void UIFAKKLoadGameClass::NoDeleteGame( Event *ev ) +void UIFAKKLoadGameClass::NoDeleteGame(Event *ev) { - // FIXME: stub + m_bRemovePending = false; } -qboolean UIFAKKLoadGameClass::KeyEvent( int key, unsigned int time ) +void UIFAKKLoadGameClass::DeleteGame(Event *ev) { - // FIXME: stub - return qfalse; + str name; + cvar_t *var; + m_bRemovePending = false; + + if (getCurrentItem() <= 0) { + return; + } + + name = GetItem(getCurrentItem())->getListItemString(3); + var = Cvar_Get("g_lastsave", "", 0); + + if (!strcmp(name, var->string)) { + // Make sure the last save is not the save being deleted + Cvar_Set("g_lastsave", ""); + } + + Com_WipeSavegame(name); + SetupFiles(); } -void UIFAKKLoadGameClass::UpdateUIElement( void ) +void UIFAKKLoadGameClass::LoadGame(Event *ev) { - // FIXME: stub + char cmdString[266]; + str name; + + if (getCurrentItem() <= 0) { + return; + } + + name = GetItem(getCurrentItem())->getListItemString(3); + // Execute the command + Com_sprintf(cmdString, sizeof(cmdString), "loadgame %s\n", name.c_str()); + Cbuf_AddText(cmdString); } -void UIFAKKLoadGameClass::SetupFiles( void ) +void UIFAKKLoadGameClass::SaveGame(Event *ev) { - // FIXME: stub + Cbuf_ExecuteText(EXEC_NOW, "savegame"); } -void UI_SetupFiles( void ) { - // FIXME: stub +qboolean UIFAKKLoadGameClass::KeyEvent(int key, unsigned int time) +{ + switch (key) { + case K_DEL: + RemoveGame(NULL); + return qtrue; + case K_ENTER: + case K_KP_ENTER: + LoadGame(NULL); + return qtrue; + case K_UPARROW: + if (getCurrentItem() > 1) { + TrySelectItem(getCurrentItem() - 1); + SelectGame(NULL); + return qtrue; + } + break; + case K_DOWNARROW: + if (getCurrentItem() < getNumItems()) { + TrySelectItem(getCurrentItem() + 1); + SelectGame(NULL); + return qtrue; + } + break; + default: + return UIListCtrl::KeyEvent(key, time); + } + + return qfalse; +} + +void UI_SetupFiles(void) +{ + if (loadgame_ui && loadgame_ui->getShow()) { + loadgame_ui->SetupFiles(); + } +} + +FAKKLoadGameItem::FAKKLoadGameItem( + const str& missionName, const str& elapsedTime, const str& dateTime, const str& fileName +) +{ + strings[0] = missionName; + strings[1] = elapsedTime; + strings[2] = dateTime; + strings[3] = fileName; +} + +int FAKKLoadGameItem::getListItemValue(int which) const +{ + return atoi(strings[which]); +} + +griditemtype_t FAKKLoadGameItem::getListItemType(int which) const +{ + return griditemtype_t::TYPE_STRING; +} + +str FAKKLoadGameItem::getListItemString(int which) const +{ + str itemstring; + + switch (which) { + case 0: + case 3: + itemstring = strings[which]; + break; + case 1: + { + int numseconds; + int numseconds_hours; + int seconds; + + // hours + numseconds = atol(strings[1]); + itemstring += (numseconds / 3600); + itemstring += ":"; + + // minutes + numseconds_hours = numseconds % 3600; + if (numseconds_hours / 60 < 10) { + itemstring += "0"; + } + itemstring += (numseconds_hours / 60); + itemstring += ":"; + + // seconds + seconds = numseconds_hours % 60; + if (seconds < 10) { + itemstring += "0"; + } + itemstring += seconds; + } + break; + case 2: + { + time_t time; + char buffer[2048]; + + time = atol(strings[2]); + strftime(buffer, sizeof(buffer), "%a %b %d %Y %H:%M:%S", localtime(&time)); + itemstring = buffer; + } + break; + } + + return itemstring; +} + +void FAKKLoadGameItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} + +qboolean FAKKLoadGameItem::IsHeaderEntry() const +{ + return qfalse; } diff --git a/code/client/cl_uiloadsave.h b/code/client/cl_uiloadsave.h index 5f9deca9..4b29f48f 100644 --- a/code/client/cl_uiloadsave.h +++ b/code/client/cl_uiloadsave.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,38 +20,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UILOADSAVE_H__ -#define __CL_UILOADSAVE_H__ +#pragma once -class UIFAKKLoadGameClass : public UIListCtrl { - bool m_bRemovePending; +class UIFAKKLoadGameClass : public UIListCtrl +{ + bool m_bRemovePending; public: - CLASS_PROTOTYPE( UIFAKKLoadGameClass ); + CLASS_PROTOTYPE(UIFAKKLoadGameClass); protected: - void SelectGame( Event *ev ); - void LoadGame( Event *ev ); - void SaveGame( Event *ev ); - void RemoveGame( Event *ev ); - void DeleteGame( Event *ev ); - void NoDeleteGame( Event *ev ); - qboolean KeyEvent( int key, unsigned int time ) override; - void UpdateUIElement( void ) override; + void SelectGame(Event *ev); + void LoadGame(Event *ev); + void SaveGame(Event *ev); + void RemoveGame(Event *ev); + void DeleteGame(Event *ev); + void NoDeleteGame(Event *ev); + qboolean KeyEvent(int key, unsigned int time) override; + void UpdateUIElement(void) override; + public: - UIFAKKLoadGameClass(); + UIFAKKLoadGameClass(); + ~UIFAKKLoadGameClass(); - void SetupFiles( void ); + void SetupFiles(void); }; - -#ifdef __cplusplus -extern "C" { -#endif - -void UI_SetupFiles( void ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/code/client/cl_uimaprotationsetup.cpp b/code/client/cl_uimaprotationsetup.cpp new file mode 100644 index 00000000..3189d19f --- /dev/null +++ b/code/client/cl_uimaprotationsetup.cpp @@ -0,0 +1,457 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cl_ui.h" +#include "cl_uimaprotationsetup.h" + +Event EV_MapListBox_RefreshMapList +( + "RefreshMapList", + EV_DEFAULT, + NULL, + NULL, + "Refreshes the map list." +); + +Event EV_MapRotationListBox_RefreshRotationList +( + "RefreshRotationList", + EV_DEFAULT, + NULL, + NULL, + "Refreshed the map rotation list." +); + +CLASS_DECLARATION(UIListBox, UIMapRotationListBox, NULL) { + {&EV_MapRotationListBox_RefreshRotationList, &UIMapRotationListBox::RefreshRotationList}, + {NULL, NULL } +}; + +UIMapRotationListBox::UIMapRotationListBox() {} + +void UIMapRotationListBox::RefreshRotationList(Event *ev) +{ + DeleteAllItems(); + PopulateRotationList(); +} + +void UIMapRotationListBox::PopulateRotationList() +{ + cvar_t *filter; + cvar_t *maplistVar; + const char *token; + char mapBuffer[1024]; + + filter = Cvar_Get("g_maprotation_filter", "ffa", 0); + if (!Q_stricmp(filter->string, "obj")) { + maplistVar = Cvar_Get("ui_maplist_obj", "", 0); + } else if (!Q_stricmp(filter->string, "tow")) { + maplistVar = Cvar_Get("ui_maplist_tow", "", 0); + } else if (!Q_stricmp(filter->string, "lib")) { + maplistVar = Cvar_Get("ui_maplist_lib", "", 0); + } else if (!Q_stricmp(filter->string, "team")) { + maplistVar = Cvar_Get("ui_maplist_team", "", 0); + } else if (!Q_stricmp(filter->string, "round")) { + maplistVar = Cvar_Get("ui_maplist_round", "", 0); + } else { + maplistVar = Cvar_Get("ui_maplist_ffa", "", 0); + } + + Q_strncpyz(mapBuffer, maplistVar->string, sizeof(mapBuffer)); + + for (token = strtok(mapBuffer, " /"); token; token = strtok(NULL, " /")) { + if (!Q_stricmp(token, "dm")) { + continue; + } + if (!Q_stricmp(token, "obj")) { + continue; + } + if (!Q_stricmp(token, "lib")) { + continue; + } + + AddItem(token, NULL); + } +} + +CLASS_DECLARATION(UIListBox, UIMapListBox, NULL) { + {&EV_MapListBox_RefreshMapList, &UIMapListBox::RefreshMapList}, + {NULL, NULL } +}; + +UIMapListBox::UIMapListBox() {} + +void UIMapListBox::RefreshMapList(Event *ev) +{ + DeleteAllItems(); + PopulateMapList(); +} + +void UIMapListBox::PopulateMapList() +{ + cvar_t *filter; + char **filenames; + int numfiles; + str path; + int i; + bool bTugOfWar = false; + bool bObjective = false; + bool bLiberation = false; + + filter = Cvar_Get("g_maprotation_filter", "ffa", 0); + if (!Q_stricmp(filter->string, "lib")) { + path = "maps/lib/"; + bLiberation = true; + } else if (!Q_stricmp(filter->string, "obj") || !Q_stricmp(filter->string, "tow")) { + path = "maps/obj/"; + if (!Q_stricmp(filter->string, "tow")) { + bTugOfWar = true; + } else { + bObjective = true; + } + } else { + path = "maps/dm/"; + } + + filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + const char *token; + char mapName[256]; + char tokenized[256]; + bool bHasMP = false; + bool bHasTOW = false; + bool bHasLib = false; + + Q_strncpyz(mapName, filename, sizeof(mapName)); + mapName[strlen(mapName) - 4] = 0; + + if (!COM_IsMapValid(mapName)) { + continue; + } + + if (bTugOfWar || bLiberation) { + Q_strncpyz(tokenized, mapName, sizeof(tokenized)); + + for (token = strtok(tokenized, "_"); token; token = strtok(NULL, "_")) { + if (bLiberation) { + if (!Q_stricmp(token, "MP")) { + bHasMP = true; + } + if (!Q_stricmp(token, "LIB")) { + bHasLib = true; + } + if (bHasMP && bHasLib) { + AddItem(mapName, NULL); + break; + } + } + + if (bTugOfWar) { + if (!Q_stricmp(token, "MP")) { + bHasMP = true; + } + if (!Q_stricmp(token, "TOW")) { + bHasTOW = true; + } + if (bHasMP && bHasTOW) { + AddItem(mapName, NULL); + break; + } + } + } + } else if (bObjective) { + Q_strncpyz(tokenized, mapName, sizeof(tokenized)); + + for (token = strtok(tokenized, "_"); token; token = strtok(NULL, "_")) { + if (!Q_stricmp(token, "obj")) { + AddItem(mapName, NULL); + break; + } + } + + if (!Q_stricmp(mapName, "mp_ship_lib")) { + AddItem(mapName, NULL); + } + } else { + AddItem(mapName, NULL); + } + } + + if (bObjective) { + path = "maps/lib/"; + + filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + const char *token; + char mapName[256]; + char tokenized[256]; + + Q_strncpyz(mapName, filename, sizeof(mapName)); + mapName[strlen(mapName) - 4] = 0; + Q_strncpyz(tokenized, mapName, sizeof(tokenized)); + + token = strtok(tokenized, "_"); + if (!Q_stricmp(token, "obj") || !Q_stricmp(mapName, "mp_ship_lib")) { + AddItem(mapName, NULL); + break; + } + } + } + + if (!bTugOfWar && !bObjective && !bLiberation) { + int type; + + for (type = 0; type < 2; type++) { + if (type == 0) { + path = "maps/obj/"; + } else { + path = "maps/lib/"; + } + + filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + char mapName[256]; + + Q_strncpyz(mapName, filename, sizeof(mapName)); + mapName[strlen(mapName) - 4] = 0; + + if (!COM_IsMapValid(mapName)) { + continue; + } + + if (!Q_stricmp(mapName, "obj_team2") || !Q_stricmp(mapName, "obj_team4")) { + continue; + } + + AddItem(mapName, NULL); + } + } + } +} + +CLASS_DECLARATION(UIButton, UIAddToRotationButton, NULL) { + {&W_LeftMouseUp, &UIAddToRotationButton::Released}, + {NULL, NULL } +}; + +void UIAddToRotationButton::Released(Event *ev) +{ + UIListBox *mapList; + UIListBox *rotationList; + size_t prefixLength; + int i; + + mapList = static_cast(uWinMan.FindWidget("Map List")); + rotationList = static_cast(uWinMan.FindWidget("Rotation List")); + + if (Cvar_Get("g_maprotation_filter", "ffa", 0)) { + prefixLength = strlen("obj/") + 1; + } else { + prefixLength = 1; + } + + if (mapList && rotationList) { + size_t mapLength = 0; + int item = mapList->getCurrentItem(); + str currentItemText; + + if (item) { + currentItemText = mapList->getItemText(item); + } + + for (i = 1; i <= rotationList->getNumItems(); i++) { + str text = rotationList->getItemText(i); + if (text == currentItemText) { + // Added in OPM + // Prevent adding duplicates + item = 0; + break; + } + + mapLength += text.length(); + } + + if (item && prefixLength + mapLength + currentItemText.length() < 256) { + rotationList->AddItem(currentItemText, NULL); + } + } + + UIButtonBase::Released(ev); +} + +CLASS_DECLARATION(UIButton, UIRemoveFromRotationButton, NULL) { + {&W_LeftMouseUp, &UIRemoveFromRotationButton::Released}, + {NULL, NULL } +}; + +void UIRemoveFromRotationButton::Released(Event *ev) +{ + UIListBox *list; + + list = static_cast(uWinMan.FindWidget("Rotation List")); + if (list) { + list->DeleteItem(list->getCurrentItem()); + } + + UIButtonBase::Released(ev); +} + +CLASS_DECLARATION(UIButton, UIRotationApplyButton, NULL) { + {&W_LeftMouseUp, &UIRotationApplyButton::Released}, + {NULL, NULL } +}; + +void UIRotationApplyButton::Released(Event *ev) +{ + UIListBox *list; + cvar_t *filter; + str cvarName; + str maplistStr; + int i; + bool bObjective = false; + bool bLiberation = false; + + filter = Cvar_Get("g_maprotation_filter", "ffa", 0); + if (!Q_stricmp(filter->string, "obj")) { + cvarName = "ui_maplist_obj"; + bObjective = true; + } else if (!Q_stricmp(filter->string, "tow")) { + cvarName = "ui_maplist_obj"; + bObjective = true; + } else if (!Q_stricmp(filter->string, "lib")) { + cvarName = "ui_maplist_lib"; + bLiberation = true; + } else if (!Q_stricmp(filter->string, "team")) { + cvarName = "ui_maplist_team"; + } else if (!Q_stricmp(filter->string, "round")) { + cvarName = "ui_maplist_round"; + } else { + cvarName = "ui_maplist_ffa"; + } + Cvar_Set(cvarName, ""); + + list = static_cast(uWinMan.FindWidget("Rotation List")); + if (list) { + for (i = 1; i <= list->getNumItems(); i++) { + const char *token; + str text = list->getItemText(i); + char map[256]; + bool bHasTOW = false, bHasObj = false, bHasLib = false, bHasShip = false; + + Q_strncpyz(map, text, sizeof(map)); + for (token = strtok(map, "_"); token; token = strtok(NULL, "_")) { + if (!Q_stricmp(token, "TOW")) { + bHasTOW = true; + break; + } + if (!Q_stricmp(token, "obj")) { + bHasObj = true; + break; + } + if (!Q_stricmp(token, "lib")) { + bHasLib = true; + break; + } + if (!Q_stricmp(token, "ship")) { + bHasShip = true; + break; + } + } + + if (bHasShip) { + maplistStr += "lib/"; + } else if (bObjective || bHasTOW || bHasObj) { + maplistStr += "obj/"; + } else if (bHasLib || bLiberation) { + maplistStr += "lib/"; + } else { + maplistStr += "dm/"; + } + + maplistStr += text; + + if (i == 1) { + Cvar_Set("ui_dmmap", maplistStr); + } + + maplistStr += " "; + } + } + + Cvar_Set(cvarName, maplistStr); + + UIButtonBase::Released(ev); +} + +CLASS_DECLARATION(UIButton, UIRotationMoveItemUpButton, NULL) { + {&W_LeftMouseUp, &UIRotationMoveItemUpButton::Released}, + {NULL, NULL } +}; + +void UIRotationMoveItemUpButton::Released(Event *ev) +{ + UIListBox *list; + int item; + + list = static_cast(uWinMan.FindWidget("Rotation List")); + item = list->getCurrentItem(); + + if (item > 1 && list->getNumItems() > 1) { + str text = list->getItemText(item - 1); + + list->DeleteItem(item - 1); + list->InsertItem(text, item); + list->setCurrentItem(item - 1); + } + + UIButtonBase::Released(ev); +} + +CLASS_DECLARATION(UIButton, UIRotationMoveItemDownButton, NULL) { + {&W_LeftMouseUp, &UIRotationMoveItemDownButton::Released}, + {NULL, NULL } +}; + +void UIRotationMoveItemDownButton::Released(Event *ev) +{ + UIListBox *list; + int item; + + list = static_cast(uWinMan.FindWidget("Rotation List")); + item = list->getCurrentItem(); + + if (item < list->getNumItems() && list->getNumItems() > 1) { + str text = list->getItemText(item + 1); + + list->DeleteItem(item + 1); + list->InsertItem(text, item); + list->setCurrentItem(item + 1); + } + + UIButtonBase::Released(ev); +} diff --git a/code/client/cl_uimaprotationsetup.h b/code/client/cl_uimaprotationsetup.h new file mode 100644 index 00000000..5f9f4045 --- /dev/null +++ b/code/client/cl_uimaprotationsetup.h @@ -0,0 +1,87 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#pragma once + +#include "../uilib/uilistbox.h" + +class UIMapRotationListBox : public UIListBox +{ + CLASS_PROTOTYPE(UIMapRotationListBox); + +public: + UIMapRotationListBox(); + + void RefreshRotationList(Event *ev); + void PopulateRotationList(); +}; + +class UIMapListBox : public UIListBox +{ + CLASS_PROTOTYPE(UIMapListBox); + +public: + UIMapListBox(); + + void RefreshMapList(Event *ev); + void PopulateMapList(); +}; + +class UIAddToRotationButton : public UIButton +{ + CLASS_PROTOTYPE(UIAddToRotationButton); + +public: + void Released(Event *ev); +}; + +class UIRemoveFromRotationButton : public UIButton +{ + CLASS_PROTOTYPE(UIRemoveFromRotationButton); + +public: + void Released(Event *ev); +}; + +class UIRotationApplyButton : public UIButton +{ + CLASS_PROTOTYPE(UIRotationApplyButton); + +public: + void Released(Event *ev); +}; + +class UIRotationMoveItemUpButton : public UIButton +{ + CLASS_PROTOTYPE(UIRotationMoveItemUpButton); + +public: + void Released(Event *ev); +}; + +class UIRotationMoveItemDownButton : public UIButton +{ + CLASS_PROTOTYPE(UIRotationMoveItemDownButton); + +public: + void Released(Event *ev); +}; diff --git a/code/client/cl_uimaprunner.cpp b/code/client/cl_uimaprunner.cpp index 11f33873..20f4fbb9 100644 --- a/code/client/cl_uimaprunner.cpp +++ b/code/client/cl_uimaprunner.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,47 +22,107 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" -CLASS_DECLARATION( FilePickerClass, MapRunnerClass, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(FilePickerClass, MapRunnerClass, NULL) { + {NULL, NULL} }; -void MapRunnerClass::FileChosen( str ¤tDirectory, str &partialName, str &fullname ) +void MapRunnerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) { - // FIXME: stub + str newName; + + newName = "spmap " + str(fullname, 5, fullname.length() - 4) + "\n"; + // insert the command + Cbuf_AddText(newName); + + CloseWindow(); } -CLASS_DECLARATION( FilePickerClass, ViewSpawnerClass, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(FilePickerClass, UIPickFileClass, NULL) { + {NULL, NULL} }; -void ViewSpawnerClass::FileChosen( str ¤tDirectory, str &partialName, str &fullname ) +UIPickFileClass::UIPickFileClass() { - // FIXME: stub + retobj = NULL; + retevent = NULL; } -CLASS_DECLARATION( FilePickerClass, LODSpawnerClass, NULL ) +UIPickFileClass::~UIPickFileClass() { - { NULL, NULL } + if (retevent) { + delete retevent; + } +} + +void UIPickFileClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) +{ + if (!retobj || !retevent) { + CloseWindow(); + return; + } + + retevent->AddString(fullname); + retobj->ProcessEvent(retevent); + + retevent = NULL; + retobj = NULL; + + CloseWindow(); +} + +void PickFile(const char *name, Listener *obj, Event& event) +{ + UIPickFileClass *picker; + str currentpath; + int i; + + picker = new UIPickFileClass(); + picker->retevent = new Event(event); + picker->retobj = obj; + + if (name && *name && strchr(name, '/')) { + currentpath = name; + + for (i = currentpath.length() - 1; i > 0; i--) { + if (currentpath[i] == '/') { + break; + } + } + + currentpath = str(currentpath, 0, i + 1); + } else { + currentpath = ""; + } + + picker->Setup("", currentpath, ".*", ""); +} + +CLASS_DECLARATION(FilePickerClass, ViewSpawnerClass, NULL) { + {NULL, NULL} }; -void LODSpawnerClass::FileChosen( str ¤tDirectory, str &partialName, str &fullname ) +void ViewSpawnerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) { - // FIXME: stub + str newName; + + newName = "viewspawn " + fullname + "\n"; + // insert the command + Cbuf_AddText(newName); + + CloseWindow(); } -CLASS_DECLARATION( FilePickerClass, UIPickFileClass, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(FilePickerClass, LODSpawnerClass, NULL) { + {NULL, NULL} }; -void UIPickFileClass::FileChosen( str ¤tDirectory, str &partialName, str &fullname ) +void LODSpawnerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) { - // FIXME: stub -} + str newName; -void PickFile( const char *name, Listener *obj, Event& event ) -{ - // FIXME: stub + newName = "lod_spawn " + fullname + "\n"; + // insert the command + Cbuf_AddText(newName); + + CloseWindow(); } diff --git a/code/client/cl_uimaprunner.h b/code/client/cl_uimaprunner.h index 7b03f30d..21d8a708 100644 --- a/code/client/cl_uimaprunner.h +++ b/code/client/cl_uimaprunner.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,40 +20,44 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIMAPRUNNER_H__ -#define __CL_UIMAPRUNNER_H__ +#pragma once -class MapRunnerClass : public FilePickerClass { +class MapRunnerClass : public FilePickerClass +{ public: - CLASS_PROTOTYPE( MapRunnerClass ); + CLASS_PROTOTYPE(MapRunnerClass); - void FileChosen( str ¤tDirectory, str &partialName, str &fullname ) override; + void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override; }; -class ViewSpawnerClass : public FilePickerClass { +class ViewSpawnerClass : public FilePickerClass +{ public: - CLASS_PROTOTYPE( ViewSpawnerClass ); + CLASS_PROTOTYPE(ViewSpawnerClass); - void FileChosen( str ¤tDirectory, str &partialName, str &fullname ) override; + void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override; }; -class LODSpawnerClass : public FilePickerClass { +class LODSpawnerClass : public FilePickerClass +{ public: - CLASS_PROTOTYPE( LODSpawnerClass ); + CLASS_PROTOTYPE(LODSpawnerClass); - void FileChosen( str ¤tDirectory, str &partialName, str &fullname ) override; + void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override; }; -class UIPickFileClass : public FilePickerClass { +class UIPickFileClass : public FilePickerClass +{ public: - Listener *retobj; - Event *retevent; + Listener *retobj; + Event *retevent; - CLASS_PROTOTYPE( UIPickFileClass ); + CLASS_PROTOTYPE(UIPickFileClass); - void FileChosen( str ¤tDirectory, str &partialName, str &fullname ) override; + UIPickFileClass(); + ~UIPickFileClass(); + + void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override; }; -void PickFile( const char *name, Listener *obj, Event& event ); - -#endif /* __CL_UIMAPRUNNER_H__ */ +void PickFile(const char *name, Listener *obj, Event& event); diff --git a/code/client/cl_uiminicon.cpp b/code/client/cl_uiminicon.cpp index dcfbce1a..c1c8e6db 100644 --- a/code/client/cl_uiminicon.cpp +++ b/code/client/cl_uiminicon.cpp @@ -22,68 +22,179 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" -CLASS_DECLARATION( UIWidget, FakkMiniconsole, NULL ) -{ - { NULL, NULL } +Event EV_Minicon_Goin("_minicon_goin", EV_DEFAULT, NULL, NULL, "Event to make the miniconsole disappear"); + +CLASS_DECLARATION(UIWidget, FakkMiniconsole, NULL) { + {&W_SizeChanged, &FakkMiniconsole::OnSizeChanged}, + {&EV_Minicon_Goin, &FakkMiniconsole::MoveInEvent }, + {NULL, NULL } }; FakkMiniconsole::FakkMiniconsole() { - // FIXME: stub + m_maxlines = 0; + m_reallyshown = true; + m_boxstate = boxstate_t::box_in; + m_boxtime = uid.time; + m_movespeed = 500; } - -void FakkMiniconsole::VerifyBoxOut( void ) +void FakkMiniconsole::setShowState(void) { - // FIXME: stub + if (m_reallyshown) { + setShow(m_boxstate != boxstate_t::box_in); + } else { + setShow(false); + } } -void FakkMiniconsole::ChangeBoxState( boxstate_t state ) +void FakkMiniconsole::setRealShow(bool b) { - // FIXME: stub + m_reallyshown = b; + setShowState(); } -void FakkMiniconsole::HandleBoxMoving( void ) +void FakkMiniconsole::VerifyBoxOut(void) { - // FIXME: stub + PostMoveinEvent(); + + if (m_boxstate && m_boxstate != boxstate_t::box_out) { + ChangeBoxState(box_moving_out); + } } -void FakkMiniconsole::PostMoveinEvent( void ) +void FakkMiniconsole::Print(const char *text) { - // FIXME: stub + str *lastline; + const char *p; + + if (!m_lines.NumObjects()) { + m_lines.AddObject({}); + } + + lastline = &m_lines.ObjectAt(m_lines.NumObjects()); + + if (*text) { + for (p = text; *p; p++) { + if (*p != '\n') { + *lastline += *p; + } else { + m_lines.AddObject({}); + lastline = &m_lines.ObjectAt(m_lines.NumObjects()); + } + } + } + + if (lastline && lastline->length() > 128) { + Print("\n"); + } + + if (m_maxlines < 0) { + m_maxlines = 1; + } + + while (m_lines.NumObjects() > this->m_maxlines) { + m_lines.RemoveObjectAt(1); + } + + VerifyBoxOut(); } -void FakkMiniconsole::setShowState( void ) +void FakkMiniconsole::PostMoveinEvent(void) { - // FIXME: stub + if (m_boxstate != boxstate_t::box_out) { + return; + } + + CancelEventsOfType(EV_Minicon_Goin); + PostEvent(new Event(EV_Minicon_Goin), 5.f); } -void FakkMiniconsole::OnSizeChanged( Event *ev ) +void FakkMiniconsole::OnSizeChanged(Event *ev) { - // FIXME: stub + m_maxlines = m_frame.size.height / m_font->getHeight(getHighResScale()); } -void FakkMiniconsole::Print( const char *text ) +void FakkMiniconsole::MoveInEvent(Event *ev) { - // FIXME: stub + ChangeBoxState(boxstate_t::box_moving_in); } -void FakkMiniconsole::Create( const UISize2D& size, const UColor& fore, const UColor& back, float alpha ) +void FakkMiniconsole::HandleBoxMoving(void) { - // FIXME: stub + int delta; + UIRect2D newRect; + + if (m_boxstate == boxstate_t::box_out || m_boxstate == boxstate_t::box_in) { + return; + } + + delta = m_movespeed * (uid.time - m_boxtime) / 1000; + m_boxtime = 1000 * delta / m_movespeed + m_boxtime; + + switch (m_boxstate) { + case boxstate_t::box_moving_in: + newRect = UIRect2D(delta + m_frame.pos.x, m_frame.pos.y, m_frame.size.width, m_frame.size.height); + if (newRect.pos.x >= uid.vidWidth) { + newRect.pos.x = uid.vidWidth; + ChangeBoxState(boxstate_t::box_in); + } + break; + case boxstate_t::box_moving_out: + newRect = UIRect2D(-delta + m_frame.pos.x, m_frame.pos.y, m_frame.size.width, m_frame.size.height); + if (newRect.pos.x <= uid.vidWidth - newRect.size.width) { + newRect.pos.x = uid.vidWidth - newRect.size.width; + ChangeBoxState(boxstate_t::box_out); + } + break; + default: + ChangeBoxState(boxstate_t::box_in); + break; + } + + setFrame(newRect); } -void FakkMiniconsole::MoveInEvent( Event *ev ) +void FakkMiniconsole::Draw(void) { - // FIXME: stub + float aty; + int i; + + HandleBoxMoving(); + + m_font->setColor(m_foreground_color); + aty = m_frame.size.height - m_font->getHeight(getHighResScale()); + for (i = m_lines.NumObjects(); i > 0; i--) { + if (-m_font->getHeight(getHighResScale()) >= aty) { + break; + } + + m_font->Print(0, aty / getHighResScale()[1], m_lines.ObjectAt(i), -1, getHighResScale()); + aty -= m_font->getHeight(getHighResScale()); + } } -void FakkMiniconsole::Draw( void ) +void FakkMiniconsole::Create(const UISize2D& size, const UColor& fore, const UColor& back, float alpha) { - // FIXME: stub + InitFrame(NULL, uid.vidWidth, 0, size.width, size.height, 0); + + setBackgroundColor(back, true); + setForegroundColor(fore); + setBackgroundAlpha(alpha); + Connect(this, W_SizeChanged, W_SizeChanged); + OnSizeChanged(NULL); + + m_movespeed = size.width * 3; + + setShowState(); } -void FakkMiniconsole::setRealShow( bool b ) +void FakkMiniconsole::ChangeBoxState(boxstate_t state) { - // FIXME: stub + m_boxstate = state; + m_boxtime = uid.time; + setShowState(); + if (state == boxstate_t::box_out) { + PostMoveinEvent(); + } } diff --git a/code/client/cl_uiminicon.h b/code/client/cl_uiminicon.h index 791bf23d..3f49773d 100644 --- a/code/client/cl_uiminicon.h +++ b/code/client/cl_uiminicon.h @@ -20,38 +20,36 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIMINICON_H__ -#define __CL_UIMINICON_H__ +#pragma once -class FakkMiniconsole : public UIWidget { +class FakkMiniconsole : public UIWidget +{ protected: - Container m_lines; - int m_maxlines; - bool m_reallyshown; - bool m_boxmovingout; - boxstate_t m_boxstate; - int m_boxtime; - int m_movespeed; + Container m_lines; + int m_maxlines; + bool m_reallyshown; + bool m_boxmovingout; + boxstate_t m_boxstate; + int m_boxtime; + int m_movespeed; public: - CLASS_PROTOTYPE( FakkMiniconsole ); + CLASS_PROTOTYPE(FakkMiniconsole); protected: - void VerifyBoxOut( void ); - void ChangeBoxState( boxstate_t state ); - void HandleBoxMoving( void ); - void PostMoveinEvent( void ); - void setShowState( void ); + void VerifyBoxOut(void); + void ChangeBoxState(boxstate_t state); + void HandleBoxMoving(void); + void PostMoveinEvent(void); + void setShowState(void); public: - FakkMiniconsole(); + FakkMiniconsole(); - void OnSizeChanged( Event *ev ); - void Print( const char *text ); - void Create( const UISize2D& size, const UColor& fore, const UColor& back, float alpha ); - void MoveInEvent( Event *ev ); - void Draw( void ) override; - void setRealShow( bool b ); + void OnSizeChanged(Event *ev); + void Print(const char *text); + void Create(const UISize2D& size, const UColor& fore, const UColor& back, float alpha); + void MoveInEvent(Event *ev); + void Draw(void) override; + void setRealShow(bool b); }; - -#endif diff --git a/code/client/cl_uimpmappicker.cpp b/code/client/cl_uimpmappicker.cpp index 2db4ac26..8146459f 100644 --- a/code/client/cl_uimpmappicker.cpp +++ b/code/client/cl_uimpmappicker.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,73 +21,339 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/localization.h" -CLASS_DECLARATION( USignal, MpMapPickerClass, NULL ) +class MpMapPickerItem : public UIListCtrlItem { - { NULL, NULL } + str m_string; + // Added in 2.0 + str m_directory; + +public: + MpMapPickerItem(const str& string, const str& directory); + + int getListItemValue(int which) const override; + griditemtype_t getListItemType(int which) const override; + str getListItemString(int which) const override; + void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; + qboolean IsHeaderEntry() const override; +}; + +CLASS_DECLARATION(USignal, MpMapPickerClass, NULL) { + {&EV_UIListBase_ItemSelected, &MpMapPickerClass::FileSelected }, + {&EV_UIListBase_ItemDoubleClicked, &MpMapPickerClass::FileChosen }, + {&W_Deactivated, &MpMapPickerClass::OnDeactivated}, + {NULL, NULL } }; MpMapPickerClass::MpMapPickerClass() { - // FIXME: stub + window = new UIFloatingWindow(); + window->Create( + NULL, + UIRect2D((uid.vidWidth - 300) / 2, (uid.vidHeight - 200) / 2, 300, 200), + "Select a Map", + UColor(0.15f, 0.195f, 0.278f), + UHudColor + ); + window->setFont("facfont-20"); + window->PassEventToWidget("closebutton", new Event(EV_Widget_Disable)); + window->PassEventToWidget("minimizebutton", new Event(EV_Widget_Disable)); + window->Connect(this, W_Deactivated, W_Deactivated); + + listbox = new UIListCtrl(); + listbox->InitFrame(window->getChildSpace(), window->getChildSpace()->getClientFrame(), 0); + listbox->SetDrawHeader(false); + listbox->setFont("facfont-20"); + listbox->FrameInitialized(); + listbox->AddColumn(Sys_LV_CL_ConvertString("Select a Map"), 0, 400, false, false); + + listbox->Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); + listbox->Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); + listbox->AllowActivate(true); + + // Added in 2.0 + // Don't localize elements + listbox->SetDontLocalize(); } MpMapPickerClass::~MpMapPickerClass() { - // FIXME: stub + if (listbox) { + delete listbox; + listbox = NULL; + } + + if (window) { + delete window; + window = NULL; + } } -void MpMapPickerClass::SetupFiles( void ) +void MpMapPickerClass::Setup(const char *root_directory, const char *current_directory, const char *game_type) { - // FIXME: stub + Initialize(root_directory, current_directory, game_type); } -void MpMapPickerClass::GotoParentDirectory( void ) +void MpMapPickerClass::Initialize(const char *root_directory, const char *current_directory, const char *game_type) { - // FIXME: stub + rootDirectory = root_directory; + if (rootDirectory.length() > 1 && rootDirectory[rootDirectory.length() - 1] != '/') { + rootDirectory += "/"; + } + + currentDirectory = current_directory; + if (currentDirectory.length() > 1 && currentDirectory[currentDirectory.length() - 1] != '/') { + currentDirectory += "/"; + } + + if (game_type) { + gameType = game_type; + } + + SetupFiles(); } -void MpMapPickerClass::GotoSubDirectory( str subdir ) +void MpMapPickerClass::GotoParentDirectory(void) { - // FIXME: stub + uintptr_t i; + + if (currentDirectory == rootDirectory) { + return; + } + + for (i = currentDirectory.length() - 2; i > 0; i--) { + if (currentDirectory[i] == '/') { + break; + } + } + + if (currentDirectory[i] == '/') { + i++; + } + + currentDirectory = str(currentDirectory, 0, i); + + // refresh files + SetupFiles(); } -void MpMapPickerClass::Initialize( const char *root_directory, const char *current_directory ) +void MpMapPickerClass::GotoSubDirectory(str subdir) { - // FIXME: stub + currentDirectory += subdir + "/"; + + // refresh files + SetupFiles(); } -void MpMapPickerClass::CloseWindow( void ) +void MpMapPickerClass::SetupFiles(void) { - // FIXME: stub + char **filenames; + int numfiles; + int i; + char mapname[128]; + bool bTugOfWar = false, bObjective = false, bLiberation = false; + + listbox->DeleteAllItems(); + + if (gameType == "tow") { + bTugOfWar = true; + } else if (gameType == "obj") { + bObjective = true; + } else if (gameType == "lib") { + bLiberation = true; + } else { + // retrieve directories + filenames = FS_ListFiles(rootDirectory, ".bsp", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + + strcpy(mapname, filename); + mapname[strlen(mapname) - 4] = 0; + + if (COM_IsMapValid(mapname)) { + listbox->AddItem(new MpMapPickerItem(mapname, rootDirectory)); + } + } + + FS_FreeFileList(filenames); + } + + if (com_target_game->integer > target_game_e::TG_MOH) { + if (currentDirectory.length()) { + if (currentDirectory == "maps/-/") { + SetupSecondaryFiles(currentDirectory, bTugOfWar, bObjective, bLiberation); + } else { + SetupSecondaryFiles("maps/obj/", bTugOfWar, bObjective, bLiberation); + SetupSecondaryFiles("maps/lib/", bTugOfWar, bObjective, bLiberation); + } + } + } + + listbox->SortByColumn(0); } -void MpMapPickerClass::FileSelected( Event *ev ) +void MpMapPickerClass::SetupSecondaryFiles(const char *path, bool bTugOfWar, bool bObjective, bool bLiberation) { - // FIXME: stub + char **filenames; + int numfiles; + int i; + char mapname[128]; + char string[1024]; + + filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + const char *filename = filenames[i]; + const char *token; + + strcpy(mapname, filename); + mapname[strlen(mapname) - 4] = 0; + + if (!COM_IsMapValid(mapname)) { + continue; + } + + if (bTugOfWar || bObjective || bLiberation) { + bool bHasMP = false, bHasTOW = false, bHasLib = false; + + strcpy(string, mapname); + + for (token = strtok(string, "_"); token; token = strtok(NULL, "_")) { + if (bObjective) { + if (!Q_stricmp(token, "obj")) { + listbox->AddItem(new MpMapPickerItem(mapname, path)); + } else if (!Q_stricmp(token, "ship")) { + listbox->AddItem(new MpMapPickerItem(mapname, path)); + } + } + + if (bTugOfWar) { + if (!Q_stricmp(token, "MP")) { + bHasMP = true; + } + if (!Q_stricmp(token, "TOW")) { + bHasTOW = true; + } + + if (bHasMP && bHasTOW) { + listbox->AddItem(new MpMapPickerItem(mapname, path)); + } + } + + if (bLiberation) { + if (!Q_stricmp(token, "MP")) { + bHasMP = true; + } + if (!Q_stricmp(token, "LIB")) { + bHasLib = true; + } + + if (bHasMP && bHasLib) { + listbox->AddItem(new MpMapPickerItem(mapname, path)); + } + } + } + } else { + if (!Q_stricmp(mapname, "obj_team2") || !Q_stricmp(mapname, "obj_team4")) { + continue; + } + + listbox->AddItem(new MpMapPickerItem(mapname, path)); + } + } + + FS_FreeFileList(filenames); } -void MpMapPickerClass::FileSelected( str& currentDirectory, str& partialName, str& fullname ) +void MpMapPickerClass::FileSelected(const str& currentDirectory, const str& partialName, const str& fullname) { - // FIXME: stub + FileChosen(currentDirectory, partialName, fullname); } -void MpMapPickerClass::FileChosen( Event *ev ) +void MpMapPickerClass::FileSelected(Event *ev) { - // FIXME: stub + if (!listbox->getCurrentItem()) { + return; + } + + uii.Snd_PlaySound("sound/menu/apply.wav"); + + UIListCtrlItem *item = listbox->GetItem(listbox->getCurrentItem()); + str name = item->getListItemString(0); + str directory = item->getListItemString(1); + + FileSelected(directory, name, directory + name); } -void MpMapPickerClass::FileChosen( str& currentDirectory, str& partialName, str& fullname ) +void MpMapPickerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) { - // FIXME: stub + const char *pszFilename; + str sCommand; + + pszFilename = fullname.c_str(); + sCommand = va("ui_dmmap %s\n", pszFilename + 5); + + Cbuf_AddText(sCommand); + CloseWindow(); } -void MpMapPickerClass::OnDeactivated( Event *ev ) +void MpMapPickerClass::FileChosen(Event *ev) { - // FIXME: stub + if (!listbox->getCurrentItem()) { + return; + } + + uii.Snd_PlaySound("sound/menu/apply.wav"); + + UIListCtrlItem *item = listbox->GetItem(listbox->getCurrentItem()); + str name = item->getListItemString(0); + str directory = item->getListItemString(1); + + FileSelected(directory, name, directory + name); } -void MpMapPickerClass::Setup( const char *root_directory, const char *current_directory ) +void MpMapPickerClass::CloseWindow(void) { - // FIXME: stub + PostEvent(EV_Remove, 0); +} + +void MpMapPickerClass::OnDeactivated(Event *ev) +{ + CloseWindow(); +} + +MpMapPickerItem::MpMapPickerItem(const str& string, const str& directory) +{ + m_string = string; + m_directory = directory; +} + +int MpMapPickerItem::getListItemValue(int which) const +{ + return atoi(m_string); +} + +griditemtype_t MpMapPickerItem::getListItemType(int which) const +{ + return griditemtype_t::TYPE_STRING; +} + +str MpMapPickerItem::getListItemString(int which) const +{ + switch (which) { + default: + case 0: + return m_string; + case 1: + return m_directory; + } +} + +void MpMapPickerItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} + +qboolean MpMapPickerItem::IsHeaderEntry() const +{ + return qfalse; } diff --git a/code/client/cl_uimpmappicker.h b/code/client/cl_uimpmappicker.h index cfc85e64..8c6ed0c1 100644 --- a/code/client/cl_uimpmappicker.h +++ b/code/client/cl_uimpmappicker.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,39 +20,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIMPMAPPICKER_H__ -#define __CL_UIMPMAPPICKER_H__ +#pragma once class UIFloatingWindow; -class MpMapPickerClass : public USignal { - UIFloatingWindow *window; - UIListCtrl *listbox; - str currentDirectory; - str rootDirectory; +class MpMapPickerClass : public USignal +{ + UIFloatingWindow *window; + UIListCtrl *listbox; + str currentDirectory; + str rootDirectory; + str gameType; public: - CLASS_PROTOTYPE( MpMapPickerClass ); + CLASS_PROTOTYPE(MpMapPickerClass); private: - void SetupFiles( void ); - void GotoParentDirectory( void ); - void GotoSubDirectory( str subdir ); - void Initialize( const char *root_directory, const char *current_directory ); + void SetupFiles(void); + void SetupSecondaryFiles(const char *path, bool bTugOfWar, bool bObjective, bool bLiberation); + void GotoParentDirectory(void); + void GotoSubDirectory(str subdir); + void Initialize(const char *root_directory, const char *current_directory, const char *game_type); protected: - void CloseWindow( void ); - void FileSelected( Event *ev ); - virtual void FileSelected( str& currentDirectory, str& partialName, str& fullname ); - void FileChosen( Event *ev ); - virtual void FileChosen( str& currentDirectory, str& partialName, str& fullname ); - void OnDeactivated( Event *ev ); + void CloseWindow(void); + void FileSelected(Event *ev); + virtual void FileSelected(const str& currentDirectory, const str& partialName, const str& fullname); + void FileChosen(Event *ev); + virtual void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname); + void OnDeactivated(Event *ev); public: - MpMapPickerClass(); - ~MpMapPickerClass(); + MpMapPickerClass(); + ~MpMapPickerClass(); - void Setup( const char *root_directory, const char *current_directory ); + // game_type was added in 2.0 + void Setup(const char *root_directory, const char *current_directory, const char *game_type = NULL); }; - -#endif /* __CL_UIMPMAPPICKER_H__ */ diff --git a/code/client/cl_uiplayermodelpicker.cpp b/code/client/cl_uiplayermodelpicker.cpp index 6aa7b336..ca89a42d 100644 --- a/code/client/cl_uiplayermodelpicker.cpp +++ b/code/client/cl_uiplayermodelpicker.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,62 +22,361 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" -CLASS_DECLARATION( USignal, PlayerModelPickerClass, NULL ) +class PMPickerItem : public UIListCtrlItem { - { NULL, NULL } + str m_string; + +public: + PMPickerItem(const str& string); + + int getListItemValue(int which) const override; + griditemtype_t getListItemType(int which) const override; + str getListItemString(int which) const override; + void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; + qboolean IsHeaderEntry() const override; +}; + +typedef struct { + const char *fileName; + const char *displayName; +} PMPickerModel_t; + +static const PMPickerModel_t pickerModels[] = { + // 2.0 skins + {"allied_101st_captain", "US - 101st Airborne Captain" }, + {"allied_101st_infantry", "US - 101st Airborne Private 1" }, + {"allied_101st_scout", "US - 101st Airborne Private 2" }, + {"allied_501st_pir_scout", "US - 501st Paratrooper 1" }, + {"allied_501st_pir_soldier", "US - 501st Paratrooper 2" }, + // 1.0 skins + {"allied_airborne", "US - 501st Paratrooper 3" }, + // Readded in OPM (was removed in 2.0) + {"allied_manon", "US - Manon" }, + // 2.0 skins + {"allied_british_6th_airborne_captain", "UK - 6th Airborne Captain" }, + {"allied_british_6th_airborne_paratrooper", "UK - 6th Airborne Paratrooper" }, + // 1.0 skins + {"allied_pilot", "US - Army Pilot" }, + // 2.0 skins + {"allied_russian_corporal", "RA - Corporal" }, + {"allied_russian_crazy_boris", "RA - Crazy Boris" }, + {"allied_russian_recon_scout", "RA - Junior Lieutenant" }, + {"allied_russian_recon_soldier", "RA - Black Sea Petty Officer" }, + // 1.0 skins + {"allied_sas", "UK - SAS Officer" }, + {"american_army", "US - Soldier" }, + {"american_ranger", "US - Ranger" }, + // 1.0 skins + {"german_afrika_officer", "DE - Afrika Officer" }, + {"german_afrika_private", "DE - Afrika Private" }, + // 2.0 skins + {"german_ardennes_artillery_commander", "DE - Artillery Commander" }, + {"german_dday_colonel", "DE - Normandy Colonel" }, + // 1.0 skins + {"german_elite_officer", "DE - Elite Officer" }, + {"german_elite_sentry", "DE - Elite Sentry" }, + {"german_kradshutzen", "DE - Kradshutzen" }, + {"german_panzer_grenadier", "DE - Panzer Grenadier" }, + {"german_panzer_obershutze", "DE - Panzer Obershutze" }, + {"german_panzer_shutze", "DE - Panzer Shutze" }, + {"german_panzer_tankcommander", "DE - Panzer Tank Commander" }, + {"german_scientist", "DE - German Scientist" }, + // Those skins were superseded by german_waffenss + {"german_waffen_officer", "DE - Waffen Officer" }, + {"german_waffen_shutze", "DE - Waffen Shutze" }, + // 1.0 skins + {"german_waffenss_officer", "DE - Waffen Officer" }, + {"german_waffenss_shutze", "DE - Waffen Shutze" }, + {"german_wehrmacht_officer", "DE - Wehrmacht Officer" }, + {"german_wehrmacht_soldier", "DE - Wehrmacht Soldier" }, + {"german_winter_1", "DE - Winter Infantry 1" }, + {"german_winter_2", "DE - Winter Infantry 2" }, + {"german_worker", "DE - German Mechanic" }, + // 2.11 skins + {"allied_british_tank_corporal", "UK - 6th Royal Tank Regiment" }, + {"allied_russian_seaman", "RA - Red Navy Seaman" }, + {"german_Panzer_Corporal", "DE - 1st Panzer Regiment" }, + {"allied_technician", "US - Air Force Technician" }, + {"german_stukageschwader", "DE - Stukageschwader" }, + // 2.30 skins + {"It_AX_Ital_Vol", "IT - 10th Army XXI Corps" }, + {"SC_AX_Ital_Inf", "IT - 6th Army 202nd Coastal Div"}, + {"SC_AX_Ital_Inf2", "IT - 114th Inf Regiment" }, + {"SC_AX_ITAL_PARA", "IT - Paracadutista Militare" }, + // 2.40 skins + {"allied_Wheathers", "US - General Wheathers" }, + {"allied_US_Tank", "US - II Corps Tank Commander" }, + {"allied_US_Mask", "US - II Corps Infantry" }, + {"allied_british_Cmd", "UK - 10th Corps" }, + {"allied_british_Tank", "UK - 8th Army" }, + {NULL, NULL } +}; + +const char *PM_FilenameToDisplayname(const char *fileName) +{ + int i; + + for (i = 0; pickerModels[i].fileName; i++) { + const PMPickerModel_t& model = pickerModels[i]; + + if (!Q_stricmp(model.fileName, fileName)) { + return model.displayName; + } + } + + return fileName; +} + +const char *PM_DisplaynameToFilename(const char *displayName) +{ + int i; + + for (i = 0; pickerModels[i].fileName; i++) { + const PMPickerModel_t& model = pickerModels[i]; + + if (!Q_stricmp(model.displayName, displayName)) { + return model.fileName; + } + } + + return displayName; +} + +CLASS_DECLARATION(USignal, PlayerModelPickerClass, NULL) { + {&EV_UIListBase_ItemSelected, &PlayerModelPickerClass::FileSelected }, + {&EV_UIListBase_ItemDoubleClicked, &PlayerModelPickerClass::FileChosen }, + {&UIFloatingWindow::W_ClosePressed, &PlayerModelPickerClass::OnDeactivated}, + {&W_Deactivated, &PlayerModelPickerClass::OnDeactivated}, + {NULL, NULL } }; PlayerModelPickerClass::PlayerModelPickerClass() { - // FIXME: stub + window = new UIFloatingWindow(); + window->Create( + NULL, + UIRect2D((uid.vidWidth - 400) / 2, (uid.vidHeight - 300) / 2, 400, 300), + "Player Model Select...", + UColor(0.15f, 0.195f, 0.278f), + UHudColor + ); + window->setFont("facfont-20"); + window->PassEventToWidget("closebutton", new Event(EV_Widget_Disable)); + window->PassEventToWidget("minimizebutton", new Event(EV_Widget_Disable)); + window->Connect(this, W_Deactivated, W_Deactivated); + + listbox = new UIListCtrl(); + listbox->InitFrame(window->getChildSpace(), window->getChildSpace()->getClientFrame(), 0); + listbox->SetDrawHeader(false); + listbox->setFont("facfont-20"); + listbox->FrameInitialized(); + listbox->AddColumn("Player Model", 0, 400, false, false); + + listbox->Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); + listbox->Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); + listbox->AllowActivate(true); + + // Added in 2.0 + // Don't localize elements + listbox->SetDontLocalize(); + + m_bGermanModels = false; } PlayerModelPickerClass::~PlayerModelPickerClass() { - // FIXME: stub + if (listbox) { + delete listbox; + listbox = NULL; + } + + if (window) { + delete window; + window = NULL; + } } -void PlayerModelPickerClass::SetupFiles( void ) +void PlayerModelPickerClass::Setup(const char *root_directory, const char *current_directory, qboolean bGermanModels) { - // FIXME: stub + Initialize(root_directory, current_directory, bGermanModels); } -void PlayerModelPickerClass::Initialize( const char *root_directory, const char *current_directory, qboolean bGermanModels ) +void PlayerModelPickerClass::Initialize( + const char *root_directory, const char *current_directory, qboolean bGermanModels +) { - // FIXME: stub + rootDirectory = root_directory; + m_bGermanModels = bGermanModels; + if (rootDirectory.length() > 1 && rootDirectory[rootDirectory.length() - 1] != '/') { + rootDirectory += "/"; + } + + currentDirectory = current_directory; + if (currentDirectory.length() > 1 && currentDirectory[currentDirectory.length() - 1] != '/') { + currentDirectory += "/"; + } + + SetupFiles(); } -void PlayerModelPickerClass::CloseWindow( void ) +void PlayerModelPickerClass::SetupFiles(void) { - // FIXME: stub + str mappath; + char work[128]; + char **filenames; + const char *displayName; + int numfiles; + int i; + int iLen; + qboolean bIsGerman; + + // cleanup + listbox->DeleteAllItems(); + + if (m_bGermanModels) { + window->setTitle("Select Your Axis Player Model"); + } else { + window->setTitle("Select Your Allied Player Model"); + } + + filenames = FS_ListFiles(currentDirectory, ".tik", qfalse, &numfiles); + + for (i = 0; i < numfiles; i++) { + Q_strncpyz(work, filenames[i], sizeof(work)); + + if (strstr(work, "_fps")) { + // ignore view models + continue; + } + + if (work[0] == '_') { + // ignore hidden models + continue; + } + + // allied_manon readded in OPM + //if (!Q_stricmpn(work, "allied_manon")) { + // continue; + //} + + bIsGerman = !Q_stricmpn(work, "german", 6u) || !Q_stricmpn(work, "axis", 4u) || !Q_stricmpn(work, "it", 2u) + || !Q_stricmpn(work, "sc", 2u); + + if (m_bGermanModels != bIsGerman) { + continue; + } + + // strip the extension + work[strlen(work) - 4] = 0; + displayName = PM_FilenameToDisplayname(work); + + listbox->AddItem(new PMPickerItem(displayName)); + } + + FS_FreeFileList(filenames); + + listbox->SortByColumn(0); } -void PlayerModelPickerClass::FileSelected( Event *ev ) +void PlayerModelPickerClass::FileSelected( + const str& name, const str& currentDirectory, const str& partialName, const str& fullname +) { - // FIXME: stub + FileChosen(name, currentDirectory, partialName, fullname); } -void PlayerModelPickerClass::FileSelected( str& currentDirectory, str& partialName, str& fullname ) +void PlayerModelPickerClass::FileSelected(Event *ev) { - // FIXME: stub + str name; + char donotshowssindeorfr[64]; + str fullname; + + name = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0); + fullname = PM_DisplaynameToFilename(name); + + if (!Q_stricmpn(fullname, "german_waffen_", 14)) { + Q_strncpyz(donotshowssindeorfr, "german_waffenss_", sizeof(donotshowssindeorfr)); + Q_strcat(donotshowssindeorfr, sizeof(donotshowssindeorfr), fullname.c_str() + 14); + } else { + Q_strncpyz(donotshowssindeorfr, fullname, sizeof(donotshowssindeorfr)); + } + + FileSelected(name, currentDirectory, fullname, currentDirectory + donotshowssindeorfr); } -void PlayerModelPickerClass::FileChosen( Event *ev ) +void PlayerModelPickerClass::FileChosen( + const str& name, const str& currentDirectory, const str& partialName, const str& fullname +) { - // FIXME: stub + str sCommand; + + if (m_bGermanModels) { + sCommand += "ui_dm_playergermanmodel \"" + name; + sCommand += "\" ; ui_dm_playergermanmodel_set " + partialName; + sCommand += " ; ui_disp_playergermanmodel " + fullname + ".tik"; + } else { + sCommand += "ui_dm_playermodel \"" + name; + sCommand += "\" ; ui_dm_playermodel_set " + partialName; + sCommand += " ; ui_disp_playermodel " + fullname + ".tik"; + } + sCommand += "\n"; + + Cbuf_AddText(sCommand); + CloseWindow(); } -void PlayerModelPickerClass::FileChosen( str& currentDirectory, str& partialName, str& fullname ) +void PlayerModelPickerClass::FileChosen(Event *ev) { - // FIXME: stub + str name; + char donotshowssindeorfr[64]; + str fullname; + + name = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0); + fullname = PM_DisplaynameToFilename(name); + + if (!Q_stricmpn(fullname, "german_waffen_", 14)) { + Q_strncpyz(donotshowssindeorfr, "german_waffen_", sizeof(donotshowssindeorfr)); + Q_strcat(donotshowssindeorfr, sizeof(donotshowssindeorfr), fullname.c_str() + 14); + } else { + Q_strncpyz(donotshowssindeorfr, fullname, sizeof(donotshowssindeorfr)); + } + + FileChosen(name, currentDirectory, fullname, currentDirectory + donotshowssindeorfr); } -void PlayerModelPickerClass::OnDeactivated( Event *ev ) +void PlayerModelPickerClass::CloseWindow(void) { - // FIXME: stub + PostEvent(EV_Remove, 0); } -void PlayerModelPickerClass::Setup( const char *root_directory, const char *current_directory, qboolean bGermanModels ) +void PlayerModelPickerClass::OnDeactivated(Event *ev) { - // FIXME: stub + CloseWindow(); +} + +PMPickerItem::PMPickerItem(const str& string) +{ + m_string = string; +} + +int PMPickerItem::getListItemValue(int which) const +{ + return atoi(m_string); +} + +griditemtype_t PMPickerItem::getListItemType(int which) const +{ + return griditemtype_t::TYPE_STRING; +} + +str PMPickerItem::getListItemString(int which) const +{ + return m_string; +} + +void PMPickerItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} + +qboolean PMPickerItem::IsHeaderEntry() const +{ + return qfalse; } diff --git a/code/client/cl_uiplayermodelpicker.h b/code/client/cl_uiplayermodelpicker.h index d33f53e4..2464b83e 100644 --- a/code/client/cl_uiplayermodelpicker.h +++ b/code/client/cl_uiplayermodelpicker.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,37 +20,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIPLAYERMODELPICKER_H__ -#define __CL_UIPLAYERMODELPICKER_H__ +#pragma once class UIFloatingWindow; -class PlayerModelPickerClass : public USignal { - UIFloatingWindow *window; - UIListCtrl *listbox; - str currentDirectory; - str rootDirectory; - qboolean m_bGermanModels; +class PlayerModelPickerClass : public USignal +{ + UIFloatingWindow *window; + UIListCtrl *listbox; + str currentDirectory; + str rootDirectory; + qboolean m_bGermanModels; + public: - CLASS_PROTOTYPE( PlayerModelPickerClass ); + CLASS_PROTOTYPE(PlayerModelPickerClass); private: - void SetupFiles( void ); - void Initialize( const char *root_directory, const char *current_directory, qboolean bGermanModels ); + void SetupFiles(void); + void Initialize(const char *root_directory, const char *current_directory, qboolean bGermanModels); protected: - void CloseWindow( void ); - void FileSelected( Event *ev ); - virtual void FileSelected( str& currentDirectory, str& partialName, str& fullname ); - void FileChosen( Event *ev ); - virtual void FileChosen( str& currentDirectory, str& partialName, str& fullname ); - void OnDeactivated( Event *ev ); + void CloseWindow(void); + void FileSelected(Event *ev); + // The name parameter was added in 2.0. + virtual void FileSelected(const str& name, const str& currentDirectory, const str& partialName, const str& fullname); + void FileChosen(Event *ev); + // The name parameter was added in 2.0. + virtual void FileChosen(const str& name, const str& currentDirectory, const str& partialName, const str& fullname); + void OnDeactivated(Event *ev); public: - PlayerModelPickerClass(); - ~PlayerModelPickerClass(); + PlayerModelPickerClass(); + ~PlayerModelPickerClass(); - void Setup( const char *root_directory, const char *current_directory, qboolean bGermanModels ); + void Setup(const char *root_directory, const char *current_directory, qboolean bGermanModels); }; -#endif /* __CL_UIPLAYERMODELPICKER_H__ */ +const char* PM_FilenameToDisplayname(const char* fileName); +const char* PM_DisplaynameToFilename(const char* displayName); diff --git a/code/client/cl_uiradar.cpp b/code/client/cl_uiradar.cpp index be2c80ce..654ecc26 100644 --- a/code/client/cl_uiradar.cpp +++ b/code/client/cl_uiradar.cpp @@ -58,7 +58,7 @@ void UIRadar::Draw(void) float inv; float iconSize; int blinkTime, speakTime; - float origin[2], axis[2]; + vec2_t origin, axis; float halfScale; int i; @@ -105,17 +105,17 @@ void UIRadar::Draw(void) halfScale = iconSize * 0.5f; for (i = 0; i < MAX_CLIENTS; i++) { - float delta[2]; - float newOrg[2]; - float screenOrg[2]; - float length; + vec2_t delta; + vec2_t newOrg; + vec2_t screenOrg; + float length; radar = &g_radarClients[i]; if (i == g_radarClientNum) { continue; } - if (!g_radarClients[i].time) { + if (!radar->time) { continue; } @@ -128,10 +128,13 @@ void UIRadar::Draw(void) // make the icon blink if (delta >= 0 && delta < speakTime && ((delta / blinkTime) % 2) == 0) { continue; + } + + if (delta < 0 || delta >= speakTime) { + radar->lastSpeakTime = 0; } } - radar->lastSpeakTime = 0; delta[0] = radar->origin[0] - origin[0]; delta[1] = radar->origin[1] - origin[1]; newOrg[0] = -(delta[0] * axis[0] + delta[1] * axis[1]) * inv; @@ -140,12 +143,12 @@ void UIRadar::Draw(void) if (length > 1) { - newOrg[0] = -(delta[0] * axis[0] + delta[1] * axis[1]) * inv * (1.f / length); - newOrg[1] = (delta[0] * axis[1] + delta[1] * -axis[0]) * inv * (1.f / length); + newOrg[0] *= 1.f / length; + newOrg[1] *= 1.f / length; } - screenOrg[0] = -((halfScale * (1.141f * newOrg[1] + m_vVirtualScale[0])) - ((1.f + newOrg[1]) * 0.5f * m_frame.size.width)); - screenOrg[1] = -((halfScale * (1.141f * newOrg[0] + m_vVirtualScale[1])) - ((1.f + newOrg[0]) * 0.5f * m_frame.size.height)); + screenOrg[0] = -((halfScale * (1.414f * newOrg[1] + m_vVirtualScale[0])) - ((1.f + newOrg[1]) * 0.5f * m_frame.size.width)); + screenOrg[1] = -((halfScale * (1.414f * newOrg[0] + m_vVirtualScale[1])) - ((1.f + newOrg[0]) * 0.5f * m_frame.size.height)); uii.Rend_DrawPicStretched2( screenOrg[0], diff --git a/code/client/cl_uiserverlist.cpp b/code/client/cl_uiserverlist.cpp index c227d8f6..28e87c9b 100644 --- a/code/client/cl_uiserverlist.cpp +++ b/code/client/cl_uiserverlist.cpp @@ -25,7 +25,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../gamespy/sv_gamespy.h" #include "../gamespy/common/gsPlatformSocket.h" -Event EV_FAKKServerList_Connect( +Event EV_FAKKServerList_Connect +( "connect", EV_DEFAULT, NULL, @@ -33,7 +34,8 @@ Event EV_FAKKServerList_Connect( "Connect to the specified server" ); -Event EV_FAKKServerList_RefreshServerList( +Event EV_FAKKServerList_RefreshServerList +( "refreshserverlist", EV_DEFAULT, NULL, @@ -41,7 +43,8 @@ Event EV_FAKKServerList_RefreshServerList( "Refresh the serverlist" ); -Event EV_FAKKServerList_RefreshLANServerList( +Event EV_FAKKServerList_RefreshLANServerList +( "refreshlanserverlist", EV_DEFAULT, NULL, @@ -49,7 +52,8 @@ Event EV_FAKKServerList_RefreshLANServerList( "Refresh the LAN serverlist" ); -Event EV_FAKKServerList_CancelRefresh( +Event EV_FAKKServerList_CancelRefresh +( "cancelrefresh", EV_DEFAULT, NULL, @@ -57,7 +61,8 @@ Event EV_FAKKServerList_CancelRefresh( "Cancel serverlist Refresh" ); -Event EV_FAKKServerList_LANListing( +Event EV_FAKKServerList_LANListing +( "lanlisting", EV_DEFAULT, NULL, @@ -65,7 +70,8 @@ Event EV_FAKKServerList_LANListing( "Makes this server list to LAN stuff when there's a choice between Internet & LAN servers" ); -Event EV_FAKKServerList_UpdateServer( +Event EV_FAKKServerList_UpdateServer +( "updateserver", EV_DEFAULT, NULL, @@ -74,71 +80,83 @@ Event EV_FAKKServerList_UpdateServer( ); struct ServerListInstance { - int iServerType; - UIFAKKServerList* serverList; + int iServerType; + UIFAKKServerList *serverList; }; -class FAKKServerListItem : public UIListCtrlItem { - str m_strings[6]; - str m_sVersion; - bool m_bDifferentVersion; - bool m_bFavorite; - bool m_bQueryDone; - bool m_bQueryFailed; - int m_iNumPlayers; +class FAKKServerListItem : public UIListCtrlItem +{ + UIFAKKServerList *m_parent; // Added in OPM + str m_strings[6]; + str m_sVersion; + bool m_bDifferentVersion; + bool m_bFavorite; + bool m_bQueryDone; + bool m_bQueryFailed; + int m_iNumPlayers; public: - str m_sIP; + str m_sIP; unsigned int m_uiRealIP; - int m_iPort; - int m_iGameSpyPort; + int m_iPort; + int m_iGameSpyPort; public: - FAKKServerListItem(str string1, str string2, str string3, str string4, str string5, str string6, str ver); + FAKKServerListItem( + UIFAKKServerList *parent, str string1, str string2, str string3, str string4, str string5, str string6, str ver + ); griditemtype_t getListItemType(int index) const override; - int getListItemValue(int i) const override; - str getListItemString(int i) const override; - void setListItemString(int i, str sNewString); - void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont* pFont) override; - qboolean IsHeaderEntry() const override; - bool IsQueried() const; - void SetQueried(bool bIsQueried); - bool IfQueryFailed() const; - void SetQueryFailed(bool bFailed); - void SetNumPlayers(int iNum); - bool IsFavorite() const; - void SetFavorite(bool bIsFavorite); - str GetListItemVersion() const; - void SetListItemVersion(str sNewVer); - void SetDifferentVersion(bool bIsDifferentVersion); - bool IsDifferentVersion() const; + int getListItemValue(int i) const override; + str getListItemString(int i) const override; + void setListItemString(int i, str sNewString); + void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; + qboolean IsHeaderEntry() const override; + bool IsQueried() const; + void SetQueried(bool bIsQueried); + bool IfQueryFailed() const; + void SetQueryFailed(bool bFailed); + void SetNumPlayers(int iNum); + bool IsFavorite() const; + void SetFavorite(bool bIsFavorite); + str GetListItemVersion() const; + void SetListItemVersion(str sNewVer); + void SetDifferentVersion(bool bIsDifferentVersion); + bool IsDifferentVersion() const; }; -static int g_iTotalNumPlayers; -qboolean g_bNumericSort = qfalse; -qboolean g_bReverseSort = qfalse; -qboolean g_NeedAdditionalLANSearch = qfalse; -qboolean g_bDoneUpdating[2]; +static int g_iTotalNumPlayers; +qboolean g_bNumericSort = qfalse; +qboolean g_bReverseSort = qfalse; +qboolean g_NeedAdditionalLANSearch = qfalse; +qboolean g_bDoneUpdating[2]; ServerListInstance g_ServerListInst[2]; -void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, void* param1, void* param2); -static void AddFilter(char* filter, const char* value); +// Fixed in OPM +// It was a static vaariable inside UpdateServerListCallBack +// that was set to 0 when the mode changed. This caused some issues +static int g_iServerQueryCount = 0; +static int g_iServerTotalCount = 0; -FAKKServerListItem::FAKKServerListItem(str string1, str string2, str string3, str string4, str string5, str string6, str ver) +static void AddFilter(char *filter, const char *value); + +FAKKServerListItem::FAKKServerListItem( + UIFAKKServerList *parent, str string1, str string2, str string3, str string4, str string5, str string6, str ver +) { + m_parent = parent; m_strings[0] = string1; m_strings[1] = string2; m_strings[2] = string3; m_strings[3] = string4; m_strings[4] = string5; m_strings[5] = string6; - m_sVersion = ver; + m_sVersion = ver; - m_bFavorite = false; - m_bQueryDone = false; + m_bFavorite = false; + m_bQueryDone = false; m_bQueryFailed = false; - m_iNumPlayers = 0; + m_iNumPlayers = 0; } griditemtype_t FAKKServerListItem::getListItemType(int index) const @@ -161,87 +179,101 @@ void FAKKServerListItem::setListItemString(int i, str sNewString) m_strings[i] = sNewString; } -void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont* pFont) +void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) { static cvar_t *pColoringType = Cvar_Get("cl_browserdetailedcolors", "0", CVAR_ARCHIVE); - + UIRect2D newRect = drawRect; + vec2_t virtualScale = {1.f, 1.f}; + + /* + if (m_parent->isVirtual()) { + virtualScale[0] = uid.vidWidth / 640.f; + virtualScale[1] = uid.vidHeight / 480.f; + newRect.size.width *= uid.vidWidth / 1024; + newRect.size.height *= uid.vidHeight / 768; + } + */ + + virtualScale[0] = m_parent->getHighResScale()[0]; + virtualScale[1] = m_parent->getHighResScale()[1]; + if (!pColoringType->integer) { if (IfQueryFailed() || (IsDifferentVersion() && IsQueried())) { if (bSelected) { - DrawBox(drawRect, UColor(0.2f, 0.0f, 0.0f), 1.0); + DrawBox(newRect, UColor(0.2f, 0.0f, 0.0f), 1.0); pFont->setColor(UColor(0.9f, 0.0f, 0.0f)); } else { - DrawBox(drawRect, UColor(0.1f, 0.0f, 0.0f), 1.0); + DrawBox(newRect, UColor(0.1f, 0.0f, 0.0f), 1.0); pFont->setColor(UColor(0.55f, 0.0f, 0.0f)); } } else if (IsQueried()) { if (bSelected) { - DrawBox(drawRect, UColor(0.2f, 0.18f, 0.015f), 1.0); + DrawBox(newRect, UColor(0.2f, 0.18f, 0.015f), 1.0); pFont->setColor(UColor(0.9f, 0.8f, 0.6f)); } else { - DrawBox(drawRect, UColor(0.02f, 0.07f, 0.004f), 1.0); + DrawBox(newRect, UColor(0.02f, 0.07f, 0.004f), 1.0); pFont->setColor(UHudColor); } } else { if (bSelected) { - DrawBox(drawRect, UColor(0.15f, 0.18f, 0.18f), 1.0); + DrawBox(newRect, UColor(0.15f, 0.18f, 0.18f), 1.0); pFont->setColor(UColor(0.6f, 0.7f, 0.8f)); } else { - DrawBox(drawRect, UColor(0.005f, 0.07f, 0.02f), 1.0); + DrawBox(newRect, UColor(0.005f, 0.07f, 0.02f), 1.0); pFont->setColor(UColor(0.05f, 0.5f, 0.6f)); } } pFont->Print( - drawRect.pos.x + 1.0, - drawRect.pos.y, + newRect.pos.x / virtualScale[0] + 1.0, + newRect.pos.y / virtualScale[1], getListItemString(iColumn).c_str(), -1, - qfalse + virtualScale ); } else { if (IsDifferentVersion()) { if (IsQueried()) { if (bSelected) { - DrawBox(drawRect, UColor(0.25f, 0.0f, 0.0f), 1.0); + DrawBox(newRect, UColor(0.25f, 0.0f, 0.0f), 1.0); pFont->setColor(UColor(0.0f, 0.5f, 0.0f)); } else { - DrawBox(drawRect, UColor(0.005f, 0.07f, 0.02f), 1.0); + DrawBox(newRect, UColor(0.005f, 0.07f, 0.02f), 1.0); pFont->setColor(UColor(0.0f, 0.35f, 0.0f)); } } else { if (bSelected) { - DrawBox(drawRect, UColor(0.25f, 0.0f, 0.0f), 1.0); + DrawBox(newRect, UColor(0.25f, 0.0f, 0.0f), 1.0); pFont->setColor(UColor(0.5f, 0.6f, 0.7f)); } else { - DrawBox(drawRect, UColor(0.15f, 0.0f, 0.0f), 1.0); + DrawBox(newRect, UColor(0.15f, 0.0f, 0.0f), 1.0); pFont->setColor(UColor(0.05f, 0.4f, 0.5f)); } } } else if (IsQueried()) { if (bSelected) { - DrawBox(drawRect, UColor(0.2f, 0.18f, 0.015f), 1.0); + DrawBox(newRect, UColor(0.2f, 0.18f, 0.015f), 1.0); pFont->setColor(UColor(0.9f, 0.8f, 0.6f)); } else { - DrawBox(drawRect, UColor(0.02f, 0.07f, 0.005f), 1.0); + DrawBox(newRect, UColor(0.02f, 0.07f, 0.005f), 1.0); pFont->setColor(UHudColor); } } else { if (bSelected) { - DrawBox(drawRect, UColor(0.15f, 0.18f, 0.18f), 1.0); + DrawBox(newRect, UColor(0.15f, 0.18f, 0.18f), 1.0); pFont->setColor(UColor(0.6f, 0.7f, 0.8f)); } else { - DrawBox(drawRect, UColor(0.005f, 0.07f, 0.02f), 1.0); + DrawBox(newRect, UColor(0.005f, 0.07f, 0.02f), 1.0); pFont->setColor(UColor(0.05f, 0.5f, 0.6f)); } if (IfQueryFailed()) { DrawBox( UIRect2D( - drawRect.pos.x, - drawRect.pos.y + drawRect.size.height * 0.5 - 1.0 + drawRect.pos.y, - drawRect.size.width, - drawRect.size.height * 0.5 - 1.0 + drawRect.pos.y + newRect.pos.x, + newRect.pos.y + newRect.size.height * 0.5 - 1.0 + newRect.pos.y, + newRect.size.width, + newRect.size.height * 0.5 - 1.0 + newRect.pos.y ), URed, 0.3f @@ -249,19 +281,19 @@ void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, boo } pFont->Print( - drawRect.pos.x + 1.0, - drawRect.pos.y, + newRect.pos.x / virtualScale[0] + 1.0, + newRect.pos.y / virtualScale[1], getListItemString(iColumn).c_str(), -1, - qfalse + virtualScale ); if (IsDifferentVersion()) { DrawBox( UIRect2D( - drawRect.pos.x, - drawRect.pos.y + drawRect.size.height * 0.5 - 1.0 + drawRect.pos.y, - drawRect.size.width, + newRect.pos.x, + newRect.pos.y + newRect.size.height * 0.5 - 1.0 + newRect.pos.y, + newRect.size.width, 1.0 ), URed, @@ -343,66 +375,69 @@ bool FAKKServerListItem::IsDifferentVersion() const return m_bDifferentVersion; } -CLASS_DECLARATION( UIListCtrl, UIFAKKServerList, NULL ) -{ - { &EV_UIListBase_ItemSelected, &UIFAKKServerList::SelectServer }, - { &EV_UIListBase_ItemDoubleClicked, &UIFAKKServerList::ConnectServer }, - { &EV_FAKKServerList_RefreshServerList, &UIFAKKServerList::RefreshServerList }, - { &EV_FAKKServerList_RefreshLANServerList, &UIFAKKServerList::RefreshLANServerList }, - { &EV_FAKKServerList_CancelRefresh, &UIFAKKServerList::CancelRefresh }, - { &EV_FAKKServerList_Connect, &UIFAKKServerList::ConnectServer }, - { &EV_FAKKServerList_LANListing, &UIFAKKServerList::MakeLANListing }, - { &EV_FAKKServerList_UpdateServer, &UIFAKKServerList::UpdateServer }, - { NULL, NULL } +CLASS_DECLARATION(UIListCtrl, UIFAKKServerList, NULL) { + {&EV_UIListBase_ItemSelected, &UIFAKKServerList::SelectServer }, + {&EV_UIListBase_ItemDoubleClicked, &UIFAKKServerList::ConnectServer }, + {&EV_FAKKServerList_RefreshServerList, &UIFAKKServerList::RefreshServerList }, + {&EV_FAKKServerList_RefreshLANServerList, &UIFAKKServerList::RefreshLANServerList}, + {&EV_FAKKServerList_CancelRefresh, &UIFAKKServerList::CancelRefresh }, + {&EV_FAKKServerList_Connect, &UIFAKKServerList::ConnectServer }, + {&EV_FAKKServerList_LANListing, &UIFAKKServerList::MakeLANListing }, + {&EV_FAKKServerList_UpdateServer, &UIFAKKServerList::UpdateServer }, + {NULL, NULL } }; UIFAKKServerList::UIFAKKServerList() { - setBackgroundColor(UWhite, true); + setBackgroundColor(UWhite, true); Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); - AllowActivate(true); - setHeaderFont("facfont-20"); - m_serverList[0] = NULL; - m_serverList[1] = NULL; - m_bHasList = false; - m_bGettingList[0] = false; - m_bGettingList[1] = false; - m_bUpdatingList = false; - m_bLANListing = false; - m_iLastSortColumn = 2; + AllowActivate(true); + setHeaderFont("facfont-20"); + m_serverList[0] = NULL; + m_serverList[1] = NULL; + m_bHasList = false; + m_bGettingList[0] = false; + m_bGettingList[1] = false; + m_bUpdatingList = false; + m_bLANListing = false; + m_iLastSortColumn = 2; } -void UIFAKKServerList::SelectServer( Event *ev ) -{ -} +void UIFAKKServerList::SelectServer(Event *ev) {} -void UIFAKKServerList::ConnectServer( Event *ev ) +void UIFAKKServerList::ConnectServer(Event *ev) { - const FAKKServerListItem* pItem; + const FAKKServerListItem *pItem; if (getCurrentItem() <= 0) { return; } - pItem = static_cast(GetItem(getCurrentItem())); + pItem = static_cast(GetItem(getCurrentItem())); if (pItem->IsDifferentVersion()) { - const char* message; - float neededVersion = com_target_version->value; - float serverVersion = atof(pItem->GetListItemVersion().c_str()); + const char *message; + float neededVersion = com_target_version->value; + float serverVersion = atof(pItem->GetListItemVersion().c_str()); // Tolerate patch version if (fabs(neededVersion - serverVersion) >= 0.1) { UI_SetReturnMenuToCurrent(); - message = va("Server is version %s, you are targeting %s", pItem->GetListItemVersion().c_str(), com_target_version->string); + message = + va("Server is version %s, you are targeting %s", + pItem->GetListItemVersion().c_str(), + com_target_version->string); Cvar_Set("com_errormessage", message); UI_PushMenu("wrongversion"); } else { - message = va("Can not connect to v%s server, you are targeting v%s", pItem->GetListItemVersion().c_str(), com_target_version->string); - + message = + va("Can not connect to v%s server, you are targeting v%s", + pItem->GetListItemVersion().c_str(), + com_target_version->string); + Cvar_Set("dm_serverstatus", message); } } else { @@ -416,10 +451,9 @@ void UIFAKKServerList::ConnectServer( Event *ev ) } } -qboolean UIFAKKServerList::KeyEvent( int key, unsigned int time ) +qboolean UIFAKKServerList::KeyEvent(int key, unsigned int time) { - switch (key) - { + switch (key) { case K_ENTER: case K_KP_ENTER: ConnectServer(NULL); @@ -440,17 +474,17 @@ qboolean UIFAKKServerList::KeyEvent( int key, unsigned int time ) SelectServer(NULL); return qtrue; - } - else { + } else { return qfalse; } break; case 'u': case 'U': - if (getCurrentItem() > 0) - { - const FAKKServerListItem* pItem = static_cast(GetItem(getCurrentItem())); - ServerListAuxUpdate(m_serverList[0], pItem->m_sIP.c_str(), pItem->m_iGameSpyPort, true, GQueryType::qt_status); + if (getCurrentItem() > 0) { + const FAKKServerListItem *pItem = static_cast(GetItem(getCurrentItem())); + ServerListAuxUpdate( + m_serverList[0], pItem->m_sIP.c_str(), pItem->m_iGameSpyPort, true, GQueryType::qt_status + ); } return UIListCtrl::KeyEvent(key, time); case 'c': @@ -460,25 +494,33 @@ qboolean UIFAKKServerList::KeyEvent( int key, unsigned int time ) case 'i': case 'I': { - int i, j; - const FAKKServerListItem* pServerItem1; - const FAKKServerListItem* pServerItem2; - int iNumErrors = 0; + int i, j; + const FAKKServerListItem *pServerItem1; + const FAKKServerListItem *pServerItem2; + int iNumErrors = 0; for (i = 1; i <= getNumItems(); i++) { - pServerItem1 = static_cast(GetItem(i)); + pServerItem1 = static_cast(GetItem(i)); for (j = i + 1; j <= getNumItems(); j++) { - pServerItem2 = static_cast(GetItem(j)); + pServerItem2 = static_cast(GetItem(j)); if (!str::icmp(pServerItem1->m_sIP.c_str(), pServerItem2->m_sIP.c_str())) { if (pServerItem1->m_iPort == pServerItem2->m_iPort) { - Com_DPrintf("*#*#* Duplicate server address: %s:%i\n", pServerItem1->m_sIP.c_str(), pServerItem1->m_iPort); + Com_DPrintf( + "*#*#* Duplicate server address: %s:%i\n", + pServerItem1->m_sIP.c_str(), + pServerItem1->m_iPort + ); iNumErrors++; } if (pServerItem1->m_iGameSpyPort == pServerItem2->m_iGameSpyPort) { - Com_DPrintf("*#*#* servers at IP %s sharing GameSpy port %i\n", pServerItem1->m_sIP.c_str(), pServerItem1->m_iGameSpyPort); + Com_DPrintf( + "*#*#* servers at IP %s sharing GameSpy port %i\n", + pServerItem1->m_sIP.c_str(), + pServerItem1->m_iGameSpyPort + ); iNumErrors++; } } @@ -493,7 +535,7 @@ qboolean UIFAKKServerList::KeyEvent( int key, unsigned int time ) } } -void UIFAKKServerList::UpdateUIElement( void ) +void UIFAKKServerList::UpdateUIElement(void) { float width; @@ -511,13 +553,24 @@ void UIFAKKServerList::UpdateUIElement( void ) uWinMan.ActivateControl(this); } -void UIFAKKServerList::RefreshServerList( Event *ev ) +void UIFAKKServerList::RefreshServerList(Event *ev) { - int i; - FAKKServerListItem* pNewServerItem; + int i; + FAKKServerListItem *pNewServerItem; + + if (m_serverList[0] && ServerListState(m_serverList[0]) != sl_idle) { + // Fixed in OPM + // Only free the server list if it isn't currently being queried. + // The server list must not be queried + return; + } + + if (m_serverList[1] && ServerListState(m_serverList[1]) != sl_idle) { + return; + } for (i = 1; i <= getNumItems(); i++) { - pNewServerItem = static_cast(GetItem(i)); + pNewServerItem = static_cast(GetItem(i)); pNewServerItem->SetQueried(false); pNewServerItem->SetNumPlayers(0); pNewServerItem->SetQueryFailed(false); @@ -525,6 +578,8 @@ void UIFAKKServerList::RefreshServerList( Event *ev ) if (m_serverList[0]) { ServerListClear(m_serverList[0]); + // Added in 2.0: Free the server list + // Since 2.0, the UI no longer refreshes the server list when clicking "Browse Internet Servers" ServerListFree(m_serverList[0]); m_serverList[0] = NULL; } @@ -534,8 +589,8 @@ void UIFAKKServerList::RefreshServerList( Event *ev ) ServerListFree(m_serverList[1]); m_serverList[1] = NULL; } - - if (!m_serverList[0]) { + + if (!m_serverList[0] && (com_target_game->integer < target_game_e::TG_MOHTT || !m_serverList[1])) { NewServerList(); } @@ -544,14 +599,14 @@ void UIFAKKServerList::RefreshServerList( Event *ev ) Cvar_Set("dm_playercount", "0"); { - char filter[2048] = { 0 }; - static cvar_t* dm_max_players = Cvar_Get("dm_max_players", "0", CVAR_ARCHIVE); - static cvar_t* dm_min_players = Cvar_Get("dm_min_players", "0", CVAR_ARCHIVE); - static cvar_t* dm_show_demo_servers = Cvar_Get("dm_show_demo_servers", "1", CVAR_ARCHIVE); - static cvar_t* dm_realism_mode = Cvar_Get("dm_realism_mode", "0", CVAR_ARCHIVE); - static cvar_t* dm_filter_listen = Cvar_Get("dm_filter_listen", "1", CVAR_ARCHIVE); - static cvar_t* dm_filter_empty = Cvar_Get("dm_filter_empty", "0", CVAR_ARCHIVE); - static cvar_t* dm_filter_full = Cvar_Get("dm_filter_full", "0", CVAR_ARCHIVE); + char filter[2048] = {0}; + static cvar_t *dm_max_players = Cvar_Get("dm_max_players", "0", CVAR_ARCHIVE); + static cvar_t *dm_min_players = Cvar_Get("dm_min_players", "0", CVAR_ARCHIVE); + static cvar_t *dm_show_demo_servers = Cvar_Get("dm_show_demo_servers", "1", CVAR_ARCHIVE); + static cvar_t *dm_realism_mode = Cvar_Get("dm_realism_mode", "0", CVAR_ARCHIVE); + static cvar_t *dm_filter_listen = Cvar_Get("dm_filter_listen", "1", CVAR_ARCHIVE); + static cvar_t *dm_filter_empty = Cvar_Get("dm_filter_empty", "0", CVAR_ARCHIVE); + static cvar_t *dm_filter_full = Cvar_Get("dm_filter_full", "0", CVAR_ARCHIVE); if (dm_min_players->integer) { AddFilter(filter, va("numplayers >= %d", dm_min_players->integer)); @@ -591,43 +646,46 @@ void UIFAKKServerList::RefreshServerList( Event *ev ) m_bUpdatingList = true; } -void UIFAKKServerList::RefreshLANServerList( Event *ev ) +void UIFAKKServerList::RefreshLANServerList(Event *ev) { - int i; - FAKKServerListItem* pNewServerItem; + int i; + FAKKServerListItem *pNewServerItem; for (i = 1; i <= getNumItems(); i++) { - pNewServerItem = static_cast(GetItem(i)); + pNewServerItem = static_cast(GetItem(i)); pNewServerItem->SetQueried(false); pNewServerItem->SetNumPlayers(0); pNewServerItem->SetQueryFailed(false); } + if (m_serverList[0]) { + ServerListClear(m_serverList[0]); + } + if (m_serverList[1]) { ServerListClear(m_serverList[1]); } - if (m_serverList[0]) { - ServerListClear(m_serverList[0]); - } else { + if (!m_serverList[0] && (com_target_game->integer < target_game_e::TG_MOHTT || !m_serverList[1])) { NewServerList(); } - g_bDoneUpdating[0] = false; - g_bDoneUpdating[1] = false; + g_bDoneUpdating[0] = false; + g_bDoneUpdating[1] = false; g_NeedAdditionalLANSearch = true; Cvar_Set("dm_playercount", "0"); // Search all LAN servers from port 12300 to 12316 ServerListLANUpdate(m_serverList[0], true, 12300, 12316, 1); - + if (m_serverList[1]) { // If another game is supported search for it ServerListLANUpdate(m_serverList[1], true, 12300, 12316, 1); } } -static void AddFilter(char* filter, const char* value) { +static void AddFilter(char *filter, const char *value) +{ if (*filter) { strcat(filter, va(" and %s", value)); } else { @@ -635,17 +693,20 @@ static void AddFilter(char* filter, const char* value) { } } -void UIFAKKServerList::CancelRefresh( Event *ev ) +void UIFAKKServerList::CancelRefresh(Event *ev) { - ServerListHalt(m_serverList[0]); + ServerListHalt(m_serverList[0]); + if (m_serverList[1]) { + ServerListHalt(m_serverList[1]); + } } -void UIFAKKServerList::NewServerList( void ) +void UIFAKKServerList::NewServerList(void) { - int iNumConcurrent; - const char* secret_key; - const char* game_name; - cvar_t* pRateCvar = Cvar_Get("rate", "5000", CVAR_ARCHIVE | CVAR_USERINFO); + int iNumConcurrent; + const char *secret_key; + const char *game_name; + cvar_t *pRateCvar = Cvar_Get("rate", "5000", CVAR_ARCHIVE | CVAR_USERINFO); if (pRateCvar->integer <= 3000) { iNumConcurrent = 4; @@ -657,97 +718,111 @@ void UIFAKKServerList::NewServerList( void ) iNumConcurrent = 15; } + g_iServerQueryCount = 0; + g_iServerTotalCount = 0; + if (com_target_game->integer < target_game_e::TG_MOHTT) { - game_name = GS_GetCurrentGameName(); + game_name = GS_GetCurrentGameName(); secret_key = GS_GetCurrentGameKey(); // standard mohaa server g_ServerListInst[0].iServerType = com_target_game->integer; - g_ServerListInst[0].serverList = this; + g_ServerListInst[0].serverList = this; m_serverList[0] = ServerListNew( game_name, game_name, secret_key, iNumConcurrent, - (void*)&UpdateServerListCallBack, + (void *)&UpdateServerListCallBack, 1, - (void*)&g_ServerListInst[0] + (void *)&g_ServerListInst[0] ); m_serverList[1] = NULL; } else { - static cvar_t* dm_omit_spearhead = Cvar_Get("dm_omit_spearhead", "0", 1); + static cvar_t *dm_omit_spearhead = Cvar_Get("dm_omit_spearhead", "0", 1); - game_name = GS_GetGameName(target_game_e::TG_MOHTT); + game_name = GS_GetGameName(target_game_e::TG_MOHTT); secret_key = GS_GetGameKey(target_game_e::TG_MOHTT); g_ServerListInst[0].iServerType = target_game_e::TG_MOHTT; - g_ServerListInst[0].serverList = this; + g_ServerListInst[0].serverList = this; m_serverList[0] = ServerListNew( game_name, game_name, secret_key, iNumConcurrent, - (void*)&UpdateServerListCallBack, + (void *)&UpdateServerListCallBack, 1, - (void*)&g_ServerListInst[0] + (void *)&g_ServerListInst[0] ); - + if (!dm_omit_spearhead->integer) { // Since mohtt is compatible with mohta // Search for both type of servers - game_name = GS_GetGameName(target_game_e::TG_MOHTA); + game_name = GS_GetGameName(target_game_e::TG_MOHTA); secret_key = GS_GetGameKey(target_game_e::TG_MOHTA); g_ServerListInst[1].iServerType = target_game_e::TG_MOHTA; - g_ServerListInst[1].serverList = this; + g_ServerListInst[1].serverList = this; m_serverList[1] = ServerListNew( game_name, game_name, secret_key, iNumConcurrent, - (void*)&UpdateServerListCallBack, + (void *)&UpdateServerListCallBack, 1, - (void*)&g_ServerListInst[1] + (void *)&g_ServerListInst[1] ); } } } -void UIFAKKServerList::MakeLANListing( Event *ev ) +void UIFAKKServerList::MakeLANListing(Event *ev) { - m_bLANListing = true; + m_bLANListing = true; } -void UIFAKKServerList::UpdateServer( Event *ev ) +void UIFAKKServerList::UpdateServer(Event *ev) { - if (m_currentItem <= 0) { - return; - } + if (m_currentItem <= 0) { + return; + } - FAKKServerListItem* item = (FAKKServerListItem*)GetItem(getCurrentItem()); + FAKKServerListItem *item = (FAKKServerListItem *)GetItem(getCurrentItem()); ServerListAuxUpdate(m_serverList[0], item->m_sIP.c_str(), item->m_iGameSpyPort, true, GQueryType::qt_status); + + if (com_target_game->integer >= target_game_e::TG_MOHTT) { + const cvar_t *dm_omit_spearhead = Cvar_Get("dm_omit_spearhead", "0", CVAR_ARCHIVE); + // check for Spearhead + if (!dm_omit_spearhead->integer) { + ServerListAuxUpdate( + m_serverList[1], item->m_sIP.c_str(), item->m_iGameSpyPort, true, GQueryType::qt_status + ); + } + } } -int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIListCtrlItem *i2, int columnname ) +int UIFAKKServerList::ServerCompareFunction(const UIListCtrlItem *i1, const UIListCtrlItem *i2, int columnname) { - int iCompResult; - int val1, val2; - const FAKKServerListItem* fi1 = static_cast(i1); - const FAKKServerListItem* fi2 = static_cast(i2); + int iCompResult; + int val1, val2; + const FAKKServerListItem *fi1 = static_cast(i1); + const FAKKServerListItem *fi2 = static_cast(i2); - if (fi1->IsFavorite() != fi2->IsFavorite()) - { + if (fi1->IsFavorite() != fi2->IsFavorite()) { if (fi1->IsFavorite()) { iCompResult = -1; } else { iCompResult = 1; } - if (g_bReverseSort) iCompResult = -iCompResult; + if (g_bReverseSort) { + iCompResult = -iCompResult; + } } else if (fi1->IsQueried() != fi2->IsQueried()) { if (fi1->IsQueried()) { iCompResult = -1; @@ -755,16 +830,19 @@ int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIL iCompResult = 1; } - if (g_bReverseSort) iCompResult = -iCompResult; + if (g_bReverseSort) { + iCompResult = -iCompResult; + } } else if (fi1->IsDifferentVersion() != fi2->IsDifferentVersion()) { - if (fi1->IsDifferentVersion()) { iCompResult = 1; } else { iCompResult = -1; } - if (g_bReverseSort) iCompResult = -iCompResult; + if (g_bReverseSort) { + iCompResult = -iCompResult; + } } else if (fi1->IfQueryFailed() != fi2->IfQueryFailed()) { if (fi1->IfQueryFailed()) { iCompResult = 1; @@ -772,7 +850,9 @@ int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIL iCompResult = -1; } - if (g_bReverseSort) iCompResult = -iCompResult; + if (g_bReverseSort) { + iCompResult = -iCompResult; + } } else if (g_bNumericSort) { val1 = fi1->getListItemValue(columnname); val2 = fi2->getListItemValue(columnname); @@ -788,8 +868,7 @@ int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIL iCompResult = str::icmp(fi1->getListItemString(columnname), fi2->getListItemString(columnname)); } - if (!iCompResult) - { + if (!iCompResult) { if (columnname != -2) { val1 = fi1->getListItemValue(2); val2 = fi2->getListItemValue(2); @@ -822,11 +901,9 @@ int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIL if (val1 < val2) { iCompResult = 1; - } - else if (val1 > val2) { + } else if (val1 > val2) { iCompResult = -1; - } - else { + } else { iCompResult = 0; } } @@ -844,16 +921,17 @@ int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIL } } - if (g_bReverseSort) iCompResult = -iCompResult; + if (g_bReverseSort) { + iCompResult = -iCompResult; + } } return iCompResult; } -void UIFAKKServerList::Draw( void ) +void UIFAKKServerList::Draw(void) { - if (m_serverList[0]) - { + if (m_serverList[0]) { GServerListState listState[2]; ServerListThink(m_serverList[0]); @@ -863,22 +941,17 @@ void UIFAKKServerList::Draw( void ) listState[0] = ServerListState(m_serverList[0]); listState[1] = m_serverList[1] ? ServerListState(m_serverList[1]) : GServerListState::sl_idle; - if (listState[0] != GServerListState::sl_idle || listState[1] != GServerListState::sl_idle) - { + if (listState[0] != GServerListState::sl_idle || listState[1] != GServerListState::sl_idle) { menuManager.PassEventToWidget("refresh", new Event(EV_Widget_Disable)); menuManager.PassEventToWidget("cancelrefresh", new Event(EV_Widget_Enable)); - } - else - { + } else { menuManager.PassEventToWidget("refresh", new Event(EV_Widget_Enable)); menuManager.PassEventToWidget("cancelrefresh", new Event(EV_Widget_Disable)); } } else if (!m_bHasList) { - if (m_bLANListing) { RefreshLANServerList(NULL); - } - else { + } else { RefreshServerList(NULL); } @@ -900,14 +973,14 @@ void UIFAKKServerList::Draw( void ) UIListCtrl::Draw(); } -void UIFAKKServerList::SortByColumn( int column ) +void UIFAKKServerList::SortByColumn(int column) { - int i; - bool exists = 0; - bool numeric = 0; - bool reverse = 0; - UIListCtrlItem* selected = NULL; - bool selvisible = false; + int i; + bool exists = 0; + bool numeric = 0; + bool reverse = 0; + UIListCtrlItem *selected = NULL; + bool selvisible = false; for (i = 1; i <= m_columnlist.NumObjects(); i++) { const columndef_t& def = m_columnlist.ObjectAt(i); @@ -915,7 +988,7 @@ void UIFAKKServerList::SortByColumn( int column ) // found one numeric = def.numeric; reverse = def.reverse_sort; - exists = true; + exists = true; break; } } @@ -926,11 +999,11 @@ void UIFAKKServerList::SortByColumn( int column ) } m_iLastSortColumn = column; - s_qsortcolumn = column; - s_qsortobject = this; - s_qsortreverse = reverse; - g_bNumericSort = numeric; - g_bReverseSort = reverse; + s_qsortcolumn = column; + s_qsortobject = this; + s_qsortreverse = reverse; + g_bNumericSort = numeric; + g_bReverseSort = reverse; if (getCurrentItem()) { selected = m_itemlist.ObjectAt(getCurrentItem()); @@ -956,47 +1029,44 @@ void UIFAKKServerList::SortByColumn( int column ) } } -void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, void* param1, void* param2) +void UIFAKKServerList::UpdateServerListCallBack(GServerList serverlist, int msg, void *instance, void *param1, void *param2) { - int i, j; - int iPort, iGameSpyPort; - unsigned int iRealIP; - str sAddress; - GServer server; - FAKKServerListItem* pNewServerItem; - static int iServerQueryCount = 0; - static int iServerTotalCount = 0; - UIFAKKServerList* uiServerList; - int iServerType; + int i, j; + int iPort, iGameSpyPort; + unsigned int iRealIP; + str sAddress; + GServer server; + FAKKServerListItem *pNewServerItem; + UIFAKKServerList *uiServerList; + int iServerType; // filters - static cvar_t* dm_filter_empty = Cvar_Get("dm_filter_empty", "0", CVAR_ARCHIVE); - static cvar_t* dm_filter_full = Cvar_Get("dm_filter_full", "0", CVAR_ARCHIVE); - static cvar_t* dm_filter_pure = Cvar_Get("dm_filter_pure", "0", CVAR_ARCHIVE); - static cvar_t* dm_max_ping = Cvar_Get("dm_max_ping", "0", CVAR_ARCHIVE); - static cvar_t* dm_free_for_all = Cvar_Get("dm_free_for_all", "1", CVAR_ARCHIVE); - static cvar_t* dm_objective_match = Cvar_Get("dm_objective_match", "1", CVAR_ARCHIVE); - static cvar_t* dm_round_based_match = Cvar_Get("dm_round_based_match", "1", CVAR_ARCHIVE); - static cvar_t* dm_team_match = Cvar_Get("dm_team_match", "1", CVAR_ARCHIVE); - static cvar_t* dm_tow_match = Cvar_Get("dm_tow_match", "1", CVAR_ARCHIVE); - static cvar_t* dm_liberation_match = Cvar_Get("dm_liberation_match", "1", CVAR_ARCHIVE); - static cvar_t* dm_run_fast = Cvar_Get("dm_run_fast", "1", CVAR_ARCHIVE); - static cvar_t* dm_run_normal = Cvar_Get("dm_run_normal", "1", CVAR_ARCHIVE); - static cvar_t* dm_omit_spearhead = Cvar_Get("dm_omit_spearhead", "0", CVAR_ARCHIVE); + static cvar_t *dm_filter_empty = Cvar_Get("dm_filter_empty", "0", CVAR_ARCHIVE); + static cvar_t *dm_filter_full = Cvar_Get("dm_filter_full", "0", CVAR_ARCHIVE); + static cvar_t *dm_filter_pure = Cvar_Get("dm_filter_pure", "0", CVAR_ARCHIVE); + static cvar_t *dm_max_ping = Cvar_Get("dm_max_ping", "0", CVAR_ARCHIVE); + static cvar_t *dm_free_for_all = Cvar_Get("dm_free_for_all", "1", CVAR_ARCHIVE); + static cvar_t *dm_objective_match = Cvar_Get("dm_objective_match", "1", CVAR_ARCHIVE); + static cvar_t *dm_round_based_match = Cvar_Get("dm_round_based_match", "1", CVAR_ARCHIVE); + static cvar_t *dm_team_match = Cvar_Get("dm_team_match", "1", CVAR_ARCHIVE); + static cvar_t *dm_tow_match = Cvar_Get("dm_tow_match", "1", CVAR_ARCHIVE); + static cvar_t *dm_liberation_match = Cvar_Get("dm_liberation_match", "1", CVAR_ARCHIVE); + static cvar_t *dm_run_fast = Cvar_Get("dm_run_fast", "1", CVAR_ARCHIVE); + static cvar_t *dm_run_normal = Cvar_Get("dm_run_normal", "1", CVAR_ARCHIVE); + static cvar_t *dm_omit_spearhead = Cvar_Get("dm_omit_spearhead", "0", CVAR_ARCHIVE); - iServerType = ((ServerListInstance*)instance)->iServerType; - uiServerList = ((ServerListInstance*)instance)->serverList; + iServerType = ((ServerListInstance *)instance)->iServerType; + uiServerList = ((ServerListInstance *)instance)->serverList; pNewServerItem = NULL; - server = (GServer)param1; + server = (GServer)param1; - if (param2) - { - if (msg == LIST_PROGRESS && param2 == (void*)-1) { + if (param2) { + if (msg == LIST_PROGRESS && param2 == (void *)-1) { iRealIP = inet_addr(ServerGetAddress(server)); ServerGetIntValue(server, "hostport", PORT_SERVER); iGameSpyPort = ServerGetQueryPort(server); for (i = 1; i <= uiServerList->getNumItems(); i++) { - pNewServerItem = static_cast(uiServerList->GetItem(i)); + pNewServerItem = static_cast(uiServerList->GetItem(i)); if (pNewServerItem->m_uiRealIP == iRealIP && pNewServerItem->m_iGameSpyPort == iGameSpyPort) { break; } @@ -1009,55 +1079,80 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v return; } - Cvar_Set("dm_serverstatusbar", va("%i", param2)); + //Cvar_Set("dm_serverstatusbar", va("%i", (int)(uintptr_t)param2)); + // Fixed in OPM + // As both lists are combined, show the correct percentage + Cvar_Set("dm_serverstatusbar", va("%i", 100 * g_iServerQueryCount / g_iServerTotalCount)); } - if (msg == LIST_PROGRESS) - { - const char* pszHostName; - bool bDiffVersion; - str sServerName; - str sPlayers; - const char* pszGameVer; + if (msg == LIST_PROGRESS) { + const char *pszHostName; + bool bDiffVersion; + bool bIsDemo; + str sServerName; + str sPlayers; + const char *pszGameVer; + const char *pszGameVerNumber; + float fGameVer; - pszHostName = ServerGetStringValue(server, "hostname", "(NONE)"); - bDiffVersion = false; - pszGameVer = ServerGetStringValue(server, "gamever", "1.00"); + pszHostName = ServerGetStringValue(server, "hostname", "(NONE)"); + bDiffVersion = false; + bIsDemo = false; + pszGameVer = ServerGetStringValue(server, "gamever", "1.00"); + pszGameVerNumber = pszGameVer; + + if (pszGameVerNumber[0] == 'd') { + // demo server + pszGameVerNumber++; + bIsDemo = true; + } + + fGameVer = atof(pszGameVerNumber); if (com_target_game->integer >= target_game_e::TG_MOHTT) { if (iServerType == target_game_e::TG_MOHTT) { - if (fabs(atof(pszGameVer) - com_target_version->value) > 0.1f) { + //if (fabs(fGameVer - com_target_version->value) > 0.1f) { + // bDiffVersion = true; + //} + if (fabs(fGameVer) < 2.3f) { bDiffVersion = true; } } else { - if (fabs(atof(pszGameVer) - com_target_version->value) > 0.3f) { + //if (fabs(fGameVer - com_target_version->value) > 0.3f) { + // bDiffVersion = true; + //} + if (fabs(fGameVer) < 2.1f) { bDiffVersion = true; } } } else { - if (fabs(atof(pszGameVer) - com_target_version->value) > 0.1f) { + if (fabs(fGameVer - com_target_version->value) > 0.1f) { bDiffVersion = true; } } // always show the version - sServerName = va(" (%s) %s", pszGameVer, pszHostName); + if (!bIsDemo) { + sServerName = va(" (%s) %s", pszGameVerNumber, pszHostName); + } else { + sServerName = va(" (d%s) %s", pszGameVerNumber, pszHostName); + } - iRealIP = inet_addr(ServerGetAddress(server)); - iPort = ServerGetIntValue(server, "hostport", PORT_SERVER); + iRealIP = inet_addr(ServerGetAddress(server)); + iPort = ServerGetIntValue(server, "hostport", PORT_SERVER); iGameSpyPort = ServerGetQueryPort(server); - sAddress = va("%s:%i", ServerGetAddress(server), iPort); + sAddress = va("%s:%i", ServerGetAddress(server), iPort); sPlayers = va("%d/%d", ServerGetIntValue(server, "numplayers", 0), ServerGetIntValue(server, "maxplayers", 0)); - + for (i = 1; i <= uiServerList->getNumItems(); i++) { - pNewServerItem = static_cast(uiServerList->GetItem(i)); + pNewServerItem = static_cast(uiServerList->GetItem(i)); if (pNewServerItem->m_uiRealIP == iRealIP && pNewServerItem->m_iGameSpyPort == iGameSpyPort) { break; } } if (i > uiServerList->getNumItems() || !pNewServerItem) { - pNewServerItem = new FAKKServerListItem("?", sAddress, "?", "?/?", "?", "?", "?"); - pNewServerItem->m_sIP = ServerGetAddress(server); + pNewServerItem = new FAKKServerListItem(uiServerList, "?", sAddress, "?", "?/?", "?", "?", "?"); + pNewServerItem->m_sIP = ServerGetAddress(server); pNewServerItem->m_uiRealIP = iRealIP; pNewServerItem->m_iGameSpyPort = iGameSpyPort; @@ -1077,15 +1172,12 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v pNewServerItem->SetQueried(true); pNewServerItem->SetNumPlayers(ServerGetIntValue(server, "numplayers", 0)); - iServerQueryCount++; - Cvar_Set("dm_servercount", va("%d/%d", iServerQueryCount, iServerTotalCount)); + g_iServerQueryCount++; + Cvar_Set("dm_servercount", va("%d/%d", g_iServerQueryCount, g_iServerTotalCount)); uiServerList->SortByLastSortColumn(); - } - else if (msg == LIST_STATECHANGED) - { - switch (ServerListState(serverlist)) - { + } else if (msg == LIST_STATECHANGED) { + switch (ServerListState(serverlist)) { case GServerListState::sl_idle: if (com_target_game->integer >= target_game_e::TG_MOHTT) { if (iServerType == target_game_e::TG_MOHTT) { @@ -1109,14 +1201,17 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v case GServerListState::sl_listxfer: Cvar_Set("dm_serverstatus", "Getting List."); if (com_target_game->integer >= target_game_e::TG_MOHTT) { - if (iServerType == target_game_e::TG_MOHTT) uiServerList->m_bGettingList[0] = true; - if (iServerType == target_game_e::TG_MOHTA) uiServerList->m_bGettingList[1] = true; + if (iServerType == target_game_e::TG_MOHTT) { + uiServerList->m_bGettingList[0] = true; + } + if (iServerType == target_game_e::TG_MOHTA) { + uiServerList->m_bGettingList[1] = true; + } } else { uiServerList->m_bGettingList[0] = true; uiServerList->m_bGettingList[1] = false; } uiServerList->m_bUpdatingList = true; - iServerQueryCount = 0; return; case GServerListState::sl_lanlist: Cvar_Set("dm_serverstatus", "Searching LAN."); @@ -1125,18 +1220,27 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v case GServerListState::sl_querying: Cvar_Set("dm_serverstatus", "Querying Servers."); uiServerList->m_bUpdatingList = true; - iServerQueryCount = 0; - iServerTotalCount = 0; break; default: break; } - if (!uiServerList->m_bGettingList[0] && !uiServerList->m_bGettingList[1]) { - return; + //if (!uiServerList->m_bGettingList[0] && !uiServerList->m_bGettingList[1]) { + // return; + //} + + // Rebuild the number of servers + g_iServerTotalCount = 0; + for(i = 0; i < ARRAY_LEN(uiServerList->m_serverList); i++) { + if (uiServerList->m_bGettingList[i] && uiServerList->m_serverList[i]) { + g_iServerTotalCount += ServerListCount(uiServerList->m_serverList[i]); + } } - iServerTotalCount += ServerListCount(serverlist); + // Removed in 2.0 + // Only add entries for servers that are queried successfully + // it avoids unnecessary entries +#if 0 for (j = 0; j < ServerListCount(serverlist); j++) { GServer arrayServer = ServerListGetServer(serverlist, j); @@ -1154,7 +1258,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v continue; } - pNewServerItem = new FAKKServerListItem("?", sAddress, "?", "?/?", "?", "?", "?"); + pNewServerItem = new FAKKServerListItem(uiServerList, "?", sAddress, "?", "?/?", "?", "?", "?"); pNewServerItem->m_sIP = ServerGetAddress(arrayServer); pNewServerItem->m_uiRealIP = iRealIP; pNewServerItem->m_iPort = PORT_SERVER; @@ -1164,6 +1268,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v uiServerList->AddItem(pNewServerItem); } +#endif /* for (i = 1; i <= uiServerList->getNumItems(); i++) @@ -1191,4 +1296,4 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v } */ } -} \ No newline at end of file +} diff --git a/code/client/cl_uiserverlist.h b/code/client/cl_uiserverlist.h index d8638b32..91c46016 100644 --- a/code/client/cl_uiserverlist.h +++ b/code/client/cl_uiserverlist.h @@ -22,6 +22,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #pragma once +#include "../gamespy/goaceng.h" + class UIFAKKServerList : public UIListCtrl { protected: // need a new struct instead of gamespy @@ -47,6 +49,7 @@ protected: void MakeLANListing( Event *ev ); void UpdateServer( Event *ev ); static int ServerCompareFunction( const UIListCtrlItem *i1, const UIListCtrlItem *i2, int columnname ); + static void UpdateServerListCallBack(GServerList serverlist, int msg, void *instance, void *param1, void *param2); public: UIFAKKServerList(); diff --git a/code/client/cl_uisoundpicker.cpp b/code/client/cl_uisoundpicker.cpp index a45c434c..384ac8ff 100644 --- a/code/client/cl_uisoundpicker.cpp +++ b/code/client/cl_uisoundpicker.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,22 +22,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" -CLASS_DECLARATION( FilePickerClass, SoundPickerClass, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(FilePickerClass, SoundPickerClass, NULL) { + {NULL, NULL} }; SoundPickerClass::SoundPickerClass() { - // FIXME: stub + str soundpath; + str currentpath; + const char *varValue; + int i; + + soundpath = "sound"; + + varValue = UI_GetCvarString("ui_pickedsound", NULL); + if (varValue && *varValue) { + currentpath = varValue; + + for (i = currentpath.length(); i > 0; i--) { + if (currentpath[i] == '/') { + break; + } + } + + currentpath = str(currentpath, 0, i + 1); + } else { + currentpath = soundpath; + } } -void SoundPickerClass::FileSelected( str ¤tDirectory, str &partialName, str &fullname ) +void SoundPickerClass::FileSelected(const str& currentDirectory, const str& partialName, const str& fullname) { - + uii.Snd_PlaySound(fullname); } -void SoundPickerClass::FileChosen( str ¤tDirectory, str &partialName, str &fullname ) +void SoundPickerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) { - + uii.Cvar_Set("ui_pickedsound", fullname); + CloseWindow(); } diff --git a/code/client/cl_uisoundpicker.h b/code/client/cl_uisoundpicker.h index 4ead3be2..6c6a9275 100644 --- a/code/client/cl_uisoundpicker.h +++ b/code/client/cl_uisoundpicker.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,17 +20,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UISOUNDPICKER_H__ -#define __CL_UISOUNDPICKER_H__ +#pragma once -class SoundPickerClass : public FilePickerClass { +class SoundPickerClass : public FilePickerClass +{ public: - CLASS_PROTOTYPE( SoundPickerClass ); + CLASS_PROTOTYPE(SoundPickerClass); - SoundPickerClass(); + SoundPickerClass(); - void FileSelected( str ¤tDirectory, str &partialName, str &fullname ) override; - void FileChosen( str ¤tDirectory, str &partialName, str &fullname ) override; + void FileSelected(const str& currentDirectory, const str& partialName, const str& fullname) override; + void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override; }; - -#endif /* __CL_UISOUNDPICKER_H__ */ diff --git a/code/client/cl_uistd.cpp b/code/client/cl_uistd.cpp index 80e3ec53..4fd41c6e 100644 --- a/code/client/cl_uistd.cpp +++ b/code/client/cl_uistd.cpp @@ -24,601 +24,700 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110EV_DEFAULT301 U #include "../qcommon/localization.h" Event EV_Layout_PlayerStat - ( - "playerstat", - EV_DEFAULT, - "i", - "playerstatValue", - "set playerstat for layout\n" - ); +( + "playerstat", + EV_DEFAULT, + "i", + "playerstatValue", + "set playerstat for layout\n" +); +// Added in 2.0 +Event EV_Layout_PlayerStatAlpha +( + "playerstatalpha", + EV_DEFAULT, + "i", + "playerstatValue", + "set playerstat to control alpha for layout\n" +); Event EV_Layout_PlayerStatConfigstring - ( - "playerstatconfigstring", - EV_DEFAULT, - "i", - "playerstatValue", - "set playerstat for layout - will print out the corresponding configstring\n" - ); +( + "playerstatconfigstring", + EV_DEFAULT, + "i", + "playerstatValue", + "set playerstat for layout - will print out the corresponding configstring\n" +); Event EV_Layout_MaxPlayerStat - ( - "maxplayerstat", - EV_DEFAULT, - "i", - "maxPlayerstatValue", - "set the playerstat that holds the max value for that stat. Used for statbars\n" - ); +( + "maxplayerstat", + EV_DEFAULT, + "i", + "maxPlayerstatValue", + "set the playerstat that holds the max value for that stat. Used for statbars\n" +); Event EV_Layout_ItemIndex - ( - "itemstat", - EV_DEFAULT, - "i", - "itemstatValue", - "set itemstat for layout\n" - ); +( + "itemstat", + EV_DEFAULT, + "i", + "itemstatValue", + "set itemstat for layout\n" +); Event EV_Layout_InventoryRenderModelIndex - ( - "invmodelhand", - EV_DEFAULT, - "i", - "handindex", - "set the specified hand index to render a 3d model from\n" - ); +( + "invmodelhand", + EV_DEFAULT, + "i", + "handindex", + "set the specified hand index to render a 3d model from\n" +); Event EV_Layout_Statbar - ( - "statbar", - EV_DEFAULT, - "sII", - "orientation min max", - "make this label present the stat using a graphical bar. Optionally specify a min and max value" - ); +( + "statbar", + EV_DEFAULT, + "sII", + "orientation min max", + "make this label present the stat using a graphical bar. Optionally specify a min and max value" +); Event EV_Layout_StatbarTileShader - ( - "statbar_tileshader", - EV_DEFAULT, - "s", - "shader", - "set the tile shader for this statbar" - ); +( + "statbar_tileshader", + EV_DEFAULT, + "s", + "shader", + "set the tile shader for this statbar" +); Event EV_Layout_StatbarTileShader_Flash - ( - "statbar_tileshader_flash", - EV_DEFAULT, - "s", - "shader", - "set the flash tile shader for this statbar" - ); +( + "statbar_tileshader_flash", + EV_DEFAULT, + "s", + "shader", + "set the flash tile shader for this statbar" +); Event EV_Layout_StatbarShader - ( - "statbar_shader", - EV_DEFAULT, - "s", - "shader", - "set the shader for this statbar" - ); +( + "statbar_shader", + EV_DEFAULT, + "s", + "shader", + "set the shader for this statbar" +); Event EV_Layout_StatbarShader_Flash - ( - "statbar_shader_flash", - EV_DEFAULT, - "s", - "shader", - "set the flash shader for this statbar" - ); +( + "statbar_shader_flash", + EV_DEFAULT, + "s", + "shader", + "set the flash shader for this statbar" +); +// Added in 2.0 +Event EV_Layout_StatbarShader_Marker +( + "statbar_shader_marker", + EV_DEFAULT, + "s", + "shader", + "set the marker shader for this statbar\nThis is drawn at the end of the status bar" +); Event EV_Layout_Statbar_EndAngles - ( - "statbar_endangles", - EV_DEFAULT, - "ff", - "startang endang", - "Sets the start and end angles for a circular stat bar" - ); +( + "statbar_endangles", + EV_DEFAULT, + "ff", + "startang endang", + "Sets the start and end angles for a circular stat bar" +); Event EV_Layout_Statbar_NeedleWidth - ( - "statbar_needlewidth", - EV_DEFAULT, - "f", - "width", - "Sets the width of the needle for a needle statbar" - ); +( + "statbar_needlewidth", + EV_DEFAULT, + "f", + "width", + "Sets the width of the needle for a needle statbar" +); Event EV_Layout_Statbar_RotatorSize - ( - "statbar_rotatorsize", - EV_DEFAULT, - "f", - "width", - "Sets the width of the needle for a needle statbar" - ); +( + "statbar_rotatorsize", + EV_DEFAULT, + "f", + "width", + "Sets the width of the needle for a needle statbar" +); Event EV_Layout_DrawModelName - ( - "invmodelname", - EV_DEFAULT, - "s", - "name", - "set the name of the 3d model to render\n" - ); +( + "invmodelname", + EV_DEFAULT, + "s", + "name", + "set the name of the 3d model to render\n" +); Event EV_Layout_RenderModel - ( - "rendermodel", - EV_DEFAULT, - "b", - "bool", - "Render the model specified by the cvar." - ); +( + "rendermodel", + EV_DEFAULT, + "b", + "bool", + "Render the model specified by the cvar." +); Event EV_Layout_RenderModelOffset - ( - "modeloffset", - EV_DEFAULT, - "v", - "offset", - "Render model offset" - ); +( + "modeloffset", + EV_DEFAULT, + "v", + "offset", + "Render model offset" +); Event EV_Layout_RenderModelRotateOffset - ( - "modelrotateoffset", - EV_DEFAULT, - "v", - "offset", - "Render model rotation offset" - ); +( + "modelrotateoffset", + EV_DEFAULT, + "v", + "offset", + "Render model rotation offset" +); Event EV_Layout_RenderModelAngles - ( - "modelangles", - EV_DEFAULT, - "v", - "angles", - "Render model angles" - ); +( + "modelangles", + EV_DEFAULT, + "v", + "angles", + "Render model angles" +); Event EV_Layout_RenderModelScale - ( - "modelscale", - EV_DEFAULT, - "f", - "scale", - "Render model scale" - ); +( + "modelscale", + EV_DEFAULT, + "f", + "scale", + "Render model scale" +); Event EV_Layout_RenderModelAnim - ( - "modelanim", - EV_DEFAULT, - "s", - "anim", - "Render model anim" - ); +( + "modelanim", + EV_DEFAULT, + "s", + "anim", + "Render model anim" +); Event EV_ClearInvItemReference - ( - "clearinvitemref", - EV_DEFAULT, - NULL, - NULL, - "used internally when the inventory is reset\n" - ); +( + "clearinvitemref", + EV_DEFAULT, + NULL, + NULL, + "used internally when the inventory is reset\n" +); -CLASS_DECLARATION( UILabel, UIFakkLabel, NULL ) -{ - { &EV_Layout_PlayerStat, &UIFakkLabel::LayoutPlayerStat }, - { &EV_Layout_PlayerStatConfigstring, &UIFakkLabel::LayoutPlayerStatConfigstring }, - { &EV_Layout_MaxPlayerStat, &UIFakkLabel::LayoutMaxPlayerStat }, - { &EV_Layout_ItemIndex, &UIFakkLabel::LayoutItemIndex }, - { &EV_Layout_InventoryRenderModelIndex, &UIFakkLabel::InventoryRenderModelIndex }, - { &EV_Layout_Statbar, &UIFakkLabel::LayoutStatbar }, - { &EV_Layout_StatbarTileShader, &UIFakkLabel::LayoutStatbarTileShader }, - { &EV_Layout_StatbarShader, &UIFakkLabel::LayoutStatbarShader }, - { &EV_Layout_StatbarTileShader_Flash, &UIFakkLabel::LayoutStatbarTileShader_Flash }, - { &EV_Layout_StatbarShader_Flash, &UIFakkLabel::LayoutStatbarShader_Flash }, - { &EV_Layout_Statbar_EndAngles, &UIFakkLabel::LayoutStatbarEndAngles }, - { &EV_Layout_Statbar_NeedleWidth, &UIFakkLabel::LayoutStatbarNeedleWidth }, - { &EV_Layout_Statbar_RotatorSize, &UIFakkLabel::LayoutStatbarRotatorSize }, - { &EV_Layout_DrawModelName, &UIFakkLabel::LayoutModelName }, - { &EV_Layout_RenderModel, &UIFakkLabel::LayoutRenderModel }, - { &EV_Layout_RenderModelOffset, &UIFakkLabel::LayoutRenderModelOffset }, - { &EV_Layout_RenderModelRotateOffset, &UIFakkLabel::LayoutRenderModelRotateOffset }, - { &EV_Layout_RenderModelAngles, &UIFakkLabel::LayoutRenderModelAngles }, - { &EV_Layout_RenderModelScale, &UIFakkLabel::LayoutRenderModelScale }, - { &EV_Layout_RenderModelAnim, &UIFakkLabel::LayoutRenderModelAnim }, - { &EV_ClearInvItemReference, &UIFakkLabel::ClearInvItemReference }, - { NULL, NULL } +CLASS_DECLARATION(UILabel, UIFakkLabel, NULL) { + {&EV_Layout_PlayerStat, &UIFakkLabel::LayoutPlayerStat }, + {&EV_Layout_PlayerStatAlpha, &UIFakkLabel::LayoutPlayerStatAlpha }, + {&EV_Layout_PlayerStatConfigstring, &UIFakkLabel::LayoutPlayerStatConfigstring }, + {&EV_Layout_MaxPlayerStat, &UIFakkLabel::LayoutMaxPlayerStat }, + {&EV_Layout_ItemIndex, &UIFakkLabel::LayoutItemIndex }, + {&EV_Layout_InventoryRenderModelIndex, &UIFakkLabel::InventoryRenderModelIndex }, + {&EV_Layout_Statbar, &UIFakkLabel::LayoutStatbar }, + {&EV_Layout_StatbarTileShader, &UIFakkLabel::LayoutStatbarTileShader }, + {&EV_Layout_StatbarShader, &UIFakkLabel::LayoutStatbarShader }, + {&EV_Layout_StatbarTileShader_Flash, &UIFakkLabel::LayoutStatbarTileShader_Flash}, + {&EV_Layout_StatbarShader_Marker, &UIFakkLabel::LayoutStatbarShader_Marker }, + {&EV_Layout_StatbarShader_Flash, &UIFakkLabel::LayoutStatbarShader_Flash }, + {&EV_Layout_Statbar_EndAngles, &UIFakkLabel::LayoutStatbarEndAngles }, + {&EV_Layout_Statbar_NeedleWidth, &UIFakkLabel::LayoutStatbarNeedleWidth }, + {&EV_Layout_Statbar_RotatorSize, &UIFakkLabel::LayoutStatbarRotatorSize }, + {&EV_Layout_DrawModelName, &UIFakkLabel::LayoutModelName }, + {&EV_Layout_RenderModel, &UIFakkLabel::LayoutRenderModel }, + {&EV_Layout_RenderModelOffset, &UIFakkLabel::LayoutRenderModelOffset }, + {&EV_Layout_RenderModelRotateOffset, &UIFakkLabel::LayoutRenderModelRotateOffset}, + {&EV_Layout_RenderModelAngles, &UIFakkLabel::LayoutRenderModelAngles }, + {&EV_Layout_RenderModelScale, &UIFakkLabel::LayoutRenderModelScale }, + {&EV_Layout_RenderModelAnim, &UIFakkLabel::LayoutRenderModelAnim }, + {&EV_ClearInvItemReference, &UIFakkLabel::ClearInvItemReference }, + {NULL, NULL } }; UIFakkLabel::UIFakkLabel() { - m_statbar_min = m_statbar_max = -1.0; - m_stat = -1; - m_stat_configstring = -1; - m_maxstat = -1; - m_itemindex = -1; - m_inventoryrendermodelindex = -1; - m_rendermodel = false; - m_statbar_or = L_STATBAR_NONE; - m_statbar_material = NULL; - m_statbar_material_flash = NULL; - m_lastitemindex = -1; + m_statbar_min = m_statbar_max = -1.0; + m_stat = -1; + m_stat_alpha = -1; + m_stat_configstring = -1; + m_maxstat = -1; + m_itemindex = -1; + m_inventoryrendermodelindex = -1; + m_rendermodel = false; + m_statbar_or = L_STATBAR_NONE; + m_statbar_material = NULL; + m_statbar_material_flash = NULL; + m_statbar_material_marker = NULL; + m_lastitemindex = -1; } -void UIFakkLabel::LayoutPlayerStat( Event *ev ) +void UIFakkLabel::LayoutPlayerStat(Event *ev) { - m_stat = ev->GetInteger( 1 ); + m_stat = ev->GetInteger(1); } -void UIFakkLabel::LayoutPlayerStatConfigstring( Event *ev ) +void UIFakkLabel::LayoutPlayerStatAlpha(Event *ev) { - m_stat_configstring = ev->GetInteger( 1 ); + m_stat_alpha = ev->GetInteger(1); } -void UIFakkLabel::LayoutMaxPlayerStat( Event *ev ) +void UIFakkLabel::LayoutPlayerStatConfigstring(Event *ev) { - m_maxstat = ev->GetInteger( 1 ); + m_stat_configstring = ev->GetInteger(1); } -void UIFakkLabel::LayoutItemIndex( Event *ev ) +void UIFakkLabel::LayoutMaxPlayerStat(Event *ev) { - m_itemindex = ev->GetInteger( 1 ); + m_maxstat = ev->GetInteger(1); } -void UIFakkLabel::InventoryRenderModelIndex( Event *ev ) +void UIFakkLabel::LayoutItemIndex(Event *ev) { - m_inventoryrendermodelindex = ev->GetInteger( 1 ); + m_itemindex = ev->GetInteger(1); } -void UIFakkLabel::LayoutModelName( Event *ev ) +void UIFakkLabel::InventoryRenderModelIndex(Event *ev) { - m_sDrawModelName = ev->GetString( 1 ); + m_inventoryrendermodelindex = ev->GetInteger(1); } -void UIFakkLabel::ClearInvItemReference( Event *ev ) +void UIFakkLabel::LayoutModelName(Event *ev) { - m_lastitem = NULL; - m_lastitemindex = -1; + m_sDrawModelName = ev->GetString(1); } -void UIFakkLabel::LayoutStatbar( Event *ev ) +void UIFakkLabel::ClearInvItemReference(Event *ev) { - str _or = ev->GetString( 1 ); - - if( ev->NumArgs() > 1 ) - { - m_statbar_min = ev->GetFloat( 2 ); - m_statbar_max = ev->GetFloat( 3 ); - } - - if( !str::icmp( _or, "horizontal" ) ) - { - m_statbar_or = L_STATBAR_HORIZONTAL; - } - else if( !str::icmp( _or, "vertical_stagger_even" ) ) - { - m_statbar_or = L_STATBAR_VERTICAL_STAGGER_EVEN; - } - else if( !str::icmp( _or, "vertical_stagger_odd" ) ) - { - m_statbar_or = L_STATBAR_VERTICAL_STAGGER_ODD; - } - else if( !str::icmp( _or, "vertical" ) ) - { - m_statbar_or = L_STATBAR_VERTICAL; - } - else if( !str::icmp( _or, "vertical_reverse" ) ) - { - m_statbar_or = L_STATBAR_VERTICAL_REVERSE; - } - else if( !str::icmp( _or, "circular" ) ) - { - m_statbar_or = L_STATBAR_CIRCULAR; - - if( !m_statbar_material ) - { - m_statbar_material = uWinMan.RegisterShader( "blank" ); - } - } - else if( !str::icmp( _or, "needle" ) ) - { - m_statbar_or = L_STATBAR_NEEDLE; - - if( !m_statbar_material ) - { - m_statbar_material = uWinMan.RegisterShader( "blank" ); - } - } - else if( !str::icmp( _or, "rotator" ) ) - { - m_statbar_or = L_STATBAR_ROTATOR; - - if( !m_statbar_material ) - { - m_statbar_material = uWinMan.RegisterShader( "blank" ); - } - } - else if( !str::icmp( _or, "compass" ) ) - { - m_statbar_or = L_STATBAR_COMPASS; - - if( !m_statbar_material ) - { - m_statbar_material = uWinMan.RegisterShader( "blank" ); - } - } - else if( !str::icmp( _or, "spinner" ) ) - { - m_statbar_or = L_STATBAR_SPINNER; - - if( !m_statbar_material ) - { - m_statbar_material = uWinMan.RegisterShader( "blank" ); - } - } - else if( !str::icmp( _or, "headingspinner" ) ) - { - m_statbar_or = L_STATBAR_HEADING_SPINNER; - - if( !m_statbar_material ) - { - m_statbar_material = uWinMan.RegisterShader( "blank" ); - } - } - else - { - warning( "LayoutPlayerStat", "Invalid statbar orientation: \"%s\"", _or.c_str() ); - } + m_lastitem = NULL; + m_lastitemindex = -1; } -void UIFakkLabel::LayoutStatbarShader( Event *ev ) +void UIFakkLabel::LayoutStatbar(Event *ev) { - m_statbar_material = uWinMan.RegisterShader( ev->GetString( 1 ) ); + str _or = ev->GetString(1); + + if (ev->NumArgs() > 1) { + m_statbar_min = ev->GetFloat(2); + m_statbar_max = ev->GetFloat(3); + } + + if (!str::icmp(_or, "horizontal")) { + m_statbar_or = L_STATBAR_HORIZONTAL; + } else if (!str::icmp(_or, "vertical_stagger_even")) { + m_statbar_or = L_STATBAR_VERTICAL_STAGGER_EVEN; + } else if (!str::icmp(_or, "vertical_stagger_odd")) { + m_statbar_or = L_STATBAR_VERTICAL_STAGGER_ODD; + } else if (!str::icmp(_or, "vertical")) { + m_statbar_or = L_STATBAR_VERTICAL; + } else if (!str::icmp(_or, "vertical_reverse")) { + m_statbar_or = L_STATBAR_VERTICAL_REVERSE; + } else if (!str::icmp(_or, "circular")) { + m_statbar_or = L_STATBAR_CIRCULAR; + + if (!m_statbar_material) { + m_statbar_material = uWinMan.RegisterShader("blank"); + } + } else if (!str::icmp(_or, "needle")) { + m_statbar_or = L_STATBAR_NEEDLE; + + if (!m_statbar_material) { + m_statbar_material = uWinMan.RegisterShader("blank"); + } + } else if (!str::icmp(_or, "rotator")) { + m_statbar_or = L_STATBAR_ROTATOR; + + if (!m_statbar_material) { + m_statbar_material = uWinMan.RegisterShader("blank"); + } + } else if (!str::icmp(_or, "compass")) { + m_statbar_or = L_STATBAR_COMPASS; + + if (!m_statbar_material) { + m_statbar_material = uWinMan.RegisterShader("blank"); + } + } else if (!str::icmp(_or, "spinner")) { + m_statbar_or = L_STATBAR_SPINNER; + + if (!m_statbar_material) { + m_statbar_material = uWinMan.RegisterShader("blank"); + } + } else if (!str::icmp(_or, "headingspinner")) { + m_statbar_or = L_STATBAR_HEADING_SPINNER; + + if (!m_statbar_material) { + m_statbar_material = uWinMan.RegisterShader("blank"); + } + } else { + warning("LayoutPlayerStat", "Invalid statbar orientation: \"%s\"", _or.c_str()); + } } -void UIFakkLabel::LayoutStatbarTileShader( Event *ev ) +void UIFakkLabel::LayoutStatbarShader(Event *ev) { - m_statbar_material = uWinMan.RegisterShader( ev->GetString( 1 ) ); - AddFlag( WF_TILESHADER ); + m_statbar_material = uWinMan.RegisterShader(ev->GetString(1)); } -void UIFakkLabel::LayoutStatbarShader_Flash( Event *ev ) +void UIFakkLabel::LayoutStatbarTileShader(Event *ev) { - m_statbar_material_flash = uWinMan.RegisterShader( ev->GetString( 1 ) ); + m_statbar_material = uWinMan.RegisterShader(ev->GetString(1)); + AddFlag(WF_TILESHADER); } -void UIFakkLabel::LayoutStatbarEndAngles( Event *ev ) +void UIFakkLabel::LayoutStatbarShader_Flash(Event *ev) { - m_angles[ 0 ] = ev->GetFloat( 1 ); - m_angles[ 1 ] = ev->GetFloat( 2 ); + m_statbar_material_flash = uWinMan.RegisterShader(ev->GetString(1)); } -void UIFakkLabel::LayoutStatbarNeedleWidth( Event *ev ) +void UIFakkLabel::LayoutStatbarShader_Marker(Event *ev) { - m_angles[ 2 ] = ev->GetFloat( 1 ); + m_statbar_material_marker = uWinMan.RegisterShader(ev->GetString(1)); } -void UIFakkLabel::LayoutStatbarRotatorSize( Event *ev ) +void UIFakkLabel::LayoutStatbarEndAngles(Event *ev) { - m_angles[ 2 ] = ev->GetFloat( 1 ); - - if( ev->NumArgs() > 1 ) { - m_scale = ev->GetFloat( 2 ); - } else { - m_scale = m_angles[ 2 ]; - } + m_angles[0] = ev->GetFloat(1); + m_angles[1] = ev->GetFloat(2); } -void UIFakkLabel::LayoutStatbarTileShader_Flash( Event *ev ) +void UIFakkLabel::LayoutStatbarNeedleWidth(Event *ev) { - m_statbar_material_flash = uWinMan.RegisterShader( ev->GetString( 1 ) ); - AddFlag( WF_TILESHADER ); + m_angles[2] = ev->GetFloat(1); } -void UIFakkLabel::LayoutRenderModel( Event *ev ) +void UIFakkLabel::LayoutStatbarRotatorSize(Event *ev) { - m_rendermodel = ev->GetBoolean( 1 ); + m_angles[2] = ev->GetFloat(1); + + if (ev->NumArgs() > 1) { + m_scale = ev->GetFloat(2); + } else { + m_scale = m_angles[2]; + } } -void UIFakkLabel::LayoutRenderModelOffset( Event *ev ) +void UIFakkLabel::LayoutStatbarTileShader_Flash(Event *ev) { - Vector vec = ev->GetVector( 1 ); - VectorCopy( vec, m_offset ); + m_statbar_material_flash = uWinMan.RegisterShader(ev->GetString(1)); + AddFlag(WF_TILESHADER); } -void UIFakkLabel::LayoutRenderModelRotateOffset( Event *ev ) +void UIFakkLabel::LayoutRenderModel(Event *ev) { - Vector vec = ev->GetVector( 1 ); - VectorCopy( vec, m_rotateoffset ); + m_rendermodel = ev->GetBoolean(1); } -void UIFakkLabel::LayoutRenderModelAngles( Event *ev ) +void UIFakkLabel::LayoutRenderModelOffset(Event *ev) { - Vector vec = ev->GetVector( 1 ); - VectorCopy( vec, m_angles ); + Vector vec = ev->GetVector(1); + VectorCopy(vec, m_offset); } -void UIFakkLabel::LayoutRenderModelScale( Event *ev ) +void UIFakkLabel::LayoutRenderModelRotateOffset(Event *ev) { - m_scale = ev->GetFloat( 1 ); + Vector vec = ev->GetVector(1); + VectorCopy(vec, m_rotateoffset); } -void UIFakkLabel::LayoutRenderModelAnim( Event *ev ) +void UIFakkLabel::LayoutRenderModelAngles(Event *ev) { - m_anim = ev->GetString( 1 ); + Vector vec = ev->GetVector(1); + VectorCopy(vec, m_angles); } -void UIFakkLabel::DrawStatbar( float frac ) +void UIFakkLabel::LayoutRenderModelScale(Event *ev) { - vec4_t col; - float alpha; - - col[0] = col[1] = col[2] = col[3] = 1.0; - - switch (m_statbar_or) - { - case L_STATBAR_CIRCULAR: - DrawStatCircle(frac); - return; - case L_STATBAR_NEEDLE: - DrawStatNeedle(frac); - return; - case L_STATBAR_ROTATOR: - DrawStatRotator(frac); - return; - case L_STATBAR_COMPASS: - DrawStatCompass(frac); - return; - case L_STATBAR_SPINNER: - case L_STATBAR_HEADING_SPINNER: - DrawStatSpinner(frac); - return; - default: - break; - } - - if (!frac) { - return; - } - - if (frac != m_lastfrac) { - m_flashtime = uid.time; - } - m_lastfrac = frac; - - alpha = 1.0 - ((float)uid.time - m_flashtime) / 1500.0; - if (alpha < 0.0) alpha = 0.0; - else if (alpha > 1.0) alpha = 1.0; - - col[3] = alpha; - - if (m_statbar_material) - { - if (m_flags & WF_TILESHADER) - { - switch (m_statbar_or) - { - case L_STATBAR_HORIZONTAL: - { - float width = frac * m_frame.size.width; - - m_statbar_material->ReregisterMaterial(); - re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material->GetMaterial()); - - if (alpha != 0.0 && m_statbar_material_flash) - { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial()); - } - break; - } - case L_STATBAR_VERTICAL: - case L_STATBAR_VERTICAL_REVERSE: - case L_STATBAR_VERTICAL_STAGGER_EVEN: - case L_STATBAR_VERTICAL_STAGGER_ODD: - { - float y = m_frame.size.height * (1.0 - frac); - - m_statbar_material->ReregisterMaterial(); - re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material->GetMaterial()); - - if (alpha != 0.0 && m_statbar_material_flash) - { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial()); - } - break; - } - default: - break; - } - } - else - { - switch (m_statbar_or) - { - case L_STATBAR_HORIZONTAL: - { - float width = frac * m_frame.size.width; - - m_statbar_material->ReregisterMaterial(); - re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material->GetMaterial()); - - if(alpha != 0.0 && m_statbar_material_flash) - { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material_flash->GetMaterial()); - } - break; - } - case L_STATBAR_VERTICAL: - case L_STATBAR_VERTICAL_STAGGER_EVEN: - case L_STATBAR_VERTICAL_STAGGER_ODD: - { - float y = m_frame.size.height * (1.0 - frac); - float height = m_frame.size.height * frac; - - m_statbar_material->ReregisterMaterial(); - re.DrawStretchPic(0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material->GetMaterial()); - - if (alpha != 0.0 && m_statbar_material_flash) - { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawStretchPic(0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material_flash->GetMaterial()); - } - break; - } - case L_STATBAR_VERTICAL_REVERSE: - { - float height = m_frame.size.height * frac; - - m_statbar_material->ReregisterMaterial(); - re.DrawStretchPic(0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material->GetMaterial()); - - if (alpha != 0.0 && m_statbar_material_flash) - { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawStretchPic(0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material_flash->GetMaterial()); - } - break; - } - default: - break; - } - } - } - else - { - switch (m_statbar_or) - { - case L_STATBAR_VERTICAL: - case L_STATBAR_VERTICAL_STAGGER_EVEN: - case L_STATBAR_VERTICAL_STAGGER_ODD: - DrawBox( - 0.0, - m_frame.size.height * (1.0 - frac), - m_frame.size.width, - m_frame.size.height, - m_foreground_color, - 1.0 - ); - break; - case L_STATBAR_HORIZONTAL: - DrawBox( - 0.0, - 0.0, - frac * m_frame.size.width, - m_frame.size.height, - m_foreground_color, - 1.0 - ); - break; - default: - break; - } - } + m_scale = ev->GetFloat(1); } -void UIFakkLabel::DrawStatCircle( float frac ) +void UIFakkLabel::LayoutRenderModelAnim(Event *ev) { - vec4_t col; - float alpha; - float fCurrAng, fEndAng, fNextAng; - vec2_t vVerts[3]; - vec2_t vTexCoords[3]; + m_anim = ev->GetString(1); +} + +void UIFakkLabel::DrawStatbar(float frac) +{ + vec4_t col; + float alpha; + qhandle_t hMat; + float w, h; + float fvWidth, fvHeight; + + col[0] = col[1] = col[2] = col[3] = 1.0; + + switch (m_statbar_or) { + case L_STATBAR_CIRCULAR: + DrawStatCircle(frac); + return; + case L_STATBAR_NEEDLE: + DrawStatNeedle(frac); + return; + case L_STATBAR_ROTATOR: + DrawStatRotator(frac); + return; + case L_STATBAR_COMPASS: + DrawStatCompass(frac); + return; + case L_STATBAR_SPINNER: + case L_STATBAR_HEADING_SPINNER: + DrawStatSpinner(frac); + return; + default: + break; + } + + if (!frac) { + return; + } + + if (frac != m_lastfrac) { + m_flashtime = uid.time; + } + m_lastfrac = frac; + + alpha = 1.0 - ((float)uid.time - m_flashtime) / 1500.0; + alpha = Q_clamp_float(alpha, 0, 1); + + col[3] = alpha; + + if (m_statbar_material) { + if (m_flags & WF_TILESHADER) { + switch (m_statbar_or) { + case L_STATBAR_HORIZONTAL: + { + float width = frac * m_frame.size.width; + + fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material->GetMaterial()); + fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material->GetMaterial()); + + re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material->GetMaterial()); + //re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material->GetMaterial()); + + if (alpha != 0.0 && m_statbar_material_flash) { + re.SetColor(col); + + fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material_flash->GetMaterial()); + fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material_flash->GetMaterial()); + + re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material_flash->GetMaterial()); + //re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial()); + } + + if (m_statbar_material_marker) { + hMat = m_statbar_material_marker->GetMaterial(); + w = re.GetShaderWidth(hMat); + h = re.GetShaderHeight(hMat); + + re.DrawStretchPic( + m_frame.size.width * frac - w * 0.5, + m_frame.size.height * 0.5 - h * 0.5, + w, + h, + 0, + 0, + 1, + 1, + hMat + ); + } + break; + } + case L_STATBAR_VERTICAL: + case L_STATBAR_VERTICAL_REVERSE: + case L_STATBAR_VERTICAL_STAGGER_EVEN: + case L_STATBAR_VERTICAL_STAGGER_ODD: + { + float y = m_frame.size.height * (1.0 - frac); + + fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material->GetMaterial()); + fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material->GetMaterial()); + + re.DrawStretchPic(0.0, y, m_frame.size.width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material->GetMaterial()); + //re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material->GetMaterial()); + + if (alpha != 0.0 && m_statbar_material_flash) { + re.SetColor(col); + + fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material_flash->GetMaterial()); + fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material_flash->GetMaterial()); + + re.DrawStretchPic(0.0, y, m_frame.size.width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material_flash->GetMaterial()); + //re.DrawTilePic( + // 0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial() + //); + } + + if (m_statbar_material_marker) { + hMat = m_statbar_material_marker->GetMaterial(); + w = re.GetShaderWidth(hMat); + h = re.GetShaderHeight(hMat); + + re.DrawStretchPic( + m_frame.size.width * frac - w * 0.5, + m_frame.size.height * 0.5 - h * 0.5, + w, + h, + 0, + 0, + 1, + 1, + hMat + ); + } + break; + } + default: + break; + } + } else { + switch (m_statbar_or) { + case L_STATBAR_HORIZONTAL: + { + float width = frac * m_frame.size.width; + + re.DrawStretchPic( + 0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material->GetMaterial() + ); + + if (alpha != 0.0 && m_statbar_material_flash) { + re.SetColor(col); + re.DrawStretchPic( + 0.0, + 0.0, + width, + m_frame.size.height, + 0.0, + 0.0, + 1.0, + 1.0, + m_statbar_material_flash->GetMaterial() + ); + } + + if (m_statbar_material_marker) { + hMat = m_statbar_material_marker->GetMaterial(); + w = re.GetShaderWidth(hMat); + h = re.GetShaderHeight(hMat); + + re.DrawStretchPic( + m_frame.size.width * frac - w * 0.5, + m_frame.size.height * 0.5 - h * 0.5, + w, + h, + 0, + 0, + 1, + 1, + hMat + ); + } + break; + } + case L_STATBAR_VERTICAL: + case L_STATBAR_VERTICAL_STAGGER_EVEN: + case L_STATBAR_VERTICAL_STAGGER_ODD: + { + float y = m_frame.size.height * (1.0 - frac); + float height = m_frame.size.height * frac; + + re.DrawStretchPic( + 0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material->GetMaterial() + ); + + if (alpha != 0.0 && m_statbar_material_flash) { + re.SetColor(col); + re.DrawStretchPic( + 0.0, + y, + m_frame.size.width, + height, + 0.0, + 1.0 - frac, + 1.0, + 1.0, + m_statbar_material_flash->GetMaterial() + ); + } + + if (m_statbar_material_marker) { + hMat = m_statbar_material_marker->GetMaterial(); + w = re.GetShaderWidth(hMat); + h = re.GetShaderHeight(hMat); + + re.DrawStretchPic( + m_frame.size.width * frac - w * 0.5, + m_frame.size.height * 0.5 - h * 0.5, + w, + h, + 0, + 0, + 1, + 1, + hMat + ); + } + break; + } + case L_STATBAR_VERTICAL_REVERSE: + { + float height = m_frame.size.height * frac; + + re.DrawStretchPic( + 0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material->GetMaterial() + ); + + if (alpha != 0.0 && m_statbar_material_flash) { + re.SetColor(col); + re.DrawStretchPic( + 0.0, + 0.0, + m_frame.size.width, + height, + 0.0, + 0.0, + 1.0, + frac, + m_statbar_material_flash->GetMaterial() + ); + } + break; + } + default: + break; + } + } + } else { + switch (m_statbar_or) { + case L_STATBAR_VERTICAL: + case L_STATBAR_VERTICAL_STAGGER_EVEN: + case L_STATBAR_VERTICAL_STAGGER_ODD: + DrawBox( + 0.0, + m_frame.size.height * (1.0 - frac), + m_frame.size.width, + m_frame.size.height, + m_foreground_color, + 1.0 + ); + break; + case L_STATBAR_HORIZONTAL: + DrawBox(0.0, 0.0, frac * m_frame.size.width, m_frame.size.height, m_foreground_color, 1.0); + break; + default: + break; + } + } +} + +void UIFakkLabel::DrawStatCircle(float frac) +{ + vec4_t col; + float alpha; + float fCurrAng, fEndAng, fNextAng; + vec2_t vVerts[3]; + vec2_t vTexCoords[3]; col[0] = 1.f; col[1] = 1.f; @@ -631,190 +730,181 @@ void UIFakkLabel::DrawStatCircle( float frac ) m_lastfrac = frac; alpha = 1.f - (uid.time - m_flashtime) / 1500.f; - if (alpha < 0.f) alpha = 0.f; - else if (alpha > 1.f) alpha = 1.f; + if (alpha < 0.f) { + alpha = 0.f; + } else if (alpha > 1.f) { + alpha = 1.f; + } col[3] = alpha; - vVerts[0][0] = m_frame.size.width * 0.5f; - vVerts[0][1] = m_frame.size.height * 0.5f; - vTexCoords[0][0] = 0.5f; - vTexCoords[0][1] = 0.5f; + vVerts[0][0] = m_frame.size.width * 0.5f; + vVerts[0][1] = m_frame.size.height * 0.5f; + vTexCoords[0][0] = 0.5f; + vTexCoords[0][1] = 0.5f; - if (ui_health_start->value && ui_health_end->value) { - m_angles[0] = ui_health_start->value; - m_angles[1] = ui_health_end->value; - } + if (ui_health_start->value && ui_health_end->value) { + m_angles[0] = ui_health_start->value; + m_angles[1] = ui_health_end->value; + } - fCurrAng = m_angles[0]; - fEndAng = frac * (m_angles[1] - fCurrAng) + fCurrAng; + fCurrAng = m_angles[0]; + fEndAng = frac * (m_angles[1] - fCurrAng) + fCurrAng; if (m_angles[1] > fCurrAng) { StatCircleTexCoord(fCurrAng, vTexCoords[1]); vVerts[1][0] = m_frame.size.width * vTexCoords[1][0]; vVerts[1][1] = m_frame.size.height * vTexCoords[1][1]; - - if ((int)fCurrAng - (((int)fCurrAng - 45) % 90 + 90) % 90 == (int)fEndAng - (((int)fEndAng - 45) % 90 + 90) % 90) - { + + if ((int)fCurrAng - (((int)fCurrAng - 45) % 90 + 90) % 90 + == (int)fEndAng - (((int)fEndAng - 45) % 90 + 90) % 90) { StatCircleTexCoord(fEndAng, vTexCoords[2]); vVerts[2][0] = m_frame.size.width * vTexCoords[2][0]; vVerts[2][1] = m_frame.size.height * vTexCoords[2][1]; - + if (alpha && m_statbar_material_flash) { re.SetColor(m_foreground_color); } - m_statbar_material->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); if (alpha && m_statbar_material_flash) { re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); } - } - else - { - while (fCurrAng > fEndAng) - { - fNextAng = ((int)fCurrAng - (((int)fCurrAng - 45) % 90 + 90) % 90) + 90.0; - if (fNextAng > fEndAng) { - fNextAng = fEndAng; - } + } else { + while (fCurrAng > fEndAng) { + fNextAng = ((int)fCurrAng - (((int)fCurrAng - 45) % 90 + 90) % 90) + 90.0; + if (fNextAng > fEndAng) { + fNextAng = fEndAng; + } StatCircleTexCoord(fNextAng, vTexCoords[2]); vVerts[2][0] = m_frame.size.width * vTexCoords[2][0]; vVerts[2][1] = m_frame.size.height * vTexCoords[2][1]; - if (alpha && m_statbar_material_flash) { - re.SetColor(m_foreground_color); - } - - m_statbar_material->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); - - if (alpha && m_statbar_material_flash) { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); - } - - vTexCoords[1][0] = vTexCoords[2][0]; - vTexCoords[1][1] = vTexCoords[2][1]; - vVerts[1][0] = vVerts[2][0]; - vVerts[1][1] = vVerts[2][1]; - fCurrAng = fNextAng; - } - } - } else { - StatCircleTexCoord(fCurrAng, vTexCoords[2]); - vVerts[2][0] = m_frame.size.width * vTexCoords[2][0]; - vVerts[2][1] = m_frame.size.height * vTexCoords[2][1]; - if ((int)fCurrAng - (((int)fCurrAng - 45) % 90 + 90) % 90 == (int)fEndAng - - (((int)fEndAng - 45) % 90 + 90) % 90) - { - StatCircleTexCoord(fEndAng, vTexCoords[1]); - vVerts[1][0] = m_frame.size.width * vTexCoords[1][0]; - vVerts[1][1] = m_frame.size.height * vTexCoords[1][1]; - - if (alpha && m_statbar_material_flash) { - re.SetColor(m_foreground_color); - } - - m_statbar_material->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); - - if (alpha && m_statbar_material_flash) { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); - } - } - else - { - while (fCurrAng > fEndAng) - { - fNextAng = ((int)fCurrAng - (((int)fCurrAng + 45) % 90 + 90) % 90); - if (fNextAng == fCurrAng) { - fNextAng -= 90.f; - } - - if (fNextAng < fEndAng) { - fNextAng = fEndAng; - } - - StatCircleTexCoord(fNextAng, vTexCoords[1]); - vVerts[1][0] = m_frame.size.width * vTexCoords[1][0]; - vVerts[1][1] = m_frame.size.height * vTexCoords[1][1]; - if (alpha && m_statbar_material_flash) { re.SetColor(m_foreground_color); } - m_statbar_material->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); if (alpha && m_statbar_material_flash) { re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); + } + + vTexCoords[1][0] = vTexCoords[2][0]; + vTexCoords[1][1] = vTexCoords[2][1]; + vVerts[1][0] = vVerts[2][0]; + vVerts[1][1] = vVerts[2][1]; + fCurrAng = fNextAng; + } + } + } else { + StatCircleTexCoord(fCurrAng, vTexCoords[2]); + vVerts[2][0] = m_frame.size.width * vTexCoords[2][0]; + vVerts[2][1] = m_frame.size.height * vTexCoords[2][1]; + if ((int)fCurrAng - (((int)fCurrAng - 45) % 90 + 90) % 90 + == (int)fEndAng - (((int)fEndAng - 45) % 90 + 90) % 90) { + StatCircleTexCoord(fEndAng, vTexCoords[1]); + vVerts[1][0] = m_frame.size.width * vTexCoords[1][0]; + vVerts[1][1] = m_frame.size.height * vTexCoords[1][1]; + + if (alpha && m_statbar_material_flash) { + re.SetColor(m_foreground_color); + } + + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); + + if (alpha && m_statbar_material_flash) { + re.SetColor(col); + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); + } + } else { + while (fCurrAng > fEndAng) { + fNextAng = ((int)fCurrAng - (((int)fCurrAng + 45) % 90 + 90) % 90); + if (fNextAng == fCurrAng) { + fNextAng -= 90.f; + } + + if (fNextAng < fEndAng) { + fNextAng = fEndAng; + } + + StatCircleTexCoord(fNextAng, vTexCoords[1]); + vVerts[1][0] = m_frame.size.width * vTexCoords[1][0]; + vVerts[1][1] = m_frame.size.height * vTexCoords[1][1]; + + if (alpha && m_statbar_material_flash) { + re.SetColor(m_foreground_color); + } + + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); + + if (alpha && m_statbar_material_flash) { + re.SetColor(col); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); } vTexCoords[2][0] = vTexCoords[1][0]; vTexCoords[2][1] = vTexCoords[1][1]; - vVerts[2][0] = vVerts[1][0]; - vVerts[2][1] = vVerts[1][1]; - fCurrAng = fNextAng; - } - } - } + vVerts[2][0] = vVerts[1][0]; + vVerts[2][1] = vVerts[1][1]; + fCurrAng = fNextAng; + } + } + } } -void UIFakkLabel::DrawStatNeedle( float frac ) +void UIFakkLabel::DrawStatNeedle(float frac) { - vec4_t col; - float alpha; - float fTargAng; - float fSinVal; - float fCosVal; - vec2_t vCenter; - vec2_t vVerts[3]; - vec2_t vTexCoords[3]; - vec2_t vNeedleDir; - vec2_t vSideDir; + vec4_t col; + float alpha; + float fTargAng; + float fSinVal; + float fCosVal; + vec2_t vCenter; + vec2_t vVerts[3]; + vec2_t vTexCoords[3]; + vec2_t vNeedleDir; + vec2_t vSideDir; - col[0] = 1.f; - col[1] = 1.f; - col[2] = 1.f; - col[3] = 1.f; + col[0] = 1.f; + col[1] = 1.f; + col[2] = 1.f; + col[3] = 1.f; - if (m_lastfrac != frac) { - m_flashtime = uid.time; - } - m_lastfrac = frac; + if (m_lastfrac != frac) { + m_flashtime = uid.time; + } + m_lastfrac = frac; - alpha = 1.f - (uid.time - m_flashtime) / 1500.f; - if (alpha < 0.f) alpha = 0.f; - else if (alpha > 1.f) alpha = 1.f; + alpha = 1.f - (uid.time - m_flashtime) / 1500.f; + if (alpha < 0.f) { + alpha = 0.f; + } else if (alpha > 1.f) { + alpha = 1.f; + } - col[3] = alpha; + col[3] = alpha; - fTargAng = DEG2RAD(frac * (m_angles[1] - m_angles[0]) + m_angles[0]); - fSinVal = sin(fTargAng); - fCosVal = cos(fTargAng); + fTargAng = DEG2RAD(frac * (m_angles[1] - m_angles[0]) + m_angles[0]); + fSinVal = sin(fTargAng); + fCosVal = cos(fTargAng); - vSideDir[0] = m_frame.size.width * 0.5f; - vSideDir[1] = m_frame.size.height * 0.5f; - vCenter[0] = m_frame.size.width + fSinVal * vSideDir[0]; - vCenter[1] = m_frame.size.height + -fCosVal * vSideDir[1]; - vNeedleDir[0] = m_angles[2] * fCosVal; - vNeedleDir[1] = m_angles[2] * fSinVal; + vSideDir[0] = m_frame.size.width * 0.5f; + vSideDir[1] = m_frame.size.height * 0.5f; + vCenter[0] = m_frame.size.width + fSinVal * vSideDir[0]; + vCenter[1] = m_frame.size.height + -fCosVal * vSideDir[1]; + vNeedleDir[0] = m_angles[2] * fCosVal; + vNeedleDir[1] = m_angles[2] * fSinVal; - vVerts[0][0] = vCenter[0] - vNeedleDir[0]; - vVerts[0][1] = vCenter[1] - vNeedleDir[1]; - vVerts[1][0] = vCenter[0] + vNeedleDir[0]; - vVerts[1][1] = vCenter[1] + vNeedleDir[1]; - vVerts[2][0] = vSideDir[0] - vNeedleDir[1] - vNeedleDir[0]; - vVerts[2][1] = vSideDir[1] + vNeedleDir[0] - vNeedleDir[1]; + vVerts[0][0] = vCenter[0] - vNeedleDir[0]; + vVerts[0][1] = vCenter[1] - vNeedleDir[1]; + vVerts[1][0] = vCenter[0] + vNeedleDir[0]; + vVerts[1][1] = vCenter[1] + vNeedleDir[1]; + vVerts[2][0] = vSideDir[0] - vNeedleDir[1] - vNeedleDir[0]; + vVerts[2][1] = vSideDir[1] + vNeedleDir[0] - vNeedleDir[1]; vTexCoords[0][0] = 0.f; vTexCoords[0][1] = 0.f; @@ -823,51 +913,47 @@ void UIFakkLabel::DrawStatNeedle( float frac ) vTexCoords[2][0] = 0.f; vTexCoords[2][1] = 1.f; - if (alpha != 0.f) { - re.SetColor(m_foreground_color); - } + if (alpha != 0.f) { + re.SetColor(m_foreground_color); + } - m_statbar_material->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); - if (alpha != 0.f && m_statbar_material_flash) { - re.SetColor(col); - m_statbar_material_flash->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); - } + if (alpha != 0.f && m_statbar_material_flash) { + re.SetColor(col); + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); + } - vVerts[0][0] = vVerts[2][0]; - vVerts[0][1] = vVerts[2][1]; - vVerts[2][0] = m_angles[2] * vCenter[0] + m_frame.size.width * 0.5f - m_angles[2] * vCenter[1]; - vVerts[2][1] = m_angles[2] * vCenter[1] + m_frame.size.height * 0.5f - m_angles[2] * -vCenter[0]; + vVerts[0][0] = vVerts[2][0]; + vVerts[0][1] = vVerts[2][1]; + vVerts[2][0] = m_angles[2] * vCenter[0] + m_frame.size.width * 0.5f - m_angles[2] * vCenter[1]; + vVerts[2][1] = m_angles[2] * vCenter[1] + m_frame.size.height * 0.5f - m_angles[2] * -vCenter[0]; vTexCoords[0][0] = vTexCoords[2][0]; vTexCoords[0][1] = vTexCoords[2][1]; - if (alpha != 0.f && m_statbar_material_flash) { - re.SetColor(m_foreground_color); - } + if (alpha != 0.f && m_statbar_material_flash) { + re.SetColor(m_foreground_color); + } - m_statbar_material->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); - if (alpha != 0.f && m_statbar_material_flash) { - m_statbar_material_flash->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); - } + if (alpha != 0.f && m_statbar_material_flash) { + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); + } } -void UIFakkLabel::DrawStatRotator( float frac ) +void UIFakkLabel::DrawStatRotator(float frac) { - vec4_t col; - float alpha; - float fTargAng; - float fSinVal, fCosVal; + vec4_t col; + float alpha; + float fTargAng; + float fSinVal, fCosVal; vec2_t vCenter; vec2_t vVerts[3]; vec2_t vTexCoords[3]; vec2_t vNeedleDir; - vec2_t vSize; + vec2_t vSize; col[0] = 1.f; col[1] = 1.f; @@ -880,288 +966,261 @@ void UIFakkLabel::DrawStatRotator( float frac ) m_lastfrac = frac; alpha = 1.f - (uid.time - m_flashtime) / 1500.f; - if (alpha < 0.f) alpha = 0.f; - else if (alpha > 1.f) alpha = 1.f; + if (alpha < 0.f) { + alpha = 0.f; + } else if (alpha > 1.f) { + alpha = 1.f; + } col[3] = alpha; - fTargAng = DEG2RAD(frac * (m_angles[1] - m_angles[0]) + m_angles[0]); - fSinVal = sin(fTargAng); - fCosVal = cos(fTargAng); - vNeedleDir[0] = fSinVal; - vNeedleDir[1] = -fCosVal; + fTargAng = DEG2RAD(frac * (m_angles[1] - m_angles[0]) + m_angles[0]); + fSinVal = sin(fTargAng); + fCosVal = cos(fTargAng); + vNeedleDir[0] = fSinVal; + vNeedleDir[1] = -fCosVal; - vSize[0] = (m_frame.size.width + m_frame.size.height) / m_frame.size.width * m_angles[2] * m_vVirtualScale[0]; - vSize[1] = (m_frame.size.width + m_frame.size.height) / m_frame.size.height * m_scale * m_vVirtualScale[1]; + vSize[0] = (m_frame.size.width + m_frame.size.height) / m_frame.size.width * m_angles[2] * getVirtualScale()[0]; + vSize[1] = (m_frame.size.width + m_frame.size.height) / m_frame.size.height * m_scale * getVirtualScale()[1]; - vCenter[0] = (m_frame.size.width * 0.5f - vSize[0]) * vNeedleDir[0] + m_frame.size.width * 0.5f; - vCenter[1] = (m_frame.size.height * 0.5f - vSize[1]) * vNeedleDir[1] + m_frame.size.height * 0.5f; + vCenter[0] = (m_frame.size.width * 0.5f - vSize[0]) * vNeedleDir[0] + m_frame.size.width * 0.5f; + vCenter[1] = (m_frame.size.height * 0.5f - vSize[1]) * vNeedleDir[1] + m_frame.size.height * 0.5f; - vVerts[0][0] = vCenter[0] - vSize[0]; - vVerts[0][1] = vCenter[1] - vSize[1]; - vVerts[1][0] = vCenter[0] + vSize[0]; - vVerts[1][1] = vCenter[1] - vSize[1]; - vVerts[2][0] = vCenter[0] - vSize[0]; - vVerts[2][1] = vCenter[1] + vSize[1]; + vVerts[0][0] = vCenter[0] - vSize[0]; + vVerts[0][1] = vCenter[1] - vSize[1]; + vVerts[1][0] = vCenter[0] + vSize[0]; + vVerts[1][1] = vCenter[1] - vSize[1]; + vVerts[2][0] = vCenter[0] - vSize[0]; + vVerts[2][1] = vCenter[1] + vSize[1]; vTexCoords[0][0] = 0.f; vTexCoords[0][1] = 0.f; - vTexCoords[1][0] = 1.f; - vTexCoords[1][1] = 0.f; - vTexCoords[2][0] = 0.f; - vTexCoords[2][1] = 1.f; + vTexCoords[1][0] = 1.f; + vTexCoords[1][1] = 0.f; + vTexCoords[2][0] = 0.f; + vTexCoords[2][1] = 1.f; if (alpha != 0.f && m_statbar_material_flash) { re.SetColor(m_foreground_color); } - m_statbar_material->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); if (alpha != 0.f && m_statbar_material_flash) { - m_statbar_material_flash->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); } vVerts[0][0] = vVerts[2][0]; vVerts[0][1] = vVerts[2][1]; - vVerts[2][0] = vCenter[0] + vSize[0]; - vVerts[2][1] = vCenter[1] + vSize[1]; + vVerts[2][0] = vCenter[0] + vSize[0]; + vVerts[2][1] = vCenter[1] + vSize[1]; vTexCoords[0][0] = vTexCoords[2][0]; vTexCoords[0][1] = vTexCoords[2][1]; - vTexCoords[2][0] = 1.f; - vTexCoords[2][1] = 1.f; + vTexCoords[2][0] = 1.f; + vTexCoords[2][1] = 1.f; if (alpha != 0.f && m_statbar_material_flash) { re.SetColor(m_foreground_color); } - m_statbar_material->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); if (alpha != 0.f && m_statbar_material_flash) { - m_statbar_material_flash->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); } } -void UIFakkLabel::DrawStatCompass( float frac ) -{ - vec4_t col; - float fTargAng; - float fSinVal, fCosVal; - vec2_t vCenter; - vec2_t vVerts[3]; - vec2_t vTexCoords[3]; - vec2_t vCompassDir; - vec2_t vSideDir; - - col[0] = col[1] = col[2] = col[3] = 1.0; - - if (!cge) { - return; - } - - static int iLastCompassTime = -9999, iLastTimeDelta = 0; - static float fLastPitch = 0, fLastYaw = 0, fLastYawDelta = 0; - static float fYawOffset = 0, fYawSpeed = 0; - static float fNeedleOffset = 0, fNeedleSpeed = 0; - int iTimeCount, iTimeDelta; - float fYawDelta, fYawDeltaDiff; - vec3_t vViewAngles; - - cge->CG_EyeAngles(&vViewAngles); - - vViewAngles[1] -= cl.snap.ps.stats[STAT_COMPASSNORTH] / 182.0f; - - iTimeCount = uid.time - iLastCompassTime; - if (iTimeCount <= 1000) - { - fYawDelta = AngleSubtract(vViewAngles[1], fLastYaw); - if (fYawDelta > 0.1) - { - if ((fYawDelta > 0.0 && fLastYawDelta < fYawDelta) - || (fYawDelta < 0.0 && fLastYawDelta > fYawDelta)) - { - - fYawSpeed += (fYawDelta - fLastYawDelta) * 0.75; - fYawOffset += (fYawDelta - fLastYawDelta) * 0.75; - } - - if (fYawSpeed > 90.0) { - fYawSpeed = 90.0; - } - else if (fYawSpeed < 0.05) { - fYawSpeed = 0.05; - } - - } - - while (iTimeCount > 0) - { - iTimeDelta = iTimeCount; - if (iTimeCount > 15) { - iTimeDelta = 15; - } - iTimeCount -= iTimeDelta; - - if (fabs(fYawOffset) >= 0.1 || fabs(fYawSpeed) >= 0.01) - { - fYawOffset += fYawSpeed * iTimeDelta; - if (fYawOffset > 0.0) { - fYawSpeed -= iTimeDelta * 0.00175; - } - else if (fYawOffset < 0.0) { - fYawSpeed += iTimeDelta * 0.00175; - } - - if (fYawOffset > 40.0) { - fYawOffset = 40.0; - fYawSpeed = 0.0; - } - else if (fYawOffset < -40.0) { - fYawOffset = -40.0; - fYawSpeed = 0.0; - } - - fYawSpeed -= iTimeDelta * 0.003; - if (fYawSpeed > 0.0) { - fYawSpeed -= iTimeDelta * 0.0004; - } - else { - fYawSpeed += iTimeDelta * 0.0004; - if (fYawSpeed > 0.0) { - fYawSpeed = 0.0; - } - } - } - else - { - iTimeCount = 0; - fYawOffset = 0.0; - fYawSpeed = 0.0; - } - } - - fLastYawDelta = fYawDelta; - iLastTimeDelta = uid.time - iLastCompassTime; - } - else - { - fLastYawDelta = 0; - fYawOffset = 0; - fYawSpeed = 0; - iLastTimeDelta = 0; - } - - fLastPitch = vViewAngles[0]; - fLastYaw = vViewAngles[1]; - iLastCompassTime = uid.time; - - if (iLastTimeDelta) - { - if (fabs(fLastYawDelta) > 0.1) { - fNeedleOffset -= fLastYawDelta; - } - - iTimeCount = iLastTimeDelta; - while (iTimeCount > 0) - { - iTimeDelta = iTimeCount; - if (iTimeCount > 15) { - iTimeDelta = 15; - } - iTimeCount -= iTimeDelta; - - if (fabs(fNeedleOffset) >= 0.1 || fabs(fNeedleSpeed) >= 0.01) { - - fNeedleOffset += iTimeDelta * fNeedleSpeed; - if (fNeedleOffset > 180.0) { - fNeedleOffset -= 360.0; - } - else if (fNeedleOffset < -180.0) { - fNeedleOffset += 360.0; - } - - if (fNeedleOffset > 0.0) { - fNeedleSpeed -= iTimeDelta * 0.00175; - } - else if (fNeedleOffset < 0.0) { - fNeedleSpeed += iTimeDelta * 0.00175; - } - - fNeedleSpeed -= fNeedleSpeed * 0.0025 * iTimeDelta; - if (fNeedleSpeed > 0.0) { - fNeedleSpeed -= iTimeDelta * 0.00035; - if (fNeedleSpeed < 0.0) { - fNeedleSpeed = 0.0; - } - } - else { - fNeedleSpeed += iTimeDelta * 0.00035; - if (fNeedleSpeed > 0.0) { - fNeedleSpeed = 0.0; - } - } - } else { - iTimeCount = 0; - fNeedleOffset = 0.0; - fNeedleSpeed = 0.0; - } - } - } - else - { - fNeedleOffset = 0.0; - fNeedleSpeed = 0.0; - } - - fSinVal = sin(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI)); - fCosVal = cos(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI)); - - vCompassDir[0] = fSinVal; - vCompassDir[1] = -fCosVal; - - vCenter[0] = m_frame.size.width * 0.5; - vCenter[1] = m_frame.size.height * 0.5; - vTexCoords[0][0] = 0.0; - vTexCoords[0][1] = 0.0; - vTexCoords[1][0] = 1.0; - vTexCoords[1][1] = 0.0; - vTexCoords[2][0] = 0.0; - vTexCoords[2][1] = 1.0; - - vVerts[0][0] = vCenter[0] + vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1]; - vVerts[1][0] = vCenter[0] + vCompassDir[0] * vCenter[0] + fCosVal * vCenter[1]; - vVerts[2][0] = vCenter[0] - vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1]; - vVerts[0][1] = vCenter[1] + vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0]; - vVerts[1][1] = vCenter[1] + vCompassDir[1] * vCenter[1] + fSinVal * vCenter[0]; - vVerts[2][1] = vCenter[1] - vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0]; - - m_statbar_material->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); - - vVerts[0][0] = vVerts[2][0]; - vVerts[0][1] = vVerts[2][1]; - vTexCoords[0][0] = vTexCoords[2][0]; - vTexCoords[0][1] = vTexCoords[2][1]; - vTexCoords[2][0] = 1.0; - vTexCoords[2][1] = 1.0; - - vVerts[2][0] = vCenter[0] + fCosVal * vCenter[1] - vCompassDir[0] * vCenter[0]; - vVerts[2][1] = vCenter[1] * fSinVal + vCenter[0] - vCompassDir[1] * vCenter[1]; - - m_statbar_material->ReregisterMaterial(); - re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); -} - -void UIFakkLabel::DrawStatSpinner( float frac ) +void UIFakkLabel::DrawStatCompass(float frac) { vec4_t col; - float alpha; - float fTargAng; - float fSinVal, fCosVal; + float fTargAng; + float fSinVal, fCosVal; + vec2_t vCenter; + vec2_t vVerts[3]; + vec2_t vTexCoords[3]; + vec2_t vCompassDir; + vec2_t vSideDir; + + col[0] = col[1] = col[2] = col[3] = 1.0; + + if (!cge) { + return; + } + + static int iLastCompassTime = -9999, iLastTimeDelta = 0; + static float fLastPitch = 0, fLastYaw = 0, fLastYawDelta = 0; + static float fYawOffset = 0, fYawSpeed = 0; + static float fNeedleOffset = 0, fNeedleSpeed = 0; + int iTimeCount, iTimeDelta; + float fYawDelta, fYawDeltaDiff; + vec3_t vViewAngles; + + cge->CG_EyeAngles(&vViewAngles); + + vViewAngles[1] -= cl.snap.ps.stats[STAT_COMPASSNORTH] / 182.0f; + + iTimeCount = uid.time - iLastCompassTime; + if (iTimeCount <= 1000) { + fYawDelta = AngleSubtract(vViewAngles[1], fLastYaw); + if (fYawDelta > 0.1) { + if ((fYawDelta > 0.0 && fLastYawDelta < fYawDelta) || (fYawDelta < 0.0 && fLastYawDelta > fYawDelta)) { + fYawSpeed += (fYawDelta - fLastYawDelta) * 0.75; + fYawOffset += (fYawDelta - fLastYawDelta) * 0.75; + } + + if (fYawSpeed > 90.0) { + fYawSpeed = 90.0; + } else if (fYawSpeed < 0.05) { + fYawSpeed = 0.05; + } + } + + while (iTimeCount > 0) { + iTimeDelta = iTimeCount; + if (iTimeCount > 15) { + iTimeDelta = 15; + } + iTimeCount -= iTimeDelta; + + if (fabs(fYawOffset) >= 0.1 || fabs(fYawSpeed) >= 0.01) { + fYawOffset += fYawSpeed * iTimeDelta; + if (fYawOffset > 0.0) { + fYawSpeed -= iTimeDelta * 0.00175; + } else if (fYawOffset < 0.0) { + fYawSpeed += iTimeDelta * 0.00175; + } + + if (fYawOffset > 40.0) { + fYawOffset = 40.0; + fYawSpeed = 0.0; + } else if (fYawOffset < -40.0) { + fYawOffset = -40.0; + fYawSpeed = 0.0; + } + + fYawSpeed -= iTimeDelta * 0.003; + if (fYawSpeed > 0.0) { + fYawSpeed -= iTimeDelta * 0.0004; + } else { + fYawSpeed += iTimeDelta * 0.0004; + if (fYawSpeed > 0.0) { + fYawSpeed = 0.0; + } + } + } else { + iTimeCount = 0; + fYawOffset = 0.0; + fYawSpeed = 0.0; + } + } + + fLastYawDelta = fYawDelta; + iLastTimeDelta = uid.time - iLastCompassTime; + } else { + fLastYawDelta = 0; + fYawOffset = 0; + fYawSpeed = 0; + iLastTimeDelta = 0; + } + + fLastPitch = vViewAngles[0]; + fLastYaw = vViewAngles[1]; + iLastCompassTime = uid.time; + + if (iLastTimeDelta) { + if (fabs(fLastYawDelta) > 0.1) { + fNeedleOffset -= fLastYawDelta; + } + + iTimeCount = iLastTimeDelta; + while (iTimeCount > 0) { + iTimeDelta = iTimeCount; + if (iTimeCount > 15) { + iTimeDelta = 15; + } + iTimeCount -= iTimeDelta; + + if (fabs(fNeedleOffset) >= 0.1 || fabs(fNeedleSpeed) >= 0.01) { + fNeedleOffset += iTimeDelta * fNeedleSpeed; + if (fNeedleOffset > 180.0) { + fNeedleOffset -= 360.0; + } else if (fNeedleOffset < -180.0) { + fNeedleOffset += 360.0; + } + + if (fNeedleOffset > 0.0) { + fNeedleSpeed -= iTimeDelta * 0.00175; + } else if (fNeedleOffset < 0.0) { + fNeedleSpeed += iTimeDelta * 0.00175; + } + + fNeedleSpeed -= fNeedleSpeed * 0.0025 * iTimeDelta; + if (fNeedleSpeed > 0.0) { + fNeedleSpeed -= iTimeDelta * 0.00035; + if (fNeedleSpeed < 0.0) { + fNeedleSpeed = 0.0; + } + } else { + fNeedleSpeed += iTimeDelta * 0.00035; + if (fNeedleSpeed > 0.0) { + fNeedleSpeed = 0.0; + } + } + } else { + iTimeCount = 0; + fNeedleOffset = 0.0; + fNeedleSpeed = 0.0; + } + } + } else { + fNeedleOffset = 0.0; + fNeedleSpeed = 0.0; + } + + fSinVal = sin(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI)); + fCosVal = cos(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI)); + + vCompassDir[0] = fSinVal; + vCompassDir[1] = -fCosVal; + + vCenter[0] = m_frame.size.width * 0.5; + vCenter[1] = m_frame.size.height * 0.5; + vTexCoords[0][0] = 0.0; + vTexCoords[0][1] = 0.0; + vTexCoords[1][0] = 1.0; + vTexCoords[1][1] = 0.0; + vTexCoords[2][0] = 0.0; + vTexCoords[2][1] = 1.0; + + vVerts[0][0] = vCenter[0] + vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1]; + vVerts[1][0] = vCenter[0] + vCompassDir[0] * vCenter[0] + fCosVal * vCenter[1]; + vVerts[2][0] = vCenter[0] - vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1]; + vVerts[0][1] = vCenter[1] + vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0]; + vVerts[1][1] = vCenter[1] + vCompassDir[1] * vCenter[1] + fSinVal * vCenter[0]; + vVerts[2][1] = vCenter[1] - vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0]; + + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); + + vVerts[0][0] = vVerts[2][0]; + vVerts[0][1] = vVerts[2][1]; + vTexCoords[0][0] = vTexCoords[2][0]; + vTexCoords[0][1] = vTexCoords[2][1]; + vTexCoords[2][0] = 1.0; + vTexCoords[2][1] = 1.0; + + vVerts[2][0] = vCenter[0] + fCosVal * vCenter[1] - vCompassDir[0] * vCenter[0]; + vVerts[2][1] = vCenter[1] * fSinVal + vCenter[0] - vCompassDir[1] * vCenter[1]; + + re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); +} + +void UIFakkLabel::DrawStatSpinner(float frac) +{ + vec4_t col; + float alpha; + float fTargAng; + float fSinVal, fCosVal; vec2_t vCenter; vec2_t vVerts[3]; vec2_t vTexCoords[3]; @@ -1179,43 +1238,46 @@ void UIFakkLabel::DrawStatSpinner( float frac ) m_lastfrac = frac; alpha = 1.f - (uid.time - m_flashtime) / 1500.f; - if (alpha < 0.f) alpha = 0.f; - else if (alpha > 1.f) alpha = 1.f; + if (alpha < 0.f) { + alpha = 0.f; + } else if (alpha > 1.f) { + alpha = 1.f; + } col[3] = alpha; - if (m_statbar_or == L_STATBAR_HEADING_SPINNER) { - if (cge) { - vec3_t vViewAngles; - float fAngAlpha; - cge->CG_EyeAngles(&vViewAngles); + if (m_statbar_or == L_STATBAR_HEADING_SPINNER) { + if (cge) { + vec3_t vViewAngles; + float fAngAlpha; + cge->CG_EyeAngles(&vViewAngles); - frac = (AngleSubtract(vViewAngles[1], frac * 360.f + 180.f) + 180.f) / 360.f; - if (frac < 0.f || frac > 1.f) { - frac = 0.f; - } - } - } + frac = (AngleSubtract(vViewAngles[1], frac * 360.f + 180.f) + 180.f) / 360.f; + if (frac < 0.f || frac > 1.f) { + frac = 0.f; + } + } + } fTargAng = DEG2RAD(frac * (m_angles[1] - m_angles[0]) + m_angles[0]); - fSinVal = sin(fTargAng); - fCosVal = cos(fTargAng); + fSinVal = sin(fTargAng); + fCosVal = cos(fTargAng); - vSideDir[0] = fCosVal; - vSideDir[1] = fSinVal; + vSideDir[0] = fCosVal; + vSideDir[1] = fSinVal; vCompassDir[0] = fSinVal; - vCompassDir[1] = -fCosVal; - vCenter[0] = m_frame.size.width * 0.5f; - vCenter[1] = m_frame.size.height * 0.5f; + vCompassDir[1] = -fCosVal; + vCenter[0] = m_frame.size.width * 0.5f; + vCenter[1] = m_frame.size.height * 0.5f; - vVerts[0][0] = (fSinVal * vCenter[0] + vCenter[0]) - (fCosVal * vCenter[1]); - vVerts[0][1] = (vCompassDir[1] * vCenter[1] + vCenter[1]) - (vSideDir[1] * vCenter[0]); - vVerts[1][0] = (fSinVal * vCenter[0] + vCenter[0]) + (fCosVal * vCenter[1]); - vVerts[1][1] = (vSideDir[1] * vCenter[0]) + (vCompassDir[1] * vCenter[1] + vCenter[1]); - vVerts[2][0] = vCenter[0] - fSinVal * vCenter[0] - fCosVal * vCenter[1]; - vVerts[2][1] = vCenter[1] - vCompassDir[1] * vCenter[1] - vSideDir[1] * vCenter[0]; + vVerts[0][0] = (fSinVal * vCenter[0] + vCenter[0]) - (fCosVal * vCenter[1]); + vVerts[0][1] = (vCompassDir[1] * vCenter[1] + vCenter[1]) - (vSideDir[1] * vCenter[0]); + vVerts[1][0] = (fSinVal * vCenter[0] + vCenter[0]) + (fCosVal * vCenter[1]); + vVerts[1][1] = (vSideDir[1] * vCenter[0]) + (vCompassDir[1] * vCenter[1] + vCenter[1]); + vVerts[2][0] = vCenter[0] - fSinVal * vCenter[0] - fCosVal * vCenter[1]; + vVerts[2][1] = vCenter[1] - vCompassDir[1] * vCenter[1] - vSideDir[1] * vCenter[0]; - vTexCoords[0][0] = 0.f; + vTexCoords[0][0] = 0.f; vTexCoords[0][1] = 0.f; vTexCoords[1][0] = 1.f; vTexCoords[1][1] = 0.f; @@ -1226,11 +1288,9 @@ void UIFakkLabel::DrawStatSpinner( float frac ) re.SetColor(m_foreground_color); } - m_statbar_material->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); if (alpha != 0.f && m_statbar_material_flash) { - m_statbar_material_flash->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); } @@ -1248,283 +1308,334 @@ void UIFakkLabel::DrawStatSpinner( float frac ) re.SetColor(m_foreground_color); } - m_statbar_material->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial()); if (alpha != 0.f && m_statbar_material_flash) { - m_statbar_material_flash->ReregisterMaterial(); re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material_flash->GetMaterial()); } } -void UIFakkLabel::StatCircleTexCoord( float fAng, vec3_t vTexCoord ) +void UIFakkLabel::StatCircleTexCoord(float fAng, vec3_t vTexCoord) { - int iSector; - float fSinVal, fCosVal; + int iSector; + float fSinVal, fCosVal; - iSector = (AngleMod(fAng) + 45.f) / 90; - fSinVal = sin(DEG2RAD(fAng)); - fCosVal = cos(DEG2RAD(fAng)); + iSector = (AngleMod(fAng) + 45.f) / 90; + fSinVal = sin(DEG2RAD(fAng)); + fCosVal = cos(DEG2RAD(fAng)); - if (iSector >= 0) { - if (iSector == 0) { - vTexCoord[0] = 0.f; - vTexCoord[1] = 0.5f / fCosVal * fSinVal + 0.5f; - } else if (iSector == 1) { - vTexCoord[0] = 1.f; - vTexCoord[1] = -0.5f / fSinVal * fCosVal + 0.5f; - } else if (iSector == 2) { - vTexCoord[0] = fSinVal * (-0.5f * fCosVal) + 0.5f; - vTexCoord[1] = 1.f; - } else if (iSector == 4) { - vTexCoord[0] = 0.5f / fCosVal * fSinVal + 0.5f; - vTexCoord[1] = 0.f; - } else { - vTexCoord[0] = 0.f; - vTexCoord[1] = 0.5f / fSinVal * fCosVal + 0.5f; - } - } else { - vTexCoord[0] = 0.f; - vTexCoord[1] = 0.5f / fSinVal * fCosVal + 0.5f; - } + if (iSector >= 0) { + if (iSector == 0) { + vTexCoord[0] = 0.f; + vTexCoord[1] = 0.5f / fCosVal * fSinVal + 0.5f; + } else if (iSector == 1) { + vTexCoord[0] = 1.f; + vTexCoord[1] = -0.5f / fSinVal * fCosVal + 0.5f; + } else if (iSector == 2) { + vTexCoord[0] = fSinVal * (-0.5f * fCosVal) + 0.5f; + vTexCoord[1] = 1.f; + } else if (iSector == 4) { + vTexCoord[0] = 0.5f / fCosVal * fSinVal + 0.5f; + vTexCoord[1] = 0.f; + } else { + vTexCoord[0] = 0.f; + vTexCoord[1] = 0.5f / fSinVal * fCosVal + 0.5f; + } + } else { + vTexCoord[0] = 0.f; + vTexCoord[1] = 0.5f / fSinVal * fCosVal + 0.5f; + } } -void UIFakkLabel::Draw( void ) +void UIFakkLabel::Draw(void) { - if( m_stat == -1 && m_itemindex == -1 && m_inventoryrendermodelindex == -1 ) - { - if( m_stat_configstring != -1 ) - { - m_font->setColor( m_foreground_color ); - m_font->PrintJustified( getClientFrame(), - m_iFontAlignmentHorizontal, - m_iFontAlignmentVertical, - Sys_LV_CL_ConvertString( va( "%s", CL_ConfigString( cl.snap.ps.stats[ m_stat_configstring ] ) ) ), - m_bVirtual ? m_vVirtualScale : NULL ); + if (m_stat_alpha != -1) { + float frac; - return; - } + frac = (cl.snap.ps.stats[m_stat_alpha] + 1) / 100.0; + frac = Q_clamp_float(frac, 0, 1); - if( !m_rendermodel && m_statbar_or == L_STATBAR_NONE && !m_sDrawModelName.length() ) - { - UILabel::Draw(); - return; - } - } + m_alpha = frac; + } - if( m_stat_configstring != -1 ) - { - m_font->setColor( m_foreground_color ); - m_font->PrintJustified( getClientFrame(), - m_iFontAlignmentHorizontal, - m_iFontAlignmentVertical, - Sys_LV_CL_ConvertString( va( "%s", CL_ConfigString( cl.snap.ps.stats[ m_stat_configstring ] ) ) ), - m_bVirtual ? m_vVirtualScale : NULL ); + if (m_stat == -1 && m_itemindex == -1 && m_inventoryrendermodelindex == -1 && m_stat_configstring == -1 + && !m_rendermodel && m_statbar_or == L_STATBAR_NONE) { + if (!m_sDrawModelName.length()) { + UILabel::Draw(); + return; + } + } - return; - } + if (m_stat_configstring != -1) { + m_font->setColor(m_foreground_color); - if( m_stat == -1 ) - { - float scale; - qhandle_t handle; - vec3_t origin; - vec3_t mins; - vec3_t maxs; - vec3_t angles; - vec3_t offset; - vec3_t rotateoffset; - vec4_t color; - str sAnimName; - float height; + if (m_bOutlinedText) { + m_font->PrintOutlinedJustified( + getClientFrame(), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(cl.snap.ps.stats[m_stat_configstring]))), + UBlack, + getVirtualScale() + ); + } else { + m_font->PrintJustified( + getClientFrame(), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(cl.snap.ps.stats[m_stat_configstring]))), + getVirtualScale() + ); + } + return; + } - if( m_itemindex != -1 ) - { - if( m_itemindex < 0 ) - return; + if (m_stat != -1) { + int delta = cl.snap.ps.stats[m_stat]; - m_font->setColor( m_foreground_color ); - m_font->PrintJustified( getClientFrame(), - m_iFontAlignmentHorizontal, - m_iFontAlignmentVertical, - Sys_LV_CL_ConvertString( va( "%s", CL_ConfigString( CS_WEAPONS + cl.snap.ps.activeItems[ m_itemindex ] ) ) ), - m_bVirtual ? m_vVirtualScale : NULL ); + if (m_statbar_or == L_STATBAR_NONE) { + m_font->setColor(m_foreground_color); - return; - } + if (m_bOutlinedText) { + m_font->PrintOutlinedJustified( + getClientFrame(), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + va("%d", delta), + UBlack, + getVirtualScale() + ); + } else { + m_font->PrintJustified( + getClientFrame(), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + va("%d", delta), + getVirtualScale() + ); + } + return; + } - if( m_inventoryrendermodelindex == -1 && !m_sDrawModelName.length() || !m_rendermodel ) - { - float frac = 0.0; + if (m_statbar_or == L_STATBAR_VERTICAL_STAGGER_EVEN || m_statbar_or == L_STATBAR_VERTICAL_STAGGER_ODD) { + int stat; - if( m_statbar_or == L_STATBAR_NONE ) - return; + if (m_maxstat < 0) { + stat = m_statbar_max; + } else { + stat = cl.snap.ps.stats[m_maxstat]; + } - if( m_cvarname.length() ) - { - frac = Cvar_VariableValue( m_cvarname ) / ( m_statbar_max - m_statbar_min ); - } + delta = stat - cl.snap.ps.stats[m_stat]; - if( frac > 1.0 ) - frac = 1.0; - if( frac < 0.0 ) - frac = 0.0; + if (delta & 1) { + if (m_statbar_or == L_STATBAR_VERTICAL_STAGGER_EVEN) { + delta--; + } else { + delta++; + } + } - DrawStatbar( frac ); - return; - } + delta = stat - delta; - VectorSet4( color, 255, 255, 255, 255 ); + if (m_maxstat >= 0 || m_statbar_min <= delta) { + if (delta < 0) { + delta = 0; + } + } else { + delta = m_statbar_min; + } + } - if( m_rendermodel ) - { - if( !m_cvarname.length() ) - return; + float frac; - handle = re.RegisterModel( Cvar_VariableString( m_cvarname ) ); - if( !handle ) - return; + if (m_maxstat >= 0) { + frac = (float)delta / (float)cl.snap.ps.stats[m_maxstat]; + } else { + frac = (float)delta / (float)(m_statbar_max - m_statbar_min); + } - VectorCopy( m_angles, angles ); - VectorCopy( m_rotateoffset, rotateoffset ); - VectorCopy( m_offset, offset ); - scale = m_scale; - sAnimName = m_anim; - } - else if( m_sDrawModelName.length() ) - { - if( m_lastitemindex != cl.snap.ps.activeItems[ m_inventoryrendermodelindex ] ) - { - if( !m_lastitem ) - m_lastitem = CL_GetInvItemByName( &client_inv, m_sDrawModelName ); - } + if (frac > 1.0) { + frac = 1.0; + } else if (frac < 0.0) { + frac = 0.0; + } -_shitlabel01: - if( !m_lastitem ) - return; + DrawStatbar(frac); + return; + } - VectorCopy( m_lastitem->hudprops.rotateoffset, rotateoffset ); - VectorCopy( m_lastitem->hudprops.offset, offset ); + float scale; + qhandle_t handle; + vec3_t origin; + vec3_t mins; + vec3_t maxs; + vec3_t angles; + vec3_t offset; + vec3_t rotateoffset; + vec4_t color; + str sAnimName; + float height; - handle = re.RegisterModel( m_lastitem->hudprops.model ); + if (m_itemindex != -1) { + if (m_itemindex < 0) { + return; + } - VectorCopy( m_lastitem->hudprops.angledeltas, angles ); + if (cl.snap.ps.activeItems[m_itemindex] < 0 || cl.snap.ps.activeItems[m_itemindex] >= MAX_WEAPONS) { + // Fixed in OPM + // Make sure to not overflow configstrings + return; + } - if( m_lastitem->hudprops.move == INV_MOVE_BOB ) - { - float frac = uid.time / 600.0; - angles[ 0 ] += sin( frac ) * m_lastitem->hudprops.angledeltas[ 0 ]; - angles[ 1 ] += sin( frac ) * m_lastitem->hudprops.angledeltas[ 1 ]; - angles[ 2 ] += sin( frac ) * m_lastitem->hudprops.angledeltas[ 2 ]; - } - else if( m_lastitem->hudprops.model == INV_MOVE_SPIN ) - { - float frac = uid.time / 600.0; - angles[ 0 ] += frac * m_lastitem->hudprops.angledeltas[ 0 ]; - angles[ 1 ] += frac * m_lastitem->hudprops.angledeltas[ 1 ]; - angles[ 2 ] += frac * m_lastitem->hudprops.angledeltas[ 2 ]; - } + m_font->setColor(m_foreground_color); - if( m_rendermodel ) - { - VectorSet( mins, -16, -16, 0 ); - VectorSet( maxs, 16, 16, 96 ); - } - else - { - re.ModelBounds( handle, mins, maxs ); - } + if (m_bOutlinedText) { + m_font->PrintOutlinedJustified( + getClientFrame(), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[m_itemindex]))), + UBlack, + getVirtualScale() + ); + } else { + m_font->PrintJustified( + getClientFrame(), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[m_itemindex]))), + getVirtualScale() + ); + } - origin[ 1 ] = ( mins[ 1 ] + maxs[ 1 ] ) * 0.5; - origin[ 2 ] = ( mins[ 1 ] + maxs[ 1 ] ) * -0.5; + return; + } - height = maxs[ 2 ] - mins[ 2 ]; + if (m_inventoryrendermodelindex == -1 && !m_sDrawModelName.length() && !m_rendermodel) { + float frac = 0.0; - if( height < maxs[ 1 ] - mins[ 1 ] ) - height = maxs[ 1 ] - mins[ 1 ]; + if (m_statbar_or == L_STATBAR_NONE) { + return; + } - if( height <= maxs[ 0 ] - mins[ 0 ] ) - height = maxs[ 0 ] - mins[ 0 ]; + if (m_cvarname.length()) { + frac = Cvar_VariableValue(m_cvarname) / (m_statbar_max - m_statbar_min); + } - origin[ 0 ] = height * scale * 0.5 / 0.268f; + if (frac > 1.0) { + frac = 1.0; + } + if (frac < 0.0) { + frac = 0.0; + } - CL_Draw3DModel( m_screenframe.pos.x, m_screenframe.pos.y, m_screenframe.size.width, m_screenframe.size.height, handle, origin, rotateoffset, offset, angles, color, sAnimName ); - return; - } + DrawStatbar(frac); + return; + } - if( m_lastitemindex == cl.snap.ps.activeItems[ m_inventoryrendermodelindex ] ) - goto _shitlabel01; + VectorSet4(color, 255, 255, 255, 255); - if( m_lastitem == CL_GetInvItemByName( &client_inv, CL_ConfigString( CS_WEAPONS + cl.snap.ps.activeItems[ m_inventoryrendermodelindex ] ) ) ) - { - m_lastitemindex = cl.snap.ps.activeItems[ m_inventoryrendermodelindex ]; - goto _shitlabel01; - } + if (m_rendermodel) { + if (!m_cvarname.length()) { + return; + } - m_lastitem = CL_GetInvItemByName( &client_inv, CL_ConfigString( CS_WEAPONS + cl.snap.ps.activeItems[ m_inventoryrendermodelindex ] ) ); - goto _shitlabel01; - } + handle = re.RegisterModel(Cvar_VariableString(m_cvarname)); + if (!handle) { + return; + } - int delta = cl.snap.ps.stats[ m_stat ]; + VectorCopy(m_angles, angles); + VectorCopy(m_rotateoffset, rotateoffset); + VectorCopy(m_offset, offset); + scale = m_scale; + sAnimName = m_anim; - if( m_statbar_or ) - { - if( m_statbar_or == L_STATBAR_VERTICAL_STAGGER_EVEN || m_statbar_or == L_STATBAR_VERTICAL_STAGGER_ODD ) - { - int stat; + // Added in 2.11 + // Tunak easter egg + if (Cvar_Get("tunak", "0", 0)->integer) { + // Since 2.15, those animations start has 'zz' prefix + if (strstr(m_anim, "american")) { + sAnimName = "zzamericanspecialidle"; + } else { + // Added in 2.15 + sAnimName = "zzgermanspecialidle"; + } + } + } else { + if (m_sDrawModelName.length()) { + if (!m_lastitem) { + m_lastitem = CL_GetInvItemByName(&client_inv, m_sDrawModelName); + } + } else { + if (m_inventoryrendermodelindex >= 0 + && m_lastitemindex != cl.snap.ps.activeItems[m_inventoryrendermodelindex]) { + m_lastitem = CL_GetInvItemByName( + &client_inv, CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[m_inventoryrendermodelindex]) + ); + m_lastitemindex = cl.snap.ps.activeItems[m_inventoryrendermodelindex]; + } + } - if( m_maxstat < 0 ) { - stat = m_statbar_max; - } else { - stat = cl.snap.ps.stats[ m_maxstat ]; - } + if (!m_lastitem) { + return; + } - delta = stat - cl.snap.ps.stats[ m_stat ]; + VectorCopy(m_lastitem->hudprops.rotateoffset, rotateoffset); + VectorCopy(m_lastitem->hudprops.offset, offset); + scale = m_lastitem->hudprops.scale; + handle = re.RegisterModel(m_lastitem->hudprops.model); + VectorCopy(m_lastitem->hudprops.angledeltas, angles); - if( delta & 1 ) - { - if( m_statbar_or == L_STATBAR_VERTICAL_STAGGER_EVEN ) - delta--; - else - delta++; - } + if (m_lastitem->hudprops.move == INV_MOVE_BOB) { + float frac = uid.time / 600.0; + angles[0] += sin(frac) * m_lastitem->hudprops.angledeltas[0]; + angles[1] += sin(frac) * m_lastitem->hudprops.angledeltas[1]; + angles[2] += sin(frac) * m_lastitem->hudprops.angledeltas[2]; + } else if (m_lastitem->hudprops.model == INV_MOVE_SPIN) { + float frac = uid.time / 600.0; + angles[0] += frac * m_lastitem->hudprops.angledeltas[0]; + angles[1] += frac * m_lastitem->hudprops.angledeltas[1]; + angles[2] += frac * m_lastitem->hudprops.angledeltas[2]; + } + } - delta = stat - delta; + if (m_rendermodel) { + VectorSet(mins, -16, -16, 0); + VectorSet(maxs, 16, 16, 96); + } else { + re.ModelBounds(handle, mins, maxs); + } - if( m_maxstat >= 0 || m_statbar_min <= delta ) - { - if( delta < 0 ) - delta = 0; - } - else - { - delta = m_statbar_min; - } - } + origin[1] = (mins[1] + maxs[1]) * 0.5; + origin[2] = (mins[2] + maxs[2]) * -0.5; - float frac; + height = maxs[2] - mins[2]; - if( m_maxstat >= 0 ) - { - frac = (float)delta / (float)cl.snap.ps.stats[m_maxstat]; - } - else - { - frac = (float)delta / (float)(m_statbar_max - m_statbar_min); - } + if (height < maxs[1] - mins[1]) { + height = maxs[1] - mins[1]; + } - if( frac > 1.0 ) frac = 1.0; - else if( frac < 0.0 ) frac = 0.0; + if (height < maxs[0] - mins[0]) { + height = maxs[0] - mins[0]; + } - DrawStatbar( frac ); - - return; - } + origin[0] = height * scale * 0.5 / 0.268f; - m_font->setColor( m_foreground_color ); - m_font->PrintJustified( getClientFrame(), - m_iFontAlignmentHorizontal, - m_iFontAlignmentVertical, - va( "%d", delta ), - m_bVirtual ? m_vVirtualScale : NULL ); + CL_Draw3DModel( + m_screenframe.pos.x, + m_screenframe.pos.y, + m_screenframe.size.width, + m_screenframe.size.height, + handle, + origin, + rotateoffset, + offset, + angles, + color, + sAnimName + ); + + set2D(); } diff --git a/code/client/cl_uistd.h b/code/client/cl_uistd.h index c4fe9d7e..15a7afa3 100644 --- a/code/client/cl_uistd.h +++ b/code/client/cl_uistd.h @@ -20,85 +20,88 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UISTD_H__ -#define __CL_UISTD_H__ +#pragma once typedef enum { - L_STATBAR_NONE, - L_STATBAR_HORIZONTAL, - L_STATBAR_VERTICAL, - L_STATBAR_VERTICAL_REVERSE, - L_STATBAR_VERTICAL_STAGGER_EVEN, - L_STATBAR_VERTICAL_STAGGER_ODD, - L_STATBAR_CIRCULAR, - L_STATBAR_NEEDLE, - L_STATBAR_ROTATOR, - L_STATBAR_COMPASS, - L_STATBAR_SPINNER, - L_STATBAR_HEADING_SPINNER + L_STATBAR_NONE, + L_STATBAR_HORIZONTAL, + L_STATBAR_VERTICAL, + L_STATBAR_VERTICAL_REVERSE, + L_STATBAR_VERTICAL_STAGGER_EVEN, + L_STATBAR_VERTICAL_STAGGER_ODD, + L_STATBAR_CIRCULAR, + L_STATBAR_NEEDLE, + L_STATBAR_ROTATOR, + L_STATBAR_COMPASS, + L_STATBAR_SPINNER, + L_STATBAR_HEADING_SPINNER } statbar_orientation_t; -class UIFakkLabel : public UILabel { +extern Event EV_ClearInvItemReference; + +class UIFakkLabel : public UILabel +{ protected: - SafePtr m_lastitem; - int m_lastitemindex; - int m_stat; - int m_stat_configstring; - int m_maxstat; - int m_itemindex; - int m_inventoryrendermodelindex; - str m_sDrawModelName; - qboolean m_rendermodel; - statbar_orientation_t m_statbar_or; - float m_statbar_min; - float m_statbar_max; - float m_lastfrac; - float m_flashtime; - vec3_t m_offset; - vec3_t m_rotateoffset; - vec3_t m_angles; - float m_scale; - str m_anim; - UIReggedMaterial *m_statbar_material; - UIReggedMaterial *m_statbar_material_flash; + SafePtr m_lastitem; + int m_lastitemindex; + int m_stat; + int m_stat_alpha; + int m_stat_configstring; + int m_maxstat; + int m_itemindex; + int m_inventoryrendermodelindex; + str m_sDrawModelName; + qboolean m_rendermodel; + statbar_orientation_t m_statbar_or; + float m_statbar_min; + float m_statbar_max; + float m_lastfrac; + float m_flashtime; + vec3_t m_offset; + vec3_t m_rotateoffset; + vec3_t m_angles; + float m_scale; + str m_anim; + UIReggedMaterial *m_statbar_material; + UIReggedMaterial *m_statbar_material_flash; + UIReggedMaterial *m_statbar_material_marker; public: - CLASS_PROTOTYPE( UIFakkLabel ); + CLASS_PROTOTYPE(UIFakkLabel); - UIFakkLabel(); + UIFakkLabel(); - void LayoutPlayerStat( Event *ev ); - void LayoutPlayerStatConfigstring( Event *ev ); - void LayoutMaxPlayerStat( Event *ev ); - void LayoutItemIndex( Event *ev ); - void InventoryRenderModelIndex( Event *ev ); - void LayoutModelName( Event *ev ); - void ClearInvItemReference( Event *ev ); - void LayoutStatbar( Event *ev ); - void LayoutStatbarShader( Event *ev ); - void LayoutStatbarTileShader( Event *ev ); - void LayoutStatbarShader_Flash( Event *ev ); - void LayoutStatbarEndAngles( Event *ev ); - void LayoutStatbarNeedleWidth( Event *ev ); - void LayoutStatbarRotatorSize( Event *ev ); - void LayoutStatbarTileShader_Flash( Event *ev ); - void LayoutRenderModel( Event *ev ); - void LayoutRenderModelOffset( Event *ev ); - void LayoutRenderModelRotateOffset( Event *ev ); - void LayoutRenderModelAngles( Event *ev ); - void LayoutRenderModelScale( Event *ev ); - void LayoutRenderModelAnim( Event *ev ); + void LayoutPlayerStat(Event *ev); + void LayoutPlayerStatAlpha(Event *ev); // Added in 2.0 + void LayoutPlayerStatConfigstring(Event *ev); + void LayoutMaxPlayerStat(Event *ev); + void LayoutItemIndex(Event *ev); + void InventoryRenderModelIndex(Event *ev); + void LayoutModelName(Event *ev); + void ClearInvItemReference(Event *ev); + void LayoutStatbar(Event *ev); + void LayoutStatbarShader(Event *ev); + void LayoutStatbarTileShader(Event *ev); + void LayoutStatbarShader_Flash(Event *ev); + void LayoutStatbarShader_Marker(Event *ev); // Added in 2.0 + void LayoutStatbarEndAngles(Event *ev); + void LayoutStatbarNeedleWidth(Event *ev); + void LayoutStatbarRotatorSize(Event *ev); + void LayoutStatbarTileShader_Flash(Event *ev); + void LayoutRenderModel(Event *ev); + void LayoutRenderModelOffset(Event *ev); + void LayoutRenderModelRotateOffset(Event *ev); + void LayoutRenderModelAngles(Event *ev); + void LayoutRenderModelScale(Event *ev); + void LayoutRenderModelAnim(Event *ev); - void DrawStatbar( float frac ); - void DrawStatCircle( float frac ); - void DrawStatNeedle( float frac ); - void DrawStatRotator( float frac ); - void DrawStatCompass( float frac ); - void DrawStatSpinner( float frac ); - void StatCircleTexCoord( float fAng, vec3_t vTexCoord ); + void DrawStatbar(float frac); + void DrawStatCircle(float frac); + void DrawStatNeedle(float frac); + void DrawStatRotator(float frac); + void DrawStatCompass(float frac); + void DrawStatSpinner(float frac); + void StatCircleTexCoord(float fAng, vec3_t vTexCoord); - void Draw( void ) override; + void Draw(void) override; }; - -#endif - diff --git a/code/client/cl_uiview3d.cpp b/code/client/cl_uiview3d.cpp index 5bf6e78c..98440439 100644 --- a/code/client/cl_uiview3d.cpp +++ b/code/client/cl_uiview3d.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,424 +21,852 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cl_ui.h" +#include "../qcommon/localization.h" -CLASS_DECLARATION( UIWidget, View3D, NULL ) -{ - { &W_Activated, &View3D::OnActivate }, - { &W_Deactivated, &View3D::OnDeactivate }, - { &W_LeftMouseDown, &View3D::Pressed }, - { NULL, NULL } +#include "../server/server.h" + +CLASS_DECLARATION(UIWidget, View3D, NULL) { + {&W_Activated, &View3D::OnActivate }, + {&W_Deactivated, &View3D::OnDeactivate}, + {&W_LeftMouseDown, &View3D::Pressed }, + {NULL, NULL } }; -#define MAX_SUBTITLES 4 - -cvar_t* subs[MAX_SUBTITLES]; -cvar_t* teams[MAX_SUBTITLES]; -float fadeTime[MAX_SUBTITLES]; -float subLife[MAX_SUBTITLES]; -float alpha[MAX_SUBTITLES]; -char oldStrings[MAX_SUBTITLES][2048]; +cvar_t *subs[MAX_SUBTITLES]; +cvar_t *teams[MAX_SUBTITLES]; +float fadeTime[MAX_SUBTITLES]; +float subLife[MAX_SUBTITLES]; +float alpha[MAX_SUBTITLES]; +char oldStrings[MAX_SUBTITLES][2048]; View3D::View3D() { - // set as transparent - setBackgroundColor(UClear, true); - // no border - setBorderStyle(border_none); - AllowActivate(true); + // set as transparent + setBackgroundColor(UClear, true); + // no border + setBorderStyle(border_none); + AllowActivate(true); - m_printfadetime = 0.0; - m_print_mat = NULL; - m_locationprint = qfalse; + m_printfadetime = 0.0; + m_print_mat = NULL; + m_locationprint = qfalse; } -void View3D::Draw - ( - void - ) - +void View3D::UpdateCenterPrint(const char *s, float alpha) { - if (clc.state != CA_DISCONNECTED) { - SCR_DrawScreenField(); - } + m_printstring = s; - set2D(); + if (s[0] == '@') { + m_print_mat = uWinMan.RegisterShader(s + 1); + } else { + m_print_mat = NULL; + } - re.SavePerformanceCounters(); - - Draw2D(); + m_printalpha = alpha; + m_printfadetime = 4000.0; + m_locationprint = qfalse; } -void View3D::DrawLetterbox - ( - void - ) - +void View3D::UpdateLocationPrint(int x, int y, const char *s, float alpha) { - float frac; - vec4_t col; - - col[0] = col[1] = col[2] = 0; - col[3] = 1; - - frac = cl.snap.ps.stats[STAT_LETTERBOX] / 32767.0; - if (frac > 0.0) { - m_letterbox_active = true; - re.SetColor(col); - - re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height); - re.DrawBox(0.0, m_screenframe.size.height - m_screenframe.size.height * frac, m_screenframe.size.width, m_screenframe.size.height); - } else { - m_letterbox_active = false; - } + m_printstring = s; + m_printalpha = alpha; + m_printfadetime = 4000.0; + m_x_coord = x; + m_y_coord = y; + m_locationprint = qtrue; } -void View3D::DrawFades - ( - void - ) - +void View3D::FrameInitialized(void) { - if (cl.snap.ps.blend[3] > 0) { - re.SetColor(cl.snap.ps.blend); - if (cl.snap.ps.stats[STAT_ADDFADE]) { - re.AddBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height); - } else { - re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height); - } - } + Connect(this, W_Activated, W_Activated); + Connect(this, W_Deactivated, W_Deactivated); } -void View3D::Draw2D - ( - void - ) - +void View3D::Pressed(Event *ev) { - if (!cls.no_menus) { - DrawFades(); - } - - DrawLetterbox(); - - if ((cl_debuggraph->integer || cl_timegraph->integer) && !cls.no_menus) - { - SCR_DrawDebugGraph(); - } - else if (!cls.no_menus) - { - if (cge) { - cge->CG_Draw2D(); - } - - if (m_locationprint) { - LocationPrint(); - } else { - CenterPrint(); - } - - if (!cls.no_menus) - { - DrawSoundOverlay(); - DrawSubtitleOverlay(); - } - } - - if (fps->integer && !cls.no_menus) - { - DrawFPS(); - DrawProf(); - } + IN_MouseOff(); + OnActivate(ev); } -void View3D::DrawFPS - ( - void - ) - +void View3D::OnActivate(Event *ev) { - char string[128]; - - setFont("verdana-14"); - if (fps->integer == 2) - { - re.SetColor(UBlack); - re.DrawBox( - 0.0, - m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0, - m_frame.pos.x + m_frame.size.width, - m_font->getHeight(qfalse) * 4.0 - ); - } - - sprintf(string, "FPS %4.1f", currentfps); - if (currentfps > 23.94) { - if (cl_greenfps->integer) { - m_font->setColor(UGreen); - } else { - m_font->setColor(UWhite); - } - } else if (currentfps > 18.0) { - m_font->setColor(UYellow); - } else { - // low fps - m_font->setColor(URed); - } - - m_font->Print( - m_font->getHeight(qfalse) * 10.0, - m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0, - string, - -1, - qfalse - ); - - // Draw elements count - if (cl_greenfps->integer) { - m_font->setColor(UGreen); - } - else { - m_font->setColor(UWhite); - } - - sprintf(string, "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights); - - m_font->Print( - m_font->getHeight(qfalse) * 10.0, - m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0, - string, - -1, - qfalse - ); - - sprintf(string, "t%5d v%5d Mtex%5.2f", cls.total_tris, cls.total_verts, (float)cls.total_texels * 0.00000095367432); - - - m_font->Print( - m_font->getHeight(qfalse) * 10.0, - m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse), - string, - -1, - qfalse - ); - - m_font->setColor(UBlack); -} - -void View3D::DrawProf - ( - void - ) - -{ - // Normal empty function -} - -void View3D::PrintSound - ( - int channel, - const char *name, - float vol, - int rvol, - float pitch, - float base, - int& line - ) - -{ - // FIXME: unimplemented -} - -void View3D::DrawSoundOverlay - ( - void - ) - -{ - setFont("verdana-14"); - m_font->setColor(UWhite); - - if (sound_overlay->integer) { - Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n"); - Cvar_Set("sound_overlay", "0"); - } -} - -void View3D::CenterPrint - ( - void - ) - -{ - // FIXME: unimplemented -} - -void View3D::LocationPrint - ( - void - ) - -{ - // FIXME: unimplemented -} - -void View3D::OnActivate - ( - Event *ev - ) - -{ - UIWidget* wid; - UList widgets; + UIWidget *wid; + UList widgets; UI_CloseInventory(); - cls.keyCatchers &= ~KEYCATCH_UI; + Key_SetCatcher(Key_GetCatcher() & ~KEYCATCH_UI); - for (wid = getParent()->getFirstChild(); wid; wid = getParent()->getNextChild(wid)) - { - if (wid->getAlwaysOnBottom() && wid != this) { - widgets.AddTail(wid); - } - } + for (wid = getParent()->getFirstChild(); wid; wid = getParent()->getNextChild(wid)) { + if (wid->getAlwaysOnBottom() && wid != this) { + widgets.AddTail(wid); + } + } - widgets.IterateFromHead(); - while (widgets.IsCurrentValid()) - { - widgets.getCurrent()->BringToFrontPropogated(); - widgets.IterateNext(); - } + widgets.IterateFromHead(); + while (widgets.IsCurrentValid()) { + widgets.getCurrent()->BringToFrontPropogated(); + widgets.IterateNext(); + } } -void View3D::OnDeactivate - ( - Event *ev - ) - +void View3D::OnDeactivate(Event *ev) { - cls.keyCatchers |= KEYCATCH_UI; + Key_SetCatcher(Key_GetCatcher() | KEYCATCH_UI); } -void View3D::DrawSubtitleOverlay - ( - void - ) - +void View3D::DrawFPS(void) { - // FIXME: unimplemented + char string[128]; + + setFont("verdana-14"); + if (fps->integer == 2) { + re.SetColor(UBlack); + re.DrawBox( + 0.0, + m_frame.pos.y + m_frame.size.height - m_font->getHeight() * 4.0, + m_frame.pos.x + m_frame.size.width, + m_font->getHeight() * 4.0 + ); + } + + Com_sprintf(string, sizeof(string), "FPS %4.1f", currentfps); + if (currentfps > 23.94) { + if (cl_greenfps->integer) { + m_font->setColor(UGreen); + } else { + m_font->setColor(UWhite); + } + } else if (currentfps > 18.0) { + m_font->setColor(UYellow); + } else { + // low fps + m_font->setColor(URed); + } + + m_font->Print( + m_font->getHeight(getHighResScale()) * 10.0 / getHighResScale()[0], + (m_frame.pos.y + m_frame.size.height - m_font->getHeight(getHighResScale()) * 3.0) / getHighResScale()[1], + string, + -1, + getHighResScale() + ); + + // Draw elements count + if (cl_greenfps->integer) { + m_font->setColor(UGreen); + } else { + m_font->setColor(UWhite); + } + + Com_sprintf(string, sizeof(string), "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights); + + m_font->Print( + (m_font->getHeight(getHighResScale()) * 10.0) / getHighResScale()[0], + (m_frame.pos.y + m_frame.size.height - m_font->getHeight(getHighResScale()) * 2.0) / getHighResScale()[1], + string, + -1, + getHighResScale() + ); + + Com_sprintf( + string, + sizeof(string), + "t%5d v%5d Mtex%5.2f", + cls.total_tris, + cls.total_verts, + (float)cls.total_texels * 0.00000095367432 + ); + + m_font->Print( + (m_font->getHeight(getHighResScale()) * 10.0) / getHighResScale()[0], + (m_frame.pos.y + m_frame.size.height - m_font->getHeight(getHighResScale())) / getHighResScale()[1], + string, + -1, + getHighResScale() + ); + + m_font->setColor(UBlack); } -void View3D::ClearCenterPrint - ( - void - ) - +/* +void ProfPrint(UIFont* m_font, float minY, int line, char* label, prof_var_t* var, int level) { - m_printfadetime = 0.0; + +} +*/ + +void View3D::DrawProf(void) +{ + // FIXME: unimplemented } -void View3D::UpdateCenterPrint - ( - const char *s, - float alpha - ) - +void View3D::PrintSound(int channel, const char *name, float vol, int rvol, float pitch, float base, int& line) { - m_printstring = s; + char buf[255]; + float x; + float xStep; + float height; - if (s[0] == '@') { - m_print_mat = uWinMan.RegisterShader(s + 1); - } else { - m_print_mat = NULL; - } + height = m_font->getHeight(getHighResScale()); + xStep = height; - m_printalpha = alpha; - m_printfadetime = 4000.0; - m_locationprint = qfalse; + x = 0; + Com_sprintf(buf, sizeof(buf), "%d", channel); + m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale()); + + x += xStep + xStep; + Com_sprintf(buf, sizeof(buf), "%s", name); + m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale()); + + x += xStep * 30.0; + Com_sprintf(buf, sizeof(buf), "vol:%.2f", vol); + m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale()); + + x += xStep * 8; + Com_sprintf(buf, sizeof(buf), "rvol:%.2f", (float)(rvol / 128.f)); + m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale()); + + x += xStep * 5; + Com_sprintf(buf, sizeof(buf), "pit:%.2f", pitch); + m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale()); + + x += xStep * 5; + Com_sprintf(buf, sizeof(buf), "base:%d", (int)base); + m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale()); + + line++; } -void View3D::UpdateLocationPrint - ( - int x, - int y, - const char *s, - float alpha - ) - +void View3D::DrawSoundOverlay(void) { - m_printstring = s; - m_printalpha = alpha; - m_printfadetime = 4000.0; - m_x_coord = x; - m_y_coord = y; - m_locationprint = qtrue; + setFont("verdana-14"); + m_font->setColor(UWhite); + + // FIXME: Unimplemented + if (sound_overlay->integer) { + Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n"); + Cvar_Set("sound_overlay", "0"); + } } -qboolean View3D::LetterboxActive - ( - void - ) - +void DisplayServerNetProfileInfo(UIFont *font, float y, netprofclient_t *netprofile) { - return m_letterbox_active; + font->Print(104, y, va("%i", netprofile->inPackets.packetsPerSec)); + font->Print(144, y, va("%i", netprofile->outPackets.packetsPerSec)); + font->Print(184, y, va("%i", netprofile->inPackets.packetsPerSec + netprofile->outPackets.packetsPerSec)); + font->Print(234, y, va("%i", netprofile->inPackets.percentFragmented)); + font->Print(264, y, va("%i", netprofile->outPackets.percentFragmented)); + font->Print( + 294, + y, + va("%i", + (unsigned int)((float)(netprofile->outPackets.numFragmented + netprofile->inPackets.numFragmented) + / (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed) + )), + -1 + ); + font->Print(334, y, va("%i", netprofile->inPackets.percentDropped)); + font->Print(364, y, va("%i", netprofile->outPackets.percentDropped)); + font->Print( + 394, + y, + va("%i", + (unsigned int)((float)(netprofile->outPackets.numDropped + netprofile->inPackets.numDropped) + / (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed) + )), + -1 + ); + font->Print(434, y, va("%i", netprofile->inPackets.percentDropped)); + font->Print(464, y, va("%i", netprofile->outPackets.percentDropped)); + font->Print( + 494, + y, + va("%i", + (unsigned int)((float)(netprofile->outPackets.totalLengthConnectionLess + + netprofile->inPackets.totalLengthConnectionLess) + / (float)(netprofile->outPackets.totalSize + netprofile->inPackets.totalSize))), + -1 + ); + font->Print(534, y, va("%i", netprofile->inPackets.bytesPerSec)); + font->Print(594, y, va("%i", netprofile->outPackets.bytesPerSec)); + font->Print(654, y, va("%i", netprofile->outPackets.bytesPerSec + netprofile->inPackets.bytesPerSec)); + font->Print(714, y, va("%i", netprofile->rate)); +} + +void DisplayClientNetProfile(UIFont *font, float x, float y, netprofclient_t *netprofile) +{ + float columns[5]; + float fontHeight; + float columnHeight; + + fontHeight = font->getHeight(); + columns[0] = x + 120; + columns[1] = x + 230; + columns[2] = x + 330; + columns[3] = x + 430; + columns[4] = x + 530; + columnHeight = y; + + font->Print(x, y, va("Rate: %i", netprofile->rate)); + + columnHeight += fontHeight * 1.5; + font->Print(x, columnHeight, "Data Type"); + font->Print(columns[0], columnHeight, "Packets per Sec"); + font->Print(columns[1], columnHeight, "% Fragmented"); + font->Print(columns[2], columnHeight, "% Dropped"); + font->Print(columns[3], columnHeight, "% OOB data"); + font->Print(columns[4], columnHeight, "Data per Sec"); + + columnHeight += fontHeight * 0.5; + font->Print(x, columnHeight, "----------"); + font->Print(columns[0], columnHeight, "----------"); + font->Print(columns[1], columnHeight, "----------"); + font->Print(columns[2], columnHeight, "----------"); + font->Print(columns[3], columnHeight, "----------"); + font->Print(columns[4], columnHeight, "----------"); + + columnHeight += fontHeight; + font->Print(x, columnHeight, "Data In"); + font->Print(columns[0], columnHeight, va("%i", netprofile->outPackets.packetsPerSec)); + font->Print(columns[1], columnHeight, va("%i%%", netprofile->outPackets.percentFragmented)); + font->Print(columns[2], columnHeight, va("%i%%", netprofile->outPackets.percentDropped)); + font->Print(columns[3], columnHeight, va("%i%%", netprofile->outPackets.percentConnectionLess)); + font->Print(columns[4], columnHeight, va("%i", netprofile->outPackets.bytesPerSec)); + + columnHeight += fontHeight; + font->Print(x, columnHeight, "Data Out"); + font->Print(columns[0], columnHeight, va("%i", netprofile->inPackets.packetsPerSec)); + font->Print(columns[1], columnHeight, va("%i%%", netprofile->inPackets.percentFragmented)); + font->Print(columns[2], columnHeight, va("%i%%", netprofile->inPackets.percentDropped)); + font->Print(columns[3], columnHeight, va("%i%%", netprofile->inPackets.percentConnectionLess)); + font->Print(columns[4], columnHeight, va("%i", netprofile->inPackets.bytesPerSec)); + + columnHeight += fontHeight; + + font->Print(x, columnHeight, "Total Data"); + + font->Print( + columns[0], + columnHeight, + va("%i", netprofile->inPackets.packetsPerSec + netprofile->outPackets.packetsPerSec) + ); + font->Print( + columns[1], + columnHeight, + va("%i%%", + (unsigned int)((float)(netprofile->outPackets.numFragmented + netprofile->inPackets.numFragmented) + / (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed) + )) + ); + font->Print( + columns[2], + columnHeight, + va("%i%%", + (unsigned int)((float)(netprofile->outPackets.numDropped + netprofile->inPackets.numDropped) + / (double)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed + ))) + ); + font->Print( + columns[3], + columnHeight, + va("%i%%", + (unsigned int)((float)(netprofile->outPackets.totalLengthConnectionLess + + netprofile->inPackets.totalLengthConnectionLess) + / (float)(netprofile->outPackets.totalSize + netprofile->inPackets.totalSize))) + ); + font->Print( + columns[4], + columnHeight, + va("%i", netprofile->inPackets.bytesPerSec + netprofile->outPackets.bytesPerSec) + ); +} + +void View3D::DrawNetProfile(void) +{ + float fontHeight; + float yOffset; + int i; + + if (sv_netprofileoverlay->integer && sv_netprofile->integer && com_sv_running->integer) { + float columnHeight; + float valueHeight; + float separatorHeight; + float categoryHeight; + float currentHeight; + netprofclient_t netproftotal; + + setFont("verdana-14"); + m_font->setColor(UWhite); + + fontHeight = m_font->getHeight(); + yOffset = sv_netprofileoverlay->integer + 8; + + if (svs.netprofile.rate) { + m_font->Print(8, yOffset, va("Server Net Profile Max Rate: %i", svs.netprofile.rate), -1); + } else { + m_font->Print(8, yOffset, "Server Net Profile Max Rate: none", -1); + } + + columnHeight = fontHeight + fontHeight + yOffset; + valueHeight = columnHeight + fontHeight; + separatorHeight = fontHeight * 1.5 + columnHeight; + categoryHeight = fontHeight * 0.5 + columnHeight; + + m_font->Print(8, categoryHeight, "Data Source"); + m_font->Print(8, separatorHeight, "---------------"); + m_font->Print(104, columnHeight, "Packets per Sec"); + m_font->Print(104, valueHeight, "In"); + m_font->Print(144, valueHeight, "Out"); + m_font->Print(184, valueHeight, "Total"); + m_font->Print(104, separatorHeight, "---"); + m_font->Print(144, separatorHeight, "-----"); + m_font->Print(184, separatorHeight, "------"); + m_font->Print(234, columnHeight, "% Fragmented"); + m_font->Print(234, valueHeight, "In"); + m_font->Print(264, valueHeight, "Out"); + m_font->Print(294, valueHeight, "Total"); + m_font->Print(234, separatorHeight, "---"); + m_font->Print(264, separatorHeight, "-----"); + m_font->Print(294, separatorHeight, "------"); + m_font->Print(334, columnHeight, "% Dropped"); + m_font->Print(334, valueHeight, "In"); + m_font->Print(364, valueHeight, "Out"); + m_font->Print(394, valueHeight, "Total"); + m_font->Print(334, separatorHeight, "---"); + m_font->Print(364, separatorHeight, "-----"); + m_font->Print(394, separatorHeight, "------"); + m_font->Print(434, columnHeight, "% OOB Data"); + m_font->Print(434, valueHeight, "In"); + m_font->Print(464, valueHeight, "Out"); + m_font->Print(494, valueHeight, "Total"); + m_font->Print(434, separatorHeight, "---"); + m_font->Print(464, separatorHeight, "-----"); + m_font->Print(494, separatorHeight, "------"); + m_font->Print(534, columnHeight, "Data per Sec"); + m_font->Print(534, valueHeight, "In"); + m_font->Print(594, valueHeight, "Out"); + m_font->Print(654, valueHeight, "Total"); + m_font->Print(534, separatorHeight, "---"); + m_font->Print(594, separatorHeight, "-----"); + m_font->Print(654, separatorHeight, "------"); + m_font->Print(714, categoryHeight, "Rate"); + m_font->Print(714, separatorHeight, "------"); + + currentHeight = fontHeight * 2.5 + columnHeight; + SV_NET_CalcTotalNetProfile(&netproftotal, qfalse); + m_font->Print(8, columnHeight + fontHeight * 2.5, "Total"); + DisplayServerNetProfileInfo(m_font, currentHeight, &netproftotal); + + currentHeight += fontHeight * 1.5; + m_font->Print(8, currentHeight, "Clientless"); + DisplayServerNetProfileInfo(m_font, currentHeight, &svs.netprofile); + + currentHeight += fontHeight; + + for (i = 0; i < svs.iNumClients; i++) { + client_t *client = &svs.clients[i]; + if (client->state != CS_ACTIVE || !client->gentity) { + continue; + } + + if (client->netchan.remoteAddress.type == NA_LOOPBACK) { + m_font->Print(8.0, currentHeight, va("#%i-Loopback", i), -1, 0); + + } else { + m_font->Print(8.0, currentHeight, va("Client #%i", i), -1, 0); + } + + DisplayServerNetProfileInfo(m_font, currentHeight, &client->netprofile); + currentHeight = currentHeight + fontHeight; + } + } else if (cl_netprofileoverlay->integer && cl_netprofile->integer && com_cl_running->integer) { + setFont("verdana-14"); + m_font->setColor(UWhite); + + fontHeight = m_font->getHeight(); + yOffset = cl_netprofileoverlay->integer + 16; + + m_font->Print(16, yOffset, "Client Net Profile", -1); + + NetProfileCalcStats(&cls.netprofile.outPackets, 500); + NetProfileCalcStats(&cls.netprofile.inPackets, 500); + + DisplayClientNetProfile(m_font, 16, yOffset + fontHeight * 2, &cls.netprofile); + } +} + +void View3D::Draw2D(void) +{ + if (!cls.no_menus) { + DrawFades(); + } + + DrawLetterbox(); + + if ((cl_debuggraph->integer || cl_timegraph->integer) && !cls.no_menus) { + SCR_DrawDebugGraph(); + } else if (!cls.no_menus) { + if (cge) { + cge->CG_Draw2D(); + } + + if (m_locationprint) { + LocationPrint(); + } else { + CenterPrint(); + } + + if (!cls.no_menus) { + DrawSoundOverlay(); + DrawNetProfile(); + DrawSubtitleOverlay(); + } + } + + if (fps->integer && !cls.no_menus) { + DrawFPS(); + DrawProf(); + } +} + +void View3D::CenterPrint(void) +{ + float alpha; + const char *p; + qhandle_t mat; + float x, y; + float w, h; + + if (!m_printfadetime) { + return; + } + + p = Sys_LV_CL_ConvertString(m_printstring); + if (m_printfadetime > 3250) { + alpha = 1.f - (m_printfadetime - 3250.f) / 750.f * m_printalpha; + } else if (m_printfadetime >= 750) { + alpha = 1.f; + } else { + alpha = m_printfadetime / 750.f * m_printalpha; + } + + alpha = Q_clamp_float(alpha, 0, 1); + + if (!m_print_mat) { + UIRect2D frame; + m_font->setColor(UColor(0, 0, 0, alpha)); + + frame = getClientFrame(); + + m_font->PrintJustified( + UIRect2D(frame.pos.x + 1, frame.pos.y + 1, frame.size.width, frame.size.height), + m_iFontAlignmentHorizontal, + m_iFontAlignmentVertical, + p, + getVirtualScale() + ); + + m_font->setColor(UColor(1, 1, 1, alpha)); + + frame = getClientFrame(); + + m_font->PrintJustified( + frame, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, p, getVirtualScale() + ); + + m_font->setColor(UBlack); + } else if ((mat = m_print_mat->GetMaterial())) { + vec4_t col {alpha, alpha, alpha, alpha}; + + re.SetColor(col); + + w = re.GetShaderWidth(mat); + h = re.GetShaderHeight(mat); + x = (m_frame.pos.x + m_frame.size.width - w) * 0.5f; + y = (m_frame.pos.y + m_frame.size.height - h) * 0.5f; + + re.DrawStretchPic(x, y, w, h, 0, 0, 1, 1, mat); + } + + m_printfadetime -= cls.frametime; + + if (m_printfadetime < 0) { + m_printfadetime = 0; + } +} + +void View3D::LocationPrint(void) +{ + fonthorzjustify_t horiz; + fontvertjustify_t vert; + int x, y; + const char *p; + float alpha; + UIRect2D frame; + + if (!m_printfadetime) { + m_locationprint = false; + return; + } + + horiz = FONT_JUSTHORZ_LEFT; + vert = FONT_JUSTVERT_TOP; + + p = Sys_LV_CL_ConvertString(m_printstring); + if (m_printfadetime > 3250) { + alpha = 1.f - (m_printfadetime - 3250.f) / 750.f * m_printalpha; + } else if (m_printfadetime >= 750) { + alpha = 1.f; + } else { + alpha = m_printfadetime / 750.f * m_printalpha; + } + + alpha = Q_clamp_float(alpha, 0, 1); + + x = m_x_coord / 640.f * m_screenframe.size.width; + y = (480 - m_font->getHeight(getHighResScale()) - m_y_coord) / 480.f * m_screenframe.size.height; + + if (m_x_coord == -1) { + horiz = FONT_JUSTHORZ_CENTER; + x = 0; + } + if (m_y_coord == -1) { + vert = FONT_JUSTVERT_CENTER; + y = 0; + } + + m_font->setColor(UColor(0, 0, 0, alpha)); + frame = getClientFrame(); + + m_font->PrintJustified( + UIRect2D(frame.pos.x + x + 1, frame.pos.y + y + 1, frame.size.width, frame.size.height), + horiz, + vert, + p, + getVirtualScale() + ); + + m_font->setColor(UColor(1, 1, 1, alpha)); + frame = getClientFrame(); + + m_font->PrintJustified( + UIRect2D(frame.pos.x + x, frame.pos.y + y, frame.size.width, frame.size.height), + horiz, + vert, + p, + getVirtualScale() + ); + + m_font->setColor(UBlack); + m_printfadetime -= cls.frametime; + + if (m_printfadetime < 0) { + m_printfadetime = 0; + } +} + +void View3D::DrawLetterbox(void) +{ + float frac; + vec4_t col; + + col[0] = col[1] = col[2] = 0; + col[3] = 1; + + frac = (float)cl.snap.ps.stats[STAT_LETTERBOX] / MAX_LETTERBOX_SIZE; + if (frac <= 0) { + m_letterbox_active = false; + return; + } + + m_letterbox_active = true; + re.SetColor(col); + + re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height * frac); + re.DrawBox( + 0.0, + m_screenframe.size.height - m_screenframe.size.height * frac, + m_screenframe.size.width, + m_screenframe.size.height + ); +} + +void View3D::DrawFades(void) +{ + if (cl.snap.ps.blend[3] > 0) { + re.SetColor(cl.snap.ps.blend); + if (cl.snap.ps.stats[STAT_ADDFADE]) { + re.AddBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height); + } else { + re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height); + } + } +} + +void View3D::Draw(void) +{ + if (clc.state != CA_DISCONNECTED) { + SCR_DrawScreenField(); + } + + set2D(); + + re.SavePerformanceCounters(); + + Draw2D(); } float avWidth = 0.0; -void View3D::InitSubtitle - ( - void - ) - +void View3D::InitSubtitle(void) { - float totalWidth; + float totalWidth; - for (int i = 0; i < 4; i++) { - subs[i] = Cvar_Get(va("subtitle%d", i), "", 0); - teams[i] = Cvar_Get(va("subteam%d", i), "0", 0); - strcpy(oldStrings[i], subs[i]->string); - fadeTime[i] = 4000.0; - subLife[i] = 4000.0; - } + for (int i = 0; i < 4; i++) { + subs[i] = Cvar_Get(va("subtitle%d", i), "", 0); + teams[i] = Cvar_Get(va("subteam%d", i), "0", 0); + Q_strncpyz(oldStrings[i], subs[i]->string, sizeof(oldStrings[i])); + fadeTime[i] = 4000.0; + subLife[i] = 4000.0; + } - totalWidth = 0.0; - for (char j = 'A'; j <= 'Z'; j++) { - totalWidth += m_font->getCharWidth(j); - } + totalWidth = 0.0; + for (char j = 'A'; j <= 'Z'; j++) { + totalWidth += m_font->getCharWidth(j); + } - avWidth = totalWidth / 26.0; + avWidth = totalWidth / 26.0; } -void View3D::FrameInitialized - ( - void - ) - +void View3D::DrawSubtitleOverlay(void) { - Connect(this, W_Activated, W_Activated); - Connect(this, W_Deactivated, W_Deactivated); + cvar_t *subAlpha; + int i; + float minX, maxX; + int line; + + subAlpha = Cvar_Get("subAlpha", "0.5", 0); + + setFont("facfont-20"); + m_font->setColor(URed); + + for (i = 0; i < MAX_SUBTITLES; i++) { + if (strcmp(oldStrings[i], subs[i]->string)) { + fadeTime[i] = 2500 * ((strlen(subs[i]->string) / 68) + 1.f) + 1500; + subLife[i] = fadeTime[i]; + Q_strncpyz(oldStrings[i], subs[i]->string, sizeof(oldStrings[i])); + } + + if (fadeTime[i] > subLife[i] - 750.f) { + alpha[i] = 1.f - (fadeTime[i] - (subLife[i] - 750.f)) / 750.f; + } else if (fadeTime[i] < 750) { + alpha[i] = fadeTime[i] / 750.f; + } else { + alpha[i] = 1.f; + } + + fadeTime[i] -= cls.frametime; + if (fadeTime[i] < 0) { + // Clear the subtitle + fadeTime[i] = 0; + oldStrings[i][0] = 0; + + if (subs[i]->string && subs[i]->string[0]) { + Cvar_Set(va("subtitle%d", i), ""); + } + } + } + + minX = m_screenframe.size.height - m_font->getHeight(getHighResScale()) * 10; + maxX = ((m_frame.pos.x + m_frame.size.width) - (m_frame.pos.x + m_frame.size.width) * 0.2f) / getHighResScale()[0]; + line = 0; + + for (i = 0; i < MAX_SUBTITLES; i++) { + if (fadeTime[i] <= 0) { + continue; + } + + if (m_font->getWidth(subs[i]->string, sizeof(oldStrings[i])) > maxX) { + char buf[2048]; + char *c; + char *end; + char *start; + float total; + float width; + int blockcount; + + c = subs[i]->string; + + total = 0; + end = NULL; + start = buf; + + while (*c) { + blockcount = m_font->DBCSGetWordBlockCount(c, -1); + if (!blockcount) { + break; + } + + width = m_font->getWidth(c, blockcount); + + if (total + width > maxX) { + m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value)); + m_font->Print(18, (m_font->getHeight(getHighResScale()) * line + minX + 1.f) / getHighResScale()[1], buf, -1, getHighResScale()); + + m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value)); + m_font->Print(20, (m_font->getHeight(getHighResScale()) * line + minX) / getHighResScale()[1], buf, -1, getHighResScale()); + + line++; + + total = 0; + start = buf; + } + + end = start + blockcount + 1; + if (end > buf + MAX_STRING_CHARS) { + Com_DPrintf("ERROR - word longer than possible line\n"); + break; + } + + memcpy(start, c, blockcount); + start += blockcount; + total += width; + *start = 0; + + c += blockcount; + } + + m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value)); + m_font->Print(18, (m_font->getHeight(getHighResScale()) * line + minX + 1.f) / getHighResScale()[1], buf, -1, getHighResScale()); + + m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value)); + m_font->Print(20, (m_font->getHeight(getHighResScale()) * line + minX) / getHighResScale()[1], buf, -1, getHighResScale()); + line++; + } else { + m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value)); + m_font->Print(18, (m_font->getHeight(getHighResScale()) * line + minX + 1.f) / getHighResScale()[1], subs[i]->string, -1, getHighResScale()); + + m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value)); + m_font->Print(20, (m_font->getHeight(getHighResScale()) * line + minX) / getHighResScale()[1], subs[i]->string, -1, getHighResScale()); + + line++; + } + } } -void View3D::Pressed - ( - Event *ev - ) - +void View3D::ClearCenterPrint(void) { - IN_MouseOff(); - OnActivate(ev); + m_printfadetime = 0.0; } -CLASS_DECLARATION( UIWidget, ConsoleView, NULL ) +qboolean View3D::LetterboxActive(void) { - { NULL, NULL } + return m_letterbox_active; +} + +CLASS_DECLARATION(UIWidget, ConsoleView, NULL) { + {NULL, NULL} }; -void ConsoleView::Draw - ( - void - ) - -{ - // FIXME: unimplemented -} - +void ConsoleView::Draw(void) {} diff --git a/code/client/cl_uiview3d.h b/code/client/cl_uiview3d.h index 31200c05..ef11c986 100644 --- a/code/client/cl_uiview3d.h +++ b/code/client/cl_uiview3d.h @@ -20,55 +20,57 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __CL_UIVIEW3D__ -#define __CL_UIVIEW3D__ +#pragma once -class View3D : public UIWidget { - float m_printfadetime; - float m_printalpha; - str m_printstring; - UIReggedMaterial *m_print_mat; - qboolean m_locationprint; - int m_x_coord; - int m_y_coord; - qboolean m_letterbox_active; +class View3D : public UIWidget +{ + float m_printfadetime; + float m_printalpha; + str m_printstring; + UIReggedMaterial *m_print_mat; + qboolean m_locationprint; + int m_x_coord; + int m_y_coord; + qboolean m_letterbox_active; public: - CLASS_PROTOTYPE( View3D ); + CLASS_PROTOTYPE(View3D); protected: - void Draw( void ) override; - void DrawLetterbox( void ); - void DrawFades( void ); - void Draw2D( void ); - void DrawFPS( void ); - void DrawProf( void ); - void PrintSound( int channel, const char *name, float vol, int rvol, float pitch, float base, int& line ); - void DrawSoundOverlay( void ); - void CenterPrint( void ); - void LocationPrint( void ); - void OnActivate( Event *ev ); - void OnDeactivate( Event *ev ); - void DrawSubtitleOverlay( void ); + void Draw(void) override; + void DrawLetterbox(void); + void DrawFades(void); + void Draw2D(void); + void DrawFPS(void); + void DrawProf(void); + void PrintSound(int channel, const char *name, float vol, int rvol, float pitch, float base, int& line); + void DrawSoundOverlay(void); + void CenterPrint(void); + void LocationPrint(void); + void OnActivate(Event *ev); + void OnDeactivate(Event *ev); + void DrawSubtitleOverlay(void); + + // Added in 2.0 + void DrawNetProfile(void); public: - View3D(); + View3D(); - void ClearCenterPrint( void ); - void UpdateCenterPrint( const char *s, float alpha ); - void UpdateLocationPrint( int x, int y, const char *s, float alpha ); - qboolean LetterboxActive( void ); - void InitSubtitle( void ); - void FrameInitialized( void ) override; - virtual void Pressed( Event *ev ); + void ClearCenterPrint(void); + void UpdateCenterPrint(const char *s, float alpha); + void UpdateLocationPrint(int x, int y, const char *s, float alpha); + qboolean LetterboxActive(void); + void InitSubtitle(void); + void FrameInitialized(void) override; + virtual void Pressed(Event *ev); }; -class ConsoleView : public UIWidget { +class ConsoleView : public UIWidget +{ public: - CLASS_PROTOTYPE( ConsoleView ); + CLASS_PROTOTYPE(ConsoleView); protected: - void Draw( void ) override; + void Draw(void) override; }; - -#endif /* __CL_UIVIEW3D__ */ diff --git a/code/client/client.h b/code/client/client.h index b6f44303..c693fbe8 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -21,8 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // client.h -- primary header for client -#ifndef __CLIENT_H__ -#define __CLIENT_H__ +#pragma once #include "../qcommon/q_shared.h" #include "../qcommon/qcommon.h" @@ -37,6 +36,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_curl.h" #endif /* USE_CURL */ +#ifdef USE_VOIP +#include +#endif + // file full of random crap that gets used to create cl_guid #define QKEY_FILE "qkey" #define QKEY_SIZE 2048 @@ -175,6 +178,7 @@ typedef struct { int lastPacketSentTime; // for retransmits during connection int lastPacketTime; // for timeouts + char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect) netadr_t serverAddress; int connectTime; // for connection retransmits int connectStartTime; @@ -240,15 +244,42 @@ typedef struct { int timeDemoMaxDuration; // maximum frame duration unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations + float aviVideoFrameRemainder; + float aviSoundFrameRemainder; + +#ifdef USE_VOIP + qboolean voipEnabled; + qboolean voipCodecInitialized; + + // incoming data... + // !!! FIXME: convert from parallel arrays to array of a struct. + OpusDecoder *opusDecoder[MAX_CLIENTS]; + byte voipIncomingGeneration[MAX_CLIENTS]; + int voipIncomingSequence[MAX_CLIENTS]; + float voipGain[MAX_CLIENTS]; + qboolean voipIgnore[MAX_CLIENTS]; + qboolean voipMuteAll; + + // outgoing data... + // if voipTargets[i / 8] & (1 << (i % 8)), + // then we are sending to clientnum i. + uint8_t voipTargets[(MAX_CLIENTS + 7) / 8]; + uint8_t voipFlags; + OpusEncoder *opusEncoder; + int voipOutgoingDataSize; + int voipOutgoingDataFrames; + int voipOutgoingSequence; + byte voipOutgoingGeneration; + byte voipOutgoingData[1024]; + float voipPower; +#endif + #ifdef LEGACY_PROTOCOL qboolean compat; #endif // big stuff at end of structure so most offsets are 15 bits or less netchan_t netchan; - - float aviVideoFrameRemainder; - float aviSoundFrameRemainder; } clientConnection_t; extern clientConnection_t clc; @@ -298,8 +329,6 @@ typedef struct { qboolean cddialog; // bring up the cd needed dialog next frame qboolean no_menus; - char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect) - // when the server clears the hunk, all of these must be restarted qboolean rendererRegistered; qboolean cgameStarted; @@ -321,7 +350,7 @@ typedef struct { serverInfo_t globalServers[MAX_GLOBAL_SERVERS]; // additional global servers int numGlobalServerAddresses; - serverAddress_t globalServerAddresses[MAX_GLOBAL_SERVERS]; + netadr_t globalServerAddresses[MAX_GLOBAL_SERVERS]; int numfavoriteservers; serverInfo_t favoriteServers[MAX_OTHER_SERVERS]; @@ -352,14 +381,16 @@ typedef struct { clientAnim_t anim; stopWatch_t stopwatch; void* savedCgameState; - int savedCgameStateSize; + size_t savedCgameStateSize; char gcdResponse[73]; - int unknown3_0; - int currentRate; + // Added in 2.0 + netprofclient_t netprofile; qhandle_t charSetShader; qhandle_t whiteShader; qhandle_t consoleShader; fontInfo_t consoleFont; + + int refSequence; } clientStatic_t; extern clientStatic_t cls; @@ -386,6 +417,8 @@ extern cvar_t *cl_connect_timeout; extern cvar_t *cl_maxpackets; extern cvar_t *cl_packetdup; extern cvar_t *cl_shownet; +extern cvar_t *cl_netprofile; +extern cvar_t *cl_netprofileoverlay; extern cvar_t *cl_showSend; extern cvar_t *cl_timeNudge; extern cvar_t *cl_showTimeDelta; @@ -446,6 +479,32 @@ extern cvar_t *cl_r_fullscreen; extern cvar_t *cl_consoleKeys; +#ifdef USE_MUMBLE +extern cvar_t *cl_useMumble; +extern cvar_t *cl_mumbleScale; +#endif + +#ifdef USE_VOIP +// cl_voipSendTarget is a string: "all" to broadcast to everyone, "none" to +// send to no one, or a comma-separated list of client numbers: +// "0,7,2,23" ... an empty string is treated like "all". +extern cvar_t *cl_voipUseVAD; +extern cvar_t *cl_voipVADThreshold; +extern cvar_t *cl_voipSend; +extern cvar_t *cl_voipSendTarget; +extern cvar_t *cl_voipGainDuringCapture; +extern cvar_t *cl_voipCaptureMult; +extern cvar_t *cl_voipShowMeter; +extern cvar_t *cl_voip; + +// 20ms at 48k +#define VOIP_MAX_FRAME_SAMPLES ( 20 * 48 ) + +// 3 frame is 60ms of audio, the max opus will encode at once +#define VOIP_MAX_PACKET_FRAMES 3 +#define VOIP_MAX_PACKET_SAMPLES ( VOIP_MAX_FRAME_SAMPLES * VOIP_MAX_PACKET_FRAMES ) +#endif + extern cvar_t *cg_gametype; extern cvar_t* j_pitch; @@ -471,7 +530,7 @@ void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd); void CL_StartHunkUsers( qboolean rendererOnly ); -void CL_Connect( const char *server ); +void CL_Connect( const char *server, netadrtype_t family ); void CL_Disconnect_f (void); void CL_GetChallengePacket (void); @@ -500,6 +559,10 @@ void UI_LoadResource( const char *name ); qboolean CL_CheckPaused(void); +int CL_GetRefSequence(void); +qboolean CL_IsRendererLoaded(void); +void CL_ApplyOriginalConfigTweaks(); + // // cl_input // @@ -521,6 +584,7 @@ void IN_MouseOn( void ); void IN_MouseOff( void ); void CL_InitInput (void); +void CL_ShutdownInput(void); void CL_SendCmd (void); void CL_ClearState (void); void CL_ReadPackets (void); @@ -546,6 +610,10 @@ extern int cl_connectedToPureServer; extern int cl_connectedToCheatServer; extern msg_t *cl_currentMSG; +#ifdef USE_VOIP +void CL_Voip_f( void ); +#endif + void CL_SystemInfoChanged( void ); void CL_ParseServerMessage( msg_t *msg ); @@ -584,6 +652,7 @@ void Con_DrawCharacter (int cx, int line, int num); void Con_CheckResize (void); void Con_Init (void); +void Con_Shutdown (void); void Con_Clear_f (void); void Con_ToggleConsole_f (void); void Con_DrawNotify (void); @@ -671,6 +740,7 @@ void LAN_SaveServersToCache( void ); void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg); //int length, const byte *data ); void CL_Netchan_TransmitNextFragment( netchan_t *chan ); qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ); +void CL_NET_OutOfBandPrint( netadr_t adr, const char* format, ... ); // // cl_avi.c @@ -690,5 +760,3 @@ void CL_InitConsoleCommands( void ); #ifdef __cplusplus } #endif - -#endif // __CLIENT_H__ diff --git a/code/client/new/snd_local_new.h b/code/client/new/snd_local_new.h index ac253ec8..69ae7dcf 100644 --- a/code/client/new/snd_local_new.h +++ b/code/client/new/snd_local_new.h @@ -58,6 +58,10 @@ typedef struct { void S_ChannelFree_Callback(channel_t* v); void S_LoadData(soundsystemsavegame_t* pSave); +void S_SaveData(soundsystemsavegame_t* pSave); +void S_ReLoad(soundsystemsavegame_t* pSave); + +extern qboolean s_bSoundPaused; #ifdef __cplusplus } diff --git a/code/client/new/snd_main_new.cpp b/code/client/new/snd_main_new.cpp index 3b6971be..2bb4aa37 100644 --- a/code/client/new/snd_main_new.cpp +++ b/code/client/new/snd_main_new.cpp @@ -21,11 +21,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../snd_local.h" +#include "../client.h" + +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA + +qboolean s_bSoundPaused = qfalse; void S_Init2() { S_Init(); SND_setup(); + + // HACK: S_RegisterSound returns 0 when unsuccessful, or it returns the the sfx handle + // But the first sfx handle is also 0... + S_RegisterSound("sound/null.wav", qfalse); + + Cmd_AddCommand("tmstart", S_TriggeredMusic_Start); + Cmd_AddCommand("tmstartloop", S_TriggeredMusic_StartLoop); + Cmd_AddCommand("tmstop", S_TriggeredMusic_Stop); } /* @@ -46,7 +59,18 @@ S_AddLoopingSound */ void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle, float volume, float minDist, float maxDist, float pitch, int flags) { + if (!sfxHandle) { + return; + } + // FIXME: unimplemented + + if (VectorCompare(origin, vec3_origin)) { + // Consider it to be a local sound, uses the player origin + S_AddLoopingSound(cl.snap.ps.clientNum, cl.snap.ps.origin, velocity, sfxHandle); + return; + } + S_AddLoopingSound(ENTITYNUM_WORLD, origin, velocity, sfxHandle); } @@ -55,7 +79,7 @@ void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t s S_StopAllSounds ================= */ -void S_StopAllSounds(qboolean stop_music) +void S_StopAllSounds2(qboolean stop_music) { // Call the original function S_StopAllSounds(); @@ -83,12 +107,29 @@ void S_Respatialize(int entityNum, const vec3_t origin, { S_Respatialize(entityNum, origin, axis, 0); } + +/* +================= +S_StartLocalSoundChannel +================= +*/ +void S_StartLocalSound(const char* sound_name, qboolean force_load) +{ + sfxHandle_t h; + + h = S_RegisterSound(sound_name, qfalse); + + if (h) { + S_StartLocalSound(h, CHAN_LOCAL_SOUND); + } +} + /* ================= S_StartLocalSound ================= */ -void S_StartLocalSound(const char* sound_name, qboolean force_load) +void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, int channel) { // FIXME: unimplemented } @@ -340,6 +381,16 @@ void MUSIC_CheckForStoppedSongs(void) STUB(); } +/* +============== +S_CurrentSoundtrack +============== +*/ +const char* S_CurrentSoundtrack() +{ + return ""; +} + /* ================= S_IsSoundRegistered @@ -404,22 +455,166 @@ void S_FadeSound(float fTime) // FIXME: unimplemented } +/* +============== +S_TriggeredMusic_Start +============== +*/ +void S_TriggeredMusic_Start() +{ + if (Cmd_Argc() != 2) { + Com_Printf("tmstart \n"); + return; + } + + S_StartBackgroundTrack(Cmd_Argv(1), ""); +} + +/* +============== +S_TriggeredMusic_StartLoop +============== +*/ +void S_TriggeredMusic_StartLoop() +{ + if (Cmd_Argc() != 2) { + Com_Printf("tmstartloop \n"); + return; + } + + S_StartBackgroundTrack(Cmd_Argv(1), Cmd_Argv(1)); +} + +/* +============== +S_TriggeredMusic_Stop +============== +*/ +void S_TriggeredMusic_Stop() +{ + S_StopBackgroundTrack(); +} + +/* +============== +S_TriggeredMusic_PlayIntroMusic +============== +*/ void S_TriggeredMusic_PlayIntroMusic() { + S_StartBackgroundTrack("sound/music/mus_MainTheme.mp3", ""); +} + +/* +============== +S_TriggeredMusic_SetupHandle +============== +*/ +void S_TriggeredMusic_SetupHandle(const char* pszName, int iLoopCount, int iOffset, qboolean autostart) { // FIXME: unimplemented } +/* +============== +S_GetMusicFilename +============== +*/ +const char* S_GetMusicFilename() { + // FIXME: unimplemented + return ""; +} + +/* +============== +S_GetMusicLoopCount +============== +*/ +int S_GetMusicLoopCount() { + // FIXME: unimplemented + return 0; +} + +/* +============== +S_GetMusicOffset +============== +*/ +unsigned int S_GetMusicOffset() { + // FIXME: unimplemented + return 0; +} + +/* +============== +callbackServer +============== +*/ void callbackServer(int entnum, int channel_number, const char* name) { if (com_sv_running->integer) { SV_SoundCallback(entnum, channel_number, name); } } +/* +============== +S_ChannelFree_Callback +============== +*/ void S_ChannelFree_Callback(channel_t* v) { if (v->entnum & S_FLAG_DO_CALLBACK) { callbackServer(v->entnum & ~S_FLAG_DO_CALLBACK, v - s_channels, v->thesfx->soundName); } } +/* +============== +S_LoadData +============== +*/ void S_LoadData(soundsystemsavegame_t* pSave) { // FIXME: unimplemented } + +/* +============== +S_SaveData +============== +*/ +void S_SaveData(soundsystemsavegame_t* pSave) { + // FIXME: unimplemented +} + +/* +============== +S_ReLoad +============== +*/ +void S_ReLoad(soundsystemsavegame_t* pSave) { + // FIXME: unimplemented +} + +/* +============== +S_StopMovieAudio +============== +*/ +void S_StopMovieAudio() { +} + +/* +============== +S_CurrentMoviePosition +============== +*/ +int S_CurrentMoviePosition() { + return 0; +} + +/* +============== +S_SetupMovieAudio +============== +*/ +void S_SetupMovieAudio(const char* pszMovieName) { +} + +#endif diff --git a/code/client/new/snd_public_new.h b/code/client/new/snd_public_new.h index d2a7f9a8..4b98fb86 100644 --- a/code/client/new/snd_public_new.h +++ b/code/client/new/snd_public_new.h @@ -30,8 +30,8 @@ void S_Respatialize(int entityNum, const vec3_t origin, vec3_t axis[3]); sfxHandle_t S_RegisterSound(const char* sample, qboolean compressed, qboolean streamed); void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle, float volume, float minDist, float maxDist, float pitch, int flags); void S_StartLocalSound(const char* name, qboolean force_load); +void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, int channel); void S_StartSound(const vec3_t origin, int entNum, int entChannel, sfxHandle_t sfxHandle, float volume, float minDist, float pitch, float maxDist, qboolean streamed); -void S_StopAllSounds(qboolean stop_music); void S_ClearLoopingSounds(void); qboolean S_IsSoundRegistered(const char* name); void S_Init2(); @@ -64,7 +64,14 @@ qboolean MUSIC_PlaySong(const char* alias); void MUSIC_UpdateMusicVolumes(void); void MUSIC_CheckForStoppedSongs(void); +void S_TriggeredMusic_Start(); +void S_TriggeredMusic_StartLoop(); +void S_TriggeredMusic_Stop(); + +const char* S_CurrentSoundtrack(); + void S_StopSound(int entnum, int channel); +void S_StopAllSounds2(qboolean stop_music); float S_GetSoundTime(sfxHandle_t handle); void S_SetGlobalAmbientVolumeLevel(float volume); void S_SetReverb(int reverb_type, float reverb_level); @@ -73,6 +80,15 @@ qboolean S_IsSoundPlaying(int channelNumber, const char* name); void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t velocity, qboolean use_listener); void S_FadeSound(float fTime); void S_TriggeredMusic_PlayIntroMusic(); +void S_TriggeredMusic_SetupHandle(const char* pszName, int iLoopCount, int iOffset, qboolean autostart); + +const char* S_GetMusicFilename(); +int S_GetMusicLoopCount(); +unsigned int S_GetMusicOffset(); + +void S_StopMovieAudio(); +int S_CurrentMoviePosition(); +void S_SetupMovieAudio(const char* pszMovieName); #ifdef __cplusplus } diff --git a/code/client/qal.c b/code/client/qal.c index 5cc40de2..78e0b80e 100644 --- a/code/client/qal.c +++ b/code/client/qal.c @@ -66,6 +66,7 @@ LPALGETSOURCEF qalGetSourcef; LPALGETSOURCE3F qalGetSource3f; LPALGETSOURCEFV qalGetSourcefv; LPALGETSOURCEI qalGetSourcei; +LPALGETSOURCEIV qalGetSourceiv; LPALSOURCEPLAYV qalSourcePlayv; LPALSOURCESTOPV qalSourceStopv; LPALSOURCEREWINDV qalSourceRewindv; @@ -80,7 +81,9 @@ LPALGENBUFFERS qalGenBuffers; LPALDELETEBUFFERS qalDeleteBuffers; LPALISBUFFER qalIsBuffer; LPALBUFFERDATA qalBufferData; +LPALBUFFERI qalBufferi; LPALGETBUFFERF qalGetBufferf; +LPALGETBUFFERFV qalGetBufferfv; LPALGETBUFFERI qalGetBufferi; LPALDOPPLERFACTOR qalDopplerFactor; LPALSPEEDOFSOUND qalSpeedOfSound; @@ -184,6 +187,7 @@ qboolean QAL_Init(const char *libname) qalGetSource3f = GPA("alGetSource3f"); qalGetSourcefv = GPA("alGetSourcefv"); qalGetSourcei = GPA("alGetSourcei"); + qalGetSourceiv = GPA("alGetSourceiv"); qalSourcePlayv = GPA("alSourcePlayv"); qalSourceStopv = GPA("alSourceStopv"); qalSourceRewindv = GPA("alSourceRewindv"); @@ -198,7 +202,9 @@ qboolean QAL_Init(const char *libname) qalDeleteBuffers = GPA("alDeleteBuffers"); qalIsBuffer = GPA("alIsBuffer"); qalBufferData = GPA("alBufferData"); + qalBufferi = GPA("alBufferi"); qalGetBufferf = GPA("alGetBufferf"); + qalGetBufferfv = GPA("alGetBufferfv"); qalGetBufferi = GPA("alGetBufferi"); qalDopplerFactor = GPA("alDopplerFactor"); qalSpeedOfSound = GPA("alSpeedOfSound"); @@ -283,6 +289,7 @@ void QAL_Shutdown( void ) qalGetSource3f = NULL; qalGetSourcefv = NULL; qalGetSourcei = NULL; + qalGetSourceiv = NULL; qalSourcePlayv = NULL; qalSourceStopv = NULL; qalSourceRewindv = NULL; @@ -298,6 +305,7 @@ void QAL_Shutdown( void ) qalIsBuffer = NULL; qalBufferData = NULL; qalGetBufferf = NULL; + qalGetBufferfv = NULL; qalGetBufferi = NULL; qalDopplerFactor = NULL; qalSpeedOfSound = NULL; diff --git a/code/client/qal.h b/code/client/qal.h index a478eb53..c676b195 100644 --- a/code/client/qal.h +++ b/code/client/qal.h @@ -36,15 +36,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifdef USE_LOCAL_HEADERS #include "../AL/al.h" #include "../AL/alc.h" +#include "../AL/alext.h" #else #if defined(_MSC_VER) || defined(__APPLE__) // MSVC users must install the OpenAL SDK which doesn't use the AL/*.h scheme. // OSX framework also needs this #include #include + #include #else #include #include + #include #endif #endif @@ -55,6 +58,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # define ALC_ALL_DEVICES_SPECIFIER 0x1013 #endif +#ifdef __cplusplus +extern "C" { +#endif + #ifdef USE_OPENAL_DLOPEN extern LPALENABLE qalEnable; extern LPALDISABLE qalDisable; @@ -116,7 +123,7 @@ extern LPALBUFFERDATA qalBufferData; extern LPALBUFFERF qalBufferf; extern LPALBUFFER3F qalBuffer3f; extern LPALBUFFERFV qalBufferfv; -extern LPALBUFFERF qalBufferi; +extern LPALBUFFERI qalBufferi; extern LPALBUFFER3F qalBuffer3i; extern LPALBUFFERFV qalBufferiv; extern LPALGETBUFFERF qalGetBufferf; @@ -248,4 +255,8 @@ extern LPALCCAPTURESAMPLES qalcCaptureSamples; qboolean QAL_Init(const char *libname); void QAL_Shutdown( void ); +#ifdef __cplusplus +} +#endif + #endif // __QAL_H__ diff --git a/code/client/snd_codec.h b/code/client/snd_codec.h index 49970dff..8551827d 100644 --- a/code/client/snd_codec.h +++ b/code/client/snd_codec.h @@ -27,14 +27,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/q_shared.h" #include "../qcommon/qcommon.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct snd_info_s { int rate; - int width; + float width; int channels; int samples; int size; int dataofs; + int dataalign; } snd_info_t; typedef struct snd_codec_s snd_codec_t; @@ -113,4 +118,8 @@ void S_OggOpus_CodecCloseStream(snd_stream_t *stream); int S_OggOpus_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer); #endif // USE_CODEC_OPUS +#ifdef __cplusplus +} +#endif + #endif // !_SND_CODEC_H_ diff --git a/code/client/snd_codec_mp3.c b/code/client/snd_codec_mp3.c index 80a02326..bcb60e60 100644 --- a/code/client/snd_codec_mp3.c +++ b/code/client/snd_codec_mp3.c @@ -31,7 +31,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "snd_codec.h" // includes for the MP3 codec -#include "../libmad-0.15.1b/synth.h" +#include "mad.h" #define MP3_SAMPLE_WIDTH 2 #define MP3_PCMSAMPLES_PERSLICE 32 @@ -622,7 +622,7 @@ int S_MP3_CodecReadStream(snd_stream_t* stream, int bytes, void* buffer) mp3info = stream->ptr; // Make sure we get complete frames all the way through. - bytes -= bytes % (stream->info.channels * stream->info.width); + bytes -= fmod(bytes, (stream->info.channels * stream->info.width)); if (mp3info->buflen) { diff --git a/code/client/snd_codec_wav.c b/code/client/snd_codec_wav.c index 7fcdea59..7fed9bf3 100644 --- a/code/client/snd_codec_wav.c +++ b/code/client/snd_codec_wav.c @@ -133,6 +133,7 @@ static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info) char dump[16]; int bits; int fmtlen = 0; + int bytealign; // skip the riff wav header FS_Read(dump, 12, file); @@ -149,17 +150,22 @@ static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info) info->channels = FGetLittleShort(file); info->rate = FGetLittleLong(file); FGetLittleLong(file); - FGetLittleShort(file); + bytealign = FGetLittleShort(file); bits = FGetLittleShort(file); - if( bits < 8 ) - { - Com_Printf( S_COLOR_RED "ERROR: Less than 8 bit sound is not supported\n"); - return qfalse; - } + //if( bits < 8 ) + //{ + // Com_Printf( S_COLOR_RED "ERROR: Less than 8 bit sound is not supported\n"); + // return qfalse; + //} - info->width = bits / 8; + info->width = bits / 8.0; info->dataofs = 0; + if (bits == 16) { + info->dataalign = 1; + } else { + info->dataalign = (bytealign / info->channels - 4) / 4 * 8 + 1; + } // Skip the rest of the format chunk if required if(fmtlen > 16) diff --git a/code/client/snd_dma.c b/code/client/snd_dma.c index 67720678..cfb0ca28 100644 --- a/code/client/snd_dma.c +++ b/code/client/snd_dma.c @@ -161,12 +161,12 @@ void S_Base_SoundList( void ) { char type[4][16]; char mem[2][16]; - strcpy(type[0], "16bit"); - strcpy(type[1], "adpcm"); - strcpy(type[2], "daub4"); - strcpy(type[3], "mulaw"); - strcpy(mem[0], "paged out"); - strcpy(mem[1], "resident "); + Q_strncpyz(type[0], "16bit", sizeof(type[0])); + Q_strncpyz(type[1], "adpcm", sizeof(type[1])); + Q_strncpyz(type[2], "daub4", sizeof(type[2])); + Q_strncpyz(type[3], "mulaw", sizeof(type[3])); + Q_strncpyz(mem[0], "paged out", sizeof(mem[0])); + Q_strncpyz(mem[1], "resident ", sizeof(mem[1])); total = 0; for (sfx=s_knownSfx, i=0 ; isoundLength; @@ -303,7 +303,7 @@ static sfx_t *S_FindName( const char *name ) { sfx = &s_knownSfx[i]; Com_Memset (sfx, 0, sizeof(*sfx)); - strcpy (sfx->soundName, name); + Q_strncpyz (sfx->soundName, name, sizeof(sfx->soundName)); sfx->next = sfxHash[hash]; sfxHash[hash] = sfx; @@ -785,7 +785,11 @@ void S_Base_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t ve } if ( !sfx->soundLength ) { - Com_Error( ERR_DROP, "%s has length 0", sfx->soundName ); + // Fixed in OPM + // Why should it crash??? + //Com_Error( ERR_DROP, "%s has length 0", sfx->soundName ); + Com_Printf( "%s has length 0\n", sfx->soundName ); + return; } VectorCopy( origin, loopSounds[entityNum].origin ); @@ -848,7 +852,11 @@ void S_Base_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_ } if ( !sfx->soundLength ) { - Com_Error( ERR_DROP, "%s has length 0", sfx->soundName ); + // Fixed in OPM + // Why should it crash??? + //Com_Error( ERR_DROP, "%s has length 0", sfx->soundName ); + Com_Printf( "%s has length 0", sfx->soundName ); + return; } VectorCopy( origin, loopSounds[entityNum].origin ); VectorCopy( velocity, loopSounds[entityNum].velocity ); @@ -1581,7 +1589,9 @@ qboolean S_Base_Init( soundInterface_t *si ) { if ( r ) { s_soundStarted = 1; - s_soundMuted = 1; +// Fixed in OPM +// The UI must be able to play sounds +// s_soundMuted = 1; // s_numSfx = 0; Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH); diff --git a/code/client/snd_dma_new.cpp b/code/client/snd_dma_new.cpp new file mode 100644 index 00000000..47fb79eb --- /dev/null +++ b/code/client/snd_dma_new.cpp @@ -0,0 +1,830 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "snd_local.h" +#include "snd_openal_new.h" +#include "client.h" +#include "cl_ui.h" + +typedef struct { + vec3_t origin; + vec3_t velocity; + sfx_t *sfx; + int mergeFrame; +} loopSound_t; + +qboolean s_bLastInitSound = qfalse; +qboolean s_bSoundStarted = qfalse; +qboolean s_bSoundPaused = qfalse; +qboolean s_bTryUnpause = qfalse; +int s_iListenerNumber = 0; +float s_fAmbientVolume = 1.f; + +int number_of_sfx_infos = 0; + +cvar_t *s_volume; +cvar_t *s_loadas8bit; +cvar_t *s_khz; +cvar_t *s_show; +cvar_t *s_testsound; +cvar_t *s_separation; +cvar_t *s_musicVolume; +cvar_t *s_ambientVolume; + +sfx_info_t sfx_infos[MAX_SFX_INFOS]; + +sfx_t s_knownSfx[MAX_SFX]; +int s_numSfx; + +s_entity_t s_entity[MAX_GENTITIES]; + +static int s_registrationSequence; +static qboolean s_inRegistration; + +cvar_t *s_mixPreStep; +cvar_t *s_dialogscale; + +int numLoopSounds; +loopSound_t loopSounds[MAX_LOOP_SOUNDS]; + +/* +============== +S_SoundInfo_f +============== +*/ +void S_SoundInfo_f() +{ + S_PrintInfo(); +} + +/* +============== +S_SoundDump_f +============== +*/ +void S_SoundDump_f() +{ + S_DumpInfo(); +} + +/* +============== +S_Init +============== +*/ +void S_Init(qboolean full_startup) +{ + int iStart, iEnd; + cvar_t *cv; + + Com_Printf("------- Sound Initialization (%s) -------\n", full_startup ? "full" : "partial"); + + iStart = Sys_Milliseconds(); + + s_volume = Cvar_Get("s_volume", "0.9", CVAR_ARCHIVE); + s_musicVolume = Cvar_Get("s_musicvolume", "0.9", CVAR_ARCHIVE); + s_ambientVolume = Cvar_Get("s_ambientvolume", "1.00", CVAR_ARCHIVE); + s_separation = Cvar_Get("s_separation", "0.5", CVAR_ARCHIVE); + s_khz = Cvar_Get("s_khz", "44", CVAR_ARCHIVE | CVAR_SOUND_LATCH); + s_loadas8bit = Cvar_Get("s_loadas8bit", "0", CVAR_ARCHIVE | CVAR_LATCH); + s_mixPreStep = Cvar_Get("s_mixPreStep", "0.05", CVAR_ARCHIVE); + s_show = Cvar_Get("s_show", "0", CVAR_CHEAT); + s_testsound = Cvar_Get("s_testsound", "0", CVAR_CHEAT); + s_dialogscale = Cvar_Get("s_dialogscale", "1", CVAR_ARCHIVE); + s_bLastInitSound = false; + + cv = Cvar_Get("s_initsound", "1", 0); + + if (cv->integer) { + Cmd_AddCommand("play", S_Play); + Cmd_AddCommand("soundlist", S_SoundList); + Cmd_AddCommand("soundinfo", S_SoundInfo_f); + Cmd_AddCommand("sounddump", S_SoundDump_f); + + if (S_Driver_Init()) { + s_bLastInitSound = true; + s_bSoundStarted = true; + + if (full_startup) { + s_numSfx = 0; + S_StopAllSounds(true); + } + + S_FindName("***DEFAULT***", -1); + S_SoundInfo_f(); + } + } else { + Com_Printf("Sound Not Initializing.\n"); + s_bSoundStarted = 0; + } + + iEnd = Sys_Milliseconds(); + Com_Printf("------- Sound Initialization Complete ------- %i ms\n", iEnd - iStart); +} + +/* +============== +S_Shutdown +============== +*/ +void S_Shutdown(qboolean full_shutdown) +{ + int i; + sfx_t *sfx; + + if (!s_bSoundStarted) { + return; + } + + Com_Printf("------- Sound Shutdown (%s) -------\n", full_shutdown ? "full" : "partial"); + + S_Driver_Shutdown(); + s_bSoundStarted = false; + + Cmd_RemoveCommand("play"); + Cmd_RemoveCommand("music"); + Cmd_RemoveCommand("stopsound"); + Cmd_RemoveCommand("soundlist"); + Cmd_RemoveCommand("soundinfo"); + + if (full_shutdown) { + for (i = 0; i < s_numSfx; i++) { + sfx = &s_knownSfx[i]; + + if (sfx->name[0]) { + if (sfx->data) { + Z_Free(sfx->data); + } + + *sfx = {}; + } + } + + s_numSfx = 0; + } + + Com_Printf("------- Sound Shutdown Complete -------\n"); +} + +/* +============== +S_NameExists +============== +*/ +qboolean S_NameExists(const char *name) +{ + int i; + + if (strlen(name) >= MAX_RES_NAME) { + Com_DPrintf("Sound name too long: %s", name); + return qfalse; + } + + for (i = 0; i < s_numSfx; i++) { + if (!strcmp(s_knownSfx[i].name, name)) { + return qtrue; + } + } + + return qfalse; +} + +/* +============== +S_FindName +============== +*/ +sfx_t *S_FindName(const char *name, int sequenceNumber) +{ + int i; + sfx_t *sfx; + + if (!name) { + Com_DPrintf("S_FindName: NULL\n"); + return NULL; + } + + if (!name[0]) { + Com_DPrintf("S_FindName: empty name\n"); + return NULL; + } + + if (strlen(name) >= MAX_RES_NAME) { + Com_DPrintf("Sound name too long: %s", name); + return NULL; + } + + for (i = 0; i < s_numSfx; i++) { + sfx = &s_knownSfx[i]; + + if (!strcmp(sfx->name, name)) { + if (sfx->registration_sequence != -1) { + sfx->registration_sequence = sequenceNumber; + } + + return sfx; + } + } + + sfx = &s_knownSfx[0]; + + for (i = 0; i < s_numSfx; i++) { + sfx = &s_knownSfx[i]; + if (!sfx->name[0]) { + break; + } + } + + if (i == s_numSfx) { + if (i == MAX_SFX) { + Com_Error(ERR_FATAL, "S_FindName: out of sfx_t"); + } + + sfx = &s_knownSfx[s_numSfx]; + s_numSfx++; + } + + *sfx = {}; + // Fixed in OPM + // strcpy was used before + //strcpy(sfx->name, name); + Q_strncpyz(sfx->name, name, sizeof(sfx->name)); + sfx->registration_sequence = sequenceNumber; + + return sfx; +} + +/* +============== +S_BeginRegistration +============== +*/ +void S_BeginRegistration() +{ + int i; + + Com_Printf("------- Sound Begin Registration -------\n"); + + S_StopAllSounds(true); + + s_registrationSequence++; + s_inRegistration = true; + s_knownSfx[0].registration_sequence = s_registrationSequence; + + Com_Printf("------- Sound Begin Registration Complete -------\n"); + + // Added in OPM + // Reset all sound entities + // OG doesn't do this but this makes sure + // entities don't leak info from previous sessions + for (i = 0; i < ARRAY_LEN(s_entity); i++) { + s_entity[i] = s_entity_t{}; + } +} + +/* +============== +S_DefaultSound +============== +*/ +void S_DefaultSound(sfx_t *sfx) +{ + sfx->data = NULL; + sfx->iFlags |= SFX_FLAG_DEFAULT_SOUND; +} + +/* +============== +S_IsSoundRegistered +============== +*/ +qboolean S_IsSoundRegistered(const char *name) +{ + char szCacheName[MAX_QPATH]; + int i; + + if (!s_bSoundStarted) { + return qfalse; + } + + for (i = 0; name[i] && i < MAX_QPATH; i++) { + szCacheName[i] = tolower(name[i]); + } + szCacheName[i] = 0; + + if (i >= MAX_QPATH) { + Com_Printf("Sound name exceeds MAX_QPATH\n"); + return qfalse; + } + + return S_NameExists(szCacheName); +} + +/* +============== +S_RegisterSound +============== +*/ +sfxHandle_t S_RegisterSound(const char *name, int streamed, qboolean force_load) +{ + char szCacheName[MAX_QPATH]; + sfx_t *sfx; + int i; + + if (!s_bSoundStarted) { + Com_Printf("ERROR: Trying to register sound %s when soundsystem hasn't started.\n", name); + return 0; + } + + if (!name) { + return 0; + } + + for (i = 0; name[i] && i < MAX_QPATH; i++) { + szCacheName[i] = tolower(name[i]); + } + szCacheName[i] = 0; + + if (i >= MAX_QPATH) { + Com_Printf("Sound name exceeds MAX_QPATH\n"); + return 0; + } + + sfx = S_FindName(szCacheName, s_registrationSequence); + if (!sfx) { + return 0; + } + + if (!sfx->data) { + if (!S_LoadSound(sfx->name, sfx, streamed, force_load)) { + Com_DPrintf("Couldn't load sound: %s\n", sfx->name); + if (!S_LoadSound("sound/default.wav", sfx, streamed, 0)) { + Com_DPrintf("Couldn't load sound: sound/default.wav\n"); + sfx->iFlags |= SFX_FLAG_DEFAULT_SOUND; + return 0; + } + } + + sfx->iFlags &= ~SFX_FLAG_DEFAULT_SOUND; + sfx->sfx_info_index = 0; + + for (i = 0; i < number_of_sfx_infos; i++) { + if (!Q_stricmp(sfx->name, sfx_infos[i].name)) { + sfx->sfx_info_index = i; + break; + } + } + } + + return sfx - s_knownSfx; +} + +/* +============== +S_GetSoundTime +============== +*/ +float S_GetSoundTime(sfxHandle_t handle) +{ + return s_knownSfx[handle].time_length; +} + +/* +============== +S_EndRegistration +============== +*/ +void S_EndRegistration() +{ + int i; + sfx_t *sfx; + + Com_Printf("------- Sound End Registration -------\n"); + s_inRegistration = qfalse; + + for (i = 0; i < s_numSfx; i++) { + sfx = &s_knownSfx[i]; + + if (!sfx->name[0]) { + continue; + } + + if (sfx->registration_sequence && sfx->registration_sequence != s_registrationSequence) { + if (sfx->data) { + Z_Free(sfx->data); + } + + *sfx = {}; + } + } + + Com_Printf("------- Sound End Registration Complete -------\n"); +} + +/* +============== +S_UpdateEntity +============== +*/ +void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t vel, qboolean use_listener) +{ + if (entityNum > MAX_GENTITIES) { + Com_Error(ERR_DROP, "S_UpdateEntityPosition: bad entitynum %i", entityNum); + } + + VectorCopy(origin, s_entity[entityNum].position); + VectorCopy(vel, s_entity[entityNum].velocity); + s_entity[entityNum].use_listener = use_listener; + s_entity[entityNum].time = cl.serverTime; +} + +/* +============== +S_SetGlobalAmbientVolumeLevel +============== +*/ +void S_SetGlobalAmbientVolumeLevel(float volume) +{ + s_fAmbientVolume = volume; +} + +/* +============== +S_StartSound +============== +*/ +void S_StartSound( + const vec3_t origin, + int entnum, + int entchannel, + sfxHandle_t sfxHandle, + float volume, + float min_dist, + float pitch, + float maxDist, + int streamed +) +{ + if (s_show_sounds->integer > 0 && sfxHandle > 0 && sfxHandle < s_numSfx) { + Com_DPrintf("S_StartSound: %s\n", s_knownSfx[sfxHandle].name); + } + + if (!s_bSoundStarted) { + if (s_show_sounds->integer > 0) { + Com_DPrintf("^~^~^ sound system not yet started\n"); + } + return; + } + + if (server_loading) { + if (s_show_sounds->integer > 0) { + Com_DPrintf("^~^~^ cannot start sounds while loading a server\n"); + } + return; + } + + if (sfxHandle < 0 || sfxHandle >= s_numSfx) { + Com_Error(ERR_DROP, "S_StartSound: handle %i out of range", sfxHandle); + } + + if (!sfxHandle) { + if (s_show_sounds->integer > 0) { + Com_DPrintf("^~^~^ null handle\n"); + } + return; + } + + if (entnum && (entchannel == CHAN_DIALOG || entchannel == CHAN_DIALOG_SECONDARY) && s_dialogscale->value > 0) { + volume *= s_dialogscale->value; + } + + S_Driver_StartSound(origin, entnum, entchannel, sfxHandle, volume, min_dist, pitch, maxDist, streamed); +} + +/* +============== +S_StartLocalSound +============== +*/ +void S_StartLocalSound(const char *sound_name, qboolean force_load) +{ + sfxHandle_t sfxHandle; + const char *name; + AliasListNode_t *pSoundAlias = NULL; + + if (!s_bSoundStarted) { + return; + } + + if (!sound_name) { + return; + } + + name = Alias_FindRandom(sound_name, &pSoundAlias); + if (!name) { + name = sound_name; + } + + sfxHandle = S_RegisterSound(name, pSoundAlias ? pSoundAlias->streamed : qfalse, force_load); + + if (!pSoundAlias) { + S_StartSound(NULL, s_iListenerNumber, CHAN_MENU, sfxHandle, -1.0, -1.0, 1.0, -1.0, qfalse); + return; + } + + S_StartSound( + NULL, + s_iListenerNumber, + CHAN_MENU, + sfxHandle, + pSoundAlias->volume + random() * pSoundAlias->volumeMod, + -1.0, + pSoundAlias->pitch + random() * pSoundAlias->pitchMod, + pSoundAlias->maxDist, + pSoundAlias->streamed + ); +} + +/* +============== +S_StartLocalSoundChannel + +Added in 2.0 +Starts a local sound, with the specified channel +============== +*/ +void S_StartLocalSoundChannel(const char *sound_name, qboolean force_load, soundChannel_t channel) +{ + sfxHandle_t sfxHandle; + const char *name; + AliasListNode_t *pSoundAlias = NULL; + + if (!s_bSoundStarted) { + return; + } + + if (!sound_name) { + return; + } + + name = Alias_FindRandom(sound_name, &pSoundAlias); + if (!name) { + name = sound_name; + } + + sfxHandle = S_RegisterSound(name, pSoundAlias ? pSoundAlias->streamed : qfalse, force_load); + + if (!pSoundAlias) { + S_StartSound(NULL, s_iListenerNumber, channel, sfxHandle, -1.0, -1.0, 1.0, -1.0, qfalse); + return; + } + + S_StartSound( + 0, + s_iListenerNumber, + channel, + sfxHandle, + pSoundAlias->volume + random() * pSoundAlias->volumeMod, + -1.0, + pSoundAlias->pitch + random() * pSoundAlias->pitchMod, + pSoundAlias->maxDist, + pSoundAlias->streamed + ); +} + +/* +============== +S_StopAllSounds +============== +*/ +void S_StopAllSounds(qboolean stop_music) +{ + if (!s_bSoundStarted) { + return; + } + + Com_Printf("------- S_StopAllSounds (%s) -------\n", stop_music ? "stop music" : "don't stop music"); + + // Tell the driver to stop all sounds + S_Driver_StopAllSounds(stop_music); + + Com_Printf("------- S_StopAllSounds Complete-------\n"); +} + +/* +============== +S_ClearLoopingSounds +============== +*/ +void S_ClearLoopingSounds() +{ + if (!s_bSoundStarted) { + return; + } + + S_Driver_ClearLoopingSounds(); +} + +/* +============== +S_AddLoopingSound +============== +*/ +void S_AddLoopingSound( + const vec3_t origin, + const vec3_t velocity, + sfxHandle_t sfxHandle, + float volume, + float min_dist, + float max_dist, + float pitch, + int flags +) +{ + if (!s_bSoundStarted) { + return; + } + + if (sfxHandle < 0 || sfxHandle >= s_numSfx) { + Com_Error(ERR_DROP, "S_AddLoopingSound: handle %i out of range", sfxHandle); + } + + if (!sfxHandle) { + return; + } + + S_Driver_AddLoopingSound(origin, velocity, sfxHandle, volume, min_dist, max_dist, pitch, flags); +} + +/* +============== +S_Respatialize +============== +*/ +void S_Respatialize(int entityNum, const vec3_t head, vec3_t axis[3]) +{ + if (!s_bSoundStarted) { + return; + } + + S_Driver_Respatialize(entityNum, head, axis); +} + +/* +============== +S_Update +============== +*/ +void S_Update() +{ + if (!s_bSoundStarted) { + return; + } + + if (server_loading) { + return; + } + + S_Driver_Update(); +} + +/* +============== +S_StopSound +============== +*/ +void S_StopSound(int entnum, int channel) +{ + if (!s_bSoundStarted) { + return; + } + + if (channel == CHAN_AUTO) { + return; + } + + S_Driver_StopSound(entnum, channel); +} + +/* +============== +S_SetReverb +============== +*/ +void S_SetReverb(int reverb_type, float reverb_level) +{ + if (!s_bSoundStarted) { + return; + } + + S_Driver_SetReverb(reverb_type, reverb_level); +} + +/* +============== +S_Play +============== +*/ +void S_Play() +{ + int i; + char name[MAX_QPATH]; + + if (Cmd_Argc() < 2) { + return; + } + + for (i = 1; i < Cmd_Argc(); i++) { + if (strrchr(Cmd_Argv(i), '.')) { + Q_strncpyz(name, Cmd_Argv(i), sizeof(name)); + } else { + Com_sprintf(name, sizeof(name), "%s.wav", Cmd_Argv(1)); + } + } + + S_StartLocalSound(name, qfalse); +} + +/* +============== +S_SoundList +============== +*/ +void S_SoundList() +{ + int i; + sfx_t *sfx; + int size; + int total = 0; + + for (i = 0; i < s_numSfx; i++) { + sfx = &s_knownSfx[i]; + + if (sfx->registration_sequence) { + size = sfx->length * sfx->width; + total += size; + Com_Printf("(%2db) %6i : %s\n", sfx->width * 8, size, sfx->name); + } + } + + Com_Printf("Total resident: %i\n", total); +} + +/* +============== +S_ClearSoundBuffer +============== +*/ +void S_ClearSoundBuffer() +{ + // TODO: Remove once AL is fully implemented +} + +/* +============== +S_GetMusicFilename +============== +*/ +const char* S_GetMusicFilename() +{ + return S_Driver_GetMusicFilename(); +} + +/* +============== +S_GetMusicLoopCount +============== +*/ +int S_GetMusicLoopCount() +{ + return S_Driver_GetMusicLoopCount(); +} + +/* +============== +S_GetMusicOffset +============== +*/ +unsigned int S_GetMusicOffset() +{ + return S_Driver_GetMusicOffset(); +} diff --git a/code/client/snd_info.cpp b/code/client/snd_info.cpp new file mode 100644 index 00000000..0d994107 --- /dev/null +++ b/code/client/snd_info.cpp @@ -0,0 +1,95 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "snd_local.h" +#include "../qcommon/tiki.h" + +void load_sfx_info() +{ + TikiScript tiki; + const char *token; + int current_sound_file; + char file_name[MAX_QPATH]; + + sfx_infos[0].name[0] = 0; + sfx_infos[0].max_factor = -1.0; + sfx_infos[0].loop_start = -1; + sfx_infos[0].loop_end = -1; + sfx_infos[0].max_number_playing = DEFAULT_SFX_NUMBER_PLAYING; + number_of_sfx_infos = 1; + + for (current_sound_file = 0; current_sound_file < 10; current_sound_file++) { + Com_sprintf(file_name, sizeof(file_name), "global/sound%d.txt", current_sound_file); + + if (!tiki.LoadFile(file_name, qtrue)) { + continue; + } + + Com_Printf("Loading %s\n", file_name); + + while (tiki.TokenAvailable(qtrue)) { + token = tiki.GetToken(qtrue); + + if (!Q_stricmp(token, "sound")) { + if (tiki.TokenAvailable(qtrue)) { + token = tiki.GetToken(qtrue); + + if (number_of_sfx_infos == 1000) { + Com_DPrintf("Too many sound infos specified\n"); + break; + } + + Q_strncpyz(sfx_infos[number_of_sfx_infos].name, token, sizeof(sfx_infos[number_of_sfx_infos].name)); + sfx_infos[number_of_sfx_infos].max_factor = -1.f; + sfx_infos[number_of_sfx_infos].loop_start = -1; + sfx_infos[number_of_sfx_infos].loop_end = -1; + sfx_infos[number_of_sfx_infos].max_number_playing = DEFAULT_SFX_NUMBER_PLAYING; + number_of_sfx_infos++; + } + } else if (!Q_stricmp(token, "loopstart")) { + if (!tiki.TokenAvailable(qtrue)) { + token = tiki.GetToken(qtrue); + sfx_infos[number_of_sfx_infos - 1].loop_start = atoi(token); + } + } else if (!Q_stricmp(token, "loopend")) { + if (!tiki.TokenAvailable(qtrue)) { + token = tiki.GetToken(qtrue); + sfx_infos[number_of_sfx_infos - 1].loop_end = atoi(token); + } + } else if (!Q_stricmp(token, "maxnumber")) { + if (!tiki.TokenAvailable(qtrue)) { + token = tiki.GetToken(qtrue); + sfx_infos[number_of_sfx_infos - 1].max_number_playing = atoi(token); + } + } else if (!Q_stricmp(token, "maxfactor")) { + if (!tiki.TokenAvailable(qtrue)) { + token = tiki.GetToken(qtrue); + sfx_infos[number_of_sfx_infos - 1].max_factor = atoi(token); + } + } + } + } + + tiki.Close(); + + sfx_infos[0].name[0] = 0; +} diff --git a/code/client/snd_local.h b/code/client/snd_local.h index d92c6700..04c6ba9f 100644 --- a/code/client/snd_local.h +++ b/code/client/snd_local.h @@ -27,6 +27,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/qcommon.h" #include "snd_public.h" +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA + #define PAINTBUFFER_SIZE 4096 // this is in samples #define SND_CHUNK_SIZE 1024 // samples @@ -281,3 +283,7 @@ void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER #ifdef __cplusplus } #endif + +#else +# include "snd_local_new.h" +#endif diff --git a/code/client/snd_local_new.h b/code/client/snd_local_new.h new file mode 100644 index 00000000..877df120 --- /dev/null +++ b/code/client/snd_local_new.h @@ -0,0 +1,252 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#pragma once + +#include "../qcommon/q_shared.h" +#include "../qcommon/qcommon.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern cvar_t *s_volume; +extern cvar_t *s_khz; +extern cvar_t *s_loadas8bit; +extern cvar_t *s_separation; +extern cvar_t *s_musicVolume; +extern cvar_t *s_ambientVolume; + +#define MAX_SOUNDSYSTEM_CHANNELS_3D 32 +#define MAX_SOUNDSYSTEM_CHANNELS_2D 32 +#define MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM 32 +#define MAX_SOUNDSYSTEM_POSITION_CHANNELS (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM) +#define MAX_SOUNDSYSTEM_SONGS 2 +#define MAX_SOUNDSYSTEM_MISC_CHANNELS 3 +#define MAX_SOUNDSYSTEM_CHANNELS \ + (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + MAX_SOUNDSYSTEM_SONGS \ + + MAX_SOUNDSYSTEM_MISC_CHANNELS) +#define MAX_SOUNDSYSTEM_LOOP_SOUNDS 64 + +#define SOUNDSYSTEM_CHANNEL_MP3_ID \ + (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + MAX_SOUNDSYSTEM_SONGS) +#define SOUNDSYSTEM_CHANNEL_TRIGGER_MUSIC_ID (SOUNDSYSTEM_CHANNEL_MP3_ID + 1) +#define SOUNDSYSTEM_CHANNEL_MOVIE_ID (SOUNDSYSTEM_CHANNEL_TRIGGER_MUSIC_ID + 1) + +typedef struct { + int format; + float rate; + + float width; + int channels; + int samples; + + int dataofs; + int datasize; + int dataalign; +} wavinfo_t; + +typedef struct sfx_s { + int iFlags; + + int length; + int width; + byte *data; + char name[64]; + + int registration_sequence; + int sfx_info_index; + float time_length; + + wavinfo_t info; + unsigned int buffer; +} sfx_t; + +typedef struct { + unsigned short wFormatTag; + unsigned short nChannels; + unsigned int nSamplesPerSec; + unsigned int nAvgBytesPerSec; + unsigned short nBlockAlign; + unsigned short wBitsPerSample; + unsigned short cbSize; +} wavinfo_x_t; + +typedef struct { + char name[64]; + + int loop_start; + int loop_end; + + int max_number_playing; + float max_factor; +} sfx_info_t; + +typedef struct { + vec3_t position; + vec3_t velocity; + int time; + qboolean use_listener; +} s_entity_t; + +typedef struct { + char alias[32]; + char path[64]; + + int mood_num; + int flags; + float volume; + float fadetime; + + int current_pos; + int current_state; +} song_t; + +typedef struct { + int iFlags; + char szName[64]; +} sfxsavegame_t; + +typedef struct { + qboolean bPlaying; + int iStatus; + sfxsavegame_t sfx; + + int iEntNum; + int iEntChannel; + vec3_t vOrigin; + float fVolume; + int iBaseRate; + float fNewPitchMult; + float fMinDist; + float fMaxDist; + + int iStartTime; + int iTime; + int iNextCheckObstructionTime; + int iEndTime; + + int iFlags; + int iOffset; + int iLoopCount; +} channelbasesavegame_t; + +typedef struct { + channelbasesavegame_t Channels[MAX_SOUNDSYSTEM_CHANNELS]; +} soundsystemsavegame_t; + +enum channel_flags_t { + CHANNEL_FLAG_PLAY_DEFERRED = 1, + CHANNEL_FLAG_LOCAL_LISTENER = 16, + CHANNEL_FLAG_NO_ENTITY = 32, + CHANNEL_FLAG_PAUSED = 64, + CHANNEL_FLAG_LOOPING = 128, + // Added in OPM + CHANNEL_FLAG_MISSING_ENT = 256, +}; + +enum sfx_flags_t { + SFX_FLAG_DEFAULT_SOUND = 1, + SFX_FLAG_MP3 = 2, + SFX_FLAG_STREAMED = 4, + SFX_FLAG_NO_OFFSET = 8, + SFX_FLAG_NULL = 16, +}; + +enum loopsound_flags_t { + LOOPSOUND_FLAG_NO_PAN = 1 +}; + +#define MAX_SFX 1400 +#define MAX_SFX_INFOS 1000 +#define MAX_LOOP_SOUNDS 64 +#define DEFAULT_SFX_NUMBER_PLAYING 10 //5 + +extern qboolean s_bLastInitSound; +extern qboolean s_bSoundStarted; +extern qboolean s_bSoundPaused; +extern qboolean s_bTryUnpause; +extern int s_iListenerNumber; +extern float s_fAmbientVolume; +extern int number_of_sfx_infos; +extern sfx_info_t sfx_infos[]; +extern sfx_t s_knownSfx[]; +extern int s_numSfx; +extern s_entity_t s_entity[]; + +// The current sound driver. +// Currently OPENAL +#define SOUND_DRIVER OPENAL + +// +// snd_info.cpp +// +void load_sfx_info(); + +// +// snd_dma_new.cpp +// + +sfx_t *S_FindName(const char *name, int sequenceNumber); +void S_DefaultSound(sfx_t *sfx); + +void S_LoadData(soundsystemsavegame_t *pSave); +void S_SaveData(soundsystemsavegame_t *pSave); +void S_ClearSoundBuffer(); + +// +// snd_mem.c +// +qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean force_load); + +#define S_StopAllSounds2 S_StopAllSounds + +// +// Driver-specific functions +// +#define S_Call_SndDriver(driver, func) S_##driver##_##func +#define S_Call_SndDriverX(driver, func) S_Call_SndDriver(driver, func) + +#define S_Driver_Init S_Call_SndDriverX(SOUND_DRIVER, Init) +#define S_Driver_Shutdown S_Call_SndDriverX(SOUND_DRIVER, Shutdown) +#define S_Driver_StartSound S_Call_SndDriverX(SOUND_DRIVER, StartSound) +#define S_Driver_AddLoopingSound S_Call_SndDriverX(SOUND_DRIVER, AddLoopingSound) +#define S_Driver_ClearLoopingSounds S_Call_SndDriverX(SOUND_DRIVER, ClearLoopingSounds) +#define S_Driver_StopSound S_Call_SndDriverX(SOUND_DRIVER, StopSound) +#define S_Driver_StopAllSounds S_Call_SndDriverX(SOUND_DRIVER, StopAllSounds) +#define S_Driver_Respatialize S_Call_SndDriverX(SOUND_DRIVER, Respatialize) +#define S_Driver_SetReverb S_Call_SndDriverX(SOUND_DRIVER, SetReverb) +#define S_Driver_Update S_Call_SndDriverX(SOUND_DRIVER, Update) +#define S_Driver_GetMusicFilename S_Call_SndDriverX(SOUND_DRIVER, GetMusicFilename) +#define S_Driver_GetMusicLoopCount S_Call_SndDriverX(SOUND_DRIVER, GetMusicLoopCount) +#define S_Driver_GetMusicOffset S_Call_SndDriverX(SOUND_DRIVER, GetMusicOffset) + +void S_PrintInfo(); +void S_DumpInfo(); +qboolean S_NeedFullRestart(); +void S_ReLoad(soundsystemsavegame_t* pSave); + +extern cvar_t *s_show_sounds; + +#ifdef __cplusplus +} +#endif diff --git a/code/client/snd_mem_new.cpp b/code/client/snd_mem_new.cpp new file mode 100644 index 00000000..0bf2dd63 --- /dev/null +++ b/code/client/snd_mem_new.cpp @@ -0,0 +1,566 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "snd_local.h" +#include "cl_ui.h" + +byte *data_p; +byte *iff_end; +byte *last_chunk; +byte *iff_data; +int iff_chunk_len; + +qboolean S_LoadMP3(const char *fileName, sfx_t *sfx); + +/* +============== +GetLittleShort +============== +*/ +short int GetLittleShort() +{ + union { + short value; + byte bytes[2]; + } val; + +#ifdef Q3_LITTLE_ENDIAN + val.bytes[0] = data_p[0]; + val.bytes[1] = data_p[1]; +#else + val.bytes[0] = data_p[1]; + val.bytes[1] = data_p[0]; +#endif + + data_p += sizeof(short); + return val.value; +} + +/* +============== +GetLittleLong +============== +*/ +int GetLittleLong() +{ + union { + int value; + byte bytes[4]; + } val; + +#ifdef Q3_LITTLE_ENDIAN + val.bytes[0] = data_p[0]; + val.bytes[1] = data_p[1]; + val.bytes[2] = data_p[2]; + val.bytes[3] = data_p[3]; +#else + val.bytes[0] = data_p[3]; + val.bytes[1] = data_p[2]; + val.bytes[2] = data_p[1]; + val.bytes[3] = data_p[0]; +#endif + + data_p += sizeof(int); + return val.value; +} + +/* +============== +SetLittleShort +============== +*/ +void SetLittleShort(int i) +{ + union { + short value; + byte bytes[2]; + } val; + + val.value = i; + +#ifdef Q3_LITTLE_ENDIAN + data_p[0] = val.bytes[0]; + data_p[1] = val.bytes[1]; +#else + data_p[0] = val.bytes[1]; + data_p[1] = val.bytes[0]; +#endif + + data_p += sizeof(short); +} + +/* +============== +SetLittleLong +============== +*/ +void SetLittleLong(int i) +{ + union { + int value; + byte bytes[4]; + } val; + + val.value = i; + +#ifdef Q3_LITTLE_ENDIAN + data_p[0] = val.bytes[0]; + data_p[1] = val.bytes[1]; + data_p[2] = val.bytes[2]; + data_p[3] = val.bytes[3]; +#else + data_p[0] = val.bytes[3]; + data_p[1] = val.bytes[2]; + data_p[2] = val.bytes[1]; + data_p[3] = val.bytes[0]; +#endif + + data_p += sizeof(int); +} + +/* +============== +FindNextChunk +============== +*/ +void FindNextChunk(const char *name) +{ + int value; + + while (1) { + data_p = last_chunk; + + if (last_chunk >= (byte *)iff_end) { + break; + } + + data_p = last_chunk + 4; + value = GetLittleLong(); + + iff_chunk_len = value; + if (value < 0) { + break; + } + + data_p -= 8; + value++; + value &= ~1; + + last_chunk = data_p + value + 8; + if (!strncmp((const char *)data_p, name, 4u)) { + return; + } + } + + data_p = NULL; +} + +/* +============== +FindChunk +============== +*/ +void FindChunk(const char *name) +{ + last_chunk = iff_data; + FindNextChunk(name); +} + +/* +============== +DumpChunks +============== +*/ +void DumpChunks() +{ + char str[5]; + + str[4] = 0; + + data_p = iff_data; + do { + memcpy(str, data_p, 4); + data_p += 4; + + iff_chunk_len = GetLittleLong(); + + Com_Printf("0x%p : %s (%d)\n", data_p - 4, str, iff_chunk_len); + + data_p += (iff_chunk_len + 1) & ~1; + } while (data_p < (byte *)iff_end); +} + +/* +============== +GetWavinfo +============== +*/ +wavinfo_t GetWavinfo(const char *name, byte *wav, int wavlength) +{ + wavinfo_t info; + int samples; + short bytealign; + + memset(&info, 0, sizeof(wavinfo_t)); + + if (!wav) { + return info; + } + + iff_data = wav; + iff_end = &wav[wavlength]; + FindChunk("RIFF"); + + if (!data_p || strncmp((const char *)data_p + 8, "WAVE", 4u)) { + Com_Printf("Missing RIFF/WAVE chunks\n"); + return info; + } + + iff_data = data_p + 12; + FindChunk("fmt "); + if (!data_p) { + Com_Printf("Missing fmt chunk\n"); + return info; + } + + data_p += 8; + + info.format = GetLittleShort(); + if (info.format == 17) { + info.channels = GetLittleShort(); + info.rate = (float)GetLittleLong(); + data_p += 4; + + bytealign = GetLittleShort(); + info.width = (float)GetLittleShort() / 8.f; + data_p += 2; + + FindChunk("data"); + if (!data_p) { + Com_Printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + if (info.width >= 1.0) { + samples = (int)((float)GetLittleLong() / info.width); + } else { + samples = (int)((float)GetLittleLong() * info.width); + } + + if (!info.samples) { + info.samples = samples; + } else if (samples < info.samples) { + Com_Error(ERR_DROP, "Sound %s has a bad loop length", name); + } + + info.dataofs = data_p - wav; + info.datasize = iff_chunk_len - bytealign + info.dataofs; + info.dataalign = (bytealign / info.channels - 4) / 4 * 8 + 1; + } else if (info.format == 1) { + info.channels = GetLittleShort(); + info.rate = (float)GetLittleLong(); + data_p += 4; + + bytealign = GetLittleShort(); + info.width = (float)GetLittleShort() / 8.f; + + FindChunk("data"); + if (!data_p) { + Com_Printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = (float)GetLittleLong() / info.width; + + if (!info.samples) { + info.samples = samples; + } else if (samples < info.samples) { + Com_Error(ERR_DROP, "Sound %s has a bad loop length", name); + } + + info.dataofs = data_p - wav; + info.datasize = iff_chunk_len; + info.dataalign = (bytealign / info.channels - 4) / 4 * 8 + 1; + // dataalign should always be 1 + assert(info.dataalign == 1); + } else { + Com_Printf("Microsoft PCM format only\n"); + return info; + } + + return info; +} + +/* +============== +DownSampleWav +============== +*/ +qboolean DownSampleWav(wavinfo_t *info, byte *wav, int wavlength, int newkhz, byte **newdata) +{ + int newdatasize; + byte *datap; + int i; + int ii; + int error; + int width; + int oldsamples; + int oldrate; + + newdatasize = 0; + datap = &wav[info->dataofs]; + + if (info->channels > 1) { + Com_DPrintf("Could not downsample WAV file. Stereo WAVs not supported!\n"); + return 0; + } + + if (info->format != 1 || !info->dataofs) { + Com_DPrintf("Could not downsample WAV file. Not PCM format!\n"); + return 0; + } + + if (info->rate <= newkhz) { + return 0; + } + + error = 0; + width = info->width; + for (i = 0; i < info->samples; i++) { + error += newkhz; + while (error > info->rate) { + error -= info->rate; + newdatasize += width; + } + } + + oldsamples = info->samples; + oldrate = info->rate; + info->samples = newdatasize / width; + info->rate = (float)newkhz; + newdatasize += info->dataofs; + + *newdata = (byte *)Z_TagMalloc(newdatasize, TAG_SOUND); + memcpy(*newdata, wav, info->dataofs); + + iff_data = *newdata; + iff_end = *newdata + newdatasize; + FindChunk("RIFF"); + + if (!data_p || strncmp((const char *)data_p + 8, "WAVE", 4u)) { + Com_DPrintf("Missing RIFF/WAVE chunks\n"); + return 0; + } + + iff_data = data_p + 12; + FindChunk("fmt "); + if (!data_p) { + Com_DPrintf("Missing fmt chunk\n"); + return 0; + } + + data_p += 12; + SetLittleShort((int)info->rate); + data_p += 8; + + FindChunk("data"); + if (!data_p) { + Com_DPrintf("Missing data chunk\n"); + return 0; + } + + data_p += 4; + SetLittleLong((int)(info->samples * info->width)); + + error = 0; + for (i = 0; i < oldsamples; i++) { + error += newkhz; + while (error > oldrate) { + error -= oldrate; + for (ii = 0; ii < width; ii++) { + data_p[ii] = datap[ii]; + } + + data_p += width; + } + + datap += width; + } + + assert(iff_end - data_p == 0); + + return newdatasize; +} + +/* +============== +DownSampleWav_MILES +============== +*/ +int DownSampleWav_MILES(wavinfo_t *info, byte *wav, int wavlength, int newkhz, byte **newdata) +{ + // Fallback to software downsampling + return DownSampleWav(info, wav, wavlength, newkhz, newdata); +} + +/* +============== +S_LoadSound +============== +*/ +qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean force_load) +{ + int size; + fileHandle_t file_handle; + char tempName[MAX_RES_NAME + 1]; + int realKhz; + + sfx->buffer = 0; + + if (fileName[0] == '*') { + return qfalse; + } + + if (streamed) { + sfx->length = 5000; + sfx->width = 1; + sfx->iFlags |= SFX_FLAG_STREAMED; + sfx->time_length = 5000.0; + sfx->data = NULL; + return qtrue; + } + + if (clc.state != CA_LOADING && !force_load) { + Com_Printf("**************S_LoadSound: %s\n", fileName); + } + + if (strstr(fileName, ".mp3")) { + return S_LoadMP3(fileName, sfx); + } + + size = FS_FOpenFileRead(fileName, &file_handle, qfalse, qtrue); + if (size <= 0) { + if (file_handle) { + FS_FCloseFile(file_handle); + } + return qfalse; + } + + sfx->data = (byte *)Z_TagMalloc(size, TAG_SOUND); + + FS_Read(sfx->data, size, file_handle); + FS_FCloseFile(file_handle); + sfx->info = GetWavinfo(fileName, sfx->data, size); + + if (sfx->info.channels != 1 && !streamed) { + Com_Printf("%s is a stereo wav file\n", fileName); + Z_Free(sfx->data); + sfx->data = NULL; + return qfalse; + } + + if (!sfx->info.dataofs) { + sfx->iFlags |= SFX_FLAG_NO_OFFSET; + } + + switch (s_khz->integer) { + case 11: + realKhz = 11025; + break; + case 22: + default: + realKhz = 22050; + break; + case 44: + realKhz = 44100; + break; + } + + if (!(sfx->iFlags & SFX_FLAG_STREAMED) && realKhz < sfx->info.rate) { + byte *newdata; + int newdatasize; + + newdata = NULL; + if (sfx->iFlags & SFX_FLAG_NO_OFFSET) { + newdatasize = DownSampleWav_MILES(&sfx->info, sfx->data, size, realKhz, &newdata); + } else { + newdatasize = DownSampleWav(&sfx->info, sfx->data, size, realKhz, &newdata); + } + + if (newdatasize) { + Z_Free(sfx->data); + sfx->data = newdata; + sfx->info.datasize = newdatasize; + } + } + + sfx->length = sfx->info.samples; + sfx->width = sfx->info.width; + sfx->time_length = sfx->info.samples / sfx->info.rate * 1000.f; + + if (sfx->iFlags & SFX_FLAG_STREAMED) { + Z_Free(sfx->data); + sfx->data = NULL; + } + + Com_sprintf(tempName, sizeof(tempName), "k%s", fileName); + UI_LoadResource(tempName); + + if (strstr(fileName, "sound/null.wav")) { + sfx->iFlags |= SFX_FLAG_NULL; + return qtrue; + } + + return qtrue; +} + +/* +============== +S_LoadMP3 +============== +*/ +qboolean S_LoadMP3(const char *fileName, sfx_t *sfx) +{ + int length; + fileHandle_t file_handle; + + length = FS_FOpenFileRead(fileName, &file_handle, 0, 1); + if (length <= 0) { + if (file_handle) { + FS_FCloseFile(file_handle); + } + return qfalse; + } + + memset(&sfx->info, 0, sizeof(sfx->info)); + sfx->data = (byte *)Z_TagMalloc(length, TAG_SOUND); + sfx->length = length; + sfx->width = 1; + FS_Read(sfx->data, length, file_handle); + FS_FCloseFile(file_handle); + + sfx->iFlags |= SFX_FLAG_MP3; + + return qtrue; +} diff --git a/code/renderer/tr_ghost.cpp b/code/client/snd_miles_new.cpp similarity index 89% rename from code/renderer/tr_ghost.cpp rename to code/client/snd_miles_new.cpp index 2b619982..16d86cb7 100644 --- a/code/renderer/tr_ghost.cpp +++ b/code/client/snd_miles_new.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -// tr_ghost.cpp +// See the header file for information -#include "tr_local.h" -#include "tr_ghost.h" +#include "snd_miles_new.h" \ No newline at end of file diff --git a/code/renderergl2/new/tr_image.c b/code/client/snd_miles_new.h similarity index 83% rename from code/renderergl2/new/tr_image.c rename to code/client/snd_miles_new.h index c8106ae3..1fd9e211 100644 --- a/code/renderergl2/new/tr_image.c +++ b/code/client/snd_miles_new.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,4 +20,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#include "../tr_local.h" +// +// This file exists in the original source code. +// But this driver won't be implemented, as OpenAL is a better sound system! +// + +#pragma once diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c index a5f4dadf..236f859a 100644 --- a/code/client/snd_openal.c +++ b/code/client/snd_openal.c @@ -233,7 +233,7 @@ static sfxHandle_t S_AL_BufferFind(const char *filename) ptr = &knownSfx[sfx]; memset(ptr, 0, sizeof(*ptr)); ptr->masterLoopSrc = -1; - strcpy(ptr->filename, filename); + Q_strncpyz(ptr->filename, filename, sizeof(ptr->filename)); } // Return the handle diff --git a/code/client/snd_openal_new.cpp b/code/client/snd_openal_new.cpp new file mode 100644 index 00000000..2e35801c --- /dev/null +++ b/code/client/snd_openal_new.cpp @@ -0,0 +1,5045 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "snd_local.h" +#include "snd_openal_new.h" +#include "client.h" +#include "../server/server.h" +#include "snd_codec.h" + +typedef struct { + const char *funcname; + void **funcptr; + bool required; +} extensions_table_t; + +#define MAX_MUSIC_SONGS 16 + +static int s_iNextLoopingWarning = 0; +static int s_iReverbType = 0; +static float s_fReverbLevel = 0; +static bool s_bReverbChanged = false; +static bool s_bFading = false; +static float s_fFadeVolume = 1.f; +static float s_fVelocityScale = 0.005f; + +static constexpr float s_fVolumeGain = 1.f; // = 84.f; + +cvar_t *s_milesdriver; +cvar_t *s_openaldevice; +cvar_t *s_reverb; +cvar_t *s_show_cpu; +cvar_t *s_show_num_active_sounds; +cvar_t *s_show_sounds; +cvar_t *s_speaker_type; +cvar_t *s_obstruction_cal_time; +cvar_t *s_lastSoundTime; +// Added in OPM +cvar_t *s_openaldriver; +cvar_t *s_alAvailableDevices; + +static float reverb_table[] = { + 0.5f, 0.25f, 0.417f, 0.653f, 0.208f, 0.5f, 0.403f, 0.5f, 0.5f, + 0.361f, 0.5f, 0.153f, 0.361f, 0.44400001f, 0.25f, 0.111f, 0.111f, 0.19400001f, + 1.0f, 0.097000003f, 0.208f, 0.65200001f, 1.0f, 0.875f, 0.139f, 0.486f, +}; + +static vec3_t vec_zero = {0, 0, 0}; +int s_iNumMilesAudioProviders = 0; +bool s_bProvidersEmunerated = false; +static bool al_initialized = false; +static bool al_use_reverb = false; +static float al_current_volume = 0; +static unsigned int al_frequency = 22050; +static ALCcontext *al_context_id = NULL; +static ALCdevice *al_device = NULL; +static ALsizei al_default_resampler_index = 0; +static ALsizei al_resampler_index = 0; + +static ALboolean (*_alutLoadMP3_LOKI)(unsigned int buffer, const byte *data, int length); +static void (*_alReverbScale_LOKI)(); +static void (*_alReverbDelay_LOKI)(); + +static qboolean music_active = qfalse; +int music_current_mood = 0; +int music_fallback_mood = 0; +float old_music_volume = 1.f; +float music_volume = 1.f; +float new_music_volume = 1.f; +float music_volume_fade_time = 0; +long int music_volume_start_time = 0; +int music_volume_direction = 0; +int music_volume_changed = 0; +int music_loaded = 0; +int music_numsongs = 0; +int music_currentsong = 0; + +static qboolean enumeration_ext = qfalse; +static qboolean enumeration_all_ext = qfalse; + +static qboolean ima4_ext = qfalse; +static qboolean soft_block_align = qfalse; + +song_t music_songs[MAX_MUSIC_SONGS]; +openal_internal_t openal; +static float s_fFadeStartTime; +static float s_fFadeStopTime; +static char current_soundtrack[128]; + +static void S_OPENAL_PlayMP3(); +static void S_OPENAL_StopMP3(); +static void S_OPENAL_Pitch(); +static int +S_OPENAL_SpatializeStereoSound(const vec3_t listener_origin, const vec3_t listener_left, const vec3_t origin); +static void S_OPENAL_reverb(int iChannel, int iReverbType, float fReverbLevel); +static bool S_OPENAL_LoadMP3_Codec(const char *_path, sfx_t *pSfx); +static ALuint S_OPENAL_Format(float width, int channels); + +#define alDieIfError() __alDieIfError(__FILE__, __LINE__) + +#if defined(_WIN64) +# define ALDRIVER_DEFAULT "OpenAL64.dll" +#elif defined(_WIN32) +# define ALDRIVER_DEFAULT "OpenAL32.dll" +#elif defined(__APPLE__) +# define ALDRIVER_DEFAULT "libopenal.1.dylib" +#elif defined(__OpenBSD__) +# define ALDRIVER_DEFAULT "libopenal.so" +#else +# define ALDRIVER_DEFAULT "libopenal.so.1" +#endif + +// +// alext +// +#ifdef AL_SOFT_source_resampler +LPALGETSTRINGISOFT qalGetStringiSOFT; +#endif + +/* +============== +__alDieIfError +============== +*/ +static void __alDieIfError(const char *file, int line) +{ + ALint alErr = qalGetError(); + if (alErr) { + if (s_show_sounds->integer) { + Com_DPrintf("OpenAL error, %s, line %i: [%s].\n", file, line, qalGetString(alErr)); + } + } +} + +/* +============== +S_OPENAL_NukeSource +============== +*/ +static void S_OPENAL_NukeSource(ALuint *srcptr) +{ + ALuint source; + + source = *srcptr; + if (!*srcptr) { + return; + } + + if (!qalIsSource(*srcptr)) { + return; + } + + alDieIfError(); + qalSourceStop(source); + + alDieIfError(); + qalSourcei(source, AL_BUFFER, 0); + + alDieIfError(); + qalDeleteSources(1, srcptr); + + alDieIfError(); + *srcptr = 0; +} + +/* +============== +S_OPENAL_NukeBuffer +============== +*/ +static void S_OPENAL_NukeBuffer(ALuint *bufptr) +{ + if (!*bufptr) { + return; + } + + if (!qalIsBuffer(*bufptr)) { + return; + } + + alDieIfError(); + qalDeleteBuffers(1, bufptr); + + alDieIfError(); + *bufptr = 0; +} + +/* +============== +S_OPENAL_NukeChannel +============== +*/ +static void S_OPENAL_NukeChannel(openal_channel *channel) +{ + if (!channel) { + return; + } + + S_OPENAL_NukeSource(&channel->source); + S_OPENAL_NukeBuffer(&channel->buffer); + + if (channel->bufferdata) { + delete[] channel->bufferdata; + } +} + +/* +============== +S_OPENAL_NukeContext +============== +*/ +static void S_OPENAL_NukeContext() +{ + int i; + + Com_Printf("OpenAL: Destroying channels...\n"); + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS; ++i) { + S_OPENAL_NukeChannel(openal.channel[i]); + } + + Com_Printf("OpenAL: Channels destroyed successfully.\n"); + + for (i = 0; i < s_numSfx; i++) { + S_OPENAL_NukeBuffer(&s_knownSfx[i].buffer); + } + + S_OPENAL_NukeBuffer(&openal.movieSFX.buffer); + + if (al_context_id) { + Com_Printf("OpenAL: Destroying context...\n"); + + qalcSuspendContext(al_context_id); + qalcMakeContextCurrent(NULL); + qalcDestroyContext(al_context_id); + al_context_id = NULL; + + Com_Printf("OpenAL: Context destroyed successfully.\n"); + } + + if (al_device) { + Com_Printf("OpenAL: Closing device...\n"); + + qalcCloseDevice(al_device); + al_device = NULL; + + Com_Printf("OpenAL: Device closed successfully.\n"); + } +} + +/* +============== +S_OPENAL_InitContext +============== +*/ +static bool S_OPENAL_InitContext() +{ + const char *dev; + int attrlist[12]; + + Com_DPrintf("OpenAL: Context initialization\n"); + + dev = NULL; + if (s_openaldevice) { + dev = s_openaldevice->string; + } + + if (dev && !*dev) { + dev = NULL; + } + + // Device enumeration support + enumeration_all_ext = qalcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"); + enumeration_ext = qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); + + if (enumeration_ext || enumeration_all_ext) { + char devicenames[16384] = ""; + const char *devicelist; +#ifdef _WIN32 + const char *defaultdevice; +#endif + int curlen; + + // get all available devices + the default device name. + if (enumeration_all_ext) { + devicelist = qalcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); +#ifdef _WIN32 + defaultdevice = qalcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); +#endif + } else { + // We don't have ALC_ENUMERATE_ALL_EXT but normal enumeration. + devicelist = qalcGetString(NULL, ALC_DEVICE_SPECIFIER); +#ifdef _WIN32 + defaultdevice = qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); +#endif + enumeration_ext = qtrue; + } + +#ifdef _WIN32 + Com_DPrintf("OpenAL: Default playback device: \"%s\"\n", defaultdevice); +#endif + +#ifdef _WIN32 + // check whether the default device is generic hardware. If it is, change to + // Generic Software as that one works more reliably with various sound systems. + // If it's not, use OpenAL's default selection as we don't want to ignore + // native hardware acceleration. + if (!dev && defaultdevice && !strcmp(defaultdevice, "Generic Hardware")) { + dev = "Generic Software"; + } +#endif + + // dump a list of available devices to a cvar for the user to see. + + if (devicelist) { + while ((curlen = strlen(devicelist))) { + Q_strcat(devicenames, sizeof(devicenames), devicelist); + Q_strcat(devicenames, sizeof(devicenames), "\n"); + + devicelist += curlen + 1; + } + } + + Com_Printf("OpenAL: List of available devices:\n%s\n", devicenames); + + s_alAvailableDevices = Cvar_Get("s_alAvailableDevices", devicenames, CVAR_ROM | CVAR_NORESTART); + } + + Com_Printf("OpenAL: Opening device \"%s\"...\n", dev ? dev : "{default}"); + + al_device = qalcOpenDevice(dev); + if (!al_device && dev) { + Com_Printf("Failed to open OpenAL device '%s', trying default.\n", dev); + al_device = qalcOpenDevice(NULL); + } + + if (!al_device) { + Com_Printf("OpenAL: Could not open device\n"); + S_OPENAL_NukeContext(); + return false; + } + + Com_Printf("OpenAL: Device opened successfully.\n"); + switch (s_khz->integer) { + case 11: + al_frequency = 11025; + break; + default: + case 22: + al_frequency = 22050; + break; + case 44: + al_frequency = 44100; + break; + } + + attrlist[0] = ALC_FREQUENCY; + attrlist[1] = al_frequency; + attrlist[2] = ALC_SYNC; + attrlist[3] = qfalse; + + s_speaker_type->modified = false; + +#ifdef ALC_SOFT_output_mode + attrlist[4] = ALC_OUTPUT_MODE_SOFT; + // Disable HRTF by default + // For example, actual speakers that are recognized as headphones by the OS + // will not get forced HRTF + attrlist[6] = ALC_HRTF_SOFT; + attrlist[7] = ALC_FALSE; + + switch (s_speaker_type->integer) { + // Two speakers + default: + case 0: + attrlist[5] = ALC_STEREO_SOFT; + break; + // Headphones + case 1: + attrlist[5] = ALC_STEREO_HRTF_SOFT; + // Allow HRTF mixing (without forcing in case it's unsupported) + attrlist[7] = ALC_DONT_CARE_SOFT; + break; + // Surround + case 2: + attrlist[5] = ALC_SURROUND_5_1_SOFT; + break; + // Quad speakers + case 3: + attrlist[5] = ALC_QUAD_SOFT; + break; + } +#else +# pragma message("OpenAL: ALC_OUTPUT_MODE_SOFT unavailable") + + Com_Printf( + "OpenAL: ALC_OUTPUT_MODE_SOFT is unavailable. The speaker type will be ignored, fallback to normal stereo.\n" + ); + attrlist[4] = 0; + attrlist[5] = 0; +#endif + +#ifdef ALC_SOFT_output_limiter + // Disable limiter + attrlist[8] = ALC_OUTPUT_LIMITER_SOFT; + attrlist[9] = ALC_FALSE; +#endif + attrlist[10] = 0; + attrlist[11] = 0; + + Com_Printf("OpenAL: Creating AL context...\n"); + al_context_id = qalcCreateContext(al_device, attrlist); + if (!al_context_id) { + Com_Printf("OpenAL: Could not create context\n"); + S_OPENAL_NukeContext(); + return false; + } + + Com_Printf("OpenAL: Context created successfully.\n"); + + qalcMakeContextCurrent(al_context_id); + alDieIfError(); + + Com_Printf("AL_VENDOR: %s\n", qalGetString(AL_VENDOR)); + alDieIfError(); + + Com_Printf("AL_VERSION: %s\n", qalGetString(AL_VERSION)); + alDieIfError(); + + Com_Printf("AL_RENDERER: %s\n", qalGetString(AL_RENDERER)); + alDieIfError(); + + Com_Printf("AL_EXTENSIONS: %s\n", qalGetString(AL_EXTENSIONS)); + alDieIfError(); + + qalDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); + alDieIfError(); + + qalcProcessContext(al_context_id); + alDieIfError(); + + return true; +} + +/* +============== +S_OPENAL_InitExtensions +============== +*/ +static bool S_OPENAL_InitExtensions() +{ + /* + extensions_table_t extensions_table[4] = { + "alutLoadMP3_LOKI", + (void **)&_alutLoadMP3_LOKI, + true, + "alReverbScale_LOKI", + (void **)&_alReverbScale_LOKI, + true, + "alReverbDelay_LOKI", + (void **)&_alReverbDelay_LOKI, + true + }; + */ + + extensions_table_t extensions_table[] = { +#ifdef AL_SOFT_source_resampler + extensions_table_t { + "alGetStringiSOFT", (void **)&qalGetStringiSOFT, + false, }, +#endif + extensions_table_t {NULL, NULL, NULL} + }; + + extensions_table_t *i; + + for (i = extensions_table; i->funcname; ++i) { + *i->funcptr = NULL; + } + + for (i = extensions_table; i->funcname; ++i) { + Com_Printf("AL extension: Looking up %ssymbol \"%s\"...", i->required ? "required " : "", i->funcname); + + *i->funcptr = qalGetProcAddress(i->funcname); + if (!*i->funcptr) { + Com_Printf("...not found! %d [%s]\n", qalGetError(), qalGetString(qalGetError())); + if (i->required) { + S_OPENAL_NukeContext(); + return false; + } + continue; + } + + Com_Printf("...found.\n"); + } + + ima4_ext = qalIsExtensionPresent("AL_EXT_IMA4"); + soft_block_align = qalIsExtensionPresent("AL_SOFT_block_alignment"); + + qalGetError(); + return true; +} + +/* +============== +S_OPENAL_InitChannel +============== +*/ +static bool S_OPENAL_InitChannel(int idx, openal_channel *chan) +{ + openal.channel[idx] = chan; + VectorClear(chan->vOrigin); + chan->fVolume = 1.0; + chan->fNewPitchMult = 0.0; + chan->fMinDist = 0.0; + chan->fMaxDist = 0.0; + chan->pSfx = 0; + chan->iEntNum = 0; + chan->iEntChannel = 0; + chan->iBaseRate = 0; + chan->iStartTime = 0; + chan->iTime = 0; + chan->iEndTime = 0; + chan->iFlags = 0; + chan->iPausedOffset = 0; + chan->source = 0; + chan->buffer = 0; + chan->bufferdata = 0; + chan->fading = FADE_NONE; + chan->fade_time = 0; + chan->fade_start_time = 0; + chan->song_number = 0; + + qalGenSources(1, &chan->source); + alDieIfError(); + qalSourcei(chan->source, AL_SOURCE_RELATIVE, true); + alDieIfError(); + +#ifdef AL_SOFT_source_resampler + qalSourcei(chan->source, AL_SOURCE_RESAMPLER_SOFT, al_resampler_index); + alDieIfError(); +#endif + + return true; +} + +/* +============== +S_OPENAL_Init +============== +*/ +qboolean S_OPENAL_Init() +{ + int i; + + if (al_initialized) { + Com_DPrintf("S_OPENAL_Init(): Called when sound is already initialized!\n"); + return qtrue; + } + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS; i++) { + openal.channel[i] = NULL; + } + + for (i = 0; i < MAX_SOUNDSYSTEM_LOOP_SOUNDS; i++) { + openal.loop_sounds[i] = {}; + } + + s_milesdriver = Cvar_Get("s_milesdriver", "auto", CVAR_SOUND_LATCH | CVAR_ARCHIVE); + s_openaldevice = Cvar_Get("s_openaldevice", "", CVAR_SOUND_LATCH); + s_reverb = Cvar_Get("s_reverb", "0", CVAR_SOUND_LATCH | CVAR_ARCHIVE); + s_show_cpu = Cvar_Get("s_show_cpu", "0", 0); + s_show_num_active_sounds = Cvar_Get("s_show_num_active_sounds", "0", 0); + s_show_sounds = Cvar_Get("s_show_sounds", "0", 0); + s_speaker_type = Cvar_Get("s_speaker_type", "0", CVAR_ARCHIVE); + s_obstruction_cal_time = Cvar_Get("s_obstruction_cal_time", "500", CVAR_ARCHIVE); + // + // Added in OPM + // Initialize the AL driver DLL + s_openaldriver = Cvar_Get("s_openaldriver", ALDRIVER_DEFAULT, CVAR_LATCH | CVAR_PROTECTED); + + if (!QAL_Init(s_openaldriver->string)) { + Com_Printf("Failed to load library: \"%s\".\n", s_openaldriver->string); + if (!Q_stricmp(s_openaldriver->string, ALDRIVER_DEFAULT) || !QAL_Init(ALDRIVER_DEFAULT)) { + return qfalse; + } + } + + if (!Cvar_Get("s_initsound", "1", 0)->integer) { + Com_Printf("OpenAL: s_initsound set to zero...disabling audio.\n"); + return true; + } + + if (!S_OPENAL_InitContext()) { + Com_Printf("OpenAL: initialization failed. No audio will play.\n"); + return false; + } + + if (!S_OPENAL_InitExtensions()) { + Com_Printf("OpenAL: A required extension is missing. No audio will play.\n"); + return false; + } + + al_use_reverb = false; + if (s_reverb->integer) { + STUB_DESC("reenable reverb support later."); + + if (al_use_reverb) { + S_OPENAL_SetReverb(s_iReverbType, s_fReverbLevel); + } else { + Com_Printf("OpenAL: No reverb support. Reverb is disabled.\n"); + } + } + s_reverb->modified = false; + + al_current_volume = Square(s_volume->value); + qalListenerf(AL_GAIN, al_current_volume); + alDieIfError(); + +#ifdef AL_SOFT_source_resampler + if (qalGetStringiSOFT) { + size_t numResamplers; + size_t i; + + al_default_resampler_index = qalGetInteger(AL_DEFAULT_RESAMPLER_SOFT); + alDieIfError(); + al_resampler_index = al_default_resampler_index; + numResamplers = qalGetInteger(AL_NUM_RESAMPLERS_SOFT); + alDieIfError(); + + for (i = 0; i < numResamplers; i++) { + const ALchar *resamplerName = qalGetStringiSOFT(AL_RESAMPLER_NAME_SOFT, i); + if (Q_stristr(resamplerName, "spline")) { + Com_Printf("OpenAL: Using %s as the resampler.\n", resamplerName); + al_resampler_index = i; + break; + } + } + } +#endif + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_3D; i++) { + if (!S_OPENAL_InitChannel(i, &openal.chan_3D[i])) { + return false; + } + } + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_2D; i++) { + if (!S_OPENAL_InitChannel(i + MAX_SOUNDSYSTEM_CHANNELS_3D, &openal.chan_2D[i])) { + return false; + } + } + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM; i++) { + if (!S_OPENAL_InitChannel( + i + MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D, &openal.chan_2D_stream[i] + )) { + return false; + } + } + + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + if (!S_OPENAL_InitChannel( + i + MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM, + &openal.chan_song[i] + )) { + return false; + } + } + + if (!S_OPENAL_InitChannel(SOUNDSYSTEM_CHANNEL_MP3_ID, &openal.chan_mp3)) { + return false; + } + + if (!S_OPENAL_InitChannel(SOUNDSYSTEM_CHANNEL_TRIGGER_MUSIC_ID, &openal.chan_trig_music)) { + return false; + } + + if (!S_OPENAL_InitChannel(SOUNDSYSTEM_CHANNEL_MOVIE_ID, &openal.chan_movie)) { + return false; + } + + // + // Disable sound virtualization on special channels + // (triggered music, ambient sounds...) + // + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + openal.chan_song[i].set_no_virtualization(); + } + openal.chan_mp3.set_no_virtualization(); + openal.chan_trig_music.set_no_virtualization(); + openal.chan_movie.set_no_virtualization(); + + Cmd_AddCommand("playmp3", S_OPENAL_PlayMP3); + Cmd_AddCommand("stopmp3", S_OPENAL_StopMP3); + Cmd_AddCommand("loadsoundtrack", S_loadsoundtrack); + Cmd_AddCommand("playsong", S_PlaySong); + Cmd_AddCommand("pitch", S_OPENAL_Pitch); + Cmd_AddCommand("tmstart", S_TriggeredMusic_Start); + Cmd_AddCommand("tmstartloop", S_TriggeredMusic_StartLoop); + Cmd_AddCommand("tmstop", S_TriggeredMusic_Stop); + // Added in 2.0 + Cmd_AddCommand("tmvolume", S_TriggeredMusic_Volume); + + S_OPENAL_ClearLoopingSounds(); + load_sfx_info(); + s_bProvidersEmunerated = true; + al_initialized = true; + + // Added in OPM + S_CodecInit(); + + return true; +} + +/* +============== +S_OPENAL_Shutdown +============== +*/ +void S_OPENAL_Shutdown() +{ + if (!al_initialized) { + Com_DPrintf("S_OPENAL_Shutdown(): Called when sound is NOT initialized!\n"); + return; + } + + S_OPENAL_StopAllSounds(true); + + Cmd_RemoveCommand("playmp3"); + Cmd_RemoveCommand("stopmp3"); + Cmd_RemoveCommand("loadsoundtrack"); + Cmd_RemoveCommand("playsong"); + Cmd_RemoveCommand("pitch"); + Cmd_RemoveCommand("tmstart"); + Cmd_RemoveCommand("tmstartloop"); + Cmd_RemoveCommand("tmstop"); + // Added in 2.0 + Cmd_RemoveCommand("tmvolume"); + + S_OPENAL_NukeContext(); + + s_bProvidersEmunerated = false; + al_initialized = false; + + QAL_Shutdown(); +} + +/* +============== +S_FadeSound +============== +*/ +void S_FadeSound(float fTime) +{ + Com_Printf("Called FadeSound with: %f\n", fTime); + + if (fTime > 0) { + s_bFading = true; + s_fFadeStartTime = cls.realtime; + s_fFadeVolume = 1; + s_fFadeStopTime = cls.realtime + fTime; + } else { + s_fFadeVolume = 1; + s_bFading = false; + // Fixed in OPM + // Make sure to restore the music volume + // in case the map restarts immediately after the intermission + music_volume_changed = true; + } +} + +/* +============== +S_GetBaseVolume +============== +*/ +float S_GetBaseVolume() +{ + return s_volume->value * s_fFadeVolume; +} + +/* +============== +S_NeedFullRestart +============== +*/ +qboolean S_NeedFullRestart() +{ + return Cvar_Get("s_initsound", "1", 0)->integer != s_bLastInitSound; +} + +/* +============== +S_PrintInfo +============== +*/ +void S_PrintInfo() +{ + const char *dev; + + Com_Printf("----- Sound Info -----\n"); + + if (s_bSoundStarted) { + dev = NULL; + if (s_openaldevice) { + dev = s_openaldevice->string; + } + if (!dev || !*dev) { + dev = "{default}"; + } + Com_Printf("device - %s\n", dev); + if (al_use_reverb) { + Com_Printf("reverb - ON\n"); + } else { + Com_Printf("reverb - OFF\n"); + } + Com_Printf("samplebits - 16\n"); + Com_Printf("speed - %d\n", al_frequency); + if (s_loadas8bit->integer) { + Com_Printf("Can NOT force all sounds to 8 bit in OpenAL, I think.\n"); + } + } else { + Com_Printf("sound system not started\n"); + } + + Com_Printf("----------------------\n"); +} + +/* +============== +S_DumpStatus +============== +*/ +static void S_DumpStatus(const char *pszChanName, int iChanNum, openal_channel *channel) +{ + sfx_t *sfx; + ALint status; + + sfx = channel->pSfx; + + qalGetSourceiv(channel->source, AL_SOURCE_STATE, &status); + alDieIfError(); + + if (status == AL_PLAYING || status == AL_PAUSED) { + const char *pszMode = status == AL_PLAYING ? "playing" : "paused"; + + if (sfx) { + if (sfx != (sfx_t *)-16 && sfx->name[0]) { + Com_Printf("%s channel %i - %s sfx %s\n", pszChanName, iChanNum, pszMode, sfx->name); + } else { + Com_Printf("%s channel %i - %s with nameless sfx\n", pszChanName, iChanNum, pszMode); + } + } else { + Com_Printf("%s channel %i - %s with NULL sfx\n", pszChanName, iChanNum, pszMode); + } + } +} + +/* +============== +S_DumpInfo +============== +*/ +void S_DumpInfo() +{ + int i; + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_3D; i++) { + S_DumpStatus("3D", i, openal.channel[i]); + } + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_2D; i++) { + S_DumpStatus("2D", i, openal.channel[MAX_SOUNDSYSTEM_CHANNELS_3D + i]); + } + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM; i++) { + S_DumpStatus("2D stream", i, openal.channel[MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + i]); + } + + for (i = 0; i < MAX_SOUNDSYSTEM_MISC_CHANNELS; i++) { + S_DumpStatus( + "Misc", + i, + openal.channel + [MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + i] + ); + } +} + +/* +============== +S_OPENAL_Pitch +============== +*/ +static void S_OPENAL_Pitch() +{ + Com_Printf("S_OPENAL_Pitch() needs to be implemented!\n"); +} + +/* +============== +S_OPENAL_LoadMP3 +============== +*/ +static bool S_OPENAL_LoadMP3(const char *_path, openal_channel *chan) +{ + char path[MAX_QPATH]; + snd_info_t info; + ALuint format; + + chan->stop(); + + qalSourcei(chan->source, AL_BUFFER, 0); + alDieIfError(); + + Q_strncpyz(path, _path, sizeof(path)); + path[MAX_QPATH - 1] = 0; + + FS_CorrectCase(path); + + // Try to load + chan->bufferdata = (ALubyte *)S_CodecLoad(path, &info); + if (!chan->bufferdata) { + return false; + } + + format = S_OPENAL_Format(info.width, info.channels); + + // Create a buffer + qalGenBuffers(1, &chan->buffer); + alDieIfError(); + + // Fill the buffer + if (info.size == 0) { + // We have no data to buffer, so buffer silence + byte dummyData[2] = {0}; + + qalBufferData(chan->buffer, AL_FORMAT_MONO16, (void *)dummyData, 2, 22050); + } else { + qalBufferData(chan->buffer, format, chan->bufferdata, info.size, info.rate); + } + + alDieIfError(); + + // Free the memory + Hunk_FreeTempMemory(chan->bufferdata); + chan->bufferdata = NULL; + + qalSourcei(chan->source, AL_BUFFER, chan->buffer); + alDieIfError(); + + chan->set_no_3d(); + + return true; +} + +/* +============== +S_OPENAL_PlayMP3 +============== +*/ +static void S_OPENAL_PlayMP3() +{ + const char *path; + + if (Cmd_Argc() != 2) { + Com_Printf("playmp3 \n"); + return; + } + + path = Cmd_Argv(1); + if (!S_OPENAL_LoadMP3(path, &openal.chan_mp3)) { + Com_Printf("Failed to play mp3 - %s\n", path); + return; + } + + openal.chan_mp3.play(); + Com_Printf("Playing mp3 - %s\n", path); +} + +/* +============== +S_OPENAL_StopMP3 +============== +*/ +static void S_OPENAL_StopMP3() +{ + S_OPENAL_NukeChannel(&openal.chan_mp3); +} + +/* +============== +MUSIC_Pause +============== +*/ +void MUSIC_Pause() +{ + int i; + + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + openal.chan_song[i].pause(); + } +} + +/* +============== +MUSIC_Unpause +============== +*/ +void MUSIC_Unpause() +{ + int i; + + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + if (openal.chan_song[i].is_paused()) { + openal.chan_song[i].play(); + } + } +} + +/* +============== +S_PauseSound +============== +*/ +void S_PauseSound() +{ + int i; + + if (!s_bSoundStarted) { + return; + } + + s_bSoundPaused = true; + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + openal_channel *pChannel = openal.channel[i]; + if (!pChannel) { + continue; + } + + if (pChannel->iEntChannel == CHAN_MENU) { + continue; + } + + if (!pChannel->is_playing()) { + continue; + } + + pChannel->pause(); + } + + if (openal.chan_mp3.is_playing()) { + openal.chan_mp3.pause(); + } + + MUSIC_Pause(); + S_TriggeredMusic_Pause(); +} + +/* +============== +S_UnpauseSound +============== +*/ +void S_UnpauseSound() +{ + int i; + + if (!s_bSoundStarted) { + return; + } + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + openal_channel *pChannel = openal.channel[i]; + if (!pChannel) { + continue; + } + + if (pChannel->is_paused() || (pChannel->iFlags & CHANNEL_FLAG_PLAY_DEFERRED)) { + pChannel->iFlags &= ~CHANNEL_FLAG_PLAY_DEFERRED; + pChannel->play(); + } + } + + if (openal.chan_mp3.is_paused()) { + openal.chan_mp3.play(); + } + + MUSIC_Unpause(); + S_TriggeredMusic_Unpause(); + + s_bSoundPaused = false; +} + +/* +============== +S_OPENAL_ShouldPlay +============== +*/ +static qboolean S_OPENAL_ShouldPlay(sfx_t *pSfx) +{ + if (sfx_infos[pSfx->sfx_info_index].max_number_playing <= 0) { + return qtrue; + } + + int iRemainingTimesToPlay; + int i; + + iRemainingTimesToPlay = sfx_infos[pSfx->sfx_info_index].max_number_playing; + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + openal_channel *pChannel = openal.channel[i]; + if (!pChannel) { + continue; + } + + if (pChannel->pSfx == pSfx && pChannel->is_playing()) { + iRemainingTimesToPlay--; + if (!iRemainingTimesToPlay) { + return qfalse; + } + } + } + + return qtrue; +} + +/* +============== +S_OPENAL_ShouldStart +============== +*/ +static qboolean S_OPENAL_ShouldStart(const vec3_t vOrigin, float fMinDist, float fMaxDist) +{ + vec3_t vDir; + vec3_t vListenerOrigin; + vec3_t alvec; + + if (!al_initialized) { + return false; + } + + qalGetListenerfv(AL_POSITION, alvec); + + VectorCopy(alvec, vListenerOrigin); + VectorSubtract(vOrigin, vListenerOrigin, vDir); + + return Square(fMaxDist) > VectorLengthSquared(vDir); +} + +/* +============== +S_OPENAL_PickChannelBase +============== +*/ +static int S_OPENAL_PickChannelBase(int iEntNum, int iEntChannel, int iFirstChannel, int iLastChannel) +{ + int i; + int iBestChannel; + openal_channel *pChannel; + + iBestChannel = -1; + if (iEntNum != ENTITYNUM_NONE && iEntChannel) { + bool bStoppedChannel = false; + + for (i = iFirstChannel; i <= iLastChannel; i++) { + pChannel = openal.channel[i]; + if (!pChannel) { + continue; + } + + if (pChannel->is_free()) { + iBestChannel = i; + continue; + } + + if (pChannel->iEntNum == iEntNum && pChannel->iEntChannel == iEntChannel) { + pChannel->end_sample(); + bStoppedChannel = 1; + iBestChannel = i; + break; + } + } + + if (!bStoppedChannel) { + for (i = 0; i < iFirstChannel; ++i) { + pChannel = openal.channel[i]; + if (!pChannel || pChannel->is_free()) { + continue; + } + + if (pChannel->iEntNum == iEntNum && pChannel->iEntChannel == iEntChannel) { + bStoppedChannel = 1; + break; + } + } + + if (!bStoppedChannel) { + for (i = iLastChannel + 1; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + pChannel = openal.channel[i]; + if (!pChannel || pChannel->is_free()) { + continue; + } + + if (pChannel->iEntNum == iEntNum && pChannel->iEntChannel == iEntChannel) { + break; + } + } + } + } + } + + if (iBestChannel < 0) { + int iBestTime = 0x7FFFFFFF; + + for (i = iFirstChannel; i <= iLastChannel; i++) { + pChannel = openal.channel[i]; + if (!pChannel) { + continue; + } + + if (pChannel->is_free()) { + return i; + } + + if (pChannel->iEntNum == s_iListenerNumber && iEntNum != pChannel->iEntNum) { + continue; + } + + if (pChannel->iEntChannel < iEntChannel + || (pChannel->iEntChannel == iEntChannel && pChannel->iStartTime < iBestTime)) { + iBestChannel = i; + iEntChannel = pChannel->iEntChannel; + iBestTime = pChannel->iStartTime; + } + } + } + + return iBestChannel; +} + +/* +============== +S_OPENAL_PickChannel3D +============== +*/ +static int S_OPENAL_PickChannel3D(int iEntNum, int iEntChannel) +{ + return S_OPENAL_PickChannelBase(iEntNum, iEntChannel, 0, MAX_SOUNDSYSTEM_CHANNELS_3D - 1); +} + +/* +============== +S_OPENAL_PickChannel2D +============== +*/ +static int S_OPENAL_PickChannel2D(int iEntNum, int iEntChannel) +{ + return S_OPENAL_PickChannelBase( + iEntNum, iEntChannel, MAX_SOUNDSYSTEM_CHANNELS_3D, MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D - 1 + ); +} + +/* +============== +S_OPENAL_PickChannel2DStreamed +============== +*/ +static int S_OPENAL_PickChannel2DStreamed(int iEntNum, int iEntChannel) +{ + return S_OPENAL_PickChannelBase( + iEntNum, + iEntChannel, + MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D, + MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM - 1 + ); +} + +/* +============== +callbackServer +============== +*/ +void callbackServer(int entnum, int channel_number, const char *name) +{ + if (!com_sv_running->integer) { + return; + } + + SV_SoundCallback(entnum, channel_number, name); +} + +/* +============== +S_OPENAL_Start2DSound +============== +*/ +static void S_OPENAL_Start2DSound( + const vec3_t vOrigin, + int iEntNum, + int iEntChannel, + sfx_t *pSfx, + float fVolume, + float fMinDistance, + float fPitch, + float fMaxDistance +) +{ + int iRealEntNum; + int iFreeChannel; + openal_channel *pChannel; + float fRealVolume; + bool bSupportWaitTillSoundDone; + + iRealEntNum = iEntNum & ~S_FLAG_DO_CALLBACK; + + if (pSfx->iFlags & SFX_FLAG_STREAMED) { + iFreeChannel = S_OPENAL_PickChannel2DStreamed(iRealEntNum, iEntChannel); + } else { + iFreeChannel = S_OPENAL_PickChannel2D(iRealEntNum, iEntChannel); + } + + if (iFreeChannel < 0) { + Com_DPrintf( + "OpenAL: Couldn't play %s sound '%s' for entity %i on channel %s\n", + (pSfx->iFlags & SFX_FLAG_STREAMED) ? "2Dstreamed" : "2D", + pSfx->name, + iRealEntNum, + S_ChannelNumToName(iEntChannel) + ); + return; + } + + if (iEntNum & S_FLAG_DO_CALLBACK) { + callbackServer(iRealEntNum, iFreeChannel, pSfx->name); + } + + pChannel = openal.channel[iFreeChannel]; + pChannel->force_free(); + + if (fVolume < 0) { + fVolume = 1; + } + + fRealVolume = S_GetBaseVolume() * fVolume; + pChannel->fVolume = fVolume; + + if (pChannel->iEntChannel == CHAN_LOCAL) { + pChannel->iFlags |= CHANNEL_FLAG_LOCAL_LISTENER; + } else { + pChannel->iFlags &= ~CHANNEL_FLAG_LOCAL_LISTENER; + } + pChannel->iFlags &= ~CHANNEL_FLAG_PAUSED; + + if (fMinDistance < 0.0) { + fMinDistance = 200.0; + } + pChannel->fMinDist = fMinDistance; + + if (fMaxDistance < 0.0) { + fMaxDistance = pChannel->fMinDist * 64; + } + pChannel->fMaxDist = fMaxDistance; + + pChannel->fNewPitchMult = fPitch; + pChannel->pSfx = pSfx; + pChannel->iEntNum = iRealEntNum; + pChannel->iEntChannel = iEntChannel; + if (iRealEntNum == ENTITYNUM_NONE) { + VectorClear(pChannel->vOrigin); + pChannel->iFlags |= CHANNEL_FLAG_NO_ENTITY; + pChannel->iEntNum = 0; + + if (vOrigin) { + VectorCopy(vOrigin, pChannel->vOrigin); + } + } else { + pChannel->iFlags &= ~CHANNEL_FLAG_NO_ENTITY; + pChannel->iEntNum = iRealEntNum; + if (vOrigin) { + VectorCopy(vOrigin, pChannel->vOrigin); + + bSupportWaitTillSoundDone = cl.serverTime - 1 < 0; + pChannel->iTime = cl.serverTime - 1; + if (bSupportWaitTillSoundDone) { + pChannel->iTime = 0; + } + + if (s_entity[iEntNum].time < pChannel->iTime) { + // Fixed in OPM + // Not sure if it's the real solution, but script_origin entities are usually + // never sent to client so the sound will immediately get stopped + pChannel->iFlags |= CHANNEL_FLAG_MISSING_ENT; + } + } else { + VectorClear(pChannel->vOrigin); + pChannel->iTime = 0; + } + } + + pChannel->iStartTime = cl.serverTime; + pChannel->iEndTime = (int)(cl.serverTime + pSfx->time_length + 250.f); + + if (iFreeChannel > MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D) { + // streamed + if (!pChannel->set_sfx(pSfx)) { + Com_DPrintf("OpenAL: Set stream error - %s\n", pSfx->name); + return; + } + + pChannel->iBaseRate = pChannel->sample_playback_rate(); + pChannel->set_no_3d(); + fRealVolume = fRealVolume * s_fVolumeGain; + } else { + pChannel->stop(); + pChannel->set_no_3d(); + pChannel->set_sfx(pSfx); + } + + pChannel->set_gain(fRealVolume); + pChannel->play(); + + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: 2D - %d (#%i) - %s (vol %f, mindist %f, maxdist %f)\n", + cl.serverTime, + iFreeChannel, + pSfx->name, + fVolume, + fMinDistance, + fMaxDistance + ); + } +} + +/* +============== +S_OPENAL_StartSound +============== +*/ +void S_OPENAL_StartSound( + const vec3_t vOrigin, + int iEntNum, + int iEntChannel, + sfxHandle_t sfxHandle, + float fVolume, + float fMinDist, + float fPitch, + float fMaxDist, + qboolean bStreamed +) +{ + int iChannel; + openal_channel *pChannel; + sfx_info_t *pSfxInfo; + sfx_t *pSfx; + ALint state; + bool bOnlyUpdate; + bool bSupportWaitTillSoundDone; + + bOnlyUpdate = false; + pSfx = &s_knownSfx[sfxHandle]; + if (bStreamed) { + pSfx->iFlags |= SFX_FLAG_STREAMED; + } + + if (!S_OPENAL_ShouldPlay(pSfx)) { + Com_DPrintf("OpenAL: ^~^~^ Not playing sound '%s'\n", pSfx->name); + return; + } + + if ((pSfx->iFlags & (SFX_FLAG_NO_OFFSET) || pSfx->iFlags & (SFX_FLAG_STREAMED | SFX_FLAG_MP3)) + || iEntChannel == CHAN_MENU || iEntChannel == CHAN_LOCAL) { + S_OPENAL_Start2DSound(vOrigin, iEntNum, iEntChannel, pSfx, fVolume, fMinDist, fPitch, fMaxDist); + return; + } + + bSupportWaitTillSoundDone = (iEntNum & S_FLAG_DO_CALLBACK) != 0; + iEntNum &= ~S_FLAG_DO_CALLBACK; + + pSfxInfo = &sfx_infos[pSfx->sfx_info_index]; + if (pSfx->iFlags & SFX_FLAG_STREAMED) { + Com_DPrintf("OpenAL: 3D sounds not supported - couldn't play '%s'\n", pSfx->name); + return; + } + + iChannel = S_OPENAL_PickChannel3D(iEntNum, iEntChannel); + if (iChannel < 0) { + Com_DPrintf( + "OpenAL: Couldn't play %s sound '%s' for entity %i on channel %s\n", + (pSfx->iFlags & SFX_FLAG_STREAMED) ? "3Dstreamed" : "3D", + pSfx->name, + iEntNum, + S_ChannelNumToName(iEntChannel) + ); + return; + } + + if (bSupportWaitTillSoundDone) { + callbackServer(iEntNum, iChannel, pSfx->name); + } + + pChannel = &openal.chan_3D[iChannel]; + pChannel->fNewPitchMult = fPitch; + pChannel->iEntChannel = iEntChannel; + pChannel->iFlags &= ~(CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_LOCAL_LISTENER); + state = pChannel->sample_status(); + + if (pChannel->iEntNum == iEntNum && (state == AL_PLAYING || state == AL_PAUSED) && pChannel->pSfx == pSfx) { + bOnlyUpdate = true; + } else { + pChannel->stop(); + pChannel->iFlags &= ~(CHANNEL_FLAG_LOOPING | CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_LOCAL_LISTENER); + if (!pChannel->set_sfx(pSfx)) { + Com_DPrintf("OpenAL: Set sample error - %s\n", pSfx->name); + return; + } + } + + if (fMinDist < 0.0) { + fMinDist = 200.0; + fMaxDist = 12800.0; + } + pChannel->fMinDist = fMinDist; + pChannel->fMaxDist = fMaxDist; + + if (fVolume < 0.0) { + fVolume = 1.0; + } + + pChannel->fVolume = S_GetBaseVolume() * fVolume; + pChannel->set_gain(pChannel->fVolume); + + // Fixed in OPM + // Setup the channel for 3D + pChannel->set_3d(); + + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: %d (#%i) - %s (vol %f, mindist %f, maxdist %f)\n", + cl.serverTime, + iChannel, + pSfx->name, + pChannel->fVolume, + fMinDist, + fMaxDist + ); + } + + pChannel->set_velocity(0, 0, 0); + if (iEntNum == ENTITYNUM_NONE) { + if (vOrigin) { + VectorCopy(vOrigin, pChannel->vOrigin); + } else { + //VectorClear(vOrigin); + // Fixed in OPM + // Tiny mistake found in original where the vOrigin parameter is set to 0 + VectorClear(pChannel->vOrigin); + } + + pChannel->set_position(pChannel->vOrigin[0], pChannel->vOrigin[1], pChannel->vOrigin[2]); + pChannel->iFlags |= CHANNEL_FLAG_NO_ENTITY; + pChannel->iEntNum = 0; + } else { + pChannel->iFlags &= ~CHANNEL_FLAG_NO_ENTITY; + pChannel->iEntNum = iEntNum; + if (vOrigin) { + VectorCopy(vOrigin, pChannel->vOrigin); + + bSupportWaitTillSoundDone = cl.serverTime - 1 < 0; + pChannel->iTime = cl.serverTime - 1; + if (bSupportWaitTillSoundDone) { + pChannel->iTime = 0; + } + + if (s_entity[iEntNum].time < pChannel->iTime) { + // Fixed in OPM + // Not sure if it's the real solution, but script_origin entities are usually + // never sent to client so the sound will immediately get stopped + pChannel->iFlags |= CHANNEL_FLAG_MISSING_ENT; + } + } else { + VectorClear(pChannel->vOrigin); + pChannel->iTime = 0; + } + pChannel->set_position(pChannel->vOrigin[0], pChannel->vOrigin[1], pChannel->vOrigin[2]); + } + + if (pSfxInfo->loop_start != -1) { + pChannel->set_sample_loop_block(pSfxInfo->loop_start, pSfxInfo->loop_end); + pChannel->set_sample_loop_count(0); + + pChannel->iFlags |= CHANNEL_FLAG_LOOPING; + if (s_show_sounds->integer) { + Com_DPrintf("OpenAL: loopblock - %d to %d\n", pSfxInfo->loop_start, pSfxInfo->loop_end); + } + } else { + pChannel->set_sample_loop_count(1); + } + + if (!bOnlyUpdate && S_OPENAL_ShouldStart(pChannel->vOrigin, pChannel->fMinDist, pChannel->fMaxDist)) { + // Fixed in OPM + // Make sure to set the pitch before playing the sound + pChannel->iBaseRate = pSfx->info.rate; + pChannel->set_sample_playback_rate(pChannel->iBaseRate * pChannel->fNewPitchMult); + pChannel->fNewPitchMult = 0; + + pChannel->play(); + pChannel->iEndTime = cl.serverTime + (int)pChannel->pSfx->time_length + 250; + pChannel->iStartTime = cl.serverTime; + } +} + +/* +============== +S_OPENAL_AddLoopingSound +============== +*/ +void S_OPENAL_AddLoopingSound( + const vec3_t vOrigin, + const vec3_t vVelocity, + sfxHandle_t sfxHandle, + float fVolume, + float fMinDist, + float fMaxDist, + float fPitch, + int iFlags +) +{ + int i; + int iFreeLoopSound; + sfx_t *pSfx; + openal_loop_sound_t *pLoopSound; + + iFreeLoopSound = -1; + pSfx = &s_knownSfx[sfxHandle]; + if (!pSfx || !pSfx->length) { + return; + } + + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + pLoopSound = &openal.loop_sounds[i]; + if (pLoopSound->pSfx == pSfx && !pLoopSound->bInUse) { + iFreeLoopSound = i; + break; + } + } + + if (iFreeLoopSound < 0) { + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + pLoopSound = &openal.loop_sounds[i]; + if (!pLoopSound->pSfx && !pLoopSound->bInUse) { + iFreeLoopSound = i; + pLoopSound->bPlaying = false; + break; + } + } + } + + if (iFreeLoopSound < 0) { + if (cls.realtime >= s_iNextLoopingWarning) { + Com_DPrintf("OpenAL: Too many looping sounds\n"); + s_iNextLoopingWarning = cls.realtime + 1000; + } + return; + } + + pLoopSound = &openal.loop_sounds[iFreeLoopSound]; + VectorCopy(vOrigin, pLoopSound->vOrigin); + VectorCopy(vVelocity, pLoopSound->vVelocity); + pLoopSound->pSfx = pSfx; + pLoopSound->bInUse = true; + pLoopSound->iStartTime = cls.realtime; + pLoopSound->fBaseVolume = fVolume; + pLoopSound->fMinDist = fMinDist; + pLoopSound->fMaxDist = fMaxDist; + pLoopSound->fPitch = fPitch; + pLoopSound->iFlags = iFlags; + pLoopSound->bCombine = VectorCompare(vVelocity, vec_zero) == 0; + + if (pLoopSound->bCombine) { + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + if (openal.loop_sounds[i].pSfx == pSfx && openal.loop_sounds[i].bInUse) { + pLoopSound->iStartTime = openal.loop_sounds[i].iStartTime; + if (openal.loop_sounds[i].bPlaying) { + pLoopSound->bPlaying = true; + pLoopSound->iChannel = openal.loop_sounds[i].iChannel; + } + } + } + } +} + +/* +============== +S_OPENAL_StopLoopingSound +============== +*/ +void S_OPENAL_StopLoopingSound(openal_loop_sound_t *pLoopSound) +{ + bool bMayStop; + int i; + openal_channel *pChannel; + + if (!pLoopSound->bPlaying) { + return; + } + bMayStop = true; + + if (pLoopSound->bCombine) { + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + if (openal.loop_sounds[i].pSfx == pLoopSound->pSfx && openal.loop_sounds[i].bInUse) { + bMayStop = false; + break; + } + } + } + + if (bMayStop) { + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: %d (#%i) - stopped loop - %s\n", + cl.serverTime, + pLoopSound->iChannel, + openal.channel[pLoopSound->iChannel]->pSfx->name + ); + } + openal.channel[pLoopSound->iChannel]->force_free(); + } + pLoopSound->pSfx = NULL; + pLoopSound->bPlaying = false; + + if (pLoopSound->bCombine) { + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + if (openal.loop_sounds[i].pSfx == pLoopSound->pSfx) { + openal.loop_sounds[i].bPlaying = false; + openal.loop_sounds[i].pSfx = NULL; + } + } + } +} + +/* +============== +S_OPENAL_ClearLoopingSounds +============== +*/ +void S_OPENAL_ClearLoopingSounds() +{ + int i; + + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + openal.loop_sounds[i].bInUse = false; + } +} + +/* +============== +S_OPENAL_StopLoopingSounds +============== +*/ +void S_OPENAL_StopLoopingSounds() +{ + int i; + + for (i = 0; i < (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D); i++) { + openal.loop_sounds[i].bInUse = false; + S_OPENAL_StopLoopingSound(&openal.loop_sounds[i]); + } +} + +/* +============== +S_OPENAL_StopSound +============== +*/ +void S_OPENAL_StopSound(int iEntNum, int iEntChannel) +{ + int i; + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + openal_channel *pChannel = openal.channel[i]; + if (!pChannel->is_free() && pChannel->iEntNum == iEntNum && pChannel->iEntChannel == iEntChannel) { + pChannel->end_sample(); + break; + } + } +} + +/* +============== +S_OPENAL_StopAllSounds +============== +*/ +void S_OPENAL_StopAllSounds(qboolean bStopMusic) +{ + int i; + + if (!s_bSoundStarted) { + return; + } + + S_OPENAL_StopLoopingSounds(); + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + openal_channel *pChannel = openal.channel[i]; + if (pChannel) { + pChannel->force_free(); + } + } + + if (bStopMusic) { + MUSIC_FreeAllSongs(); + S_TriggeredMusic_Stop(); + } +} + +/* +============== +S_OPENAL_Start2DLoopSound +============== +*/ +static int S_OPENAL_Start2DLoopSound( + openal_loop_sound_t *pLoopSound, float fVolume, float fVolumeToPlay, float fMinDistance, const vec3_t vLoopOrigin +) +{ + int iChannel; + int iSoundOffset; + openal_channel *pChannel; + + if (pLoopSound->pSfx->iFlags & SFX_FLAG_STREAMED) { + iChannel = S_OPENAL_PickChannel2DStreamed(0, 0); + } else { + iChannel = S_OPENAL_PickChannel2D(0, 0); + } + + if (iChannel < 0) { + Com_DPrintf("OpenAL: Could not find a free 2D sound channel\n"); + return iChannel; + } + + pChannel = openal.channel[iChannel]; + pChannel->force_free(); + pChannel->fVolume = fVolume; + + if (pLoopSound->iFlags & LOOPSOUND_FLAG_NO_PAN) { + pChannel->iFlags |= CHANNEL_FLAG_LOCAL_LISTENER; + } else { + pChannel->iFlags &= ~CHANNEL_FLAG_LOCAL_LISTENER; + } + pChannel->fMinDist = fMinDistance; + + if (!pChannel->set_sfx(pLoopSound->pSfx)) { + Com_DPrintf("OpenAL: Set sample error (loopsound) - %s\n", pLoopSound->pSfx->name); + pChannel->iFlags &= ~CHANNEL_FLAG_PLAY_DEFERRED; + return -1; + } + + pChannel->iEntNum = 0; + pChannel->iEntChannel = 0; + pChannel->pSfx = pLoopSound->pSfx; + pChannel->iFlags |= CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_NO_ENTITY; + pChannel->iBaseRate = pChannel->sample_playback_rate(); + VectorCopy(vLoopOrigin, pChannel->vOrigin); + + iSoundOffset = (int)(pLoopSound->pSfx->info.width * pLoopSound->pSfx->info.rate + * (float)(cls.realtime - pLoopSound->iStartTime) / 1000.0); + pChannel->set_sample_offset(iSoundOffset % pLoopSound->pSfx->length); + pChannel->set_sample_loop_count(0); + pChannel->fVolume = fVolumeToPlay; + pChannel->set_gain(fVolumeToPlay); + pChannel->start_sample(); + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: %d (#%i) - %s (vol %f)\n", cl.serverTime, pLoopSound->iChannel, pLoopSound->pSfx->name, fVolume + ); + } + + return iChannel; +} + +/* +============== +S_OPENAL_Start3DLoopSound +============== +*/ +static int S_OPENAL_Start3DLoopSound( + openal_loop_sound_t *pLoopSound, + float fVolumeToPlay, + float fMinDistance, + float fMaxDistance, + const vec3_t vLoopOrigin, + const vec3_t vListenerOrigin +) +{ + int iChannel; + vec3_t vDir; + int iSoundOffset; + openal_channel *pChan3D; + + if (pLoopSound->pSfx->iFlags & SFX_FLAG_STREAMED) { + return -1; + } + + if (!pLoopSound->pSfx->data || !pLoopSound->pSfx->length) { + return -1; + } + + iChannel = S_OPENAL_PickChannel3D(0, 0); + if (iChannel < 0) { + Com_DPrintf("OpenAL: Could not find a free channel\n"); + return iChannel; + } + + pChan3D = &openal.chan_3D[iChannel]; + pChan3D->force_free(); + pChan3D->iEntNum = 0; + pChan3D->iEntChannel = 0; + pChan3D->fMinDist = fMinDistance; + pChan3D->fMaxDist = fMaxDistance; + pChan3D->set_3d(); + + if (!pChan3D->set_sfx(pLoopSound->pSfx)) { + Com_DPrintf("OpenAL: Set sample error - %s\n", pLoopSound->pSfx->name); + return -1; + } + + pChan3D->set_position(vLoopOrigin[0], vLoopOrigin[1], vLoopOrigin[2]); + VectorScale(pLoopSound->vVelocity, s_fVelocityScale, pLoopSound->vVelocity); + pChan3D->set_velocity(pLoopSound->vVelocity[0], pLoopSound->vVelocity[1], pLoopSound->vVelocity[2]); + pChan3D->pSfx = pLoopSound->pSfx; + pChan3D->iFlags |= CHANNEL_FLAG_PAUSED | CHANNEL_FLAG_NO_ENTITY; + pChan3D->iBaseRate = pChan3D->sample_playback_rate(); + + iSoundOffset = (int)((int)pLoopSound->pSfx->info.width * pLoopSound->pSfx->info.rate + * (float)(cls.realtime - pLoopSound->iStartTime) / 1000.0) + % pLoopSound->pSfx->length; + pChan3D->set_sample_offset(iSoundOffset); + pChan3D->set_sample_loop_count(0); + pChan3D->fVolume = fVolumeToPlay; + pChan3D->set_gain(fVolumeToPlay); + pChan3D->play(); + + S_OPENAL_reverb(iChannel, s_iReverbType, s_fReverbLevel); + + return iChannel; +} + +/* +============== +S_OPENAL_UpdateLoopSound +============== +*/ +static bool S_OPENAL_UpdateLoopSound( + openal_loop_sound_t *pLoopSound, + float fVolumeToPlay, + float fMinDistance, + float fMaxDistance, + const vec3_t vListenerOrigin, + const vec3_t vTempAxis, + const vec3_t vLoopOrigin +) +{ + openal_channel *pChannel; + float fVolume; + float fMaxVolume; + vec3_t vDir; + float fDistance; + + pChannel = openal.channel[pLoopSound->iChannel]; + if (!pChannel) { + return false; + } + + if (pChannel->pSfx != pLoopSound->pSfx) { + pLoopSound->bPlaying = 0; + return false; + } + + pChannel->iStartTime = cl.serverTime; + + if (pLoopSound->pSfx->iFlags & (SFX_FLAG_NO_OFFSET) || pLoopSound->pSfx->iFlags & (SFX_FLAG_STREAMED | SFX_FLAG_MP3) + || (pLoopSound->iFlags & LOOPSOUND_FLAG_NO_PAN)) { + vec3_t vOrigin; + int iPan; + + pChannel->fVolume = fVolumeToPlay / s_fVolumeGain; + fVolume = S_GetBaseVolume() * pChannel->fVolume; + fMaxVolume = fVolume; + + if (pLoopSound->iFlags & LOOPSOUND_FLAG_NO_PAN) { + // Center the sound + iPan = 64; + } else { + VectorCopy(vLoopOrigin, vOrigin); + iPan = S_OPENAL_SpatializeStereoSound(vListenerOrigin, vTempAxis, vOrigin); + + VectorSubtract(vListenerOrigin, vOrigin, vDir); + // Clamp the volume by distance + fDistance = VectorLength(vDir); + if (pChannel->fMinDist >= fDistance) { + fVolume = fMaxVolume; + } else { + fVolume = pChannel->fMinDist / fDistance * fMaxVolume; + } + } + + pChannel->set_gain(fVolume); + pChannel->set_sample_pan(iPan); + } else { + pChannel->set_position(vLoopOrigin[0], vLoopOrigin[1], vLoopOrigin[2]); + pChannel->fVolume = fVolumeToPlay; + pChannel->set_gain(fVolumeToPlay); + } + + if (s_bReverbChanged) { + // Make sure to update the reverb + S_OPENAL_reverb(pLoopSound->iChannel, s_iReverbType, s_fReverbLevel); + } + + return true; +} + +/* +============== +S_OPENAL_AddLoopSounds +============== +*/ +void S_OPENAL_AddLoopSounds(const vec3_t vTempAxis) +{ + int i, j; + static int iLoopFrame = 0; + float fDistance; + int iChannel; + vec3_t vListenerOrigin; + vec3_t vLoopOrigin; + openal_loop_sound_t *pLoopSound; + float fTotalVolume; + float fVolumeToPlay; + float fMinDistance, fMaxDistance; + float fVolume; + float fPitch; + float fMaxVolume, fMaxFactor; + openal_channel *pChannel; + bool bAlreadyAdded[MAX_SOUNDSYSTEM_LOOP_SOUNDS] = {false}; + vec3_t alvec; + + qalGetListenerfv(AL_POSITION, alvec); + VectorCopy(alvec, vListenerOrigin); + + for (i = 0; i < MAX_SOUNDSYSTEM_LOOP_SOUNDS; i++) { + vec3_t vDir; + + if (bAlreadyAdded[i]) { + continue; + } + + pLoopSound = &openal.loop_sounds[i]; + if (!pLoopSound->pSfx) { + continue; + } + pChannel = openal.channel[pLoopSound->iChannel]; + + fMinDistance = pLoopSound->fMinDist; + if (fMinDistance < 0) { + fMinDistance = 200; + } + + fMaxDistance = pLoopSound->fMaxDist; + if (fMaxDistance < 0) { + fMaxDistance = fMinDistance * 64; + } + + fVolume = pLoopSound->fBaseVolume; + if (fVolume < 0) { + fVolume = 1; + } + fVolume = fVolume * s_fAmbientVolume; + + fTotalVolume = 0.0; + fMaxVolume = 0.0; + + if (pLoopSound->bPlaying) { + pChannel->fNewPitchMult = pLoopSound->fPitch; + } + + if (pLoopSound->bCombine) { + for (j = 0; j < MAX_LOOP_SOUNDS; j++) { + openal_loop_sound_t *pLoopSound2 = &openal.loop_sounds[j]; + + if (pLoopSound2->pSfx == pLoopSound->pSfx) { + VectorSubtract(pLoopSound2->vOrigin, vListenerOrigin, vDir); + VectorCopy(vDir, pLoopSound2->vRelativeOrigin); + fDistance = VectorLength(pLoopSound2->vRelativeOrigin); + + if (fDistance <= fMinDistance) { + fVolumeToPlay = fVolume; + } else if (fDistance >= fMaxDistance) { + fVolumeToPlay = 0; + } else { + fVolumeToPlay = fMinDistance * fMinDistance * fVolume / (fDistance * fDistance); + } + + if (fMaxVolume < fVolumeToPlay) { + fMaxVolume = fVolumeToPlay; + } + fTotalVolume += fVolumeToPlay; + bAlreadyAdded[j] = true; + } + } + } else { + VectorSubtract(pLoopSound->vOrigin, vListenerOrigin, vDir); + VectorCopy(vDir, pLoopSound->vRelativeOrigin); + fDistance = VectorLength(pLoopSound->vRelativeOrigin); + + if (fDistance <= fMinDistance) { + fTotalVolume = fVolume; + } else if (fDistance >= fMaxDistance) { + fTotalVolume = 0; + } else { + fTotalVolume = fMinDistance * fMinDistance * fVolume / (fDistance * fDistance); + } + pLoopSound->fVolume = fTotalVolume; + fMaxVolume = fTotalVolume; + } + + fMaxFactor = sfx_infos[pLoopSound->pSfx->sfx_info_index].max_factor; + if (fMaxFactor >= 1 && fMaxVolume * fMaxFactor < fTotalVolume) { + fTotalVolume = fMaxVolume * fMaxFactor; + } + + if (fTotalVolume <= 0 && !(pLoopSound->iFlags & LOOPSOUND_FLAG_NO_PAN)) { + if (pLoopSound->bPlaying) { + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: %d (#%i) - stopped loop - %s\n", + cl.serverTime, + pLoopSound->iChannel, + openal.channel[pLoopSound->iChannel]->pSfx->name + ); + } + + pChannel->stop(); + pLoopSound->bPlaying = false; + if (pLoopSound->bCombine) { + for (j = 0; j < MAX_LOOP_SOUNDS; j++) { + openal_loop_sound_t *pLoopSound2 = &openal.loop_sounds[j]; + + if (pLoopSound2->pSfx == pLoopSound->pSfx) { + pLoopSound2->bPlaying = false; + } + } + } + } + + continue; + } + + VectorClear(vLoopOrigin); + + if (pLoopSound->bCombine) { + for (j = 0; j < MAX_LOOP_SOUNDS; j++) { + openal_loop_sound_t *pLoopSound2 = &openal.loop_sounds[j]; + + if (pLoopSound2->pSfx == pLoopSound->pSfx) { + VectorNormalize(pLoopSound2->vRelativeOrigin); + + VectorScale( + pLoopSound2->vRelativeOrigin, pLoopSound2->fVolume / fTotalVolume, pLoopSound2->vRelativeOrigin + ); + VectorAdd(pLoopSound2->vRelativeOrigin, vLoopOrigin, vLoopOrigin); + } + } + + VectorNormalize(vLoopOrigin); + VectorMA(vListenerOrigin, fMinDistance * 0.5f, vLoopOrigin, vLoopOrigin); + } else { + VectorCopy(pLoopSound->vOrigin, vLoopOrigin); + } + + if (pLoopSound->bPlaying) { + S_OPENAL_UpdateLoopSound( + pLoopSound, + S_GetBaseVolume() * s_fVolumeGain * fTotalVolume, + fMinDistance, + fMaxDistance, + vListenerOrigin, + vTempAxis, + vLoopOrigin + ); + + continue; + } + + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: %d (#%i) - started loop - %s\n", cl.serverTime, pLoopSound->iChannel, pLoopSound->pSfx->name + ); + } + + if (pLoopSound->pSfx->iFlags & (SFX_FLAG_NO_OFFSET) + || pLoopSound->pSfx->iFlags & (SFX_FLAG_STREAMED | SFX_FLAG_MP3) + || (pLoopSound->iFlags & LOOPSOUND_FLAG_NO_PAN)) { + iChannel = S_OPENAL_Start2DLoopSound( + pLoopSound, fVolume, S_GetBaseVolume() * s_fVolumeGain * fTotalVolume, fMinDistance, vLoopOrigin + ); + } else { + iChannel = S_OPENAL_Start3DLoopSound( + pLoopSound, + S_GetBaseVolume() * s_fVolumeGain * fTotalVolume, + fMinDistance, + fMaxDistance, + vLoopOrigin, + vListenerOrigin + ); + } + + if (iChannel < 0) { + continue; + } + + pLoopSound->bPlaying = true; + pLoopSound->iChannel = iChannel; + + if (pLoopSound->bCombine) { + for (j = 0; j < MAX_LOOP_SOUNDS; j++) { + openal_loop_sound_t *pLoopSound2 = &openal.loop_sounds[j]; + + if (pLoopSound2->pSfx == pLoopSound->pSfx) { + pLoopSound2->bPlaying = true; + pLoopSound2->iChannel = iChannel; + } + } + } + } +} + +/* +============== +S_OPENAL_Respatialize +============== +*/ +void S_OPENAL_Respatialize(int iEntNum, const vec3_t vHeadPos, const vec3_t vAxis[3]) +{ + int i; + vec3_t vOrigin; + vec3_t vVelocity; + vec3_t vEntOrigin; + vec3_t vEntVelocity; + vec3_t vDir; + vec3_t vUp; + vec3_t vListenerOrigin; + int iPan; + vec3_t vTempAxis; + float fMaxVolume; + float fVolume; + float fDist; + openal_channel *pChannel; + vec3_t alvec {0}; + vec3_t alorientation[2]; + + if (cls.no_menus) { + return; + } + + s_iListenerNumber = iEntNum; + + // + // Velocity + // + VectorCopy(s_entity[iEntNum].velocity, alvec); + VectorScale(alvec, s_fVelocityScale, alvec); + qalListenerfv(AL_VELOCITY, alvec); + alDieIfError(); + + // + // Position + // + VectorCopy(vHeadPos, alvec); + VectorCopy(alvec, vListenerOrigin); + qalListenerfv(AL_POSITION, alvec); + alDieIfError(); + + // + // Orientation + // + alorientation[0][0] = vAxis[0][0]; + alorientation[0][1] = vAxis[0][1]; + alorientation[0][2] = vAxis[0][2]; + alorientation[1][0] = vAxis[2][0]; + alorientation[1][1] = vAxis[2][1]; + alorientation[1][2] = vAxis[2][2]; + qalListenerfv(AL_ORIENTATION, (const ALfloat *)alorientation); + alDieIfError(); + + VectorCopy(vAxis[1], vTempAxis); + + fVolume = 1; + iPan = 64; + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + pChannel = openal.channel[i]; + fMaxVolume = S_GetBaseVolume() * pChannel->fVolume; + + if (!pChannel) { + continue; + } + + if (!pChannel->is_playing()) { + continue; + } + + if (pChannel->iFlags & CHANNEL_FLAG_PAUSED) { + continue; + } + + if (pChannel->iFlags & CHANNEL_FLAG_NO_ENTITY) { + VectorCopy(pChannel->vOrigin, vOrigin); + + if (pChannel->iFlags & CHANNEL_FLAG_LOCAL_LISTENER) { + VectorCopy(vListenerOrigin, vOrigin); + if (i >= MAX_SOUNDSYSTEM_CHANNELS_3D) { + fVolume = fMaxVolume; + iPan = 64; + } else { + pChannel->set_position(vOrigin[0], vOrigin[1], vOrigin[2]); + } + } else { + if (i >= MAX_SOUNDSYSTEM_CHANNELS_3D) { + iPan = S_OPENAL_SpatializeStereoSound(vListenerOrigin, vTempAxis, vOrigin); + VectorSubtract(vListenerOrigin, vOrigin, vDir); + + fDist = VectorLength(vDir); + if (fDist <= pChannel->fMinDist + 0.001f) { + fVolume = fMaxVolume; + } else if (fDist >= pChannel->fMaxDist - 0.001f) { + fVolume = 0; + } else { + fVolume = (1.0 - (fDist - pChannel->fMinDist) / (pChannel->fMaxDist - pChannel->fMinDist)) + * fMaxVolume; + } + } else { + pChannel->set_position(vOrigin[0], vOrigin[1], vOrigin[2]); + } + } + } else if (pChannel->iFlags & CHANNEL_FLAG_LOCAL_LISTENER) { + VectorCopy(vListenerOrigin, vOrigin); + if (i >= MAX_SOUNDSYSTEM_CHANNELS_3D) { + fVolume = fMaxVolume; + iPan = 64; + } else { + pChannel->set_position(vOrigin[0], vOrigin[1], vOrigin[2]); + } + } else { + if (s_entity[pChannel->iEntNum].time < pChannel->iTime) { + VectorCopy(pChannel->vOrigin, vOrigin); + if (!(pChannel->iFlags & CHANNEL_FLAG_LOOPING) && !(pChannel->iFlags & (CHANNEL_FLAG_MISSING_ENT))) { + pChannel->end_sample(); + continue; + } + } else { + pChannel->iFlags &= ~CHANNEL_FLAG_MISSING_ENT; + + VectorCopy(s_entity[pChannel->iEntNum].position, vEntOrigin); + VectorCopy(vEntOrigin, vOrigin); + VectorCopy(vOrigin, pChannel->vOrigin); + pChannel->iTime = s_entity[pChannel->iEntNum].time; + } + + if (s_entity[pChannel->iEntNum].use_listener) { + VectorCopy(vListenerOrigin, vOrigin); + } + + if (pChannel->iEntNum == s_iListenerNumber) { + if (vListenerOrigin[0] == vOrigin[0] && vListenerOrigin[2] == vOrigin[2]) { + float fDelta = vListenerOrigin[1] - vOrigin[1]; + + if (fDelta > 89.9f && fDelta < 90.09f) { + VectorCopy(vListenerOrigin, vOrigin); + } + } + } + + if (i >= MAX_SOUNDSYSTEM_CHANNELS_3D) { + iPan = S_OPENAL_SpatializeStereoSound(vListenerOrigin, vTempAxis, vOrigin); + VectorSubtract(vListenerOrigin, vOrigin, vDir); + fDist = VectorLength(vDir); + if (fDist <= pChannel->fMinDist + 0.001f) { + fVolume = fMaxVolume; + } else if (fDist >= pChannel->fMaxDist - 0.001f) { + fVolume = 0; + } else { + fVolume = + (1.0 - (fDist - pChannel->fMinDist) / (pChannel->fMaxDist - pChannel->fMinDist)) * fMaxVolume; + } + } else { + pChannel->set_position(vOrigin[0], vOrigin[1], vOrigin[2]); + VectorCopy(s_entity[pChannel->iEntNum].velocity, vEntVelocity); + VectorCopy(vEntVelocity, vVelocity); + VectorScale(vVelocity, s_fVelocityScale, vVelocity); + pChannel->set_velocity(vVelocity[0], vVelocity[1], vVelocity[2]); + } + } + + if (i >= MAX_SOUNDSYSTEM_CHANNELS_3D) { + pChannel->set_gain(fVolume); + pChannel->set_sample_pan(iPan); + } + + if (s_bReverbChanged) { + S_OPENAL_reverb(i, s_iReverbType, s_fReverbLevel); + } + } + + S_OPENAL_AddLoopSounds(vTempAxis); + s_bReverbChanged = false; +} + +/* +============== +S_OPENAL_SpatializeStereoSound +============== +*/ +static int S_OPENAL_SpatializeStereoSound(const vec3_t listener_origin, const vec3_t listener_left, const vec3_t origin) +{ + float lscale, rscale; + vec3_t source_vec; + float pan; + + VectorSubtract(origin, listener_origin, source_vec); + VectorNormalize(source_vec); + + pan = s_separation->value + (1.f - s_separation->value) * -DotProduct(listener_left, source_vec); + + if (pan < 0) { + pan = 0; + } + + return ceilf(pan * 127); +} + +/* +============== +S_OPENAL_reverb +============== +*/ +static void S_OPENAL_reverb(int iChannel, int iReverbType, float fReverbLevel) +{ + // FIXME: Connect source to effect slot + // see https://github.com/kcat/openal-soft/blob/master/examples/alreverb.c + + // No reverb currently. +} + +/* +============== +S_OPENAL_SetReverb +============== +*/ +void S_OPENAL_SetReverb(int iType, float fLevel) +{ + s_fReverbLevel = fLevel; + s_iReverbType = iType; + if (al_use_reverb) { + s_bReverbChanged = true; + } + + // FIXME: generate effect and auxiliary effect slot + // or destroy them + // see https://github.com/kcat/openal-soft/blob/master/examples/alreverb.c +} + +/* +============== +S_OPENAL_Update +============== +*/ +void S_OPENAL_Update() +{ + int i; + openal_channel *pChannel; + + if (cl.snap.ps.stats[STAT_CINEMATIC]) { + S_SetGlobalAmbientVolumeLevel(0.5f); + } else { + S_SetGlobalAmbientVolumeLevel(1.f); + } + + if (paused->integer && !s_bSoundPaused) { + S_PauseSound(); + } else if (!paused->integer && s_bSoundPaused) { + S_UnpauseSound(); + } + + if (s_bFading) { + s_fFadeVolume = 1.f - (cls.realtime - s_fFadeStartTime) / (s_fFadeStopTime - s_fFadeStartTime); + if (s_fFadeVolume < 0) { + s_fFadeVolume = 0; + } + music_volume_changed = true; + } + + if (s_volume->modified) { + if (s_volume->value > 1) { + Cvar_Set("s_volume", "1.0"); + } else if (s_volume->value < 0) { + Cvar_Set("s_volume", "0.0"); + } + + music_volume_changed = true; + s_volume->modified = 0; + al_current_volume = Square(s_volume->value); + qalListenerf(AL_GAIN, al_current_volume); + alDieIfError(); + } + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + pChannel = openal.channel[i]; + if (!pChannel) { + continue; + } + + if (!pChannel->is_playing()) { + continue; + } + + if (pChannel->fNewPitchMult <= 0) { + continue; + } + + pChannel->set_sample_playback_rate(pChannel->iBaseRate * pChannel->fNewPitchMult); + pChannel->fNewPitchMult = 0; + } + + if (s_speaker_type->modified) { + Cbuf_AddText("snd_restart\n"); + s_speaker_type->modified = false; + } + + if (s_reverb->modified) { + s_reverb->modified = false; + + if (s_reverb->integer) { + if (al_use_reverb) { + S_OPENAL_SetReverb(s_iReverbType, s_fReverbLevel); + } else { + Com_Printf("OpenAL: No reverb support. Reverb is disabled.\n"); + } + } else if (al_use_reverb) { + S_OPENAL_SetReverb(0, 0); + } + } + + if (s_show_num_active_sounds->integer == 1) { + int num = 0; + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + pChannel = openal.channel[i]; + if (pChannel && pChannel->is_playing()) { + ++num; + } + } + Com_DPrintf("OpenAL: Number of active sounds = %d\n", num); + } + + Music_Update(); + + for (i = 0; i < MAX_LOOP_SOUNDS; i++) { + if (!openal.loop_sounds[i].bInUse) { + S_OPENAL_StopLoopingSound(&openal.loop_sounds[i]); + } + } + + for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS; i++) { + openal.channel[i]->update(); + } +} + +/* +============== +S_OPENAL_GetMusicFilename +============== +*/ +const char *S_OPENAL_GetMusicFilename() +{ + // Don't call into the channel if QAL initialisation did not succeed. + if (!al_initialized) { + return ""; + } + + if (!openal.chan_trig_music.is_playing() && !openal.chan_trig_music.is_paused()) { + return ""; + } + + return openal.tm_filename; +} + +/* +============== +S_OPENAL_GetMusicLoopCount +============== +*/ +int S_OPENAL_GetMusicLoopCount() +{ + return openal.tm_loopcount; +} + +/* +============== +S_OPENAL_GetMusicOffset +============== +*/ +unsigned int S_OPENAL_GetMusicOffset() +{ + return openal.chan_trig_music.sample_offset(); +} + +/* +============== +S_IsSoundPlaying +============== +*/ +qboolean S_IsSoundPlaying(int channel_number, const char *sfxName) +{ + openal_channel *pChannel = openal.channel[channel_number]; + if (!pChannel) { + return false; + } + + if (s_bSoundPaused) { + return false; + } + + if (!pChannel->is_playing()) { + return false; + } + + if (!pChannel->pSfx) { + return false; + } + + if (strcmp(sfxName, pChannel->pSfx->name)) { + return false; + } + + return true; +} + +/* +============== +S_StoreBase +============== +*/ +static void S_StoreBase(channelbasesavegame_t *pBase, openal_channel *pChannel) +{ + if (!pChannel) { + return; + } + + if (pChannel->iEntChannel == CHAN_MENU || pChannel->is_free()) { + pBase->bPlaying = false; + pBase->iOffset = 0; + pBase->iLoopCount = 0; + pBase->sfx.szName[0] = 0; + pBase->sfx.iFlags = 0; + pBase->fNewPitchMult = 1.f; + pBase->iBaseRate = pChannel->iBaseRate; + pBase->iStatus = 0; + } else { + pBase->bPlaying = true; + pBase->iOffset = pChannel->sample_offset(); + pBase->iLoopCount = pChannel->sample_loop_count(); + memcpy(pBase->sfx.szName, pChannel->pSfx->name, sizeof(pBase->sfx.szName)); + pBase->sfx.iFlags = pChannel->pSfx->iFlags; + pBase->iBaseRate = pChannel->iBaseRate; + pBase->iStatus = 0; + pBase->fNewPitchMult = (float)pBase->iBaseRate / (float)pChannel->sample_playback_rate(); + } + + pBase->iStartTime = pChannel->iStartTime - cl.serverTime; + pBase->iEndTime = pChannel->iEndTime - cl.serverTime; + pBase->iEntChannel = pChannel->iEntChannel; + pBase->iEntNum = pChannel->iEntNum; + pBase->iFlags = pChannel->iFlags; + pBase->fMaxDist = pChannel->fMaxDist; + pBase->fMinDist = pChannel->fMinDist; + pBase->iNextCheckObstructionTime = 0; + VectorCopy(pChannel->vOrigin, pBase->vOrigin); + pBase->iTime = pChannel->iTime - cl.serverTime; + pBase->fVolume = pChannel->fVolume; +} + +/* +============== +S_StartSoundFromBase +============== +*/ +static void +S_StartSoundFromBase(channelbasesavegame_t *pBase, openal_channel *pChannel, sfx_t *pSfx, bool bStartUnpaused) +{ + if (!pChannel->set_sfx(pSfx)) { + Com_DPrintf("OpenAL: Set sample error - %s\n", pSfx->name); + pChannel->iFlags &= ~CHANNEL_FLAG_PLAY_DEFERRED; + return; + } + + pChannel->iBaseRate = pChannel->sample_playback_rate(); + + if (sfx_infos[pSfx->sfx_info_index].loop_start != -1) { + pChannel->set_sample_loop_block( + sfx_infos[pSfx->sfx_info_index].loop_start, sfx_infos[pSfx->sfx_info_index].loop_end + ); + pChannel->set_sample_loop_count(1); + pChannel->iFlags |= CHANNEL_FLAG_LOOPING; + if (s_show_sounds->integer > 0) { + Com_DPrintf( + "OpenAL: loopblock - %d to %d\n", + sfx_infos[pSfx->sfx_info_index].loop_start, + sfx_infos[pSfx->sfx_info_index].loop_end + ); + } + } else { + pChannel->set_sample_loop_count(1); + } + + pChannel->set_gain(pChannel->fVolume); + pChannel->set_sample_offset(pBase->iOffset); + pChannel->set_sample_playback_rate(pChannel->iBaseRate * pBase->fNewPitchMult); + + if (bStartUnpaused) { + pChannel->resume_sample(); + } else { + pChannel->iFlags |= CHANNEL_FLAG_PLAY_DEFERRED; + } + + if (pChannel->iEntNum != ENTITYNUM_NONE) { + s_entity[pChannel->iEntNum].time = pChannel->iTime; + VectorCopy(pChannel->vOrigin, s_entity[pChannel->iEntNum].position); + } +} + +/* +============== +S_LoadBase +============== +*/ +static void S_LoadBase(channelbasesavegame_t *pBase, openal_channel *pChannel, bool bStartUnpaused) +{ + sfxHandle_t handle; + + if (!pChannel) { + return; + } + + if (!pBase->bPlaying) { + return; + } + + if (strstr(pBase->sfx.szName, "null.wav")) { + return; + } + + handle = S_RegisterSound(pBase->sfx.szName, (pBase->sfx.iFlags & SFX_FLAG_STREAMED), false); + + pChannel->iBaseRate = pBase->iBaseRate; + pChannel->iStartTime = pBase->iStartTime; + pChannel->iEndTime = pBase->iEndTime; + pChannel->iEntChannel = pBase->iEntChannel; + pChannel->iEntNum = pBase->iEntNum; + pChannel->iFlags = pBase->iFlags; + pChannel->fMaxDist = pBase->fMaxDist; + pChannel->fMinDist = pBase->fMinDist; + pChannel->fNewPitchMult = pBase->fNewPitchMult; + VectorCopy(pBase->vOrigin, pChannel->vOrigin); + pChannel->iTime = pBase->iTime; + pChannel->fVolume = pBase->fVolume; + pChannel->pSfx = &s_knownSfx[handle]; + + S_StartSoundFromBase(pBase, pChannel, &s_knownSfx[handle], bStartUnpaused); +} + +/* +============== +S_SaveData +============== +*/ +void S_SaveData(soundsystemsavegame_t *pSave) +{ + int i; + bool bSoundWasUnpaused; + + bSoundWasUnpaused = !s_bSoundPaused; + if (!s_bSoundPaused) { + S_PauseSound(); + } + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + S_StoreBase(&pSave->Channels[i], openal.channel[i]); + } + + if (bSoundWasUnpaused) { + S_UnpauseSound(); + } +} + +/* +============== +S_ReLoad +============== +*/ +void S_ReLoad(soundsystemsavegame_t *pSave) +{ + int i; + bool bSoundWasUnpaused; + + bSoundWasUnpaused = !s_bSoundPaused; + if (!s_bSoundPaused) { + S_PauseSound(); + } + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + S_LoadBase(&pSave->Channels[i], openal.channel[i], bSoundWasUnpaused); + } + + if (bSoundWasUnpaused) { + S_UnpauseSound(); + } +} + +/* +============== +S_InitBase +============== +*/ +static void S_InitBase(channelbasesavegame_t *pBase) +{ + if (!pBase->bPlaying) { + return; + } + + if (strstr(pBase->sfx.szName, "null.wav")) { + return; + } + + SV_AddSvsTimeFixup(&pBase->iStartTime); + SV_AddSvsTimeFixup(&pBase->iEndTime); + SV_AddSvsTimeFixup(&pBase->iTime); +} + +/* +============== +S_LoadData +============== +*/ +void S_LoadData(soundsystemsavegame_t *pSave) +{ + int i; + + for (i = 0; i < MAX_SOUNDSYSTEM_POSITION_CHANNELS; i++) { + S_InitBase(&pSave->Channels[i]); + } +} + +/* +============== +openal_channel::set_velocity +============== +*/ +void openal_channel::set_velocity(float v0, float v1, float v2) +{ + qalSource3f(source, AL_VELOCITY, v0, v1, v2); + alDieIfError(); +} + +/* +============== +openal_channel::set_position +============== +*/ +void openal_channel::set_position(float v0, float v1, float v2) +{ + qalSource3f(source, AL_POSITION, v0, v1, v2); + alDieIfError(); +} + +/* +============== +openal_channel::set_gain +============== +*/ +void openal_channel::set_gain(float gain) +{ + qalSourcef(source, AL_GAIN, gain); + alDieIfError(); +} + +/* +============== +openal_channel::set_no_3d +============== +*/ +void openal_channel::set_no_3d() +{ + qalSource3f(source, AL_POSITION, 0, 0, 0); + alDieIfError(); + qalSource3f(source, AL_VELOCITY, 0, 0, 0); + alDieIfError(); + qalSourcei(source, AL_SOURCE_RELATIVE, true); + alDieIfError(); + qalSourcei(source, AL_LOOPING, false); + alDieIfError(); + qalSourcei(source, AL_ROLLOFF_FACTOR, 0); + alDieIfError(); + qalSourcef(source, AL_GAIN, S_GetBaseVolume()); + alDieIfError(); +} + +/* +============== +openal_channel::set_3d +============== +*/ +void openal_channel::set_3d() +{ + qalSourcei(source, AL_SOURCE_RELATIVE, false); + alDieIfError(); + qalSourcei(source, AL_LOOPING, false); + alDieIfError(); + qalSourcef(source, AL_ROLLOFF_FACTOR, 1.0f); + alDieIfError(); + qalSourcef(source, AL_GAIN, S_GetBaseVolume()); + alDieIfError(); + qalSourcei(source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE_CLAMPED); + alDieIfError(); + // + // Added in OPM + // + if (fMinDist > 0) { + qalSourcef(source, AL_REFERENCE_DISTANCE, fMinDist); + alDieIfError(); + } + if (fMaxDist > 0) { + qalSourcef(source, AL_MAX_DISTANCE, fMaxDist); + alDieIfError(); + } +} + +/* +============== +openal_channel::play +============== +*/ +void openal_channel::play() +{ + qalSourcePlay(source); + alDieIfError(); +} + +/* +============== +openal_channel::set_no_virtualization +============== +*/ +void openal_channel::set_no_virtualization() +{ +#if AL_SOFT_direct_channels_remix + qalSourcei(source, AL_DIRECT_CHANNELS_SOFT, AL_REMIX_UNMATCHED_SOFT); + alDieIfError(); +#elif AL_SOFT_direct_channels + qalSourcei(source, AL_DIRECT_CHANNELS_SOFT, AL_TRUE); + alDieIfError(); +#endif +} + +/* +============== +openal_channel::set_virtualization +============== +*/ +void openal_channel::set_virtualization() +{ +#if AL_SOFT_direct_channels_remix || AL_SOFT_direct_channels + qalSourcei(source, AL_DIRECT_CHANNELS_SOFT, AL_FALSE); + alDieIfError(); +#endif +} + +/* +============== +openal_channel::pause +============== +*/ +void openal_channel::pause() +{ + qalSourcePause(source); + alDieIfError(); +} + +/* +============== +openal_channel::stop +============== +*/ +void openal_channel::stop() +{ + qalSourceStop(source); + alDieIfError(); +} + +/* +============== +openal_channel::is_free +============== +*/ +bool openal_channel::is_free() +{ + ALint state = sample_status(); + + return state == AL_INITIAL || state == AL_STOPPED; +} + +/* +============== +openal_channel::is_paused +============== +*/ +bool openal_channel::is_paused() +{ + ALint state = sample_status(); + + return state == AL_PAUSED; +} + +/* +============== +openal_channel::is_playing +============== +*/ +bool openal_channel::is_playing() +{ + ALint state = sample_status(); + + return state == AL_PLAYING; +} + +/* +============== +openal_channel::force_free +============== +*/ +void openal_channel::force_free() +{ + stop(); + iFlags = 0; +} + +/* +============== +openal_channel::set_sfx +============== +*/ +bool openal_channel::set_sfx(sfx_t *pSfx) +{ + ALint freq = 0; + + assert(pSfx->length); + + this->pSfx = pSfx; + if (!pSfx->buffer || !qalIsBuffer(pSfx->buffer)) { + if (pSfx->iFlags & SFX_FLAG_MP3) { + qalGenBuffers(1, &pSfx->buffer); + alDieIfError(); + + if (!S_OPENAL_LoadMP3_Codec(pSfx->name, pSfx)) { + qalDeleteBuffers(1, &pSfx->buffer); + alDieIfError(); + + Com_DPrintf("OpenAL: Failed to load MP3.\n"); + return false; + } + + alDieIfError(); + } else { + ALenum fmt = S_OPENAL_Format(pSfx->info.width, pSfx->info.channels); + + if (!fmt) { + Com_Printf( + "OpenAL: Bad Wave file (%d channels, %d bits) [%s].\n", + pSfx->info.channels, + (int)(pSfx->info.width * 8), + pSfx->name + ); + return false; + } + + if (pSfx->info.dataalign > 1 && !soft_block_align) { + Com_DPrintf( + "OpenAL: Alignment specified but AL doesn't support block alignment (%d).", pSfx->info.dataalign + ); + return false; + } + + qalGenBuffers(1, &pSfx->buffer); + alDieIfError(); + +#if AL_SOFT_block_alignment + if (pSfx->info.dataalign > 1) { + qalBufferi(pSfx->buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, pSfx->info.dataalign); + alDieIfError(); + } +#endif + + qalBufferData( + pSfx->buffer, + fmt, + &pSfx->data[pSfx->info.dataofs], + pSfx->info.datasize - pSfx->info.dataofs, + pSfx->info.rate + ); + alDieIfError(); + } + } + + qalSourceStop(source); + alDieIfError(); + + qalSourcei(source, AL_BUFFER, pSfx->buffer); + alDieIfError(); + + qalSourcef(source, AL_PITCH, 1.0); + alDieIfError(); + + // Get the base frequency + qalGetBufferi(pSfx->buffer, AL_FREQUENCY, &freq); + alDieIfError(); + + iBaseRate = freq; + + return true; +} + +/* +============== +openal_channel::start_sample +============== +*/ +void openal_channel::start_sample() +{ + play(); +} + +/* +============== +openal_channel::stop_sample +============== +*/ +void openal_channel::stop_sample() +{ + pause(); +} + +/* +============== +openal_channel::resume_sample +============== +*/ +void openal_channel::resume_sample() +{ + play(); +} + +/* +============== +openal_channel::end_sample +============== +*/ +void openal_channel::end_sample() +{ + stop(); +} + +/* +============== +openal_channel::set_sample_pan +============== +*/ +void openal_channel::set_sample_pan(S32 pan) +{ + const float panning = (pan - 64) / 127.f; + const ALfloat sourcePosition[3] = {panning, 0, sqrtf(1.f - Square(panning))}; + + qalSourcef(source, AL_ROLLOFF_FACTOR, 0); + qalSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); + qalSourcefv(source, AL_POSITION, sourcePosition); +} + +/* +============== +openal_channel::set_sample_playback_rate +============== +*/ +void openal_channel::set_sample_playback_rate(S32 rate) +{ + // Fixed in OPM + // Set the pitch in OpenAL + qalSourcef(source, AL_PITCH, rate / (float)iBaseRate); + alDieIfError(); +} + +/* +============== +openal_channel::sample_playback_rate +============== +*/ +S32 openal_channel::sample_playback_rate() +{ + float pitch = 1; + ALint freq = 0; + + // Fixed in OPM + // The sample rate varies according to the pitch + qalGetSourcef(source, AL_PITCH, &pitch); + alDieIfError(); + + return buffer_frequency() * pitch; +} + +/* +============== +openal_channel::buffer_frequency +============== +*/ +U32 openal_channel::buffer_frequency() const +{ + ALint freq = 0; + + if (buffer) { + qalGetBufferi(buffer, AL_FREQUENCY, &freq); + alDieIfError(); + } else if (pSfx) { + qalGetBufferi(pSfx->buffer, AL_FREQUENCY, &freq); + alDieIfError(); + } else { + freq = 22050; + } + + return freq; +} + +/* +============== +openal_channel::sample_volume +============== +*/ +S32 openal_channel::sample_volume() +{ + ALfloat gain = 0; + + qalGetSourcef(source, AL_GAIN, &gain); + alDieIfError(); + + return (gain / S_GetBaseVolume()) * 100; +} + +/* +============== +openal_channel::sample_offset +============== +*/ +U32 openal_channel::sample_offset() +{ + ALint offset = 0; + + qalGetSourcei(source, AL_SAMPLE_OFFSET, &offset); + alDieIfError(); + + return offset; +} + +/* +============== +openal_channel::sample_ms_offset +============== +*/ +U32 openal_channel::sample_ms_offset() +{ + if (!is_playing()) { + return 0; + } + + return sample_offset() * 1000ull / sample_playback_rate(); +} + +/* +============== +openal_channel::sample_loop_count +============== +*/ +U32 openal_channel::sample_loop_count() +{ + ALuint queued; + ALuint processed; + S32 left; + + qalGetSourceiv(source, AL_BUFFERS_QUEUED, (ALint *)&queued); + alDieIfError(); + qalGetSourcei(source, AL_BUFFERS_PROCESSED, (ALint *)&processed); + alDieIfError(); + + left = queued + ~processed; + if (left < 0) { + left = 0; + } + return left; +} + +/* +============== +openal_channel::set_sample_offset +============== +*/ +void openal_channel::set_sample_offset(U32 offset) +{ + qalSourcei(source, AL_SAMPLE_OFFSET, offset); + alDieIfError(); +} + +/* +============== +openal_channel::set_sample_ms_offset +============== +*/ +void openal_channel::set_sample_ms_offset(U32 offset) +{ + set_sample_offset(offset * sample_playback_rate() / 1000); +} + +/* +============== +openal_channel::set_sample_loop_count +============== +*/ +void openal_channel::set_sample_loop_count(S32 count) +{ + ALuint processed = 0; + + stop(); + + qalGetSourceiv(source, AL_BUFFERS_PROCESSED, (ALint *)&processed); + alDieIfError(); + + for (ALuint i = 0; i < processed; i++) { + ALuint bufName; + + qalSourceUnqueueBuffers(source, 1, &bufName); + alDieIfError(); + } + + if (buffer) { + for (S32 i = 0; i < count; i++) { + qalSourceQueueBuffers(source, 1, &buffer); + alDieIfError(); + } + } + + if (count == 0) { + qalSourcei(source, AL_LOOPING, true); + alDieIfError(); + } else { + qalSourcei(source, AL_LOOPING, false); + alDieIfError(); + } +} + +/* +============== +openal_channel::set_sample_loop_block +============== +*/ +void openal_channel::set_sample_loop_block(S32 start_offset, S32 end_offset) +{ + // FIXME: unimplemented + STUB_DESC("sample_loop_block"); +} + +/* +============== +openal_channel::sample_status +============== +*/ +U32 openal_channel::sample_status() +{ + ALint retval; + + qalGetSourcei(source, AL_SOURCE_STATE, &retval); + alDieIfError(); + + return retval; +} + +/* +============== +MUSIC_LoadSoundtrackFile +============== +*/ +qboolean MUSIC_LoadSoundtrackFile(const char *filename) +{ + song_t *psong = NULL; + char args[MAX_MUSIC_SONGS][MAX_RES_NAME]; + int numargs; + char com_token[MAX_STRING_CHARS]; + char alias[128]; + char file[128]; + char load_path[128]; + char *buffer; + char path[MAX_RES_NAME]; + int i; + byte *data; + + if (strrchr(filename, '.')) { + Com_sprintf(path, sizeof(path), "%s", filename); + } else { + Com_sprintf(path, sizeof(path), "%s.mus", filename); + } + + music_numsongs = 0; + + FS_ReadFile(path, (void **)&data); + if (!data) { + Com_DPrintf("OpenAL: Couldn't load %s\n", path); + return false; + } + Com_DPrintf("SOUNDTRACK: Loading %s\n", path); + + MUSIC_StopAllSongs(); + + buffer = (char *)data; + load_path[0] = 0; + + while (1) { + Q_strncpyz(com_token, COM_GetToken(&buffer, true), sizeof(com_token)); + if (!com_token[0]) { + break; + } + + if (strlen(com_token) >= MAX_RES_NAME) { + Com_Printf("MUSIC_LoadSoundtrackFile: argument too long, truncating in %s\n", path); + com_token[MAX_RES_NAME - 1] = 0; + } + + numargs = 1; + Q_strncpyz(args[0], com_token, sizeof(args[0])); + + while (1) { + Q_strncpyz(com_token, COM_GetToken(&buffer, false), sizeof(com_token)); + if (!com_token[0]) { + break; + } + + if (strlen(com_token) >= MAX_RES_NAME) { + Com_Printf("MUSIC_LoadSoundtrackFile: argument too long, truncating in %s\n", path); + com_token[MAX_RES_NAME - 1] = 0; + } + + Q_strncpyz(args[numargs], com_token, sizeof(args[numargs])); + numargs++; + } + + if (!Q_stricmp(args[0], "path")) { + Q_strncpyz(load_path, args[1], sizeof(load_path)); + if (load_path[strlen(load_path) - 1] != '/' && load_path[strlen(load_path) - 1] != '\\') { + Q_strcat(load_path, sizeof(load_path), "/"); + } + } else if (args[0][0] == '!') { + for (i = 0; i < music_numsongs; i++) { + psong = &music_songs[i]; + if (!Q_stricmp(psong->alias, &args[0][1])) { + break; + } + } + + if (i == music_numsongs) { + Com_Printf("MUSIC_LoadSoundtrackFile: song %s not found, command skipped in %s.\n", &args[0][1], path); + continue; + } + + if (!Q_stricmp(args[1], "volume")) { + psong->volume = atof(args[2]); + } else if (!Q_stricmp(args[1], "fadetime")) { + psong->fadetime = atof(args[2]); + } else if (!Q_stricmp(args[1], "loop")) { + psong->flags |= 1; + } else if (!Q_stricmp(args[1], "restart")) { + psong->flags |= 2; + } else if (!Q_stricmp(args[1], "interrupt")) { + psong->fadetime = 0; + psong->flags |= 4 | 2; + } else { + Com_Printf( + "MUSIC_LoadSoundtrackFile: unknown command %s for song %s in %s.\n", args[1], &args[0][1], path + ); + } + } else { + if (numargs > 1) { + Q_strncpyz(alias, args[0], sizeof(alias)); + Q_strncpyz(file, load_path, sizeof(file)); + Q_strcat(file, sizeof(file), args[1]); + } else { + size_t len; + + Q_strncpyz(file, load_path, sizeof(file)); + Q_strcat(file, sizeof(file), args[1]); + + len = strlen(args[0]); + if (len >= 4) { + Q_strncpyz(alias, args[0], len - 4); + } else { + alias[0] = 0; + } + } + + if (music_numsongs >= MAX_MUSIC_SONGS) { + Com_Printf("MUSIC_LoadSoundtrackFile: Too many songs in %s, skipping %s.\n", path, alias); + continue; + } + + psong = &music_songs[music_numsongs]; + Q_strncpyz(psong->alias, alias, sizeof(psong->alias)); + Q_strncpyz(psong->path, file, sizeof(psong->path)); + music_songs[music_numsongs].fadetime = 1.0; + music_songs[music_numsongs].volume = 1.0; + music_songs[music_numsongs].flags = 0; + music_songs[music_numsongs].current_pos = 0; + music_songs[music_numsongs].mood_num = MusicMood_NameToNum(alias); + music_numsongs++; + } + } + + if (!music_numsongs) { + Com_Printf("MUSIC_LoadSoundtrackFile: could not load %s, no songs defined.\n", path); + FS_FreeFile(data); + return false; + } + + music_currentsong = -1; + FS_FreeFile(data); + + if (music_current_mood == mood_none) { + MUSIC_UpdateMood(mood_normal, mood_normal); + } + + return true; +} + +/* +============== +MUSIC_SongValid +============== +*/ +qboolean MUSIC_SongValid(const char *mood) +{ + return MUSIC_FindSong(mood) != -1; +} + +/* +============== +MUSIC_Loaded +============== +*/ +qboolean MUSIC_Loaded() +{ + return music_loaded; +} + +/* +============== +Music_Update +============== +*/ +void Music_Update() +{ + int currentsong; + + if (!s_bSoundStarted) { + return; + } + + if (!music_active) { + return; + } + + if (s_bSoundPaused) { + return; + } + + MUSIC_CheckForStoppedSongs(); + + if (!MUSIC_Loaded() && music_active && strlen(current_soundtrack)) { + MUSIC_LoadSoundtrackFile(current_soundtrack); + music_loaded = true; + } + + if (music_currentsong >= 0) { + currentsong = music_songs[music_currentsong].mood_num; + } else { + currentsong = -1; + } + + if (music_current_mood == mood_none) { + if (MUSIC_Playing()) { + MUSIC_StopAllSongs(); + } + } else if (music_current_mood != currentsong) { + const char *mood = MusicMood_NumToName(music_current_mood); + if (MUSIC_SongValid(mood) && MUSIC_Loaded() && strlen(current_soundtrack)) { + Com_DebugPrintf("Playing %s.\n", mood); + MUSIC_PlaySong(mood); + } + } + + if (new_music_volume != music_volume) { + if (music_volume_fade_time > 0) { + if (music_volume_direction == 0) { + music_volume = (cls.realtime - music_volume_start_time) * (new_music_volume - old_music_volume) + / (music_volume_fade_time * 1000.f) + + old_music_volume; + + if (music_volume > new_music_volume) { + music_volume = new_music_volume; + music_volume_changed = 1; + } else { + music_volume_changed = 1; + } + } else if (music_volume_direction == 1) { + music_volume = 1.0 + - (cls.realtime - music_volume_start_time) * (old_music_volume - new_music_volume) + / (music_volume_fade_time * 1000.f); + + if (music_volume >= new_music_volume) { + music_volume_changed = true; + } else { + music_volume = new_music_volume; + music_volume_changed = true; + } + } else { + music_volume_changed = true; + } + } else { + music_volume = new_music_volume; + music_volume_changed = true; + } + } + + MUSIC_UpdateMusicVolumes(); +} + +/* +============== +MUSIC_SongEnded +============== +*/ +void MUSIC_SongEnded() +{ + Com_DPrintf( + "MUSIC: Song ended, changing from [ %s ] to [ %s ]\n", + MusicMood_NumToName(music_current_mood), + MusicMood_NumToName(music_fallback_mood) + ); + music_current_mood = music_fallback_mood; +} + +/* +============== +MUSIC_NewSoundtrack +============== +*/ +void MUSIC_NewSoundtrack(const char *name) +{ + if (!s_bSoundStarted) { + return; + } + + if (!Q_stricmp(name, current_soundtrack)) { + return; + } + + // Fixed in OPM + // Make sure to not get past the end of the buffer + //strcpy(current_soundtrack, name); + Q_strncpyz(current_soundtrack, name, sizeof(current_soundtrack)); + + if (!Q_stricmp(current_soundtrack, "none") || !Q_stricmp(current_soundtrack, "")) { + music_active = qfalse; + if (MUSIC_Playing()) { + MUSIC_StopAllSongs(); + } + } else { + music_active = qtrue; + MUSIC_LoadSoundtrackFile(name); + music_loaded = qtrue; + } +} + +/* +============== +MUSIC_UpdateMood +============== +*/ +void MUSIC_UpdateMood(int current, int fallback) +{ + static int last_current_mood = -1; + static int last_fallback_mood = -1; + static int current_mood = -1; + static int fallback_mood = -1; + qboolean was_action; + + if (current == current_mood && fallback == fallback_mood) { + return; + } + + was_action = current == last_current_mood && fallback == last_fallback_mood && current_mood == mood_action; + last_current_mood = current_mood; + last_fallback_mood = fallback_mood; + current_mood = current; + music_current_mood = current; + fallback_mood = fallback; + music_fallback_mood = fallback; + music_active = qtrue; + + Com_DPrintf( + "MUSIC: changing from [ %s | %s ] to [ %s | %s ]\n", + MusicMood_NumToName(last_current_mood), + MusicMood_NumToName(last_fallback_mood), + MusicMood_NumToName(current_mood), + MusicMood_NumToName(fallback) + ); + + if (was_action) { + int songnum = MUSIC_FindSong(MusicMood_NumToName(current_mood)); + + if (songnum != -1 && (music_songs[songnum].flags & 4)) { + Com_DPrintf( + "MUSIC: restoring music from action state, skipping [ %s ] for [ %s ]\n", + MusicMood_NumToName(current_mood), + MusicMood_NumToName(fallback_mood) + ); + music_current_mood = music_fallback_mood; + } + } +} + +/* +============== +MUSIC_UpdateVolume +============== +*/ +void MUSIC_UpdateVolume(float volume, float fade_time) +{ + if (new_music_volume == volume && music_volume_fade_time == fade_time) { + return; + } + + old_music_volume = music_volume; + new_music_volume = volume; + music_volume_fade_time = fade_time; + music_volume_start_time = cls.realtime; + + if (volume > music_volume) { + music_volume_direction = 0; + } else if (volume < music_volume) { + music_volume_direction = 1; + } +} + +/* +============== +MUSIC_StopAllSongs +============== +*/ +void MUSIC_StopAllSongs() +{ + for (int i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + MUSIC_StopChannel(i); + } + + music_currentsong = -1; +} + +/* +============== +MUSIC_FreeAllSongs +============== +*/ +void MUSIC_FreeAllSongs() +{ + MUSIC_StopAllSongs(); + MUSIC_UpdateMood(mood_none, mood_none); + current_soundtrack[0] = 0; + music_loaded = false; + + // Added in OPM + // Clear the list of songs so the songs from previous maps + // won't get played + music_numsongs = 0; +} + +/* +============== +MUSIC_Playing +============== +*/ +qboolean MUSIC_Playing() +{ + return MUSIC_CurrentSongChannel() != -1; +} + +/* +============== +MUSIC_FindSong +============== +*/ +int MUSIC_FindSong(const char *name) +{ + int i; + + for (i = 0; i < music_numsongs; i++) { + if (!Q_stricmp(music_songs[i].alias, name)) { + return i; + } + } + + return -1; +} + +/* +============== +S_loadsoundtrack +============== +*/ +void S_loadsoundtrack() +{ + if (Cmd_Argc() != 2) { + Com_Printf("loadsoundtrack \n"); + return; + } + + MUSIC_LoadSoundtrackFile(Cmd_Argv(1)); + music_loaded = true; + Q_strncpyz(current_soundtrack, Cmd_Argv(1), sizeof(current_soundtrack)); +} + +/* +============== +S_CurrentSoundtrack +============== +*/ +const char *S_CurrentSoundtrack() +{ + return current_soundtrack; +} + +/* +============== +S_PlaySong +============== +*/ +void S_PlaySong() +{ + if (Cmd_Argc() != 2) { + Com_Printf("playsong \n"); + return; + } + + MUSIC_PlaySong(Cmd_Argv(1)); + music_active = true; +} + +/* +============== +MUSIC_CurrentSongChannel +============== +*/ +int MUSIC_CurrentSongChannel() +{ + int channel_number = -1; + int ch_idx = 0; + + for (ch_idx = 0; ch_idx < MAX_SOUNDSYSTEM_SONGS; ch_idx++) { + if (openal.chan_song[ch_idx].is_playing() && openal.chan_song[ch_idx].song_number == music_currentsong) { + channel_number = ch_idx; + } + } + + return channel_number; +} + +/* +============== +MUSIC_StopChannel +============== +*/ +void MUSIC_StopChannel(int channel_number) +{ + openal_channel *channel = &openal.chan_song[channel_number]; + + channel->pause(); + if (music_songs[channel->song_number].flags & 2) { + music_songs[channel->song_number].current_pos = 0; + } else { + music_songs[channel->song_number].current_pos = channel->sample_ms_offset(); + } + + channel->stop(); +} + +/* +============== +MUSIC_PlaySong +============== +*/ +qboolean MUSIC_PlaySong(const char *alias) +{ + int channel_number; + song_t *song; + int songnum; + int channel_to_play_on; + int fading_song; + openal_channel_two_d_stream *song_channel; + unsigned int loop_start; + int rate; + + fading_song = 0; + songnum = MUSIC_FindSong(alias); + + if (songnum == -1) { + return true; + } + + song = &music_songs[songnum]; + + if (MUSIC_Playing() && songnum == music_currentsong) { + return true; + } + + channel_number = MUSIC_CurrentSongChannel(); + music_currentsong = songnum; + + if (channel_number != -1) { + if (song->flags & 4) { + MUSIC_StopChannel(channel_number); + } else { + song_channel = &openal.chan_song[channel_number]; + song_channel->fading = FADE_OUT; + song_channel->fade_time = (int)song->fadetime; + song_channel->fade_start_time = cls.realtime; + fading_song = true; + } + } + channel_to_play_on = (fading_song != 0) && (channel_number == 0); + song_channel = &openal.chan_song[channel_to_play_on]; + + if (song_channel->is_playing() || song_channel->is_paused()) { + MUSIC_StopChannel(channel_to_play_on); + } + + if (!song_channel->queue_stream(song->path)) { + Com_DPrintf("Could not start music file '%s'!", song->path); + return false; + } + + rate = song_channel->sample_playback_rate(); + + song_channel->song_number = songnum; + if (song->current_pos) { + song_channel->set_sample_ms_offset(song->current_pos); + } else { + song_channel->set_sample_offset(rate * 0.063f); + } + + if (song->flags & 1) { + song_channel->set_sample_loop_count(0); + song_channel->set_sample_loop_block(rate * 0.063f, -1); + } else { + song_channel->set_sample_loop_count(1); + } + + if (fading_song) { + song_channel->fading = FADE_IN; + song_channel->fade_time = (int)song->fadetime; + song_channel->set_gain(0.0); + song_channel->fade_start_time = cls.realtime; + } else { + song_channel->fading = FADE_NONE; + song_channel->set_gain(S_GetBaseVolume() * (song->volume * s_ambientVolume->value) * s_fVolumeGain); + } + + song_channel->play(); + + return true; +} + +/* +============== +MUSIC_UpdateMusicVolumes +============== +*/ +void MUSIC_UpdateMusicVolumes() +{ + int i; + unsigned int current_time; + float new_volume, max_volume; + + if (s_ambientVolume->modified || music_volume_changed) { + s_ambientVolume->modified = false; + + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + if (!openal.chan_song[i].is_playing() && !openal.chan_song[i].is_paused()) { + continue; + } + + if (openal.chan_song[i].fading != FADE_NONE) { + continue; + } + + openal.chan_song[i].set_gain( + S_GetBaseVolume() * (music_songs[openal.chan_song[i].song_number].volume * s_ambientVolume->value) + * s_fVolumeGain * music_volume + ); + } + } + + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + if (!openal.chan_song[i].is_playing() && !openal.chan_song[i].is_paused()) { + continue; + } + + switch (openal.chan_song[i].fading) { + case fade_t::FADE_IN: + max_volume = music_songs[openal.chan_song[i].song_number].volume * s_ambientVolume->value; + new_volume = (unsigned int)(cls.realtime - openal.chan_song[i].fade_start_time) + / (openal.chan_song[i].fade_time * 1000.f) * max_volume; + + if (new_volume > max_volume) { + openal.chan_song[i].set_gain(S_GetBaseVolume() * (max_volume * s_fVolumeGain * music_volume)); + openal.chan_song[i].fading = FADE_NONE; + } else { + openal.chan_song[i].set_gain(S_GetBaseVolume() * (new_volume * s_fVolumeGain * music_volume)); + } + break; + case fade_t::FADE_OUT: + max_volume = music_songs[openal.chan_song[i].song_number].volume * s_ambientVolume->value; + new_volume = (unsigned int)(cls.realtime - openal.chan_song[i].fade_start_time) + / (openal.chan_song[i].fade_time * 1000.f) * max_volume; + + if (new_volume > 0) { + openal.chan_song[i].set_gain(S_GetBaseVolume() * (new_volume * s_fVolumeGain * music_volume)); + } else { + MUSIC_StopChannel(i); + } + break; + default: + break; + } + } + + if (s_musicVolume->modified || music_volume_changed) { + s_musicVolume->modified = false; + if (openal.chan_trig_music.is_playing() || openal.chan_trig_music.is_paused()) { + openal.chan_trig_music.set_gain( + S_GetBaseVolume() * (openal.chan_trig_music.fVolume * s_musicVolume->value) * s_fVolumeGain + ); + } + } + + music_volume_changed = false; +} + +/* +============== +MUSIC_CheckForStoppedSongs +============== +*/ +void MUSIC_CheckForStoppedSongs() +{ + int i; + + for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) { + if (!openal.chan_song[i].is_playing()) { + continue; + } + + if (openal.chan_song[i].sample_loop_count()) { + continue; + } + + MUSIC_FindSong(MusicMood_NumToName(music_fallback_mood)); + if (!openal.chan_song[i].is_playing() && !openal.chan_song[i].is_paused()) { + MUSIC_SongEnded(); + } + } +} + +/* +============== +S_TriggeredMusic_SetupHandle +============== +*/ +void S_TriggeredMusic_SetupHandle(const char *pszName, int iLoopCount, int iOffset, qboolean autostart) +{ + char *pszFilename; + const char *pszRealName; + float fVolume = 1.0; + AliasListNode_t *pSoundAlias = NULL; + void *stream = NULL; + + if (!s_bSoundStarted) { + return; + } + + if (openal.chan_trig_music.is_playing() || openal.chan_trig_music.is_paused()) { + Com_DPrintf("Didn't start new triggered music because some was already playing\n"); + return; + } + + openal.chan_trig_music.stop(); + // Fixed in OPM + // Use strncpy instead + //strcpy(openal.tm_filename, pszName); + Q_strncpyz(openal.tm_filename, pszName, sizeof(openal.tm_filename)); + + openal.tm_loopcount = iLoopCount; + openal.chan_trig_music.set_sample_loop_count(iLoopCount); + pszRealName = Alias_FindRandom(pszName, &pSoundAlias); + + if (!pszRealName) { + pszRealName = pszName; + } else if (pSoundAlias) { + fVolume = random() * pSoundAlias->volumeMod + pSoundAlias->volume; + } + + pszFilename = FS_BuildOSPath(Cvar_VariableString("fs_basepath"), FS_Gamedir(), pszRealName); + + if (!openal.chan_trig_music.queue_stream(pszRealName)) { + S_OPENAL_InitChannel(SOUNDSYSTEM_CHANNEL_TRIGGER_MUSIC_ID, &openal.chan_trig_music); + Com_DPrintf("Could not start triggered music '%s'\n", pszName); + return; + } + + openal.chan_trig_music.fVolume = fVolume; + openal.chan_trig_music.set_gain(S_GetBaseVolume() * (fVolume * s_musicVolume->value) * s_fVolumeGain); + openal.chan_trig_music.set_sample_loop_count(iLoopCount); + openal.chan_trig_music.set_sample_offset(iOffset); + + // Fixed in OPM + // Play the sound then pause it immediately + // So it can be unpaused upon loading from save + openal.chan_trig_music.play(); + + if (!autostart) { + openal.chan_trig_music.pause(); + } +} + +/* +============== +S_TriggeredMusic_Start +============== +*/ +void S_TriggeredMusic_Start() +{ + if (Cmd_Argc() != 2) { + Com_Printf("tmstart \n"); + return; + } + + S_TriggeredMusic_SetupHandle(Cmd_Argv(1), 1, 0, true); +} + +/* +============== +S_TriggeredMusic_StartLoop +============== +*/ +void S_TriggeredMusic_StartLoop() +{ + if (Cmd_Argc() != 2) { + Com_Printf("tmstartloop \n"); + return; + } + + S_TriggeredMusic_SetupHandle(Cmd_Argv(1), 0, 0, true); +} + +/* +============== +S_TriggeredMusic_Stop +============== +*/ +void S_TriggeredMusic_Stop() +{ + if (!s_bSoundStarted) { + return; + } + + openal.chan_trig_music.stop(); + // Fixed in OPM + // Make sure to clear the triggered music in case snd_restart is called + openal.tm_filename[0] = 0; + openal.tm_loopcount = 0; +} + +/* +============== +S_TriggeredMusic_Volume + +Added in 2.0 +============== +*/ +void S_TriggeredMusic_Volume() +{ + if (!s_bSoundStarted) { + return; + } + + if (Cmd_Argc() != 2) { + Com_Printf("tmvolume <0-1>\n\n"); + return; + } + + openal.chan_trig_music.fVolume = atof(Cmd_Argv(1)); + music_volume_changed = true; +} + +/* +============== +S_TriggeredMusic_Pause +============== +*/ +void S_TriggeredMusic_Pause() +{ + if (!s_bSoundStarted) { + return; + } + + if (openal.chan_trig_music.is_playing()) { + openal.chan_trig_music.pause(); + } +} + +/* +============== +S_TriggeredMusic_Unpause +============== +*/ +void S_TriggeredMusic_Unpause() +{ + if (!s_bSoundStarted) { + return; + } + + if (openal.chan_trig_music.is_paused()) { + openal.chan_trig_music.play(); + } + + openal.chan_trig_music.set_gain( + S_GetBaseVolume() * (openal.chan_trig_music.fVolume * s_musicVolume->value) * s_fVolumeGain + ); +} + +/* +============== +S_TriggeredMusic_PlayIntroMusic +============== +*/ +void S_TriggeredMusic_PlayIntroMusic() +{ + S_TriggeredMusic_SetupHandle("sound/music/mus_MainTheme.mp3", 0, 0, true); +} + +/* +============== +S_StopMovieAudio +============== +*/ +void S_StopMovieAudio() +{ + openal.chan_movie.stop(); +} + +/* +============== +S_SetupMovieAudio +============== +*/ +void S_SetupMovieAudio(const char *pszMovieName) +{ + char filename[MAX_QPATH]; + + S_StopMovieAudio(); + + COM_StripExtension(pszMovieName, filename, sizeof(filename)); + Q_strcat(filename, sizeof(filename), ".mp3"); + + if (!openal.chan_movie.queue_stream(filename)) { + COM_StripExtension(pszMovieName, filename, sizeof(filename)); + Q_strcat(filename, sizeof(filename), ".wav"); + + if (!openal.chan_movie.queue_stream(filename)) { + Com_DPrintf("Can't find any matching audio file for movie: %s\n", pszMovieName); + return; + } + } + + openal.chan_movie.set_gain(S_GetBaseVolume() * 1.5f); + openal.chan_movie.play(); + + Com_DPrintf("Movie Audio setup: %s\n", filename); +} + +/* +============== +S_CurrentMoviePosition +============== +*/ +int S_CurrentMoviePosition() +{ + return openal.chan_movie.sample_ms_offset(); +} + +/* +================= +S_AL_Format +================= +*/ +static ALuint S_OPENAL_Format(float width, int channels) +{ + ALuint format = AL_FORMAT_MONO16; + + // Work out format + if (width == 1) { + if (channels == 1) { + format = AL_FORMAT_MONO8; + } else if (channels == 2) { + format = AL_FORMAT_STEREO8; + } + } else if (width == 2) { + if (channels == 1) { + format = AL_FORMAT_MONO16; + } else if (channels == 2) { + format = AL_FORMAT_STEREO16; + } + } else if (width == 0.5) { + if (ima4_ext && soft_block_align) { + if (channels == 1) { + format = AL_FORMAT_MONO_IMA4; + } else if (channels == 2) { + format = AL_FORMAT_STEREO_IMA4; + } + } else { + // unsupported + format = 0; + } + } + + return format; +} + +/* +============== +S_OPENAL_LoadMP3_Codec +============== +*/ +static bool S_OPENAL_LoadMP3_Codec(const char *_path, sfx_t *pSfx) +{ + void *data; + snd_info_t info; + ALuint format; + + // Try to load + data = S_CodecLoad(_path, &info); + if (!data) { + return false; + } + + format = S_OPENAL_Format(info.width, info.channels); + + // Create a buffer + qalGenBuffers(1, &pSfx->buffer); + alDieIfError(); + + // Fill the buffer + if (info.size == 0) { + // We have no data to buffer, so buffer silence + byte dummyData[2] = {0}; + + qalBufferData(pSfx->buffer, AL_FORMAT_MONO16, (void *)dummyData, 2, 22050); + } else { + qalBufferData(pSfx->buffer, format, data, info.size, info.rate); + } + + alDieIfError(); + + // Free the memory + Hunk_FreeTempMemory(data); + + return true; +} + +/* +============== +openal_channel::update +============== +*/ +void openal_channel::update() {} + +/* +============== +openal_channel_two_d_stream::stop +============== +*/ +void openal_channel_two_d_stream::stop() +{ + openal_channel::stop(); + + clear_stream(); +} + +/* +============== +openal_channel_two_d_stream::set_sfx +============== +*/ +bool openal_channel_two_d_stream::set_sfx(sfx_t *pSfx) +{ + snd_stream_t *stream; + unsigned int bytesToRead, bytesRead; + ALint freq = 0; + char rawData[MAX_BUFFER_SAMPLES * 2 * 2]; + + stop(); + + sampleLoopCount = 1; + + this->pSfx = pSfx; + Q_strncpyz(this->fileName, pSfx->name, sizeof(this->fileName)); + + streamHandle = S_CodecLoad(pSfx->name, NULL); + if (!streamHandle) { + Com_DPrintf("OpenAL: Failed to load sound file.\n"); + return false; + } + + stream = (snd_stream_t *)streamHandle; + pSfx->info.channels = stream->info.channels; + pSfx->info.dataofs = stream->info.dataofs; + pSfx->info.datasize = stream->info.size; + pSfx->info.rate = stream->info.rate; + pSfx->info.samples = stream->info.samples; + pSfx->info.width = stream->info.width; + + pSfx->info.format = S_OPENAL_Format(stream->info.width, stream->info.channels); + if (!pSfx->info.format) { + Com_DPrintf( + "OpenAL: Bad Wave file (%d channels, %d bits) [%s].\n", + pSfx->info.channels, + (int)(pSfx->info.width * 8.f), + pSfx->name + ); + + S_CodecCloseStream(stream); + return false; + } + + qalSourceStop(source); + alDieIfError(); + + qalGenBuffers(MAX_STREAM_BUFFERS, buffers); + alDieIfError(); + + // Read a smaller sample + bytesToRead = Q_min(MAX_BUFFER_SAMPLES * stream->info.width * stream->info.channels, sizeof(rawData)); + bytesRead = S_CodecReadStream(stream, bytesToRead, rawData); + streamNextOffset = bytesRead; + if (!bytesRead) { + // Valid stream but no data? + S_CodecCloseStream(stream); + return true; + } + +#if AL_SOFT_block_alignment + if (stream->info.dataalign > 1 && soft_block_align) { + qalBufferi(buffers[currentBuf], AL_UNPACK_BLOCK_ALIGNMENT_SOFT, stream->info.dataalign); + alDieIfError(); + } +#endif + + qalBufferData(buffers[currentBuf], pSfx->info.format, rawData, bytesRead, stream->info.rate); + alDieIfError(); + + qalSourceQueueBuffers(source, 1, &buffers[currentBuf]); + alDieIfError(); + + iBaseRate = stream->info.rate; + currentBuf = (currentBuf + 1) % MAX_STREAM_BUFFERS; + streaming = true; + + return true; +} + +/* +============== +openal_channel_two_d_stream::set_sample_loop_count +============== +*/ +void openal_channel_two_d_stream::set_sample_loop_count(S32 count) +{ + sampleLoopCount = count; + sampleLooped = 0; +} + +/* +============== +openal_channel_two_d_stream::openal_channel_two_d_stream +============== +*/ +openal_channel_two_d_stream::openal_channel_two_d_stream() +{ + int i; + + streamHandle = NULL; + for (i = 0; i < MAX_STREAM_BUFFERS; i++) { + buffers[i] = 0; + } + currentBuf = 0; + sampleLoopCount = 0; + sampleLooped = 0; + streamNextOffset = 0; + streaming = false; +} + +/* +============== +openal_channel_two_d_stream::openal_channel_two_d_stream +============== +*/ +openal_channel_two_d_stream::~openal_channel_two_d_stream() +{ + clear_stream(); +} + +/* +============== +openal_channel_two_d_stream::update +============== +*/ +void openal_channel_two_d_stream::update() +{ + snd_stream_t *stream = (snd_stream_t *)streamHandle; + unsigned int bytesToRead, bytesRead; + ALuint format; + ALint numProcessedBuffers = 0, numQueuedBuffers = 0; + ALint state = sample_status(); + // 2 channels with a width of 2 + char rawData[MAX_BUFFER_SAMPLES * 2 * 2]; + + if (!streaming || is_paused() || state == AL_INITIAL) { + return; + } + + qalGetSourcei(source, AL_BUFFERS_PROCESSED, &numProcessedBuffers); + alDieIfError(); + + qalGetSourcei(source, AL_BUFFERS_QUEUED, &numQueuedBuffers); + alDieIfError(); + + // Remove processed buffers after half of the queued buffers has been processed + if (numProcessedBuffers >= Q_max(numQueuedBuffers / 2, 1)) { + while (numProcessedBuffers-- > 0) { + ALuint tmpBuffer; + qalSourceUnqueueBuffers(source, 1, &tmpBuffer); + } + } + + if (numQueuedBuffers >= MAX_STREAM_BUFFERS) { + return; + } + + if (sampleLoopCount && sampleLooped >= sampleLoopCount) { + if (!is_playing()) { + // Can clear the stream + clear_stream(); + } + return; + } + + bytesToRead = Q_min(MAX_BUFFER_SAMPLES * stream->info.width * stream->info.channels, sizeof(rawData)); + + format = S_OPENAL_Format(stream->info.width, stream->info.channels); + + bytesRead = S_CodecReadStream(stream, bytesToRead, rawData); + streamNextOffset += bytesRead; + if (!bytesRead) { + S_CodecCloseStream(stream); + + sampleLooped++; + if (sampleLoopCount && sampleLooped >= sampleLoopCount) { + // Finished the last loop + streamHandle = NULL; + return; + } + + // + // Looped, start again from the beginning + // + streamHandle = S_CodecLoad(this->fileName, NULL); + if (!streamHandle) { + clear_stream(); + return; + } + + stream = (snd_stream_t *)streamHandle; + // + // Re-read the format, we never know... + // + format = S_OPENAL_Format(stream->info.width, stream->info.channels); + + bytesRead = S_CodecReadStream(stream, bytesToRead, rawData); + streamNextOffset = bytesRead; + if (!bytesRead) { + S_CodecCloseStream(stream); + streamHandle = NULL; + return; + } + } + +#if AL_SOFT_block_alignment + if (stream->info.dataalign > 1 && soft_block_align) { + qalBufferi(buffers[currentBuf], AL_UNPACK_BLOCK_ALIGNMENT_SOFT, stream->info.dataalign); + alDieIfError(); + } +#endif + + qalBufferData(buffers[currentBuf], format, rawData, bytesRead, stream->info.rate); + alDieIfError(); + + qalSourceQueueBuffers(source, 1, &buffers[currentBuf]); + alDieIfError(); + + if (!is_playing()) { + // The sample has stopped during stream + // Could be because the storage is slow enough for the buffer + // or because the storage was powering on after standby + play(); + } + + currentBuf = (currentBuf + 1) % MAX_STREAM_BUFFERS; +} + +/* +============== +openal_channel_two_d_stream::sample_offset +============== +*/ +U32 openal_channel_two_d_stream::sample_offset() +{ + snd_stream_t *stream = (snd_stream_t *)streamHandle; + ALint playerByteOffset = 0; + ALint numProcessedBuffers = 0; + ALint numQueuedBuffers = 0; + unsigned int totalQueueLength = 0; + unsigned int bitsPerSample = 0; + unsigned int offset = 0; + ALint bits = 0, channels = 0; + + if (!streaming) { + // no stream + return 0; + } + + // Get the byte offset in the queue + qalGetSourcei(source, AL_BYTE_OFFSET, &playerByteOffset); + alDieIfError(); + + totalQueueLength = getQueueLength(); + bitsPerSample = getBitsPerSample(); + + assert(playerByteOffset < totalQueueLength); + assert(streamNextOffset >= totalQueueLength || stream); + + if (streamNextOffset >= totalQueueLength) { + offset = streamNextOffset - totalQueueLength + playerByteOffset; + } else if (stream) { + // it probably means the sound is looped and will restart from the beginning + if (streamNextOffset + playerByteOffset <= totalQueueLength) { + // near the end of the stream + if (stream->info.size > totalQueueLength) { + offset = stream->info.size + streamNextOffset - totalQueueLength + playerByteOffset; + } else { + // the buffer is really small + offset = (streamNextOffset - totalQueueLength + playerByteOffset) % stream->info.size; + } + } else { + // it is past end of stream + // so, start from the beginning of the stream + offset = streamNextOffset + playerByteOffset - totalQueueLength; + } + + assert(offset < stream->info.size); + } else { + offset = totalQueueLength - streamNextOffset + playerByteOffset; + } + + return offset * 8 / bitsPerSample; +} + +/* +============== +openal_channel_two_d_stream::buffer_frequency +============== +*/ +U32 openal_channel_two_d_stream::buffer_frequency() const +{ + unsigned int bufferId; + ALint freq = 0; + + bufferId = (currentBuf - 1) % MAX_STREAM_BUFFERS; + qalGetBufferi(buffers[bufferId], AL_FREQUENCY, &freq); + alDieIfError(); + + return freq; +} + +/* +============== +openal_channel_two_d_stream::set_sample_offset +============== +*/ +void openal_channel_two_d_stream::set_sample_offset(U32 offset) +{ + snd_stream_t *stream; + unsigned int bytesToRead, bytesRead; + unsigned int byteOffset; + unsigned int bitsPerSample; + unsigned int streamPosition; + ALuint format; + ALint numQueuedBuffers; + bool bWasPlaying; + char rawData[MAX_BUFFER_SAMPLES * 2 * 2]; + + if (!streaming) { + return; + } + + stream = (snd_stream_t *)streamHandle; + streamPosition = getCurrentStreamPosition(); + bitsPerSample = getBitsPerSample(); + byteOffset = offset * bitsPerSample / 8; + + if (byteOffset >= streamPosition && byteOffset < streamNextOffset) { + // + // Sample is in the currently streamed data + // + qalSourcei(source, AL_BYTE_OFFSET, byteOffset - streamPosition); + alDieIfError(); + + return; + } + + bWasPlaying = is_playing(); + + if (stream) { + if (byteOffset < streamPosition) { + // + // New offset is before the current offset, + // reload the stream from the beginning + // + S_CodecCloseStream(stream); + streamHandle = NULL; + } else if (byteOffset >= stream->info.size) { + // + // This shouldn't happen unless the file is different + // from the one used while saving + // + byteOffset %= stream->info.size; + S_CodecCloseStream(stream); + streamHandle = NULL; + } + } + + if (!streamHandle) { + streamHandle = S_CodecLoad(this->fileName, NULL); + if (!streamHandle) { + clear_stream(); + return; + } + + stream = (snd_stream_t *)streamHandle; + streamNextOffset = 0; + } + + while (streamNextOffset <= byteOffset) { + streamPosition = streamNextOffset; + + bytesToRead = Q_min(MAX_BUFFER_SAMPLES * stream->info.width * stream->info.channels, sizeof(rawData)); + bytesRead = S_CodecReadStream(stream, bytesToRead, rawData); + if (!bytesRead) { + clear_stream(); + return; + } + + streamNextOffset += bytesRead; + } + + // + // Stop the sound and remove all buffers from the queue + // + qalSourceStop(source); + alDieIfError(); + + // + // Remove all buffers from the queue + // + numQueuedBuffers = 0; + qalGetSourcei(source, AL_BUFFERS_QUEUED, &numQueuedBuffers); + alDieIfError(); + + while (numQueuedBuffers--) { + ALuint b; + qalSourceUnqueueBuffers(source, 1, &b); + alDieIfError(); + } + + format = S_OPENAL_Format(stream->info.width, stream->info.channels); + + qalBufferData(buffers[currentBuf], format, rawData, bytesRead, stream->info.rate); + alDieIfError(); + + qalSourceQueueBuffers(source, 1, &buffers[currentBuf]); + alDieIfError(); + currentBuf = (currentBuf + 1) % MAX_STREAM_BUFFERS; + + // + // Now set the source offset + // + qalSourcei(source, AL_BYTE_OFFSET, byteOffset - streamPosition); + alDieIfError(); + + if (bWasPlaying) { + // + // The sound was stopped when re-streaming + // + play(); + } +} + +/* +============== +openal_channel_two_d_stream::queue_stream +============== +*/ +bool openal_channel_two_d_stream::queue_stream(const char *fileName) +{ + snd_stream_t *stream; + unsigned int bytesToRead, bytesRead; + ALint freq = 0; + ALuint format = 0; + ALuint old = 0; + char rawData[MAX_BUFFER_SAMPLES * 2 * 2]; + + // Store the filename so it can be looped later + Q_strncpyz(this->fileName, fileName, sizeof(this->fileName)); + clear_stream(); + + sampleLoopCount = 1; + + // + // Load the file + // + streamHandle = S_CodecLoad(this->fileName, NULL); + if (!streamHandle) { + return false; + } + stream = (snd_stream_t *)streamHandle; + + iStartTime = cl.serverTime; + iEndTime = (int)(cl.serverTime + (stream->info.samples / stream->info.rate * 1000.f)); + + format = S_OPENAL_Format(stream->info.width, stream->info.channels); + if (!format) { + Com_Printf( + "OpenAL: Bad Wave file (%d channels, %d bits) [%s].\n", + pSfx->info.channels, + (int)(pSfx->info.width * 8.f), + pSfx->name + ); + + S_CodecCloseStream(stream); + return false; + } + + qalGenBuffers(MAX_STREAM_BUFFERS, buffers); + alDieIfError(); + + // Read a smaller sample + bytesToRead = Q_min(MAX_BUFFER_SAMPLES * stream->info.width * stream->info.channels, sizeof(rawData)); + bytesRead = S_CodecReadStream(stream, bytesToRead, rawData); + if (!bytesRead) { + // Valid stream but no data? + return true; + } + + streamNextOffset = bytesRead; + + qalBufferData(buffers[currentBuf], format, rawData, bytesRead, stream->info.rate); + alDieIfError(); + + qalSourceQueueBuffers(source, 1, &buffers[currentBuf]); + alDieIfError(); + + currentBuf = (currentBuf + 1) % MAX_STREAM_BUFFERS; + + streaming = true; + + return true; +} + +/* +============== +openal_channel_two_d_stream::clear_stream +============== +*/ +void openal_channel_two_d_stream::clear_stream() +{ + if (!streaming) { + return; + } + + qalSourceStop(source); + qalSourcei(source, AL_BUFFER, 0); + qalDeleteBuffers(MAX_STREAM_BUFFERS, buffers); + + if (streamHandle) { + S_CodecCloseStream((snd_stream_t *)streamHandle); + } + + fileName[0] = 0; + streamHandle = NULL; + + currentBuf = 0; + streamNextOffset = 0; + streaming = false; + sampleLooped = 0; +} + +/* +============== +openal_channel_two_d_stream::getQueueLength + +Return the total length of all buffers being streamed. +============== +*/ +unsigned int openal_channel_two_d_stream::getQueueLength() const +{ + ALint numQueuedBuffers = 0; + unsigned int totalQueueLength = 0; + unsigned int bufferId; + unsigned int i; + + qalGetSourcei(source, AL_BUFFERS_QUEUED, &numQueuedBuffers); + alDieIfError(); + + for (i = 0; i < numQueuedBuffers; i++) { + ALint bufferSize = 0; + + bufferId = (currentBuf - i - 1) % MAX_STREAM_BUFFERS; + qalGetBufferi(buffers[bufferId], AL_SIZE, &bufferSize); + + totalQueueLength += bufferSize; + } + + return totalQueueLength; +} + +/* +============== +openal_channel_two_d_stream::getCurrentStreamPosition + +Return the current position in the sound being streamed. +============== +*/ +unsigned int openal_channel_two_d_stream::getCurrentStreamPosition() const +{ + unsigned int queueLength = getQueueLength(); + + if (streamNextOffset >= queueLength) { + return streamNextOffset - queueLength; + } else if (streamHandle) { + snd_stream_t *stream = (snd_stream_t *)streamHandle; + return (stream->info.size + streamNextOffset - queueLength) % stream->info.size; + } else { + return queueLength - streamNextOffset; + } +} + +/* +============== +openal_channel_two_d_stream::getBitsPerSample + +Return the number of bytes per sample. +It assumes that all pending buffers have the same channels and bits. +============== +*/ +unsigned int openal_channel_two_d_stream::getBitsPerSample() const +{ + unsigned int bufferId; + ALint bits = 0, channels = 0; + + bufferId = (currentBuf - 1) % MAX_STREAM_BUFFERS; + qalGetBufferi(buffers[bufferId], AL_BITS, &bits); + alDieIfError(); + qalGetBufferi(buffers[bufferId], AL_CHANNELS, &channels); + alDieIfError(); + + return bits * channels; +} diff --git a/code/client/snd_openal_new.h b/code/client/snd_openal_new.h new file mode 100644 index 00000000..a22e2d6f --- /dev/null +++ b/code/client/snd_openal_new.h @@ -0,0 +1,238 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#pragma once + +#include "qal.h" + +#undef OPENAL + +typedef int S32; +typedef unsigned int U32; + +#define MAX_STREAM_BUFFERS 16 +#define MAX_BUFFER_SAMPLES 16384 + +typedef enum { + FADE_NONE, + FADE_IN, + FADE_OUT +} fade_t; + +typedef struct { + vec3_t vOrigin; + vec3_t vRelativeOrigin; + vec3_t vVelocity; + + sfx_t *pSfx; + qboolean bPlaying; + + int iChannel; + float fVolume; + float fPitch; + + int iStartTime; + qboolean bInUse; + qboolean bCombine; + + float fBaseVolume; + float fMinDist; + float fMaxDist; + int iFlags; +} openal_loop_sound_t; + +struct openal_channel { + sfx_t *pSfx; + int iEntNum; + int iEntChannel; + vec3_t vOrigin; + + float fVolume; + int iBaseRate; + float fNewPitchMult; + float fMinDist; + float fMaxDist; + + int iStartTime; + int iTime; + int iEndTime; + int iFlags; + int iPausedOffset; + + int song_number; + + fade_t fading; + int fade_time; + int fade_start_time; + + ALuint source; + ALuint buffer; + ALubyte *bufferdata; + +public: + void play(); + virtual void stop(); + void pause(); + + void set_no_3d(); + void set_3d(); + void set_no_virtualization(); + void set_virtualization(); + + void set_gain(float gain); + void set_velocity(float v0, float v1, float v2); + void set_position(float v0, float v1, float v2); + + bool is_free(); + bool is_paused(); + bool is_playing(); + + void force_free(); + virtual bool set_sfx(sfx_t *pSfx); + + void start_sample(); + void stop_sample(); + void resume_sample(); + void end_sample(); + + void set_sample_pan(S32 pan); + void set_sample_playback_rate(S32 pan); + S32 sample_playback_rate(); + + S32 sample_volume(); + virtual U32 sample_offset(); + U32 sample_ms_offset(); + U32 sample_loop_count(); + virtual void set_sample_offset(U32 offset); + void set_sample_ms_offset(U32 offset); + virtual void set_sample_loop_count(S32 count); + void set_sample_loop_block(S32 start_offset, S32 end_offset); + + U32 sample_status(); + +public: + virtual void update(); + + virtual U32 buffer_frequency() const; +}; + +struct openal_channel_two_d_stream : public openal_channel { +private: + char fileName[64]; + void *streamHandle; + unsigned int buffers[MAX_STREAM_BUFFERS]; + unsigned int currentBuf; + unsigned int sampleLoopCount; + unsigned int sampleLooped; + unsigned int streamNextOffset; + bool streaming; + +public: + openal_channel_two_d_stream(); + ~openal_channel_two_d_stream(); + + void stop() override; + bool set_sfx(sfx_t *pSfx) override; + void set_sample_loop_count(S32 count) override; + void update() override; + U32 sample_offset() override; + void set_sample_offset(U32 offset) override; + + bool queue_stream(const char *fileName); + +protected: + U32 buffer_frequency() const override; + +private: + void clear_stream(); + + unsigned int getQueueLength() const; + unsigned int getCurrentStreamPosition() const; + unsigned int getBitsPerSample() const; +}; + +struct openal_movie_channel : public openal_channel { + +}; + +struct openal_internal_t { + openal_channel chan_3D[MAX_SOUNDSYSTEM_CHANNELS_3D]; + openal_channel chan_2D[MAX_SOUNDSYSTEM_CHANNELS_2D]; + openal_channel_two_d_stream chan_2D_stream[MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM]; + openal_channel_two_d_stream chan_song[MAX_SOUNDSYSTEM_SONGS]; + openal_channel_two_d_stream chan_mp3; + openal_channel_two_d_stream chan_trig_music; + openal_channel_two_d_stream chan_movie; + + // Pointers to channels + openal_channel *channel[MAX_SOUNDSYSTEM_CHANNELS]; + + openal_loop_sound_t loop_sounds[MAX_SOUNDSYSTEM_LOOP_SOUNDS]; + + openal_channel movieChannel; + sfx_t movieSFX; + + char tm_filename[MAX_RES_NAME]; + int tm_loopcount; +}; + +#ifdef __cplusplus +extern "C" { +#endif + + qboolean S_OPENAL_Init(); + void S_OPENAL_Shutdown(); + void S_OPENAL_StartSound( + const vec3_t vOrigin, + int iEntNum, + int iEntChannel, + sfxHandle_t sfxHandle, + float fVolume, + float fMinDist, + float fPitch, + float fMaxDist, + qboolean bStreamed + ); + void S_OPENAL_AddLoopingSound( + const vec3_t vOrigin, + const vec3_t vVelocity, + sfxHandle_t sfxHandle, + float fVolume, + float fMinDist, + float fMaxDist, + float fPitch, + int iFlags + ); + void S_OPENAL_ClearLoopingSounds(); + void S_OPENAL_StopSound(int iEntNum, int iEntChannel); + void S_OPENAL_StopAllSounds(qboolean bStopMusic); + void S_OPENAL_Respatialize(int iEntNum, const vec3_t vHeadPos, const vec3_t vAxis[3]); + void S_OPENAL_SetReverb(int iType, float fLevel); + void S_OPENAL_Update(); + + const char *S_OPENAL_GetMusicFilename(); + int S_OPENAL_GetMusicLoopCount(); + unsigned int S_OPENAL_GetMusicOffset(); + +#ifdef __cplusplus +} +#endif diff --git a/code/client/snd_public.h b/code/client/snd_public.h index e37453f4..9edf4768 100644 --- a/code/client/snd_public.h +++ b/code/client/snd_public.h @@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA + #ifdef __cplusplus extern "C" { #endif @@ -89,3 +91,96 @@ void S_MasterGain(float gain); #endif #include "new/snd_public_new.h" + +#else + +#ifdef __cplusplus +extern "C" { +#endif + +void S_SoundInfo_f(); +void S_SoundDump_f(); +void S_Init(qboolean full_startup); +void S_Shutdown(qboolean full_shutdown); +qboolean S_NameExists(const char* name); +void S_BeginRegistration(); +qboolean S_IsSoundRegistered(const char* name); +sfxHandle_t S_RegisterSound(const char* name, int streamed, qboolean force_load); +float S_GetSoundTime(sfxHandle_t handle); +void S_EndRegistration(); +void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t vel, qboolean use_listener); +void S_SetGlobalAmbientVolumeLevel(float volume); +void S_StartSound(const vec3_t origin, int entnum, int entchannel, sfxHandle_t sfxHandle, float volume, float min_dist, float pitch, float maxDist, int streamed); +void S_StartLocalSound(const char* sound_name, qboolean force_load); +void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, soundChannel_t channel); +void S_StopAllSounds(qboolean stop_music); +void S_ClearLoopingSounds(); +void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle, float volume, float min_dist, float max_dist, float pitch, int flags); +void S_Respatialize(int entityNum, const vec3_t head, vec3_t axis[3]); +void S_Update(); +void S_StopSound(int entnum, int channel); +void S_SetReverb(int reverb_type, float reverb_level); +void S_Play(); +void S_SoundList(); + +qboolean S_IsSoundPlaying(int channel_number, const char* sfxName); +void S_FadeSound(float fTime); + +qboolean MUSIC_LoadSoundtrackFile(const char* filename); +qboolean MUSIC_SongValid(const char* mood); +qboolean MUSIC_Loaded(); +void Music_Update(); +void MUSIC_SongEnded(); +void MUSIC_NewSoundtrack(const char* name); +void MUSIC_UpdateMood(int current, int fallback); +void MUSIC_UpdateVolume(float volume, float fade_time); +void MUSIC_StopAllSongs(); +void MUSIC_FreeAllSongs(); +qboolean MUSIC_Playing(); +int MUSIC_FindSong(const char* name); +void S_loadsoundtrack(); +const char* S_CurrentSoundtrack(); +void S_PlaySong(); +int MUSIC_CurrentSongChannel(); +void MUSIC_StopChannel(int channel_number); +qboolean MUSIC_PlaySong(const char* alias); +void MUSIC_UpdateMusicVolumes(); +void MUSIC_CheckForStoppedSongs(); +void S_TriggeredMusic_SetupHandle(const char* pszName, int iLoopCount, int iOffset, qboolean autostart); +void S_TriggeredMusic_Start(); +void S_TriggeredMusic_StartLoop(); +void S_TriggeredMusic_Stop(); +void S_TriggeredMusic_Volume(); +void S_TriggeredMusic_Pause(); +void S_TriggeredMusic_Unpause(); +void S_TriggeredMusic_PlayIntroMusic(); +void S_StopMovieAudio(); +void S_SetupMovieAudio(const char* pszMovieName); +int S_CurrentMoviePosition(); + +const char* S_GetMusicFilename(); +int S_GetMusicLoopCount(); +unsigned int S_GetMusicOffset(); + +#ifdef __cplusplus +} +#endif + +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef USE_VOIP +void S_StartCapture( void ); +int S_AvailableCaptureSamples( void ); +void S_Capture( int samples, byte *data ); +void S_StopCapture( void ); +void S_MasterGain( float gain ); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/code/client/usignal.cpp b/code/client/usignal.cpp index dad646e3..6e161b6e 100644 --- a/code/client/usignal.cpp +++ b/code/client/usignal.cpp @@ -120,7 +120,7 @@ bool UConnection::SendEvent ptr = m_listeners.ObjectAt( i ); if( ptr ) { - Event *e = new Event( m_events.ObjectAt( i ) ); + Event *e = new Event( *m_events.ObjectAt( i ) ); for( j = 1; j < numargs; j++ ) { diff --git a/code/fgame/CMakeLists.txt b/code/fgame/CMakeLists.txt index c688fa85..ed8fdc31 100644 --- a/code/fgame/CMakeLists.txt +++ b/code/fgame/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(fgame) # Shared source files for modules @@ -27,8 +27,24 @@ file( add_library(fgame SHARED ${SOURCES_GAME}) -find_package(BISON) -find_package(FLEX) +# +# Workaround to get a recent version Flex and Bison executables in MacOS +# as Bison 2.3 shipped with MacOS doesn't work +# +if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") + execute_process(COMMAND brew --prefix bison RESULT_VARIABLE APP_RESULT OUTPUT_VARIABLE APP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) + if (APP_RESULT EQUAL 0 AND EXISTS "${APP_PREFIX}") + set(BISON_EXECUTABLE "${APP_PREFIX}/bin/bison") + endif() + + execute_process(COMMAND brew --prefix flex RESULT_VARIABLE APP_RESULT OUTPUT_VARIABLE APP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) + if (APP_RESULT EQUAL 0 AND EXISTS "${APP_PREFIX}") + set(FLEX_EXECUTABLE "${APP_PREFIX}/bin/flex") + endif() +endif() + +find_package(BISON 3 REQUIRED) +find_package(FLEX REQUIRED) if (FLEX_FOUND) flex_target(fgame-lexer ${CMAKE_SOURCE_DIR}/code/parser/lex_source.txt ${CMAKE_SOURCE_DIR}/code/parser/generated/yyLexer.cpp DEFINES_FILE ${CMAKE_SOURCE_DIR}/code/parser/generated/yyLexer.h COMPILE_FLAGS "-Cem --nounistd") @@ -50,16 +66,11 @@ target_compile_features(fgame PUBLIC cxx_nullptr) target_compile_features(fgame PUBLIC c_variadic_macros) target_link_libraries(fgame PUBLIC qcommon) -set_target_properties(fgame PROPERTIES PREFIX "${TARGET_PLATFORM_PREFIX}") -set_target_properties(fgame PROPERTIES OUTPUT_NAME "game${TARGET_ARCH_SUFFIX}") -set_target_properties(fgame PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TARGET_BASE_GAME}") +set_target_properties(fgame PROPERTIES PREFIX "") +set_target_properties(fgame PROPERTIES OUTPUT_NAME "game${TARGET_BIN_SUFFIX}") -INSTALL( - TARGETS fgame - LIBRARY DESTINATION "${TARGET_BASE_GAME}" - RUNTIME DESTINATION "${TARGET_BASE_GAME}" -) +INSTALL(TARGETS fgame DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR}) if(MSVC) - INSTALL(FILES $ DESTINATION "${TARGET_BASE_GAME}" OPTIONAL) + INSTALL(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR} OPTIONAL) endif() diff --git a/code/fgame/DrivableVehicleTandem.cpp b/code/fgame/DrivableVehicleTandem.cpp index 71af7245..164b6b6b 100644 --- a/code/fgame/DrivableVehicleTandem.cpp +++ b/code/fgame/DrivableVehicleTandem.cpp @@ -21,6 +21,46 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "DrivableVehicleTandem.h" +#include "vehicleturret.h" -// FIXME: unimplemented +CLASS_DECLARATION(DrivableVehicle, DrivableVehicleTandem, "DrivableVehicleTandem") { + {NULL, NULL} +}; + +DrivableVehicleTandem::DrivableVehicleTandem() +{ +} + +DrivableVehicleTandem::~DrivableVehicleTandem() +{ +} + +void DrivableVehicleTandem::SpawnTurret(Event* ev) +{ + VehicleTurretGunTandem* pTurret = new VehicleTurretGunTandem(); + int slot; + + pTurret->SetBaseOrientation(orientation, NULL); + pTurret->setModel(ev->GetString(2)); + + slot = ev->GetInteger(1); + AttachTurretSlot(slot, pTurret, vec_zero, NULL); + pTurret->SetVehicleOwner(this); + + pTurret->PostEvent(EV_TakeDamage, EV_POSTSPAWN); + + UpdateTurretSlot(slot); + + pTurret->ProcessPendingEvents(); +} + +void DrivableVehicleTandem::UpdateTurretSlot(int iSlot) +{ + DrivableVehicle::UpdateTurretSlot(iSlot); + + if (Turrets[iSlot].ent && Turrets[iSlot].ent->isSubclassOf(VehicleTurretGunTandem)) { + VehicleTurretGunTandem* pTurret = static_cast(Turrets[iSlot].ent.Pointer()); + pTurret->UpdateLinkedTurret(); + } +} diff --git a/code/fgame/DrivableVehicleTandem.h b/code/fgame/DrivableVehicleTandem.h index 64b139d4..3bc5b916 100644 --- a/code/fgame/DrivableVehicleTandem.h +++ b/code/fgame/DrivableVehicleTandem.h @@ -21,3 +21,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once + +#include "vehicle.h" + +class DrivableVehicleTandem : public DrivableVehicle { +private: + CLASS_PROTOTYPE(DrivableVehicleTandem); + +public: + DrivableVehicleTandem(); + ~DrivableVehicleTandem(); + + void SpawnTurret(Event* ev) override; + void UpdateTurretSlot(int iSlot) override; +}; diff --git a/code/fgame/Entities.cpp b/code/fgame/Entities.cpp index 58d26cc7..25a53961 100644 --- a/code/fgame/Entities.cpp +++ b/code/fgame/Entities.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -31,62 +31,289 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "sentient.h" #include "player.h" -Container g_projectileTargets; +Container g_projectileTargets; -Event EV_PG_SetID("ID", EV_DEFAULT, "i", "ID", "Sets the ID for this projectile generator\nDefault=0:"); -Event EV_PG_SetModel( - "Model", EV_DEFAULT, "s", "Model", "Projectile model to use.\nDefault=models/projectiles/bazookashell.tik" +/*QUAKED ProjectileGenerator_Target (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) + + Place this target down and assign it a ProjectileGenerator ID and it will + shoot here.... + + Here are the params: + + ID (Generator ID number.) + +******************************************************************************/ + +Event EV_PG_SetID +( + "ID", + EV_DEFAULT, + "i", + "ID", + "Sets the ID for this projectile generator\nDefault=0:", + EV_NORMAL ); -Event EV_PG_MinDuration( - "MinDuration", EV_DEFAULT, "f", "MinDuration", "Sets the minimum duration of the bursts (in seconds)\nDefault=3" +Event EV_PG_SetModel +( + "Model", + EV_DEFAULT, + "s", + "Model", + "Projectile model to use.\nDefault=models/projectiles/bazookashell.tik", + EV_NORMAL ); -Event EV_PG_MaxDuration( - "MaxDuration", EV_DEFAULT, "f", "MaxDuration", "Sets the maximum duration of bursts(in seconds)\nDefault=3" +Event EV_PG_MinDuration +( + "MinDuration", + EV_DEFAULT, + "f", + "MinDuration", + "Sets the minimum duration of the bursts (in seconds)\nDefault=3", + EV_NORMAL ); -Event EV_PG_MinNumShots( - "MinNumShots", EV_DEFAULT, "i", "MinNumShots", "Sets the minimum # of shots to fire in a cycle\nDefault=1" +Event EV_PG_MaxDuration +( + "MaxDuration", + EV_DEFAULT, + "f", + "MaxDuration", + "Sets the maximum duration of bursts(in seconds)\nDefault=3", + EV_NORMAL ); -Event EV_PG_MaxNumShots( - "MaxNumShots", EV_DEFAULT, "i", "MaxNumShots", "Sets the maximum # of shots to fire in a cycle\nDefault=1" +Event EV_PG_MinNumShots +( + "MinNumShots", + EV_DEFAULT, + "i", + "MinNumShots", + "Sets the minimum # of shots to fire in a cycle\nDefault=1", + EV_NORMAL +); +Event EV_PG_MaxNumShots +( + "MaxNumShots", + EV_DEFAULT, + "i", + "MaxNumShots", + "Sets the maximum # of shots to fire in a cycle\nDefault=1", + EV_NORMAL +); +Event EV_PG_Cycles +( + "Cycles", + EV_DEFAULT, + "i", + "Cycles", + "Number of cycles. 0=infinte\nDefault=0", + EV_NORMAL +); +Event EV_PG_MinDelay +( + "MinDelay", + EV_DEFAULT, + "f", + "MinDelay", + "Minimum time between bursts.\n", + EV_NORMAL +); +Event EV_PG_MaxDelay +( + "MaxDelay", + EV_DEFAULT, + "f", + "MaxDelay", + "Maximum time between bursts\nDefault=10", + EV_NORMAL +); +Event EV_PG_Accuracy +( + "Accuracy", + EV_DEFAULT, + "f", + "Accuracy", + "Accuracy 0-25 feet\nDefault=10", + EV_NORMAL +); +Event EV_PG_ClearTarget +( + "ClearTarget", + EV_DEFAULT, + NULL, + NULL, + "Pick another target...", + EV_NORMAL +); +Event EV_PG_BeginCycle +( + "BeginCycle", + EV_DEFAULT, + NULL, + NULL, + "Startup the cycle..", + EV_NORMAL +); +Event EV_TickCycle +( + "TickCycle", + EV_DEFAULT, + NULL, + NULL, + "Tick the cycle..", + EV_NORMAL +); +Event EV_EndCycle +( + "EndCycle", + EV_DEFAULT, + NULL, + NULL, + "End the cycle..", + EV_NORMAL +); +Event EV_TurnOn +( + "TurnOn", + EV_DEFAULT, + NULL, + NULL, + "Turn On and begin the first cycle", + EV_NORMAL +); +Event EV_TurnOff +( + "TurnOff", + EV_DEFAULT, + NULL, + NULL, + "Turn Off and cancel the current cycle (if any)", + EV_NORMAL +); +Event EV_Set_FireDelay +( + "firedelay", + EV_DEFAULT, + "f", + "fFireDelay", + "Set the minimum time between shots from the weapon", + EV_NORMAL +); +Event EV_Initialize +( + "initialize", + EV_DEFAULT, + NULL, + NULL, + "Initialize object", + EV_NORMAL ); -Event EV_PG_Cycles("Cycles", EV_DEFAULT, "i", "Cycles", "Number of cycles. 0=infinte\nDefault=0"); -Event EV_PG_MinDelay("MinDelay", EV_DEFAULT, "f", "MinDelay", "Minimum time between bursts.\n"); -Event EV_PG_MaxDelay("MaxDelay", EV_DEFAULT, "f", "MaxDelay", "Maximum time between bursts\nDefault=10"); -Event EV_PG_Accuracy("Accuracy", EV_DEFAULT, "f", "Accuracy", "Accuracy 0-25 feet\nDefault=10"); -Event EV_PG_ClearTarget("ClearTarget", EV_DEFAULT, NULL, NULL, "Pick another target..."); -Event EV_PG_BeginCycle("BeginCycle", EV_DEFAULT, NULL, NULL, "Startup the cycle.."); -Event EV_TickCycle("TickCycle", EV_DEFAULT, NULL, NULL, "Tick the cycle.."); -Event EV_EndCycle("EndCycle", EV_DEFAULT, NULL, NULL, "End the cycle.."); -Event EV_TurnOn("TurnOn", EV_DEFAULT, NULL, NULL, "Turn On and begin the first cycle"); -Event EV_TurnOff("TurnOff", EV_DEFAULT, NULL, NULL, "Turn Off and cancel the current cycle (if any)"); -Event - EV_Set_FireDelay("firedelay", EV_DEFAULT, "f", "fFireDelay", "Set the minimum time between shots from the weapon"); -Event EV_Initialize("initialize", EV_DEFAULT, NULL, NULL, "Initialize object"); Event EV_Set_FireOnStartUp( - "FireOnStartUp", EV_DEFAULT, 0, "i", "Default=1; Set this to 0 if you don't want the PG to fire on startup." + "FireOnStartUp", + EV_DEFAULT, + NULL, + "i", + "Default=1; Set this to 0 if you don't want the PG to fire on startup.", + EV_NORMAL ); -Event EV_PG_isDonut("isdonut", EV_DEFAULT, "i", "isdonut", "will target donut"); -Event EV_PG_arcDonut("arc", EV_DEFAULT, "f", "arc", "arc in front of the player"); -Event EV_PG_minDonut("mindonut", EV_DEFAULT, "f", "mindonut", "min extent of donut from player"); -Event EV_PG_maxDonut("maxdonut", EV_DEFAULT, "f", "maxdonut", "max extent of donut from player"); -Event EV_PG_PlayPreImpactSound("playpreimpact", EV_DEFAULT, NULL, NULL, "Play a pre-impact sound"); -Event EV_PG_SetPreImpactSound("preimpactsound", EV_DEFAULT, "s", "Sound", "Set a pre-impact sound."); -Event EV_PG_SetPreImpactSoundTime( - "preimpactsoundtime", EV_DEFAULT, "f", "delay", "Set the time before impact to play the preimpact sound." +Event EV_PG_isDonut +( + "isdonut", + EV_DEFAULT, + "i", + "isdonut", + "will target donut", + EV_NORMAL ); -Event EV_PG_SetPreImpactSoundProbability( +Event EV_PG_arcDonut +( + "arc", + EV_DEFAULT, + "f", + "arc", + "arc in front of the player", + EV_NORMAL +); +Event EV_PG_minDonut +( + "mindonut", + EV_DEFAULT, + "f", + "mindonut", + "min extent of donut from player", + EV_NORMAL +); +Event EV_PG_maxDonut +( + "maxdonut", + EV_DEFAULT, + "f", + "maxdonut", + "max extent of donut from player", + EV_NORMAL +); +Event EV_PG_PlayPreImpactSound +( + "playpreimpact", + EV_DEFAULT, + NULL, + NULL, + "Play a pre-impact sound", + EV_NORMAL +); +Event EV_PG_SetPreImpactSound +( + "preimpactsound", + EV_DEFAULT, + "s", + "Sound", + "Set a pre-impact sound.", + EV_NORMAL +); +Event EV_PG_SetPreImpactSoundTime +( + "preimpactsoundtime", + EV_DEFAULT, + "f", + "delay", + "Set the time before impact to play the preimpact sound.", + EV_NORMAL +); +Event EV_PG_SetPreImpactSoundProbability +( "preimpactsoundprob", EV_DEFAULT, "f", "probability", "Set the chance for a pre-impact sound to occur.\n" - "Range: ( 0.0, 1.0 ), with 0 having no chance, and 1 always occurring." + "Range: ( 0.0, 1.0 ), with 0 having no chance, and 1 always occurring.", + EV_NORMAL ); -Event EV_PG_SetLaunchSound("launchsound", EV_DEFAULT, "s", "Sound", "Set a launch sound for the projectile."); -Event EV_PG_GetTargetEntity( - "gettargetentity", EV_DEFAULT, NULL, NULL, "Returns entity being targeted by the projectile generator,", EV_GETTER +Event EV_PG_SetLaunchSound +( + "launchsound", + EV_DEFAULT, + "s", + "Sound", + "Set a launch sound for the projectile.", + EV_NORMAL +); +Event EV_PG_GetTargetEntity +( + "gettargetentity", + EV_DEFAULT, + NULL, + NULL, + "Returns entity being targeted by the projectile generator,", + EV_RETURN +); +Event EV_PG_IsTurnedOn +( + "isturnedon", + EV_DEFAULT, + NULL, + NULL, + "Returns whether the generator is on or off.", + EV_RETURN ); -Event EV_PG_IsTurnedOn("isturnedon", EV_DEFAULT, NULL, NULL, "Returns whether the generator is on or off.", EV_GETTER); CLASS_DECLARATION(Entity, ProjectileTarget, "ProjectileGenerator_Target") { {&EV_PG_SetID, &ProjectileTarget::EventSetId}, @@ -100,7 +327,7 @@ void ClearProjectileTargets() ProjectileTarget::ProjectileTarget() { - m_iTarget = -1; + m_iID = -1; setMoveType(MOVETYPE_NONE); setSolidType(SOLID_NOT); hideModel(); @@ -110,12 +337,19 @@ ProjectileTarget::ProjectileTarget() void ProjectileTarget::EventSetId(Event *ev) { - m_iTarget = ev->GetInteger(1); + m_iID = ev->GetInteger(1); } -int ProjectileTarget::GetTarget() const +int ProjectileTarget::GetId() const { - return m_iTarget; + return m_iID; +} + +void ProjectileTarget::Archive(Archiver& arc) +{ + Entity::Archive(arc); + + arc.ArchiveInteger(&m_iID); } CLASS_DECLARATION(Animate, ProjectileGenerator, "ProjectileGenerator") { @@ -146,53 +380,47 @@ CLASS_DECLARATION(Animate, ProjectileGenerator, "ProjectileGenerator") { ProjectileGenerator::ProjectileGenerator() { - m_iId = -1; - m_fMinDuration = 1; - m_fMaxDuration = 3; - m_iCycles = 0; - m_fMinDelay = 3.0; - m_fMaxDelay = 10; - m_fAccuracy = 10; - m_iCurrentCycle = 0; - m_iMinNumShots = 1; - m_iMaxNumShots = 1; - m_fCurrentTime = 0; - m_fShotsPerSec = 0; - m_iTargetIndex = -1; - m_fLastShotTime = 0; - m_iAnimSlot = 0; - m_bIsTurnedOn = 0; - m_bFireOnStartUp = 1; - m_bIsDonut = 0; - m_fArcDonut = 0; - m_fMinDonut = 0; - m_fMaxDonut = 0; - m_pTarget = 0; + m_iId = -1; + m_fMinDuration = 1; + m_fMaxDuration = 3; + m_iCycles = 0; + m_fMinDelay = 3.0; + m_fMaxDelay = 10; + m_fAccuracy = 10; + m_iCurrentCycle = 0; + m_iMinNumShots = 1; + m_iMaxNumShots = 1; + m_fCurrentTime = 0; + m_fShotsPerSec = 0; + m_iTargetIndex = -1; + m_fLastShotTime = 0; + m_iAnimSlot = 0; + m_bIsTurnedOn = false; + m_bFireOnStartUp = true; + m_bIsDonut = false; + m_fArcDonut = 0; + m_fMinDonut = 0; + m_fMaxDonut = 0; + m_pTarget = NULL; m_fCycleTime = 1; setMoveType(MOVETYPE_NONE); setSolidType(SOLID_NOT); - if (spawnflags & PT_SPAWNFLAG_PLAY_FIRE_SOUND) - { - if (spawnflags & PT_SPAWNFLAG_HIDDEN) - { + if (ShouldPlayFireSound()) { + if (ShouldHideModel()) { hideModel(); edict->r.svFlags |= SVF_NOCLIENT; } - } - else - { + } else { hideModel(); } - if (!LoadingSavegame && spawnflags & PT_SPAWNFLAG_TURN_ON) - { + if (!LoadingSavegame && ShouldStartOn()) { PostEvent(EV_TurnOn, 0.1f); } m_pCurrent = NULL; - if (!LoadingSavegame) - { + if (!LoadingSavegame) { PostEvent(EV_Initialize, 0.001f); } } @@ -209,7 +437,22 @@ bool ProjectileGenerator::ShouldHideModel() const bool ProjectileGenerator::ShouldPlayFireSound() const { - return (spawnflags & PT_SPAWNFLAG_PLAY_FIRE_SOUND) ? true : false; + return (spawnflags & PT_SPAWNFLAG_PLAY_FIRE_SOUND) ? true : false; +} + +bool ProjectileGenerator::ShouldPlayMotionSound() const +{ + return (spawnflags & PT_SPAWNFLAG_PLAY_MOTION_SOUND) ? true : false; +} + +bool ProjectileGenerator::ShouldRotateYaw() const +{ + return (spawnflags & PT_SPAWNFLAG_ROTATE_YAW) ? true : false; +} + +bool ProjectileGenerator::ShouldRotateRoll() const +{ + return (spawnflags & PT_SPAWNFLAG_ROTATE_ROLL) ? true : false; } void ProjectileGenerator::EventIsTurnedOn(Event *ev) @@ -224,26 +467,27 @@ void ProjectileGenerator::EventGetTargetEntity(Event *ev) void ProjectileGenerator::EventLaunchSound(Event *ev) { - m_sLaunchSound = ev->GetString(1);; + m_sLaunchSound = ev->GetString(1); } void ProjectileGenerator::SetTarget(Event *ev) { - m_pTarget = ev->GetEntity(1); + SetTarget(ev->GetEntity(1)); +} + +void ProjectileGenerator::SetTarget(Entity *ent) +{ + m_pTarget = ent; } void ProjectileGenerator::OnInitialize(Event *ev) { - if (spawnflags & PT_SPAWNFLAG_SET_YAW) - { - angles.y += 180; - setAngles(angles); - } - if (spawnflags & PT_SPAWNFLAG_SET_ROLL) - { - angles.z += 180; - setAngles(angles); - } + if (ShouldRotateYaw()) { + angles.setYaw(angles.yaw() + 180); + } + if (ShouldRotateRoll()) { + angles.setRoll(angles.roll() + 180); + } } void ProjectileGenerator::TurnOff(Event *ev) @@ -255,17 +499,43 @@ void ProjectileGenerator::TurnOff(Event *ev) void ProjectileGenerator::TurnOn(Event *ev) { - if (!m_bIsTurnedOn) - { - CancelEventsOfType(EV_PG_BeginCycle); - CancelEventsOfType(EV_TickCycle); - m_bIsTurnedOn = true; + if (!m_bIsTurnedOn) { + CancelEventsOfType(EV_PG_BeginCycle); + CancelEventsOfType(EV_TickCycle); + SetupNextCycle(); + m_bIsTurnedOn = true; } } void ProjectileGenerator::SetupNextCycle() { - // FIXME: unimplemented + float numShots; + float delay; + + if (m_iCycles && m_iCurrentCycle >= m_iCycles) { + m_pCurrent = NULL; + TurnOff(NULL); + return; + } + + // retrieve the target + m_pCurrent = ChooseTarget(); + m_fCycleTime = G_Random(m_fMaxDuration - m_fMinDuration) + m_fMinDuration; + + // get a random number of shots + numShots = m_iMinNumShots; + if (numShots < m_iMaxNumShots) { + numShots = rand() % (m_iMaxNumShots - m_iMinNumShots) + m_iMinNumShots; + } + + // get a random delay + m_fShotsPerSec = numShots / m_fCycleTime; + delay = 0.01f; + if (m_bIsTurnedOn || !m_bFireOnStartUp) { + delay = G_Random(m_fMaxDelay - m_fMinDelay) + m_fMinDelay; + } + + PostEvent(EV_PG_BeginCycle, delay); } bool ProjectileGenerator::ShouldTargetRandom() const @@ -273,9 +543,44 @@ bool ProjectileGenerator::ShouldTargetRandom() const return (spawnflags & PT_SPAWNFLAG_TARGET_RANDOM) ? true : false; } -void ProjectileGenerator::ChooseTarget() +Entity *ProjectileGenerator::ChooseTarget() { - // FIXME: unimplemented + int numTargets; + + if (m_pTarget) { + m_vTargetOrg = GetTargetPos(m_pTarget); + return m_pTarget; + } + + if (ShouldTargetPlayer()) { + Entity *target = G_FindTarget(this, "player"); + if (target) { + m_vTargetOrg = GetTargetPos(target); + return target; + } + } + + if (!m_projectileTargets.NumObjects()) { + GetLocalTargets(); + } + + numTargets = m_projectileTargets.NumObjects(); + if (numTargets) { + ProjectileTarget *target; + + if (ShouldTargetRandom()) { + target = m_projectileTargets.ObjectAt((rand() % numTargets) + 1); + } else { + m_iTargetIndex = (m_iTargetIndex + 1) % numTargets; + target = m_projectileTargets.ObjectAt(m_iTargetIndex + 1); + } + + m_vTargetOrg = GetTargetPos(target); + return target; + } + + spawnflags |= PT_SPAWNFLAG_TARGET_PLAYER; + return ChooseTarget(); } void ProjectileGenerator::GetLocalTargets() @@ -283,11 +588,9 @@ void ProjectileGenerator::GetLocalTargets() int i; m_projectileTargets.ClearObjectList(); - for (i = 1; i <= g_projectileTargets.NumObjects(); i++) - { - ProjectileTarget* target = g_projectileTargets.ObjectAt(i); - if (m_iId == target->GetTarget()) - { + for (i = 1; i <= g_projectileTargets.NumObjects(); i++) { + ProjectileTarget *target = g_projectileTargets.ObjectAt(i); + if (m_iId == target->GetId()) { m_projectileTargets.AddObject(target); } } @@ -298,9 +601,107 @@ bool ProjectileGenerator::ShouldTargetPlayer() const return (spawnflags & PT_SPAWNFLAG_TARGET_PLAYER) ? true : false; } -void ProjectileGenerator::GetTargetPos(Entity *target) +Vector ProjectileGenerator::GetTargetPos(Entity *target) { - // FIXME: unimplemented + Vector vOrg; + Vector vForward; + Vector vAngles; + float fRandDonut; + + if (!target) { + return Vector(0, 0, 0); + } + + vOrg = target->origin; + + if (target->IsSubclassOfActor()) { + vOrg += Vector(0, 0, 36); + } + + if (m_bIsDonut) { + Entity *playerTarget = G_FindTarget(this, "player"); + + if (playerTarget) { + vAngles = playerTarget->client->ps.viewangles; + } else { + vAngles = target->angles; + } + + if (rand() & 1) { + vAngles.setYaw(vAngles[1] + m_fArcDonut / 2.0); + } else { + vAngles.setYaw(vAngles[1] - m_fArcDonut / 2.0); + } + + AngleVectors(vAngles, vForward, NULL, NULL); + + fRandDonut = G_Random(m_fMaxDonut - m_fMinDonut) + m_fMinDonut; + vOrg += vForward * (fRandDonut * 16); + } else { + vAngles.setYaw(G_Random(360)); + AngleVectors(vAngles, vForward, NULL, NULL); + + fRandDonut = G_Random(m_fAccuracy) * 16; + vOrg += vForward * fRandDonut; + } + + return vOrg; +} + +void ProjectileGenerator::GetMuzzlePos(Vector& pos) +{ + orientation_t orient; + + pos = origin; + + if (GetRawTag("tag_barrel", &orient)) { + vec3_t axis[3]; + int i; + + AnglesToAxis(angles, axis); + for (i = 0; i < 3; i++) { + VectorMA(pos, orient.origin[i], axis[i], pos); + } + } +} + +void ProjectileGenerator::Fire() +{ + m_fLastShotTime = level.time; + SetWeaponAnim("Fire", 0); +} + +void ProjectileGenerator::TryLaunchSound() +{ + if (m_sLaunchSound != "") { + Sound(m_sLaunchSound, CHAN_AUTO); + } +} + +void ProjectileGenerator::SetWeaponAnim(const char *name, Event *ev) +{ + int animnum = gi.Anim_NumForName(edict->tiki, name); + if (animnum == -1) { + return; + } + + StopAnimating(m_iAnimSlot); + RestartAnimSlot(m_iAnimSlot); + + int idleanim = gi.Anim_NumForName(edict->tiki, "idle"); + + edict->s.frameInfo[m_iAnimSlot].index = idleanim; + m_iAnimSlot = (m_iAnimSlot + 1) & 3; + edict->s.frameInfo[m_iAnimSlot].index = idleanim; + + if (ev) { + NewAnim(animnum, ev, m_iAnimSlot); + } else { + NewAnim(animnum, m_iAnimSlot); + } + + SetOnceType(m_iAnimSlot); + RestartAnimSlot(m_iAnimSlot); } void ProjectileGenerator::EventAccuracy(Event *ev) @@ -310,12 +711,12 @@ void ProjectileGenerator::EventAccuracy(Event *ev) void ProjectileGenerator::EventMaxDelay(Event *ev) { - m_fMaxDelay = ev->GetFloat(1); + m_fMaxDelay = ev->GetFloat(1); } void ProjectileGenerator::EventMinDelay(Event *ev) { - m_fMinDelay = ev->GetFloat(1); + m_fMinDelay = ev->GetFloat(1); } void ProjectileGenerator::EventFireOnStartUp(Event *ev) @@ -330,12 +731,12 @@ void ProjectileGenerator::EventMaxNumShots(Event *ev) void ProjectileGenerator::EventMinNumShots(Event *ev) { - m_iMinNumShots = ev->GetInteger(1); + m_iMinNumShots = ev->GetInteger(1); } void ProjectileGenerator::EventCycles(Event *ev) { - m_iCycles = ev->GetInteger(1); + m_iCycles = ev->GetInteger(1); } void ProjectileGenerator::EventMaxDuration(Event *ev) @@ -345,7 +746,7 @@ void ProjectileGenerator::EventMaxDuration(Event *ev) void ProjectileGenerator::EventMinDuration(Event *ev) { - m_fMinDuration = ev->GetFloat(1); + m_fMinDuration = ev->GetFloat(1); } void ProjectileGenerator::SetWeaponModel(Event *ev) @@ -360,27 +761,42 @@ void ProjectileGenerator::EventSetId(Event *ev) void ProjectileGenerator::BeginCycle(Event *ev) { - // FIXME: unimplemented + if (!m_bIsTurnedOn) { + return; + } + + if (!m_fShotsPerSec) { + SetupNextCycle(); + return; + } + + if (m_pCurrent) { + m_vTargetOrg = GetTargetPos(m_pCurrent); + } + + m_iCurrentCycle++; + m_fCurrentTime = 0; + + TickCycle(ev); + + PostEvent(EV_EndCycle, m_fCycleTime); } void ProjectileGenerator::TickCycle(Event *ev) { - if (!m_bIsTurnedOn) { - return; - } + if (!m_bIsTurnedOn) { + return; + } - m_fCurrentTime += level.frametime * m_fShotsPerSec; - if (m_fCurrentTime >= 1.f) - { - float f = floor(m_fCurrentTime); - if (Attack(floor(f))) - { - m_fCurrentTime -= floor(f); - } + m_fCurrentTime += level.frametime * m_fShotsPerSec; + if (m_fCurrentTime >= 1.f) { + float f = floor(m_fCurrentTime); + if (Attack(floor(f))) { + m_fCurrentTime -= floor(f); + } + } - } - - PostEvent(EV_TickCycle, 0.01f); + PostEvent(EV_TickCycle, 0.01f); } void ProjectileGenerator::EndCycle(Event *ev) @@ -389,14 +805,14 @@ void ProjectileGenerator::EndCycle(Event *ev) SetupNextCycle(); } -void ProjectileGenerator::EventmaxDonut(Event* ev) +void ProjectileGenerator::EventmaxDonut(Event *ev) { m_fMaxDonut = ev->GetFloat(1); } -void ProjectileGenerator::EventminDonut(Event* ev) +void ProjectileGenerator::EventminDonut(Event *ev) { - m_fMinDonut = ev->GetFloat(1); + m_fMinDonut = ev->GetFloat(1); } void ProjectileGenerator::EventarcDonut(Event *ev) @@ -445,6 +861,45 @@ void ProjectileGenerator::Archive(Archiver& arc) arc.ArchiveObjectPointer((Class **)&m_pCurrent); } +/*QUAKED ProjectileGenerator_Projectile (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) LaunchSound x TargetRandom StartOn FlipYaw FlipRoll TargetPlayer HideModel + + Allows you to launch projectiles without the need for actual AI. Useful for faking large battles. + Here are the params: + + ID + Model (Defaults to bazooka weapon) + Projectile (Defaults to bazooka projectile) + MinDuration (Min burst cycle duration) + MaxDuration (Max burst cycle duration) + Cycles (0=infinite) + MinNumShots (Minimum # of shots per cycle) + MaxNumShots (Maximum # of shots per cycle) + + MinDelay (min amount of time between cycles) + MaxDelay (max amount of time between cycles) + Accuracy (accuracy measured in feet. 0-25 feet range) + FireOnStartUp (defaults to 1. This flag tells the PG to fire immediately when turned on. Then do its delay from then on.) + + IsDonut (indicates to use donut to calculate impact location) + Arc (mindistance from player) + maxDonut (maxdistance from player) + launchsound (Defaults to no sound) + + preimpactsound (Defaults to no sound) + preimpactsoundtime (Time before impact to begin preimpact sound) + preimpactsoundprob (Chance of an impact sound being played. 0..1 range ) + + Here are some useful script commands: + + $ TurnOn + $ TurnOff + $ playpreimpact ( plays the preimpact sound immediately ) + $ gettargetentity ( return the entity that is targeted ) + $ isturnedon ( is the projectil generator turned on? ) + +******************************************************************************/ + CLASS_DECLARATION(ProjectileGenerator, ProjectileGenerator_Projectile, "ProjectileGenerator_Projectile") { {&EV_Weapon_SetProjectile, &ProjectileGenerator_Projectile::SetProjectileModel }, {&EV_PG_isDonut, &ProjectileGenerator_Projectile::EventisDonut }, @@ -466,8 +921,8 @@ ProjectileGenerator_Projectile::ProjectileGenerator_Projectile() m_sProjectileModel = "models/projectiles/bazookashell.tik"; setModel("models/weapons/bazooka.tik"); - m_sPreImpactSound = ""; - m_fImpactSoundTime = 1; + m_sPreImpactSound = ""; + m_fImpactSoundTime = 1; m_fImpactSoundProbability = 0; } @@ -496,9 +951,95 @@ void ProjectileGenerator_Projectile::SetProjectileModel(Event *ev) m_sProjectileModel = ev->GetString(1); } +float ProjectileGenerator_Projectile::EstimateImpactTime( + const Vector& targetOrigin, const Vector& fromOrigin, float speed +) const +{ + Vector delta = fromOrigin - targetOrigin; + + return delta.length() / speed; +} + bool ProjectileGenerator_Projectile::Attack(int count) { - // FIXME: unimplemented + Projectile *proj; + static int NukePlayer = 0; + Vector dir(0, 0, 1); + float speed = 500; + + Vector muzzlePos = origin; + GetMuzzlePos(muzzlePos); + + if (m_pCurrent) { + m_vTargetOrg = GetTargetPos(m_pCurrent); + + if (m_bIsDonut) { + Entity *playerTarget = G_FindTarget(this, "player"); + + if (playerTarget) { + if (playerTarget->takedamage) { + if (!Q_stricmp(targetname, "artillerykiller")) { + NukePlayer++; + } + } else { + NukePlayer = 0; + } + + if (NukePlayer > 2) { + m_vTargetOrg = playerTarget->origin; + muzzlePos = playerTarget->origin; + muzzlePos[2] += 256; + NukePlayer = 0; + } else { + muzzlePos = m_vTargetOrg; + muzzlePos[2] += random() * 500.0 + 500.0; + } + } else { + muzzlePos = m_vTargetOrg; + muzzlePos[2] += 1000.0; + } + } + + dir = m_vTargetOrg - muzzlePos; + dir.normalize(); + + Vector newAngles; + VectorToAngles(dir, newAngles); + + if (ShouldRotateYaw()) { + newAngles.setYaw(newAngles.yaw() + 180); + } + + if (ShouldRotateRoll()) { + newAngles.setRoll(newAngles.roll() + 180); + } + + setAngles(newAngles); + } else { + AngleVectors(angles, dir, NULL, NULL); + } + + Fire(); + TryLaunchSound(); + + proj = ProjectileAttack(muzzlePos, dir, this, m_sProjectileModel, 1.0, speed); + + if (proj->flags & FL_THINK) { + gi.DPrintf("Projectile used is thinking...pre-impact sound cannot be predicted.\n"); + return true; + } + + if (G_Random() <= m_fImpactSoundProbability && m_sPreImpactSound.length()) { + float time; + + time = EstimateImpactTime(m_vTargetOrg, muzzlePos, speed); + time -= 1.0; + + if (time > 0) { + PostEvent(EV_PG_PlayPreImpactSound, time); + } + } + return true; } @@ -512,6 +1053,36 @@ void ProjectileGenerator_Projectile::Archive(Archiver& arc) arc.ArchiveFloat(&m_fImpactSoundProbability); } +/*QUAKED ProjectileGenerator_Gun (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) LaunchSound x TargetRandom StartOn FlipYaw FlipRoll TargetPlayer HideModel + + Allows you to launch projectiles without the need for actual AI. Useful for faking large battles. + Here are the params: + + ID + MinDuration (Min burst cycle duration) + MaxDuration (Max burst cycle duration) + Cycles (0=infinite) + MinNumShots (Minimum # of shots per cycle) + MaxNumShots (Maximum # of shots per cycle) + + MinDelay (min amount of time between cycles) + MaxDelay (max amount of time between cycles) + Accuracy (accuracy measured in feet. 0-25 feet range) + launchsound (Defaults to no sound) + FireOnStartUp (defaults to 1. This flag tells the PG to fire immediately when turned on. Then do its delay from then on.) + + bulletLarge <0,1,2,3> (whether to fire normal, rifle, artillery or larger bullets) + tracerSpeed <0,2> (scale factor for tracer speed) + + Here are some useful script commands: + + $ TurnOn + $ TurnOff + $ gettargetentity ( return the entity that is targeted ) + $ isturnedon ( is the projectil generator turned on? ) + +******************************************************************************/ + Event EV_PG_SetFakeBullets( "fakebullets", EV_DEFAULT, @@ -540,25 +1111,25 @@ CLASS_DECLARATION(ProjectileGenerator, ProjectileGenerator_Gun, "ProjectileGener ProjectileGenerator_Gun::ProjectileGenerator_Gun() { - m_fBulletRange = 4000; - m_fBulletDamage = 40; - m_iBulletCount = 1; - m_vBulletSpread = Vector(40, 40, 0); - m_iTracerFrequency = 0; - m_iBulletLarge = 0; - m_iMeansOfDeath = MOD_BULLET; - m_fBulletThroughWood = 0; - m_fBulletThroughMetal = 0; - m_iBulletKnockback = 0; - m_iAttackCount = 0; - m_fFireDelay = 1; - m_fTracerSpeed = 1.0; - m_bFakeBullets = 0; + m_fBulletRange = 4000; + m_fBulletDamage = 40; + m_iBulletCount = 1; + m_vBulletSpread = Vector(40, 40, 0); + m_iTracerFrequency = 0; + m_iBulletLarge = 0; + m_iMeansOfDeath = MOD_BULLET; + m_fBulletThroughWood = 0; + m_fBulletThroughMetal = 0; + m_iBulletKnockback = 0; + m_iAttackCount = 0; + m_fFireDelay = 1; + m_fTracerSpeed = 1.0; + m_bFakeBullets = 0; } void ProjectileGenerator_Gun::SetFireDelay(Event *ev) { - m_fFireDelay = ev->GetFloat(1); + m_fFireDelay = ev->GetFloat(1); } void ProjectileGenerator_Gun::SetMeansOfDeath(Event *ev) @@ -573,7 +1144,7 @@ void ProjectileGenerator_Gun::SetBulletThroughWood(Event *ev) void ProjectileGenerator_Gun::SetBulletThroughMetal(Event *ev) { - m_fBulletThroughMetal = ev->GetFloat(1); + m_fBulletThroughMetal = ev->GetFloat(1); } void ProjectileGenerator_Gun::SetBulletKnockback(Event *ev) @@ -624,28 +1195,111 @@ void ProjectileGenerator_Gun::SetBulletRange(Event *ev) bool ProjectileGenerator_Gun::Attack(int count) { - // FIXME: unimplemented - return true; + Vector dir; + Vector right, up; + Vector muzzlePos; + int iTracerCount = 0; + + if (ShouldPlayFireSound() && m_fLastShotTime + m_fFireDelay > level.time) { + return false; + } + + GetMuzzlePos(muzzlePos); + + if (m_pCurrent) { + dir = m_vTargetOrg - muzzlePos; + dir.normalize(); + + Vector newAngles; + VectorToAngles(dir, newAngles); + + AngleVectors(newAngles, NULL, right, up); + + if (ShouldRotateYaw()) { + newAngles.setYaw(newAngles.yaw() + 180); + } + + if (ShouldRotateRoll()) { + newAngles.setRoll(newAngles.roll() + 180); + } + + setAngles(newAngles); + } else { + AngleVectors(angles, dir, right, up); + } + + int iTracerFrequency = 0; + + m_iAttackCount += count; + if (!m_iTracerFrequency) { + m_iTracerFrequency = 4; + } + + if (!(m_iAttackCount % m_iTracerFrequency)) { + m_iAttackCount = 0; + iTracerFrequency = count; + } + + if (ShouldPlayFireSound()) { + Fire(); + } + + TryLaunchSound(); + + if (m_bFakeBullets) { + FakeBulletAttack( + muzzlePos, + muzzlePos, + dir, + right, + up, + m_fBulletRange, + m_fBulletDamage, + m_iBulletLarge, + m_vBulletSpread, + count, + this, + iTracerFrequency, + &iTracerCount, + m_fTracerSpeed + ); + } else { + BulletAttack( + muzzlePos, + muzzlePos, + dir, + right, + up, + m_fBulletRange, + m_fBulletDamage, + m_iBulletLarge, + m_iBulletKnockback, + 0, + m_iMeansOfDeath, + m_vBulletSpread, + count, + this, + iTracerFrequency, + &iTracerCount, + m_fBulletThroughWood, + m_fBulletThroughMetal, + NULL, + m_fTracerSpeed + ); + } + + return true; +} + +bool ProjectileGenerator_Gun::TickWeaponAnim() +{ + return m_fLastShotTime + m_fFireDelay < level.time; } void ProjectileGenerator_Gun::TickCycle(Event *ev) { - if (!m_bIsTurnedOn) { - return; - } - - m_fCurrentTime += level.frametime * m_fShotsPerSec; - if (m_fCurrentTime >= 1.f) - { - float f = floor(m_fCurrentTime); - if (Attack(floor(f))) - { - m_fCurrentTime -= floor(f); - } - - } - - PostEvent(EV_TickCycle, 0.01f); + ProjectileGenerator::TickCycle(ev); + TickWeaponAnim(); } void ProjectileGenerator_Gun::Archive(Archiver& arc) @@ -668,6 +1322,41 @@ void ProjectileGenerator_Gun::Archive(Archiver& arc) arc.ArchiveFloat(&m_fTracerSpeed); } +/*QUAKED ProjectileGenerator_Heavy (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) LaunchSound x TargetRandom StartOn FlipYaw FlipRoll TargetPlayer HideModel + + Allows you to launch projectiles without the need for actual AI. Useful for faking large battles. + Here are the params: + + ID + Model (Defaults to bazooka weapon) + Projectile (Defaults to bazooka projectile) + MinDuration (Min burst cycle duration) + MaxDuration (Max burst cycle duration) + Cycles (0=infinite) + MinNumShots (Minimum # of shots per cycle) + MaxNumShots (Maximum # of shots per cycle) + + MinDelay (min amount of time between cycles) + MaxDelay (max amount of time between cycles) + Accuracy (accuracy measured in feet. 0-25 feet range) + + FireOnStartUp (defaults to 1. This flag tells the PG to fire immediately when turned on. Then do its delay from then on.) + + IsDonut (indicates to use donut to calculate impact location) + Arc (mindistance from player) + maxDonut (maxdistance from player) + launchsound (Defaults to no sound) + + Here are some useful script commands: + + $ TurnOn + $ TurnOff + $ gettargetentity ( return the entity that is targeted ) + $ isturnedon ( is the projectil generator turned on? ) + +******************************************************************************/ + CLASS_DECLARATION(ProjectileGenerator, ProjectileGenerator_Heavy, "ProjectileGenerator_Heavy") { {&EV_Weapon_SetProjectile, &ProjectileGenerator_Heavy::SetProjectileModel}, {NULL, NULL } @@ -690,8 +1379,67 @@ void ProjectileGenerator_Heavy::SetProjectileModel(Event *ev) bool ProjectileGenerator_Heavy::Attack(int count) { - // FIXME: unimplemented - return true; + static int NukePlayer = 0; + Vector dir(0, 0, 1); + float speed = 500; + + Vector muzzlePos = origin; + GetMuzzlePos(muzzlePos); + + if (m_pCurrent) { + m_vTargetOrg = GetTargetPos(m_pCurrent); + + if (m_bIsDonut) { + Entity *playerTarget = G_FindTarget(this, "player"); + + if (playerTarget) { + if (playerTarget->takedamage) { + if (!Q_stricmp(targetname, "artillerykiller")) { + NukePlayer++; + } + } else { + NukePlayer = 0; + } + + if (NukePlayer > 2) { + m_vTargetOrg = playerTarget->origin; + muzzlePos = playerTarget->origin; + muzzlePos[2] += 256; + NukePlayer = 0; + } else { + muzzlePos = m_vTargetOrg; + muzzlePos[2] += random() * 1000.0 + 500.0; + } + } else { + muzzlePos = m_vTargetOrg; + muzzlePos[2] += 2000.0; + } + } + + dir = m_vTargetOrg - muzzlePos; + dir.normalize(); + + Vector newAngles; + VectorToAngles(dir, newAngles); + + if (ShouldRotateYaw()) { + newAngles.setYaw(newAngles.yaw() + 180); + } + + if (ShouldRotateRoll()) { + newAngles.setRoll(newAngles.roll() + 180); + } + + setAngles(newAngles); + } else { + AngleVectors(angles, dir, NULL, NULL); + } + + TryLaunchSound(); + // spawn the projectile + HeavyAttack(muzzlePos, dir, m_sProjectileModel, speed, this, NULL); + + return true; } void ProjectileGenerator_Heavy::Archive(Archiver& arc) @@ -701,21 +1449,171 @@ void ProjectileGenerator_Heavy::Archive(Archiver& arc) arc.ArchiveString(&m_sProjectileModel); } -Event EV_DestroyModel("DestroyModel", EV_DEFAULT, "s", "DestroyModel", 0); -Event EV_UsedModel("UsedModel", EV_DEFAULT, "s", "UsedModel", 0); -Event EV_ExplosionSound("ExplosionSound", EV_DEFAULT, "s", "ExplosionSound", 0); -Event EV_ActivateSound("ActivateSound", EV_DEFAULT, "s", "ActivateSound", 0); -Event EV_TickSound("TickSound", EV_DEFAULT, "s", "TickSound", 0); -Event EV_SetDamage("SetDamage", EV_DEFAULT, "f", "Damage", 0); -Event EV_Radius("Radius", EV_DEFAULT, "f", "Radius", 0); -Event EV_StopWatchDuration("StopWatchDuration", EV_DEFAULT, "f", "StopWatchDuration", 0); -Event EV_SetThread("setthread", EV_DEFAULT, "s", "thread", "Set the thread to execute when this object is used"); -Event EV_SetUseThread("setusethread", EV_DEFAULT, "s", "thread", "Set the thread to execute when this object is used"); -Event EV_DoExplosion("Explode", EV_DEFAULT, NULL, NULL, "Cause the explosion to happen."); -Event EV_SetTriggered("triggered", EV_DEFAULT, "i", "0 or 1", "Set the triggered status"); -Event EV_SetExplosionEffect("explosioneffect", EV_DEFAULT, "s", "effect model", "Set the explosion effect model"); -Event EV_SetExplosionOffset("explosionoffset", EV_DEFAULT, "v", "offset vector", "Set the explosion offset"); -Event EV_BlowUp("BlowUp", EV_DEFAULT, NULL, NULL, NULL); +/*QUAKED ThrobbingBox_explosive (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel + + Explosive throbbing box. Connect to the object you want to make explode. + + ReplaceModel - check this if you want the destroy model to replace the model instead of doing + a model switch. + + + Parameters: + Model - name of pulse model (default=items/pulse_explosive.tik") + UsedModel - name of non-pulse version (default=items/explosive.tik") + ExplosionSound - name of explosion sound (default=explode_flak88) + ActivateSound - name of activation sound (default=plantbomb) + TickSound - name of 'ticking' sound (default=bombtick) + Damage - amount of damage to do (default=300) + radius - radius to do the damage (default=300) + stopwatchduration - how long should the stopwatch go (default=5 seconds) + DestroyModel - name of model to switch target to. + setthread - name of thread to call when the explosion happens... + setusethread - name of thread to call when explosive was placed. + explosionpos - vector of the position the explosion should occur + + Note: + * Set stopwatchduration to 0 to prevent the explosion and stopwatch from happening. + * You may then send the Explode event to this object to make the explosion happen. + + --------------------------------------------------------------------------------------------- + +*/ + +Event EV_DestroyModel +( + "DestroyModel", + EV_DEFAULT, + "s", + "DestroyModel", + NULL, + EV_NORMAL +); +Event EV_UsedModel +( + "UsedModel", + EV_DEFAULT, + "s", + "UsedModel", + NULL, + EV_NORMAL +); +Event EV_ExplosionSound +( + "ExplosionSound", + EV_DEFAULT, + "s", + "ExplosionSound", + NULL, + EV_NORMAL +); +Event EV_ActivateSound +( + "ActivateSound", + EV_DEFAULT, + "s", + "ActivateSound", + NULL, + EV_NORMAL +); +Event EV_TickSound +( + "TickSound", + EV_DEFAULT, + "s", + "TickSound", + NULL, + EV_NORMAL +); +Event EV_SetDamage +( + "SetDamage", + EV_DEFAULT, + "f", + "Damage", + NULL, + EV_NORMAL +); +Event EV_Radius +( + "Radius", + EV_DEFAULT, + "f", + "Radius", + NULL, + EV_NORMAL +); +Event EV_StopWatchDuration +( + "StopWatchDuration", + EV_DEFAULT, + "f", + "StopWatchDuration", + NULL, + EV_NORMAL +); +Event EV_SetThread +( + "setthread", + EV_DEFAULT, + "s", + "thread", + "Set the thread to execute when this object is used", + EV_NORMAL +); +Event EV_SetUseThread +( + "setusethread", + EV_DEFAULT, + "s", + "thread", + "Set the thread to execute when this object is used", + EV_NORMAL +); +Event EV_DoExplosion +( + "Explode", + EV_DEFAULT, + NULL, + NULL, + "Cause the explosion to happen.", + EV_NORMAL +); +Event EV_SetTriggered +( + "triggered", + EV_DEFAULT, + "i", + "triggered", + "Set the triggered status (0 or 1)", + EV_NORMAL +); +Event EV_SetExplosionEffect +( + "explosioneffect", + EV_DEFAULT, + "s", + "effectModel", + "Set the explosion effect model", + EV_NORMAL +); +Event EV_SetExplosionOffset +( + "explosionoffset", + EV_DEFAULT, + "v", + "offset", + "Set the explosion offset", + EV_NORMAL +); +Event EV_BlowUp +( + "BlowUp", + EV_DEFAULT, + NULL, + NULL, + NULL, + EV_NORMAL +); CLASS_DECLARATION(Animate, ThrobbingBox_Explosive, "ThrobbingBox_Explosive") { {&EV_Use, &ThrobbingBox_Explosive::OnUse }, @@ -740,23 +1638,28 @@ ThrobbingBox_Explosive::ThrobbingBox_Explosive() { if (LoadingSavegame) { return; - } + } - setModel("items\\\\pulse_explosive.tik"); - m_sUsedModel = "items/explosive.tik"; - m_sSound = "explose_flak88"; + setModel("items\\\\pulse_explosive.tik"); + m_sUsedModel = "items/explosive.tik"; + m_sSound = "explode_flak88"; m_sActivateSound = "plantbomb"; - m_sTickSound = "bombtick"; + m_sTickSound = "bombtick"; - m_bUsed = false; - m_fExplosionDamage = 300; - m_fRadius = 300; + m_bUsed = false; + m_fExplosionDamage = 300; + m_fRadius = 300; m_fStopwatchDuration = 5; m_sEffect = "emitters/mortar_higgins.tik"; m_vOffset = Vector(0, 0, 0); } +bool ThrobbingBox_Explosive::ShouldDoExplosion() +{ + return m_fStopwatchDuration; +} + void ThrobbingBox_Explosive::SetExplosionOffset(Event *ev) { m_vOffset = ev->GetVector(1); @@ -774,38 +1677,27 @@ void ThrobbingBox_Explosive::SetTriggered(Event *ev) void ThrobbingBox_Explosive::DoExplosion(Event *ev) { - SpawnArgs sp; - ScriptModel* spawned; + SpawnArgs sp; + ScriptModel *spawned; sp.setArg("model", m_sEffect); sp.setArg("origin", va("%f %f %f", origin.x, origin.y, origin.z)); sp.setArg("classname", "ScriptModel"); - if (target.length()) - { - SimpleEntity* targetEnt = G_FindTarget(NULL, target.c_str()); - if (targetEnt) - { + if (target.length()) { + SimpleEntity *targetEnt = G_FindTarget(NULL, target.c_str()); + if (targetEnt) { sp.setArg("origin", va("%f %f %f", targetEnt->origin.x, targetEnt->origin.y, targetEnt->origin.z)); } } - spawned = static_cast(sp.Spawn()); - if (spawned) - { + spawned = static_cast(sp.Spawn()); + if (spawned) { spawned->NewAnim("start"); spawned->setSolidType(SOLID_NOT); } - RadiusDamage( - origin + Vector(0, 0, 128), - this, - this, - m_fExplosionDamage, - this, - MOD_EXPLOSION, - m_fRadius - ); + RadiusDamage(origin + Vector(0, 0, 128), this, this, m_fExplosionDamage, this, MOD_EXPLOSION, m_fRadius); Sound(m_sSound, CHAN_BODY); @@ -815,26 +1707,20 @@ void ThrobbingBox_Explosive::DoExplosion(Event *ev) void ThrobbingBox_Explosive::SetUseThread(Event *ev) { - if (ev->IsFromScript()) - { + if (ev->IsFromScript()) { m_useThread.SetThread(ev->GetValue(1)); - } - else - { + } else { m_useThread.Set(ev->GetString(1)); } } void ThrobbingBox_Explosive::SetThread(Event *ev) { - if (ev->IsFromScript()) - { - m_thread.SetThread(ev->GetValue(1)); - } - else - { + if (ev->IsFromScript()) { + m_thread.SetThread(ev->GetValue(1)); + } else { m_thread.Set(ev->GetString(1)); - } + } } void ThrobbingBox_Explosive::SetStopWatchDuration(Event *ev) @@ -859,122 +1745,90 @@ void ThrobbingBox_Explosive::TickSound(Event *ev) void ThrobbingBox_Explosive::ActivateSound(Event *ev) { - m_sActivateSound = ev->GetString(1); + m_sActivateSound = ev->GetString(1); } void ThrobbingBox_Explosive::ExplosionSound(Event *ev) { - m_sSound = ev->GetString(1); + m_sSound = ev->GetString(1); } void ThrobbingBox_Explosive::UsedModel(Event *ev) { - m_sUsedModel = ev->GetString(1); + m_sUsedModel = ev->GetString(1); } void ThrobbingBox_Explosive::SetDestroyModel(Event *ev) { - m_sDestroyedModel = ev->GetString(1); + m_sDestroyedModel = ev->GetString(1); } void ThrobbingBox_Explosive::OnBlowUp(Event *ev) { - Player* player; - Entity* targetEnt; - ScriptModel* mdl; + Player *player; + Entity *targetEnt; + ScriptModel *mdl; StopLoopSound(); setSolidType(SOLID_NOT); - player = static_cast(G_FindTarget(this, "player")); + player = static_cast(G_FindTarget(this, "player")); if (player) { // clear the player's stopwatch player->SetStopwatch(0); } - if (target.length() && (targetEnt = static_cast(G_FindTarget(NULL, target.c_str()))) && m_sDestroyedModel.length()) - { - if (spawnflags & TBE_SPAWNFLAG_DESTROYED_MODEL) - { - SpawnArgs sp; + if (target.length() && (targetEnt = static_cast(G_FindTarget(NULL, target.c_str()))) + && m_sDestroyedModel.length()) { + if (spawnflags & TBE_SPAWNFLAG_DESTROYED_MODEL) { + SpawnArgs sp; sp.setArg("model", m_sDestroyedModel.c_str()); sp.setArg("origin", va("%f %f %f", targetEnt->origin.x, targetEnt->origin.y, targetEnt->origin.z)); sp.setArg("angles", va("%f %f %f", targetEnt->angles.x, targetEnt->angles.y, targetEnt->angles.z)); sp.setArg("classname", "ScriptModel"); - mdl = static_cast(sp.Spawn()); - if (mdl) - { + mdl = static_cast(sp.Spawn()); + if (mdl) { mdl->NewAnim("start"); - mdl->setSolidType(targetEnt->edict->solid); + mdl->setSolidType(static_cast(targetEnt->getSolidType())); } - if (targetEnt->IsSubclassOfVehicle()) - { - Vehicle* veh = static_cast(targetEnt); - Entity* ent; - int i; + if (targetEnt->IsSubclassOfVehicle()) { + Vehicle *veh = static_cast(targetEnt); + Entity *ent; + int i; // remove all turrets - for (i = 0; i < 8; i++) - { + for (i = 0; i < MAX_TURRETS; i++) { ent = veh->QueryTurretSlotEntity(i); - if (ent) - { + if (ent) { ent->PostEvent(EV_Remove, 0); } } - for (i = 0; i < 32; i++) - { + for (i = 0; i < MAX_PASSENGERS; i++) { ent = veh->QueryPassengerSlotEntity(i); - if (ent) - { + if (ent) { ent->Damage(this, this, ent->health * 2.f, vec_zero, vec_zero, vec_zero, 50, 0, MOD_VEHICLE); } } ent = veh->QueryDriverSlotEntity(0); - if (ent) - { - ent->Damage(this, this, ent->health * 2.f, vec_zero, vec_zero, vec_zero, 50, 0, MOD_VEHICLE); + if (ent) { + ent->takedamage = DAMAGE_YES; + ent->Damage(this, this, ent->health * 2.f, vec_zero, vec_zero, vec_zero, 50, 0, MOD_VEHICLE); } } targetEnt->PostEvent(EV_Remove, 0); - } - else - { + } else { targetEnt->setModel(m_sDestroyedModel.c_str()); } } - if (m_fStopwatchDuration) - { - SpawnArgs sp; - - sp.setArg("model", m_sEffect.c_str()); - sp.setArg("origin", va("%f %f %f", origin.x, origin.y, origin.z)); - sp.setArg("classname", "ScriptModel"); - - if (target.length() > 0 && (targetEnt = static_cast(G_FindTarget(NULL, target.c_str())))) - { - sp.setArg("origin", va("%f %f %f", targetEnt->origin.x, targetEnt->origin.y, targetEnt->origin.z)); - } - - mdl = static_cast(sp.Spawn()); - if (mdl) - { - mdl->NewAnim("start"); - mdl->setSolidType(targetEnt->edict->solid); - } - - RadiusDamage(Vector(), this, this, m_fExplosionDamage, this, MOD_EXPLOSION, m_fRadius); - Sound(m_sSound, CHAN_BODY); - - m_thread.Execute(this); - PostEvent(EV_Remove, 0); + if (ShouldDoExplosion()) { + DoExplosion(NULL); } } @@ -990,25 +1844,23 @@ void ThrobbingBox_Explosive::OnUse(Event *ev) return; } - m_bUsed = true; + m_bUsed = true; - setModel(m_sUsedModel); + setModel(m_sUsedModel); - if (m_fStopwatchDuration > 0) - { - Player* player = static_cast(G_FindTarget(this, "player")); - player->SetStopwatch(m_fStopwatchDuration, SWT_FUSE); - LoopSound(m_sTickSound); - } + if (m_fStopwatchDuration > 0) { + Player *player = static_cast(G_FindTarget(this, "player")); + player->SetStopwatch(m_fStopwatchDuration, SWT_NORMAL); + LoopSound(m_sTickSound); + } - // Play the activation sound - Sound(m_sActivateSound, CHAN_BODY); + // Play the activation sound + Sound(m_sActivateSound, CHAN_BODY); - Unregister(STRING_TRIGGER); - m_useThread.Execute(this); + Unregister(STRING_TRIGGER); + m_useThread.Execute(this); - if (m_fStopwatchDuration > 0) - { + if (m_fStopwatchDuration > 0) { PostEvent(EV_BlowUp, m_fStopwatchDuration); } } @@ -1032,42 +1884,177 @@ void ThrobbingBox_Explosive::Archive(Archiver& arc) m_useThread.Archive(arc); } +/*QUAKED ThrobbingBox_ExplodePlayerFlak88 (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) + + Explosive throbbing box. Connect to the object you want to make explode. + + + Parameters: + Model - name of pulse model (default=items/pulse_explosive.tik") + UsedModel - name of non-pulse version (default=items/explosive.tik") + ExplosionSound - name of explosion sound (default=explode_flak88) + ActivateSound - name of activation sound (default=plantbomb) + TickSound - name of 'ticking' sound (default=bombtick) + Damage - amount of damage to do (default=300) + radius - radius to do the damage (default=300) + stopwatchduration - how long should the stopwatch go (default=5 seconds) + setthread - name of thread to call when the explosion happens... + + --------------------------------------------------------------------------------------------- +*/ + CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerFlak88, "ThrobbingBox_ExplodePlayerFlak88") { {NULL, NULL} }; +ThrobbingBox_ExplodePlayerFlak88::ThrobbingBox_ExplodePlayerFlak88() +{ + spawnflags |= TBE_SPAWNFLAG_DESTROYED_MODEL; + m_sDestroyedModel = "statweapons/flak88_d.tik"; + m_sEffect = "fx/demodamage_flak88.tik"; +} + +/*QUAKED ThrobbingBox_ExplodeFlak88 (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) + + Explosive throbbing box. Connect to the object you want to make explode. + + Parameters: + Model - name of pulse model (default=items/pulse_explosive.tik") + UsedModel - name of non-pulse version (default=items/explosive.tik") + ExplosionSound - name of explosion sound (default=explode_flak88) + ActivateSound - name of activation sound (default=plantbomb) + TickSound - name of 'ticking' sound (default=bombtick) + Damage - amount of damage to do (default=300) + radius - radius to do the damage (default=300) + stopwatchduration - how long should the stopwatch go (default=5 seconds) + setthread - name of thread to call when the explosion happens... + + --------------------------------------------------------------------------------------------- +*/ + CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodeFlak88, "ThrobbingBox_ExplodeFlak88") { {NULL, NULL} }; +ThrobbingBox_ExplodeFlak88::ThrobbingBox_ExplodeFlak88() +{ + m_sDestroyedModel = "statweapons/flak88_d.tik"; + m_sEffect = "fx/demodamage_flak88.tik"; +} + +/*QUAKED ThrobbingBox_ExplodeNebelwerfer (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel + + Explosive throbbing box. Connect to the object you want to make explode. + + Parameters: + Model - name of pulse model (default=items/pulse_explosive.tik") + UsedModel - name of non-pulse version (default=items/explosive.tik") + ExplosionSound - name of explosion sound (default=explode_flak88) + ActivateSound - name of activation sound (default=plantbomb) + TickSound - name of 'ticking' sound (default=bombtick) + Damage - amount of damage to do (default=300) + radius - radius to do the damage (default=300) + stopwatchduration - how long should the stopwatch go (default=5 seconds) + setthread - name of thread to call when the explosion happens... + + --------------------------------------------------------------------------------------------- +*/ + CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodeNebelwerfer, "ThrobbingBox_ExplodeNebelwerfer") { {NULL, NULL} }; -CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerNebelwerfer, "ThrobbingBox_ExplodeNebelwerfer") { +ThrobbingBox_ExplodeNebelwerfer::ThrobbingBox_ExplodeNebelwerfer() +{ + m_sDestroyedModel = "statweapons/nebelwerfer_d.tik"; +} + +/*QUAKED ThrobbingBox_ExplodePlayerNebelwerfer (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel + + Explosive throbbing box. Connect to the object you want to make explode. + + Parameters: + Model - name of pulse model (default=items/pulse_explosive.tik") + UsedModel - name of non-pulse version (default=items/explosive.tik") + ExplosionSound - name of explosion sound (default=explode_flak88) + ActivateSound - name of activation sound (default=plantbomb) + TickSound - name of 'ticking' sound (default=bombtick) + Damage - amount of damage to do (default=300) + radius - radius to do the damage (default=300) + stopwatchduration - how long should the stopwatch go (default=5 seconds) + setthread - name of thread to call when the explosion happens... + + --------------------------------------------------------------------------------------------- +*/ + +CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerNebelwerfer, "ThrobbingBox_ExplodePlayerNebelwerfer") { {NULL, NULL} }; +ThrobbingBox_ExplodePlayerNebelwerfer::ThrobbingBox_ExplodePlayerNebelwerfer() +{ + spawnflags |= TBE_SPAWNFLAG_DESTROYED_MODEL; + m_sDestroyedModel = "statweapons/nebelwerfer_d.tik"; +} + +/*QUAKED ThrobbingBox_Stickybomb (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel WetFuse + + Stickybomb throbbing box. Connect to the object you want to make explode. + When WetFuse is selected, the bomb will fizzle out and can only be destroyed by shooting it. + + Parameters: + ExplosionSound - name of explosion sound (default=explode_flak88) + Damage - amount of damage to do (default=300) + radius - radius to do the damage (default=300) + stopwatchduration - how long should the fuse go (default=5 seconds) + setthread - name of thread to call when the explosion happens... + DestroyModel - name of model to switch target to. + setusethread - name of thread to call when stickybomb is placed. + + --------------------------------------------------------------------------------------------- +*/ + Event EV_StickyBombWet("stickybombwet", EV_DEFAULT, NULL, NULL, NULL); -CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_Stickybomb, "ThrobbingBox_ExplodeNebelwerfer") { +CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_Stickybomb, "ThrobbingBox_Stickybomb") { {&EV_Damage, &ThrobbingBox_Stickybomb::OnBlowUp }, {&EV_Use, &ThrobbingBox_Stickybomb::OnStickyBombUse}, {&EV_StickyBombWet, &ThrobbingBox_Stickybomb::OnStickyBombWet}, {NULL, NULL } }; +ThrobbingBox_Stickybomb::ThrobbingBox_Stickybomb() +{ + if (LoadingSavegame) { + return; + } + + setModel("items/pulse_stickybomb.tik"); + m_sUsedModel = "items/stickybomb.tik"; + m_sSound = "explode_flak88"; + m_sActivateSound = "stickybomb_plant"; + m_sTickSound = "stickybomb_fuse"; + + health = 10; + m_fStopwatchStartTime = 0; + + setSolidType(SOLID_BBOX); + takedamage = DAMAGE_NO; + setContents(CONTENTS_WEAPONCLIP); +} + void ThrobbingBox_Stickybomb::OnStickyBombWet(Event *ev) { - Player* player; + Player *player; CancelEventsOfType(EV_BlowUp); NewAnim("idle_fuse_wet"); + StopLoopSound(); Sound("stickybomb_fuse_out", CHAN_BODY); - player = static_cast(G_FindTarget(this, "player")); + player = static_cast(G_FindTarget(this, "player")); player->SetStopwatch(0, SWT_NORMAL); - player->SetStopwatch(m_fStopwatchDuration - (level.svsFloatTime - m_fStopwatchStartTime), SWT_FUSE); + player->SetStopwatch(m_fStopwatchDuration - (level.svsFloatTime - m_fStopwatchStartTime), SWT_FUSE_WET); } void ThrobbingBox_Stickybomb::OnStickyBombUse(Event *ev) @@ -1077,14 +2064,14 @@ void ThrobbingBox_Stickybomb::OnStickyBombUse(Event *ev) } setSolidType(SOLID_BBOX); + setContents(CONTENTS_WEAPONCLIP); takedamage = DAMAGE_YES; - m_bUsed = true; + m_bUsed = true; setModel(m_sUsedModel); - if (m_fStopwatchDuration > 0) - { - Player* player = static_cast(G_FindTarget(this, "player")); + if (m_fStopwatchDuration > 0) { + Player *player = static_cast(G_FindTarget(this, "player")); player->SetStopwatch(m_fStopwatchDuration, SWT_FUSE); LoopSound(m_sTickSound); m_fStopwatchStartTime = level.svsFloatTime; @@ -1097,9 +2084,8 @@ void ThrobbingBox_Stickybomb::OnStickyBombUse(Event *ev) m_useThread.Execute(this); PostEvent(EV_BlowUp, m_fStopwatchDuration); - if (spawnflags & TBE_SPAWNFLAG_MAKE_WET) - { - PostEvent(EV_StickyBombWet, m_fStopwatchDuration * 0.5f * random() + m_fStopwatchDuration * 0.25f); + if (spawnflags & TBE_SPAWNFLAG_MAKE_WET) { + PostEvent(EV_StickyBombWet, G_Random(m_fStopwatchDuration / 2.0) + m_fStopwatchDuration / 4.0); } NewAnim("idle_fuse_lit"); @@ -1112,13 +2098,68 @@ void ThrobbingBox_Stickybomb::Archive(Archiver& arc) arc.ArchiveFloat(&m_fStopwatchStartTime); } -Event EV_Complete("Complete", EV_DEFAULT, NULL, NULL, "Complete this objective."); +/*QUAKED func_objective (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) StartOn -Event EV_SetCurrent("SetCurrent", EV_DEFAULT, NULL, NULL, "Set this objective as current."); + object used to simplify placing objectives. You may optionally connect this object to the + target you want to use for the compass position.... -Event EV_SetText("Text", EV_DEFAULT, "s", "text", "Set current text."); + Checkboxes: + StartOn - check this if you want this objective to be displayed when the level first loads -Event EV_SetObjectiveNbr("ObjectiveNbr", EV_DEFAULT, "i", "index", "Sets the objective number."); + Parameters: + + ObjectiveNbr + Text + + Events: + TurnOn + TurnOff + Complete + Text + SetCurrent + +//--------------------------------------------------------------------------------------------- +*/ + +Event EV_Complete +( + "Complete", + EV_DEFAULT, + NULL, + NULL, + "Complete this objective.", + EV_NORMAL +); + +Event EV_SetCurrent +( + "SetCurrent", + EV_DEFAULT, + NULL, + NULL, + "Set this objective as current.", + EV_NORMAL +); + +Event EV_SetText +( + "Text", + EV_DEFAULT, + "s", + "text", + "Set current text.", + EV_NORMAL +); + +Event EV_SetObjectiveNbr +( + "ObjectiveNbr", + EV_DEFAULT, + "i", + "index", + "Sets the objective number.", + EV_NORMAL +); CLASS_DECLARATION(Entity, Objective, "func_objective") { {&EV_TurnOn, &Objective::TurnOn }, @@ -1202,131 +2243,289 @@ int Objective::GetObjectiveIndex() const return m_iObjectiveIndex; } +/*QUAKED func_fencepost (0 1 0) ? + fencepost that can be blown up + "health" how much health the fence post should have (default 50) +//--------------------------------------------------------------------------------------------- +*/ + CLASS_DECLARATION(Entity, FencePost, "func_fencepost") { - {&EV_Killed, NULL}, - {NULL, NULL} + {&EV_Killed, &FencePost::Killed}, + {NULL, NULL } }; -Event EV_SetEnemyName("enemyname", EV_DEFAULT, "s", "enemyname", ""); -Event EV_SetEnemyName2("enemyname", EV_DEFAULT, "s", "enemyname", "", EV_GETTER); -Event EV_GetEnemyName("enemyname", EV_DEFAULT, "s", "enemyname", "", EV_SETTER); -Event EV_Sentient_GetDontDropWeapons("dontdropweapons", EV_DEFAULT, NULL, NULL, "dontdropweapons getter", EV_GETTER); -Event EV_SetDontDropHealth("dontdrophealth", EV_DEFAULT, NULL, NULL, "dontdrophealth setter"); -Event EV_GetDontDropHealth("dontdrophealth", EV_DEFAULT, NULL, NULL, "dontdrophealth getter", EV_GETTER); +FencePost::FencePost() +{ + max_health = 20; + health = 20; + damage_type = MOD_AAGUN; + + if (!LoadingSavegame) { + PostEvent(EV_BecomeSolid, EV_POSTSPAWN); + } + + takedamage = DAMAGE_YES; +} + +void FencePost::Killed(Event *ev) +{ + Vector vMins, vMaxs; + Vector vStart, vEnd; + Vector vCenter; + float fHalf; + + vCenter = mins - maxs; + vCenter *= 0.5; + + if (size.x > size.y) { + if (size.x > size.z) { + if (size.y > size.z) { + fHalf = size.y / 2.f; + } else { + fHalf = size.z / 2.f; + } + + vMins[0] = mins[0]; + vMaxs[0] = maxs[0]; + vMins[1] = vCenter[1]; + vMaxs[1] = vCenter[1]; + vMins[2] = vCenter[2]; + vMaxs[2] = vCenter[2]; + } else { + fHalf = size.x / 2.f; + + vMins[2] = mins[2]; + vMaxs[2] = maxs[2]; + vMins[1] = vCenter[1]; + vMaxs[1] = vCenter[1]; + vMins[0] = vCenter[0]; + vMaxs[0] = vCenter[0]; + } + } else { + if (size.y > size.z) { + if (size.x > size.z) { + fHalf = size.x / 2.f; + } else { + fHalf = size.z / 2.f; + } + + vMins[1] = mins[1]; + vMaxs[1] = maxs[1]; + vMins[0] = vCenter[0]; + vMaxs[0] = vCenter[0]; + vMins[2] = vCenter[2]; + vMaxs[2] = vCenter[2]; + } else { + fHalf = size.y / 2.f; + + vMins[2] = mins[2]; + vMaxs[2] = maxs[2]; + vMins[1] = vCenter[1]; + vMaxs[1] = vCenter[1]; + vMins[0] = vCenter[0]; + vMaxs[0] = vCenter[0]; + } + } + + MatrixTransformVector(vMins, orientation, vStart); + MatrixTransformVector(vMaxs, orientation, vEnd); + + vStart += origin; + vEnd += origin; + + if (fHalf > 255) { + fHalf = 255; + } + + gi.SetBroadcastVisible(vStart, vEnd); + gi.MSG_StartCGM(CGM_FENCEPOST); + gi.MSG_WriteCoord(vStart[0]); + gi.MSG_WriteCoord(vStart[1]); + gi.MSG_WriteCoord(vStart[2]); + gi.MSG_WriteCoord(vEnd[0]); + gi.MSG_WriteCoord(vEnd[1]); + gi.MSG_WriteCoord(vEnd[2]); + gi.MSG_WriteByte((int)fHalf); + gi.MSG_WriteByte(0); + gi.MSG_EndCGM(); + + deadflag = DEAD_DEAD; + + PostEvent(EV_Remove, 0); +} + +Event EV_SetEnemyName +( + "enemyname", + EV_DEFAULT, + "s", + "enemyname", + "", + EV_NORMAL +); +Event EV_SetEnemyName2 +( + "enemyname", + EV_DEFAULT, + "s", + "enemyname", + "", + EV_SETTER +); +Event EV_GetEnemyName +( + "enemyname", + EV_DEFAULT, + "s", + "enemyname", + "", + EV_GETTER +); +Event EV_Sentient_GetDontDropWeapons +( + "dontdropweapons", + EV_DEFAULT, + NULL, + NULL, + "dontdropweapons getter", + EV_GETTER +); +Event EV_SetDontDropHealth +( + "dontdrophealth", + EV_DEFAULT, + NULL, + NULL, + "dontdrophealth setter", + EV_NORMAL +); +Event EV_GetDontDropHealth +( + "dontdrophealth", + EV_DEFAULT, + NULL, + NULL, + "dontdrophealth getter", + EV_GETTER +); CLASS_DECLARATION(SimpleArchivedEntity, AISpawnPoint, "info_aispawnpoint") { - {&EV_Model, &AISpawnPoint::SetModel}, - {&EV_GetModel, &AISpawnPoint::GetModel}, - {&EV_SetHealth2, &AISpawnPoint::SetHealth}, - {&EV_Entity_GetHealth, &AISpawnPoint::GetHealth}, - {&EV_SetEnemyName, &AISpawnPoint::SetEnemyName}, - { - &EV_SetEnemyName2, - &AISpawnPoint::SetEnemyName, - }, - {&EV_GetEnemyName, &AISpawnPoint::GetEnemyName}, - {&EV_Actor_SetAccuracy, &AISpawnPoint::SetAccuracy}, - {&EV_Actor_GetAccuracy, &AISpawnPoint::GetAccuracy}, - {&EV_Actor_SetAmmoGrenade, &AISpawnPoint::SetAmmoGrenade}, - {&EV_Actor_GetAmmoGrenade, &AISpawnPoint::GetAmmoGrenade}, - {&EV_Actor_SetBalconyHeight, &AISpawnPoint::SetBalconyHeight}, - {&EV_Actor_GetBalconyHeight, &AISpawnPoint::GetBalconyHeight}, - {&EV_Actor_SetDisguiseLevel, &AISpawnPoint::SetDisguiseLevel}, - {&EV_Actor_GetDisguiseLevel, &AISpawnPoint::GetDisguiseLevel}, - {&EV_Actor_SetDisguisePeriod2, &AISpawnPoint::SetDisguisePeriod}, - {&EV_Actor_GetDisguisePeriod, &AISpawnPoint::GetDisguisePeriod}, - {&EV_Actor_SetDisguiseRange2, &AISpawnPoint::SetDisguiseRange}, - {&EV_Actor_GetDisguiseRange, &AISpawnPoint::GetDisguiseRange}, - {&EV_Actor_SetEnemyShareRange2, &AISpawnPoint::SetEnemyShareRange}, - {&EV_Actor_GetEnemyShareRange, &AISpawnPoint::GetEnemyShareRange}, - {&EV_Actor_GetFixedLeash, &AISpawnPoint::GetFixedLeash}, - {&EV_Actor_SetFixedLeash2, &AISpawnPoint::SetFixedLeash}, - {&EV_Actor_SetGrenadeAwareness, &AISpawnPoint::SetGrenadeAwareness}, - {&EV_Actor_GetGrenadeAwareness, &AISpawnPoint::GetGrenadeAwareness}, - {&EV_Actor_SetGun, &AISpawnPoint::SetGun}, - {&EV_Actor_GetGun, &AISpawnPoint::GetGun}, + {&EV_Model, &AISpawnPoint::SetModel }, + {&EV_GetModel, &AISpawnPoint::GetModel }, + {&EV_SetHealth2, &AISpawnPoint::SetHealth }, + {&EV_Entity_GetHealth, &AISpawnPoint::GetHealth }, + {&EV_SetEnemyName, &AISpawnPoint::SetEnemyName }, + {&EV_SetEnemyName2, &AISpawnPoint::SetEnemyName }, + {&EV_GetEnemyName, &AISpawnPoint::GetEnemyName }, + {&EV_Actor_SetAccuracy, &AISpawnPoint::SetAccuracy }, + {&EV_Actor_GetAccuracy, &AISpawnPoint::GetAccuracy }, + {&EV_Actor_SetAmmoGrenade, &AISpawnPoint::SetAmmoGrenade }, + {&EV_Actor_GetAmmoGrenade, &AISpawnPoint::GetAmmoGrenade }, + {&EV_Actor_SetBalconyHeight, &AISpawnPoint::SetBalconyHeight }, + {&EV_Actor_GetBalconyHeight, &AISpawnPoint::GetBalconyHeight }, + {&EV_Actor_SetDisguiseLevel, &AISpawnPoint::SetDisguiseLevel }, + {&EV_Actor_GetDisguiseLevel, &AISpawnPoint::GetDisguiseLevel }, + {&EV_Actor_SetDisguisePeriod2, &AISpawnPoint::SetDisguisePeriod }, + {&EV_Actor_GetDisguisePeriod, &AISpawnPoint::GetDisguisePeriod }, + {&EV_Actor_SetDisguiseRange2, &AISpawnPoint::SetDisguiseRange }, + {&EV_Actor_GetDisguiseRange, &AISpawnPoint::GetDisguiseRange }, + {&EV_Actor_SetEnemyShareRange2, &AISpawnPoint::SetEnemyShareRange }, + {&EV_Actor_GetEnemyShareRange, &AISpawnPoint::GetEnemyShareRange }, + {&EV_Actor_GetFixedLeash, &AISpawnPoint::GetFixedLeash }, + {&EV_Actor_SetFixedLeash2, &AISpawnPoint::SetFixedLeash }, + {&EV_Actor_SetGrenadeAwareness, &AISpawnPoint::SetGrenadeAwareness }, + {&EV_Actor_GetGrenadeAwareness, &AISpawnPoint::GetGrenadeAwareness }, + {&EV_Actor_SetGun, &AISpawnPoint::SetGun }, + {&EV_Actor_GetGun, &AISpawnPoint::GetGun }, {&EV_Actor_GetMaxNoticeTimeScale, &AISpawnPoint::GetMaxNoticeTimeScale}, {&EV_Actor_SetMaxNoticeTimeScale, &AISpawnPoint::SetMaxNoticeTimeScale}, - {&EV_Actor_GetSoundAwareness, &AISpawnPoint::GetSoundAwareness}, - {&EV_Actor_SetSoundAwareness, &AISpawnPoint::SetSoundAwareness}, - {&EV_Actor_SetTypeAttack, &AISpawnPoint::SetTypeAttack}, - {&EV_Actor_GetTypeAttack, &AISpawnPoint::GetTypeAttack}, - {&EV_Actor_SetTypeDisguise, &AISpawnPoint::SetTypeDisguise}, - {&EV_Actor_GetTypeDisguise, &AISpawnPoint::GetTypeDisguise}, - {&EV_Actor_SetTypeGrenade, &AISpawnPoint::SetTypeGrenade}, - {&EV_Actor_GetTypeGrenade, &AISpawnPoint::GetTypeGrenade}, - {&EV_Actor_SetTypeIdle, &AISpawnPoint::SetTypeIdle}, - {&EV_Actor_GetTypeIdle, &AISpawnPoint::GetTypeIdle}, - {&EV_Actor_SetPatrolWaitTrigger, &AISpawnPoint::SetPatrolWaitTrigger}, - {&EV_Actor_GetPatrolWaitTrigger, &AISpawnPoint::GetPatrolWaitTrigger}, - {&EV_Actor_SetHearing, &AISpawnPoint::SetHearing}, - {&EV_Actor_GetHearing, &AISpawnPoint::GetHearing}, - {&EV_Actor_GetSight, &AISpawnPoint::GetSight}, - {&EV_Actor_SetSight2, &AISpawnPoint::SetSight}, - {&EV_Actor_SetFov, &AISpawnPoint::SetFov}, - {&EV_Actor_GetFov, &AISpawnPoint::GetFov}, - {&EV_Actor_SetLeash2, &AISpawnPoint::SetLeash}, - {&EV_Actor_GetLeash, &AISpawnPoint::GetLeash}, - {&EV_Actor_SetMinDistance, &AISpawnPoint::SetMinDistance}, - {&EV_Actor_GetMinDistance, &AISpawnPoint::GetMinDistance}, - {&EV_Actor_SetMaxDistance, &AISpawnPoint::SetMaxDistance}, - {&EV_Actor_GetMaxDistance, &AISpawnPoint::GetMaxDistance}, - {&EV_Actor_SetInterval2, &AISpawnPoint::SetInterval}, - {&EV_Actor_GetInterval, &AISpawnPoint::GetInterval}, - {&EV_Sentient_DontDropWeapons, &AISpawnPoint::SetDontDropWeapons}, - {&EV_Sentient_GetDontDropWeapons, &AISpawnPoint::GetDontDropWeapons}, - {&EV_SetDontDropHealth, &AISpawnPoint::SetDontDropHealth}, - {&EV_GetDontDropHealth, &AISpawnPoint::GetDontDropHealth}, - {&EV_Actor_GetFavoriteEnemy, &AISpawnPoint::GetFavoriteEnemy}, - {&EV_Actor_SetFavoriteEnemy2, &AISpawnPoint::SetFavoriteEnemy}, - {&EV_Actor_SetNoSurprise2, &AISpawnPoint::SetNoSurprise}, - {&EV_Actor_GetNoSurprise, &AISpawnPoint::GetNoSurprise}, - {&EV_Actor_SetPatrolPath, &AISpawnPoint::SetPatrolPath}, - {&EV_Actor_GetPatrolPath, &AISpawnPoint::GetPatrolPath}, - {&EV_Actor_SetTurret, &AISpawnPoint::SetTurret}, - {&EV_Actor_GetTurret, &AISpawnPoint::GetTurret}, - {&EV_Actor_SetAlarmNode, &AISpawnPoint::SetAlarmNode}, - {&EV_Actor_GetAlarmNode, &AISpawnPoint::GetAlarmNode}, - {&EV_Actor_SetWeapon, &AISpawnPoint::SetWeapon}, - {&EV_Actor_GetWeapon, &AISpawnPoint::GetWeapon}, - {&EV_SetTarget, &AISpawnPoint::SetTarget}, - {&EV_GetTarget, &AISpawnPoint::GetTarget}, - {&EV_Actor_SetVoiceType, &AISpawnPoint::SetVoiceType}, - {&EV_Actor_GetVoiceType, &AISpawnPoint::GetVoiceType}, - {&EV_Sentient_ForceDropWeapon, &AISpawnPoint::SetForceDropWeapon}, - {&EV_Sentient_GetForceDropWeapon, &AISpawnPoint::GetForceDropWeapon}, - {&EV_Sentient_ForceDropHealth, &AISpawnPoint::SetForceDropHealth}, - {&EV_Sentient_GetForceDropHealth, &AISpawnPoint::GetForceDropHealth}, - {NULL, NULL} + {&EV_Actor_GetSoundAwareness, &AISpawnPoint::GetSoundAwareness }, + {&EV_Actor_SetSoundAwareness, &AISpawnPoint::SetSoundAwareness }, + {&EV_Actor_SetTypeAttack, &AISpawnPoint::SetTypeAttack }, + {&EV_Actor_GetTypeAttack, &AISpawnPoint::GetTypeAttack }, + {&EV_Actor_SetTypeDisguise, &AISpawnPoint::SetTypeDisguise }, + {&EV_Actor_GetTypeDisguise, &AISpawnPoint::GetTypeDisguise }, + {&EV_Actor_SetTypeGrenade, &AISpawnPoint::SetTypeGrenade }, + {&EV_Actor_GetTypeGrenade, &AISpawnPoint::GetTypeGrenade }, + {&EV_Actor_SetTypeIdle, &AISpawnPoint::SetTypeIdle }, + {&EV_Actor_GetTypeIdle, &AISpawnPoint::GetTypeIdle }, + {&EV_Actor_SetPatrolWaitTrigger, &AISpawnPoint::SetPatrolWaitTrigger }, + {&EV_Actor_GetPatrolWaitTrigger, &AISpawnPoint::GetPatrolWaitTrigger }, + {&EV_Actor_SetHearing, &AISpawnPoint::SetHearing }, + {&EV_Actor_GetHearing, &AISpawnPoint::GetHearing }, + {&EV_Actor_GetSight, &AISpawnPoint::GetSight }, + {&EV_Actor_SetSight2, &AISpawnPoint::SetSight }, + {&EV_Actor_SetFov, &AISpawnPoint::SetFov }, + {&EV_Actor_GetFov, &AISpawnPoint::GetFov }, + {&EV_Actor_SetLeash2, &AISpawnPoint::SetLeash }, + {&EV_Actor_GetLeash, &AISpawnPoint::GetLeash }, + {&EV_Actor_SetMinDistance, &AISpawnPoint::SetMinDistance }, + {&EV_Actor_GetMinDistance, &AISpawnPoint::GetMinDistance }, + {&EV_Actor_SetMaxDistance, &AISpawnPoint::SetMaxDistance }, + {&EV_Actor_GetMaxDistance, &AISpawnPoint::GetMaxDistance }, + {&EV_Actor_SetInterval2, &AISpawnPoint::SetInterval }, + {&EV_Actor_GetInterval, &AISpawnPoint::GetInterval }, + {&EV_Sentient_DontDropWeapons, &AISpawnPoint::SetDontDropWeapons }, + {&EV_Sentient_GetDontDropWeapons, &AISpawnPoint::GetDontDropWeapons }, + {&EV_SetDontDropHealth, &AISpawnPoint::SetDontDropHealth }, + {&EV_GetDontDropHealth, &AISpawnPoint::GetDontDropHealth }, + {&EV_Actor_GetFavoriteEnemy, &AISpawnPoint::GetFavoriteEnemy }, + {&EV_Actor_SetFavoriteEnemy2, &AISpawnPoint::SetFavoriteEnemy }, + {&EV_Actor_SetNoSurprise2, &AISpawnPoint::SetNoSurprise }, + {&EV_Actor_GetNoSurprise, &AISpawnPoint::GetNoSurprise }, + {&EV_Actor_SetPatrolPath, &AISpawnPoint::SetPatrolPath }, + {&EV_Actor_GetPatrolPath, &AISpawnPoint::GetPatrolPath }, + {&EV_Actor_SetTurret, &AISpawnPoint::SetTurret }, + {&EV_Actor_GetTurret, &AISpawnPoint::GetTurret }, + {&EV_Actor_SetAlarmNode, &AISpawnPoint::SetAlarmNode }, + {&EV_Actor_GetAlarmNode, &AISpawnPoint::GetAlarmNode }, + {&EV_Actor_SetWeapon, &AISpawnPoint::SetWeapon }, + {&EV_Actor_GetWeapon, &AISpawnPoint::GetWeapon }, + {&EV_SetTarget, &AISpawnPoint::SetTarget }, + {&EV_GetTarget, &AISpawnPoint::GetTarget }, + {&EV_Actor_SetVoiceType, &AISpawnPoint::SetVoiceType }, + {&EV_Actor_GetVoiceType, &AISpawnPoint::GetVoiceType }, + {&EV_Sentient_ForceDropWeapon, &AISpawnPoint::SetForceDropWeapon }, + {&EV_Sentient_GetForceDropWeapon, &AISpawnPoint::GetForceDropWeapon }, + {&EV_Sentient_ForceDropHealth, &AISpawnPoint::SetForceDropHealth }, + {&EV_Sentient_GetForceDropHealth, &AISpawnPoint::GetForceDropHealth }, + {NULL, NULL } }; AISpawnPoint::AISpawnPoint() { - m_iHealth = 100; - m_iAccuracy = 20; - m_iAmmoGrenade = 0; - m_iBalconyHeight = 128; - m_iDisguiseLevel = 1; - m_fDisguisePeriod = 30000; - m_fDisguiseRange = 256; - m_fEnemyShareRange = 0; - m_fFixedLeash = 0.0; - m_fGrenadeAwareness = 20.0; - m_fMaxNoticeTimeScale = 1; - m_fSoundAwareness = 100; - m_bPatrolWaitTrigger = 0; - m_fHearing = 2048; - m_fSight = world->m_fAIVisionDistance; - m_fFov = 90; - m_fLeash = 512; - m_fMinDist = 128.0; - m_fMaxDist = 1024; - m_fInterval = 128.0; - m_bDontDropWeapons = 0; - m_bDontDropHealth = 0; - m_bNoSurprise = 0; - m_bForceDropWeapon = 0; - m_bForceDropHealth = 0; + m_iHealth = 100; + + m_iAccuracy = 20; + m_iAmmoGrenade = 0; + m_iBalconyHeight = 128; + + m_iDisguiseLevel = 1; + m_fDisguisePeriod = 30000; + m_fDisguiseRange = 256; + + m_fEnemyShareRange = 0; + m_fFixedLeash = 0.0; + + m_fGrenadeAwareness = 20.0; + m_fMaxNoticeTimeScale = 1; + m_fSoundAwareness = 100; + + m_bPatrolWaitTrigger = false; + + m_fHearing = 2048; + m_fSight = world->m_fAIVisionDistance; + m_fFov = 90; + m_fLeash = 512; + m_fMinDist = 128.0; + m_fMaxDist = 1024; + m_fInterval = 128.0; + + m_bDontDropWeapons = false; + m_bDontDropHealth = false; + m_bNoSurprise = false; + m_bForceDropWeapon = false; + m_bForceDropHealth = false; } void AISpawnPoint::GetForceDropHealth(Event *ev) @@ -1336,7 +2535,10 @@ void AISpawnPoint::GetForceDropHealth(Event *ev) void AISpawnPoint::SetForceDropHealth(Event *ev) { - // This is a bug on original mohaab (2.30 and 2.40), it should be m_bForceDropHealth + // Fixed in OPM + // This does look like a mistake on original mohaab (2.30 and 2.40) + // it should be m_bForceDropHealth. + // That's the reason why AI often don't drop weapons //m_bForceDropWeapon = ev->GetBoolean(1); m_bForceDropHealth = ev->GetBoolean(1); } @@ -1503,12 +2705,12 @@ void AISpawnPoint::SetFov(Event *ev) void AISpawnPoint::SetSight(Event *ev) { - ev->AddFloat(m_fSight); + m_fSight = ev->GetFloat(1); } void AISpawnPoint::GetSight(Event *ev) { - m_fSight = ev->GetFloat(1); + ev->AddFloat(m_fSight); } void AISpawnPoint::GetHearing(Event *ev) diff --git a/code/fgame/Entities.h b/code/fgame/Entities.h index c40028de..16ed9600 100644 --- a/code/fgame/Entities.h +++ b/code/fgame/Entities.h @@ -26,25 +26,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "animate.h" typedef enum { - CONTROLLER_ALLIES, - CONTROLLER_AXIS, + CONTROLLER_AXIS, + CONTROLLER_ALLIES, CONTROLLER_DRAW } eController; -#define PT_SPAWNFLAG_PLAY_FIRE_SOUND 1 -#define PT_SPAWNFLAG_TARGET_RANDOM 4 -#define PT_SPAWNFLAG_TURN_ON 8 -#define PT_SPAWNFLAG_SET_YAW 16 -#define PT_SPAWNFLAG_SET_ROLL 32 -#define PT_SPAWNFLAG_TARGET_PLAYER 64 -#define PT_SPAWNFLAG_HIDDEN 128 +#define PT_SPAWNFLAG_PLAY_FIRE_SOUND 1 +#define PT_SPAWNFLAG_PLAY_MOTION_SOUND 2 +#define PT_SPAWNFLAG_TARGET_RANDOM 4 +#define PT_SPAWNFLAG_TURN_ON 8 +#define PT_SPAWNFLAG_ROTATE_YAW 16 +#define PT_SPAWNFLAG_ROTATE_ROLL 32 +#define PT_SPAWNFLAG_TARGET_PLAYER 64 +#define PT_SPAWNFLAG_HIDDEN 128 void ClearProjectileTargets(); class ProjectileTarget : public Entity { private: - int m_iTarget; + int m_iID; public: CLASS_PROTOTYPE(ProjectileTarget); @@ -52,7 +53,9 @@ public: ProjectileTarget(); void EventSetId(Event *ev); - int GetTarget() const; + int GetId() const; + + void Archive(Archiver& arc) override; }; #define MAX_PROJECTILE_GENERATOR_TARGETS 16 @@ -101,20 +104,28 @@ public: bool ShouldStartOn() const; bool ShouldHideModel() const; bool ShouldPlayFireSound() const; + bool ShouldPlayMotionSound() const; + bool ShouldRotateYaw() const; + bool ShouldRotateRoll() const; - void EventIsTurnedOn(Event *ev); - void EventGetTargetEntity(Event *ev); - void EventLaunchSound(Event *ev); - void SetTarget(Event *ev); - void OnInitialize(Event *ev); - void TurnOff(Event *ev); - void TurnOn(Event *ev); - bool ShouldTargetRandom() const; - void ChooseTarget(); + void EventIsTurnedOn(Event *ev); + void EventGetTargetEntity(Event *ev); + void EventLaunchSound(Event *ev); + void SetTarget(Event *ev); + void SetTarget(Entity *ent); + void OnInitialize(Event *ev); + void TurnOff(Event *ev); + void TurnOn(Event *ev); + bool ShouldTargetRandom() const; + Entity *ChooseTarget(); void GetLocalTargets(); bool ShouldTargetPlayer() const; - void GetTargetPos(Entity *target); + Vector GetTargetPos(Entity *target); + void GetMuzzlePos(Vector& pos); + void Fire(); + void TryLaunchSound(); + void SetWeaponAnim(const char *name, Event *ev); void EventAccuracy(Event *ev); void EventMaxDelay(Event *ev); void EventMinDelay(Event *ev); @@ -125,11 +136,11 @@ public: void EventMaxDuration(Event *ev); void EventMinDuration(Event *ev); void SetWeaponModel(Event *ev); - void EventSetId(Event* ev); - void EventmaxDonut(Event* ev); - void EventminDonut(Event* ev); - void EventarcDonut(Event* ev); - void EventisDonut(Event* ev); + void EventSetId(Event *ev); + void EventmaxDonut(Event *ev); + void EventminDonut(Event *ev); + void EventarcDonut(Event *ev); + void EventisDonut(Event *ev); virtual bool Attack(int count); void Archive(Archiver& arc) override; @@ -154,8 +165,9 @@ public: void PlayPreImpactSound(Event *ev); void SetProjectileModel(Event *ev); - bool Attack(int count) override; - void Archive(Archiver& arc) override; + float EstimateImpactTime(const Vector& targetOrigin, const Vector& fromOrigin, float speed) const; + bool Attack(int count) override; + void Archive(Archiver& arc) override; }; class ProjectileGenerator_Gun : public ProjectileGenerator @@ -196,6 +208,7 @@ public: void SetBulletRange(Event *ev); bool Attack(int count) override; + bool TickWeaponAnim(); void TickCycle(Event *ev) override; void Archive(Archiver& arc) override; }; @@ -238,6 +251,8 @@ public: ThrobbingBox_Explosive(); + bool ShouldDoExplosion(); + void SetExplosionOffset(Event *ev); void SetExplosionEffect(Event *ev); void SetTriggered(Event *ev); @@ -262,24 +277,36 @@ class ThrobbingBox_ExplodePlayerFlak88 : public ThrobbingBox_Explosive { public: CLASS_PROTOTYPE(ThrobbingBox_ExplodePlayerFlak88); + +public: + ThrobbingBox_ExplodePlayerFlak88(); }; class ThrobbingBox_ExplodeFlak88 : public ThrobbingBox_Explosive { public: CLASS_PROTOTYPE(ThrobbingBox_ExplodeFlak88); + +public: + ThrobbingBox_ExplodeFlak88(); }; class ThrobbingBox_ExplodeNebelwerfer : public ThrobbingBox_Explosive { public: CLASS_PROTOTYPE(ThrobbingBox_ExplodeNebelwerfer); + +public: + ThrobbingBox_ExplodeNebelwerfer(); }; class ThrobbingBox_ExplodePlayerNebelwerfer : public ThrobbingBox_Explosive { public: CLASS_PROTOTYPE(ThrobbingBox_ExplodePlayerNebelwerfer); + +public: + ThrobbingBox_ExplodePlayerNebelwerfer(); }; #define TBE_SPAWNFLAG_DESTROYED_MODEL 1 @@ -293,6 +320,8 @@ private: public: CLASS_PROTOTYPE(ThrobbingBox_Stickybomb); + ThrobbingBox_Stickybomb(); + void OnStickyBombWet(Event *ev); void OnStickyBombUse(Event *ev); @@ -312,7 +341,7 @@ public: Objective(); - void Archive(Archiver &arc) override; + void Archive(Archiver& arc) override; void TurnOn(Event *ev); void TurnOff(Event *ev); void Complete(Event *ev); @@ -327,6 +356,10 @@ class FencePost : public Entity { public: CLASS_PROTOTYPE(FencePost); + + FencePost(); + + void Killed(Event* ev) override; }; class AISpawnPoint : public SimpleArchivedEntity diff --git a/code/fgame/Tow_Entities.cpp b/code/fgame/Tow_Entities.cpp index ea10c309..b59c2ec7 100644 --- a/code/fgame/Tow_Entities.cpp +++ b/code/fgame/Tow_Entities.cpp @@ -114,19 +114,105 @@ void TOWObjectiveMan::TakeOverObjective(eController controller, eController cont } } -Event EV_SetController("ControlledBy", EV_DEFAULT, "i", "ControlledBy", "Sets the team controlling the objective"); -Event EV_TakeOver( - "TakeOver", EV_DEFAULT, "i", "TeamNum", "Sets the team controlling the objective. 0 = Axis, 1 = Allies" +//--------------------------------------------------------------------------------------------- +/*QUAKED func_TOWObjective (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) StartOn Respawner + + This object is an extension of the standard objective object. It is used for Tug of War + Maps. + + object used to simplify placing objectives. You may optionally connect this object to the + target you want to use for the compass position.... + + Checkboxes: + StartOn - check this if you want this objective to be displayed when the level first loads + + Respawner - check this if the objective is the respawn point for a team. If you set this + you must set ControlledBy to a valid team and not Neutral. + + + Parameters: + ControlledBy 0 = Axis, 1 = Allies, 2 = Neutral + AxisObjNum 1 - 5. Set the objective number for the axis. This will associate the objective with + the check box for the corresponding text in the score screen. + AlliesObjNum 1 - 5. Set the objective number for the allies. This will associate the objective with + the check box for the corresponding text in the score screen. + + ObjectiveNbr Please ignore this for now. + + Events: + TurnOn + TurnOff + Complete + Text + SetCurrent + SetController - This will set the starting controller default is neutral. See ControlledBy var above. + +//--------------------------------------------------------------------------------------------- +*/ + +Event EV_SetController +( + "ControlledBy", + EV_DEFAULT, + "i", + "ControlledBy", + "Sets the team controlling the objective", + EV_NORMAL ); -Event EV_SetAxisObjNum("AxisObjNum", EV_DEFAULT, "i", "AxisObjNum", "Sets the objective number for the axis team"); -Event EV_SetAlliesObjNum( - "AlliesObjNum", EV_DEFAULT, "i", "AlliesObjNum", "Sets the objective number for the allies team" +Event EV_TakeOver +( + "TakeOver", + EV_DEFAULT, + "i", + "TeamNum", + "Sets the team controlling the objective. 0 = Axis, 1 = Allies", + EV_NORMAL ); -static Event EV_Initialize("initialize", EV_DEFAULT, 0, 0, "Initialize object"); -static Event EV_SetCurrent( - "SetCurrent", EV_DEFAULT, "i", "TeamNum", "Set this objective as the current objective for the specified team." +Event EV_SetAxisObjNum +( + "AxisObjNum", + EV_DEFAULT, + "i", + "AxisObjNum", + "Sets the objective number for the axis team", + EV_NORMAL +); +Event EV_SetAlliesObjNum +( + "AlliesObjNum", + EV_DEFAULT, + "i", + "AlliesObjNum", + "Sets the objective number for the allies team", + EV_NORMAL +); +static Event EV_Initialize +( + "initialize", + EV_DEFAULT, + 0, + 0, + "Initialize object", + EV_NORMAL +); +static Event EV_SetCurrent +( + "SetCurrent", + EV_DEFAULT, + "i", + "TeamNum", + "Set this objective as the current objective for the specified team.", + EV_NORMAL +); +Event EV_GetController +( + "ControlledBy", + EV_DEFAULT, + 0, + 0, + "Objective controller", + EV_GETTER ); -Event EV_GetController("ControlledBy", EV_DEFAULT, 0, 0, "Objective controller", EV_GETTER); CLASS_DECLARATION(Objective, TOWObjective, "func_towobjective") { {&EV_SetController, &TOWObjective::SetController }, @@ -183,18 +269,19 @@ void TOWObjective::TakeOver(Event *ev) switch (controller) { case CONTROLLER_ALLIES: - gi.cvar_set(m_sAxisObjName.c_str(), "1"); - gi.cvar_set(m_sAlliesObjName.c_str(), "0"); - break; - case CONTROLLER_AXIS: gi.cvar_set(m_sAxisObjName.c_str(), "0"); gi.cvar_set(m_sAlliesObjName.c_str(), "1"); break; + case CONTROLLER_AXIS: + gi.cvar_set(m_sAxisObjName.c_str(), "1"); + gi.cvar_set(m_sAlliesObjName.c_str(), "0"); + break; default: break; } g_TOWObjectiveMan.TakeOverObjective(m_eController, controller); + m_eController = controller; if (m_bNoRespawnForLeading) { // @@ -216,18 +303,18 @@ void TOWObjective::SetAxisObjNum(Event *ev) void TOWObjective::OnInitialize(Event *ev) { - m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum); - m_sAxisObjName = "tow_allied_obj" + str(m_iAxisObjNum); + m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum); + m_sAxisObjName = "tow_axis_obj" + str(m_iAxisObjNum); switch (m_eController) { case CONTROLLER_ALLIES: - gi.cvar_set(m_sAxisObjName.c_str(), "1"); - gi.cvar_set(m_sAlliesObjName.c_str(), "0"); - break; - case CONTROLLER_AXIS: gi.cvar_set(m_sAxisObjName.c_str(), "0"); gi.cvar_set(m_sAlliesObjName.c_str(), "1"); break; + case CONTROLLER_AXIS: + gi.cvar_set(m_sAxisObjName.c_str(), "1"); + gi.cvar_set(m_sAlliesObjName.c_str(), "0"); + break; case CONTROLLER_DRAW: gi.cvar_set(m_sAxisObjName.c_str(), "0"); gi.cvar_set(m_sAlliesObjName.c_str(), "0"); diff --git a/code/fgame/Tow_Entities.h b/code/fgame/Tow_Entities.h index eee8cd6f..dca59a86 100644 --- a/code/fgame/Tow_Entities.h +++ b/code/fgame/Tow_Entities.h @@ -59,8 +59,8 @@ class TOWObjectiveMan { private: Container m_towObjectives; - int m_iNumAxisObjectives; int m_iNumAlliesObjectives; + int m_iNumAxisObjectives; public: TOWObjectiveMan(); diff --git a/code/fgame/VehicleCollisionEntity.cpp b/code/fgame/VehicleCollisionEntity.cpp index adf32d86..8c53faa6 100644 --- a/code/fgame/VehicleCollisionEntity.cpp +++ b/code/fgame/VehicleCollisionEntity.cpp @@ -24,72 +24,77 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "VehicleCollisionEntity.h" #include "g_phys.h" -CLASS_DECLARATION( Entity, VehicleCollisionEntity, NULL ) -{ - { &EV_Damage, &VehicleCollisionEntity::EventDamage }, - { NULL, NULL } +Event EV_Owner +( + "owner", + EV_DEFAULT, + NULL, + NULL, + "owner", + EV_GETTER +); + +CLASS_DECLARATION(Entity, VehicleCollisionEntity, NULL) { + {&EV_Damage, &VehicleCollisionEntity::EventDamage}, + {&EV_Owner, &VehicleCollisionEntity::GetOwner }, + {NULL, NULL } }; -VehicleCollisionEntity::VehicleCollisionEntity - ( - Entity *ent - ) +VehicleCollisionEntity::VehicleCollisionEntity(Entity *ent) { - if( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - edict->s.eType = ET_GENERAL; + edict->s.eType = ET_GENERAL; - m_pOwner = ent; - takedamage = DAMAGE_YES; + m_pOwner = ent; + takedamage = DAMAGE_YES; - edict->s.renderfx &= ~RF_DONTDRAW; - edict->r.svFlags &= ~SVF_NOCLIENT; + showModel(); + setMoveType(MOVETYPE_PUSH); + setSolidType(SOLID_NOT); - setMoveType( MOVETYPE_PUSH ); - - edict->clipmask |= MASK_CLIP; - edict->s.eFlags |= EF_LINKANGLES; + edict->clipmask |= MASK_VEHICLE; + edict->s.eFlags |= EF_LINKANGLES; } -VehicleCollisionEntity::VehicleCollisionEntity - ( - void - ) +VehicleCollisionEntity::VehicleCollisionEntity(void) { - if( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - gi.Error( ERR_DROP, "VehicleCollisionEntity Created with no parameters!\n" ); + gi.Error(ERR_DROP, "VehicleCollisionEntity Created with no parameters!\n"); } -void VehicleCollisionEntity::EventDamage - ( - Event *ev - ) +void VehicleCollisionEntity::GetOwner(Event *ev) { - Event *event = new Event( ev ); - - m_pOwner->ProcessEvent( event ); + ev->AddListener(m_pOwner); } -void VehicleCollisionEntity::Solid - ( - void - ) +void VehicleCollisionEntity::Solid(void) { - setContents( CONTENTS_SOLID ); - setSolidType( SOLID_BSP ); + setContents(CONTENTS_SOLID); + setSolidType(SOLID_BSP); } -void VehicleCollisionEntity::NotSolid - ( - void - ) +void VehicleCollisionEntity::NotSolid(void) { - setSolidType( SOLID_NOT ); + setSolidType(SOLID_NOT); +} + +void VehicleCollisionEntity::EventDamage(Event *ev) +{ + m_pOwner->ProcessEvent(*ev); +} + +void VehicleCollisionEntity::Used(Event *ev) +{ + m_pOwner->ProcessEvent(*ev); +} + +Entity *VehicleCollisionEntity::GetOwner() const +{ + return m_pOwner; } diff --git a/code/fgame/VehicleCollisionEntity.h b/code/fgame/VehicleCollisionEntity.h index f2b508a1..5185fc3c 100644 --- a/code/fgame/VehicleCollisionEntity.h +++ b/code/fgame/VehicleCollisionEntity.h @@ -21,40 +21,36 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // VehicleCollisionEntity.h : MOHAA vehicle collision -#ifndef __VEHICLECOLLISIONENTITY_H__ -#define __VEHICLECOLLISIONENTITY_H__ +#pragma once #include "entity.h" class VehicleCollisionEntity : public Entity { private: - EntityPtr m_pOwner; + EntityPtr m_pOwner; private: - void EventDamage( Event *ev ); + void EventDamage(Event *ev); + void GetOwner(Event *ev); + void Used(Event *ev); public: - CLASS_PROTOTYPE( VehicleCollisionEntity ); + CLASS_PROTOTYPE(VehicleCollisionEntity); - VehicleCollisionEntity( Entity *ent ); - VehicleCollisionEntity(); + VehicleCollisionEntity(Entity *ent); + VehicleCollisionEntity(); - void Archive( Archiver& arc ) override; + void Archive(Archiver& arc) override; - void Solid( void ); - void NotSolid( void ); + void Solid(void); + void NotSolid(void); + Entity *GetOwner() const; }; -inline -void VehicleCollisionEntity::Archive - ( - Archiver& arc - ) +inline void VehicleCollisionEntity::Archive(Archiver& arc) { - Entity::Archive( arc ); + Entity::Archive(arc); - arc.ArchiveSafePointer( &m_pOwner ); + arc.ArchiveSafePointer(&m_pOwner); } - -#endif // __VEHICLECOLLISIONENTITY_H__ \ No newline at end of file diff --git a/code/fgame/VehicleHalfTrack.cpp b/code/fgame/VehicleHalfTrack.cpp index 72b83768..5e0341ad 100644 --- a/code/fgame/VehicleHalfTrack.cpp +++ b/code/fgame/VehicleHalfTrack.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2018 the OpenMoHAA team +Copyright (C) 2018-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,42 +22,222 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "vehicle.h" #include "player.h" +#include "g_phys.h" -CLASS_DECLARATION(DrivableVehicle, VehicleHalfTrack, "VehicleHalfTrack") -{ - { &EV_Damage, &VehicleHalfTrack::EventDamage }, - { &EV_Killed, &VehicleHalfTrack::Killed }, - { NULL, NULL } +CLASS_DECLARATION(DrivableVehicle, VehicleHalfTrack, "VehicleHalfTrack") { + {&EV_Damage, &VehicleHalfTrack::EventDamage}, + {&EV_Killed, &VehicleHalfTrack::Killed }, + {NULL, NULL } }; VehicleHalfTrack::VehicleHalfTrack() { - - ; } void VehicleHalfTrack::Think() { - vmove_t vm; - flags |= FL_POSTTHINK; + vmove_t vm; + flags |= FL_POSTTHINK; - prev_velocity = velocity; + prev_velocity = velocity; - SetSlotsNonSolid(); + SetSlotsNonSolid(); - SetMoveInfo(&vm); - VmoveSingle(&vm); - GetMoveInfo(&vm); + SetMoveInfo(&vm); + VmoveSingle(&vm); + GetMoveInfo(&vm); - SetSlotsSolid(); + SetSlotsSolid(); } void VehicleHalfTrack::Postthink() { - // FIXME: STUB + float turn; + Vector i, j, k; + int index; + trace_t trace; + Vector normalsum; + int numnormals; + Vector temp; + Vector pitch, roll; + Vector acceleration; + Vector atmp, atmp2, aup; + VehicleBase *v; + VehicleBase *last; + float drivespeed; + Vector primal_angles; + Vector vTmp; + Vector n_angles; + + primal_angles = angles; + + if (drivable) { + if (m_bAutoPilot) { + AutoPilot(); + } + + currentspeed = moveimpulse; + turnangle = turnangle * 0.25 + turnimpulse; + turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate); + + real_velocity = origin - prev_origin; + prev_origin = origin; + prev_acceleration = real_acceleration; + real_acceleration = real_velocity - prev_velocity; + prev_velocity = real_velocity; + acceleration = real_acceleration - prev_acceleration; + + temp = angles; + temp.AngleVectorsLeft(&i, &j, &k); + + j = vec_zero - j; + + numnormals = 0; + for (index = 0; index < MAX_CORNERS; index++) { + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8), t_maxs(8, 8, 8); + + boxoffset = Corners[index]; + start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2]; + end = start + Vector(0, 0, -400); + + trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_VEHICLE_TIRES, false, "Vehicle::PostThink Corners"); + + if (trace.fraction != 1.0 || trace.startsolid) { + normalsum += trace.plane.normal; + } + } + + angles[2] = 0; + + if (m_iNumNormals > 1) { + temp = normalsum / numnormals; + temp.normalize(); + i = temp.CrossProduct(temp, j); + + pitch = i; + angles[0] = -pitch.toPitch(); + } + + turn = turnangle / 200.0; + if (groundentity) { + Vector newvel; + Vector flatvel; + + velocity[0] *= 0.925f; + velocity[1] *= 0.925f; + + flatvel = orientation[0]; + velocity += flatvel * currentspeed; + flatvel[2] = 0; + + drivespeed = Q_clamp_float(velocity * flatvel, -speed, speed); + + newvel = flatvel * drivespeed; + velocity[0] = newvel[0]; + velocity[1] = newvel[1]; + velocity[2] += drivespeed * jumpimpulse; + + avelocity *= 0.05f; + + if (steerinplace) { + if (drivespeed < 350) { + drivespeed = 350; + } + } + + avelocity.y += turn * drivespeed; + } else { + avelocity *= 0.1f; + } + + angles += avelocity * level.frametime; + setAngles(angles); + } + + drivespeed = acceleration * orientation[0]; + + if (drivable && driver.ent) { + str sound_name; + + if (currentspeed > 0) { + sound_name = "snd_forward"; + } else if (currentspeed < 0) { + sound_name = "snd_backward"; + } else { + sound_name = "snd_idle"; + } + + LoopSound(sound_name); + } + + i = orientation[0]; + j = orientation[1]; + k = orientation[2]; + + if (driver.ent) { + driver.ent->setOrigin(origin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2]); + + if (drivable) { + // clear the driver velocity + driver.ent->velocity = vec_zero; + // set the driver angles to the vehicle's angle + driver.ent->setAngles(angles); + } + } + + n_angles = (angles - primal_angles) * level.frametime; + if (n_angles.x > 180 || n_angles.x < -180) { + n_angles.x = 0; + } + if (n_angles.y > 180 || n_angles.y < -180) { + n_angles.y = 0; + } + if (n_angles.z > 180 || n_angles.z < -180) { + n_angles.z = 0; + } + + if (n_angles.x > -1 || n_angles.x < 1) { + n_angles.x = 0; + } + if (n_angles.y > -1 || n_angles.y < 1) { + n_angles.y = 0; + } + if (n_angles.z > -1 || n_angles.z < 1) { + n_angles.z = 0; + } + + avelocity = n_angles; + + for (last = this; last->vlink; last = v) { + v = last->vlink; + + v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z); + v->avelocity = avelocity; + v->velocity = velocity; + + v->angles[ROLL] = angles[ROLL]; + v->angles[YAW] = angles[YAW]; + v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360; + v->setAngles(v->angles); + } + + CheckWater(); + WorldEffects(); + + last_origin = origin; + + if (!driver.ent && !velocity.length() && groundentity && !(watertype & CONTENTS_LAVA)) { + // make the vehicle stationary if it's completely immobile + flags &= ~FL_POSTTHINK; + if (drivable) { + setMoveType(MOVETYPE_STATIONARY); + } + } } -void VehicleHalfTrack::Killed(Event* ev) +void VehicleHalfTrack::Killed(Event *ev) { - deadflag = DEAD_DEAD; + deadflag = DEAD_DEAD; } diff --git a/code/fgame/VehicleSlot.cpp b/code/fgame/VehicleSlot.cpp index c091e704..e4858da5 100644 --- a/code/fgame/VehicleSlot.cpp +++ b/code/fgame/VehicleSlot.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -28,131 +28,209 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cVehicleSlot::cVehicleSlot() { - prev_takedamage = ( damage_t )-1; - prev_solid = ( solid_t )-1; - prev_contents = -1; + prev_takedamage = (damage_t)-1; + prev_solid = (solid_t)-1; + prev_contents = -1; + + prev_num_children = 0; } -void cVehicleSlot::NotSolid - ( - void - ) +void cVehicleSlot::NotSolid(void) { - if( !( flags & FL_SWIM ) ) - { - return; - } + int i; - if( !ent ) - { - return; - } + if (!(flags & SLOT_BUSY)) { + return; + } - // Save previous values - prev_takedamage = ent->takedamage; - prev_solid = ent->edict->solid; - prev_contents = ent->edict->r.contents; - - ent->takedamage = DAMAGE_NO; - ent->setSolidType( SOLID_NOT ); + if (!ent) { + return; + } + + // Save previous values + prev_takedamage = ent->takedamage; + prev_solid = ent->edict->solid; + prev_contents = ent->edict->r.contents; + + ent->takedamage = DAMAGE_NO; + + prev_num_children = 0; + + for (i = 0; i < ent->numchildren; i++) { + Entity *sub = G_GetEntity(ent->children[i]); + // Fixed in OPM + // Check for solidity + if (sub && !sub->IsSubclassOfWeapon() && sub->getSolidType() != SOLID_NOT) { + // Fixed in OPM + // Save children solidity so it can properly be restored later + prev_children_ent[prev_num_children] = sub; + prev_children_solid[prev_num_children] = (solid_t)sub->getSolidType(); + prev_num_children++; + + sub->setSolidType(SOLID_NOT); + } + } + + // Added in 2.0 + // Commented in OPM + // Not sure why since 2.0, players aren't made non-solid in slots + //if (!ent->IsSubclassOfPlayer()) { + // ent->setSolidType(SOLID_NOT); + //} + + ent->setSolidType(SOLID_NOT); } -void cVehicleSlot::Solid - ( - void - ) +void cVehicleSlot::Solid(void) { - if( !( flags & FL_SWIM ) ) - { - return; - } + int i, j; - if( !ent ) - { - return; - } + if (!(flags & FL_SWIM)) { + return; + } - // Restore previous values - ent->takedamage = prev_takedamage; - ent->setSolidType( prev_solid ); - ent->edict->r.contents = prev_contents; + if (!ent) { + return; + } - // Save previous values - prev_takedamage = ( damage_t )-1; - prev_solid = ( solid_t )-1; - prev_contents = -1; + // Restore previous values + ent->takedamage = prev_takedamage; + ent->setSolidType(prev_solid); + ent->setContents(prev_contents); + + // Save previous values + prev_takedamage = (damage_t)-1; + prev_solid = (solid_t)-1; + prev_contents = -1; + + // + // Fixed in OPM + // Restore children solidity + // + for (i = 0; i < ent->numchildren; i++) { + Entity *sub = G_GetEntity(ent->children[i]); + if (sub && !sub->IsSubclassOfWeapon()) { + for (j = 0; j < prev_num_children; j++) { + if (prev_children_ent[j] == sub) { + sub->setSolidType(prev_children_solid[j]); + } + } + + //sub->setSolidType(SOLID_NOT); + } + } + + prev_num_children = 0; } cTurretSlot::cTurretSlot() { - owner_prev_takedamage = ( damage_t )-1; - owner_prev_solid = ( solid_t )-1; - owner_prev_contents = -1; + owner_prev_takedamage = (damage_t)-1; + owner_prev_solid = (solid_t)-1; + owner_prev_contents = -1; } -void cTurretSlot::NotSolid - ( - void - ) +void cTurretSlot::NotSolid(void) { - if( !( flags & FL_SWIM ) ) - { - return; - } + int i; - if( !ent ) - { - return; - } + if (!(flags & FL_SWIM)) { + return; + } - cVehicleSlot::NotSolid(); + if (!ent) { + return; + } - if( ent->IsSubclassOfTurretGun() ) - { - TurretGun *turret = ( TurretGun * )ent.Pointer(); - Entity *owner = turret->GetOwner(); + // Save previous values + prev_takedamage = ent->takedamage; + prev_solid = ent->edict->solid; + prev_contents = ent->edict->r.contents; - if( owner ) - { - owner_prev_takedamage = owner->takedamage; - owner_prev_solid = owner->edict->solid; - owner_prev_contents = owner->edict->r.contents; + ent->takedamage = DAMAGE_NO; + ent->setSolidType(SOLID_NOT); - owner->takedamage = DAMAGE_NO; - owner->setSolidType( SOLID_NOT ); - } - } + if (ent->IsSubclassOfTurretGun()) { + TurretGun *turret = static_cast(ent.Pointer()); + Entity *owner = turret->GetOwner(); + + if (owner) { + owner_prev_takedamage = owner->takedamage; + owner_prev_solid = owner->edict->solid; + owner_prev_contents = owner->edict->r.contents; + + owner->takedamage = DAMAGE_NO; + owner->setSolidType(SOLID_NOT); + } + } + + prev_num_children = 0; + + for (i = 0; i < ent->numchildren; i++) { + Entity *sub = G_GetEntity(ent->children[i]); + // Fixed in OPM + // Check for solidity + if (sub && !sub->IsSubclassOfWeapon() && sub->getSolidType() != SOLID_NOT) { + // Fixed in OPM + // Save children solidity so it can properly be restored later + prev_children_ent[prev_num_children] = sub; + prev_children_solid[prev_num_children] = (solid_t)sub->getSolidType(); + prev_num_children++; + + sub->setSolidType(SOLID_NOT); + } + } } -void cTurretSlot::Solid - ( - void - ) +void cTurretSlot::Solid(void) { - if( !( flags & FL_SWIM ) ) - { - return; - } + int i, j; - if( !ent ) - { - return; - } + if (!(flags & FL_SWIM)) { + return; + } - cVehicleSlot::NotSolid(); + if (!ent) { + return; + } - if( ent->IsSubclassOfTurretGun() ) - { - TurretGun *turret = ( TurretGun * )ent.Pointer(); - Entity *owner = turret->GetOwner(); + // Restore previous values + ent->takedamage = prev_takedamage; + ent->setSolidType(prev_solid); - if( owner ) - { - owner->takedamage = owner_prev_takedamage; - owner->setSolidType( owner_prev_solid ); + // Save previous values + prev_takedamage = (damage_t)-1; + prev_solid = (solid_t)-1; - owner_prev_takedamage = ( damage_t )-1; - owner_prev_solid = ( solid_t )-1; - } - } + if (ent->IsSubclassOfTurretGun()) { + TurretGun *turret = static_cast(ent.Pointer()); + Entity *owner = turret->GetOwner(); + + if (owner) { + owner->takedamage = owner_prev_takedamage; + owner->setSolidType(owner_prev_solid); + + owner_prev_takedamage = (damage_t)-1; + owner_prev_solid = (solid_t)-1; + } + } + + // + // Fixed in OPM + // Restore children solidity + // + for (i = 0; i < ent->numchildren; i++) { + Entity *sub = G_GetEntity(ent->children[i]); + if (sub && !sub->IsSubclassOfWeapon()) { + for (j = 0; j < prev_num_children; j++) { + if (prev_children_ent[j] == sub) { + sub->setSolidType(prev_children_solid[j]); + } + } + + //sub->setSolidType(SOLID_NOT); + } + } + + prev_num_children = 0; } diff --git a/code/fgame/VehicleSlot.h b/code/fgame/VehicleSlot.h index 98e46523..509c3d31 100644 --- a/code/fgame/VehicleSlot.h +++ b/code/fgame/VehicleSlot.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,78 +23,76 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // VehicleSlot.h // -#ifndef __VEHICLESLOT_H__ -#define __VEHICLESLOT_H__ +#pragma once #include "g_local.h" #include "class.h" #include "entity.h" -#define SLOT_FREE 1 -#define SLOT_BUSY 2 -#define SLOT_UNUSED 4 +#define SLOT_FREE 1 +#define SLOT_BUSY 2 +#define SLOT_UNUSED 4 -class cVehicleSlot : public Class { +class cVehicleSlot : public Class +{ public: - SafePtr ent; - int flags; - int boneindex; - int enter_boneindex; + SafePtr ent; + int flags; + int boneindex; + int enter_boneindex; -private: - damage_t prev_takedamage; - solid_t prev_solid; - int prev_contents; +protected: + damage_t prev_takedamage; + solid_t prev_solid; + int prev_contents; + + // + // Added in OPM + // Used for properly saving and restoring children solidity + Entity *prev_children_ent[MAX_MODEL_CHILDREN]; + solid_t prev_children_solid[MAX_MODEL_CHILDREN]; + int prev_num_children; public: - cVehicleSlot(); + cVehicleSlot(); - virtual void NotSolid( void ); - virtual void Solid( void ); - void Archive( Archiver& arc ) override; + virtual void NotSolid(void); + virtual void Solid(void); + void Archive(Archiver& arc) override; }; -inline -void cVehicleSlot::Archive - ( - Archiver& arc - ) +inline void cVehicleSlot::Archive(Archiver& arc) { - Class::Archive( arc ); + Class::Archive(arc); - arc.ArchiveSafePointer( &ent ); - arc.ArchiveInteger( &flags ); - arc.ArchiveInteger( &boneindex ); - arc.ArchiveInteger( &enter_boneindex ); - ArchiveEnum( prev_takedamage, damage_t ); - ArchiveEnum( prev_solid, solid_t ); - arc.ArchiveInteger( &prev_contents ); + arc.ArchiveSafePointer(&ent); + arc.ArchiveInteger(&flags); + arc.ArchiveInteger(&boneindex); + arc.ArchiveInteger(&enter_boneindex); + ArchiveEnum(prev_takedamage, damage_t); + ArchiveEnum(prev_solid, solid_t); + arc.ArchiveInteger(&prev_contents); } -class cTurretSlot : public cVehicleSlot { - damage_t owner_prev_takedamage; - solid_t owner_prev_solid; - int owner_prev_contents; +class cTurretSlot : public cVehicleSlot +{ + damage_t owner_prev_takedamage; + solid_t owner_prev_solid; + int owner_prev_contents; public: - cTurretSlot(); + cTurretSlot(); - void NotSolid( void ) override; - void Solid( void ) override; - void Archive( Archiver& arc ) override; + void NotSolid(void) override; + void Solid(void) override; + void Archive(Archiver& arc) override; }; -inline -void cTurretSlot::Archive - ( - Archiver& arc - ) +inline void cTurretSlot::Archive(Archiver& arc) { - cVehicleSlot::Archive( arc ); + cVehicleSlot::Archive(arc); - ArchiveEnum( owner_prev_takedamage, damage_t ); - ArchiveEnum( owner_prev_solid, solid_t ); - arc.ArchiveInteger( &owner_prev_contents ); + ArchiveEnum(owner_prev_takedamage, damage_t); + ArchiveEnum(owner_prev_solid, solid_t); + arc.ArchiveInteger(&owner_prev_contents); } - -#endif // __VEHICLESLOT_H__ diff --git a/code/fgame/VehicleSoundEntity.cpp b/code/fgame/VehicleSoundEntity.cpp index cc3f2c5a..284b4094 100644 --- a/code/fgame/VehicleSoundEntity.cpp +++ b/code/fgame/VehicleSoundEntity.cpp @@ -26,159 +26,128 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "vehicle.h" Event EV_VehicleSoundEntity_PostSpawn - ( - "vehiclesoundentity_post", - EV_DEFAULT, - NULL, - NULL, - "PostSpawn of a Vehicle Sound Entity" - ); +( + "vehiclesoundentity_post", + EV_DEFAULT, + NULL, + NULL, + "PostSpawn of a Vehicle Sound Entity" +); Event EV_VehicleSoundEntity_UpdateTraces - ( - "vehiclesoudnentity_updatetraces", - EV_DEFAULT, - NULL, - NULL, - "Updates the traces of a Vehicle Sound Entity" - ); +( + "vehiclesoudnentity_updatetraces", + EV_DEFAULT, + NULL, + NULL, + "Updates the traces of a Vehicle Sound Entity" +); -CLASS_DECLARATION( Entity, VehicleSoundEntity, NULL ) -{ - { &EV_VehicleSoundEntity_PostSpawn, &VehicleSoundEntity::EventPostSpawn }, - { &EV_VehicleSoundEntity_UpdateTraces, &VehicleSoundEntity::EventUpdateTraces }, - { NULL, NULL } +CLASS_DECLARATION(Entity, VehicleSoundEntity, NULL) { + {&EV_VehicleSoundEntity_PostSpawn, &VehicleSoundEntity::EventPostSpawn }, + {&EV_VehicleSoundEntity_UpdateTraces, &VehicleSoundEntity::EventUpdateTraces}, + {NULL, NULL } }; VehicleSoundEntity::VehicleSoundEntity() { - if( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - gi.Error( ERR_DROP, "VehicleSoundEntity Created with no parameters!\n" ); + gi.Error(ERR_DROP, "VehicleSoundEntity Created with no parameters!\n"); } -VehicleSoundEntity::VehicleSoundEntity( Vehicle *owner ) +VehicleSoundEntity::VehicleSoundEntity(Vehicle *owner) { - m_pVehicle = owner; - m_bDoSoundStuff = false; - m_iTraceSurfaceFlags = 0; + m_pVehicle = owner; + m_bDoSoundStuff = false; + m_iTraceSurfaceFlags = 0; - PostEvent( EV_VehicleSoundEntity_PostSpawn, EV_POSTSPAWN ); + PostEvent(EV_VehicleSoundEntity_PostSpawn, EV_POSTSPAWN); } -void VehicleSoundEntity::Start - ( - void - ) +void VehicleSoundEntity::Start(void) { - m_bDoSoundStuff = true; + m_bDoSoundStuff = true; } -void VehicleSoundEntity::Stop - ( - void - ) +void VehicleSoundEntity::Stop(void) { - m_bDoSoundStuff = false; + m_bDoSoundStuff = false; } -void VehicleSoundEntity::Think - ( - void - ) +void VehicleSoundEntity::Think(void) { - DoSoundStuff(); + DoSoundStuff(); } -void VehicleSoundEntity::EventPostSpawn - ( - Event *ev - ) +void VehicleSoundEntity::EventPostSpawn(Event *ev) { - setModel( "models/vehicles/vehiclesoundentity.tik" ); + setModel("models/vehicles/vehiclesoundentity.tik"); - PostEvent( EV_VehicleSoundEntity_UpdateTraces, 1.0f ); - flags |= FL_THINK; + PostEvent(EV_VehicleSoundEntity_UpdateTraces, 1.0f); + flags |= FL_THINK; } -void VehicleSoundEntity::EventUpdateTraces - ( - Event *ev - ) +void VehicleSoundEntity::EventUpdateTraces(Event *ev) { - if( m_bDoSoundStuff ) - { - m_pVehicle->SetSlotsNonSolid(); + if (m_bDoSoundStuff) { + m_pVehicle->SetSlotsNonSolid(); - trace_t trace = G_Trace( - origin, - vec3_origin, - vec3_origin, - Vector( origin[ 0 ], origin[ 1 ], origin[ 2 ] - 256.0f ), - m_pVehicle->edict, - MASK_SOUND, - qfalse, - "VehicleSoundEntity::DoSoundStuff" - ); + trace_t trace = G_Trace( + origin, + vec3_origin, + vec3_origin, + Vector(origin[0], origin[1], origin[2] - 256.0f), + m_pVehicle->edict, + MASK_SOUND, + qfalse, + "VehicleSoundEntity::DoSoundStuff" + ); - if( trace.fraction >= 1.0f ) - m_iTraceSurfaceFlags = 0; - else - m_iTraceSurfaceFlags = trace.surfaceFlags; + if (trace.fraction >= 1.0f) { + m_iTraceSurfaceFlags = 0; + } else { + m_iTraceSurfaceFlags = trace.surfaceFlags; + } - m_pVehicle->SetSlotsSolid(); - } + m_pVehicle->SetSlotsSolid(); + } - PostEvent( EV_VehicleSoundEntity_UpdateTraces, 1.0f ); + PostEvent(EV_VehicleSoundEntity_UpdateTraces, 1.0f); } -void VehicleSoundEntity::DoSoundStuff - ( - void - ) +void VehicleSoundEntity::DoSoundStuff(void) { - float pitch; + float pitch; - if( !m_bDoSoundStuff ) - { - StopLoopSound(); - return; - } + if (!m_bDoSoundStuff) { + StopLoopSound(); + return; + } - pitch = ( velocity.length() - m_pVehicle->m_fSoundMinSpeed ) / ( m_pVehicle->m_fSoundMaxSpeed - m_pVehicle->m_fSoundMinSpeed ); - if( pitch > 1.0f ) { - pitch = 1.0f; - } else if( pitch < 0.0f ) { - pitch = 0.0f; - } + pitch = (velocity.length() - m_pVehicle->m_fSoundMinSpeed) + / (m_pVehicle->m_fSoundMaxSpeed - m_pVehicle->m_fSoundMinSpeed); + if (pitch > 1.0f) { + pitch = 1.0f; + } else if (pitch < 0.0f) { + pitch = 0.0f; + } - pitch *= m_pVehicle->m_fSoundMinPitch + ( m_pVehicle->m_fSoundMaxPitch - m_pVehicle->m_fSoundMinPitch ); + pitch *= m_pVehicle->m_fSoundMinPitch + (m_pVehicle->m_fSoundMaxPitch - m_pVehicle->m_fSoundMinPitch); - if( m_iTraceSurfaceFlags & SURF_DIRT ) - { - LoopSound( m_pVehicle->m_sSoundSet + "treat_snd_dirt", -1.0f, -1.0f, -1.0f, pitch ); - } - else if( m_iTraceSurfaceFlags & SURF_GRASS ) - { - LoopSound( m_pVehicle->m_sSoundSet + "treat_snd_grass", -1.0f, -1.0f, -1.0f, pitch ); - } - else if( m_iTraceSurfaceFlags & SURF_WOOD ) - { - LoopSound( m_pVehicle->m_sSoundSet + "treat_snd_wood", -1.0f, -1.0f, -1.0f, pitch ); - } - else if( m_iTraceSurfaceFlags & SURF_MUD ) - { - LoopSound( m_pVehicle->m_sSoundSet + "treat_snd_mud", -1.0f, -1.0f, -1.0f, pitch ); - } - else if( m_iTraceSurfaceFlags & ( SURF_GRAVEL | SURF_ROCK ) ) - { - LoopSound( m_pVehicle->m_sSoundSet + "treat_snd_stone", -1.0f, -1.0f, -1.0f, pitch ); - } - else - { - StopLoopSound(); - } + if (m_iTraceSurfaceFlags & SURF_DIRT) { + LoopSound(m_pVehicle->m_sSoundSet + "tread_snd_dirt", -1.0f, -1.0f, -1.0f, pitch); + } else if (m_iTraceSurfaceFlags & SURF_GRASS) { + LoopSound(m_pVehicle->m_sSoundSet + "tread_snd_grass", -1.0f, -1.0f, -1.0f, pitch); + } else if (m_iTraceSurfaceFlags & SURF_WOOD) { + LoopSound(m_pVehicle->m_sSoundSet + "tread_snd_wood", -1.0f, -1.0f, -1.0f, pitch); + } else if (m_iTraceSurfaceFlags & SURF_MUD) { + LoopSound(m_pVehicle->m_sSoundSet + "tread_snd_mud", -1.0f, -1.0f, -1.0f, pitch); + } else if (m_iTraceSurfaceFlags & (SURF_GRAVEL | SURF_ROCK) || m_iTraceSurfaceFlags == 0) { + LoopSound(m_pVehicle->m_sSoundSet + "tread_snd_stone", -1.0f, -1.0f, -1.0f, pitch); + } else { + StopLoopSound(); + } } diff --git a/code/fgame/VehicleSoundEntity.h b/code/fgame/VehicleSoundEntity.h index fa41dc65..2b5c93d5 100644 --- a/code/fgame/VehicleSoundEntity.h +++ b/code/fgame/VehicleSoundEntity.h @@ -21,47 +21,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // VehicleSoundEntity.h : Sound helper for vehicles -#ifndef __VEHICLESOUNDENTITY_H__ -#define __VEHICLESOUNDENTITY_H__ +#pragma once #include "entity.h" class Vehicle; -class VehicleSoundEntity : public Entity { +class VehicleSoundEntity : public Entity +{ private: - SafePtr m_pVehicle; - bool m_bDoSoundStuff; - int m_iTraceSurfaceFlags; + SafePtr m_pVehicle; + bool m_bDoSoundStuff; + int m_iTraceSurfaceFlags; public: - CLASS_PROTOTYPE( VehicleSoundEntity ); + CLASS_PROTOTYPE(VehicleSoundEntity); - VehicleSoundEntity(); - VehicleSoundEntity( Vehicle *owner ); + VehicleSoundEntity(); + VehicleSoundEntity(Vehicle *owner); - void Start( void ); - void Stop( void ); - void Think( void ) override; - void Archive( Archiver& arc ) override; + void Start(void); + void Stop(void); + void Think(void) override; + void Archive(Archiver& arc) override; private: - void EventPostSpawn( Event *ev ); - void EventUpdateTraces( Event *ev ); - void DoSoundStuff( void ); + void EventPostSpawn(Event *ev); + void EventUpdateTraces(Event *ev); + void DoSoundStuff(void); }; -inline -void VehicleSoundEntity::Archive - ( - Archiver& arc - ) +inline void VehicleSoundEntity::Archive(Archiver& arc) { - Entity::Archive( arc ); + Entity::Archive(arc); - arc.ArchiveSafePointer( &m_pVehicle ); - arc.ArchiveBool( &m_bDoSoundStuff ); - arc.ArchiveInteger( &m_iTraceSurfaceFlags ); + arc.ArchiveSafePointer(&m_pVehicle); + arc.ArchiveBool(&m_bDoSoundStuff); + arc.ArchiveInteger(&m_iTraceSurfaceFlags); } - -#endif // __VEHICLECOLLISIONENTITY_H__ \ No newline at end of file diff --git a/code/fgame/VehicleTank.cpp b/code/fgame/VehicleTank.cpp index 2fa63801..bcc17fba 100644 --- a/code/fgame/VehicleTank.cpp +++ b/code/fgame/VehicleTank.cpp @@ -23,127 +23,550 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "vehicle.h" #include "vehicleturret.h" #include "player.h" +#include "g_phys.h" -CLASS_DECLARATION(DrivableVehicle, VehicleTank, "VehicleTank") -{ - { &EV_Damage, &VehicleTank::EventDamage }, - { NULL, NULL } +CLASS_DECLARATION(DrivableVehicle, VehicleTank, "VehicleTank") { + {&EV_Damage, &VehicleTank::EventDamage}, + {NULL, NULL } }; VehicleTank::VehicleTank() { - entflags |= FL_ROTATEDBOUNDS; + entflags |= FL_ROTATEDBOUNDS; } VehicleTank::~VehicleTank() { - entflags &= ~FL_ROTATEDBOUNDS; + entflags &= ~FL_ROTATEDBOUNDS; } qboolean VehicleTank::Drive(usercmd_t *ucmd) { - Vector i; - Vector j; - Vector k; - Vector vTmp; + Vector i; + Vector j; + Vector k; + Vector vTmp; - vTmp = velocity; - VectorNormalize(vTmp); + vTmp = velocity; + vTmp.normalize(); - if (!driver.ent || !driver.ent->client) - { - return qfalse; - } + if (!driver.ent || !driver.ent->isClient()) { + return qfalse; + } - if (!drivable) - { - driver.ent->client->ps.pm_flags |= PMF_FROZEN; - ucmd->forwardmove = 0; - ucmd->rightmove = 0; - ucmd->upmove = 0; - return qfalse; - } + if (!drivable) { + driver.ent->client->ps.pm_flags |= PMF_FROZEN; + ucmd->forwardmove = 0; + ucmd->rightmove = 0; + ucmd->upmove = 0; + return qfalse; + } - moveimpulse = ucmd->forwardmove * (vTmp.length() + 1.0); - - m_bIsBraking = ucmd->forwardmove >> 31; + if (!m_bAutoPilot) { + // + // ignore client's control if the vehicle is in auto-pilot mode + // + moveimpulse = ucmd->forwardmove * (vTmp.length() + 1.0); + m_bIsBraking = ucmd->forwardmove < 0; + m_fAccelerator += ucmd->forwardmove * 0.005; + // acceleration must be an alpha value between [0, 1] + m_fAccelerator = Q_clamp_float(m_fAccelerator, 0, 1); - m_fAccelerator += ucmd->forwardmove * 0.005; + turnimpulse = -ucmd->rightmove; + jumpimpulse = ucmd->upmove; + } - if (m_fAccelerator < 0) - { - m_fAccelerator = 0.0; - } + VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer(); - turnimpulse = -ucmd->rightmove; + if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) { + vtg->RemoteControl(ucmd, (Sentient *)driver.ent.Pointer()); - VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer(); - - if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) - { - vtg->RemoteControl(ucmd, (Sentient *)driver.ent.Pointer()); - - if (ucmd->upmove) - turnimpulse -= AngleSubtract(angles[1], vtg->angles[1]); - } - return qtrue; + if (ucmd->upmove) { + turnimpulse -= AngleSubtract(angles[1], vtg->angles[1]); + } + } + return qtrue; } void VehicleTank::EventDamage(Event *ev) { - int mod; - mod = ev->GetInteger(9); + int mod; + mod = ev->GetInteger(9); - if (mod > MOD_VEHICLE && mod != MOD_SHOTGUN && mod != MOD_GRENADE) - { - Vehicle::EventDamage(ev); - if (g_gametype->integer == GT_SINGLE_PLAYER) - { - Player *p = (Player *)driver.ent.Pointer(); - if (p) - { - if (p->IsSubclassOfPlayer()) - { - p->m_iNumHitsTaken++; - } - } - } - } + if (g_gametype->integer == GT_TOW && !dmManager.RoundActive()) { + return; + } + + switch (mod) { + case MOD_BULLET: + case MOD_BASH: + case MOD_FAST_BULLET: + case MOD_VEHICLE: + case MOD_SHOTGUN: + case MOD_GRENADE: + return; + } + + Vehicle::EventDamage(ev); + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + Player *p = (Player *)driver.ent.Pointer(); + if (p) { + if (p->IsSubclassOfPlayer()) { + p->m_iNumHitsTaken++; + } + } + } } void VehicleTank::Think() { - flags |= FL_POSTTHINK; + flags |= FL_POSTTHINK; } void VehicleTank::Postthink() { - // FIXME: STUB + float turn; + Vector i, j, k; + Vector normalsum; + Vector temp; + Vector pitch, roll; + Vector acceleration; + Vector atmp, atmp2, aup; + VehicleBase *v, *last; + float drivespeed; + Vector primal_angles, primal_origin; + Vector vTmp; + Vector vAddedAngles; + Vector n_angles; + float dot; + Vector newvel, flatvel; + Vector anglediff; + + primal_angles = angles; + primal_origin = origin; + + if (!g_vehicle->integer || edict->s.renderfx & RF_DONTDRAW) { + // don't process physics + return; + } + + if (m_pCollisionEntity) { + // use the collision entity for collision + setSolidType(SOLID_NOT); + m_pCollisionEntity->Solid(); + } + + prev_velocity = velocity; + SetSlotsNonSolid(); + + if (m_bAnimMove) { + AnimMoveVehicle(); + } else { + if (!m_bMovementLocked) { + FactorOutAnglesOffset(); + FactorOutOriginOffset(); + } + + MoveVehicle(); + } + + SetSlotsSolid(); + + if (m_vOldMins != vec_zero && m_vOldMaxs != vec_zero) { + mins = m_vOldMins; + maxs = m_vOldMaxs; + } else if (mins != vec_zero && maxs != vec_zero) { + m_vOldMins = mins; + m_vOldMaxs = maxs; + } + + if (m_bAnimMove) { + moveimpulse = velocity.length() * level.frametime; + turnimpulse = avelocity[1] * level.frametime; + } else if (m_bAutoPilot) { + AutoPilot(); + } + + currentspeed = moveimpulse; + turnangle = turnangle * 0.25 + turnimpulse; + turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate); + + real_velocity = origin - prev_origin; + prev_origin = origin; + prev_acceleration = real_acceleration; + real_acceleration = real_velocity - prev_velocity; + prev_velocity = real_velocity; + acceleration = real_acceleration - prev_acceleration; + + UpdateBones(); + UpdateShaderOffset(); + UpdateTires(); + UpdateNormals(); + + temp = angles; + temp.AngleVectorsLeft(&i, &j, &k); + + velocity[0] *= 0.925f; + velocity[1] *= 0.925f; + turn = turnangle / 200.0; + + flatvel = orientation[0]; + velocity += flatvel * currentspeed; + flatvel[2] = 0; + + dot = velocity * flatvel; + dot = Q_clamp_float(dot, -speed, speed); + newvel = flatvel * dot; + velocity[0] = newvel[0]; + velocity[1] = newvel[1]; + avelocity *= 0.05f; + if (dot < 350) { + dot = 350; + } + + avelocity.y += turn * dot; + angles += avelocity * level.frametime; + setAngles(angles); + + if (Turrets[0].ent && Turrets[0].ent->IsSubclassOfVehicleTurretGun() && driver.ent + && driver.ent->IsSubclassOfSentient()) { + VehicleTurretGun *pTurret = static_cast(Turrets[0].ent.Pointer()); + if (jumpimpulse != 0) { + pTurret->SetUserViewAngles(pTurret->GetUserViewAngles() - Vector(0, avelocity[1] * level.frametime, 0)); + } + } + + drivespeed = acceleration * orientation[0]; + UpdateSound(); + + if (AssertRotation(angles, primal_angles) != true) { + angles = primal_angles; + } + + CalculateAnglesOffset(acceleration); + CalculateOriginOffset(); + + last_origin = origin; + anglediff = (angles - primal_angles) * level.frametime; + + if (anglediff.x > 180 || anglediff.x < -180) anglediff.x = 0; + if (anglediff.y > 180 || anglediff.y < -180) anglediff.y = 0; + if (anglediff.z > 180 || anglediff.z < -180) anglediff.z = 0; + + if (anglediff.x > -1 || anglediff.x < 1) anglediff.x = 0; + if (anglediff.y > -1 || anglediff.y < 1) anglediff.y = 0; + if (anglediff.z > -1 || anglediff.z < 1) anglediff.z = 0; + + avelocity = anglediff; + + if (!m_bAnimMove && !m_bMovementLocked) { + FactorInOriginOffset(); + FactorInAnglesOffset(&vAddedAngles); + } + + CalculateAnimationData(vAddedAngles, m_vOriginOffset + m_vOriginOffset2); + if (m_pCollisionEntity) { + Vector vaDelta; + + SetSlotsNonSolid(); + + vaDelta[0] = angledist(angles[0] - m_pCollisionEntity->angles[0]); + vaDelta[1] = angledist(angles[1] - m_pCollisionEntity->angles[1]); + vaDelta[2] = angledist(angles[2] - m_pCollisionEntity->angles[2]); + + m_pCollisionEntity->Solid(); + + G_PushMove(m_pCollisionEntity, origin - primal_origin, vaDelta); + G_TouchTriggers(m_pCollisionEntity); + + SetSlotsSolid(); + + m_pCollisionEntity->setOrigin(origin); + m_pCollisionEntity->setAngles(angles); + } + + SetupVehicleSoundEntities(); + i = orientation[0]; + j = orientation[1]; + k = orientation[2]; + + // + // update slots + // + for (int ii = 0; ii < MAX_PASSENGERS; ii++) { + UpdatePassengerSlot(ii); + } + + for (int ii = 0; ii < MAX_TURRETS; ii++) { + UpdateTurretSlot(ii); + } + + for (last = this; last->vlink; last = v) { + v = last->vlink; + + v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z); + v->avelocity = avelocity; + v->velocity = velocity; + + v->angles[ROLL] = angles[ROLL]; + v->angles[YAW] = angles[YAW]; + v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360; + v->setAngles(v->angles); + } + + CheckWater(); + WorldEffects(); + + if (m_pCollisionEntity) { + setSolidType(SOLID_NOT); + m_pCollisionEntity->Solid(); + } else { + setSolidType(SOLID_BBOX); + setContents(CONTENTS_UNKNOWN2); + } + + if ((driver.flags & SLOT_BUSY) && driver.ent) { + if (driver.ent->IsSubclassOfPlayer()) { + driver.ent->takedamage = DAMAGE_YES; + // Fixed in OPM. + // It's probably a mistake in moh 2.0 and above, + // the tank was non-solid with a player driver, + // instead of the driver being non-solid. + //setSolidType(SOLID_NOT); + + // Fixed in OPM + // Driver is made non-solid in Vehicle::MoveThink + //driver.ent->setSolidType(SOLID_NOT); + } else { + driver.ent->takedamage = DAMAGE_NO; + driver.ent->setSolidType(SOLID_NOT); + } + } } void VehicleTank::CalculateOriginOffset() { - // FIXME: STUB + int index; + Vector vTireAvg; + Vector vMissHit; + Vector temp; + int iNum = 0; + Vector acceleration; + Vector oldoffset; + + oldoffset = m_vOriginOffset; + m_vOriginOffset += m_vOriginOffset2; + m_vOriginOffset2 = vec_zero; + + for (index = 0; index < NUM_VEHICLE_TIRES; index++) { + if (m_bTireHit[index]) { + vTireAvg += origin - m_vTireEnd[index]; + iNum++; + } else { + vMissHit = Corners[index]; + } + } + + if (m_iNumNormals > 0 && iNum == NUM_VEHICLE_TIRES - 1) { + Vector point; + + temp = m_vNormalSum * (1.f / m_iNumNormals); + temp.normalize(); + ProjectPointOnPlane(point, vMissHit, temp); + vTireAvg += point; + + iNum++; + } + + if (iNum == NUM_VEHICLE_TIRES) { + vec3_t vOriginCornerOffset; + + vTireAvg *= 1.f / NUM_VEHICLE_TIRES; + MatrixTransformVector(m_vOriginCornerOffset, orientation, vOriginCornerOffset); + vTireAvg -= vOriginCornerOffset; + m_vOriginOffset2 += vTireAvg; + } + + //m_vOriginOffset2 += vec_zero; + m_vOriginOffset -= m_vOriginOffset2; + + if (!isfinite(m_vOriginOffset[0]) || !isfinite(m_vOriginOffset[1]) || !isfinite(m_vOriginOffset[2])) { + m_vOriginOffset = oldoffset; + } } void VehicleTank::UpdateSound() { - // FIXME: STUB + float pitch = 1.f; + float volume = 1.f; + + if (level.time < m_fNextSoundState) { + return; + } + + pitch = (velocity.length() - m_fSoundMinSpeed) / (m_fSoundMaxSpeed - m_fSoundMinSpeed); + pitch = Q_clamp_float(pitch, 0, 1); + pitch = (m_fSoundMaxPitch - m_fSoundMinPitch) * pitch + m_fSoundMinPitch; + + volume = (velocity.length() - m_fVolumeMinSpeed) / (m_fVolumeMaxSpeed - m_fVolumeMinSpeed); + volume = Q_clamp_float(volume, 0, 1); + volume = (m_fVolumeMaxPitch - m_fVolumeMinPitch) * volume + m_fVolumeMinPitch; + + if (level.intermissiontime) { + m_eSoundState = ST_OFF; + } + + switch (m_eSoundState) { + case ST_OFF: + StopLoopSound(); + TurnOffVehicleSoundEntities(); + m_fNextSoundState = level.time; + if (driver.ent || m_bAutoPilot) { + m_eSoundState = ST_OFF_TRANS_IDLE; + } + break; + case ST_OFF_TRANS_IDLE: + m_fNextSoundState = level.time; + m_eSoundState = ST_IDLE; + Sound(m_sSoundSet + "snd_on", CHAN_AUTO); + LoopSound(m_sSoundSet + "snd_idle"); + break; + case ST_IDLE_TRANS_OFF: + m_fNextSoundState = level.time; + m_eSoundState = ST_OFF; + Sound(m_sSoundSet + "snd_off", CHAN_AUTO); + StopLoopSound(); + break; + case ST_IDLE: + m_fNextSoundState = level.time; + if (driver.ent || m_bAutoPilot) { + if (fabs(velocity * orientation[0]) > 150) { + m_eSoundState = ST_IDLE_TRANS_RUN; + } else if (fabs(turnimpulse) > 1) { + m_eSoundState = ST_IDLE_TRANS_TURN; + } + } else { + m_eSoundState = ST_IDLE_TRANS_OFF; + } + + LoopSound(m_sSoundSet + "snd_idle"); + TurnOffVehicleSoundEntities(); + break; + case ST_IDLE_TRANS_RUN: + m_fNextSoundState = level.time; + m_eSoundState = ST_RUN; + Sound(m_sSoundSet + "snd_revup", CHAN_AUTO); + Sound(m_sSoundSet + "snd_shift", CHAN_AUTO); + LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch); + break; + case ST_RUN: + m_fNextSoundState = level.time; + if (fabs(velocity * orientation[0]) < 150) { + m_eSoundState = ST_RUN_TRANS_IDLE; + } + TurnOnVehicleSoundEntities(); + LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch); + break; + case ST_RUN_TRANS_IDLE: + m_fNextSoundState = level.time; + m_eSoundState = ST_IDLE; + Sound(m_sSoundSet + "snd_revdown", CHAN_AUTO); + LoopSound(m_sSoundSet + "snd_idle"); + break; + case ST_IDLE_TRANS_TURN: + m_fNextSoundState = level.time; + m_eSoundState = ST_TURN; + Sound(m_sSoundSet + "snd_revup", CHAN_AUTO); + Sound(m_sSoundSet + "snd_shift", CHAN_AUTO); + LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch); + break; + case ST_TURN: + m_fNextSoundState = level.time; + if (fabs(turnimpulse) < 1) { + m_eSoundState = ST_TURN_TRANS_IDLE; + } + LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch); + break; + case ST_TURN_TRANS_IDLE: + m_fNextSoundState = level.time; + m_eSoundState = ST_IDLE; + Sound(m_sSoundSet + "snd_revdown", CHAN_AUTO); + LoopSound(m_sSoundSet + "snd_idle"); + break; + default: + m_fNextSoundState = level.time; + m_eSoundState = ST_OFF; + break; + } } -void VehicleTank::AttachDriverSlot(Event* ev) +// +// Fixed in OPM: +// This method only work when called from script. +// But it is not called automatically when the player actually uses the vehicle +// when that vehicle is unlocked. +// So the other native method is overridden instead +/* +void VehicleTank::AttachDriverSlot(Event *ev) { - Vehicle::AttachDriverSlot(ev); + Vehicle::AttachDriverSlot(ev); - VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer(); + if (!driver.ent) { + // + // Added in OPM. + // original mohaa doesn't check if driver.ent is valid, which can cause crash if the attached entity is null. + // on single-player, it would crash while loading m5l2a when sv_maxclients is above 1. + // The reason of the crash is that attachdriverslot is called with $player which can be NULL on prespawn. + // $player is not created on prespawn when sv_maxclients is above 1 + // + return; + } - if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) - { - vtg->SetOwner((Sentient *)driver.ent.Pointer()); - Think(); - Postthink(); - vtg->Think(); - } + VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer(); + if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) { + vtg->SetRemoteOwner(static_cast(driver.ent.Pointer())); + Think(); + Postthink(); + vtg->Think(); + } +} +*/ + +void VehicleTank::AttachDriverSlot(int slot, Entity* ent, Vector vExitPosition) +{ + Vehicle::AttachDriverSlot(slot, ent, vExitPosition); + + if (!driver.ent) { + // + // Added in OPM. + // original mohaa doesn't check if driver.ent is valid, which can cause crash if the attached entity is null. + // on single-player, it would crash while loading m5l2a when sv_maxclients is above 1. + // The reason of the crash is that attachdriverslot is called with $player which can be NULL on prespawn. + // $player is not created on prespawn when sv_maxclients is above 1 + // + return; + } + + VehicleTurretGun* vtg = static_cast(Turrets[0].ent.Pointer()); + + if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) { + vtg->SetRemoteOwner(static_cast(driver.ent.Pointer())); + Think(); + Postthink(); + vtg->Think(); + } } +void VehicleTank::DriverAdded() +{ + int i; + + for (i = 0; i < MAX_TURRETS; i++) { + if (Turrets[i].flags & SLOT_BUSY && Turrets[i].ent && Turrets[i].ent->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *pTurret = static_cast(Turrets[i].ent.Pointer()); + pTurret->TurretHasBeenMounted(); + } + } +} diff --git a/code/fgame/VehicleWheelsX2.cpp b/code/fgame/VehicleWheelsX2.cpp index 9b5179bc..a031499a 100644 --- a/code/fgame/VehicleWheelsX2.cpp +++ b/code/fgame/VehicleWheelsX2.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2018 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,64 +22,667 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "vehicle.h" #include "player.h" +#include "debuglines.h" +#include "g_phys.h" -CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX2, "VehicleWheelsX2") -{ - { &EV_Damage, &VehicleWheelsX2::EventDamage }, - { &EV_Killed, &VehicleWheelsX2::Killed }, - { NULL, NULL } +CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX2, "VehicleWheelsX2") { + {&EV_Damage, &VehicleWheelsX2::EventDamage}, + {&EV_Killed, &VehicleWheelsX2::Killed }, + {NULL, NULL } }; VehicleWheelsX2::VehicleWheelsX2() { - m_iGear = 1; - m_iRPM = 0; - gravity = 1.0; - m_fDifferentialRatio = 4.8800001f; - m_fGearEfficiency = 0.69999999f; - m_fGearRatio[0] = -2.9400001f; - m_fGearRatio[1] = 2.9400001f; - m_fGearRatio[2] = 1.9400001f; - m_fGearRatio[3] = 1.0f; - m_fAccelerator = 0.0f; - m_bAutomatic = qtrue; - m_bBackSlipping = qfalse; - m_bFrontSlipping = qfalse; + gravity = 1.0; + m_fDifferentialRatio = 4.88f; + m_fGearEfficiency = 0.7f; + m_fGearRatio[0] = -2.95f; + m_fGearRatio[1] = 2.95f; + m_fGearRatio[2] = 1.95f; + m_fGearRatio[3] = 1.0f; + m_iGear = 1; + m_iRPM = 0; + m_fAccelerator = 0.0f; + m_bAutomatic = qtrue; + m_bBackSlipping = qfalse; + m_bFrontSlipping = qfalse; } -void VehicleWheelsX2::UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright) +void VehicleWheelsX2::Killed(Event *ev) { - // FIXME: STUB + deadflag = DEAD_DEAD; } float VehicleWheelsX2::TorqueLookup(int rpm) { - if (rpm <= 2099) - return 100.0; - if (rpm > 3599) - return 0.0; - return (100 * (3600 - rpm)) * 0.001; + if (rpm < 2100) { + return 100.0; + } else if (rpm >= 3600) { + return 0.0; + } else { + return (100 * (3600 - rpm)) / 1000.f; + } +} + +void VehicleWheelsX2::UpdateVariables( + Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright +) +{ + int i; + Vector vNewCG; + Vector vBoxSize; + float longspeed; + Vector _i, _j, _k; + Vector r_i, r_j, r_k; + Vector r_velocity; + float dots[4]; + + r_velocity = velocity; + + m_bIsSkidding = false; + vBoxSize = maxs - mins; + + SetControllerAngles(0, Vector(0, turnangle, 0)); + SetControllerAngles(1, Vector(0, turnangle, 0)); + + vNewCG = localorigin; + + if (vNewCG != m_vCG) { + m_vCG = vNewCG; + vNewCG -= localorigin; + + m_fWheelBase = vBoxSize.x; + m_fWheelFrontDist = vBoxSize.x * 0.5 - vNewCG.x; + m_fWheelBackDist = vBoxSize.x * -0.5 + vNewCG.x; + m_fTrackWidth = vBoxSize.y; + } + + Vector vNewVpn = angles; + vNewVpn.AngleVectorsLeft(&r_i, &r_j, &r_k); + vNewVpn.y += turnangle; + vNewVpn.AngleVectorsLeft(&_i, &_j, &_k); + + dots[3] = r_velocity * *vpn * 0.02; + dots[2] = r_velocity * *vright * 0.02; + dots[1] = r_velocity * *t_vpn * 0.02; + dots[0] = r_velocity * *t_vright * 0.02; + + m_sWheels[0].fTraction = 0.8f; + m_sWheels[1].fTraction = 0.9f; + m_sWheels[0].fYawOffset = 0; + m_sWheels[1].fYawOffset = DEG2RAD(turnangle); + m_sWheels[0].fLongDist = m_fWheelBackDist * 0.02; + m_sWheels[1].fLongDist = m_fWheelFrontDist * 0.02; + m_sWheels[0].fLatDist = m_fTrackWidth * -0.02; + m_sWheels[1].fLatDist = m_fTrackWidth * 0.02; + + // initialize the wheels + for (i = 0; i < 2; i++) { + m_sWheels[i].fLongForce = 0; + m_sWheels[i].fForce = 0; + + m_sWheels[i].vLongForce = vec_zero; + m_sWheels[i].vLatForce = vec_zero; + m_sWheels[i].vForce = vec_zero; + m_sWheels[i].vVelocity = vec_zero; + m_sWheels[i].bSkidding = false; + m_sWheels[i].bSpinning = false; + m_sWheels[i].fTorque = 0; + m_sWheels[i].fLatTorque = 0; + m_sWheels[i].fLongTorque = 0; + } + + for (i = 0; i < 2; i++) { + Vector p1, p3, p4; + Vector vTp, vTr, vTu; + vec3_t p2; + + p3 = Corners[i]; + p3.normalize(); + + vectoangles(p3, p2); + p1 = vec_zero; + p1[1] = angles[1] + p2[1] + 90; + p1.AngleVectorsLeft(&vTp, &vTr, &vTu); + + m_sWheels[i].vVelocity = vTp * RAD2DEG(m_vAngularVelocity.y) * fabs(m_sWheels[i].fLongDist) * level.frametime; + + G_LineWidth(5.0); + + G_DebugLine( + origin + Corners[i][0] * r_i + Corners[i][1] * r_j, + origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vVelocity * 50, + 0.7f, + 0.5f, + 1.0f, + 1.0f + ); + + p1 = vec_zero; + p1[1] = angles[1] + RAD2DEG(m_sWheels[i].fYawOffset); + p1.AngleVectorsLeft(&vTp, &vTr, &vTu); + + m_sWheels[i].vOrientation = vTp; + + G_LineWidth(5.0); + + G_DebugLine( + origin + Corners[i][0] * r_i + Corners[i][1] * r_j, + origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vOrientation * 50, + 0.7f, + 0.0f, + 1.0f, + 1.0f + ); + } + + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8); + Vector t_maxs(8, 8, 8); + trace_t trace; + + start = origin + *vpn * (m_vCG[0] - localorigin[0]) + *vright * (m_vCG[1] - localorigin[1]) + + *vup * (m_vCG[2] - localorigin[2]); + + end = start; + end[2] -= maxtracedist; + + trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners"); + + m_fInertia = m_fMass * 100; + m_fWheelFrontLoad = m_fMass * 9.81 * fabs(m_fWheelFrontDist / m_fWheelBase); + m_fWheelBackLoad = m_fMass * 9.81 * fabs(m_fWheelBackDist / m_fWheelBase); + + longspeed = m_vAcceleration.length() * 0.02 * m_fMass / m_fWheelBase; + m_fWheelFrontLoad -= longspeed; + m_fWheelBackLoad += longspeed; + m_sWheels[0].fLoad = m_fWheelBackLoad; + m_sWheels[1].fLoad = m_fWheelFrontLoad; + + float fMassShifted = m_fTireRadius * M_PI; + m_fTireRotationalSpeed = dots[3] / (fMassShifted + fMassShifted); + m_iRPM = m_fTireRotationalSpeed * m_fGearRatio[m_iGear] * m_fDifferentialRatio * 10; + m_fMaxTraction = + TorqueLookup(m_iRPM) * m_fGearRatio[m_iGear] * m_fDifferentialRatio * m_fGearEfficiency / m_fTireRadius; + m_fTractionForce = m_fAccelerator * m_fMaxTraction; + + if (m_bIsBraking && dots[3] > 0) { + m_fTractionForce = -fSign(dots[3]) * 1000 * dots[3]; + } + + for (i = 0; i < 2; i++) { + float maxgrip; + + maxgrip = m_sWheels[i].fTraction * m_sWheels[i].fLoad * 9.81; + if (m_fTractionForce > maxgrip) { + m_fTractionForce = maxgrip * 0.6; + m_sWheels[i].bSpinning = true; + m_sWheels[i].bSkidding = true; + Com_Printf("Skidding!\n"); + } + + if (m_fTractionForce < -maxgrip) { + m_fTractionForce = -maxgrip * 0.6; + m_sWheels[i].bSkidding = true; + Com_Printf("Skidding!\n"); + } + + m_sWheels[i].fLongForce = this->m_sWheels[i].fLongForce + m_fTractionForce; + m_sWheels[i].vLongForce += m_sWheels[i].vOrientation * m_sWheels[i].fLongForce; + } + + m_vResistance[0] = + -(velocity[0] * 0.02 * m_fRollingResistance + velocity[0] * 0.02 * m_fDrag * fabs(velocity[0] * 0.02)); + m_vResistance[1] = + -(velocity[1] * 0.02 * m_fRollingResistance + velocity[1] * 0.02 * m_fDrag * fabs(velocity[1] * 0.02)); + m_vResistance[2] = + -(velocity[2] * 0.02 * m_fRollingResistance + velocity[2] * 0.02 * m_fDrag * fabs(velocity[2] * 0.02)); + + m_fBrakingPerformance = -m_fRollingResistance - *vpn * Vector(0, 0, -1) * m_fMass; + if (dots[3] == 0) { + m_fBrakingPerformance = 0; + } else { + m_fBrakingPerformance = (dots[3] - (m_fTireRotationalSpeed * m_fTireRadius - m_fBrakingPerformance)) / dots[3]; + m_fBrakingPerformance = (1.0 - m_fBrakingPerformance) * -(-m_fFrontBrakingForce - m_fBackBrakingForce); + } + + if (r_velocity.length() * 0.02 > 0.01) { + m_fTangForce = 0; + m_vTangForce = vec_zero; + + for (i = 0; i < 2; i++) { + Vector va, vr; + Vector vVel; + Vector v1, v2; + + va = angles; + va.x = 0; + va.y += RAD2DEG(m_sWheels[i].fYawOffset); + va.z = 0; + va.AngleVectorsLeft(NULL, &vr, NULL); + + vVel = m_sWheels[i].vVelocity + velocity; + // get the direction + v1 = vVel; + v1.normalize(); + // get the angles + vectoangles(v1, v2); + + m_sWheels[i].fSlipAngle = DEG2RAD(angledist(va.y - v2.y)); + m_sWheels[i].fGripCoef = m_sWheels[i].fSlipAngle * 0.15; + m_sWheels[i].fGripCoef = Q_clamp_float(m_sWheels[i].fGripCoef, -1.2f, 1.2f); + m_sWheels[i].fLatForce += m_sWheels[i].fGripCoef * m_sWheels[i].fLoad * 9.81; + + if (m_sWheels[i].fLoad * 2 * m_sWheels[i].fTraction < fabs(m_sWheels[i].fLatForce)) { + m_sWheels[i].fLatForce = m_sWheels[i].fLatForce / 9.81; + m_sWheels[i].bSkidding = true; + Com_Printf("Skidding %i!\n", i); + } + + m_sWheels[i].vLatForce += vr * m_sWheels[i].fLatForce; + + G_LineWidth(3.0); + + G_DebugLine( + origin + Corners[i][0] * r_i + Corners[i][1] * r_j, + origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vLatForce * 50 * (1.0 / m_fMass), + 0.7f, + 0.5f, + 0.2f, + 1.0f + ); + } + } else { + m_fTangForce = 0; + m_vTangForce = vec_zero; + } + + m_vForce = vec_zero; + + for (i = 0; i < 2; i++) { + m_sWheels[i].vForce = m_sWheels[i].vLatForce + m_sWheels[i].vLongForce; + m_vForce += m_sWheels[i].vForce; + } + + m_vForce += m_vResistance; + + G_LineWidth(5.0); + + G_DebugLine(origin, origin + m_vTangForce * (1.0 / m_fMass) * 50, 1.0, 0.0, 1.0, 1.0); + + m_vAcceleration = m_vForce * (1.0 / m_fMass) * 50; + m_fTorque = 0; + + for (i = 0; i < 2; i++) { + m_sWheels[i].fTorque += m_sWheels[i].fLongTorque + m_sWheels[i].fLatTorque; + m_fTorque += m_sWheels[i].fTorque; + } + + m_vAngularAcceleration[1] = angledist(RAD2DEG(m_fTorque)); + m_vAngularVelocity += m_vAngularAcceleration * level.frametime; + m_vAngularVelocity *= 0.825f; + avelocity = m_vAngularVelocity; + + if (m_bAutomatic) { + // + // set the gear + // + if (m_iRPM >= 2100 && m_iGear <= 2) { + m_iGear++; + } + if (m_iRPM <= 600 && m_iGear > 1) { + m_iGear--; + } + } + + prev_moveimpulse = moveimpulse; } void VehicleWheelsX2::Think() { - vmove_t vm; + vmove_t vm; - flags |= FL_POSTTHINK; - prev_velocity = velocity; + flags |= FL_POSTTHINK; + prev_velocity = velocity; - SetMoveInfo(&vm); - VmoveSingle(&vm); - GetMoveInfo(&vm); + SetMoveInfo(&vm); + VmoveSingle(&vm); + GetMoveInfo(&vm); } void VehicleWheelsX2::Postthink() { - // FIXME: STUB -} + float turn; + Vector i, j, k; + int index; + trace_t trace; + Vector normalsum; + Vector normalsum_Front; + int numnormals_Front; + Vector normalsum_Back; + int numnormals_Back; + Vector temp; + Vector pitch, roll; + Vector acceleration; + Vector atmp, atmp2, aup; + VehicleBase *v; + VehicleBase *last; + float drivespeed; + Vector primal_angles; + Vector vTmp; + Vector n_angles; -void VehicleWheelsX2::Killed(Event* ev) -{ - deadflag = DEAD_DEAD; -} + primal_angles = angles; + if (drivable) { + currentspeed = moveimpulse; + turnangle = turnangle * 0.25f + turnimpulse; + turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate); + + if (turnangle > maxturnrate) { + turnangle = maxturnrate; + } else if (turnangle < -maxturnrate) { + turnangle = -maxturnrate; + } else if (fabs(turnangle) < 2) { + turnangle = 0; + } + + real_velocity = origin - prev_origin; + prev_origin = origin; + prev_acceleration = real_acceleration; + real_acceleration = real_velocity - prev_velocity; + prev_velocity = real_velocity; + acceleration = real_acceleration - prev_acceleration; + + angles[0] = 0; + angles[2] = 0; + + temp[0] = angles[0]; + temp[1] = angles[1]; + temp[2] = angles[2]; + temp.AngleVectorsLeft(&i, &j, &k); + + j = vec_zero - j; + + index = 0; + numnormals_Front = 0; + numnormals_Back = 0; + + for (index = 0; index < 4; index++) { + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8); + Vector t_maxs(8, 8, 8); + + boxoffset = Corners[index]; + + start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2]; + end = start; + end[2] -= maxtracedist; + + trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners"); + + if (trace.fraction != 1 && !trace.startsolid) { + if (index > 2) { + normalsum_Front += trace.plane.normal; + numnormals_Front++; + } else { + normalsum_Back += trace.plane.normal; + numnormals_Back++; + } + + normalsum += trace.plane.normal; + } + } + + if (angles[2] < 60 || angles[2] > 300) { + if (numnormals_Front > 1) { + m_vFrontNormal = normalsum_Front * (1.0 / numnormals_Front); + + temp = m_vFrontNormal; + m_vFrontAngles[0] = -temp.CrossProduct(temp, j).toPitch(); + // no yaw + m_vFrontAngles[1] = 0; + + temp = m_vFrontNormal; + m_vFrontAngles[2] = temp.CrossProduct(temp, i).toPitch(); + } + + if (numnormals_Back > 1) { + m_vBackNormal = normalsum_Back * (1.0 / numnormals_Back); + + temp = m_vBackNormal; + m_vBackAngles[0] = -temp.CrossProduct(temp, j).toPitch(); + // no yaw + m_vBackAngles[1] = 0; + + temp = m_vBackNormal; + m_vBackAngles[2] = temp.CrossProduct(temp, i).toPitch(); + } + + if (numnormals_Front + numnormals_Back > 1) { + m_vBaseNormal = (normalsum_Front + normalsum_Back) * (1.0 / numnormals_Front + numnormals_Back); + + temp = m_vBaseNormal; + m_vBaseAngles[0] = -temp.CrossProduct(temp, j).toPitch(); + // no yaw + m_vBaseAngles[1] = 0; + + temp = m_vBaseNormal; + m_vBaseAngles[2] = temp.CrossProduct(temp, i).toPitch(); + } + } + + n_angles = m_vBaseAngles - angles; + n_angles[0] = angledist(n_angles[0]); + n_angles[1] = angledist(n_angles[1]); + n_angles[2] = angledist(n_angles[2]); + + angles[0] += n_angles[0] * 4.5 * level.frametime; + angles[2] += n_angles[2] * 4.5 * level.frametime; + + m_vPrevNormal = m_vBaseNormal; + + if (currentspeed < 0 && velocity * i > 0) { + m_fFrontBrakingForce = 0.2f; + m_fBackBrakingForce = 0.1f; + } else { + m_fFrontBrakingForce = 0; + m_fBackBrakingForce = 0; + } + + turn = turnangle * 0.005; + + Vector _i, _j, _k; + Vector vNewVpn = angles; + vNewVpn.y += turnangle; + + vNewVpn.AngleVectorsLeft(&_i, &_j, &_k); + UpdateVariables(&acceleration, &i, &j, &k, &_i, &_j, &_k); + + m_vAngles = angles; + + if (currentspeed < 0 && velocity * i > 0) { + currentspeed = 0; + } + + normalsum = vec_zero; + + for (index = 0; index < 4; index++) { + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8); + Vector t_maxs(8, 8, 8); + + boxoffset = Corners[index]; + + start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2] + Vector(0, 0, 10); + end = start; + end[2] -= maxtracedist; + + trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners"); + + if (trace.fraction != 1.0) { + float fCoef; + + if (index > 2) { + fCoef = m_fWheelFrontLoad / (m_fWheelFrontDist / m_fWheelBase * m_fMass); + fCoef = Q_clamp_float(fCoef, 0, 1); + + normalsum += _i * currentspeed * fCoef; + normalsum += i * currentspeed * (1.0 - fCoef); + } else { + fCoef = m_fWheelBackLoad / (m_fWheelBackDist / m_fWheelBase * m_fMass); + fCoef = Q_clamp_float(fCoef, 0, 1); + + normalsum += i * currentspeed * fCoef; + normalsum += _i * currentspeed * (1.0 - fCoef); + } + } + } + + AnglesToAxis(angles, orientation); + + vmove_t vm; + SetMoveInfo(&vm); + m_sMoveGrid->SetMoveInfo(&vm); + m_sMoveGrid->SetOrientation(orientation); + + if (m_sMoveGrid->CheckStuck()) { + angles = primal_angles; + AnglesToAxis(angles, orientation); + } + + if (groundentity && (angles[2] < 60 || angles[2] > 300)) { + float dot; + Vector newvel, flatvel; + + velocity[0] *= 0.925f; + velocity[1] *= 0.925f; + + newvel = orientation[0]; + velocity += newvel * currentspeed; + newvel[2] = 0; + + dot = velocity * newvel; + dot = Q_clamp_float(dot, -speed, speed); + + if (dot > speed) { + dot = speed; + } else if (dot < -speed) { + dot = -speed; + } else if (fabs(dot) < 20) { + dot = 0; + } + + flatvel = newvel * dot; + + velocity[0] = flatvel[0]; + velocity[1] = flatvel[1]; + velocity[2] += jumpimpulse * dot; + avelocity *= 0.05f; + + if (steerinplace) { + if (dot < 350) { + dot = 350; + } + + avelocity.y += turn * dot; + } else { + avelocity.y += turn * dot; + } + } else { + if (angles[2] > 60) { + angles[2]; // FIXME: ?? + } + + velocity += m_vAcceleration * level.frametime; + } + + angles += avelocity * level.frametime; + setAngles(angles); + + prev_origin = origin; + } + + drivespeed = acceleration * orientation[0]; + + if (drivable && driver.ent) { + str sound_name; + + if (currentspeed > 0) { + sound_name = "snd_forward"; + } else if (currentspeed == 0) { + sound_name = "snd_idle"; + } else { + sound_name = "snd_backward"; + } + + LoopSound(sound_name); + } + + i = orientation[0]; + j = orientation[1]; + k = orientation[2]; + + if (driver.ent) { + driver.ent->setOrigin(origin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2]); + + if (drivable) { + // clear the driver velocity + driver.ent->velocity = vec_zero; + // set the driver angles to the vehicle's angle + driver.ent->setAngles(angles); + } + } + + vTmp = (angles - primal_angles) * level.frametime; + if (vTmp.x > 180 || vTmp.x < -180) { + vTmp.x = 0; + } + if (vTmp.y > 180 || vTmp.y < -180) { + vTmp.y = 0; + } + if (vTmp.z > 180 || vTmp.z < -180) { + vTmp.z = 0; + } + + if (vTmp.x > -1 || vTmp.x < 1) { + vTmp.x = 0; + } + if (vTmp.y > -1 || vTmp.y < 1) { + vTmp.y = 0; + } + if (vTmp.z > -1 || vTmp.z < 1) { + vTmp.z = 0; + } + + avelocity = vTmp; + + for (last = this; last->vlink; last = v) { + v = last->vlink; + + v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z); + v->avelocity = avelocity; + v->velocity = velocity; + + v->angles[ROLL] = angles[ROLL]; + v->angles[YAW] = angles[YAW]; + v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360; + v->setAngles(v->angles); + } + + CheckWater(); + WorldEffects(); + + last_origin = origin; + + if (!driver.ent && !velocity.length() && groundentity && !(watertype & CONTENTS_LAVA)) { + // make the vehicle stationary if it's completely immobile + flags &= ~FL_POSTTHINK; + if (drivable) { + setMoveType(MOVETYPE_STATIONARY); + } + } +} diff --git a/code/fgame/VehicleWheelsX4.cpp b/code/fgame/VehicleWheelsX4.cpp index 59aea106..27ef7276 100644 --- a/code/fgame/VehicleWheelsX4.cpp +++ b/code/fgame/VehicleWheelsX4.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2018 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,69 +22,680 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "vehicle.h" #include "player.h" +#include "debuglines.h" +#include "g_phys.h" -CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX4, "VehicleWheelsX4") -{ - { &EV_Damage, &VehicleWheelsX4::EventDamage }, - { &EV_Killed, &VehicleWheelsX4::Killed }, - { NULL, NULL } +CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX4, "VehicleWheelsX4") { + {&EV_Damage, &VehicleWheelsX4::EventDamage}, + {&EV_Killed, &VehicleWheelsX4::Killed }, + {NULL, NULL } }; VehicleWheelsX4::VehicleWheelsX4() { - m_iGear = 1; - m_iRPM = 0; - gravity = 1.0; - m_fDifferentialRatio = 4.8800001f; - m_fGearEfficiency = 0.69999999f; - m_fGearRatio[0] = -2.9400001f; - m_fGearRatio[1] = 2.9400001f; - m_fGearRatio[2] = 1.9400001f; - m_fGearRatio[3] = 1.0f; - m_fAccelerator = 0.0f; - m_bBackSlipping = qfalse; - m_bAutomatic = qtrue; - m_bFrontSlipping = qfalse; + gravity = 1.0; + m_fDifferentialRatio = 4.88f; + m_fGearEfficiency = 0.7f; + m_fGearRatio[0] = -2.95f; + m_fGearRatio[1] = 2.95f; + m_fGearRatio[2] = 1.95f; + m_fGearRatio[3] = 1.0f; + m_iGear = 1; + m_iRPM = 0; + m_fAccelerator = 0.0f; + m_bAutomatic = qtrue; + m_bBackSlipping = qfalse; + m_bFrontSlipping = qfalse; } -void VehicleWheelsX4::UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright) +void VehicleWheelsX4::UpdateVariables( + Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright +) { - // FIXME: STUB + int i; + Vector vNewCG; + Vector vBoxSize; + float longspeed; + Vector _i, _j, _k; + Vector r_i, r_j, r_k; + Vector r_velocity; + float dots[4]; + + r_velocity = velocity; + + m_bIsSkidding = false; + vBoxSize = maxs - mins; + + SetControllerAngles(0, Vector(0, turnangle, 0)); + SetControllerAngles(1, Vector(0, turnangle, 0)); + + vNewCG = localorigin; + + if (vNewCG != m_vCG) { + m_vCG = vNewCG; + vNewCG -= localorigin; + + m_fWheelBase = vBoxSize.x; + m_fWheelFrontDist = vBoxSize.x * 0.5 - vNewCG.x; + m_fWheelBackDist = vBoxSize.x * -0.5 + vNewCG.x; + m_fTrackWidth = vBoxSize.y; + } + + Vector vNewVpn = angles; + vNewVpn.AngleVectorsLeft(&r_i, &r_j, &r_k); + vNewVpn.y += turnangle; + vNewVpn.AngleVectorsLeft(&_i, &_j, &_k); + + dots[3] = r_velocity * *vpn * 0.02; + dots[2] = r_velocity * *vright * 0.02; + dots[1] = r_velocity * *t_vpn * 0.02; + dots[0] = r_velocity * *t_vright * 0.02; + + m_sWheels[0].fTraction = 0.8f; + m_sWheels[1].fTraction = 0.9f; + m_sWheels[2].fTraction = 0.8f; + m_sWheels[3].fTraction = 0.9f; + m_sWheels[0].fYawOffset = 0; + m_sWheels[1].fYawOffset = DEG2RAD(turnangle); + m_sWheels[2].fYawOffset = 0; + m_sWheels[3].fYawOffset = DEG2RAD(turnangle); + m_sWheels[0].fLongDist = m_fWheelBackDist * 0.02; + m_sWheels[1].fLongDist = m_fWheelFrontDist * 0.02; + m_sWheels[2].fLongDist = m_fWheelBackDist * 0.02; + m_sWheels[3].fLongDist = m_fWheelFrontDist * 0.02; + m_sWheels[0].fLatDist = m_fTrackWidth * 0.5 * -0.02; + m_sWheels[1].fLatDist = m_fTrackWidth * 0.5 * 0.02; + m_sWheels[2].fLatDist = m_fTrackWidth * 0.5 * -0.02; + m_sWheels[3].fLatDist = m_fTrackWidth * 0.5 * 0.02; + + // initialize the wheels + for (i = 0; i < 4; i++) { + m_sWheels[i].fLongForce = 0; + m_sWheels[i].fForce = 0; + + m_sWheels[i].vLongForce = vec_zero; + m_sWheels[i].vLatForce = vec_zero; + m_sWheels[i].vForce = vec_zero; + m_sWheels[i].vVelocity = vec_zero; + m_sWheels[i].bSkidding = false; + m_sWheels[i].bSpinning = false; + m_sWheels[i].fTorque = 0; + m_sWheels[i].fLatTorque = 0; + m_sWheels[i].fLongTorque = 0; + } + + for (i = 0; i < 4; i++) { + Vector p1, p3, p4; + Vector vTp, vTr, vTu; + vec3_t p2; + + p3 = Corners[i]; + p3.normalize(); + + vectoangles(p3, p2); + p1 = vec_zero; + p1[1] = angles[1] + p2[1] + 90; + p1.AngleVectorsLeft(&vTp, &vTr, &vTu); + + m_sWheels[i].vVelocity = vTp * RAD2DEG(m_vAngularVelocity.y) * fabs(m_sWheels[i].fLongDist) * level.frametime; + + G_LineWidth(5.0); + + G_DebugLine( + origin + Corners[i][0] * r_i + Corners[i][1] * r_j, + origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vVelocity * 50, + 0.7f, + 0.5f, + 1.0f, + 1.0f + ); + + p1 = vec_zero; + p1[1] = angles[1] + RAD2DEG(m_sWheels[i].fYawOffset); + p1.AngleVectorsLeft(&vTp, &vTr, &vTu); + + m_sWheels[i].vOrientation = vTp; + + G_LineWidth(5.0); + + G_DebugLine( + origin + Corners[i][0] * r_i + Corners[i][1] * r_j, + origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vOrientation * 50, + 0.7f, + 0.0f, + 1.0f, + 1.0f + ); + } + + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8); + Vector t_maxs(8, 8, 8); + trace_t trace; + + start = origin + *vpn * (m_vCG[0] - localorigin[0]) + *vright * (m_vCG[1] - localorigin[1]) + + *vup * (m_vCG[2] - localorigin[2]); + + end = start; + end[2] -= maxtracedist; + + trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners"); + + m_fInertia = m_fMass * 100; + m_fWheelFrontLoad = m_fMass * 9.81 * fabs(m_fWheelFrontDist / m_fWheelBase); + m_fWheelBackLoad = m_fMass * 9.81 * fabs(m_fWheelBackDist / m_fWheelBase); + + longspeed = m_vAcceleration.length() * 0.02 * m_fMass / m_fWheelBase; + m_fWheelFrontLoad -= longspeed; + m_fWheelBackLoad += longspeed; + m_sWheels[0].fLoad = m_fWheelBackLoad / 2.0; + m_sWheels[1].fLoad = m_fWheelBackLoad / 2.0; + m_sWheels[2].fLoad = m_fWheelFrontLoad / 2.0; + m_sWheels[3].fLoad = m_fWheelFrontLoad / 2.0; + + float fMassShifted = m_fTireRadius * M_PI; + m_fTireRotationalSpeed = dots[3] / (fMassShifted + fMassShifted); + m_iRPM = m_fTireRotationalSpeed * m_fGearRatio[m_iGear] * m_fDifferentialRatio * 10; + m_fMaxTraction = + TorqueLookup(m_iRPM) * m_fGearRatio[m_iGear] * m_fDifferentialRatio * m_fGearEfficiency / m_fTireRadius; + m_fTractionForce = m_fAccelerator * m_fMaxTraction; + + if (m_bIsBraking && dots[3] > 0) { + m_fTractionForce = -fSign(dots[3]) * 1000 * dots[3]; + } + + for (i = 0; i < 4; i++) { + float maxgrip; + + maxgrip = m_sWheels[i].fTraction * m_sWheels[i].fLoad * 9.81; + if (m_fTractionForce > maxgrip) { + m_fTractionForce = maxgrip * 0.6; + m_sWheels[i].bSpinning = true; + m_sWheels[i].bSkidding = true; + Com_Printf("Skidding!\n"); + } + + if (m_fTractionForce < -maxgrip) { + m_fTractionForce = -maxgrip * 0.6; + m_sWheels[i].bSkidding = true; + Com_Printf("Skidding!\n"); + } + + m_sWheels[i].fLongForce = this->m_sWheels[i].fLongForce + m_fTractionForce; + m_sWheels[i].vLongForce += m_sWheels[i].vOrientation * m_sWheels[i].fLongForce; + } + + m_vResistance[0] = + -(velocity[0] * 0.02 * m_fRollingResistance + velocity[0] * 0.02 * m_fDrag * fabs(velocity[0] * 0.02)); + m_vResistance[1] = + -(velocity[1] * 0.02 * m_fRollingResistance + velocity[1] * 0.02 * m_fDrag * fabs(velocity[1] * 0.02)); + m_vResistance[2] = + -(velocity[2] * 0.02 * m_fRollingResistance + velocity[2] * 0.02 * m_fDrag * fabs(velocity[2] * 0.02)); + + m_fBrakingPerformance = -m_fRollingResistance - *vpn * Vector(0, 0, -1) * m_fMass; + if (dots[3] == 0) { + m_fBrakingPerformance = 0; + } else { + m_fBrakingPerformance = (dots[3] - (m_fTireRotationalSpeed * m_fTireRadius - m_fBrakingPerformance)) / dots[3]; + m_fBrakingPerformance = (1.0 - m_fBrakingPerformance) * -(-m_fFrontBrakingForce - m_fBackBrakingForce); + } + + if (r_velocity.length() * 0.02 > 0.01) { + m_fTangForce = 0; + m_vTangForce = vec_zero; + + for (i = 0; i < 2; i++) { + Vector va, vr; + Vector vVel; + Vector v1, v2; + + va = angles; + va.x = 0; + va.y += RAD2DEG(m_sWheels[i].fYawOffset); + va.z = 0; + va.AngleVectorsLeft(NULL, &vr, NULL); + + vVel = m_sWheels[i].vVelocity + velocity; + // get the direction + v1 = vVel; + v1.normalize(); + // get the angles + vectoangles(v1, v2); + + m_sWheels[i].fSlipAngle = DEG2RAD(angledist(va.y - v2.y)); + m_sWheels[i].fGripCoef = m_sWheels[i].fSlipAngle * 0.15; + m_sWheels[i].fGripCoef = Q_clamp_float(m_sWheels[i].fGripCoef, -1.2f, 1.2f); + m_sWheels[i].fLatForce += m_sWheels[i].fGripCoef * m_sWheels[i].fLoad * 9.81; + + if (m_sWheels[i].fLoad * 2 * m_sWheels[i].fTraction < fabs(m_sWheels[i].fLatForce)) { + m_sWheels[i].fLatForce = m_sWheels[i].fLatForce / 9.81; + m_sWheels[i].bSkidding = true; + Com_Printf("Skidding %i!\n", i); + } + + m_sWheels[i].vLatForce += vr * m_sWheels[i].fLatForce; + + G_LineWidth(3.0); + + G_DebugLine( + origin + Corners[i][0] * r_i + Corners[i][1] * r_j, + origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vLatForce * 50 * (1.0 / m_fMass), + 0.7f, + 0.5f, + 0.2f, + 1.0f + ); + } + } else { + m_fTangForce = 0; + m_vTangForce = vec_zero; + } + + m_vForce = vec_zero; + + for (i = 0; i < 4; i++) { + m_sWheels[i].vForce = m_sWheels[i].vLatForce + m_sWheels[i].vLongForce; + m_vForce += m_sWheels[i].vForce; + } + + m_vForce += m_vResistance; + + G_LineWidth(5.0); + + G_DebugLine(origin, origin + m_vTangForce * (1.0 / m_fMass) * 50, 1.0, 0.0, 1.0, 1.0); + + m_vAcceleration = m_vForce * (1.0 / m_fMass) * 50; + m_fTorque = 0; + + for (i = 0; i < 4; i++) { + m_sWheels[i].fTorque += m_sWheels[i].fLongTorque + m_sWheels[i].fLatTorque; + m_fTorque += m_sWheels[i].fTorque; + } + + m_vAngularAcceleration[1] = angledist(RAD2DEG(m_fTorque)); + m_vAngularVelocity += m_vAngularAcceleration * level.frametime; + m_vAngularVelocity *= 0.825f; + avelocity = m_vAngularVelocity; + + if (m_bAutomatic) { + // + // set the gear + // + if (m_iRPM >= 2100 && m_iGear <= 2) { + m_iGear++; + } + if (m_iRPM <= 600 && m_iGear > 1) { + m_iGear--; + } + } + + prev_moveimpulse = moveimpulse; +} + +void VehicleWheelsX4::Killed(Event *ev) +{ + deadflag = DEAD_DEAD; } float VehicleWheelsX4::TorqueLookup(int rpm) { - if (rpm <= 2099) - return 20.0; - if (rpm > 3599) - return 0.0; - return (20 * (3600 - rpm)) * 0.001; + if (rpm <= 2099) { + return 20.0; + } + if (rpm > 3599) { + return 0.0; + } + return (20 * (3600 - rpm)) * 0.001; } void VehicleWheelsX4::Think() { - vmove_t vm; - flags |= FL_POSTTHINK; - - prev_velocity = velocity; + vmove_t vm; + flags |= FL_POSTTHINK; - angles -= m_vAnglesOffset; - origin -= m_vOriginOffset; + prev_velocity = velocity; - mins = m_vOldMins; - maxs = m_vOldMaxs; + angles -= m_vAnglesOffset; + origin -= m_vOriginOffset; - SetMoveInfo(&vm); - VmoveSingle(&vm); - GetMoveInfo(&vm); + mins = m_vOldMins; + maxs = m_vOldMaxs; + + SetMoveInfo(&vm); + VmoveSingle(&vm); + GetMoveInfo(&vm); } void VehicleWheelsX4::Postthink() { - // FIXME: STUB -} + float turn; + Vector i, j, k; + int index; + trace_t trace; + Vector normalsum; + Vector normalsum_Front; + int numnormals_Front; + Vector normalsum_Back; + int numnormals_Back; + Vector temp; + Vector pitch, roll; + Vector acceleration; + Vector atmp, atmp2, aup; + VehicleBase *v; + VehicleBase *last; + float drivespeed; + Vector primal_angles; + Vector vTmp; + Vector n_angles; -void VehicleWheelsX4::Killed(Event* ev) -{ - deadflag = DEAD_DEAD; + primal_angles = angles; + + if (drivable) { + if (m_bAutoPilot) { + AutoPilot(); + } else { + moveimpulse *= 0.825f; + turnimpulse *= 0.825f; + } + + currentspeed = moveimpulse; + turnangle = turnangle * 0.25f + turnimpulse; + turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate); + + if (turnangle > maxturnrate) { + turnangle = maxturnrate; + } else if (turnangle < -maxturnrate) { + turnangle = -maxturnrate; + } else if (fabs(turnangle) < 2) { + turnangle = 0; + } + + real_velocity = origin - prev_origin; + prev_origin = origin; + prev_acceleration = real_acceleration; + real_acceleration = real_velocity - prev_velocity; + prev_velocity = real_velocity; + acceleration = real_acceleration - prev_acceleration; + + angles[0] = 0; + angles[2] = 0; + + temp[0] = angles[0]; + temp[1] = angles[1]; + temp[2] = angles[2]; + temp.AngleVectorsLeft(&i, &j, &k); + + j = vec_zero - j; + + index = 0; + numnormals_Front = 0; + numnormals_Back = 0; + + for (index = 0; index < 4; index++) { + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8); + Vector t_maxs(8, 8, 8); + + boxoffset = Corners[index]; + + start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2]; + end = start; + end[2] -= maxtracedist; + + trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners"); + + if (trace.fraction != 1 && !trace.startsolid) { + if (index > 2) { + normalsum_Front += trace.plane.normal; + numnormals_Front++; + } else { + normalsum_Back += trace.plane.normal; + numnormals_Back++; + } + + normalsum += trace.plane.normal; + } + } + + if (angles[2] < 60 || angles[2] > 300) { + if (numnormals_Front > 1) { + m_vFrontNormal = normalsum_Front * (1.0 / numnormals_Front); + + temp = m_vFrontNormal; + m_vFrontAngles[0] = -temp.CrossProduct(temp, j).toPitch(); + // no yaw + m_vFrontAngles[1] = 0; + + temp = m_vFrontNormal; + m_vFrontAngles[2] = temp.CrossProduct(temp, i).toPitch(); + } + + if (numnormals_Back > 1) { + m_vBackNormal = normalsum_Back * (1.0 / numnormals_Back); + + temp = m_vBackNormal; + m_vBackAngles[0] = -temp.CrossProduct(temp, j).toPitch(); + // no yaw + m_vBackAngles[1] = 0; + + temp = m_vBackNormal; + m_vBackAngles[2] = temp.CrossProduct(temp, i).toPitch(); + } + + if (numnormals_Front + numnormals_Back > 1) { + m_vBaseNormal = (normalsum_Front + normalsum_Back) * (1.0 / numnormals_Front + numnormals_Back); + + temp = m_vBaseNormal; + m_vBaseAngles[0] = -temp.CrossProduct(temp, j).toPitch(); + // no yaw + m_vBaseAngles[1] = 0; + + temp = m_vBaseNormal; + m_vBaseAngles[2] = temp.CrossProduct(temp, i).toPitch(); + } + } + + n_angles = m_vBaseAngles - angles; + n_angles[0] = angledist(n_angles[0]); + n_angles[1] = angledist(n_angles[1]); + n_angles[2] = angledist(n_angles[2]); + + angles[0] += n_angles[0] * 4.5 * level.frametime; + angles[2] += n_angles[2] * 4.5 * level.frametime; + + m_vPrevNormal = m_vBaseNormal; + + if (currentspeed < 0 && velocity * i > 0) { + m_fFrontBrakingForce = 0.2f; + m_fBackBrakingForce = 0.1f; + } else { + m_fFrontBrakingForce = 0; + m_fBackBrakingForce = 0; + } + + turn = turnangle * 0.005; + + Vector _i, _j, _k; + Vector vNewVpn = angles; + vNewVpn.y += turnangle; + + vNewVpn.AngleVectorsLeft(&_i, &_j, &_k); + UpdateVariables(&acceleration, &i, &j, &k, &_i, &_j, &_k); + + m_vAngles = angles; + + if (currentspeed < 0 && velocity * i > 0) { + currentspeed = 0; + } + + normalsum = vec_zero; + + for (index = 0; index < 4; index++) { + Vector start, end; + Vector boxoffset; + Vector t_mins(-8, -8, -8); + Vector t_maxs(8, 8, 8); + + boxoffset = Corners[index]; + + start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2] + Vector(0, 0, 10); + end = start; + end[2] -= maxtracedist; + + trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners"); + + if (trace.fraction != 1.0) { + float fCoef; + + if (index > 2) { + fCoef = m_fWheelFrontLoad / (m_fWheelFrontDist / m_fWheelBase * m_fMass); + fCoef = Q_clamp_float(fCoef, 0, 1); + + normalsum += _i * currentspeed * fCoef; + normalsum += i * currentspeed * (1.0 - fCoef); + } else { + fCoef = m_fWheelBackLoad / (m_fWheelBackDist / m_fWheelBase * m_fMass); + fCoef = Q_clamp_float(fCoef, 0, 1); + + normalsum += i * currentspeed * fCoef; + normalsum += _i * currentspeed * (1.0 - fCoef); + } + } + } + + AnglesToAxis(angles, orientation); + + vmove_t vm; + SetMoveInfo(&vm); + m_sMoveGrid->SetMoveInfo(&vm); + m_sMoveGrid->SetOrientation(orientation); + + if (m_sMoveGrid->CheckStuck()) { + angles = primal_angles; + AnglesToAxis(angles, orientation); + } + + m_fForwardForce = acceleration * i * 0.1; + m_fBackForce += -m_vAnglesOffset[0] * m_fBouncyCoef; + m_fBackForce *= m_fSpringyCoef; + + m_vAnglesOffset[0] += m_fForwardForce + m_fBackForce * 12.0 * level.frametime; + m_vAnglesOffset[0] = Q_clamp_float(m_vAnglesOffset[0], m_fYawMin, m_fYawMax); + + m_fLeftForce += acceleration * j * 0.1; + m_fRightForce += -m_vAnglesOffset[2] * m_fBouncyCoef; + m_fRightForce *= m_fSpringyCoef; + + m_vAnglesOffset[2] += (m_fLeftForce + m_fRightForce) * 12.0 * level.frametime; + m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fRollMin, m_fRollMax); + + m_fDownForce = acceleration[2]; + m_fUpForce += -m_vOriginOffset[2] * m_fBouncyCoef; + m_fUpForce *= m_fSpringyCoef; + + m_vAnglesOffset[2] += (m_fDownForce + m_fUpForce) * 12.0 * level.frametime; + m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fZMin, m_fZMax); + + if (groundentity && (angles[2] < 60 || angles[2] > 300)) { + velocity += m_vAcceleration * level.frametime; + } else { + if (angles[2] > 60) { + angles[2]; // FIXME: ?? + } + + velocity += m_vAcceleration * level.frametime; + } + + angles += avelocity * level.frametime; + setAngles(angles); + + prev_origin = origin; + } + + drivespeed = acceleration * orientation[0]; + + if (drivable && driver.ent) { + str sound_name; + + if (currentspeed > 0) { + sound_name = "snd_forward"; + } else if (currentspeed == 0) { + sound_name = "snd_idle"; + } else { + sound_name = "snd_backward"; + } + + LoopSound(sound_name); + } + + i = orientation[0]; + j = orientation[1]; + k = orientation[2]; + + last_origin = origin; + + vTmp = (angles - primal_angles) * level.frametime; + if (vTmp.x > 180 || vTmp.x < -180) { + vTmp.x = 0; + } + if (vTmp.y > 180 || vTmp.y < -180) { + vTmp.y = 0; + } + if (vTmp.z > 180 || vTmp.z < -180) { + vTmp.z = 0; + } + + if (vTmp.x > -1 || vTmp.x < 1) { + vTmp.x = 0; + } + if (vTmp.y > -1 || vTmp.y < 1) { + vTmp.y = 0; + } + if (vTmp.z > -1 || vTmp.z < 1) { + vTmp.z = 0; + } + + avelocity = vTmp; + origin += m_vOriginOffset; + setOrigin(origin); + + angles += m_vAnglesOffset; + setAngles(angles); + + if (driver.ent) { + driver.ent->setOrigin(origin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2]); + + if (drivable) { + // clear the driver velocity + driver.ent->velocity = vec_zero; + // set the driver angles to the vehicle's angle + driver.ent->setAngles(angles); + } + } + + for (last = this; last->vlink; last = v) { + v = last->vlink; + + v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z); + v->avelocity = avelocity; + v->velocity = velocity; + + v->angles[ROLL] = angles[ROLL]; + v->angles[YAW] = angles[YAW]; + v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360; + v->setAngles(v->angles); + } + + CheckWater(); + WorldEffects(); + + if (!driver.ent && !velocity.length() && groundentity && !(watertype & CONTENTS_LAVA)) { + // make the vehicle stationary if it's completely immobile + flags &= ~FL_POSTTHINK; + if (drivable) { + setMoveType(MOVETYPE_STATIONARY); + } + } } diff --git a/code/fgame/actor.cpp b/code/fgame/actor.cpp index 3d843e78..5045e93e 100644 --- a/code/fgame/actor.cpp +++ b/code/fgame/actor.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -46,12 +46,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "scriptexception.h" #include "parm.h" #include "../qcommon/tiki.h" +#include "smokesprite.h" #include -Vector MINS(-15.0,-15.0,0.0); -Vector MAXS(15.0,15.0,96.0); - extern Vector PLAYER_BASE_MIN; extern Vector PLAYER_BASE_MAX; @@ -59,2496 +57,2690 @@ bool bEntinfoInit = false; cvar_t *g_showinfo; -const char * gAmericanVoices[] = {"a", "c", "h"}; -const char * gGermanVoices[] = {"a", "c", "d"}; +const char *gAmericanVoices[] = {"a", "c", "h"}; +const char *gGermanVoices[] = {"a", "c", "d"}; + +static const float DEFAULT_NEARBY_SQUAD_DIST = 1024; +static const float MIN_BADPLACE_UPDATE_DIST = 256; Event EV_Actor_SetGun - ( - "gun", - EV_DEFAULT, - "s", - "s", - "specifies the gun to use" - ); - +( + "gun", + EV_DEFAULT, + "s", + "s", + "specifies the gun to use", + EV_NORMAL +); Event EV_Actor_SetGun2 - ( - "gun", - EV_DEFAULT, - "s", - "s", - "specifies the gun to use", - EV_SETTER - ); - +( + "gun", + EV_DEFAULT, + "s", + "s", + "specifies the gun to use", + EV_SETTER +); Event EV_Actor_GetGun - ( - "gun", - EV_DEFAULT, - NULL, - NULL, - "gets the gun to being used", - 2 - ); - +( + "gun", + EV_DEFAULT, + NULL, + NULL, + "gets the gun to being used", + EV_GETTER +); Event EV_Actor_WeaponInternal - ( - "weapon_internal", - EV_DEFAULT, - "s", - "s", - "internal use" - ); - +( + "weapon_internal", + EV_DEFAULT, + "s", + "s", + "internal use", + EV_NORMAL +); Event EV_Actor_TestAnim - ( - "testanim", - EV_DEFAULT, - NULL, - NULL, - "", - 0 - ); - +( + "testanim", + EV_DEFAULT, + NULL, + NULL, + "", + EV_NORMAL +); Event EV_Actor_DistToEnemy - ( - "distancetoenemy", - EV_DEFAULT, - NULL, - NULL, - "Get the distance from the Actor to its enemy", - EV_GETTER - ); - +( + "distancetoenemy", + EV_DEFAULT, + NULL, + NULL, + "Get the distance from the Actor to its enemy", + EV_GETTER +); Event EV_Actor_MoveTo - ( - "moveto", - EV_DEFAULT, - "ss", - "anim dest", - "Specify the location to move to, with animation anim." - ); - +( + "moveto", + EV_DEFAULT, + "ss", + "anim dest", + "Specify the location to move to, with animation anim.", + EV_NORMAL +); Event EV_Actor_WalkTo - ( - "walkto", - EV_DEFAULT, - "s", - "dest", - "Specify the location to walk to." - ); - +( + "walkto", + EV_DEFAULT, + "s", + "dest", + "Specify the location to walk to.", + EV_NORMAL +); Event EV_Actor_RunTo - ( - "runto", - EV_DEFAULT, - "s", - "dest", - "Specify the location to run to." - ); - +( + "runto", + EV_DEFAULT, + "s", + "dest", + "Specify the location to run to.", + EV_NORMAL +); Event EV_Actor_CrouchTo - ( - "crouchto", - EV_DEFAULT, - "s", - "dest", - "Specify the location to crouch to." - ); - +( + "crouchto", + EV_DEFAULT, + "s", + "dest", + "Specify the location to crouch to.", + EV_NORMAL +); Event EV_Actor_CrawlTo - ( - "crawlto", - EV_DEFAULT, - "s", - "dest", - "Specify the location to crawl to." - ); - +( + "crawlto", + EV_DEFAULT, + "s", + "dest", + "Specify the location to crawl to.", + EV_NORMAL +); Event EV_Actor_AimAt - ( - "aimat", - EV_DEFAULT, - "s", - "target", - "Specify the target to aim at." - ); - +( + "aimat", + EV_DEFAULT, + "s", + "target", + "Specify the target to aim at.", + EV_NORMAL +); Event EV_Actor_Follow - ( - "follow", - EV_DEFAULT, - "e", - "entity", - "Specify the entity to follow." - ); - +( + "follow", + EV_DEFAULT, + "e", + "entity", + "Specify the entity to follow.", + EV_NORMAL +); Event EV_Actor_DeathEmbalm - ( - "deathembalm", - EV_DEFAULT, - NULL, - NULL, - "preps the dead actor for turning nonsolid gradually over time" - ); - +( + "deathembalm", + EV_DEFAULT, + NULL, + NULL, + "preps the dead actor for turning nonsolid gradually over time", + EV_NORMAL +); Event EV_Actor_Anim - ( - "anim", - EV_DEFAULT, - "s", - "name", - "Play animation." - ); - +( + "anim", + EV_DEFAULT, + "s", + "name", + "Play animation.", + EV_NORMAL +); Event EV_Actor_Anim_Scripted - ( - "anim_scripted", - EV_DEFAULT, - "s", - "name", - "Play scripted animation." - ); - +( + "anim_scripted", + EV_DEFAULT, + "s", + "name", + "Play scripted animation.", + EV_NORMAL +); Event EV_Actor_Anim_Noclip - ( - "anim_noclip", - EV_DEFAULT, - "s", - "name", - "Play noclip animation." - ); - +( + "anim_noclip", + EV_DEFAULT, + "s", + "name", + "Play noclip animation.", + EV_NORMAL +); +Event EV_Actor_Anim_Attached +( + "anim_attached", + EV_DEFAULT, + "s", + "name", + "Play attached animation.", + EV_NORMAL +); Event EV_Actor_AnimLoop - ( - "animloop", - EV_DEFAULT, - "s", - "name", - "Loop animation." - ); - +( + "animloop", + EV_DEFAULT, + "s", + "name", + "Loop animation.", + EV_NORMAL +); Event EV_Actor_AnimScript - ( - "animscript", - EV_DEFAULT, - "s", - "name", - "Play the animation script" - ); - +( + "animscript", + EV_DEFAULT, + "s", + "name", + "Play the animation script", + EV_NORMAL +); Event EV_Actor_AnimScript_Scripted - ( - "animscript_scripted", - EV_DEFAULT, - "s", - "name", - "Play the scripted animation script" - ); - +( + "animscript_scripted", + EV_DEFAULT, + "s", + "name", + "Play the scripted animation script", + EV_NORMAL +); Event EV_Actor_AnimScript_Noclip - ( - "animscript_noclip", - EV_DEFAULT, - "s", - "name", - "Play the noclip animation script" - ); - +( + "animscript_noclip", + EV_DEFAULT, + "s", + "name", + "Play the noclip animation script", + EV_NORMAL +); +// Added in 2.0 +//==== +Event EV_Actor_AnimScript_Attached +( + "animscript_attached", + EV_DEFAULT, + "s", + "name", + "Play a noclip animation even when attached", + EV_NORMAL +); +//==== Event EV_Actor_Reload_mg42 - ( - "reload_mg42", - EV_DEFAULT, - NULL, - NULL, - "Reload the mg42 - only used by machinegunner" - ); - +( + "reload_mg42", + EV_DEFAULT, + NULL, + NULL, + "Reload the mg42 - only used by machinegunner", + EV_NORMAL +); Event EV_Actor_Dumb - ( - "dumb", - EV_DEFAULT, - NULL, - NULL, - "Make Actor dumb." - ); - +( + "dumb", + EV_DEFAULT, + NULL, + NULL, + "Make Actor dumb.", + EV_NORMAL +); Event EV_Actor_Physics_On - ( - "physics_on", - EV_DEFAULT, - NULL, - NULL, - "turn physics on." - ); - +( + "physics_on", + EV_DEFAULT, + NULL, + NULL, + "turn physics on.", + EV_NORMAL +); Event EV_Actor_Physics_Off - ( - "physics_off", - EV_DEFAULT, - NULL, - NULL, - "turn physics off." - ); - +( + "physics_off", + EV_DEFAULT, + NULL, + NULL, + "turn physics off.", + EV_NORMAL +); Event EV_Actor_SetAnim - ( - "setanim", - EV_DEFAULT, - "sifs", - "anim slot weight flagged", - "Set animation slot" - ); - +( + "setanim", + EV_DEFAULT, + "sifs", + "anim slot weight flagged", + "Set animation slot", + EV_NORMAL +); Event EV_Actor_SetAnimLength - ( - "setanimlength", - EV_DEFAULT, - "f", - "time", - "Set the maximum time an animation will play" - ); - +( + "setanimlength", + EV_DEFAULT, + "f", + "time", + "Set the maximum time an animation will play", + EV_NORMAL +); Event EV_Actor_EndActionAnim - ( - "endactionanim", - EV_DEFAULT, - "", - "", - "End any aiming/action animation which is currently playing" - ); - +( + "endactionanim", + EV_DEFAULT, + "", + "", + "End any aiming/action animation which is currently playing", + EV_NORMAL +); Event EV_Actor_SetMotionAnim - ( - "setmotionanim", - EV_DEFAULT, - "s", - "anim", - "Set motion animation (handler scripts only)" - ); - +( + "setmotionanim", + EV_DEFAULT, + "s", + "anim", + "Set motion animation (handler scripts only)", + EV_NORMAL +); Event EV_Actor_SetAimMotionAnim - ( - "setaimmotionanim", - EV_DEFAULT, - "sss", - "anim_crouch anim_stand anim_high", - "Set aim motion animation (handler scripts only)" - ); - - - +( + "setaimmotionanim", + EV_DEFAULT, + "ss", + "anim_crouch anim_stand", + "Set aim motion animation (handler scripts only)", + EV_NORMAL +); Event EV_Actor_SetActionAnim - ( - "setactionanim", - EV_DEFAULT, - "sff", - "base_anim lower_limit upper_limit", - "Set the base action animation and range that they cover" - ); - +( + "setactionanim", + EV_DEFAULT, + "sff", + "base_anim lower_limit upper_limit", + "Set the base action animation and range that they cover", + EV_NORMAL +); Event EV_Actor_UpperAnim - ( - "upperanim", - EV_DEFAULT, - "s", - "anim", - "Set the upper body " - ); - +( + "upperanim", + EV_DEFAULT, + "s", + "anim", + "Set the upper body animation", + EV_NORMAL +); Event EV_Actor_SetUpperAnim - ( - "setupperanim", - EV_DEFAULT, - "s", - "anim", - "Set the upper body animation - used by animation script only" - ); - +( + "setupperanim", + EV_DEFAULT, + "s", + "anim", + "Set the upper body animation - used by animation script only", + EV_NORMAL +); Event EV_Actor_SetCrossblendTime - ( - "blendtime", - EV_DEFAULT, - NULL, - NULL, - "Set the crossblend time to something other than the default, in seconds", - EV_SETTER - ); - +( + "blendtime", + EV_DEFAULT, + NULL, + NULL, + "Set the crossblend time to something other than the default, in seconds", + EV_SETTER +); Event EV_Actor_GetCrossblendTime - ( - "blendtime", - EV_DEFAULT, - NULL, - NULL, - "Get the crossblend time", - EV_GETTER - ); - +( + "blendtime", + EV_DEFAULT, + NULL, + NULL, + "Get the crossblend time", + EV_GETTER +); Event EV_Actor_SetPosition - ( - "position", - EV_DEFAULT, - NULL, - NULL, - "The Position the Actor wants to be and should animate towards", - EV_SETTER - ); - +( + "position", + EV_DEFAULT, + NULL, + NULL, + "The Position the Actor wants to be and should animate towards", + EV_SETTER +); Event EV_Actor_GetPosition - ( - "position", - EV_DEFAULT, - NULL, - NULL, - "The Position the Actor wants to be and should animate towards", - EV_GETTER - ); - +( + "position", + EV_DEFAULT, + NULL, + NULL, + "The Position the Actor wants to be and should animate towards", + EV_GETTER +); Event EV_Actor_SetEmotion - ( - "emotion", - EV_DEFAULT, - NULL, - NULL, - "The method of setting the facial expression of the Actor", - EV_SETTER - ); - +( + "emotion", + EV_DEFAULT, + NULL, + NULL, + "The method of setting the facial expression of the Actor", + EV_SETTER +); Event EV_Actor_SetAnimFinal - ( - "animfinal", - EV_DEFAULT, - NULL, - NULL, - "Whether the animation was succesfully finished", - EV_SETTER - ); - +( + "animfinal", + EV_DEFAULT, + NULL, + NULL, + "Whether the animation was successfully finished", + EV_SETTER +); Event EV_Actor_GetWeaponType - ( - "weapontype", - EV_DEFAULT, - NULL, - NULL, - "The Weapon Type of the ", - EV_GETTER - ); - +( + "weapontype", + EV_DEFAULT, + NULL, + NULL, + "The Weapon Type of the Actor", + EV_GETTER +); Event EV_Actor_GetWeaponGroup - ( - "weapongroup", - EV_DEFAULT, - NULL, - NULL, - "Specifies weapon animation set to use in anim scripts", - EV_GETTER - ); - +( + "weapongroup", + EV_DEFAULT, + NULL, + NULL, + "Specifies weapon animation set to use in anim scripts", + EV_GETTER +); Event EV_Entity_Start - ( - "entitystart", - EV_DEFAULT, - NULL, - NULL, - "Initialize a Actor." - ); - +( + "entitystart", + EV_DEFAULT, + NULL, + NULL, + "Initialize a Actor.", + EV_NORMAL +); Event EV_Actor_LookAt - ( - "lookat", - EV_DEFAULT, - "e", - "entity", - "The actor will look at this entity." - ); - +( + "lookat", + EV_DEFAULT, + "e", + "entity", + "The actor will look at this entity.", + EV_NORMAL +); Event EV_Actor_EyesLookAt - ( - "eyeslookat", - EV_DEFAULT, - "e", - "entity", - "The actor will look at this entity." - ); - +( + "eyeslookat", + EV_DEFAULT, + "e", + "entity", + "The actor will look at this entity.", + EV_NORMAL +); Event EV_Actor_PointAt - ( - "pointat", - EV_DEFAULT, - "e", - "entity", - "The actor will point at this entity." - ); - +( + "pointat", + EV_DEFAULT, + "e", + "entity", + "The actor will point at this entity.", + EV_NORMAL +); Event EV_Actor_TurnTo - ( - "turnto", - EV_DEFAULT, - "e", - "entity", - "The actor will turn to this entity." - ); - +( + "turnto", + EV_DEFAULT, + "e", + "entity", + "The actor will turn to this entity.", + EV_NORMAL +); Event EV_Actor_SetTurnDoneError - ( - "turndoneerror", - EV_DEFAULT, - "f", - "error", - "The error amount that turndone will occur for the turnto command." - ); - +( + "turndoneerror", + EV_DEFAULT, + "f", + "error", + "The error amount that turndone will occur for the turnto command.", + EV_NORMAL +); Event EV_Actor_SetTurnDoneError2 - ( - "turndoneerror", - EV_DEFAULT, - "f", - "error", - "The error amount that turndone will occur for the turnto command.", - EV_SETTER - ); - +( + "turndoneerror", + EV_DEFAULT, + "f", + "error", + "The error amount that turndone will occur for the turnto command.", + EV_SETTER +); Event EV_Actor_GetTurnDoneError - ( - "turndoneerror", - EV_DEFAULT, - NULL, - NULL, - "The error amount that turndone will occur for the turnto command.", - EV_GETTER - ); - +( + "turndoneerror", + EV_DEFAULT, + NULL, + NULL, + "The error amount that turndone will occur for the turnto command.", + EV_GETTER +); Event EV_Actor_IdleSayAnim - ( - "idlesay", - EV_DEFAULT, - "s", - "animation", - "The name of an idle dialog animation to play" - ); - +( + "idlesay", + EV_DEFAULT, + "s", + "animation", + "The name of an idle dialog animation to play", + EV_NORMAL +); Event EV_Actor_SayAnim - ( - "say", - EV_DEFAULT, - "s", - "animation", - "The name of a dialog animation to play" - ); - +( + "say", + EV_DEFAULT, + "s", + "animation", + "The name of a dialog animation to play", + EV_NORMAL +); Event EV_Actor_SetSayAnim - ( - "setsay", - EV_DEFAULT, - "s", - "animation", - "The name of a dialog animation to play - used by animation script only" - ); - +( + "setsay", + EV_DEFAULT, + "s", + "animation", + "The name of a dialog animation to play - used by animation script only", + EV_NORMAL +); Event EV_Actor_DamagePuff - ( - "damagepuff", - EV_DEFAULT, - "vv", - "position direction", - "Spawns a puff of 'blood' smoke at the speficied location in the specified direction." - ); - +( + "damagepuff", + EV_DEFAULT, + "vv", + "position direction", + "Spawns a puff of 'blood' smoke at the specified location in the specified direction.", + EV_NORMAL +); Event EV_Actor_SetAngleYawSpeed - ( - "turnspeed", - EV_DEFAULT, - "f", - "speed", - "The turn speed of the actor.", - EV_SETTER - ); - +( + "turnspeed", + EV_DEFAULT, + "f", + "speed", + "The turn speed of the actor.", + EV_SETTER +); Event EV_Actor_SetAngleYawSpeed2 - ( - "turnspeed", - EV_DEFAULT, - "f", - "speed", - "The turn speed of the actor." - ); - +( + "turnspeed", + EV_DEFAULT, + "f", + "speed", + "The turn speed of the actor.", + EV_NORMAL +); Event EV_Actor_GetAngleYawSpeed - ( - "turnspeed", - EV_DEFAULT, - NULL, - NULL, - "The turn speed of the actor.", - EV_GETTER - ); - +( + "turnspeed", + EV_DEFAULT, + NULL, + NULL, + "The turn speed of the actor.", + EV_GETTER +); Event EV_Actor_SetAimTarget - ( - "setaimtarget", - EV_DEFAULT, - "e", - "entity", - "Sets the primary weapon's aim target." - ); - +( + "setaimtarget", + EV_DEFAULT, + "ei", + "entity bMakeEnemy", + "Sets the primary weapon's aim target. if you pass a 1 for p2, the target will become the current enemy...", + EV_NORMAL +); Event EV_Actor_ReadyToFire - ( - "ReadyToFire", - EV_DEFAULT, - NULL, - NULL, - "Returns if ready to fire", - EV_RETURN - ); - +( + "ReadyToFire", + EV_DEFAULT, + NULL, + NULL, + "Returns if ready to fire", + EV_RETURN +); Event EV_Actor_AIOff - ( - "ai_off", - EV_DEFAULT, - NULL, - NULL, - "Turns the AI off for this actor." - ); - +( + "ai_off", + EV_DEFAULT, + NULL, + NULL, + "Turns the AI off for this actor.", + EV_NORMAL +); Event EV_Actor_AIOn - ( - "ai_on", - EV_DEFAULT, - NULL, - NULL, - "Turns the AI on for this actor." - ); - -Event EV_Actor_GetLocalYawFromVector - ( - "GetLocalYawFromVector", - EV_DEFAULT, - NULL, - NULL, - "Turn a worldspace vector into a local space yaw", - EV_RETURN - ); - +( + "ai_on", + EV_DEFAULT, + NULL, + NULL, + "Turns the AI on for this actor.", + EV_NORMAL +); Event EV_Actor_GetSight - ( - "sight", - EV_DEFAULT, - NULL, - NULL, - "Gets the vision distance of the actor.", - EV_GETTER - ); - +( + "sight", + EV_DEFAULT, + NULL, + NULL, + "Gets the vision distance of the actor.", + EV_GETTER +); Event EV_Actor_SetSight - ( - "sight", - EV_DEFAULT, - "f", - "max_sight_range", - "Sets the vision distance of the actor.", - EV_SETTER - ); - +( + "sight", + EV_DEFAULT, + "f", + "max_sight_range", + "Sets the vision distance of the actor.", + EV_SETTER +); Event EV_Actor_SetSight2 - ( - "sight", - EV_DEFAULT, - "f", - "max_sight_range", - "Sets the vision distance of the actor." - ); - +( + "sight", + EV_DEFAULT, + "f", + "max_sight_range", + "Sets the vision distance of the actor.", + EV_NORMAL +); Event EV_Actor_GetHearing - ( - "hearing", - EV_DEFAULT, - "f", - "radius", - "The hearing radius of the actor", - EV_GETTER - ); - +( + "hearing", + EV_DEFAULT, + "f", + "radius", + "The hearing radius of the actor", + EV_GETTER +); Event EV_Actor_SetHearing - ( - "hearing", - EV_DEFAULT, - "f", - "radius", - "The hearing radius of the actor" - ); - +( + "hearing", + EV_DEFAULT, + "f", + "radius", + "The hearing radius of the actor", + EV_NORMAL +); Event EV_Actor_SetHearing2 - ( - "hearing", - EV_DEFAULT, - "f", - "radius", - "The hearing radius of the actor", - EV_SETTER - ); - +( + "hearing", + EV_DEFAULT, + "f", + "radius", + "The hearing radius of the actor", + EV_SETTER +); Event EV_Actor_GetFov - ( - "fov", - EV_DEFAULT, - NULL, - NULL, - "The fov angle of the actor", - EV_GETTER - ); - +( + "fov", + EV_DEFAULT, + NULL, + NULL, + "The fov angle of the actor", + EV_GETTER +); Event EV_Actor_SetFov - ( - "fov", - EV_DEFAULT, - "f", - "angle", - "The fov angle of the actor" - ); - +( + "fov", + EV_DEFAULT, + "f", + "angle", + "The fov angle of the actor", + EV_NORMAL +); Event EV_Actor_SetFov2 - ( - "fov", - EV_DEFAULT, - "f", - "angle", - "The fov angle of the actor", - EV_SETTER - ); - +( + "fov", + EV_DEFAULT, + "f", + "angle", + "The fov angle of the actor", + EV_SETTER +); Event EV_Actor_SetTypeIdle - ( - "type_idle", - EV_DEFAULT, - "s", - "value", - "Sets the idle type of the actor." - ); - +( + "type_idle", + EV_DEFAULT, + "s", + "value", + "Sets the idle type of the actor.", + EV_NORMAL +); Event EV_Actor_SetTypeIdle2 - ( - "type_idle", - EV_DEFAULT, - "s", - "value", - "Sets the idle type of the actor.", - EV_SETTER - ); - +( + "type_idle", + EV_DEFAULT, + "s", + "value", + "Sets the idle type of the actor.", + EV_SETTER +); Event EV_Actor_GetTypeIdle - ( - "type_idle", - EV_DEFAULT, - NULL, - NULL, - "Gets the idle type of the actor.", - EV_GETTER - ); - +( + "type_idle", + EV_DEFAULT, + NULL, + NULL, + "Gets the idle type of the actor.", + EV_GETTER +); Event EV_Actor_SetTypeAttack - ( - "type_attack", - EV_DEFAULT, - "s", - "value", - "Sets the attack type of the actor." - ); - +( + "type_attack", + EV_DEFAULT, + "s", + "value", + "Sets the attack type of the actor.", + EV_NORMAL +); Event EV_Actor_SetTypeAttack2 - ( - "type_attack", - EV_DEFAULT, - "s", - "value", - "Sets the attack type of the actor.", - EV_SETTER - ); - +( + "type_attack", + EV_DEFAULT, + "s", + "value", + "Sets the attack type of the actor.", + EV_SETTER +); Event EV_Actor_GetTypeAttack - ( - "type_attack", - EV_DEFAULT, - NULL, - NULL, - "Gets the attack type of the actor.", - EV_GETTER - ); - +( + "type_attack", + EV_DEFAULT, + NULL, + NULL, + "Gets the attack type of the actor.", + EV_GETTER +); Event EV_Actor_SetTypeDisguise - ( - "type_disguise", - EV_DEFAULT, - "s", - "value", - "Sets the disguise type of the actor." - ); - +( + "type_disguise", + EV_DEFAULT, + "s", + "value", + "Sets the disguise type of the actor.", + EV_NORMAL +); Event EV_Actor_SetTypeDisguise2 - ( - "type_disguise", - EV_DEFAULT, - "s", - "value", - "Sets the disguise type of the actor.", - EV_SETTER - ); - +( + "type_disguise", + EV_DEFAULT, + "s", + "value", + "Sets the disguise type of the actor.", + EV_SETTER +); Event EV_Actor_GetTypeDisguise - ( - "type_disguise", - EV_DEFAULT, - NULL, - NULL, - "Gets the disguise type of the actor.", - EV_GETTER - ); - +( + "type_disguise", + EV_DEFAULT, + NULL, + NULL, + "Gets the disguise type of the actor.", + EV_GETTER +); Event EV_Actor_SetDisguiseLevel - ( - "disguise_level", - EV_DEFAULT, - "i", - "value", - "Sets the disguise level of the actor. May be 1 or 2" - ); - +( + "disguise_level", + EV_DEFAULT, + "i", + "value", + "Sets the disguise level of the actor. May be 1 or 2", + EV_NORMAL +); Event EV_Actor_SetDisguiseLevel2 - ( - "disguise_level", - EV_DEFAULT, - "i", - "value", - "Sets the disguise level of the actor. May be 1 or 2", - EV_SETTER - ); - +( + "disguise_level", + EV_DEFAULT, + "i", + "value", + "Sets the disguise level of the actor. May be 1 or 2", + EV_SETTER +); Event EV_Actor_GetDisguiseLevel - ( - "disguise_level", - EV_DEFAULT, - NULL, - NULL, - "Gets the disguise level of the actor. May be 1 or 2", - EV_GETTER - ); - +( + "disguise_level", + EV_DEFAULT, + NULL, + NULL, + "Gets the disguise level of the actor. May be 1 or 2", + EV_GETTER +); Event EV_Actor_SetTypeGrenade - ( - "type_grenade", - EV_DEFAULT, - "s", - "value", - "Sets the grenade type of the actor." - ); - +( + "type_grenade", + EV_DEFAULT, + "s", + "value", + "Sets the grenade type of the actor.", + EV_NORMAL +); Event EV_Actor_SetTypeGrenade2 - ( - "type_grenade", - EV_DEFAULT, - "s", - "value", - "Sets the grenade type of the actor.", - EV_SETTER - ); - +( + "type_grenade", + EV_DEFAULT, + "s", + "value", + "Sets the grenade type of the actor.", + EV_SETTER +); Event EV_Actor_GetTypeGrenade - ( - "type_grenade", - EV_DEFAULT, - NULL, - NULL, - "Gets the grenade type of the actor.", - EV_GETTER - ); - +( + "type_grenade", + EV_DEFAULT, + NULL, + NULL, + "Gets the grenade type of the actor.", + EV_GETTER +); Event EV_Actor_SetPatrolPath - ( - "patrolpath", - EV_DEFAULT, - "s", - "value", - "Sets the name of the patrol path for the actor (must have type set to patrol for effect)" - ); - +( + "patrolpath", + EV_DEFAULT, + "s", + "value", + "Sets the name of the patrol path for the actor (must have type set to patrol for effect)", + EV_NORMAL +); Event EV_Actor_SetPatrolPath2 - ( - "patrolpath", - EV_DEFAULT, - "s", - "value", - "Sets the name of the patrol path for the actor (must have type set to patrol for effect)", - EV_SETTER - ); - +( + "patrolpath", + EV_DEFAULT, + "s", + "value", + "Sets the name of the patrol path for the actor (must have type set to patrol for effect)", + EV_SETTER +); Event EV_Actor_GetPatrolPath - ( - "patrolpath", - EV_DEFAULT, - NULL, - NULL, - "Gets the name of the patrol path for the actor (must have type set to patrol for effect)", - EV_GETTER - ); - +( + "patrolpath", + EV_DEFAULT, + NULL, + NULL, + "Gets the name of the patrol path for the actor (must have type set to patrol for effect)", + EV_GETTER +); Event EV_Actor_SetPatrolWaitTrigger - ( - "waittrigger", - EV_DEFAULT, - "b", - "bool", - "If true, patrol guys and running men wait until triggered to move" - ); - +( + "waittrigger", + EV_DEFAULT, + "b", + "bool", + "If true, patrol guys and running men wait until triggered to move", + EV_NORMAL +); Event EV_Actor_SetPatrolWaitTrigger2 - ( - "waittrigger", - EV_DEFAULT, - "b", - "bool", - "If true, patrol guys and running men wait until triggered to move", - EV_SETTER - ); - +( + "waittrigger", + EV_DEFAULT, + "b", + "bool", + "If true, patrol guys and running men wait until triggered to move", + EV_SETTER +); Event EV_Actor_GetPatrolWaitTrigger - ( - "waittrigger", - EV_DEFAULT, - NULL, - NULL, - "If true, patrol guys and running men wait until triggered to move", - EV_GETTER - ); - +( + "waittrigger", + EV_DEFAULT, + NULL, + NULL, + "If true, patrol guys and running men wait until triggered to move", + EV_GETTER +); Event EV_Actor_SetAlarmNode - ( - "alarmnode", - EV_DEFAULT, - "s", - "value", - "Sets the name of the alarm node for the actor (must have type set to alarm for effect)" - ); - +( + "alarmnode", + EV_DEFAULT, + "s", + "value", + "Sets the name of the alarm node for the actor (must have type set to alarm for effect)", + EV_NORMAL +); Event EV_Actor_SetAlarmNode2 - ( - "alarmnode", - EV_DEFAULT, - "s", - "value", - "Sets the name of the alarm node for the actor (must have type set to alarm for effect)", - EV_SETTER - ); - +( + "alarmnode", + EV_DEFAULT, + "s", + "value", + "Sets the name of the alarm node for the actor (must have type set to alarm for effect)", + EV_SETTER +); Event EV_Actor_GetAlarmNode - ( - "alarmnode", - EV_DEFAULT, - NULL, - NULL, - "Gets the name of the alarm node for the actor (must have type set to alarm for effect)", - EV_GETTER - ); - +( + "alarmnode", + EV_DEFAULT, + NULL, + NULL, + "Gets the name of the alarm node for the actor (must have type set to alarm for effect)", + EV_GETTER +); +// Added in 2.30 +//==== +Event EV_Actor_SetPreAlarmThread +( + "prealarmthread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the pre alarm thread for the actor (must have type set to alarm for effect)", + EV_NORMAL +); +Event EV_Actor_SetPreAlarmThread2 +( + "prealarmthread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the pre alarm thread for the actor (must have type set to alarm for effect)", + EV_SETTER +); +//==== Event EV_Actor_SetAlarmThread - ( - "alarmthread", - EV_DEFAULT, - "s", - "value", - "Sets the name of the alarm thread for the actor (must have type set to alarm for effect)" - ); - +( + "alarmthread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the alarm thread for the actor (must have type set to alarm for effect)", + EV_NORMAL +); Event EV_Actor_SetAlarmThread2 - ( - "alarmthread", - EV_DEFAULT, - "s", - "value", - "Sets the name of the alarm thread for the actor (must have type set to alarm for effect)", - EV_SETTER - ); - +( + "alarmthread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the alarm thread for the actor (must have type set to alarm for effect)", + EV_SETTER +); Event EV_Actor_GetAlarmThread - ( - "alarmthread", - EV_DEFAULT, - NULL, - NULL, - "Gets the name of the alarm thread for the actor (must have type set to alarm for effect)", - EV_GETTER - ); - +( + "alarmthread", + EV_DEFAULT, + NULL, + NULL, + "Gets the name of the alarm thread for the actor (must have type set to alarm for effect)", + EV_GETTER +); Event EV_Actor_SetDisguiseAcceptThread - ( - "disguise_accept_thread", - EV_DEFAULT, - "s", - "value", - "Sets the name of the thread for the actor to start when accepting papers" - ); - +( + "disguise_accept_thread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the thread for the actor to start when accepting papers", + EV_NORMAL +); Event EV_Actor_SetDisguiseAcceptThread2 - ( - "disguise_accept_thread", - EV_DEFAULT, - "s", - "value", - "Sets the name of the thread for the actor to start when accepting papers", - EV_SETTER - ); - +( + "disguise_accept_thread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the thread for the actor to start when accepting papers", + EV_SETTER +); Event EV_Actor_GetDisguiseAcceptThread - ( - "disguise_accept_thread", - EV_DEFAULT, - NULL, - NULL, - "Gets the name of the thread for the actor to start when accepting papers", - EV_GETTER - ); - +( + "disguise_accept_thread", + EV_DEFAULT, + NULL, + NULL, + "Gets the name of the thread for the actor to start when accepting papers", + EV_GETTER +); Event EV_Actor_SetAccuracy - ( - "accuracy", - EV_DEFAULT, - "f", - "value", - "Set percent to hit" - ); - +( + "accuracy", + EV_DEFAULT, + "f", + "value", + "Set percent to hit", + EV_NORMAL +); Event EV_Actor_SetAccuracy2 - ( - "accuracy", - EV_DEFAULT, - "f", - "value", - "Set percent to hit", - EV_SETTER - ); - +( + "accuracy", + EV_DEFAULT, + "f", + "value", + "Set percent to hit", + EV_SETTER +); Event EV_Actor_GetAccuracy - ( - "accuracy", - EV_DEFAULT, - NULL, - NULL, - "Set percent to hit", - EV_GETTER - ); - +( + "accuracy", + EV_DEFAULT, + NULL, + NULL, + "Set percent to hit", + EV_GETTER +); Event EV_Actor_SetMinDistance - ( - "mindist", - EV_DEFAULT, - "f", - "distance", - "Sets the minimum distance the AI tries to keep between itself and the player" - ); - +( + "mindist", + EV_DEFAULT, + "f", + "distance", + "Sets the minimum distance the AI tries to keep between itself and the player", + EV_NORMAL +); Event EV_Actor_SetMinDistance2 - ( - "mindist", - EV_DEFAULT, - "f", - "distance", - "Sets the minimum distance the AI tries to keep between itself and the player", - EV_SETTER - ); - +( + "mindist", + EV_DEFAULT, + "f", + "distance", + "Sets the minimum distance the AI tries to keep between itself and the player", + EV_SETTER +); Event EV_Actor_GetMinDistance - ( - "mindist", - EV_DEFAULT, - NULL, - NULL, - "Gets the minimum distance the AI tries to keep between itself and the player", - EV_GETTER - ); - +( + "mindist", + EV_DEFAULT, + NULL, + NULL, + "Gets the minimum distance the AI tries to keep between itself and the player", + EV_GETTER +); Event EV_Actor_SetMaxDistance - ( - "maxdist", - EV_DEFAULT, - "f", - "distance", - "Sets the maximum distance the AI tries to allow between itself and the player" - ); - +( + "maxdist", + EV_DEFAULT, + "f", + "distance", + "Sets the maximum distance the AI tries to allow between itself and the player", + EV_NORMAL +); Event EV_Actor_SetMaxDistance2 - ( - "maxdist", - EV_DEFAULT, - "f", - "distance", - "Sets the maximum distance the AI tries to allow between itself and the player", - EV_SETTER - ); - +( + "maxdist", + EV_DEFAULT, + "f", + "distance", + "Sets the maximum distance the AI tries to allow between itself and the player", + EV_SETTER +); Event EV_Actor_GetMaxDistance - ( - "maxdist", - EV_DEFAULT, - NULL, - NULL, - "Gets the maximum distance the AI tries to keep between itself and the player", - EV_GETTER - ); - +( + "maxdist", + EV_DEFAULT, + NULL, + NULL, + "Gets the maximum distance the AI tries to keep between itself and the player", + EV_GETTER +); Event EV_Actor_GetLeash - ( - "leash", - EV_DEFAULT, - NULL, - NULL, - "Gets the maximum distance the AI will wander from its leash home", - EV_GETTER - ); - +( + "leash", + EV_DEFAULT, + NULL, + NULL, + "Gets the maximum distance the AI will wander from its leash home", + EV_GETTER +); Event EV_Actor_SetLeash - ( - "leash", - EV_DEFAULT, - "f", - "distance", - "Sets the maximum distance the AI will wander from its leash home", - EV_SETTER - ); - +( + "leash", + EV_DEFAULT, + "f", + "distance", + "Sets the maximum distance the AI will wander from its leash home", + EV_SETTER +); Event EV_Actor_SetLeash2 - ( - "leash", - EV_DEFAULT, - "f", - "distance", - "Sets the maximum distance the AI will wander from its leash home" - ); - +( + "leash", + EV_DEFAULT, + "f", + "distance", + "Sets the maximum distance the AI will wander from its leash home", + EV_NORMAL +); Event EV_Actor_GetInterval - ( - "interval", - EV_DEFAULT, - NULL, - NULL, - "Gets the distance AI tries to keep between squadmates while moving.", - EV_GETTER - ); - +( + "interval", + EV_DEFAULT, + NULL, + NULL, + "Gets the distance AI tries to keep between squadmates while moving.", + EV_GETTER +); Event EV_Actor_SetInterval - ( - "interval", - EV_DEFAULT, - "f", - "distance", - "Sets the distance AI tries to keep between squadmates while moving.", - EV_SETTER - ); - +( + "interval", + EV_DEFAULT, + "f", + "distance", + "Sets the distance AI tries to keep between squadmates while moving.", + EV_SETTER +); Event EV_Actor_SetInterval2 - ( - "interval", - EV_DEFAULT, - "f", - "distance", - "Sets the distance AI tries to keep between squadmates while moving." - ); - +( + "interval", + EV_DEFAULT, + "f", + "distance", + "Sets the distance AI tries to keep between squadmates while moving.", + EV_NORMAL +); Event EV_Actor_GetRunAnim - ( - "GetRunAnim", - EV_DEFAULT, - NULL, - NULL, - "Internal usage", - EV_RETURN - ); - +( + "GetRunAnim", + EV_DEFAULT, + NULL, + NULL, + "Internal usage", + EV_RETURN +); Event EV_Actor_GetWalkAnim - ( - "GetWalkAnim", - EV_DEFAULT, - NULL, - NULL, - "Internal usage", - EV_RETURN - ); - +( + "GetWalkAnim", + EV_DEFAULT, + NULL, + NULL, + "Internal usage", + EV_RETURN +); Event EV_Actor_GetAnimName - ( - "animname", - EV_DEFAULT, - NULL, - NULL, - "Gets the animname.", - EV_GETTER - ); - +( + "animname", + EV_DEFAULT, + NULL, + NULL, + "Gets the animname.", + EV_GETTER +); Event EV_Actor_SetAnimName - ( - "animname", - EV_DEFAULT, - NULL, - NULL, - "Sets the animname.", - EV_SETTER - ); - +( + "animname", + EV_DEFAULT, + NULL, + NULL, + "Sets the animname.", + EV_SETTER +); Event EV_Actor_SetDisguiseRange - ( - "disguise_range", - EV_DEFAULT, - "f", - "range_in_units", - "Sets the maximum distance for disguise behavior to get triggered", - EV_SETTER - ); - +( + "disguise_range", + EV_DEFAULT, + "f", + "range_in_units", + "Sets the maximum distance for disguise behavior to get triggered", + EV_SETTER +); Event EV_Actor_SetDisguiseRange2 - ( - "disguise_range", - EV_DEFAULT, - "f", - "range_in_units", - "Sets the maximum distance for disguise behavior to get triggered" - ); - +( + "disguise_range", + EV_DEFAULT, + "f", + "range_in_units", + "Sets the maximum distance for disguise behavior to get triggered", + EV_NORMAL +); Event EV_Actor_GetDisguiseRange - ( - "disguise_range", - EV_DEFAULT, - NULL, - NULL, - "Gets the maximum distance for disguise behavior to get triggered", - EV_GETTER - ); - +( + "disguise_range", + EV_DEFAULT, + NULL, + NULL, + "Gets the maximum distance for disguise behavior to get triggered", + EV_GETTER +); Event EV_Actor_SetDisguisePeriod - ( - "disguise_period", - EV_DEFAULT, - "f", - "period_in_seconds", - "Sets the time between the end of one disguise behavior and start of the next", - EV_SETTER - ); - +( + "disguise_period", + EV_DEFAULT, + "f", + "period_in_seconds", + "Sets the time between the end of one disguise behavior and start of the next", + EV_SETTER +); Event EV_Actor_SetDisguisePeriod2 - ( - "disguise_period", - EV_DEFAULT, - "f", - "period_in_seconds", - "Sets the time between the end of one disguise behavior and start of the next" - ); - +( + "disguise_period", + EV_DEFAULT, + "f", + "period_in_seconds", + "Sets the time between the end of one disguise behavior and start of the next", + EV_NORMAL +); Event EV_Actor_GetDisguisePeriod - ( - "disguise_period", - EV_DEFAULT, - NULL, - NULL, - "Gets the time between the end of one disguise behavior and start of the next", - EV_GETTER - ); - +( + "disguise_period", + EV_DEFAULT, + NULL, + NULL, + "Gets the time between the end of one disguise behavior and start of the next", + EV_GETTER +); Event EV_Actor_AttackPlayer - ( - "attackplayer", - EV_DEFAULT, - NULL, - NULL, - "Force Actor to attack the player" - ); - +( + "attackplayer", + EV_DEFAULT, + NULL, + NULL, + "Force Actor to attack the player", + EV_NORMAL +); Event EV_Actor_SetSoundAwareness - ( - "sound_awareness", - EV_DEFAULT, - "f", - "awareness_percent", - "sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius" - ); - +( + "sound_awareness", + EV_DEFAULT, + "f", + "awareness_percent", + "sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades " + "to z" + "ero outside sound's radius", + EV_NORMAL +); Event EV_Actor_SetSoundAwareness2 - ( - "sound_awareness", - EV_DEFAULT, - "f", - "awareness_percent", - "sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius", - EV_SETTER - ); - +( + "sound_awareness", + EV_DEFAULT, + "f", + "awareness_percent", + "sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades " + "to z" + "ero outside sound's radius", + EV_SETTER +); Event EV_Actor_GetSoundAwareness - ( - "sound_awareness", - EV_DEFAULT, - NULL, - NULL, - "gets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius", - EV_GETTER - ); - +( + "sound_awareness", + EV_DEFAULT, + NULL, + NULL, + "gets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades " + "to z" + "ero outside sound's radius", + EV_GETTER +); Event EV_Actor_SetGrenadeAwareness - ( - "gren_awareness", - EV_DEFAULT, - "f", - "awareness_percent", - "sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)" - ); - - +( + "gren_awareness", + EV_DEFAULT, + "f", + "awareness_percent", + "sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied " + "once e" + "very 0.4 seconds)", + EV_NORMAL +); Event EV_Actor_SetGrenadeAwareness2 - ( - "gren_awareness", - EV_DEFAULT, - "f", - "awareness_percent", - "sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)", - EV_SETTER - ); - +( + "gren_awareness", + EV_DEFAULT, + "f", + "awareness_percent", + "sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied " + "once e" + "very 0.4 seconds)", + EV_SETTER +); Event EV_Actor_GetGrenadeAwareness - ( - "gren_awareness", - EV_DEFAULT, - NULL, - NULL, - "gets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)", - EV_GETTER - ); - +( + "gren_awareness", + EV_DEFAULT, + NULL, + NULL, + "gets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied " + "once e" + "very 0.4 seconds)", + EV_GETTER +); Event EV_Actor_SetTurret - ( - "turret", - EV_DEFAULT, - "s", - "turret", - "Sets the turret of the actor." - ); - +( + "turret", + EV_DEFAULT, + "s", + "turret", + "Sets the turret of the actor.", + EV_NORMAL +); Event EV_Actor_SetTurret2 - ( - "turret", - EV_DEFAULT, - "s", - "turret", - "Sets the turret of the actor.", - EV_SETTER - ); - +( + "turret", + EV_DEFAULT, + "s", + "turret", + "Sets the turret of the actor.", + EV_SETTER +); Event EV_Actor_GetTurret - ( - "turret", - EV_DEFAULT, - NULL, - NULL, - "Gets the turret of the actor.", - EV_GETTER - ); - +( + "turret", + EV_DEFAULT, + NULL, + NULL, + "Gets the turret of the actor.", + EV_GETTER +); Event EV_Actor_AttachGrenade - ( - "attachgrenade", - EV_DEFAULT, - NULL, - NULL, - "Used only by grenade return animations to tell the code when to attach the grenade to the actor" - ); - +( + "attachgrenade", + EV_DEFAULT, + NULL, + NULL, + "Used only by grenade return animations to tell the code when to attach the grenade to the actor", + EV_NORMAL +); Event EV_Actor_DetachGrenade - ( - "detachgrenade", - EV_DEFAULT, - NULL, - NULL, - "Used only by grenade return animations to tell the code when to throw the grenade" - ); - +( + "detachgrenade", + EV_DEFAULT, + NULL, + NULL, + "Used only by grenade return animations to tell the code when to throw the grenade", + EV_NORMAL +); Event EV_Actor_FireGrenade - ( - "fire_grenade", - EV_DEFAULT, - NULL, - NULL, - "Used only by grenade throw animations to tell the code when to throw a grenade" - ); - +( + "fire_grenade", + EV_DEFAULT, + NULL, + NULL, + "Used only by grenade throw animations to tell the code when to throw a grenade", + EV_NORMAL +); Event EV_Actor_EnableEnemy - ( - "enableEnemy", - EV_DEFAULT, - NULL, - NULL, - "sets enableEnemy variable", - EV_SETTER - ); - +( + "enableEnemy", + EV_DEFAULT, + NULL, + NULL, + "sets enableEnemy variable", + EV_SETTER +); Event EV_Actor_EnablePain - ( - "enablePain", - EV_DEFAULT, - NULL, - NULL, - "sets enablePain variable", - EV_SETTER - ); - +( + "enablePain", + EV_DEFAULT, + NULL, + NULL, + "sets enablePain variable", + EV_SETTER +); Event EV_Actor_SetPainHandler - ( - "painhandler", - EV_DEFAULT, - NULL, - NULL, - "Sets the current script that will handle pain events", - EV_SETTER - ); - +( + "painhandler", + EV_DEFAULT, + NULL, + NULL, + "Sets the current script that will handle pain events", + EV_SETTER +); Event EV_Actor_GetPainHandler - ( - "painhandler", - EV_DEFAULT, - NULL, - NULL, - "Gets the current script that will handle pain events", - EV_GETTER - ); - +( + "painhandler", + EV_DEFAULT, + NULL, + NULL, + "Gets the current script that will handle pain events", + EV_GETTER +); Event EV_Actor_SetDeathHandler - ( - "deathhandler", - EV_DEFAULT, - NULL, - NULL, - "Sets the current script that will handle death events", - EV_SETTER - ); - +( + "deathhandler", + EV_DEFAULT, + NULL, + NULL, + "Sets the current script that will handle death events", + EV_SETTER +); Event EV_Actor_GetDeathHandler - ( - "deathhandler", - EV_DEFAULT, - NULL, - NULL, - "Gets the current script that will handle death events", - EV_GETTER - ); - +( + "deathhandler", + EV_DEFAULT, + NULL, + NULL, + "Gets the current script that will handle death events", + EV_GETTER +); Event EV_Actor_SetAttackHandler - ( - "attackhandler", - EV_DEFAULT, - NULL, - NULL, - "Sets the current script that will handle attack events", - EV_SETTER - ); - +( + "attackhandler", + EV_DEFAULT, + NULL, + NULL, + "Sets the current script that will handle attack events", + EV_SETTER +); Event EV_Actor_GetAttackHandler - ( - "attackhandler", - EV_DEFAULT, - NULL, - NULL, - "Gets the current script that will handle attack events", - EV_GETTER - ); - +( + "attackhandler", + EV_DEFAULT, + NULL, + NULL, + "Gets the current script that will handle attack events", + EV_GETTER +); Event EV_Actor_SetAmmoGrenade - ( - "ammo_grenade", - EV_DEFAULT, - "i", - "grenade_count", - "Gives the AI some grenades" - ); - +( + "ammo_grenade", + EV_DEFAULT, + "i", + "grenade_count", + "Gives the AI some grenades", + EV_NORMAL +); Event EV_Actor_SetAmmoGrenade2 - ( - "ammo_grenade", - EV_DEFAULT, - "i", - "grenade_count", - "Gives the AI some grenades", - EV_SETTER - ); - +( + "ammo_grenade", + EV_DEFAULT, + "i", + "grenade_count", + "Gives the AI some grenades", + EV_SETTER +); Event EV_Actor_GetAmmoGrenade - ( - "ammo_grenade", - EV_DEFAULT, - NULL, - NULL, - "Returns how many grenades an AI has", - EV_GETTER - ); - +( + "ammo_grenade", + EV_DEFAULT, + NULL, + NULL, + "Returns how many grenades an AI has", + EV_GETTER +); Event EV_Actor_SetMood - ( - "mood", - EV_DEFAULT, - "s", - "new_mood", - "sets the AI mood... must be 'bored', 'nervous', 'curious', or 'alert'.", - EV_SETTER - ); - +( + "mood", + EV_DEFAULT, + "s", + "new_mood", + "sets the AI mood... must be 'bored', 'nervous', 'curious', or 'alert'.", + EV_SETTER +); Event EV_Actor_GetMood - ( - "mood", - EV_DEFAULT, - NULL, - NULL, - "gets the AI mood: 'bored', 'nervous', 'curious', or 'alert'.", - EV_GETTER - ); - +( + "mood", + EV_DEFAULT, + NULL, + NULL, + "gets the AI mood: 'bored', 'nervous', 'curious', or 'alert'.", + EV_GETTER +); Event EV_Actor_SetHeadModel - ( - "headmodel", - EV_DEFAULT, - "s", - "headmodel", - "sets the head model" - ); - +( + "headmodel", + EV_DEFAULT, + "s", + "headmodel", + "sets the head model", + EV_NORMAL +); Event EV_Actor_GetHeadModel - ( - "headmodel", - EV_DEFAULT, - NULL, - NULL, - "gets the head model", - EV_GETTER - ); - +( + "headmodel", + EV_DEFAULT, + NULL, + NULL, + "gets the head model", + EV_GETTER +); Event EV_Actor_SetHeadSkin - ( - "headskin", - EV_DEFAULT, - "s", - "headskin", - "sets the head skin" - ); - +( + "headskin", + EV_DEFAULT, + "s", + "headskin", + "sets the head skin", + EV_NORMAL +); Event EV_Actor_GetHeadSkin - ( - "headskin", - EV_DEFAULT, - NULL, - NULL, - "gets the head skin", - EV_GETTER - ); - +( + "headskin", + EV_DEFAULT, + NULL, + NULL, + "gets the head skin", + EV_GETTER +); Event EV_Actor_ShareEnemy - ( - "share_enemy", - EV_DEFAULT, - NULL, - NULL, - "internal code use only - shares an AI's enemy with his squad mates." - ); - +( + "share_enemy", + EV_DEFAULT, + NULL, + NULL, + "internal code use only - shares an AI's enemy with his squad mates.", + EV_NORMAL +); Event EV_Actor_ShareGrenade - ( - "share_grenade", - EV_DEFAULT, - NULL, - NULL, - "internal code use only - shares an AI's grenade with his squad mates." - ); - +( + "share_grenade", + EV_DEFAULT, + NULL, + NULL, + "internal code use only - shares an AI's grenade with his squad mates.", + EV_NORMAL +); Event EV_Actor_InterruptPoint - ( - "interrupt_point", - EV_DEFAULT, - NULL, - NULL, - "hint from animation scripts to AI code that now is a good time to switch animations" - ); - +( + "interrupt_point", + EV_DEFAULT, + NULL, + NULL, + "hint from animation scripts to AI code that now is a good time to switch animations", + EV_NORMAL +); Event EV_Actor_SetNoIdle - ( - "no_idle", - EV_DEFAULT, - NULL, - NULL, - "Specifies if the actor will not go into idle after playing an animation", - EV_SETTER - ); - +( + "no_idle", + EV_DEFAULT, + NULL, + NULL, + "Specifies if the actor will not go into idle after playing an animation", + EV_SETTER +); Event EV_Actor_GetNoIdle - ( - "no_idle", - EV_DEFAULT, - NULL, - NULL, - "Gets if the actor will not go into idle after playing an animation", - EV_GETTER - ); - +( + "no_idle", + EV_DEFAULT, + NULL, + NULL, + "Gets if the actor will not go into idle after playing an animation", + EV_GETTER +); Event EV_Actor_GetEnemy - ( - "enemy", - EV_DEFAULT, - NULL, - NULL, - "Get the actor's current enemy", - EV_GETTER - ); - +( + "enemy", + EV_DEFAULT, + NULL, + NULL, + "Get the actor's current enemy", + EV_GETTER +); Event EV_Actor_GetMaxNoticeTimeScale - ( - "noticescale", - EV_DEFAULT, - NULL, - NULL, - "Get the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)", - EV_GETTER - ); - +( + "noticescale", + EV_DEFAULT, + NULL, + NULL, + "Get the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)", + EV_GETTER +); Event EV_Actor_SetMaxNoticeTimeScale - ( - "noticescale", - EV_DEFAULT, - "f", - "multiplier", - "Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)", - EV_SETTER - ); - +( + "noticescale", + EV_DEFAULT, + "f", + "multiplier", + "Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)", + EV_SETTER +); Event EV_Actor_SetMaxNoticeTimeScale2 - ( - "noticescale", - EV_DEFAULT, - "f", - "multiplier", - "Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)" - ); - -Event EV_Actor_GetFixedLeash - ( - "fixedleash", - EV_DEFAULT, - NULL, - NULL, - "if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset", - EV_GETTER - ); - -Event EV_Actor_SetFixedLeash - ( - "fixedleash", - EV_DEFAULT, - "f", - "multiplier", - "if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset", - EV_SETTER - ); - -Event EV_Actor_SetFixedLeash2 - ( - "fixedleash", - EV_DEFAULT, - "f", - "multiplier", - "if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset" - ); - +( + "noticescale", + EV_DEFAULT, + "f", + "multiplier", + "Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)", + EV_NORMAL +); +Event EV_Actor_GetFixedLeash( + "fixedleash", + EV_DEFAULT, + NULL, + NULL, + "if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset", + EV_GETTER +); +Event EV_Actor_SetFixedLeash( + "fixedleash", + EV_DEFAULT, + "f", + "multiplier", + "if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset", + EV_SETTER +); +Event EV_Actor_SetFixedLeash2( + "fixedleash", + EV_DEFAULT, + "f", + "multiplier", + "if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset", + EV_NORMAL +); Event EV_Actor_Holster - ( - "holster", - EV_DEFAULT, - NULL, - NULL, - "Holster weapon" - ); - +( + "holster", + EV_DEFAULT, + "i", + "holster", + "If non-zero, affects offhand. Holster weapon", + EV_NORMAL +); Event EV_Actor_Unholster - ( - "unholster", - EV_DEFAULT, - NULL, - NULL, - "Unholster weapon" - ); - +( + "unholster", + EV_DEFAULT, + "i", + "holster", + "If non-zero, affects offhand. Unholster weapon", + EV_NORMAL +); Event EV_Actor_IsEnemyVisible - ( - "is_enemy_visible", - EV_DEFAULT, - NULL, - NULL, - "0 if the enemy is not currently visible, 1 if he is" - ); - +( + "is_enemy_visible", + EV_DEFAULT, + NULL, + NULL, + "0 if the enemy is not currently visible, 1 if he is", + EV_NORMAL +); Event EV_Actor_GetEnemyVisibleChangeTime - ( - "enemy_visible_change_time", - EV_DEFAULT, - NULL, - NULL, - "Get the last time whether or not the enemy is visible changed, in seconds" - ); - +( + "enemy_visible_change_time", + EV_DEFAULT, + NULL, + NULL, + "Get the last time whether or not the enemy is visible changed, in seconds", + EV_NORMAL +); Event EV_Actor_GetLastEnemyVisibleTime - ( - "last_enemy_visible_time", - EV_DEFAULT, - NULL, - NULL, - "Get the last time the enemy was visible, in seconds" - ); - +( + "last_enemy_visible_time", + EV_DEFAULT, + NULL, + NULL, + "Get the last time the enemy was visible, in seconds", + EV_NORMAL +); Event EV_Actor_SetFallHeight - ( - "fallheight", - EV_DEFAULT, - "f", - "height", - "Set the fallheight", - EV_SETTER - ); - +( + "fallheight", + EV_DEFAULT, + "f", + "height", + "Set the fallheight", + EV_SETTER +); Event EV_Actor_SetFallHeight2 - ( - "fallheight", - EV_DEFAULT, - "f", - "height", - "Set the fallheight" - ); - +( + "fallheight", + EV_DEFAULT, + "f", + "height", + "Set the fallheight", + EV_NORMAL +); Event EV_Actor_GetFallHeight - ( - "fallheight", - EV_DEFAULT, - NULL, - NULL, - "Set the fallheight", - EV_GETTER - ); - -Event EV_Actor_CanMoveTo - ( - "canmoveto", - EV_DEFAULT, - "v", - "position", - "returns a boolean if the AI can move to a point; for use in anim scripts", - EV_RETURN - ); - +( + "fallheight", + EV_DEFAULT, + NULL, + NULL, + "Set the fallheight", + EV_GETTER +); +Event EV_Actor_CanMoveTo( + "canmoveto", + EV_DEFAULT, + "v", + "position", + "returns a boolean if the AI can move to a point; for use in anim scripts", + EV_RETURN +); Event EV_Actor_MoveDir - ( - "movedir", - EV_DEFAULT, - NULL, - NULL, - "Returns a unit vector pointing in the current direction of motion, or zero if not moving.This still has meaning if velocity is zero but the AI is starting to move on a path.", - EV_GETTER - ); - +( + "movedir", + EV_DEFAULT, + NULL, + NULL, + "Returns a unit vector pointing in the current direction of motion, or zero if not moving.This still has meaning " + "if v" + "elocity is zero but the AI is starting to move on a path.", + EV_GETTER +); Event EV_Actor_ResetLeash - ( - "resetleash", - EV_DEFAULT, - NULL, - NULL, - "resets the AI's leash to their current position" - ); - +( + "resetleash", + EV_DEFAULT, + NULL, + NULL, + "resets the AI's leash to their current position", + EV_NORMAL +); Event EV_Actor_IntervalDir - ( - "intervaldir", - EV_DEFAULT, - NULL, - NULL, - "the direction the AI would like to move to maintain its interval", - EV_GETTER - ); - +( + "intervaldir", + EV_DEFAULT, + NULL, + NULL, + "the direction the AI would like to move to maintain its interval", + EV_GETTER +); Event EV_Actor_Tether - ( - "tether", - EV_DEFAULT, - "e", - "entity", - "the entity to which the AI's leash should be tethered" - ); - -Event EV_Actor_GetThinkState - ( - "thinkstate", - EV_DEFAULT, - NULL, - NULL, - "current ai think state; can be void, idle, pain, killed, attack, curious, disguise, or grenade.", - EV_GETTER - ); - +( + "tether", + EV_DEFAULT, + "e", + "entity", + "the entity to which the AI's leash should be tethered", + EV_NORMAL +); +Event EV_Actor_GetThinkState( + "thinkstate", + EV_DEFAULT, + NULL, + NULL, + "current ai think state; can be void, idle, pain, killed, attack, curious, disguise, or grenade.", + EV_GETTER +); Event EV_Actor_GetEnemyShareRange - ( - "enemysharerange", - EV_DEFAULT, - NULL, - NULL, - "gets the range outside which the AI will not receive notification that a teammate has a new enemy", - EV_GETTER - ); - +( + "enemysharerange", + EV_DEFAULT, + NULL, + NULL, + "gets the range outside which the AI will not receive notification that a teammate has a new enemy", + EV_GETTER +); Event EV_Actor_SetEnemyShareRange - ( - "enemysharerange", - EV_DEFAULT, - "f", - "range", - "sets the range outside which the AI will not receive notification that a teammate has a new enemy", - EV_SETTER - ); - +( + "enemysharerange", + EV_DEFAULT, + "f", + "range", + "sets the range outside which the AI will not receive notification that a teammate has a new enemy", + EV_SETTER +); Event EV_Actor_SetEnemyShareRange2 - ( - "enemysharerange", - EV_DEFAULT, - "f", - "range", - "sets the range outside which the AI will not receive notification that a teammate has a new enemy" - ); - +( + "enemysharerange", + EV_DEFAULT, + "f", + "range", + "sets the range outside which the AI will not receive notification that a teammate has a new enemy", + EV_NORMAL +); Event EV_Actor_SetWeapon - ( - "weapon", - EV_DEFAULT, - "s", - "weapon_modelname", - "Sets the weapon.", - EV_SETTER - ); - +( + "weapon", + EV_DEFAULT, + "s", + "weapon_modelname", + "Sets the weapon.", + EV_SETTER +); Event EV_Actor_GetWeapon - ( - "weapon", - EV_DEFAULT, - NULL, - NULL, - "Gets the weapon.", - EV_GETTER - ); - +( + "weapon", + EV_DEFAULT, + NULL, + NULL, + "Gets the weapon.", + EV_GETTER +); Event EV_Actor_GetVoiceType - ( - "voicetype", - EV_DEFAULT, - NULL, - NULL, - "Gets the voice type", - EV_GETTER - ); - +( + "voicetype", + EV_DEFAULT, + NULL, + NULL, + "Gets the voice type", + EV_GETTER +); Event EV_Actor_SetVoiceType - ( - "voicetype", - EV_DEFAULT, - NULL, - NULL, - "Set voicetype to magic letter postfix" - ); - +( + "voicetype", + EV_DEFAULT, + NULL, + NULL, + "Set voicetype to magic letter postfix", + EV_NORMAL +); Event EV_Actor_SetVoiceType2 - ( - "voicetype", - EV_DEFAULT, - NULL, - NULL, - "Set voicetype to magic letter postfix", - EV_SETTER - ); - +( + "voicetype", + EV_DEFAULT, + NULL, + NULL, + "Set voicetype to magic letter postfix", + EV_SETTER +); Event EV_Actor_KickDir - ( - "kickdir", - EV_DEFAULT, - NULL, - NULL, - "Gets the direction the AI wants to kick", - EV_GETTER - ); - +( + "kickdir", + EV_DEFAULT, + NULL, + NULL, + "Gets the direction the AI wants to kick", + EV_GETTER +); Event EV_Actor_GetNoLongPain - ( - "nolongpain", - EV_DEFAULT, - NULL, - NULL, - "Returns 1 if long pain is not allowed, or 0 if long pain is allowed.", - EV_GETTER - ); - +( + "nolongpain", + EV_DEFAULT, + NULL, + NULL, + "Returns 1 if long pain is not allowed, or 0 if long pain is allowed.", + EV_GETTER +); Event EV_Actor_SetNoLongPain - ( - "nolongpain", - EV_DEFAULT, - "i", - "allow", - "Set to 1 if long pain is not allowed, or 0 if long pain is allowed.", - EV_SETTER - ); - +( + "nolongpain", + EV_DEFAULT, + "i", + "allow", + "Set to 1 if long pain is not allowed, or 0 if long pain is allowed.", + EV_SETTER +); Event EV_Actor_SetNoLongPain2 - ( - "nolongpain", - EV_DEFAULT, - "i", - "allow", - "Set to 1 if long pain is not allowed, or 0 if long pain is allowed." - ); - +( + "nolongpain", + EV_DEFAULT, + "i", + "allow", + "Set to 1 if long pain is not allowed, or 0 if long pain is allowed.", + EV_NORMAL +); Event EV_Actor_GetFavoriteEnemy - ( - "favoriteenemy", - EV_DEFAULT, - NULL, - NULL, - "Gets this AI's favorite enemy", - EV_GETTER - ); - +( + "favoriteenemy", + EV_DEFAULT, + NULL, + NULL, + "Gets this AI's favorite enemy", + EV_GETTER +); Event EV_Actor_SetFavoriteEnemy - ( - "favoriteenemy", - EV_DEFAULT, - "e", - "ai_or_player", - "Gets this AI's favorite enemy", - EV_SETTER - ); - +( + "favoriteenemy", + EV_DEFAULT, + "e", + "ai_or_player", + "Gets this AI's favorite enemy", + EV_SETTER +); Event EV_Actor_SetFavoriteEnemy2 - ( - "favoriteenemy", - EV_DEFAULT, - "e", - "ai_or_player", - "Gets this AI's favorite enemy" - ); - +( + "favoriteenemy", + EV_DEFAULT, + "e", + "ai_or_player", + "Gets this AI's favorite enemy", + EV_NORMAL +); Event EV_Actor_GetMumble - ( - "mumble", - EV_DEFAULT, - NULL, - NULL, - "Returns 1 if this guy is allowed to mumble, or 0 if he is not", - EV_GETTER - ); - +( + "mumble", + EV_DEFAULT, + NULL, + NULL, + "Returns 1 if this guy is allowed to mumble, or 0 if he is not", + EV_GETTER +); Event EV_Actor_SetMumble - ( - "mumble", - EV_DEFAULT, - "i", - "can_mumble", - "Set to 1 if this guy is allowed to mumble, or 0 if he is not", - EV_SETTER - ); - +( + "mumble", + EV_DEFAULT, + "i", + "can_mumble", + "Set to 1 if this guy is allowed to mumble, or 0 if he is not", + EV_SETTER +); Event EV_Actor_SetMumble2 - ( - "mumble", - EV_DEFAULT, - "i", - "can_mumble", - "Set to 1 if this guy is allowed to mumble, or 0 if he is not" - ); - +( + "mumble", + EV_DEFAULT, + "i", + "can_mumble", + "Set to 1 if this guy is allowed to mumble, or 0 if he is not", + EV_NORMAL +); Event EV_Actor_GetBreathSteam - ( - "breathsteam", - EV_DEFAULT, - NULL, - NULL, - "Returns 1 if this guy is allowed to have steamy breath, or 0 if he is not", - EV_GETTER - ); - +( + "breathsteam", + EV_DEFAULT, + NULL, + NULL, + "Returns 1 if this guy is allowed to have steamy breath, or 0 if he is not", + EV_GETTER +); Event EV_Actor_SetBreathSteam - ( - "breathsteam", - EV_DEFAULT, - "i", - "can_breathe_out", - "Set to 1 if this guy is allowed to have steamy breath, or 0 if he is not", - EV_SETTER - ); - +( + "breathsteam", + EV_DEFAULT, + "i", + "can_breathe_out", + "Set to 1 if this guy is allowed to have steamy breath, or 0 if he is not", + EV_SETTER +); Event EV_Actor_SetBreathSteam2 - ( - "breathsteam", - EV_DEFAULT, - "i", - "can_breathe_out", - "Set to 1 if this guy is allowed to have steamy breath, or 0 if he is not" - ); - +( + "breathsteam", + EV_DEFAULT, + "i", + "can_breathe_out", + "Set to 1 if this guy is allowed to have steamy breath, or 0 if he is not", + EV_NORMAL +); Event EV_Actor_SetNextBreathTime - ( - "nextbreathtime", - EV_DEFAULT, - "f", - "time_in_sec", - "Sets the next time the guy will breath out" - ); - +( + "nextbreathtime", + EV_DEFAULT, + "f", + "time_in_sec", + "Sets the next time the guy will breath out", + EV_NORMAL +); Event EV_Actor_CalcGrenadeToss - ( - "calcgrenadetoss", - EV_DEFAULT, - "v", - "target_position", - "Called to calculate a grenade toss. Must be called before a grenade throwing animation.\nReturns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.\nShould be called infrequently, and never during the middle of a grenade toss.", - EV_RETURN - ); - +( + "calcgrenadetoss", + EV_DEFAULT, + "v", + "target_position", + "Called to calculate a grenade toss. Must be called before a grenade throwing animation.\n" + "Returns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.\n" + "Should be called infrequently, and never during the middle of a grenade toss.", + EV_RETURN +); +Event EV_Actor_CalcGrenadeToss2 +( + "calcgrenadetoss2", + EV_DEFAULT, + "vf", + "target_position speed", + "Called to calculate a grenade toss. Must be called before a grenade throwing animation.\n" + "Returns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.\n" + "Should be called infrequently, and never during the middle of a grenade toss.\n" + " The speed parameter is optional. Pass a speed if you just want to override and throw no matter what...", + EV_RETURN +); Event EV_Actor_GetNoSurprise - ( - "nosurprise", - EV_DEFAULT, - NULL, - NULL, - "gets whether or not this guy is allowed to play a surprised animation when first encountering an enemy.\n", - EV_GETTER - ); - +( + "nosurprise", + EV_DEFAULT, + NULL, + NULL, + "gets whether or not this guy is allowed to play a surprised animation when first encountering an enemy.\n", + EV_GETTER +); Event EV_Actor_SetNoSurprise - ( - "nosurprise", - EV_DEFAULT, - "i", - "nosurprise", - "set to 0 to allow this guy to play a surprised animation when first encountering an enemy.\n", - EV_SETTER - ); - +( + "nosurprise", + EV_DEFAULT, + "i", + "nosurprise", + "set to 0 to allow this guy to play a surprised animation when first encountering an enemy.\n", + EV_SETTER +); Event EV_Actor_SetNoSurprise2 - ( - "nosurprise", - EV_DEFAULT, - "i", - "nosurprise", - "set to 0 to allow this guy to play a surprised animation when first encountering an enemy.\n" - ); - +( + "nosurprise", + EV_DEFAULT, + "i", + "nosurprise", + "set to 0 to allow this guy to play a surprised animation when first encountering an enemy.\n", + EV_NORMAL +); Event EV_Actor_GetSilent - ( - "silent", - EV_DEFAULT, - NULL, - NULL, - "gets whether or not this guy is allowed to say stuff besides pain and death sounds", - EV_GETTER - ); - +( + "silent", + EV_DEFAULT, + NULL, + NULL, + "gets whether or not this guy is allowed to say stuff besides pain and death sounds", + EV_GETTER +); Event EV_Actor_SetSilent - ( - "silent", - EV_DEFAULT, - "i", - "silent", - "set to 0 to prevent this guy from saying stuff besides pain and death sounds.\n", - EV_SETTER - ); - +( + "silent", + EV_DEFAULT, + "i", + "silent", + "set to 0 to prevent this guy from saying stuff besides pain and death sounds.\n", + EV_SETTER +); Event EV_Actor_SetSilent2 - ( - "silent", - EV_DEFAULT, - "i", - "silent", - "set to 0 to prevent this guy from saying stuff besides pain and death sounds.\n" - ); - +( + "silent", + EV_DEFAULT, + "i", + "silent", + "set to 0 to prevent this guy from saying stuff besides pain and death sounds.\n", + EV_NORMAL +); Event EV_Actor_GetAvoidPlayer - ( - "avoidplayer", - EV_DEFAULT, - NULL, - NULL, - "is 0 if this AI won't automatically get out of the way, non-zero if he will\n", - EV_GETTER - ); - +( + "avoidplayer", + EV_DEFAULT, + NULL, + NULL, + "is 0 if this AI won't automatically get out of the way, non-zero if he will\n", + EV_GETTER +); Event EV_Actor_SetAvoidPlayer - ( - "avoidplayer", - EV_DEFAULT, - "i", - "allowavoid", - "set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.\n", - EV_SETTER - ); - +( + "avoidplayer", + EV_DEFAULT, + "i", + "allowavoid", + "set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.\n", + EV_SETTER +); Event EV_Actor_SetAvoidPlayer2 - ( - "avoidplayer", - EV_DEFAULT, - "i", - "allowavoid", - "set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.\n" - ); - +( + "avoidplayer", + EV_DEFAULT, + "i", + "allowavoid", + "set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.\n", + EV_NORMAL +); Event EV_Actor_SetMoveDoneRadius - ( - "movedoneradius", - EV_DEFAULT, - "f", - "radius", - "Set the waittill movedone radius, default 0 means don't use manual radius", - EV_SETTER - ); - -Event EV_Actor_BeDead - ( - "bedead", - EV_DEFAULT, - NULL, - NULL, - "Forces the actor to be instantly and totally dead; no death animation is played" - ); - +( + "movedoneradius", + EV_DEFAULT, + "f", + "radius", + "Set the waittill movedone radius, default 0 means don't use manual radius", + EV_SETTER +); +Event EV_Actor_GetMoveDoneRadius +( + "movedoneradius", + EV_DEFAULT, + "f", + "radius", + "Set the waittill movedone radius, default 0 means don't use manual radius", + EV_GETTER +); +Event EV_Actor_BeDead( + "bedead", + EV_DEFAULT, + NULL, + NULL, + "Forces the actor to be instantly and totally dead; no death animation is played", + EV_NORMAL +); Event EV_Actor_GetLookAroundAngle - ( - "lookaround", - EV_DEFAULT, - NULL, - NULL, - "gets the angle in degrees left or right of center that the AI will look around while patrolling", - EV_GETTER - ); - +( + "lookaroundangle", + EV_DEFAULT, + NULL, + NULL, + "gets the angle in degrees left or right of center that the AI will look around while patrolling", + EV_GETTER +); Event EV_Actor_SetLookAroundAngle - ( - "lookaround", - EV_DEFAULT, - "f", - "angle", - "gets the angle in degrees left or right of center that the AI will look around while patrolling", - EV_SETTER - ); - +( + "lookaroundangle", + EV_DEFAULT, + "f", + "angle", + "gets the angle in degrees left or right of center that the AI will look around while patrolling", + EV_SETTER +); Event EV_Actor_SetLookAroundAngle2 - ( - "lookaround", - EV_DEFAULT, - "f", - "angle", - "gets the angle in degrees left or right of center that the AI will look around while patrolling" - ); - +( + "lookaroundangle", + EV_DEFAULT, + "f", + "angle", + "gets the angle in degrees left or right of center that the AI will look around while patrolling", + EV_NORMAL +); Event EV_Actor_HasCompleteLookahead - ( - "hascompletelookahead", - EV_DEFAULT, - NULL, - NULL, - "returns true if there are no corners to turn on the rest of the AI's current path", - EV_GETTER - ); - +( + "hascompletelookahead", + EV_DEFAULT, + NULL, + NULL, + "returns true if there are no corners to turn on the rest of the AI's current path", + EV_GETTER +); Event EV_Actor_PathDist - ( - "pathdist", - EV_DEFAULT, - NULL, - NULL, - "returns total distance along current path to the path goal", - EV_GETTER - ); - +( + "pathdist", + EV_DEFAULT, + NULL, + NULL, + "returns total distance along current path to the path goal", + EV_GETTER +); Event EV_Actor_CanShootEnemyFrom - ( - "canshootenemyfrom", - EV_DEFAULT, - "v", - "shootOrigin", - "Determines if it would be possible to shoot the sentient's enemy from the given position.", - EV_RETURN - ); - +( + "canshootenemyfrom", + EV_DEFAULT, + "v", + "shootOrigin", + "Determines if it would be possible to shoot the sentient's enemy from the given position.", + EV_RETURN +); Event EV_Actor_CanShoot - ( - "canshoot", - EV_DEFAULT, - "v", - "shootOrigin", - "Determines if it would be possible to shoot the sentient's enemy from the given position.", - EV_RETURN - ); - +( + "canshoot", + EV_DEFAULT, + "v", + "shootOrigin", + "Determines if it would be possible to shoot the sentient's enemy from the given position.", + EV_RETURN +); Event EV_Actor_GetInReload - ( - "inreload", - EV_DEFAULT, - NULL, - NULL, - "returns non-zero if the AI is in a reload", - EV_GETTER - ); - +( + "inreload", + EV_DEFAULT, + NULL, + NULL, + "returns non-zero if the AI is in a reload", + EV_GETTER +); Event EV_Actor_SetInReload - ( - "inreload", - EV_DEFAULT, - "i", - "reloading", - "set to non-zero to indicate the AI is in a reload", - EV_SETTER - ); - -Event EV_Actor_SetReloadCover - ( - "setreloadcover", - EV_DEFAULT, - NULL, - NULL, - "do this command to let the ai know it needs to reload; used to reload while going to cover" - ); - +( + "inreload", + EV_DEFAULT, + "i", + "reloading", + "set to non-zero to indicate the AI is in a reload", + EV_SETTER +); +Event EV_Actor_SetReloadCover( + "setreloadcover", + EV_DEFAULT, + NULL, + NULL, + "do this command to let the ai know it needs to reload; used to reload while going to cover", + EV_NORMAL +); Event EV_Actor_BreakSpecial - ( - "breakspecial", - EV_DEFAULT, - NULL, - NULL, - "tell ai to break special attack" - ); - +( + "breakspecial", + EV_DEFAULT, + NULL, + NULL, + "tell ai to break special attack", + EV_NORMAL +); Event EV_Actor_SetBalconyHeight - ( - "balconyheight", - EV_DEFAULT, - "f", - "height", - "minimum height a balcony guy must fall to do special balcony death" - ); - +( + "balconyheight", + EV_DEFAULT, + "f", + "height", + "minimum height a balcony guy must fall to do special balcony death", + EV_NORMAL +); Event EV_Actor_SetBalconyHeight2 - ( - "balconyheight", - EV_DEFAULT, - "f", - "height", - "minimum height a balcony guy must fall to do special balcony death", - EV_SETTER - ); - +( + "balconyheight", + EV_DEFAULT, + "f", + "height", + "minimum height a balcony guy must fall to do special balcony death", + EV_SETTER +); Event EV_Actor_GetBalconyHeight - ( - "balconyheight", - EV_DEFAULT, - NULL, - NULL, - "minimum height a balcony guy must fall to do special balcony death", - EV_GETTER - ); +( + "balconyheight", + EV_DEFAULT, + NULL, + NULL, + "minimum height a balcony guy must fall to do special balcony death", + EV_GETTER +); +// +// Added in 2.0 +//==== +Event EV_Actor_SetVisibilityThreshold +( + "nonvislevel", + EV_DEFAULT, + NULL, + NULL, + "visibility level in range 0-1 below which an enemy is treated as non-visible", + EV_NORMAL +); +Event EV_Actor_SetVisibilityThreshold2 +( + "nonvislevel", + EV_DEFAULT, + NULL, + NULL, + "visibility level in range 0-1 below which an enemy is treated as non-visible", + EV_SETTER +); +Event EV_Actor_GetVisibilityThreshold +( + "nonvislevel", + EV_DEFAULT, + NULL, + NULL, + "visibility level in range 0-1 below which an enemy is treated as non-visible", + EV_GETTER +); +Event EV_Actor_SetDefaultVisibilityThreshold +( + "defaultnonvislevel", + EV_DEFAULT, + NULL, + NULL, + "updates the default value for 'nonvislevel'", + EV_NORMAL +); +Event EV_Actor_SetSuppressChance +( + "suppresschance", + EV_DEFAULT, + NULL, + NULL, + "sets the percent chance of doing suppressing fire when appropriate (0-100)", + EV_NORMAL +); +Event EV_Actor_SetSuppressChance2 +( + "suppresschance", + EV_DEFAULT, + NULL, + NULL, + "sets the percent chance of doing suppressing fire when appropriate (0-100)", + EV_SETTER +); +Event EV_Actor_GetSuppressChance +( + "suppresschance", + EV_DEFAULT, + NULL, + NULL, + "sets the percent chance of doing suppressing fire when appropriate (0-100)", + EV_GETTER +); +Event EV_Actor_SetIgnoreBadPlace +( + "ignorebadplaces", + EV_DEFAULT, + "i", + "ignore", + "sets whether or not this AI guy will ignore bad places (0 = not suicidal)", + EV_NORMAL +); +Event EV_Actor_SetIgnoreBadPlace2 +( + "ignorebadplaces", + EV_DEFAULT, + "i", + "ignore", + "sets whether or not this AI guy will ignore bad places (0 = not suicidal)", + EV_SETTER +); +Event EV_Actor_GetIgnoreBadPlace +( + "ignorebadplaces", + EV_DEFAULT, + NULL, + NULL, + "gets whether or not this AI guy will ignore bad places (0 = not suicidal)", + EV_GETTER +); +Event EV_Actor_FindEnemy +( + "findenemy", + EV_DEFAULT, + NULL, + NULL, + "Finds the best enemy to target", + EV_RETURN +); +Event EV_Actor_DisableEnemySwitch +( + "enemyswitchdisable", + EV_DEFAULT, + NULL, + NULL, + "Disable enemy switching...", + EV_NORMAL +); +Event EV_Actor_EnableEnemySwitch +( + "enemyswitchenable", + EV_DEFAULT, + NULL, + NULL, + "Enable enemy switching...", + EV_NORMAL +); +Event EV_Actor_SetRunAnimRate +( + "runanimrate", + EV_DEFAULT, + "f", + "multiplier", + "Set the rate at which the run animation plays back", + EV_SETTER +); +Event EV_Actor_SetRunAnimRate2 +( + "runanimrate", + EV_DEFAULT, + "f", + "multiplier", + "Set the rate at which the run animation plays back", + EV_NORMAL +); +Event EV_Actor_GetRunAnimRate +( + "runanimrate", + EV_DEFAULT, + NULL, + NULL, + "Get the rate at which the run animation plays back", + EV_GETTER +); +//==== +// +// Added in 2.30 +//==== +Event EV_Actor_SetNationality +( + "nationality", + EV_DEFAULT, + "s", + "nationality", + "Set the nationality of an actor. Valid entries are default, ger, it, usa, uk, and ussr.", + EV_NORMAL +); +Event EV_Actor_SetNationality2 +( + "nationality", + EV_DEFAULT, + "s", + "nationality", + "Set the nationality of an actor. Valid entries are default, ger, it, usa, uk, and ussr.", + EV_SETTER +); +Event EV_Actor_GetNationality +( + "nationality", + EV_DEFAULT, + NULL, + NULL, + "Get the nationality of an actor. Return values are ger, it, usa, uk, ussr and unset.", + EV_GETTER +); +Event EV_Actor_WriteStats +( + "writestats", + EV_DEFAULT, + NULL, + NULL, + "Used internally to write stats to a CSV file.", + EV_NORMAL +); +Event EV_Actor_CuriousOff +( + "curiousoff", + EV_DEFAULT, + NULL, + NULL, + "Turn off an actor's curious state", + EV_NORMAL +); +Event EV_Actor_CuriousOn +( + "curiouson", + EV_DEFAULT, + NULL, + NULL, + "Turn on an actor's curious state", + EV_NORMAL +); +//==== -CLASS_DECLARATION( SimpleActor, Actor, "Actor" ) -{ - { &EV_Entity_Start, &Actor::EventStart }, - { &EV_Actor_MoveTo, &Actor::MoveTo }, - { &EV_Actor_WalkTo, &Actor::WalkTo }, - { &EV_Actor_RunTo, &Actor::RunTo }, - { &EV_Actor_CrouchTo, &Actor::CrouchTo }, - { &EV_Actor_CrawlTo, &Actor::CrawlTo }, - { &EV_Actor_AimAt, &Actor::AimAt }, - { &EV_Pain, &Actor::EventPain }, - { &EV_Killed, &Actor::EventKilled }, - { &EV_Actor_DeathEmbalm, &Actor::DeathEmbalm }, - { &EV_Actor_Anim, &Actor::PlayAnimation }, - { &EV_Actor_AnimLoop, &Actor::PlayAnimation }, - { &EV_Actor_Anim_Scripted, &Actor::PlayScriptedAnimation }, - { &EV_Actor_Anim_Noclip, &Actor::PlayNoclipAnimation }, - { &EV_Actor_AnimScript, &Actor::EventAnimScript }, - { &EV_Actor_AnimScript_Scripted, &Actor::EventAnimScript_Scripted }, - { &EV_Actor_AnimScript_Noclip, &Actor::EventAnimScript_Noclip }, - { &EV_Actor_Reload_mg42, &Actor::EventReload_mg42 }, - { &EV_Actor_Dumb, &Actor::Dumb }, - { &EV_Actor_Physics_On, &Actor::PhysicsOn }, - { &EV_Actor_Physics_Off, &Actor::PhysicsOff }, - { &EV_Actor_SetAnim, &Actor::EventSetAnim }, - { &EV_Actor_SetAnimLength, &SimpleActor::EventSetAnimLength }, - { &EV_Actor_EndActionAnim, &Actor::EventEndActionAnim }, - { &EV_Actor_SetMotionAnim, &Actor::EventSetMotionAnim }, - { &EV_Actor_SetAimMotionAnim, &Actor::EventSetAimMotionAnim }, - { &EV_Actor_SetActionAnim, &Actor::EventSetActionAnim }, - { &EV_Actor_UpperAnim, &Actor::EventUpperAnim }, - { &EV_Actor_SetUpperAnim, &Actor::EventSetUpperAnim }, - { &EV_Actor_SetCrossblendTime, &SimpleActor::EventSetCrossblendTime }, - { &EV_Actor_GetCrossblendTime, &SimpleActor::EventGetCrossblendTime }, - { &EV_Actor_GetPosition, &SimpleActor::EventGetPosition }, - { &EV_Actor_SetPosition, &SimpleActor::EventSetPosition }, - { &EV_Actor_SetEmotion, &SimpleActor::EventSetEmotion }, - { &EV_Actor_SetAnimFinal, &SimpleActor::EventSetAnimFinal }, - { &EV_Actor_GetWeaponType, &SimpleActor::EventGetWeaponType }, - { &EV_Actor_GetWeaponGroup, &SimpleActor::EventGetWeaponGroup }, - { &EV_Actor_LookAt, &Actor::EventLookAt }, - { &EV_Actor_EyesLookAt, &Actor::EventEyesLookAt }, - { &EV_Actor_PointAt, &Actor::EventPointAt }, - { &EV_Actor_TurnTo, &Actor::EventTurnTo }, - { &EV_Actor_SetTurnDoneError, &Actor::EventSetTurnDoneError }, - { &EV_Actor_SetTurnDoneError2, &Actor::EventSetTurnDoneError }, - { &EV_Actor_GetTurnDoneError, &Actor::EventGetTurnDoneError }, - { &EV_Actor_IdleSayAnim, &Actor::EventIdleSayAnim }, - { &EV_Actor_SayAnim, &Actor::EventSayAnim }, - { &EV_Actor_SetSayAnim, &Actor::EventSetSayAnim }, - { &EV_Sentient_UseItem, &Actor::EventGiveWeapon }, - { &EV_Sentient_GiveWeapon, &Actor::EventGiveWeapon }, - { &EV_Actor_SetWeapon, &Actor::EventGiveWeapon }, - { &EV_Actor_GetWeapon, &Actor::EventGetWeapon }, - { &EV_Actor_SetGun, &Actor::EventGiveWeapon }, - { &EV_Actor_SetGun2, &Actor::EventGiveWeapon }, - { &EV_Actor_GetGun, &Actor::EventGetWeapon }, - { &EV_Actor_WeaponInternal, &Actor::EventGiveWeaponInternal }, - { &EV_Actor_DamagePuff, &Actor::EventDamagePuff }, - { &EV_Actor_SetAngleYawSpeed, &Actor::EventSetAngleYawSpeed }, - { &EV_Actor_SetAngleYawSpeed2, &Actor::EventSetAngleYawSpeed }, - { &EV_Actor_GetAngleYawSpeed, &Actor::EventGetAngleYawSpeed }, - { &EV_Actor_SetAimTarget, &Actor::EventSetAimTarget }, - { &EV_Actor_ReadyToFire, &Actor::ReadyToFire }, - { &EV_Actor_AIOn, &SimpleActor::EventAIOn }, - { &EV_Actor_AIOff, &SimpleActor::EventAIOff }, - { &EV_Actor_GetLocalYawFromVector, &Actor::GetLocalYawFromVector }, - { &EV_DeathSinkStart, &Actor::DeathSinkStart }, - { &EV_Actor_GetSight, &Actor::EventGetSight }, - { &EV_Actor_SetSight, &Actor::EventSetSight }, - { &EV_Actor_SetSight2, &Actor::EventSetSight }, - { &EV_Actor_GetHearing, &Actor::EventGetHearing }, - { &EV_Actor_SetHearing, &Actor::EventSetHearing }, - { &EV_Actor_SetHearing2, &Actor::EventSetHearing }, - { &EV_Actor_SetFov, &Actor::EventSetFov }, - { &EV_Actor_SetFov2, &Actor::EventSetFov }, - { &EV_Actor_GetFov, &Actor::EventGetFov }, - { &EV_Actor_DistToEnemy, &Actor::EventDistToEnemy }, - { &EV_Actor_SetPatrolPath, &Actor::EventSetPatrolPath }, - { &EV_Actor_SetPatrolPath2, &Actor::EventSetPatrolPath }, - { &EV_Actor_GetPatrolPath, &Actor::EventGetPatrolPath }, - { &EV_Actor_SetPatrolWaitTrigger, &Actor::EventSetPatrolWaitTrigger }, - { &EV_Actor_SetPatrolWaitTrigger2, &Actor::EventSetPatrolWaitTrigger }, - { &EV_Actor_GetPatrolWaitTrigger, &Actor::EventGetPatrolWaitTrigger }, - { &EV_Actor_SetAccuracy, &Actor::EventSetAccuracy }, - { &EV_Actor_SetAccuracy2, &Actor::EventSetAccuracy }, - { &EV_Actor_GetAccuracy, &Actor::EventGetAccuracy }, - { &EV_Actor_SetTypeIdle, &Actor::EventSetTypeIdle }, - { &EV_Actor_SetTypeIdle2, &Actor::EventSetTypeIdle }, - { &EV_Actor_GetTypeIdle, &Actor::EventGetTypeIdle }, - { &EV_Actor_SetTypeAttack, &Actor::EventSetTypeAttack }, - { &EV_Actor_SetTypeAttack2, &Actor::EventSetTypeAttack }, - { &EV_Actor_GetTypeAttack, &Actor::EventGetTypeAttack }, - { &EV_Actor_SetTypeDisguise, &Actor::EventSetTypeDisguise }, - { &EV_Actor_SetTypeDisguise2, &Actor::EventSetTypeDisguise }, - { &EV_Actor_GetTypeDisguise, &Actor::EventGetTypeDisguise }, - { &EV_Actor_SetDisguiseLevel, &Actor::EventSetDisguiseLevel }, - { &EV_Actor_SetDisguiseLevel2, &Actor::EventSetDisguiseLevel }, - { &EV_Actor_GetDisguiseLevel, &Actor::EventGetDisguiseLevel }, - { &EV_Actor_SetTypeGrenade, &Actor::EventSetTypeGrenade }, - { &EV_Actor_SetTypeGrenade2, &Actor::EventSetTypeGrenade }, - { &EV_Actor_GetTypeGrenade, &Actor::EventGetTypeGrenade }, - { &EV_Actor_SetMinDistance, &Actor::EventSetMinDistance }, - { &EV_Actor_SetMinDistance2, &Actor::EventSetMinDistance }, - { &EV_Actor_GetMinDistance, &Actor::EventGetMinDistance }, - { &EV_Actor_SetMaxDistance, &Actor::EventSetMaxDistance }, - { &EV_Actor_SetMaxDistance2, &Actor::EventSetMaxDistance }, - { &EV_Actor_GetMaxDistance, &Actor::EventGetMaxDistance }, - { &EV_Actor_GetLeash, &Actor::EventGetLeash }, - { &EV_Actor_SetLeash, &Actor::EventSetLeash }, - { &EV_Actor_SetLeash2, &Actor::EventSetLeash }, - { &EV_Actor_GetInterval, &Actor::EventGetInterval }, - { &EV_Actor_SetInterval, &Actor::EventSetInterval }, - { &EV_Actor_SetInterval2, &Actor::EventSetInterval }, - { &EV_Actor_GetRunAnim, &Actor::EventGetRunAnim }, - { &EV_Actor_GetWalkAnim, &Actor::EventGetWalkAnim }, - { &EV_Actor_GetAnimName, &Actor::EventGetAnimName }, - { &EV_Actor_SetAnimName, &Actor::EventSetAnimName }, - { &EV_Actor_SetDisguiseRange, &Actor::EventSetDisguiseRange }, - { &EV_Actor_SetDisguiseRange2, &Actor::EventSetDisguiseRange }, - { &EV_Actor_GetDisguiseRange, &Actor::EventGetDisguiseRange }, - { &EV_Actor_SetDisguisePeriod, &Actor::EventSetDisguisePeriod }, - { &EV_Actor_SetDisguisePeriod2, &Actor::EventSetDisguisePeriod }, - { &EV_Actor_GetDisguisePeriod, &Actor::EventGetDisguisePeriod }, - { &EV_Actor_SetDisguiseAcceptThread, &Actor::EventSetDisguiseAcceptThread }, - { &EV_Actor_SetDisguiseAcceptThread2, &Actor::EventSetDisguiseAcceptThread }, - { &EV_Actor_GetDisguiseAcceptThread, &Actor::EventGetDisguiseAcceptThread }, - { &EV_Actor_AttackPlayer, &Actor::EventAttackPlayer }, - { &EV_Actor_SetAlarmNode, &Actor::EventSetAlarmNode }, - { &EV_Actor_SetAlarmNode2, &Actor::EventSetAlarmNode }, - { &EV_Actor_GetAlarmNode, &Actor::EventGetAlarmNode }, - { &EV_Actor_SetAlarmThread, &Actor::EventSetAlarmThread }, - { &EV_Actor_SetAlarmThread2, &Actor::EventSetAlarmThread }, - { &EV_Actor_GetAlarmThread, &Actor::EventGetAlarmThread }, - { &EV_Actor_SetSoundAwareness, &Actor::EventSetSoundAwareness }, - { &EV_Actor_SetSoundAwareness2, &Actor::EventSetSoundAwareness }, - { &EV_Actor_GetSoundAwareness, &Actor::EventGetSoundAwareness }, - { &EV_Actor_SetGrenadeAwareness, &Actor::EventSetGrenadeAwareness }, - { &EV_Actor_SetGrenadeAwareness2, &Actor::EventSetGrenadeAwareness }, - { &EV_Actor_GetGrenadeAwareness, &Actor::EventGetGrenadeAwareness }, - { &EV_Actor_SetTurret, &Actor::EventSetTurret }, - { &EV_Actor_SetTurret2, &Actor::EventSetTurret }, - { &EV_Actor_GetTurret, &Actor::EventGetTurret }, - { &EV_Actor_AttachGrenade, &Actor::Grenade_EventAttach }, - { &EV_Actor_DetachGrenade, &Actor::Grenade_EventDetach }, - { &EV_Actor_FireGrenade, &Actor::Grenade_EventFire }, - { &EV_Actor_EnableEnemy, &Actor::EventEnableEnemy }, - { &EV_Actor_EnablePain, &Actor::EventEnablePain }, - { &EV_Activate, &Actor::EventActivate }, - { &EV_Actor_GetAmmoGrenade, &Actor::EventGetAmmoGrenade }, - { &EV_Actor_SetAmmoGrenade, &Actor::EventSetAmmoGrenade }, - { &EV_Actor_SetAmmoGrenade2, &Actor::EventSetAmmoGrenade }, - { &EV_Actor_GetMood, &Actor::EventGetMood }, - { &EV_Actor_SetMood, &Actor::EventSetMood }, - { &EV_Actor_ShareEnemy, &Actor::EventShareEnemy }, - { &EV_Actor_ShareGrenade, &Actor::EventShareGrenade }, - { &EV_Actor_InterruptPoint, &Actor::EventInterruptPoint }, - { &EV_Actor_GetPainHandler, &SimpleActor::EventGetPainHandler }, - { &EV_Actor_SetPainHandler, &SimpleActor::EventSetPainHandler }, - { &EV_Actor_GetDeathHandler, &SimpleActor::EventGetDeathHandler }, - { &EV_Actor_SetDeathHandler, &SimpleActor::EventSetDeathHandler }, - { &EV_Actor_GetAttackHandler, &SimpleActor::EventGetAttackHandler }, - { &EV_Actor_SetAttackHandler, &SimpleActor::EventSetAttackHandler }, - { &EV_Actor_SetHeadModel, &Actor::EventSetHeadModel }, - { &EV_Actor_GetHeadModel, &Actor::EventGetHeadModel }, - { &EV_Actor_SetHeadSkin, &Actor::EventSetHeadSkin }, - { &EV_Actor_GetHeadSkin, &Actor::EventGetHeadSkin }, - { &EV_Actor_SetNoIdle, &Actor::EventSetNoIdle }, - { &EV_Actor_GetNoIdle, &Actor::EventGetNoIdle }, - { &EV_Actor_GetEnemy, &Actor::EventGetEnemy }, - { &EV_Actor_GetMaxNoticeTimeScale, &Actor::EventGetMaxNoticeTimeScale }, - { &EV_Actor_SetMaxNoticeTimeScale, &Actor::EventSetMaxNoticeTimeScale }, - { &EV_Actor_SetMaxNoticeTimeScale2, &Actor::EventSetMaxNoticeTimeScale }, - { &EV_Actor_GetFixedLeash, &Actor::EventGetFixedLeash }, - { &EV_Actor_SetFixedLeash, &Actor::EventSetFixedLeash }, - { &EV_Actor_SetFixedLeash2, &Actor::EventSetFixedLeash }, - { &EV_Actor_Holster, &Actor::EventHolster }, - { &EV_Actor_Unholster, &Actor::EventUnholster }, - { &EV_SoundDone, &Actor::EventSoundDone }, - { &EV_Sound, &Actor::EventSound }, - { &EV_Actor_IsEnemyVisible, &Actor::EventIsEnemyVisible }, - { &EV_Actor_GetEnemyVisibleChangeTime, &Actor::EventGetEnemyVisibleChangeTime }, - { &EV_Actor_GetLastEnemyVisibleTime, &Actor::EventGetLastEnemyVisibleTime }, - { &EV_Actor_SetFallHeight, &Actor::EventSetFallHeight }, - { &EV_Actor_GetFallHeight, &Actor::EventGetFallHeight }, - { &EV_Actor_CanMoveTo, &Actor::EventCanMoveTo }, - { &EV_Actor_MoveDir, &Actor::EventMoveDir }, - { &EV_Actor_IntervalDir, &Actor::EventIntervalDir }, - { &EV_Actor_ResetLeash, &Actor::EventResetLeash }, - { &EV_Actor_Tether, &Actor::EventTether }, - { &EV_Actor_GetThinkState, &Actor::EventGetThinkState }, - { &EV_Actor_GetEnemyShareRange, &Actor::EventGetEnemyShareRange }, - { &EV_Actor_SetEnemyShareRange, &Actor::EventSetEnemyShareRange }, - { &EV_Actor_SetEnemyShareRange2, &Actor::EventSetEnemyShareRange }, - { &EV_Actor_GetVoiceType, &Actor::GetVoiceType }, - { &EV_Actor_SetVoiceType, &Actor::SetVoiceType }, - { &EV_Actor_SetVoiceType2, &Actor::SetVoiceType }, - { &EV_Remove, &Actor::Remove }, - { &EV_Delete, &Actor::Remove }, - { &EV_ScriptRemove, &Actor::Remove }, - { &EV_Actor_KickDir, &Actor::EventGetKickDir }, - { &EV_Actor_GetNoLongPain, &Actor::EventGetNoLongPain }, - { &EV_Actor_SetNoLongPain, &Actor::EventSetNoLongPain }, - { &EV_Actor_SetNoLongPain2, &Actor::EventSetNoLongPain }, - { &EV_Actor_GetFavoriteEnemy, &Actor::EventGetFavoriteEnemy }, - { &EV_Actor_SetFavoriteEnemy, &Actor::EventSetFavoriteEnemy }, - { &EV_Actor_SetFavoriteEnemy2, &Actor::EventSetFavoriteEnemy }, - { &EV_Actor_GetMumble, &Actor::EventGetMumble }, - { &EV_Actor_SetMumble, &Actor::EventSetMumble }, - { &EV_Actor_SetMumble2, &Actor::EventSetMumble }, - { &EV_Actor_GetBreathSteam, &Actor::EventGetBreathSteam }, - { &EV_Actor_SetBreathSteam, &Actor::EventSetBreathSteam }, - { &EV_Actor_SetBreathSteam2, &Actor::EventSetBreathSteam }, - { &EV_Actor_CalcGrenadeToss, &Actor::EventCalcGrenadeToss }, - { &EV_Actor_GetNoSurprise, &Actor::EventGetNoSurprise }, - { &EV_Actor_SetNoSurprise, &Actor::EventSetNoSurprise }, - { &EV_Actor_SetNoSurprise2, &Actor::EventSetNoSurprise }, - { &EV_Actor_GetSilent, &Actor::EventGetSilent }, - { &EV_Actor_SetSilent, &Actor::EventSetSilent }, - { &EV_Actor_SetSilent2, &Actor::EventSetSilent }, - { &EV_Actor_GetAvoidPlayer, &Actor::EventGetAvoidPlayer }, - { &EV_Actor_SetAvoidPlayer, &Actor::EventSetAvoidPlayer }, - { &EV_Actor_SetAvoidPlayer2, &Actor::EventSetAvoidPlayer }, - { &EV_Actor_SetMoveDoneRadius, &Actor::EventSetMoveDoneRadius }, - { &EV_Actor_BeDead, &Actor::EventBeDead }, - { &EV_Actor_GetLookAroundAngle, &Actor::EventGetLookAroundAngle }, - { &EV_Actor_SetLookAroundAngle, &Actor::EventSetLookAroundAngle }, - { &EV_Actor_SetLookAroundAngle2, &Actor::EventSetLookAroundAngle }, - { &EV_Actor_HasCompleteLookahead, &Actor::EventHasCompleteLookahead }, - { &EV_Actor_PathDist, &Actor::EventPathDist }, - { &EV_Actor_CanShootEnemyFrom, &Actor::EventCanShootEnemyFrom }, - { &EV_Actor_CanShoot, &Actor::EventCanShoot }, - { &EV_Actor_GetInReload, &Actor::EventGetInReload }, - { &EV_Actor_SetInReload, &Actor::EventSetInReload }, - { &EV_Actor_SetReloadCover, &Actor::EventSetReloadCover }, - { &EV_Actor_BreakSpecial, &Actor::EventBreakSpecial }, - { &EV_Actor_SetBalconyHeight, &Actor::EventSetBalconyHeight }, - { &EV_Actor_SetBalconyHeight2, &Actor::EventSetBalconyHeight }, - { &EV_Actor_GetBalconyHeight, &Actor::EventGetBalconyHeight }, - { &EV_CanSee, &Actor::CanSee }, - { NULL, NULL } +CLASS_DECLARATION(SimpleActor, Actor, "Actor") { + {&EV_Entity_Start, &Actor::EventStart }, + {&EV_Actor_MoveTo, &Actor::MoveTo }, + {&EV_Actor_WalkTo, &Actor::WalkTo }, + {&EV_Actor_RunTo, &Actor::RunTo }, + {&EV_Actor_CrouchTo, &Actor::CrouchTo }, + {&EV_Actor_CrawlTo, &Actor::CrawlTo }, + {&EV_Actor_AimAt, &Actor::AimAt }, + {&EV_Pain, &Actor::EventPain }, + {&EV_Killed, &Actor::EventKilled }, + {&EV_Actor_DeathEmbalm, &Actor::DeathEmbalm }, + {&EV_Actor_Anim, &Actor::PlayAnimation }, + {&EV_Actor_AnimLoop, &Actor::PlayAnimation }, + {&EV_Actor_Anim_Scripted, &Actor::PlayScriptedAnimation }, + {&EV_Actor_Anim_Noclip, &Actor::PlayNoclipAnimation }, + {&EV_Actor_Anim_Attached, &Actor::PlayAttachedAnimation }, + {&EV_Actor_AnimScript, &Actor::EventAnimScript }, + {&EV_Actor_AnimScript_Scripted, &Actor::EventAnimScript_Scripted }, + {&EV_Actor_AnimScript_Noclip, &Actor::EventAnimScript_Noclip }, + // Added in 2.0 + //==== + {&EV_Actor_AnimScript_Attached, &Actor::EventAnimScript_Attached }, + //==== + {&EV_Actor_Reload_mg42, &Actor::EventReload_mg42 }, + {&EV_Actor_Dumb, &Actor::Dumb }, + {&EV_Actor_Physics_On, &Actor::PhysicsOn }, + {&EV_Actor_Physics_Off, &Actor::PhysicsOff }, + {&EV_Actor_SetAnim, &Actor::EventSetAnim }, + {&EV_Actor_SetAnimLength, &SimpleActor::EventSetAnimLength }, + {&EV_Actor_EndActionAnim, &Actor::EventEndActionAnim }, + {&EV_Actor_SetMotionAnim, &Actor::EventSetMotionAnim }, + {&EV_Actor_SetAimMotionAnim, &Actor::EventSetAimMotionAnim }, + {&EV_Actor_SetActionAnim, &Actor::EventSetActionAnim }, + {&EV_Actor_UpperAnim, &Actor::EventUpperAnim }, + {&EV_Actor_SetUpperAnim, &Actor::EventSetUpperAnim }, + {&EV_Actor_SetCrossblendTime, &SimpleActor::EventSetCrossblendTime }, + {&EV_Actor_GetCrossblendTime, &SimpleActor::EventGetCrossblendTime }, + {&EV_Actor_GetPosition, &SimpleActor::EventGetPosition }, + {&EV_Actor_SetPosition, &SimpleActor::EventSetPosition }, + {&EV_Actor_SetEmotion, &SimpleActor::EventSetEmotion }, + {&EV_Actor_SetAnimFinal, &SimpleActor::EventSetAnimFinal }, + {&EV_Actor_GetWeaponType, &SimpleActor::EventGetWeaponType }, + {&EV_Actor_GetWeaponGroup, &SimpleActor::EventGetWeaponGroup }, + {&EV_Actor_LookAt, &Actor::EventLookAt }, + {&EV_Actor_EyesLookAt, &Actor::EventEyesLookAt }, + {&EV_Actor_PointAt, &Actor::EventPointAt }, + {&EV_Actor_TurnTo, &Actor::EventTurnTo }, + {&EV_Actor_SetTurnDoneError, &Actor::EventSetTurnDoneError }, + {&EV_Actor_SetTurnDoneError2, &Actor::EventSetTurnDoneError }, + {&EV_Actor_GetTurnDoneError, &Actor::EventGetTurnDoneError }, + {&EV_Actor_IdleSayAnim, &Actor::EventIdleSayAnim }, + {&EV_Actor_SayAnim, &Actor::EventSayAnim }, + {&EV_Actor_SetSayAnim, &Actor::EventSetSayAnim }, + {&EV_Sentient_UseItem, &Actor::EventGiveWeapon }, + {&EV_Sentient_GiveWeapon, &Actor::EventGiveWeapon }, + {&EV_Actor_SetWeapon, &Actor::EventGiveWeapon }, + {&EV_Actor_GetWeapon, &Actor::EventGetWeapon }, + {&EV_Actor_SetGun, &Actor::EventGiveWeapon }, + {&EV_Actor_SetGun2, &Actor::EventGiveWeapon }, + {&EV_Actor_GetGun, &Actor::EventGetWeapon }, + {&EV_Actor_WeaponInternal, &Actor::EventGiveWeaponInternal }, + {&EV_Actor_DamagePuff, &Actor::EventDamagePuff }, + {&EV_Actor_SetAngleYawSpeed, &Actor::EventSetAngleYawSpeed }, + {&EV_Actor_SetAngleYawSpeed2, &Actor::EventSetAngleYawSpeed }, + {&EV_Actor_GetAngleYawSpeed, &Actor::EventGetAngleYawSpeed }, + {&EV_Actor_SetAimTarget, &Actor::EventSetAimTarget }, + {&EV_Actor_ReadyToFire, &Actor::ReadyToFire }, + {&EV_Actor_AIOn, &SimpleActor::EventAIOn }, + {&EV_Actor_AIOff, &SimpleActor::EventAIOff }, + {&EV_DeathSinkStart, &Actor::DeathSinkStart }, + {&EV_Actor_GetSight, &Actor::EventGetSight }, + {&EV_Actor_SetSight, &Actor::EventSetSight }, + {&EV_Actor_SetSight2, &Actor::EventSetSight }, + {&EV_Actor_GetHearing, &Actor::EventGetHearing }, + {&EV_Actor_SetHearing, &Actor::EventSetHearing }, + {&EV_Actor_SetHearing2, &Actor::EventSetHearing }, + {&EV_Actor_SetFov, &Actor::EventSetFov }, + {&EV_Actor_SetFov2, &Actor::EventSetFov }, + {&EV_Actor_GetFov, &Actor::EventGetFov }, + {&EV_Actor_DistToEnemy, &Actor::EventDistToEnemy }, + {&EV_Actor_SetPatrolPath, &Actor::EventSetPatrolPath }, + {&EV_Actor_SetPatrolPath2, &Actor::EventSetPatrolPath }, + {&EV_Actor_GetPatrolPath, &Actor::EventGetPatrolPath }, + {&EV_Actor_SetPatrolWaitTrigger, &Actor::EventSetPatrolWaitTrigger }, + {&EV_Actor_SetPatrolWaitTrigger2, &Actor::EventSetPatrolWaitTrigger }, + {&EV_Actor_GetPatrolWaitTrigger, &Actor::EventGetPatrolWaitTrigger }, + {&EV_Actor_SetAccuracy, &Actor::EventSetAccuracy }, + {&EV_Actor_SetAccuracy2, &Actor::EventSetAccuracy }, + {&EV_Actor_GetAccuracy, &Actor::EventGetAccuracy }, + {&EV_Actor_SetTypeIdle, &Actor::EventSetTypeIdle }, + {&EV_Actor_SetTypeIdle2, &Actor::EventSetTypeIdle }, + {&EV_Actor_GetTypeIdle, &Actor::EventGetTypeIdle }, + {&EV_Actor_SetTypeAttack, &Actor::EventSetTypeAttack }, + {&EV_Actor_SetTypeAttack2, &Actor::EventSetTypeAttack }, + {&EV_Actor_GetTypeAttack, &Actor::EventGetTypeAttack }, + {&EV_Actor_SetTypeDisguise, &Actor::EventSetTypeDisguise }, + {&EV_Actor_SetTypeDisguise2, &Actor::EventSetTypeDisguise }, + {&EV_Actor_GetTypeDisguise, &Actor::EventGetTypeDisguise }, + {&EV_Actor_SetDisguiseLevel, &Actor::EventSetDisguiseLevel }, + {&EV_Actor_SetDisguiseLevel2, &Actor::EventSetDisguiseLevel }, + {&EV_Actor_GetDisguiseLevel, &Actor::EventGetDisguiseLevel }, + {&EV_Actor_SetTypeGrenade, &Actor::EventSetTypeGrenade }, + {&EV_Actor_SetTypeGrenade2, &Actor::EventSetTypeGrenade }, + {&EV_Actor_GetTypeGrenade, &Actor::EventGetTypeGrenade }, + {&EV_Actor_SetMinDistance, &Actor::EventSetMinDistance }, + {&EV_Actor_SetMinDistance2, &Actor::EventSetMinDistance }, + {&EV_Actor_GetMinDistance, &Actor::EventGetMinDistance }, + {&EV_Actor_SetMaxDistance, &Actor::EventSetMaxDistance }, + {&EV_Actor_SetMaxDistance2, &Actor::EventSetMaxDistance }, + {&EV_Actor_GetMaxDistance, &Actor::EventGetMaxDistance }, + {&EV_Actor_GetLeash, &Actor::EventGetLeash }, + {&EV_Actor_SetLeash, &Actor::EventSetLeash }, + {&EV_Actor_SetLeash2, &Actor::EventSetLeash }, + {&EV_Actor_GetInterval, &Actor::EventGetInterval }, + {&EV_Actor_SetInterval, &Actor::EventSetInterval }, + {&EV_Actor_SetInterval2, &Actor::EventSetInterval }, + {&EV_Actor_GetRunAnim, &Actor::EventGetRunAnim }, + {&EV_Actor_GetWalkAnim, &Actor::EventGetWalkAnim }, + {&EV_Actor_GetAnimName, &Actor::EventGetAnimName }, + {&EV_Actor_SetAnimName, &Actor::EventSetAnimName }, + {&EV_Actor_SetDisguiseRange, &Actor::EventSetDisguiseRange }, + {&EV_Actor_SetDisguiseRange2, &Actor::EventSetDisguiseRange }, + {&EV_Actor_GetDisguiseRange, &Actor::EventGetDisguiseRange }, + {&EV_Actor_SetDisguisePeriod, &Actor::EventSetDisguisePeriod }, + {&EV_Actor_SetDisguisePeriod2, &Actor::EventSetDisguisePeriod }, + {&EV_Actor_GetDisguisePeriod, &Actor::EventGetDisguisePeriod }, + {&EV_Actor_SetDisguiseAcceptThread, &Actor::EventSetDisguiseAcceptThread }, + {&EV_Actor_SetDisguiseAcceptThread2, &Actor::EventSetDisguiseAcceptThread }, + {&EV_Actor_GetDisguiseAcceptThread, &Actor::EventGetDisguiseAcceptThread }, + {&EV_Actor_AttackPlayer, &Actor::EventAttackPlayer }, + {&EV_Actor_SetAlarmNode, &Actor::EventSetAlarmNode }, + {&EV_Actor_SetAlarmNode2, &Actor::EventSetAlarmNode }, + {&EV_Actor_GetAlarmNode, &Actor::EventGetAlarmNode }, + // Added in 2.30 + //==== + {&EV_Actor_SetPreAlarmThread, &Actor::EventSetPreAlarmThread }, + {&EV_Actor_SetPreAlarmThread2, &Actor::EventSetPreAlarmThread }, + //==== + {&EV_Actor_SetAlarmThread, &Actor::EventSetAlarmThread }, + {&EV_Actor_SetAlarmThread2, &Actor::EventSetAlarmThread }, + {&EV_Actor_GetAlarmThread, &Actor::EventGetAlarmThread }, + {&EV_Actor_SetSoundAwareness, &Actor::EventSetSoundAwareness }, + {&EV_Actor_SetSoundAwareness2, &Actor::EventSetSoundAwareness }, + {&EV_Actor_GetSoundAwareness, &Actor::EventGetSoundAwareness }, + {&EV_Actor_SetGrenadeAwareness, &Actor::EventSetGrenadeAwareness }, + {&EV_Actor_SetGrenadeAwareness2, &Actor::EventSetGrenadeAwareness }, + {&EV_Actor_GetGrenadeAwareness, &Actor::EventGetGrenadeAwareness }, + {&EV_Actor_SetTurret, &Actor::EventSetTurret }, + {&EV_Actor_SetTurret2, &Actor::EventSetTurret }, + {&EV_Actor_GetTurret, &Actor::EventGetTurret }, + {&EV_Actor_AttachGrenade, &Actor::Grenade_EventAttach }, + {&EV_Actor_DetachGrenade, &Actor::Grenade_EventDetach }, + {&EV_Actor_FireGrenade, &Actor::Grenade_EventFire }, + {&EV_Actor_EnableEnemy, &Actor::EventEnableEnemy }, + {&EV_Actor_EnablePain, &Actor::EventEnablePain }, + {&EV_Activate, &Actor::EventActivate }, + {&EV_Actor_GetAmmoGrenade, &Actor::EventGetAmmoGrenade }, + {&EV_Actor_SetAmmoGrenade, &Actor::EventSetAmmoGrenade }, + {&EV_Actor_SetAmmoGrenade2, &Actor::EventSetAmmoGrenade }, + {&EV_Actor_GetMood, &Actor::EventGetMood }, + {&EV_Actor_SetMood, &Actor::EventSetMood }, + {&EV_Actor_ShareEnemy, &Actor::EventShareEnemy }, + {&EV_Actor_ShareGrenade, &Actor::EventShareGrenade }, + {&EV_Actor_InterruptPoint, &Actor::EventInterruptPoint }, + // Added in 2.0 + //==== + {&EV_Actor_GetVisibilityThreshold, &Actor::EventGetVisibilityThreshold }, + {&EV_Actor_SetVisibilityThreshold, &Actor::EventSetVisibilityThreshold }, + {&EV_Actor_SetVisibilityThreshold2, &Actor::EventSetVisibilityThreshold }, + {&EV_Actor_SetDefaultVisibilityThreshold, &Actor::EventSetDefaultVisibilityThreshold}, + {&EV_Actor_GetSuppressChance, &Actor::EventGetSuppressChance }, + {&EV_Actor_SetSuppressChance, &Actor::EventSetSuppressChance }, + {&EV_Actor_SetSuppressChance2, &Actor::EventSetSuppressChance }, + //==== + {&EV_Actor_GetPainHandler, &Actor::EventGetPainHandler }, + {&EV_Actor_SetPainHandler, &Actor::EventSetPainHandler }, + {&EV_Actor_GetDeathHandler, &Actor::EventGetDeathHandler }, + {&EV_Actor_SetDeathHandler, &Actor::EventSetDeathHandler }, + {&EV_Actor_GetAttackHandler, &Actor::EventGetAttackHandler }, + {&EV_Actor_SetAttackHandler, &Actor::EventSetAttackHandler }, + {&EV_Actor_SetHeadModel, &Actor::EventSetHeadModel }, + {&EV_Actor_GetHeadModel, &Actor::EventGetHeadModel }, + {&EV_Actor_SetHeadSkin, &Actor::EventSetHeadSkin }, + {&EV_Actor_GetHeadSkin, &Actor::EventGetHeadSkin }, + {&EV_Actor_SetNoIdle, &Actor::EventSetNoIdle }, + {&EV_Actor_GetNoIdle, &Actor::EventGetNoIdle }, + {&EV_Actor_GetEnemy, &Actor::EventGetEnemy }, + {&EV_Actor_GetMaxNoticeTimeScale, &Actor::EventGetMaxNoticeTimeScale }, + {&EV_Actor_SetMaxNoticeTimeScale, &Actor::EventSetMaxNoticeTimeScale }, + {&EV_Actor_SetMaxNoticeTimeScale2, &Actor::EventSetMaxNoticeTimeScale }, + {&EV_Actor_GetFixedLeash, &Actor::EventGetFixedLeash }, + {&EV_Actor_SetFixedLeash, &Actor::EventSetFixedLeash }, + {&EV_Actor_SetFixedLeash2, &Actor::EventSetFixedLeash }, + {&EV_Actor_Holster, &Actor::EventHolster }, + {&EV_Actor_Unholster, &Actor::EventUnholster }, + {&EV_SoundDone, &Actor::EventSoundDone }, + {&EV_Sound, &Actor::EventSound }, + {&EV_Actor_IsEnemyVisible, &Actor::EventIsEnemyVisible }, + {&EV_Actor_GetEnemyVisibleChangeTime, &Actor::EventGetEnemyVisibleChangeTime }, + {&EV_Actor_GetLastEnemyVisibleTime, &Actor::EventGetLastEnemyVisibleTime }, + {&EV_Actor_SetFallHeight, &Actor::EventSetFallHeight }, + {&EV_Actor_GetFallHeight, &Actor::EventGetFallHeight }, + {&EV_Actor_CanMoveTo, &Actor::EventCanMoveTo }, + {&EV_Actor_MoveDir, &Actor::EventMoveDir }, + {&EV_Actor_IntervalDir, &Actor::EventIntervalDir }, + {&EV_Actor_ResetLeash, &Actor::EventResetLeash }, + {&EV_Actor_Tether, &Actor::EventTether }, + {&EV_Actor_GetThinkState, &Actor::EventGetThinkState }, + {&EV_Actor_GetEnemyShareRange, &Actor::EventGetEnemyShareRange }, + {&EV_Actor_SetEnemyShareRange, &Actor::EventSetEnemyShareRange }, + {&EV_Actor_SetEnemyShareRange2, &Actor::EventSetEnemyShareRange }, + {&EV_Actor_GetVoiceType, &Actor::GetVoiceType }, + {&EV_Actor_SetVoiceType, &Actor::SetVoiceType }, + {&EV_Actor_SetVoiceType2, &Actor::SetVoiceType }, + {&EV_Remove, &Actor::Remove }, + {&EV_Delete, &Actor::Remove }, + {&EV_ScriptRemove, &Actor::Remove }, + {&EV_Actor_KickDir, &Actor::EventGetKickDir }, + {&EV_Actor_GetNoLongPain, &Actor::EventGetNoLongPain }, + {&EV_Actor_SetNoLongPain, &Actor::EventSetNoLongPain }, + {&EV_Actor_SetNoLongPain2, &Actor::EventSetNoLongPain }, + {&EV_Actor_GetFavoriteEnemy, &Actor::EventGetFavoriteEnemy }, + {&EV_Actor_SetFavoriteEnemy, &Actor::EventSetFavoriteEnemy }, + {&EV_Actor_SetFavoriteEnemy2, &Actor::EventSetFavoriteEnemy }, + {&EV_Actor_GetMumble, &Actor::EventGetMumble }, + {&EV_Actor_SetMumble, &Actor::EventSetMumble }, + {&EV_Actor_SetMumble2, &Actor::EventSetMumble }, + // Removed in 2.0 + //==== + //{&EV_Actor_GetBreathSteam, &Actor::EventGetBreathSteam }, + //{&EV_Actor_SetBreathSteam, &Actor::EventSetBreathSteam }, + //{&EV_Actor_SetBreathSteam2, &Actor::EventSetBreathSteam }, + //==== + {&EV_Actor_CalcGrenadeToss, &Actor::EventCalcGrenadeToss }, + {&EV_Actor_CalcGrenadeToss2, &Actor::EventCalcGrenadeToss2 }, + {&EV_Actor_GetNoSurprise, &Actor::EventGetNoSurprise }, + {&EV_Actor_SetNoSurprise, &Actor::EventSetNoSurprise }, + {&EV_Actor_SetNoSurprise2, &Actor::EventSetNoSurprise }, + {&EV_Actor_GetSilent, &Actor::EventGetSilent }, + {&EV_Actor_SetSilent, &Actor::EventSetSilent }, + {&EV_Actor_SetSilent2, &Actor::EventSetSilent }, + {&EV_Actor_GetAvoidPlayer, &Actor::EventGetAvoidPlayer }, + {&EV_Actor_SetAvoidPlayer, &Actor::EventSetAvoidPlayer }, + {&EV_Actor_SetAvoidPlayer2, &Actor::EventSetAvoidPlayer }, + {&EV_Actor_SetMoveDoneRadius, &Actor::EventSetMoveDoneRadius }, + {&EV_Actor_GetMoveDoneRadius, &Actor::EventGetMoveDoneRadius }, + {&EV_Actor_BeDead, &Actor::EventBeDead }, + {&EV_Actor_GetLookAroundAngle, &Actor::EventGetLookAroundAngle }, + {&EV_Actor_SetLookAroundAngle, &Actor::EventSetLookAroundAngle }, + {&EV_Actor_SetLookAroundAngle2, &Actor::EventSetLookAroundAngle }, + {&EV_Actor_HasCompleteLookahead, &Actor::EventHasCompleteLookahead }, + {&EV_Actor_PathDist, &Actor::EventPathDist }, + {&EV_Actor_CanShootEnemyFrom, &Actor::EventCanShootEnemyFrom }, + {&EV_Actor_CanShoot, &Actor::EventCanShoot }, + {&EV_Actor_GetInReload, &Actor::EventGetInReload }, + {&EV_Actor_SetInReload, &Actor::EventSetInReload }, + {&EV_Actor_SetReloadCover, &Actor::EventSetReloadCover }, + {&EV_Actor_BreakSpecial, &Actor::EventBreakSpecial }, + {&EV_Actor_SetBalconyHeight, &Actor::EventSetBalconyHeight }, + {&EV_Actor_SetBalconyHeight2, &Actor::EventSetBalconyHeight }, + {&EV_Actor_GetBalconyHeight, &Actor::EventGetBalconyHeight }, + // Removed in 2.0 + //==== + //{&EV_CanSee, &Actor::CanSee }, + //==== + // Added in 2.0 + //==== + {&EV_Actor_SetIgnoreBadPlace, &Actor::EventSetIgnoreBadPlace }, + {&EV_Actor_SetIgnoreBadPlace2, &Actor::EventSetIgnoreBadPlace }, + {&EV_Actor_GetIgnoreBadPlace, &Actor::EventGetIgnoreBadPlace }, + {&EV_Actor_FindEnemy, &Actor::EventFindEnemy }, + {&EV_Actor_EnableEnemySwitch, &Actor::EventEnableEnemySwitch }, + {&EV_Actor_DisableEnemySwitch, &Actor::EventDisableEnemySwitch }, + {&EV_Actor_SetRunAnimRate, &Actor::EventSetRunAnimRate }, + {&EV_Actor_SetRunAnimRate2, &Actor::EventSetRunAnimRate }, + {&EV_Actor_GetRunAnimRate, &Actor::EventGetRunAnimRate }, + //==== + // Added in 2.30 + //==== + {&EV_Stop, &Actor::Landed }, + {&EV_Actor_SetNationality, &Actor::SetNationality }, + {&EV_Actor_SetNationality2, &Actor::SetNationality }, + {&EV_Actor_GetNationality, &Actor::GetNationality }, + {&EV_Actor_WriteStats, &Actor::EventWriteStats }, + {&EV_Actor_CuriousOff, &Actor::EventCuriousOff }, + {&EV_Actor_CuriousOn, &Actor::EventCuriousOn }, + //==== + {NULL, NULL } }; Actor::GlobalFuncs_t Actor::GlobalFuncs[NUM_THINKS]; -const_str Actor::m_csThinkNames[NUM_THINKS] = { - STRING_VOID, - STRING_TURRET, - STRING_COVER, - STRING_PATROL, - STRING_RUNNER, - STRING_PAIN, - STRING_KILLED, - STRING_MOVETO, - STRING_IDLE, - STRING_CURIOUS, - STRING_DISGUISE_SALUTE, - STRING_DISGUISE_SENTRY, - STRING_DISGUISE_OFFICER, - STRING_DISGUISE_ROVER, - STRING_DISGUISE_NONE, - STRING_ALARM, - STRING_GRENADE, - STRING_MACHINEGUNNER, - STRING_DOG_IDLE, - STRING_DOG_ATTACK, - STRING_DOG_CURIOUS, - STRING_DOG_GRENADE, - STRING_ANIM, - STRING_ANIM_CURIOUS, - STRING_AIM, - STRING_BALCONY_IDLE, - STRING_BALCONY_CURIOUS, - STRING_BALCONY_ATTACK, - STRING_BALCONY_DISGUISE, - STRING_BALCONY_GRENADE, - STRING_BALCONY_PAIN, - STRING_BALCONY_KILLED, - STRING_WEAPONLESS, - STRING_NOCLIP, - STRING_DEAD +const_str Actor::m_csThinkNames[NUM_THINKS] = { + STRING_VOID, + STRING_TURRET, + STRING_COVER, + STRING_PATROL, + STRING_RUNNER, + STRING_PAIN, + STRING_KILLED, + STRING_MOVETO, + STRING_IDLE, + STRING_CURIOUS, + STRING_DISGUISE_SALUTE, + STRING_DISGUISE_SENTRY, + STRING_DISGUISE_OFFICER, + STRING_DISGUISE_ROVER, + STRING_DISGUISE_NONE, + STRING_ALARM, + STRING_GRENADE, + STRING_MACHINEGUNNER, + STRING_DOG_IDLE, + STRING_DOG_ATTACK, + STRING_DOG_CURIOUS, + STRING_DOG_GRENADE, + STRING_ANIM, + STRING_ANIM_CURIOUS, + STRING_AIM, + STRING_BALCONY_IDLE, + STRING_BALCONY_CURIOUS, + STRING_BALCONY_ATTACK, + STRING_BALCONY_DISGUISE, + STRING_BALCONY_GRENADE, + STRING_BALCONY_PAIN, + STRING_BALCONY_KILLED, + STRING_WEAPONLESS, + STRING_NOCLIP, + STRING_DEAD, + // Added in 2.0 + STRING_BADPLACE, + // Added in 2.30 + STRING_RUNANDSHOOT }; -const_str Actor::m_csThinkStateNames[ NUM_THINKSTATES ] = { - STRING_VOID, - STRING_IDLE, - STRING_PAIN, - STRING_KILLED, - STRING_ATTACK, - STRING_CURIOUS, - STRING_DISGUISE, - STRING_GRENADE, - STRING_NOCLIP +const_str Actor::m_csThinkStateNames[NUM_THINKSTATES] = { + STRING_VOID, + STRING_IDLE, + STRING_PAIN, + STRING_KILLED, + STRING_ATTACK, + STRING_CURIOUS, + STRING_DISGUISE, + STRING_GRENADE, + STRING_BADPLACE, // Added in 2.0 + STRING_NOCLIP }; -SafePtr< Actor > Actor::mBodyQueue[MAX_BODYQUEUE]; -int Actor::mCurBody; - +SafePtr Actor::mBodyQueue[MAX_BODYQUEUE]; +int Actor::mCurBody; /* =============== @@ -2558,3011 +2750,391 @@ Constructor =============== */ Actor::Actor() + : mVoiceType(-1) { - entflags |= EF_ACTOR; + entflags |= ECF_ACTOR; - if( LoadingSavegame ) - { - return; - } + m_pszDebugState = ""; + m_pFallPath = NULL; + m_iOriginTime = -1; - edict->s.eType = ET_MODELANIM; - edict->r.svFlags |= SVF_USE_CURRENT_ORIGIN; - edict->r.ownerNum = ENTITYNUM_NONE; - edict->clipmask = MASK_MONSTERSOLID; - setMoveType( MOVETYPE_WALK ); - mass = 175; - flags |= FL_THINK; - flags &= ~FL_ANIMATE; - setContentsSolid(); - setSolidType( SOLID_BBOX ); - m_fFov = 90.0f; - takedamage = DAMAGE_AIM; - m_fFovDot = cos( 0.5 * m_fFov * M_PI / 180 ); - m_eAnimMode = 0; - Anim_Emotion(EMOTION_NONE); - m_bDoPhysics = true; - path_failed_time = 0; - health = 100; - max_health = 100; - m_fAngleYawSpeed = 360; - m_fHeadMaxTurnSpeed = 520; - m_bHeadAnglesAchieved = true; - VectorClear( m_vHeadDesiredAngles ); - m_fLUpperArmTurnSpeed = 360; - m_bLUpperArmAnglesAchieved = true; - VectorClear( m_vLUpperArmDesiredAngles ); - m_fTorsoMaxTurnSpeed = 120; - m_fTorsoCurrentTurnSpeed = 0; - m_bTorsoAnglesAchieved = true; - VectorClear( m_vTorsoDesiredAngles ); - m_pLookEntity = NULL; - m_pPointEntity = NULL; - m_pTurnEntity = NULL; - VectorClear( edict->s.eyeVector ); - m_bDoAI = true; - m_bTurretNoInitialCover = false; - m_bThink = false; - m_bAutoAvoidPlayer = true; - m_fHearing = 2048; - m_PainTime = 0; - m_fSight = world->m_fAIVisionDistance; - m_bNoLongPain = false; - hit_obstacle_time = 0; - VectorClear2D( obstacle_vel ); - m_bLockThinkState = false; - InitThinkStates(); - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - m_fMinDistance = 128; - m_fMinDistanceSquared = Square(128); - m_fMaxDistance = 1024; - m_fMaxDistanceSquared = Square(1024); - m_fLeash = 512; - m_fLeashSquared = Square(512); - m_iEyeUpdateTime = level.inttime; - if( m_iEyeUpdateTime < 1000 ) - m_iEyeUpdateTime = 1000; - m_iEyeUpdateTime += rand() % 100 + 100; - m_vIntervalDir = vec_zero; - m_iIntervalDirTime = 0; - edict->r.lastNetTime = -10000000; - m_iEnemyCheckTime = 0; - m_iEnemyChangeTime = 0; - m_iEnemyVisibleCheckTime = 0; - m_bNewEnemy = false; - m_bEnemyIsDisguised = false; - m_bEnemyVisible = false; - m_iEnemyVisibleChangeTime = 0; - m_iLastEnemyVisibleTime = 0; - m_iEnemyFovCheckTime = 0; - m_iEnemyFovChangeTime = 0; - m_bEnemyInFOV = false; - m_iIgnoreSoundsMask = 0; - m_State = -1; - m_iStateTime = 0; - m_iGunPositionCheckTime = 0; - m_vLastEnemyPos = vec_origin; - m_iLastEnemyPosChangeTime = 0; - m_vScriptGoal = vec_origin; - m_iNextWatchStepTime = 0; - m_iCuriousTime = 0; - m_iCuriousLevel = 0; - SetCuriousAnimHint(0); - m_bScriptGoalValid = false; - m_bNoSurprise = false; - memset( &m_pPotentialCoverNode, 0, sizeof( m_pPotentialCoverNode ) ); - m_iPotentialCoverCount = 0; - m_pCoverNode = NULL; - m_csSpecialAttack = STRING_NULL; - m_sCurrentPathNodeIndex = -1; - m_iDisguiseLevel = 1; - m_iNextDisguiseTime = 1; - m_iDisguisePeriod = 30000; - m_bNeedReload = false; - m_bInReload = false; - m_bFaceEnemy = true; - m_fMaxDisguiseDistSquared = 256 * 256; - m_patrolCurrentNode = NULL; - m_csPatrolCurrentAnim = STRING_ANIM_RUN_SCR; - m_iSquadStandTime = 0; - m_bPatrolWaitTrigger = false; - m_fInterval = 128; - m_aimNode = NULL; - m_vHome = vec_origin; - m_bFixedLeash = false; - m_pTetherEnt = NULL; - m_pGrenade = NULL; - m_vGrenadePos = vec_origin; - m_eGrenadeMode = AI_GREN_TOSS_NONE; - m_iFirstGrenadeTime = 0; - m_bGrenadeBounced = false; - m_vGrenadeVel = vec_zero; - m_vKickDir = vec_zero; - m_fNoticeTimeScale = 1.0f; - m_iCanShootCheckTime = 0; - m_csAnimScript = STRING_ANIM_IDLE_SCR; - m_fSoundAwareness = 100; - m_fGrenadeAwareness = 20; - m_fMaxNoticeTimeScale = 1.0f; - m_bCanShootEnemy = false; - m_bEnableEnemy = true; - m_bDesiredEnableEnemy = true; - m_bEnablePain = true; - m_bAnimScriptSet = false; - m_AnimMode = 0; - m_csAnimName = STRING_EMPTY; - m_csSayAnim = STRING_EMPTY; - m_csUpperAnim = STRING_EMPTY; - m_fDfwRequestedYaw = 0; - m_fDfwDerivedYaw = 0; - m_vDfwPos = vec_zero; - m_fDfwTime = 0; - m_AlarmNode = NULL; - m_csHeadSkin = STRING_EMPTY; - m_iWallDodgeTimeout = 0; - m_csHeadModel = STRING_EMPTY; - m_csLoadOut = STRING_EMPTY; - m_iRunHomeTime = 0; - m_iLookFlags = 0; - m_csWeapon = STRING_EMPTY; - m_eDontFaceWallMode = 0; - m_WallDir = 0; - VectorClear2D( m_PrevObstacleNormal ); - m_bNoIdleAfterAnim = false; - m_fMaxShareDistSquared = 0; - m_bBreathSteam = false; - m_fMoveDoneRadiusSquared = 0; - m_bForceAttackPlayer = false; - m_iNextLookTime = 0; - m_fLookAroundFov = 45; - m_bHasDesiredLookDest = false; - m_bHasDesiredLookAngles = false; - m_iLastFaceDecideTime = 0; - m_iOriginTime = -1; - m_fTurnDoneError = 0; - m_fBalconyHeight = 128; - m_bNoPlayerCollision = false; - m_pFallPath = NULL; - for( int i = 0; i < MAX_ORIGIN_HISTORY; i++ ) - { - VectorClear2D( m_vOriginHistory[ i ] ); - } - m_bAnimating = false; - m_iCurrentHistory = 0; - m_bDog = false; - m_bBecomeRunner = false; - mVoiceType = -1; + if (LoadingSavegame) { + return; + } + + m_PainState = 500; + m_iEnemyShowPapersTime = 0; + m_eGrenadeState = eGrenadeState::AI_GRENSTATE_FLEE; + + edict->s.eType = ET_MODELANIM; + edict->r.svFlags |= SVF_MONSTER; + edict->r.ownerNum = ENTITYNUM_NONE; + edict->clipmask = MASK_MONSTERSOLID; + setMoveType(MOVETYPE_WALK); + + mass = 175; + flags |= FL_THINK; + flags &= ~FL_ANIMATE; + + setContentsSolid(); + setSolidType(SOLID_BBOX); + + m_fFov = 90.0f; + takedamage = DAMAGE_AIM; + m_fFovDot = cos(DEG2RAD(m_fFov / 2.0)); + + m_eAnimMode = ANIM_MODE_NONE; + Anim_Emotion(EMOTION_NONE); + + m_bDoPhysics = true; + path_failed_time = 0; + + health = 100; + max_health = 100; + + m_fAngleYawSpeed = 360; + m_fHeadMaxTurnSpeed = 520; + m_bHeadAnglesAchieved = true; + VectorClear(m_vHeadDesiredAngles); + + m_fLUpperArmTurnSpeed = 360; + m_bLUpperArmAnglesAchieved = true; + VectorClear(m_vLUpperArmDesiredAngles); + + m_fTorsoMaxTurnSpeed = 120; + m_fTorsoCurrentTurnSpeed = 0; + m_bTorsoAnglesAchieved = true; + VectorClear(m_vTorsoDesiredAngles); + + m_pLookEntity = NULL; + m_pPointEntity = NULL; + m_pTurnEntity = NULL; + + VectorClear(edict->s.eyeVector); + + m_bDoAI = true; + m_bTurretNoInitialCover = false; + m_bThink = false; + m_fSight = world->m_fAIVisionDistance; + m_fHearing = 2048; + m_PainTime = 0; + m_bNoLongPain = false; + hit_obstacle_time = 0; + VectorClear2D(obstacle_vel); + + m_bLockThinkState = false; + m_bAutoAvoidPlayer = true; + m_bIsCurious = true; + + InitThinkStates(); + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + + m_fMinDistance = 128; + m_fMinDistanceSquared = Square(m_fMinDistance); + m_fMaxDistance = 1024; + m_fMaxDistanceSquared = Square(m_fMaxDistance); + m_fLeash = 512; + m_fLeashSquared = Square(m_fLeash); + + m_iEyeUpdateTime = level.inttime; + if (m_iEyeUpdateTime < 1000) { + m_iEyeUpdateTime = 1000; + } + m_iEyeUpdateTime += rand() % 100 + 100; + + m_vIntervalDir = vec_zero; + m_iIntervalDirTime = 0; + edict->r.lastNetTime = -10000000; + + m_bNewEnemy = false; + m_iEnemyCheckTime = 0; + m_iEnemyChangeTime = 0; + m_bEnemyIsDisguised = false; + m_bEnemyVisible = false; + m_iEnemyVisibleCheckTime = 0; + m_iEnemyVisibleChangeTime = 0; + m_iLastEnemyVisibleTime = 0; + m_fVisibilityAlpha = 0; + m_fVisibilityThreshold = 0.5f; + m_bHasVisibilityThreshold = false; + + m_bEnemyInFOV = false; + m_iEnemyFovCheckTime = 0; + m_iEnemyFovChangeTime = 0; + m_iIgnoreSoundsMask = 0; + + m_State = -1; + m_iStateTime = 0; + + m_iGunPositionCheckTime = 0; + m_vLastEnemyPos = vec3_origin; + m_iLastEnemyPosChangeTime = 0; + m_vScriptGoal = vec3_origin; + m_bScriptGoalValid = false; + m_iNextWatchStepTime = 0; + + m_iCuriousTime = 0; + m_iCuriousLevel = 0; + SetCuriousAnimHint(0); + + m_bNoSurprise = false; + memset(&m_pPotentialCoverNode, 0, sizeof(m_pPotentialCoverNode)); + m_iPotentialCoverCount = 0; + m_pCoverNode = NULL; + + m_csSpecialAttack = STRING_NULL; + m_bNeedReload = false; + m_bInReload = false; + m_bFaceEnemy = true; + m_sCurrentPathNodeIndex = -1; + + m_iNextDisguiseTime = 1; + m_iDisguisePeriod = 30000; + m_fMaxDisguiseDistSquared = Square(256); + m_iDisguiseLevel = 1; + + m_patrolCurrentNode = NULL; + m_csPatrolCurrentAnim = STRING_ANIM_RUN_SCR; + m_bPatrolWaitTrigger = false; + m_fInterval = 128; + m_iSquadStandTime = 0; + m_aimNode = NULL; + + m_vHome = vec3_origin; + m_bFixedLeash = false; + m_pTetherEnt = NULL; + + m_pGrenade = NULL; + m_vGrenadePos = vec3_origin; + m_iFirstGrenadeTime = 0; + m_bGrenadeBounced = false; + m_eGrenadeMode = AI_GREN_TOSS_NONE; + m_vGrenadeVel = vec_zero; + m_vKickDir = vec_zero; + + m_fSoundAwareness = 100; + m_fGrenadeAwareness = 20; + m_fMaxNoticeTimeScale = 1.0f; + m_fNoticeTimeScale = 1.0f; + + m_iCanShootCheckTime = 0; + m_bCanShootEnemy = false; + m_bEnableEnemy = true; + m_bDesiredEnableEnemy = true; + m_bEnablePain = true; + + m_csAnimScript = STRING_ANIM_IDLE_SCR; + m_bAnimScriptSet = false; + m_AnimMode = ANIM_MODE_NORMAL; + m_csAnimName = STRING_EMPTY; + m_csSayAnim = STRING_EMPTY; + m_csUpperAnim = STRING_EMPTY; + + m_fRunAnimRate = 1; + m_fDfwRequestedYaw = 0; + m_fDfwDerivedYaw = 0; + m_vDfwPos = vec_zero; + m_fDfwTime = 0; + + m_AlarmNode = NULL; + + m_iWallDodgeTimeout = 0; + m_WallDir = 0; + VectorClear2D(m_PrevObstacleNormal); + + m_csHeadModel = STRING_EMPTY; + m_csHeadSkin = STRING_EMPTY; + m_bNoIdleAfterAnim = false; + m_csWeapon = STRING_EMPTY; + m_csLoadOut = STRING_EMPTY; + + m_fMaxShareDistSquared = 0; + m_iRunHomeTime = 0; + m_iSuppressChance = 50; + + m_bBreathSteam = false; + + m_fMoveDoneRadiusSquared = 0; + + m_bForceAttackPlayer = false; + + m_iLookFlags = 0; + m_iNextLookTime = 0; + m_fLookAroundFov = 45; + m_bHasDesiredLookDest = false; + m_bHasDesiredLookAngles = false; + + m_eDontFaceWallMode = 0; + m_iLastFaceDecideTime = 0; + m_iOriginTime = -1; + m_fTurnDoneError = 0; + + m_fBalconyHeight = 128; + m_bNoPlayerCollision = false; + for (int i = 0; i < MAX_ORIGIN_HISTORY; i++) { + VectorClear2D(m_vOriginHistory[i]); + } + m_iCurrentHistory = 0; + m_bAnimating = false; + m_bIgnoreBadPlace = false; + m_iBadPlaceIndex = 0; + m_bBecomeRunner = false; + m_bEnemySwitch = true; + m_iNationality = ACTOR_NATIONALITY_DEFAULT; + + if (g_aistats) { + PostEvent(EV_Actor_WriteStats, 1.0); + } + + mVoiceType = -1; + + // + // Added in OPM + // The variable isn't set in original + // + m_bSilent = false; + m_bMumble = true; } /* =============== -Actor::ShowInfo +Actor::~Actor -Prints basic actor information. +Destructor =============== */ -void Actor::ShowInfo - ( - void - ) +Actor::~Actor() { - Com_Printf( "-------------------------------------------------------------------------------\n" ); - Com_Printf( "Info for Actor:\n" ); - Com_Printf( "Current think type: %s %s\n", ThinkName().c_str(), ThinkStateName().c_str() ); - Com_Printf( "leash: %f\n", m_fLeash ); - Com_Printf( "mindist: %f\n", m_fMinDistance ); - Com_Printf( "maxdist: %f\n", m_fMaxDistance ); + EndStates(); + ClearPatrolCurrentNode(); + ClearAimNode(); + ClearLookEntity(); + ClearPointEntity(); + ClearTurnEntity(); - GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ]; - if( func->ShowInfo ) - ( this->*func->ShowInfo )( ); - - Com_Printf( "-------------------------------------------------------------------------------\n" ); -} - -/* -=============== -Actor::MoveTo - -Move actor to specific location/listener with specific animation. -=============== -*/ -void Actor::MoveTo - ( - Event *ev - ) -{ - m_csPatrolCurrentAnim = ev->GetConstString( 1 ); - - if( ev->IsVectorAt( 2 ) ) - { - Vector vec = ev->GetVector( 2 ); - SetPatrolCurrentNode( vec ); - } - else - { - SetPatrolCurrentNode( ev->GetListener( 2 ) ); - } - - if( m_patrolCurrentNode ) - { - m_vScriptGoal = origin; - m_bScriptGoalValid = true; - } - - SetThinkIdle(THINK_RUNNER); -} - -/* -=============== -Actor::WalkTo - -Walk to specific location. -=============== -*/ -void Actor::WalkTo - ( - Event *ev - ) -{ - Event event = EV_Listener_ExecuteScript; - event.AddConstString( STRING_GLOBAL_WALKTO_SCR ); - event.AddValue( ev->GetValue( 1 ) ); - ExecuteScript( &event ); -} - -/* -=============== -Actor::RunTo - -Run to specific location. -=============== -*/ -void Actor::RunTo - ( - Event *ev - ) -{ - Event event = EV_Listener_ExecuteScript; - event.AddConstString( STRING_GLOBAL_RUNTO_SCR ); - event.AddValue( ev->GetValue( 1 ) ); - ExecuteScript( &event ); -} - -/* -=============== -Actor::CrouchTo - -Crouch to specific location. -=============== -*/ -void Actor::CrouchTo - ( - Event *ev - ) -{ - Event event = EV_Listener_ExecuteScript; - event.AddConstString( STRING_GLOBAL_CROUCHTO_SCR ); - event.AddValue( ev->GetValue( 1 ) ); - ExecuteScript( &event ); -} - -/* -=============== -Actor::CrawlTo - -Crawl to specific location. -=============== -*/ -void Actor::CrawlTo - ( - Event *ev - ) -{ - Event event = EV_Listener_ExecuteScript; - event.AddConstString( STRING_GLOBAL_CRAWLTO_SCR ); - event.AddValue( ev->GetValue( 1 ) ); - ExecuteScript( &event ); -} - -/* -=============== -Actor::AimAt - -Aim at specified target. -=============== -*/ -void Actor::AimAt - ( - Event *ev - ) -{ - - if( ev->IsVectorAt( 1 ) ) - { - Vector orig = ev->GetVector(1); - if (m_aimNode) - { - if (m_aimNode->IsSubclassOfTempWaypoint()) - { - delete m_aimNode; - } - m_aimNode = NULL; - } - TempWaypoint * twp = new TempWaypoint; - m_aimNode = twp; - m_aimNode->setOrigin(orig); - } - else - { - SetAimNode(ev->GetListener(1)); - } - - SetThinkIdle( m_aimNode != NULL ? THINK_AIM : THINK_IDLE); -} - -/* -=============== -Actor::DefaultRestart - -Default restart of current think state. -=============== -*/ -void Actor::DefaultRestart - ( - void - ) -{ - EndState( m_ThinkLevel ); - BeginState(); -} - -/* -=============== -Actor::SuspendState - -Suspend current think state. -=============== -*/ -void Actor::SuspendState - ( - void - ) -{ - GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ]; - - if( func->SuspendState ) - ( this->*func->SuspendState )( ); -} - -/* -=============== -Actor::ResumeState - -Resume current think state. -=============== -*/ -void Actor::ResumeState - ( - void - ) -{ - GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ]; - - if( func->ResumeState ) - ( this->*func->ResumeState )( ); -} - -/* -=============== -Actor::BeginState - -Begin current think state. -=============== -*/ -void Actor::BeginState - ( - void - ) -{ - m_Think[ m_ThinkLevel ] = m_ThinkMap[ m_ThinkState ]; - - GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ]; - - if( func->BeginState ) - ( this->*func->BeginState )(); - - m_Think[ m_ThinkLevel ] = m_ThinkMap[ m_ThinkState ]; -} - -/* -=============== -Actor::EndState - -End current think state. -=============== -*/ -void Actor::EndState - ( - int level - ) -{ - GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ level ] ]; - - m_Think[ level ] = THINK_VOID; - - if( func->EndState ) - ( this->*func->EndState )(); - - if( m_pAnimThread ) - m_pAnimThread->AbortRegistration( STRING_EMPTY, this ); -} - -/* -=============== -Actor::RestartState - -Restart current think state. -=============== -*/ -void Actor::RestartState - ( - void - ) -{ - GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ]; - - if( func->RestartState) - ( this->*func->RestartState)(); + entflags &= ~ECF_ACTOR; } /* =============== Actor::setContentsSolid - =============== */ -void Actor::setContentsSolid - ( - void - ) +void Actor::setContentsSolid(void) { - setContents(CONTENTS_NOBOTCLIP); + setContents(CONTENTS_NOBOTCLIP); } /* =============== -Actor::InitThinkStates - -Initialize think related stuff. +Actor::EndStates =============== */ -void Actor::InitThinkStates - ( - void - ) +void Actor::EndStates(void) { - for (size_t i = 0; i < NUM_THINKSTATES; i++) - { - m_ThinkMap[i] = THINK_VOID; - } - for (size_t i = 0; i < NUM_THINKLEVELS; i++) - { - m_Think[i] = THINK_VOID; - m_ThinkStates[i] = THINKSTATE_VOID; - } - - - m_ThinkMap[THINKSTATE_VOID] = THINK_VOID; - m_ThinkMap[THINKSTATE_IDLE] = THINK_IDLE; - m_ThinkMap[THINKSTATE_PAIN] = THINK_PAIN; - m_ThinkMap[THINKSTATE_KILLED] = THINK_KILLED; - m_ThinkMap[THINKSTATE_ATTACK] = THINK_TURRET; - m_ThinkMap[THINKSTATE_CURIOUS] = THINK_CURIOUS; - m_ThinkMap[THINKSTATE_DISGUISE] = THINK_DISGUISE_SALUTE; - m_ThinkMap[THINKSTATE_GRENADE] = THINK_GRENADE; - m_ThinkMap[THINKSTATE_NOCLIP] = THINK_NOCLIP; - - m_ThinkLevel = THINKLEVEL_NORMAL; - m_ThinkState = THINKSTATE_VOID; - m_bDirtyThinkState = false; - + for (int i = 0; i < NUM_THINKLEVELS; i++) { + EndState(i); + } } /* =============== -Actor::UpdateEyeOrigin - -Update eye position. +Actor::ClearStates =============== */ -void Actor::UpdateEyeOrigin - ( - void - ) +void Actor::ClearStates(void) { - Vector eyeTag = vec_zero; - - int currLvlTime = level.inttime; - int currTime = m_iEyeUpdateTime; - - if (currLvlTime > currTime) - { - - m_iEyeUpdateTime = NextUpdateTime(currTime, 100); - - GetTag( "eyes bone", &eyeTag, &m_vEyeDir); - - eyeposition = eyeTag - origin; - - m_vEyeDir[2] = 0.0; - VectorNormalizeFast(m_vEyeDir); - - if (eyeposition[0] < -10.5) - { - eyeposition[0] = -10.5; - } - if (eyeposition[0] > 10.5) - eyeposition[0] = 10.5; - - if (eyeposition[1] < -10.5) - { - eyeposition[1] = -10.5; - } - if (eyeposition[1] > 10.5) - eyeposition[1] = 10.5; - - if (eyeposition[2] < 4.5) - { - eyeposition[2] = 4.5; - } - if (eyeposition[2] > 89.5) - eyeposition[2] = 89.5; - - } + for (int i = 0; i < NUM_THINKSTATES; i++) { + SetThink((eThinkState)i, THINK_VOID); + } } /* =============== -Actor::RequireThink - -Do I need to think ? +Actor::ResolveVoiceType =============== */ -bool Actor::RequireThink - ( - void - ) +void Actor::ResolveVoiceType(void) { - if(G_GetEntity(0)) - return ( level.inttime < edict->r.lastNetTime + 60000 ); - else - return false; - + char validVoice[128]; + + if (mVoiceType != -1) { + if (m_Team == TEAM_AMERICAN) { + for (int i = 0; i < 3; i++) { + if (gAmericanVoices[i][0] == mVoiceType) { + return; + } + } + + validVoice[0] = '\0'; + for (int i = 0; i < 3; i++) { + strcat(validVoice, gAmericanVoices[i]); + strcat(validVoice, " "); + } + Com_Printf("ERROR: Bad voice type %c. Valid American voicetypes are: %s\n", mVoiceType, validVoice); + } else { + for (int i = 0; i < 3; i++) { + if (gGermanVoices[i][0] == mVoiceType) { + return; + } + } + + validVoice[0] = '\0'; + for (int i = 0; i < 3; i++) { + strcat(validVoice, gGermanVoices[i]); + strcat(validVoice, " "); + } + Com_Printf("ERROR: Bad voice type %c. Valid German voicetypes are: %s\n", mVoiceType, validVoice); + } + + mVoiceType = -1; + } + + if (mVoiceType == -1) { + int d = random() * 3.0 * 0.99; + + if (m_Team == TEAM_AMERICAN) { + mVoiceType = gAmericanVoices[d][0]; + } else { + mVoiceType = gGermanVoices[d][0]; + } + } } /* =============== -Actor::UpdateEnemy +Actor::EventStart -Update enemy w.r.t m_iEnemyCheckTime. +Initialize actor. =============== */ -void Actor::UpdateEnemy - ( - int iMaxDirtyTime - ) +void Actor::EventStart(Event *ev) { - if (level.inttime > iMaxDirtyTime + m_iEnemyCheckTime) - UpdateEnemyInternal(); + ResolveVoiceType(); + setSize(MINS, MAXS); //notsure + + droptofloor(16384); + + SetControllerTag(HEAD_TAG, gi.Tag_NumForName(edict->tiki, "Bip01 Head")); + SetControllerTag(TORSO_TAG, gi.Tag_NumForName(edict->tiki, "Bip01")); + SetControllerTag(ARMS_TAG, gi.Tag_NumForName(edict->tiki, "Bip01 L UpperArm")); + + JoinNearbySquads(1024); + + if (level.Spawned()) { + Unregister(STRING_SPAWN); + } } /* =============== -Actor::UpdateEnemyInternal - -Real update enemy. +Actor::ClearEnemies =============== */ -void Actor::UpdateEnemyInternal - ( - void - ) +void Actor::ClearEnemies(void) { - - - for (Sentient *pSent = level.m_HeadSentient[1 - m_Team]; pSent; pSent = pSent->m_NextSentient) - { - m_PotentialEnemies.AddPotentialEnemy(pSent); - } - - m_PotentialEnemies.CheckEnemies(this); - - if (m_Enemy != m_PotentialEnemies.GetCurrentEnemy()) - SetEnemy(m_PotentialEnemies.GetCurrentEnemy(), false); - - m_fNoticeTimeScale += (level.inttime - m_iEnemyCheckTime) / 10000; - - if (m_fNoticeTimeScale > m_fMaxNoticeTimeScale) - m_fNoticeTimeScale = m_fMaxNoticeTimeScale; - - m_iEnemyCheckTime = level.inttime; -} - -/* -=============== -Actor::SetEnemy - -Set current enemy. -=============== -*/ -void Actor::SetEnemy - ( - Sentient *pEnemy, - bool bForceConfirmed - ) -{ - if (pEnemy == m_Enemy) - { - return; - } - - if (m_Enemy) - { - m_Enemy->m_iAttackerCount--; - } - m_bNewEnemy = m_Enemy == NULL; - //delete m_Enemy; - - m_Enemy = pEnemy; - - m_iEnemyChangeTime = level.inttime; - - if (m_Enemy) - { - Event e1(EV_Actor_ShareEnemy); - //FIXME: macro - PostEvent(e1, 0.75); - - if (m_Enemy->m_bHasDisguise) - { - if (level.inttime > m_iEnemyVisibleCheckTime) - { - //this cansee call changes m_bEnemyVisible and m_bEnemyInFOV - //FIXME: macro - CanSee(m_Enemy, 0, 0.828 * world->farplane_distance, false); - } - } - - m_bEnemyIsDisguised = m_Enemy->m_bHasDisguise && (m_Enemy->m_bIsDisguised || !m_bEnemyVisible); - - SetEnemyPos(m_Enemy->origin); - - m_Enemy->m_iAttackerCount++; - - if (bForceConfirmed) - { - m_PotentialEnemies.ConfirmEnemy(this, m_Enemy); - } - } -} - -/* -=============== -Actor::SetEnemyPos - -Update stored enemy position information. -=============== -*/ -void Actor::SetEnemyPos -( - Vector vPos -) -{ - if (m_vLastEnemyPos != vPos) - { - m_iLastEnemyPosChangeTime = level.inttime; - m_vLastEnemyPos = vPos; - mTargetPos = m_vLastEnemyPos; - if (m_Enemy) - { - mTargetPos += m_Enemy->eyeposition; - } - else - { - mTargetPos.z += 88; - } - - if (mTargetPos.z - EyePosition().z < 128) - { - mTargetPos.z -= 16; - } - } -} - -/* -=============== -Actor::ResetBodyQueue - -Clear body queue. -Called upon Level::Cleanup() -=============== -*/ -void Actor::ResetBodyQueue - ( - void - ) -{ - //weird useless loop ? - - for (int i = MAX_BODYQUEUE-1; i >= 0; i--) - { - //do nothing. - } - //mBodyQueue - //this resets curBody, but all the magic happens in AddToBodyQue - mCurBody = 0; -} - -/* -=============== -Actor::AddToBodyQue - -Add this to body queue. -=============== -*/ -void Actor::AddToBodyQue - ( - void - ) -{ - SafePtr lastActor = mBodyQueue[mCurBody + 3]; - - - - if (lastActor) - { - Event ev(EV_Remove); - lastActor->PostEvent(ev, 0); - } - - mBodyQueue[mCurBody] = this; - - //update current body index - mCurBody = (mCurBody + 1) % 5; - -} - -/* -=============== -Actor::GetAntiBunchPoint - -=============== -*/ -Vector Actor::GetAntiBunchPoint - ( - void - ) -{ - int count = 0; - Vector ret = vec_origin; - if (m_pNextSquadMate != this) - { - for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) - { - - Vector dist = origin - pSquadMate->origin; - float distSq = dist * dist; - if (distSq != 0) - { - if (Square(m_fInterval) > distSq) - { - count++; - ret += origin + (dist/sqrt(distSq)) * (m_fInterval - sqrt(distSq)); - } - } - } - - if (count) - { - if (count != 1) - { - ret /= count; - } - } - else - { - ret = origin; - } - } - return ret; -} - -/* -=============== -Actor::InitVoid - -Init void global func -=============== -*/ -void Actor::InitVoid - ( - GlobalFuncs_t *func - ) -{ - func->IsState = &Actor::IsVoidState; -} - -/* -=============== -Actor::DumpCallTrace - -Dump useful debug info. -=============== -*/ -const char *Actor::DumpCallTrace - ( - const char *pszFmt, - ... - ) const -{ - cvar_t *sv_mapname; - tm *ptm; - time_t t; - Vector vPlayer = vec_zero; - char szFile[64]; - int i2; - //int i1; - int i; - char szTemp[65536]; - char szTemp2[1024]; - - va_list va; - - va_start(va, pszFmt); - - sv_mapname = gi.Cvar_Get("mapname", "unknown", 0); - - Player *p = (Player *)G_GetEntity(0); - if (p) - { - vPlayer = p->origin; - } - - i = sprintf( - szTemp, - "map = %s\n" - "time = %i (%i:%02i)\n" - "entnum = %i, targetname = '%s'\n" - "origin = (%g %g %g)\n" - "think = %s, thinkstate = %s\n" - "type_idle = %s\n" - "type_attack = %s\n" - "m_State = %i, m_pszDebugState = %s\n" - "player is at (%g %g %g)\n" - "--------------------------------------\n", - sv_mapname->string, - level.inttime, - level.inttime / 60000, - level.inttime / 1000 - 60 * (level.inttime / 60000), - entnum, - targetname.c_str(), - origin[0], - origin[1], - origin[2], - ThinkName().c_str(), - ThinkStateName().c_str(), - Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_IDLE]]).c_str(), - Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]).c_str(), - m_State, - m_pszDebugState, - vPlayer[0], - vPlayer[1], - vPlayer[2]); - - if (pszFmt) - { - i2 = i + vsprintf(&szTemp[i], pszFmt, va); - } - if (i2 != i) - { - strcpy(&szTemp[i2], "\n--------------------------------------\n"); - } - - t = time(0); - ptm = localtime(&t); - sprintf( - szFile, - "main\\ai_trace_%s_%i_%i_%02i%02i.log", - sv_mapname->string, - ptm->tm_mon + 1, - ptm->tm_mday, - ptm->tm_hour, - ptm->tm_min); - - for (i=0; szFile[i]; i++) - { - if (szFile[i] == '\\' || szFile[i] == '/') - szFile[i] = '_'; - } - sprintf(szTemp2, "Include '%s' in your bug report!", szFile); - //PreAssertMessage: - fprintf(stderr, "IMPORTANT: %s\n", szTemp2); - - va_end(va); - - return ::va( - "\n" - "\t-------------------------- IMPORTANT REMINDER --------------------------\n" - "\n" - "\tinclude '%s' in your bug report! \n" - "\n" - "\t----------------------- END IMPORTANT REMINDER -----------------------\n" - "\n" - "%s", - szFile, - szTemp); -} - - -/* -=============== -Actor::Init - -Initialize global actor variables. -Called from G_InitGame() -=============== -*/ -void Actor::Init - ( - void - ) -{ - g_showinfo = gi.Cvar_Get("g_showinfo", "0", 0); - - for (int i = 0; i < NUM_THINKS; i++) - { - GlobalFuncs[i].ThinkState = NULL; - GlobalFuncs[i].BeginState = NULL; - GlobalFuncs[i].ResumeState = NULL; - GlobalFuncs[i].EndState = NULL; - GlobalFuncs[i].SuspendState = NULL; - GlobalFuncs[i].RestartState = &Actor::DefaultRestart; - GlobalFuncs[i].FinishedAnimation = NULL; - GlobalFuncs[i].PostShoot = NULL; - GlobalFuncs[i].Pain = &Actor::DefaultPain; - GlobalFuncs[i].Killed = &Actor::DefaultKilled; - GlobalFuncs[i].PassesTransitionConditions = NULL; - GlobalFuncs[i].ShowInfo = NULL; - GlobalFuncs[i].ReceiveAIEvent = &Actor::DefaultReceiveAIEvent; - GlobalFuncs[i].IsState = NULL; - GlobalFuncs[i].PathnodeClaimRevoked = NULL; - } - - InitVoid(&GlobalFuncs[THINK_VOID]); - InitTurret(&GlobalFuncs[THINK_TURRET]); - InitCover(&GlobalFuncs[THINK_COVER]); - InitPatrol(&GlobalFuncs[THINK_PATROL]); - InitRunner(&GlobalFuncs[THINK_RUNNER]); - InitPain(&GlobalFuncs[THINK_PAIN]); - InitKilled(&GlobalFuncs[THINK_KILLED]); - InitIdle(&GlobalFuncs[THINK_IDLE]); - InitCurious(&GlobalFuncs[THINK_CURIOUS]); - InitDisguiseSalute(&GlobalFuncs[THINK_DISGUISE_SALUTE]); - InitDisguiseSentry(&GlobalFuncs[THINK_DISGUISE_SENTRY]); - InitDisguiseOfficer(&GlobalFuncs[THINK_DISGUISE_OFFICER]); - InitDisguiseRover(&GlobalFuncs[THINK_DISGUISE_ROVER]); - InitDisguiseNone(&GlobalFuncs[THINK_DISGUISE_NONE]); - InitAlarm(&GlobalFuncs[THINK_ALARM]); - InitGrenade(&GlobalFuncs[THINK_GRENADE]); - InitMachineGunner(&GlobalFuncs[THINK_MACHINEGUNNER]); - InitDogIdle(&GlobalFuncs[THINK_DOG_IDLE]); - InitDogAttack(&GlobalFuncs[THINK_DOG_ATTACK]); - InitDogCurious(&GlobalFuncs[THINK_DOG_CURIOUS]); - InitAnim(&GlobalFuncs[THINK_ANIM]); - InitAnimCurious(&GlobalFuncs[THINK_ANIM_CURIOUS]); - InitAim(&GlobalFuncs[THINK_AIM]); - InitBalconyIdle(&GlobalFuncs[THINK_BALCONY_IDLE]); - InitBalconyCurious(&GlobalFuncs[THINK_BALCONY_CURIOUS]); - InitBalconyAttack(&GlobalFuncs[THINK_BALCONY_ATTACK]); - InitBalconyDisguise(&GlobalFuncs[THINK_BALCONY_DISGUISE]); - InitBalconyGrenade(&GlobalFuncs[THINK_BALCONY_GRENADE]); - InitBalconyPain(&GlobalFuncs[THINK_BALCONY_PAIN]); - InitBalconyKilled(&GlobalFuncs[THINK_BALCONY_KILLED]); - InitWeaponless(&GlobalFuncs[THINK_WEAPONLESS]); - InitNoClip(&GlobalFuncs[THINK_NOCLIP]); - InitDead(&GlobalFuncs[THINK_DEAD]); - - - - AddWaitTill(STRING_TRIGGER); - AddWaitTill(STRING_MOVE); - AddWaitTill(STRING_ANIMDONE); - AddWaitTill(STRING_VISIBLE); - AddWaitTill(STRING_UPPERANIMDONE); - AddWaitTill(STRING_SAYDONE); - AddWaitTill(STRING_FLAGGEDANIMDONE); - AddWaitTill(STRING_DEATH); - AddWaitTill(STRING_PAIN); - AddWaitTill(STRING_HASENEMY); - AddWaitTill(STRING_MOVEDONE); - AddWaitTill(STRING_SOUNDDONE); - AddWaitTill(STRING_TURNDONE); - - gi.DPrintf("actor waittills registered\n"); - - if (developer->integer) - { - Com_Printf("sizeof(Actor) == %zi\n", sizeof(Actor)); - //FIXME: magic ?? - Com_Printf("Magic sizeof actor number: %zd\n", sizeof(Actor)); - } -} - -/* -=============== -Actor::FixAIParameters - -Fix path related parameters. -=============== -*/ -void Actor::FixAIParameters - ( - void - ) -{ - //FIXME: needs revision(silly mistakes) - - float distmin, distmin2, distmax; - if (m_pTetherEnt) - { - float leash = 64; - if ( m_pTetherEnt->IsSubclassOfEntity() ) - { - leash = m_pTetherEnt->angles.y - m_pTetherEnt->origin.y + m_pTetherEnt->angles.z + m_pTetherEnt->origin.z; - } - if ( leash <= m_fLeash) - { - distmin = m_fLeash; - } - else - { - Com_Printf("^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing leash from %g to %g.\n" - "^~^~^ Leash must be larger than the size of the entity to which an AI is tethered.\n" - "\n", - entnum, - radnum, - targetname.c_str(), - m_fLeash, - leash); - m_fLeash = leash; - distmin = leash; - m_fLeashSquared = Square(leash); - } - } - else - { - distmin = m_fLeash; - } - if (m_fMinDistance <= distmin) - { - distmax = m_fMinDistance; - } - else - { - Com_Printf("^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to match leash.\n" - "^~^~^ Leash must be greater than mindist, or the AI will want to both run away and stay put.\n" - "\n", - entnum, - radnum, - targetname.c_str(), - m_fMinDistance, - distmin); - m_fMinDistance = distmin; - distmax = distmin; - m_fMinDistanceSquared = distmin * distmin; - } - distmax += 128; - if (distmax - 1 > m_fMaxDistance) - { - Com_Printf("^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing maxdist from %g to %g to exceed mindist.\n" - "^~^~^ Maxdist should be %i greater than mindist, or the AI will want to both run away and charge, or just do oscillatory behavior.\n" - "\n", - entnum, - radnum, - targetname.c_str(), - m_fMaxDistance, - distmax, - 128); - - m_fMaxDistance = distmax; - m_fMaxDistanceSquared = distmax * distmax; - } - if (world->farplane_distance > 0) - { - //FIXME: macro and floats - if (m_fMaxDistance > world->farplane_distance * 0.828 +1) - { - Com_Printf( - "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing maxdist from %g to %g to be %g%% of farplane.\n" - "^~^~^ Maxdist should be this distance within fog, or AI will be able to see and attack through fog.\n" - "\n", - entnum, - radnum, - targetname.c_str(), - m_fMaxDistance, - world->farplane_distance * 0.828, - 2.0); - distmin2 = m_fMinDistance; - m_fMaxDistance = world->farplane_distance * 0.828; - m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance; - if (distmin2 + 128.0 - 1.0 > m_fMaxDistance) - { - Com_Printf( - "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to be less than maxdist " - "after fog adjustment.\n" - "\n", - entnum, - radnum, - targetname.c_str(), - distmin2, - m_fMaxDistance <= 128 ? 0 : m_fMaxDistance - 128); - m_fMinDistance = m_fMaxDistance - 128.0; - if (m_fMaxDistance - 128.0 < 0) - { - m_fMinDistance = 0.0; - } - m_fMinDistanceSquared = Square(m_fMinDistance); - } - } - } -} - - -/* -=============== -Actor::AttackEntryAnimation - -Returns true if actor stands/draws his weapon. -=============== -*/ -bool Actor::AttackEntryAnimation - ( - void - ) -{ - if (m_Enemy) - { - - if (level.inttime >= level.m_iAttackEntryAnimTime + 3000) - { - float distSq = (m_Enemy->origin - origin).lengthXYSquared(); - - if (m_bNoSurprise || distSq >= Square(256)) - { - if (distSq > Square(1024) && !(rand() & 3)) - { - if (m_pNextSquadMate != this) - { - for (auto pSquadMate = m_pNextSquadMate; ; pSquadMate = pSquadMate->m_pNextSquadMate) - { - if (Square(m_fInterval) * Square(2) > (pSquadMate->origin - origin).lengthSquared()) - { - break; - } - if (pSquadMate == this) - { - if (m_bNewEnemy) - Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, false); - - m_bNoSurprise = true; - m_bNewEnemy = false; - return false; - } - } - vec2_t vDelta; - vDelta[0] = m_Enemy->origin.x - origin.x; - vDelta[1] = m_Enemy->origin.y - origin.y; - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } - - SetDesiredLookDir(m_Enemy->origin - origin); - - m_csNextAnimString = STRING_ANIM_STANDIDENTIFY_SCR; - - m_bNextForceStart = true; - m_bNoSurprise = true; - m_bNewEnemy = false; - - return true; - - } - } - } - else - { - //FIXME: macro - if ( rand() > distSq * 0.0026041667) //rand() / 0x17F - { - //FIXME: macro - StartAnimation(1, STRING_ANIM_STANDSHOCK_SCR); - m_bNoSurprise = true; - m_bNewEnemy = false; - - return true; - } - } - } - - //FIXME: macro - if (m_bNewEnemy) - Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, false); - - m_bNoSurprise = true; - m_bNewEnemy = false; - - } - return false; -} - -/* -=============== -Actor::CheckForThinkStateTransition - -Check for all thinkstates transitions. -=============== -*/ -void Actor::CheckForThinkStateTransition - ( - void - ) -{ - if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL)) - { - if (!m_bEnableEnemy) - { - CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } - else - { - if (!CheckForTransition(THINKSTATE_ATTACK, THINKLEVEL_NORMAL)) - { - - if (!CheckForTransition(THINKSTATE_DISGUISE, THINKLEVEL_NORMAL)) - { - - if (CheckForTransition(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL)) - { - m_pszDebugState = "from_sight"; - } - else - { - CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } - } - } - } - } -} - -/* -=============== -Actor::CheckForTransition - -Check for thinkstate transition. -=============== -*/ -bool Actor::CheckForTransition - ( - eThinkState state, - eThinkLevel level - ) -{ - GlobalFuncs_t *func; - - if( m_ThinkStates[ level ] != state ) - { - func = &GlobalFuncs[ m_ThinkMap[ state ] ]; - - if( func->PassesTransitionConditions && ( this->*( func->PassesTransitionConditions ) )() ) - { - SetThinkState( state, THINKLEVEL_NORMAL); - return true; - } - } - - return false; -} - - -/* -=============== -Actor::PassesTransitionConditions_Grenade - -Should actor transition think state to grenade ? -=============== -*/ -bool Actor::PassesTransitionConditions_Grenade - ( - void - ) -{ - if( !m_bLockThinkState && m_bEnableEnemy && m_pGrenade ) - { - return m_fGrenadeAwareness >= random(); - } - - return false; -} - -/* -=============== -Actor::PassesTransitionConditions_Attack - -Should actor transition think state to attack ? -=============== -*/ -bool Actor::PassesTransitionConditions_Attack - ( - void - ) -{ - UpdateEnemy(0); - - if( m_bLockThinkState ) - return false; - - if( m_Enemy && !( m_Enemy->flags & FL_NOTARGET ) ) - { - if(EnemyIsDisguised()) - { - return true; - } - - if( m_PotentialEnemies.GetCurrentVisibility() > 0.999f ) - return true; - } - - return false; -} - -/* -=============== -Actor::PassesTransitionConditions_Disguise - -Should actor transition think state to disguise ? -=============== -*/ -bool Actor::PassesTransitionConditions_Disguise - ( - void - ) -{ - if( m_bLockThinkState ) - return false; - - if( m_iNextDisguiseTime > level.inttime ) - return false; - - m_iNextDisguiseTime = level.inttime + 200; - - UpdateEnemy(200); - - if( !m_Enemy ) - return false; - - if(EnemyIsDisguised()) - { - { - if( m_PotentialEnemies.GetCurrentVisibility() > 0.999f ) - { - if( fabs( m_Enemy->origin[ 2 ] - origin[ 2 ] ) <= 48.0f ) - { - vec2_t delta; - float fHorzDistanceSquared; - - VectorSub2D(m_Enemy->origin, origin, delta); - - fHorzDistanceSquared = VectorLength2DSquared(delta); - - if(fHorzDistanceSquared > Square(32) && fHorzDistanceSquared < m_fMaxDisguiseDistSquared) - { - Player *player = ( Player * )G_GetEntity( 0 ); - Vector pos = EyePosition(); - - return G_SightTrace( - pos, - vec_zero, - vec_zero, - player->centroid, - this, - player, - MASK_TRANSITION, - qfalse, - "Actor::PassesTransitionConditions_Disguise" ); - } - } - } - } - } - - return false; -} - -/* -=============== -Actor::PassesTransitionConditions_Curious - -Should actor transition think state to curious ? -=============== -*/ -bool Actor::PassesTransitionConditions_Curious - ( - void - ) -{ - UpdateEnemy(200); - - if( m_bLockThinkState ) - return false; - - if( !m_Enemy && m_iCuriousTime ) - { - SetCuriousAnimHint(6); - return true; - } - - if(m_Enemy && !EnemyIsDisguised() && m_PotentialEnemies.GetCurrentVisibility() <= 0.999f ) - { - //THINKSTATE_CURIOUS - SetCuriousAnimHint(6); - return true; - } - - return false; -} - -/* -=============== -Actor::UpdateEnableEnemy - -Enable/disable enemy based on desired value. -Can be changed from script. -=============== -*/ -void Actor::UpdateEnableEnemy - ( - void - ) -{ - if (m_bEnableEnemy != m_bDesiredEnableEnemy) - { - m_bEnableEnemy = m_bDesiredEnableEnemy; - if (m_bDesiredEnableEnemy) - { - SetLeashHome(origin); - } - else - { - if (m_ThinkStates[THINKLEVEL_NORMAL] <= THINKSTATE_DISGUISE) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } - SetEnemy(NULL, false); - } - } -} - -/* -=============== -Actor::ThinkStateTransitions - -Transition think state and level. -Called when thinkstate/level are change. -=============== -*/ -void Actor::ThinkStateTransitions - ( - void - ) -{ - int newThinkLevel; - int newThinkState; - - //GlobalFuncs_t *func;// = &GlobalFuncs[m_Think[m_ThinkLevel]]; - - //loop on all think levels. - for (newThinkLevel = NUM_THINKLEVELS -1; newThinkLevel >= 0 ; newThinkLevel--) - { - newThinkState = m_ThinkStates[newThinkLevel]; - //a new think level is found if it's think state is not THINKSTATE_VOID - if (newThinkState != THINKSTATE_VOID) - { - break; - } - } - - if (m_ThinkMap[newThinkState] == m_Think[m_ThinkLevel]) - { - if (newThinkLevel != m_ThinkLevel || m_ThinkState != newThinkState) - { - m_ThinkLevel = (eThinkLevel)newThinkLevel; - m_ThinkState = (eThinkState)newThinkState; - m_Think[newThinkLevel] = m_ThinkMap[newThinkState]; - } - else - { - RestartState(); - } - } - else - { - if (newThinkLevel > THINKLEVEL_NORMAL) - { - for (int i = 0 ; i < newThinkLevel; i++) - { - if (m_ThinkStates[i] == THINKSTATE_VOID) - EndState(i); - } - } - - if (newThinkLevel > m_ThinkLevel) - { - SuspendState(); - - m_ThinkLevel = (eThinkLevel)newThinkLevel; - m_ThinkState = m_ThinkStates[newThinkLevel]; - m_Think[newThinkLevel] = m_ThinkMap[m_ThinkState]; - - BeginState(); - m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; - } - else - { - EndState(m_ThinkLevel); - - if (newThinkLevel == m_ThinkLevel) - { - m_ThinkState = m_ThinkStates[newThinkLevel]; - m_Think[newThinkLevel] = m_ThinkMap[m_ThinkState]; - - BeginState(); - m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; - } - else - { - m_ThinkLevel = (eThinkLevel)newThinkLevel; - m_ThinkState = m_ThinkStates[newThinkLevel]; - - - if (m_Think[newThinkLevel] != m_ThinkMap[m_ThinkState]) - { - EndState(newThinkLevel); - - - m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; - - BeginState(); - m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; - } - else - { - ResumeState(); - } - } - } - } -} - -/* -=============== -Actor::TransitionState - -=============== -*/ -void Actor::TransitionState - ( - int iNewState, - int iPadTime - ) -{ - //fixme: this is an inline function. - m_State = iNewState; - m_iStateTime = level.inttime + iPadTime; -} - -/* -=============== -Actor::ChangeAnim - -Change current animation. -=============== -*/ - -void Actor::ChangeAnim -( - void -) -{ - bool v3; // zf - - if (m_pAnimThread) - { - if (g_scripttrace->integer) - { - if (m_pAnimThread->CanScriptTracePrint()) - Com_Printf("--- Change Anim\n"); - } - m_pAnimThread->AbortRegistration( - STRING_EMPTY, - this); - ScriptClass * sc = m_pAnimThread->GetScriptClass(); - if (sc) - { - delete sc; - } - Com_Printf("ChangeAnim: m_pAnimThread aborted\n"); - } - - if (m_ThinkState != 4) // THINKSTATE_ATTACK - { - if (m_ThinkState <= 4) // THINKSTATE_ATTACK - { - if (m_ThinkState >= 2) // THINKSTATE_PAIN - { - if (m_bMotionAnimSet) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet) - AnimFinished(m_iActionSlot, true); - v3 = m_bSayAnimSet == 0; - LABEL_13: - if (v3) - goto LABEL_14; - goto LABEL_20; - } - goto LABEL_21; - } - if (m_ThinkState != 7) // m_ThinkState != THINKSTATE_GRENADE - { - LABEL_21: - if (m_bMotionAnimSet) - { - if (!m_bLevelMotionAnim) - AnimFinished(m_iMotionSlot, true); - } - if (m_bActionAnimSet) - { - if (!m_bLevelActionAnim) - AnimFinished(m_iActionSlot, true); - } - if (m_bSayAnimSet && !m_bLevelSayAnim) - { - LABEL_20: - AnimFinished(m_iSaySlot, true); - goto LABEL_14; - } - goto LABEL_14; - } - } - if (m_bMotionAnimSet) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet) - AnimFinished(m_iActionSlot, true); - if (m_bSayAnimSet) - { - v3 = m_bLevelSayAnim == 2; - goto LABEL_13; - } -LABEL_14: - m_fCrossblendTime = 0.5; - m_pAnimThread = m_Anim.Create(this); - if (m_pAnimThread) - { - if (g_scripttrace->integer) - { - if (m_pAnimThread->CanScriptTracePrint()) - Com_Printf("+++ Change Anim\n"); - } - m_pAnimThread->Register(STRING_EMPTY, this); - - m_pAnimThread->StartTiming(); - Com_Printf("ChangeAnim: m_pAnimThread started\n"); - } -} -/* -void Actor::ChangeAnim - ( - void - ) -{ - if (m_pAnimThread) - { - if (g_scripttrace->integer && m_pAnimThread->CanScriptTracePrint()) - { - Com_Printf("--- Change Anim\n"); - } - m_pAnimThread->AbortRegistration(STRING_EMPTY, this); - ScriptClass * sc = m_pAnimThread->GetScriptClass(); - if (sc) - { - delete sc; - } - Com_Printf("ChangeAnim: m_pAnimThread aborted\n"); - } - - if (m_ThinkState != THINKSTATE_ATTACK) - { - if (m_ThinkState > THINKSTATE_ATTACK) - { - if (m_ThinkState != THINKSTATE_GRENADE) - { - if (m_bMotionAnimSet && !m_bLevelMotionAnim) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet && !m_bLevelActionAnim) - AnimFinished(m_iActionSlot, true); - if (m_bSayAnimSet && !m_bLevelSayAnim) - AnimFinished(m_iSaySlot, true); - } - else - { - if (m_bMotionAnimSet) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet) - AnimFinished(m_iActionSlot, true); - if (m_bSayAnimSet && m_bLevelSayAnim != 2) - AnimFinished(m_iSaySlot, true); - - } - - } - else - { - if (m_ThinkState < THINKSTATE_PAIN) - { - if (m_bMotionAnimSet && !m_bLevelMotionAnim) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet && !m_bLevelActionAnim) - AnimFinished(m_iActionSlot, true); - if (m_bSayAnimSet && !m_bLevelSayAnim) - AnimFinished(m_iSaySlot, true); - } - else - { - if (m_bMotionAnimSet) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet) - AnimFinished(m_iActionSlot, true); - if (m_bSayAnimSet) - AnimFinished(m_iSaySlot, true); - } - - } - - } - else - { - if (m_bMotionAnimSet) - AnimFinished(m_iMotionSlot, true); - if (m_bActionAnimSet) - AnimFinished(m_iActionSlot, true); - if (m_bSayAnimSet && m_bLevelSayAnim != 2) - AnimFinished(m_iSaySlot, true); - } - - //FIXME: macro - m_fCrossblendTime = 0.5; - - m_pAnimThread = m_Anim.Create(this); - - if (m_pAnimThread) - { - if (g_scripttrace->integer) - { - if (m_pAnimThread->CanScriptTracePrint()) - Com_Printf("+++ Change Anim\n"); - } - m_pAnimThread->Register(STRING_EMPTY, this); - - m_pAnimThread->StartTiming(); - Com_Printf("ChangeAnim: m_pAnimThread started\n"); - } -} -*/ - - -/* -=============== -Actor::UpdateSayAnim - -Update say animation. -=============== -*/ -void Actor::UpdateSayAnim - ( - void - ) -{ - gi.DPrintf("Actor::UpdateSayAnim 1\n"); - - if (m_ThinkState > THINKSTATE_KILLED) - { - gi.DPrintf("Actor::UpdateSayAnim 2\n"); - int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csSayAnim).c_str()); - if (animnum == -1) - { - return; - } - gi.DPrintf("Actor::UpdateSayAnim 3\n"); - - int flags = gi.Anim_FlagsSkel(edict->tiki, animnum); - - //FIXME: macro - if (flags & 256) - { - gi.DPrintf("Actor::UpdateSayAnim 4\n"); - if ( !IsAttackState(m_ThinkState) && !IsGrenadeState(m_ThinkState) ) - { - ChangeActionAnim(); - if (flags & ANIM_NOACTION) - { - ChangeMotionAnim(); - - StartMotionAnimSlot(0, animnum, 1); - - m_bLevelActionAnim = true; - m_bLevelMotionAnim = true; - - m_iMotionSlot = m_iActionSlot = GetMotionSlot(0); - } - else - { - m_bActionAnimSet = true; - - StartActionAnimSlot(animnum); - - m_bLevelActionAnim = true; - - m_iActionSlot = GetActionSlot(0); - } - ChangeSayAnim(); - m_bSayAnimSet = true; - m_bLevelSayAnim = m_bNextLevelSayAnim; - m_bNextLevelSayAnim = 0; - m_iSaySlot = m_iActionSlot; - return; - } - gi.DPrintf("Actor::UpdateSayAnim 4\n"); - } - else if (m_bNextLevelSayAnim == 2 || (!IsAttackState(m_ThinkState) && !IsGrenadeState(m_ThinkState)) ) - { - gi.DPrintf("Actor::UpdateSayAnim 6\n"); - ChangeSayAnim(); - m_bSayAnimSet = true; - StartSayAnimSlot(animnum); - m_bLevelSayAnim = m_bNextLevelSayAnim; - m_bNextLevelSayAnim = 0; - m_iSaySlot = GetSaySlot(); - gi.DPrintf("Actor::UpdateSayAnim 7\n"); - return; - } - } - - if (!m_bSayAnimSet) - { - Unregister(STRING_SAYDONE); - gi.DPrintf("Actor::UpdateSayAnim 8\n"); - } -} - -/* -=============== -Actor::UpdateUpperAnim - -Update upper animation. -=============== -*/ -void Actor::UpdateUpperAnim - ( - void - ) -{ - int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csUpperAnim).c_str()); - if (animnum != -1) - { - if (IsAttackState(m_ThinkState) || IsGrenadeState(m_ThinkState) || IsKilledState(m_ThinkState) || IsPainState(m_ThinkState)) - { - if (!m_bActionAnimSet) - { - Unregister(STRING_UPPERANIMDONE); - } - } - else - { - ChangeActionAnim(); - - m_bActionAnimSet = true; - - StartActionAnimSlot(animnum); - - m_bLevelActionAnim = true; - m_iActionSlot = SimpleActor::GetActionSlot(0); - - } - } -} - -/* -=============== -Actor::UpdateAnim - -Update animation. -=============== -*/ -void Actor::UpdateAnim - ( - void - ) -{ - m_bAnimating = true; - SimpleActor::UpdateAim(); - if (SimpleActor::UpdateSelectedAnimation()) - { - Com_Printf("ChangeAnim\n"); - ChangeAnim(); - } - Director.Unpause(); - Director.Pause(); - - if (m_csSayAnim != STRING_EMPTY) - { - UpdateSayAnim(); - m_csSayAnim = STRING_EMPTY; - } - - if (m_csUpperAnim != STRING_EMPTY) - { - UpdateUpperAnim(); - m_csUpperAnim = STRING_EMPTY; - } - - if (!m_bSayAnimSet && !m_bDog) - { - SimpleActor::UpdateEmotion(); - } - - //FIXME: macro - for (int slot = 0; slot < 14; slot++) - { - - //FIXME: better notation - if (!((m_bUpdateAnimDoneFlags >> slot) & 1) ) - { - SimpleActor::UpdateAnimSlot(slot); - } - } - - float fAnimTime, fAnimWeight, total_weight = 0, time = 0; - for (int slot = 0; slot < 14; slot++) - { - if ((m_weightType[slot] == 1 || m_weightType[slot] == 4) && animFlags[slot] & ANIM_LOOP) - { - UseSyncTime(slot, 1); - fAnimTime = AnimTime(slot); - fAnimWeight = edict->s.frameInfo[slot].weight; - time += fAnimTime * fAnimWeight; - if (std::isinf(time)) - { - Com_Printf("ent %i, targetname '%s', anim '%s', slot %i, fAnimTime %f, fAnimWeight %f\n", - entnum, - targetname.c_str(), - AnimName(slot), - slot, - fAnimTime, - fAnimWeight); - } - total_weight += fAnimWeight; - } - else - { - UseSyncTime(slot, 0); - } - } - - if (total_weight != 0) - { - SetSyncRate(time / total_weight); - } - - PostAnimate(); -} - -/* -=============== -Actor::StoppedWaitFor - -Called when stopped wait for an actor. -=============== -*/ -void Actor::StoppedWaitFor -( - const_str name, - bool bDeleting -) -{ - g_iInThinks++; - - GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]]; - - if (func->FinishedAnimation) - { - (this->*func->FinishedAnimation)(); - } - - g_iInThinks--; -} - -/* -=============== -Actor::ValidGrenadePath - -Returns true if grenade trajectory is valid. -i.e grenade can get from vFrom to vTo with vVel with any obstacles. -=============== -*/ -bool Actor::ValidGrenadePath - ( - const Vector& vFrom, - const Vector& vTo, - Vector& vVel - ) -{ - //FIXME: macros - float fGravity, fTime1, fTime2, fTime3, fTimeLand; - Vector mins(-4, -4, -4); - Vector maxs(4, 4, 4); - - Vector vPoint1, vPoint2, vPoint3; - - if (vVel.lengthSquared() > 589824) - { - return false; - } - fGravity = 0.8 * sv_gravity->value; - - fTime1 = vVel.z * fGravity / 0.5; - - vPoint1.x = vVel.x * fTime1 + vFrom.x; - vPoint1.y = vVel.y * fTime1 + vFrom.y; - vPoint1.z = vVel.z * fTime1 * 0.75 + vFrom.z; - - maxs.z = fGravity * 0.125 * fTime1 * fTime1 + 4; - - if (ai_debug_grenades->integer) - { - G_DebugLine(vFrom, vPoint1, 1.0, 0.5, 0.5, 1.0); - } - - if (G_SightTrace(vFrom, - mins, - maxs, - vPoint1, - this, - NULL, - //FIXME: macro - 1107569409, - qfalse, - "Actor::ValidGrenadePath 1")) - { - fTime2 = fTime1 + fTime1; - - vPoint2.x = vVel.x * fTime2 + vFrom.x; - vPoint2.y = vVel.y * fTime2 + vFrom.y; - vPoint2.z = vVel.z * fTime2 * 0.5 + vFrom.z; - - if (ai_debug_grenades->integer) - { - G_DebugLine(vPoint1, vPoint2, 1.0, 0.5, 0.5, 1.0); - } - if (G_SightTrace(vPoint1, - mins, - maxs, - vPoint2, - this, - NULL, - //FIXME: macro - 1107569409, - qfalse, - "Actor::ValidGrenadePath 2")) - { - if (fabs(vVel.y) >= fabs(vVel.x)) - { - fTimeLand = (vTo.y - vFrom.y) / vVel.y; - } - else - { - fTimeLand = (vTo.x - vFrom.x) / vVel.x; - } - - fTime3 = (fTime2 + fTimeLand) / 2; - maxs.z = fGravity * 0.03125 * (fTimeLand - fTime2) * (fTimeLand - fTime2) + 4; - - - vPoint3.x = vVel.x * fTime3 + vFrom.x; - vPoint3.y = vVel.y * fTime3 + vFrom.y; - vPoint3.z = (vVel.z - fGravity * 0.5 * fTime3) * fTime3 + vFrom.z; - - if (ai_debug_grenades->integer) - { - G_DebugLine(vPoint2, vPoint3, 1.0, 0.5, 0.5, 1.0); - } - if (G_SightTrace(vPoint2, - mins, - maxs, - vPoint3, - this, - NULL, - //FIXME: macro - 1107569409, - qfalse, - "Actor::ValidGrenadePath 3")) - { - - if (ai_debug_grenades->integer) - { - G_DebugLine(vPoint3, vTo, 1.0, 0.5, 0.5, 1.0); - } - trace_t trace = G_Trace(vPoint3, mins, maxs, vTo, this, 1107569409, qfalse, "Actor::ValidGrenadePath 4"); - if (!trace.allsolid) - { - if (trace.ent) - { - if (trace.ent->entity->IsSubclassOfSentient()) - { - Sentient *sen = (Sentient *)trace.ent->entity; - if (sen->m_Team != m_Team) - { - return true; - } - } - - } - } - else if(trace.entityNum == 1022 && trace.plane.normal[2] >= 1) - { - return true; - } - } - } - } - return false; -} - -/* -=============== -Actor::CalcThrowVelocity - -Calculates required grenade throw velocity to get grenade from vFrom to vTo. -=============== -*/ -Vector Actor::CalcThrowVelocity - ( - const Vector& vFrom, - const Vector& vTo - ) -{ - - Vector ret; - Vector vDelta; - float v10; // ST0C_4 - float v11; // fst3 - ////// - float fGravity; - float fVelHorz; - float fVelVert; - float fDeltaZ; - float fDistance; - float fHorzDistSquared; - float fOOTime; - - fGravity = 0.8 * sv_gravity->value; - - vDelta = vTo - vFrom; - - fVelHorz = vDelta.x; - fVelVert = vDelta.y; - fDeltaZ = vDelta.z; - - fHorzDistSquared = fVelVert * fVelVert + fVelHorz * fVelHorz; - - fDistance = sqrt(fDeltaZ * fDeltaZ + fHorzDistSquared); - - // original irl equation: v10 = sqrt(fGravity * 0.5 * fHorzDistSquared / (fDistance * trigMult )) - // trigMult = (cos(th)/ tan(al) - sin(th)/tanSquared(al)) - // al = inital velocity angle with ground plane. - // th = angle between vDelta and ground plane. - // mohaa devs decided to let trigMult be 1, for the sake of simplicity I guess. - v10 = sqrt(fGravity * 0.5 * fHorzDistSquared / fDistance); - - - // no I dea what this means. - // maybe it's related to their angle choice. - // calculates the 1/distanceSquared necessary for fOOTime calculation. - v11 = (fDistance + fDeltaZ) / (fDistance - fDeltaZ) / fHorzDistSquared; - - // 1/(speed * sqrt(1/distanceSquared)) - // 1/(speed * 1/distance) - // 1/(1/time) - // time - fOOTime = 1 / (v10 * sqrt(v11)); - - ret.z = v10; - ret.x = fVelHorz / fOOTime; - ret.y = fVelVert / fOOTime; - return ret; -} - -/* -=============== -Actor::CanThrowGrenade - -Returns required velocity to throw grenade from vFrom to vTo. -Or vec_zero if it's not possible. -=============== -*/ -Vector Actor::CanThrowGrenade - ( - const Vector& vFrom, - const Vector& vTo - ) -{ - Vector vVel = vec_zero; - - vVel = CalcThrowVelocity(vFrom, vTo); - if ( vVel == vec_zero || !ValidGrenadePath(vFrom, vTo, vVel)) - { - return vec_zero; - } - else - { - return vVel; - } -} - -/* -=============== -Actor::CalcRollVelocity - -Calculates required grenade roll velocity to get grenade from vFrom to vTo. -Roll here means a low toss. -=============== -*/ -Vector Actor::CalcRollVelocity - ( - const Vector& vFrom, - const Vector& vTo - ) -{ - float fOOTime, fVelVert, fVelHorz, fGravity; - Vector vDelta = vFrom - vTo, vRet; - - // you must throw from above. - // start point must be above (higher) than end point. - if (vDelta.z > 0) - { - fGravity = 0.8 * sv_gravity->value; - - // Required down velocity to hit the ground twice as fast as freefall time. - vRet.z = sqrt(vDelta.z * fGravity); - - - - // accel = speed / time, hence : time = speed / accel, 0.21961521 is an arbitary scalar. - // since the scalar is way less than 1, it will take more time to hit the ground than to arrive to target dest. - // this is kinda like a low toss rather than a roll. if I understand correctly. - fOOTime = vRet.z / fGravity * 0.21961521; - - // speed = distance / time - vRet.x = fVelHorz = -vDelta.x / fOOTime; - vRet.y = fVelVert = -vDelta.y / fOOTime; - - - return vRet; - } - else - { - return vec_zero; - } -} - -/* -=============== -Actor::CanRollGrenade - -Returns required velocity to roll grenade from vFrom to vTo. -Or vec_zero if it's not possible. -Roll here means a low toss. -=============== -*/ -Vector Actor::CanRollGrenade - ( - const Vector& vFrom, - const Vector& vTo - ) -{ - Vector vVel = vec_zero; - vVel = CalcRollVelocity(vFrom, vTo); - if (vVel == vec_zero || !ValidGrenadePath(vFrom, vTo, vVel)) - { - return vec_zero; - } - else - { - return vVel; - } -} - -/* -=============== -Actor::CanTossGrenadeThroughHint - -Returns true if actor can toss grenade through specified hint. -pvVel and peMode are modified. -=============== -*/ -bool Actor::CanTossGrenadeThroughHint - ( - GrenadeHint *pHint, - const Vector& vFrom, - const Vector& vTo, - bool bDesperate, - Vector *pvVel, - eGrenadeTossMode *peMode - ) -{ - float fGravity = 0.8 * sv_gravity->value; - float fAngle, fTemp, fTemp2, fTemp3, fTemp4, /*fVelVert, fVelHorz,*/ fRange, fRangeSquared, fDist, fDistSquared, fHeight; - bool bSuccess = false; - - Vector vDelta, vHintDelta; - - if (!bDesperate) - { - vHintDelta = pHint->origin - vFrom; - vDelta = vFrom - vTo; - - fDist = vDelta.lengthXY(); - fDistSquared = fDist * fDist; - - fRange = vHintDelta.z * fDist - vDelta.z * vHintDelta.lengthXY(); - - if (fRange == 0) - { - return false; - } - fTemp4 = 1 / fRange; - fRange = (fDist - vHintDelta.lengthXY()) / fRange; - - if (fRange <= 0) - { - return false; - } - - fTemp = sqrt(fRange * (fDist * (fGravity * 0.5 * vHintDelta.lengthXY()))); - fTemp2 = (vHintDelta.z * fDistSquared - vDelta.z * vHintDelta.lengthXYSquared()) * fGravity * 0.5; - fTemp3 = fTemp / vHintDelta.lengthXY(); - - pvVel->x = vHintDelta.x * fTemp3; - pvVel->y = vHintDelta.y * fTemp3; - pvVel->z = 0.5 * fTemp2 / fTemp * fTemp4; - - *peMode = AI_GREN_TOSS_HINT; - - return ValidGrenadePath(vFrom, pHint->origin, *pvVel); - } - - vHintDelta = pHint->origin - vFrom; - - - fRange = vHintDelta.lengthXY(); - fRangeSquared = fRange * fRange; - - if (fRangeSquared != 0) - { - fDist = vHintDelta.length(); - fHeight = fRangeSquared * fGravity / 589824.0 + vHintDelta.z; - if (-fHeight <= -fDist) - { - fAngle = (atan2(vHintDelta.z / fRangeSquared, 1.0) + atan2(fHeight / fDist, sqrt(1.0 - fHeight / fDist * (fHeight / fDist)))) / 2; - pvVel->x = vHintDelta.x * 768.0 / fRangeSquared * cos(fAngle); - pvVel->y = vHintDelta.y * 768.0 / fRangeSquared * cos(fAngle); - pvVel->z = 768.0 * cos(fAngle); - return ValidGrenadePath(vFrom, pHint->origin, *pvVel); - } - } - - return bSuccess; -} - -/* -=============== -Actor::GrenadeThrowPoint - -Returns real grenade throw point. -=============== -*/ -Vector Actor::GrenadeThrowPoint - ( - const Vector& vFrom, - const Vector& vDelta, - const_str csAnim - ) -{ - vec2_t axis; - Vector vRet; - - VectorCopy2D(vDelta, axis); - VectorNormalize2D(axis); - - if (csAnim == STRING_ANIM_GRENADEKICK_SCR) - { - vRet = vFrom; - vRet.z += 8; - return vRet; - } - else - { - if (csAnim > STRING_ANIM_GRENADEKICK_SCR) - { - if (csAnim != STRING_ANIM_GRENADETHROW_SCR && csAnim != STRING_ANIM_GRENADETOSS_SCR) - { - vRet = vFrom; - vRet.z += 80; - return vRet; - } - else - { - vRet.x = vFrom.x - axis[0] * 34 + axis[1] * 8; - vRet.y = vFrom.y - axis[0] * 8 - axis[1] * 34; - vRet.z = 52 + vFrom.z; - return vRet; - } - } - else - { - if (csAnim != STRING_ANIM_GRENADERETURN_SCR) - { - vRet = vFrom; - vRet.z += 80; - return vRet; - } - else - { - - vRet.x = vFrom.x + axis[0] * 25 + axis[1] * 2; - vRet.y = vFrom.y - axis[0] * 2 + axis[1] * 25; - vRet.z = 89 + vFrom.z; - return vRet; - } - } - } -} - -/* -=============== -Actor::CalcKickVelocity - -Calculates required grenade kick velocity. -=============== -*/ -Vector Actor::CalcKickVelocity - ( - Vector& vDelta, - float fDist - ) const -{ - float fScale, fGravity; - Vector ret; - float v4; - - fGravity = 0.8 * sv_gravity->value; - - fScale = 0.57735032 * fDist; - v4 = sqrt(fGravity * 0.5 / (fScale - vDelta[2])); - ret[0] = vDelta[0] * v4; - ret[1] = vDelta[1] * v4; - ret[2] = fScale * v4; - - return ret; -} - -/* -=============== -Actor::CanKickGrenade - -Returns true if actor can kick grenade from vFrom to vTo. -Or false if it's not possible. -pvVel is changed. -=============== -*/ -bool Actor::CanKickGrenade - ( - Vector &vFrom, - Vector &vTo, - Vector &vFace, - Vector *pvVel - ) -{ - Vector vEnd, vStart, vDelta, vVel; - float fDist, fGravity, fScale; - fGravity = sv_gravity->value * 0.8; - if (fGravity <= 0.0) - { - return false; - } - - vStart = GrenadeThrowPoint(vFrom, vFace, STRING_ANIM_GRENADEKICK_SCR); - vDelta = vTo - vStart; - - fDist = vDelta.lengthXY(); - if (vDelta.z >= 0 || Vector::Dot(vDelta, vFace) < 0.0 || fDist < 256 || fDist >= 255401.28 / fGravity + 192.0) - { - return false; - } - - if (fDist < 512) - fScale = 192.0 / fDist + 0.25; - else - fScale = 1.0 - 192.0 / fDist; - - - - vEnd = vStart + vDelta; - - - vDelta[0] *= fScale; - vDelta[1] *= fScale; - - *pvVel = CalcKickVelocity(vDelta, fScale * fDist); - - - if (*pvVel == vec_zero || !ValidGrenadePath(vStart, vEnd, *pvVel)) - { - return false; - } - else - { - return true; - } -} - -/* -=============== -Actor::GrenadeWillHurtTeamAt - -Returns true if grenade will hurt team at vTo. -=============== -*/ -bool Actor::GrenadeWillHurtTeamAt - ( - const Vector& vTo - ) -{ - if (m_pNextSquadMate == this) - { - return false; - } - - for (Actor * pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer()) - { - if ((pSquadMate->origin-vTo).length() <= 65536) - { - return true; - } - } - return false; -} - -/* -=============== -Actor::CanGetGrenadeFromAToB - -Returns true if actor can get a grenade from vFrom to vTo. -pvVel is the kick/roll/throw velocity. -peMode is the possible toss mode. -=============== -*/ -bool Actor::CanGetGrenadeFromAToB - ( - const Vector& vFrom, - const Vector& vTo, - bool bDesperate, - Vector *pvVel, - eGrenadeTossMode *peMode - ) -{ - float fDot; - Vector vHint; - Vector vStart; - Vector vAxisY; - Vector vAxisX; - Vector vDelta; - Vector vDelta2 = vec_zero; - int nHints; - GrenadeHint *apHint[4]; - float fRangeSquared; - - if (sv_gravity->value <= 0) - return false; - - vDelta = vTo - vFrom; - fRangeSquared = vDelta.lengthSquared(); - - //range < 256 - if (fRangeSquared < Square(256)) - return false; - if (bDesperate) - { - vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADERETURN_SCR); - } - - //range < 32 - if (fRangeSquared < Square(1024)) - { - if (!bDesperate) - { - vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETOSS_SCR); - } - - *pvVel = CanRollGrenade(vStart, vTo); - - if (*pvVel != vec_zero) - { - *peMode = AI_GREN_TOSS_ROLL; - return true; - } - - if (!bDesperate) - { - vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR); - } - - *pvVel = CanThrowGrenade(vStart, vTo); - - if (*pvVel != vec_zero) - { - *peMode = AI_GREN_TOSS_THROW; - return true; - } - } - - if (!bDesperate) - { - return false; - } - - nHints = GrenadeHint::GetClosestSet(apHint, 4, vStart, Square(1024)); - - for (int i = 0; i <= nHints; i++) - { - if (bDesperate) - { - vStart = GrenadeThrowPoint(vFrom, vDelta2, STRING_ANIM_GRENADERETURN_SCR); - if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode)) - return true; - continue; - } - - vHint = apHint[i]->origin; - vDelta2 = vHint - vFrom; - - fDot = DotProduct2D(vDelta2, vDelta); - if (fDot >= 0 && fDot * fDot <= vDelta.lengthXYSquared() * vDelta2.lengthXYSquared() * 0.89999998) - { - vStart = GrenadeThrowPoint(vFrom, vDelta2, STRING_ANIM_GRENADETOSS_SCR); - if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode)) - return true; - } - - - } - - *peMode = AI_GREN_TOSS_NONE; - return false; -} - -/* -=============== -Actor::DecideToThrowGrenade - -Returns true if actor will throw grenade to vTo. -pvVel is the kick/roll/throw velocity. -peMode is the toss mode. -=============== -*/ -bool Actor::DecideToThrowGrenade - ( - const Vector& vTo, - Vector *pvVel, - eGrenadeTossMode *peMode - ) -{ - if (Sentient::AmmoCount("grenade")) - { - if (!GrenadeWillHurtTeamAt(vTo)) - { - return CanGetGrenadeFromAToB(origin, vTo, false, pvVel, peMode); - } - } - return false; -} - -/* -=============== -Actor::Grenade_EventFire - -Throw grenade animation -=============== -*/ -void Actor::Grenade_EventFire - ( - Event *ev - ) -{ - const_str csAnim; - str strGrenade; - float speed; - Vector pos, dir, vStart; - - gi.Tag_NumForName(edict->tiki, "tag_weapon_right"); - - if (m_eGrenadeMode == AI_GREN_TOSS_ROLL) - { - csAnim = STRING_ANIM_GRENADETHROW_SCR; - } - else - { - csAnim = STRING_ANIM_GRENADETOSS_SCR; - } - - vStart = GrenadeThrowPoint(origin, orientation[0], csAnim); - - dir = m_vGrenadeVel; - - speed = VectorNormalize(dir); - - if (m_Team == TEAM_AMERICAN) - { - strGrenade = "models/projectiles/M2FGrenade.tik"; - } - else - { - strGrenade = "models/projectiles/steilhandgranate.tik"; - } - - ProjectileAttack(vStart, dir, this, strGrenade, 0, speed); - - UseAmmo("grenade", 1); - -} - -/* -=============== -Actor::GenericGrenadeTossThink - -Called when actor in grenade state. -i.e. actor noticed a grenade and must think fast. -=============== -*/ -void Actor::GenericGrenadeTossThink - ( - void - ) -{ - Vector vGrenadeVel = vec_zero; - eGrenadeTossMode eGrenadeMode; - - if (m_Enemy && level.inttime >= m_iStateTime + 200) - { - if (CanGetGrenadeFromAToB( - origin, - m_Enemy->velocity - m_Enemy->origin, - false, - &vGrenadeVel, - &eGrenadeMode)) - { - m_vGrenadeVel = vGrenadeVel; - m_eGrenadeMode = eGrenadeMode; - } - m_iStateTime = level.inttime; - } - - SetDesiredYawDir(m_vGrenadeVel); - ContinueAnimation(); -} - -/* -=============== -Actor::CanSee - -Returns true to script if actor cansee entity. -=============== -*/ -void Actor::CanSee - ( - Event *ev - ) -{ - float fov = 0; - float vision_distance = 0; - - if (m_Think[m_ThinkLevel] != THINK_MACHINEGUNNER || !m_pTurret) - { - return Entity::CanSee(ev); - } - switch (ev->NumArgs()) - { - case 1: - { - //do nothing - } - break; - case 2: - { - fov = ev->GetFloat(2); - if (fov < 0 || fov> 360) - { - ScriptError("fov must be in range 0 <= fov <= 360"); - } - } - break; - case 3: - { - vision_distance = ev->GetFloat(3); - if (vision_distance < 0) - { - ScriptError("vision distance must be >= 0"); - } - } - break; - default: - { - ScriptError("cansee should have 1, 2, or 3 arguments"); - } - break; - } - - - Entity *ent = ev->GetEntity(1); - if (!ent) - { - ScriptError("NULL entity in parameter 1"); - } - else - { - int cansee = MachineGunner_CanSee(ent, fov, vision_distance); - ev->AddInteger(cansee); - } -} - -/* -=============== -Actor::Think - -Think function for actor. -Calls think function related to the current thinkstate. -=============== -*/ -void Actor::Think - ( - void - ) -{ - int v1, v2, v3, tempHistory,ohIndex; - m_bAnimating = false; - if (g_ai->integer - && m_bDoAI - && edict->tiki) - { - //gi.DPrintf("Actor::Think 1\n"); - Director.iPaused++; - - v1 = level.inttime; - v2 = v1 / 125; - v3 = v1 / 125; - if (v1 / 125 < 0) - v3 = v2 + 3; - tempHistory = v2 - (v3 & 0xFFFFFFFC); - - if (m_iCurrentHistory != tempHistory) - { - m_iCurrentHistory = tempHistory; - ohIndex = tempHistory - 1; - if (ohIndex < 0) - { - ohIndex = 3; - } - - VectorCopy2D(origin, m_vOriginHistory[ohIndex]); - } - if (m_bNoPlayerCollision) - { - Entity *ent = G_GetEntity(0); - if (!IsTouching(ent)) - { - Com_Printf("(entnum %d, radnum %d) is going solid after not getting stuck in the player\n", entnum, radnum); - setSolidType(SOLID_BBOX); - m_bNoPlayerCollision = false; - } - } - //gi.DPrintf("Actor::Think 2\n"); - m_eNextAnimMode = -1; - FixAIParameters(); - UpdateEnableEnemy(); - - if (m_pTetherEnt) - { - m_vHome = m_pTetherEnt->origin; - } - - //gi.DPrintf("Actor::Think 3\n"); - if (m_bBecomeRunner) - { - parm.movefail = false; - if (m_ThinkMap[THINKSTATE_IDLE] != THINK_RUNNER && m_ThinkMap[THINKSTATE_IDLE] != THINK_PATROL) - { - parm.movefail = true; - } - } - - if (m_bDirtyThinkState) - { - m_bDirtyThinkState = false; - ThinkStateTransitions(); - } - - //gi.DPrintf("Actor::Think 4\n"); - GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]]; - - if (func->ThinkState) - (this->*func->ThinkState)(); - - m_bNeedReload = false; - mbBreakSpecialAttack = false; - Director.Unpause(); - - //gi.DPrintf("Actor::Think 5: entnum %d, classname: %s\n", entnum, G_GetEntity(0) ? G_GetEntity(0)->getClassname() : ""); - } -} - -/* -=============== -Actor::PostThink - -Called after think is finished. -=============== -*/ -void Actor::PostThink - ( - bool bDontFaceWall - ) -{ - CheckUnregister(); - if (bDontFaceWall) - { - if (!m_pTurnEntity || m_ThinkState != THINKSTATE_IDLE) - { - DontFaceWall(); - } - } - UpdateAngles(); - UpdateAnim(); - DoMove(); - //gi.DPrintf("Actor::PostThink 1\n"); - UpdateBoneControllers(); - //gi.DPrintf("Actor::PostThink 2\n"); - UpdateFootsteps(); + m_PotentialEnemies.RemoveAll(); + SetEnemy(NULL, false); } /* @@ -5572,40 +3144,45 @@ Actor::SetMoveInfo Copies current move information to mm. =============== */ -void Actor::SetMoveInfo - ( - mmove_t *mm - ) +void Actor::SetMoveInfo(mmove_t *mm) { - memset(mm, 0, sizeof(mmove_t)); + memset(mm, 0, sizeof(mmove_t)); - mm->velocity[0] = velocity.x; - mm->velocity[1] = velocity.y; - mm->velocity[2] = velocity.z; + velocity.copyTo(mm->velocity); + origin.copyTo(mm->origin); - mm->origin[0] = origin.x; - mm->origin[1] = origin.y; - mm->origin[2] = origin.z; + mm->entityNum = entnum; - mm->entityNum = entnum; + mm->walking = m_walking; + mm->groundPlane = m_groundPlane; + VectorCopy(m_groundPlaneNormal, mm->groundPlaneNormal); - mm->walking = m_walking; + mm->frametime = level.frametime; - mm->groundPlane = m_groundPlane; - mm->groundPlaneNormal[0] = m_groundPlaneNormal[0]; - mm->groundPlaneNormal[1] = m_groundPlaneNormal[1]; - mm->groundPlaneNormal[2] = m_groundPlaneNormal[2]; + if (m_bNoPlayerCollision) { + mm->tracemask = MASK_TARGETPATH; + } else { + mm->tracemask = MASK_PATHSOLID; + } - mm->frametime = level.frametime; + VectorCopy(MINS, mm->mins); + VectorCopy(MAXS, mm->maxs); + mm->maxs[2] = 94; +} - mm->mins[0] = MINS.x; - mm->mins[1] = MINS.y; - mm->mins[2] = MINS.z; - mm->maxs[0] = MAXS.x; - mm->maxs[1] = MAXS.y; - mm->maxs[2] = MAXS.z; +/* +=============== +Actor::DoFailSafeMove - mm->tracemask = m_bNoPlayerCollision == false ? MASK_PATHSOLID : MASK_TARGETPATH; +=============== +*/ +void Actor::DoFailSafeMove(vec3_t dest) +{ + Com_Printf("(entnum %d, radnum %d) blocked, doing failsafe\n", entnum, radnum); + + VectorCopy(dest, m_NoClipDest); + + SetThinkState(THINKSTATE_NOCLIP, THINKLEVEL_NOCLIP); } /* @@ -5615,159 +3192,110 @@ Actor::GetMoveInfo Fetch current move information from mm. =============== */ -void Actor::GetMoveInfo - ( - mmove_t *mm - ) +void Actor::GetMoveInfo(mmove_t *mm) { - //FIXME: macros - m_walking = mm->walking; - m_groundPlane = mm->groundPlane; - m_groundPlaneNormal = mm->groundPlaneNormal; - groundentity = NULL; + trace_t trace; - TouchStuff(mm); + m_walking = mm->walking; + m_groundPlane = mm->groundPlane; + VectorCopy(mm->groundPlaneNormal, m_groundPlaneNormal); + groundentity = NULL; - if (m_eAnimMode >= 2) - { - if (m_eAnimMode <= 3) - { - if (mm->hit_temp_obstacle) - { - if (mm->hit_temp_obstacle & 1) - { - m_Path.Clear(); - Player *p = (Player *)G_GetEntity(0); + TouchStuff(mm); - if (!IsTeamMate(p)) - { - if (!m_bEnableEnemy) - { - m_bDesiredEnableEnemy = true; - m_bEnableEnemy = true; - SetLeashHome(origin); - } + switch (m_eAnimMode) { + case ANIM_MODE_DEST: + if (!mm->hit_temp_obstacle && mm->hit_obstacle) { + trace = G_Trace( + m_Dest, + PLAYER_BASE_MIN, + PLAYER_BASE_MAX, + m_Dest - Vector(0, 0, 16384), + (Entity *)NULL, + MASK_MOVEINFO, + false, + "Actor::GetMoveInfo" + ); - BecomeTurretGuy(); + DoFailSafeMove(trace.endpos); + } else if (mm->hit_temp_obstacle && (mm->hit_temp_obstacle & 1)) { + Player *p; - m_PotentialEnemies.ConfirmEnemy(this, p); - m_bForceAttackPlayer = true; - } - } - velocity = vec_zero; - return; - } - if (mm->hit_obstacle) - { - if (level.inttime >= m_Path.Time() + 1000) - { - m_Path.ReFindPath(origin, this); - } - else - { - if (!m_Path.NextNode() || - (!(m_Path.NextNode()->bAccurate && m_Path.IsSide()) - && m_Path.NextNode() == m_Path.CurrentNode() - && m_Path.CurrentNode() != m_Path.StartNode()) - ) - { - m_Path.Clear(); - velocity = vec_zero; - return; - } + p = static_cast(G_GetEntity(0)); - if (m_Path.CurrentNode() == m_Path.StartNode()) - { - Com_Printf( - "^~^~^ BAD FAILSAFE: %.2f %.2f %.2f, '%s'\n", - origin[0], - origin[1], - origin[2], - targetname.c_str()); - } + if (!IsTeamMate(p)) { + if (!m_bEnableEnemy) { + m_bDesiredEnableEnemy = true; + UpdateEnableEnemy(); + } - DoFailSafeMove(m_Path.NextNode()->point); - } - } - else if (velocity.lengthXYSquared() < -0.69999999 && level.inttime >= m_Path.Time() + 1000) - { - m_Path.ReFindPath(origin, this); - } - } - else if (m_eAnimMode == 4) - { - if (mm->hit_temp_obstacle) - { - if (mm->hit_temp_obstacle & 1) - { - m_Path.Clear(); - Player *p = (Player *)G_GetEntity(0); + BecomeTurretGuy(); + ForceAttackPlayer(); + } + } + break; + case ANIM_MODE_PATH: + case ANIM_MODE_PATH_GOAL: + if (mm->hit_temp_obstacle) { + if (mm->hit_temp_obstacle & 1) { + Player *p; - if (!IsTeamMate(p)) - { - if (!m_bEnableEnemy) - { - m_bDesiredEnableEnemy = true; - m_bEnableEnemy = true; - SetLeashHome(origin); - } + m_Path.Clear(); + p = static_cast(G_GetEntity(0)); - BecomeTurretGuy(); + if (!IsTeamMate(p)) { + if (!m_bEnableEnemy) { + m_bDesiredEnableEnemy = true; + UpdateEnableEnemy(); + } - m_PotentialEnemies.ConfirmEnemy(this, p); - m_bForceAttackPlayer = true; - } - } - } - else if (mm->hit_obstacle) - { - Vector end = m_Dest; - end.z -= 16384.0; - trace_t trace = G_Trace( - Vector(m_Dest), - Vector(PLAYER_BASE_MIN), - Vector(PLAYER_BASE_MAX), - Vector(end), - NULL, - 1, - qfalse, - "Actor::GetMoveInfo"); + BecomeTurretGuy(); + ForceAttackPlayer(); + } + } - DoFailSafeMove(trace.endpos); - } - } - } + VectorClear(velocity); + } else if (mm->hit_obstacle) { + if (level.inttime >= m_Path.Time() + 1000) { + m_Path.ReFindPath(origin, this); + } else { + PathInfo *node = m_Path.NextNode(); - setOrigin(mm->origin); + if (!node + || !m_Path.IsAccurate() + && (node == m_Path.LastNode() && m_Path.CurrentNode() != m_Path.StartNode())) { + m_Path.Clear(); + VectorClear(velocity); + return; + } - if (VectorLengthSquared(mm->velocity) < 1) - { - velocity = vec_zero; - } - else - { - velocity = mm->velocity; - } + if (m_Path.CurrentNode() == m_Path.StartNode()) { + Com_Printf( + "^~^~^ BAD FAILSAFE: %.2f %.2f %.2f, '%s'\n", + origin[0], + origin[1], + origin[2], + targetname.c_str() + ); + } -} + DoFailSafeMove(node->point); + } + } else if (DotProduct2D(mm->velocity, velocity) < -0.7f && level.inttime >= m_Path.Time() + 1000) { + m_Path.ReFindPath(origin, this); + } + break; + default: + break; + } -/* -=============== -Actor::DoFailSafeMove + setOrigin(mm->origin); -=============== -*/ -void Actor::DoFailSafeMove - ( - vec3_t dest - ) -{ - Com_Printf("(entnum %d, radnum %d) blocked, doing failsafe\n", entnum, radnum); - - VectorCopy(dest, m_NoClipDest); - - - SetThinkState(THINKSTATE_NOCLIP, THINKLEVEL_NOCLIP); + if (VectorLengthSquared(mm->velocity) < 1) { + VectorClear(velocity); + } else { + VectorCopy(mm->velocity, velocity); + } } /* @@ -5776,66 +3304,1636 @@ Actor::TouchStuff =============== */ -void Actor::TouchStuff - ( - mmove_t *mm - ) +void Actor::TouchStuff(mmove_t *mm) { - int i, j; - gentity_t *other; - Event *event; + int i, j; + gentity_t *other; + Event *event; - if (getMoveType() != MOVETYPE_NOCLIP) - { - G_TouchTriggers( this ); - } + if (getMoveType() != MOVETYPE_NOCLIP) { + G_TouchTriggers(this); + } - for (i = 0; i < mm->numtouch; i++) - { - other = &g_entities[mm->touchents[i]]; + for (i = 0; i < mm->numtouch; i++) { + other = &g_entities[mm->touchents[i]]; - for (j = 0; j < i; j++) - { - gentity_t *ge = &g_entities[j]; + for (j = 0; j < i; j++) { + if (&g_entities[j] == other) { + break; + } + } - if (ge == other) - break; - } + if (j != i) { + // duplicated + continue; + } - if (j != i) - { - // duplicated - continue; - } + // Don't bother touching the world + if (!other->entity || other->entity == world) { + continue; + } - // Don't bother touching the world - if ((!other->entity) || (other->entity == world)) - { - continue; - } + event = new Event(EV_Touch); + event->AddEntity(this); + other->entity->ProcessEvent(event); - event = new Event(EV_Touch); - event->AddEntity(this); - other->entity->ProcessEvent(event); - - event = new Event(EV_Touch); - event->AddEntity(other->entity); - ProcessEvent(event); - } + event = new Event(EV_Touch); + event->AddEntity(other->entity); + ProcessEvent(event); + } } /* =============== -Actor::ExtractConstraints +Actor::ResetBoneControllers +Reset Bone Controllers. =============== */ -void Actor::ExtractConstraints - ( - mmove_t *mm - ) +void Actor::ResetBoneControllers(void) { - // not found in ida + if (edict->s.bone_tag[HEAD_TAG] != -1) { + SetControllerAngles(HEAD_TAG, vec_zero); + } + if (edict->s.bone_tag[TORSO_TAG] != -1) { + SetControllerAngles(TORSO_TAG, vec_zero); + } + if (edict->s.bone_tag[ARMS_TAG] != -1) { + SetControllerAngles(ARMS_TAG, vec_zero); + } +} + +/* +=============== +Actor::UpdateBoneControllers + +Update Bone Controllers. +Reversed incorrectly, since decompiled output has different behaviour as reversed output. +=============== +*/ +void Actor::UpdateBoneControllers(void) +{ + float pitchError, yawError, error; + float max_change, max_accel_change, min_accel_change; + Vector headAngles, torsoAngles; + float tolerable_error; + vec3_t LocalLookAngles; + float torsoYawError; + + if (m_bHasDesiredLookAngles) { + vec3_t myAxis[3]; + vec3_t eyePosition; + vec3_t lookAxis[3]; + vec3_t endPosition; + vec3_t worldLookAngles; + vec3_t lineVec; + int tagnum; + orientation_t tag_or; + Vector vError; + + if (g_showlookat->integer == entnum || g_showlookat->integer == -1) { + tagnum = gi.Tag_NumForName(edict->tiki, "eyes bone"); + tag_or = G_TIKI_Orientation(edict, tagnum & TAG_MASK); + AnglesToAxis(angles, myAxis); + + VectorCopy(origin, eyePosition); + + for (int i = 0; i < 3; i++) { + VectorMA(eyePosition, tag_or.origin[i], myAxis[i], eyePosition); + } + + Vector vEndPoint; + + if (m_bHasDesiredLookDest) { + vEndPoint = m_vDesiredLookDest; + } else if (m_pLookEntity) { + if (m_pLookEntity->IsSubclassOfSentient()) { + Sentient *sent = static_cast(m_pLookEntity.Pointer()); + vEndPoint = sent->EyePosition(); + } else { + vEndPoint = m_pLookEntity->centroid; + } + } + + for (int i = 0; i < 3; i++) { + worldLookAngles[i] = m_DesiredLookAngles[i] + angles[i]; + } + + AnglesToAxis(worldLookAngles, lookAxis); + + Vector vEndPointDir = vEndPoint - eyePosition; + vEndPointDir.normalize(); + + // calculate the error + Vector vError = vEndPointDir - lookAxis[0]; + + if (vError.length() >= 0.1f) { + VectorSet(lineVec, 128, 0, 0); + VectorCopy(eyePosition, endPosition); + + for (int i = 0; i < 3; i++) { + VectorMA(endPosition, lineVec[i], lookAxis[i], endPosition); + } + } else { + int boxalpha; + + VectorCopy(vEndPoint, endPosition); + + if (vError.length() >= 0.04f) { + boxalpha = (vError.length() - 0.1f) / 0.06f; + } else { + boxalpha = 1; + } + + G_DebugLine(vEndPoint + Vector(8, 8, 8), vEndPoint + Vector(8, 8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, -8, 8), vEndPoint + Vector(8, -8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(-8, 8, 8), vEndPoint + Vector(-8, 8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(-8, -8, 8), vEndPoint + Vector(-8, -8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, 8, 8), vEndPoint + Vector(8, -8, 8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, 8, -8), vEndPoint + Vector(8, -8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(-8, 8, 8), vEndPoint + Vector(-8, -8, 8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(-8, 8, -8), vEndPoint + Vector(-8, -8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, 8, 8), vEndPoint + Vector(-8, 8, 8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, 8, -8), vEndPoint + Vector(-8, 8, -8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, -8, 8), vEndPoint + Vector(-8, -8, 8), 0, 0, boxalpha, boxalpha); + G_DebugLine(vEndPoint + Vector(8, -8, -8), vEndPoint + Vector(-8, -8, -8), 0, 0, boxalpha, boxalpha); + } + G_DebugLine(eyePosition, endPosition, 0, 0, 1, 1); + + VectorSet(lineVec, 0, 0, -2); + for (int i = 0; i < 3; i++) { + VectorMA(eyePosition, lineVec[i], lookAxis[i], eyePosition); + VectorMA(endPosition, lineVec[i], lookAxis[i], endPosition); + } + + G_DebugLine(eyePosition, endPosition, 0, 0, 1, 1); + + VectorSet(lineVec, 0, 2, 0); + for (int i = 0; i < 3; i++) { + VectorMA(eyePosition, lineVec[i], lookAxis[i], eyePosition); + VectorMA(endPosition, lineVec[i], lookAxis[i], endPosition); + } + + G_DebugLine(eyePosition, endPosition, 0, 0, 1, 1); + } + + VectorCopy(m_DesiredLookAngles, LocalLookAngles); + + Vector EyeDelta; + Vector fwd; + + EyeDelta = LocalLookAngles; + EyeDelta.AngleVectorsLeft(&fwd, NULL, NULL); + VectorCopy(fwd, edict->s.eyeVector); + } else { + VectorClear(edict->s.eyeVector); + VectorClear(LocalLookAngles); + } + + torsoAngles = GetControllerAngles(TORSO_TAG); + headAngles = GetControllerAngles(HEAD_TAG); + + yawError = LocalLookAngles[1] - (torsoAngles[1] + headAngles[1]); + pitchError = LocalLookAngles[0] - headAngles[0]; + torsoYawError = LocalLookAngles[1] - torsoAngles[1]; + + if (torsoYawError > 180) { + torsoYawError -= 360; + } else if (torsoYawError < -180) { + torsoYawError += 360; + } + + if (torsoYawError >= 0) { + if (yawError < -120) { + yawError += 360; + } + } else { + if (yawError > 120) { + yawError -= 360; + } + } + + if (!(m_iLookFlags & 1)) { + if (yawError > 25) { + max_change = (yawError - 25) * 0.2f; + } else if (yawError < -25) { + max_change = (yawError + 25) * 0.2f; + } else { + max_change = 0; + } + + tolerable_error = yawError + headAngles[1]; + if (-torsoAngles[1] < tolerable_error) { + max_change = Q_clamp_float(max_change, -torsoAngles[1], tolerable_error); + } else { + max_change = Q_clamp_float(max_change, tolerable_error, -torsoAngles[1]); + } + + max_accel_change = m_fTorsoCurrentTurnSpeed + level.frametime * 15; + min_accel_change = m_fTorsoCurrentTurnSpeed - level.frametime * 15; + + max_change = Q_clamp_float(max_change, min_accel_change, max_accel_change); + max_change = Q_clamp_float( + max_change, level.frametime * -m_fTorsoCurrentTurnSpeed, level.frametime * m_fTorsoCurrentTurnSpeed + ); + + torsoAngles[1] += max_change; + + if (torsoAngles[1] > 30) { + max_change -= torsoAngles[1] - 30; + torsoAngles[1] = 30; + } else if (torsoAngles[1] < -30) { + max_change -= torsoAngles[1] + 30; + torsoAngles[1] = -30; + } + + m_fTorsoCurrentTurnSpeed = max_change; + + // clear pitch/roll + torsoAngles[0] = 0; + torsoAngles[2] = 0; + + SetControllerAngles(TORSO_TAG, torsoAngles); + yawError -= max_change; + } + + if (yawError > 15.f) { + max_change = (yawError - 15.f) * level.frametime * 4.f; + } else if (yawError < -15.f) { + max_change = (yawError + 15.f) * level.frametime * 4.f; + } else { + max_change = 0; + } + + if (-headAngles[1] < yawError) { + max_change = Q_clamp_float(max_change, -headAngles[1], yawError); + } else { + max_change = Q_clamp_float(max_change, yawError, -headAngles[1]); + } + + max_change = + Q_clamp_float(max_change, level.frametime * -m_fHeadMaxTurnSpeed, level.frametime * m_fHeadMaxTurnSpeed); + + headAngles[1] += max_change; + // clamp head yaw to 60 degrees + headAngles[1] = Q_clamp_float(headAngles[1], -60, 60); + + error = 15.f; + + if (fabs(LocalLookAngles[0]) < 15) { + error = fabs(LocalLookAngles[0]); + } + + if (pitchError > error) { + max_change = (pitchError - error) * 0.2f; + } else if (pitchError < -error) { + max_change = (pitchError + error) * 0.2f; + } else { + max_change = 0; + } + + max_change = + Q_clamp_float(max_change, level.frametime * -m_fHeadMaxTurnSpeed, level.frametime * m_fHeadMaxTurnSpeed); + headAngles[0] += max_change; + // clamp head pitch to 35 degrees + headAngles[0] = Q_clamp_float(headAngles[0], -35, 35); + headAngles[2] = 0; + + if (m_iLookFlags & 1) { + // half view + headAngles[0] /= 2.f; + headAngles[1] /= 2.f; + } + + SetControllerAngles(HEAD_TAG, headAngles); + + Vector tmp_angles; + Vector new_angles; + + // arms + tmp_angles = GetControllerAngles(ARMS_TAG); + + max_change = m_vLUpperArmDesiredAngles[1] - tmp_angles[1]; + if (max_change > 180) { + max_change -= 360; + } else if (max_change < -180) { + max_change += 360; + } + + max_change = + Q_clamp_float(max_change, level.frametime * -m_fLUpperArmTurnSpeed, level.frametime * m_fLUpperArmTurnSpeed); + // set the new arms angles + new_angles[0] = m_vLUpperArmDesiredAngles[0]; + new_angles[1] = tmp_angles[1] + max_change; + new_angles[2] = 0; + SetControllerAngles(ARMS_TAG, new_angles); +} + +/* +=============== +Actor::setOriginEvent +=============== +*/ +void Actor::setOriginEvent(Vector org) +{ + float dist; + bool bRejoin = false; + + dist = (org - origin).lengthSquared(); + + if (dist > Square(DEFAULT_NEARBY_SQUAD_DIST)) { + bRejoin = true; + DisbandSquadMate(this); + } + + m_iOriginTime = level.inttime; + + VectorCopy2D(org, m_vOriginHistory[0]); + VectorCopy2D(org, m_vOriginHistory[1]); + VectorCopy2D(org, m_vOriginHistory[2]); + VectorCopy2D(org, m_vOriginHistory[3]); + + VectorClear(velocity); + + if (level.Spawned()) { + SafeSetOrigin(org); + } else { + setOrigin(org); + } + + m_vHome = origin; + + if (bRejoin) { + JoinNearbySquads(DEFAULT_NEARBY_SQUAD_DIST); + } + + if (dist > Square(MIN_BADPLACE_UPDATE_DIST)) { + UpdateBadPlaces(); + } +} + +/* +=============== +Actor::SafeSetOrigin + +Safe set origin. +=============== +*/ +void Actor::SafeSetOrigin(vec3_t newOrigin) +{ + // don't update the origin if it's the same + if (newOrigin == origin) { + return; + } + + setOrigin(newOrigin); + + if (!m_bNoPlayerCollision) { + Player *p = (Player *)G_GetEntity(0); + + // Added in 2.30 + // Solidity check. + // If the Actor is already nonsolid the player won't get stuck + if (p && IsTouching(p) && getSolidType() != SOLID_NOT) { + Com_Printf("(entnum %d, radnum %d) is going not solid to not get stuck in the player\n", entnum, radnum); + m_bNoPlayerCollision = true; + setSolidType(SOLID_NOT); + } + } +} + +/* +=============== +Actor::DoMove + +Move the actor based on m_eAnimMode. +=============== +*/ +void Actor::DoMove(void) +{ + mmove_t mm; + trace_t trace; + + if (m_eAnimMode != ANIM_MODE_ATTACHED + && (!m_bDoPhysics || m_iOriginTime == level.inttime || m_pGlueMaster || bindmaster)) { + return; + } + + switch (m_eAnimMode) { + case ANIM_MODE_NORMAL: + SetMoveInfo(&mm); + + VectorCopy2D(frame_delta, mm.desired_dir); + mm.desired_speed = VectorNormalize2D(mm.desired_dir) / level.frametime; + + if (mm.desired_speed > m_maxspeed) { + mm.desired_speed = m_maxspeed; + } + + MmoveSingle(&mm); + GetMoveInfo(&mm); + break; + case ANIM_MODE_PATH: + MovePath(frame_delta.length() / level.frametime); + break; + case ANIM_MODE_PATH_GOAL: + MovePathGoal(frame_delta.length() / level.frametime); + break; + case ANIM_MODE_DEST: + MoveDest(frame_delta.length() / level.frametime); + break; + case ANIM_MODE_SCRIPTED: + setAngles(angles + Vector(0, angular_delta, 0)); + trace = G_Trace( + origin, mins, maxs, origin + frame_delta, this, edict->clipmask & ~MASK_SCRIPT_SLAVE, true, "Actor" + ); + SafeSetOrigin(trace.endpos); + velocity = frame_delta / level.frametime; + break; + case ANIM_MODE_NOCLIP: + setAngles(angles + Vector(0, angular_delta, 0)); + SafeSetOrigin(origin + frame_delta); + velocity = frame_delta / level.frametime; + break; + case ANIM_MODE_FALLING_PATH: + SafeSetOrigin(m_pFallPath->pos[m_pFallPath->currentPos]); + m_pFallPath->currentPos++; + velocity = vec_zero; + break; + case ANIM_MODE_ATTACHED: + { + Vector frame_offset; + Vector attach_angles; + + frame_offset = edict->s.attach_offset; + frame_offset += frame_delta; + frame_offset.copyTo(edict->s.attach_offset); + setOrigin(); + + attach_angles = angles; + attach_angles[1] += angular_delta; + setAngles(attach_angles); + + velocity = frame_delta / level.frametime; + break; + } + default: + break; + } + + m_maxspeed = 1000000.0f; +} + +/* +=============== +Actor::UpdateAngles + +Update current angles. +=============== +*/ +void Actor::UpdateAngles(void) +{ + float max_change, error, dist; + + if (m_YawAchieved) { + return; + } + + error = m_DesiredYaw - angles[1]; + if (error > 180) { + error -= 360; + } else if (error < -180) { + error += 360; + } + + dist = m_fAngleYawSpeed * level.frametime; + if (error < -dist) { + max_change = -dist; + } else if (error > dist) { + max_change = dist; + } else { + max_change = error; + StopTurning(); + } + + setAngles(Vector(0, angles[1] + max_change, 0)); +} + +/* +=============== +Actor::SetLeashHome + +Set leash home. +=============== +*/ +void Actor::SetLeashHome(Vector vHome) +{ + if (!m_bFixedLeash) { + m_vHome = vHome; + } +} + +/* +=============== +Actor::GunPosition + +Returns current gun position. +=============== +*/ +Vector Actor::GunPosition(void) +{ + if (m_iGunPositionCheckTime < level.inttime) { + m_iGunPositionCheckTime = level.inttime; + Weapon *weap = GetActiveWeapon(WEAPON_MAIN); + if (weap) { + weap->GetMuzzlePosition(m_vGunPosition); + } else { + m_vGunPosition = vec_zero; + } + } + return m_vGunPosition; +} + +/* +=============== +Actor::CanSee + +Returns true if actor cansee entity through fov and vision_distance. +=============== +*/ +bool Actor::CanSee(Entity *e1, float fov, float vision_distance, bool bNoEnts) +{ + bool bCanSee = Sentient::CanSee(e1, fov, vision_distance, false); + if (e1 == m_Enemy) { + m_iEnemyVisibleCheckTime = level.inttime; + // Added in 2.0. + // Check for obfuscation like smoke sprite + m_fVisibilityAlpha = 0; + if (bCanSee) { + m_fVisibilityAlpha = 1.0f - G_VisualObfuscation(VirtualEyePosition(), m_Enemy->EyePosition()); + if (m_fVisibilityAlpha < m_fVisibilityThreshold) { + // enemy is obfuscated behind something + bCanSee = false; + } + } + + if (bCanSee) { + SetEnemyPos(m_Enemy->origin); + m_bEnemyIsDisguised = m_Enemy->m_bIsDisguised; + m_iLastEnemyVisibleTime = level.inttime; + } + + if (bCanSee != m_bEnemyVisible) { + m_bEnemyVisible = !m_bEnemyVisible; + m_iEnemyVisibleChangeTime = level.inttime; + } + + if (fov != 0) { + m_iEnemyFovCheckTime = level.inttime; + if (bCanSee != m_bEnemyInFOV) { + m_bEnemyInFOV = !m_bEnemyInFOV; + m_iEnemyFovChangeTime = level.inttime; + } + } + } + + return bCanSee; +} + +/* +=============== +Actor::WithinVisionDistance + +Returns true if entity is witthin vision distance. +=============== +*/ +bool Actor::WithinVisionDistance(Entity *ent) const +{ + float distance = world->farplane_distance; + + if (!distance || distance < m_fSight) { + return WithinDistance(ent, m_fSight); + } + + return WithinDistance(ent, distance); +} + +/* +=============== +Actor::InFOV + +Returns true if positin is within fov. +=============== +*/ +bool Actor::InFOV(Vector pos, float check_fov, float check_fovdot) +{ + if (check_fov == 360) { + return true; + } + + Vector delta = pos - VirtualEyePosition(); + if (!delta.x && !delta.y) { + return true; + } + + float fDot = DotProduct2D(delta, orientation[0]); + if (fDot < 0) { + return false; + } + + return Square(fDot) > (delta.lengthXYSquared() * Square(check_fovdot)); +} + +/* +=============== +Actor::CanShoot + +Returns true if actor can shoot entity. +=============== +*/ +bool Actor::CanShoot(Entity *ent) +{ + bool bCanShoot = false; + Vector vGunPos; + + if (FriendlyInLineOfFire(ent)) { + // Added in 2.0 + // Check if a friend is in sight + bCanShoot = false; + } else if (ent->IsSubclassOfSentient()) { + Sentient *sen = static_cast(ent); + + vGunPos = GunPosition(); + bCanShoot = false; + + if (WithinFarplaneDistance(origin - ent->origin) && AreasConnected(ent)) { + if (G_SightTrace( + vGunPos, + vec_zero, + vec_zero, + sen->centroid, + this, + sen, + MASK_CANSEE, + false, + "Actor::CanShoot centroid" + )) { + bCanShoot = true; + } else if (G_SightTrace( + vGunPos, + vec_zero, + vec_zero, + sen->EyePosition(), + this, + sen, + MASK_CANSEE, + false, + "Actor::CanShoot eyes" + )) { + bCanShoot = true; + } + } + } else { + bCanShoot = false; + if (AreasConnected(ent)) { + vGunPos = GunPosition(); + bCanShoot = CanSeeFrom(vGunPos, ent); + } + } + + if (ent == m_Enemy) { + m_iCanShootCheckTime = level.inttime; + m_bCanShootEnemy = bCanShoot; + } + + return bCanShoot; +} + +/* +=============== +Actor::CanSeeFrom + +Returns true if actor can see entity from pos. +=============== +*/ +bool Actor::CanSeeFrom(vec3_t pos, Entity *ent) +{ + if (!WithinFarplaneDistance(pos)) { + // outside the farplane + return false; + } + + if (ent->flags & FL_NOTARGET) { + // ent must be ignored by AI + return false; + } + + return G_SightTrace(pos, vec_zero, vec_zero, ent->centroid, this, ent, MASK_CANSEE, false, "Actor::CanSeeFrom"); +} + +/* +=============== +Actor::EnemyInFOV + +Returns true if enemy is within fov. +=============== +*/ +bool Actor::EnemyInFOV(int iMaxDirtyTime) +{ + if (level.inttime > iMaxDirtyTime + m_iEnemyFovCheckTime) { + if (m_bEnemyInFOV != InFOV(m_Enemy->centroid)) { + m_bEnemyInFOV = !m_bEnemyInFOV; + m_iEnemyFovChangeTime = level.inttime; + } + m_iEnemyFovCheckTime = level.inttime; + } + + return m_bEnemyInFOV; +} + +/* +=============== +Actor::CanSeeEnemy + +Returns true if actor can see enemy. +=============== +*/ +bool Actor::CanSeeEnemy(int iMaxDirtyTime) +{ + if (level.inttime > iMaxDirtyTime + m_iEnemyVisibleCheckTime) { + CanSee(m_Enemy, 0, world->farplane_distance * 0.828f, false); + } + + return m_bEnemyVisible; +} + +/* +=============== +Actor::CanShootEnemy + +Returns true if actor can shoot enemy. +=============== +*/ +bool Actor::CanShootEnemy(int iMaxDirtyTime) +{ + if (level.inttime > iMaxDirtyTime + m_iCanShootCheckTime) { + CanShoot(m_Enemy); + } + + return m_bCanShootEnemy; +} + +/* +=============== +Actor::FriendlyInLineOfFire +=============== +*/ +bool Actor::FriendlyInLineOfFire(Entity *other) +{ + Vector delta; + float inverseDot; + + if (g_target_game <= target_game_e::TG_MOH) { + return false; + } + + delta = other->origin - origin; + inverseDot = 1.0 / (delta * delta); + + for (Sentient *pSquad = m_pNextSquadMate; pSquad != this; pSquad = pSquad->m_pNextSquadMate) { + Vector squadDelta; + float squadDot; + + squadDelta = pSquad->origin - origin; + squadDot = squadDelta * delta; + if (squadDot >= 0) { + Vector org; + + org = squadDot * inverseDot * delta - squadDelta; + if (org * org >= Square(64)) { + return true; + } + } + } + + return false; +} + +/* +=============== +Actor::VirtualEyePosition +=============== +*/ +Vector Actor::VirtualEyePosition() +{ + if (m_pTurret && CurrentThink() == THINK_MACHINEGUNNER) { + // return the turret eye position + return m_pTurret->EyePosition(); + } else { + return EyePosition(); + } +} + +/* +=============== +Actor::CanTarget + +Actor can target. +=============== +*/ +bool Actor::CanTarget(void) +{ + return true; +} + +/* +=============== +Actor::IsImmortal + +Actor is immortal ? +=============== +*/ +bool Actor::IsImmortal(void) +{ + return false; +} + +/* +=============== +Actor::ShowInfo + +Prints basic actor information. +=============== +*/ +void Actor::ShowInfo(void) +{ + Com_Printf("-------------------------------------------------------------------------------\n"); + Com_Printf("Info for Actor:\n"); + Com_Printf("Current think type: %s %s\n", ThinkStateName().c_str(), ThinkName().c_str()); + Com_Printf("leash: %f\n", m_fLeash); + Com_Printf("mindist: %f\n", m_fMinDistance); + Com_Printf("maxdist: %f\n", m_fMaxDistance); + + GlobalFuncs_t *func = &GlobalFuncs[CurrentThink()]; + if (func->ShowInfo) { + (this->*func->ShowInfo)(); + } + + Com_Printf("-------------------------------------------------------------------------------\n"); +} + +/* +=============== +Actor::ShowInfo + +Display actor info. +=============== +*/ +void Actor::ShowInfo(float fDot, float fDist) +{ + float fMaxDist, fMinDot; + static cvar_t *g_entinfo_max; + + if (!bEntinfoInit) { + g_entinfo_max = gi.Cvar_Get("g_entinfo_max", "2048", 0); + bEntinfoInit = true; + } + + fMinDot = 0.9f; + fMaxDist = g_entinfo_max->value; + + if (IsKilledState(m_ThinkState)) { + fMinDot = 0.99f; + fMaxDist = 512; + } + + if (g_entinfo->integer != 4) { + if (fDot <= fMinDot) { + if (fDot <= 0 || fDist >= 256) { + return; + } + } + + if (fMaxDist <= fDist || fDist <= 64) { + return; + } + } + if (!m_bEnableEnemy) { + Vector a = origin; + a.z += maxs.z + 74; + + G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "DISABLED"); + } + + { + Vector a = origin; + a.z += maxs.z + 56; + + G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "%i:%i:%s:%.1f", entnum, radnum, targetname.c_str(), health); + } + + if (m_Enemy) { + Vector a = origin; + a.z += maxs.z + 38; + + G_DebugString( + a, + 1.0, + 1.0, + 1.0, + 1.0, + "%i:%s:%.1f:%i", + m_Enemy->entnum, + m_Enemy->targetname.c_str(), + m_Enemy->health, + m_PotentialEnemies.GetCurrentThreat() + ); + } + + if (IsCuriousState(m_ThinkState)) { + Vector a = origin; + a.z += maxs.z + 20; + + G_DebugString( + a, + 1.0, + 1.0, + 1.0, + 1.0, + "%s:%%%.1f", + Director.GetString(m_csThinkStateNames[THINKSTATE_CURIOUS]).c_str(), + m_PotentialEnemies.GetCurrentVisibility() * 100 + ); + } else { + Vector a = origin; + a.z += maxs.z + 20; + + G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "%s", ThinkStateName().c_str()); + } + + { + Vector a = origin; + a.z += maxs.z + 2; + + str sAnimThreadFile = m_pAnimThread ? m_pAnimThread->FileName() : "(null)"; + + G_DebugString( + a, + 1.0, + 1.0, + 1.0, + 1.0, + "%s:%s:%i - %s", + ThinkName().c_str(), + m_pszDebugState, + m_State, + sAnimThreadFile.c_str() + ); + } + + if (g_entinfo->integer == 1) { + if (m_pGrenade) { + G_DebugLine(m_pGrenade->origin, m_vGrenadePos, 1.0, 0.0, 0.0, 1.0); + } + + Vector a = m_vHome; + a.z += maxs.z + 18; + + G_DebugLine(centroid, a, 0.0, 1.0, 0.0, 1.0); + + G_DebugCircle(a, m_fLeash, 0.0, 1.0, 0.0, 1.0, true); + + G_DebugCircle(centroid, m_fMinDistance, 1.0, 0.0, 0.0, 1.0, true); + + G_DebugCircle(centroid, m_fMaxDistance, 0.0, 0.0, 1.0, 1.0, true); + } else if (g_entinfo->integer == 2) { + G_DebugCircle(centroid, m_fHearing, 1.0, 0.0, 0.0, 1.0, true); + G_DebugCircle(centroid, m_fSight, 0.0, 0.0, 1.0, 1.0, true); + } +} + +/* +=============== +Actor::ThinkName +=============== +*/ +str Actor::ThinkName(void) const +{ + return Director.GetString(m_csThinkNames[CurrentThink()]); +} + +/* +=============== +Actor::ThinkStateName +=============== +*/ +str Actor::ThinkStateName(void) const +{ + return Director.GetString(m_csThinkStateNames[m_ThinkState]); +} + +/* +=============== +Actor::MoveTo + +Move actor to specific location/listener with specific animation. +=============== +*/ +void Actor::MoveTo(Event *ev) +{ + m_csPatrolCurrentAnim = ev->GetConstString(1); + + if (ev->IsVectorAt(2)) { + Vector vec = ev->GetVector(2); + SetPatrolCurrentNode(vec); + } else { + SetPatrolCurrentNode(ev->GetListener(2)); + } + + if (m_patrolCurrentNode) { + m_vScriptGoal = origin; + m_bScriptGoalValid = true; + } + + SetThinkIdle(THINK_RUNNER); +} + +/* +=============== +Actor::WalkTo + +Walk to specific location. +=============== +*/ +void Actor::WalkTo(Event *ev) +{ + Event event = Event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_WALKTO_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::RunTo + +Run to specific location. +=============== +*/ +void Actor::RunTo(Event *ev) +{ + Event event = Event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_RUNTO_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::CrouchTo + +Crouch to specific location. +=============== +*/ +void Actor::CrouchTo(Event *ev) +{ + Event event = Event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_CROUCHTO_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::CrawlTo + +Crawl to specific location. +=============== +*/ +void Actor::CrawlTo(Event *ev) +{ + Event event = Event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_CRAWLTO_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::ClearAimNode + +Clear aim node. +=============== +*/ +void Actor::ClearAimNode(void) +{ + if (m_aimNode) { + if (m_aimNode->IsSubclassOfTempWaypoint()) { + delete m_aimNode; + } + m_aimNode = NULL; + } +} + +/* +=============== +Actor::SetAimNode + +Change aim node. +=============== +*/ +void Actor::SetAimNode(const Vector& vec) +{ + ClearAimNode(); + + m_aimNode = new TempWaypoint(); + m_aimNode->setOrigin(vec); +} + +/* +=============== +Actor::SetAimNode + +Change aim node. +=============== +*/ +void Actor::SetAimNode(Listener *l) +{ + ClearAimNode(); + if (l) { + if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) { + ScriptError( + "Bad aim node with classname '%s' specified for '%s' at (%f %f %f)\n", + l->getClassname(), + targetname.c_str(), + origin.x, + origin.y, + origin.z + ); + } + m_aimNode = (SimpleEntity *)l; + } +} + +/* +=============== +Actor::AimAt + +Aim at specified target. +=============== +*/ +void Actor::AimAt(Event *ev) +{ + if (ev->IsVectorAt(1)) { + SetAimNode(ev->GetVector(1)); + } else { + SetAimNode(ev->GetListener(1)); + } + + SetThinkIdle(m_aimNode ? THINK_AIM : THINK_IDLE); +} + +/* +=============== +Actor::LookAtLookEntity + +Change current look entity. +=============== +*/ +void Actor::LookAtLookEntity(void) +{ + Vector dir; + + if (m_pLookEntity->IsSubclassOfSentient()) { + Sentient *sen = static_cast(m_pLookEntity.Pointer()); + dir = sen->EyePosition() - EyePosition(); + } else { + dir = m_pLookEntity->centroid - EyePosition(); + } + + SetDesiredLookDir(dir); +} + +/* +=============== +Actor::IdleLook + +Idle look behaviour. +=============== +*/ +void Actor::IdleLook(void) +{ + if (m_pLookEntity) { + LookAtLookEntity(); + } else { + ForwardLook(); + } +} + +/* +=============== +Actor::IdleLook + +Idle look behaviour. +=============== +*/ +void Actor::IdleLook(vec3_t dir) +{ + if (m_pLookEntity) { + LookAtLookEntity(); + } else { + SetDesiredLookDir(dir); + } +} + +/* +=============== +Actor::ClearLookEntity + +Clear look entity. +=============== +*/ +void Actor::ClearLookEntity(void) +{ + if (m_pLookEntity) { + if (m_pLookEntity->IsSubclassOfTempWaypoint()) { + delete m_pLookEntity; + } + m_pLookEntity = NULL; + } +} + +/* +=============== +Actor::LookAt + +Change current look entity. +=============== +*/ +void Actor::LookAt(const Vector& vec) +{ + if (g_showlookat->integer == entnum || g_showlookat->integer == -1) { + Com_Printf( + "Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n", + entnum, + radnum, + targetname.c_str(), + vec.x, + vec.y, + vec.z + ); + } + + ClearLookEntity(); + + m_pLookEntity = new TempWaypoint(); + m_pLookEntity->setOrigin(vec); +} + +/* +=============== +Actor::LookAt + +Change current look entity. +=============== +*/ +void Actor::LookAt(Listener *l) +{ + ClearLookEntity(); + if (!l) { + if (g_showlookat->integer == entnum || g_showlookat->integer == -1) { + Com_Printf("Script lookat: %i %i %s cleared lookat\n", entnum, radnum, TargetName().c_str()); + } + return; + } + + if (!l->isSubclassOf(SimpleEntity)) { + ScriptError( + "Bad look entity with classname '%s' specified for '%s' at (%f %f %f)\n", + l->getClassname(), + targetname.c_str(), + origin.x, + origin.y, + origin.z + ); + } + + if (l != this) { + l = (SimpleEntity *)l; + if (g_showlookat->integer == entnum || g_showlookat->integer == -1) { + Com_Printf( + "Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n", + entnum, + radnum, + targetname.c_str(), + ((SimpleEntity *)l)->origin.x, + ((SimpleEntity *)l)->origin.y, + ((SimpleEntity *)l)->origin.z + ); + } + m_pLookEntity = (SimpleEntity *)l; + } +} + +/* +=============== +Actor::EventLookAt + +Look at event. +=============== +*/ +void Actor::EventLookAt(Event *ev) +{ + if (ev->IsVectorAt(1)) { + LookAt(ev->GetVector(1)); + } else { + LookAt(ev->GetListener(1)); + } + + m_iLookFlags = 0; +} + +/* +=============== +Actor::EventEyesLookAt + +Eyes look at event. +=============== +*/ +void Actor::EventEyesLookAt(Event *ev) +{ + EventLookAt(ev); + + m_iLookFlags = LOOK_FLAG_EYE; +} + +/* +=============== +Actor::NoPoint + +Don't point at anything. +=============== +*/ +void Actor::NoPoint(void) +{ + VectorClear(m_vLUpperArmDesiredAngles); +} + +/* +=============== +Actor::IdlePoint + +Idle point behaviour. +=============== +*/ +void Actor::IdlePoint(void) +{ + if (!m_pPointEntity) { + NoPoint(); + return; + } + + Vector delta = m_pPointEntity->centroid - origin; + delta.normalize(); + + Vector pointAngles = delta.toAngles(); + pointAngles.y -= angles.y; + + pointAngles += Vector(0, 30, 0); + pointAngles.y = AngleNormalize180(delta.y); + pointAngles.y = Q_clamp_float(pointAngles.y, -80, 100); + + m_vLUpperArmDesiredAngles[0] = pointAngles[0]; + m_vLUpperArmDesiredAngles[1] = pointAngles[1]; + m_vLUpperArmDesiredAngles[2] = pointAngles[2]; +} + +/* +=============== +Actor::ClearPointEntity + +Clear point entity. +=============== +*/ +void Actor::ClearPointEntity(void) +{ + if (m_pPointEntity) { + if (m_pPointEntity->IsSubclassOfTempWaypoint()) { + delete m_pPointEntity; + } + m_pPointEntity = NULL; + } +} + +/* +=============== +Actor::PointAt + +Change point entity. +=============== +*/ +void Actor::PointAt(const Vector& vec) +{ + ClearPointEntity(); + + m_pPointEntity = new TempWaypoint(); + m_pPointEntity->setOrigin(vec); +} + +/* +=============== +Actor::PointAt + +Change point entity. +=============== +*/ +void Actor::PointAt(Listener *l) +{ + ClearPointEntity(); + + if (l) { + if (l->isSubclassOf(SimpleEntity)) { + ScriptError( + "Bad point entity with classname '%s' specified for '%s' at (%f %f %f)\n", + l->getClassname(), + targetname.c_str(), + origin.x, + origin.y, + origin.z + ); + } + + if (l != this) { + m_pPointEntity = static_cast(l); + } + } +} + +/* +=============== +Actor::EventPointAt + +Point at event. +=============== +*/ +void Actor::EventPointAt(Event *ev) +{ + if (ev->IsVectorAt(1)) { + PointAt(ev->GetVector(1)); + } else { + PointAt(ev->GetListener(1)); + } +} + +/* +=============== +Actor::IdleTurn + +Idle turn behaviour. +=============== +*/ +void Actor::IdleTurn(void) +{ + if (!m_pTurnEntity) { + return; + } + + for (int i = 0; i < 2; i++) { + if (m_pTurnEntity == this) { + StopTurning(); + m_pTurnEntity = NULL; + return; + } + + SetDesiredYawDest(m_pTurnEntity->centroid); + + float error = m_DesiredYaw - angles[1]; + if (error > 180) { + error -= 360; + } else if (error < -180) { + error += 360; + } + + if (error >= m_fTurnDoneError + 0.001f || error <= -m_fTurnDoneError - 0.001f) { + return; + } + + SafePtr prevTurnEntity = m_pTurnEntity; + + Director.Unpause(); + Unregister(STRING_TURNDONE); + Director.Pause(); + + if (m_pTurnEntity == prevTurnEntity) { + break; + } + } +} + +/* +=============== +Actor::ClearTurnEntity + +Clear turn entity. +=============== +*/ +void Actor::ClearTurnEntity(void) +{ + if (m_pTurnEntity) { + if (m_pTurnEntity->IsSubclassOfTempWaypoint()) { + delete m_pTurnEntity; + } + m_pTurnEntity = NULL; + } +} + +/* +=============== +Actor::TurnTo + +Change turn entity. +=============== +*/ +void Actor::TurnTo(const Vector& vec) +{ + ClearTurnEntity(); + + m_pTurnEntity = new TempWaypoint(); + m_pTurnEntity->setOrigin(vec); +} + +/* +=============== +Actor::TurnTo + +Change turn entity. +=============== +*/ +void Actor::TurnTo(Listener *l) +{ + ClearTurnEntity(); + + if (!l) { + m_pTurnEntity = this; + return; + } + + if (!l->isSubclassOf(SimpleEntity)) { + ScriptError( + "Bad turn entity with classname '%s' specified for '%s' at (%f %f %f)\n", + l->getClassname(), + targetname.c_str(), + origin.x, + origin.y, + origin.z + ); + } + + m_pTurnEntity = (SimpleEntity *)l; +} + +/* +=============== +Actor::EventTurnTo + +Turn to event. +=============== +*/ +void Actor::EventTurnTo(Event *ev) +{ + if (ev->IsVectorAt(1)) { + TurnTo(ev->GetVector(1)); + } else { + TurnTo(ev->GetListener(1)); + } +} + +/* +=============== +Actor::EventSetTurnDoneError + +Set the error amount that turndone will occur for the turnto command. +=============== +*/ +void Actor::EventSetTurnDoneError(Event *ev) +{ + m_fTurnDoneError = ev->GetFloat(1); + if (m_fTurnDoneError < 0) { + m_fTurnDoneError = 0; + ScriptError("turndoneerror was set to a negative value - capped to 0"); + } +} + +/* +=============== +Actor::EventGetTurnDoneError + +Get the error amount that turndone will occur for the turnto command. +=============== +*/ +void Actor::EventGetTurnDoneError(Event *ev) +{ + ev->AddFloat(m_fTurnDoneError); } /* @@ -5847,18 +4945,15 @@ Give weapon to actor. Called from STRING_GLOBAL_WEAPON_SCR. =============== */ -void Actor::EventGiveWeaponInternal - ( - Event *ev - ) +void Actor::EventGiveWeaponInternal(Event *ev) { - Holster(); - RemoveWeapons(); - str weapName = ev->GetString(1); - if (giveItem(weapName)) - { - Unholster(); - } + Holster(); + RemoveWeapons(); + + const str weapName = ev->GetString(1); + if (weapName.length() > 0 && giveItem(weapName)) { + Unholster(); + } } /* @@ -5868,32 +4963,27 @@ Actor::EventGiveWeapon Give weapon to actor. =============== */ -void Actor::EventGiveWeapon - ( - Event *ev - ) +void Actor::EventGiveWeapon(Event *ev) { - Event e1(EV_Listener_ExecuteScript); - str weapName = ev->GetString(1); - weapName.tolower(); - const_str csWeapName = Director.AddString(weapName); + Event event(EV_Listener_ExecuteScript); - m_csLoadOut = csWeapName; + str weapName = ev->GetString(1); + weapName.tolower(); - if (csWeapName == STRING_MG42) - { - csWeapName = STRING_MP40; - } + m_csLoadOut = Director.AddString(weapName); - m_csWeapon = csWeapName; + if (m_csLoadOut == STRING_MG42) { + m_csWeapon = STRING_MP40; + } else { + m_csWeapon = m_csLoadOut; + } - setModel(); + setModel(); - e1.AddConstString(STRING_GLOBAL_WEAPON_SCR); - e1.AddString(weapName); - glbs.Printf("EventGiveWeapon script: %s weapName: %s \n", Director.GetString(STRING_GLOBAL_WEAPON_SCR).c_str(), weapName.c_str()); - ExecuteScript(&e1); + event.AddConstString(STRING_GLOBAL_WEAPON_SCR); + event.AddString(weapName); + ExecuteScript(&event); } /* @@ -5903,1460 +4993,9 @@ Actor::EventGetWeapon Returns weapon path to script. =============== */ -void Actor::EventGetWeapon - ( - Event *ev - ) +void Actor::EventGetWeapon(Event *ev) { - ev->AddConstString(m_csWeapon); -} - -/* -=============== -Actor::FireWeapon - -Fire weapon from script. -=============== -*/ -void Actor::FireWeapon - ( - Event *ev - ) -{ - Sentient::FireWeapon(WEAPON_MAIN, FIRE_PRIMARY); -} - -/* -=============== -Actor::CanTarget - -Actor can target. -=============== -*/ -bool Actor::CanTarget - ( - void - ) -{ - return true; -} - -/* -=============== -Actor::IsImmortal - -Actor is immortal ? -=============== -*/ -bool Actor::IsImmortal - ( - void - ) -{ - return false; -} - -bool Actor::IsVoidState - ( - int state - ) -{ - return true; -} - -bool Actor::IsCuriousState - ( - int state - ) -{ - return state == THINKSTATE_CURIOUS; -} - -bool Actor::IsDisguiseState - ( - int state - ) -{ - return state == THINKSTATE_DISGUISE; -} - -bool Actor::IsAttackState - ( - int state - ) -{ - return state == THINKSTATE_ATTACK; -} - -bool Actor::IsGrenadeState - ( - int state - ) -{ - return state == THINKSTATE_GRENADE; -} - -bool Actor::IsPainState - ( - int state - ) -{ - return state == THINKSTATE_PAIN; -} - -bool Actor::IsKilledState - ( - int state - ) -{ - return state == THINKSTATE_KILLED; -} - -bool Actor::IsMachineGunnerState - ( - int state - ) -{ - return true; -} - -bool Actor::IsDogState - ( - int state - ) -{ - return true; -} - -/* -=============== -Actor::IgnoreSoundSet - -Make actor ignore iType sound. -=============== -*/ -void Actor::IgnoreSoundSet - ( - int iType - ) -{ - m_iIgnoreSoundsMask |= 1 << iType; -} - -/* -=============== -Actor::IgnoreSoundSetAll - -Make actor ignore all types of sound. -=============== -*/ -void Actor::IgnoreSoundSetAll - ( - void - ) -{ - m_iIgnoreSoundsMask = ~AI_EVENT_NONE; -} - -/* -=============== -Actor::IgnoreSoundClear - -Don't ignore iType of sound. -=============== -*/ -void Actor::IgnoreSoundClear - ( - int iType - ) -{ - m_iIgnoreSoundsMask &= ~iType; -} - -/* -=============== -Actor::IgnoreSoundClearAll - -Make actor ignore no type of sound. -=============== -*/ -void Actor::IgnoreSoundClearAll - ( - void - ) -{ - m_iIgnoreSoundsMask = 0; -} - -/* -=============== -Actor::IgnoreSoundClearAll - -returns true if actor should ignore iType of sound. -=============== -*/ -bool Actor::IgnoreSound - ( - int iType - ) -{ - return ( m_iIgnoreSoundsMask >> iType ) & 1; -} - -/* -=============== -Actor::EventShareEnemy - -Share enemy with squad mates. -=============== -*/ -void Actor::EventShareEnemy - ( - Event *ev - ) -{ - - if (m_Enemy) - { - if (!EnemyIsDisguised()) - { - for (Actor * pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer()) - { - if (pSquadMate->IsSubclassOfActor()) - { - Vector dist = pSquadMate->origin - origin; - float distSq = dist * dist; - if (pSquadMate->m_fMaxShareDistSquared == 0.0 || distSq <= pSquadMate->m_fMaxShareDistSquared) - { - pSquadMate->m_PotentialEnemies.ConfirmEnemyIfCanSeeSharerOrEnemy(pSquadMate, this, m_Enemy); - } - } - } - } - } -} - -/* -=============== -Actor::EventShareGrenade - -Share grenade with squad mates. -=============== -*/ -void Actor::EventShareGrenade - ( - Event *ev - ) -{ - - if (m_pGrenade) - { - for (Actor * pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer()) - { - if (pSquadMate->IsSubclassOfActor()) - { - if (!pSquadMate->m_pGrenade) - { - Vector dist = pSquadMate->origin - origin; - float distSq = Square(dist); - - if (distSq < Square(768)) - { - - if (DoesTheoreticPathExist(pSquadMate->origin, 1536)) - { - pSquadMate->SetGrenade(m_pGrenade); - } - } - } - } - } - } -} - -/* -=============== -Actor::ReceiveAIEvent - -Calls proper RecieveAIEvent for current ThinkState. -=============== -*/ -void Actor::ReceiveAIEvent - ( - vec3_t event_origin, - int iType, - Entity *originator, - float fDistSquared, - float fMaxDistSquared - ) -{ - if (originator != this && originator != GetActiveWeapon(WEAPON_MAIN)) - { - - GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]]; - - if (func->ReceiveAIEvent) - (this->*func->ReceiveAIEvent)(event_origin, iType, originator, fDistSquared, fMaxDistSquared); - } -} - -/* -=============== -Actor::DefaultReceiveAIEvent - -Default AI event handler. -=============== -*/ -void Actor::DefaultReceiveAIEvent - ( - vec3_t event_origin, - int iType, - Entity *originator, - float fDistSquared, - float fMaxDistSquared - ) -{ - if (!IsDead()) - { - if (!originator->IsDead() && originator->IsSubclassOfSentient() && ((Sentient *)originator)->m_Team == m_Team && !IsSquadMate((Sentient *)originator)) - { - MergeWithSquad((Sentient *)originator); - } - - switch (iType) - { - case AI_EVENT_WEAPON_FIRE: - case AI_EVENT_WEAPON_IMPACT: - if ( Square(m_fHearing) > fDistSquared) - WeaponSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator); - break; - case AI_EVENT_EXPLOSION: - case AI_EVENT_MISC: - case AI_EVENT_MISC_LOUD: - if ( Square(m_fHearing) > fDistSquared) - CuriousSound(iType, event_origin, fDistSquared, fMaxDistSquared); - break; - case AI_EVENT_AMERICAN_VOICE: - case AI_EVENT_GERMAN_VOICE: - case AI_EVENT_AMERICAN_URGENT: - case AI_EVENT_GERMAN_URGENT: - if ( Square(m_fHearing) > fDistSquared) - VoiceSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator); - break; - case AI_EVENT_FOOTSTEP: - if ( Square(m_fHearing) > fDistSquared) - FootstepSound(event_origin, fDistSquared, fMaxDistSquared, originator); - break; - case AI_EVENT_GRENADE: - GrenadeNotification(originator); - break; - default: - { - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"unknown ai_event type\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("iType = %i", iType)); - assert(false && assertStr); - } - break; - } - } -} - -/* -=============== -Actor::PriorityForEventType - -Returns priority for event type. -=============== -*/ -int Actor::PriorityForEventType - ( - int iType - ) -{ - switch( iType ) - { - - //FIXME: return macros - case AI_EVENT_WEAPON_FIRE: - return 7; - case AI_EVENT_WEAPON_IMPACT: - return 5; - case AI_EVENT_EXPLOSION: - return 6; - case AI_EVENT_AMERICAN_VOICE: - case AI_EVENT_GERMAN_VOICE: - return 3; - case AI_EVENT_AMERICAN_URGENT: - case AI_EVENT_GERMAN_URGENT: - return 4; - case AI_EVENT_MISC: - return 1; - case AI_EVENT_MISC_LOUD: - case AI_EVENT_FOOTSTEP: - return 2; - case AI_EVENT_GRENADE: - return 8; - default: - assert( !"PriorityForEventType: unknown ai_event type" ); - return 0; - } -} - -/* -=============== -Actor::CuriousSound - -Handles curious sound. -=============== -*/ -void Actor::CuriousSound - ( - int iType, - vec3_t sound_origin, - float fDistSquared, - float fMaxDistSquared - ) -{ - float v7, v8, fRangeFactor = 1.0; - int iPriority; - if (m_bEnableEnemy) - { - if (m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE || m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_CURIOUS) - { - //FIXME: name variables. - if (fMaxDistSquared != 0.0) - { - v7 = 1*(1.0/3) - fDistSquared * (1*(1.0 / 3)) / fMaxDistSquared; - if (v7 <= 1.0) - fRangeFactor = v7; - } - v8 = fRangeFactor * m_fSoundAwareness; - //FIXME: macro - if (v8 >= rand() * 0.000000046566129) - { - RaiseAlertnessForEventType(iType); - iPriority = PriorityForEventType(iType); - if (iPriority >= m_iCuriousLevel) - { - m_iCuriousLevel = iPriority; - if (iType == AI_EVENT_WEAPON_IMPACT) - { - //FIXME: macro - if (fDistSquared <= Square(192)) - SetCuriousAnimHint(1); - } - else if (iType > AI_EVENT_WEAPON_IMPACT) - { - if (iType == AI_EVENT_EXPLOSION) - { - //FIXME: macro - if (fDistSquared <= Square(768)) - SetCuriousAnimHint(3); - } - else - { - SetCuriousAnimHint(5); - } - } - else if (iType == AI_EVENT_WEAPON_FIRE) - { - //FIXME: macro - if (fDistSquared <= Square(512)) - SetCuriousAnimHint(2); - } - else - { - SetCuriousAnimHint(5); - } - - SetEnemyPos(sound_origin); - - EndCurrentThinkState(); - SetThinkState(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL); - - m_pszDebugState = G_AIEventStringFromType(iType); - } - } - } - } -} - -/* -=============== -Actor::WeaponSound - -Handles weapon sound. -=============== -*/ -void Actor::WeaponSound - ( - int iType, - vec3_t sound_origin, - float fDistSquared, - float fMaxDistSquared, - Entity *originator - ) -{ - Sentient *pOwner; - gi.Printf("Actor::WeaponSound"); - if (originator->IsSubclassOfWeapon()) - { - pOwner = ((Weapon *)originator)->GetOwner(); - } - else - { - if (!originator->IsSubclassOfProjectile()) - { - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"Actor::WeaponSound: non-weapon made a weapon sound.\\n\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("class = %s", originator->getClassname())); - assert(false && assertStr); - - return; - } - pOwner = ((Projectile *)originator)->GetOwner(); - } - - if (!pOwner) - { - return; - } - Sentient *pEnemy; - - pEnemy = pOwner->m_Enemy; - if (pOwner->m_Team == m_Team) - { - if (!pEnemy) - { - if (pOwner->IsSubclassOfActor()) - { - Actor *pAOwner = (Actor *)pOwner; - //FIXME: macro - if (originator->IsSubclassOfWeapon() && pAOwner->m_Think[0] == THINK_MACHINEGUNNER) - { - Weapon *pWOriginator = (Weapon *)originator; - if (pWOriginator->aim_target) - { - if (pWOriginator->aim_target->IsSubclassOfSentient()) - { - if (((Sentient *)(pWOriginator->aim_target.Pointer()))->m_Team != pAOwner->m_Team) - pEnemy = (Sentient *)(pWOriginator->aim_target.Pointer()); - } - else if (pAOwner->m_Team == TEAM_GERMAN) - { - for (pEnemy = level.m_HeadSentient[1]; ; pEnemy = pEnemy->m_NextSentient) - { - if (!pEnemy) - { - return; - } - Vector vDist = pEnemy->centroid - pWOriginator->aim_target->origin; - if (vDist.lengthSquared() <= 2304 || vDist.lengthSquared() != 2304) - { - break; - } - } - } - } - } - } - } - if (!pEnemy) - return; - } - else - { - if (!pEnemy) - return; - } - - //v14 = &this->m_PotentialEnemies; - if (m_PotentialEnemies.CaresAboutPerfectInfo(pEnemy)) - { - float fDist = sqrt(fDistSquared); - if (NoticeShot(pOwner, pEnemy, fDist)) - { - m_PotentialEnemies.ConfirmEnemy(this, pOwner); - CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared); - } - } -} - -/* -=============== -Actor::FootstepSound - -Handles footstep sound. -=============== -*/ -void Actor::FootstepSound - ( - vec3_t sound_origin, - float fDistSquared, - float fMaxDistSquared, - Entity *originator - ) -{ - if (originator->IsSubclassOfSentient()) - { - if ( (m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE || m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_CURIOUS ) && m_bEnableEnemy) - { - if (NoticeFootstep((Sentient *)originator)) - { - CuriousSound(AI_EVENT_FOOTSTEP, sound_origin, fDistSquared, fMaxDistSquared); - } - } - } - else - { - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"'ai_event footstep' in a tiki used by something besides AI or player.\\n\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); - assert(false && assertStr); - } -} - -/* -=============== -Actor::VoiceSound - -Handles voice sound. -=============== -*/ -void Actor::VoiceSound - ( - int iType, - vec3_t sound_origin, - float fDistSquared, - float fMaxDistSquared, - Entity *originator - ) -{ - bool bFriendly; - //FIXME: macros - if ((m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_IDLE && m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_CURIOUS) || !m_bEnableEnemy) - return; - - bFriendly = m_Team == TEAM_GERMAN; - - if (iType <= AI_EVENT_GERMAN_VOICE) - { - assert(iType == AI_EVENT_AMERICAN_VOICE); - } - else - { - assert(iType <= AI_EVENT_GERMAN_URGENT); - - if (iType == AI_EVENT_AMERICAN_URGENT) - { - bFriendly = m_Team == TEAM_AMERICAN; - } - } - - if (bFriendly) - { - if (NoticeVoice((Sentient *)originator)) - { - CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared); - } - } - -} - -/* -=============== -Actor::GrenadeNotification - -Handles grenade notification. -=============== -*/ -void Actor::GrenadeNotification - ( - Entity *originator - ) -{ - if (!m_pGrenade) - { - if (CanSeeFOV(originator)) - { - assert(originator->IsSubclassOfProjectile()); - - SetGrenade(originator); - Event e1(EV_Actor_ShareGrenade); - PostEvent(e1, 0.5); - - Anim_Say(STRING_ANIM_SAY_GRENADE_SIGHTED_SCR, 0, true); - } - } - - if (m_pGrenade == originator) - { - - float fGrav, fDeltaZ, fVelDivGrav, fTimeLand; - vec2_t vLand; - vec2_t vMove; - - fGrav = sv_gravity->value * m_pGrenade->gravity; - - fDeltaZ = originator->origin[2] - origin[2]; - - fVelDivGrav = originator->velocity[2] / fGrav; - - //from s=v*t + 0.5*a*t^2, apply for z velocity, solve. - fTimeLand = fVelDivGrav + sqrt((fDeltaZ + fDeltaZ) / fGrav + Square(fVelDivGrav)); - - - VectorMA2D(originator->origin, fTimeLand, originator->velocity, vLand); - - VectorSub2D(m_vGrenadePos, vLand, vMove); - - if (VectorLength2D(vMove) > 16) - { - m_vGrenadePos = Vector(vLand[0], vLand[1], origin[2]); - m_bGrenadeBounced = true; - } - - } -} - -/* -=============== -Actor::SetGrenade - -Set current grenade. -=============== -*/ -void Actor::SetGrenade - ( - Entity *pGrenade - ) -{ - m_pGrenade = pGrenade; - - m_bGrenadeBounced = true; - - m_iFirstGrenadeTime = level.inttime; - - m_vGrenadePos = pGrenade->origin; - -} - -/* -=============== -Actor::NotifySquadmateKilled - -Handle squadmate killed notification. -=============== -*/ -void Actor::NotifySquadmateKilled - ( - Sentient *pSquadMate, - Sentient *pAttacker - ) -{ - if (m_PotentialEnemies.CaresAboutPerfectInfo(pAttacker)) - { - - Vector dist = pSquadMate->origin - origin; - float distSq = dist * dist; - if (distSq < m_fSight*m_fSight) - { - bool shouldConfirm = false; - if (gi.AreasConnected(edict->r.areanum,pSquadMate->edict->r.areanum)) - { - shouldConfirm = G_SightTrace( - EyePosition(), - vec_zero, - vec_zero, - pSquadMate->EyePosition(), - this, - pSquadMate, - MASK_TRANSITION, - qfalse, - "Actor::NotifySquadmateKilled"); - } - //FIXME: macro for that constant - if (!shouldConfirm) - { - if (distSq <= Square(768)) - { - Vector start, end; - if (origin.z <= pSquadMate->origin.z) - { - start = origin; - end = pSquadMate->origin; - } - else - { - start = pSquadMate->origin; - end = origin; - } - shouldConfirm = m_Path.DoesTheoreticPathExist(start, end, this, 1536, 0, 0); - } - } - if (shouldConfirm) - { - m_PotentialEnemies.ConfirmEnemy(this, pAttacker); - } - } - } -} - -/* -=============== -Actor::RaiseAlertnessForEventType - -Raise alertness(enemy notice) for specifc event. -=============== -*/ -void Actor::RaiseAlertnessForEventType - ( - int iType - ) -{ - float fAmount; - - switch (iType) - { - case AI_EVENT_WEAPON_FIRE: - fAmount = 0.2f; - case AI_EVENT_WEAPON_IMPACT: - fAmount = 0.1f; - case AI_EVENT_EXPLOSION: - fAmount = 0.4f; - case AI_EVENT_AMERICAN_VOICE: - case AI_EVENT_AMERICAN_URGENT: - if (m_Team == TEAM_AMERICAN) - return; - fAmount = 0.25f; - case AI_EVENT_MISC: - fAmount = 0.02f; - case AI_EVENT_MISC_LOUD: - case AI_EVENT_FOOTSTEP: - fAmount = 0.05f; - case AI_EVENT_GRENADE: - fAmount = 0.04f; - break; - case AI_EVENT_GERMAN_VOICE: - case AI_EVENT_GERMAN_URGENT: - if (m_Team == TEAM_AMERICAN) - { - RaiseAlertness(0.25); - } - default: - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"Actor::RaiseAlertnessForEventType: unknown event type\\n\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); - assert(false && assertStr); - return; - break; - } - RaiseAlertness(fAmount); -} - -/* -=============== -Actor::RaiseAlertness - -Lower enemy notice time by fAmount. -=============== -*/ -void Actor::RaiseAlertness - ( - float fAmount - ) -{ - float fMaxAmount; - - fMaxAmount = m_fNoticeTimeScale * 2/3; - - m_fNoticeTimeScale -= fAmount <= fMaxAmount ? fAmount : fMaxAmount; -} - -/* -=============== -Actor::CanSee - -Returns true if actor cansee entity through fov and vision_distance. -=============== -*/ -bool Actor::CanSee - ( - Entity *e1, - float fov, - float vision_distance, - bool bNoEnts - ) -{ - bool canSee = Sentient::CanSee(e1, fov, vision_distance, false); - if (e1 == m_Enemy) - { - m_iEnemyVisibleCheckTime = level.inttime; - if (canSee) - { - SetEnemyPos(e1->origin); - m_bEnemyIsDisguised = m_Enemy->m_bIsDisguised; - m_iEnemyCheckTime = level.inttime; - m_iLastEnemyVisibleTime = level.inttime; - } - - if (canSee != m_bEnemyVisible) - { - m_bEnemyVisible = true; - m_iEnemyVisibleChangeTime = level.inttime; - } - - if (fov != 0) - { - - m_iEnemyFovCheckTime = level.inttime; - if (canSee != m_bEnemyInFOV) - { - m_bEnemyInFOV = true; - m_iEnemyFovChangeTime = level.inttime; - } - } - } - return canSee; -} - -/* -=============== -Actor::GunPosition - -Returns current gun position. -=============== -*/ -Vector Actor::GunPosition - ( - void - ) -{ - if (m_iGunPositionCheckTime < level.inttime) - { - m_iGunPositionCheckTime = level.inttime; - Weapon *weap = GetActiveWeapon(WEAPON_MAIN); - if (weap) - { - weap->GetMuzzlePosition(&m_vGunPosition); - } - else - { - m_vGunPosition = vec_zero; - } - } - return m_vGunPosition; -} - -/* -=============== -Actor::WithinVisionDistance - -Returns true if entity is witthin vision distance. -=============== -*/ -bool Actor::WithinVisionDistance - ( - Entity *ent - ) const -{ - float fRadius = world->m_fAIVisionDistance; - - if(fRadius == 0 ) - { - fRadius = m_fSight; - } - else if( m_fSight <= fRadius ) - { - fRadius = m_fSight; - } - - if( ent ) - { - Vector vDelta = ent->origin - origin; - //it's basically the same as vDelta.length() < fRadius, - //but this is faster because sqrt in vDelta.length() is slower than multiplication. - return vDelta.lengthSquared() < Square(fRadius); - } - - return false; -} - -/* -=============== -Actor::InFOV - -Returns true if positin is within fov. -=============== -*/ -bool Actor::InFOV - ( - Vector pos, - float check_fov, - float check_fovdot - ) -{ - - bool bInFov = true; - if (check_fov != 360.0) - { - Vector delta = pos - EyePosition(); - if (delta.x == 0 && delta.y == 0) - { - return bInFov; - } - bInFov = false; - - - float fDot = DotProduct2D(delta, orientation[0]); - if (fDot >= 0) - { - bInFov = Square(fDot) > delta.lengthXYSquared() * Square(check_fovdot); - } - - } - return bInFov; -} - -/* -=============== -Actor::EnemyInFOV - -Returns true if enemy is within fov. -=============== -*/ -bool Actor::EnemyInFOV - ( - int iMaxDirtyTime - ) -{ - if (level.inttime > iMaxDirtyTime + m_iEnemyFovCheckTime) - { - bool bInFov = InFOV(m_Enemy->centroid, m_fFov, m_fFovDot); - if (m_bEnemyInFOV != bInFov) - { - m_bEnemyInFOV = !m_bEnemyInFOV; - m_iEnemyFovChangeTime = level.inttime; - } - m_iEnemyFovCheckTime = level.inttime; - - } - return m_iEnemyFovCheckTime; -} - -/* -=============== -Actor::InFOV - -Returns true if pos is within fov. -=============== -*/ -bool Actor::InFOV - ( - Vector pos - ) -{ - return InFOV(pos, m_fFov, m_fFovDot); -} - -/* -=============== -Actor::InFOV - -Returns true if ent is within fov. -=============== -*/ -bool Actor::InFOV - ( - Entity *ent - ) -{ - if (ent == m_Enemy) - { - return EnemyInFOV(0); - } - else - { - return InFOV(ent->centroid, m_fFov, m_fFovDot); - } -} - -bool Actor::CanSeeNoFOV - ( - Entity *ent - ) -{ - if (ent == m_Enemy) - { - return CanSeeEnemy(0); - } - else - { - bool bCanSee = false; - if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum)) - { - bCanSee = CanSeeFrom(EyePosition(), ent); - } - return bCanSee; - } -} - -bool Actor::CanSeeFOV - ( - Entity *ent - ) -{ - //fixme: this is an inline function. - if (ent == m_Enemy) - { - return CanSeeEnemyFOV(0, 0); - } - else - { - bool bCanSee = false; - if (InFOV(ent->centroid, m_fFov, m_fFovDot) && gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum)) - { - bCanSee = CanSeeFrom(EyePosition(), ent); - } - return bCanSee; - } -} - -bool Actor::CanSeeEnemyFOV - ( - int iMaxFovDirtyTime, - int iMaxSightDirtyTime - ) -{ - return EnemyInFOV(iMaxFovDirtyTime) && CanSeeEnemy(iMaxSightDirtyTime); -} - -/* -=============== -Actor::CanShoot - -Returns true if actor can shoot entity. -=============== -*/ -bool Actor::CanShoot - ( - Entity *ent - ) -{ - bool bCanShootEnemy = false; - if (ent->IsSubclassOfSentient()) - { - Sentient * sen = (Sentient *)ent; - //FIXME: macro. - if (world->farplane_distance == 0 || Square(world->farplane_distance * 0.828) > (origin - sen->origin).lengthSquared()) - { - if (gi.AreasConnected( - edict->r.areanum, - sen->edict->r.areanum)) - { - if (G_SightTrace( - GunPosition(), - vec_zero, - vec_zero, - sen->centroid, - this, - sen, - MASK_CANSEE, - qfalse, - "Actor::CanShoot centroid") - || G_SightTrace( - GunPosition(), - vec_zero, - vec_zero, - sen->EyePosition(), - this, - sen, - MASK_CANSEE, - qfalse, - "Actor::CanShoot eyes")) - { - bCanShootEnemy = true; - } - } - } - if (m_Enemy) - { - m_bCanShootEnemy = bCanShootEnemy; - m_iCanShootCheckTime = level.inttime; - } - } - else - { - - if (gi.AreasConnected( - edict->r.areanum, - ent->edict->r.areanum)) - { - if (CanSeeFrom(GunPosition(), ent)) - { - bCanShootEnemy = true; - } - } - } - - return bCanShootEnemy; -} - -/* -=============== -Actor::CanSeeFrom - -Returns true if actor can see entity from pos. -=============== -*/ -bool Actor::CanSeeFrom - ( - vec3_t pos, - Entity *ent - ) -{ - Vector vPos(pos); - bool bCanSee = false; - if (world->farplane_distance == 0 || Square(world->farplane_distance * 0.828) > (origin - ent->origin).lengthSquared()) - { - if (!ent->IsSubclassOfActor() && G_SightTrace(vPos, vec_zero, vec_zero, ent->centroid, this, ent, MASK_CANSEE, qfalse, "Actor::CanSeeFrom")) - { - bCanSee = true; - } - } - return bCanSee; -} - -/* -=============== -Actor::CanSeeEnemy - -Returns true if actor can see enemy. -=============== -*/ -bool Actor::CanSeeEnemy - ( - int iMaxDirtyTime - ) -{ - //FIXME: macro - if (level.inttime > iMaxDirtyTime + m_iEnemyVisibleCheckTime) - CanSee(m_Enemy, 0, 0.828 * world->farplane_distance, false); - - return m_bEnemyVisible; -} - -/* -=============== -Actor::CanShootEnemy - -Returns true if actor can shoot enemy. -=============== -*/ -bool Actor::CanShootEnemy - ( - int iMaxDirtyTime - ) -{ - if( level.inttime > iMaxDirtyTime + m_iCanShootCheckTime ) - CanShoot( m_Enemy ); - - return m_bCanShootEnemy; -} - -/* -=============== -Actor::ShowInfo - -Display actor info. -=============== -*/ -void Actor::ShowInfo - ( - float fDot, - float fDist - ) -{ - float fMaxDist, fMinDot; - static cvar_t *g_entinfo_max; - - if (!bEntinfoInit) - { - g_entinfo_max = gi.Cvar_Get("g_entinfo_max", "2048", 0); - bEntinfoInit = true; - } - - fMinDot = 0.9f; - fMaxDist = g_entinfo_max->value; - - if ( IsKilledState(m_ThinkState) ) - { - fMinDot = 0.99f; - fMaxDist = 512; - } - - if (g_entinfo->integer != 4) - { - if (fDot <= fMinDot) - { - if (fDot <= 0 || fDist >= 256) - return; - } - - if (fMaxDist <= fDist || fDist <= 64) - return; - } - if (!m_bEnableEnemy) - { - Vector a = origin; - a.z += maxs.z + 74; - - G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "DISABLED"); - } - - { - Vector a = origin; - a.z += maxs.z + 56; - - - G_DebugString( - a, - 1.0, - 1.0, - 1.0, - 1.0, - "%i:%i:%s:%.1f", - entnum, - radnum, - targetname.c_str(), - health); - } - - if (m_Enemy) - { - Vector a = origin; - a.z += maxs.z + 38; - - - G_DebugString( - a, - 1.0, - 1.0, - 1.0, - 1.0, - "%i:%s:%.1f:%i", - m_Enemy->entnum, - m_Enemy->targetname.c_str(), - m_Enemy->health, - m_PotentialEnemies.GetCurrentThreat()); - } - - if ( IsCuriousState(m_ThinkState) ) - { - - Vector a = origin; - a.z += maxs.z + 20; - - - G_DebugString( - a, - 1.0, - 1.0, - 1.0, - 1.0, - "%s:%%%.1f", - Director.GetString(m_csThinkStateNames[THINKSTATE_CURIOUS]).c_str(), - m_PotentialEnemies.GetCurrentVisibility() * 100); - } - else - { - - Vector a = origin; - a.z += maxs.z + 20; - - - G_DebugString( - a, - 1.0, - 1.0, - 1.0, - 1.0, - "%s", - ThinkStateName().c_str()); - } - - - { - Vector a = origin; - a.z += maxs.z + 2; - - str sAnimThreadFile = m_pAnimThread ? m_pAnimThread->FileName() : "(null)"; - - - - G_DebugString( - a, - 1.0, - 1.0, - 1.0, - 1.0, - "%s:%s:%i - %s", - ThinkName().c_str(), - m_pszDebugState, - m_State, - sAnimThreadFile.c_str()); - } - - if (g_entinfo->integer == 1) - { - if (m_pGrenade) - G_DebugLine(m_pGrenade->origin, m_vGrenadePos, 1.0, 0.0, 0.0, 1.0); - - Vector a = m_vHome; - a.z += maxs.z + 18; - - G_DebugLine(centroid, a, 0.0, 1.0, 0.0, 1.0); - - G_DebugCircle(a, m_fLeash, 0.0, 1.0, 0.0, 1.0, qtrue); - - G_DebugCircle( - centroid, - m_fMinDistance, - 1.0, - 0.0, - 0.0, - 1.0, - qtrue); - - G_DebugCircle( - centroid, - m_fMaxDistance, - 0.0, - 0.0, - 1.0, - 1.0, - qtrue); - } - else if (g_entinfo->integer == 2) - { - G_DebugCircle( - centroid, - m_fHearing, - 1.0, - 0.0, - 0.0, - 1.0, - qtrue); - G_DebugCircle( - centroid, - m_fSight, - 0.0, - 0.0, - 1.0, - 1.0, - qtrue); - } + ev->AddConstString(m_csWeapon); } /* @@ -7366,15 +5005,10 @@ Actor::DefaultPain Default pain handler. =============== */ -void Actor::DefaultPain - ( - Event *ev - ) +void Actor::DefaultPain(Event *ev) { - gi.Printf("DefaultPain event"); - SetThink(THINKSTATE_PAIN, THINK_PAIN); - - HandlePain(ev); + SetThink(THINKSTATE_PAIN, THINK_PAIN); + HandlePain(ev); } /* @@ -7384,49 +5018,55 @@ Actor::HandlePain Hangled pain event. =============== */ -void Actor::HandlePain - ( - Event *ev - ) +void Actor::HandlePain(Event *ev) { - gi.Printf("HandlePain"); - Event e1(EV_Listener_ExecuteScript); - if (m_bEnablePain) - { + int i; + Event event(EV_Listener_ExecuteScript); + int num; + Entity *attacker; - e1.AddConstString(STRING_GLOBAL_PAIN_SCR); + if (!m_bEnablePain) { + return; + } - for (int i = 1; i <= ev->NumArgs(); i++) - { - e1.AddValue(ev->GetValue(i)); - } - ExecuteScript(&e1); - - SetThinkState(THINKSTATE_PAIN, THINKLEVEL_PAIN); + attacker = ev->GetEntity(1); + if (attacker && attacker->IsSubclassOfSentient() && IsTeamMate(static_cast(attacker))) { + return; + } - RaiseAlertness(0.5); + if (!m_bNoLongPain) { + event.AddConstString(STRING_GLOBAL_PAIN_SCR); - m_PainTime = level.inttime; + num = ev->NumArgs(); + for (i = 1; i <= num; i++) { + event.AddValue(ev->GetValue(i)); + } - Entity *ent = ev->GetEntity(1); - if (ent && ent->IsSubclassOfSentient() && !IsTeamMate((Sentient *)ent)) - { - m_pLastAttacker = ent; + ExecuteScript(&event); + SetThinkState(THINKSTATE_PAIN, THINKLEVEL_PAIN); + } - m_iCuriousLevel = 9; + RaiseAlertness(0.5f); - //FIXME: macro - SetCuriousAnimHint(7); + m_PainTime = level.inttime; - if (m_bEnableEnemy && m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE) - { - SetEnemyPos(ent->origin); - m_pszDebugState = "from_pain"; - SetThinkState(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL); - } - } - Unregister(STRING_PAIN); - } + if (attacker && attacker->IsSubclassOfSentient() && !IsTeamMate(static_cast(attacker))) { + m_pLastAttacker = attacker; + + m_iCuriousLevel = 9; + + //FIXME: macro + SetCuriousAnimHint(7); + + // Added in 2.30 the m_bIsCurous check + if (m_bEnableEnemy && m_ThinkStates[THINKLEVEL_IDLE] == THINKSTATE_IDLE && m_bIsCurious) { + SetEnemyPos(attacker->origin); + m_pszDebugState = "from_pain"; + SetThinkState(THINKSTATE_CURIOUS, THINKLEVEL_IDLE); + } + } + + Unregister(STRING_PAIN); } /* @@ -7436,18 +5076,17 @@ Actor::EventPain Pain event. =============== */ -void Actor::EventPain - ( - Event *ev - ) +void Actor::EventPain(Event *ev) { - ShowInfo(); + if (g_showinfo->integer) { + ShowInfo(); + } - GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]]; + GlobalFuncs_t *func = &GlobalFuncs[CurrentThink()]; - gi.Printf("pain event"); - if (func->Pain) - (this->*func->Pain)(ev); + if (func->Pain) { + (this->*func->Pain)(ev); + } } /* @@ -7457,17 +5096,11 @@ Actor::DefaultKilled Default killed handler. =============== */ -void Actor::DefaultKilled - ( - Event *ev, - bool bPlayDeathAnim - ) +void Actor::DefaultKilled(Event *ev, bool bPlayDeathAnim) { - ClearStates(); - - SetThink(THINKSTATE_KILLED, THINK_KILLED); - - HandleKilled(ev, bPlayDeathAnim); + ClearStates(); + SetThink(THINKSTATE_KILLED, THINK_KILLED); + HandleKilled(ev, bPlayDeathAnim); } /* @@ -7477,36 +5110,28 @@ Actor::HandleKilled Hangled killed event. =============== */ -void Actor::HandleKilled - ( - Event *ev, - bool bPlayDeathAnim - ) +void Actor::HandleKilled(Event *ev, bool bPlayDeathAnim) { - deadflag = DEAD_DEAD; - health = 0.0; - if (bPlayDeathAnim) - { - Event e1(EV_Listener_ExecuteScript); - e1.AddConstString(STRING_GLOBAL_KILLED_SCR); - for (int i = 1; i < ev->NumArgs(); i++) - { - e1.AddValue(ev->GetValue(i)); - } - ExecuteScript(&e1); - } - else - { - SetThink(THINKSTATE_KILLED, THINK_DEAD); - } + deadflag = DEAD_DEAD; + health = 0.0; - ClearThinkStates(); + if (bPlayDeathAnim) { + Event event(EV_Listener_ExecuteScript, ev->NumArgs() + 1); + event.AddConstString(STRING_GLOBAL_KILLED_SCR); + for (int i = 1; i <= ev->NumArgs(); i++) { + event.AddValue(ev->GetValue(i)); + } + ExecuteScript(&event); + } else { + SetThink(THINKSTATE_KILLED, THINK_DEAD); + } - SetThinkState(THINKSTATE_KILLED, THINKLEVEL_KILLED); + ClearThinkStates(); - gi.DPrintf("Waittill death unregisterd\n"); - Unregister(STRING_DEATH); - Unregister(STRING_PAIN); + SetThinkState(THINKSTATE_KILLED, THINKLEVEL_KILLED); + + Unregister(STRING_DEATH); + Unregister(STRING_PAIN); } /* @@ -7516,25 +5141,19 @@ Actor::DispatchEventKilled Dispatch killed event. =============== */ -void Actor::DispatchEventKilled - ( - Event *ev, - bool bPlayDeathAnim - ) +void Actor::DispatchEventKilled(Event *ev, bool bPlayDeathAnim) { - GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]]; + GlobalFuncs_t *func = &GlobalFuncs[CurrentThink()]; - if (func->Killed) - (this->*func->Killed)(ev, bPlayDeathAnim); - - SetEnemy(NULL, false); + assert(func->Killed); + (this->*func->Killed)(ev, bPlayDeathAnim); - DisbandSquadMate(this); - if (bPlayDeathAnim) - { - DropInventoryItems(); - } + SetEnemy(NULL, false); + DisbandSquadMate(this); + if (bPlayDeathAnim) { + DropInventoryItems(); + } } /* @@ -7544,34 +5163,33 @@ Actor::EventKilled Killed event. =============== */ -void Actor::EventKilled - ( - Event *ev - ) +void Actor::EventKilled(Event *ev) { - DispatchEventKilled(ev, true); + Entity *attacker; + Sentient *pBuddy; + Sentient *sent; + Player *player; - Player *p1 = (Player *)ev->GetEntity(1); - if (p1) - { - if (p1->IsSubclassOfPlayer() && p1->m_Team == m_Team) - { - p1->m_iNumEnemiesKilled++; - } - if (p1->IsSubclassOfSentient()) - { - for (Sentient *pSent = level.m_HeadSentient[m_Team]; pSent; pSent = pSent->m_NextSentient) - { - if (pSent != this) - { - if (pSent->IsSubclassOfActor()) - NotifySquadmateKilled(pSent, p1); - } - } - } + DispatchEventKilled(ev, true); - } + attacker = ev->GetEntity(1); + if (attacker && attacker->IsSubclassOfPlayer()) { + player = static_cast(attacker); + if (player->m_Team != m_Team) { + player->m_iNumEnemiesKilled++; + } + } + if (attacker && attacker->IsSubclassOfSentient()) { + sent = static_cast(attacker); + + for (pBuddy = level.m_HeadSentient[m_Team]; pBuddy; pBuddy = pBuddy->m_NextSentient) { + if (pBuddy != this && pBuddy->IsSubclassOfActor()) { + Actor *actor = static_cast(pBuddy); + actor->NotifySquadmateKilled(this, sent); + } + } + } } /* @@ -7581,12 +5199,10 @@ Actor::EventBeDead Become dead. =============== */ -void Actor::EventBeDead - ( - Event *ev - ) +void Actor::EventBeDead(Event *ev) { - DispatchEventKilled(ev, false); + health = 0; + DispatchEventKilled(ev, false); } /* @@ -7596,26 +5212,19 @@ Actor::DeathEmbalm preps the dead actor for turning nonsolid gradually over time =============== */ -void Actor::DeathEmbalm - ( - Event *ev - ) +void Actor::DeathEmbalm(Event *ev) { - if (maxs[2] > 8) - { - maxs[2] -= 4; - if (maxs[2] > 8) - { - Event e1(EV_Actor_DeathEmbalm); - PostEvent(e1, 0.5); - } - else - { - maxs[2] = 8.0; - } + if (maxs.z > 8) { + maxs.z -= 4; - setSize(mins, maxs); - } + if (maxs.z > 8) { + PostEvent(EV_Actor_DeathEmbalm, 0.5f); + } else { + maxs.z = 8.0; + } + + setSize(mins, maxs); + } } /* @@ -7625,16 +5234,4318 @@ Actor::DeathSinkStart Makes the actor sink into the ground and then get removed(this starts it). =============== */ -void Actor::DeathSinkStart - ( - Event *ev - ) +void Actor::DeathSinkStart(Event *ev) { - flags &= ~FL_BLOOD; + setMoveType(MOVETYPE_NONE); + flags &= ~FL_THINK; + Entity::DeathSinkStart(ev); +} - setMoveType(MOVETYPE_NONE); +/* +=============== +Actor::FireWeapon - Entity::DeathSinkStart(ev); +Fire weapon from script. +=============== +*/ +void Actor::FireWeapon(Event *ev) +{ + if (ev->NumArgs() > 0 && ev->GetInteger(1) == WEAPON_OFFHAND) { + // shoot using off hand + Sentient::FireWeapon(WEAPON_OFFHAND, FIRE_PRIMARY); + } else { + Sentient::FireWeapon(WEAPON_MAIN, FIRE_PRIMARY); + } +} + +/* +=============== +Actor::PlayAnimation + +Play animation +=============== +*/ +void Actor::PlayAnimation(Event *ev) +{ + Event event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_ANIM_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::PlayScriptedAnimation + +Play scripted animation +=============== +*/ +void Actor::PlayScriptedAnimation(Event *ev) +{ + Event event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_ANIM_SCRIPTED_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::PlayNoclipAnimation + +Play noclip animation +=============== +*/ +void Actor::PlayNoclipAnimation(Event *ev) +{ + Event event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_ANIM_NOCLIP_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::PlayAttachedAnimation + +Play attached animation +=============== +*/ +void Actor::PlayAttachedAnimation(Event *ev) +{ + Event event(EV_Listener_ExecuteScript, 2); + event.AddConstString(STRING_GLOBAL_ANIM_ATTACHED_SCR); + event.AddValue(ev->GetValue(1)); + ExecuteScript(&event); +} + +/* +=============== +Actor::MoveDest + +Play noclip animation +=============== +*/ +void Actor::MoveDest(float fMoveSpeed) +{ + mmove_t mm; + vec2_t offset; + + SetMoveInfo(&mm); + + mm.desired_speed = fMoveSpeed; + if (mm.desired_speed > m_maxspeed) { + mm.desired_speed = m_maxspeed; + } + + VectorSub2D(m_Dest, origin, offset); + VectorNormalize2D(offset); + VectorCopy2D(offset, mm.desired_dir); + + MmoveSingle(&mm); + + GetMoveInfo(&mm); +} + +/* +=============== +Actor::MovePath + +Move on path. +=============== +*/ +void Actor::MovePath(float fMoveSpeed) +{ + mmove_t mm; + const float *dir; + vec2_t delta; + + SetMoveInfo(&mm); + + mm.desired_speed = fMoveSpeed; + if (mm.desired_speed > m_maxspeed) { + mm.desired_speed = m_maxspeed; + } + + m_Path.UpdatePos(origin); + + if (ai_debugpath->integer) { + Vector pos, dest; + PathInfo *current_path; + + pos = origin; + pos.z += 32; + + VectorAdd2D(origin, m_Path.CurrentDelta(), dest); + dest[2] = origin[2] + 32; + + G_DebugLine(pos, dest, 1, 0, 0, 1); + + for (current_path = m_Path.CurrentNode(); current_path != m_Path.LastNode(); current_path--) { + pos = current_path->point; + dest = (current_path - 1)->point; + + G_DebugLine(pos + Vector(0, 0, 32), dest + Vector(0, 0, 32), 0, 1, 0, 1); + } + } + + VectorCopy2D(m_Path.CurrentDelta(), mm.desired_dir); + MmoveSingle(&mm); + + if (!mm.hit_obstacle) { + if (m_WallDir) { + if (level.inttime >= m_iWallDodgeTimeout) { + m_WallDir = 0; + } else if (DotProduct2D(mm.desired_dir, m_PrevObstacleNormal) > 0 + && CrossProduct2D(mm.desired_dir, m_PrevObstacleNormal) < 0) { + m_iWallDodgeTimeout = level.inttime + 1000; + m_WallDir = -m_WallDir; + } + } + GetMoveInfo(&mm); + return; + } + + velocity.copyTo(mm.velocity); + origin.copyTo(mm.origin); + mm.groundPlane = m_groundPlane; + mm.walking = m_walking; + VectorCopy(m_groundPlaneNormal, mm.groundPlaneNormal); + VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal); + + m_Path.UpdatePos(mm.hit_origin); + + if (m_Path.NextNode() && m_Path.IsAccurate()) { + dir = m_Path.CurrentPathDir(); + + m_iWallDodgeTimeout = level.inttime + 1000; + VectorSub2D(m_Path.NextNode()->point, mm.hit_origin, delta); + + if (delta[0] * dir[1] > delta[1] * dir[0]) { + m_WallDir = -1; + mm.desired_dir[0] = -mm.obstacle_normal[1]; + mm.desired_dir[1] = mm.obstacle_normal[0]; + } else { + mm.desired_dir[0] = mm.obstacle_normal[1]; + mm.desired_dir[1] = -mm.obstacle_normal[0]; + } + + MmoveSingle(&mm); + + if (!mm.hit_obstacle) { + GetMoveInfo(&mm); + return; + } + + velocity.copyTo(mm.velocity); + origin.copyTo(mm.origin); + + mm.groundPlane = m_groundPlane; + mm.walking = m_walking; + VectorCopy(m_groundPlaneNormal, mm.groundPlaneNormal); + VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal); + + if (m_WallDir == (char)-1) { + mm.desired_dir[0] = -mm.obstacle_normal[1]; + mm.desired_dir[1] = mm.obstacle_normal[0]; + } else { + mm.desired_dir[0] = mm.obstacle_normal[1]; + mm.desired_dir[1] = -mm.obstacle_normal[0]; + } + + MmoveSingle(&mm); + GetMoveInfo(&mm); + } else { + if (m_Path.NextNode() && !m_Path.IsAccurate() && m_WallDir == 0) { + dir = m_Path.CurrentPathDir(); + + VectorSub2D(m_Path.NextNode()->point, mm.hit_origin, delta); + + if (DotProduct2D(dir, delta) >= 0) { + float cross = CrossProduct2D(dir, delta); + if (cross <= -16) { + mm.desired_dir[0] = -mm.obstacle_normal[1]; + mm.desired_dir[1] = mm.obstacle_normal[0]; + + MmoveSingle(&mm); + GetMoveInfo(&mm); + return; + + } else if (cross >= 16) { + mm.desired_dir[0] = mm.obstacle_normal[1]; + mm.desired_dir[1] = -mm.obstacle_normal[0]; + + MmoveSingle(&mm); + GetMoveInfo(&mm); + return; + } + } + } + + if (m_WallDir == 0) { + dir = m_Path.CurrentPathDir(); + + if (m_Path.NextNode()) { + dir = m_Path.NextNode()->dir; + } + + if (dir[0] * mm.obstacle_normal[1] > dir[1] * mm.obstacle_normal[0]) { + m_WallDir = 1; + mm.desired_dir[0] = mm.obstacle_normal[1]; + mm.desired_dir[1] = -mm.obstacle_normal[0]; + } else { + m_WallDir = -1; + mm.desired_dir[0] = -mm.obstacle_normal[1]; + mm.desired_dir[1] = mm.obstacle_normal[0]; + } + + MmoveSingle(&mm); + if (mm.hit_obstacle) { + m_WallDir = 0; + m_iWallDodgeTimeout = 0; + } else { + m_iWallDodgeTimeout = level.inttime + 1000; + } + } else { + if (m_WallDir >= 0) { + mm.desired_dir[0] = mm.obstacle_normal[1]; + mm.desired_dir[1] = -mm.obstacle_normal[0]; + } else { + mm.desired_dir[0] = -mm.obstacle_normal[1]; + mm.desired_dir[1] = mm.obstacle_normal[0]; + } + + MmoveSingle(&mm); + + if (mm.hit_obstacle) { + m_WallDir = 0; + m_iWallDodgeTimeout = 0; + } + } + + GetMoveInfo(&mm); + } +} + +/* +=============== +Actor::MovePathGoal + +Move on path end(goal). +=============== +*/ +void Actor::MovePathGoal(float fMoveSpeed) +{ + vec2_t vDelta; + float fSlowdownSpeed; + float fTimeToGo; + float fDeltaSquareLen; + + if (!m_Path.HasCompleteLookahead()) { + MovePath(fMoveSpeed); + m_fPathGoalTime = 0; + return; + } + + VectorSub2D(origin, m_Path.CurrentPathGoal(), vDelta); + fDeltaSquareLen = VectorLength2DSquared(vDelta); + fTimeToGo = m_fPathGoalTime - level.time; + + if (fTimeToGo > -0.001f) { + fSlowdownSpeed = sqrt(fDeltaSquareLen) * (2.f / (fTimeToGo + level.frametime)); + + if (fSlowdownSpeed > (fMoveSpeed + 0.001f) && fSlowdownSpeed > sv_runspeed->value * 0.4f) { + m_fPathGoalTime = 0; + StartAnimation(ANIM_MODE_PATH_GOAL, m_Anim); + MovePath(fMoveSpeed); + } else { + MovePath(fSlowdownSpeed); + if (level.time >= m_fPathGoalTime) { + m_eAnimMode = ANIM_MODE_NORMAL; + } + } + } else if (fDeltaSquareLen < Square(fMoveSpeed * 0.5 * 0.5)) { + fTimeToGo = 0.5f; + m_fPathGoalTime = level.time + fTimeToGo; + if (m_csPathGoalEndAnimScript == STRING_EMPTY) { + m_csPathGoalEndAnimScript = STRING_ANIM_IDLE_SCR; + } + m_bStartPathGoalEndAnim = true; + } else { + MovePath(fMoveSpeed); + m_fPathGoalTime = 0; + return; + } +} + +/* +=============== +Actor::Dumb + +Make actor dumb. +=============== +*/ +void Actor::Dumb(Event *ev) +{ + Event event(EV_Listener_ExecuteScript); + event.AddConstString(STRING_GLOBAL_DISABLE_AI_SCR); + ExecuteScript(&event); +} + +/* +=============== +Actor::PhysicsOn + +Disable PhysicsOff. +=============== +*/ +void Actor::PhysicsOff(Event *ev) +{ + m_bDoPhysics = false; +} + +/* +=============== +Actor::PhysicsOn + +Enable physics. +=============== +*/ +void Actor::PhysicsOn(Event *ev) +{ + m_bDoPhysics = true; +} + +/* +=============== +Actor::EventGetMood + +Get current mood. +=============== +*/ +void Actor::EventGetMood(Event *ev) +{ + ev->AddConstString(m_csMood); +} + +/* +=============== +Actor::EventSetMood + +Set current mood. +=============== +*/ +void Actor::EventSetMood(Event *ev) +{ + m_csMood = ev->GetConstString(1); + if (m_csMood != STRING_BORED && m_csMood != STRING_NERVOUS && m_csMood != STRING_CURIOUS + && m_csMood != STRING_ALERT) { + m_csMood = STRING_BORED; + ScriptError("invalid mood - setting to bored"); + } +} + +/* +=============== +Actor::EventDamagePuff + +Spawns a puff of 'blood' smoke at the specified location in the specified direction. +=============== +*/ +void Actor::EventDamagePuff(Event *ev) +{ + Vector pos = ev->GetVector(1); + Vector dir = ev->GetVector(2); + int bulletbits; + + // Fixed in OPM + // Large bullet flag normally take 2 bits since 2.0. + // However, in OG Spearhead and Breakthrough, EventDamagePuff + // mistakenly uses 1 bit which causes a parse message error + bulletbits = (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) ? 2 : 1; + + gi.SetBroadcastVisible(pos, NULL); + + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_8)); + gi.MSG_WriteCoord(pos.x); + gi.MSG_WriteCoord(pos.y); + gi.MSG_WriteCoord(pos.z); + + gi.MSG_WriteDir(dir); + gi.MSG_WriteBits(0, bulletbits); + gi.MSG_EndCGM(); +} + +/* +=============== +Actor::EventGetAngleYawSpeed + +Get current AngleYawSpeed. +=============== +*/ +void Actor::EventGetAngleYawSpeed(Event *ev) +{ + ev->AddFloat(m_fAngleYawSpeed); +} + +/* +=============== +Actor::EventSetAngleYawSpeed + +Set current AngleYawSpeed. +=============== +*/ +void Actor::EventSetAngleYawSpeed(Event *ev) +{ + float speed = ev->GetFloat(1); + if (speed <= 0) { + ScriptError("Attempting to set illegal turnspeed %f", speed); + } + m_fAngleYawSpeed = speed; +} + +/* +=============== +Actor::EventSetAimTarget + +Set current weapon's aim tagret. +=============== +*/ +void Actor::EventSetAimTarget(Event *ev) +{ + Entity *ent; + Weapon *weap; + + ent = ev->GetEntity(1); + if (!ent) { + // Added in 2.0 + // Check for NULL + ScriptError("EventSetAimTarget::NULL entity given as first argument."); + return; + } + + weap = GetActiveWeapon(WEAPON_MAIN); + weap->SetAimTarget(ent); + + // Added in 2.0 + // Make the ent an enemy + if (ev->NumArgs() > 1 && ev->GetInteger(2) == 1 && ent->IsSubclassOfSentient()) { + SetEnemy(static_cast(ent), false); + } +} + +/* +=============== +Actor::ReadyToFire + +Returns true if weapon is ready to fire. +=============== +*/ +void Actor::ReadyToFire(Event *ev) +{ + Weapon *weap = GetActiveWeapon(WEAPON_MAIN); + if (weap) { + ev->AddInteger(weap->ReadyToFire(FIRE_PRIMARY, true)); + } else { + ev->AddInteger(0); + } +} + +/* +=============== +Actor::EventGetSight + +Return current sight (vision distance). +=============== +*/ +void Actor::EventGetSight(Event *ev) +{ + ev->AddFloat(m_fSight); +} + +/* +=============== +Actor::EventSetSight + +Set current sight (vision distance). +=============== +*/ +void Actor::EventSetSight(Event *ev) +{ + m_fSight = ev->GetFloat(1); +} + +/* +=============== +Actor::EventGetHearing + +Get current hearing distance. +=============== +*/ +void Actor::EventGetHearing(Event *ev) +{ + ev->AddFloat(m_fHearing); +} + +/* +=============== +Actor::EventSetHearing + +Set current hearing distance. +=============== +*/ +void Actor::EventSetHearing(Event *ev) +{ + m_fHearing = ev->GetFloat(1); +} + +/* +=============== +Actor::EventGetFov + +Get current fov. +=============== +*/ +void Actor::EventGetFov(Event *ev) +{ + ev->AddFloat(m_fFov); +} + +/* +=============== +Actor::EventSetFov + +Set current fov. +============ +*/ +void Actor::EventSetFov(Event *ev) +{ + float fov = ev->GetFloat(1); + if (fov < 0 || fov > 360) { + ScriptError("fov must be in the range [0,360]"); + } + m_fFov = fov; + m_fFovDot = cos(fov * 0.5f * M_PI / 180.0); +} + +/* +=============== +Actor::ClearPatrolCurrentNode + +Clear current patrol node. +=============== +*/ +void Actor::ClearPatrolCurrentNode(void) +{ + if (m_patrolCurrentNode) { + if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) { + delete m_patrolCurrentNode; + } + m_patrolCurrentNode = NULL; + } +} + +/* +=============== +Actor::NextPatrolCurrentNode + +Switch to next patrol node. +=============== +*/ +void Actor::NextPatrolCurrentNode(void) +{ + if (m_bScriptGoalValid) { + if (m_patrolCurrentNode->origin == m_vScriptGoal) { + m_bScriptGoalValid = false; + } + } + + if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) { + ClearPatrolCurrentNode(); + } else { + m_patrolCurrentNode = m_patrolCurrentNode->Next(); + } +} + +/* +=============== +Actor::SetPatrolCurrentNode + +Set current patrol node. +=============== +*/ +void Actor::SetPatrolCurrentNode(Vector& vec) +{ + ClearPatrolCurrentNode(); + + m_patrolCurrentNode = new TempWaypoint(); + m_patrolCurrentNode->setOrigin(vec); +} + +/* +=============== +Actor::SetPatrolCurrentNode + +Set current patrol node. +=============== +*/ +void Actor::SetPatrolCurrentNode(Listener *l) +{ + ClearPatrolCurrentNode(); + + if (l && !l->isSubclassOf(SimpleEntity)) { + ScriptError( + "Bad patrol path with classname '%s' specified for '%s' at (%f %f %f)\n", + l->getClassname(), + targetname.c_str(), + origin.x, + origin.y, + origin.z + ); + } + + m_patrolCurrentNode = static_cast(l); +} + +/* +=============== +Actor::EventSetPatrolPath + +Set current patrol path. +=============== +*/ +void Actor::EventSetPatrolPath(Event *ev) +{ + SetPatrolCurrentNode(ev->GetListener(1)); +} + +/* +=============== +Actor::EventGetPatrolPath + +Get current patrol path. +=============== +*/ +void Actor::EventGetPatrolPath(Event *ev) +{ + ev->AddListener(m_patrolCurrentNode); +} + +/* +=============== +Actor::EventSetPatrolWaitTrigger + +Set m_bPatrolWaitTrigger. +=============== +*/ +void Actor::EventSetPatrolWaitTrigger(Event *ev) +{ + m_bPatrolWaitTrigger = ev->GetBoolean(1); +} + +/* +=============== +Actor::EventGetPatrolWaitTrigger + +Get m_bPatrolWaitTrigger. +=============== +*/ +void Actor::EventGetPatrolWaitTrigger(Event *ev) +{ + ev->AddInteger(m_bPatrolWaitTrigger); +} + +/* +=============== +Actor::ShowInfo_PatrolCurrentNode + +Show current patrol node info. +=============== +*/ +void Actor::ShowInfo_PatrolCurrentNode(void) +{ + if (m_patrolCurrentNode) { + Com_Printf("current patrol node: %s\n", m_patrolCurrentNode->targetname.c_str()); + } else { + Com_Printf("no current patrol node\n"); + } +} + +/* +=============== +Actor::ShowInfo_AimNode + +Show current aim node info. +=============== +*/ +void Actor::ShowInfo_AimNode(void) +{ + if (m_aimNode) { + Com_Printf("aim node: %s\n", m_aimNode->targetname.c_str()); + } else { + Com_Printf("no current aim node\n"); + } +} + +/* +=============== +Actor::MoveOnPathWithSquad + +Move on path with squad. +=============== +*/ +bool Actor::MoveOnPathWithSquad(void) +{ + const float *pvMyDir, *pvHisDir; + vec2_t vDelta; + Sentient *pSquadMate; + float fIntervalSquared; + vec2_t vMyNormalDir; + float fDistSquared; + + if (level.inttime < m_iSquadStandTime + 500) { + return false; + } + + if (!PathExists() || PathComplete()) { + return false; + } + + pvMyDir = PathDelta(); + fIntervalSquared = Square(m_fInterval); + if (m_iSquadStandTime) { + fIntervalSquared *= 2; + } + + pSquadMate = static_cast(G_GetEntity(0)); + + if (IsTeamMate(pSquadMate)) { + VectorSub2D(pSquadMate->origin, origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (fIntervalSquared > fDistSquared && DotProduct2D(vDelta, pvMyDir) > 0) { + VectorSub2D(velocity, pSquadMate->velocity, vMyNormalDir); + VectorNormalize2D(vMyNormalDir); + + if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) < Square(48)) { + m_iSquadStandTime = level.inttime; + return false; + } + } + } + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + if (!pSquadMate->IsSubclassOfActor()) { + continue; + } + + Actor *pActorSquadMate = static_cast(pSquadMate); + + VectorSub2D(pActorSquadMate->origin, origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (fDistSquared >= fIntervalSquared || DotProduct2D(vDelta, pvMyDir) <= 0) { + continue; + } + + if (!pActorSquadMate->PathExists() || pActorSquadMate->PathComplete()) { + pvHisDir = pActorSquadMate->velocity; + + if (VectorLength2DSquared(pvHisDir) <= 8) { + continue; + } + } else { + pvHisDir = pActorSquadMate->PathDelta(); + } + + if (DotProduct2D(pvMyDir, pvHisDir) >= 0 + && (entnum >= pActorSquadMate->entnum || DotProduct2D(pvHisDir, vDelta) >= 0)) { + m_iSquadStandTime = level.inttime; + return false; + } + } + + m_iSquadStandTime = 0; + return true; +} + +/* +=============== +Actor::MoveToWaypointWithPlayer + +Move to waypoint with player. +=============== +*/ +bool Actor::MoveToWaypointWithPlayer(void) +{ + vec2_t pvMyDir; + vec2_t vDelta; + float fIntervalSquared; + vec2_t vMyNormalDir; + float fDistSquared; + Sentient *pSquadMate; + + if (level.inttime < m_iSquadStandTime + 500) { + return false; + } + + fIntervalSquared = Square(m_fInterval); + if (m_iSquadStandTime) { + fIntervalSquared += fIntervalSquared; + } + + pSquadMate = static_cast(G_GetEntity(0)); + if (!IsTeamMate(pSquadMate)) { + return true; + } + + VectorSub2D(pSquadMate->origin, origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (fDistSquared >= fIntervalSquared) { + m_iSquadStandTime = 0; + return true; + } + + VectorSub2D(m_patrolCurrentNode->origin, origin, pvMyDir); + if (DotProduct2D(vDelta, pvMyDir) <= 0) { + m_iSquadStandTime = 0; + return true; + } + + VectorSub2D(velocity, pSquadMate->velocity, vMyNormalDir); + VectorNormalize2D(vMyNormalDir); + + if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) >= Square(48)) { + m_iSquadStandTime = 0; + return true; + } + + m_iSquadStandTime = level.inttime; + return false; +} + +/* +=============== +Actor::PatrolNextNodeExists + +Returns true if next patrol node exits. +=============== +*/ +bool Actor::PatrolNextNodeExists(void) +{ + if (!m_patrolCurrentNode) { + return false; + } + + if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) { + return false; + } + + if (!m_patrolCurrentNode->Next()) { + return false; + } + + return true; +} + +/* +=============== +Actor::UpdatePatrolCurrentNode + +Update current patrol node. +=============== +*/ +void Actor::UpdatePatrolCurrentNode(void) +{ + if (!m_patrolCurrentNode) { + return; + } + + if (m_patrolCurrentNode->IsSubclassOfWaypoint()) { + vec2_t delta; + VectorSub2D(origin, m_patrolCurrentNode->origin, delta); + + if (fabs(delta[0]) < 16.0 && fabs(delta[1]) < 16.0) { + NextPatrolCurrentNode(); + } + } else if (PathExists() && PathComplete()) { + NextPatrolCurrentNode(); + } +} + +/* +=============== +Actor::MoveToPatrolCurrentNode + + +=============== +*/ +bool Actor::MoveToPatrolCurrentNode(void) +{ + UpdatePatrolCurrentNode(); + + if (!m_patrolCurrentNode || m_bPatrolWaitTrigger) { + IdleLook(); + Anim_Idle(); + return false; + } + + if (m_patrolCurrentNode->IsSubclassOfWaypoint()) { + if (MoveToWaypointWithPlayer()) { + DesiredAnimation(ANIM_MODE_DEST, m_csPatrolCurrentAnim); + FaceMotion(); + } else { + Anim_Stand(); + IdleLook(); + } + + SetDest(m_patrolCurrentNode->origin); + + if (!m_fMoveDoneRadiusSquared || m_patrolCurrentNode->Next()) { + return false; + } + + vec2_t delta; + VectorSub2D(m_patrolCurrentNode->origin, origin, delta); + return VectorLength2DSquared(delta) <= m_fMoveDoneRadiusSquared; + } else { + SetPath(m_patrolCurrentNode->origin, "Actor::MoveToPatrolCurrentNode", 0, NULL, 0); + + if (!PathExists()) { + IdleLook(); + Anim_Idle(); + // tell scripts the move has failed + parm.movefail = true; + return false; + } + + if (MoveOnPathWithSquad()) { + if (PatrolNextNodeExists()) { + DesiredAnimation(ANIM_MODE_PATH, m_csPatrolCurrentAnim); + } else { + DesiredAnimation(ANIM_MODE_PATH_GOAL, m_csPatrolCurrentAnim); + } + + FaceMotion(); + } else { + Anim_Stand(); + IdleLook(); + } + + if (!m_fMoveDoneRadiusSquared) { + return false; + } + + if (PathComplete()) { + return true; + } + + if (!m_Path.HasCompleteLookahead()) { + return false; + } + + if (m_patrolCurrentNode->Next()) { + return false; + } + + const float *delta = PathDelta(); + return VectorLength2DSquared(delta) <= m_fMoveDoneRadiusSquared; + } +} + +/* +=============== +Actor::EventSetAccuracy + +Set current accuracy. +=============== +*/ +void Actor::EventSetAccuracy(Event *ev) +{ + mAccuracy = ev->GetFloat(1) / 100.f; +} + +/* +=============== +Actor::EventGetAccuracy + +Get current accuracy. +=============== +*/ +void Actor::EventGetAccuracy(Event *ev) +{ + ev->AddFloat(mAccuracy * 100.f); +} + +/* +=============== +Actor::EventSetMinDistance +=============== +*/ +void Actor::EventSetMinDistance(Event *ev) +{ + m_fMinDistance = ev->GetFloat(1); + + if (m_fMinDistance < 0) { + m_fMinDistance = 0; + Com_Printf( + "^~^~^ Warning: mindist negative, forcing to %g for entity %i, targetname '%s'\n", + m_fMinDistance, + entnum, + TargetName().c_str() + ); + } + + m_fMinDistanceSquared = Square(m_fMinDistance); +} + +/* +=============== +Actor::EventGetMinDistance +=============== +*/ +void Actor::EventGetMinDistance(Event *ev) +{ + ev->AddFloat(m_fMinDistance); +} + +/* +=============== +Actor::EventSetMaxDistance +=============== +*/ +void Actor::EventSetMaxDistance(Event *ev) +{ + m_fMaxDistance = ev->GetFloat(1); + + if (m_fMaxDistance < 256) { + m_fMaxDistance = 256; + + Com_Printf( + "^~^~^ Warning: maxdist too small, forcing to %g for entity %i, targetname '%s'\n", + m_fMaxDistance, + entnum, + targetname.c_str() + ); + } + + m_fMaxDistanceSquared = Square(m_fMaxDistance); +} + +/* +=============== +Actor::EventGetMaxDistance +=============== +*/ +void Actor::EventGetMaxDistance(Event *ev) +{ + ev->AddFloat(m_fMaxDistance); +} + +/* +=============== +Actor::EventGetLeash +=============== +*/ +void Actor::EventGetLeash(Event *ev) +{ + ev->AddFloat(m_fLeash); +} + +/* +=============== +Actor::EventSetLeash +=============== +*/ +void Actor::EventSetLeash(Event *ev) +{ + m_fLeash = ev->GetFloat(1); + m_fLeashSquared = Square(m_fLeash); +} + +/* +=============== +Actor::EventGetInterval +=============== +*/ +void Actor::EventGetInterval(Event *ev) +{ + ev->AddFloat(m_fInterval); +} + +/* +=============== +Actor::EventSetInterval +=============== +*/ +void Actor::EventSetInterval(Event *ev) +{ + m_fInterval = ev->GetFloat(1); +} + +/* +=============== +Actor::EventDistToEnemy +=============== +*/ +void Actor::EventDistToEnemy(Event *ev) +{ + if (!m_Enemy) { + ev->AddFloat(0); + return; + } + + ev->AddFloat((origin - m_Enemy->origin).length()); +} + +/* +=============== +Actor::Init + +Initialize global actor variables. +Called from G_InitGame() +=============== +*/ +void Actor::Init(void) +{ + g_showinfo = gi.Cvar_Get("g_showinfo", "0", 0); + + for (int i = 0; i < NUM_THINKS; i++) { + GlobalFuncs[i].ThinkState = NULL; + GlobalFuncs[i].BeginState = NULL; + GlobalFuncs[i].ResumeState = NULL; + GlobalFuncs[i].EndState = NULL; + GlobalFuncs[i].SuspendState = NULL; + GlobalFuncs[i].RestartState = &Actor::DefaultRestart; + GlobalFuncs[i].FinishedAnimation = NULL; + GlobalFuncs[i].PostShoot = NULL; + GlobalFuncs[i].Pain = &Actor::DefaultPain; + GlobalFuncs[i].Killed = &Actor::DefaultKilled; + GlobalFuncs[i].PassesTransitionConditions = NULL; + GlobalFuncs[i].ShowInfo = NULL; + GlobalFuncs[i].ReceiveAIEvent = &Actor::DefaultReceiveAIEvent; + GlobalFuncs[i].IsState = NULL; + GlobalFuncs[i].PathnodeClaimRevoked = NULL; + } + + InitVoid(&GlobalFuncs[THINK_VOID]); + InitTurret(&GlobalFuncs[THINK_TURRET]); + InitCover(&GlobalFuncs[THINK_COVER]); + InitPatrol(&GlobalFuncs[THINK_PATROL]); + InitRunner(&GlobalFuncs[THINK_RUNNER]); + InitIdle(&GlobalFuncs[THINK_IDLE]); + InitPain(&GlobalFuncs[THINK_PAIN]); + InitKilled(&GlobalFuncs[THINK_KILLED]); + InitCurious(&GlobalFuncs[THINK_CURIOUS]); + InitAlarm(&GlobalFuncs[THINK_ALARM]); + InitDisguiseSalute(&GlobalFuncs[THINK_DISGUISE_SALUTE]); + InitDisguiseSentry(&GlobalFuncs[THINK_DISGUISE_SENTRY]); + InitDisguiseOfficer(&GlobalFuncs[THINK_DISGUISE_OFFICER]); + InitDisguiseRover(&GlobalFuncs[THINK_DISGUISE_ROVER]); + InitDisguiseNone(&GlobalFuncs[THINK_DISGUISE_NONE]); + InitGrenade(&GlobalFuncs[THINK_GRENADE]); + InitMachineGunner(&GlobalFuncs[THINK_MACHINEGUNNER]); + InitDogIdle(&GlobalFuncs[THINK_DOG_IDLE]); + InitDogAttack(&GlobalFuncs[THINK_DOG_ATTACK]); + InitDogCurious(&GlobalFuncs[THINK_DOG_CURIOUS]); + InitAnim(&GlobalFuncs[THINK_ANIM]); + InitAnimCurious(&GlobalFuncs[THINK_ANIM_CURIOUS]); + InitAim(&GlobalFuncs[THINK_AIM]); + InitBalconyIdle(&GlobalFuncs[THINK_BALCONY_IDLE]); + InitBalconyCurious(&GlobalFuncs[THINK_BALCONY_CURIOUS]); + InitBalconyAttack(&GlobalFuncs[THINK_BALCONY_ATTACK]); + InitBalconyDisguise(&GlobalFuncs[THINK_BALCONY_DISGUISE]); + InitBalconyGrenade(&GlobalFuncs[THINK_BALCONY_GRENADE]); + InitBalconyPain(&GlobalFuncs[THINK_BALCONY_PAIN]); + InitBalconyKilled(&GlobalFuncs[THINK_BALCONY_KILLED]); + InitWeaponless(&GlobalFuncs[THINK_WEAPONLESS]); + InitNoClip(&GlobalFuncs[THINK_NOCLIP]); + InitDead(&GlobalFuncs[THINK_DEAD]); + // Added in 2.0 + InitBadPlace(&GlobalFuncs[THINK_BADPLACE]); + // Added in 2.30 + InitRunAndShoot(&GlobalFuncs[THINK_RUN_AND_SHOOT]); + + AddWaitTill(STRING_VISIBLE); + AddWaitTill(STRING_PAIN); + AddWaitTill(STRING_DEATH); + AddWaitTill(STRING_HASENEMY); + AddWaitTill(STRING_FLAGGEDANIMDONE); + AddWaitTill(STRING_UPPERANIMDONE); + AddWaitTill(STRING_SAYDONE); + AddWaitTill(STRING_SOUNDDONE); + AddWaitTill(STRING_ANIMDONE); + AddWaitTill(STRING_MOVEDONE); + AddWaitTill(STRING_TRIGGER); + AddWaitTill(STRING_MOVE); + AddWaitTill(STRING_TURNDONE); + + if (developer->integer) { + Com_Printf("sizeof(Actor) == %zi\n", sizeof(Actor)); + //FIXME: magic ?? + Com_Printf("Magic sizeof actor number: %zd\n", sizeof(Actor) - 64); + } +} + +/* +=============== +Actor::UpdateEyeOrigin + +Update eye position. +=============== +*/ +void Actor::UpdateEyeOrigin(void) +{ + Vector eyeTag = vec_zero; + + int currLvlTime = level.inttime; + int currTime = m_iEyeUpdateTime; + + if (currLvlTime > currTime) { + m_iEyeUpdateTime = NextUpdateTime(currTime, 100); + + GetTag("eyes bone", &eyeTag, &m_vEyeDir); + + eyeposition = eyeTag - origin; + + m_vEyeDir[2] = 0.0; + m_vEyeDir.normalizefast(); + + eyeposition[0] = Q_clamp_float(eyeposition[0], -10.5f, 10.5f); + eyeposition[1] = Q_clamp_float(eyeposition[1], -10.5f, 10.5f); + eyeposition[2] = Q_clamp_float(eyeposition[2], 4.5f, 89.5f); + } +} + +/* +=============== +Actor::RequireThink + +Do I need to think ? +=============== +*/ +bool Actor::RequireThink(void) +{ + if (G_GetEntity(0)) { + return (level.inttime < edict->r.lastNetTime + 60000); + } else { + return false; + } +} + +/* +=============== +Actor::UpdateEnemyInternal + +Real update enemy. +=============== +*/ +void Actor::UpdateEnemyInternal(void) +{ + // Added in 2.0 + DetectSmokeGrenades(); + + for (Sentient *pSent = level.m_HeadSentient[1 - m_Team]; pSent; pSent = pSent->m_NextSentient) { + m_PotentialEnemies.AddPotentialEnemy(pSent); + } + + m_PotentialEnemies.CheckEnemies(this); + + if (m_Enemy != m_PotentialEnemies.GetCurrentEnemy() && (m_bEnemySwitch || !m_Enemy)) { + SetEnemy(m_PotentialEnemies.GetCurrentEnemy(), false); + } + + m_fNoticeTimeScale += (level.inttime - m_iEnemyCheckTime) / 10000.f; + + if (m_fNoticeTimeScale > m_fMaxNoticeTimeScale) { + m_fNoticeTimeScale = m_fMaxNoticeTimeScale; + } + + m_iEnemyCheckTime = level.inttime; +} + +/* +=============== +Actor::UpdateEnemy + +Update enemy w.r.t m_iEnemyCheckTime. +=============== +*/ +void Actor::UpdateEnemy(int iMaxDirtyTime) +{ + if (level.inttime > iMaxDirtyTime + m_iEnemyCheckTime) { + UpdateEnemyInternal(); + } +} + +/* +=============== +Actor::DetectSmokeGrenades +=============== +*/ +void Actor::DetectSmokeGrenades(void) +{ + SmokeSprite *sprite; + + if (m_Enemy) { + return; + } + + sprite = G_GetRandomSmokeSprite(); + if (!sprite || !sprite->owner) { + return; + } + + if (sprite->owner->m_Team != m_Team) { + return; + } + + const Vector eyePos = VirtualEyePosition(); + const float fDistSquared = (sprite->origin - eyePos).lengthSquared(); + + if (fDistSquared > Square(256) || InFOV(sprite->origin)) { + if (G_SightTrace( + eyePos, vec_zero, vec_zero, sprite->origin, this, NULL, MASK_CANSEE, false, "Actor::DetectSmokeGrenades" + )) { + m_PotentialEnemies.ConfirmEnemy(this, sprite->owner); + } + } +} + +/* +=============== +Actor::SetEnemy + +Set current enemy. +=============== +*/ +void Actor::SetEnemy(Sentient *pEnemy, bool bForceConfirmed) +{ + if (pEnemy == m_Enemy) { + return; + } + + if (m_Enemy) { + m_Enemy->m_iAttackerCount--; + } + m_bNewEnemy = m_Enemy == NULL; + m_Enemy = pEnemy; + + m_iEnemyChangeTime = level.inttime; + + if (m_Enemy) { + PostEvent(EV_Actor_ShareEnemy, 0.75f); + + m_bEnemyIsDisguised = m_Enemy->m_bHasDisguise && (m_Enemy->m_bIsDisguised || !CanSeeEnemy(0)); + + SetEnemyPos(m_Enemy->origin); + m_Enemy->m_iAttackerCount++; + + if (bForceConfirmed) { + m_PotentialEnemies.ConfirmEnemy(this, m_Enemy); + } + } +} + +/* +=============== +Actor::SetEnemyPos + +Update stored enemy position information. +=============== +*/ +void Actor::SetEnemyPos(Vector vPos) +{ + if (m_vLastEnemyPos == vPos) { + return; + } + + m_iLastEnemyPosChangeTime = level.inttime; + m_vLastEnemyPos = vPos; + mTargetPos = m_vLastEnemyPos; + + if (!m_Enemy) { + mTargetPos.z += 88; + } else if (m_Enemy->m_bIsAnimal) { + mTargetPos.z += 10; + } else { + mTargetPos += m_Enemy->eyeposition; + } + + if (mTargetPos.z - EyePosition().z < 128) { + mTargetPos.z -= 16; + } +} + +static bool UnknownAnim(const char *name, dtiki_t *tiki) +{ + ScriptException::next_bIsForAnim = true; + ScriptError("unknown animation '%s' in '%s'", name, tiki->a->name); +} + +/* +=============== +Actor::EventSetAnim + +Set animation event. +=============== +*/ +void Actor::EventSetAnim(Event *ev) +{ + const_str name = 0; + float weight = 1; + int slot = 0; + int anim; + const_str flagVal; + qboolean flagged = false; + + switch (ev->NumArgs()) { + case 4: + flagVal = ev->GetConstString(4); + flagged = true; + if (flagVal != STRING_FLAGGED) { + ScriptError("unknown keyword '%s', expected 'flagged'", Director.GetString(flagVal).c_str()); + } + case 3: + weight = ev->GetFloat(3); + if (weight < 0) { + ScriptError("Negative anim weight not allowed"); + } + + if (!weight) { + return; + } + case 2: + slot = ev->GetInteger(2); + if (slot > 2) { + ScriptError("Bad animation slot, only 0 and 1 supported"); + } + case 1: + name = ev->GetConstString(1); + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str()); + if (anim == -1) { + UnknownAnim(Director.GetString(name).c_str(), edict->tiki); + } + break; + default: + ScriptError("bad number of arguments"); + break; + } + + if (!slot) { + flagged = true; + } + + if (flagged) { + parm.motionfail = true; + } + + if (!m_bLevelMotionAnim) { + if (slot) { + m_weightType[GetMotionSlot(slot)] = 0; + } else { + ChangeMotionAnim(); + m_bMotionAnimSet = true; + } + + StartMotionAnimSlot(slot, anim, weight); + if (flagged) { + m_iMotionSlot = GetMotionSlot(slot); + parm.motionfail = false; + } + } +} + +/* +=============== +Actor::EventEndActionAnim + +End action animation. +=============== +*/ +void Actor::EventEndActionAnim(Event *ev) +{ + parm.upperfail = true; + if (!m_bLevelActionAnim) { + ChangeActionAnim(); + parm.upperfail = false; + } +} + +/* +=============== +Actor::EventSetMotionAnim + +Set motion animation. +=============== +*/ +void Actor::EventSetMotionAnim(Event *ev) +{ + int anim; + const_str name; + + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + + if (anim == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + parm.motionfail = true; + + if (!m_bLevelMotionAnim) { + ChangeMotionAnim(); + + // start the animation + m_bMotionAnimSet = true; + StartMotionAnimSlot(0, anim, 2.0); + // set the slot + m_iMotionSlot = GetMotionSlot(0); + + parm.motionfail = false; + } +} + +/* +=============== +Actor::EventSetAimMotionAnim + +Set aim motion animation. +=============== +*/ +void Actor::EventSetAimMotionAnim(Event *ev) +{ + const_str name; + int anim_crouch, anim_stand, anim_high; + + if (ev->NumArgs() != 3) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + anim_crouch = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + if (anim_crouch == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + name = ev->GetConstString(2); + anim_stand = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + if (anim_stand == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + name = ev->GetConstString(3); + anim_high = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + if (anim_high == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + parm.motionfail = true; + + if (!m_bLevelMotionAnim) { + ChangeMotionAnim(); + + m_bMotionAnimSet = true; + UpdateAimMotion(); + + StartAimMotionAnimSlot(0, anim_crouch); + StartAimMotionAnimSlot(1, anim_stand); + StartAimMotionAnimSlot(2, anim_high); + + m_iMotionSlot = GetMotionSlot(1); + parm.motionfail = false; + } +} + +/* +=============== +Actor::EventSetActionAnim + +Set action animation. +=============== +*/ +void Actor::EventSetActionAnim(Event *ev) +{ + const_str name; + int anim_forward, anim_up, anim_down; + str derivedName; + + if (ev->NumArgs() != 3) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + m_fAimLimit_down = ev->GetFloat(2); + if (m_fAimLimit_down >= 0) { + m_fAimLimit_down = -0.001f; + ScriptError("Positive lower_limit not allowed"); + } + + m_fAimLimit_up = ev->GetFloat(3); + if (m_fAimLimit_up <= 0) { + m_fAimLimit_up = 0.001f; + ScriptError("Negative upper_limit not allowed"); + } + + anim_forward = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + if (anim_forward == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + derivedName = Director.GetString(name) + "_up"; + anim_up = gi.Anim_NumForName(edict->tiki, derivedName); + if (anim_up == -1) { + UnknownAnim(derivedName, edict->tiki); + } + + derivedName = Director.GetString(name) + "_down"; + anim_down = gi.Anim_NumForName(edict->tiki, derivedName); + if (anim_down == -1) { + UnknownAnim(derivedName, edict->tiki); + } + + parm.upperfail = true; + if (!m_bLevelActionAnim) { + ChangeActionAnim(); + m_bAimAnimSet = true; + m_bActionAnimSet = true; + UpdateAim(); + + StartAimAnimSlot(0, anim_up); + StartAimAnimSlot(1, anim_forward); + StartAimAnimSlot(2, anim_down); + m_iActionSlot = GetActionSlot(0); + parm.upperfail = false; + } +} + +/* +=============== +Actor::EventUpperAnim + +Set upper body. +=============== +*/ +void Actor::EventUpperAnim(Event *ev) +{ + int anim; + const_str name; + + if (ev->NumArgs()) { + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + if (anim == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + m_csUpperAnim = name; + } else if (m_bLevelActionAnim) { + AnimFinished(m_iActionSlot, true); + } +} + +/* +=============== +Actor::EventSetUpperAnim + +Set upper body animation. +=============== +*/ +void Actor::EventSetUpperAnim(Event *ev) +{ + int anim; + const_str name; + + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + if (anim == -1) { + UnknownAnim(Director.GetString(name), edict->tiki); + } + + parm.upperfail = true; + + if (!m_bLevelActionAnim) { + ChangeActionAnim(); + m_bActionAnimSet = true; + + StartActionAnimSlot(anim); + m_iActionSlot = GetActionSlot(0); + + parm.upperfail = false; + } +} + +/* +=============== +Actor::SoundSayAnim + +Returns true if animation not found. +=============== +*/ +bool Actor::SoundSayAnim(const_str name, byte bLevelSayAnim) +{ + if (gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str()) != -1) { + return false; + } + + ChangeSayAnim(); + m_bSayAnimSet = true; + m_bLevelSayAnim = bLevelSayAnim; + m_iSaySlot = -2; + + Com_Printf( + "Couldn't find animation '%s' in '%s' - trying sound alias instead.\n", + Director.GetString(name).c_str(), + edict->tiki->a->name + ); + + Sound(Director.GetString(name), CHAN_AUTO, 0, 0, NULL, 0, 0, 1, 1, -1); + + return true; +} + +/* +=============== +Actor::EventIdleSayAnim + +Play idle say dialogue. +=============== +*/ +void Actor::EventIdleSayAnim(Event *ev) +{ + const_str name; + + if (!ev->NumArgs() && m_bLevelSayAnim == 1) { + AnimFinished(m_iSaySlot, true); + return; + } + + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + + if (m_ThinkState == THINKSTATE_KILLED || m_ThinkState == THINKSTATE_PAIN || m_ThinkState == THINKSTATE_ATTACK + || m_ThinkState == THINKSTATE_GRENADE || !SoundSayAnim(name, 1)) { + m_csSayAnim = name; + m_bNextLevelSayAnim = 1; + } +} + +/* +=============== +Actor::EventSayAnim + +Play idle dialogue. +=============== +*/ +void Actor::EventSayAnim(Event *ev) +{ + const_str name; + + if (!ev->NumArgs() && m_bLevelSayAnim) { + AnimFinished(m_iSaySlot, true); + return; + } + + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + name = ev->GetConstString(1); + + if (m_ThinkState == THINKSTATE_KILLED || m_ThinkState == THINKSTATE_PAIN || !SoundSayAnim(name, 2)) { + m_csSayAnim = name; + m_bNextLevelSayAnim = 2; + } +} + +/* +=============== +Actor::EventSetSayAnim + +Set say animation. +=============== +*/ +void Actor::EventSetSayAnim(Event *ev) +{ + int anim; + int animflags; + const_str name; + + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + if (m_bLevelSayAnim) { + return; + } + + name = ev->GetConstString(1); + parm.sayfail = true; + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(name)); + + if (anim == -1) { + ChangeSayAnim(); + m_bSayAnimSet = true; + m_iSaySlot = -2; + + Com_Printf( + "Couldn't find animation '%s' in '%s' - trying sound alias instead.\n", + Director.GetString(name).c_str(), + edict->tiki->a->name + ); + Sound(Director.GetString(name), CHAN_AUTO, 0, 0, NULL, 0, 0, true, true); + return; + } + + animflags = gi.Anim_FlagsSkel(edict->tiki, anim); + if (animflags & TAF_HASUPPER) { + if (m_bLevelActionAnim) { + if (!m_bSayAnimSet) { + m_iSaySlot = m_iActionSlot; + } + return; + } + + if (flags & TAF_HASDELTA) { + if (m_bLevelMotionAnim) { + if (!m_bSayAnimSet) { + m_iSaySlot = m_iMotionSlot; + } + return; + } + + ChangeActionAnim(); + ChangeMotionAnim(); + StartMotionAnimSlot(0, anim, 1.0); + + m_iMotionSlot = m_iActionSlot = GetMotionSlot(0); + } else { + ChangeActionAnim(); + m_bActionAnimSet = true; + StartActionAnimSlot(anim); + m_iActionSlot = GetActionSlot(0); + } + + ChangeSayAnim(); + m_bSayAnimSet = true; + m_iSaySlot = m_iActionSlot; + } else { + ChangeSayAnim(); + m_bSayAnimSet = true; + StartSayAnimSlot(anim); + m_iSaySlot = GetSaySlot(); + } + + parm.sayfail = false; +} + +/* +=============== +Actor::ChangeAnim + +Change current animation. +=============== +*/ + +void Actor::ChangeAnim(void) +{ + if (m_pAnimThread) { + if (g_scripttrace->integer && m_pAnimThread->CanScriptTracePrint()) { + Com_Printf("--- Change Anim\n"); + } + + m_pAnimThread->AbortRegistration(STRING_EMPTY, this); + delete m_pAnimThread->GetScriptClass(); + // The animation thread must be deleted afterwards + assert(!m_pAnimThread); + } + + switch (m_ThinkState) { + case THINKSTATE_PAIN: + case THINKSTATE_KILLED: + if (m_bMotionAnimSet) { + AnimFinished(m_iMotionSlot, true); + } + if (m_bActionAnimSet) { + AnimFinished(m_iActionSlot, true); + } + if (m_bSayAnimSet) { + AnimFinished(m_iSaySlot, true); + } + break; + case THINKSTATE_ATTACK: + case THINKSTATE_GRENADE: + if (m_bMotionAnimSet) { + AnimFinished(m_iMotionSlot, true); + } + if (m_bActionAnimSet) { + AnimFinished(m_iActionSlot, true); + } + if (m_bSayAnimSet && m_bLevelSayAnim != 2) { + AnimFinished(m_iSaySlot, true); + } + break; + default: + if (m_bMotionAnimSet && m_bLevelMotionAnim == 0) { + AnimFinished(m_iMotionSlot, true); + } + if (m_bActionAnimSet && m_bLevelActionAnim == 0) { + AnimFinished(m_iActionSlot, true); + } + if (m_bSayAnimSet && m_bLevelSayAnim == 0) { + AnimFinished(m_iSaySlot, true); + } + break; + } + + m_fCrossblendTime = 0.5f; + m_pAnimThread = m_Anim.Create(this); + if (m_pAnimThread) { + if (g_scripttrace->integer && m_pAnimThread->CanScriptTracePrint()) { + Com_Printf("+++ Change Anim\n"); + } + + m_pAnimThread->Register(STRING_EMPTY, this); + m_pAnimThread->StartTiming(); + } +} + +/* +=============== +Actor::UpdateSayAnim + +Update say animation. +=============== +*/ +void Actor::UpdateSayAnim(void) +{ + int anim; + int animflags; + + if (m_ThinkState == THINKSTATE_KILLED || m_ThinkState == THINKSTATE_PAIN) { + if (!m_bSayAnimSet) { + Unregister(STRING_SAYDONE); + } + return; + } + + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csSayAnim)); + if (anim == -1) { + return; + } + + animflags = gi.Anim_FlagsSkel(edict->tiki, anim); + if (animflags & TAF_HASUPPER) { + if (m_ThinkState == THINKSTATE_ATTACK || m_ThinkState == THINKSTATE_GRENADE) { + if (!m_bSayAnimSet) { + Unregister(STRING_SAYDONE); + } + return; + } + + ChangeActionAnim(); + + if (animflags & TAF_HASDELTA) { + ChangeMotionAnim(); + StartMotionAnimSlot(0, anim, 1.0); + + m_bLevelActionAnim = true; + m_bLevelMotionAnim = true; + m_iMotionSlot = m_iActionSlot = GetMotionSlot(0); + } else { + m_bActionAnimSet = true; + StartActionAnimSlot(anim); + m_bLevelActionAnim = true; + m_iActionSlot = GetActionSlot(0); + } + + ChangeSayAnim(); + m_bSayAnimSet = true; + m_bLevelSayAnim = m_bNextLevelSayAnim; + m_bNextLevelSayAnim = false; + m_iSaySlot = m_iActionSlot; + } else if (m_bNextLevelSayAnim != 2 && (m_ThinkState == THINKSTATE_ATTACK || m_ThinkState == THINKSTATE_GRENADE)) { + if (!m_bSayAnimSet) { + Unregister(STRING_SAYDONE); + } + } else { + ChangeSayAnim(); + + m_bSayAnimSet = true; + StartSayAnimSlot(anim); + + m_bLevelSayAnim = m_bNextLevelSayAnim; + m_bNextLevelSayAnim = 0; + m_iSaySlot = GetSaySlot(); + return; + } +} + +/* +=============== +Actor::UpdateUpperAnim + +Update upper animation. +=============== +*/ +void Actor::UpdateUpperAnim(void) +{ + int anim; + + anim = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csUpperAnim).c_str()); + if (anim == -1) { + return; + } + + if (m_ThinkState == THINKSTATE_ATTACK || m_ThinkState == THINKSTATE_GRENADE || m_ThinkState == THINKSTATE_KILLED + || m_ThinkState == THINKSTATE_PAIN) { + if (!m_bActionAnimSet) { + Unregister(STRING_UPPERANIMDONE); + } + + return; + } + + gi.Anim_FlagsSkel(edict->tiki, anim); + + ChangeActionAnim(); + + m_bActionAnimSet = true; + StartActionAnimSlot(anim); + m_bLevelActionAnim = true; + m_iActionSlot = GetActionSlot(0); +} + +/* +=============== +Actor::UpdateAnim + +Update animation. +=============== +*/ +void Actor::UpdateAnim(void) +{ + float time; + float total_weight; + float fAnimTime; + float fAnimWeight; + + m_bAnimating = true; + UpdateAim(); + + if (UpdateSelectedAnimation()) { + ChangeAnim(); + } + + Director.Unpause(); + Director.Pause(); + + if (m_csSayAnim != STRING_EMPTY) { + UpdateSayAnim(); + m_csSayAnim = STRING_EMPTY; + } + + if (m_csUpperAnim != STRING_EMPTY) { + UpdateUpperAnim(); + m_csUpperAnim = STRING_EMPTY; + } + + if (!m_bSayAnimSet && !m_bIsAnimal) { + UpdateEmotion(); + } + + for (int slot = 0; slot < MAX_FRAMEINFOS - 2; slot++) { + if (!((m_bUpdateAnimDoneFlags >> slot) & 1)) { + UpdateAnimSlot(slot); + } + } + + time = 0; + total_weight = 0; + + for (int slot = 0; slot < MAX_FRAMEINFOS - 2; slot++) { + if (m_weightType[slot] != ANIM_WEIGHT_MOTION && m_weightType[slot] != ANIM_WEIGHT_CROSSBLEND_2) { + UseSyncTime(slot, 0); + continue; + } + + if (!IsRepeatType(slot)) { + UseSyncTime(slot, 0); + continue; + } + + UseSyncTime(slot, 1); + fAnimTime = AnimTime(slot); + fAnimWeight = GetWeight(slot); + time += fAnimTime * fAnimWeight; + + if (!isfinite(time)) { + Com_Printf( + "ent %i, targetname '%s', anim '%s', slot %i, fAnimTime %f, fAnimWeight %f\n", + entnum, + targetname.c_str(), + AnimName(slot), + slot, + fAnimTime, + fAnimWeight + ); + } + total_weight += fAnimWeight; + } + + if (total_weight != 0) { + float rate; + + rate = time / total_weight; + if (m_Team != TEAM_GERMAN) { + rate /= 1.45f; + } + + SetSyncRate(rate / m_fRunAnimRate); + } + + PostAnimate(); +} + +/* +=============== +Actor::Think + +Think function for actor. +Calls think function related to the current thinkstate. +=============== +*/ +void Actor::Think(void) +{ + int iNewCurrentHistory; + + if (!g_ai->integer) { + // AI is disabled + return; + } + + if (!m_bDoAI) { + return; + } + + if (!edict->tiki) { + return; + } + + m_bAnimating = false; + + Director.Pause(); + + iNewCurrentHistory = level.inttime / 125 % 4; + if (m_iCurrentHistory != iNewCurrentHistory) { + m_iCurrentHistory = iNewCurrentHistory; + + if (iNewCurrentHistory >= 1) { + VectorCopy2D(origin, m_vOriginHistory[iNewCurrentHistory - 1]); + } else { + VectorCopy2D(origin, m_vOriginHistory[3]); + } + } + + if (m_bNoPlayerCollision) { + Entity *player = G_GetEntity(0); + + if (!IsTouching(player)) { + Com_Printf("(entnum %d, radnum %d) is going solid after not getting stuck in the player\n", entnum, radnum); + setSolidType(SOLID_BBOX); + m_bNoPlayerCollision = false; + } + } + + m_eNextAnimMode = -1; + FixAIParameters(); + UpdateEnableEnemy(); + + if (m_pTetherEnt) { + m_vHome = m_pTetherEnt->origin; + } + + parm.movefail = false; + if (m_bBecomeRunner && m_ThinkMap[THINKSTATE_IDLE] != THINK_RUNNER && m_ThinkMap[THINKSTATE_IDLE] != THINK_PATROL) { + parm.movefail = true; + } + + if (m_bDirtyThinkState) { + m_bDirtyThinkState = false; + ThinkStateTransitions(); + } + + GlobalFuncs_t *Think = &GlobalFuncs[m_Think[m_ThinkLevel]]; + + if (Think->ThinkState) { + (this->*Think->ThinkState)(); + } + + m_bNeedReload = false; + mbBreakSpecialAttack = false; + + Director.Unpause(); +} + +/* +=============== +Actor::CheckUnregister + +Notify scripts when the actor has: +- Finished moving +- Has a new enemy +- And/or if the enemy is visible +=============== +*/ +void Actor::CheckUnregister(void) +{ + m_bBecomeRunner = false; + + if (parm.movefail) { + parm.movedone = false; + Unregister(STRING_MOVEDONE); + } + + if (m_Enemy) { + Unregister(STRING_HASENEMY); + } + + if (m_bEnemyVisible) { + Unregister(STRING_VISIBLE); + } +} + +/* +=============== +Actor::PostThink + +Called after think is finished. +=============== +*/ +void Actor::PostThink(bool bDontFaceWall) +{ + CheckUnregister(); + + if (bDontFaceWall && (!m_pTurnEntity || m_ThinkState != THINKSTATE_IDLE)) { + DontFaceWall(); + } + + if (is_paused) { + return; + } + + UpdateAngles(); + UpdateAnim(); + DoMove(); + UpdateBoneControllers(); + UpdateFootsteps(); +} + +/* +=============== +Actor::AnimFinished + +=============== +*/ +void Actor::AnimFinished(int slot, bool stop) +{ + if (stop && slot >= 0) { + animFlags[slot] |= ANIM_NOACTION; + } + + if (slot == m_iMotionSlot) { + if (stop) { + m_iMotionSlot = -1; + m_bLevelMotionAnim = false; + } + + MPrintf("flagged anim finished slot %d\n", slot); + Unregister(STRING_FLAGGEDANIMDONE); + } + + if (slot == m_iActionSlot) { + if (stop) { + ChangeActionAnim(); + } + + if (m_csUpperAnim == STRING_EMPTY) { + MPrintf("upper anim finished slot %d\n", slot); + Unregister(STRING_UPPERANIMDONE); + } + } + + if (slot == m_iSaySlot) { + if (stop) { + ChangeSayAnim(); + } + + if (m_csSayAnim == STRING_EMPTY) { + MPrintf("say anim finished slot %d\n", slot); + Unregister(STRING_SAYDONE); + } + } else if (slot == GetSaySlot() && stop) { + ChangeSayAnim(); + } +} + +/* +=============== +Actor::AnimFinished + +=============== +*/ +void Actor::AnimFinished(int slot) +{ + animFlags[slot] &= ~ANIM_FINISHED; + AnimFinished(slot, !IsRepeatType(slot)); +} + +/* +=============== +Actor::SetThink + +Modifies think num of current thinkstate inside m_ThinkMap. +=============== +*/ +void Actor::SetThink(eThinkState state, eThinkNum think) +{ + m_ThinkMap[state] = think; + + if (m_ThinkState == state) { + m_bDirtyThinkState = true; + } +} + +/* +=============== +Actor::SetThink + +Set think to idle. +=============== +*/ +void Actor::SetThinkIdle(eThinkNum think_idle) +{ + eThinkNum think_curious; + + switch (think_idle) { + case THINK_PATROL: + case THINK_RUNNER: + think_curious = THINK_CURIOUS; + m_bBecomeRunner = true; + break; + case THINK_MACHINEGUNNER: + think_curious = THINK_MACHINEGUNNER; + break; + case THINK_DOG_IDLE: + think_curious = THINK_DOG_CURIOUS; + SetThink(THINKSTATE_GRENADE, THINK_DOG_CURIOUS); + break; + case THINK_ANIM: + think_curious = THINK_ANIM_CURIOUS; + break; + case THINK_BALCONY_IDLE: + think_curious = THINK_BALCONY_CURIOUS; + break; + default: + think_curious = THINK_CURIOUS; + break; + } + + SetThink(THINKSTATE_IDLE, think_idle); + SetThink(THINKSTATE_CURIOUS, think_curious); +} + +/* +=============== +Actor::GetThinkType + +Get think for csName. +=============== +*/ +int Actor::GetThinkType(const_str csName) +{ + int i; + + for (i = 0; i < NUM_THINKS; i++) { + if (m_csThinkNames[i] == csName) { + return i; + } + } + + ScriptError("unknown think type '%s'", Director.GetString(csName).c_str()); +} + +/* +=============== +Actor::SetThinkState + +Set thinkstate. +=============== +*/ +void Actor::SetThinkState(eThinkState state, eThinkLevel level) +{ + eThinkNum map; + + if (state == THINKSTATE_ATTACK) { + m_csIdleMood = STRING_NERVOUS; + map = m_ThinkMap[THINKSTATE_ATTACK]; + + if (map != THINK_ALARM && map != THINK_WEAPONLESS && map != THINK_DOG_ATTACK && !GetWeapon(WEAPON_MAIN)) { + Com_Printf( + "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): forcing weaponless attack state.\n" + "^~^~^ Level designers should specify 'type_attack weaponless' for this guy.\n", + entnum, + radnum, + TargetName().c_str() + ); + + SetThink(THINKSTATE_ATTACK, THINK_WEAPONLESS); + } + } + + m_ThinkStates[level] = state; + + if (m_ThinkLevel <= level) { + m_bDirtyThinkState = true; + } +} + +/* +=============== +Actor::EndCurrentThinkState + +End current think state. +=============== +*/ +void Actor::EndCurrentThinkState(void) +{ + SetThinkState(THINKSTATE_VOID, m_ThinkLevel); +} + +/* +=============== +Actor::ClearThinkStates + +Clear all thinkstates. +=============== +*/ +void Actor::ClearThinkStates(void) +{ + for (int i = 0; i < NUM_THINKLEVELS; i++) { + SetThinkState(THINKSTATE_VOID, (eThinkLevel)i); + } +} + +/* +=============== +Actor::EventSetAlarmNode +=============== +*/ +void Actor::EventSetAlarmNode(Event *ev) +{ + Listener *l = ev->GetListener(1); + if (l && !l->isSubclassOf(SimpleEntity)) { + ScriptError("Alarm node must be an entity"); + } + + m_AlarmNode = static_cast(l); +} + +/* +=============== +Actor::EventGetAlarmNode +=============== +*/ +void Actor::EventGetAlarmNode(Event *ev) +{ + ev->AddListener(m_AlarmNode); +} + +/* +=============== +Actor::EventSetPreAlarmThread +=============== +*/ +void Actor::EventSetPreAlarmThread(Event *ev) +{ + if (ev->IsFromScript()) { + m_PreAlarmThread.SetThread(ev->GetValue()); + } else { + m_PreAlarmThread.Set(ev->GetString(1)); + } +} + +/* +=============== +Actor::EventSetAlarmThread +=============== +*/ +void Actor::EventSetAlarmThread(Event *ev) +{ + if (ev->IsFromScript()) { + m_AlarmThread.SetThread(ev->GetValue()); + } else { + m_AlarmThread.Set(ev->GetString(1)); + } +} + +/* +=============== +Actor::EventGetAlarmThread +=============== +*/ +void Actor::EventGetAlarmThread(Event *ev) +{ + m_AlarmThread.GetScriptValue(&ev->GetValue()); +} + +/* +=============== +Actor::EventSetSoundAwareness +=============== +*/ +void Actor::EventSetSoundAwareness(Event *ev) +{ + m_fSoundAwareness = ev->GetFloat(1); +} + +/* +=============== +Actor::EventGetSoundAwareness +=============== +*/ +void Actor::EventGetSoundAwareness(Event *ev) +{ + ev->AddFloat(m_fSoundAwareness); +} + +/* +=============== +Actor::EventSetGrenadeAwareness +=============== +*/ +void Actor::EventSetGrenadeAwareness(Event *ev) +{ + m_fGrenadeAwareness = ev->GetFloat(1); +} + +/* +=============== +Actor::EventGetGrenadeAwareness +=============== +*/ +void Actor::EventGetGrenadeAwareness(Event *ev) +{ + ev->AddFloat(m_fGrenadeAwareness); +} + +/* +=============== +Actor::EventSetTypeIdle +=============== +*/ +void Actor::EventSetTypeIdle(Event *ev) +{ + bool (*AllowedState)(int state); + eThinkNum think; + + think = (eThinkNum)GetThinkType(ev->GetConstString(1)); + AllowedState = Actor::GlobalFuncs[think].IsState; + + if (!AllowedState(THINKSTATE_IDLE)) { + SetThinkIdle(THINK_IDLE); + ScriptError("Invalid idle think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); + } + + SetThinkIdle(think); +} + +/* +=============== +Actor::EventGetTypeIdle +=============== +*/ +void Actor::EventGetTypeIdle(Event *ev) +{ + ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_IDLE]]); +} + +/* +=============== +Actor::EventSetTypeAttack +=============== +*/ +void Actor::EventSetTypeAttack(Event *ev) +{ + bool (*AllowedState)(int state); + eThinkNum think; + + think = (eThinkNum)GetThinkType(ev->GetConstString(1)); + AllowedState = Actor::GlobalFuncs[think].IsState; + + if (!AllowedState(THINKSTATE_ATTACK)) { + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + ScriptError("Invalid attack think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); + } + + SetThink(THINKSTATE_ATTACK, think); +} + +/* +=============== +Actor::EventGetTypeAttack +=============== +*/ +void Actor::EventGetTypeAttack(Event *ev) +{ + ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]); +} + +/* +=============== +Actor::EventSetTypeDisguise +=============== +*/ +void Actor::EventSetTypeDisguise(Event *ev) +{ + bool (*AllowedState)(int state); + eThinkNum think; + + think = (eThinkNum)GetThinkType(ev->GetConstString(1)); + AllowedState = Actor::GlobalFuncs[think].IsState; + + if (!AllowedState(THINKSTATE_DISGUISE)) { + SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE); + ScriptError("Invalid disguise think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); + } + + SetThink(THINKSTATE_DISGUISE, think); +} + +/* +=============== +Actor::EventSetDisguiseAcceptThread +=============== +*/ +void Actor::EventSetDisguiseAcceptThread(Event *ev) +{ + if (ev->IsFromScript()) { + m_DisguiseAcceptThread.SetThread(ev->GetValue()); + } else { + m_DisguiseAcceptThread.Set(ev->GetString(1)); + } +} + +/* +=============== +Actor::EventGetDisguiseAcceptThread +=============== +*/ +void Actor::EventGetDisguiseAcceptThread(Event *ev) +{ + m_DisguiseAcceptThread.GetScriptValue(&ev->GetValue()); +} + +/* +=============== +Actor::EventGetTypeDisguise +=============== +*/ +void Actor::EventGetTypeDisguise(Event *ev) +{ + ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_DISGUISE]]); +} + +/* +=============== +Actor::EventSetDisguiseLevel +=============== +*/ +void Actor::EventSetDisguiseLevel(Event *ev) +{ + m_iDisguiseLevel = ev->GetInteger(1); + + if (m_iDisguiseLevel != 1 && m_iDisguiseLevel != 2) { + m_iDisguiseLevel = 1; + ScriptError("bad disguise level %d for %s, setting to 1\n", m_iDisguiseLevel, TargetName().c_str()); + } +} + +/* +=============== +Actor::EventGetDisguiseLevel +=============== +*/ +void Actor::EventGetDisguiseLevel(Event *ev) +{ + ev->AddInteger(m_iDisguiseLevel); +} + +/* +=============== +Actor::EventSetTypeGrenade +=============== +*/ +void Actor::EventSetTypeGrenade(Event *ev) +{ + bool (*AllowedState)(int state); + eThinkNum think; + + think = (eThinkNum)GetThinkType(ev->GetConstString(1)); + AllowedState = Actor::GlobalFuncs[think].IsState; + + if (!AllowedState(THINKSTATE_GRENADE)) { + SetThink(THINKSTATE_GRENADE, THINK_GRENADE); + ScriptError("Invalid grenade think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); + } + + SetThink(THINKSTATE_GRENADE, think); +} + +/* +=============== +Actor::EventGetTypeGrenade +=============== +*/ +void Actor::EventGetTypeGrenade(Event *ev) +{ + ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_GRENADE]]); +} + +/* +=============== +Actor::InitThinkStates + +Initialize think related stuff. +=============== +*/ +void Actor::InitThinkStates(void) +{ + for (size_t i = 0; i < NUM_THINKSTATES; i++) { + m_ThinkMap[i] = THINK_VOID; + } + + for (size_t i = 0; i < NUM_THINKLEVELS; i++) { + m_Think[i] = THINK_VOID; + m_ThinkStates[i] = THINKSTATE_VOID; + } + + m_ThinkMap[THINKSTATE_VOID] = THINK_VOID; + m_ThinkMap[THINKSTATE_IDLE] = THINK_IDLE; + m_ThinkMap[THINKSTATE_PAIN] = THINK_PAIN; + m_ThinkMap[THINKSTATE_KILLED] = THINK_KILLED; + m_ThinkMap[THINKSTATE_ATTACK] = THINK_TURRET; + m_ThinkMap[THINKSTATE_CURIOUS] = THINK_CURIOUS; + m_ThinkMap[THINKSTATE_DISGUISE] = THINK_DISGUISE_SALUTE; + m_ThinkMap[THINKSTATE_GRENADE] = THINK_GRENADE; + m_ThinkMap[THINKSTATE_BADPLACE] = THINK_BADPLACE; + m_ThinkMap[THINKSTATE_NOCLIP] = THINK_NOCLIP; + + m_ThinkLevel = THINKLEVEL_IDLE; + m_ThinkState = THINKSTATE_VOID; + m_bDirtyThinkState = false; +} + +/* +=============== +Actor::DefaultRestart + +Default restart of current think state. +=============== +*/ +void Actor::DefaultRestart(void) +{ + EndState(m_ThinkLevel); + BeginState(); +} + +/* +=============== +Actor::SuspendState + +Suspend current think state. +=============== +*/ +void Actor::SuspendState(void) +{ + GlobalFuncs_t *think = &GlobalFuncs[CurrentThink()]; + + if (think->SuspendState) { + (this->*think->SuspendState)(); + } +} + +/* +=============== +Actor::ResumeState + +Resume current think state. +=============== +*/ +void Actor::ResumeState(void) +{ + GlobalFuncs_t *think = &GlobalFuncs[CurrentThink()]; + + if (think->ResumeState) { + (this->*think->ResumeState)(); + } +} + +/* +=============== +Actor::BeginState + +Begin current think state. +=============== +*/ +void Actor::BeginState(void) +{ + GlobalFuncs_t *think; + + m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; + think = &GlobalFuncs[CurrentThink()]; + + if (think->BeginState) { + (this->*think->BeginState)(); + } + + m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; +} + +/* +=============== +Actor::EndState + +End current think state. +=============== +*/ +void Actor::EndState(int level) +{ + GlobalFuncs_t *think; + + think = &GlobalFuncs[m_Think[level]]; + m_Think[level] = THINK_VOID; + + if (think->EndState) { + (this->*think->EndState)(); + } + + if (m_pAnimThread) { + m_pAnimThread->AbortRegistration(STRING_EMPTY, this); + } +} + +/* +=============== +Actor::RestartState + +Restart current think state. +=============== +*/ +void Actor::RestartState(void) +{ + GlobalFuncs_t *think = &GlobalFuncs[CurrentThink()]; + + if (think->RestartState) { + (this->*think->RestartState)(); + } +} + +/* +=============== +Actor::UpdateEnableEnemy + +Enable/disable enemy based on desired value. +Can be changed from script. +=============== +*/ +void Actor::UpdateEnableEnemy(void) +{ + if (m_bEnableEnemy == m_bDesiredEnableEnemy) { + // no change + return; + } + + m_bEnableEnemy = m_bDesiredEnableEnemy; + + if (m_bEnableEnemy) { + SetLeashHome(origin); + } else { + if (m_ThinkStates[THINKLEVEL_IDLE] == THINKSTATE_ATTACK || m_ThinkStates[THINKLEVEL_IDLE] == THINKSTATE_CURIOUS + || m_ThinkStates[THINKLEVEL_IDLE] == THINKSTATE_DISGUISE) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } + + SetEnemy(NULL, false); + } +} + +/* +=============== +Actor::ThinkStateTransitions + +Transition think state and level. +Called when thinkstate/level are change. +=============== +*/ +void Actor::ThinkStateTransitions(void) +{ + int i; + eThinkLevel newThinkLevel; + + for (newThinkLevel = THINKLEVEL_NOCLIP; newThinkLevel; newThinkLevel = (eThinkLevel)(newThinkLevel - 1)) { + if (m_ThinkStates[newThinkLevel]) { + break; + } + } + + if (m_ThinkMap[m_ThinkStates[newThinkLevel]] != CurrentThink()) { + for (i = 0; i < newThinkLevel; i++) { + if (!m_ThinkStates[i]) { + EndState(i); + } + } + + if (newThinkLevel > m_ThinkLevel) { + SuspendState(); + m_ThinkLevel = newThinkLevel; + m_ThinkState = m_ThinkStates[m_ThinkLevel]; + BeginState(); + } else { + EndState(m_ThinkLevel); + + if (newThinkLevel == m_ThinkLevel) { + m_ThinkState = m_ThinkStates[m_ThinkLevel]; + BeginState(); + } else { + m_ThinkLevel = newThinkLevel; + m_ThinkState = m_ThinkStates[m_ThinkLevel]; + + if (CurrentThink() == m_ThinkMap[m_ThinkState]) { + ResumeState(); + } else { + EndState(m_ThinkLevel); + BeginState(); + } + } + } + } else if (newThinkLevel == m_ThinkLevel && m_ThinkState == m_ThinkStates[m_ThinkLevel]) { + RestartState(); + } else { + m_ThinkLevel = newThinkLevel; + m_ThinkState = m_ThinkStates[m_ThinkLevel]; + m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState]; + } +} + +/* +=============== +Actor::FixAIParameters + +Fix path related parameters. +=============== +*/ +void Actor::FixAIParameters(void) +{ + float fMinLeash; + + if (m_pTetherEnt) { + fMinLeash = 64; + if (m_pTetherEnt->IsSubclassOfEntity()) { + Entity *pEnt = static_cast(m_pTetherEnt.Pointer()); + fMinLeash = pEnt->maxs[0] - pEnt->mins[1] + pEnt->maxs[1] - pEnt->mins[1]; + } + + if (m_fLeash < fMinLeash) { + Com_Printf( + "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing leash from %g to %g.\n" + "^~^~^ Leash must be larger than the size of the entity to which an AI is tethered.\n" + "\n", + entnum, + radnum, + TargetName().c_str(), + m_fLeash, + fMinLeash + ); + + m_fLeash = fMinLeash; + m_fLeashSquared = Square(fMinLeash); + } + } + + if (m_fLeash < m_fMinDistance) { + Com_Printf( + "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to match " + "leash.\n" + "^~^~^ Leash must be greater than mindist, or the AI will want to both run away and stay put.\n" + "\n", + entnum, + radnum, + TargetName().c_str(), + m_fMinDistance, + m_fLeash + ); + + m_fMinDistance = m_fLeash; + m_fMinDistanceSquared = Square(m_fMinDistance); + } + + if (m_fMaxDistance < m_fMinDistance + 128.0 - 1.0) { + Com_Printf( + "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing maxdist from %g to %g to exceed " + "mindist.\n" + "^~^~^ Maxdist should be %i greater than mindist, or the AI will want to both run away and charge, or just " + "do oscillitaroy behavior.\n" + "\n", + entnum, + radnum, + TargetName().c_str(), + m_fMaxDistance, + m_fMinDistance + 128.0, + 128 + ); + + m_fMaxDistance = m_fMinDistance + 128; + m_fMaxDistanceSquared = Square(m_fMaxDistance); + } + + if (world->farplane_distance > 0 && m_fMaxDistance > world->farplane_distance * 0.828f) { + Com_Printf( + "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing maxdist from %g to %g to be %g%% " + "of farplane.\n" + "^~^~^ Maxdist should be this distance within fog, or AI will be able to see and attack through fog.\n" + "\n", + entnum, + radnum, + TargetName().c_str(), + m_fMaxDistance, + world->farplane_distance * 0.828, + 2.0 + ); + + m_fMaxDistance = world->farplane_distance * 0.828f; + m_fMaxDistanceSquared = Square(m_fMaxDistance); + + if (m_fMaxDistance < m_fMinDistance + 128.0 - 1.0) { + Com_Printf( + "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to be less " + "than maxdist after fog adjustment.\n" + "\n", + entnum, + radnum, + TargetName().c_str(), + m_fMinDistance, + ((m_fMaxDistance > 128) ? (m_fMaxDistance - 128) : 0) + ); + + m_fMinDistance = m_fMaxDistance - 128; + if (m_fMinDistance < 0) { + m_fMinDistance = 0; + } + + m_fMinDistanceSquared = Square(m_fMinDistance); + } + } +} + +/* +=============== +Actor::AttackEntryAnimation + +Returns true if actor stands/draws his weapon. +=============== +*/ +bool Actor::AttackEntryAnimation(void) +{ + float fDistSquared; + vec2_t vDelta; + + if (!m_Enemy) { + return false; + } + + if (level.inttime >= level.m_iAttackEntryAnimTime + 3000) { + VectorSub2D(m_Enemy->origin, origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (!m_bNoSurprise && fDistSquared < Square(256)) { + if (fDistSquared / 384.f < rand()) { + StartAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STANDSHOCK_SCR); + m_bNoSurprise = true; + m_bNewEnemy = true; + return true; + } + } else if (fDistSquared > Square(1024) && (rand() % 4) == 0) { + Sentient *pSquadMate; + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + if (Square(m_fInterval) * 4 > (pSquadMate->origin - origin).lengthSquared()) { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + + StartAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STANDIDENTIFY_SCR); + m_bNoSurprise = true; + m_bNewEnemy = false; + + return true; + } + } + } + } + + if (m_bNewEnemy) { + Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, true); + } + + m_bNoSurprise = true; + m_bNewEnemy = false; + return false; +} + +/* +=============== +Actor::CheckForThinkStateTransition + +Check for all thinkstates transitions. +=============== +*/ +void Actor::CheckForThinkStateTransition(void) +{ + if (CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE) + || CheckForTransition(THINKSTATE_BADPLACE, THINKLEVEL_IDLE)) { + return; + } + + if (!m_bEnableEnemy) { + CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } + + if (CheckForTransition(THINKSTATE_ATTACK, THINKLEVEL_IDLE) + || CheckForTransition(THINKSTATE_DISGUISE, THINKLEVEL_IDLE)) { + return; + } + + if (CheckForTransition(THINKSTATE_CURIOUS, THINKLEVEL_IDLE)) { + m_pszDebugState = "from_sight"; + return; + } + + CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_IDLE); +} + +/* +=============== +Actor::CheckForTransition + +Check for thinkstate transition. +=============== +*/ +bool Actor::CheckForTransition(eThinkState state, eThinkLevel level) +{ + GlobalFuncs_t *func; + + if (m_ThinkStates[level] == state) { + return false; + } + + func = &GlobalFuncs[m_ThinkMap[state]]; + if (!func->PassesTransitionConditions) { + return false; + } + + if (!(this->*(func->PassesTransitionConditions))()) { + return false; + } + + SetThinkState(state, THINKLEVEL_IDLE); + return true; +} + +/* +=============== +Actor::PassesTransitionConditions_Grenade + +Should actor transition think state to grenade ? +=============== +*/ +bool Actor::PassesTransitionConditions_Grenade(void) +{ + if (!m_bIsCurious) { + // Added in 2.30 + return false; + } + + if (m_bLockThinkState || !m_bEnableEnemy) { + return false; + } + + if (!m_pGrenade) { + return false; + } + + return m_fGrenadeAwareness >= random(); +} + +/* +=============== +Actor::PassesTransitionConditions_BadPlace + +Should actor transition think state to bad place? +=============== +*/ +bool Actor::PassesTransitionConditions_BadPlace(void) +{ + if (m_bLockThinkState) { + return false; + } + + return m_iBadPlaceIndex != 0; +} + +/* +=============== +Actor::PassesTransitionConditions_Attack + +Should actor transition think state to attack ? +=============== +*/ +bool Actor::PassesTransitionConditions_Attack(void) +{ + UpdateEnemy(0); + + if (m_bLockThinkState) { + return false; + } + + if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) { + return false; + } + + if (EnemyIsDisguised() || !m_PotentialEnemies.IsEnemyConfirmed()) { + return false; + } + + return true; +} + +/* +=============== +Actor::PassesTransitionConditions_Disguise + +Should actor transition think state to disguise ? +=============== +*/ +bool Actor::PassesTransitionConditions_Disguise(void) +{ + vec2_t vDelta; + float fDistSquared; + + if (m_bLockThinkState) { + return false; + } + + if (m_iNextDisguiseTime > level.inttime) { + return false; + } + + m_iNextDisguiseTime = level.inttime + 200; + + UpdateEnemy(200); + + if (!m_Enemy) { + return false; + } + + if (!EnemyIsDisguised()) { + return false; + } + + if (!m_PotentialEnemies.IsEnemyConfirmed()) { + return false; + } + + if (fabs(m_Enemy->origin[2] - origin[2]) > 48) { + return false; + } + + VectorSub2D(m_Enemy->origin, origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + if (fDistSquared <= Square(32) || fDistSquared >= m_fMaxDisguiseDistSquared) { + return false; + } + + Entity *player = G_GetEntity(0); + + return G_SightTrace( + EyePosition(), + vec_zero, + vec_zero, + player->centroid, + this, + player, + MASK_TRANSITION, + false, + "Actor::PassesTransitionConditions_Disguise" + ); +} + +/* +=============== +Actor::PassesTransitionConditions_Curious + +Should actor transition think state to curious ? +=============== +*/ +bool Actor::PassesTransitionConditions_Curious(void) +{ + UpdateEnemy(200); + + if (m_bLockThinkState) { + return false; + } + + if (!m_Enemy && m_iCuriousTime) { + SetCuriousAnimHint(6); + return true; + } + + if (m_Enemy && !EnemyIsDisguised() && !m_PotentialEnemies.IsEnemyConfirmed()) { + SetCuriousAnimHint(6); + return true; + } + + return false; +} + +/* +=============== +Actor::PassesTransitionConditions_Idle + +Should actor transition think state to idle ? +=============== +*/ +bool Actor::PassesTransitionConditions_Idle(void) +{ + if (m_bEnableEnemy) { + UpdateEnemy(500); + } + + if (m_bLockThinkState) { + return false; + } + + if (!m_Enemy && !m_iCuriousTime) { + return true; + } + + return false; +} + +/* +=============== +Actor::EventGetRunAnim +=============== +*/ +void Actor::EventGetRunAnim(Event *ev) +{ + ev->AddConstString(GetRunAnim()); +} + +/* +=============== +Actor::EventGetWalkAnim +=============== +*/ +void Actor::EventGetWalkAnim(Event *ev) +{ + ev->AddConstString(GetWalkAnim()); +} + +/* +=============== +Actor::PathDistanceAlongVector + +Returns projected distance from vDir along path. +=============== +*/ +float Actor::PathDistanceAlongVector(vec3_t vDir) +{ + const float *delta = m_Path.CurrentDelta(); + + return DotProduct2D(delta, vDir); +} + +/* +=============== +Actor::FaceEnemyOrMotion + + +=============== +*/ +void Actor::FaceEnemyOrMotion(int iTimeIntoMove) +{ + vec2_t vDelta; + + VectorSub2D(origin, m_vLastEnemyPos, vDelta); + + if (iTimeIntoMove <= 999) { + m_bFaceEnemy = true; + } else if (m_Path.CurrentNodeIndex() != m_sCurrentPathNodeIndex) { + float fDist; + + fDist = PathDistanceAlongVector(vDelta); + + if (fDist > 0 || VectorLength2DSquared(vDelta) * 4096 < Square(fDist)) { + m_bFaceEnemy = false; + } else { + m_bFaceEnemy = true; + } + + m_sCurrentPathNodeIndex = m_Path.CurrentNodeIndex(); + } + + if (!m_bFaceEnemy) { + FaceMotion(); + return; + } + + if (vDelta[0] < 15 && vDelta[0] > -15 && vDelta[1] < 15 && vDelta[1] > -15) { + FaceMotion(); + return; + } + + vDelta[0] = -vDelta[0]; + vDelta[1] = -vDelta[1]; + FaceDirectionDuringMotion(vDelta); +} + +/* +=============== +Actor::FaceDirectionDuringMotion + +Face direction during motion. +=============== +*/ +void Actor::FaceDirectionDuringMotion(vec3_t vLook) +{ + float yaw; + + SetDesiredLookDir(vLook); + + if (!velocity[0] && !velocity[1]) { + SetDesiredYawDir(vLook); + return; + } + + float fDot = DotProduct2D(velocity, vLook); + float fDotSquared = Square(fDot); + float fMagsSquared = VectorLength2DSquared(vLook) * VectorLength2DSquared(velocity); + + yaw = velocity.toYaw(); + + if (fDotSquared < fMagsSquared / 2.f) { + if (velocity.y * vLook[0] > velocity.x * vLook[1]) { + yaw -= 90; + } else { + yaw -= 270; + } + + if (yaw < 0) { + yaw += 360; + } + } else if (fDot < 0) { + yaw -= 180; + + if (yaw < 0) { + yaw += 360; + } + } + + SetDesiredYaw(yaw); +} + +/* +=============== +Actor::EventGetAnimName +=============== +*/ +void Actor::EventGetAnimName(Event *ev) +{ + ev->AddConstString(m_csAnimName); +} + +/* +=============== +Actor::EventSetAnimName +=============== +*/ +void Actor::EventSetAnimName(Event *ev) +{ + m_csAnimName = ev->GetConstString(1); +} + +/* +=============== +Actor::EventSetDisguiseRange +=============== +*/ +void Actor::EventSetDisguiseRange(Event *ev) +{ + m_fMaxDisguiseDistSquared = ev->GetFloat(1); + m_fMaxDisguiseDistSquared = Square(m_fMaxDisguiseDistSquared); +} + +/* +=============== +Actor::EventGetDisguiseRange +=============== +*/ +void Actor::EventGetDisguiseRange(Event *ev) +{ + ev->AddFloat(sqrt(m_fMaxDisguiseDistSquared)); +} + +/* +=============== +Actor::EventSetDisguisePeriod +=============== +*/ +void Actor::EventSetDisguisePeriod(Event *ev) +{ + m_iDisguisePeriod = ev->GetFloat(1) * 1000 + 0.5; +} + +/* +=============== +Actor::EventGetDisguisePeriod +=============== +*/ +void Actor::EventGetDisguisePeriod(Event *ev) +{ + ev->AddFloat(m_iDisguisePeriod / 1000.0); +} + +/* +=============== +Actor::FaceMotion + +=============== +*/ +void Actor::FaceMotion(void) +{ + vec2_t vDelta; + + if (VectorLength2DSquared(velocity) > 1) { + vec3_t dir; + + VectorCopy2D(velocity, dir); + VectorSub2D(origin, m_vOriginHistory[m_iCurrentHistory], vDelta); + + if (VectorLength2DSquared(vDelta) >= 1 && DotProduct2D(vDelta, dir) > 0) { + VectorCopy2D(vDelta, dir); + } + + dir[2] = 0; + + if (m_ThinkState == THINKSTATE_IDLE) { + IdleLook(dir); + } else { + SetDesiredLookDir(dir); + } + + SetDesiredYawDir(dir); + } else if (m_ThinkState == THINKSTATE_IDLE) { + IdleLook(); + } else { + ForwardLook(); + } +} + +/* +=============== +Actor::ForceAttackPlayer +=============== +*/ +void Actor::ForceAttackPlayer(void) +{ + m_PotentialEnemies.ConfirmEnemy(this, static_cast(G_GetEntity(0))); + m_bForceAttackPlayer = true; +} + +/* +=============== +Actor::EventAttackPlayer +=============== +*/ +void Actor::EventAttackPlayer(Event *ev) +{ + if (!G_GetEntity(0)) { + ScriptError("player doesn't exist"); + } + + ForceAttackPlayer(); +} + +/* +=============== +Actor::EventShareEnemy + +Share enemy with squad mates. +=============== +*/ +void Actor::EventShareEnemy(Event *ev) +{ + Sentient *pSquadMate; + + if (!m_Enemy) { + return; + } + + if (EnemyIsDisguised()) { + return; + } + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + if (!pSquadMate->IsSubclassOfActor()) { + continue; + } + + Actor *pActorSquadMate = static_cast(pSquadMate); + + if (!m_fMaxShareDistSquared || m_fMaxShareDistSquared < (pActorSquadMate->origin - origin).lengthSquared()) { + pActorSquadMate->m_PotentialEnemies.ConfirmEnemyIfCanSeeSharerOrEnemy(pActorSquadMate, this, m_Enemy); + } + } +} + +/* +=============== +Actor::EventShareGrenade + +Share grenade with squad mates. +=============== +*/ +void Actor::EventShareGrenade(Event *ev) +{ + Sentient *pSquadMate; + + if (!m_pGrenade) { + return; + } + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + if (!pSquadMate->IsSubclassOfActor()) { + continue; + } + + Actor *pActorSquadMate = static_cast(pSquadMate); + + if (pActorSquadMate->m_pGrenade) { + continue; + } + + if ((pSquadMate->origin - origin).lengthSquared() < Square(768) + && DoesTheoreticPathExist(pSquadMate->origin, 1536)) { + pActorSquadMate->SetGrenade(m_pGrenade); + } + } +} + +/* +=============== +Actor::ReceiveAIEvent + +Calls proper RecieveAIEvent for current ThinkState. +=============== +*/ +void Actor::ReceiveAIEvent( + vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared +) +{ + if (originator) { + if (originator == this || originator == GetActiveWeapon(WEAPON_MAIN)) { + return; + } + } + + GlobalFuncs_t *func = &GlobalFuncs[CurrentThink()]; + + if (func->ReceiveAIEvent) { + (this->*func->ReceiveAIEvent)(event_origin, iType, originator, fDistSquared, fMaxDistSquared); + } +} + +/* +=============== +Actor::DefaultReceiveAIEvent + +Default AI event handler. +=============== +*/ +void Actor::DefaultReceiveAIEvent( + vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared +) +{ + if (IsDead()) { + return; + } + + if (originator && !originator->IsDead() && originator->IsSubclassOfSentient() + && ((Sentient *)originator)->m_Team == m_Team && !IsSquadMate((Sentient *)originator)) { + MergeWithSquad((Sentient *)originator); + } + + switch (iType) { + case AI_EVENT_WEAPON_FIRE: + case AI_EVENT_WEAPON_IMPACT: + if (fDistSquared < Square(m_fHearing)) { + WeaponSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator); + } + break; + case AI_EVENT_EXPLOSION: + case AI_EVENT_MISC: + case AI_EVENT_MISC_LOUD: + if (fDistSquared < Square(m_fHearing)) { + CuriousSound(iType, event_origin, fDistSquared, fMaxDistSquared); + } + break; + case AI_EVENT_AMERICAN_VOICE: + case AI_EVENT_GERMAN_VOICE: + case AI_EVENT_AMERICAN_URGENT: + case AI_EVENT_GERMAN_URGENT: + if (fDistSquared < Square(m_fHearing)) { + VoiceSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator); + } + break; + case AI_EVENT_FOOTSTEP: + if (fDistSquared < Square(m_fHearing)) { + FootstepSound(event_origin, fDistSquared, fMaxDistSquared, originator); + } + break; + case AI_EVENT_GRENADE: + GrenadeNotification(originator); + break; + case AI_EVENT_BADPLACE: + UpdateBadPlaces(); + break; + default: + { + char assertStr[16317] = {0}; + strcpy(assertStr, "\"unknown ai_event type\"\n\tMessage: "); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("iType = %i", iType)); + assert(false && assertStr); + } + break; + } +} + +/* +=============== +Actor::PriorityForEventType + +Returns priority for event type. +=============== +*/ +int Actor::PriorityForEventType(int iType) +{ + switch (iType) { + //FIXME: return macros + case AI_EVENT_WEAPON_FIRE: + return 7; + case AI_EVENT_WEAPON_IMPACT: + return 5; + case AI_EVENT_EXPLOSION: + return 6; + case AI_EVENT_AMERICAN_VOICE: + case AI_EVENT_GERMAN_VOICE: + return 3; + case AI_EVENT_AMERICAN_URGENT: + case AI_EVENT_GERMAN_URGENT: + return 4; + case AI_EVENT_MISC: + return 1; + case AI_EVENT_MISC_LOUD: + case AI_EVENT_FOOTSTEP: + return 2; + case AI_EVENT_GRENADE: + return 8; + default: + assert(!"PriorityForEventType: unknown ai_event type"); + return 0; + } +} + +const char *DebugStringForEvent(int iType) +{ + switch (iType) { + case AI_EVENT_WEAPON_FIRE: + return "weapon_fire"; + case AI_EVENT_WEAPON_IMPACT: + return "weapon_impact"; + case AI_EVENT_EXPLOSION: + return "explosion"; + case AI_EVENT_AMERICAN_VOICE: + return "american_voice"; + case AI_EVENT_GERMAN_VOICE: + return "german_voice"; + case AI_EVENT_AMERICAN_URGENT: + return "american_urgent"; + case AI_EVENT_GERMAN_URGENT: + return "german_urgent"; + case AI_EVENT_MISC: + return "misc"; + case AI_EVENT_MISC_LOUD: + return "misc_loud"; + case AI_EVENT_FOOTSTEP: + return "footstep"; + case AI_EVENT_GRENADE: + return "grenade"; + default: + return "????"; + } +} + +/* +=============== +Actor::CuriousSound + +Handles curious sound. +=============== +*/ +void Actor::CuriousSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared) +{ + float fRangeFactor; + int iPriority; + + if (!m_bEnableEnemy) { + return; + } + + if (m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_IDLE && m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_CURIOUS) { + return; + } + + if (!m_bIsCurious) { + // Added in 2.30 + return; + } + + fRangeFactor = 1.0; + if (fMaxDistSquared) { + fRangeFactor = (4.0 / 3.0 - ((4.0 / 3.0 * fDistSquared) / fMaxDistSquared)); + if (fRangeFactor > 1) { + fRangeFactor = 1; + } + } + + if ((fRangeFactor * m_fSoundAwareness) < random()) { + return; + } + + RaiseAlertnessForEventType(iType); + // get the priority + iPriority = PriorityForEventType(iType); + + if (iPriority < m_iCuriousLevel) { + return; + } + + m_iCuriousLevel = iPriority; + switch (iType) { + case AI_EVENT_WEAPON_IMPACT: + if (fDistSquared <= Square(192)) { + SetCuriousAnimHint(1); + } + break; + case AI_EVENT_EXPLOSION: + if (fDistSquared <= Square(768)) { + SetCuriousAnimHint(3); + } + break; + case AI_EVENT_WEAPON_FIRE: + if (fDistSquared <= Square(512)) { + SetCuriousAnimHint(2); + } + break; + default: + SetCuriousAnimHint(5); + break; + } + + SetEnemyPos(sound_origin); + + EndCurrentThinkState(); + SetThinkState(THINKSTATE_CURIOUS, THINKLEVEL_IDLE); + + m_pszDebugState = DebugStringForEvent(iType); +} + +/* +=============== +Actor::WeaponSound + +Handles weapon sound. +=============== +*/ +void Actor::WeaponSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator) +{ + Sentient *pOwner; + + if (originator->IsSubclassOfWeapon()) { + pOwner = static_cast(originator)->GetOwner(); + } else if (originator->IsSubclassOfProjectile()) { + pOwner = static_cast(originator)->GetOwner(); + } else if (originator->IsSubclassOfSentient()) { + pOwner = static_cast(originator); + } else { + char assertStr[16317] = {0}; + strcpy(assertStr, "\"Actor::WeaponSound: non-weapon made a weapon sound.\\n\"\n\tMessage: "); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("class = %s", originator->getClassname())); + assert(false && assertStr); + + return; + } + + if (!pOwner) { + return; + } + + Sentient *pEnemy; + + pEnemy = pOwner; + + if (pOwner->m_Team == m_Team) { + pEnemy = pOwner->m_Enemy; + } + + if (pOwner->m_Team == m_Team && !pEnemy && pOwner->IsSubclassOfActor() && originator->IsSubclassOfWeapon()) { + Actor *pActor = static_cast(pOwner); + Weapon *pWeapon = static_cast(originator); + + if (pActor->m_Think[THINKLEVEL_IDLE] == THINK_MACHINEGUNNER && pWeapon->aim_target) { + if (pWeapon->aim_target->IsSubclassOfSentient()) { + Sentient *pTarget = static_cast(pWeapon->aim_target.Pointer()); + if (pTarget->m_Team == m_Team) { + pEnemy = pTarget; + } + } else if (!m_Team) { + for (pEnemy = level.m_HeadSentient[TEAM_AMERICAN]; pEnemy; pEnemy = pEnemy->m_NextSentient) { + if ((pEnemy->origin - pWeapon->aim_target->centroid).lengthSquared() < Square(48)) { + break; + } + } + } + } + } + + if (pEnemy && m_PotentialEnemies.CaresAboutPerfectInfo(pEnemy) && NoticeShot(pOwner, pEnemy, sqrt(fDistSquared))) { + if (pOwner->m_Team != m_Team) { + m_PotentialEnemies.ConfirmEnemy(this, pOwner); + } + + CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared); + } +} + +/* +=============== +Actor::FootstepSound + +Handles footstep sound. +=============== +*/ +void Actor::FootstepSound(vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator) +{ + if (!originator->IsSubclassOfSentient()) { + char assertStr[16317] = {0}; + strcpy(assertStr, "\"'ai_event footstep' in a tiki used by something besides AI or player.\\n\"\n\tMessage: "); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); + assert(false && assertStr); + return; + } + + if (m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_IDLE && m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_CURIOUS) { + return; + } + + if (!m_bEnableEnemy) { + return; + } + + if (!NoticeFootstep(static_cast(originator))) { + return; + } + + CuriousSound(AI_EVENT_FOOTSTEP, sound_origin, fDistSquared, fMaxDistSquared); +} + +/* +=============== +Actor::VoiceSound + +Handles voice sound. +=============== +*/ +void Actor::VoiceSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator) +{ + bool bFriendly; + + if (m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_IDLE && m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_CURIOUS) { + return; + } + + if (!m_bEnableEnemy) { + return; + } + + switch (iType) { + case AI_EVENT_AMERICAN_VOICE: + case AI_EVENT_AMERICAN_URGENT: + bFriendly = m_Team == TEAM_AMERICAN; + break; + case AI_EVENT_GERMAN_VOICE: + case AI_EVENT_GERMAN_URGENT: + bFriendly = m_Team == TEAM_GERMAN; + break; + default: + break; + } + + if (!bFriendly) { + CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared); + } else if (NoticeVoice(static_cast(originator))) { + CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared); + } +} + +/* +=============== +Actor::GrenadeNotification + +Handles grenade notification. +=============== +*/ +void Actor::GrenadeNotification(Entity *originator) +{ + if (!m_pGrenade && CanSeeFOV(originator) && originator->IsSubclassOfProjectile()) { + Projectile *proj = static_cast(originator); + Entity *projOwner = NULL; + Sentient *sentientOwner = NULL; + + SetGrenade(originator); + PostEvent(EV_Actor_ShareGrenade, 0.5f); + + if (proj->owner != ENTITYNUM_NONE) { + projOwner = G_GetEntity(proj->owner); + } + + if (projOwner && projOwner->IsSubclassOfSentient()) { + sentientOwner = static_cast(projOwner); + } + + if (!sentientOwner || sentientOwner->m_Team != m_Team) { + Anim_Say(STRING_ANIM_SAY_GRENADE_SIGHTED_SCR, 0, true); + } + } + + if (m_pGrenade == originator) { + float fTimeLand; + float fVelDivGrav; + vec2_t vLand; + vec2_t vMove; + + fVelDivGrav = originator->velocity[2] / (sv_gravity->value * m_pGrenade->gravity); + fTimeLand = fVelDivGrav + + sqrt( + Square(fVelDivGrav) + + Square(originator->origin[2] - origin[2]) / (sv_gravity->value * m_pGrenade->gravity) + ); + + VectorMA2D(originator->origin, fTimeLand, originator->velocity, vLand); + VectorSub2D(m_vGrenadePos, vLand, vMove); + + if (VectorLength2DSquared(vMove) > Square(4)) { + VectorCopy2D(vLand, m_vGrenadePos); + m_vGrenadePos[2] = origin[2]; + m_bGrenadeBounced = true; + } + } +} + +/* +=============== +Actor::SetGrenade + +Set current grenade. +=============== +*/ +void Actor::SetGrenade(Entity *pGrenade) +{ + m_pGrenade = pGrenade; + m_bGrenadeBounced = true; + m_iFirstGrenadeTime = level.inttime; + m_vGrenadePos = pGrenade->origin; +} + +/* +=============== +Actor::UpdateBadPlaces + +Update bad places, with a new path +=============== +*/ +void Actor::UpdateBadPlaces(void) +{ + m_iBadPlaceIndex = 0; + if (m_bIgnoreBadPlace) { + return; + } + + if (PathExists()) { + m_Path.ReFindPath(origin, this); + } + + m_iBadPlaceIndex = level.GetNearestBadPlace(origin, 64, 1 << m_Team); +} + +/* +=============== +Actor::NotifySquadmateKilled + +Handle squadmate killed notification. +=============== +*/ +void Actor::NotifySquadmateKilled(Sentient *pSquadMate, Sentient *pAttacker) +{ + Vector vDelta; + float fSquareDist; + bool bCanSee; + + if (!m_PotentialEnemies.CaresAboutPerfectInfo(pAttacker)) { + return; + } + + vDelta = pSquadMate->origin - origin; + fSquareDist = vDelta.lengthSquared(); + if (fSquareDist > Square(m_fSight)) { + return; + } + + bCanSee = false; + if (AreasConnected(pSquadMate)) { + bCanSee = G_SightTrace( + VirtualEyePosition(), + vec_zero, + vec_zero, + pSquadMate->EyePosition(), + this, + pSquadMate, + MASK_AI_CANSEE, + false, + "Actor::NotifySquadmateKilled" + ); + } + + if (!bCanSee) { + if (fSquareDist > Square(768)) { + return; + } + + if (origin.z > pSquadMate->origin.z) { + if (!m_Path.DoesTheoreticPathExist(origin, pSquadMate->origin, this, 1536, NULL, 0)) { + return; + } + } else { + if (!m_Path.DoesTheoreticPathExist(pSquadMate->origin, origin, this, 1536, NULL, 0)) { + return; + } + } + } + + m_PotentialEnemies.ConfirmEnemy(this, pAttacker); +} + +/* +=============== +Actor::RaiseAlertnessForEventType + +Raise alertness(enemy notice) for specifc event. +=============== +*/ +void Actor::RaiseAlertnessForEventType(int iType) +{ + switch (iType) { + case AI_EVENT_WEAPON_FIRE: + RaiseAlertness(0.2f); + break; + case AI_EVENT_WEAPON_IMPACT: + RaiseAlertness(0.1f); + break; + case AI_EVENT_EXPLOSION: + RaiseAlertness(0.4f); + break; + case AI_EVENT_AMERICAN_VOICE: + case AI_EVENT_AMERICAN_URGENT: + if (m_Team == TEAM_GERMAN) { + RaiseAlertness(0.25f); + } + break; + case AI_EVENT_GERMAN_VOICE: + case AI_EVENT_GERMAN_URGENT: + if (m_Team == TEAM_AMERICAN) { + RaiseAlertness(0.25); + } + break; + case AI_EVENT_MISC: + RaiseAlertness(0.02f); + break; + case AI_EVENT_MISC_LOUD: + case AI_EVENT_FOOTSTEP: + RaiseAlertness(0.05f); + break; + case AI_EVENT_GRENADE: + RaiseAlertness(0.04f); + break; + default: + char assertStr[16317] = {0}; + strcpy(assertStr, "\"Actor::RaiseAlertnessForEventType: unknown event type\\n\"\n\tMessage: "); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); + assert(false && assertStr); + return; + break; + } +} + +/* +=============== +Actor::RaiseAlertness + +Lower enemy notice time by fAmount. +=============== +*/ +void Actor::RaiseAlertness(float fAmount) +{ + if (fAmount > m_fNoticeTimeScale * (2.0 / 3.0)) { + fAmount = m_fNoticeTimeScale * (2.0 / 3.0); + } + + m_fNoticeTimeScale -= fAmount; } /* @@ -7645,31 +9556,22 @@ Returns true if shooter is an enemy. Otherwise the shooter is a team mate and target is registered an enemy if he's visible/reachable. =============== */ -bool Actor::NoticeShot - ( - Sentient *pShooter, - Sentient *pTarget, - float fDist - ) +bool Actor::NoticeShot(Sentient *pShooter, Sentient *pTarget, float fDist) { - gi.Printf("Notice shot"); - if (pShooter->m_Team != m_Team) - { - return true; - } + if (pShooter->m_Team != m_Team) { + return true; + } - m_bEnemyIsDisguised = false; + m_bEnemyIsDisguised = false; - if (pTarget) - { - if (DoesTheoreticPathExist(pShooter->origin, fDist * 1.5) || CanSee(pTarget, 0, 0.828 * world->farplane_distance, false)) - { - m_PotentialEnemies.ConfirmEnemy(this, pTarget); - } - } - - return false; + if (pTarget) { + if (DoesTheoreticPathExist(pShooter->origin, fDist * 1.5f) + || CanSee(pTarget, 0, world->farplane_distance * 0.828, false)) { + m_PotentialEnemies.ConfirmEnemy(this, pTarget); + } + } + return false; } /* @@ -7680,15 +9582,13 @@ Returns true if actor should notice this footstep sound (pedestrian is not visib Otherwise returns false. =============== */ -bool Actor::NoticeFootstep - ( - Sentient *pPedestrian - ) +bool Actor::NoticeFootstep(Sentient *pPedestrian) { - if (m_Team == pPedestrian->m_Team || pPedestrian->m_bIsDisguised) - return false; + if (m_Team == pPedestrian->m_Team || pPedestrian->m_bIsDisguised) { + return false; + } - return !CanSeeFOV(pPedestrian); + return !CanSeeFOV(pPedestrian); } /* @@ -7699,603 +9599,2549 @@ Returns true if actor should notice this voice sound (vocalist is not visible fo Otherwise returns false. =============== */ -bool Actor::NoticeVoice - ( - Sentient *pVocallist - ) +bool Actor::NoticeVoice(Sentient *pVocallist) { - if (IsSquadMate(pVocallist)) - return false; - - return !CanSeeFOV(pVocallist); + return !IsSquadMate(pVocallist) && !CanSeeFOV(pVocallist); } /* =============== -Actor::ClearLookEntity +Actor::ValidGrenadePath -Clear look entity. +Returns true if grenade trajectory is valid. +i.e grenade can get from vFrom to vTo with vVel with any obstacles. =============== */ -void Actor::ClearLookEntity - ( - void - ) +bool Actor::ValidGrenadePath(const Vector& vFrom, const Vector& vTo, Vector& vVel) { - if (m_pLookEntity) - { - if (m_pLookEntity->IsSubclassOfTempWaypoint()) - { - delete m_pLookEntity; - } - m_pLookEntity = NULL; - } + vec3_t mins, maxs; + Vector vPoint1, vPoint2, vPoint3; + float fTime, fTimeLand; + trace_t trace; + float fGravity; + + VectorSet(mins, -4, -4, -4); + VectorSet(maxs, 4, 4, 4); + + if (vVel.lengthSquared() > Square(768)) { + return false; + } + + fGravity = sv_gravity->value * 0.8f; + + fTime = vVel.z / fGravity * 0.5f; + + vPoint1.x = vVel.x * fTime + vFrom.x; + vPoint1.y = vVel.y * fTime + vFrom.y; + vPoint1.z = vVel.z * fTime * 0.75 + vFrom.z; + maxs[2] = fGravity / 8.0f * fTime * fTime + 4.0f; + + if (ai_debug_grenades->integer) { + G_DebugLine(vFrom, vPoint1, 1.0, 0.5, 0.5, 1.0); + } + + if (!G_SightTrace(vFrom, mins, maxs, vPoint1, this, NULL, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 1")) { + return false; + } + + fTime *= 2; + vPoint2.x = vVel.x * fTime + vFrom.x; + vPoint2.y = vVel.y * fTime + vFrom.y; + vPoint2.z = vVel.z * fTime * 0.5 + vFrom.z; + + if (ai_debug_grenades->integer) { + G_DebugLine(vPoint1, vPoint2, 1.0, 0.5, 0.5, 1.0); + } + + if (!G_SightTrace(vPoint1, mins, maxs, vPoint2, this, NULL, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 2")) { + return false; + } + + if (fabs(vVel.x) > fabs(vVel.y)) { + fTimeLand = (vTo.x - vFrom.x) / vVel.x; + } else { + fTimeLand = (vTo.y - vFrom.y) / vVel.y; + } + + maxs[2] = fGravity / 32.f * (fTimeLand - fTime) * (fTimeLand - fTime) + 4; + fTime = (fTime + fTimeLand) * 0.5f; + + vPoint3.x = vVel.x * fTime + vFrom.x; + vPoint3.y = vVel.y * fTime + vFrom.y; + vPoint3.z = vFrom.z + (vVel.z - fGravity * 0.5 * fTime) * fTime; + + if (ai_debug_grenades->integer) { + G_DebugLine(vPoint2, vPoint3, 1.0, 0.5, 0.5, 1.0); + } + if (!G_SightTrace(vPoint2, mins, maxs, vPoint3, this, NULL, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 3")) { + return false; + } + if (ai_debug_grenades->integer) { + G_DebugLine(vPoint3, vTo, 1.0, 0.5, 0.5, 1.0); + } + + trace = G_Trace(vPoint3, mins, maxs, vTo, this, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 4"); + if (!trace.allsolid) { + if (!trace.ent) { + return true; + } + + if (trace.ent->entity->IsSubclassOfSentient() && static_cast(trace.ent->entity)->m_Team != m_Team) { + return true; + } + } + + if (trace.entityNum != ENTITYNUM_WORLD || trace.plane.normal[2] < 0.999f) { + return false; + } + + return true; } /* =============== -Actor::LookAt +Actor::CalcThrowVelocity -Change current look entity. +Calculates required grenade throw velocity to get grenade from vFrom to vTo. =============== */ -void Actor::LookAt - ( - const Vector& vec - ) +Vector Actor::CalcThrowVelocity(const Vector& vFrom, const Vector& vTo) { - if (g_showlookat->integer == entnum || g_showlookat->integer == -1) - { - Com_Printf( - "Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n", - entnum, - radnum, - targetname.c_str(), - vec.x, - vec.y, - vec.z); - } + Vector vDelta; + float fHorzDistSquared, fDistance; + float fVelHorz, fVelVert; - ClearLookEntity(); + vDelta = vTo - vFrom; + fHorzDistSquared = vDelta.lengthXYSquared(); + fDistance = sqrt(fHorzDistSquared + Square(vDelta.z)); - TempWaypoint *twp = new TempWaypoint(); - m_pLookEntity = twp; + // original irl equation: v10 = sqrt(fGravity * 0.5 * fHorzDistSquared / (fDistance * trigMult )) + // trigMult = (cos(th)/ tan(al) - sin(th)/tanSquared(al)) + // al = inital velocity angle with ground plane. + // th = angle between vDelta and ground plane. + // mohaa devs decided to let trigMult be 1, for the sake of simplicity I guess. + fVelVert = sqrt(sv_gravity->value * 0.8f * 0.5f * fHorzDistSquared / fDistance); - m_pLookEntity->setOrigin(vec); + // no I dea what this means. + // maybe it's related to their angle choice. + // calculates the 1/distanceSquared necessary for fOOTime calculation. + fVelHorz = sqrt((fDistance + vDelta.z) / (fDistance - vDelta.z) / fHorzDistSquared) * fVelVert; + // 1/(speed * sqrt(1/distanceSquared)) + // 1/(speed * 1/distance) + // 1/(1/time) + // time + return Vector(vDelta.x * fVelHorz, vDelta.y * fVelHorz, fVelVert); } /* =============== -Actor::LookAt +Actor::CanThrowGrenade -Change current look entity. +Returns required velocity to throw grenade from vFrom to vTo. +Or vec_zero if it's not possible. =============== */ -void Actor::LookAt - ( - Listener *l - ) +Vector Actor::CanThrowGrenade(const Vector& vFrom, const Vector& vTo) { - ClearLookEntity(); - if ( l ) - { - if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) - { - ScriptError("Bad look entity with classname '%s' specified for '%s' at (%f %f %f)\n", - l->getClassname(), - targetname.c_str(), - origin.x, - origin.y, - origin.z - ); - } - if (l != this) - { - l = (SimpleEntity*)l; - if (g_showlookat->integer == entnum || g_showlookat->integer == -1) - { - Com_Printf( - "Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n", - entnum, - radnum, - targetname.c_str(), - ((SimpleEntity*)l)->origin.x, - ((SimpleEntity*)l)->origin.y, - ((SimpleEntity*)l)->origin.z); - } - m_pLookEntity = (SimpleEntity*)l; - } - } + Vector vVel; + + vVel = CalcThrowVelocity(vFrom, vTo); + + if (vVel != vec_zero && ValidGrenadePath(vFrom, vTo, vVel)) { + return vVel; + } else { + return vec_zero; + } } /* =============== -Actor::ForwardLook - +Actor::CalcRollVelocity +Calculates required grenade roll velocity to get grenade from vFrom to vTo. +Roll here means a low toss. =============== */ -void Actor::ForwardLook - ( - void - ) +Vector Actor::CalcRollVelocity(const Vector& vFrom, const Vector& vTo) { - //fixme: this is an inline function. - m_bHasDesiredLookAngles = false; + Vector vDelta; + float fVelVert; + float fOOTime; + + // you must throw from above. + // start point must be above (higher) than end point. + if (vTo.z >= vFrom.z) { + return vec_zero; + } + + vDelta = vTo - vFrom; + // Required down velocity to hit the ground twice as fast as freefall time. + fVelVert = sqrt(-vDelta.z * sv_gravity->value * 0.8f); + + // accel = speed / time, hence : time = speed / accel, 0.21961521 is an arbitary scalar. + // since the scalar is way less than 1, it will take more time to hit the ground than to arrive to target dest. + // this is kinda like a low toss rather than a roll. if I understand correctly. + fOOTime = sv_gravity->value * 0.8f * 0.21961521f / fVelVert; + + // speed = distance / time + return Vector(vDelta.x * fOOTime, vDelta.y * fOOTime, fVelVert); } /* =============== -Actor::LookAtLookEntity +Actor::CanRollGrenade -Change current look entity. +Returns required velocity to roll grenade from vFrom to vTo. +Or vec_zero if it's not possible. +Roll here means a low toss. =============== */ -void Actor::LookAtLookEntity - ( - void - ) +Vector Actor::CanRollGrenade(const Vector& vFrom, const Vector& vTo) { - Vector dir; - if (m_pLookEntity->IsSubclassOfSentient()) - { - dir = ((Sentient *)m_pLookEntity.Pointer())->EyePosition() - EyePosition(); - } - else - { - dir = m_pLookEntity->centroid - EyePosition(); - } + Vector vVel; - SetDesiredLookDir(dir); + vVel = CalcRollVelocity(vFrom, vTo); + + if (vVel != vec_zero && ValidGrenadePath(vFrom, vTo, vVel)) { + return vVel; + } else { + return vec_zero; + } } /* =============== -Actor::IdleLook +Actor::CanTossGrenadeThroughHint -Idle look behaviour. +Returns true if actor can toss grenade through specified hint. +pvVel and peMode are modified. =============== */ -void Actor::IdleLook - ( - void - ) +bool Actor::CanTossGrenadeThroughHint( + GrenadeHint *pHint, const Vector& vFrom, const Vector& vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode +) { - if (m_pLookEntity) - { - LookAtLookEntity(); - } - else - { - m_bHasDesiredLookAngles = false; - } + Vector vDelta; + float fHeight; + float fDistSquared, fDist; + float fRangeSquared, fRange; + float fVelHorz, fVelVert; + float fTemp; + float fAngle; + bool bSuccess; + float fGravity; + + fGravity = sv_gravity->value * 0.8f; + + if (bDesperate) { + vDelta = pHint->origin - vFrom; + + fDistSquared = vDelta.lengthXYSquared(); + if (!fDistSquared) { + return false; + } + + fDist = sqrt(fDistSquared); + fRangeSquared = vDelta.z * vDelta.z + fDistSquared; + fRange = sqrt(fRangeSquared); + fHeight = fGravity * fDistSquared / Square(768) + vDelta.z; + + if (fabs(fHeight) > fabs(fRange)) { + return false; + } + + fAngle = (asin(fHeight / fRange) + atan(vDelta.z / fDist)) * 0.5f; + fVelVert = sin(fAngle) * 768.f; + fVelHorz = 768.f / fDist * cos(fAngle); + + pvVel->x = fVelHorz * vDelta.x; + pvVel->y = fVelHorz * vDelta.y; + pvVel->z = fVelVert; + + *peMode = AI_GREN_TOSS_HINT; + bSuccess = ValidGrenadePath(vFrom, pHint->origin, *pvVel); + } else { + vDelta = pHint->origin - vFrom; + fDistSquared = vDelta.lengthXYSquared(); + fDist = sqrt(fDistSquared); + + vDelta = vTo - vFrom; + fRangeSquared = vDelta.x * vDelta.x + vDelta.y * vDelta.y; + fRange = sqrt(fRangeSquared); + fHeight = vDelta.z * fRange - vDelta.z * fDist; + + if (!fHeight) { + return false; + } + + fHeight = 1.f / fHeight; + fVelHorz = (fRange - fDist) * fHeight; + if (fVelHorz <= 0) { + return false; + } + + fTemp = sqrt(fGravity * 0.5f * fDist * fRange * fVelHorz); + fVelVert = (fRangeSquared * vDelta.z - fDistSquared * vDelta.z) * fGravity * 0.5f / fTemp * fHeight; + fVelHorz = fTemp / fDist; + + pvVel->x = (pHint->origin.x - vFrom.x) * fVelHorz; + pvVel->y = (pHint->origin.y - vFrom.y) * fVelHorz; + pvVel->z = fVelVert; + + *peMode = AI_GREN_TOSS_HINT; + + bSuccess = ValidGrenadePath(vFrom, pHint->origin, *pvVel); + } + + return bSuccess; } /* =============== -Actor::IdleLook +Actor::GrenadeThrowPoint -Idle look behaviour. +Returns real grenade throw point. =============== */ -void Actor::IdleLook - ( - vec3_t dir - ) +Vector Actor::GrenadeThrowPoint(const Vector& vFrom, const Vector& vDelta, const_str csAnim) { - if (m_pLookEntity) - { - LookAtLookEntity(); - } - else - { - SetDesiredLookDir(dir); - } + vec2_t axis; + + VectorCopy2D(vDelta, axis); + VectorNormalize2D(axis); + + switch (csAnim) { + case STRING_ANIM_GRENADEKICK_SCR: + return Vector(vFrom.x, vFrom.y, vFrom.z + 8); + case STRING_ANIM_GRENADETHROW_SCR: + case STRING_ANIM_GRENADETOSS_SCR: + return Vector( + axis[0] * -34.0 + vFrom.x - axis[1] * -8.0, axis[1] * -34.0 + vFrom.y + axis[0] * -8.0, vFrom.z + 52 + ); + case STRING_ANIM_GRENADERETURN_SCR: + return Vector( + axis[0] * 25.0 + vFrom.x - axis[1] * -2.0, axis[1] * 25.0 + vFrom.y + axis[0] * -2.0, vFrom.z + 89 + ); + break; + default: + return vFrom + Vector(0, 0, 80); + } } /* =============== -Actor::SetDesiredLookDir +Actor::CalcKickVelocity -Change desired look direction. +Calculates required grenade kick velocity. =============== */ -void Actor::SetDesiredLookDir - ( - vec3_t dir - ) +Vector Actor::CalcKickVelocity(Vector& vDelta, float fDist) const { - m_bHasDesiredLookAngles = true; - vectoangles( dir, m_DesiredLookAngles ); - m_DesiredLookAngles[ 1 ] = m_DesiredLookAngles[ 1 ] - angles[ 1 ]; - m_DesiredLookAngles[ 1 ] = AngleNormalize180( m_DesiredLookAngles[ 1 ] ); - m_DesiredLookAngles[ 0 ] = AngleNormalize180( m_DesiredLookAngles[ 0 ] ); + float fScale = sqrt(sv_gravity->value * 0.8f * 0.5f / (fDist * 0.57735032 - vDelta.z)); + + return Vector(vDelta.x * fScale, vDelta.y * fScale, fDist * 0.57735032 * fScale); } /* =============== -Actor::SetDesiredLookAnglesRelative +Actor::CanKickGrenade -Change desired look angles relatively. +Returns true if actor can kick grenade from vFrom to vTo. +Or false if it's not possible. +pvVel is changed. =============== */ -void Actor::SetDesiredLookAnglesRelative - ( - vec3_t ang - ) +bool Actor::CanKickGrenade(Vector& vFrom, Vector& vTo, Vector& vFace, Vector *pvVel) { - m_bHasDesiredLookAngles = true; - m_DesiredLookAngles[ 0 ] = AngleNormalize180( ang[ 0 ] ); - m_DesiredLookAngles[ 1 ] = AngleNormalize180( ang[ 1 ] ); - m_DesiredLookAngles[ 2 ] = AngleNormalize180( ang[ 2 ] ); + Vector vDelta, vStart, vEnd; + float fDist, fScale; + + if (sv_gravity->value <= 0) { + return false; + } + + vStart = GrenadeThrowPoint(vFrom, vFace, STRING_ANIM_GRENADEKICK_SCR); + vDelta = vTo - vStart; + if (vDelta.z >= 0) { + return false; + } + + if (DotProduct(vDelta, vFace) < 0) { + return false; + } + + fDist = VectorLength2D(vDelta); + if (fDist < 256 || fDist >= (255401.28f / sv_gravity->value * 0.8f + 192.f)) { + return false; + } + + if (fDist < 512) { + fScale = 192.0f / fDist + 0.25f; + } else { + fScale = 1.0f - 192.0f / fDist; + } + + vDelta.x *= fScale; + vDelta.y *= fScale; + vEnd = vStart + vDelta; + + *pvVel = CalcKickVelocity(vDelta, fDist); + + if (*pvVel == vec_zero || !ValidGrenadePath(vStart, vEnd, *pvVel)) { + return false; + } + + return true; } /* =============== -Actor::EventLookAt +Actor::GrenadeWillHurtTeamAt -Look at event. +Returns true if grenade will hurt team at vTo. =============== */ -void Actor::EventLookAt - ( - Event *ev - ) +bool Actor::GrenadeWillHurtTeamAt(const Vector& vTo) { - if (ev->IsVectorAt(1)) - { - LookAt(ev->GetVector(1)); - } - else - { - LookAt(ev->GetListener(1)); - } + Sentient *pSquadMate; + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + if ((pSquadMate->origin - vTo).length() < 65536) { + return true; + } + } - m_iLookFlags = 0;//LOOK_NORMAL + return false; } /* =============== -Actor::EventEyesLookAt +Actor::CanGetGrenadeFromAToB -Eyes look at event. +Returns true if actor can get a grenade from vFrom to vTo. +pvVel is the kick/roll/throw velocity. +peMode is the possible toss mode. =============== */ -void Actor::EventEyesLookAt - ( - Event *ev - ) +bool Actor::CanGetGrenadeFromAToB( + const Vector& vFrom, const Vector& vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode +) { - EventLookAt(ev); + static constexpr unsigned int MAX_GRENADE_HINTS = 4; - m_iLookFlags = 1;//LOOK_EYE + float fRangeSquared; + GrenadeHint *apHint[MAX_GRENADE_HINTS]; + int nHints; + int i; + Vector vDelta; + Vector vAxisX, vAxisY; + Vector vStart; + Vector vHint; + float fDot; + + if (sv_gravity->value <= 0) { + return false; + } + + vDelta = vTo - vFrom; + fRangeSquared = vDelta.lengthSquared(); + + if (fRangeSquared < Square(256)) { + return false; + } + + if (bDesperate) { + vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADERETURN_SCR); + } + + if (fRangeSquared < Square(1024)) { + if (!bDesperate) { + vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETOSS_SCR); + } + + *pvVel = CanRollGrenade(vStart, vTo); + + if (*pvVel != vec_zero) { + *peMode = AI_GREN_TOSS_ROLL; + return true; + } + + if (!bDesperate) { + vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR); + } + + *pvVel = CanThrowGrenade(vStart, vTo); + + if (*pvVel != vec_zero) { + *peMode = AI_GREN_TOSS_THROW; + return true; + } + } else if (!bDesperate) { + return false; + } + + nHints = GrenadeHint::GetClosestSet(apHint, MAX_GRENADE_HINTS, vStart, Square(1024)); + + for (i = 0; i < nHints; i++) { + if (!bDesperate) { + fDot = DotProduct2D(vHint, vDelta); + if (fDot < 0) { + continue; + } + + if ((vHint.lengthXYSquared() * 0.9f * vDelta.lengthXYSquared()) >= (fDot * fDot)) { + continue; + } + } + + vStart = + GrenadeThrowPoint(vFrom, vHint, bDesperate ? STRING_ANIM_GRENADERETURN_SCR : STRING_ANIM_GRENADETOSS_SCR); + if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode)) { + return true; + } + } + + *peMode = AI_GREN_TOSS_NONE; + return false; } /* =============== -Actor::NoPoint +Actor::DecideToThrowGrenade -Don't point at anything. +Returns true if actor will throw grenade to vTo. +pvVel is the kick/roll/throw velocity. +peMode is the toss mode. =============== */ -void Actor::NoPoint - ( - void - ) +bool Actor::DecideToThrowGrenade(const Vector& vTo, Vector *pvVel, eGrenadeTossMode *peMode, bool bDesperate) { - VectorClear(m_vLUpperArmDesiredAngles); + if (!AmmoCount("grenade")) { + return false; + } + + if (GrenadeWillHurtTeamAt(vTo)) { + return false; + } + + return CanGetGrenadeFromAToB(origin, vTo, bDesperate, pvVel, peMode); } /* =============== -Actor::IdlePoint +Actor::GenericGrenadeTossThink -Idle point behaviour. +Called when actor in grenade state. +i.e. actor noticed a grenade and must think fast. =============== */ -void Actor::IdlePoint - ( - void - ) +void Actor::GenericGrenadeTossThink(void) { - if (m_pPointEntity) - { - Vector delta = m_pPointEntity->centroid - origin; - Vector v2; - VectorNormalize(delta); - v2 = delta.toAngles(); + Vector vGrenadeVel = vec_zero; + eGrenadeTossMode eGrenadeMode; - float yaw = AngleNormalize180(v2[1] - angles[1] + 30); - if (yaw > 100) - yaw = 100; - if (yaw < -80) - yaw = -80; - m_vLUpperArmDesiredAngles[0] = v2[0]; - m_vLUpperArmDesiredAngles[1] = yaw; - m_vLUpperArmDesiredAngles[2] = v2[2]; - } - else - { - NoPoint(); - } + if (m_Enemy && level.inttime >= m_iStateTime + 200) { + if (CanGetGrenadeFromAToB(origin, m_Enemy->origin + m_Enemy->velocity, false, &vGrenadeVel, &eGrenadeMode)) { + m_vGrenadeVel = vGrenadeVel; + m_eGrenadeMode = eGrenadeMode; + } + m_iStateTime = level.inttime; + } + + SetDesiredYawDir(m_vGrenadeVel); + ContinueAnimation(); } /* =============== -Actor::ClearPointEntity +Actor::Grenade_EventFire -Clear point entity. +Throw grenade animation =============== */ -void Actor::ClearPointEntity - ( - void - ) +void Actor::Grenade_EventFire(Event *ev) { - if (m_pPointEntity) - { - if (m_pPointEntity->IsSubclassOfTempWaypoint()) - { - delete m_pPointEntity; - } - m_pPointEntity = NULL; - } + Vector dir; + Vector pos; + float speed; + str strGrenade; + const_str csAnim; + + gi.Tag_NumForName(edict->tiki, "tag_weapon_right"); + + if (m_eGrenadeMode == AI_GREN_TOSS_ROLL) { + csAnim = STRING_ANIM_GRENADETOSS_SCR; + } else { + csAnim = STRING_ANIM_GRENADETHROW_SCR; + } + + pos = GrenadeThrowPoint(origin, orientation[0], csAnim); + dir = m_vGrenadeVel; + speed = dir.normalize(); + + if (g_protocol >= PROTOCOL_MOHTA_MIN) { + // Added in 2.30 + switch (m_iNationality) { + case ACTOR_NATIONALITY_ITALIAN: + strGrenade = "models/projectiles/Bomba_ai.tik"; + break; + case ACTOR_NATIONALITY_RUSSIAN: + strGrenade = "models/projectiles/Russian_F1_grenade_ai.tik"; + break; + case ACTOR_NATIONALITY_BRITISH: + strGrenade = "models/projectiles/Mills_grenade_ai.tik"; + break; + case ACTOR_NATIONALITY_AMERICAN: + strGrenade = "models/projectiles/M2FGrenade_ai.tik"; + break; + case ACTOR_NATIONALITY_GERMAN: + strGrenade = "models/projectiles/steilhandgranate_ai.tik"; + break; + default: + // fallback to team + if (m_Team != TEAM_GERMAN) { + strGrenade = "models/projectiles/M2FGrenade_ai.tik"; + } else { + strGrenade = "models/projectiles/steilhandgranate_ai.tik"; + } + break; + } + } else { + if (m_Team != TEAM_GERMAN) { + strGrenade = "models/projectiles/M2FGrenade.tik"; + } else { + strGrenade = "models/projectiles/steilhandgranate.tik"; + } + } + + ProjectileAttack(pos, dir, this, strGrenade, 0, speed); + UseAmmo("grenade", 1); } /* =============== -Actor::PointAt - -Change point entity. +Actor::EventSetTurret =============== */ -void Actor::PointAt - ( - const Vector& vec - ) +void Actor::EventSetTurret(Event *ev) { - ClearPointEntity(); - - TempWaypoint *twp = new TempWaypoint(); - m_pPointEntity = twp; - m_pPointEntity->setOrigin(vec); + Listener *l = ev->GetListener(1); + if (l && l->isSubclassOf(TurretGun)) { + m_pTurret = (TurretGun *)l; + } } /* =============== -Actor::PointAt - -Change point entity. +Actor::EventGetTurret =============== */ -void Actor::PointAt - ( - Listener* l - ) +void Actor::EventGetTurret(Event *ev) { - ClearPointEntity(); - if (l) - { - if (l->inheritsFrom(&SimpleEntity::ClassInfo)) - { - ScriptError("Bad point entity with classname '%s' specified for '%s' at (%f %f %f)\n", - l->getClassname(), - targetname.c_str(), - origin.x, - origin.y, - origin.z); - } - if (l != this) - { - m_pPointEntity = (SimpleEntity *)l; - } - } + ev->AddListener(m_pTurret); } /* =============== -Actor::EventPointAt - -Point at event. +Actor::EventGetAmmoGrenade =============== */ -void Actor::EventPointAt - ( - Event *ev - ) +void Actor::EventGetAmmoGrenade(Event *ev) { - if (ev->IsVectorAt(1)) - { - - PointAt(ev->GetVector(1)); - } - else - { - PointAt(ev->GetListener(1)); - } + ev->AddInteger(AmmoCount("grenade")); } /* =============== -Actor::ClearTurnEntity - -Clear turn entity. +Actor::EventSetAmmoGrenade =============== */ -void Actor::ClearTurnEntity - ( - void - ) +void Actor::EventSetAmmoGrenade(Event *ev) { - if (m_pTurnEntity) - { - if (m_pTurnEntity->IsSubclassOfTempWaypoint()) - { - delete m_pTurnEntity; - } - m_pTurnEntity = NULL; - } + GiveAmmo("grenade", ev->GetInteger(1)); } /* =============== -Actor::TurnTo - -Change turn entity. +Actor::EventEnableEnemy =============== */ -void Actor::TurnTo - ( - const Vector& vec - ) +void Actor::EventEnableEnemy(Event *ev) { - ClearTurnEntity(); - - TempWaypoint *twp = new TempWaypoint(); - m_pTurnEntity = twp; - m_pTurnEntity->setOrigin(vec); + m_bDesiredEnableEnemy = ev->GetBoolean(1); } /* =============== -Actor::TurnTo - -Change turn entity. +Actor::EventEnablePain =============== */ -void Actor::TurnTo - ( - Listener *l - ) +void Actor::EventEnablePain(Event *ev) { - ClearTurnEntity(); - if (l) - { - if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) - { - ScriptError("Bad turn entity with classname '%s' specified for '%s' at (%f %f %f)\n", - l->getClassname(), - targetname.c_str(), - origin.x, - origin.y, - origin.z); - } - - m_pTurnEntity = (SimpleEntity *)l; - } - else - { - m_pTurnEntity = this; - } + m_bEnablePain = ev->GetBoolean(1); + if (!m_bEnablePain) { + SetThinkState(THINKSTATE_VOID, THINKLEVEL_PAIN); + } } /* =============== -Actor::IdleTurn - -Idle turn behaviour. +Actor::EventActivate =============== */ -void Actor::IdleTurn - ( - void - ) +void Actor::EventActivate(Event *ev) { - if (m_pTurnEntity) - { - for (int i = 0; i <= 1; i++) - { - if (m_pTurnEntity == this) - { - StopTurning(); - m_pTurnEntity = NULL; - return; - } - vec2_t facedir; - VectorSub2D(m_pTurnEntity->centroid, origin, facedir); - if (facedir[0] || facedir[1]) - { - SetDesiredYawDir(facedir); - } - - float error = AngleNormalize180(m_DesiredYaw - angles[1]); - - if (error >= m_fTurnDoneError + 0.001 || -(m_fTurnDoneError + 0.001) >= error) - { - return; - } - - SafePtr prevTurnEntity = m_pTurnEntity; - - Director.Unpause(); - Unregister(STRING_TURNDONE); - Director.Pause(); - - - if (m_pTurnEntity == prevTurnEntity) - { - break; - } - } - } + m_bPatrolWaitTrigger = false; + Unregister(STRING_TRIGGER); } /* =============== -Actor::EventTurnTo - -Turn to event. +Actor::EventInterruptPoint =============== */ -void Actor::EventTurnTo - ( - Event *ev - ) +void Actor::EventInterruptPoint(Event *ev) { - if (ev->IsVectorAt(1)) - { - TurnTo(ev->GetVector(1)); - } - else - { - TurnTo(ev->GetListener(1)); - } + GlobalFuncs_t *interrupt = &GlobalFuncs[m_Think[m_ThinkLevel]]; + + if (interrupt->PostShoot) { + (this->*interrupt->PostShoot)(); + } } /* =============== -Actor::EventSetTurnDoneError - -Set the error amount that turndone will occur for the turnto command. +Actor::EventGetVisibilityThreshold =============== */ -void Actor::EventSetTurnDoneError - ( - Event *ev - ) +void Actor::EventGetVisibilityThreshold(Event *ev) { - m_fTurnDoneError = ev->GetFloat(1); - if (m_fTurnDoneError < 0) - { - m_fTurnDoneError = 0; - ScriptError("turndoneerror was set to a negative value - capped to 0"); - } + ev->AddFloat(m_fVisibilityThreshold); } /* =============== -Actor::EventGetTurnDoneError - -Get the error amount that turndone will occur for the turnto command. +Actor::EventSetVisibilityThreshold =============== */ -void Actor::EventGetTurnDoneError - ( - Event *ev - ) +void Actor::EventSetVisibilityThreshold(Event *ev) { - ev->AddFloat(m_fTurnDoneError); + float threshold; + + threshold = ev->GetFloat(1); + + if (threshold < 0 || threshold > 1) { + ScriptError("DefaultNonVisLevel must be in range 0-1"); + } + + m_bHasVisibilityThreshold = true; + m_fVisibilityThreshold = threshold; +} + +/* +=============== +Actor::EventSetDefaultVisibilityThreshold +=============== +*/ +void Actor::EventSetDefaultVisibilityThreshold(Event *ev) +{ + float threshold; + + threshold = ev->GetFloat(1); + + if (threshold < 0 || threshold > 1) { + ScriptError("DefaultNonVisLevel must be in range 0-1"); + } + + if (!m_bHasVisibilityThreshold) { + m_fVisibilityThreshold = threshold; + } +} + +/* +=============== +Actor::EventGetSuppressChance +=============== +*/ +void Actor::EventGetSuppressChance(Event *ev) +{ + ev->AddInteger(m_iSuppressChance); +} + +/* +=============== +Actor::EventSetSuppressChance +=============== +*/ +void Actor::EventSetSuppressChance(Event *ev) +{ + m_iSuppressChance = ev->GetInteger(1); + if (m_iSuppressChance != ev->GetFloat(1)) { + Com_Printf( + "WARNING: suppresschance should be an integer in the range 0 - 100, was set to %g for entnum %i (%s)\n", + (double)ev->GetFloat(1), + entnum, + TargetName().c_str() + ); + } + + if (m_iSuppressChance > 100) { + Com_Printf( + "WARNING: suppresschance should be in the range 0 - 100, was set to %i for entnum %i (%s)\n", + m_iSuppressChance, + entnum, + TargetName().c_str() + ); + + if (m_iSuppressChance >= 0) { + m_iSuppressChance = 100; + } else { + m_iSuppressChance = 0; + } + } +} + +/* +=============== +Actor::EventAnimScript +=============== +*/ +void Actor::EventAnimScript(Event *ev) +{ + m_csAnimScript = ev->GetConstString(1); + m_bAnimScriptSet = true; + m_AnimMode = ANIM_MODE_NORMAL; + + SetThinkIdle(THINK_ANIM); +} + +/* +=============== +Actor::EventAnimScript_Scripted +=============== +*/ +void Actor::EventAnimScript_Scripted(Event *ev) +{ + m_csAnimScript = ev->GetConstString(1); + m_bAnimScriptSet = true; + m_AnimMode = ANIM_MODE_SCRIPTED; + + SetThinkIdle(THINK_ANIM); +} + +/* +=============== +Actor::EventAnimScript_Noclip +=============== +*/ +void Actor::EventAnimScript_Noclip(Event *ev) +{ + m_csAnimScript = ev->GetConstString(1); + m_bAnimScriptSet = true; + m_AnimMode = ANIM_MODE_NOCLIP; + + SetThinkIdle(THINK_ANIM); +} + +/* +=============== +Actor::EventAnimScript_Attached +=============== +*/ +void Actor::EventAnimScript_Attached(Event *ev) +{ + m_csAnimScript = ev->GetConstString(1); + m_bAnimScriptSet = true; + m_AnimMode = ANIM_MODE_ATTACHED; + + SetThinkIdle(THINK_ANIM); +} + +/* +=============== +Actor::EventReload_mg42 +=============== +*/ +void Actor::EventReload_mg42(Event *ev) +{ + if (m_State != ACTOR_STATE_MACHINE_GUNNER_RELOADING) { + if (m_State == ACTOR_STATE_MACHINE_GUNNER_READY) { + m_bAnimScriptSet = true; + TransitionState(ACTOR_STATE_MACHINE_GUNNER_RELOADING, 0); + } else { + Unregister(STRING_ANIMDONE); + } + } +} + +/* +=============== +Actor::CanMovePathWithLeash +=============== +*/ +bool Actor::CanMovePathWithLeash(void) const +{ + vec2_t delta; + + if (!PathExists()) { + return false; + } + + VectorSub2D(origin, m_vHome, delta); + if (VectorLength2DSquared(delta) >= m_fLeashSquared && DotProduct2D(m_Path.CurrentDelta(), delta) >= 0) { + return false; + } + + return true; +} + +/* +=============== +Actor::MovePathWithLeash +=============== +*/ +bool Actor::MovePathWithLeash(void) +{ + if (!CanMovePathWithLeash()) { + Anim_Aim(); + return false; + } + + Anim_RunToInOpen(ANIM_MODE_PATH); + FaceMotion(); + + return true; +} + +/* +=============== +Actor::GunTarget +=============== +*/ +Vector Actor::GunTarget(bool bNoCollision, const vec3_t position, const vec3_t forward) +{ + static cvar_t *aifSupressScatter = gi.Cvar_Get("g_aiSupressScatter", "2.0", 0); + static cvar_t *aifCoverFactor = gi.Cvar_Get("g_aimcoverfactor", "0.80", 0); + static cvar_t *aiMaxDeviation = gi.Cvar_Get("g_aimaxdeviation", "0.965", 0); + static cvar_t *aiMinAccuracy = gi.Cvar_Get("g_aiminaccuracy", "0.33", 0); + static cvar_t *aiScatterWide = gi.Cvar_Get("g_aiScatterWide", "16.0", 0); + static cvar_t *aiScatterHeight = gi.Cvar_Get("g_aiScatterHeight", "45.0", 0); + static cvar_t *aiRanges[4]; + static qboolean doInit = true; + float fAccuracy, fCoverFactor; + Vector aimDir; + + fCoverFactor = mAccuracy * ((1.0 - m_fVisibilityAlpha) * aiMinAccuracy->value + m_fVisibilityAlpha); + + if (doInit) { + aiRanges[0] = gi.Cvar_Get("g_aishortrange", "500", 0); + aiRanges[1] = gi.Cvar_Get("g_aimediumrange", "700", 0); + aiRanges[2] = gi.Cvar_Get("g_ailongrange", "1000", 0); + aiRanges[3] = gi.Cvar_Get("g_aisniperrange", "2200", 0); + doInit = false; + } + + if (m_aimNode) { + Vector centroid = m_aimNode->centroid; + + if (m_aimNode->IsSubclassOfActor()) { + Actor *pActor = static_cast(m_aimNode.Pointer()); + if (pActor->IsOnFloor()) { + centroid = m_aimNode->origin + Vector(0, 0, 12); + } + } + + aimDir = centroid - Vector(position); + aimDir.normalize(); + + if (DotProduct(forward, aimDir) < 0.866f) { + return centroid; + } + } + + Vector dir = mTargetPos - EyePosition(); + dir.normalize(); + + if (g_target_game > target_game_e::TG_MOH) { + if (DotProduct(forward, dir) < aiMaxDeviation->value) { + Vector vOut; + + VectorMA(position, 2048, forward, vOut); + + return vOut; + } + } + + if (mTargetPos == vec_zero) { + Vector vOut; + + AnglesToAxis(angles, orientation); + + vOut = Vector(orientation[0]) * 2048; + vOut += EyePosition(); + + return vOut; + } + + Player *player = NULL; + Weapon *weapon; + float scatterMult = 1.f; + Vector vPos; + Vector vDelta; + + if (m_Enemy) { + if (!m_Enemy->IsSubclassOfPlayer() && fabs(m_Enemy->origin.z - origin.z) >= 128) { + // half towards for the player + scatterMult = 0.5f; + } + + vDelta = m_Enemy->centroid - centroid; + weapon = GetActiveWeapon(WEAPON_MAIN); + if (weapon) { + fAccuracy = vDelta.length() / aiRanges[weapon->mAIRange]->value; + if (fAccuracy < 1) { + fAccuracy = 1; + } + + scatterMult = fAccuracy * 0.75f; + } + + if (m_Enemy->IsSubclassOfPlayer()) { + player = static_cast(m_Enemy.Pointer()); + vPos = player->centroid; + + if (!G_SightTrace( + GunPosition(), vec_zero, vec_zero, vPos, m_Enemy, this, MASK_CANSEE, false, "Actor::GunTarget 1" + )) { + fCoverFactor *= aifCoverFactor->value; + vPos = m_Enemy->EyePosition(); + } + } + } + + if (m_State == ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE) { + scatterMult = aifSupressScatter->value; + } + + Vector error(0, 0, 0); + + fAccuracy = (1.0 - fCoverFactor) * 2 * scatterMult; + if (fAccuracy < 0) { + fAccuracy = 0; + } + + if (player) { + error[0] = fAccuracy * aiScatterWide->value * crandom(); + error[1] = fAccuracy * aiScatterWide->value * crandom(); + error[2] = fAccuracy * aiScatterHeight->value * crandom(); + vPos = player->centroid; + } else { + error[0] = fAccuracy * 32.0 * crandom(); + error[1] = fAccuracy * 32.0 * crandom(); + error[2] = fAccuracy * 48.0 * crandom(); + vPos = mTargetPos; + } + + if (m_Enemy && m_Enemy->GetVehicleTank()) { + vPos.z -= 128; + } + + return vPos + error; +} + +/* +=============== +Actor::setModel +=============== +*/ +qboolean Actor::setModel(void) +{ + str name; + qboolean success; + + if (model != "") { + if (m_csLoadOut != STRING_EMPTY) { + name = "weapon|" + Director.GetString(m_csLoadOut) + "|"; + } + + if (m_csHeadModel == STRING_EMPTY) { + m_csHeadModel = Director.AddString(level.GetRandomHeadModel(model)); + } + + if (m_csHeadModel != STRING_EMPTY) { + name += "headmodel|" + Director.GetString(m_csHeadModel) + "|"; + } + + if (m_csHeadSkin == STRING_EMPTY) { + m_csHeadSkin = Director.AddString(level.GetRandomHeadSkin(model)); + } + + if (m_csHeadSkin != STRING_EMPTY) { + name += "headskin|" + Director.GetString(m_csHeadSkin) + "|"; + } + + name += model; + } + + level.skel_index[edict->s.number] = -1; + + success = gi.setmodel(edict, name); + return success; +} + +/* +=============== +Actor::EventSetHeadModel +=============== +*/ +void Actor::EventSetHeadModel(Event *ev) +{ + m_csHeadModel = ev->GetConstString(1); + setModel(); +} + +/* +=============== +Actor::EventGetHeadModel +=============== +*/ +void Actor::EventGetHeadModel(Event *ev) +{ + ev->AddConstString(m_csHeadModel); +} + +/* +=============== +Actor::EventSetHeadSkin +=============== +*/ +void Actor::EventSetHeadSkin(Event *ev) +{ + m_csHeadSkin = ev->GetConstString(1); + setModel(); +} + +/* +=============== +Actor::EventGetHeadSkin +=============== +*/ +void Actor::EventGetHeadSkin(Event *ev) +{ + ev->AddConstString(m_csHeadSkin); +} + +/* +=============== +Actor::SetPathWithLeash +=============== +*/ +void Actor::SetPathWithLeash(Vector vDestPos, const char *description, int iMaxDirtyTime) +{ + vec2_t vDelta; + + VectorSub2D(vDestPos, m_vHome, vDelta); + + if (VectorLength2DSquared(vDelta) > m_fLeashSquared) { + ClearPath(); + return; + } + + VectorSub2D(origin, m_vHome, vDelta); + + if (VectorLength2DSquared(vDelta) > m_fLeashSquared) { + ClearPath(); + return; + } + + SetPath(vDestPos, description, iMaxDirtyTime, m_vHome, m_fLeashSquared); +} + +/* +=============== +Actor::SetPathWithLeash +=============== +*/ +void Actor::SetPathWithLeash(SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime) +{ + if (!pDestNode) { + if (m_bPathErrorTime + 5000 < level.inttime) { + m_bPathErrorTime = level.inttime; + Com_Printf( + "^~^~^ No destination node specified for '%s' at (%f %f %f)\n", + TargetName().c_str(), + origin[0], + origin[1], + origin[2] + ); + } + + ClearPath(); + return; + } + + SetPathWithLeash(pDestNode->origin, description, iMaxDirtyTime); +} + +/* +=============== +Actor::FindPathAwayWithLeash +=============== +*/ +void Actor::FindPathAwayWithLeash(vec3_t vAwayFrom, vec3_t vDirPreferred, float fMinSafeDist) +{ + m_Path.FindPathAway(origin, vAwayFrom, vDirPreferred, this, fMinSafeDist, m_vHome, m_fLeashSquared); + ShortenPathToAvoidSquadMates(); +} + +/* +=============== +Actor::FindPathNearWithLeash +=============== +*/ +void Actor::FindPathNearWithLeash(vec3_t vNearbyTo, float fCloseDistSquared) +{ + vec2_t vDelta; + + VectorSub2D(vNearbyTo, m_vHome, vDelta); + + if ((sqrt(m_fLeashSquared * fCloseDistSquared) * 2 + m_fLeashSquared + fCloseDistSquared) + < VectorLength2DSquared(vDelta)) { + return; + } + + VectorSub2D(origin, m_vHome, vDelta); + + if (VectorLength2DSquared(vDelta) > m_fLeashSquared) { + return; + } + + m_Path.FindPathNear(origin, vNearbyTo, this, 0, fCloseDistSquared, m_vHome, m_fLeashSquared); + ShortenPathToAvoidSquadMates(); +} + +/* +=============== +Actor::GetAntiBunchPoint + +=============== +*/ +Vector Actor::GetAntiBunchPoint(void) +{ + float fMinDistSquared; + Vector vDelta; + Sentient *pSquadMate; + Vector vFinalPos; + int nAvoid; + + fMinDistSquared = m_fInterval * m_fInterval; + nAvoid = 0; + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + float fLengthSquared, fLength; + + fLengthSquared = vDelta.lengthSquared(); + if (!fLengthSquared) { + continue; + } + + if (fLengthSquared >= fMinDistSquared) { + continue; + } + + fLength = sqrt(fLengthSquared); + vDelta *= 1.0f / fLength; + vFinalPos += origin + vDelta * (m_fInterval - fLength); + } + + if (!nAvoid) { + return origin; + } else if (nAvoid == 1) { + return vFinalPos; + } else { + vFinalPos *= 1.f / nAvoid; + return vFinalPos; + } +} + +/* +=============== +Actor::AutoArchiveModel +=============== +*/ +bool Actor::AutoArchiveModel(void) +{ + return false; +} + +/* +=============== +Actor::AddToBodyQue + +Add this to body queue. +=============== +*/ +void Actor::AddToBodyQue(void) +{ + if (mBodyQueue[mCurBody]) { + mBodyQueue[mCurBody]->PostEvent(EV_Remove, 0); + } + + mBodyQueue[mCurBody] = this; + + //update current body index + mCurBody = (mCurBody + 1) % MAX_BODYQUEUE; +} + +/* +=============== +Actor::ResetBodyQueue + +Clear body queue. +Called upon Level::Cleanup() +=============== +*/ +void Actor::ResetBodyQueue(void) +{ + //weird useless loop ? + + for (int i = 0; i < MAX_BODYQUEUE; i++) { + //do nothing. + } + //mBodyQueue + //this resets curBody, but all the magic happens in AddToBodyQue + mCurBody = 0; +} + +/* +=============== +Actor::EventSetNoIdle +=============== +*/ +void Actor::EventSetNoIdle(Event *ev) +{ + m_bNoIdleAfterAnim = ev->GetInteger(1); +} + +/* +=============== +Actor::EventGetNoIdle +=============== +*/ +void Actor::EventGetNoIdle(Event *ev) +{ + ev->AddInteger(m_bNoIdleAfterAnim); +} + +/* +=============== +Actor::EventGetEnemy +=============== +*/ +void Actor::EventGetEnemy(Event *ev) +{ + ev->AddListener(m_Enemy); +} + +/* +=============== +Actor::EventSetMaxNoticeTimeScale +=============== +*/ +void Actor::EventSetMaxNoticeTimeScale(Event *ev) +{ + float fScale; + + fScale = ev->GetFloat(1); + if (fScale <= 0) { + Com_Printf("^~^~^ ERROR: noticescale: value must be greater than 0\n"); + return; + } + + m_fMaxNoticeTimeScale = fScale * 0.01f; +} + +/* +=============== +Actor::EventGetMaxNoticeTimeScale +=============== +*/ +void Actor::EventGetMaxNoticeTimeScale(Event *ev) +{ + ev->AddFloat(m_fMaxNoticeTimeScale * 100); +} + +/* +=============== +Actor::EventSetFixedLeash +=============== +*/ +void Actor::EventSetFixedLeash(Event *ev) +{ + m_bFixedLeash = ev->GetBoolean(1); +} + +/* +=============== +Actor::EventGetFixedLeash +=============== +*/ +void Actor::EventGetFixedLeash(Event *ev) +{ + ev->AddInteger(m_bFixedLeash); +} + +/* +=============== +Actor::Holster +=============== +*/ +void Actor::Holster(void) +{ + if (activeWeaponList[WEAPON_MAIN]) { + DeactivateWeapon(WEAPON_MAIN); + } +} + +/* +=============== +Actor::HolsterOffHand +=============== +*/ +void Actor::HolsterOffHand(void) +{ + if (activeWeaponList[WEAPON_OFFHAND]) { + DeactivateWeapon(WEAPON_OFFHAND); + } +} + +/* +=============== +Actor::Unholster +=============== +*/ +void Actor::Unholster(void) +{ + Weapon *weap; + + if (!activeWeaponList[WEAPON_MAIN]) { + weap = GetWeapon(0); + if (weap) { + useWeapon(weap, WEAPON_MAIN); + ActivateNewWeapon(); + } + } +} + +/* +=============== +Actor::UnholsterOffHand +=============== +*/ +void Actor::UnholsterOffHand(void) +{ + Weapon *weap; + + if (!activeWeaponList[WEAPON_OFFHAND]) { + weap = GetWeapon(0); + if (weap) { + useWeapon(weap, WEAPON_OFFHAND); + ActivateNewWeapon(); + } + } +} + +/* +=============== +Actor::EventHolster +=============== +*/ +void Actor::EventHolster(Event *ev) +{ + if (ev->NumArgs() > 0 && ev->GetInteger(1) > 0) { + HolsterOffHand(); + } else { + Holster(); + } +} + +/* +=============== +Actor::EventUnholster +=============== +*/ +void Actor::EventUnholster(Event *ev) +{ + if (ev->NumArgs() > 0 && ev->GetInteger(1) > 0) { + UnholsterOffHand(); + } else { + Unholster(); + } +} + +/* +=============== +Actor::EventIsEnemyVisible +=============== +*/ +void Actor::EventIsEnemyVisible(Event *ev) +{ + ev->AddInteger(m_bEnemyVisible); +} + +/* +=============== +Actor::EventGetEnemyVisibleChangeTime +=============== +*/ +void Actor::EventGetEnemyVisibleChangeTime(Event *ev) +{ + ev->AddFloat(m_iEnemyVisibleChangeTime / 100.f); +} + +/* +=============== +Actor::EventGetLastEnemyVisibleTime +=============== +*/ +void Actor::EventGetLastEnemyVisibleTime(Event *ev) +{ + ev->AddFloat(m_iLastEnemyVisibleTime / 100.f); +} + +/* +=============== +Actor::EventSoundDone +=============== +*/ +void Actor::EventSoundDone(Event *ev) +{ + int channelNum; + str sfxName; + + channelNum = ev->GetInteger(1); + sfxName = ev->GetString(2); + + if (gi.S_IsSoundPlaying(channelNum, sfxName)) { + Event event(EV_SoundDone); + event.AddInteger(channelNum); + event.AddString(sfxName); + PostEvent(event, level.frametime); + } else if (m_bSayAnimSet && m_iSaySlot == -2) { + ChangeSayAnim(); + if (m_csSayAnim == STRING_EMPTY) { + Unregister(STRING_SAYDONE); + } + } else { + Unregister(STRING_SOUNDDONE); + } +} + +/* +=============== +Actor::EventSound +=============== +*/ +void Actor::EventSound(Event *ev) +{ + if (g_gametype->integer == GT_SINGLE_PLAYER || m_Team == TEAM_AMERICAN) { + ProcessSoundEvent(ev, true); + } else { + ProcessSoundEvent(ev, false); + } +} + +/* +=============== +Actor::EventSetFallHeight +=============== +*/ +void Actor::EventSetFallHeight(Event *ev) +{ + float fHeight = ev->GetFloat(1); + + if (fHeight < MIN_FALLHEIGHT) { + ScriptError("value less than %d not allowed", MIN_FALLHEIGHT); + } + if (fHeight > MAX_FALLHEIGHT) { + ScriptError("value greater than %d not allowed", MAX_FALLHEIGHT); + } + + m_Path.SetFallHeight(fHeight); +} + +/* +=============== +Actor::EventGetFallHeight +=============== +*/ +void Actor::EventGetFallHeight(Event *ev) +{ + ev->AddFloat(m_Path.GetFallHeight()); +} + +/* +=============== +Actor::EventCanMoveTo +=============== +*/ +void Actor::EventCanMoveTo(Event *ev) +{ + Vector vDest; + vec2_t vDelta; + float fDistSquared; + float fIntervalSquared; + Sentient *pSquadMate; + + vDest = ev->GetVector(1); + + VectorSub2D(vDest, m_vHome, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (fDistSquared >= m_fLeashSquared) { + ev->AddInteger(0); + return; + } + + if (m_Enemy) { + VectorSub2D(vDest, m_Enemy->origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (fDistSquared <= m_fMinDistanceSquared || fDistSquared >= m_fMaxDistanceSquared) { + ev->AddInteger(false); + return; + } + } + + if (m_fInterval) { + fIntervalSquared = Square(m_fInterval); + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + fDistSquared = (vDest - pSquadMate->origin).lengthSquared(); + + if (fDistSquared >= fIntervalSquared) { + continue; + } + + if ((origin - pSquadMate->origin).lengthSquared() > fDistSquared) { + ev->AddInteger(false); + return; + } + } + } + + for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + Actor *pActor; + + if (pSquadMate->IsSubclassOfActor()) { + pActor = static_cast(pSquadMate); + if (!pActor->m_Enemy) { + continue; + } + + VectorSub2D(pActor->m_Enemy->origin, pSquadMate->origin, vDelta); + } else { + VectorCopy2D(pSquadMate->orientation[0], vDelta); + } + + float fIntercept = CrossProduct2D(vDelta, pSquadMate->origin); + float a1 = CrossProduct2D(vDelta, origin) - fIntercept; + float a2 = CrossProduct2D(vDelta, vDest) - fIntercept; + + if (signbit(a1) != signbit(a2)) { + ev->AddInteger(false); + return; + } + } + + ev->AddInteger(true); +} + +/* +=============== +Actor::EventMoveDir +=============== +*/ +void Actor::EventMoveDir(Event *ev) +{ + vec3_t vDir; + + VectorClear(vDir); + + if (!PathGoalSlowdownStarted()) { + VectorCopy2D(velocity, vDir); + + if (velocity.x || velocity.y) { + VectorCopy2D(velocity, vDir); + VectorNormalize2D(vDir); + vDir[2] = 0; + } else if (PathExists() && !PathComplete()) { + VectorCopy2D(PathDelta(), vDir); + VectorNormalize2D(vDir); + vDir[2] = 0; + } + } + + ev->AddVector(vDir); +} + +/* +=============== +Actor::EventIntervalDir +=============== +*/ +void Actor::EventIntervalDir(Event *ev) +{ + if (level.inttime >= m_iIntervalDirTime + 250) { + m_vIntervalDir = vec_zero; + m_iIntervalDirTime = level.inttime; + + if (m_Enemy) { + m_vIntervalDir = GetAntiBunchPoint() - origin; + if (m_vIntervalDir.x || m_vIntervalDir.y) { + m_vIntervalDir.normalizefast(); + } + } + } + + ev->AddVector(m_vIntervalDir); +} + +/* +=============== +Actor::EventResetLeash +=============== +*/ +void Actor::EventResetLeash(Event *ev) +{ + m_vHome = origin; + m_pTetherEnt = NULL; +} + +/* +=============== +Actor::EventTether +=============== +*/ +void Actor::EventTether(Event *ev) +{ + m_pTetherEnt = ev->GetSimpleEntity(1); +} + +/* +=============== +Actor::ShortenPathToAttack +=============== +*/ +bool Actor::ShortenPathToAttack(float fMinDist) +{ + float fMinDistSquared; + PathInfo *pathnode; + Vector vEyePos; + + if (!PathExists() || PathComplete()) { + return false; + } + + if (!PathAvoidsSquadMates()) { + return false; + } + + fMinDistSquared = Square(fMinDist); + for (pathnode = CurrentPathNode(); pathnode > LastPathNode(); pathnode--) { + if ((pathnode->point - origin).lengthSquared() < fMinDistSquared) { + continue; + } + + if (CanSeeFrom(pathnode->point - eyeposition, m_Enemy)) { + m_Path.TrimPathFromEnd(pathnode - LastPathNode()); + return true; + } + } + + return false; +} + +/* +=============== +Actor::StrafeToAttack +=============== +*/ +void Actor::StrafeToAttack(float fDist, vec3_t vDir) +{ + static const vec3_t mins = {-16, -16, 16}; + static const vec3_t maxs = {16, 16, 128}; + Vector vSpot; + Vector vDelta; + Vector vEnemyCentroid; + + VectorScale(vDir, fDist, vDelta); + VectorAdd(origin, vDelta, vSpot); + + float fDistSquared = (vSpot - m_vLastEnemyPos).lengthSquared(); + if (fDistSquared >= m_fMaxDistanceSquared || fDistSquared <= m_fMinDistanceSquared) { + ClearPath(); + return; + } + + if (!G_SightTrace(origin, mins, maxs, vSpot, this, NULL, MASK_TARGETPATH, true, "Actor::StrafeToAttack 1")) { + ClearPath(); + return; + } + + vEnemyCentroid = m_vLastEnemyPos; + vEnemyCentroid.z += m_Enemy->centroid.z - m_Enemy->origin.z; + + if (!G_SightTrace( + vDelta + EyePosition(), + vec3_origin, + vec3_origin, + vEnemyCentroid, + this, + m_Enemy, + MASK_CANSEE, + false, + "Actor::StrafeToAttack 1" + )) { + ClearPath(); + return; + } + + SetPathWithLeash(vSpot, NULL, 0); +} + +/* +=============== +Actor::EventGetThinkState +=============== +*/ +void Actor::EventGetThinkState(Event *ev) +{ + ev->AddConstString(m_csThinkStateNames[m_ThinkState]); +} + +/* +=============== +Actor::EventGetEnemyShareRange +=============== +*/ +void Actor::EventGetEnemyShareRange(Event *ev) +{ + ev->AddFloat(sqrt(m_fMaxShareDistSquared)); +} + +/* +=============== +Actor::EventSetEnemyShareRange +=============== +*/ +void Actor::EventSetEnemyShareRange(Event *ev) +{ + float fLength = ev->GetFloat(1); + m_fMaxShareDistSquared = Square(fLength); +} + +/* +=============== +Actor::GetVoiceType +=============== +*/ +void Actor::GetVoiceType(Event *ev) +{ + //voice type in actor is a char. + ev->AddString(va("%c", mVoiceType)); +} + +/* +=============== +Actor::SetVoiceType +=============== +*/ +void Actor::SetVoiceType(Event *ev) +{ + //voice type in actor is a char. + const str vType = ev->GetString(1); + + if (vType.length() && vType[0]) { + mVoiceType = vType[0]; + } else { + mVoiceType = -1; + } +} + +/* +=============== +Actor::FindSniperNodeAndSetPath +=============== +*/ +PathNode *Actor::FindSniperNodeAndSetPath(bool *pbTryAgain) +{ + PathNode *pSniperNode; + + pSniperNode = PathManager.FindNearestSniperNode(this, origin, m_Enemy); + + if (!pSniperNode) { + *pbTryAgain = false; + return NULL; + } + + SetPathWithLeash(pSniperNode, NULL, 0); + + if (!PathExists()) { + pSniperNode->MarkTemporarilyBad(); + *pbTryAgain = true; + return NULL; + } + + if (!PathComplete() && !PathAvoidsSquadMates()) { + pSniperNode->MarkTemporarilyBad(); + *pbTryAgain = true; + return NULL; + } + + *pbTryAgain = true; + return pSniperNode; +} + +/* +=============== +Actor::Remove +=============== +*/ +void Actor::Remove(Event *ev) +{ + EndStates(); + + if (deadflag != DEAD_DEAD) { + deadflag = DEAD_DEAD; + health = 0; + Unregister(STRING_DEATH); + } + + Delete(); +} + +/* +=============== +Actor::EventGetKickDir +=============== +*/ +void Actor::EventGetKickDir(Event *ev) +{ + ev->AddVector(m_vKickDir); +} + +/* +=============== +Actor::EventGetNoLongPain +=============== +*/ +void Actor::EventGetNoLongPain(Event *ev) +{ + ev->AddInteger(m_bNoLongPain || m_Team == TEAM_AMERICAN); +} + +/* +=============== +Actor::EventSetNoLongPain +=============== +*/ +void Actor::EventSetNoLongPain(Event *ev) +{ + m_bNoLongPain = ev->GetBoolean(1); +} + +/* +=============== +Actor::DontFaceWall +=============== +*/ +void Actor::DontFaceWall(void) +{ + trace_t trace; + Vector start, end; + float fAngle, fSinAngle, fCosAngle; + float fEyeRadius; + float fErrorLerp; + vec2_t vDelta; + PathNode *pNode; + + if (m_pCoverNode && m_pCoverNode->nodeflags & (AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE)) { + m_eDontFaceWallMode = 1; + return; + } + + if (velocity.lengthXYSquared() > Square(8)) { + m_eDontFaceWallMode = 2; + return; + } + + fAngle = AngleNormalize360(m_YawAchieved ? angles.y : m_DesiredYaw); + + fErrorLerp = (level.time - m_fDfwTime) * 0.5; + if (fErrorLerp > 1) { + fErrorLerp = 1; + } + + VectorSub2D(m_vDfwPos, origin, vDelta); + + if (Square(fErrorLerp * -14.0 + 16.0) > VectorLength2DSquared(vDelta) + && (fabs(AngleNormalize180(m_fDfwRequestedYaw - m_DesiredYaw)) <= fErrorLerp * -29.0 + 30.0 + || fabs(AngleNormalize180(m_fDfwDerivedYaw - m_DesiredYaw)) <= fErrorLerp * -29.0 + 30.0)) { + if (AvoidingFacingWall()) { + SetDesiredYaw(m_fDfwDerivedYaw); + } + return; + } + + m_vDfwPos = origin; + m_fDfwRequestedYaw = fAngle; + m_fDfwTime = level.time; + + fSinAngle = sin(DEG2RAD(fAngle)); + fCosAngle = cos(DEG2RAD(fAngle)); + + VectorSub2D(EyePosition(), origin, vDelta); + start = EyePosition(); + start.x -= origin.x; + start.y -= origin.y; + fEyeRadius = VectorLength2D(start); + start.x = origin.x + fEyeRadius * fCosAngle; + start.y = origin.y + fEyeRadius * fSinAngle; + end.x = start.x + fCosAngle * 64; + end.y = start.y + fSinAngle * 64; + end.z = start.z; + + trace = G_Trace(start, vec_zero, vec_zero, end, this, MASK_CANSEE, false, "Actor::DontFaceWall"); + + if (trace.entityNum == ENTITYNUM_NONE || trace.fraction > 0.999f || trace.startsolid) { + m_eDontFaceWallMode = 3; + m_fDfwDerivedYaw = m_fDfwRequestedYaw; + return; + } + + if (trace.entityNum != ENTITYNUM_WORLD && !trace.ent->entity->AIDontFace()) { + m_eDontFaceWallMode = 4; + m_fDfwDerivedYaw = m_fDfwRequestedYaw; + return; + } + + if (trace.plane.normal[2] < -0.7f || trace.plane.normal[2] > 0.7f) { + m_eDontFaceWallMode = 5; + m_fDfwDerivedYaw = m_fDfwRequestedYaw; + return; + } + + if (m_Enemy && (m_Enemy->origin * trace.plane.normal - trace.plane.dist) < 0) { + end = m_Enemy->origin; + } else { + end = start + 128 * (end - start); + } + + pNode = PathManager.FindCornerNodeForWall(origin, end, this, 0.0f, trace.plane.normal); + if (pNode) { + SetDesiredYawDest(pNode->m_PathPos); + } else if (trace.fraction > 0.46875f) { + if (m_DesiredYaw < 90.0) { + SetDesiredYaw(m_DesiredYaw + 270); + } else { + SetDesiredYaw(m_DesiredYaw - 90); + } + m_eDontFaceWallMode = 8; + } else { + SetDesiredYawDir(trace.plane.normal); + m_eDontFaceWallMode = 7; + } + + m_fDfwDerivedYaw = m_DesiredYaw; +} + +/* +=============== +Actor::IsVoidState +=============== +*/ +bool Actor::IsVoidState(int state) +{ + return true; +} + +/* +=============== +Actor::IsIdleState +=============== +*/ +bool Actor::IsIdleState(int state) +{ + return state == THINKSTATE_IDLE; +} + +/* +=============== +Actor::IsCuriousState +=============== +*/ +bool Actor::IsCuriousState(int state) +{ + return state == THINKSTATE_CURIOUS; +} + +/* +=============== +Actor::IsDisguiseState +=============== +*/ +bool Actor::IsDisguiseState(int state) +{ + return state == THINKSTATE_DISGUISE; +} + +/* +=============== +Actor::IsAttackState +=============== +*/ +bool Actor::IsAttackState(int state) +{ + return state == THINKSTATE_ATTACK; +} + +/* +=============== +Actor::IsGrenadeState +=============== +*/ +bool Actor::IsGrenadeState(int state) +{ + return state == THINKSTATE_GRENADE; +} + +/* +=============== +Actor::IsBadPlaceState +=============== +*/ +bool Actor::IsBadPlaceState(int state) +{ + return state == THINKSTATE_BADPLACE; +} + +/* +=============== +Actor::IsPainState +=============== +*/ +bool Actor::IsPainState(int state) +{ + return state == THINKSTATE_PAIN; +} + +/* +=============== +Actor::IsKilledState +=============== +*/ +bool Actor::IsKilledState(int state) +{ + return state == THINKSTATE_KILLED; +} + +/* +=============== +Actor::IsNoClipState +=============== +*/ +bool Actor::IsNoClipState(int state) +{ + return state == THINKSTATE_NOCLIP; +} + +/* +=============== +Actor::InitVoid + +Init void global func +=============== +*/ +void Actor::InitVoid(GlobalFuncs_t *func) +{ + func->IsState = &Actor::IsVoidState; +} + +/* +=============== +Actor::BecomeCorpse +=============== +*/ +void Actor::BecomeCorpse(void) +{ + AddToBodyQue(); + + setContents(CONTENTS_TRIGGER); + edict->r.svFlags &= ~SVF_MONSTER; + setSolidType(SOLID_NOT); + + CheckGround(); + if (groundentity) { + setMoveType(MOVETYPE_NONE); + } else { + // enable physics if on air + setMoveType(MOVETYPE_TOSS); + } + + // don't cast shadow + edict->s.renderfx &= ~RF_SHADOW; + + PostEvent(EV_DeathSinkStart, 10); +} + +/* +=============== +Actor::EventGetFavoriteEnemy +=============== +*/ +void Actor::EventGetFavoriteEnemy(Event *ev) +{ + ev->AddEntity(m_FavoriteEnemy); +} + +/* +=============== +Actor::EventSetFavoriteEnemy +=============== +*/ +void Actor::EventSetFavoriteEnemy(Event *ev) +{ + m_FavoriteEnemy = static_cast(ev->GetEntity(1)); +} + +/* +=============== +Actor::EventFindEnemy +=============== +*/ +void Actor::EventFindEnemy(Event *ev) +{ + if (level.inttime > m_iEnemyCheckTime + 200) { + UpdateEnemyInternal(); + } + + ev->AddEntity(m_Enemy); +} + +/* +=============== +Actor::EventGetMumble +=============== +*/ +void Actor::EventGetMumble(Event *ev) +{ + ev->AddInteger(m_bMumble); +} + +/* +=============== +Actor::EventSetMumble +=============== +*/ +void Actor::EventSetMumble(Event *ev) +{ + m_bMumble = ev->GetInteger(1) != false; +} + +/* +=============== +Actor::EventGetBreathSteam +=============== +*/ +void Actor::EventGetBreathSteam(Event *ev) +{ + ev->AddInteger(m_bBreathSteam); +} + +/* +=============== +Actor::EventSetBreathSteam +=============== +*/ +void Actor::EventSetBreathSteam(Event *ev) +{ + m_bBreathSteam = ev->GetInteger(1) != false; +} + +/* +=============== +Actor::EventSetNextBreathTime +=============== +*/ +void Actor::EventSetNextBreathTime(Event *ev) +{ + ScriptVariable var; + ScriptThread *thread; + + thread = Director.CreateThread("global/breathe.scr", "nextbreathtime"); + + // pass the breath time as the first argument + var.setFloatValue(ev->GetFloat(1)); + thread->Execute(&var, 1); +} + +/* +=============== +Actor::EventCalcGrenadeToss2 +=============== +*/ +void Actor::EventCalcGrenadeToss2(Event *ev) +{ + Vector vTargetPos; + Vector vFrom; + Vector vPoint; + Vector vDelta; + Vector vVel; + Vector vPointTarget(0, 0, 0); + float speed; + float fDistSquared; + + vFrom = origin; + speed = 0; + vTargetPos = ev->GetVector(1); + vDelta = vTargetPos - vFrom; + fDistSquared = vDelta.lengthSquared(); + + if (ev->NumArgs() > 1) { + speed = ev->GetFloat(2); + } + + if (fDistSquared < Square(1024)) { + // See if it can roll + vPoint = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETOSS_SCR); + vVel = CanRollGrenade(vPoint, vTargetPos); + + if (vVel != vPointTarget) { + m_vGrenadeVel = vVel; + m_eGrenadeMode = AI_GREN_TOSS_ROLL; + ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR); + SetDesiredYawDir(m_vGrenadeVel); + return; + } + } + + if (!speed) { + vPoint = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR); + vVel = CanThrowGrenade(vPoint, vTargetPos); + + if (vVel != vec_zero) { + m_vGrenadeVel = vVel; + m_eGrenadeMode = AI_GREN_TOSS_THROW; + ev->AddConstString(STRING_ANIM_GRENADETHROW_SCR); + SetDesiredYawDir(m_vGrenadeVel); + } else { + ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR); + } + return; + } + + vPoint = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR); + + vVel = vTargetPos - vPoint; + vVel.normalize(); + vVel *= speed; + + m_vGrenadeVel = vVel; + m_eGrenadeMode = AI_GREN_TOSS_THROW; + + ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR); + SetDesiredYawDir(m_vGrenadeVel); +} + +/* +=============== +Actor::EventCalcGrenadeToss +=============== +*/ +void Actor::EventCalcGrenadeToss(Event *ev) +{ + bool bSuccess; + + if (ev->NumArgs() > 1) { + bSuccess = ev->GetBoolean(2); + } + + if (!DecideToThrowGrenade(ev->GetVector(1), &m_vGrenadeVel, &m_eGrenadeMode, bSuccess)) { + ev->AddConstString(STRING_EMPTY); + return; + } + + switch (m_eGrenadeMode) { + case AI_GREN_TOSS_ROLL: + ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR); + break; + case AI_GREN_TOSS_HINT: + case AI_GREN_TOSS_THROW: + ev->AddConstString(STRING_ANIM_GRENADETHROW_SCR); + break; + default: + { + char assertStr[16384] = {0}; + strcpy(assertStr, "\"invalid return condition for Actor::EventCalcGrenadeToss\"\n\tMessage: "); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); + assert(false && assertStr); + } + break; + } + + SetDesiredYawDir(m_vGrenadeVel); +} + +/* +=============== +Actor::EventGetNoSurprise +=============== +*/ +void Actor::EventGetNoSurprise(Event *ev) +{ + ev->AddInteger(m_bNoSurprise); +} + +/* +=============== +Actor::EventSetNoSurprise +=============== +*/ +void Actor::EventSetNoSurprise(Event *ev) +{ + m_bNoSurprise = ev->GetBoolean(1); +} + +/* +=============== +Actor::EventGetSilent +=============== +*/ +void Actor::EventGetSilent(Event *ev) +{ + ev->AddInteger(m_bSilent); +} + +/* +=============== +Actor::EventSetSilent +=============== +*/ +void Actor::EventSetSilent(Event *ev) +{ + m_bSilent = ev->GetBoolean(1); +} + +/* +=============== +Actor::EventGetAvoidPlayer +=============== +*/ +void Actor::EventGetAvoidPlayer(Event *ev) +{ + ev->AddInteger(m_bAutoAvoidPlayer); +} + +/* +=============== +Actor::EventSetAvoidPlayer +=============== +*/ +void Actor::EventSetAvoidPlayer(Event *ev) +{ + m_bAutoAvoidPlayer = ev->GetBoolean(1); +} + +/* +=============== +Actor::PathnodeClaimRevoked +=============== +*/ +void Actor::PathnodeClaimRevoked(PathNode *node) +{ + int iThinkLevel; + + for (iThinkLevel = m_ThinkLevel; iThinkLevel >= 0; --iThinkLevel) { + GlobalFuncs_t *func = &GlobalFuncs[m_Think[iThinkLevel]]; + + if (func->PathnodeClaimRevoked) { + (this->*func->PathnodeClaimRevoked)(); + } + } + + node->Relinquish(); + m_pCoverNode = NULL; +} + +/* +=============== +Actor::SetPathToNotBlockSentient +=============== +*/ +void Actor::SetPathToNotBlockSentient(Sentient *pOther) +{ + Vector vAway; + Vector vPerp; + Vector vDest; + + if (!pOther) { + return; + } + + if (pOther->IsDead()) { + return; + } + + if (!IsTeamMate(pOther)) { + return; + } + + if (pOther->velocity.lengthSquared() <= 1) { + return; + } + + vAway = origin - pOther->origin; + + if (vAway.lengthSquared() >= Square(48)) { + return; + } + + if (DotProduct2D(pOther->velocity, vAway) <= 0) { + return; + } + + if (CrossProduct2D(pOther->velocity, vAway) >= 0) { + vPerp[0] = -pOther->velocity[1]; + vPerp[1] = pOther->velocity[0]; + } else { + vPerp[0] = pOther->velocity[1]; + vPerp[1] = -pOther->velocity[0]; + } + vPerp[2] = 0; + vPerp.normalizefast(); + + vDest = origin + vPerp * 48; + + if (G_SightTrace(vDest, mins, maxs, vDest, this, pOther, MASK_SOLID, false, "Actor::SetPathToNotBlockSentient 1")) { + SetPathWithinDistance(vDest, NULL, 96, 0); + } + + if (PathExists()) { + return; + } + + vDest = origin - vPerp * 48; + + if (G_SightTrace(vDest, mins, maxs, vDest, this, pOther, MASK_SOLID, false, "Actor::SetPathToNotBlockSentient 2")) { + SetPathWithinDistance(vDest, NULL, 96, 0); + } + + if (PathExists()) { + return; + } + + FindPathAway(pOther->origin, vAway * 100, 96); } /* @@ -8305,1538 +12151,419 @@ Actor::LookAround Look around behaviour. =============== */ -void Actor::LookAround - ( - float fFovAdd - ) +void Actor::LookAround(float fFovAdd) { - Vector vDest, vAngle; - float fModTime; + float fModTime; + vec3_t vAngle; + vec3_t vDest; + trace_t trace; - if (level.inttime >= m_iNextLookTime) - { - fModTime = level.time; - vAngle = angles; + if (level.inttime >= m_iNextLookTime) { + VectorCopy(angles, vAngle); + fModTime = level.time / 8 - floor(level.time / 8); - vAngle.y += fFovAdd * (2*(fModTime * 0.125 - floor(fModTime * 0.125)) - 1.0); - vAngle.x += (noise1(fModTime * 1.005309626678312 + entnum) + 1.0) * 15.0; + vAngle[1] = fFovAdd * (fModTime * 2 - 1) + vAngle[1]; + vAngle[0] += (noise1(entnum + level.time * 1.005309626678312f) + 1) * 15; + AngleVectors(vAngle, vDest, NULL, NULL); - AngleVectors(vAngle, vDest, NULL, NULL); + Vector vEyePos = EyePosition(); - vDest += EyePosition() * 1024; - trace_t trace = G_Trace(EyePosition(), vec_zero, vec_zero, vDest, this, 25, qfalse, "Actor::LookAround"); - if (trace.fraction > 0.125) - { - m_bHasDesiredLookDest = true; - VectorCopy(trace.endpos, m_vDesiredLookDest); - m_iNextLookTime = level.inttime + rand() % 500 + 750; - } - else - { - m_bHasDesiredLookDest = false; - m_iNextLookTime = level.inttime + 187; - } - } + VectorMA(vEyePos, 1024, vDest, vDest); - - if (m_bHasDesiredLookDest) - { - SetDesiredLookDir(m_vDesiredLookDest - EyePosition()); - } - else - { - m_bHasDesiredLookAngles = false; - } + trace = G_Trace(EyePosition(), vec_zero, vec_zero, vDest, this, MASK_LOOK, false, "Actor::LookAround"); + if (trace.fraction > 0.125) { + m_bHasDesiredLookDest = true; + VectorCopy(trace.endpos, m_vDesiredLookDest); + m_iNextLookTime = level.inttime + (rand() % 500) + 750; + } else { + m_bHasDesiredLookDest = false; + m_iNextLookTime = level.inttime + 187; + } + } + + if (m_bHasDesiredLookDest) { + SetDesiredLookDir(m_vDesiredLookDest - EyePosition()); + } else { + ForwardLook(); + } } /* =============== -Actor::SoundSayAnim - -Returns true if animation not found. +Actor::EventGetLookAroundAngle =============== */ -bool Actor::SoundSayAnim - ( - const_str name, - byte bLevelSayAnim - ) +void Actor::EventGetLookAroundAngle(Event *ev) { - int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str()); - if (animnum == -1) - { - ChangeSayAnim(); - m_bSayAnimSet = true; - m_iSaySlot = -2; - m_bLevelSayAnim = bLevelSayAnim; + // Fixed in OPM + // Seems like a mistake in 2.40 and below, it should return a float instead + //ev->GetFloat(m_fLookAroundFov); - Com_Printf( - "Couldn't find animation '%s' in '%s' - trying sound alias instead.\n", - Director.GetString(name).c_str(), - edict->tiki->a->name); - - Sound(Director.GetString(name), 0, 0, 0, NULL, 0, 1, 1, -1); - - return true; - } - return false; -} - -static bool UnknownAnim(const char *name, dtiki_t *tiki) -{ - ScriptException::next_bIsForAnim = true; - ScriptError("unknown animation '%s' in '%s'", name, tiki->a->name); + ev->AddFloat(m_fLookAroundFov); } /* =============== -Actor::EventSetAnim - -Set animation event. +Actor::EventSetLookAroundAngle =============== */ -void Actor::EventSetAnim - ( - Event *ev - ) +void Actor::EventSetLookAroundAngle(Event *ev) { - //"anim slot weight flagged" - int numArgs = ev->NumArgs(), slot = 0, animnum; - float weight = 1; - const_str anim, flagVal; - qboolean flagged = qfalse; + float fLookAroundFov; - //FIXME: better notation, but this works for now. - if (numArgs < 1 || numArgs > 4) - { - ScriptError("bad number of arguments"); - } - else if (numArgs == 1) - { - anim = ev->GetConstString(1); - animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } - } - else if (numArgs == 2) - { - anim = ev->GetConstString(1); - animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } - slot = ev->GetInteger(2); - if (slot > 2) - { - ScriptError("Bad animation slot, only 0 and 1 supported"); - } - } - else if (numArgs == 3) - { - weight = ev->GetFloat(3); - if (weight < 0) - { - ScriptError("Negative anim weight not allowed"); - } - if (weight != 0) - { - slot = ev->GetInteger(2); - if (slot > 2) - { - ScriptError("Bad animation slot, only 0 and 1 supported"); - } - } + fLookAroundFov = ev->GetFloat(1); + if (fLookAroundFov < 0.0 || fLookAroundFov > 60.0) { + ScriptError("lookaroundangle must be >= 0 and <= 60"); + } - anim = ev->GetConstString(1); - animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } - } - else if (numArgs == 4) - { - flagVal = ev->GetConstString(4); - flagged = qtrue; - if (flagVal != STRING_FLAGGED) - { - ScriptError("unknown keyword '%s', expected 'flagged'", Director.GetString(flagVal).c_str()); - } - weight = ev->GetFloat(3); - if (weight < 0) - { - ScriptError("Negative anim weight not allowed"); - } - if (weight != 0) - { - slot = ev->GetInteger(2); - if (slot > 2) - { - ScriptError("Bad animation slot, only 0 and 1 supported"); - } - } - - anim = ev->GetConstString(1); - animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } - } - - if (!slot) - { - flagged = qtrue; - } - if (flagged) - { - parm.motionfail = qtrue; - } - if (!m_bLevelMotionAnim) - { - if (slot) - { - m_weightType[GetMotionSlot(slot)] = 0; - } - else - { - ChangeMotionAnim(); - m_bMotionAnimSet = true; - } - StartMotionAnimSlot(slot, animnum, weight); - if (flagged) - { - m_iMotionSlot = GetMotionSlot(slot); - parm.motionfail = qfalse; - } - } + m_fLookAroundFov = fLookAroundFov; } /* =============== -Actor::EventIdleSayAnim - -Play idle say dialogue. +Actor::DumpAnimInfo =============== */ -void Actor::EventIdleSayAnim - ( - Event *ev - ) +void Actor::DumpAnimInfo(void) { - const_str name; - if (ev->NumArgs()) - { - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } + vec3_t LocalLookAngles; + Vector actualHeadAngle, actualTorsoAngle; - name = ev->GetConstString(1); + Animate::DumpAnimInfo(); - if (m_ThinkState <= THINKSTATE_ATTACK || IsGrenadeState(m_ThinkState)) - { - m_csSayAnim = name; - //FIXME: macro - m_bNextLevelSayAnim = 1; - } - else - { - if (!SoundSayAnim(name, 1) ) - { - m_csSayAnim = name; - //FIXME: macro - m_bNextLevelSayAnim = 1; - } + if (m_bHasDesiredLookAngles) { + VectorCopy(m_DesiredLookAngles, LocalLookAngles); + } else { + VectorClear(LocalLookAngles); + } - } - } - else if (m_bLevelSayAnim == 1) - { - AnimFinished(m_iSaySlot, true); - } + actualHeadAngle = GetControllerAngles(HEAD_TAG); + actualTorsoAngle = GetControllerAngles(TORSO_TAG); + + MPrintf( + "Desired look yaw: %.1f, pitch: %.1f. Head yaw: %.1f, pitch %.1f. Torso yaw: %.1f, pitch: %.1f\n", + LocalLookAngles[1], + LocalLookAngles[0], + actualHeadAngle[1], + actualHeadAngle[0], + actualTorsoAngle[1], + actualTorsoAngle[0] + ); } /* =============== -Actor::EventSayAnim +Actor::DumpCallTrace -Play idle dialogue. +Dump useful debug info. =============== */ -void Actor::EventSayAnim - ( - Event *ev - ) +const char *Actor::DumpCallTrace(const char *pszFmt, ...) const { - const_str name; - if (ev->NumArgs()) - { - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } + char szTemp[65536]; + int i; + int i1, i2; + char szFile[MAX_QPATH]; + Vector vPlayer; + time_t t; + tm *ptm; + cvar_t *sv_mapname; - name = ev->GetConstString(1); + va_list args; - if (m_ThinkState <= THINKSTATE_KILLED || !SoundSayAnim(name, 2)) - { - m_csSayAnim = name; - //FIXME: macro - m_bNextLevelSayAnim = 2; - gi.DPrintf("Actor::EventSayAnim: 1 %s\n", targetname.c_str()); - } - gi.DPrintf("Actor::EventSayAnim: 2 %s\n", targetname.c_str()); - } - else if (m_bLevelSayAnim == 1) - { - AnimFinished(m_iSaySlot, true); - gi.DPrintf("Actor::EventSayAnim: 3 %s\n", targetname.c_str()); - } - gi.DPrintf("Actor::EventSayAnim: 4 %s\n", targetname.c_str()); + va_start(args, pszFmt); + + sv_mapname = gi.Cvar_Get("mapname", "unknown", 0); + + Player *p = (Player *)G_GetEntity(0); + if (p) { + vPlayer = p->origin; + } + + i1 = Com_sprintf( + szTemp, + sizeof(szTemp), + "map = %s\n" + "time = %i (%i:%02i)\n" + "entnum = %i, targetname = '%s'\n" + "origin = (%g %g %g)\n" + "think = %s, thinkstate = %s\n" + "type_idle = %s\n" + "type_attack = %s\n" + "m_State = %i, m_pszDebugState = %s\n" + "player is at (%g %g %g)\n" + "--------------------------------------\n", + sv_mapname->string, + level.inttime, + level.inttime / 60000, + level.inttime / 1000 - 60 * (level.inttime / 60000), + entnum, + targetname.c_str(), + origin[0], + origin[1], + origin[2], + ThinkName().c_str(), + ThinkStateName().c_str(), + Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_IDLE]]).c_str(), + Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]).c_str(), + m_State, + m_pszDebugState, + vPlayer[0], + vPlayer[1], + vPlayer[2] + ); + + i2 = i1; + if (pszFmt) { + va_list args2; + va_copy(args2, args); + i2 = i1 + Q_vsnprintf(szTemp + i1, sizeof(szTemp) - i1, pszFmt, args); + } + + va_end(args); + + if (i1 != i2) { + strcpy(&szTemp[i2], "\n--------------------------------------\n"); + } + + t = time(0); + ptm = localtime(&t); + Com_sprintf( + szFile, + sizeof(szFile), + "main\\ai_trace_%s_%i_%i_%02i%02i.log", + sv_mapname->string, + ptm->tm_mon + 1, + ptm->tm_mday, + ptm->tm_hour, + ptm->tm_min + ); + + for (i = 5; szFile[i]; i++) { + if (szFile[i] == '\\' || szFile[i] == '/') { + szFile[i] = '_'; + } + } + + fprintf(stderr, "IMPORTANT: Include '%s' in your bug report!\n", szFile); + + return va( + "\n" + "\t-------------------------- IMPORTANT REMINDER --------------------------\n" + "\n" + "\tinclude '%s' in your bug report! \n" + "\n" + "\t----------------------- END IMPORTANT REMINDER -----------------------\n" + "\n" + "%s", + szFile, + &szTemp[i1] + ); } /* =============== -Actor::EventSetSayAnim - -Set say animation. +Actor::EventSetMoveDoneRadius =============== */ -void Actor::EventSetSayAnim - ( - Event *ev - ) +void Actor::EventSetMoveDoneRadius(Event *ev) { - const_str name; - str sName; - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } - - if (m_bLevelSayAnim == 0) - { - name = ev->GetConstString(1); - - parm.sayfail = qtrue; - sName = Director.GetString(name); - int animnum = gi.Anim_NumForName(edict->tiki, sName.c_str()); - - Com_Printf("EventSetSayAnim sName: %s, animnum: %d, mVoiceType: %d\n", sName.c_str(), animnum, mVoiceType); - if (!SoundSayAnim(name, m_bLevelSayAnim)) - { - int flags = gi.Anim_FlagsSkel(edict->tiki, animnum); - if (flags & TAF_HASUPPER) - { - if (m_bLevelActionAnim) - { - if (!m_bSayAnimSet) - { - m_iSaySlot = m_iActionSlot; - } - return; - } - if (flags & TAF_HASDELTA) - { - if (m_bLevelMotionAnim) - { - if (!m_bSayAnimSet) - { - m_iSaySlot = m_iMotionSlot; - } - return; - } - ChangeActionAnim(); - ChangeMotionAnim(); - StartMotionAnimSlot(0, animnum, 1.0); - - m_iMotionSlot = m_iActionSlot = GetMotionSlot(0); - } - else - { - ChangeActionAnim(); - m_bActionAnimSet = true; - StartActionAnimSlot(animnum); - m_iActionSlot = GetActionSlot(0); - } - ChangeSayAnim(); - m_bSayAnimSet = true; - m_iSaySlot = m_iActionSlot; - } - else - { - ChangeSayAnim(); - m_bSayAnimSet = true; - StartSayAnimSlot(animnum); - m_iSaySlot = GetSaySlot(); - - } - - } - parm.sayfail = qfalse; - } + float radius = ev->GetFloat(1); + m_fMoveDoneRadiusSquared = Square(radius); } /* =============== -Actor::EventSetMotionAnim - -Set motion animation. +Actor::EventGetMoveDoneRadius =============== */ -void Actor::EventSetMotionAnim - ( - Event *ev - ) +void Actor::EventGetMoveDoneRadius(Event *ev) { - gi.DPrintf("Actor::EventSetMotionAnim\n"); - - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } - const_str anim = ev->GetConstString(1); - str animstr = Director.GetString(anim); - int animnum = gi.Anim_NumForName(edict->tiki, animstr.c_str()); - if (animnum == -1) - { - UnknownAnim(animstr.c_str(), edict->tiki); - } - - gi.DPrintf("Actor::EventSetMotionAnim %s %d\n", animstr.c_str(), animnum); - parm.motionfail = qtrue; - - if (!m_bLevelMotionAnim) - { - ChangeMotionAnim(); - m_bMotionAnimSet = true; - StartMotionAnimSlot(0, animnum, 1.0); - m_iMotionSlot = GetMotionSlot(0); - parm.motionfail = qfalse; - } + ev->AddFloat(sqrtf(m_fMoveDoneRadiusSquared)); } /* =============== -Actor::EventSetAimMotionAnim +Actor::StoppedWaitFor -Set aim motion animation. +Called when stopped wait for an actor. =============== */ -void Actor::EventSetAimMotionAnim - ( - Event *ev - ) +void Actor::StoppedWaitFor(const_str name, bool bDeleting) { - int anim_crouch, anim_stand, anim_high; - const_str name; - if (ev->NumArgs() != 3) - { - ScriptError("bad number of arguments"); - } + g_iInThinks++; - //FIXME: maybe inline func ? + GlobalFuncs_t *func = &GlobalFuncs[CurrentThink()]; - name = ev->GetConstString(1); - anim_crouch = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str()); - if (anim_crouch == -1) - { - UnknownAnim(Director.GetString(name).c_str(), edict->tiki); - } - - name = ev->GetConstString(2); - anim_stand = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str()); - if (anim_stand == -1) - { - UnknownAnim(Director.GetString(name).c_str(), edict->tiki); - } - - name = ev->GetConstString(3); - anim_high = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str()); - if (anim_high == -1) - { - UnknownAnim(Director.GetString(name).c_str(), edict->tiki); - } - - - parm.motionfail = qtrue; - - if (!m_bLevelMotionAnim) - { - ChangeMotionAnim(); - m_bMotionAnimSet = true; - UpdateAimMotion(); - StartAimMotionAnimSlot(0, anim_crouch); - StartAimMotionAnimSlot(1, anim_stand); - StartAimMotionAnimSlot(2, anim_high); - m_iMotionSlot = GetMotionSlot(1); - parm.motionfail = qfalse; - } + if (func->FinishedAnimation) { + (this->*func->FinishedAnimation)(); + } + g_iInThinks--; } /* =============== -Actor::EventSetActionAnim - -Set action animation. +Actor::EventHasCompleteLookahead =============== */ -void Actor::EventSetActionAnim - ( - Event *ev - ) +void Actor::EventHasCompleteLookahead(Event *ev) { - if (ev->NumArgs() != 3) - { - ScriptError("bad number of arguments"); - } - - m_fAimLimit_down = ev->GetFloat(2); - if (m_fAimLimit_down > 0) - { - m_fAimLimit_down = -0.001f; - ScriptError("Positive lower_limit not allowed"); - } - - m_fAimLimit_up = ev->GetFloat(3); - if (m_fAimLimit_up <= 0) - { - m_fAimLimit_up = 0.001f; - ScriptError("Negative upper_limit not allowed"); - } - - const_str anim = ev->GetConstString(1); - int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } - - const_str anim2 = ev->GetConstString(2); - int animnum2 = gi.Anim_NumForName(edict->tiki, Director.GetString(anim2)); - if (animnum2 == -1) - { - UnknownAnim(Director.GetString(anim2).c_str(), edict->tiki); - } - - const_str anim3 = ev->GetConstString(3); - int animnum3 = gi.Anim_NumForName(edict->tiki, Director.GetString(anim3)); - if (animnum3 == -1) - { - UnknownAnim(Director.GetString(anim3).c_str(), edict->tiki); - } - - parm.upperfail = qtrue; - if (!m_bLevelActionAnim) - { - ChangeActionAnim(); - m_bAimAnimSet = true; - m_bActionAnimSet = true; - UpdateAim(); - - StartAimAnimSlot(0, animnum); - StartAimAnimSlot(1, anim2); - StartAimAnimSlot(2, anim3); - m_iActionSlot = GetActionSlot(0); - parm.upperfail = qfalse; - } + ev->AddInteger(PathExists() && PathHasCompleteLookahead()); } /* =============== -Actor::EventUpperAnim - -Set upper body. +Actor::EventPathDist =============== */ -void Actor::EventUpperAnim - ( - Event *ev - ) +void Actor::EventPathDist(Event *ev) { - if (ev->NumArgs()) - { - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } - const_str anim = ev->GetConstString(1); - int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } + if (!PathExists() || PathComplete()) { + ev->AddFloat(0); + return; + } - m_csUpperAnim = anim; - } - else if (m_bLevelActionAnim) - { - AnimFinished(m_iActionSlot, true); - } + ev->AddFloat(PathDist()); } /* =============== -Actor::EventSetUpperAnim - -Set upper body animation. +Actor::EventCanShootEnemyFrom =============== */ -void Actor::EventSetUpperAnim - ( - Event *ev - ) +void Actor::EventCanShootEnemyFrom(Event *ev) { - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } + if (!m_Enemy) { + ev->AddInteger(false); + return; + } - const_str anim = ev->GetConstString(1); - int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str()); - if (animnum == -1) - { - UnknownAnim(Director.GetString(anim).c_str(), edict->tiki); - } - - parm.upperfail = qtrue; - if (!m_bLevelActionAnim) - { - ChangeActionAnim(); - m_bActionAnimSet = true; - StartActionAnimSlot(animnum); - m_iActionSlot = SimpleActor::GetActionSlot(0); - parm.upperfail = qfalse; - } + ev->AddInteger(CanSeeFrom(ev->GetVector(1), m_Enemy)); } /* =============== -Actor::EventSetUpperAnim - -End action animation. +Actor::EventSetInReload =============== */ -void Actor::EventEndActionAnim - ( - Event *ev - ) +void Actor::EventSetInReload(Event *ev) { - parm.upperfail = qtrue; - if (!m_bLevelActionAnim) - { - ChangeActionAnim(); - parm.upperfail = qfalse; - } + m_bInReload = ev->GetBoolean(1); } /* =============== -Actor::EventDamagePuff - -Spawns a puff of 'blood' smoke at the speficied location in the specified direction. +Actor::EventGetInReload =============== */ -void Actor::EventDamagePuff - ( - Event *ev - ) +void Actor::EventGetInReload(Event *ev) { - - Vector pos = ev->GetVector(1), dir = ev->GetVector(2); - gi.SetBroadcastVisible(pos, NULL); - //FIXME: macro - gi.MSG_StartCGM(7); - gi.MSG_WriteCoord(pos.x); - gi.MSG_WriteCoord(pos.y); - gi.MSG_WriteCoord(pos.z); - - gi.MSG_WriteDir(dir); - gi.MSG_WriteBits(0, 1); - gi.MSG_EndCGM(); + ev->AddInteger(m_bInReload); } /* =============== -Actor::SafeSetOrigin - -Safe set origin. +Actor::EventSetReloadCover =============== */ -void Actor::SafeSetOrigin - ( - vec3_t newOrigin - ) +void Actor::EventSetReloadCover(Event *ev) { - if (newOrigin == origin) - { - return; - } - - setOrigin(newOrigin); - - if (!m_bNoPlayerCollision) - { - Player *p = (Player *)G_GetEntity(0); - if (p && IsTouching(p)) - { - Com_Printf("(entnum %d, radnum %d) is going not solid to not get stuck in the player\n", entnum, radnum); - m_bNoPlayerCollision = true; - setSolidType(SOLID_NOT); - } - } + m_bNeedReload = ev->GetBoolean(1); } /* =============== -Actor::DoMove - -Move the actor based on m_eAnimMode. +Actor::EventBreakSpecial =============== */ -void Actor::DoMove - ( - void - ) +void Actor::EventBreakSpecial(Event *ev) { - mmove_t mm; - //FIXME: macros - if (m_bDoPhysics - && m_iOriginTime != level.inttime - && !m_pGlueMaster - && !bindmaster) - { - switch (m_eAnimMode) - { - case 1://normal i guess ? - { - SetMoveInfo(&mm); - - VectorCopy2D(frame_delta, mm.desired_dir); - float frameDeltaLen = VectorNormalize2D(mm.desired_dir); - - mm.desired_speed = frameDeltaLen / level.frametime; - - if (mm.desired_speed > m_maxspeed) - mm.desired_speed = m_maxspeed; - - MmoveSingle(&mm); - GetMoveInfo(&mm); - - } - break; - case 2://path - { - MovePath(frame_delta.length() / level.frametime); - } - break; - case 3://path_goal (end) ? - { - MovePathGoal(frame_delta.length() / level.frametime); - } - break; - case 4://dest - { - MoveDest(frame_delta.length() / level.frametime); - } - break; - case 5://scripted - { - trace_t trace; - trace = G_Trace(origin, mins, maxs, frame_delta + origin, this, edict->clipmask & 0xF9FFE47D, qtrue, "Actor"); - SafeSetOrigin(trace.endpos); - velocity = frame_delta / level.frametime; - } - break; - case 6://noclip - { - SafeSetOrigin(frame_delta+origin); - velocity = frame_delta / level.frametime; - } - break; - case 7://falling path - { - SafeSetOrigin(m_pFallPath->pos[m_pFallPath->currentPos]); - m_pFallPath->currentPos++; - velocity = vec_zero; - } - break; - default: - break; - } - m_maxspeed = 1000000.0f; - } + mbBreakSpecialAttack = true; } /* =============== -Actor::AnimFinished - +Actor::EventCanShoot =============== */ -void Actor::AnimFinished - ( - int slot, - bool stop - ) +void Actor::EventCanShoot(Event *ev) { - if (stop && slot >= 0) - animFlags[slot] |= ANIM_NOACTION; - if (slot == m_iMotionSlot) - { - if (stop) - { - m_bLevelMotionAnim = false; - m_iMotionSlot = -1; - } - MPrintf("flagged anim finished slot %d\n", slot); - Unregister(STRING_FLAGGEDANIMDONE); - } - if (slot == m_iActionSlot) - { - if (stop) - ChangeActionAnim(); - if (m_csUpperAnim == STRING_EMPTY) - { - MPrintf("upper anim finished slot %d\n", slot); - Unregister(STRING_UPPERANIMDONE); - } - } - if (slot == m_iSaySlot) - { - if (stop) - ChangeSayAnim(); - if (m_csSayAnim == STRING_EMPTY) - { - MPrintf("say anim finished slot %d\n", slot); - //gi.DPrintf("unregister STRING_SAYDONE\n"); - Unregister(STRING_SAYDONE); - } - } - else if (slot == GetSaySlot() && stop) - { - ChangeSayAnim(); - } + Entity *ent; + + ent = ev->GetEntity(1); + + if (!ent) { + ScriptError("canshoot applied to NULL listener"); + } + + ev->AddInteger(CanShoot(ent)); } /* =============== -Actor::AnimFinished - +Actor::EventSetBalconyHeight =============== */ -void Actor::AnimFinished - ( - int slot - ) +void Actor::EventSetBalconyHeight(Event *ev) { - animFlags[slot] &= ~ANIM_FINISHED; - AnimFinished(slot, ((animFlags[slot] & ANIM_LOOP) != ANIM_LOOP)); + m_fBalconyHeight = ev->GetFloat(1); } /* =============== -Actor::PlayAnimation - -Play animation +Actor::EventSetIgnoreBadPlace =============== */ -void Actor::PlayAnimation - ( - Event *ev - ) +void Actor::EventSetIgnoreBadPlace(Event *ev) { - Event e1(EV_Listener_ExecuteScript); - e1.AddConstString(STRING_GLOBAL_ANIM_SCR); - e1.AddValue(ev->GetValue(1)); - ExecuteScript(&e1); + if (m_bIgnoreBadPlace == ev->GetBoolean(1)) { + return; + } + + m_bIgnoreBadPlace = ev->GetBoolean(1); + + if (level.m_badPlaces.NumObjects() && m_bIgnoreBadPlace) { + UpdateBadPlaces(); + } } /* =============== -Actor::PlayScriptedAnimation - -Play scripted animation +Actor::EventGetIgnoreBadPlace =============== */ -void Actor::PlayScriptedAnimation - ( - Event *ev - ) +void Actor::EventGetIgnoreBadPlace(Event *ev) { - Event e1(EV_Listener_ExecuteScript); - e1.AddConstString(STRING_GLOBAL_ANIM_SCRIPTED_SCR); - e1.AddValue(ev->GetValue(1)); - ExecuteScript(&e1); + ev->AddInteger(m_bIgnoreBadPlace); } /* =============== -Actor::PlayNoclipAnimation - -Play noclip animation +Actor::EventGetBalconyHeight =============== */ -void Actor::PlayNoclipAnimation - ( - Event *ev - ) +void Actor::EventGetBalconyHeight(Event *ev) { - Event e1(EV_Listener_ExecuteScript); - e1.AddConstString(STRING_GLOBAL_ANIM_NOCLIP_SCR); - e1.AddValue(ev->GetValue(1)); - ExecuteScript(&e1); + ev->AddFloat(m_fBalconyHeight); } /* =============== -Actor::MoveDest - -Play noclip animation +Actor::BecomeTurretGuy =============== */ -void Actor::MoveDest - ( - float fMoveSpeed - ) +void Actor::BecomeTurretGuy(void) { - mmove_t mm; - vec2_t offset; + SetThinkIdle(THINK_IDLE); - SetMoveInfo(&mm); + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE); + SetThink(THINKSTATE_GRENADE, THINK_GRENADE); - if (fMoveSpeed > m_maxspeed) - fMoveSpeed = m_maxspeed; - - mm.desired_speed = fMoveSpeed; - - VectorSub2D(m_Dest, origin, offset); - - VectorNormalize2D2(offset, mm.desired_dir); - - MmoveSingle(&mm); - - GetMoveInfo(&mm); -} - -/* -=============== -Actor::MovePath - -Move on path. -=============== -*/ -void Actor::MovePath - ( - float fMoveSpeed - ) -{ - //FIXME: macros - mmove_t mm; - - - - SetMoveInfo(&mm); - - mm.desired_speed = fMoveSpeed; - if (mm.desired_speed > m_maxspeed) - { - mm.desired_speed = m_maxspeed; - } - - m_Path.UpdatePos(origin); - - if (ai_debugpath->integer) - { - - Vector pos, dest; - pos = origin; - pos.z += 32; - dest = m_Path.CurrentDelta(); - dest += origin; - dest.z += 32; - G_DebugLine(pos, dest, 1, 0, 0, 1); - for (PathInfo *current_path = m_Path.CurrentNode(); current_path != m_Path.LastNode(); current_path = m_Path.NextNode()) - { - pos = current_path->point; - pos.z += 32; - - dest = m_Path.NextNode()->point; - dest.z += 32; - G_DebugLine(pos, dest, 0, 1, 0, 1); - } - } - - VectorCopy2D(m_Path.CurrentDelta(), mm.desired_dir); - - MmoveSingle(&mm); - if (!mm.hit_obstacle) - { - if (m_WallDir) - { - if (level.inttime >= m_iWallDodgeTimeout) - { - m_WallDir = 0; - } - else - { - if (DotProduct2D(mm.desired_dir, m_PrevObstacleNormal) > 0 && CrossProduct2D(mm.desired_dir, m_PrevObstacleNormal) < 0) - { - m_iWallDodgeTimeout = level.inttime + 1000; - m_WallDir = -m_WallDir; - } - } - } - GetMoveInfo(&mm); - return; - } - - velocity.copyTo(mm.velocity); - origin.copyTo(mm.origin); - mm.groundPlane = m_groundPlane; - mm.walking = m_walking; - m_groundPlaneNormal.copyTo(mm.groundPlaneNormal); - VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal); - - m_Path.UpdatePos(mm.hit_origin); - if (!m_Path.NextNode()) - { - if (!m_WallDir) - { - auto dir = m_Path.CurrentDelta(); - if (m_Path.NextNode()) - { - dir = m_Path.NextNode()->dir; - } - - if (dir[1] * mm.obstacle_normal[0] < dir[0] * mm.obstacle_normal[1]) - { - mm.desired_dir[0] = mm.obstacle_normal[0]; - mm.desired_dir[1] = -mm.obstacle_normal[1]; - m_WallDir = 1; - } - else - { - mm.desired_dir[0] = -mm.obstacle_normal[0]; - mm.desired_dir[1] = mm.obstacle_normal[1]; - m_WallDir = -1; - } - MmoveSingle(&mm); - if (!mm.hit_obstacle) - { - m_iWallDodgeTimeout = level.inttime + 1000; - } - else - { - m_WallDir = 0; - m_iWallDodgeTimeout = 0; - } - GetMoveInfo(&mm); - return; - } - } - - if (! (m_Path.NextNode() && m_Path.NextNode()->bAccurate && m_Path.IsSide()) ) - { - if (m_WallDir) - { - if (m_WallDir < 0) - { - mm.desired_dir[0] = -mm.obstacle_normal[1]; - mm.desired_dir[1] = mm.obstacle_normal[0]; - } - else - { - mm.desired_dir[0] = mm.obstacle_normal[1]; - mm.desired_dir[1] = -mm.obstacle_normal[0]; - } - MmoveSingle(&mm); - if (mm.hit_obstacle) - { - m_WallDir = 0; - m_iWallDodgeTimeout = 0; - } - GetMoveInfo(&mm); - return; - } - else - { - - auto dir = m_Path.CurrentDelta(); - auto pNextNode = m_Path.NextNode(); - - if (pNextNode) - { - dir = pNextNode->dir; - } - - vec2_t vDelta; - vDelta[0] = pNextNode->point[1] - mm.hit_origin[0]; - vDelta[1] = pNextNode->point[0] - mm.hit_origin[1]; - - if (DotProduct2D(dir, vDelta) >= 0) - { - float fCross = CrossProduct2D(dir, vDelta); - if (fCross <= -16) - { - mm.desired_dir[1] = mm.obstacle_normal[0]; - mm.desired_dir[0] = -mm.obstacle_normal[1]; - } - else - { - if (fCross >= 16) - { - - mm.desired_dir[0] = mm.obstacle_normal[1]; - mm.desired_dir[1] = -mm.obstacle_normal[0]; - MmoveSingle(&mm); - GetMoveInfo(&mm); - return; - } - } - } - { - if (!m_WallDir) - { - auto dir = m_Path.CurrentDelta(); - if (m_Path.NextNode()) - { - dir = m_Path.NextNode()->dir; - } - - if (dir[1] * mm.obstacle_normal[0] < dir[0] * mm.obstacle_normal[1]) - { - mm.desired_dir[0] = mm.obstacle_normal[1]; - mm.desired_dir[1] = -mm.obstacle_normal[0]; - m_WallDir = 1; - } - else - { - mm.desired_dir[0] = -mm.obstacle_normal[1]; - mm.desired_dir[1] = mm.obstacle_normal[0]; - m_WallDir = -1; - } - MmoveSingle(&mm); - if (!mm.hit_obstacle) - { - m_iWallDodgeTimeout = level.inttime + 1000; - } - else - { - m_WallDir = 0; - m_iWallDodgeTimeout = 0; - } - GetMoveInfo(&mm); - return; - } - else if (m_WallDir < 0) - { - mm.desired_dir[0] = -mm.obstacle_normal[1]; - mm.desired_dir[1] = mm.obstacle_normal[0]; - } - else - { - mm.desired_dir[0] = mm.obstacle_normal[1]; - mm.desired_dir[1] = -mm.obstacle_normal[0]; - } - MmoveSingle(&mm); - if (mm.hit_obstacle) - { - m_WallDir = 0; - m_iWallDodgeTimeout = 0; - } - GetMoveInfo(&mm); - return; - } - } - } - - m_iWallDodgeTimeout = level.inttime + 1000; - - { - auto dir = m_Path.CurrentDelta(); - auto pNextNode = m_Path.NextNode(); - - if (pNextNode) - { - dir = pNextNode->dir; - } - - vec2_t vDelta; - vDelta[0] = pNextNode->point[1] - mm.hit_origin[0]; - vDelta[1] = pNextNode->point[0] - mm.hit_origin[1]; - - if (vDelta[0] * dir[1] <= vDelta[1] * dir[0]) - { - mm.desired_dir[0] = mm.obstacle_normal[1]; - mm.desired_dir[1] = -mm.obstacle_normal[0]; - m_WallDir = 1; - } - else - { - mm.desired_dir[0] = -mm.obstacle_normal[1]; - mm.desired_dir[1] = mm.obstacle_normal[0]; - m_WallDir = -1; - } - MmoveSingle(&mm); - if (mm.hit_obstacle) - { - VectorCopy(velocity, mm.velocity); - VectorCopy(origin, mm.origin); - mm.groundPlane = m_groundPlane; - mm.walking = m_walking; - VectorCopy(m_groundPlaneNormal, mm.groundPlaneNormal); - - VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal); - - if (m_WallDir == char(-1)) - { - mm.desired_dir[0] = -mm.obstacle_normal[1]; - mm.desired_dir[1] = mm.obstacle_normal[0]; - } - else - { - mm.desired_dir[0] = mm.obstacle_normal[1]; - mm.desired_dir[1] = -mm.obstacle_normal[0]; - } - MmoveSingle(&mm); - } - } - GetMoveInfo(&mm); -} - -/* -=============== -Actor::MovePathGoal - -Move on path end(goal). -=============== -*/ -void Actor::MovePathGoal - ( - float fMoveSpeed - ) -{ - float fTimeToGo, fDeltaSquareLen, fSlowdownSpeed; - vec2_t vDelta; - - if (!m_Path.HasCompleteLookahead()) - { - MovePath(fMoveSpeed); - m_fPathGoalTime = 0; - return; - } - fTimeToGo = m_fPathGoalTime - level.time; - - - VectorSub2D(origin, m_Path.LastNode()->point, vDelta); - - fDeltaSquareLen = VectorLength2DSquared(vDelta); - if (fTimeToGo <= -0.001) - { - if (fDeltaSquareLen < (Square(fMoveSpeed * Square(0.5)))) - { - fTimeToGo = 0.5; - m_fPathGoalTime = level.time + fTimeToGo; - if (m_csPathGoalEndAnimScript == STRING_EMPTY) - { - m_csPathGoalEndAnimScript = STRING_ANIM_IDLE_SCR; - } - m_bStartPathGoalEndAnim = true; - } - else - { - MovePath(fMoveSpeed); - m_fPathGoalTime = 0; - return; - } - } - - fSlowdownSpeed = sqrt(fDeltaSquareLen) * (2 / (fTimeToGo + level.frametime)); - if (fSlowdownSpeed > fMoveSpeed + 0.001 && fSlowdownSpeed > 0.4 * sv_runspeed->value) - { - m_fPathGoalTime = 0; - StartAnimation(3, m_Anim); - MovePath(fMoveSpeed); - } - else - { - MovePath(fSlowdownSpeed); - if (level.time >= m_fPathGoalTime) - { - m_eAnimMode = 1; - Com_Printf("m_eAnimMode MovePathGoal \n"); - } - } -} - -/* -=============== -Actor::Dumb - -Make actor dumb. -=============== -*/ -void Actor::Dumb - ( - Event *ev - ) -{ - Event e1(EV_Listener_ExecuteScript); - e1.AddConstString(STRING_GLOBAL_DISABLE_AI_SCR); - ExecuteScript(&e1); -} - -/* -=============== -Actor::PhysicsOn - -Enable physics. -=============== -*/ -void Actor::PhysicsOn - ( - Event *ev - ) -{ - m_bDoPhysics = true; -} - -/* -=============== -Actor::PhysicsOn - -Disable PhysicsOff. -=============== -*/ -void Actor::PhysicsOff - ( - Event *ev - ) -{ - m_bDoPhysics = false; -} - -/* -=============== -Actor::EventStart - -Initialize actor. -=============== -*/ -void Actor::EventStart - ( - Event *ev - ) -{ - ResolveVoiceType(); - setSize(MINS, MAXS);//notsure - - droptofloor(16384); - - SetControllerTag( HEAD_TAG, gi.Tag_NumForName( edict->tiki, "Bip01 Head" ) ); - SetControllerTag( TORSO_TAG, gi.Tag_NumForName( edict->tiki, "Bip01" ) ); - SetControllerTag( ARMS_TAG, gi.Tag_NumForName( edict->tiki, "Bip01 L UpperArm" ) ); - - JoinNearbySquads(); - - if (level.Spawned()) - { - Unregister(STRING_SPAWN); - } -} - -/* -=============== -Actor::EventGetMood - -Get current mood. -=============== -*/ -void Actor::EventGetMood - ( - Event *ev - ) -{ - ev->AddConstString(m_csMood); -} - -/* -=============== -Actor::EventSetMood - -Set current mood. -=============== -*/ -void Actor::EventSetMood - ( - Event *ev - ) -{ - m_csMood = ev->GetConstString(1); - if (m_csMood > STRING_ALERT) - { - m_csMood = STRING_BORED; - ScriptError("invalid mood - setting to bored"); - } -} - -/* -=============== -Actor::EventGetAngleYawSpeed - -Get current AngleYawSpeed. -=============== -*/ -void Actor::EventGetAngleYawSpeed - ( - Event *ev - ) -{ - ev->AddFloat(m_fAngleYawSpeed); -} - -/* -=============== -Actor::EventSetAngleYawSpeed - -Set current AngleYawSpeed. -=============== -*/ -void Actor::EventSetAngleYawSpeed - ( - Event *ev - ) -{ - float speed = ev->GetFloat(1); - if (speed <= 0) - { - ScriptError("Attempting to set illegal turnspeed %f", speed); - } - m_fAngleYawSpeed = speed; -} - -/* -=============== -Actor::EventSetAimTarget - -Set current weapon's aim tagret. -=============== -*/ -void Actor::EventSetAimTarget - ( - Event *ev - ) -{ - Weapon *weap = GetActiveWeapon(WEAPON_MAIN); - weap->SetAimTarget(ev->GetEntity(1)); -} - -/* -=============== -Actor::UpdateAngles - -Update current angles. -=============== -*/ -void Actor::UpdateAngles - ( - void - ) -{ - float max_change, error, dist; - - if (!m_YawAchieved) - { - - error = m_DesiredYaw - angles[1]; - if (error <= 180) - { - if (error < -180.0) - error += 360; - } - else - { - error -= 360; - } - - dist = m_fAngleYawSpeed * level.frametime; - if (-dist <= error) - { - max_change = dist; - if (error <= dist) - { - max_change = error; - StopTurning(); - } - } - else - { - max_change = -dist; - } - setAngles(Vector{0, angles[1] + max_change, 0}); - } -} - -/* -=============== -Actor::SetLeashHome - -Set leash home. -=============== -*/ -void Actor::SetLeashHome -( - Vector vHome -) -{ - if (!m_bFixedLeash) - { - m_vHome = vHome; - } -} - -/* -=============== -Actor::AimAtTargetPos - -Aim at mTargetPos. -=============== -*/ -void Actor::AimAtTargetPos - ( - void - ) -{ - Vector vDir = mTargetPos - EyePosition() + Vector(0, 0, 16); - SetDesiredLookDir(vDir); - m_DesiredGunDir[0] = 360.0f - vDir.toPitch(); - m_DesiredGunDir[1] = vDir.toYaw(); - m_DesiredGunDir[2] = 0; - - SetDesiredYawDir(vDir); -} - -/* -=============== -Actor::AimAtAimNode - -Aim at m_aimNode. -=============== -*/ -void Actor::AimAtAimNode - ( - void - ) -{ - mTargetPos = m_aimNode->origin; - - AimAtTargetPos(); + if (CurrentThink() == THINK_TURRET && Turret_DecideToSelectState()) { + TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + } } /* @@ -9847,4963 +12574,219 @@ Aiming at enemy behaviour. Usally called after SetEnemyPos() =============== */ -void Actor::AimAtEnemyBehavior - ( - void - ) +void Actor::AimAtEnemyBehavior(void) { - AimAtTargetPos(); - - Anim_Aim(); + AimAtTargetPos(); + Anim_Aim(); } /* =============== -Actor::FaceMotion - +Actor::EventEnableEnemySwitch =============== */ -void Actor::FaceMotion - ( - void - ) +void Actor::EventEnableEnemySwitch(Event *ev) { - Vector delta; - - if (VectorLength2DSquared(velocity) > 1) - { - vec3_t dir; - velocity.copyTo(dir); - delta = origin - m_vOriginHistory[m_iCurrentHistory]; - - if (delta.lengthXYSquared() >= 1) - { - if (DotProduct2D(velocity, delta) > 0) - { - delta.copyTo(dir); - } - } - - if (IsIdleState(m_ThinkState)) - { - IdleLook(dir); - } - else - { - SetDesiredLookDir(dir); - } - - SetDesiredYawDir(dir); - } - else if (IsIdleState(m_ThinkState) && m_pLookEntity) - { - LookAtLookEntity(); - } - else - { - m_bHasDesiredLookAngles = false; - } + m_bEnemySwitch = true; } /* =============== -Actor::FaceDirectionDuringMotion - -Face direction during motion. +Actor::EventDisableEnemySwitch =============== */ -void Actor::FaceDirectionDuringMotion - ( - vec3_t vLook - ) +void Actor::EventDisableEnemySwitch(Event *ev) { - float yaw; - - SetDesiredLookDir(vLook); - - - if (velocity[0] != 0 || velocity[1] != 0) - { - float fMagsSquared = VectorLength2DSquared(vLook) * VectorLength2DSquared(velocity); - float fDot = DotProduct2D(velocity, vLook); - float fDotSquared = Square(fDot); - - yaw = velocity.toYaw(); - - float fYaw2; - if (fMagsSquared * 0.5 < fDotSquared) - { - if (fDot >= 0) - { - fYaw2 = yaw; - } - else if (yaw - 180 >= 0) - { - fYaw2 = yaw - 180; - } - else - { - fYaw2 = yaw - 180 + 360; - } - } - else - { - if (vLook[0] * velocity[1] <= vLook[1] * velocity[0]) - { - fYaw2 = yaw - 270; - } - else - { - fYaw2 = yaw - 90; - } - - if (fYaw2 < 0) - { - fYaw2 += 360; - } - } - - SetDesiredYaw(fYaw2); - } - else - { - SetDesiredYawDir(vLook); - } - + m_bEnemySwitch = false; } /* =============== -Actor::PathDistanceAlongVector - -Returns projected distance from vDir along path. +Actor::EventSetRunAnimRate =============== */ -float Actor::PathDistanceAlongVector - ( - vec3_t vDir - ) +void Actor::EventSetRunAnimRate(Event *ev) { - Vector vDelta = m_Path.CurrentDelta(); - - return DotProduct2D( vDelta, vDir ); + m_fRunAnimRate = ev->GetFloat(1); } /* =============== -Actor::FaceEnemyOrMotion - - +Actor::EventGetRunAnimRate =============== */ -void Actor::FaceEnemyOrMotion - ( - int iTimeIntoMove - ) +void Actor::EventGetRunAnimRate(Event *ev) { - Vector vDelta = origin - m_vLastEnemyPos; - vDelta.z = 0; - if (iTimeIntoMove > 999) - { - if (m_Path.CurrentNodeIndex() != m_sCurrentPathNodeIndex) - { - float fDist = PathDistanceAlongVector(vDelta); - m_bFaceEnemy = fDist <= 0 || vDelta.lengthXYSquared() * Square(64) >= Square(fDist); - - m_sCurrentPathNodeIndex = m_Path.CurrentNodeIndex(); - } - } - else - { - m_bFaceEnemy = true; - } - - if (m_bFaceEnemy && (vDelta.x >= 15.0 || vDelta.x <= -15.0 || vDelta.y >= 15.0 || vDelta.y <= -15.0)) - { - vDelta.x = -vDelta.x; - vDelta.y = -vDelta.y; - FaceDirectionDuringMotion(vDelta); - } - else - { - FaceMotion(); - } + ev->AddFloat(m_fRunAnimRate); } /* =============== -Actor::NextUpdateTime - -Returns next update time. +Actor::Landed =============== */ -int Actor::NextUpdateTime - ( - int iLastUpdateTime, - int iUpdatePeriod - ) +void Actor::Landed(Event *ev) { - int i = iLastUpdateTime; + if (groundentity && groundentity->entity != world) { + warning("Actor::Landed", "Actor %d has landed on an entity that might move\n", entnum); + } - do - i += iUpdatePeriod; - while( i < level.inttime ); - - return i; + setMoveType(MOVETYPE_NONE); } /* =============== -Actor::ResetBoneControllers - -Reset Bone Controllers. +Actor::IsOnFloor =============== */ -void Actor::ResetBoneControllers - ( - void - ) +bool Actor::IsOnFloor(void) { - - if (edict->s.bone_tag[HEAD_TAG] != -1) - { - - SetControllerAngles(HEAD_TAG, vec_zero); - } - if (edict->s.bone_tag[TORSO_TAG] != -1) - { - SetControllerAngles(TORSO_TAG, vec_zero); - } - if (edict->s.bone_tag[ARMS_TAG] != -1) - { - SetControllerAngles(ARMS_TAG, vec_zero); - } + str name = AnimName(0); + name.toupper(); + return strstr(name, "FLOOR") != NULL; } /* =============== -Actor::UpdateBoneControllers - -Update Bone Controllers. -Reversed incorrectly, since decompiled output has different behaviour as reversed output. +Actor::GetNationality =============== */ -void Actor::UpdateBoneControllers - ( - void - ) - +void Actor::GetNationality(Event *ev) { - int v1; // eax - float v2; // fst7 - float v3; // ebx - float v4; // fst7 - float error; // fst5 - float v6; // fst3 - float v7; // ST34_4 - float torsoYawError; // edx - float fErr1; // fst7 - float v10; // tt - float v11; // fst5 - float v12; // fst7 - float v13; // fst5 - float fErr2; // fst3 - float fAng1; // fst4 - float fAng2; // fst5 - float v17; // fst1 - float fAng3; // fst4 - float v19; // fst3 - float fAng3_; // fst5 - float fFrameTorsoDist; // fst4 - float fAng4; // fst5 - float v23; // fst4 - float fAng5; // fst6 - float v25; // ST48_4 - float v26; // ST38_4 - float fAng6; // fst6 - float v28; // fst5 - float v29; // fst4 - float fAng7; // fst5 - float fAng8; // fst2 - float v32; // fst1 - float fAng9; // fst6 - float v34; // fst6 - float v35; // fst3 - float v36; // fst1 - float fAng10; // fst5 - float v38; // fst3 - float v39; // fst6 - float v40; // fst3 - float v41; // fst5 - float v42; // fst5 - float v43; // t1 - float v44; // fst4 - float v45; // t2 - float v46; // fst5 - float v47; // fst7 - float v48; // fst5 - float fAng11; // fst5 - float v50; // fst5 - float fAng12; // fst5 - float v52; // t0 - float v53; // fst5 - float v54; // fst7 - float v55; // fst6 - float fAng13; // fst7 - float v57; // fst6 - float v58; // fst7 - float v59; // fst6 - float v60; // fst7 - float v61; // fst6 - float fAng15; // fst7 - float v63; // tt - float v64; // fst6 - float v65; // t0 - float v66; // fst6 - float v67; // fst2 - float v68; // tt - float v69; // fst4 - float v70; // t1 - float v71; // fst4 - float v72; // t2 - float v73; // fst4 - float v74; // tt - float v75; // fst4 - int16_t tagnum; // ax - signed int v77; // ebx - float v78; // fst7 - float v79; // fst6 - float v80; // fst5 - int *v81; // eax - float v82; // fst4 - float v83; // fst3 - float v84; // fst4 - float v85; // t2 - float v86; // tt - float v87; // fst4 - float v88; // fst5 - float v89; // fst6 - float v90; // t0 - float v91; // eax - signed int v92; // edx - float *v93; // eax - float v94; // fst7 - float v95; // fst5 - float v96; // t0 - float v97; // fst5 - float v98; // t1 - float v99; // fst5 - float v100; // fst6 - signed int fAlpha; // ebx - float fAlpha2; // ST34_4 MAPDST - int *v104; // eax - signed int v105; // edx - float v106; // fst6 - float v107; // fst5 - float v108; // fst4 - float v109; // fst3 - float v110; // fst7 - float v111; // fst2 - float v112; // fst0 - float v113; // fst1 - float v114; // fst2 - float v115; // t1 - float v116; // fst1 - float v117; // fst3 - float v118; // tt - float v119; // fst2 - float v120; // fst5 - float v121; // t0 - float v122; // fst2 - float v123; // fst7 - float v124; // fst6 - float v125; // t1 - float v126; // fst3 - float v127; // t2 - float v128; // fst3 - float v129; // tt - int *v130; // eax - signed int v131; // edx - float v132; // fst6 - float v133; // fst5 - float v134; // fst4 - float v135; // fst3 - float v136; // fst7 - float v137; // fst2 - float v138; // fst0 - float v139; // fst1 - float v140; // fst2 - float v141; // tt - float v142; // fst1 - float v143; // fst3 - float v144; // t1 - float v145; // fst2 - float v146; // fst5 - float v147; // t2 - float v148; // fst2 - float v149; // fst7 - float v150; // fst6 - float v151; // tt - float v152; // fst3 - float v153; // t0 - float v154; // fst3 - float v155; // t1 - signed int v156; // ebx - float v157; // fst7 - float v158; // fst6 - float v159; // fst5 - int *v160; // eax - float v161; // fst4 - float v162; // fst3 - float v163; // fst4 - float v164; // t1 - float v165; // t2 - float v166; // fst4 - float v167; // fst5 - float v168; // fst6 - float v169; // tt - SimpleEntityPtr v170; // ecx - struct gentity_s *v171; // esi - float v172; // [esp+2Ch] [ebp-20Ch] - float v173; // [esp+2Ch] [ebp-20Ch] - float v174; // [esp+7Ch] [ebp-1BCh] - float v175; // [esp+80h] [ebp-1B8h] - float v176; // [esp+84h] [ebp-1B4h] - Vector v177; // [esp+90h] [ebp-1A8h] - Vector v178; // [esp+A0h] [ebp-198h] - float v179; // [esp+B0h] [ebp-188h] - float v180; // [esp+B4h] [ebp-184h] - float v181; // [esp+B8h] [ebp-180h] - float v182[3]; // [esp+C0h] [ebp-178h] - float fDist; // [esp+DCh] [ebp-15Ch] - float v184; // [esp+E0h] [ebp-158h] - float v185; // [esp+E4h] [ebp-154h] - float v186; // [esp+E8h] [ebp-150h] - float v187[3]; // [esp+F0h] [ebp-148h] - float v188; // [esp+100h] [ebp-138h] - float v189; // [esp+104h] [ebp-134h] - float v190; // [esp+108h] [ebp-130h] - float vLookDest[3]; // [esp+110h] [ebp-128h] - orientation_t tag_or; // [esp+120h] [ebp-118h] - float v193[3]; // [esp+150h] [ebp-E8h] - float v194[4]; // [esp+160h] [ebp-D8h] - float v195[3]; // [esp+170h] [ebp-C8h] - float lookAxis[3][3]; // [esp+180h] [ebp-B8h] - float v197[3]; // [esp+1B0h] [ebp-88h] - float myAxis[3][3]; // [esp+1C0h] [ebp-78h] - float LocalLookAngles[3]; // [esp+1F0h] [ebp-48h] - float torsoAngles[3]; // [esp+200h] [ebp-38h] - float headAngles[3]; // [esp+210h] [ebp-28h] - int v202; // [esp+220h] [ebp-18h] - - torsoAngles[2] = 0.0; - headAngles[0] = 0.0; - headAngles[1] = 0.0; - headAngles[2] = 0.0; - torsoAngles[0] = 0.0; - torsoAngles[1] = 0.0; - if (m_bHasDesiredLookAngles) - { - v1 = g_showlookat->integer; - if (v1 != entnum && v1 != -1) - { - ACTOR_UPDATEBONECONTROLLERS_4: - v2 = m_DesiredLookAngles[0]; - LocalLookAngles[0] = m_DesiredLookAngles[0]; - LocalLookAngles[1] = m_DesiredLookAngles[1]; - v3 = m_DesiredLookAngles[2]; - v178[0] = 0.0; - LocalLookAngles[2] = v3; - v177[2] = v3; - v178[1] = 0.0; - v178[2] = 0.0; - v177[0] = v2; - v177[1] = LocalLookAngles[1]; - v177.AngleVectorsLeft(&v178); - edict->s.eyeVector[0] = v178[0]; - edict->s.eyeVector[1] = v178[1]; - edict->s.eyeVector[2] = v178[2]; - goto ACTOR_UPDATEBONECONTROLLERS_5; - } - tagnum = gi.Tag_NumForName(edict->tiki, "eyes bone"); - v77 = 0; - tag_or = G_TIKI_Orientation(edict, tagnum & 0x3FF); - AnglesToAxis(angles, myAxis); - v197[0] = origin[0]; - v197[1] = origin[1]; - v78 = v197[0]; - v79 = v197[1]; - v80 = origin[2]; - v197[2] = origin[2]; - v81 = &v202; - while (1) - { - v82 = tag_or.origin[v77++]; - v78 = v78 + *(v81 - 24) * v82; - v83 = v82; - v84 = *(v81 - 23) * v82; - v85 = v83 * *(v81 - 22); - v81 += 3; - v86 = v84 + v79; - v87 = v80; - v88 = v86; - v89 = v85 + v87; - if (v77 > 2) - break; - v90 = v88; - v80 = v89; - v79 = v90; - } - v197[2] = v89; - v197[1] = v88; - v197[0] = v78; - vLookDest[0] = 0.0; - vLookDest[1] = 0.0; - vLookDest[2] = 0.0; - if (m_bHasDesiredLookDest) - { - v188 = m_vDesiredLookDest[0]; - v189 = m_vDesiredLookDest[1]; - v91 = m_vDesiredLookDest[2]; - ACTOR_UPDATEBONECONTROLLERS_105: - v190 = v91; - vLookDest[0] = v188; - vLookDest[2] = v91; - vLookDest[1] = v189; - goto ACTOR_UPDATEBONECONTROLLERS_106; - } - v170 = this->m_pLookEntity; - if (v170) - { - if (!v170->IsSubclassOfSentient()) - { - v188 = v170->centroid[0]; - v189 = v170->centroid[1]; - v91 = v170->centroid[2]; - goto ACTOR_UPDATEBONECONTROLLERS_105; - } - ((Sentient *)v170.Pointer())->EyePosition().copyTo(vLookDest); - } - ACTOR_UPDATEBONECONTROLLERS_106: - v92 = 0; - v93 = angles; - do - { - v94 = *v93; - ++v93; - v194[v92] = v94 + m_DesiredLookAngles[v92]; - ++v92; - } while (v92 <= 2); - AnglesToAxis(v194, lookAxis); - v188 = vLookDest[0] - v197[0]; - v189 = vLookDest[1] - v197[1]; - v190 = vLookDest[2] - v197[2]; - VectorNormalize(&v188); - v187[0] = v188; - v187[1] = v189; - v187[2] = v190; - v95 = v188 - lookAxis[0][0]; - v184 = v95; - v96 = v95 * v95; - v97 = v189 - lookAxis[0][1]; - v185 = v97; - v98 = v97 * v97; - v99 = v190 - lookAxis[0][2]; - v186 = v99; - v100 = v99 * v99 + v98 + v96; - fDist = sqrt(v100); - if (fDist >= 0.1) - { - v193[0] = 128.0; - v156 = 0; - v193[1] = 0.0; - v157 = v197[0]; - v158 = v197[1]; - v159 = v197[2]; - v195[1] = v197[1]; - v160 = &v202; - v193[2] = 0.0; - v195[0] = v197[0]; - v195[2] = v197[2]; - while (1) - { - v161 = v193[v156++]; - v157 = v157 + *(v160 - 40) * v161; - v162 = v161; - v163 = *(v160 - 39) * v161; - v164 = v162 * *(v160 - 38); - v160 += 3; - v165 = v163 + v158; - v166 = v159; - v167 = v165; - v168 = v164 + v166; - if (v156 > 2) - break; - v169 = v167; - v159 = v168; - v158 = v169; - } - v195[2] = v168; - v195[1] = v167; - v195[0] = v157; - } - else - { - v195[0] = vLookDest[0]; - v195[1] = vLookDest[1]; - v195[2] = vLookDest[2]; - fDist = sqrt(v100); - if (fDist >= 0.039999999) - { - fDist = sqrt(v184 * v184 + v185 * v185 + v186 * v186); - fAlpha = ((0.1 - fDist) / 0.060000002); - } - else - { - fAlpha = 1; - } - v187[0] = vLookDest[0] + 8.0; - v182[0] = vLookDest[0] + 8.0; - v187[1] = vLookDest[1] + 8.0; - v187[2] = vLookDest[2] + -8.0; - fAlpha2 = fAlpha; - v182[1] = vLookDest[1] + 8.0; - v182[2] = vLookDest[2] + 8.0; - G_DebugLine(v182, v187, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + 8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + -8.0; - v179 = 8.0; - v180 = -8.0; - v181 = -8.0; - v182[0] = 8.0; - v182[1] = -8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + 8.0; - v178[1] = vLookDest[1] + -8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + 8.0; - v177[2] = vLookDest[2] + -8.0; - v179 = -8.0; - v180 = 8.0; - v181 = -8.0; - v182[0] = -8.0; - v182[1] = 8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + -8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + -8.0; - v179 = -8.0; - v180 = -8.0; - v181 = -8.0; - v182[0] = -8.0; - v182[1] = -8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + -8.0; - v178[1] = vLookDest[1] + -8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + 8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + 8.0; - v179 = 8.0; - v180 = -8.0; - v181 = 8.0; - v182[0] = 8.0; - v182[1] = 8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + 8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + 8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + -8.0; - v179 = 8.0; - v180 = -8.0; - v181 = -8.0; - v182[0] = 8.0; - v182[1] = 8.0; - v182[2] = -8.0; - v178[0] = vLookDest[0] + 8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + -8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + 8.0; - v179 = -8.0; - v180 = -8.0; - v181 = 8.0; - v182[0] = -8.0; - v182[1] = 8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + -8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + -8.0; - v179 = -8.0; - v180 = -8.0; - v181 = -8.0; - v182[0] = -8.0; - v182[1] = 8.0; - v182[2] = -8.0; - v178[0] = vLookDest[0] + -8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + -8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + 8.0; - v177[2] = vLookDest[2] + 8.0; - v179 = -8.0; - v180 = 8.0; - v181 = 8.0; - v182[0] = 8.0; - v182[1] = 8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + 8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + 8.0; - v177[2] = vLookDest[2] + -8.0; - v179 = -8.0; - v180 = 8.0; - v181 = -8.0; - v182[0] = 8.0; - v182[1] = 8.0; - v182[2] = -8.0; - v178[0] = vLookDest[0] + 8.0; - v178[1] = vLookDest[1] + 8.0; - v178[2] = vLookDest[2] + -8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[0] = vLookDest[0]; - v187[1] = vLookDest[1]; - v187[2] = vLookDest[2]; - v177[0] = vLookDest[0] + -8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + 8.0; - v179 = -8.0; - v180 = -8.0; - v181 = 8.0; - v182[0] = 8.0; - v182[1] = -8.0; - v182[2] = 8.0; - v178[0] = vLookDest[0] + 8.0; - v178[1] = vLookDest[1] + -8.0; - v178[2] = vLookDest[2] + 8.0; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - v187[1] = vLookDest[1]; - v177[0] = vLookDest[0] + -8.0; - v187[0] = vLookDest[0]; - v187[2] = vLookDest[2]; - v179 = -8.0; - v180 = -8.0; - v181 = -8.0; - v182[0] = 8.0; - v182[1] = -8.0; - v182[2] = -8.0; - v177[1] = vLookDest[1] + -8.0; - v177[2] = vLookDest[2] + -8.0; - v178[0] = 8.0 + vLookDest[0]; - v178[1] = vLookDest[1] + -8.0; - v178[2] = -8.0 + vLookDest[2]; - G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2); - } - G_DebugLine(v197, v195, 0.0, 0.0, 1.0, 1.0); - v104 = &v202; - v105 = 0; - v106 = v197[1]; - v107 = v197[2]; - v108 = v195[0]; - v109 = v195[1]; - v110 = v195[2]; - v193[0] = 0.0; - v193[1] = 0.0; - v193[2] = -2.0; - v174 = v197[0]; - while (1) - { - v111 = v193[v105++]; - v112 = *(v104 - 40) * v111; - v108 = v108 + v112; - v174 = v174 + v112; - v113 = v111; - v114 = *(v104 - 39) * v111; - v115 = v113 * *(v104 - 38); - v104 += 3; - v116 = v109; - v117 = v106 + v114; - v118 = v114 + v116; - v119 = v107; - v120 = v118; - v121 = v119 + v115; - v122 = v110; - v123 = v121; - v124 = v115 + v122; - if (v105 > 2) - break; - v125 = v117; - v126 = v124; - v106 = v125; - v127 = v126; - v128 = v123; - v110 = v127; - v129 = v128; - v109 = v120; - v107 = v129; - } - v195[2] = v124; - v195[1] = v120; - v195[0] = v108; - v197[2] = v123; - v197[1] = v117; - v197[0] = v174; - G_DebugLine(v197, v195, 0.0, 0.0, 1.0, 1.0); - v130 = &v202; - v131 = 0; - v132 = v197[1]; - v133 = v197[2]; - v134 = v195[0]; - v135 = v195[1]; - v136 = v195[2]; - v193[0] = 0.0; - v193[1] = 2.0; - v193[2] = 0.0; - v175 = v197[0]; - while (1) - { - v137 = v193[v131++]; - v138 = *(v130 - 40) * v137; - v134 = v134 + v138; - v175 = v175 + v138; - v139 = v137; - v140 = *(v130 - 39) * v137; - v141 = v139 * *(v130 - 38); - v130 += 3; - v142 = v135; - v143 = v132 + v140; - v144 = v140 + v142; - v145 = v133; - v146 = v144; - v147 = v145 + v141; - v148 = v136; - v149 = v147; - v150 = v141 + v148; - if (v131 > 2) - break; - v151 = v143; - v152 = v150; - v132 = v151; - v153 = v152; - v154 = v149; - v136 = v153; - v155 = v154; - v135 = v146; - v133 = v155; - } - v195[2] = v150; - v195[1] = v146; - v195[0] = v134; - v197[2] = v149; - v197[1] = v143; - v197[0] = v175; - G_DebugLine(v197, v195, 0.0, 0.0, 1.0, 1.0); - goto ACTOR_UPDATEBONECONTROLLERS_4; - } - v171 = edict; - v171->s.eyeVector[2] = 0.0; - v171->s.eyeVector[1] = 0.0; - v171->s.eyeVector[0] = 0.0; - LocalLookAngles[2] = 0.0; - LocalLookAngles[1] = 0.0; - LocalLookAngles[0] = 0.0; -ACTOR_UPDATEBONECONTROLLERS_5: - GetControllerAngles(1).copyTo(v177); - torsoAngles[2] = v177[2]; - torsoAngles[0] = v177[0]; - torsoAngles[1] = v177[1]; - GetControllerAngles(0).copyTo(v177); - v4 = LocalLookAngles[0]; - headAngles[2] = v177[2]; - headAngles[1] = v177[1]; - headAngles[0] = v177[0]; - error = LocalLookAngles[1] - (torsoAngles[1] + v177[1]); - v6 = LocalLookAngles[1] - torsoAngles[1]; - v176 = LocalLookAngles[0] - v177[0]; - v7 = v6; - torsoYawError = v7; - if (v6 > 180.0) - { - v172 = v6 - 360.0; - ACTOR_UPDATEBONECONTROLLERS_7: - torsoYawError = v172; - goto ACTOR_UPDATEBONECONTROLLERS_8; - } - if (v6 < -180.0) - { - v172 = v6 + 360.0; - goto ACTOR_UPDATEBONECONTROLLERS_7; - } -ACTOR_UPDATEBONECONTROLLERS_8: - if (torsoYawError >= 0.0) - { - if (error < -120.0) - error = error + 360.0; - } - else if (error > 120.0) - { - error = error - 360.0; - } - if (!((((uint8_t)this->m_iLookFlags) ^ 1) & 1)) - { - fAng6 = error; - goto ACTOR_UPDATEBONECONTROLLERS_25; - } - if (error <= 25.0) - { - if (-25.0 <= error) - { - v12 = error; - v13 = 0.0; - goto ACTOR_UPDATEBONECONTROLLERS_15; - } - fErr1 = 0.2 * (error + 25.0); - } - else - { - fErr1 = (error - 25.0) * 0.2; - } - v10 = error; - v11 = fErr1; - v12 = v10; - fDist = v11; - v13 = fDist; -ACTOR_UPDATEBONECONTROLLERS_15: - fErr2 = v12 + headAngles[1]; - fAng1 = -torsoAngles[1]; - v173 = fErr2; - if (fErr2 > fAng1) - { - fErr2 = fAng1; - fAng1 = v173; - } - if (fErr2 <= v13) - { - v74 = fAng1; - v75 = v13; - fAng2 = v74; - if (v75 <= v74) - fAng2 = v75; - } - else - { - fAng2 = fErr2; - } - v17 = level.frametime * 15.0; - fAng3 = this->m_fTorsoCurrentTurnSpeed + v17; - v19 = this->m_fTorsoCurrentTurnSpeed - v17; - if (fAng2 <= fAng3) - { - fAng3 = fAng2; - if (v19 > fAng2) - fAng3 = v19; - } - fAng3_ = fAng3; - fFrameTorsoDist = level.frametime * this->m_fTorsoMaxTurnSpeed; - if (-fFrameTorsoDist <= fAng3_) - { - v72 = fFrameTorsoDist; - v73 = fAng3_; - fAng4 = v72; - if (v73 <= v72) - fAng4 = v73; - } - else - { - fAng4 = -fFrameTorsoDist; - } - v23 = torsoAngles[1] + fAng4; - torsoAngles[1] = v23; - if (v23 <= 30.0) - { - v71 = torsoAngles[1]; - if (torsoAngles[1] >= -30.0) - { - fAng5 = fAng4; - } - else - { - torsoAngles[1] = -30.0; - fAng5 = fAng4 - (v71 + 30.0); - } - } - else - { - torsoAngles[1] = 30.0; - fAng5 = fAng4 - (v23 - 30.0); - } - this->m_fTorsoCurrentTurnSpeed = fAng5; - v25 = fAng5; - v26 = v12; - torsoAngles[0] = 0.0; - torsoAngles[2] = 0.0; - SetControllerAngles(1, torsoAngles); - v4 = LocalLookAngles[0]; - fAng6 = v26 - v25; -ACTOR_UPDATEBONECONTROLLERS_25: - if (fAng6 > 15.0) - { - v28 = fAng6 - 15.0; - ACTOR_UPDATEBONECONTROLLERS_27: - v29 = level.frametime; - fAng7 = v28 * 4.0 * v29; - goto ACTOR_UPDATEBONECONTROLLERS_28; - } - if (-15.0 > fAng6) - { - v28 = fAng6 + 15.0; - goto ACTOR_UPDATEBONECONTROLLERS_27; - } - v29 = level.frametime; - fAng7 = 0.0; -ACTOR_UPDATEBONECONTROLLERS_28: - fAng8 = fAng6; - v32 = fAng6; - fAng9 = -headAngles[1]; - if (v32 > fAng9) - { - fAng8 = fAng9; - fAng9 = v32; - } - if (fAng8 <= fAng7) - { - if (fAng7 <= fAng9) - { - v34 = headAngles[1]; - } - else - { - v68 = v29; - v69 = fAng9; - v34 = headAngles[1]; - v70 = v69; - v29 = v68; - fAng7 = v70; - } - } - else - { - fAng7 = fAng8; - v34 = headAngles[1]; - } - v35 = this->m_fHeadMaxTurnSpeed; - v36 = -(v29 * v35); - if (v36 <= fAng7) - { - v67 = fAng7; - fAng10 = v29 * v35; - if (v67 <= fAng10) - fAng10 = v67; - } - else - { - fAng10 = v36; - } - v38 = v34; - v39 = this->m_fHeadMaxTurnSpeed; - v40 = fAng10 + v38; - v41 = 60.0; - headAngles[1] = v40; - if (v40 > 60.0) - goto ACTOR_UPDATEBONECONTROLLERS_37; - v42 = v29; - if (headAngles[1] < -60.0) - { - v41 = -60.0; - ACTOR_UPDATEBONECONTROLLERS_37: - v43 = v29; - v44 = v41; - v42 = v43; - headAngles[1] = v44; - } - v45 = v42; - v46 = v4; - v47 = v45; - v48 = fabs(v46); - if (v48 >= 15.0) - { - fAng11 = 15.0; - } - else - { - fDist = v48; - fAng11 = fDist; - } - if (v176 > fAng11) - { - v50 = v176 - fAng11; - ACTOR_UPDATEBONECONTROLLERS_42: - fDist = 0.2 * v50; - fAng12 = fDist; - goto ACTOR_UPDATEBONECONTROLLERS_43; - } - if (-fAng11 > v176) - { - v50 = fAng11 + v176; - goto ACTOR_UPDATEBONECONTROLLERS_42; - } - fAng12 = 0.0; -ACTOR_UPDATEBONECONTROLLERS_43: - v52 = fAng12; - v53 = v47; - v54 = v52; - v55 = v39 * v53; - if (-v55 <= v52) - { - v65 = v55; - v66 = v54; - fAng13 = v65; - if (v66 <= v65) - fAng13 = v66; - } - else - { - fAng13 = -v55; - } - v57 = fAng13 + headAngles[0]; - v58 = 35.0; - headAngles[0] = v57; - if (v57 > 35.0 || (v58 = -35.0, headAngles[0] < -35.0)) - headAngles[0] = v58; - headAngles[2] = 0.0; - if (this->m_iLookFlags & 1) - { - headAngles[0] = 0.5 * headAngles[0]; - headAngles[1] = 0.5 * headAngles[1]; - } - SetControllerAngles(0, headAngles); - v177[0] = 0.0; - v177[1] = 0.0; - v177[2] = 0.0; - v178[0] = 0.0; - v178[1] = 0.0; - v178[2] = 0.0; - GetControllerAngles(2).copyTo(v177); - v179 = v177[0]; - v180 = v177[1]; - v181 = v177[2]; - v59 = m_vLUpperArmDesiredAngles[1] - v180; - v60 = v59; - if (v59 <= 180.0) - { - if (v59 < -180.0) - v60 = v59 + 360.0; - } - else - { - v60 = v59 - 360.0; - } - v61 = this->m_fLUpperArmTurnSpeed * level.frametime; - if (-v61 <= v60) - { - v63 = v61; - v64 = v60; - fAng15 = v63; - if (v64 <= v63) - fAng15 = v64; - } - else - { - fAng15 = -v61; - } - v178[0] = this->m_vLUpperArmDesiredAngles[0]; - v178[1] = fAng15 + v177[1]; - v178[2] = 0.0; - SetControllerAngles(2, v178); -} - -/* -void Actor::UpdateBoneControllers() -{ - Vector torsoAngles, headAngles, LocalLookAngles, vec1, vLookDest, vec2, vLookDir, lineVec, eyePosition; - float error, pitchError, torsoYawError, fAlpha; //, min_accel_change, max_accel_change, max_change, yawError, tolerable_error - - if (m_bHasDesiredLookAngles) - { - if (g_showlookat->integer == entnum || g_showlookat->integer == -1) - { - float myAxis[3][3], lookAxis[3][3]; - orientation_t tag_or; - GetRawTag("eyes bone", &tag_or); - - AnglesToAxis(angles, myAxis); - - vec1 = origin; - - for (int i = 0; i < 3; i++) - { - //sizeof(orientation_t); - VectorMA(vec1, tag_or.origin[i], myAxis[i], vec1); - - } - - - if (m_bHasDesiredLookDest) - { - vLookDest = m_vDesiredLookDest; - } - else if (m_pLookEntity) - { - if (m_pLookEntity->IsSubclassOfSentient()) - { - vLookDest = ((Sentient *)m_pLookEntity.Pointer())->EyePosition(); - } - else - { - vLookDest = m_pLookEntity->centroid; - } - } - else - { - vLookDest = vec_zero; - } - - - AnglesToAxis(angles + m_DesiredLookAngles, lookAxis); - - vec2 = vLookDest - vec1; - - VectorNormalize(vec2); - - float fDist = (vec2 - lookAxis[0]).length(); - if (fDist >= 0.1) - { - lineVec = Vector(128, 0, 0); - for (int i = 0; i < 3; i++) - { - VectorMA(vec1, lineVec[i], lookAxis[i], vLookDir); - } - - } - else - { - vLookDir = vLookDest; - - if (fDist >= 0.04) - { - fAlpha = ((0.1 - fDist) / 0.06); - } - else - { - fAlpha = 1; - } - - G_DebugLine(vLookDest + Vector(8, 8, 8), vLookDest + Vector(8, 8, -8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(8, -8, 8), vLookDest + Vector(8, -8, -8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(-8, 8, 8), vLookDest + Vector(-8, 8, -8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(8, 8, 8), vLookDest + Vector(8, -8, 8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(-8, 8, -8), vLookDest + Vector(-8, -8, -8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(8, 8, 8), vLookDest + Vector(-8, 8, 8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(8, 8, -8), vLookDest + Vector(-8, 8, -8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(8, -8, 8), vLookDest + Vector(-8, -8, 8), 0, 0, fAlpha, fAlpha); - G_DebugLine(vLookDest + Vector(8, -8, -8), vLookDest + Vector(-8, -8, -8), 0, 0, fAlpha, fAlpha); - } - - G_DebugLine(vec1, vLookDir, 0, 0, 1, 1); - - - for (int i = 0; i < 3; i++) - { - //sizeof(orientation_t); - VectorMA(vLookDir, Vector(0, 0, -2)[i], lookAxis[i], vLookDir); - VectorMA(vec1, Vector(0, 0, -2)[i], lookAxis[i], vec1); - - } - - G_DebugLine(vec1, vLookDir, 0, 0, 1, 1); - - - for (int i = 0; i < 3; i++) - { - //sizeof(orientation_t); - VectorMA(vLookDir, Vector(0, 2, 0)[i], lookAxis[i], vLookDir); - VectorMA(vec1, Vector(0, 2, 0)[i], lookAxis[i], vec1); - - } - - G_DebugLine(vec1, vLookDir, 0, 0, 1, 1); - - } - - - LocalLookAngles = m_DesiredLookAngles; - - eyePosition = vec_zero; - VectorClear(edict->s.eyeVector); - LocalLookAngles.AngleVectorsLeft(&eyePosition, NULL, NULL); - VectorCopy(eyePosition, edict->s.eyeVector); - - } - else - { - VectorClear(edict->s.eyeVector); - - LocalLookAngles = vec_zero; - } - headAngles = GetControllerAngles(HEAD_TAG); - torsoAngles = GetControllerAngles(TORSO_TAG); - - - torsoYawError = LocalLookAngles[1] - torsoAngles[1]; - error = torsoYawError - headAngles[1]; - - pitchError = LocalLookAngles[0] - headAngles[0]; - - if (torsoYawError <= 180) - { - if (torsoYawError < -180.0) - torsoYawError += 360; - } - else - { - torsoYawError -= 360; - } - - if (torsoYawError >= 0.0) - { - if (error < -120.0) - error += 360.0; - } - else if (error > 120.0) - { - error -= 360.0; - } - - float fErr1, fErr2, fAng1, fAng2, fAng3, fFrameTorsoDist, fAng4, fAng5, fAng6, fAng7; - float fAng8, fAng9, fAng10; - if (m_iLookFlags) - { - fAng6 = error; - } - else - { - if (error <= 25.0) - { - if (error >= -25.0) - { - fErr1 = 0.0; - //goto LABEL_15; - } - else - { - fErr1 = (error + 25.0) * 0.2; - } - } - else - { - fErr1 = (error - 25.0) * 0.2; - } - - fErr2 = error + headAngles[1]; - - fAng1 = -torsoAngles[1]; - - if (fErr2 > fAng1) - { - fErr2 = -torsoAngles[1]; - fAng1 = error + headAngles[1]; - } - - if (fErr2 <= error) - { - fAng2 = fAng1; - if (error <= fAng1) - fAng2 = error; - } - else - { - fAng2 = fErr2; - } - - - fAng3 = m_fTorsoCurrentTurnSpeed + level.frametime * 15.0; - - if (fAng2 <= fAng3) - { - fAng3 = fAng2; - if (fAng2 < m_fTorsoCurrentTurnSpeed - level.frametime * 15.0) - fAng3 = m_fTorsoCurrentTurnSpeed + level.frametime * 15.0; - } - - fFrameTorsoDist = level.frametime * m_fTorsoMaxTurnSpeed; - - if (-fFrameTorsoDist <= fAng3) - { - fAng4 = fFrameTorsoDist; - if (fAng3 <= fFrameTorsoDist) - fAng4 = fAng3; - } - else - { - fAng4 = -fFrameTorsoDist; - } - - torsoAngles[1] += fAng4; - if (torsoAngles[1] <= 30.0) - { - if (torsoAngles[1] >= -30.0) - { - fAng5 = fAng4; - } - else - { - torsoAngles[1] = -30.0; - fAng5 = fAng4 - (torsoAngles[1] + 30.0); - } - } - else - { - torsoAngles[1] = 30.0; - fAng5 = fAng4 - (torsoAngles[1] - 30.0); - } - - m_fTorsoCurrentTurnSpeed = fAng5; - - //only yaw (left/right) angles are allowed. - torsoAngles[0] = 0.0; - torsoAngles[2] = 0.0; - SetControllerAngles(TORSO_TAG, torsoAngles); - //gi.Printf("Torso angles: %f %f %f\n", torsoAngles.x, torsoAngles.y, torsoAngles.z); - - fAng6 = error - fAng5; - } - - if (fAng6 > 15.0) - { - fAng7 = (fAng6 - 15.0) * 4.0 * level.frametime; - } - else if (-15.0 > fAng6) - { - fAng7 = (fAng6 + 15.0) * 4.0 * level.frametime; - } - else - { - fAng7 = 0.0; - } - - fAng8 = fAng6; - fAng9 = -headAngles[1]; - - if (fAng8 > fAng9) - { - fAng8 = -headAngles[1]; - fAng9 = fAng6; - } - - if (fAng8 > fAng7) - { - fAng7 = fAng8; - } - else if (fAng7 > fAng9) - { - fAng7 = fAng9; - } - - if (-(level.frametime * m_fHeadMaxTurnSpeed) <= fAng7) - { - fAng10 = (level.frametime * m_fHeadMaxTurnSpeed); - if (fAng7 <= fAng10) - fAng10 = fAng7; - } - else - { - fAng10 = -(level.frametime * m_fHeadMaxTurnSpeed); - } - - headAngles[1] += fAng10; - if (headAngles[1] > 60) - { - headAngles[1] = 60; - } - else if (headAngles[1] < -60) - { - headAngles[1] = -60; - } - - float fAng11, fAng12, fAng13; - - fAng11 = fabs(LocalLookAngles[0]); - - if (fAng11 > 15) - { - fAng11 = 15; - } - - if (pitchError > fAng11) - { - fAng12 = 0.2 * (pitchError - fAng11); - } - else if (-fAng11 > pitchError) - { - fAng12 = 0.2 * (pitchError + fAng11); - } - else - { - fAng12 = 0; - } - - - if (-(level.frametime * m_fHeadMaxTurnSpeed) <= fAng12) - { - fAng13 = (level.frametime * m_fHeadMaxTurnSpeed); - if (fAng12 <= fAng13) - fAng13 = fAng12; - } - else - { - fAng13 = -(level.frametime * m_fHeadMaxTurnSpeed); - } - - headAngles[0] += fAng13; - - if (headAngles[0] > 35.0) - headAngles[0] = 35.0; - else if (headAngles[0] < -35.0) - headAngles[0] = -35.0; - - headAngles[2] = 0.0; - - if (m_iLookFlags) - { - headAngles[0] *= 0.5; - headAngles[1] *= 0.5; - } - - SetControllerAngles(HEAD_TAG, headAngles); - //gi.Printf("Head angles: %f %f %f\n", headAngles.x, headAngles.y, headAngles.z); - - - Vector armAngles = GetControllerAngles(ARMS_TAG); - - float fAng14 = m_vLUpperArmDesiredAngles[1] - armAngles[1]; - - if (fAng14 <= 180.0) - { - if (fAng14 < -180.0) - fAng14 += 360.0; - } - else - { - fAng14 -= 360.0; - } - - float fAng15; - - if (-(level.frametime * m_fLUpperArmTurnSpeed) <= fAng14) - { - fAng15 = (level.frametime * m_fLUpperArmTurnSpeed); - if (fAng14 <= fAng15) - fAng15 = fAng14; - } - else - { - fAng15 = -(level.frametime * m_fLUpperArmTurnSpeed); - } - - Vector newArmAngles(m_vLUpperArmDesiredAngles[0], fAng15 + armAngles[1], 0); - SetControllerAngles(ARMS_TAG, newArmAngles); - //gi.Printf("Arm angles: %f %f %f\n", newArmAngles.x, newArmAngles.y, newArmAngles.z); - - ///////////////////////////////////////////// - return; - ///////////////////////////////////////////// -} - -*/ -/* -=============== -Actor::ReadyToFire - -Returns true if weapon is ready to fire. -=============== -*/ -void Actor::ReadyToFire - ( - Event *ev - ) -{ - bool ready; - - Weapon *weap = GetActiveWeapon(WEAPON_MAIN); - - ready = weap && weap->ReadyToFire(FIRE_PRIMARY, true); - - ev->AddInteger(ready); + switch (m_iNationality) { + case ACTOR_NATIONALITY_DEFAULT: + default: + switch (m_Team) { + case TEAM_AMERICAN: + ev->AddString("usa"); + break; + case TEAM_GERMAN: + ev->AddString("ger"); + break; + default: + ev->AddString("unset"); + break; + } + break; + case ACTOR_NATIONALITY_AMERICAN: + ev->AddString("usa"); + break; + case ACTOR_NATIONALITY_GERMAN: + ev->AddString("ger"); + break; + case ACTOR_NATIONALITY_ITALIAN: + ev->AddString("it"); + break; + case ACTOR_NATIONALITY_BRITISH: + ev->AddString("uk"); + break; + case ACTOR_NATIONALITY_RUSSIAN: + ev->AddString("ussr"); + break; + } } /* =============== -Actor::GetLocalYawFromVector - -Returns local yaw from vector. EV_Actor_GetLocalYawFromVector +Actor::SetNationality =============== */ -void Actor::GetLocalYawFromVector - ( - Event *ev - ) +void Actor::SetNationality(Event *ev) { - float yaw; - Vector vec; + str name; - vec = ev->GetVector(1); - yaw = vectoyaw(vec) + 180.0f; - yaw = AngleSubtract(yaw, angles[1]); - ev->AddFloat(yaw); + if (ev->NumArgs() != 1) { + ScriptError( + "Bad bad nationality specified for '%s' at (%f %f %f)\n", + TargetName().c_str(), + origin[0], + origin[1], + origin[2] + ); + } + + name = ev->GetString(1); + + if (!str::icmpn(name, "default", 8)) { + m_iNationality = ACTOR_NATIONALITY_DEFAULT; + } else if (!str::icmpn(name, "ger", 4)) { + m_iNationality = ACTOR_NATIONALITY_GERMAN; + } else if (!str::icmpn(name, "it", 3)) { + m_iNationality = ACTOR_NATIONALITY_ITALIAN; + } else if (!str::icmpn(name, "usa", 4)) { + m_iNationality = ACTOR_NATIONALITY_AMERICAN; + } else if (!str::icmpn(name, "uk", 3)) { + m_iNationality = ACTOR_NATIONALITY_BRITISH; + } else if (!str::icmpn(name, "ussr", 5)) { + m_iNationality = ACTOR_NATIONALITY_RUSSIAN; + } else { + ScriptError( + "Bad bad nationality specified for '%s', must be one of: ger, it, usa, uk, ussr or default\n", + TargetName().c_str() + ); + } } /* =============== -Actor::EventGetSight - -Return current sight (vision distance). +Actor::EventWriteStats =============== */ -void Actor::EventGetSight - ( - Event *ev - ) +void Actor::EventWriteStats(Event *ev) { - ev->AddFloat(m_fSight); + if (g_aistats->integer) { + level.WriteActorStats(this); + } } /* =============== -Actor::EventSetSight - -Set current sight (vision distance). +Actor::EventCuriousOff =============== */ -void Actor::EventSetSight - ( - Event *ev - ) +void Actor::EventCuriousOff(Event *ev) { - m_fSight = ev->GetFloat(1); + m_bIsCurious = false; } /* =============== -Actor::EventGetHearing - -Get current hearing distance. +Actor::EventCuriousOn =============== */ -void Actor::EventGetHearing - ( - Event *ev - ) +void Actor::EventCuriousOn(Event *ev) { - ev->AddFloat(m_fHearing); + m_bIsCurious = true; } /* =============== -Actor::EventSetHearing - -Set current hearing distance. +Actor::EventSetDestIdle =============== */ -void Actor::EventSetHearing - ( - Event *ev - ) +void Actor::EventSetDestIdle(Event *ev) {} + +/* +=============== +Actor::EventSetDestIdle2 +=============== +*/ +void Actor::EventSetDestIdle2(Event *ev) {} + +/* +=============== +Actor::IsDisabled +=============== +*/ +bool Actor::IsDisabled() const { - m_fHearing = ev->GetFloat(1); + return !m_bDoAI; } /* =============== -Actor::ClearPatrolCurrentNode - -Clear current patrol node. -=============== -*/ -void Actor::ClearPatrolCurrentNode - ( - void - ) -{ - if (m_patrolCurrentNode) - { - if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) - { - delete m_patrolCurrentNode; - } - m_patrolCurrentNode = NULL; - } -} - -/* -=============== -Actor::NextPatrolCurrentNode - -Switch to next patrol node. -=============== -*/ -void Actor::NextPatrolCurrentNode - ( - void - ) -{ - if (m_bScriptGoalValid) - { - if (m_patrolCurrentNode->origin == m_vScriptGoal) - { - m_bScriptGoalValid = false; - } - } - if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) - { - ClearPatrolCurrentNode(); - } - else - { - m_patrolCurrentNode = m_patrolCurrentNode->Next(); - } -} - -/* -=============== -Actor::SetPatrolCurrentNode - -Set current patrol node. -=============== -*/ -void Actor::SetPatrolCurrentNode - ( - Vector& vec - ) -{ - ClearPatrolCurrentNode(); - - TempWaypoint * twp = new TempWaypoint(); - - m_patrolCurrentNode = twp; - - m_patrolCurrentNode->setOrigin(vec); - -} - -/* -=============== -Actor::SetPatrolCurrentNode - -Set current patrol node. -=============== -*/ -void Actor::SetPatrolCurrentNode - ( - Listener *l - ) -{ - ClearPatrolCurrentNode(); - - if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) - { - ScriptError("Bad patrol path with classname '%s' specified for '%s' at (%f %f %f)\n", - l->getClassname(), - targetname.c_str(), - origin.x, - origin.y, - origin.z - ); - } - - m_patrolCurrentNode = (SimpleEntity *)l; -} - -/* -=============== -Actor::EventSetPatrolPath - -Set current patrol path. -=============== -*/ -void Actor::EventSetPatrolPath - ( - Event *ev - ) -{ - SetPatrolCurrentNode(ev->GetListener(1)); -} - -/* -=============== -Actor::EventGetPatrolPath - -Get current patrol path. -=============== -*/ -void Actor::EventGetPatrolPath - ( - Event *ev - ) -{ - ev->AddListener(m_patrolCurrentNode); -} - -/* -=============== -Actor::EventSetPatrolWaitTrigger - -Set m_bPatrolWaitTrigger. -=============== -*/ -void Actor::EventSetPatrolWaitTrigger - ( - Event *ev - ) -{ - m_bPatrolWaitTrigger = ev->GetBoolean(1); -} - -/* -=============== -Actor::EventGetPatrolWaitTrigger - -Get m_bPatrolWaitTrigger. -=============== -*/ -void Actor::EventGetPatrolWaitTrigger - ( - Event *ev - ) -{ - ev->AddInteger(m_bPatrolWaitTrigger); -} - -/* -=============== -Actor::ShowInfo_PatrolCurrentNode - -Show current patrol node info. -=============== -*/ -void Actor::ShowInfo_PatrolCurrentNode - ( - void - ) -{ - - if (m_patrolCurrentNode) - { - Com_Printf("current patrol node: %s\n", m_patrolCurrentNode->targetname.c_str()); - } - else - { - Com_Printf("no current patrol node\n"); - } -} - -/* -=============== -Actor::MoveOnPathWithSquad - -Move on path with squad. -=============== -*/ -bool Actor::MoveOnPathWithSquad - ( - void - ) -{ - float fDistSquared, fIntervalSquared; - vec2_t vMyNormalDir, vDelta, vHisDir; - Player *p; - - //FIXMEL: macro - if (level.inttime < m_iSquadStandTime + 500 || !PathExists() || PathComplete()) - { - return false; - } - fIntervalSquared = Square(m_fInterval); - if (m_iSquadStandTime) - { - fIntervalSquared *= 2; - } - - p = (Player *)G_GetEntity(0); - - if (IsTeamMate(p)) - { - VectorSub2D(p->origin, origin, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - if (fIntervalSquared > fDistSquared && DotProduct2D(vDelta, PathDelta()) > 0) - { - VectorSub2D(velocity, p->velocity, vMyNormalDir); - VectorNormalize2D(vMyNormalDir); - if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) < 2304) - { - m_iSquadStandTime = level.inttime; - return false; - } - } - } - - for (Actor *pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer()) - { - if (!pSquadMate->IsSubclassOfActor()) - { - continue; - } - VectorSub2D(pSquadMate->origin, origin, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - if (fDistSquared >= fIntervalSquared || DotProduct2D(vDelta, PathDelta()) <= 0) - { - - continue; - } - if (pSquadMate->PathExists() || pSquadMate->PathComplete()) - { - VectorCopy2D(pSquadMate->velocity, vHisDir); - if (VectorLength2DSquared(vHisDir) <= 8) - { - continue; - } - } - else - { - VectorCopy2D(pSquadMate->PathDelta(), vHisDir); - - } - - if (DotProduct2D(PathDelta(), vHisDir) >= 0 && (entnum == pSquadMate->entnum || DotProduct2D(vHisDir, vDelta) >= 0)) - { - m_iSquadStandTime = level.inttime; - return false; - } - } - m_iSquadStandTime = 0; - return true; -} - -/* -=============== -Actor::MoveToWaypointWithPlayer - -Move to waypoint with player. -=============== -*/ -bool Actor::MoveToWaypointWithPlayer - ( - void - ) -{ - float fIntervalSquared, fDistSquared; - vec2_t vMyNormalDir, vDelta, vMyDir; - - if (level.inttime < m_iSquadStandTime + 500) - { - return false; - } - - fIntervalSquared = Square(m_fInterval); - if (m_iSquadStandTime) - { - fIntervalSquared += fIntervalSquared; - } - - Player *p = (Player *)G_GetEntity(0); - if (IsTeamMate(p)) - { - vDelta[0] = p->origin[0] - origin[0]; - vDelta[1] = p->origin[1] - origin[1]; - fDistSquared = VectorLength2DSquared(vDelta); - - if (fDistSquared >= fIntervalSquared) - { - m_iSquadStandTime = 0; - return true; - } - - vMyDir[0] = m_patrolCurrentNode->origin[0] - origin[0]; - vMyDir[1] = m_patrolCurrentNode->origin[1] - origin[1]; - if (DotProduct2D(vDelta, vMyDir) < 0) - { - m_iSquadStandTime = 0; - return true; - } - - vMyNormalDir[0] = velocity[0] - p->velocity[0]; - vMyNormalDir[1] = velocity[1] - p->velocity[1]; - VectorNormalize2D(vMyNormalDir); - - if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) > 2304) - { - m_iSquadStandTime = 0; - return true; - } - m_iSquadStandTime = level.inttime; - } - return false; -} - -/* -=============== -Actor::PatrolNextNodeExists - -Returns true if next patrol node exits. -=============== -*/ -bool Actor::PatrolNextNodeExists - ( - void - ) -{ - return m_patrolCurrentNode && !( m_patrolCurrentNode->IsSubclassOfTempWaypoint() ) && m_patrolCurrentNode->Next(); -} - -/* -=============== -Actor::UpdatePatrolCurrentNode - -Update current patrol node. -=============== -*/ -void Actor::UpdatePatrolCurrentNode - ( - void - ) -{ - bool next = false; - if (m_patrolCurrentNode) - { - if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) - { - if (fabs(origin[0] - m_patrolCurrentNode->origin[0]) < 16.0 - && fabs(origin[1] - m_patrolCurrentNode->origin[1]) < 16.0) - { - next = true; - } - } - else if(PathExists() && PathComplete()) - { - - next = true; - } - - } - if (next) - { - NextPatrolCurrentNode(); - } -} - -/* -=============== -Actor::MoveToPatrolCurrentNode - +Actor::ExtractConstraints =============== */ -bool Actor::MoveToPatrolCurrentNode - ( - void - ) -{ - UpdatePatrolCurrentNode(); - if (m_patrolCurrentNode && !m_bPatrolWaitTrigger) - { - Vector delta; - if (m_patrolCurrentNode->IsSubclassOfWaypoint()) - { - if (MoveToWaypointWithPlayer()) - { - m_bNextForceStart = false; - m_eNextAnimMode = 4; - m_csNextAnimString = m_csPatrolCurrentAnim; - FaceMotion(); - } - else - { - Anim_Stand(); - IdleLook(); - } - - SetDest(m_patrolCurrentNode->origin); - - if (m_fMoveDoneRadiusSquared == 0.0 || m_patrolCurrentNode->Next()) - return false; - delta = m_patrolCurrentNode->origin - origin; - } - else - { - SimpleActor::SetPath( - m_patrolCurrentNode->origin, - "Actor::MoveToPatrolCurrentNode", - 0, - NULL, - 0); - if (!PathExists()) - { - IdleLook(); - - Anim_Idle(); - parm.movefail = qtrue; - return false; - } - if (MoveOnPathWithSquad()) - { - if (PatrolNextNodeExists()) - { - m_eNextAnimMode = 2; - } - else - { - m_eNextAnimMode = 3; - } - m_csNextAnimString = m_csPatrolCurrentAnim; - m_bNextForceStart = false; - FaceMotion(); - } - else - { - Anim_Stand(); - IdleLook(); - } - - if (m_fMoveDoneRadiusSquared == 0) - return false; - - if (PathComplete()) - { - return true; - } - - if (!m_Path.HasCompleteLookahead() || m_patrolCurrentNode->Next()) - { - return false; - } - delta = PathDelta(); - } - return m_fMoveDoneRadiusSquared >= delta.lengthXYSquared(); - - } - - - IdleLook(); - Anim_Idle(); - return false; -} - -/* -=============== -Actor::ClearAimNode - -Clear aim node. -=============== -*/ -void Actor::ClearAimNode - ( - void - ) -{ - if (m_aimNode) - { - - if (m_aimNode->IsSubclassOfTempWaypoint()) - { - delete m_aimNode; - } - m_aimNode = NULL; - } -} - -/* -=============== -Actor::SetAimNode - -Change aim node. -=============== -*/ -void Actor::SetAimNode - ( - Vector& vec - ) -{ - ClearAimNode(); - - TempWaypoint * twp = new TempWaypoint(); - m_aimNode = twp; - - m_aimNode->setOrigin(vec); -} - -/* -=============== -Actor::SetAimNode - -Change aim node. -=============== -*/ -void Actor::SetAimNode - ( - Listener *l - ) -{ - ClearAimNode(); - if (l) - { - if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) - { - ScriptError( - "Bad aim node with classname '%s' specified for '%s' at (%f %f %f)\n", - l->getClassname(), - targetname.c_str(), - origin.x, - origin.y, - origin.z); - } - m_aimNode = (SimpleEntity *)l; - } -} - -/* -=============== -Actor::ShowInfo_AimNode - -Show current aim node info. -=============== -*/ -void Actor::ShowInfo_AimNode - ( - void - ) -{ - if (m_aimNode) - { - Com_Printf("aim node: %s\n", m_aimNode->targetname.c_str()); - } - else - { - Com_Printf("no current aim node\n"); - } -} - -/* -=============== -Actor::EventSetAccuracy - -Set current accuracy. -=============== -*/ -void Actor::EventSetAccuracy - ( - Event *ev - ) -{ - mAccuracy = ev->GetFloat(1) / 100; -} - -/* -=============== -Actor::EventGetAccuracy - -Get current accuracy. -=============== -*/ -void Actor::EventGetAccuracy - ( - Event *ev - ) -{ - ev->AddFloat(mAccuracy * 100); -} - -/* -=============== -Actor::GetThinkType - -Get think for csName. -=============== -*/ -int Actor::GetThinkType - ( - const_str csName - ) -{ - int result = 0; - while (m_csThinkNames[result] != csName) - { - if (++result > NUM_THINKS - 1) - { - ScriptError("unknown think type '%s'", Director.GetString(csName).c_str()); - } - } - return result; -} - -/* -=============== -Actor::SetThink - -Modifies think num of current thinkstate inside m_ThinkMap. -=============== -*/ -void Actor::SetThink - ( - eThinkState state, - eThinkNum think - ) -{ - m_ThinkMap[state] = think; - if (m_ThinkState == state) - m_bDirtyThinkState = true; -} - -/* -=============== -Actor::SetThink - -Set think to idle. -=============== -*/ -void Actor::SetThinkIdle - ( - eThinkNum think_idle - ) -{ - eThinkNum think_curious; - - switch (think_idle) - { - case THINK_PATROL: - case THINK_RUNNER: - m_bBecomeRunner = true; - think_curious = THINK_CURIOUS; - break; - case THINK_MACHINEGUNNER: - think_curious = THINK_MACHINEGUNNER; - break; - case THINK_DOG_IDLE: - think_curious = THINK_DOG_CURIOUS; - SetThink(THINKSTATE_GRENADE, think_curious); - break; - case THINK_ANIM: - think_curious = THINK_ANIM_CURIOUS; - break; - case THINK_BALCONY_IDLE: - think_curious = THINK_BALCONY_CURIOUS; - break; - default: - think_curious = THINK_CURIOUS; - break; - } - - - SetThink(THINKSTATE_IDLE, think_idle); - - SetThink(THINKSTATE_CURIOUS, think_curious); -} - -/* -=============== -Actor::SetThinkState - -Set thinkstate. -=============== -*/ -void Actor::SetThinkState - ( - eThinkState state, - eThinkLevel level - ) -{ - if (IsAttackState(state)) - { - m_csIdleMood = STRING_NERVOUS; - if (m_ThinkMap[THINKSTATE_ATTACK] != THINK_ALARM && m_ThinkMap[THINKSTATE_ATTACK] != THINK_WEAPONLESS && m_ThinkMap[THINKSTATE_ATTACK] != THINK_DOG_ATTACK && !GetWeapon(WEAPON_MAIN)) - { - Com_Printf( - "^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): forcing weaponless attack state.\n" - "^~^~^ Level designers should specify 'type_attack weaponless' for this guy.\n", - entnum, - radnum, - targetname.c_str()); - SetThink(THINKSTATE_ATTACK, THINK_WEAPONLESS); - } - } - - m_ThinkStates[level] = state; - - if (level >= m_ThinkLevel) - { - m_bDirtyThinkState = true; - } - -} - -/* -=============== -Actor::EndCurrentThinkState - -End current think state. -=============== -*/ -void Actor::EndCurrentThinkState - ( - void - ) -{ - SetThinkState(THINKSTATE_VOID, m_ThinkLevel); -} - -/* -=============== -Actor::ClearThinkStates - -Clear all thinkstates. -=============== -*/ -void Actor::ClearThinkStates - ( - void - ) -{ - for (int i = 0; i <= NUM_THINKLEVELS -1; i++) - { - SetThinkState(THINKSTATE_VOID, (eThinkLevel)i); - } -} - -/* -=============== -Actor::CurrentThink - -Current think. -=============== -*/ -int Actor::CurrentThink - ( - void - ) const -{ - return m_Think[ m_ThinkLevel ]; -} - -/* -=============== -Actor::IsAttacking - -Returns true if actor is in attack state. -=============== -*/ -bool Actor::IsAttacking - ( - void - ) const -{ - return m_ThinkStates[ THINKLEVEL_NORMAL ] == THINKSTATE_ATTACK; -} - -/* -=============== -Actor::EventGetFov - -Get current fov. -=============== -*/ -void Actor::EventGetFov - ( - Event *ev - ) -{ - ev->AddFloat(m_fFov); -} - -/* -=============== -Actor::EventSetFov - -Set current fov. -============ -*/ -void Actor::EventSetFov - ( - Event *ev - ) -{ - float fov = ev->GetFloat(1); - if (fov < 0 || fov > 360) - { - ScriptError("fov must be in the range [0,360]"); - } - m_fFov = fov; - m_fFovDot = cos(0.5 * fov * M_PI / 180.0); -} - -void Actor::EventSetDestIdle - ( - Event *ev - ) -{ - // not found in ida -} - -void Actor::EventSetDestIdle2 - ( - Event *ev - ) -{ - // not found in ida -} - -void Actor::EventSetTypeIdle - ( - Event *ev - ) -{ - eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1)); - glbs.Printf("EventSetTypeIdle %s : %d\n", ev->GetString(1).c_str(), think); - if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_IDLE)) - { - SetThinkIdle(THINK_IDLE); - ScriptError("Invalid idle think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); - } - - SetThinkIdle(think); -} - -void Actor::EventGetTypeIdle - ( - Event *ev - ) -{ - ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_IDLE]]); -} - -void Actor::EventSetTypeAttack - ( - Event *ev - ) -{ - eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1)); - glbs.Printf("EventSetTypeAttack %s : %d\n", ev->GetString(1).c_str(), think); - //check if the wanted think is an attack one. - if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_ATTACK)) - { - SetThink(THINKSTATE_ATTACK, THINK_TURRET); - - ScriptError("Invalid attack think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); - } - - SetThink(THINKSTATE_ATTACK, think); -} - -void Actor::EventGetTypeAttack - ( - Event *ev - ) -{ - ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]); -} - -void Actor::EventSetTypeDisguise - ( - Event *ev - ) -{ - eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1)); - glbs.Printf("EventSetTypeDisguise %s : %d\n", ev->GetString(1).c_str(), think); - if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_DISGUISE)) - { - SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE); - - ScriptError("Invalid disguise think '%s'", Director.GetString(m_csThinkNames[think]).c_str()); - } - - SetThink(THINKSTATE_DISGUISE, think); -} - -void Actor::EventGetTypeDisguise - ( - Event *ev - ) -{ - ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_DISGUISE]]); -} - -void Actor::EventSetDisguiseLevel - ( - Event *ev - ) -{ - m_iDisguiseLevel = ev->GetInteger(1); - if (m_iDisguiseLevel -1 > 1) - { - m_iDisguiseLevel = 1; - ScriptError("bad disguise level %d for %s, setting to 1\n", m_iDisguiseLevel, targetname.c_str()); - } -} - -void Actor::EventGetDisguiseLevel - ( - Event *ev - ) -{ - ev->AddInteger(m_iDisguiseLevel); -} - -void Actor::EventSetTypeGrenade - ( - Event *ev - ) -{ - eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1)); - glbs.Printf("EventSetTypeGrenade %s : %d\n", ev->GetString(1).c_str(), think); - if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_GRENADE)) - { - SetThink(THINKSTATE_GRENADE, THINK_GRENADE); - - ScriptError("Invalid grenade think '%s'", Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_GRENADE]]).c_str()); - } - - SetThink(THINKSTATE_GRENADE, think); -} - -void Actor::EventGetTypeGrenade - ( - Event *ev - ) -{ - ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_GRENADE]]); -} - -void Actor::EventSetMinDistance - ( - Event *ev - ) -{ - m_fMinDistance = ev->GetFloat(1); - - if (m_fMinDistance < 0) - { - m_fMinDistance = 0; - Com_Printf( - "^~^~^ Warning: mindist negative, forcing to %g for entity %i, targetname '%s'\n", - m_fMinDistance, - entnum, - targetname.c_str()); - } - m_fMinDistanceSquared = m_fMinDistance * m_fMinDistance; -} - -void Actor::EventGetMinDistance - ( - Event *ev - ) -{ - ev->AddFloat(m_fMinDistance); -} - -void Actor::EventSetMaxDistance - ( - Event *ev - ) -{ - m_fMaxDistance = ev->GetFloat(1); - //FIXME: macro - if (m_fMaxDistance < 256) - { - m_fMaxDistance = 256; - Com_Printf( - "^~^~^ Warning: maxdist too small, forcing to %g for entity %i, targetname '%s'\n", - m_fMaxDistance, - entnum, - targetname.c_str()); - } - m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance; -} - -void Actor::EventGetMaxDistance - ( - Event *ev - ) -{ - ev->AddFloat(m_fMaxDistance); -} - -void Actor::EventSetLeash - ( - Event *ev - ) -{ - m_fLeash = ev->GetFloat(1); - m_fLeashSquared = Square(m_fLeash); -} - -void Actor::EventGetLeash -( - Event *ev -) -{ - ev->AddFloat(m_fLeash); -} - -void Actor::EventSetInterval - ( - Event *ev - ) -{ - m_fInterval = ev->GetFloat(1); -} - -void Actor::EventDistToEnemy - ( - Event *ev - ) -{ - float dist = 0; - if (m_Enemy) - { - Vector distV = origin - m_Enemy->origin; - dist = distV.length(); - } - ev->AddFloat(dist); -} - -void Actor::EventGetInterval -( - Event *ev -) -{ - ev->AddFloat(m_fInterval); -} - -void Actor::EventGetRunAnim - ( - Event *ev - ) -{ - ev->AddConstString(GetRunAnim()); -} - -void Actor::EventGetWalkAnim - ( - Event *ev - ) -{ - ev->AddConstString(GetWalkAnim()); -} - -void Actor::EventSetAnimName - ( - Event *ev - ) -{ - m_csAnimName = ev->GetConstString(1); -} - -void Actor::EventGetAnimName -( - Event *ev -) -{ - ev->AddConstString(m_csAnimName); -} - -void Actor::EventSetDisguiseRange - ( - Event *ev - ) -{ - float range = ev->GetFloat(1); - m_fMaxDisguiseDistSquared = Square(range); -} - -void Actor::EventGetDisguiseRange - ( - Event *ev - ) -{ - ev->AddFloat(sqrt(m_fMaxDisguiseDistSquared)); -} - -void Actor::EventSetDisguisePeriod - ( - Event *ev - ) -{ - m_iDisguisePeriod = ev->GetFloat(1) * 1000 + 0.5; -} - -void Actor::EventGetDisguisePeriod - ( - Event *ev - ) -{ - ev->AddFloat(m_iDisguisePeriod / 1000.0); -} - -void Actor::EventSetDisguiseAcceptThread - ( - Event *ev - ) -{ - - if (ev->IsFromScript()) - { - m_DisguiseAcceptThread.SetThread(ev->GetValue()); - } - else - { - - m_DisguiseAcceptThread.Set(ev->GetString(1)); - } -} - -void Actor::EventGetDisguiseAcceptThread - ( - Event *ev - ) -{ - m_DisguiseAcceptThread.GetScriptValue(&ev->GetValue()); -} - -void Actor::EventAttackPlayer - ( - Event *ev - ) -{ - Player *pPlayer = (Player *)G_GetEntity(0); - if (!pPlayer) - { - ScriptError("player doesn't exist"); - } - else - { - m_PotentialEnemies.ConfirmEnemy(this, pPlayer); - m_bForceAttackPlayer = true; - } -} - -void Actor::ForceAttackPlayer - ( - void - ) -{ - m_PotentialEnemies.ConfirmEnemy(this, (Sentient *)G_GetEntity(0)); -} - -void Actor::EventSetAlarmNode - ( - Event *ev - ) -{ - Listener *l = ev->GetListener(1); - if (l) - { - if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) - { - ScriptError("Alarm node must be an entity"); - } - } - m_AlarmNode = (SimpleEntity *)l; -} - -void Actor::EventGetAlarmNode - ( - Event *ev - ) -{ - ev->AddListener(m_AlarmNode); -} - -void Actor::EventSetAlarmThread - ( - Event *ev - ) -{ - if (ev->IsFromScript()) - { - m_AlarmThread.SetThread(ev->GetValue()); - } - else - { - - m_AlarmThread.Set(ev->GetString(1)); - } -} - -void Actor::EventGetAlarmThread - ( - Event *ev - ) -{ - - m_AlarmThread.GetScriptValue(&ev->GetValue()); -} - -void Actor::EventSetSoundAwareness - ( - Event *ev - ) -{ - m_fSoundAwareness = ev->GetFloat(1); -} - -void Actor::EventGetSoundAwareness - ( - Event *ev - ) -{ - ev->AddFloat(m_fSoundAwareness); -} - -void Actor::EventSetGrenadeAwareness - ( - Event *ev - ) -{ - m_fGrenadeAwareness = ev->GetFloat(1); -} - -void Actor::EventGetGrenadeAwareness - ( - Event *ev - ) -{ - ev->AddFloat(m_fGrenadeAwareness); -} - -str Actor::ThinkName - ( - void - ) const -{ - return Director.GetString( m_csThinkNames[ m_Think[ m_ThinkLevel ] ] ); -} - -str Actor::ThinkStateName - ( - void - ) const -{ - return Director.GetString( m_csThinkStateNames[ m_ThinkState ] ); -} - -void Actor::EventSetTurret - ( - Event *ev - ) -{ - Listener *l = ev->GetListener(1); - if (l->inheritsFrom(&TurretGun::ClassInfo)) - { - m_pTurret = (TurretGun *)l; - } -} - -void Actor::EventGetTurret - ( - Event *ev - ) -{ - ev->AddListener(m_pTurret); -} - -void Actor::EventEnableEnemy - ( - Event *ev - ) -{ - m_bDesiredEnableEnemy = ev->GetBoolean(1); -} - -void Actor::EventEnablePain - ( - Event *ev - ) -{ - m_bEnablePain = ev->GetBoolean(1); -} - -void Actor::EventActivate - ( - Event *ev - ) -{ - m_bPatrolWaitTrigger = false; - Unregister(STRING_TRIGGER); -} - -void Actor::EventGetAmmoGrenade - ( - Event *ev - ) -{ - ev->AddInteger(AmmoCount("grenade")); -} - -void Actor::EventSetAmmoGrenade - ( - Event *ev - ) -{ - GiveAmmo("grenade", ev->GetInteger(1)); -} - -void Actor::EventInterruptPoint - ( - Event *ev - ) -{ - - GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]]; - - if (func->PostShoot) - (this->*func->PostShoot)(); -} - -void Actor::EventAnimScript - ( - Event *ev - ) -{ - m_bAnimScriptSet = true; - m_csAnimScript = ev->GetConstString(1); - - //FIXME: macro - m_AnimMode = 1; - - - SetThinkIdle(THINK_ANIM); -} - -void Actor::EventAnimScript_Scripted - ( - Event *ev - ) -{ - m_bAnimScriptSet = true; - m_csAnimScript = ev->GetConstString(1); - - //FIXME: macro - m_AnimMode = 5; - - - SetThinkIdle(THINK_ANIM); -} - -void Actor::EventAnimScript_Noclip - ( - Event *ev - ) -{ - m_bAnimScriptSet = true; - m_csAnimScript = ev->GetConstString(1); - //FIXME: macro - m_AnimMode = 6; - - - SetThinkIdle(THINK_ANIM); -} - -void Actor::EventReload_mg42 - ( - Event *ev - ) -{ - //FIXME: macos/enum - if (m_State != 1201) - { - if (m_State == 1200) - { - m_bAnimScriptSet = true; - TransitionState(1201, 0); - } - else - { - Unregister(STRING_ANIMDONE); - } - } -} - -void Actor::SetPathWithLeash - ( - Vector vDestPos, - const char *description, - int iMaxDirtyTime - ) -{ - vec2_t dist = { vDestPos[0] - m_vHome[0], vDestPos[1] - m_vHome[1] }; - float distSq = DotProduct2D(dist, dist); - if (distSq <= m_fLeashSquared) - { - dist[0] = origin[0] - m_vHome[0]; - dist[1] = origin[1] - m_vHome[1]; - distSq = DotProduct2D(dist, dist); - if (distSq <= m_fLeashSquared) - { - SetPath( - vDestPos, - description, - iMaxDirtyTime, - m_vHome, - m_fLeashSquared); - } - } - else - { - ClearPath(); - } -} - -void Actor::SetPathWithLeash - ( - SimpleEntity *pDestNode, - const char *description, - int iMaxDirtyTime - ) -{ - if (pDestNode) - { - SetPathWithLeash( - pDestNode->origin, - description, - iMaxDirtyTime); - } - else - { - if (m_bPathErrorTime + 5000 < level.inttime) - { - m_bPathErrorTime = level.inttime; - Com_Printf( - "^~^~^ No destination node specified for '%s' at (%f %f %f)\n", - targetname.c_str(), - origin[0], - origin[1], - origin[2]); - } - ClearPath(); - } -} - -void Actor::FindPathAwayWithLeash - ( - vec3_t vAwayFrom, - vec3_t vDirPreferred, - float fMinSafeDist - ) -{ - m_Path.FindPathAway( - origin, - vAwayFrom, - vDirPreferred, - this, - fMinSafeDist, - m_vHome, - m_fLeashSquared); - ShortenPathToAvoidSquadMates(); -} - -void Actor::FindPathNearWithLeash - ( - vec3_t vNearbyTo, - float fCloseDistSquared - ) -{ - vec2_t dist = {vNearbyTo[0] - m_vHome[0], vNearbyTo[1] - m_vHome[1]}; - float distSq = DotProduct2D(dist,dist); - - if (distSq <= m_fLeashSquared + fCloseDistSquared + 2 * sqrt(m_fLeashSquared * fCloseDistSquared)) - { - dist[0] = origin[0] - m_vHome[0]; - dist[1] = origin[1] - m_vHome[1]; - distSq = DotProduct2D(dist, dist); - if (distSq <= m_fLeashSquared) - { - m_Path.FindPathNear( - origin, - vNearbyTo, - this, - 0, - fCloseDistSquared, - m_vHome, - m_fLeashSquared); - ShortenPathToAvoidSquadMates(); - } - - } -} - -bool Actor::CanMovePathWithLeash - ( - void - ) const -{ - vec2_t delta; - - if( PathExists() ) - { - delta[ 0 ] = origin[ 0 ] - m_vHome[ 0 ]; - delta[ 1 ] = origin[ 1 ] - m_vHome[ 1 ]; - - return ( VectorLength2DSquared( delta ) < m_fLeashSquared ) || ( DotProduct2D( delta, m_Path.CurrentDelta() ) < 0.0f ); - } - - return false; -} - -bool Actor::MovePathWithLeash - ( - void - ) -{ - if( CanMovePathWithLeash() ) - { - Anim_RunToInOpen( 2 ); - FaceMotion(); - return true; - } - else - { - Anim_Aim(); - return false; - } -} - -bool Actor::ShortenPathToAttack - ( - float fMinDist - ) -{ - if (PathExists() && !PathComplete() && PathAvoidsSquadMates()) - { - for (auto current_node = CurrentPathNode(); current_node >= LastPathNode(); current_node--) - { - Vector dist = current_node->point - origin; - if (dist * dist >= fMinDist * fMinDist) - { - if (CanSeeFrom(eyeposition + current_node->point, m_Enemy)) - { - m_Path.TrimPathFromEnd((current_node - LastPathNode()) / 32); - return true; - } - } - } - } - - return false; -} - -void Actor::StrafeToAttack - ( - float fDist, - vec3_t vDir - ) -{ - Vector vEnemyCentroid, vDelta, vSpot, vDestPos; - Vector mins(-16,-16,16); - Vector maxs(16,16,128); - - vDestPos = vDir; - vDestPos *= fDist; - vDestPos += origin; - - vDelta = vDestPos - m_vLastEnemyPos; - - if (m_fMaxDistanceSquared <= vDelta.lengthSquared() || vDelta.lengthSquared() <= m_fMinDistanceSquared ) - { - ClearPath(); - return; - } - if (!G_SightTrace( - origin, - mins, - maxs, - vDestPos, - this, - NULL, - //FIXME: macro - 1107437825, - qtrue, - "Actor::StrafeToAttack 1")) - { - ClearPath(); - return; - } - vSpot = vDir; - vSpot *= fDist; - - vDelta = m_vLastEnemyPos; - vDelta.z += m_Enemy->centroid.z - m_Enemy->origin.z; - - if (!G_SightTrace( - EyePosition() + vSpot, - vec_zero, - vec_zero, - vDelta, - this, - m_Enemy, - //FIXME: macro - 33819417, - qfalse, - "Actor::StrafeToAttack 1")) - { - SetPathWithLeash(vDestPos, NULL, 0); - } - else - { - ClearPath(); - - } -} - -Vector Actor::GunTarget - ( - bool bNoCollision - ) -{ - float accuracy; - static bool doInit = true; - static cvar_t *aiRanges[4]; - Vector vRet; - - if (doInit) - { - aiRanges[0] = gi.Cvar_Get("g_aishortrange", "500", 0); - aiRanges[1] = gi.Cvar_Get("g_aimediumrange", "700", 0); - aiRanges[2] = gi.Cvar_Get("g_ailongrange", "1000", 0); - aiRanges[3] = gi.Cvar_Get("g_aisniperrange", "2200", 0); - doInit = false; - } - - if (mTargetPos == vec_zero) - { - AnglesToAxis(origin, orientation); - vRet = Vector(orientation[0]) * 2048 + EyePosition(); - return vRet; - } - float scatterMult = 1; - - Player *player = NULL; - if (m_Enemy) - { - if (m_Enemy->IsSubclassOfPlayer()) - { - player = (Player *)m_Enemy.Pointer(); - - - Weapon *weap = GetActiveWeapon(WEAPON_MAIN); - Vector dir; - dir = player->centroid - centroid; - - if (weap) - { - - MPrintf("WEAPON RANGE: %f dist: %f\n", aiRanges[weap->mAIRange]->value, dir.length()); - scatterMult = dir.length() / aiRanges[weap->mAIRange]->value; - if (dir.length() > aiRanges[weap->mAIRange]->value) - { - if (scatterMult > 1) - { - accuracy = mAccuracy / scatterMult; - } - MPrintf("OUT OF RANGE - scatterMult: %f\n", scatterMult); - } - } - else - { - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"ERROR Actor::GunTarget without a weapon\\n\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); - assert(false && assertStr); - } - } - else if (fabs(m_Enemy->origin[2] - origin[2]) >= 128) - { - scatterMult = 0.5; - } - } - - if (random2() > accuracy) - { - MPrintf("MISS - scatterMult: %f\n", scatterMult); - - if (player) - { - static cvar_t *scatterHeight; - static cvar_t *scatterWide; - static bool doInitScatters = false; - int lastTrail; - - lastTrail = player->mCurTrailOrigin - 1; - if (lastTrail < 0) - lastTrail = 1; - - vRet = player->mvTrail[lastTrail]; - //continue here: - //Player *tPlayer = player + 12*lastTrail;//weird - if (!G_SightTrace(GunPosition(), vec_zero, vec_zero, player->mvTrail[lastTrail], this, player, 33819417, 0, "Actor::GunTarget 1")) - { - vRet = player->mvTrailEyes[lastTrail]; - } - if (!doInitScatters) - { - scatterWide = gi.Cvar_Get("g_aiScatterWide", "16.0", 0); - scatterHeight = gi.Cvar_Get("g_aiScatterHeight", "45.0", 0); - doInitScatters = true; - } - vRet.x += crandom() * scatterWide->value * scatterMult; - vRet.y += crandom() * scatterWide->value * scatterMult; - vRet.z += crandom() * scatterHeight->value * scatterMult; - - if (player && player->GetVehicleTank()) - { - vRet.z -= 128; - } - } - else - { - int sign; - - if (random() > 0.5) - sign = 1; - else - sign = -1; - vRet.x = sign * 32 * (random() + 1); - - if (random() > 0.5) - sign = 1; - else - sign = -1; - vRet.y = sign * 32 * (random() + 1); - - if (random() > 0.5) - sign = 1; - else - sign = -1; - vRet.z = sign * 48 * (random() + 1); - - vRet += mTargetPos; - - if (player && player->GetVehicleTank()) - { - vRet.z -= 128; - } - } - return vRet; - } - - MPrintf("HIT\n"); - - if (player) - { - vRet = player->centroid; - } - else - { - vRet = mTargetPos; - } - - if (m_Enemy) - { - if (!G_SightTrace(GunPosition(), vec_zero, vec_zero, vRet, this, m_Enemy, 33819417, qfalse, "Actor::GunTarget 1")) - { - vRet = EyePosition(); - } - } - - if (player && player->GetVehicleTank()) - { - vRet.z -= 128; - } - return vRet; -} - -qboolean Actor::setModel - ( - void - ) -{ - str headModel, headSkin, weapon; - headModel = level.GetRandomHeadModel(model); - headSkin = level.GetRandomHeadSkin(model); - //qboolean bSuccess; - str name = "", tempstr; - - if (model != "") - { - if (m_csLoadOut != STRING_EMPTY) - { - - name = "weapon|" + Director.GetString(m_csLoadOut) + "|"; - } - - if (m_csHeadModel == STRING_EMPTY) - { - m_csHeadModel = Director.AddString(level.GetRandomHeadModel(model)); - } - - if (m_csHeadModel != STRING_EMPTY) - { - name += "headmodel|" + Director.GetString(m_csHeadModel) + "|"; - } - - if (m_csHeadSkin == STRING_EMPTY) - { - m_csHeadSkin = Director.AddString(level.GetRandomHeadSkin(model)); - } - - if (m_csHeadSkin != STRING_EMPTY) - { - name += "headskin|" + Director.GetString(m_csHeadSkin) + "|";//FIXME: not sure of this last "|" - } - name += model; - } - gi.DPrintf2("Actor::setModel(): name: %s, model: %s, headModel: %s, headSkin: %s\n", name.c_str(), model.c_str(), headModel.c_str(), headSkin.c_str()); - level.skel_index[edict->s.number] = -1; - return gi.setmodel(edict, name); -} - -void Actor::EventSetHeadModel - ( - Event *ev - ) -{ - - m_csHeadModel = ev->GetConstString(1); - setModel(); -} - -void Actor::EventGetHeadModel - ( - Event *ev - ) -{ - ev->AddConstString(m_csHeadModel); -} - -void Actor::EventSetHeadSkin - ( - Event *ev - ) -{ - m_csHeadSkin = ev->GetConstString(1); - setModel(); -} - -void Actor::EventGetHeadSkin - ( - Event *ev - ) -{ - ev->AddConstString(m_csHeadSkin); -} - -void Actor::EventSetNoIdle - ( - Event *ev - ) -{ - m_bNoIdleAfterAnim = ev->GetInteger(1); -} - -void Actor::EventGetNoIdle - ( - Event *ev - ) -{ - ev->AddInteger(m_bNoIdleAfterAnim); -} - -void Actor::EventGetEnemy - ( - Event *ev - ) -{ - ev->AddListener(m_Enemy); -} - -void Actor::EventSetMaxNoticeTimeScale - ( - Event *ev - ) -{ - float noticeScale; // fst7 - - noticeScale = ev->GetFloat(1); - if (noticeScale <= 0.0) - { - Com_Printf("^~^~^ ERROR: noticescale: value must be greater than 0\n"); - } - else - { - m_fMaxNoticeTimeScale = noticeScale / 100; - } -} - -void Actor::EventGetMaxNoticeTimeScale - ( - Event *ev - ) -{ - - ev->AddFloat(m_fMaxNoticeTimeScale * 100); -} - -void Actor::EventSetFixedLeash - ( - Event *ev - ) -{ - m_bFixedLeash = ev->GetBoolean(1); -} - -void Actor::EventGetFixedLeash - ( - Event *ev - ) -{ - ev->AddInteger(m_bFixedLeash); -} - -void Actor::Holster - ( - void - ) -{ - if (activeWeaponList[0]) - { - DeactivateWeapon(WEAPON_MAIN); - } -} - -void Actor::Unholster - ( - void - ) -{ - Weapon *weap; - - if (!activeWeaponList[0]) - { - weap = GetWeapon(WEAPON_MAIN); - if (weap) - { - useWeapon(weap, WEAPON_MAIN); - ActivateNewWeapon(); - } - } -} - -void Actor::EventHolster - ( - Event *ev - ) -{ - if (activeWeaponList[WEAPON_MAIN]) - { - DeactivateWeapon(WEAPON_MAIN); - } -} - -void Actor::EventUnholster - ( - Event *ev - ) -{ - Unholster(); -} - -void Actor::EventSoundDone - ( - Event *ev - ) -{ - //soundChannel_t - int channel = ev->GetInteger(1); - str name = ev->GetString(2); - if (gi.S_IsSoundPlaying(channel, name)) - { - Event e1(EV_SoundDone); - e1.AddInteger(channel); - e1.AddString(name); - PostEvent(e1, level.frametime); - } - else if (m_bSayAnimSet && m_iSaySlot == -2) //FIXME: macro - { - ChangeSayAnim(); - if (m_csSayAnim == STRING_EMPTY) - { - //gi.DPrintf("unregister STRING_SAYDONE\n"); - Unregister(STRING_SAYDONE); - } - } - else - { - Unregister(STRING_SOUNDDONE); - } -} - -void Actor::EventSound - ( - Event *ev - ) -{ - ProcessSoundEvent(ev, m_Team == TEAM_AMERICAN); -} - -void Actor::EventIsEnemyVisible - ( - Event *ev - ) -{ - ev->AddInteger(m_bEnemyVisible); -} - -void Actor::EventGetEnemyVisibleChangeTime - ( - Event *ev - ) -{ - //FIXME: /100 ?? - ev->AddFloat(m_iEnemyVisibleChangeTime / 100); -} - -void Actor::EventGetLastEnemyVisibleTime - ( - Event *ev - ) -{ - //FIXME: /100 ?? - ev->AddFloat(m_iLastEnemyVisibleTime / 100 ); -} - -void Actor::EventSetFallHeight - ( - Event *ev - ) -{ - float fHeight = ev->GetFloat(1); - - if (fHeight < MIN_FALLHEIGHT) - { - ScriptError("value less than %d not allowed", MIN_FALLHEIGHT); - } - if (fHeight > MAX_FALLHEIGHT) - { - ScriptError("value greater than %d not allowed", MAX_FALLHEIGHT); - } - - m_Path.SetFallHeight(fHeight); -} - -void Actor::EventGetFallHeight - ( - Event *ev - ) -{ - ev->AddFloat(m_Path.GetFallHeight()); -} - -void Actor::EventCanMoveTo - ( - Event *ev - ) -{ - float fIntervalSquared, fDistSquared; - vec2_t vDelta; - Vector vDest; - - vDest = ev->GetVector(1); - VectorSub2D(vDest, m_vHome, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - if (fDistSquared >= m_fLeashSquared) - { - ev->AddInteger(0); - return; - } - else if(m_Enemy != NULL) - { - VectorSub2D(vDest, m_Enemy->origin, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - if (m_fMinDistanceSquared >= fDistSquared || fDistSquared >= m_fMaxDistanceSquared) - { - ev->AddInteger(qfalse); - return; - } - } - if (m_fInterval == 0) - { - for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this ; pSquadMate = pSquadMate->m_pNextSquadMate) - { - float v27, v29, v30, v32, v33, v34, v35, v37, v38; - if (pSquadMate->IsSubclassOfActor()) - { - Sentient *pEnemy = pSquadMate->m_Enemy; - if (pEnemy) - { - v27 = pSquadMate->origin[0]; - v29 = pEnemy->origin[0] - v27; - v30 = pSquadMate->origin[1]; - v32 = pEnemy->origin[1] - v30; - } - else - { - continue; - } - } - else - { - v27 = pSquadMate->origin[0]; - v29 = pSquadMate->orientation[0][0]; - v32 = pSquadMate->orientation[0][1]; - v30 = pSquadMate->origin[1]; - } - v33 = v32 * origin[0]; - v34 = v27 * v32 - v30 * v29; - v35 = v33 - v29 * origin[1] - v34; - v37 = v32 * vDest[0]; - v38 = v37 - v29 * vDest[1] - v34; - - // check if they both have different sign. - if (((int)v38 ^ (int)v35) < 0) - { - ev->AddInteger(qfalse); - return; - } - } - ev->AddInteger(qtrue); - return; - } - - fIntervalSquared = Square(m_fInterval); - - for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) - { - Vector vDel; - vDel = vDest - pSquadMate->origin; - if (fIntervalSquared <= vDest.lengthSquared()) - { - continue; - } - - if ((origin-pSquadMate->origin).lengthSquared() > vDest.lengthSquared()) - { - break; - } - } - ev->AddInteger(qfalse); -} - -void Actor::EventMoveDir - ( - Event *ev - ) -{ - - vec2_t vec; - if (!PathGoalSlowdownStarted()) - { - vec[0] = velocity.x; - vec[1] = velocity.y; - if ( velocity.x == 0 && velocity.y == 0 && PathExists() && !PathComplete()) - { - vec[0] = PathDelta()[0]; - vec[1] = PathDelta()[1]; - } - VectorNormalize2D(vec); - } - - ev->AddVector(vec); -} - -void Actor::EventIntervalDir - ( - Event *ev - ) -{ - //FIXME: macro - if (level.inttime >= m_iIntervalDirTime + 250) - { - m_vIntervalDir = vec_zero; - m_iIntervalDirTime = level.inttime; - if (m_Enemy) - { - m_vIntervalDir = GetAntiBunchPoint() - origin; - if (m_vIntervalDir.x != 0 || m_vIntervalDir.y != 0) - { - VectorNormalizeFast(m_vIntervalDir); - } - } - } - - ev->AddVector(m_vIntervalDir); -} - -void Actor::EventResetLeash - ( - Event *ev - ) -{ - m_vHome = origin; - //delete m_pTetherEnt; - m_pTetherEnt = NULL; -} - -void Actor::EventTether - ( - Event *ev - ) -{ - m_pTetherEnt = ev->GetSimpleEntity(1); -} - -void Actor::EventGetThinkState - ( - Event *ev - ) -{ - ev->AddConstString(m_csThinkStateNames[m_ThinkState]); -} - -void Actor::EventGetEnemyShareRange - ( - Event *ev - ) -{ - ev->AddFloat(m_fMaxShareDistSquared); -} - -void Actor::EventSetEnemyShareRange - ( - Event *ev - ) -{ - float fRange = ev->GetFloat(1); - m_fMaxShareDistSquared = fRange * fRange; -} - -void Actor::EventGetKickDir - ( - Event *ev - ) -{ - ev->AddVector(m_vKickDir); -} - -void Actor::EventGetNoLongPain - ( - Event *ev - ) -{ - ev->AddInteger(m_bNoLongPain); -} - -void Actor::EventSetNoLongPain - ( - Event *ev - ) -{ - m_bNoLongPain = ev->GetBoolean(1); -} - -void Actor::EventGetFavoriteEnemy - ( - Event *ev - ) -{ - ev->AddEntity(m_FavoriteEnemy); -} - -void Actor::EventSetFavoriteEnemy - ( - Event *ev - ) -{ - Sentient *fEnemy = (Sentient*)ev->GetEntity(1); - m_FavoriteEnemy = fEnemy; -} - -void Actor::EventGetMumble - ( - Event *ev - ) -{ - ev->AddInteger(m_bMumble); -} - -void Actor::EventSetMumble - ( - Event *ev - ) -{ - m_bMumble = ev->GetInteger(1); -} - -void Actor::EventGetBreathSteam - ( - Event *ev - ) -{ - ev->AddInteger(m_bBreathSteam); -} - -void Actor::EventSetBreathSteam - ( - Event *ev - ) -{ - m_bBreathSteam = ev->GetInteger(1); -} - -void Actor::EventSetNextBreathTime - ( - Event *ev - ) -{ - ScriptVariable sVar; - ScriptThread *t = Director.CreateThread("global/breathe.scr", "nextbreathtime"); - - sVar.setFloatValue(ev->GetFloat(1)); - t->Execute(&sVar, 1); -} - -void Actor::EventCalcGrenadeToss - ( - Event *ev - ) -{ - //FIXME: macros - Vector vTarget; - vTarget = ev->GetVector(1); - if (DecideToThrowGrenade(vTarget, &m_vGrenadeVel, &m_eGrenadeMode)) - { - if (m_eGrenadeMode == AI_GREN_TOSS_ROLL) - { - ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR); - } - else - { - if (m_eGrenadeMode > AI_GREN_TOSS_ROLL ? m_eGrenadeMode == AI_GREN_TOSS_HINT : m_eGrenadeMode == AI_GREN_TOSS_THROW) - { - ev->AddConstString(STRING_ANIM_GRENADETHROW_SCR); - } - else - { - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"invalid return condition for Actor::EventCalcGrenadeToss\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); - assert(false && assertStr); - } - - } - - SetDesiredYawDir(m_vGrenadeVel); - } - else - { - ev->AddConstString(STRING_EMPTY); - } -} - -void Actor::EventGetNoSurprise - ( - Event *ev - ) -{ - ev->AddInteger(m_bNoSurprise); -} - -void Actor::EventSetNoSurprise - ( - Event *ev - ) -{ - - m_bNoSurprise = ev->GetBoolean(1); -} - -void Actor::EventGetSilent - ( - Event *ev - ) -{ - ev->AddInteger(m_bSilent); -} - -void Actor::EventSetSilent - ( - Event *ev - ) -{ - m_bSilent = ev->GetBoolean(1); -} - -void Actor::EventGetAvoidPlayer - ( - Event *ev - ) -{ - ev->AddInteger(m_bAutoAvoidPlayer); -} - -void Actor::EventSetAvoidPlayer - ( - Event *ev - ) -{ - m_bAutoAvoidPlayer = ev->GetBoolean(1); -} - -void Actor::EventGetLookAroundAngle - ( - Event *ev - ) -{ - //FIXME: weird - //ev->GetFloat(m_fLookAroundFov); - ev->AddFloat(m_fLookAroundFov); -} - -void Actor::EventSetLookAroundAngle - ( - Event *ev - ) -{ - float angle = ev->GetFloat(1); - if (angle < 0.0 || angle > 60.0) - { - ScriptError("lookaroundangle must be >= 0 and <= 60"); - } - m_fLookAroundFov = angle; -} - -void Actor::EventHasCompleteLookahead - ( - Event *ev - ) -{ - int completeLH = PathExists() && PathHasCompleteLookahead(); - - ev->AddInteger(completeLH); -} - -void Actor::EventPathDist - ( - Event *ev - ) -{ - float dist = 0; - if (PathExists() && !PathComplete()) - { - dist = PathDist(); - } - ev->AddFloat(dist); -} - -void Actor::EventCanShootEnemyFrom - ( - Event *ev - ) -{ - int canShoot = false; - if (m_Enemy) - { - canShoot = CanSeeFrom(ev->GetVector(1), m_Enemy); - } - ev->AddInteger(canShoot); -} - -void Actor::EventCanShoot - ( - Event *ev - ) -{ - Entity *target = ev->GetEntity(1); - - if (!target) - { - ScriptError("canshoot applied to null listener"); - } - - ev->AddInteger(CanShoot(target)); -} - -void Actor::EventSetInReload - ( - Event *ev - ) -{ - - m_bInReload = ev->GetBoolean(1); -} - -void Actor::EventGetInReload - ( - Event *ev - ) -{ - ev->AddInteger(m_bInReload); -} - -void Actor::EventSetReloadCover - ( - Event *ev - ) -{ - m_bNeedReload = ev->GetBoolean(1); -} - -void Actor::EventBreakSpecial - ( - Event *ev - ) -{ - mbBreakSpecialAttack = true; -} - -void Actor::GetVoiceType - ( - Event *ev - ) -{ - //voice type in actor is a char. - const char *vType = va("%c", mVoiceType); - str vTypeStr = vType; - ev->AddString(vTypeStr); -} - -void Actor::SetVoiceType - ( - Event *ev - ) -{ - //voice type in actor is a char. - str vType = ev->GetString(1); - if (vType[0]) - { - mVoiceType = vType[0]; - } - else - { - //FIXME: enum - mVoiceType = -1; - } -} - -void Actor::ResolveVoiceType - ( - void - ) -{ - char validVoice[128]; - - if (mVoiceType == -1) - { - int d = 3.0 * 0.99 * random(); - if (m_Team == TEAM_AMERICAN) - { - mVoiceType = gAmericanVoices[d][0]; - } - else - { - mVoiceType = gGermanVoices[d][0]; - } - } - else - { - if (m_Team == TEAM_AMERICAN) - { - for (int i = 0; i < 3 ; i++) - { - if (gAmericanVoices[i][0] == mVoiceType) - { - return; - } - } - - validVoice[0] = '\0'; - for (int i = 0; i < 3; i++) - { - strcat(validVoice, gAmericanVoices[i]); - strcat(validVoice, " "); - } - Com_Printf("ERROR: Bad voice type %c. Valid American voicetypes are: %s\n", mVoiceType, validVoice); - mVoiceType = -1; - - int d = 3.0 * 0.99 * random(); - mVoiceType = gAmericanVoices[d][0]; - } - else - { - - for (int i = 0; i < 3; i++) - { - if (gGermanVoices[i][0] == mVoiceType) - { - return; - } - } - - validVoice[0] = '\0'; - for (int i = 0; i < 3; i++) - { - strcat(validVoice, gGermanVoices[i]); - strcat(validVoice, " "); - } - Com_Printf("ERROR: Bad voice type %c. Valid German voicetypes are: %s\n", mVoiceType, validVoice); - mVoiceType = -1; - - int d = 3.0 * 0.99 * random(); - mVoiceType = gGermanVoices[d][0]; - } - - } -} - -void Actor::EventSetBalconyHeight - ( - Event *ev - ) -{ - m_fBalconyHeight = ev->GetFloat(1); -} - -void Actor::EventGetBalconyHeight - ( - Event *ev - ) -{ - ev->AddFloat(m_fBalconyHeight); -} - -PathNode *Actor::FindSniperNodeAndSetPath - ( - bool *pbTryAgain - ) -{ - PathNode *pSniperNode = PathManager.FindNearestSniperNode( this, origin, m_Enemy ); - - if( pSniperNode ) - { - SetPathWithLeash( pSniperNode, NULL, 0 ); - - if( PathExists() && ( PathComplete() || PathAvoidsSquadMates() ) ) - { - *pbTryAgain = true; - return pSniperNode; - } - - pSniperNode->MarkTemporarilyBad(); - *pbTryAgain = false; - } - else - { - *pbTryAgain = true; - } - - return NULL; -} - -void Actor::Remove - ( - Event *ev - ) -{ - EndStates(); - - if (deadflag != DEAD_DEAD) - { - health = 0; - deadflag = DEAD_DEAD; - } - - Delete(); -} - -void Actor::DontFaceWall - ( - void - ) -{ - //PathNode *pNode; - vec2_t vDelta; - float /*fErrorLerp,*/ fEyeRadius, fCosAngle, fSinAngle, fAngle, fAngleRad, fTime; - Vector start; - Vector end; - - //FIXME: macro: AI_* - if (m_pCoverNode && m_pCoverNode->nodeflags & (AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE)) - { - m_eDontFaceWallMode = 1; - return; - } - - if (velocity.lengthXYSquared() > Square(8)) - { - m_eDontFaceWallMode = 2; - return; - } - - fAngle = AngleNormalize360(m_YawAchieved ? angles.y : m_DesiredYaw); - - fTime = (level.time - m_fDfwTime) * 0.5; - if (fTime > 1) - { - fTime = 1; - } - - - VectorSub2D(m_vDfwPos, origin, vDelta); - - if (Square(fTime * -14.0 + 16.0) > VectorLength2DSquared(vDelta) - && (fabs(AngleNormalize180(m_fDfwRequestedYaw - m_DesiredYaw)) <= fTime * -29.0 + 30.0 - || fabs(AngleNormalize180(m_fDfwDerivedYaw - m_DesiredYaw)) <= fTime * -29.0 + 30.0) - ) - { - if (m_eDontFaceWallMode <= 8) - { - SetDesiredYaw(m_fDfwDerivedYaw); - } - } - else - { - m_vDfwPos = origin; - m_fDfwRequestedYaw = fAngle; - m_fDfwTime = level.time; - - fAngleRad = fAngle * M_PI / 180; - fSinAngle = sin(fAngleRad); - fCosAngle = cos(fAngleRad); - - VectorSub2D(EyePosition(), origin, vDelta); - fEyeRadius = VectorLength2D(vDelta); - - start = vec_zero; - start.x = fEyeRadius * fCosAngle + origin.x; - start.y = fEyeRadius * fSinAngle + origin.y; - - end = vec_zero; - end.x = 64 * fCosAngle + start.x; - end.x = 64 * fSinAngle + start.y; - trace_t trace = G_Trace(start, vec_zero, vec_zero, end, this, 33819417, qfalse, "Actor::DontFaceWall"); - if (trace.entityNum == 1023 || trace.fraction >= 1 || trace.startsolid) - { - m_eDontFaceWallMode = 3; - } - else if (trace.entityNum == 1022 || trace.ent->entity->AIDontFace()) - { - if (trace.plane.normal[2] < -0.69999999 || trace.plane.normal[2] > 0.69999999) - { - m_eDontFaceWallMode = 5; - } - else - { - if (m_Enemy && Vector::Dot(trace.plane.normal, m_Enemy->origin) - trace.plane.dist < 0 ) - { - end = m_Enemy->origin; - } - else - { - end = start + (end - start)*128; - } - - - PathNode *node = PathManager.FindCornerNodeForWall(origin, end, this, 0.0f, trace.plane.normal); - if (node) - { - - VectorSub2D(node->m_PathPos, origin, vDelta); - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } - m_eDontFaceWallMode = 6; - } - else if (trace.fraction <= 0.46875) - { - SetDesiredYawDir(trace.plane.normal); - m_eDontFaceWallMode = 7; - } - else - { - if (m_DesiredYaw < 90.0) - m_DesiredYaw += 270.0; - else - m_DesiredYaw -= 90.0; - - m_YawAchieved = false; - m_eDontFaceWallMode = 8; - } - m_fDfwDerivedYaw = m_DesiredYaw; - return; - } - } - else - { - m_eDontFaceWallMode = 4; - } - - m_fDfwDerivedYaw = m_fDfwRequestedYaw; - } - -} - -bool Actor::AvoidingFacingWall - ( - void - ) const -{ - return m_eDontFaceWallMode <= 8; -} - -void Actor::EndStates - ( - void - ) -{ - for (int i = 0; i < NUM_THINKLEVELS; i++) - { - GlobalFuncs_t *func = &GlobalFuncs[m_Think[i]]; - - if (func->EndState) - (this->*func->EndState)(); - - if (m_pAnimThread) - { - m_pAnimThread->AbortRegistration(STRING_EMPTY, this); - } - } -} - -void Actor::ClearStates - ( - void - ) -{ - for (int i = 0; i < NUM_THINKSTATES; i++) - { - SetThink((eThinkState)i, THINK_VOID); - } -} - -void Actor::CheckUnregister - ( - void - ) -{ - m_bBecomeRunner = false; - if (parm.movefail) - { - parm.movedone = false; - Unregister(STRING_MOVEDONE); - } - if (m_Enemy) - { - Unregister(STRING_HASENEMY); - } - if (m_bEnemyVisible) - { - Unregister(STRING_VISIBLE); - } -} - -void Actor::BecomeCorpse - ( - void - ) -{ - Event e1(EV_DeathSinkStart); - - AddToBodyQue(); - - edict->r.contents = CONTENTS_TRIGGER; - edict->r.svFlags &= ~SVF_USE_CURRENT_ORIGIN; - setSolidType(SOLID_NOT); - movetype = MOVETYPE_NONE; - edict->s.renderfx &= ~RF_SHADOW; - - - PostEvent(e1, 20); -} - -void Actor::PathnodeClaimRevoked - ( - PathNode *node - ) -{ - for (int i = m_ThinkLevel; i >= 0; --i) - { - - - GlobalFuncs_t *func = &GlobalFuncs[m_Think[i]]; - if (func->PathnodeClaimRevoked) - (this->*func->PathnodeClaimRevoked)(); - } - node->Relinquish(); - m_pCoverNode = NULL; -} - -void Actor::SetPathToNotBlockSentient - ( - Sentient *pOther - ) -{ - Vector vDest, vPerp, vAway; - - if (pOther) - { - if (!pOther->IsDead()) - { - if (IsTeamMate(pOther)) - { - if (pOther->velocity.lengthSquared() > 1) - { - vDest = origin - pOther->origin; - if (vDest.lengthSquared() < 2304 && DotProduct2D(pOther->velocity, vDest) > 0) - { - if (CrossProduct2D(vDest, pOther->velocity) >= 0) - { - vPerp.x = -pOther->velocity.y; - vPerp.y = pOther->velocity.x; - vPerp.z = 0; - } - else - { - vPerp.x = pOther->velocity.y; - vPerp.y = -pOther->velocity.x; - vPerp.z = 0; - } - - VectorNormalizeFast(vPerp); - - vAway = vPerp * 48 + origin; - - if (G_SightTrace( - vAway, - mins, - maxs, - vAway, - this, - pOther, - 33557249, - 0, - "Actor::SetPathToNotBlockSentient 1")) - { - SetPathWithinDistance(vAway, NULL, 96, 0); - } - - if (!PathExists()) - { - vAway = vDest; - VectorNormalizeFast(vAway); - - vAway = vAway * 48 + origin; - if (G_SightTrace( - vAway, - mins, - maxs, - vAway, - this, - pOther, - 33557249, - 0, - "Actor::SetPathToNotBlockSentient 2")) - { - SetPathWithinDistance(vAway, NULL, 96, 0); - } - - if (!PathExists()) - { - vAway = vPerp * 48 - origin; - if (G_SightTrace( - vAway, - mins, - maxs, - vAway, - this, - pOther, - 33557249, - 0, - "Actor::SetPathToNotBlockSentient 3")) - { - SetPathWithinDistance(vAway, NULL, 96, 0); - } - - if (!PathExists()) - { - vAway = vDest; - VectorNormalizeFast(vAway); - - FindPathAway(origin, vAway * 100, 96); - - } - } - - } - } - } - } - } - } -} - -void Actor::EventSetMoveDoneRadius - ( - Event *ev - ) -{ - float moveDoneR = ev->GetFloat(1); - m_fMoveDoneRadiusSquared = Square(moveDoneR); -} - - -bool Actor::CalcFallPath - ( - void - ) -{ - float startTime, animTime, startDeltaTime, nextTime; - vec3_t vAbsDelta, vRelDelta, pos[200]; - int anim, loop, /*currentPos,*/ i; - mmove_t mm; - - SetMoveInfo(&mm); - - mm.desired_speed = 80; - mm.tracemask &= 0xFDFFF4FF; - - VectorCopy2D(orientation[0], mm.desired_dir); - - anim = gi.Anim_NumForName(edict->tiki, "death_balcony_intro"); - animTime = gi.Anim_Time(edict->tiki, anim); - - startTime = 0.65F; - - i = 0; - while (true) - { - MmoveSingle(&mm); - - i++; - VectorCopy(mm.origin, pos[i]); - - if (i >= 200) - { - break; - } - - if (mm.hit_obstacle) - { - for (float j = 0.65f; j < animTime; j = nextTime) - { - nextTime = j + level.frametime; - if (nextTime >= animTime - 0.01f) - nextTime = animTime; - startDeltaTime = j; - gi.Anim_DeltaOverTime( - edict->tiki, - anim, - startDeltaTime, - nextTime, - vAbsDelta); - MatrixTransformVector(vAbsDelta, orientation, vRelDelta); - - i++; - - VectorAdd(vRelDelta, mm.origin, mm.origin); - VectorCopy(mm.origin, pos[i]); - - if (i >= 200) - return false; - } - mm.desired_speed = 0; - mm.groundPlane = qfalse; - mm.walking = qfalse; - mm.velocity[0] = 0; - mm.velocity[1] = 0; - mm.velocity[2] = -171; - - loop = i; - - while (true) - { - MmoveSingle(&mm); - - i++; - VectorCopy(mm.origin, pos[i]); - - if (i >= 200) - { - break; - } - - if (mm.hit_obstacle) - return false; - - if (mm.groundPlane) - { - if (m_fBalconyHeight > origin[2] - pos[i][2]) - return false; - - m_pFallPath = (FallPath *)gi.Malloc((sizeof(FallPath::pos)) * i + (sizeof(FallPath) - sizeof(FallPath::pos))); - - m_pFallPath->length = i; - - m_pFallPath->currentPos = 0; - m_pFallPath->startTime = startTime; - m_pFallPath->loop = loop; - - if (i > 0) - { - for (int j = i; j ; j--) - { - VectorCopy(pos[j], m_pFallPath->pos[j]); - } - } - return true; - } - } - - return false; - } - - - if (mm.groundPlane) - { - startTime -= level.frametime; - if (startTime >= 0) - continue; - } - return false; - } - return false; - -} - -void Actor::ClearEnemies - ( - void - ) -{ - m_PotentialEnemies.RemoveAll(); - SetEnemy( NULL, false ); -} - -bool Actor::EnemyIsDisguised - ( - void - ) -{ - return ( m_bEnemyIsDisguised || (m_Enemy && m_Enemy->m_bIsDisguised) ) && ( !m_bForceAttackPlayer && m_ThinkState != THINKSTATE_ATTACK ); -} - -void Actor::setOriginEvent - ( - Vector org - ) -{ - bool bRejoin = false; - //FIXME: macro - if ((org - origin).lengthSquared() > Square(1024)) - { - bRejoin = true; - DisbandSquadMate(this); - } - - m_iOriginTime = level.inttime; - - VectorCopy2D(org, m_vOriginHistory[0]); - VectorCopy2D(org, m_vOriginHistory[1]); - VectorCopy2D(org, m_vOriginHistory[2]); - - VectorClear(velocity); - - if (level.Spawned()) - { - SafeSetOrigin(org); - } - else - { - setOrigin(org); - } - - m_vHome = origin; - - if (bRejoin) - { - //FIXME: macro - JoinNearbySquads(); - } -} - -void Actor::DumpAnimInfo - ( - void - ) -{ - Animate::DumpAnimInfo(); - Vector desiredLook = m_bHasDesiredLookAngles ? m_DesiredLookAngles : vec_zero; - //FIXME: macros: bones - Vector head = GetControllerAngles(HEAD_TAG); - Vector torso = GetControllerAngles(TORSO_TAG); - MPrintf("Desired look yaw: %.1f, pitch: %.1f. Head yaw: %.1f, pitch %.1f. Torso yaw: %.1f, pitch: %.1f\n", - desiredLook.x, - desiredLook.y, - head.x, - head.y, - torso.x, - torso.y - ); - -} - -bool Actor::AutoArchiveModel - ( - void - ) -{ - return false; -} +void Actor::ExtractConstraints(mmove_t *mm) {} diff --git a/code/fgame/actor.h b/code/fgame/actor.h index 7b91c024..7274f8ce 100644 --- a/code/fgame/actor.h +++ b/code/fgame/actor.h @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // actor.h: Base class for character AI. -#ifndef __ACTOR_H__ -#define __ACTOR_H__ +#pragma once #include "g_local.h" #include "simpleactor.h" @@ -137,271 +136,446 @@ extern Event EV_Actor_DeathEmbalm; // Bones used by actor //#define ACTOR_MOUTH_TAG 0 -#define ACTOR_HEAD_TAG 0 -#define ACTOR_TORSO_TAG 1 +#define ACTOR_HEAD_TAG 0 +#define ACTOR_TORSO_TAG 1 // Dialog stuff -#define LIP_SYNC_HZ 20.0 +#define LIP_SYNC_HZ 20.0 #define MAX_DIALOG_PARAMETERS_LENGTH 100 -#define MAX_DIALOG_PARM_LENGTH 64 -#define MAX_DIALOG_PARMS 10 +#define MAX_DIALOG_PARM_LENGTH 64 +#define MAX_DIALOG_PARMS 10 -#define DIALOG_PARM_TYPE_NONE 0 -#define DIALOG_PARM_TYPE_PLAYERHAS 1 -#define DIALOG_PARM_TYPE_PLAYERHASNOT 2 -#define DIALOG_PARM_TYPE_HAS 3 -#define DIALOG_PARM_TYPE_HASNOT 4 -#define DIALOG_PARM_TYPE_DEPENDS 5 -#define DIALOG_PARM_TYPE_DEPENDSNOT 6 +#define DIALOG_PARM_TYPE_NONE 0 +#define DIALOG_PARM_TYPE_PLAYERHAS 1 +#define DIALOG_PARM_TYPE_PLAYERHASNOT 2 +#define DIALOG_PARM_TYPE_HAS 3 +#define DIALOG_PARM_TYPE_HASNOT 4 +#define DIALOG_PARM_TYPE_DEPENDS 5 +#define DIALOG_PARM_TYPE_DEPENDSNOT 6 -typedef struct -{ - byte type; - char parm[ MAX_DIALOG_PARM_LENGTH ]; +typedef struct { + byte type; + char parm[MAX_DIALOG_PARM_LENGTH]; } DialogParm_t; -typedef struct DialogNode_s -{ - char alias_name[MAX_ALIAS_NAME_LENGTH]; - int random_flag; - int number_of_parms; - float random_percent; - DialogParm_t parms[MAX_DIALOG_PARMS]; - struct DialogNode_s *next; +typedef struct DialogNode_s { + char alias_name[MAX_ALIAS_NAME_LENGTH]; + int random_flag; + int number_of_parms; + float random_percent; + DialogParm_t parms[MAX_DIALOG_PARMS]; + struct DialogNode_s *next; } DialogNode_t; -typedef enum -{ - IS_INANIMATE, - IS_MONSTER, - IS_ENEMY, - IS_CIVILIAN, - IS_FRIEND, - IS_ANIMAL, - NUM_ACTORTYPES +typedef enum { + IS_INANIMATE, + IS_MONSTER, + IS_ENEMY, + IS_CIVILIAN, + IS_FRIEND, + IS_ANIMAL, + NUM_ACTORTYPES } actortype_t; // Stimuli types -#define STIMULI_ALL -1 -#define STIMULI_NONE 0 -#define STIMULI_SIGHT (1<<0) -#define STIMULI_SOUND (1<<1) -#define STIMULI_PAIN (1<<2) -#define STIMULI_SCRIPT (1<<3) +#define STIMULI_ALL -1 +#define STIMULI_NONE 0 +#define STIMULI_SIGHT (1 << 0) +#define STIMULI_SOUND (1 << 1) +#define STIMULI_PAIN (1 << 2) +#define STIMULI_SCRIPT (1 << 3) #define MAX_INACTIVE_TIME 30.0 // State flags -#define STATE_FLAG_IN_PAIN (1<<0) -#define STATE_FLAG_MELEE_HIT (1<<1) -#define STATE_FLAG_TOUCHED (1<<2) -#define STATE_FLAG_ACTIVATED (1<<3) -#define STATE_FLAG_USED (1<<4) -#define STATE_FLAG_TWITCH (1<<5) -#define STATE_FLAG_BLOCKED_HIT (1<<6) -#define STATE_FLAG_SMALL_PAIN (1<<7) -#define STATE_FLAG_OTHER_DIED (1<<8) -#define STATE_FLAG_STUCK (1<<9) -#define STATE_FLAG_NO_PATH (1<<10) +#define STATE_FLAG_IN_PAIN (1 << 0) +#define STATE_FLAG_MELEE_HIT (1 << 1) +#define STATE_FLAG_TOUCHED (1 << 2) +#define STATE_FLAG_ACTIVATED (1 << 3) +#define STATE_FLAG_USED (1 << 4) +#define STATE_FLAG_TWITCH (1 << 5) +#define STATE_FLAG_BLOCKED_HIT (1 << 6) +#define STATE_FLAG_SMALL_PAIN (1 << 7) +#define STATE_FLAG_OTHER_DIED (1 << 8) +#define STATE_FLAG_STUCK (1 << 9) +#define STATE_FLAG_NO_PATH (1 << 10) // Actor modes -#define ACTOR_MODE_NONE 0 -#define ACTOR_MODE_IDLE 1 -#define ACTOR_MODE_AI 2 -#define ACTOR_MODE_SCRIPT 3 -#define ACTOR_MODE_TALK 4 +#define ACTOR_MODE_NONE 0 +#define ACTOR_MODE_IDLE 1 +#define ACTOR_MODE_AI 2 +#define ACTOR_MODE_SCRIPT 3 +#define ACTOR_MODE_TALK 4 // Pain types -#define PAIN_SMALL 0 -#define PAIN_BIG 1 +#define PAIN_SMALL 0 +#define PAIN_BIG 1 -typedef struct -{ - EntityPtr ent; - unsigned int state_flags; +typedef struct { + EntityPtr ent; + unsigned int state_flags; } part_t; // Actor flags -#define ACTOR_FLAG_NOISE_HEARD 0 -#define ACTOR_FLAG_INVESTIGATING 1 -#define ACTOR_FLAG_DEATHGIB 2 -#define ACTOR_FLAG_DEATHFADE 3 -#define ACTOR_FLAG_NOCHATTER 4 -#define ACTOR_FLAG_INACTIVE 5 -#define ACTOR_FLAG_ANIM_DONE 6 -#define ACTOR_FLAG_STATE_DONE_TIME_VALID 7 -#define ACTOR_FLAG_AI_ON 8 -#define ACTOR_FLAG_LAST_CANSEEENEMY 9 -#define ACTOR_FLAG_LAST_CANSEEENEMY_NOFOV 10 -#define ACTOR_FLAG_DIALOG_PLAYING 11 -#define ACTOR_FLAG_ALLOW_TALK 12 -#define ACTOR_FLAG_DAMAGE_ONCE_ON 13 -#define ACTOR_FLAG_DAMAGE_ONCE_DAMAGED 14 -#define ACTOR_FLAG_BOUNCE_OFF 15 -#define ACTOR_FLAG_NOTIFY_OTHERS_AT_DEATH 16 -#define ACTOR_FLAG_HAS_THING1 17 -#define ACTOR_FLAG_HAS_THING2 18 -#define ACTOR_FLAG_HAS_THING3 19 -#define ACTOR_FLAG_HAS_THING4 20 -#define ACTOR_FLAG_LAST_ATTACK_HIT 21 -#define ACTOR_FLAG_STARTED 22 -#define ACTOR_FLAG_ALLOW_HANGBACK 23 -#define ACTOR_FLAG_USE_GRAVITY 24 -#define ACTOR_FLAG_SPAWN_FAILED 25 -#define ACTOR_FLAG_FADING_OUT 26 -#define ACTOR_FLAG_DEATHSHRINK 27 -#define ACTOR_FLAG_DEATHSINK 28 -#define ACTOR_FLAG_STAYSOLID 29 -#define ACTOR_FLAG_STUNNED 30 -#define ACTOR_FLAG_ALLOW_FALL 31 -#define ACTOR_FLAG_FINISHED 32 -#define ACTOR_FLAG_IN_LIMBO 33 -#define ACTOR_FLAG_CAN_WALK_ON_OTHERS 34 -#define ACTOR_FLAG_PUSHABLE 35 -#define ACTOR_FLAG_LAST_TRY_TALK 36 -#define ACTOR_FLAG_ATTACKABLE_BY_ACTORS 37 -#define ACTOR_FLAG_TARGETABLE 38 -#define ACTOR_FLAG_ATTACK_ACTORS 39 -#define ACTOR_FLAG_IMMORTAL 40 -#define ACTOR_FLAG_TURNING_HEAD 41 -#define ACTOR_FLAG_DIE_COMPLETELY 42 -#define ACTOR_FLAG_BLEED_AFTER_DEATH 43 -#define ACTOR_FLAG_IGNORE_STUCK_WARNING 44 -#define ACTOR_FLAG_IGNORE_OFF_GROUND_WARNING 45 -#define ACTOR_FLAG_ALLOWED_TO_KILL 46 -#define ACTOR_FLAG_TOUCH_TRIGGERS 47 -#define ACTOR_FLAG_IGNORE_WATER 48 -#define ACTOR_FLAG_NEVER_IGNORE_SOUNDS 49 -#define ACTOR_FLAG_SIMPLE_PATHFINDING 50 -#define ACTOR_FLAG_HAVE_MOVED 51 -#define ACTOR_FLAG_NO_PAIN_SOUNDS 52 -#define ACTOR_FLAG_UPDATE_BOSS_HEALTH 53 -#define ACTOR_FLAG_IGNORE_PAIN_FROM_ACTORS 54 -#define ACTOR_FLAG_DAMAGE_ALLOWED 55 -#define ACTOR_FLAG_ALWAYS_GIVE_WATER 56 +#define ACTOR_FLAG_NOISE_HEARD 0 +#define ACTOR_FLAG_INVESTIGATING 1 +#define ACTOR_FLAG_DEATHGIB 2 +#define ACTOR_FLAG_DEATHFADE 3 +#define ACTOR_FLAG_NOCHATTER 4 +#define ACTOR_FLAG_INACTIVE 5 +#define ACTOR_FLAG_ANIM_DONE 6 +#define ACTOR_FLAG_STATE_DONE_TIME_VALID 7 +#define ACTOR_FLAG_AI_ON 8 +#define ACTOR_FLAG_LAST_CANSEEENEMY 9 +#define ACTOR_FLAG_LAST_CANSEEENEMY_NOFOV 10 +#define ACTOR_FLAG_DIALOG_PLAYING 11 +#define ACTOR_FLAG_ALLOW_TALK 12 +#define ACTOR_FLAG_DAMAGE_ONCE_ON 13 +#define ACTOR_FLAG_DAMAGE_ONCE_DAMAGED 14 +#define ACTOR_FLAG_BOUNCE_OFF 15 +#define ACTOR_FLAG_NOTIFY_OTHERS_AT_DEATH 16 +#define ACTOR_FLAG_HAS_THING1 17 +#define ACTOR_FLAG_HAS_THING2 18 +#define ACTOR_FLAG_HAS_THING3 19 +#define ACTOR_FLAG_HAS_THING4 20 +#define ACTOR_FLAG_LAST_ATTACK_HIT 21 +#define ACTOR_FLAG_STARTED 22 +#define ACTOR_FLAG_ALLOW_HANGBACK 23 +#define ACTOR_FLAG_USE_GRAVITY 24 +#define ACTOR_FLAG_SPAWN_FAILED 25 +#define ACTOR_FLAG_FADING_OUT 26 +#define ACTOR_FLAG_DEATHSHRINK 27 +#define ACTOR_FLAG_DEATHSINK 28 +#define ACTOR_FLAG_STAYSOLID 29 +#define ACTOR_FLAG_STUNNED 30 +#define ACTOR_FLAG_ALLOW_FALL 31 +#define ACTOR_FLAG_FINISHED 32 +#define ACTOR_FLAG_IN_LIMBO 33 +#define ACTOR_FLAG_CAN_WALK_ON_OTHERS 34 +#define ACTOR_FLAG_PUSHABLE 35 +#define ACTOR_FLAG_LAST_TRY_TALK 36 +#define ACTOR_FLAG_ATTACKABLE_BY_ACTORS 37 +#define ACTOR_FLAG_TARGETABLE 38 +#define ACTOR_FLAG_ATTACK_ACTORS 39 +#define ACTOR_FLAG_IMMORTAL 40 +#define ACTOR_FLAG_TURNING_HEAD 41 +#define ACTOR_FLAG_DIE_COMPLETELY 42 +#define ACTOR_FLAG_BLEED_AFTER_DEATH 43 +#define ACTOR_FLAG_IGNORE_STUCK_WARNING 44 +#define ACTOR_FLAG_IGNORE_OFF_GROUND_WARNING 45 +#define ACTOR_FLAG_ALLOWED_TO_KILL 46 +#define ACTOR_FLAG_TOUCH_TRIGGERS 47 +#define ACTOR_FLAG_IGNORE_WATER 48 +#define ACTOR_FLAG_NEVER_IGNORE_SOUNDS 49 +#define ACTOR_FLAG_SIMPLE_PATHFINDING 50 +#define ACTOR_FLAG_HAVE_MOVED 51 +#define ACTOR_FLAG_NO_PAIN_SOUNDS 52 +#define ACTOR_FLAG_UPDATE_BOSS_HEALTH 53 +#define ACTOR_FLAG_IGNORE_PAIN_FROM_ACTORS 54 +#define ACTOR_FLAG_DAMAGE_ALLOWED 55 +#define ACTOR_FLAG_ALWAYS_GIVE_WATER 56 +// Look flags + +#define LOOK_FLAG_EYE (1 << 0) // The last actor_flag number and this one (ACTOR_FLAG_MAX) should match -#define ACTOR_FLAG_MAX 56 +#define ACTOR_FLAG_MAX 56 -#define MAX_ORIGIN_HISTORY 4 -#define MAX_COVER_NODES 16 -#define MAX_BODYQUEUE 5 +#define MAX_ORIGIN_HISTORY 4 +#define MAX_COVER_NODES 16 +#define MAX_BODYQUEUE 5 -typedef enum -{ - AI_GREN_TOSS_NONE, - AI_GREN_TOSS_THROW, - AI_GREN_TOSS_ROLL, - AI_GREN_TOSS_HINT, - AI_GREN_KICK +typedef enum { + AI_GREN_TOSS_NONE, + AI_GREN_TOSS_THROW, + AI_GREN_TOSS_ROLL, + AI_GREN_TOSS_HINT, + AI_GREN_KICK } eGrenadeTossMode; -typedef enum -{ - AI_GRENSTATE_FLEE, - AI_GRENSTATE_THROW_ACQUIRE, - AI_GRENSTATE_THROW, - AI_GRENSTATE_KICK_ACQUIRE, - AI_GRENSTATE_KICK, - AI_GRENSTATE_MARTYR_ACQUIRE, - AI_GRENSTATE_MARTYR, - AI_GRENSTATE_UNK, - AI_GRENSTATE_FLEE_SUCCESS, //fled the grenade succesfully, i'm safe - AI_GRENSTATE_FLEE_FAIL, //failed to flee, I'm gonna get hurt or die :'( +typedef enum { + AI_GRENSTATE_FLEE, + AI_GRENSTATE_THROW_ACQUIRE, + AI_GRENSTATE_THROW, + AI_GRENSTATE_KICK_ACQUIRE, + AI_GRENSTATE_KICK, + AI_GRENSTATE_MARTYR_ACQUIRE, + AI_GRENSTATE_MARTYR, + AI_GRENSTATE_UNK, + AI_GRENSTATE_FLEE_SUCCESS, //fled the grenade successfully, I'm safe + AI_GRENSTATE_FLEE_FAIL, //failed to flee, I'm gonna get hurt or die :'( } eGrenadeState; typedef struct { - byte length; - byte currentPos; - byte loop; - float startTime; - vec3_t pos[ 1 ]; + byte length; + byte currentPos; + byte loop; + float startTime; + vec3_t pos[1]; } FallPath; -enum eThinkState -{ - THINKSTATE_VOID, - THINKSTATE_IDLE, - THINKSTATE_PAIN, - THINKSTATE_KILLED, - THINKSTATE_ATTACK, - THINKSTATE_CURIOUS, - THINKSTATE_DISGUISE, - THINKSTATE_GRENADE, - THINKSTATE_NOCLIP, - NUM_THINKSTATES, +enum eThinkState { + THINKSTATE_VOID, + THINKSTATE_IDLE, + THINKSTATE_PAIN, + THINKSTATE_KILLED, + THINKSTATE_ATTACK, + THINKSTATE_CURIOUS, + THINKSTATE_DISGUISE, + THINKSTATE_BADPLACE, // Added in 2.0 + THINKSTATE_GRENADE, + THINKSTATE_NOCLIP, + NUM_THINKSTATES, }; -#define AI_EVENT_NONE 0 -#define AI_EVENT_WEAPON_FIRE 1 -#define AI_EVENT_WEAPON_IMPACT 2 -#define AI_EVENT_EXPLOSION 3 -#define AI_EVENT_AMERICAN_VOICE 4 -#define AI_EVENT_GERMAN_VOICE 5 -#define AI_EVENT_AMERICAN_URGENT 6 -#define AI_EVENT_GERMAN_URGENT 7 -#define AI_EVENT_MISC 8 -#define AI_EVENT_MISC_LOUD 9 -#define AI_EVENT_FOOTSTEP 10 -#define AI_EVENT_GRENADE 11 - -enum eThinkNum -{ - THINK_VOID, - THINK_TURRET, - THINK_COVER, - THINK_PATROL, - THINK_RUNNER, - THINK_PAIN, - THINK_KILLED, - THINK_MOVETO, - THINK_IDLE, - THINK_CURIOUS, - THINK_DISGUISE_SALUTE, - THINK_DISGUISE_SENTRY, - THINK_DISGUISE_OFFICER, - THINK_DISGUISE_ROVER, - THINK_DISGUISE_NONE, - THINK_ALARM, - THINK_GRENADE, - THINK_MACHINEGUNNER, - THINK_DOG_IDLE, - THINK_DOG_ATTACK, - THINK_DOG_CURIOUS, - THINK_DOG_GRENADE, - THINK_ANIM, - THINK_ANIM_CURIOUS, - THINK_AIM, - THINK_BALCONY_IDLE, - THINK_BALCONY_CURIOUS, - THINK_BALCONY_ATTACK, - THINK_BALCONY_DISGUISE, - THINK_BALCONY_GRENADE, - THINK_BALCONY_PAIN, - THINK_BALCONY_KILLED, - THINK_WEAPONLESS, - THINK_NOCLIP, - THINK_DEAD, - NUM_THINKS, +enum eThinkNum { + THINK_VOID, + THINK_TURRET, + THINK_COVER, + THINK_PATROL, + THINK_RUNNER, + THINK_PAIN, + THINK_KILLED, + THINK_MOVETO, + THINK_IDLE, + THINK_CURIOUS, + THINK_DISGUISE_SALUTE, + THINK_DISGUISE_SENTRY, + THINK_DISGUISE_OFFICER, + THINK_DISGUISE_ROVER, + THINK_DISGUISE_NONE, + THINK_ALARM, + THINK_GRENADE, + THINK_MACHINEGUNNER, + THINK_DOG_IDLE, + THINK_DOG_ATTACK, + THINK_DOG_CURIOUS, + THINK_DOG_GRENADE, + THINK_ANIM, + THINK_ANIM_CURIOUS, + THINK_AIM, + THINK_BALCONY_IDLE, + THINK_BALCONY_CURIOUS, + THINK_BALCONY_ATTACK, + THINK_BALCONY_DISGUISE, + THINK_BALCONY_GRENADE, + THINK_BALCONY_PAIN, + THINK_BALCONY_KILLED, + THINK_WEAPONLESS, + THINK_NOCLIP, + THINK_DEAD, + THINK_BADPLACE, // Added in 2.0 + THINK_RUN_AND_SHOOT, // Added in 2.30 + NUM_THINKS, }; -enum eThinkLevel -{ - THINKLEVEL_NORMAL, //I think it should be THINKLEVEL_IDLE - THINKLEVEL_PAIN, - THINKLEVEL_KILLED, - THINKLEVEL_NOCLIP, - NUM_THINKLEVELS +enum eThinkLevel { + THINKLEVEL_IDLE, + THINKLEVEL_PAIN, + THINKLEVEL_KILLED, + THINKLEVEL_NOCLIP, + NUM_THINKLEVELS +}; + +enum eActorNationality { + ACTOR_NATIONALITY_DEFAULT, + ACTOR_NATIONALITY_AMERICAN, + ACTOR_NATIONALITY_GERMAN, + ACTOR_NATIONALITY_ITALIAN, + ACTOR_NATIONALITY_BRITISH, + ACTOR_NATIONALITY_RUSSIAN, +}; + +// +// Actor states +// +enum eActorState { + ACTOR_STATE_DISGUISE = 0, + ACTOR_STATE_TURRET = 100, + ACTOR_STATE_BALCONY_ATTACK = 200, + ACTOR_STATE_COVER = 300, + ACTOR_STATE_PAIN = 500, + ACTOR_STATE_ALARM = 600, + ACTOR_STATE_KILLED = 700, + ACTOR_STATE_BALCONY_KILLED = 800, + ACTOR_STATE_WEAPONLESS = 900, + ACTOR_STATE_ANIMATION = 1000, + ACTOR_STATE_CURIOUS = 1100, + ACTOR_STATE_MACHINE_GUNNER = 1200, + // Added in 2.30 + ACTOR_STATE_RUN_AND_SHOOT = 1300, +}; + +// +// Disguise think state +// +enum eActorState_Disguise { + ACTOR_STATE_DISGUISE_START = ACTOR_STATE_DISGUISE, + ACTOR_STATE_DISGUISE_WAIT = ACTOR_STATE_DISGUISE_START, + ACTOR_STATE_DISGUISE_PAPERS, + ACTOR_STATE_DISGUISE_ACCEPT, + ACTOR_STATE_DISGUISE_ENEMY, + ACTOR_STATE_DISGUISE_HALT, + ACTOR_STATE_DISGUISE_DENY, +}; + +// +// Turret think state +// +enum eActorState_Turret { + ACTOR_STATE_TURRET_START = ACTOR_STATE_TURRET, + ACTOR_STATE_TURRET_COMBAT = ACTOR_STATE_TURRET_START, + ACTOR_STATE_TURRET_REACQUIRE, + ACTOR_STATE_TURRET_TAKE_SNIPER_NODE, + ACTOR_STATE_TURRET_SNIPER_NODE, + ACTOR_STATE_TURRET_RUN_HOME, + ACTOR_STATE_TURRET_RUN_AWAY, + ACTOR_STATE_TURRET_CHARGE, + ACTOR_STATE_TURRET_GRENADE, + ACTOR_STATE_TURRET_INTRO_AIM, + ACTOR_STATE_TURRET_FAKE_ENEMY, + ACTOR_STATE_TURRET_COVER_INSTEAD, + ACTOR_STATE_TURRET_BECOME_COVER, + ACTOR_STATE_TURRET_WAIT, + ACTOR_STATE_TURRET_SHOOT, // Added in 2.0 + ACTOR_STATE_TURRET_RETARGET_SUPPRESS, // Added in 2.0 + ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE, + ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_SMALL, + ACTOR_STATE_TURRET_RETARGET_PATH_EXACT, + ACTOR_STATE_TURRET_RETARGET_PATH_NEAR, + ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_MEDIUM, + ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_LARGE, + ACTOR_STATE_TURRET_RETARGET_STEP_FACE_MEDIUM, + ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE, + ACTOR_STATE_TURRET_NUM_STATES +}; + +// +// Balcony attack think state +// +enum eActorState_BalconyAttack { + ACTOR_STATE_BALCONY_ATTACK_START = ACTOR_STATE_BALCONY_ATTACK, + ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY = ACTOR_STATE_BALCONY_ATTACK_START, + ACTOR_STATE_BALCONY_ATTACK_TARGET, + ACTOR_STATE_BALCONY_ATTACK_SHOOT +}; + +// +// Balcony cover think state +// +enum eActorState_Cover { + ACTOR_STATE_COVER_START = ACTOR_STATE_COVER, + ACTOR_STATE_COVER_NEW_ENEMY = ACTOR_STATE_COVER_START, + ACTOR_STATE_COVER_FIND_COVER, + ACTOR_STATE_COVER_TAKE_COVER, + ACTOR_STATE_COVER_FINISH_RELOADING, + ACTOR_STATE_COVER_SPECIAL_ATTACK, + ACTOR_STATE_COVER_FIND_ENEMY, + ACTOR_STATE_COVER_SEARCH_NODE, + ACTOR_STATE_COVER_TARGET, + ACTOR_STATE_COVER_HIDE, + ACTOR_STATE_COVER_SHOOT, + ACTOR_STATE_COVER_GRENADE, + ACTOR_STATE_COVER_HUNT_ENEMY, + ACTOR_STATE_COVER_LOOP, + ACTOR_STATE_COVER_FAKE_ENEMY, +}; + +// +// Pain think state +// +enum eActorState_Pain { + ACTOR_STATE_PAIN_START = ACTOR_STATE_PAIN, + ACTOR_STATE_PAIN_INITIAL = ACTOR_STATE_PAIN_START, + ACTOR_STATE_PAIN_MAIN +}; + +// +// Alarm think state +// +enum eActorState_Alarm { + ACTOR_STATE_ALARM_START = ACTOR_STATE_ALARM, + ACTOR_STATE_ALARM_IDLE = ACTOR_STATE_ALARM_START, + ACTOR_STATE_ALARM_MOVE +}; + +// +// Killed think state +// +enum eActorState_Killed { + ACTOR_STATE_KILLED_START = ACTOR_STATE_KILLED, + ACTOR_STATE_KILLED_BEGIN = ACTOR_STATE_KILLED_START, + ACTOR_STATE_KILLED_END +}; + +// +// Balcony killed think state +// +enum eActorState_BalconyKilled { + ACTOR_STATE_BALCONY_KILLED_START = ACTOR_STATE_BALCONY_KILLED, + ACTOR_STATE_BALCONY_KILLED_BEGIN = ACTOR_STATE_BALCONY_KILLED_START, + ACTOR_STATE_BALCONY_KILLED_INTRO, + ACTOR_STATE_BALCONY_KILLED_LOOP, + ACTOR_STATE_BALCONY_KILLED_LOOP_END, + ACTOR_STATE_BALCONY_KILLED_OUTTRO, + ACTOR_STATE_BALCONY_KILLED_END, + ACTOR_STATE_BALCONY_KILLED_NORMAL, +}; + +// +// Weaponless think state +// +enum eActorState_WeaponLess { + ACTOR_STATE_WEAPONLESS_START = ACTOR_STATE_WEAPONLESS, + ACTOR_STATE_WEAPONLESS_NORMAL = ACTOR_STATE_WEAPONLESS_START, + ACTOR_STATE_WEAPONLESS_GRENADE, + ACTOR_STATE_WEAPONLESS_LOOP +}; + +// +// Animation think state +// +enum eActorState_Animation { + ACTOR_STATE_ANIMATION_START = ACTOR_STATE_ANIMATION, + ACTOR_STATE_ANIMATION_INITIAL = ACTOR_STATE_ANIMATION_START, + ACTOR_STATE_ANIMATION_MAIN, +}; + +// +// Curious think state +// +enum eActorState_Curious { + ACTOR_STATE_CURIOUS_START = ACTOR_STATE_CURIOUS, + ACTOR_STATE_CURIOUS_BEGIN = ACTOR_STATE_CURIOUS_START, + ACTOR_STATE_CURIOUS_RUNNING +}; + +// +// Machine gunner think state +// +enum eActorState_MachineGunner { + ACTOR_STATE_MACHINE_GUNNER_START = ACTOR_STATE_MACHINE_GUNNER, + ACTOR_STATE_MACHINE_GUNNER_READY = ACTOR_STATE_MACHINE_GUNNER_START, + ACTOR_STATE_MACHINE_GUNNER_RELOADING +}; + +// +// Run and shoot think state +// +enum eActorState_RunAndShoot { + ACTOR_STATE_RUN_AND_SHOOT_START = ACTOR_STATE_RUN_AND_SHOOT, + ACTOR_STATE_RUN_AND_SHOOT_RUN = ACTOR_STATE_RUN_AND_SHOOT_START, + ACTOR_STATE_RUN_AND_SHOOT_RUNNING }; class Actor; @@ -409,1173 +583,1574 @@ typedef SafePtr ActorPtr; class Actor : public SimpleActor { - struct GlobalFuncs_t { - void ( Actor::*ThinkState )( void ); - void ( Actor::*BeginState )( void ); - void ( Actor::*ResumeState )( void ); - void ( Actor::*EndState )( void ); - void ( Actor::*SuspendState )( void ); - void ( Actor::*RestartState )( void ); - void ( Actor::*FinishedAnimation )( void ); - void ( Actor::*PostShoot )( void ); - void ( Actor::*Pain )( Event *ev ); - void ( Actor::*Killed )( Event *ev, bool bPlayDeathAnim ); - bool ( Actor::*PassesTransitionConditions )( void ); - void ( Actor::*ShowInfo )( void ); - void ( Actor::*PathnodeClaimRevoked )( void ); - void ( Actor::*ReceiveAIEvent )( vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared ); - bool ( *IsState )( int state ); - }; + struct GlobalFuncs_t { + void (Actor::*ThinkState)(void); + void (Actor::*BeginState)(void); + void (Actor::*ResumeState)(void); + void (Actor::*EndState)(void); + void (Actor::*SuspendState)(void); + void (Actor::*RestartState)(void); + void (Actor::*FinishedAnimation)(void); + void (Actor::*PostShoot)(void); + void (Actor::*Pain)(Event *ev); + void (Actor::*Killed)(Event *ev, bool bPlayDeathAnim); + bool (Actor::*PassesTransitionConditions)(void); + void (Actor::*ShowInfo)(void); + void (Actor::*PathnodeClaimRevoked)(void); + void (Actor::*ReceiveAIEvent)( + vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared + ); + bool (*IsState)(int state); + }; public: - /* GlobalFuncs: contains different funcs needed for each actor think + /* GlobalFuncs: contains different funcs needed for each actor think * think is basically a mode for the actor * when m_ThinkLevel changes, new think value is inside m_Think * to access current think : m_Think[m_ThinkLevel] * to access GlobalFuncs related to current think * GlobalFuncs[m_Think[m_ThinkLevel]]; **/ - static GlobalFuncs_t GlobalFuncs[NUM_THINKS]; - /* const string array containig think names */ - static const_str m_csThinkNames[NUM_THINKS]; - /* const string array containig think state names */ - static const_str m_csThinkStateNames[NUM_THINKSTATES]; - /* map contating every think value for each thinkstate */ - eThinkNum m_ThinkMap[NUM_THINKSTATES]; - /* think state for every think level */ - eThinkState m_ThinkStates[NUM_THINKLEVELS]; - /* think value for every think level */ - eThinkNum m_Think[NUM_THINKLEVELS]; - /* current think level + static GlobalFuncs_t GlobalFuncs[NUM_THINKS]; + /* const string array containig think names */ + static const_str m_csThinkNames[NUM_THINKS]; + /* const string array containig think state names */ + static const_str m_csThinkStateNames[NUM_THINKSTATES]; + /* map contating every think value for each thinkstate */ + eThinkNum m_ThinkMap[NUM_THINKSTATES]; + /* think state for every think level */ + eThinkState m_ThinkStates[NUM_THINKLEVELS]; + /* think value for every think level */ + eThinkNum m_Think[NUM_THINKLEVELS]; + /* current think level * think levels are more like priorities * highest level is used. **/ - eThinkLevel m_ThinkLevel; - /* current think state*/ - eThinkState m_ThinkState; - /* current state (different than think state) */ - int m_State; - /* current state change time */ - int m_iStateTime; - /* should lock think state ? */ - bool m_bLockThinkState; - /* think state changed */ - bool m_bDirtyThinkState; - /* debug state for m_State */ - const char *m_pszDebugState; - /* currently animating ( used in G_RunFrame ) */ - bool m_bAnimating; - /* Am I a doggo ? */ - bool m_bDog; - /* char refereing to voice type, chec gAmericanVoices and gGermanVoices */ - int mVoiceType; - /* check EV_Actor_GetSilent, EV_Actor_SetSilent and EV_Actor_SetSilent2 */ - bool m_bSilent; - /* check EV_Actor_GetNoSurprise, EV_Actor_SetNoSurprise and EV_Actor_SetNoSurprise2 */ - bool m_bNoSurprise; - /* actor can mumble ? */ - bool m_bMumble; - /* actor is allowed to have steamy breath */ - bool m_bBreathSteam; - /* const string of head model */ - const_str m_csHeadModel; - /* const string of head skin */ - const_str m_csHeadSkin; - /* const string of weapon model */ - const_str m_csWeapon; - /* const string of REAL weapon model (check Actor::EventGiveWeapon) */ - const_str m_csLoadOut; - /* favorite enemy */ - SentientPtr m_FavoriteEnemy; - /* last time enemy was checked */ - int m_iEnemyCheckTime; - /* last time enemy was changed */ - int m_iEnemyChangeTime; - /* last time a visible(CanSee) enemy was checked */ - int m_iEnemyVisibleCheckTime; - /* last time a visible(CanSee) enemy was changed */ - int m_iEnemyVisibleChangeTime; - /* last time a visible(CanSee) enemy was seen */ - int m_iLastEnemyVisibleTime; - /* last time a visible(CanSee + infov) enemy was checked */ - int m_iEnemyFovCheckTime; - /* last time a visible(CanSee + infov) enemy was changed */ - int m_iEnemyFovChangeTime; - /* last known enemy position. */ - Vector m_vLastEnemyPos; - /* last time enemy position was changed. */ - int m_iLastEnemyPosChangeTime; - /* check EV_Actor_GetEnemyShareRange and EV_Actor_SetEnemyShareRange */ - float m_fMaxShareDistSquared; - /* can actor shoot enemy ? */ - bool m_bCanShootEnemy; - /* last time m_bCanShootEnemy was changed */ - int m_iCanShootCheckTime; - /* desired enable enemy(changed from script) */ - bool m_bDesiredEnableEnemy; - /* enable enemy (change from code only, Actor::UpdateEnableEnemy) */ - bool m_bEnableEnemy; - /* can take pain ? */ - bool m_bEnablePain; - /* allow long pain ? */ - bool m_bNoLongPain; - /* last set enemy is new ? */ - bool m_bNewEnemy; - /* is enemy disguised ? */ - bool m_bEnemyIsDisguised; - /* is enemy visible (CanSee) ? */ - bool m_bEnemyVisible; - /* is enemy in fov (CanSee) ? */ - bool m_bEnemyInFOV; - /* attack player even if disguised. */ - bool m_bForceAttackPlayer; - /* actor should avoud player (Actor::IdleThink) (get out of the players way) */ - bool m_bAutoAvoidPlayer; - /* actor will not go into idle after playing an animation */ - bool m_bNoIdleAfterAnim; - /* is anim script set ? */ - bool m_bAnimScriptSet; - /* const string of anim script path */ - const_str m_csAnimScript; - /* anim mode */ - int m_AnimMode; - /* Don't Face Wall request yaw. */ - float m_fDfwRequestedYaw; - /* Don't Face Wall derived yaw. */ - float m_fDfwDerivedYaw; - /* Don't Face Wall derived position. */ - Vector m_vDfwPos; - /* Don't Face Wall time. */ - float m_fDfwTime; - /* last time GunPostiton() was called */ - int m_iGunPositionCheckTime; - /* gun position */ - Vector m_vGunPosition; - int m_iWallDodgeTimeout; - vec2_t m_PrevObstacleNormal; - char m_WallDir; - /* EV_Actor_SetMoveDoneRadius */ - float m_fMoveDoneRadiusSquared; - /* last time origin was changed */ - int m_iOriginTime; - /* should I face enemy ? */ - bool m_bFaceEnemy; - /* physics on/off ? */ - bool m_bDoPhysics; - /* should become runner/patrol guy */ - bool m_bBecomeRunner; - /* If true, patrol guys and running men wait until triggered to move */ - bool m_bPatrolWaitTrigger; - bool m_bScriptGoalValid; - Vector m_vScriptGoal; - int m_iNextWatchStepTime; - /* current patrol node */ - SafePtr m_patrolCurrentNode; - /* current patrol anim */ - const_str m_csPatrolCurrentAnim; - int m_iSquadStandTime; - /* distance AI tries to keep between squadmates while moving. */ - float m_fInterval; - int m_iIntervalDirTime; - /* the direction the AI would like to move to maintain its interval */ - Vector m_vIntervalDir; - short m_sCurrentPathNodeIndex; - /* current pain state(similar to m_State) */ - int m_PainState; - /* last time actor switched to curious state. */ - int m_iCuriousTime; - /* Current level of curiousity. It's value is from PriorityForEventType() */ - int m_iCuriousLevel; - int m_iCuriousAnimHint; - /* next time to check for state change to disguise. PassesTransitionConditions_Disguise() */ - int m_iNextDisguiseTime; - /* EV_Actor_SetDisguisePeriod */ - int m_iDisguisePeriod; - /* EV_Actor_SetDisguiseRange */ - float m_fMaxDisguiseDistSquared; - /* next time enemy should show papers */ - int m_iEnemyShowPapersTime; - /* the thread for actor when accepting papers */ - ScriptThreadLabel m_DisguiseAcceptThread; - /* disguise level of the actor, might be 1 or 2 */ - int m_iDisguiseLevel; - /* node for actor to raise alaram against player. */ - SafePtr< SimpleEntity > m_AlarmNode; - /* alarm thread for actor */ - ScriptThreadLabel m_AlarmThread; - /* used for turret actot to run back to home Turret_SelectState() */ - int m_iRunHomeTime; - /* no cover path for initial turret state */ - bool m_bTurretNoInitialCover; - /* potential cover nodes */ - PathNode *m_pPotentialCoverNode[MAX_COVER_NODES]; - /* potential cover node count */ - int m_iPotentialCoverCount; - /* current cover node */ - PathNode *m_pCoverNode; - /* special cover node attack script. */ - const_str m_csSpecialAttack; - /* actor is reloading */ - bool m_bInReload; - /* actor needs reloading */ - bool m_bNeedReload; - /* should break(stop) special attack ? */ - bool mbBreakSpecialAttack; - /* grenade has bounced ? (usually means actor should flee) */ - bool m_bGrenadeBounced; - /* current grenade */ - SafePtr m_pGrenade; - /* grenade position */ - Vector m_vGrenadePos; - /* first time grenade was noticed */ - int m_iFirstGrenadeTime; - /* grenade state */ - eGrenadeState m_eGrenadeState; - /* grenade mode */ - eGrenadeTossMode m_eGrenadeMode; - /* grenade velocity */ - Vector m_vGrenadeVel; - /* grenade kick direction */ - Vector m_vKickDir; - /* falling path */ - FallPath *m_pFallPath; - /* minimum height a balcony guy must fall to do special balcony death */ - float m_fBalconyHeight; - /* actor should not collide with player */ - bool m_bNoPlayerCollision; - /* multiplier in time to notice an enemy */ - float m_fNoticeTimeScale; - /* max multiplier in time to notice an enemy */ - float m_fMaxNoticeTimeScale; - /* set of potential enemies */ - ActorEnemySet m_PotentialEnemies; - /* vision distance of the actor */ - float m_fSight; - /* hearing radius of the actor */ - float m_fHearing; - /* EV_Actor_GetSoundAwareness */ - float m_fSoundAwareness; - /* EV_Actor_GetGrenadeAwareness */ - float m_fGrenadeAwareness; - /* mask of AI_EVENT* bits for the actor to ignore. */ - int m_iIgnoreSoundsMask; - /* fov angle of the actor */ - float m_fFov; - /* used for infov check */ - float m_fFovDot; - /* eye update time */ - int m_iEyeUpdateTime; - /* eye direction */ - Vector m_vEyeDir; - /* next time to look around */ - int m_iNextLookTime; - /* fov angle for look around */ - float m_fLookAroundFov; - /* entity to look at */ - SafePtr m_pLookEntity; - /* look flags(should be a bool) */ - int m_iLookFlags; - /* entity to point at */ - SafePtr m_pPointEntity; - /* entity to turn to */ - SafePtr m_pTurnEntity; - /* allowed error(difference) in angles after doing turnto command */ - float m_fTurnDoneError; - /* turn speed of the actor */ - float m_fAngleYawSpeed; - /* node to aim at */ - SafePtr m_aimNode; - /* dont face wall mode */ - int m_eDontFaceWallMode; - int m_iLastFaceDecideTime; - /* origin history */ - vec2_t m_vOriginHistory[MAX_ORIGIN_HISTORY]; - /* current origin history index */ - int m_iCurrentHistory; - bool m_bHeadAnglesAchieved; - bool m_bLUpperArmAnglesAchieved; - bool m_bTorsoAnglesAchieved; - bool align3; - /* max head turn speed */ - float m_fHeadMaxTurnSpeed; - /* desired head angles */ - vec3_t m_vHeadDesiredAngles; - /* up arm turn speed */ - float m_fLUpperArmTurnSpeed; - /* upper arm desired angles */ - vec3_t m_vLUpperArmDesiredAngles; - /* max torso turn speed */ - float m_fTorsoMaxTurnSpeed; - /* currnet torso turn speed */ - float m_fTorsoCurrentTurnSpeed; - /* desired torso angles */ - vec3_t m_vTorsoDesiredAngles; - /* global body queue */ - static SafePtr< Actor > mBodyQueue[MAX_BODYQUEUE]; - /* current body queue index */ - static int mCurBody; - /* leash home */ - Vector m_vHome; - /* tether entity */ - SafePtr m_pTetherEnt; - /* minimum distance actor tries to keep between itself and the player */ - float m_fMinDistance; - /* square of minimum distance actor tries to keep between itself and the player */ - float m_fMinDistanceSquared; - /* maximum distance actor tries to allow between itself and the player */ - float m_fMaxDistance; - /* square of maximum distance actor tries to allow between itself and the player */ - float m_fMaxDistanceSquared; - /* maximum distance actor will wander from its leash home */ - float m_fLeash; - /* square of maximum distance actor will wander from its leash home */ - float m_fLeashSquared; - /* if true, leash will not change. */ - bool m_bFixedLeash; + eThinkLevel m_ThinkLevel; + /* current think state*/ + eThinkState m_ThinkState; + /* current state (different than think state) */ + int m_State; + /* current state change time */ + int m_iStateTime; + /* should lock think state ? */ + bool m_bLockThinkState; + /* think state changed */ + bool m_bDirtyThinkState; + /* debug state for m_State */ + const char *m_pszDebugState; + /* currently animating ( used in G_RunFrame ) */ + bool m_bAnimating; + /* 2.0: ignore bad place? */ + bool m_bIgnoreBadPlace; + /* 2.0: bad place index? (0=none) */ + int m_iBadPlaceIndex; + /* char refereing to voice type, chec gAmericanVoices and gGermanVoices */ + int mVoiceType; + /* check EV_Actor_GetSilent, EV_Actor_SetSilent and EV_Actor_SetSilent2 */ + bool m_bSilent; + /* check EV_Actor_GetNoSurprise, EV_Actor_SetNoSurprise and EV_Actor_SetNoSurprise2 */ + bool m_bNoSurprise; + /* actor can mumble ? */ + bool m_bMumble; + /* actor is allowed to have steamy breath */ + bool m_bBreathSteam; + /* const string of head model */ + const_str m_csHeadModel; + /* const string of head skin */ + const_str m_csHeadSkin; + /* const string of weapon model */ + const_str m_csWeapon; + /* const string of REAL weapon model (check Actor::EventGiveWeapon) */ + const_str m_csLoadOut; + /* favorite enemy */ + SentientPtr m_FavoriteEnemy; + /* last time enemy was checked */ + int m_iEnemyCheckTime; + /* last time enemy was changed */ + int m_iEnemyChangeTime; + /* last time a visible(CanSee) enemy was checked */ + int m_iEnemyVisibleCheckTime; + /* last time a visible(CanSee) enemy was changed */ + int m_iEnemyVisibleChangeTime; + /* last time a visible(CanSee) enemy was seen */ + int m_iLastEnemyVisibleTime; + /* 2.0: visibility alpha */ + float m_fVisibilityAlpha; + /* 2.0: max visibility threshold */ + float m_fVisibilityThreshold; + /* last time a visible(CanSee + infov) enemy was checked */ + int m_iEnemyFovCheckTime; + /* last time a visible(CanSee + infov) enemy was changed */ + int m_iEnemyFovChangeTime; + /* last known enemy position. */ + Vector m_vLastEnemyPos; + /* last time enemy position was changed. */ + int m_iLastEnemyPosChangeTime; + /* check EV_Actor_GetEnemyShareRange and EV_Actor_SetEnemyShareRange */ + float m_fMaxShareDistSquared; + /* can actor shoot enemy ? */ + bool m_bCanShootEnemy; + /* 2.0: does it has visibility threshold set? */ + bool m_bHasVisibilityThreshold; + /* last time m_bCanShootEnemy was changed */ + int m_iCanShootCheckTime; + /* desired enable enemy(changed from script) */ + bool m_bDesiredEnableEnemy; + /* enable enemy (change from code only, Actor::UpdateEnableEnemy) */ + bool m_bEnableEnemy; + /* can take pain ? */ + bool m_bEnablePain; + /* allow long pain ? */ + bool m_bNoLongPain; + /* last set enemy is new ? */ + bool m_bNewEnemy; + /* is enemy disguised ? */ + bool m_bEnemyIsDisguised; + /* is enemy visible (CanSee) ? */ + bool m_bEnemyVisible; + /* is enemy in fov (CanSee) ? */ + bool m_bEnemyInFOV; + /* attack player even if disguised. */ + bool m_bForceAttackPlayer; + /* actor should avoud player (Actor::IdleThink) (get out of the players way) */ + bool m_bAutoAvoidPlayer; + /* actor will not go into idle after playing an animation */ + bool m_bNoIdleAfterAnim; + /* is anim script set ? */ + bool m_bAnimScriptSet; + /* const string of anim script path */ + const_str m_csAnimScript; + /* anim mode */ + int m_AnimMode; + /* 2.0: the run anim rate */ + float m_fRunAnimRate; + /* Don't Face Wall request yaw. */ + float m_fDfwRequestedYaw; + /* Don't Face Wall derived yaw. */ + float m_fDfwDerivedYaw; + /* Don't Face Wall derived position. */ + Vector m_vDfwPos; + /* Don't Face Wall time. */ + float m_fDfwTime; + /* last time GunPostiton() was called */ + int m_iGunPositionCheckTime; + /* gun position */ + Vector m_vGunPosition; + int m_iWallDodgeTimeout; + vec2_t m_PrevObstacleNormal; + char m_WallDir; + /* EV_Actor_SetMoveDoneRadius */ + float m_fMoveDoneRadiusSquared; + /* last time origin was changed */ + int m_iOriginTime; + /* should I face enemy ? */ + bool m_bFaceEnemy; + /* physics on/off ? */ + bool m_bDoPhysics; + /* should become runner/patrol guy */ + bool m_bBecomeRunner; + /* If true, patrol guys and running men wait until triggered to move */ + bool m_bPatrolWaitTrigger; + bool m_bScriptGoalValid; + Vector m_vScriptGoal; + int m_iNextWatchStepTime; + /* current patrol node */ + SafePtr m_patrolCurrentNode; + /* current patrol anim */ + const_str m_csPatrolCurrentAnim; + int m_iSquadStandTime; + /* distance AI tries to keep between squadmates while moving. */ + float m_fInterval; + int m_iIntervalDirTime; + /* the direction the AI would like to move to maintain its interval */ + Vector m_vIntervalDir; + short m_sCurrentPathNodeIndex; + /* current pain state(similar to m_State) */ + int m_PainState; + /* last time actor switched to curious state. */ + int m_iCuriousTime; + /* Current level of curiousity. It's value is from PriorityForEventType() */ + int m_iCuriousLevel; + int m_iCuriousAnimHint; + /* next time to check for state change to disguise. PassesTransitionConditions_Disguise() */ + int m_iNextDisguiseTime; + /* EV_Actor_SetDisguisePeriod */ + int m_iDisguisePeriod; + /* EV_Actor_SetDisguiseRange */ + float m_fMaxDisguiseDistSquared; + /* next time enemy should show papers */ + int m_iEnemyShowPapersTime; + /* the thread for actor when accepting papers */ + ScriptThreadLabel m_DisguiseAcceptThread; + /* disguise level of the actor, might be 1 or 2 */ + int m_iDisguiseLevel; + /* node for actor to raise alaram against player. */ + SafePtr m_AlarmNode; + /* alarm thread for actor */ + ScriptThreadLabel m_AlarmThread; + /* 2.30: pre-alarm thread for actor */ + ScriptThreadLabel m_PreAlarmThread; + /* 2.0: Suppress chance */ + int m_iSuppressChance; + /* used for turret actot to run back to home Turret_SelectState() */ + int m_iRunHomeTime; + /* no cover path for initial turret state */ + bool m_bTurretNoInitialCover; + /* potential cover nodes */ + PathNode *m_pPotentialCoverNode[MAX_COVER_NODES]; + /* potential cover node count */ + int m_iPotentialCoverCount; + /* current cover node */ + PathNode *m_pCoverNode; + /* special cover node attack script. */ + const_str m_csSpecialAttack; + /* actor is reloading */ + bool m_bInReload; + /* actor needs reloading */ + bool m_bNeedReload; + /* should break(stop) special attack ? */ + bool mbBreakSpecialAttack; + /* 2.30: is the AI curious? */ + bool m_bIsCurious; + /* grenade has bounced ? (usually means actor should flee) */ + bool m_bGrenadeBounced; + /* current grenade */ + SafePtr m_pGrenade; + /* grenade position */ + Vector m_vGrenadePos; + /* first time grenade was noticed */ + int m_iFirstGrenadeTime; + /* grenade state */ + eGrenadeState m_eGrenadeState; + /* grenade mode */ + eGrenadeTossMode m_eGrenadeMode; + /* grenade velocity */ + Vector m_vGrenadeVel; + /* grenade kick direction */ + Vector m_vKickDir; + /* falling path */ + FallPath *m_pFallPath; + /* minimum height a balcony guy must fall to do special balcony death */ + float m_fBalconyHeight; + /* actor should not collide with player */ + bool m_bNoPlayerCollision; + /* multiplier in time to notice an enemy */ + float m_fNoticeTimeScale; + /* max multiplier in time to notice an enemy */ + float m_fMaxNoticeTimeScale; + /* set of potential enemies */ + ActorEnemySet m_PotentialEnemies; + /* vision distance of the actor */ + float m_fSight; + /* hearing radius of the actor */ + float m_fHearing; + /* EV_Actor_GetSoundAwareness */ + float m_fSoundAwareness; + /* EV_Actor_GetGrenadeAwareness */ + float m_fGrenadeAwareness; + /* mask of AI_EVENT* bits for the actor to ignore. */ + int m_iIgnoreSoundsMask; + /* fov angle of the actor */ + float m_fFov; + /* used for infov check */ + float m_fFovDot; + /* eye update time */ + int m_iEyeUpdateTime; + /* eye direction */ + Vector m_vEyeDir; + /* next time to look around */ + int m_iNextLookTime; + /* fov angle for look around */ + float m_fLookAroundFov; + /* entity to look at */ + SafePtr m_pLookEntity; + /* look flags(should be a bool) */ + int m_iLookFlags; + /* entity to point at */ + SafePtr m_pPointEntity; + /* entity to turn to */ + SafePtr m_pTurnEntity; + /* allowed error(difference) in angles after doing turnto command */ + float m_fTurnDoneError; + /* turn speed of the actor */ + float m_fAngleYawSpeed; + /* node to aim at */ + SafePtr m_aimNode; + /* dont face wall mode */ + int m_eDontFaceWallMode; + int m_iLastFaceDecideTime; + /* origin history */ + vec2_t m_vOriginHistory[MAX_ORIGIN_HISTORY]; + /* current origin history index */ + int m_iCurrentHistory; + bool m_bHeadAnglesAchieved; + bool m_bLUpperArmAnglesAchieved; + bool m_bTorsoAnglesAchieved; + bool align3; + /* max head turn speed */ + float m_fHeadMaxTurnSpeed; + /* desired head angles */ + vec3_t m_vHeadDesiredAngles; + /* up arm turn speed */ + float m_fLUpperArmTurnSpeed; + /* upper arm desired angles */ + vec3_t m_vLUpperArmDesiredAngles; + /* max torso turn speed */ + float m_fTorsoMaxTurnSpeed; + /* currnet torso turn speed */ + float m_fTorsoCurrentTurnSpeed; + /* desired torso angles */ + vec3_t m_vTorsoDesiredAngles; + /* global body queue */ + static SafePtr mBodyQueue[MAX_BODYQUEUE]; + /* current body queue index */ + static int mCurBody; + /* leash home */ + Vector m_vHome; + /* tether entity */ + SafePtr m_pTetherEnt; + /* minimum distance actor tries to keep between itself and the player */ + float m_fMinDistance; + /* square of minimum distance actor tries to keep between itself and the player */ + float m_fMinDistanceSquared; + /* maximum distance actor tries to allow between itself and the player */ + float m_fMaxDistance; + /* square of maximum distance actor tries to allow between itself and the player */ + float m_fMaxDistanceSquared; + /* maximum distance actor will wander from its leash home */ + float m_fLeash; + /* square of maximum distance actor will wander from its leash home */ + float m_fLeashSquared; + /* if true, leash will not change. */ + bool m_bFixedLeash; + /* 2.0: if true, enemy switch will be disabled. */ + bool m_bEnemySwitch; + /* 2.30: the nationality index. */ + int m_iNationality; public: - CLASS_PROTOTYPE( Actor ); + CLASS_PROTOTYPE(Actor); protected: - void MoveTo( Event *ev ); - void WalkTo( Event *ev ); - void RunTo( Event *ev ); - void CrouchTo( Event *ev ); - void CrawlTo( Event *ev ); - void AimAt( Event *ev ); - void DefaultRestart( void ); - void SuspendState( void ); - void ResumeState( void ); - void BeginState( void ); - void EndState( int level ); - void RestartState( void ); + void MoveTo(Event *ev); + void WalkTo(Event *ev); + void RunTo(Event *ev); + void CrouchTo(Event *ev); + void CrawlTo(Event *ev); + void AimAt(Event *ev); + void DefaultRestart(void); + void SuspendState(void); + void ResumeState(void); + void BeginState(void); + void EndState(int level); + void RestartState(void); public: - Actor(); - - virtual void setContentsSolid( void ) override; - void InitThinkStates( void ); - void UpdateEyeOrigin( void ); - bool RequireThink( void ); - void UpdateEnemy( int iMaxDirtyTime ); - void UpdateEnemyInternal( void ); - void SetEnemy( Sentient *pEnemy, bool bForceConfirmed ); - void SetEnemyPos( Vector vPos ); - static void ResetBodyQueue( void ); - void AddToBodyQue( void ); - Vector GetAntiBunchPoint( void ); - static void InitVoid( GlobalFuncs_t *func ); - virtual const char *DumpCallTrace( const char *pszFmt, ... ) const override; - static void Init( void ); - void FixAIParameters( void ); - bool AttackEntryAnimation( void ); - void CheckForThinkStateTransition( void ); - bool CheckForTransition( eThinkState state, eThinkLevel level ); - bool PassesTransitionConditions_Grenade( void ); - bool PassesTransitionConditions_Attack( void ); - bool PassesTransitionConditions_Disguise( void ); - bool PassesTransitionConditions_Curious( void ); - bool PassesTransitionConditions_Idle( void ); - void UpdateEnableEnemy( void ); - void ThinkStateTransitions( void ); - void TransitionState( int iNewState, int iPadTime ); - void ChangeAnim( void ); - void UpdateSayAnim( void ); - void UpdateUpperAnim( void ); - void UpdateAnim( void ); - virtual void StoppedWaitFor( const_str name, bool bDeleting ) override; - static void InitTurret( GlobalFuncs_t *func ); - void Begin_Turret( void ); - void End_Turret( void ); - void Suspend_Turret( void ); - void Think_Turret( void ); - void FinishedAnimation_Turret( void ); - void ReceiveAIEvent_Turret( vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared ); - void InterruptPoint_Turret( void ); - void PathnodeClaimRevoked_Turret( void ); - bool Turret_IsRetargeting( void ) const; - bool Turret_DecideToSelectState( void ); - void Turret_SelectState( void ); - bool Turret_CheckRetarget( void ); - bool Turret_TryToBecomeCoverGuy( void ); - void Turret_BeginRetarget( void ); - void Turret_NextRetarget( void ); - void Turret_SideStep( int iStepSize, vec3_t vDir ); - void State_Turret_Combat( void ); - void State_Turret_Reacquire( void ); - void State_Turret_TakeSniperNode( void ); - void State_Turret_SniperNode( void ); - bool State_Turret_RunHome( bool bAttackOnFail ); - void State_Turret_RunAway( void ); - void State_Turret_Charge( void ); - void State_Turret_Grenade( void ); - void State_Turret_FakeEnemy( void ); - void State_Turret_Wait( void ); - void State_Turret_Retarget_Sniper_Node( void ); - void State_Turret_Retarget_Step_Side_Small( void ); - void State_Turret_Retarget_Path_Exact( void ); - void State_Turret_Retarget_Path_Near( void ); - void State_Turret_Retarget_Step_Side_Medium( void ); - void State_Turret_Retarget_Step_Side_Large( void ); - void State_Turret_Retarget_Step_Face_Medium( void ); - void State_Turret_Retarget_Step_Face_Large( void ); - static void InitCover( GlobalFuncs_t *func ); - bool Cover_IsValid( PathNode *node ); - bool Cover_SetPath( PathNode *node ); - void Cover_FindCover( bool bCheckAll ); - void Begin_Cover( void ); - void End_Cover( void ); - void Suspend_Cover( void ); - void Think_Cover( void ); - void FinishedAnimation_Cover( void ); - void PathnodeClaimRevoked_Cover( void ); - void State_Cover_NewEnemy( void ); - void State_Cover_FindCover( void ); - void State_Cover_TakeCover( void ); - void State_Cover_FinishReloading( void ); - void State_Cover_SpecialAttack( void ); - void State_Cover_Target( void ); - void State_Cover_Hide( void ); - void State_Cover_Shoot( void ); - void State_Cover_Grenade( void ); - void State_Cover_FindEnemy( void ); - void State_Cover_SearchNode( void ); - void State_Cover_HuntEnemy( void ); - void State_Cover_FakeEnemy( void ); - static void InitPatrol( GlobalFuncs_t *func ); - void Begin_Patrol( void ); - void End_Patrol( void ); - void Resume_Patrol( void ); - void Think_Patrol( void ); - void ShowInfo_Patrol( void ); - void IdleThink( void ); - static void InitRunner( GlobalFuncs_t *func ); - void Begin_Runner( void ); - void End_Runner( void ); - void Resume_Runner( void ); - void Think_Runner( void ); - void ShowInfo_Runner( void ); - static void InitAlarm( GlobalFuncs_t *func ); - void Begin_Alarm( void ); - void End_Alarm( void ); - void State_Alarm_StartThread( void ); - void State_Alarm_Move( void ); - void State_Alarm_Idle( void ); - void Think_Alarm( void ); - void FinishedAnimation_Alarm( void ); - static void InitNoClip( GlobalFuncs_t *func ); - bool IsNoClipState( int state ); - void Think_NoClip( void ); - bool ValidGrenadePath( const Vector& vFrom, const Vector& vTo, Vector& vVel ); - static Vector CalcThrowVelocity( const Vector& vFrom, const Vector& vTo ); - Vector CanThrowGrenade( const Vector& vFrom, const Vector& vTo ); - static Vector CalcRollVelocity( const Vector& vFrom, const Vector& vTo ); - Vector CanRollGrenade( const Vector& vFrom, const Vector& vTo ); - bool CanTossGrenadeThroughHint( GrenadeHint *pHint, const Vector& vFrom, const Vector& vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode ); - static Vector GrenadeThrowPoint( const Vector& vFrom, const Vector& vDelta, const_str csAnim ); - Vector CalcKickVelocity( Vector& vDelta, float fDist ) const; - bool CanKickGrenade( Vector &vFrom, Vector &vTo, Vector &vFace, Vector *pvVel ); - bool GrenadeWillHurtTeamAt( const Vector& vTo ); - bool CanGetGrenadeFromAToB( const Vector& vFrom, const Vector& vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode ); - bool DecideToThrowGrenade( const Vector& vTo, Vector *pvVel, eGrenadeTossMode *peMode ); - void Grenade_EventFire( Event *ev ); - void GenericGrenadeTossThink( void ); - static void InitGrenade( GlobalFuncs_t *func ); - bool Grenade_Acquire( eGrenadeState eNextState, const_str csReturnAnim ); - void Grenade_Flee( void ); - void Grenade_ThrowAcquire( void ); - void Grenade_Throw( void ); - void Grenade_KickAcquire( void ); - void Grenade_Kick( void ); - void Grenade_MartyrAcquire( void ); - void Grenade_Martyr( void ); - void Grenade_Wait( void ); - void Grenade_NextThinkState( void ); - void Grenade_EventAttach( Event *ev ); - void Grenade_EventDetach( Event *ev ); - void Begin_Grenade( void ); - void End_Grenade( void ); - void Resume_Grenade( void ); - void Think_Grenade( void ); - void FinishedAnimation_Grenade( void ); - static void InitCurious( GlobalFuncs_t *func ); - void SetCuriousAnimHint( int iAnimHint ); - void Begin_Curious( void ); - void End_Curious( void ); - void Resume_Curious( void ); - void Suspend_Curious( void ); - void Think_Curious( void ); - void FinishedAnimation_Curious( void ); - void LookAtCuriosity( void ); - void TimeOutCurious( void ); - void State_Disguise_Wait( void ); - void State_Disguise_Papers( void ); - void State_Disguise_Fake_Papers( void ); - void State_Disguise_Enemy( void ); - void State_Disguise_Halt( void ); - void State_Disguise_Accept( void ); - void State_Disguise_Deny( void ); - static void InitDisguiseSalute( GlobalFuncs_t *func ); - void Begin_DisguiseSalute( void ); - void End_DisguiseSalute( void ); - void Resume_DisguiseSalute( void ); - void Suspend_DisguiseSalute( void ); - void Think_DisguiseSalute( void ); - void FinishedAnimation_DisguiseSalute( void ); - static void InitDisguiseSentry( GlobalFuncs_t *func ); - void Begin_DisguiseSentry( void ); - void End_DisguiseSentry( void ); - void Resume_DisguiseSentry( void ); - void Suspend_DisguiseSentry( void ); - void Think_DisguiseSentry( void ); - static void InitDisguiseOfficer( GlobalFuncs_t *func ); - void Begin_DisguiseOfficer( void ); - void End_DisguiseOfficer( void ); - void Resume_DisguiseOfficer( void ); - void Suspend_DisguiseOfficer( void ); - void Think_DisguiseOfficer( void ); - static void InitDisguiseRover( GlobalFuncs_t *func ); - void Begin_DisguiseRover( void ); - void End_DisguiseRover( void ); - void Resume_DisguiseRover( void ); - void Suspend_DisguiseRover( void ); - void Think_DisguiseRover( void ); - static void InitDisguiseNone( GlobalFuncs_t *func ); - static void InitIdle( GlobalFuncs_t *func ); - void Begin_Idle( void ); - void Think_Idle( void ); - static void InitMachineGunner( GlobalFuncs_t *func ); - void Begin_MachineGunner( void ); - void End_MachineGunner( void ); - void BecomeTurretGuy( void ); - void Think_MachineGunner( void ); - void ThinkHoldGun( void ); - void FinishedAnimation_MachineGunner( void ); - bool MachineGunner_CanSee( Entity *ent, float fov, float vision_distance ); - void CanSee( Event *ev ); - static void InitDogIdle( GlobalFuncs_t *func ); - static void InitDogAttack( GlobalFuncs_t *func ); - static void InitDogCurious( GlobalFuncs_t *func ); - void Begin_Dog( void ); - void End_Dog( void ); - void Think_Dog_Idle( void ); - void Think_Dog_Attack( void ); - void Think_Dog_Curious( void ); - static void InitAnim( GlobalFuncs_t *func ); - void Begin_Anim( void ); - void Think_Anim( void ); - void FinishedAnimation_Anim( void ); - void ShowInfo_Anim( void ); - static void InitAnimCurious( GlobalFuncs_t *func ); - void Begin_AnimCurious( void ); - void Think_AnimCurious( void ); - void FinishedAnimation_AnimCurious( void ); - static void InitAim( GlobalFuncs_t *func ); - void Begin_Aim( void ); - void Think_Aim( void ); - void ShowInfo_Aim( void ); - static void InitBalconyIdle( GlobalFuncs_t *func ); - static void InitBalconyCurious( GlobalFuncs_t *func ); - static void InitBalconyAttack( GlobalFuncs_t *func ); - static void InitBalconyDisguise( GlobalFuncs_t *func ); - static void InitBalconyGrenade( GlobalFuncs_t *func ); - static void InitBalconyPain( GlobalFuncs_t *func ); - static void InitBalconyKilled( GlobalFuncs_t *func ); - void Pain_Balcony( Event *ev ); - void Killed_Balcony( Event *ev, bool bPlayDeathAnim ); - void Think_BalconyAttack( void ); - void Begin_BalconyAttack( void ); - void FinishedAnimation_BalconyAttack( void ); - void State_Balcony_PostShoot( void ); - void State_Balcony_FindEnemy( void ); - void State_Balcony_Target( void ); - void State_Balcony_Shoot( void ); - void Begin_BalconyKilled( void ); - void End_BalconyKilled( void ); - void Think_BalconyKilled( void ); - void FinishedAnimation_BalconyKilled( void ); - bool CalcFallPath( void ); - static void InitPain( GlobalFuncs_t *func ); - void Begin_Pain( void ); - void Think_Pain( void ); - void FinishedAnimation_Pain( void ); - static void InitDead( GlobalFuncs_t *func ); - static void InitKilled( GlobalFuncs_t *func ); - void Begin_Killed( void ); - void Think_Killed( void ); - void FinishedAnimation_Killed( void ); - static void InitWeaponless( GlobalFuncs_t *func ); - void Begin_Weaponless( void ); - void Suspend_Weaponless( void ); - void Think_Weaponless( void ); - void FinishedAnimation_Weaponless( void ); - void State_Weaponless_Normal( void ); - void State_Weaponless_Grenade( void ); - virtual void Think( void ) override; - void PostThink( bool bDontFaceWall ); - virtual void SetMoveInfo( mmove_t *mm ) override; - virtual void GetMoveInfo( mmove_t *mm ) override; - void DoFailSafeMove( vec3_t dest ); - void TouchStuff( mmove_t *mm ); - void ExtractConstraints( mmove_t *mm ); - void EventGiveWeaponInternal( Event *ev ); - void EventGiveWeapon( Event *ev ); - void EventGetWeapon( Event *ev ); - void FireWeapon( Event *ev ); - virtual bool CanTarget( void ) override; - virtual bool IsImmortal( void ) override; - static bool IsVoidState( int state ); - static bool IsIdleState( int state ); - static bool IsCuriousState( int state ); - static bool IsDisguiseState( int state ); - static bool IsAttackState( int state ); - static bool IsGrenadeState( int state ); - static bool IsPainState( int state ); - static bool IsKilledState( int state ); - static bool IsMachineGunnerState( int state ); - static bool IsDogState( int state ); - void IgnoreSoundSet( int iType ); - void IgnoreSoundSetAll( void ); - void IgnoreSoundClear( int iType ); - void IgnoreSoundClearAll( void ); - bool IgnoreSound( int iType ); - void EventShareEnemy( Event *ev ); - void EventShareGrenade( Event *ev ); - void ReceiveAIEvent( vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared ); - void DefaultReceiveAIEvent( vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared ); - int PriorityForEventType( int iType ); - void CuriousSound( int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared ); - void WeaponSound( int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator ); - void FootstepSound( vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator ); - void VoiceSound( int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator ); - void GrenadeNotification( Entity *originator ); - void SetGrenade( Entity *pGrenade ); - void NotifySquadmateKilled( Sentient *pSquadMate, Sentient *pAttacker ); - void RaiseAlertnessForEventType( int iType ); - void RaiseAlertness( float fAmount ); - virtual bool CanSee( Entity *e1, float fov, float vision_distance, bool bNoEnts ) override; - virtual Vector GunPosition( void ) override; - bool WithinVisionDistance( Entity *ent ) const; - bool InFOV( Vector pos, float check_fov, float check_fovdot ); - bool EnemyInFOV( int iMaxDirtyTime ); - bool InFOV( Vector pos ); - bool InFOV( Entity *ent ); - bool CanSeeNoFOV( Entity *ent ); - bool CanSeeFOV( Entity *ent ); - bool CanSeeEnemyFOV( int iMaxFovDirtyTime, int iMaxSightDirtyTime ); - bool CanShoot( Entity *ent ); - virtual bool CanSeeFrom( vec3_t pos, Entity *ent ); - bool CanSeeEnemy( int iMaxDirtyTime ); - bool CanShootEnemy( int iMaxDirtyTime ); - void ShowInfo( void ); - virtual void ShowInfo( float fDot, float fDist ) override; - void DefaultPain( Event *ev ); - void HandlePain( Event *ev ); - void EventPain( Event *ev ); - void DefaultKilled( Event *ev, bool bPlayDeathAnim ); - void HandleKilled( Event *ev, bool bPlayDeathAnim ); - void DispatchEventKilled( Event *ev, bool bPlayDeathAnim ); - void EventKilled( Event *ev ); - void EventBeDead( Event *ev ); - void DeathEmbalm( Event *ev ); - void DeathSinkStart( Event *ev ); - bool NoticeShot( Sentient *pShooter, Sentient *pTarget, float fDist ); - bool NoticeFootstep( Sentient *pPedestrian ); - bool NoticeVoice( Sentient *pVocallist ); - void ClearLookEntity( void ); - void LookAt( const Vector& vec ); - void LookAt( Listener *l ); - void ForwardLook( void ); - void LookAtLookEntity( void ); - void IdleLook( void ); - void IdleLook( vec3_t dir ); - void SetDesiredLookDir( vec3_t dir ); - void SetDesiredLookAnglesRelative( vec3_t ang ); - void EventLookAt( Event *ev ); - void EventEyesLookAt( Event *ev ); - void NoPoint( void ); - void IdlePoint( void ); - void ClearPointEntity( void ); - void PointAt( const Vector& vec ); - void PointAt( Listener* l ); - void EventPointAt( Event *ev ); - void ClearTurnEntity( void ); - void TurnTo( const Vector& vec ); - void TurnTo( Listener *l ); - void IdleTurn( void ); - void EventTurnTo( Event *ev ); - void EventSetTurnDoneError( Event *ev ); - void EventGetTurnDoneError( Event *ev ); - void LookAround( float fFovAdd ); - bool SoundSayAnim( const_str name, byte bLevelSayAnim ); - void EventSetAnim( Event *ev ); - void EventIdleSayAnim( Event *ev ); - void EventSayAnim( Event *ev ); - void EventSetSayAnim( Event *ev ); - void EventSetMotionAnim( Event *ev ); - void EventSetAimMotionAnim( Event *ev ); - void EventSetActionAnim( Event *ev ); - void EventUpperAnim( Event *ev ); - void EventSetUpperAnim( Event *ev ); - void EventEndActionAnim( Event *ev ); - void EventDamagePuff( Event *ev ); - void SafeSetOrigin( vec3_t newOrigin ); - void DoMove( void ); - void AnimFinished( int slot, bool stop ); - virtual void AnimFinished( int slot ) override; - void PlayAnimation( Event *ev ); - void PlayScriptedAnimation( Event *ev ); - void PlayNoclipAnimation( Event *ev ); - void MoveDest( float fMoveSpeed ); - void MovePath( float fMoveSpeed ); - void MovePathGoal( float fMoveSpeed ); - void Dumb( Event *ev ); - void PhysicsOn( Event *ev ); - void PhysicsOff( Event *ev ); - void EventStart( Event *ev ); - void EventGetMood( Event *ev ); - void EventSetMood( Event *ev ); - void EventGetAngleYawSpeed( Event *ev ); - void EventSetAngleYawSpeed( Event *ev ); - void EventSetAimTarget( Event *ev ); - void UpdateAngles( void ); - void SetLeashHome( Vector vHome ); - void AimAtTargetPos( void ); - void AimAtAimNode( void ); - void AimAtEnemyBehavior( void ); - void FaceMotion( void ); - void FaceDirectionDuringMotion( vec3_t vLook ); - float PathDistanceAlongVector( vec3_t vDir ); - void FaceEnemyOrMotion( int iTimeIntoMove ); - static int NextUpdateTime( int iLastUpdateTime, int iUpdatePeriod ); - void ResetBoneControllers( void ); - void UpdateBoneControllers( void ); - void ReadyToFire( Event *ev ); - void GetLocalYawFromVector( Event *ev ); - void EventGetSight( Event *ev ); - void EventSetSight( Event *ev ); - void EventGetHearing( Event *ev ); - void EventSetHearing( Event *ev ); - void ClearPatrolCurrentNode( void ); - void NextPatrolCurrentNode( void ); - void SetPatrolCurrentNode( Vector& vec ); - void SetPatrolCurrentNode( Listener *l ); - void EventSetPatrolPath( Event *ev ); - void EventGetPatrolPath( Event *ev ); - void EventSetPatrolWaitTrigger( Event *ev ); - void EventGetPatrolWaitTrigger( Event *ev ); - void ShowInfo_PatrolCurrentNode( void ); - bool MoveOnPathWithSquad( void ); - bool MoveToWaypointWithPlayer( void ); - bool PatrolNextNodeExists( void ); - void UpdatePatrolCurrentNode( void ); - bool MoveToPatrolCurrentNode( void ); - void ClearAimNode( void ); - void SetAimNode( Vector& vec ); - void SetAimNode( Listener *l ); - void ShowInfo_AimNode( void ); - void EventSetAccuracy( Event *ev ); - void EventGetAccuracy( Event *ev ); - int GetThinkType( const_str csName ); - void SetThink( eThinkState state, eThinkNum think ); - void SetThinkIdle( eThinkNum think_idle ); - void SetThinkState( eThinkState state, eThinkLevel level ); - void EndCurrentThinkState( void ); - void ClearThinkStates( void ); - int CurrentThink( void ) const; - bool IsAttacking( void ) const; - void EventGetFov( Event *ev ); - void EventSetFov( Event *ev ); - void EventSetDestIdle( Event *ev ); - void EventSetDestIdle2( Event *ev ); - void EventSetTypeIdle( Event *ev ); - void EventGetTypeIdle( Event *ev ); - void EventSetTypeAttack( Event *ev ); - void EventGetTypeAttack( Event *ev ); - void EventSetTypeDisguise( Event *ev ); - void EventGetTypeDisguise( Event *ev ); - void EventSetDisguiseLevel( Event *ev ); - void EventGetDisguiseLevel( Event *ev ); - void EventSetTypeGrenade( Event *ev ); - void EventGetTypeGrenade( Event *ev ); - void EventSetMinDistance( Event *ev ); - void EventGetMinDistance( Event *ev ); - void EventSetMaxDistance( Event *ev ); - void EventGetMaxDistance( Event *ev ); - void EventGetLeash( Event *ev ); - void EventSetLeash( Event *ev ); - void EventGetInterval( Event *ev ); - void EventSetInterval( Event *ev ); - void EventDistToEnemy( Event *ev ); - void EventGetRunAnim( Event *ev ); - void EventGetWalkAnim( Event *ev ); - void EventGetAnimName( Event *ev ); - void EventSetAnimName( Event *ev ); - void EventSetDisguiseRange( Event *ev ); - void EventGetDisguiseRange( Event *ev ); - void EventSetDisguisePeriod( Event *ev ); - void EventGetDisguisePeriod( Event *ev ); - void EventSetDisguiseAcceptThread( Event *ev ); - void EventGetDisguiseAcceptThread( Event *ev ); - void EventAttackPlayer( Event *ev ); - void ForceAttackPlayer( void ); - void EventSetAlarmNode( Event *ev ); - void EventGetAlarmNode( Event *ev ); - void EventSetAlarmThread( Event *ev ); - void EventGetAlarmThread( Event *ev ); - void EventSetSoundAwareness( Event *ev ); - void EventGetSoundAwareness( Event *ev ); - void EventSetGrenadeAwareness( Event *ev ); - void EventGetGrenadeAwareness( Event *ev ); - str ThinkName( void ) const; - str ThinkStateName( void ) const; - void EventSetTurret( Event *ev ); - void EventGetTurret( Event *ev ); - void EventEnableEnemy( Event *ev ); - void EventEnablePain( Event *ev ); - void EventActivate( Event *ev ); - void EventGetAmmoGrenade( Event *ev ); - void EventSetAmmoGrenade( Event *ev ); - void EventInterruptPoint( Event *ev ); - void EventAnimScript( Event *ev ); - void EventAnimScript_Scripted( Event *ev ); - void EventAnimScript_Noclip( Event *ev ); - void EventReload_mg42( Event *ev ); - void SetPathWithLeash( Vector vDestPos, const char *description, int iMaxDirtyTime ); - void SetPathWithLeash( SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime ); - void FindPathAwayWithLeash( vec3_t vAwayFrom, vec3_t vDirPreferred, float fMinSafeDist ); - void FindPathNearWithLeash( vec3_t vNearbyTo, float fCloseDistSquared ); - bool CanMovePathWithLeash( void ) const; - bool MovePathWithLeash( void ); - bool ShortenPathToAttack( float fMinDist ); - void StrafeToAttack( float fDist, vec3_t vDir ); - virtual Vector GunTarget( bool bNoCollision ) override; - virtual qboolean setModel( void ) override; - void EventSetHeadModel( Event *ev ); - void EventGetHeadModel( Event *ev ); - void EventSetHeadSkin( Event *ev ); - void EventGetHeadSkin( Event *ev ); - void EventSetNoIdle( Event *ev ); - void EventGetNoIdle( Event *ev ); - void EventGetEnemy( Event *ev ); - void EventSetMaxNoticeTimeScale( Event *ev ); - void EventGetMaxNoticeTimeScale( Event *ev ); - void EventSetFixedLeash( Event *ev ); - void EventGetFixedLeash( Event *ev ); - void Holster( void ); - void Unholster( void ); - void EventHolster( Event *ev ); - void EventUnholster( Event *ev ); - void EventSoundDone( Event *ev ); - void EventSound( Event *ev ); - void EventIsEnemyVisible( Event *ev ); - void EventGetEnemyVisibleChangeTime( Event *ev ); - void EventGetLastEnemyVisibleTime( Event *ev ); - void EventSetFallHeight( Event *ev ); - void EventGetFallHeight( Event *ev ); - void EventCanMoveTo( Event *ev ); - void EventMoveDir( Event *ev ); - void EventIntervalDir( Event *ev ); - void EventResetLeash( Event *ev ); - void EventTether( Event *ev ); - void EventGetThinkState( Event *ev ); - void EventGetEnemyShareRange( Event *ev ); - void EventSetEnemyShareRange( Event *ev ); - void EventGetKickDir( Event *ev ); - void EventGetNoLongPain( Event *ev ); - void EventSetNoLongPain( Event *ev ); - void EventGetFavoriteEnemy( Event *ev ); - void EventSetFavoriteEnemy( Event *ev ); - void EventGetMumble( Event *ev ); - void EventSetMumble( Event *ev ); - void EventGetBreathSteam( Event *ev ); - void EventSetBreathSteam( Event *ev ); - void EventSetNextBreathTime( Event *ev ); - void EventCalcGrenadeToss( Event *ev ); - void EventGetNoSurprise( Event *ev ); - void EventSetNoSurprise( Event *ev ); - void EventGetSilent( Event *ev ); - void EventSetSilent( Event *ev ); - void EventGetAvoidPlayer( Event *ev ); - void EventSetAvoidPlayer( Event *ev ); - void EventGetLookAroundAngle( Event *ev ); - void EventSetLookAroundAngle( Event *ev ); - void EventHasCompleteLookahead( Event *ev ); - void EventPathDist( Event *ev ); - void EventCanShootEnemyFrom( Event *ev ); - void EventCanShoot( Event *ev ); - void EventSetInReload( Event *ev ); - void EventGetInReload( Event *ev ); - void EventSetReloadCover( Event *ev ); - void EventBreakSpecial( Event *ev ); - void GetVoiceType( Event *ev ); - void SetVoiceType( Event *ev ); - void ResolveVoiceType( void ); - void EventSetBalconyHeight( Event *ev ); - void EventGetBalconyHeight( Event *ev ); - PathNode *FindSniperNodeAndSetPath( bool *pbTryAgain ); - void Remove( Event *ev ); - void DontFaceWall( void ); - bool AvoidingFacingWall( void ) const; - void EndStates( void ); - void ClearStates( void ); - void CheckUnregister( void ); - void BecomeCorpse( void ); - virtual void PathnodeClaimRevoked( PathNode *node ) override; - void SetPathToNotBlockSentient( Sentient *pOther ); - void EventSetMoveDoneRadius( Event *ev ); - virtual void ClearEnemies( void ) override; - bool EnemyIsDisguised( void ); - virtual void setOriginEvent( Vector org ) override; - virtual void DumpAnimInfo( void ) override; - static void ArchiveStatic( Archiver& arc ); - virtual void Archive( Archiver& arc ) override; - virtual bool AutoArchiveModel( void ) override; + Actor(); + ~Actor(); + + virtual void setContentsSolid(void) override; + void InitThinkStates(void); + void UpdateEyeOrigin(void); + bool RequireThink(void); + void UpdateEnemy(int iMaxDirtyTime); + void UpdateEnemyInternal(void); + void DetectSmokeGrenades(void); + void SetEnemy(Sentient *pEnemy, bool bForceConfirmed); + void SetEnemyPos(Vector vPos); + static void ResetBodyQueue(void); + void AddToBodyQue(void); + Vector GetAntiBunchPoint(void); + static void InitVoid(GlobalFuncs_t *func); + virtual const char *DumpCallTrace(const char *pszFmt, ...) const override; + static void Init(void); + void FixAIParameters(void); + bool AttackEntryAnimation(void); + void CheckForThinkStateTransition(void); + bool CheckForTransition(eThinkState state, eThinkLevel level); + bool PassesTransitionConditions_Grenade(void); + bool PassesTransitionConditions_BadPlace(void); // Added in 2.0 + bool PassesTransitionConditions_Attack(void); + bool PassesTransitionConditions_Disguise(void); + bool PassesTransitionConditions_Curious(void); + bool PassesTransitionConditions_Idle(void); + void UpdateEnableEnemy(void); + void ThinkStateTransitions(void); + void TransitionState(int iNewState, int iPadTime = 0); + void ChangeAnim(void); + void UpdateSayAnim(void); + void UpdateUpperAnim(void); + void UpdateAnim(void); + virtual void StoppedWaitFor(const_str name, bool bDeleting) override; + static void InitTurret(GlobalFuncs_t *func); + void Begin_Turret(void); + void End_Turret(void); + void Suspend_Turret(void); + void Think_Turret(void); + void FinishedAnimation_Turret(void); + void ReceiveAIEvent_Turret( + vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared + ); + void InterruptPoint_Turret(void); + void PathnodeClaimRevoked_Turret(void); + bool Turret_IsRetargeting(void) const; + bool Turret_DecideToSelectState(void); + void Turret_SelectState(void); + bool Turret_CheckRetarget(void); + bool Turret_TryToBecomeCoverGuy(void); + void Turret_BeginRetarget(void); + void Turret_NextRetarget(void); + void Turret_SideStep(int iStepSize, vec3_t vDir); + void State_Turret_Combat(void); + void State_Turret_Reacquire(void); + void State_Turret_TakeSniperNode(void); + void State_Turret_SniperNode(void); + bool State_Turret_RunHome(bool bAttackOnFail); + void State_Turret_RunAway(void); + void State_Turret_Charge(void); + void State_Turret_Grenade(void); + void State_Turret_FakeEnemy(void); + void State_Turret_Wait(void); + void State_Turret_Shoot(void); // Added in 2.0 + void State_Turret_Retarget_Suppress(void); // Added in 2.0 + void State_Turret_Retarget_Sniper_Node(void); + void State_Turret_Retarget_Step_Side_Small(void); + void State_Turret_Retarget_Path_Exact(void); + void State_Turret_Retarget_Path_Near(void); + void State_Turret_Retarget_Step_Side_Medium(void); + void State_Turret_Retarget_Step_Side_Large(void); + void State_Turret_Retarget_Step_Face_Medium(void); + void State_Turret_Retarget_Step_Face_Large(void); + static void InitCover(GlobalFuncs_t *func); + bool Cover_IsValid(PathNode *node); + bool Cover_SetPath(PathNode *node); + void Cover_FindCover(bool bCheckAll); + void Begin_Cover(void); + void End_Cover(void); + void Suspend_Cover(void); + void Think_Cover(void); + void FinishedAnimation_Cover(void); + void PathnodeClaimRevoked_Cover(void); + void State_Cover_NewEnemy(void); + void State_Cover_FindCover(void); + void State_Cover_TakeCover(void); + void State_Cover_FinishReloading(void); + void State_Cover_SpecialAttack(void); + void State_Cover_Target(void); + void State_Cover_Hide(void); + void State_Cover_Shoot(void); + void State_Cover_Grenade(void); + void State_Cover_FindEnemy(void); + void State_Cover_SearchNode(void); + void State_Cover_HuntEnemy(void); + void State_Cover_FakeEnemy(void); + static void InitPatrol(GlobalFuncs_t *func); + void Begin_Patrol(void); + void End_Patrol(void); + void Resume_Patrol(void); + void Think_Patrol(void); + void ShowInfo_Patrol(void); + void IdleThink(void); + static void InitRunner(GlobalFuncs_t *func); + void Begin_Runner(void); + void End_Runner(void); + void Resume_Runner(void); + void Think_Runner(void); + void ShowInfo_Runner(void); + static void InitAlarm(GlobalFuncs_t *func); + void Begin_Alarm(void); + void End_Alarm(void); + void State_Alarm_StartThread(void); + void State_Alarm_Move(void); + void State_Alarm_Idle(void); + void Think_Alarm(void); + void FinishedAnimation_Alarm(void); + static void InitNoClip(GlobalFuncs_t *func); + bool IsNoClipState(int state); + void Think_NoClip(void); + bool ValidGrenadePath(const Vector &vFrom, const Vector &vTo, Vector &vVel); + static Vector CalcThrowVelocity(const Vector& vFrom, const Vector& vTo); + Vector CanThrowGrenade(const Vector &vFrom, const Vector &vTo); + static Vector CalcRollVelocity(const Vector& vFrom, const Vector& vTo); + Vector CanRollGrenade(const Vector &vFrom, const Vector &vTo); + bool CanTossGrenadeThroughHint( + GrenadeHint *pHint, + const Vector &vFrom, + const Vector &vTo, + bool bDesperate, + Vector *pvVel, + eGrenadeTossMode *peMode + ); + static Vector GrenadeThrowPoint(const Vector& vFrom, const Vector& vDelta, const_str csAnim); + Vector CalcKickVelocity(Vector &vDelta, float fDist) const; + bool CanKickGrenade(Vector &vFrom, Vector &vTo, Vector &vFace, Vector *pvVel); + bool GrenadeWillHurtTeamAt(const Vector &vTo); + bool CanGetGrenadeFromAToB( + const Vector &vFrom, const Vector &vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode + ); + bool DecideToThrowGrenade(const Vector &vTo, Vector *pvVel, eGrenadeTossMode *peMode, bool bDesperate); + void Grenade_EventFire(Event *ev); + void GenericGrenadeTossThink(void); + static void InitGrenade(GlobalFuncs_t *func); + bool Grenade_Acquire(eGrenadeState eNextState, const_str csReturnAnim); + void Grenade_Flee(void); + void Grenade_ThrowAcquire(void); + void Grenade_Throw(void); + void Grenade_KickAcquire(void); + void Grenade_Kick(void); + void Grenade_MartyrAcquire(void); + void Grenade_Martyr(void); + void Grenade_Wait(void); + void Grenade_NextThinkState(void); + void Grenade_EventAttach(Event *ev); + void Grenade_EventDetach(Event *ev); + void Begin_Grenade(void); + void End_Grenade(void); + void Resume_Grenade(void); + void Think_Grenade(void); + void FinishedAnimation_Grenade(void); + static void InitCurious(GlobalFuncs_t *func); + void SetCuriousAnimHint(int iAnimHint); + void Begin_Curious(void); + void End_Curious(void); + void Resume_Curious(void); + void Suspend_Curious(void); + void Think_Curious(void); + void FinishedAnimation_Curious(void); + void LookAtCuriosity(void); + void TimeOutCurious(void); + void State_Disguise_Wait(void); + void State_Disguise_Papers(void); + void State_Disguise_Fake_Papers(void); + void State_Disguise_Enemy(void); + void State_Disguise_Halt(void); + void State_Disguise_Accept(void); + void State_Disguise_Deny(void); + static void InitDisguiseSalute(GlobalFuncs_t *func); + void Begin_DisguiseSalute(void); + void End_DisguiseSalute(void); + void Resume_DisguiseSalute(void); + void Suspend_DisguiseSalute(void); + void Think_DisguiseSalute(void); + void FinishedAnimation_DisguiseSalute(void); + static void InitDisguiseSentry(GlobalFuncs_t *func); + void Begin_DisguiseSentry(void); + void End_DisguiseSentry(void); + void Resume_DisguiseSentry(void); + void Suspend_DisguiseSentry(void); + void Think_DisguiseSentry(void); + static void InitDisguiseOfficer(GlobalFuncs_t *func); + void Begin_DisguiseOfficer(void); + void End_DisguiseOfficer(void); + void Resume_DisguiseOfficer(void); + void Suspend_DisguiseOfficer(void); + void Think_DisguiseOfficer(void); + static void InitDisguiseRover(GlobalFuncs_t *func); + void Begin_DisguiseRover(void); + void End_DisguiseRover(void); + void Resume_DisguiseRover(void); + void Suspend_DisguiseRover(void); + void Think_DisguiseRover(void); + static void InitDisguiseNone(GlobalFuncs_t *func); + static void InitIdle(GlobalFuncs_t *func); + void Begin_Idle(void); + void Think_Idle(void); + static void InitMachineGunner(GlobalFuncs_t *func); + void Begin_MachineGunner(void); + void End_MachineGunner(void); + void BecomeTurretGuy(void); + void ThinkHoldGun_TurretGun(void); // Added in 2.0 + void Think_MachineGunner_TurretGun(void); // Added in 2.0 + void Think_MachineGunner(void); + void FinishedAnimation_MachineGunner(void); + bool MachineGunner_CanSee(Entity *ent, float fov, float vision_distance); + static void InitDogIdle(GlobalFuncs_t *func); + static void InitDogAttack(GlobalFuncs_t *func); + static void InitDogCurious(GlobalFuncs_t *func); + void Begin_Dog(void); + void End_Dog(void); + void Think_Dog_Idle(void); + void Think_Dog_Attack(void); + void Think_Dog_Curious(void); + static void InitAnim(GlobalFuncs_t *func); + void Begin_Anim(void); + void Think_Anim(void); + void FinishedAnimation_Anim(void); + void ShowInfo_Anim(void); + static void InitAnimCurious(GlobalFuncs_t *func); + void Begin_AnimCurious(void); + void Think_AnimCurious(void); + void FinishedAnimation_AnimCurious(void); + static void InitAim(GlobalFuncs_t *func); + void Begin_Aim(void); + void Think_Aim(void); + void ShowInfo_Aim(void); + static void InitBalconyIdle(GlobalFuncs_t *func); + static void InitBalconyCurious(GlobalFuncs_t *func); + static void InitBalconyAttack(GlobalFuncs_t *func); + static void InitBalconyDisguise(GlobalFuncs_t *func); + static void InitBalconyGrenade(GlobalFuncs_t *func); + static void InitBalconyPain(GlobalFuncs_t *func); + static void InitBalconyKilled(GlobalFuncs_t *func); + void Pain_Balcony(Event *ev); + void Killed_Balcony(Event *ev, bool bPlayDeathAnim); + void Think_BalconyAttack(void); + void Begin_BalconyAttack(void); + void FinishedAnimation_BalconyAttack(void); + void State_Balcony_PostShoot(void); + void State_Balcony_FindEnemy(void); + void State_Balcony_Target(void); + void State_Balcony_Shoot(void); + void Begin_BalconyKilled(void); + void End_BalconyKilled(void); + void Think_BalconyKilled(void); + void FinishedAnimation_BalconyKilled(void); + bool CalcFallPath(void); + static void InitPain(GlobalFuncs_t *func); + void Begin_Pain(void); + void Think_Pain(void); + void FinishedAnimation_Pain(void); + static void InitDead(GlobalFuncs_t *func); + static void InitKilled(GlobalFuncs_t *func); + void Begin_Killed(void); + void Think_Killed(void); + void FinishedAnimation_Killed(void); + static void InitWeaponless(GlobalFuncs_t *func); + void Begin_Weaponless(void); + void Suspend_Weaponless(void); + void Think_Weaponless(void); + void FinishedAnimation_Weaponless(void); + void State_Weaponless_Normal(void); + void State_Weaponless_Grenade(void); + static void InitBadPlace(GlobalFuncs_t *func); + // Added in 2.0 + //==== + void Begin_BadPlace(void); + void End_BadPlace(void); + void Think_BadPlace(void); + //==== + // Added in 2.30 + //==== + static void InitRunAndShoot(GlobalFuncs_t *func); + void Begin_RunAndShoot(void); + void End_RunAndShoot(void); + void Resume_RunAndShoot(void); + void Think_RunAndShoot(void); + void ShowInfo_RunAndShoot(void); + void State_RunAndShoot_Running(void); + bool RunAndShoot_MoveToPatrolCurrentNode(void); + //==== + virtual void Think(void) override; + void PostThink(bool bDontFaceWall); + virtual void SetMoveInfo(mmove_t *mm) override; + virtual void GetMoveInfo(mmove_t *mm) override; + void DoFailSafeMove(vec3_t dest); + void TouchStuff(mmove_t *mm); + void ExtractConstraints(mmove_t *mm); + void EventGiveWeaponInternal(Event *ev); + void EventGiveWeapon(Event *ev); + void EventGetWeapon(Event *ev); + void FireWeapon(Event *ev); + bool FriendlyInLineOfFire(Entity *other); // Added in 2.0 + Vector VirtualEyePosition(); // Added in 2.0 + virtual bool CanTarget(void) override; + virtual bool IsImmortal(void) override; + static bool IsVoidState(int state); + static bool IsIdleState(int state); + static bool IsCuriousState(int state); + static bool IsDisguiseState(int state); + static bool IsAttackState(int state); + static bool IsGrenadeState(int state); + static bool IsBadPlaceState(int state); // Added in 2.0 + static bool IsPainState(int state); + static bool IsKilledState(int state); + static bool IsMachineGunnerState(int state); + static bool IsDogState(int state); + void IgnoreSoundSet(int iType); + void IgnoreSoundSetAll(void); + void IgnoreSoundClear(int iType); + void IgnoreSoundClearAll(void); + bool IgnoreSound(int iType); + void EventShareEnemy(Event *ev); + void EventShareGrenade(Event *ev); + void ReceiveAIEvent(vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared); + void DefaultReceiveAIEvent( + vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared + ); + int PriorityForEventType(int iType); + void CuriousSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared); + void WeaponSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator); + void FootstepSound(vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator); + void VoiceSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator); + void GrenadeNotification(Entity *originator); + void SetGrenade(Entity *pGrenade); + void UpdateBadPlaces(void); // Added in 2.0 + void NotifySquadmateKilled(Sentient *pSquadMate, Sentient *pAttacker); + void RaiseAlertnessForEventType(int iType); + void RaiseAlertness(float fAmount); + virtual bool CanSee(Entity *e1, float fov, float vision_distance, bool bNoEnts) override; + using Sentient::CanSee; + virtual Vector GunPosition(void) override; + bool WithinVisionDistance(Entity *ent) const; + bool InFOV(Vector pos, float check_fov, float check_fovdot); + bool EnemyInFOV(int iMaxDirtyTime); + bool InFOV(Vector pos); + bool InFOV(Entity *ent); + bool CanSeeNoFOV(Entity *ent); + bool CanSeeFOV(Entity *ent); + bool CanSeeEnemyFOV(int iMaxFovDirtyTime, int iMaxSightDirtyTime); + bool CanShoot(Entity *ent); + virtual bool CanSeeFrom(vec3_t pos, Entity *ent); + bool CanSeeEnemy(int iMaxDirtyTime); + bool CanShootEnemy(int iMaxDirtyTime); + void ShowInfo(void); + virtual void ShowInfo(float fDot, float fDist) override; + void DefaultPain(Event *ev); + void HandlePain(Event *ev); + void EventPain(Event *ev); + void DefaultKilled(Event *ev, bool bPlayDeathAnim); + void HandleKilled(Event *ev, bool bPlayDeathAnim); + void DispatchEventKilled(Event *ev, bool bPlayDeathAnim); + void EventKilled(Event *ev); + void EventBeDead(Event *ev); + void DeathEmbalm(Event *ev); + void DeathSinkStart(Event *ev); + bool NoticeShot(Sentient *pShooter, Sentient *pTarget, float fDist); + bool NoticeFootstep(Sentient *pPedestrian); + bool NoticeVoice(Sentient *pVocallist); + void ClearLookEntity(void); + void LookAt(const Vector &vec); + void LookAt(Listener *l); + void ForwardLook(void); + void LookAtLookEntity(void); + void IdleLook(void); + void IdleLook(vec3_t dir); + void SetDesiredLookDir(vec3_t dir); + void SetDesiredLookAnglesRelative(vec3_t ang); + void EventLookAt(Event *ev); + void EventEyesLookAt(Event *ev); + void NoPoint(void); + void IdlePoint(void); + void ClearPointEntity(void); + void PointAt(const Vector &vec); + void PointAt(Listener *l); + void EventPointAt(Event *ev); + void ClearTurnEntity(void); + void TurnTo(const Vector &vec); + void TurnTo(Listener *l); + void IdleTurn(void); + void EventTurnTo(Event *ev); + void EventSetTurnDoneError(Event *ev); + void EventGetTurnDoneError(Event *ev); + void LookAround(float fFovAdd); + bool SoundSayAnim(const_str name, byte bLevelSayAnim); + void EventSetAnim(Event *ev); + void EventIdleSayAnim(Event *ev); + void EventSayAnim(Event *ev); + void EventSetSayAnim(Event *ev); + void EventSetMotionAnim(Event *ev); + void EventSetAimMotionAnim(Event *ev); + void EventSetActionAnim(Event *ev); + void EventUpperAnim(Event *ev); + void EventSetUpperAnim(Event *ev); + void EventEndActionAnim(Event *ev); + void EventDamagePuff(Event *ev); + void SafeSetOrigin(vec3_t newOrigin); + void DoMove(void); + void AnimFinished(int slot, bool stop); + virtual void AnimFinished(int slot) override; + void PlayAnimation(Event *ev); + void PlayScriptedAnimation(Event *ev); + void PlayNoclipAnimation(Event *ev); + void PlayAttachedAnimation(Event *ev); // Added in 2.0 + void MoveDest(float fMoveSpeed); + void MovePath(float fMoveSpeed); + void MovePathGoal(float fMoveSpeed); + void Dumb(Event *ev); + void PhysicsOn(Event *ev); + void PhysicsOff(Event *ev); + void EventStart(Event *ev); + void EventGetMood(Event *ev); + void EventSetMood(Event *ev); + void EventGetAngleYawSpeed(Event *ev); + void EventSetAngleYawSpeed(Event *ev); + void EventSetAimTarget(Event *ev); + void UpdateAngles(void); + void SetLeashHome(Vector vHome); + void AimAtTargetPos(void); + void AimAtAimNode(void); + void AimAtEnemyBehavior(void); + void FaceMotion(void); + void FaceDirectionDuringMotion(vec3_t vLook); + float PathDistanceAlongVector(vec3_t vDir); + void FaceEnemyOrMotion(int iTimeIntoMove); + static int NextUpdateTime(int iLastUpdateTime, int iUpdatePeriod); + void ResetBoneControllers(void); + void UpdateBoneControllers(void); + void ReadyToFire(Event *ev); + void EventGetSight(Event *ev); + void EventSetSight(Event *ev); + void EventGetHearing(Event *ev); + void EventSetHearing(Event *ev); + void ClearPatrolCurrentNode(void); + void NextPatrolCurrentNode(void); + void SetPatrolCurrentNode(Vector &vec); + void SetPatrolCurrentNode(Listener *l); + void EventSetPatrolPath(Event *ev); + void EventGetPatrolPath(Event *ev); + void EventSetPatrolWaitTrigger(Event *ev); + void EventGetPatrolWaitTrigger(Event *ev); + void ShowInfo_PatrolCurrentNode(void); + bool MoveOnPathWithSquad(void); + bool MoveToWaypointWithPlayer(void); + bool PatrolNextNodeExists(void); + void UpdatePatrolCurrentNode(void); + bool MoveToPatrolCurrentNode(void); + void ClearAimNode(void); + void SetAimNode(const Vector &vec); + void SetAimNode(Listener *l); + void ShowInfo_AimNode(void); + void EventSetAccuracy(Event *ev); + void EventGetAccuracy(Event *ev); + int GetThinkType(const_str csName); + void SetThink(eThinkState state, eThinkNum think); + void SetThinkIdle(eThinkNum think_idle); + void SetThinkState(eThinkState state, eThinkLevel level); + void EndCurrentThinkState(void); + void ClearThinkStates(void); + int CurrentThink(void) const; + bool IsAttacking(void) const; + void EventGetFov(Event *ev); + void EventSetFov(Event *ev); + void EventSetDestIdle(Event *ev); + void EventSetDestIdle2(Event *ev); + void EventSetTypeIdle(Event *ev); + void EventGetTypeIdle(Event *ev); + void EventSetTypeAttack(Event *ev); + void EventGetTypeAttack(Event *ev); + void EventSetTypeDisguise(Event *ev); + void EventGetTypeDisguise(Event *ev); + void EventSetDisguiseLevel(Event *ev); + void EventGetDisguiseLevel(Event *ev); + void EventSetTypeGrenade(Event *ev); + void EventGetTypeGrenade(Event *ev); + void EventSetMinDistance(Event *ev); + void EventGetMinDistance(Event *ev); + void EventSetMaxDistance(Event *ev); + void EventGetMaxDistance(Event *ev); + void EventGetLeash(Event *ev); + void EventSetLeash(Event *ev); + void EventGetInterval(Event *ev); + void EventSetInterval(Event *ev); + void EventDistToEnemy(Event *ev); + void EventGetRunAnim(Event *ev); + void EventGetWalkAnim(Event *ev); + void EventGetAnimName(Event *ev); + void EventSetAnimName(Event *ev); + void EventSetDisguiseRange(Event *ev); + void EventGetDisguiseRange(Event *ev); + void EventSetDisguisePeriod(Event *ev); + void EventGetDisguisePeriod(Event *ev); + void EventSetDisguiseAcceptThread(Event *ev); + void EventGetDisguiseAcceptThread(Event *ev); + void EventAttackPlayer(Event *ev); + void ForceAttackPlayer(void); + void EventSetAlarmNode(Event *ev); + void EventGetAlarmNode(Event *ev); + void EventSetPreAlarmThread(Event *ev); // Added in 2.30 + void EventSetAlarmThread(Event *ev); + void EventGetAlarmThread(Event *ev); + void EventSetSoundAwareness(Event *ev); + void EventGetSoundAwareness(Event *ev); + void EventSetGrenadeAwareness(Event *ev); + void EventGetGrenadeAwareness(Event *ev); + str ThinkName(void) const; + str ThinkStateName(void) const; + void EventSetTurret(Event *ev); + void EventGetTurret(Event *ev); + void EventEnableEnemy(Event *ev); + void EventEnablePain(Event *ev); + void EventActivate(Event *ev); + void EventGetAmmoGrenade(Event *ev); + void EventSetAmmoGrenade(Event *ev); + void EventInterruptPoint(Event *ev); + // Added in 2.0 + //==== + void EventGetVisibilityThreshold(Event *ev); + void EventSetVisibilityThreshold(Event *ev); + void EventSetDefaultVisibilityThreshold(Event *ev); + void EventGetSuppressChance(Event *ev); + void EventSetSuppressChance(Event *ev); + //==== + void EventAnimScript(Event *ev); + void EventAnimScript_Scripted(Event *ev); + void EventAnimScript_Noclip(Event *ev); + void EventAnimScript_Attached(Event *ev); + void EventReload_mg42(Event *ev); + void SetPathWithLeash(Vector vDestPos, const char *description, int iMaxDirtyTime); + void SetPathWithLeash(SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime); + void FindPathAwayWithLeash(vec3_t vAwayFrom, vec3_t vDirPreferred, float fMinSafeDist); + void FindPathNearWithLeash(vec3_t vNearbyTo, float fCloseDistSquared); + bool CanMovePathWithLeash(void) const; + bool MovePathWithLeash(void); + bool ShortenPathToAttack(float fMinDist); + void StrafeToAttack(float fDist, vec3_t vDir); + virtual Vector GunTarget(bool bNoCollision, const vec3_t position, const vec3_t forward) override; + virtual qboolean setModel(void) override; + void EventSetHeadModel(Event *ev); + void EventGetHeadModel(Event *ev); + void EventSetHeadSkin(Event *ev); + void EventGetHeadSkin(Event *ev); + void EventSetNoIdle(Event *ev); + void EventGetNoIdle(Event *ev); + void EventGetEnemy(Event *ev); + void EventSetMaxNoticeTimeScale(Event *ev); + void EventGetMaxNoticeTimeScale(Event *ev); + void EventSetFixedLeash(Event *ev); + void EventGetFixedLeash(Event *ev); + void Holster(void); + void HolsterOffHand(void); // Added in 2.0 + void Unholster(void); + void UnholsterOffHand(void); // Added in 2.0 + void EventHolster(Event *ev); + void EventUnholster(Event *ev); + void EventSoundDone(Event *ev); + void EventSound(Event *ev); + void EventIsEnemyVisible(Event *ev); + void EventGetEnemyVisibleChangeTime(Event *ev); + void EventGetLastEnemyVisibleTime(Event *ev); + void EventSetFallHeight(Event *ev); + void EventGetFallHeight(Event *ev); + void EventCanMoveTo(Event *ev); + void EventMoveDir(Event *ev); + void EventIntervalDir(Event *ev); + void EventResetLeash(Event *ev); + void EventTether(Event *ev); + void EventGetThinkState(Event *ev); + void EventGetEnemyShareRange(Event *ev); + void EventSetEnemyShareRange(Event *ev); + void EventGetKickDir(Event *ev); + void EventGetNoLongPain(Event *ev); + void EventSetNoLongPain(Event *ev); + void EventGetFavoriteEnemy(Event *ev); + void EventSetFavoriteEnemy(Event *ev); + void EventFindEnemy(Event *ev); // Added in 2.0 + void EventGetMumble(Event *ev); + void EventSetMumble(Event *ev); + void EventGetBreathSteam(Event *ev); + void EventSetBreathSteam(Event *ev); + void EventSetNextBreathTime(Event *ev); + void EventCalcGrenadeToss2(Event *ev); + void EventCalcGrenadeToss(Event *ev); + void EventGetNoSurprise(Event *ev); + void EventSetNoSurprise(Event *ev); + void EventGetSilent(Event *ev); + void EventSetSilent(Event *ev); + void EventGetAvoidPlayer(Event *ev); + void EventSetAvoidPlayer(Event *ev); + void EventGetLookAroundAngle(Event *ev); + void EventSetLookAroundAngle(Event *ev); + void EventHasCompleteLookahead(Event *ev); + void EventPathDist(Event *ev); + void EventCanShootEnemyFrom(Event *ev); + void EventCanShoot(Event *ev); + void EventSetInReload(Event *ev); + void EventGetInReload(Event *ev); + void EventSetReloadCover(Event *ev); + void EventBreakSpecial(Event *ev); + void GetVoiceType(Event *ev); + void SetVoiceType(Event *ev); + void ResolveVoiceType(void); + void EventSetBalconyHeight(Event *ev); + void EventGetBalconyHeight(Event *ev); + // Added in 2.0 + //==== + void EventSetIgnoreBadPlace(Event *ev); + void EventGetIgnoreBadPlace(Event *ev); + void EventEnableEnemySwitch(Event *ev); + void EventDisableEnemySwitch(Event *ev); + void EventSetRunAnimRate(Event *ev); + void EventGetRunAnimRate(Event *ev); + void Landed(Event *ev); + bool IsOnFloor(void); + //==== + // Added in 2.30 + //==== + void GetNationality(Event *ev); + void SetNationality(Event *ev); + void EventWriteStats(Event *ev); + void EventCuriousOff(Event *ev); + void EventCuriousOn(Event *ev); + //==== + PathNode *FindSniperNodeAndSetPath(bool *pbTryAgain); + void Remove(Event *ev); + void DontFaceWall(void); + bool AvoidingFacingWall(void) const; + void EndStates(void); + void ClearStates(void); + void CheckUnregister(void); + void BecomeCorpse(void); + virtual void PathnodeClaimRevoked(PathNode *node) override; + void SetPathToNotBlockSentient(Sentient *pOther); + void EventSetMoveDoneRadius(Event *ev); + void EventGetMoveDoneRadius(Event *ev); // Added in 2.0 + virtual void ClearEnemies(void) override; + bool EnemyIsDisguised(void); + virtual void setOriginEvent(Vector org) override; + virtual void DumpAnimInfo(void) override; + static void ArchiveStatic(Archiver &arc); + virtual void Archive(Archiver& arc) override; + virtual bool AutoArchiveModel(void) override; + virtual bool IsDisabled() const override; // Added in 2.30 }; -#define SAVE_FLAG_NEW_ANIM (1<<0) -#define SAVE_FLAG_FORWARD_SPEED (1<<1) -#define SAVE_FLAG_BEHAVIOR (1<<2) -#define SAVE_FLAG_PATH (1<<3) -#define SAVE_FLAG_NOISE (1<<4) -#define SAVE_FLAG_SCRIPT_THREAD (1<<5) -#define SAVE_FLAG_ACTOR_THREAD (1<<6) -#define SAVE_FLAG_KILL_THREAD (1<<7) -#define SAVE_FLAG_STATE (1<<8) -#define SAVE_FLAG_IDLE_THREAD (1<<7) -#define SAVE_FLAG_PARTS (1<<10) -#define SAVE_FLAG_TRIGGER (1<<11) -#define SAVE_FLAG_STATE_FLAGS (1<<12) -#define SAVE_FLAG_COMMAND (1<<13) -#define SAVE_FLAG_STAGE (1<<14) -#define SAVE_FLAG_NUM_OF_SPAWNS (1<<15) -#define SAVE_FLAG_SPAWN_PARENT (1<<16) -#define SAVE_FLAG_DIALOG (1<<17) -#define SAVE_FLAG_SAVED_STUFF (1<<18) -#define SAVE_FLAG_LAST_ANIM_EVENT (1<<19) -#define SAVE_FLAG_PICKUP_ENT (1<<20) -#define SAVE_FLAG_PAIN (1<<21) -#define SAVE_FLAG_SPAWN_ITEMS (1<<22) +#define SAVE_FLAG_NEW_ANIM (1 << 0) +#define SAVE_FLAG_FORWARD_SPEED (1 << 1) +#define SAVE_FLAG_BEHAVIOR (1 << 2) +#define SAVE_FLAG_PATH (1 << 3) +#define SAVE_FLAG_NOISE (1 << 4) +#define SAVE_FLAG_SCRIPT_THREAD (1 << 5) +#define SAVE_FLAG_ACTOR_THREAD (1 << 6) +#define SAVE_FLAG_KILL_THREAD (1 << 7) +#define SAVE_FLAG_STATE (1 << 8) +#define SAVE_FLAG_IDLE_THREAD (1 << 7) +#define SAVE_FLAG_PARTS (1 << 10) +#define SAVE_FLAG_TRIGGER (1 << 11) +#define SAVE_FLAG_STATE_FLAGS (1 << 12) +#define SAVE_FLAG_COMMAND (1 << 13) +#define SAVE_FLAG_STAGE (1 << 14) +#define SAVE_FLAG_NUM_OF_SPAWNS (1 << 15) +#define SAVE_FLAG_SPAWN_PARENT (1 << 16) +#define SAVE_FLAG_DIALOG (1 << 17) +#define SAVE_FLAG_SAVED_STUFF (1 << 18) +#define SAVE_FLAG_LAST_ANIM_EVENT (1 << 19) +#define SAVE_FLAG_PICKUP_ENT (1 << 20) +#define SAVE_FLAG_PAIN (1 << 21) +#define SAVE_FLAG_SPAWN_ITEMS (1 << 22) -inline void Actor::ArchiveStatic - ( - Archiver &arc - ) +/* +=============== +Actor::TransitionState + +=============== +*/ +inline void Actor::TransitionState(int iNewState, int iPadTime) { - for( int i = MAX_BODYQUEUE - 1; i >= 0; i-- ) - { - arc.ArchiveSafePointer( &mBodyQueue[ i ] ); - } - - arc.ArchiveInteger( &mCurBody ); + m_State = iNewState; + m_iStateTime = level.inttime + iPadTime; } -inline void Actor::Archive - ( - Archiver &arc - ) +/* +=============== +Actor::NextUpdateTime + +Returns next update time. +=============== +*/ +inline int Actor::NextUpdateTime(int iLastUpdateTime, int iUpdatePeriod) { - SimpleActor::Archive( arc ); + int i = iLastUpdateTime; - for( int i = NUM_THINKSTATES - 1; i >= 0; i-- ) - { - ArchiveEnum(m_ThinkMap[i], eThinkNum); - } + do { + i += iUpdatePeriod; + } while (i < level.inttime); - for( int i = NUM_THINKLEVELS - 1; i >= 0; i-- ) - { - ArchiveEnum(m_ThinkStates[i], eThinkState); - ArchiveEnum(m_Think[i], eThinkNum); - } + return i; +} - ArchiveEnum(m_ThinkLevel, eThinkLevel); - ArchiveEnum(m_ThinkState, eThinkState); - arc.ArchiveInteger( &m_State); - arc.ArchiveInteger( &m_iStateTime); - arc.ArchiveBool( &m_bLockThinkState); - arc.ArchiveBool( &m_bDirtyThinkState ); - arc.ArchiveInteger( &mVoiceType ); - arc.ArchiveBool( &m_bSilent); - arc.ArchiveBool( &m_bNoSurprise); - arc.ArchiveBool( &m_bMumble); - arc.ArchiveBool( &m_bBreathSteam); +/* +=============== +Actor::InFOV - Director.ArchiveString( arc, m_csHeadModel ); - Director.ArchiveString( arc, m_csHeadSkin ); - Director.ArchiveString( arc, m_csWeapon ); - Director.ArchiveString( arc, m_csLoadOut ); - arc.ArchiveSafePointer( &m_FavoriteEnemy ); - arc.ArchiveInteger( &m_iEnemyCheckTime ); - arc.ArchiveInteger( &m_iEnemyChangeTime ); - arc.ArchiveInteger( &m_iEnemyVisibleCheckTime ); - arc.ArchiveInteger( &m_iEnemyVisibleChangeTime ); - arc.ArchiveInteger( &m_iLastEnemyVisibleTime ); - arc.ArchiveInteger( &m_iEnemyFovCheckTime ); - arc.ArchiveInteger( &m_iEnemyFovChangeTime ); - arc.ArchiveVector( &m_vLastEnemyPos ); - arc.ArchiveInteger( &m_iLastEnemyPosChangeTime ); - arc.ArchiveFloat( &m_fMaxShareDistSquared ); - arc.ArchiveInteger( &m_iCanShootCheckTime ); - arc.ArchiveBool( &m_bCanShootEnemy ); - arc.ArchiveBool( &m_bDesiredEnableEnemy ); - arc.ArchiveBool( &m_bEnableEnemy ); - arc.ArchiveBool( &m_bEnablePain ); - arc.ArchiveBool( &m_bNoLongPain ); - arc.ArchiveBool( &m_bNewEnemy ); - arc.ArchiveBool( &m_bEnemyIsDisguised ); - arc.ArchiveBool( &m_bEnemyVisible ); - arc.ArchiveBool( &m_bEnemyInFOV ); - arc.ArchiveBool( &m_bForceAttackPlayer ); - arc.ArchiveBool( &m_bAutoAvoidPlayer ); - arc.ArchiveBool( &m_bNoIdleAfterAnim ); - Director.ArchiveString( arc, m_csAnimScript ); - arc.ArchiveBool( &m_bAnimScriptSet ); - arc.ArchiveInteger( &m_AnimMode ); - arc.ArchiveFloat( &m_fDfwRequestedYaw ); - arc.ArchiveFloat( &m_fDfwDerivedYaw ); - arc.ArchiveVector( &m_vDfwPos ); - arc.ArchiveFloat( &m_fDfwTime ); - arc.ArchiveInteger( &m_iGunPositionCheckTime ); - arc.ArchiveVector( &m_vGunPosition ); - arc.ArchiveInteger( &m_iWallDodgeTimeout ); - arc.ArchiveFloat( &m_PrevObstacleNormal[ 0 ] ); - arc.ArchiveFloat( &m_PrevObstacleNormal[ 1 ] ); - arc.ArchiveChar( &m_WallDir ); - arc.ArchiveFloat( &m_fMoveDoneRadiusSquared ); - arc.ArchiveBool( &m_bFaceEnemy ); - arc.ArchiveBool( &m_bDoPhysics ); - arc.ArchiveBool( &m_bPatrolWaitTrigger ); - arc.ArchiveBool( &m_bBecomeRunner ); - arc.ArchiveBool( &m_bScriptGoalValid ); - arc.ArchiveVector( &m_vScriptGoal ); - arc.ArchiveInteger( &m_iNextWatchStepTime ); - arc.ArchiveSafePointer( &m_patrolCurrentNode ); - Director.ArchiveString( arc, m_csPatrolCurrentAnim ); - arc.ArchiveInteger( &m_iSquadStandTime ); - arc.ArchiveFloat( &m_fInterval ); - arc.ArchiveInteger( &m_iIntervalDirTime ); - arc.ArchiveVector( &m_vIntervalDir ); - arc.ArchiveShort( &m_sCurrentPathNodeIndex ); - arc.ArchiveInteger( &m_PainState ); - arc.ArchiveInteger( &m_iCuriousTime ); - arc.ArchiveInteger( &m_iCuriousLevel ); - arc.ArchiveInteger( &m_iCuriousAnimHint ); - arc.ArchiveInteger( &m_iNextDisguiseTime ); - arc.ArchiveInteger( &m_iDisguisePeriod ); - arc.ArchiveFloat( &m_fMaxDisguiseDistSquared ); - arc.ArchiveInteger( &m_iEnemyShowPapersTime ); - m_DisguiseAcceptThread.Archive( arc ); - arc.ArchiveInteger( &m_iDisguiseLevel ); - arc.ArchiveSafePointer( &m_AlarmNode ); - m_AlarmThread.Archive( arc ); - arc.ArchiveInteger( &m_iRunHomeTime ); - arc.ArchiveBool( &m_bTurretNoInitialCover ); - arc.ArchiveInteger( &m_iPotentialCoverCount ); +Returns true if pos is within fov. +=============== +*/ +inline bool Actor::InFOV(Vector pos) +{ + return InFOV(pos, m_fFov, m_fFovDot); +} - for( int i = MAX_COVER_NODES - 1; i >= 0; i-- ) - { - arc.ArchiveObjectPointer( ( Class ** ) &m_pPotentialCoverNode[ i ] ); - } +/* +=============== +Actor::InFOV - arc.ArchiveObjectPointer( ( Class ** )&m_pCoverNode ); - Director.ArchiveString( arc, m_csSpecialAttack ); +Returns true if ent is within fov. +=============== +*/ +inline bool Actor::InFOV(Entity *ent) +{ + if (ent == m_Enemy) { + return EnemyInFOV(0); + } else { + return InFOV(ent->centroid); + } +} - arc.ArchiveBool( &m_bInReload); - arc.ArchiveBool( &m_bNeedReload); - arc.ArchiveBool( &mbBreakSpecialAttack); - arc.ArchiveBool( &m_bGrenadeBounced); - arc.ArchiveSafePointer( &m_pGrenade); - arc.ArchiveVector( &m_vGrenadePos); - arc.ArchiveInteger( &m_iFirstGrenadeTime); - ArchiveEnum( m_eGrenadeState, eGrenadeState ); - ArchiveEnum( m_eGrenadeMode, eGrenadeTossMode ); - arc.ArchiveVector( &m_vGrenadeVel); - arc.ArchiveVector( &m_vKickDir); - arc.ArchiveFloat( &m_fNoticeTimeScale); - arc.ArchiveFloat( &m_fMaxNoticeTimeScale); - m_PotentialEnemies.Archive( arc ); - arc.ArchiveFloat( &m_fSight ); - arc.ArchiveFloat( &m_fHearing ); - arc.ArchiveFloat( &m_fSoundAwareness ); - arc.ArchiveFloat( &m_fGrenadeAwareness ); - arc.ArchiveInteger( &m_iIgnoreSoundsMask ); - arc.ArchiveFloat( &m_fFov ); - arc.ArchiveFloat( &m_fFovDot ); - arc.ArchiveInteger( &m_iEyeUpdateTime ); - arc.ArchiveVector( &m_vEyeDir ); - arc.ArchiveInteger( &m_iNextLookTime ); - arc.ArchiveFloat( &m_fLookAroundFov ); - arc.ArchiveSafePointer( &m_pLookEntity ); - arc.ArchiveInteger( &m_iLookFlags ); - arc.ArchiveSafePointer( &m_pPointEntity ); - arc.ArchiveSafePointer( &m_pTurnEntity ); - arc.ArchiveFloat( &m_fTurnDoneError ); - arc.ArchiveFloat( &m_fAngleYawSpeed ); - arc.ArchiveSafePointer( &m_aimNode ); - arc.ArchiveInteger( &m_eDontFaceWallMode ); - arc.ArchiveInteger( &m_iLastFaceDecideTime ); - arc.ArchiveBool( &m_bHeadAnglesAchieved ); - arc.ArchiveBool( &m_bLUpperArmAnglesAchieved ); - arc.ArchiveBool( &m_bTorsoAnglesAchieved ); - arc.ArchiveFloat( &m_fHeadMaxTurnSpeed ); - arc.ArchiveVec3( m_vHeadDesiredAngles ); - arc.ArchiveFloat( &m_fLUpperArmTurnSpeed ); - arc.ArchiveVec3( m_vLUpperArmDesiredAngles ); - arc.ArchiveFloat( &m_fTorsoMaxTurnSpeed ); - arc.ArchiveFloat( &m_fTorsoCurrentTurnSpeed ); - arc.ArchiveVec3( m_vTorsoDesiredAngles ); - arc.ArchiveVector( &m_vHome ); - arc.ArchiveSafePointer( &m_pTetherEnt ); - arc.ArchiveFloat( &m_fMinDistance ); - arc.ArchiveFloat( &m_fMinDistanceSquared ); - arc.ArchiveFloat( &m_fMaxDistance ); - arc.ArchiveFloat( &m_fMaxDistanceSquared ); - arc.ArchiveFloat( &m_fLeash ); - arc.ArchiveFloat( &m_fLeashSquared ); - arc.ArchiveBool( &m_bFixedLeash ); - arc.ArchiveBool( &m_bAnimating ); - arc.ArchiveBool( &m_bDog ); +inline bool Actor::CanSeeNoFOV(Entity *ent) +{ + bool bCanSee; - byte length; + if (ent == m_Enemy) { + return CanSeeEnemy(0); + } - if( arc.Saving() ) - { - if( m_pFallPath ) - length = m_pFallPath->length; - else - length = 0; - } - arc.ArchiveByte( &length ); + bCanSee = false; - if( length ) - { - if( arc.Loading() ) - { - m_pFallPath = ( FallPath * )gi.Malloc((sizeof(FallPath::pos)) * length + (sizeof(FallPath) - sizeof(FallPath::pos))); - m_pFallPath->length = length; - } + if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum)) { + bCanSee = CanSee(ent, 0, 0, false); + } - arc.ArchiveByte( &m_pFallPath->currentPos ); - arc.ArchiveByte( &m_pFallPath->loop ); + return bCanSee; +} - for( int i = 0; i < length; i++ ) - { - arc.ArchiveVec3( m_pFallPath->pos[ i ] ); - } - } +inline bool Actor::CanSeeFOV(Entity *ent) +{ + bool bCanSee; - arc.ArchiveFloat( &m_fBalconyHeight ); - arc.ArchiveBool( &m_bNoPlayerCollision ); + if (ent == m_Enemy) { + return CanSeeEnemyFOV(0, 0); + } - for( int i = MAX_ORIGIN_HISTORY - 1; i >= 0; i-- ) - { - arc.ArchiveVec2( m_vOriginHistory[ i ] ); - } + bCanSee = false; - arc.ArchiveInteger( &m_iCurrentHistory ); + if (InFOV(ent) && AreasConnected(ent)) { + bCanSee = CanSee(ent, 0, 0, false); + } - // set the model - setModel(); + return bCanSee; +} + +inline bool Actor::CanSeeEnemyFOV(int iMaxFovDirtyTime, int iMaxSightDirtyTime) +{ + return EnemyInFOV(iMaxFovDirtyTime) && CanSeeEnemy(iMaxSightDirtyTime); +} + +/* +=============== +Actor::AimAtTargetPos + +Aim at mTargetPos. +=============== +*/ +inline void Actor::AimAtTargetPos(void) +{ + Vector v, v2; + + v = mTargetPos - EyePosition(); + v2 = v; + v2[2] += 16; + + SetDesiredLookDir(v2); + + m_DesiredGunDir[0] = 360.0f - v.toPitch(); + m_DesiredGunDir[1] = v.toYaw(); + m_DesiredGunDir[2] = 0; + + SetDesiredYaw(m_DesiredGunDir[1]); +} + +/* +=============== +Actor::AimAtAimNode + +Aim at m_aimNode. +=============== +*/ +inline void Actor::AimAtAimNode(void) +{ + mTargetPos = m_aimNode->centroid; + + AimAtTargetPos(); +} + +/* +=============== +Actor::IgnoreSoundSet + +Make actor ignore iType sound. +=============== +*/ +inline void Actor::IgnoreSoundSet(int iType) +{ + m_iIgnoreSoundsMask |= 1 << iType; +} + +/* +=============== +Actor::IgnoreSoundSetAll + +Make actor ignore all types of sound. +=============== +*/ +inline void Actor::IgnoreSoundSetAll(void) +{ + m_iIgnoreSoundsMask = 0xffff; +} + +/* +=============== +Actor::IgnoreSoundClear + +Don't ignore iType of sound. +=============== +*/ +inline void Actor::IgnoreSoundClear(int iType) +{ + m_iIgnoreSoundsMask &= ~(1 << iType); +} + +/* +=============== +Actor::IgnoreSoundClearAll + +Make actor ignore no type of sound. +=============== +*/ +inline void Actor::IgnoreSoundClearAll(void) +{ + m_iIgnoreSoundsMask = 0; +} + +/* +=============== +Actor::IgnoreSoundClearAll + +returns true if actor should ignore iType of sound. +=============== +*/ +inline bool Actor::IgnoreSound(int iType) +{ + return (m_iIgnoreSoundsMask >> iType) & 1; +} + +/* +=============== +Actor::CurrentThink + +Current think. +=============== +*/ +inline int Actor::CurrentThink(void) const +{ + return m_Think[m_ThinkLevel]; +} + +/* +=============== +Actor::IsAttacking + +Returns true if actor is in attack state. +=============== +*/ +inline bool Actor::IsAttacking(void) const +{ + return m_ThinkStates[THINKLEVEL_IDLE] == THINKSTATE_ATTACK; +} + +inline void Actor::ArchiveStatic(Archiver& arc) +{ + for (int i = 0; i < MAX_BODYQUEUE; i++) { + arc.ArchiveSafePointer(&mBodyQueue[i]); + } + + arc.ArchiveInteger(&mCurBody); +} + +inline void Actor::Archive(Archiver& arc) +{ + int i; + + SimpleActor::Archive(arc); + + for (i = 0; i < NUM_THINKSTATES; i++) { + ArchiveEnum(m_ThinkMap[i], eThinkNum); + } + + for (i = 0; i < NUM_THINKLEVELS; i++) { + ArchiveEnum(m_ThinkStates[i], eThinkState); + ArchiveEnum(m_Think[i], eThinkNum); + } + + ArchiveEnum(m_ThinkLevel, eThinkLevel); + ArchiveEnum(m_ThinkState, eThinkState); + arc.ArchiveInteger(&m_State); + arc.ArchiveInteger(&m_iStateTime); + arc.ArchiveBool(&m_bLockThinkState); + arc.ArchiveBool(&m_bDirtyThinkState); + + arc.ArchiveBool(&m_bAnimating); + + arc.ArchiveBool(&m_bIgnoreBadPlace); + arc.ArchiveInteger(&m_iBadPlaceIndex); + + arc.ArchiveInteger(&mVoiceType); + arc.ArchiveBool(&m_bSilent); + + arc.ArchiveBool(&m_bNoSurprise); + arc.ArchiveBool(&m_bMumble); + arc.ArchiveBool(&m_bBreathSteam); + arc.ArchiveBool(&m_bIsCurious); + + Director.ArchiveString(arc, m_csHeadModel); + Director.ArchiveString(arc, m_csHeadSkin); + Director.ArchiveString(arc, m_csWeapon); + Director.ArchiveString(arc, m_csLoadOut); + + arc.ArchiveSafePointer(&m_FavoriteEnemy); + arc.ArchiveInteger(&m_iEnemyCheckTime); + arc.ArchiveInteger(&m_iEnemyChangeTime); + arc.ArchiveInteger(&m_iEnemyVisibleCheckTime); + arc.ArchiveInteger(&m_iEnemyVisibleChangeTime); + arc.ArchiveInteger(&m_iLastEnemyVisibleTime); + arc.ArchiveFloat(&m_fVisibilityAlpha); + arc.ArchiveFloat(&m_fVisibilityThreshold); + arc.ArchiveInteger(&m_iEnemyFovCheckTime); + arc.ArchiveInteger(&m_iEnemyFovChangeTime); + arc.ArchiveVector(&m_vLastEnemyPos); + arc.ArchiveInteger(&m_iLastEnemyPosChangeTime); + arc.ArchiveFloat(&m_fMaxShareDistSquared); + arc.ArchiveInteger(&m_iCanShootCheckTime); + arc.ArchiveBool(&m_bCanShootEnemy); + arc.ArchiveBool(&m_bHasVisibilityThreshold); + arc.ArchiveBool(&m_bDesiredEnableEnemy); + arc.ArchiveBool(&m_bEnableEnemy); + arc.ArchiveBool(&m_bEnablePain); + arc.ArchiveBool(&m_bNoLongPain); + arc.ArchiveBool(&m_bNewEnemy); + arc.ArchiveBool(&m_bEnemyIsDisguised); + arc.ArchiveBool(&m_bEnemyVisible); + arc.ArchiveBool(&m_bEnemyInFOV); + arc.ArchiveBool(&m_bForceAttackPlayer); + arc.ArchiveBool(&m_bAutoAvoidPlayer); + + arc.ArchiveBool(&m_bNoIdleAfterAnim); + Director.ArchiveString(arc, m_csAnimScript); + arc.ArchiveBool(&m_bAnimScriptSet); + arc.ArchiveInteger(&m_AnimMode); + arc.ArchiveFloat(&m_fRunAnimRate); + arc.ArchiveFloat(&m_fDfwRequestedYaw); + arc.ArchiveFloat(&m_fDfwDerivedYaw); + arc.ArchiveVector(&m_vDfwPos); + arc.ArchiveFloat(&m_fDfwTime); + arc.ArchiveInteger(&m_iGunPositionCheckTime); + arc.ArchiveVector(&m_vGunPosition); + + arc.ArchiveInteger(&m_iWallDodgeTimeout); + arc.ArchiveFloat(&m_PrevObstacleNormal[0]); + arc.ArchiveFloat(&m_PrevObstacleNormal[1]); + arc.ArchiveChar(&m_WallDir); + arc.ArchiveFloat(&m_fMoveDoneRadiusSquared); + + arc.ArchiveBool(&m_bFaceEnemy); + arc.ArchiveBool(&m_bDoPhysics); + arc.ArchiveBool(&m_bPatrolWaitTrigger); + arc.ArchiveBool(&m_bBecomeRunner); + arc.ArchiveBool(&m_bScriptGoalValid); + arc.ArchiveVector(&m_vScriptGoal); + arc.ArchiveInteger(&m_iNextWatchStepTime); + + arc.ArchiveSafePointer(&m_patrolCurrentNode); + Director.ArchiveString(arc, m_csPatrolCurrentAnim); + arc.ArchiveInteger(&m_iSquadStandTime); + arc.ArchiveFloat(&m_fInterval); + arc.ArchiveInteger(&m_iIntervalDirTime); + arc.ArchiveVector(&m_vIntervalDir); + arc.ArchiveShort(&m_sCurrentPathNodeIndex); + arc.ArchiveInteger(&m_PainState); + + arc.ArchiveInteger(&m_iCuriousTime); + arc.ArchiveInteger(&m_iCuriousLevel); + arc.ArchiveInteger(&m_iCuriousAnimHint); + arc.ArchiveInteger(&m_iNextDisguiseTime); + arc.ArchiveInteger(&m_iDisguisePeriod); + arc.ArchiveFloat(&m_fMaxDisguiseDistSquared); + arc.ArchiveInteger(&m_iEnemyShowPapersTime); + + m_DisguiseAcceptThread.Archive(arc); + arc.ArchiveInteger(&m_iDisguiseLevel); + arc.ArchiveSafePointer(&m_AlarmNode); + m_AlarmThread.Archive(arc); + m_PreAlarmThread.Archive(arc); + + arc.ArchiveInteger(&m_iSuppressChance); + arc.ArchiveInteger(&m_iRunHomeTime); + arc.ArchiveBool(&m_bTurretNoInitialCover); + arc.ArchiveInteger(&m_iPotentialCoverCount); + + for (i = 0; i < MAX_COVER_NODES; i++) { + arc.ArchiveObjectPointer((Class **)&m_pPotentialCoverNode[i]); + } + + arc.ArchiveObjectPointer((Class **)&m_pCoverNode); + + Director.ArchiveString(arc, m_csSpecialAttack); + arc.ArchiveBool(&m_bInReload); + arc.ArchiveBool(&m_bNeedReload); + arc.ArchiveBool(&mbBreakSpecialAttack); + + arc.ArchiveBool(&m_bGrenadeBounced); + arc.ArchiveSafePointer(&m_pGrenade); + arc.ArchiveVector(&m_vGrenadePos); + arc.ArchiveInteger(&m_iFirstGrenadeTime); + ArchiveEnum(m_eGrenadeState, eGrenadeState); + ArchiveEnum(m_eGrenadeMode, eGrenadeTossMode); + arc.ArchiveVector(&m_vGrenadeVel); + arc.ArchiveVector(&m_vKickDir); + + arc.ArchiveFloat(&m_fNoticeTimeScale); + arc.ArchiveFloat(&m_fMaxNoticeTimeScale); + m_PotentialEnemies.Archive(arc); + + arc.ArchiveFloat(&m_fSight); + arc.ArchiveFloat(&m_fHearing); + arc.ArchiveFloat(&m_fSoundAwareness); + arc.ArchiveFloat(&m_fGrenadeAwareness); + arc.ArchiveInteger(&m_iIgnoreSoundsMask); + + arc.ArchiveFloat(&m_fFov); + arc.ArchiveFloat(&m_fFovDot); + arc.ArchiveInteger(&m_iEyeUpdateTime); + arc.ArchiveVector(&m_vEyeDir); + arc.ArchiveInteger(&m_iNextLookTime); + arc.ArchiveFloat(&m_fLookAroundFov); + arc.ArchiveSafePointer(&m_pLookEntity); + arc.ArchiveInteger(&m_iLookFlags); + arc.ArchiveSafePointer(&m_pPointEntity); + arc.ArchiveSafePointer(&m_pTurnEntity); + arc.ArchiveFloat(&m_fTurnDoneError); + arc.ArchiveFloat(&m_fAngleYawSpeed); + arc.ArchiveSafePointer(&m_aimNode); + arc.ArchiveInteger(&m_eDontFaceWallMode); + arc.ArchiveInteger(&m_iLastFaceDecideTime); + + arc.ArchiveBool(&m_bHeadAnglesAchieved); + arc.ArchiveBool(&m_bLUpperArmAnglesAchieved); + arc.ArchiveBool(&m_bTorsoAnglesAchieved); + arc.ArchiveFloat(&m_fHeadMaxTurnSpeed); + arc.ArchiveVec3(m_vHeadDesiredAngles); + arc.ArchiveFloat(&m_fLUpperArmTurnSpeed); + arc.ArchiveVec3(m_vLUpperArmDesiredAngles); + arc.ArchiveFloat(&m_fTorsoMaxTurnSpeed); + arc.ArchiveFloat(&m_fTorsoCurrentTurnSpeed); + arc.ArchiveVec3(m_vTorsoDesiredAngles); + + arc.ArchiveVector(&m_vHome); + arc.ArchiveSafePointer(&m_pTetherEnt); + + arc.ArchiveFloat(&m_fMinDistance); + arc.ArchiveFloat(&m_fMinDistanceSquared); + arc.ArchiveFloat(&m_fMaxDistance); + arc.ArchiveFloat(&m_fMaxDistanceSquared); + + arc.ArchiveFloat(&m_fLeash); + arc.ArchiveFloat(&m_fLeashSquared); + arc.ArchiveBool(&m_bFixedLeash); + + byte length; + + if (arc.Saving()) { + if (m_pFallPath) { + length = m_pFallPath->length; + } else { + length = 0; + } + } + arc.ArchiveByte(&length); + + if (arc.Loading() && length) { + m_pFallPath = + (FallPath *)gi.Malloc((sizeof(FallPath::pos)) * length + (sizeof(FallPath) - sizeof(FallPath::pos))); + m_pFallPath->length = length; + } + + if (length) { + arc.ArchiveByte(&m_pFallPath->currentPos); + arc.ArchiveByte(&m_pFallPath->loop); + + for (i = 0; i < length; i++) { + arc.ArchiveVec3(m_pFallPath->pos[i]); + } + } + + arc.ArchiveFloat(&m_fBalconyHeight); + arc.ArchiveBool(&m_bNoPlayerCollision); + + for (i = 0; i < MAX_ORIGIN_HISTORY; i++) { + arc.ArchiveVec2(m_vOriginHistory[i]); + } + + arc.ArchiveInteger(&m_iCurrentHistory); + + arc.ArchiveBool(&m_bEnemySwitch); + arc.ArchiveInteger(&m_iNationality); + + // set the model + setModel(); +} + +/* +=============== +Actor::SetDesiredLookDir + +Change desired look direction. +=============== +*/ +inline void Actor::SetDesiredLookDir(vec3_t dir) +{ + m_bHasDesiredLookAngles = true; + vectoangles(dir, m_DesiredLookAngles); + + m_DesiredLookAngles[1] = m_DesiredLookAngles[1] - angles[1]; + m_DesiredLookAngles[1] = AngleNormalize180(m_DesiredLookAngles[1]); + m_DesiredLookAngles[0] = AngleNormalize180(m_DesiredLookAngles[0]); +} + +/* +=============== +Actor::SetDesiredLookAnglesRelative + +Change desired look angles relatively. +=============== +*/ +inline void Actor::SetDesiredLookAnglesRelative(vec3_t ang) +{ + m_bHasDesiredLookAngles = true; + m_DesiredLookAngles[0] = AngleNormalize180(ang[0]); + m_DesiredLookAngles[1] = AngleNormalize180(ang[1]); + m_DesiredLookAngles[2] = AngleNormalize180(ang[2]); +} + +/* +=============== +Actor::ForwardLook +=============== +*/ +inline void Actor::ForwardLook(void) +{ + m_bHasDesiredLookAngles = false; +} + +inline bool Actor::EnemyIsDisguised(void) +{ + if (!m_bEnemyIsDisguised && !m_Enemy->m_bIsDisguised) { + return false; + } + + if (m_bForceAttackPlayer) { + return false; + } + + if (m_ThinkState == THINKSTATE_ATTACK) { + return false; + } + + return true; +} + +inline bool Actor::AvoidingFacingWall(void) const +{ + return m_eDontFaceWallMode > 5 && m_eDontFaceWallMode <= 8; } #if 0 @@ -1761,4 +2336,3 @@ class SpinningPlant : public Actor void GetClip( Event *ev ); }; */ -#endif \ No newline at end of file diff --git a/code/fgame/actor_aim.cpp b/code/fgame/actor_aim.cpp index bffea18b..df0c95ca 100644 --- a/code/fgame/actor_aim.cpp +++ b/code/fgame/actor_aim.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,52 +24,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitAim - ( - GlobalFuncs_t *func - ) +void Actor::InitAim(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Aim; - func->ThinkState = &Actor::Think_Aim; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->ShowInfo = &Actor::ShowInfo_Aim; - func->IsState = &Actor::IsIdleState; -} -void Actor::Begin_Aim - ( - void - ) -{ - m_csMood = STRING_ALERT; - m_csIdleMood = STRING_NERVOUS; - ClearPath(); -} -void Actor::Think_Aim - ( - void - ) -{ - if( !RequireThink() ) - return; - - UpdateEyeOrigin(); - NoPoint(); - m_pszDebugState = ""; - Anim_Aim(); - - if( m_aimNode ) - { - AimAtAimNode(); - } - - CheckForThinkStateTransition(); - PostThink( true ); + func->BeginState = &Actor::Begin_Aim; + func->ThinkState = &Actor::Think_Aim; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->ShowInfo = &Actor::ShowInfo_Aim; + func->IsState = &Actor::IsIdleState; } -void Actor::ShowInfo_Aim - ( - void - ) +void Actor::Begin_Aim(void) { - ShowInfo_AimNode(); + m_csMood = STRING_ALERT; + m_csIdleMood = STRING_NERVOUS; + ClearPath(); +} + +void Actor::Think_Aim(void) +{ + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + NoPoint(); + m_pszDebugState = ""; + Anim_Aim(); + + if (m_aimNode) { + AimAtAimNode(); + } + + CheckForThinkStateTransition(); + PostThink(true); +} + +void Actor::ShowInfo_Aim(void) +{ + ShowInfo_AimNode(); } diff --git a/code/fgame/actor_alarm.cpp b/code/fgame/actor_alarm.cpp index b404fb96..57514a9e 100644 --- a/code/fgame/actor_alarm.cpp +++ b/code/fgame/actor_alarm.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,143 +24,108 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitAlarm - ( - GlobalFuncs_t *func - ) +void Actor::InitAlarm(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Alarm; - func->EndState = &Actor::End_Alarm; - func->ThinkState = &Actor::Think_Alarm; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; - func->IsState = &Actor::IsAttackState; + func->BeginState = &Actor::Begin_Alarm; + func->EndState = &Actor::End_Alarm; + func->ThinkState = &Actor::Think_Alarm; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->IsState = &Actor::IsAttackState; } -void Actor::Begin_Alarm - ( - void - ) +void Actor::Begin_Alarm(void) { - DoForceActivate(); + DoForceActivate(); - m_csMood = STRING_ALERT; - m_csIdleMood = STRING_NERVOUS; + m_csMood = STRING_ALERT; + m_csIdleMood = STRING_NERVOUS; - if( m_AlarmNode ) - { - SetPath( m_AlarmNode, "Actor::Begin_Alarm", 0 ); + if (!m_AlarmNode) { + State_Alarm_StartThread(); + return; + } - if( PathExists() ) - { - TransitionState(601, 0); - } - else - { - TransitionState(600, 0); - parm.movefail = true; - } - } - else - { - SetLeashHome( origin ); - TransitionState(600, 0); - m_AlarmThread.Execute( this ); - } + SetPath(m_AlarmNode, "Actor::Begin_Alarm", 0); + + if (PathExists()) { + TransitionState(ACTOR_STATE_ALARM_MOVE, 0); + } else { + TransitionState(ACTOR_STATE_ALARM_IDLE, 0); + parm.movefail = true; + } } -void Actor::End_Alarm - ( - void - ) +void Actor::End_Alarm(void) { - parm.movefail = true; + parm.movefail = true; } -void Actor::State_Alarm_StartThread - ( - void - ) +void Actor::State_Alarm_StartThread(void) { - if( m_AlarmNode ) - SetLeashHome( m_AlarmNode->origin ); - else - SetLeashHome( origin ); + SetLeashHome(m_AlarmNode ? m_AlarmNode->origin : origin); + // Added in 2.30. + // Execute the pre-alarm thread + m_PreAlarmThread.Execute(this); - TransitionState(600, 0); - m_AlarmThread.Execute(); + TransitionState(ACTOR_STATE_ALARM_IDLE, 0); + m_AlarmThread.Execute(this); } -void Actor::State_Alarm_Move - ( - void - ) +void Actor::State_Alarm_Move(void) { - if( PathExists() ) - { - if( PathComplete() ) - { - Anim_Aim(); - AimAtTargetPos(); - } - else - { - Anim_RunToAlarm( 2 ); - FaceMotion(); - } - } - else - { - TransitionState(600, 0); - parm.movefail = true; + if (!PathExists()) { + TransitionState(ACTOR_STATE_ALARM_IDLE, 0); + parm.movefail = true; - Anim_Aim(); - AimAtTargetPos(); - } + Anim_Aim(); + AimAtTargetPos(); + } else if (PathComplete()) { + Anim_Aim(); + AimAtTargetPos(); + State_Alarm_StartThread(); + } else { + Anim_RunToAlarm(ANIM_MODE_PATH); + FaceMotion(); + } } -void Actor::State_Alarm_Idle - ( - void - ) +void Actor::State_Alarm_Idle(void) { - AimAtTargetPos(); - SetThink(THINKSTATE_ATTACK, THINK_TURRET); + Anim_Aim(); + AimAtTargetPos(); + SetThink(THINKSTATE_ATTACK, THINK_TURRET); } -void Actor::Think_Alarm - ( - void - ) +void Actor::Think_Alarm(void) { - if( !RequireThink() ) - return; + if (!RequireThink()) { + return; + } - parm.movefail = false; + parm.movefail = false; - UpdateEyeOrigin(); - NoPoint(); + UpdateEyeOrigin(); + NoPoint(); - if( m_State == 600 ) - { - m_pszDebugState = "idle"; - State_Alarm_Idle(); - } - else if( m_State == 601 ) - { - m_pszDebugState = "move"; - State_Alarm_Move(); - } - else - { - Com_Printf( "Actor::Think_Alarm: invalid think state %i\n", m_State ); - } + switch (m_State) { + case ACTOR_STATE_ALARM_IDLE: + m_pszDebugState = "idle"; + State_Alarm_Idle(); + break; + case ACTOR_STATE_ALARM_MOVE: + m_pszDebugState = "move"; + State_Alarm_Move(); + break; + default: + Com_Printf("Actor::Think_Alarm: invalid think state %i\n", m_State); + break; + } + + PostThink(true); } -void Actor::FinishedAnimation_Alarm - ( - void - ) +void Actor::FinishedAnimation_Alarm(void) { - // not needed - return; + // not needed + return; } diff --git a/code/fgame/actor_anim.cpp b/code/fgame/actor_anim.cpp index 3066c737..6a8db069 100644 --- a/code/fgame/actor_anim.cpp +++ b/code/fgame/actor_anim.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,81 +24,66 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitAnim - ( - GlobalFuncs_t *func - ) +void Actor::InitAnim(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Anim; - func->BeginState = &Actor::Begin_Anim; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->FinishedAnimation = &Actor::FinishedAnimation_Anim; - func->ShowInfo = &Actor::ShowInfo_Anim; - func->IsState = &Actor::IsIdleState; + func->ThinkState = &Actor::Think_Anim; + func->BeginState = &Actor::Begin_Anim; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->FinishedAnimation = &Actor::FinishedAnimation_Anim; + func->ShowInfo = &Actor::ShowInfo_Anim; + func->IsState = &Actor::IsIdleState; } -void Actor::Begin_Anim - ( - void - ) +void Actor::Begin_Anim(void) { - m_csMood = m_csIdleMood; - ClearPath(); - StopTurning(); - TransitionState(1000, 0); + m_csMood = m_csIdleMood; + ClearPath(); + StopTurning(); + TransitionState(ACTOR_STATE_ANIMATION_INITIAL, 0); } -void Actor::Think_Anim - ( - void - ) +void Actor::Think_Anim(void) { - if (RequireThink()) - { - UpdateEyeOrigin(); - IdlePoint(); - IdleLook(); - if (m_State == 1000) - { - m_bNextForceStart = true; + if (!RequireThink()) { + return; + } - m_bAnimScriptSet = false; - m_pszDebugState = "initial"; - TransitionState(1001, 0); - } - else if (m_State == 1001) - { - m_bNextForceStart = false; - m_pszDebugState = "main"; - } - m_eNextAnimMode = m_AnimMode; - m_csNextAnimString = m_csAnimScript; + UpdateEyeOrigin(); + IdlePoint(); + IdleLook(); - CheckForThinkStateTransition(); - IdleTurn(); - PostThink(false); - } + if (m_State == ACTOR_STATE_ANIMATION_INITIAL) { + m_pszDebugState = "initial"; + m_bAnimScriptSet = false; + StartAnimation(m_AnimMode, m_csAnimScript); + TransitionState(ACTOR_STATE_ANIMATION_MAIN, 0); + } else if (m_State == ACTOR_STATE_ANIMATION_MAIN) { + m_bNextForceStart = false; + m_pszDebugState = "main"; + DesiredAnimation(m_AnimMode, m_csAnimScript); + } + + CheckForThinkStateTransition(); + IdleTurn(); + PostThink(false); } -void Actor::FinishedAnimation_Anim - ( - void - ) +void Actor::FinishedAnimation_Anim(void) { - if (!m_bAnimScriptSet) - { - if (m_bNoIdleAfterAnim) - m_csAnimScript = STRING_ANIM_CONTINUE_LAST_ANIM_SCR; - else - SetThinkIdle(THINK_IDLE); - Unregister(STRING_ANIMDONE); - } + if (m_bAnimScriptSet) { + return; + } + + if (m_bNoIdleAfterAnim) { + m_csAnimScript = STRING_ANIM_CONTINUE_LAST_ANIM_SCR; + } else { + SetThinkIdle(THINK_IDLE); + } + + Unregister(STRING_ANIMDONE); } -void Actor::ShowInfo_Anim - ( - void - ) +void Actor::ShowInfo_Anim(void) { - Com_Printf("anim script: %s, anim mode %d\n", Director.GetString(m_csAnimScript).c_str(), m_AnimMode); + Com_Printf("anim script: %s, anim mode %d\n", Director.GetString(m_csAnimScript).c_str(), m_AnimMode); } diff --git a/code/fgame/actor_animapi.cpp b/code/fgame/actor_animapi.cpp index 6e87eaa6..11c5a5b8 100644 --- a/code/fgame/actor_animapi.cpp +++ b/code/fgame/actor_animapi.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,289 +23,201 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // actor_animapi.cpp: Base actor animation script #include "actor.h" +#include "scriptthread.h" -const_str SimpleActor::GetRunAnim - ( - void - ) +const_str SimpleActor::GetRunAnim(void) { - if( m_csCurrentPosition != STRING_PRONE && ( m_csCurrentPosition < STRING_PRONE || m_csCurrentPosition > STRING_CROUCHRUN ) ) - return STRING_ANIM_RUN_SCR; - else - return STRING_ANIM_CROUCH_RUN_SCR; + if (m_csCurrentPosition == STRING_PRONE) { + return STRING_ANIM_CROUCH_RUN_SCR; + } + + if (m_csCurrentPosition >= STRING_PRONE && m_csCurrentPosition <= STRING_CROUCHRUN && m_csCurrentPosition >= STRING_CROUCH) { + return STRING_ANIM_CROUCH_RUN_SCR; + } else { + return STRING_ANIM_RUN_SCR; + } } -const_str SimpleActor::GetWalkAnim - ( - void - ) +const_str SimpleActor::GetWalkAnim(void) { - if( m_csCurrentPosition != STRING_PRONE && ( m_csCurrentPosition < STRING_PRONE || m_csCurrentPosition > STRING_CROUCHRUN ) ) - return STRING_ANIM_WALK_SCR; - else - return STRING_ANIM_CROUCH_WALK_SCR; + if (m_csCurrentPosition == STRING_PRONE) { + return STRING_ANIM_CROUCH_WALK_SCR; + } + + if (m_csCurrentPosition >= STRING_PRONE && m_csCurrentPosition <= STRING_CROUCHRUN && m_csCurrentPosition >= STRING_CROUCH) { + return STRING_ANIM_CROUCH_WALK_SCR; + } else { + return STRING_ANIM_WALK_SCR; + } } -void SimpleActor::Anim_Attack - ( - void - ) +void SimpleActor::Anim_Attack(void) { - DesiredAnimation(1, m_AttackHandler); + DesiredAnimation(ANIM_MODE_NORMAL, m_AttackHandler); } -void SimpleActor::Anim_Sniper - ( - void - ) +void SimpleActor::Anim_Suppress(void) { - DesiredAnimation(1, m_SniperHandler); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SUPPRESS_SCR); } -void SimpleActor::Anim_Aim - ( - void - ) +void SimpleActor::Anim_Sniper(void) { - DesiredAnimation(1, STRING_ANIM_AIM_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, m_SniperHandler); } -void SimpleActor::Anim_Shoot - ( - void - ) +void SimpleActor::Anim_Aim(void) { - DesiredAnimation(1, STRING_ANIM_SHOOT_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_AIM_SCR); } -void SimpleActor::Anim_Idle - ( - void - ) +void SimpleActor::Anim_Shoot(void) { - DesiredAnimation(1, STRING_ANIM_IDLE_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SHOOT_SCR); } -void SimpleActor::Anim_Crouch - ( - void - ) +void SimpleActor::Anim_Idle(void) { - DesiredAnimation(1, STRING_ANIM_CROUCH_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_IDLE_SCR); } -void SimpleActor::Anim_Prone - ( - void - ) +void SimpleActor::Anim_Crouch(void) { - DesiredAnimation(1, STRING_ANIM_PRONE_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_CROUCH_SCR); } -void SimpleActor::Anim_Stand - ( - void - ) +void SimpleActor::Anim_Prone(void) { - DesiredAnimation(1, STRING_ANIM_STAND_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_PRONE_SCR); } -void SimpleActor::Anim_Cower - ( - void - ) +void SimpleActor::Anim_Stand(void) { - DesiredAnimation(1, STRING_ANIM_COWER_SCR); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STAND_SCR); } -void SimpleActor::Anim_Killed - ( - void - ) +void SimpleActor::Anim_Cower(void) { - Com_Printf("m_eAnimMode Anim_Killed \n"); - DesiredAnimation(1, m_DeathHandler); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_COWER_SCR); } -void SimpleActor::Anim_StartPain - ( - void - ) +void SimpleActor::Anim_Killed(void) { - Com_Printf("m_eAnimMode Anim_StartPain \n"); - StartAnimation(1, m_PainHandler); - + DesiredAnimation(ANIM_MODE_NORMAL, m_DeathHandler); } -void SimpleActor::Anim_Pain - ( - void - ) +void SimpleActor::Anim_StartPain(void) { - ContinueAnimation(); + StartAnimation(ANIM_MODE_NORMAL, m_PainHandler); } - -void SimpleActor::Anim_CrouchRunTo - ( - int eAnimMode - ) +void SimpleActor::Anim_Pain(void) { - DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_RUN_SCR); + ContinueAnimation(); } -void SimpleActor::Anim_CrouchWalkTo - ( - int eAnimMode - ) +void SimpleActor::Anim_CrouchRunTo(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_WALK_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_RUN_SCR); } -void SimpleActor::Anim_StandRunTo - ( - int eAnimMode - ) +void SimpleActor::Anim_CrouchWalkTo(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_WALK_SCR); } -void SimpleActor::Anim_StandWalkTo - ( - int eAnimMode - ) +void SimpleActor::Anim_StandRunTo(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_WALK_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SCR); } -void SimpleActor::Anim_RunTo - ( - int eAnimMode - ) +void SimpleActor::Anim_StandWalkTo(int eAnimMode) { - DesiredAnimation(eAnimMode, GetRunAnim()); + DesiredAnimation(eAnimMode, STRING_ANIM_WALK_SCR); } -void SimpleActor::Anim_WalkTo - ( - int eAnimMode - ) +void SimpleActor::Anim_RunTo(int eAnimMode) { - DesiredAnimation(eAnimMode, GetWalkAnim()); + DesiredAnimation(eAnimMode, GetRunAnim()); } -void SimpleActor::Anim_RunAwayFiring - ( - int eAnimMode - ) +void SimpleActor::Anim_RunAwayFiring(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNAWAYFIRING_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNAWAYFIRING_SCR); } -void SimpleActor::Anim_RunToShooting - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToShooting(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SHOOT_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SHOOT_SCR); } -void SimpleActor::Anim_RunToAlarm - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToAlarm(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_ALARM_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_ALARM_SCR); } -void SimpleActor::Anim_RunToCasual - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToCasual(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_CASUAL_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_CASUAL_SCR); } -void SimpleActor::Anim_RunToCover - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToCover(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_COVER_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_COVER_SCR); } -void SimpleActor::Anim_RunToDanger - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToDanger(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DANGER_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DANGER_SCR); } -void SimpleActor::Anim_RunToDive - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToDive(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DIVE_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DIVE_SCR); } -void SimpleActor::Anim_RunToFlee - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToFlee(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_FLEE_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_FLEE_SCR); } -void SimpleActor::Anim_RunToInOpen - ( - int eAnimMode - ) +void SimpleActor::Anim_RunToInOpen(int eAnimMode) { - DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_INOPEN_SCR); + DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_INOPEN_SCR); } -void SimpleActor::Anim_Emotion - ( - eEmotionMode eEmotMode - ) +void SimpleActor::Anim_WalkTo(int eAnimMode) { - m_eEmotionMode = eEmotMode; + DesiredAnimation(eAnimMode, GetWalkAnim()); } -void SimpleActor::Anim_Say - ( - const_str csSayAnimScript, - int iMinTimeSinceLastSay, - bool bCanInterrupt - ) +void SimpleActor::Anim_Emotion(eEmotionMode eEmotMode) { - if (!m_bSayAnimSet || bCanInterrupt) - { - if (level.inttime > m_iVoiceTime + iMinTimeSinceLastSay) - { - ScriptThreadLabel label; - - label.TrySetScript(csSayAnimScript); - label.Execute(this); - } - } + m_eEmotionMode = eEmotMode; } -void SimpleActor::Anim_FullBody - ( - const_str csFullBodyAnim, - int eAnimMode - ) +void SimpleActor::Anim_Say(const_str csSayAnimScript, int iMinTimeSinceLastSay, bool bCanInterrupt) { - if( m_csAnimName == csFullBodyAnim ) - { - DesiredAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR); - } - else - { - m_csAnimName = csFullBodyAnim; - StartAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR); - } + if (m_bSayAnimSet && !bCanInterrupt) { + return; + } + + if (level.inttime <= iMinTimeSinceLastSay + m_iVoiceTime) { + return; + } + + ScriptThreadLabel label; + + label.TrySetScript(csSayAnimScript); + label.Create(this)->Execute(); +} + +void SimpleActor::Anim_FullBody(const_str csFullBodyAnim, int eAnimMode) +{ + if (m_csAnimName == csFullBodyAnim) { + DesiredAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR); + } else { + m_csAnimName = csFullBodyAnim; + StartAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR); + } } diff --git a/code/fgame/actor_animcurious.cpp b/code/fgame/actor_animcurious.cpp index f2426f39..ffdd9353 100644 --- a/code/fgame/actor_animcurious.cpp +++ b/code/fgame/actor_animcurious.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,56 +24,47 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitAnimCurious - ( - GlobalFuncs_t *func - ) +void Actor::InitAnimCurious(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_AnimCurious; - func->BeginState = &Actor::Begin_AnimCurious; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; - func->FinishedAnimation = &Actor::FinishedAnimation_Anim; - func->ShowInfo = &Actor::ShowInfo_Anim; - func->IsState = &Actor::IsCuriousState; + func->ThinkState = &Actor::Think_AnimCurious; + func->BeginState = &Actor::Begin_AnimCurious; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; + func->FinishedAnimation = &Actor::FinishedAnimation_Anim; + func->ShowInfo = &Actor::ShowInfo_Anim; + func->IsState = &Actor::IsCuriousState; } -void Actor::Begin_AnimCurious - ( - void - ) +void Actor::Begin_AnimCurious(void) { - DoForceActivate(); + DoForceActivate(); - m_csMood = STRING_CURIOUS; - StartAnimation(m_AnimMode, m_csAnimScript); - StopTurning(); - m_iCuriousTime = level.inttime; + m_csMood = STRING_CURIOUS; + m_iCuriousTime = level.inttime; + StopTurning(); + StartAnimation(m_AnimMode, m_csAnimScript); } -void Actor::Think_AnimCurious - ( - void - ) +void Actor::Think_AnimCurious(void) { - if( !RequireThink() ) - return; + if (!RequireThink()) { + return; + } - UpdateEyeOrigin(); - m_pszDebugState = ""; - LookAtCuriosity(); - TimeOutCurious(); - DesiredAnimation(m_AnimMode, m_csAnimScript); - CheckForThinkStateTransition(); - PostThink( false ); + UpdateEyeOrigin(); + + m_pszDebugState = ""; + LookAtCuriosity(); + TimeOutCurious(); + + DesiredAnimation(m_AnimMode, m_csAnimScript); + CheckForThinkStateTransition(); + + PostThink(false); } -void Actor::FinishedAnimation_AnimCurious - ( - void - ) +void Actor::FinishedAnimation_AnimCurious(void) { - if( m_State == 1101 ) - { - TransitionState(1100, 0); - } + if (m_State == ACTOR_STATE_CURIOUS_RUNNING) { + TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0); + } } diff --git a/code/fgame/actor_badplace.cpp b/code/fgame/actor_badplace.cpp new file mode 100644 index 00000000..096834ce --- /dev/null +++ b/code/fgame/actor_badplace.cpp @@ -0,0 +1,84 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// actor_badplace.cpp + +#include "actor.h" + +void Actor::InitBadPlace(GlobalFuncs_t *func) +{ + func->ThinkState = &Actor::Think_BadPlace; + func->BeginState = &Actor::Begin_BadPlace; + func->EndState = &Actor::End_BadPlace; + func->ResumeState = &Actor::Begin_BadPlace; + func->SuspendState = &Actor::End_BadPlace; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_BadPlace; + func->IsState = &Actor::IsBadPlaceState; +} + +void Actor::Begin_BadPlace(void) +{ + DoForceActivate(); + + m_csMood = STRING_ALERT; + m_csIdleMood = STRING_NERVOUS; + + badplace_t& badplace = level.m_badPlaces.ObjectAt(m_iBadPlaceIndex); + + FindPathAway(badplace.m_vOrigin, origin - badplace.m_vOrigin, badplace.m_fRadius + 64); +} + +void Actor::End_BadPlace(void) +{ + m_iBadPlaceIndex = 0; +} + +void Actor::Think_BadPlace(void) +{ + if (m_bEnableEnemy) { + UpdateEnemy(200); + } + + m_pszDebugState = ""; + NoPoint(); + + if (!PathExists() || PathComplete() || !m_iBadPlaceIndex) { + m_iBadPlaceIndex = 0; + if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } else { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } + } + + if (m_Enemy) { + m_pszDebugState = "badplace_shoot"; + FaceEnemyOrMotion(m_iStateTime); + Anim_RunAwayFiring(ANIM_MODE_PATH); + } else { + m_pszDebugState = "badplace_run"; + FaceMotion(); + Anim_RunToInOpen(ANIM_MODE_PATH); + } + + PostThink(false); +} diff --git a/code/fgame/actor_balcony.cpp b/code/fgame/actor_balcony.cpp index a567e2b4..ab181089 100644 --- a/code/fgame/actor_balcony.cpp +++ b/code/fgame/actor_balcony.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,366 +25,393 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" #include "scriptexception.h" -void Actor::InitBalconyIdle - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyIdle(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Idle; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->Pain = &Actor::Pain_Balcony; - func->Killed = &Actor::Killed_Balcony; - func->IsState = &Actor::IsIdleState; + func->ThinkState = &Actor::Think_Idle; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->Pain = &Actor::Pain_Balcony; + func->Killed = &Actor::Killed_Balcony; + func->IsState = &Actor::IsIdleState; } -void Actor::InitBalconyCurious - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyCurious(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Curious; - func->BeginState = &Actor::Begin_Curious; - func->EndState = &Actor::End_Curious; - func->ResumeState = &Actor::Resume_Curious; - func->SuspendState = &Actor::Suspend_Curious; - func->FinishedAnimation = &Actor::FinishedAnimation_Curious; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; - func->IsState = &Actor::IsCuriousState; - func->Pain = &Actor::Pain_Balcony; - func->Killed = &Actor::Killed_Balcony; + func->ThinkState = &Actor::Think_Curious; + func->BeginState = &Actor::Begin_Curious; + func->EndState = &Actor::End_Curious; + func->ResumeState = &Actor::Resume_Curious; + func->SuspendState = &Actor::Suspend_Curious; + func->FinishedAnimation = &Actor::FinishedAnimation_Curious; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; + func->IsState = &Actor::IsCuriousState; + func->Pain = &Actor::Pain_Balcony; + func->Killed = &Actor::Killed_Balcony; } -void Actor::InitBalconyAttack - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyAttack(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_BalconyAttack; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; - func->BeginState = &Actor::Begin_BalconyAttack; - func->FinishedAnimation = &Actor::FinishedAnimation_BalconyAttack; - func->Pain = &Actor::Pain_Balcony; - func->Killed = &Actor::Killed_Balcony; - func->IsState = &Actor::IsAttackState; - func->PostShoot = &Actor::State_Balcony_PostShoot; + func->ThinkState = &Actor::Think_BalconyAttack; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->BeginState = &Actor::Begin_BalconyAttack; + func->FinishedAnimation = &Actor::FinishedAnimation_BalconyAttack; + func->Pain = &Actor::Pain_Balcony; + func->Killed = &Actor::Killed_Balcony; + func->IsState = &Actor::IsAttackState; + func->PostShoot = &Actor::State_Balcony_PostShoot; } -void Actor::InitBalconyDisguise - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyDisguise(GlobalFuncs_t *func) { - func->IsState = &Actor::IsDisguiseState; + func->IsState = &Actor::IsDisguiseState; } -void Actor::InitBalconyGrenade - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyGrenade(GlobalFuncs_t *func) { - func->IsState = &Actor::IsGrenadeState; + func->IsState = &Actor::IsGrenadeState; } -void Actor::InitBalconyPain - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyPain(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Pain; - func->ThinkState = &Actor::Think_Pain; - func->FinishedAnimation = &Actor::FinishedAnimation_Pain; - func->Pain = &Actor::Pain_Balcony; - func->Killed = &Actor::Killed_Balcony; - func->IsState = &Actor::IsPainState; + func->BeginState = &Actor::Begin_Pain; + func->ThinkState = &Actor::Think_Pain; + func->FinishedAnimation = &Actor::FinishedAnimation_Pain; + func->Pain = &Actor::Pain_Balcony; + func->Killed = &Actor::Killed_Balcony; + func->IsState = &Actor::IsPainState; } -void Actor::InitBalconyKilled - ( - GlobalFuncs_t *func - ) +void Actor::InitBalconyKilled(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_BalconyKilled; - func->EndState = &Actor::End_BalconyKilled; - func->ThinkState = &Actor::Think_BalconyKilled; - func->FinishedAnimation = &Actor::FinishedAnimation_BalconyKilled; - func->IsState = &Actor::IsKilledState; + func->BeginState = &Actor::Begin_BalconyKilled; + func->EndState = &Actor::End_BalconyKilled; + func->ThinkState = &Actor::Think_BalconyKilled; + func->FinishedAnimation = &Actor::FinishedAnimation_BalconyKilled; + func->IsState = &Actor::IsKilledState; } -void Actor::Pain_Balcony - ( - Event *ev - ) +void Actor::Pain_Balcony(Event *ev) { - SetThink( THINKSTATE_PAIN, THINK_BALCONY_PAIN); - HandlePain( ev ); + SetThink(THINKSTATE_PAIN, THINK_BALCONY_PAIN); + HandlePain(ev); } -void Actor::Killed_Balcony - ( - Event *ev, - bool bPlayDeathAnim - ) +void Actor::Killed_Balcony(Event *ev, bool bPlayDeathAnim) { - ClearStates(); - SetThink( THINKSTATE_KILLED, THINK_BALCONY_KILLED); - HandleKilled( ev, true ); + ClearStates(); + SetThink(THINKSTATE_KILLED, THINK_BALCONY_KILLED); + HandleKilled(ev, true); - if( !bPlayDeathAnim ) - ScriptError( "cannot do 'bedead' on balcony guys" ); + if (!bPlayDeathAnim) { + ScriptError("cannot do 'bedead' on balcony guys"); + } } -void Actor::Begin_BalconyAttack - ( - void - ) +void Actor::Begin_BalconyAttack(void) { - TransitionState(200, 0); + TransitionState(ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY, 0); } -void Actor::State_Balcony_PostShoot - ( - void - ) +void Actor::State_Balcony_PostShoot(void) { - if( m_Enemy ) - { - TransitionState(201, 0); - } + if (m_Enemy) { + TransitionState(ACTOR_STATE_BALCONY_ATTACK_TARGET, 0); + } } -void Actor::State_Balcony_FindEnemy - ( - void - ) +void Actor::State_Balcony_FindEnemy(void) { - m_bHasDesiredLookAngles = false; - Anim_Aim(); + m_bHasDesiredLookAngles = false; + Anim_Aim(); - if( CanSeeEnemy( 200 ) ) - { - TransitionState(201, 0); - } + if (CanSeeEnemy(200)) { + TransitionState(ACTOR_STATE_BALCONY_ATTACK_TARGET, 0); + } } -void Actor::State_Balcony_Target - ( - void - ) +void Actor::State_Balcony_Target(void) { - Anim_Aim(); - AimAtTargetPos(); + Anim_Aim(); + AimAtTargetPos(); - if( level.inttime > m_iStateTime + 1000 ) - { - if( CanSeeEnemy( 0 ) && CanShootEnemy( 0 ) ) - { - TransitionState(202, 0); - } - else - { - ClearPath(); - TransitionState(200, 0); - } - } + if (level.inttime > m_iStateTime + 1000) { + if (CanSeeEnemy(0) && CanShootEnemy(0)) { + TransitionState(ACTOR_STATE_BALCONY_ATTACK_SHOOT, 0); + } else { + ClearPath(); + TransitionState(ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY, 0); + } + } } -void Actor::State_Balcony_Shoot - ( - void - ) +void Actor::State_Balcony_Shoot(void) { - Anim_Shoot(); - AimAtTargetPos(); + Anim_Shoot(); + AimAtTargetPos(); } -void Actor::Think_BalconyAttack - ( - void - ) +void Actor::Think_BalconyAttack(void) { - if( !RequireThink() ) - return; + if (!RequireThink()) { + return; + } - UpdateEyeOrigin(); - UpdateEnemy( 500 ); + UpdateEyeOrigin(); + UpdateEnemy(500); - if( !m_Enemy ) - { - SetThinkState( THINKSTATE_IDLE, THINKLEVEL_NORMAL); - IdleThink(); - return; - } + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + IdleThink(); + return; + } - NoPoint(); + NoPoint(); - if( m_State == 201 ) - { - m_pszDebugState = "target"; - State_Balcony_Target(); - } - else if( m_State == 202 ) - { - m_pszDebugState = "shoot"; - State_Balcony_Shoot(); - } - else if( m_State == 200 ) - { - m_pszDebugState = "findenemy"; - State_Balcony_FindEnemy(); - } - else - { - Com_Printf( "Actor::Think_BalconyAttack: invalid think state %i\n", m_State ); - assert( 0 ); - } + switch (m_State) { + case ACTOR_STATE_BALCONY_ATTACK_TARGET: + m_pszDebugState = "target"; + State_Balcony_Target(); + break; + case ACTOR_STATE_BALCONY_ATTACK_SHOOT: + m_pszDebugState = "shoot"; + State_Balcony_Shoot(); + break; + case ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY: + m_pszDebugState = "findenemy"; + State_Balcony_FindEnemy(); + break; + default: + Com_Printf("Actor::Think_BalconyAttack: invalid think state %i\n", m_State); + assert(0); + break; + } - PostThink( true ); + PostThink(true); } -void Actor::FinishedAnimation_BalconyAttack - ( - void - ) +void Actor::FinishedAnimation_BalconyAttack(void) { - if( m_State == 202 ) - State_Balcony_PostShoot(); + if (m_State == ACTOR_STATE_BALCONY_ATTACK_SHOOT) { + State_Balcony_PostShoot(); + } } -void Actor::Begin_BalconyKilled - ( - void - ) +bool Actor::CalcFallPath(void) { - ClearPath(); - ResetBoneControllers(); + mmove_t mm; + int currentPos = 0; + int loop; + vec3_t pos[200]; + float startDeltaTime; + float nextTime; + vec3_t vRelDelta; + vec3_t vAbsDelta; + float animTime; + int anim; + int i; + float startTime; - PostEvent( EV_Actor_DeathEmbalm, 0.05f ); + SetMoveInfo(&mm); - if( CalcFallPath() ) - TransitionState(800, 0); - else - TransitionState(806, 0); + mm.tracemask &= ~(CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX); + mm.desired_speed = 80; + VectorCopy2D(orientation[0], mm.desired_dir); + + anim = gi.Anim_NumForName(edict->tiki, "death_balcony_intro"); + animTime = gi.Anim_Time(edict->tiki, anim); + startTime = 0.65f; + + for (;;) { + MmoveSingle(&mm); + VectorCopy(mm.origin, pos[currentPos]); + + currentPos++; + if (currentPos >= ARRAY_LEN(pos)) { + return false; + } + + if (mm.hit_obstacle) { + break; + } + + if (!mm.groundPlane) { + return false; + } + + startTime -= level.frametime; + if (startTime < 0) { + return false; + } + } + + for (startDeltaTime = 0.65f; startDeltaTime < animTime; startDeltaTime = nextTime) { + nextTime = startDeltaTime + level.frametime; + if (nextTime >= animTime - 0.01f) { + nextTime = animTime; + } + + gi.Anim_DeltaOverTime(edict->tiki, anim, startDeltaTime, nextTime, vRelDelta); + MatrixTransformVector(vRelDelta, orientation, vAbsDelta); + + VectorAdd(mm.origin, vAbsDelta, mm.origin); + VectorCopy(mm.origin, pos[currentPos]); + + currentPos++; + if (currentPos >= ARRAY_LEN(pos)) { + return false; + } + } + + loop = currentPos; + + mm.desired_speed = 0; + mm.groundPlane = qfalse; + mm.walking = false; + VectorSet(mm.velocity, 0, 0, -171); + + do { + MmoveSingle(&mm); + VectorCopy(mm.origin, pos[currentPos]); + + currentPos++; + if (currentPos >= ARRAY_LEN(pos)) { + return false; + } + + if (mm.hit_obstacle) { + return false; + } + } while (!mm.groundPlane); + + if (origin[2] - pos[currentPos - 1][2] < m_fBalconyHeight) { + return false; + } + + m_pFallPath = (FallPath*)gi.Malloc(sizeof(FallPath) + sizeof(FallPath::pos) * (currentPos - 1)); + m_pFallPath->length = currentPos; + m_pFallPath->currentPos = 0; + m_pFallPath->startTime = startTime; + m_pFallPath->loop = loop; + + for (i = 0; i < currentPos; i++) { + VectorCopy(pos[i], m_pFallPath->pos[i]); + } + + return true; } -void Actor::End_BalconyKilled - ( - void - ) +void Actor::Begin_BalconyKilled(void) { - if( m_pFallPath ) - { - gi.Free(m_pFallPath); - m_pFallPath = NULL; - } + ClearPath(); + ResetBoneControllers(); + + PostEvent(EV_Actor_DeathEmbalm, 0.05f); + + if (CalcFallPath()) { + TransitionState(ACTOR_STATE_BALCONY_KILLED_BEGIN, 0); + } else { + TransitionState(ACTOR_STATE_BALCONY_KILLED_NORMAL, 0); + } } -void Actor::Think_BalconyKilled - ( - void - ) +void Actor::End_BalconyKilled(void) { - int animnum; - - Unregister( STRING_ANIMDONE ); - - if( m_State == 805 ) - { - m_pszDebugState = "end"; - } - else - { - NoPoint(); - m_bHasDesiredLookAngles = false; - StopTurning(); - - switch( m_State ) - { - case 800: - m_bNextForceStart = true; - m_eNextAnimMode = 7; - m_pszDebugState = "begin"; - m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR; - - animnum = gi.Anim_NumForName(edict->tiki, "death_balcony_intro"); - - ChangeMotionAnim(); - - m_bMotionAnimSet = true; - m_iMotionSlot = GetMotionSlot(0); - m_weightType[m_iMotionSlot] = 1; - m_weightCrossBlend[m_iMotionSlot] = 0.0; - m_weightBase[m_iMotionSlot] = 1.0; - - NewAnim( animnum, m_iMotionSlot ); - SetTime( m_iMotionSlot, m_pFallPath->startTime ); - UpdateNormalAnimSlot( m_iMotionSlot ); - TransitionState(801, 0); - break; - case 801: - m_bNextForceStart = false; - m_pszDebugState = "intro"; - m_eNextAnimMode = 7; - m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR; - break; - case 802: - m_pszDebugState = "loop"; - Anim_FullBody( STRING_DEATH_BALCONY_LOOP, 7 ); - break; - case 803: - TransitionState(804, 0); - StopAllAnimating(); - case 804: - m_pszDebugState = "outtro"; - Anim_FullBody( STRING_DEATH_BALCONY_OUTTRO, 1 ); - break; - case 806: - m_pszDebugState = "normal"; - Anim_Killed(); - break; - default: - Com_Printf( "Actor::Think_BalconyKilled: invalid think state %i\n", m_State ); - assert( 0 ); - } - - PostThink( false ); - - if( m_State >= 800 ) - { - if( m_State == 801 ) - { - if( m_pFallPath->currentPos >= m_pFallPath->length ) - { - TransitionState(803, 0); - } - else if (m_pFallPath->currentPos >= m_pFallPath->loop) - { - TransitionState(802, 0); - } - } - else if( m_State == 802 ) - { - if (m_pFallPath->currentPos >= m_pFallPath->length) - { - TransitionState(803, 0); - } - } - } - } + if (m_pFallPath) { + gi.Free(m_pFallPath); + m_pFallPath = NULL; + } } -void Actor::FinishedAnimation_BalconyKilled - ( - void - ) +void Actor::Think_BalconyKilled(void) { - if( m_State == 804 || m_State == 806 ) - { - BecomeCorpse(); - TransitionState(805, 0); - } - else if( m_State == 801 ) - { - TransitionState(802, 0); - StopAllAnimating(); - } + int animnum; + + Unregister(STRING_ANIMDONE); + + if (m_State == ACTOR_STATE_BALCONY_KILLED_END) { + m_pszDebugState = ""; + return; + } + + NoPoint(); + ForwardLook(); + + switch (m_State) { + case ACTOR_STATE_BALCONY_KILLED_BEGIN: + m_bNextForceStart = true; + m_eNextAnimMode = ANIM_MODE_FALLING_PATH; + m_pszDebugState = "begin"; + m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR; + + animnum = gi.Anim_NumForName(edict->tiki, "death_balcony_intro"); + + ChangeMotionAnim(); + + m_bMotionAnimSet = true; + m_iMotionSlot = GetMotionSlot(0); + m_weightType[m_iMotionSlot] = ANIM_WEIGHT_MOTION; + m_weightCrossBlend[m_iMotionSlot] = 0.0; + m_weightBase[m_iMotionSlot] = 1.0; + + NewAnim(animnum, m_iMotionSlot); + SetTime(m_iMotionSlot, m_pFallPath->startTime); + UpdateNormalAnimSlot(m_iMotionSlot); + TransitionState(ACTOR_STATE_BALCONY_KILLED_INTRO, 0); + break; + case ACTOR_STATE_BALCONY_KILLED_INTRO: + m_bNextForceStart = false; + m_pszDebugState = "intro"; + m_eNextAnimMode = ANIM_MODE_FALLING_PATH; + m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR; + break; + case ACTOR_STATE_BALCONY_KILLED_LOOP: + m_pszDebugState = "loop"; + Anim_FullBody(STRING_DEATH_BALCONY_LOOP, 7); + break; + case ACTOR_STATE_BALCONY_KILLED_LOOP_END: + TransitionState(804, 0); + StopAllAnimating(); + case ACTOR_STATE_BALCONY_KILLED_OUTTRO: + m_pszDebugState = "outtro"; + Anim_FullBody(STRING_DEATH_BALCONY_OUTTRO, 1); + break; + case ACTOR_STATE_BALCONY_KILLED_NORMAL: + m_pszDebugState = "normal"; + Anim_Killed(); + break; + default: + Com_Printf("Actor::Think_BalconyKilled: invalid think state %i\n", m_State); + assert(0); + } + + PostThink(false); + + if (m_State >= ACTOR_STATE_BALCONY_KILLED_BEGIN) { + if (m_State == ACTOR_STATE_BALCONY_KILLED_INTRO) { + if (m_pFallPath->currentPos >= m_pFallPath->length) { + TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP_END, 0); + } + else if (m_pFallPath->currentPos >= m_pFallPath->loop) { + TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP, 0); + } + } else if (m_State == ACTOR_STATE_BALCONY_KILLED_LOOP) { + if (m_pFallPath->currentPos >= m_pFallPath->length) { + TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP_END, 0); + } + } + } +} + +void Actor::FinishedAnimation_BalconyKilled(void) +{ + switch (m_State) { + case ACTOR_STATE_BALCONY_KILLED_OUTTRO: + case ACTOR_STATE_BALCONY_KILLED_NORMAL: + BecomeCorpse(); + TransitionState(ACTOR_STATE_BALCONY_KILLED_END, 0); + break; + case ACTOR_STATE_BALCONY_KILLED_INTRO: + TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP, 0); + StopAllAnimating(); + break; + } } diff --git a/code/fgame/actor_cover.cpp b/code/fgame/actor_cover.cpp index 011ddf7d..8350849b 100644 --- a/code/fgame/actor_cover.cpp +++ b/code/fgame/actor_cover.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,915 +24,709 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitCover - ( - GlobalFuncs_t *func - ) -{ - func->ThinkState = &Actor::Think_Cover; - func->BeginState = &Actor::Begin_Cover; - func->EndState = &Actor::End_Cover; - func->SuspendState = &Actor::Suspend_Cover; - func->FinishedAnimation = &Actor::FinishedAnimation_Cover; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; - func->IsState = &Actor::IsAttackState; - func->PathnodeClaimRevoked = &Actor::PathnodeClaimRevoked_Cover; -} - -void Actor::Begin_Cover - ( - void - ) -{ - DoForceActivate(); - m_csIdleMood = STRING_NERVOUS; - m_csMood = STRING_ALERT; - - if( m_pCoverNode ) - { - TransitionState(302, 0); - return; - } - - TransitionState(300, 0); - - if( level.inttime < m_iEnemyChangeTime + 200 ) - { - SetLeashHome( origin ); - - if( AttackEntryAnimation() ) - { - m_bLockThinkState = true; - TransitionState(312, 0); - } - } -} - -void Actor::End_Cover - ( - void - ) -{ - m_pszDebugState = ""; - - if( m_pCoverNode ) - { - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - } - - TransitionState(-1, 0); -} - -void Actor::Suspend_Cover - ( - void - ) -{ - if( m_pCoverNode ) - { - m_pCoverNode->Relinquish(); - m_pCoverNode->MarkTemporarilyBad(); - m_pCoverNode = NULL; - } - - TransitionState(301, 0); -} - -void Actor::State_Cover_NewEnemy - ( - void - ) -{ - m_bHasDesiredLookAngles = true; - - Cover_FindCover( true ); - - if( m_pCoverNode && PathExists() && PathComplete() ) - { - Anim_RunToCover( 3 ); - TransitionState(302, 0); - } - else - { - Anim_Aim(); - AimAtTargetPos(); - TransitionState(307, 0); - } -} - -void Actor::State_Cover_FindCover - ( - void - ) -{ - Anim_Aim(); - AimAtTargetPos(); - Cover_FindCover( false ); - - if( m_pCoverNode ) - { - if( PathExists() && !PathComplete() ) - { - Anim_RunToCover(3); - TransitionState(302, 0); - } - else - { - TransitionState(307, 0); - } - } - else - { - if( !m_iPotentialCoverCount ) - { - SetThink( THINKSTATE_ATTACK, THINK_TURRET ); - } - } -} - -void Actor::State_Cover_TakeCover - ( - void - ) -{ - if( PathExists() && !PathComplete() ) - { - FaceEnemyOrMotion( level.inttime - m_iStateTime ); - Anim_RunToCover( 3 ); - m_csPathGoalEndAnimScript = m_bInReload ? STRING_ANIM_RUNTO_COVER_SCR : STRING_ANIM_IDLE_SCR; - } - else - { - ClearPath(); - m_eAnimMode = 1; - TransitionState(303, 0); - State_Cover_FinishReloading(); - } -} - static int Cover_HideTime(int iTeam) { - if (iTeam == TEAM_AMERICAN) - { - return rand() % 2001 + 2000; - } - else - { - return rand() % 11001 + 4000; - } + if (iTeam == TEAM_AMERICAN) { + return rand() % 2001 + 2000; + } else { + return rand() % 11001 + 4000; + } } -void Actor::State_Cover_FinishReloading - ( - void - ) +bool Actor::Cover_IsValid(PathNode *node) { - if( m_bInReload ) - { - ContinueAnimation(); - AimAtTargetPos(); - return; - } + Vector sight_origin = node->origin + eyeposition; - Weapon *pWeap = GetWeapon( 0 ); + if (node->IsClaimedByOther(this)) { + return false; + } - if( !pWeap || pWeap->GetFireType( FIRE_PRIMARY ) == FT_PROJECTILE || pWeap->GetFireType( FIRE_PRIMARY ) == FT_SPECIAL_PROJECTILE ) - { - if( m_pCoverNode->nodeflags & AI_DUCK ) - { - Anim_Crouch(); - } - else - { - Anim_Stand(); - } + if (node->nodeflags & (AI_CONCEALMENT | AI_LOW_WALL_ARC)) { + return true; + } - m_sCurrentPathNodeIndex = -1; + if (!CanSeeFrom(sight_origin, m_Enemy)) { + return true; + } - TransitionState(308, Cover_HideTime(m_Team)); + if (!(node->nodeflags & AI_DUCK)) { + return false; + } - Anim_Aim(); - AimAtTargetPos(); - return; - } + if (CanSee(sight_origin - Vector(0, 0, 32), 0, 0, false)) { + return false; + } - SetDesiredYaw(angles[1]); - - SafeSetOrigin( origin ); - m_eNextAnimMode = 1; - m_bNextForceStart = false; - m_csNextAnimString = m_csSpecialAttack; - TransitionState(304, 0); + return true; } -void Actor::State_Cover_Target - ( - void - ) +bool Actor::Cover_SetPath(PathNode *node) { - DontFaceWall(); + float origin_ratio; + Vector enemy_offset; + PathInfo *current_node; + Vector enemy_origin; + vec2_t vDelta; + float fMinDistSquared; + float fPathDist; - if( m_eDontFaceWallMode <= 8 ) - { - TransitionState(305, 0); - State_Cover_FindEnemy(); - return; - } + SetPathWithLeash(node, NULL, 0); - Anim_Aim(); - AimAtTargetPos(); + if (!PathExists()) { + return false; + } - if( level.inttime > m_iStateTime + 300 && fabs( m_DesiredYaw - angles[ 1 ] ) < 0.001f ) - { - Vector end = m_vLastEnemyPos + velocity; - if( DecideToThrowGrenade( end, &m_vGrenadeVel, &m_eGrenadeMode ) ) - { - SetDesiredYawDir(m_vGrenadeVel); - m_eNextAnimMode = 1; - m_bNextForceStart = false; - m_csNextAnimString = m_eGrenadeMode == AI_GREN_TOSS_ROLL ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR; - TransitionState(310, 0); - } - else if( CanSeeEnemy( 500 ) && CanShootEnemy( 500 ) ) - { - TransitionState(309, 0); - } - else - { - TransitionState(308, Cover_HideTime(m_Team)); + fPathDist = PathDist(); + fMinDistSquared = Square(fPathDist); - } - } + if ((node->origin - origin).lengthSquared() * 4 <= fMinDistSquared && fPathDist > 128.0f) { + return false; + } + + if (PathComplete()) { + return true; + } + + enemy_origin = m_Enemy->origin; + VectorSub2D(enemy_origin, origin, vDelta); + + origin_ratio = VectorLength2DSquared(vDelta) * 0.64f; + if (origin_ratio > Square(192)) { + origin_ratio = Square(192); + } + + for (current_node = CurrentPathNode() - 1; current_node >= LastPathNode(); current_node--) { + VectorSub2D(enemy_origin, current_node->point, enemy_offset); + + if (VectorLength2DSquared(enemy_offset) <= origin_ratio) { + return false; + } + + if (DotProduct2D(enemy_offset, current_node->dir) >= 0) { + continue; + } + + if (DotProduct2D(enemy_offset, current_node->dir) < -current_node->dist) { + continue; + } + + if (Square(CrossProduct2D(enemy_offset, current_node->dir)) <= origin_ratio) { + return false; + } + } + + return PathAvoidsSquadMates() != false; } -void Actor::State_Cover_Hide -( - void -) +void Actor::Cover_FindCover(bool bCheckAll) { - if (m_Enemy) - { - SetEnemyPos(origin); - } + if (m_pCoverNode) { + if (Cover_IsValid(m_pCoverNode) && Cover_SetPath(m_pCoverNode)) { + return; + } - if (!m_pCoverNode) - { - TransitionState(301, 0); - State_Cover_FindCover(); - return; - } + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + } - m_csSpecialAttack = m_pCoverNode->GetSpecialAttack(this); - MPrintf("special: %d", m_csSpecialAttack); + if (!m_iPotentialCoverCount) { + m_iPotentialCoverCount = + PathManager.FindPotentialCover(this, origin, m_Enemy, m_pPotentialCoverNode, MAX_COVER_NODES); + } - if (m_csSpecialAttack) - { - SetDesiredYaw(m_pCoverNode->angles[1]); - SafeSetOrigin(m_pCoverNode->origin); - m_eNextAnimMode = 1; - m_bNextForceStart = false; - m_csNextAnimString = m_csSpecialAttack; - TransitionState(304, 0); - return; - } + if (!m_iPotentialCoverCount) { + return; + } - bool bCanShoot = CanShootEnemy(500); - if (CanSeeEnemy(500)) - { - if (bCanShoot) - { - Vector vDelta = m_Enemy->origin - origin; + PathNode *pNode; - if (VectorLength2DSquared(vDelta) * 0.75f <= Square(DotProduct2D(vDelta, orientation[0]))) - { - TransitionState(307, 0); - } - else - { - TransitionState(309, 0); - State_Cover_Shoot(); - } - return; - } + while (m_iPotentialCoverCount) { + m_iPotentialCoverCount--; + pNode = m_pPotentialCoverNode[m_iPotentialCoverCount]; + m_pPotentialCoverNode[m_iPotentialCoverCount] = NULL; + if (Cover_IsValid(pNode) && Cover_SetPath(pNode)) { + break; + } - m_pCoverNode->Relinquish(); - m_pCoverNode->MarkTemporarilyBad(); - m_pCoverNode = NULL; - TransitionState(305, 0); - State_Cover_FindEnemy(); - return; - } - - if (bCanShoot) - { - m_pCoverNode->Relinquish(); - m_pCoverNode->MarkTemporarilyBad(); - m_pCoverNode = NULL; - TransitionState(305, 0); - State_Cover_FindEnemy(); - return; - } - - if (m_Team == TEAM_AMERICAN) - { - if (level.inttime >= m_iLastFaceDecideTime + 1000) - { - m_iLastFaceDecideTime = level.inttime; - PathNode *node = PathManager.FindCornerNodeForExactPath(this, m_Enemy, m_fLeash + m_fMaxDistance); - - if (!node) - { - m_bHasDesiredLookAngles = false; - Anim_Stand(); - m_PotentialEnemies.FlagBadEnemy(m_Enemy); - UpdateEnemy(-1); - return; - } - - Vector vDelta = node->m_PathPos - origin; - - if (vDelta[0] || vDelta[1]) - { - SetDesiredYawDir(vDelta); - } - } - - Anim_Aim(); - } - else - { - if (level.inttime >= m_iLastFaceDecideTime + 1000) - { - m_iLastFaceDecideTime = level.inttime; - Vector eyepos = EyePosition(); - Vector end = m_vLastEnemyPos + eyeposition; - trace_t trace = G_Trace( - eyepos, - vec_zero, - vec_zero, - end, - this, - (CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA), - false, - "State_Cover"); - - PathNode *node = PathManager.FindCornerNodeForWall(origin, m_vLastEnemyPos, this, 0.0f, trace.plane.normal); - - if (node) - { - Vector vDelta = node->m_PathPos - origin; - - if (vDelta[0] || vDelta[1]) - { - SetDesiredYawDir(vDelta); - } - - m_eDontFaceWallMode = 6; - } - else - { - AimAtTargetPos(); - DontFaceWall(); - } - } - - if (m_eDontFaceWallMode <= 8) - { - Anim_Stand(); - } - else - { - Anim_Aim(); - } - } - - if (level.inttime <= m_iStateTime) - return; - - PathNode *pNode = (PathNode *)G_FindRandomSimpleTarget(m_pCoverNode->target); - - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - - if (!pNode) - { - Anim_Stand(); - TransitionState(305, rand() & 0x7FF); - return; - } - - assert(pNode->IsSubclassOfPathNode()); - if (pNode->IsSubclassOfPathNode()) - { - if (!pNode->IsClaimedByOther(this)) - { - SetPath(pNode, "Actor::State_Cover_Target", 0); - - if (PathExists()) - { - m_pCoverNode = pNode; - pNode->Claim(this); - Anim_RunToDanger(3); - TransitionState(306, 0); - } - } - } + if (!bCheckAll || !m_iPotentialCoverCount) { + return; + } + } + m_pCoverNode = pNode; + m_pCoverNode->Claim(this); + memset(m_pPotentialCoverNode, 0, sizeof(m_pPotentialCoverNode)); + m_iPotentialCoverCount = 0; } -void Actor::State_Cover_Shoot -( - void -) +void Actor::InitCover(GlobalFuncs_t *func) { - if (m_bNeedReload) - { - Cover_FindCover(true); - - if (m_pCoverNode) - { - Anim_RunToCover(3); - FaceEnemyOrMotion(0); - TransitionState(302, 0); - return; - } - } - - Anim_Shoot(); - AimAtTargetPos(); - - if (level.inttime > m_iStateTime + 10000) - { - gi.cvar_set("g_monitornum", va("%i", entnum)); - assert(!"anim/shoot.scr took over 10 seconds"); - Com_Error(ERR_DROP, "anim/shoot.scr took over 10 seconds, entnum = %i, targetname = %s", entnum, targetname.c_str()); - } + func->ThinkState = &Actor::Think_Cover; + func->BeginState = &Actor::Begin_Cover; + func->EndState = &Actor::End_Cover; + func->SuspendState = &Actor::Suspend_Cover; + func->FinishedAnimation = &Actor::FinishedAnimation_Cover; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->IsState = &Actor::IsAttackState; + func->PathnodeClaimRevoked = &Actor::PathnodeClaimRevoked_Cover; } -void Actor::State_Cover_Grenade - ( - void - ) +void Actor::Begin_Cover(void) { - GenericGrenadeTossThink(); + DoForceActivate(); + m_csIdleMood = STRING_NERVOUS; + m_csMood = STRING_ALERT; + + if (m_pCoverNode) { + TransitionState(ACTOR_STATE_COVER_TAKE_COVER, 0); + return; + } + + TransitionState(ACTOR_STATE_COVER_NEW_ENEMY, 0); + + if (level.inttime < m_iEnemyChangeTime + 200) { + SetLeashHome(origin); + + if (AttackEntryAnimation()) { + m_bLockThinkState = true; + TransitionState(ACTOR_STATE_COVER_LOOP, 0); + } + } } -void Actor::State_Cover_SpecialAttack - ( - void - ) +void Actor::End_Cover(void) { - m_bHasDesiredLookAngles = false; + m_pszDebugState = ""; - assert( m_pCoverNode ); - if( !m_pCoverNode ) - { - TransitionState(305, 0); - State_Cover_FindEnemy(); - return; - } + if (m_pCoverNode) { + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + } - if( mbBreakSpecialAttack ) - { - if( m_pCoverNode ) - { - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - } - - TransitionState(305, 0); - State_Cover_FindEnemy(); - return; - } - - if( level.inttime >= m_iLastEnemyPosChangeTime + level.intframetime || !m_csSpecialAttack ) - { - m_csSpecialAttack = m_pCoverNode->GetSpecialAttack( this ); - - if( !m_csSpecialAttack ) - { - TransitionState(305, 0); - State_Cover_FindEnemy(); - return; - } - } - - SetDesiredYaw(angles[1]); - - m_eNextAnimMode = 1; - m_csNextAnimString = m_csSpecialAttack; - m_bNextForceStart = false; + TransitionState(-1, 0); } -void Actor::State_Cover_FindEnemy - ( - void - ) +void Actor::Suspend_Cover(void) { - if( m_Team == TEAM_AMERICAN ) - { - m_bHasDesiredLookAngles = false; + if (m_pCoverNode) { + m_pCoverNode->Relinquish(); + m_pCoverNode->MarkTemporarilyBad(); + m_pCoverNode = NULL; + } -__setpath: - Anim_Stand(); - SetPathWithLeash( m_vLastEnemyPos, NULL, 0 ); - ShortenPathToAvoidSquadMates(); - if( PathExists() && !PathComplete() && PathAvoidsSquadMates() ) - { - TransitionState(311, 0); - } - else - { - m_bTurretNoInitialCover = true; - SetThink( THINKSTATE_ATTACK, THINK_TURRET ); - } - - return; - } - - AimAtTargetPos(); - Anim_Aim(); - DontFaceWall(); - - if( CanSeeEnemy( 200 ) ) - { - if( m_eDontFaceWallMode > 8 ) - { - TransitionState(307, 0); - } - - goto __setpath; - } - - if( m_eDontFaceWallMode <= 8 || level.inttime > m_iStateTime + 500 ) - { - goto __setpath; - } + TransitionState(ACTOR_STATE_COVER_FIND_COVER, 0); } -void Actor::State_Cover_SearchNode - ( - void - ) +void Actor::State_Cover_NewEnemy(void) { - m_bHasDesiredLookAngles = false; + ForwardLook(); + Cover_FindCover(true); - if( CanSeeEnemy( 200 ) ) - { - Anim_Aim(); - AimAtTargetPos(); - TransitionState(307, 0); - return; - } - - if( PathExists() && !PathComplete() ) - { - FaceEnemyOrMotion( level.inttime - m_iStateTime ); - Anim_RunToDanger( 3 ); - } - else - { - Anim_Aim(); - AimAtTargetPos(); - - if( level.inttime > m_iStateTime + 3000 ) - { - TransitionState(301, 0); - } - } + if (m_pCoverNode && PathExists() && !PathComplete()) { + Anim_RunToCover(ANIM_MODE_PATH_GOAL); + TransitionState(ACTOR_STATE_COVER_TAKE_COVER, 0); + } else { + Anim_Aim(); + AimAtTargetPos(); + TransitionState(ACTOR_STATE_COVER_TARGET, 0); + } } -void Actor::State_Cover_HuntEnemy - ( - void - ) +void Actor::State_Cover_FindCover(void) { - FaceEnemyOrMotion( level.inttime - m_iStateTime ); - MovePathWithLeash(); + Anim_Aim(); + AimAtTargetPos(); + Cover_FindCover(false); - if( PathExists() && !PathComplete() ) - { - if( CanSeeEnemy( 300 ) ) - { - TransitionState(307, 0); - } - } - else - { - TransitionState(305, rand() & 0x7FF); - - if( m_pCoverNode ) - { - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - } - } + if (m_pCoverNode) { + if (PathExists() && !PathComplete()) { + Anim_RunToCover(ANIM_MODE_PATH_GOAL); + TransitionState(ACTOR_STATE_COVER_TAKE_COVER, 0); + } else { + TransitionState(ACTOR_STATE_COVER_TARGET, 0); + } + } else if (!m_iPotentialCoverCount) { + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + } } -void Actor::State_Cover_FakeEnemy - ( - void - ) +void Actor::State_Cover_TakeCover(void) { - AimAtTargetPos(); - Anim_Aim(); - - if( level.inttime >= m_iStateTime ) - { - SetThinkState( THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } + if (PathExists() && !PathComplete()) { + FaceEnemyOrMotion(level.inttime - m_iStateTime); + Anim_RunToCover(ANIM_MODE_PATH_GOAL); + SetPathGoalEndAnim(m_bInReload ? STRING_ANIM_RUNTO_COVER_SCR : STRING_ANIM_IDLE_SCR); + } else { + ClearPath(); + m_eAnimMode = ANIM_MODE_NORMAL; + TransitionState(ACTOR_STATE_COVER_FINISH_RELOADING, 0); + State_Cover_FinishReloading(); + } } -void Actor::Think_Cover - ( - void - ) +void Actor::State_Cover_FinishReloading(void) { - if( !RequireThink() ) - { - return; - } + Weapon *pWeapon; + firetype_t eFireType; - UpdateEyeOrigin(); - NoPoint(); - UpdateEnemy( 500 ); + if (m_bInReload) { + ContinueAnimation(); + AimAtTargetPos(); + return; + } - if( m_State == 312 ) - { - ContinueAnimation(); - } - else - { - m_bLockThinkState = false; - if( m_Enemy ) - { - if( m_State == 313 ) - { - TransitionState(300, 0); - } - } - else - { - if( m_State != 313 ) - { - TransitionState(313, (rand() & 0x7FF) + 1000); - } - } + pWeapon = GetWeapon(WEAPON_MAIN); + if (pWeapon) { + eFireType = pWeapon->GetFireType(FIRE_PRIMARY); + } - switch( m_State ) - { - case 300: - m_pszDebugState = "NewEnemy"; - State_Cover_NewEnemy(); - break; - case 301: - m_pszDebugState = "FindCover"; - State_Cover_FindCover(); - break; - case 302: - m_pszDebugState = "TakeCover"; - State_Cover_TakeCover(); - break; - case 303: - m_pszDebugState = "FinishReloading"; - State_Cover_FinishReloading(); - break; - case 304: - m_pszDebugState = "SpecialAttack"; - State_Cover_SpecialAttack(); - break; - case 305: - m_pszDebugState = "FindEnemy"; - State_Cover_FindEnemy(); - break; - case 306: - m_pszDebugState = "SearchNode"; - State_Cover_SearchNode(); - break; - case 307: - m_pszDebugState = "Target"; - State_Cover_Target(); - break; - case 308: - m_pszDebugState = "Hide"; - State_Cover_Hide(); - break; - case 309: - m_pszDebugState = "Shoot"; - State_Cover_Shoot(); - break; - case 310: - m_pszDebugState = "Grenade"; - State_Cover_Grenade(); - break; - case 311: - m_pszDebugState = "HuntEnemy"; - State_Cover_HuntEnemy(); - break; - case 313: - m_pszDebugState = "FakeEnemy"; - State_Cover_FakeEnemy(); - break; - default: - Com_Printf( "Actor::Think_Cover: invalid think state %i\n", m_State ); - assert( 0 ); - break; - } + if (pWeapon && eFireType != FT_PROJECTILE && eFireType != FT_SPECIAL_PROJECTILE + && (m_csSpecialAttack = m_pCoverNode->GetSpecialAttack(this)) != 0) { + SetDesiredYaw(m_pCoverNode->angles.yaw()); + SafeSetOrigin(m_pCoverNode->origin); + DesiredAnimation(ANIM_MODE_NORMAL, m_csSpecialAttack); + TransitionState(ACTOR_STATE_COVER_SPECIAL_ATTACK, 0); + } else { + if (m_pCoverNode->nodeflags & AI_DUCK) { + Anim_Crouch(); + } else { + Anim_Stand(); + } - CheckForTransition( THINKSTATE_GRENADE, THINKLEVEL_NORMAL ); - } + TransitionState(ACTOR_STATE_COVER_HIDE, Cover_HideTime(m_Team)); - if( m_State != 305 && m_State != 307 && m_State != 308 && m_State != 309 ) - { - PostThink( true ); - } - else - { - PostThink( false ); - } + Anim_Aim(); + AimAtTargetPos(); + } } -void Actor::FinishedAnimation_Cover - ( - void - ) +void Actor::State_Cover_Target(void) { - if( m_State == 309 ) - { - if( m_Enemy && !m_Enemy->IsDead() && CanSeeEnemy( 500 ) && CanShootEnemy( 500 ) ) - { - TransitionState(309, 0); - } - else - { - TransitionState(301, 0); - } - } - else if( m_State == 310 || m_State == 312 ) - { - TransitionState(301, 0); - } + DontFaceWall(); + + if (AvoidingFacingWall()) { + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY, 0); + State_Cover_FindEnemy(); + return; + } + + Anim_Aim(); + AimAtTargetPos(); + + if (level.inttime <= m_iStateTime + 300) { + return; + } + + if (fabs(m_DesiredYaw - angles[1]) >= 0.001f) { + return; + } + + if (DecideToThrowGrenade(m_vLastEnemyPos + velocity, &m_vGrenadeVel, &m_eGrenadeMode, false)) { + SetDesiredYawDir(m_vGrenadeVel); + DesiredAnimation( + ANIM_MODE_NORMAL, + m_eGrenadeMode == AI_GREN_TOSS_ROLL ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR + ); + TransitionState(ACTOR_STATE_COVER_GRENADE); + } else if (CanSeeEnemy(500) && CanShootEnemy(500)) { + TransitionState(ACTOR_STATE_COVER_SHOOT, 0); + } else { + TransitionState(ACTOR_STATE_COVER_HIDE, Cover_HideTime(m_Team)); + } } -void Actor::PathnodeClaimRevoked_Cover - ( - void - ) +void Actor::State_Cover_Hide(void) { - TransitionState(301, 0); + PathNode *pNode; + trace_t trace; + bool bCanShoot, bCanSee; + + if (m_Enemy) { + SetEnemyPos(m_Enemy->origin); + } + + if (!m_pCoverNode) { + TransitionState(ACTOR_STATE_COVER_FIND_COVER, 0); + State_Cover_FindCover(); + return; + } + + m_csSpecialAttack = m_pCoverNode->GetSpecialAttack(this); + MPrintf("special: %d", m_csSpecialAttack); + + if (m_csSpecialAttack) { + SetDesiredYaw(m_pCoverNode->angles.yaw()); + SafeSetOrigin(m_pCoverNode->origin); + DesiredAnimation(ANIM_MODE_NORMAL, m_csSpecialAttack); + TransitionState(ACTOR_STATE_COVER_SPECIAL_ATTACK, 0); + return; + } + + bCanSee = CanSeeEnemy(500); + bCanShoot = CanShootEnemy(500); + + if (bCanSee && bCanShoot) { + vec2_t vDelta; + + VectorSub2D(m_Enemy->origin, origin, vDelta); + if (VectorLength2DSquared(vDelta) * 0.75f > Square(DotProduct2D(vDelta, orientation[0]))) { + TransitionState(ACTOR_STATE_COVER_SHOOT); + } else { + TransitionState(ACTOR_STATE_COVER_TARGET); + } + + State_Cover_Shoot(); + return; + } + + if (bCanSee || bCanShoot) { + m_pCoverNode->Relinquish(); + m_pCoverNode->MarkTemporarilyBad(); + m_pCoverNode = NULL; + + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY); + State_Cover_FindEnemy(); + return; + } + + if (m_Team == TEAM_AMERICAN) { + if (level.inttime >= m_iLastFaceDecideTime + 1000) { + m_iLastFaceDecideTime = level.inttime; + pNode = PathManager.FindCornerNodeForExactPath(this, m_Enemy, m_fLeash + m_fMaxDistance); + + if (!pNode) { + ForwardLook(); + Anim_Stand(); + m_PotentialEnemies.FlagBadEnemy(m_Enemy); + UpdateEnemy(-1); + return; + } + + SetDesiredYawDest(pNode->m_PathPos); + } + + Anim_Aim(); + } else { + if (level.inttime >= m_iLastFaceDecideTime + 1000) { + m_iLastFaceDecideTime = level.inttime; + + trace = G_Trace( + EyePosition(), vec_zero, vec_zero, m_vLastEnemyPos + eyeposition, this, MASK_LOOK, false, "State_Cover" + ); + + pNode = PathManager.FindCornerNodeForWall(origin, m_vLastEnemyPos, this, 0.0f, trace.plane.normal); + + if (pNode) { + SetDesiredYawDest(pNode->m_PathPos); + m_eDontFaceWallMode = 6; + } else { + AimAtTargetPos(); + DontFaceWall(); + } + } + + if (m_eDontFaceWallMode == 7 || m_eDontFaceWallMode == 8) { + Anim_Stand(); + } else { + Anim_Aim(); + } + } + + if (level.inttime <= m_iStateTime) { + return; + } + + pNode = (PathNode *)G_FindRandomSimpleTarget(m_pCoverNode->Target()); + + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + + if (!pNode) { + Anim_Stand(); + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY, rand() & 0x7FF); + return; + } + + assert(pNode->IsSubclassOfPathNode()); + + if (pNode->IsSubclassOfPathNode() && !pNode->IsClaimedByOther(this)) { + SetPath(pNode, "Actor::State_Cover_Target", 0); + + if (PathExists()) { + m_pCoverNode = pNode; + pNode->Claim(this); + Anim_RunToDanger(ANIM_MODE_PATH_GOAL); + TransitionState(ACTOR_STATE_COVER_SEARCH_NODE, 0); + } + } } -bool Actor::Cover_IsValid - ( - PathNode *node - ) +void Actor::State_Cover_Shoot(void) { - if( !node->IsClaimedByOther( this ) ) - { - if( node->nodeflags & AI_CONCEALMENT ) - { - return true; - } - else if( CanSeeFrom( origin + eyeposition, m_Enemy ) ) - { - if( !( node->nodeflags & AI_DUCK ) ) - { - return false; - } - else if( CanSeeFrom( origin + eyeposition - Vector( 0, 0, 32 ), m_Enemy ) ) - { - return false; - } - else - { - return true; - } - } - else - { - return true; - } - } - else - { - return false; - } + if (m_bNeedReload) { + Cover_FindCover(true); + + if (m_pCoverNode) { + Anim_RunToCover(ANIM_MODE_PATH_GOAL); + FaceEnemyOrMotion(0); + TransitionState(ACTOR_STATE_COVER_TAKE_COVER, 0); + return; + } + } + + Anim_Shoot(); + AimAtTargetPos(); + + // FIXME: debug build only? + if (level.inttime > m_iStateTime + 10000) { + gi.cvar_set("g_monitornum", va("%i", entnum)); + assert(!"anim/shoot.scr took over 10 seconds"); + Com_Error( + ERR_DROP, "anim/shoot.scr took over 10 seconds, entnum = %i, targetname = %s", entnum, TargetName().c_str() + ); + } } -bool Actor::Cover_SetPath - ( - PathNode *node - ) + +void Actor::State_Cover_Grenade(void) { - SetPathWithLeash( node, NULL, 0 ); - - if( !PathExists() ) - { - return false; - } - - float origin_ratio; - Vector enemy_offset; - PathInfo *current_node; - Vector enemy_origin; - Vector vDelta; - float fMinDistSquared; - float fPathDist; - - fPathDist = PathDist(); - fMinDistSquared = fPathDist * fPathDist; - vDelta = node->origin - origin; - - if( fMinDistSquared >= vDelta.lengthSquared() * 4.0f ) - { - if( fPathDist > 128.0f ) - { - return false; - } - } - - if( !PathComplete() ) - { - enemy_origin = m_Enemy->origin; - vDelta = enemy_origin - origin; - - if( VectorLength2DSquared( vDelta ) * 0.64f > 192 * 192 ) - { - origin_ratio = 192 * 192; - } - - for( current_node = CurrentPathNode() - 1; current_node >= LastPathNode(); current_node-- ) - { - vDelta[ 0 ] = origin[ 0 ] - current_node->point[ 0 ]; - vDelta[ 1 ] = origin[ 1 ] - current_node->point[ 1 ]; - - if( origin_ratio >= VectorLength2DSquared( vDelta ) ) - { - return false; - } - - float fDot = DotProduct2D( vDelta, current_node->dir ); - if( fDot < 0.0f && -current_node->dist <= fDot ) - { - if( ( vDelta[ 0 ] * current_node->dir[ 0 ] - vDelta[ 1 ] * current_node->dir[ 1 ] ) * ( vDelta[ 0 ] * current_node->dir[ 0 ] - vDelta[ 1 ] * current_node->dir[ 1 ] ) ) - { - return false; - } - } - } - } - - return true; + GenericGrenadeTossThink(); } -void Actor::Cover_FindCover - ( - bool bCheckAll - ) +void Actor::State_Cover_SpecialAttack(void) { + ForwardLook(); - if( m_pCoverNode ) - { - if( Cover_IsValid( m_pCoverNode ) && Cover_SetPath( m_pCoverNode ) ) - { - return; - } + assert(m_pCoverNode); + if (!m_pCoverNode) { + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY, 0); + State_Cover_FindEnemy(); + return; + } - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - } + if (mbBreakSpecialAttack) { + if (m_pCoverNode) { + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + } - if( !m_iPotentialCoverCount ) - { - m_iPotentialCoverCount = PathManager.FindPotentialCover( this, origin, m_Enemy, m_pPotentialCoverNode, 16 ); - } + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY, 0); + State_Cover_FindEnemy(); + return; + } - if( m_iPotentialCoverCount ) - { - PathNode *pNode = NULL; + if (level.inttime >= m_iLastEnemyPosChangeTime + level.intframetime || !m_csSpecialAttack) { + m_csSpecialAttack = m_pCoverNode->GetSpecialAttack(this); + } - while( m_iPotentialCoverCount ) - { - m_iPotentialCoverCount--; - pNode = m_pPotentialCoverNode[ m_iPotentialCoverCount ]; - m_pPotentialCoverNode[ m_iPotentialCoverCount ] = NULL; + if (!m_csSpecialAttack) { + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY, 0); + State_Cover_FindEnemy(); + return; + } - if( Cover_IsValid( pNode ) && Cover_SetPath( pNode ) ) - { - break; - } + if (m_csSpecialAttack > STRING_ANIM_HIGHWALL_SCR || m_csSpecialAttack < STRING_ANIM_LOWWALL_SCR) { + SetDesiredYaw(m_pCoverNode->angles.yaw()); + } else { + AimAtTargetPos(); + } - if( !bCheckAll ) - { - return; - } - } - - m_pCoverNode = pNode; - m_pCoverNode->Claim( this ); - memset( m_pPotentialCoverNode, 0, sizeof( m_pPotentialCoverNode ) ); - m_iPotentialCoverCount = 0; - } + DesiredAnimation(ANIM_MODE_NORMAL, m_csSpecialAttack); } +void Actor::State_Cover_FindEnemy(void) +{ + if (m_Team == TEAM_AMERICAN) { + ForwardLook(); + Anim_Stand(); + } else { + AimAtTargetPos(); + Anim_Aim(); + DontFaceWall(); + + if (CanSeeEnemy(200) && !AvoidingFacingWall()) { + TransitionState(ACTOR_STATE_COVER_TARGET); + } else if (!AvoidingFacingWall() && level.inttime <= m_iStateTime + 500) { + return; + } + } + + SetPathWithLeash(m_vLastEnemyPos, NULL, 0); + ShortenPathToAvoidSquadMates(); + + if (PathExists() && !PathComplete() && PathAvoidsSquadMates()) { + TransitionState(ACTOR_STATE_COVER_HUNT_ENEMY); + } else { + m_bTurretNoInitialCover = true; + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + } +} + +void Actor::State_Cover_SearchNode(void) +{ + ForwardLook(); + + if (CanSeeEnemy(200)) { + Anim_Aim(); + AimAtTargetPos(); + TransitionState(ACTOR_STATE_COVER_TARGET, 0); + return; + } + + if (PathExists() && !PathComplete()) { + FaceEnemyOrMotion(level.inttime - m_iStateTime); + Anim_RunToDanger(ANIM_MODE_PATH_GOAL); + return; + } + + Anim_Aim(); + AimAtTargetPos(); + + if (level.inttime > m_iStateTime + 3000) { + TransitionState(ACTOR_STATE_COVER_FIND_COVER, 0); + } +} + +void Actor::State_Cover_HuntEnemy(void) +{ + FaceEnemyOrMotion(level.inttime - m_iStateTime); + MovePathWithLeash(); + + if (PathExists() && !PathComplete()) { + if (CanSeeEnemy(300)) { + TransitionState(ACTOR_STATE_COVER_TARGET, 0); + } + return; + } + + TransitionState(ACTOR_STATE_COVER_FIND_ENEMY, rand() & 0x7FF); + + if (m_pCoverNode) { + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + } +} + +void Actor::State_Cover_FakeEnemy(void) +{ + AimAtTargetPos(); + Anim_Aim(); + + if (level.inttime >= m_iStateTime) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } +} + +void Actor::Think_Cover(void) +{ + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + NoPoint(); + UpdateEnemy(500); + + if (m_State == ACTOR_STATE_COVER_LOOP) { + ContinueAnimation(); + } else { + m_bLockThinkState = false; + if (m_Enemy) { + if (m_State == ACTOR_STATE_COVER_FAKE_ENEMY) { + TransitionState(ACTOR_STATE_COVER_NEW_ENEMY, 0); + } + } else { + if (m_State != ACTOR_STATE_COVER_FAKE_ENEMY) { + TransitionState(ACTOR_STATE_COVER_FAKE_ENEMY, (rand() & 0x7FF) + 1000); + } + } + + switch (m_State) { + case ACTOR_STATE_COVER_START: + m_pszDebugState = "NewEnemy"; + State_Cover_NewEnemy(); + break; + case ACTOR_STATE_COVER_FIND_COVER: + m_pszDebugState = "FindCover"; + State_Cover_FindCover(); + break; + case ACTOR_STATE_COVER_TAKE_COVER: + m_pszDebugState = "TakeCover"; + State_Cover_TakeCover(); + break; + case ACTOR_STATE_COVER_FINISH_RELOADING: + m_pszDebugState = "FinishReloading"; + State_Cover_FinishReloading(); + break; + case ACTOR_STATE_COVER_SPECIAL_ATTACK: + m_pszDebugState = "SpecialAttack"; + State_Cover_SpecialAttack(); + break; + case ACTOR_STATE_COVER_FIND_ENEMY: + m_pszDebugState = "FindEnemy"; + State_Cover_FindEnemy(); + break; + case ACTOR_STATE_COVER_SEARCH_NODE: + m_pszDebugState = "SearchNode"; + State_Cover_SearchNode(); + break; + case ACTOR_STATE_COVER_TARGET: + m_pszDebugState = "Target"; + State_Cover_Target(); + break; + case ACTOR_STATE_COVER_HIDE: + m_pszDebugState = "Hide"; + State_Cover_Hide(); + break; + case ACTOR_STATE_COVER_SHOOT: + m_pszDebugState = "Shoot"; + State_Cover_Shoot(); + break; + case ACTOR_STATE_COVER_GRENADE: + m_pszDebugState = "Grenade"; + State_Cover_Grenade(); + break; + case ACTOR_STATE_COVER_HUNT_ENEMY: + m_pszDebugState = "HuntEnemy"; + State_Cover_HuntEnemy(); + break; + case ACTOR_STATE_COVER_FAKE_ENEMY: + m_pszDebugState = "FakeEnemy"; + State_Cover_FakeEnemy(); + break; + default: + Com_Printf("Actor::Think_Cover: invalid think state %i\n", m_State); + assert(0); + break; + } + + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_BADPLACE, THINKLEVEL_IDLE); + } + } + + if (m_State == ACTOR_STATE_COVER_HIDE || m_State == ACTOR_STATE_COVER_FIND_ENEMY + || m_State == ACTOR_STATE_COVER_TARGET || m_State == ACTOR_STATE_COVER_SHOOT) { + PostThink(false); + } else { + PostThink(true); + } +} + +void Actor::FinishedAnimation_Cover(void) +{ + if (m_State == ACTOR_STATE_COVER_SHOOT) { + if (m_Enemy && !m_Enemy->IsDead() && CanSeeEnemy(500) && CanShootEnemy(500)) { + TransitionState(ACTOR_STATE_COVER_SHOOT, 0); + } else { + TransitionState(ACTOR_STATE_COVER_FIND_COVER, 0); + } + } else if (m_State == ACTOR_STATE_COVER_GRENADE || m_State == ACTOR_STATE_COVER_LOOP) { + TransitionState(ACTOR_STATE_COVER_FIND_COVER, 0); + } +} + +void Actor::PathnodeClaimRevoked_Cover(void) +{ + TransitionState(ACTOR_STATE_COVER_FIND_COVER, 0); +} diff --git a/code/fgame/actor_curious.cpp b/code/fgame/actor_curious.cpp index e948230d..19e51e5d 100644 --- a/code/fgame/actor_curious.cpp +++ b/code/fgame/actor_curious.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,485 +24,254 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitCurious - ( - GlobalFuncs_t *func - ) +void Actor::InitCurious(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Curious; - func->BeginState = &Actor::Begin_Curious; - func->EndState = &Actor::End_Curious; - func->ResumeState = &Actor::Resume_Curious; - func->SuspendState = &Actor::Suspend_Curious; - func->FinishedAnimation = &Actor::FinishedAnimation_Cover; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; - func->IsState = &Actor::IsCuriousState; + func->ThinkState = &Actor::Think_Curious; + func->BeginState = &Actor::Begin_Curious; + func->EndState = &Actor::End_Curious; + func->ResumeState = &Actor::Resume_Curious; + func->SuspendState = &Actor::Suspend_Curious; + func->FinishedAnimation = &Actor::FinishedAnimation_Curious; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; + func->IsState = &Actor::IsCuriousState; } -void Actor::Begin_Curious - ( - void - ) +void Actor::SetCuriousAnimHint(int iAnimHint) { - Vector vDelta; - //float fDistSquared; - - DoForceActivate(); - m_csMood = STRING_CURIOUS; - Anim_Emotion(EMOTION_CURIOUS); - - if (level.inttime > level.m_iCuriousVoiceTime + 3000) - { - if (m_iCuriousAnimHint == 5) - { - Anim_Say( - STRING_ANIM_SAY_CURIOUS_SOUND_SCR, - 8000, - false); - level.m_iCuriousVoiceTime = level.inttime; - } - else if (m_iCuriousAnimHint == 6) - { - Anim_Say( - STRING_ANIM_SAY_CURIOUS_SIGHT_SCR, - 8000, - false); - level.m_iCuriousVoiceTime = level.inttime; - } - } - - m_iCuriousTime = level.inttime; - - SetLeashHome(origin); - if (m_bScriptGoalValid) - { - SetPath( - m_vScriptGoal, - "", - 0, - NULL, - 0.0); - ShortenPathToAvoidSquadMates(); - if (!PathExists()) - { - m_bScriptGoalValid = false; - } - } - TransitionState(1100, 0); - - if (!m_bScriptGoalValid) - { - //check if last enemy pos is within leash area (distance to m_vHome is <= m_fLeash) - vDelta = m_vLastEnemyPos - m_vHome; - if (vDelta.lengthSquared() <= m_fLeashSquared) - { - //it's within leash area, go check it. - SetPath(m_vLastEnemyPos, NULL, 0, NULL, 0.0); - } - else - { - //it's NOT within leash area, - - //am I within leash area ? - if ((origin - m_vHome).lengthSquared() <= m_fLeashSquared) - { - //I'm inside leash area, - //Try to go towards enemy as much as possible without leaving leash area. - //vDest = vHome + U * leash - //U = unit vector of vDelta. - SetPath(vDelta * sqrt(m_fLeashSquared / vDelta.lengthSquared()) + m_vHome, NULL, 0, NULL, 0.0); - } - else - { - //I'm outside leash area, - //go to enemy, it doesn't matter. - SetPath(m_vLastEnemyPos, NULL, 0, NULL, 0.0); - } - } - - ShortenPathToAvoidSquadMates(); - if (m_iCuriousAnimHint <= 3) - { - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_STANDFLINCH_SCR; - - m_bNextForceStart = true; - m_bLockThinkState = true; - TransitionState(1101, 0); - } - else if(m_Enemy && m_PotentialEnemies.GetCurrentVisibility() < 0.1) - { - vec2_t vDel; - VectorSub2D(m_vLastEnemyPos, origin, vDel); - if (vDel[0] != 0 || vDel[1] != 0) - { - SetDesiredYawDir(vDel); - } - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_SURPRISE_SCR; - - m_bNextForceStart = true; - m_bLockThinkState = true; - TransitionState(1101, 0); - } - } - - m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF); + m_iCuriousAnimHint = iAnimHint; } - -void Actor::End_Curious - ( - void - ) +void Actor::Begin_Curious(void) { - m_iCuriousTime = 0; - m_iCuriousLevel = 0; + float fDistSquared; + Vector vDelta; + + DoForceActivate(); + m_csMood = STRING_CURIOUS; + Anim_Emotion(EMOTION_CURIOUS); + + if (level.inttime > level.m_iCuriousVoiceTime + 3000) { + if (m_iCuriousAnimHint == 5) { + Anim_Say(STRING_ANIM_SAY_CURIOUS_SOUND_SCR, 8000, false); + level.m_iCuriousVoiceTime = level.inttime; + } else if (m_iCuriousAnimHint == 6) { + Anim_Say(STRING_ANIM_SAY_CURIOUS_SIGHT_SCR, 8000, false); + level.m_iCuriousVoiceTime = level.inttime; + } + } + + m_iCuriousTime = level.inttime; + + SetLeashHome(origin); + if (m_bScriptGoalValid) { + SetPath(m_vScriptGoal, NULL, 0, NULL, 0.0); + ShortenPathToAvoidSquadMates(); + if (!PathExists()) { + m_bScriptGoalValid = false; + } + } + TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0); + + if (!m_bScriptGoalValid) { + //check if last enemy pos is within leash area (distance to m_vHome is <= m_fLeash) + vDelta = m_vLastEnemyPos - m_vHome; + fDistSquared = vDelta.lengthSquared(); + + if (fDistSquared > m_fLeashSquared && (origin - m_vHome).lengthSquared() <= m_fLeashSquared) { + //I'm inside leash area, + //Try to go towards enemy as much as possible without leaving leash area. + //vDest = vHome + U * leash + //U = unit vector of vDelta. + SetPath(m_vHome + sqrt(m_fLeashSquared / fDistSquared) * vDelta, NULL, 0, NULL, 0); + ShortenPathToAvoidSquadMates(); + } else { + //I'm outside leash area, + //go to enemy, it doesn't matter. + SetPath(m_vLastEnemyPos, NULL, 0, NULL, 0); + ShortenPathToAvoidSquadMates(); + } + + if (m_iCuriousAnimHint <= 3 && m_iCuriousAnimHint >= 1) { + StartAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STANDFLINCH_SCR); + TransitionState(ACTOR_STATE_CURIOUS_RUNNING); + m_bLockThinkState = true; + } else if (m_Enemy && m_PotentialEnemies.GetCurrentVisibility() < 0.1) { + SetDesiredYawDest(m_vLastEnemyPos); + StartAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SURPRISE_SCR); + TransitionState(ACTOR_STATE_CURIOUS_RUNNING); + m_bLockThinkState = true; + } + } + + m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF); } -void Actor::Resume_Curious - ( - void - ) +void Actor::End_Curious(void) { - Begin_Curious(); + m_iCuriousTime = 0; + m_iCuriousLevel = 0; } -void Actor::Suspend_Curious - ( - void - ) +void Actor::Resume_Curious(void) { - End_Curious(); + Begin_Curious(); } -void Actor::Think_Curious - ( - void - ) +void Actor::Suspend_Curious(void) { - //horrible function! - if (RequireThink()) - { - UpdateEyeOrigin(); - NoPoint(); - UpdateEnemy(100); - - if(m_State == 1101) - { - ContinueAnimation(); - //LABEL_16: - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 1\n"); - PostThink(true); - return; - } - - m_bLockThinkState = false; - - if (!PathExists() || PathComplete()) - { - //v1 = &this->baseSimpleActor.baseSentient.m_Enemy; - //goto LABEL_6; - - ClearPath(); - Anim_Stand(); - LookAtCuriosity(); - - if (!m_Enemy || EnemyIsDisguised()) - { - if (level.inttime > m_iCuriousTime + 500) - { - glbs.Printf("Think_Curious m_Enemy: %s EnemyIsDisguised: %s\n", m_Enemy ? "true": "false", EnemyIsDisguised() ? "true" : "false"); - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - m_iCuriousTime = 0; - } - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 2\n"); - PostThink(true); - return; - } - - if (!m_Enemy || CanSeeEnemy(100)) - { - ClearPath(); - Anim_Stand(); - LookAtCuriosity(); - if (!m_Enemy || EnemyIsDisguised()) - { - if (level.inttime > m_iCuriousTime + 500) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - m_iCuriousTime = 0; - } - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 3\n"); - PostThink(true); - return; - } - else - { - if (m_iCuriousLevel <= 5) - { - if (!InFOV(m_vLastEnemyPos, m_fFov, m_fFovDot)) - { - - if ((m_bScriptGoalValid || CanMovePathWithLeash()) - && MoveOnPathWithSquad()) - { - if (PatrolNextNodeExists()) - { - m_eNextAnimMode = 2; - } - else - { - //v11 = SimpleActor::GetRunAnim(this); - m_eNextAnimMode = 3; - } - m_csNextAnimString = GetRunAnim(); - m_bNextForceStart = false; - - FaceMotion(); - } - else - { - Anim_Stand(); - } - - if (level.inttime >= m_iNextWatchStepTime - && velocity.lengthSquared() >= 4.0) - { - SetDesiredLookDir(velocity); - - m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500; - } - else - { - LookAtCuriosity(); - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 4\n"); - PostThink(true); - return; - } - else - { - - Vector vEnd = EyePosition() - m_vLastEnemyPos; - VectorNormalizeFast(vEnd); - - vEnd += m_vLastEnemyPos; - if (!G_SightTrace(EyePosition(), vec_zero, vec_zero, vEnd, this, NULL, 33819417, qfalse, "Actor::Think_Curious")) - { - if ((m_bScriptGoalValid || CanMovePathWithLeash()) - && MoveOnPathWithSquad()) - { - if (PatrolNextNodeExists()) - { - m_eNextAnimMode = 2; - } - else - { - //v11 = SimpleActor::GetRunAnim(this); - m_eNextAnimMode = 3; - } - m_csNextAnimString = GetRunAnim(); - m_bNextForceStart = false; - - FaceMotion(); - } - else - { - Anim_Stand(); - } - - if (level.inttime >= m_iNextWatchStepTime - && velocity.lengthSquared() >= 4.0) - { - SetDesiredLookDir(velocity); - - m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500; - } - else - { - LookAtCuriosity(); - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 5\n"); - PostThink(true); - return; - } - else - { - - ClearPath(); - Anim_Stand(); - LookAtCuriosity(); - if (!m_Enemy || EnemyIsDisguised()) - { - if (level.inttime > m_iCuriousTime + 500) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - m_iCuriousTime = 0; - } - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 6\n"); - PostThink(true); - return; - } - } - } - else - { - if ((PathGoal()-origin).lengthSquared() >= 2304) - { - if ((m_bScriptGoalValid || CanMovePathWithLeash()) - && MoveOnPathWithSquad()) - { - if (PatrolNextNodeExists()) - { - m_eNextAnimMode = 2; - } - else - { - //v11 = SimpleActor::GetRunAnim(this); - m_eNextAnimMode = 3; - } - m_csNextAnimString = GetRunAnim(); - m_bNextForceStart = false; - - FaceMotion(); - } - else - { - Anim_Stand(); - } - - if (level.inttime >= m_iNextWatchStepTime - && velocity.lengthSquared() >= 4.0) - { - SetDesiredLookDir(velocity); - - m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500; - } - else - { - LookAtCuriosity(); - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 7\n"); - PostThink(true); - return; - } - } - ClearPath(); - Anim_Stand(); - LookAtCuriosity(); - if (!m_Enemy || EnemyIsDisguised()) - { - if (level.inttime > m_iCuriousTime + 500) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - m_iCuriousTime = 0; - } - } - CheckForThinkStateTransition(); - glbs.Printf("Think_Curious CheckForThinkStateTransition 8\n"); - PostThink(true); - return; - } - } + End_Curious(); } -void Actor::FinishedAnimation_Curious - ( - void - ) +void Actor::Think_Curious(void) { - FinishedAnimation_AnimCurious(); + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + NoPoint(); + UpdateEnemy(100); + + if (m_State == ACTOR_STATE_CURIOUS_RUNNING) { + ContinueAnimation(); + CheckForThinkStateTransition(); + PostThink(true); + return; + } + + m_bLockThinkState = false; + + if (!PathExists() || PathComplete()) { + ClearPath(); + Anim_Stand(); + LookAtCuriosity(); + TimeOutCurious(); + + CheckForThinkStateTransition(); + PostThink(true); + return; + } + + if (m_Enemy && CanSeeEnemy(100)) { + ClearPath(); + Anim_Stand(); + LookAtCuriosity(); + TimeOutCurious(); + + CheckForThinkStateTransition(); + PostThink(true); + return; + } + + if (m_iCuriousLevel <= 5) { + if (InFOV(m_vLastEnemyPos, m_fFov, m_fFovDot)) { + Vector vEnd; + + vEnd = EyePosition() - m_vLastEnemyPos; + vEnd.normalizefast(); + vEnd += m_vLastEnemyPos; + + if (G_SightTrace( + EyePosition(), vec_zero, vec_zero, vEnd, this, NULL, MASK_CANSEE, qfalse, "Actor::Think_Curious" + )) { + ClearPath(); + Anim_Stand(); + LookAtCuriosity(); + TimeOutCurious(); + + CheckForThinkStateTransition(); + PostThink(true); + return; + } + } + } else if ((PathGoal() - origin).lengthSquared() < Square(48)) { + ClearPath(); + Anim_Stand(); + LookAtCuriosity(); + TimeOutCurious(); + + CheckForThinkStateTransition(); + PostThink(true); + return; + } + + if ((m_bScriptGoalValid || CanMovePathWithLeash()) && MoveOnPathWithSquad()) { + if (PatrolNextNodeExists()) { + DesiredAnimation(ANIM_MODE_PATH, GetRunAnim()); + } else { + DesiredAnimation(ANIM_MODE_PATH_GOAL, GetRunAnim()); + } + + FaceMotion(); + } else { + Anim_Stand(); + } + + if (level.inttime >= m_iNextWatchStepTime && velocity.lengthSquared() >= Square(2)) { + SetDesiredLookDir(velocity); + m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500; + } else { + LookAtCuriosity(); + } + + CheckForThinkStateTransition(); + PostThink(true); } - -void Actor::LookAtCuriosity - ( - void - ) +void Actor::LookAtCuriosity(void) { - Vector vAngles; - float fLookScale; - unsigned int iSeed; - if (m_Enemy && EnemyIsDisguised()) - { - SetDesiredLookDir(m_Enemy->origin - origin); - fLookScale = 0.25; - } - else - { - vAngles = m_vLastEnemyPos - origin; - if (vAngles.x < 15.0 && vAngles.x > -15.0 && vAngles.y < 15.0 && vAngles.y > -15.0) - { - SetDesiredLookAnglesRelative(vec_zero); - } - else - { - SetDesiredLookDir(vAngles); - if (velocity.x == 0.0 - && velocity.y == 0.0) - { - SetDesiredYawDir(vAngles); - } - else - { - FaceMotion(); - } - } - fLookScale = 1; - } - - //FIXME: wth is this ! @_@ - iSeed = 1664525 * (-783751945 * ((level.inttime - m_iCuriousTime) & 0xFFFFFF00) + m_iCuriousTime); + unsigned int iSeed; + float fLookScale; + vec3_t vAngles; - vAngles.x = fLookScale * ((1664525 * (iSeed + 1013904223) + 1013904223) * 0.000000013969839) + m_DesiredLookAngles[0]; - vAngles.y = (iSeed + 1013904223) * 0.000000027939677 * fLookScale + m_DesiredLookAngles[1]; - vAngles.z = m_DesiredLookAngles[2]; + if (m_Enemy && !EnemyIsDisguised()) { + SetDesiredLookDir(m_Enemy->origin - origin); + fLookScale = 0.25; + } else { + Vector v; - if (vAngles.x >= -90.0) - { - if (vAngles.x > 90.0) - vAngles.x = 90.0; - } - else - { - vAngles.x = -90.0; - } + v = m_vLastEnemyPos - origin; + if (v[0] < 15 && v[0] > -15 && v[1] < 15 && v[1] > -15) { + SetDesiredLookAnglesRelative(vec_zero); + } else { + SetDesiredLookDir(v); + if (velocity.x || velocity.y) { + FaceMotion(); + } else { + SetDesiredYawDir(v); + } + } + fLookScale = 1; + } - SetDesiredLookAnglesRelative(vAngles); + iSeed = 0x19660D * (m_iCuriousTime - 0x2EB71B09 * ((level.inttime - m_iCuriousTime) & 0xFFFFFF00)) + 0x3C6EF35F; + vAngles[0] = m_DesiredLookAngles[0] + (float)iSeed / (float)0x4444444 * fLookScale; + vAngles[1] = m_DesiredLookAngles[1] + (float)iSeed / (float)0x2222222 * fLookScale; + vAngles[2] = m_DesiredLookAngles[2]; + // clamp + vAngles[0] = Q_clamp_float(vAngles[0], -90, 90); + + SetDesiredLookAnglesRelative(vAngles); } -void Actor::TimeOutCurious - ( - void - ) +void Actor::TimeOutCurious(void) { - //FIXME: macros - if (!m_Enemy || EnemyIsDisguised()) - { - if (level.inttime > m_iCuriousTime + 500) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - m_iCuriousTime = 0; - } - } + if (m_Enemy && !EnemyIsDisguised()) { + return; + } + + if (level.inttime <= m_iCuriousTime + 500) { + return; + } + + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + m_iCuriousTime = 0; } -void Actor::SetCuriousAnimHint - ( - int iAnimHint - ) +void Actor::FinishedAnimation_Curious(void) { - m_iCuriousAnimHint = iAnimHint; + if (m_State == ACTOR_STATE_CURIOUS_RUNNING) { + TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0); + } } diff --git a/code/fgame/actor_disguise_common.cpp b/code/fgame/actor_disguise_common.cpp index 636d7d82..dec23b79 100644 --- a/code/fgame/actor_disguise_common.cpp +++ b/code/fgame/actor_disguise_common.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,174 +24,115 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" - -void Actor::InitDisguiseNone - ( - GlobalFuncs_t *func - ) +void Actor::InitDisguiseNone(GlobalFuncs_t *func) { - func->IsState = &Actor::IsDisguiseState; + func->IsState = &Actor::IsDisguiseState; } -void Actor::State_Disguise_Wait - ( - void - ) +void Actor::State_Disguise_Wait(void) { - vec2_t vDelta; - float fDistSquared; - VectorSub2D(origin, m_Enemy->origin, vDelta); + float fDistSquared; + vec2_t vDelta; - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_WAIT_SCR; - m_bNextForceStart = false; + VectorSub2D(origin, m_Enemy->origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); - fDistSquared = VectorLength2DSquared(vDelta); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_WAIT_SCR); - if (m_fMaxDisguiseDistSquared > fDistSquared * 4) - { - TransitionState(1, 0); - } - else - { - if (level.inttime > m_iStateTime + 3000) - { - if (fDistSquared <= 65536) - { - TransitionState(1, 0); - } - else - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } - } - } + if (fDistSquared * 4 < m_fMaxDisguiseDistSquared) { + TransitionState(ACTOR_STATE_DISGUISE_PAPERS); + return; + } + + if (level.inttime <= m_iStateTime + 3000) { + return; + } + + if (fDistSquared > Square(256)) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } else { + TransitionState(ACTOR_STATE_DISGUISE_PAPERS); + } } -void Actor::State_Disguise_Papers - ( - void - ) +void Actor::State_Disguise_Papers(void) { - vec2_t vDelta; + vec2_t vDelta; - m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR; - m_eNextAnimMode = 1; - m_bNextForceStart = false; - if (m_iEnemyShowPapersTime < m_Enemy->m_ShowPapersTime) - { - if (level.m_iPapersLevel < m_iDisguiseLevel) - { - m_State = 5; - } - else - { - if (m_DisguiseAcceptThread.IsSet()) - m_DisguiseAcceptThread.Execute(this); - TransitionState(2, 0); - } - } - else - { - if (level.inttime > m_iStateTime + 12000) - { - TransitionState(3, 0); - } - else - { - VectorSub2D(origin, m_Enemy->origin, vDelta); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR); - if (VectorLength2DSquared(vDelta) > 65536) - { - TransitionState(4, 0); - } - } - } + if (m_iEnemyShowPapersTime >= m_Enemy->m_ShowPapersTime) { + if (level.inttime > m_iStateTime + 12000) { + TransitionState(ACTOR_STATE_DISGUISE_ENEMY); + } else { + VectorSub2D(origin, m_Enemy->origin, vDelta); + + if (VectorLength2DSquared(vDelta) > Square(256)) { + TransitionState(ACTOR_STATE_DISGUISE_HALT, 0); + } + } + } else if (level.m_iPapersLevel < m_iDisguiseLevel) { + TransitionState(ACTOR_STATE_DISGUISE_DENY); + } else { + if (m_DisguiseAcceptThread.IsSet()) { + m_DisguiseAcceptThread.Execute(this); + } + + TransitionState(ACTOR_STATE_DISGUISE_ACCEPT); + } } -void Actor::State_Disguise_Fake_Papers - ( - void - ) +void Actor::State_Disguise_Fake_Papers(void) { - vec2_t vDelta; + vec2_t vDelta; - m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR; - m_eNextAnimMode = 1; - m_bNextForceStart = false; - if (m_iEnemyShowPapersTime < m_Enemy->m_ShowPapersTime || level.inttime > m_iStateTime + 12000) - { - TransitionState(3, 0); - } - else - { - VectorSub2D(origin, m_Enemy->origin, vDelta); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR); - if (VectorLength2DSquared(vDelta) > 65536) - { - TransitionState(4, 0); - } - } + if (m_iEnemyShowPapersTime < m_Enemy->m_ShowPapersTime || level.inttime > m_iStateTime + 12000) { + TransitionState(ACTOR_STATE_DISGUISE_ENEMY); + return; + } + VectorSub2D(origin, m_Enemy->origin, vDelta); + + if (VectorLength2DSquared(vDelta) > Square(256)) { + TransitionState(ACTOR_STATE_DISGUISE_HALT, 0); + } } -void Actor::State_Disguise_Enemy - ( - void - ) +void Actor::State_Disguise_Enemy(void) { - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_ENEMY_SCR; - m_bNextForceStart = false; + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_ENEMY_SCR); - if (level.inttime > m_iStateTime + 3000 && !m_Enemy->IsSubclassOfActor()) - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } + if (level.inttime > m_iStateTime + 3000 && !(m_Enemy->flags & FL_NOTARGET)) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } } -void Actor::State_Disguise_Halt - ( - void - ) +void Actor::State_Disguise_Halt(void) { - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_HALT_SCR; - m_bNextForceStart = false; + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_HALT_SCR); - if (level.inttime > m_iStateTime + 1500 && !m_Enemy->IsSubclassOfActor()) - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } + if (level.inttime > m_iStateTime + 1500 && !(m_Enemy->flags & FL_NOTARGET)) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } } -void Actor::State_Disguise_Accept - ( - void - ) +void Actor::State_Disguise_Accept(void) { - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_ACCEPT_SCR; - m_bNextForceStart = false; + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_ACCEPT_SCR); - if (level.inttime > m_iStateTime + 3000 ) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE); - } + if (level.inttime > m_iStateTime + 3000) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE); + } } -void Actor::State_Disguise_Deny - ( - void - ) +void Actor::State_Disguise_Deny(void) { - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_DENY_SCR; - m_bNextForceStart = false; + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_DENY_SCR); - if (level.inttime > m_iStateTime + 3000) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } + if (level.inttime > m_iStateTime + 3000) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } } diff --git a/code/fgame/actor_disguise_officer.cpp b/code/fgame/actor_disguise_officer.cpp new file mode 100644 index 00000000..8293312f --- /dev/null +++ b/code/fgame/actor_disguise_officer.cpp @@ -0,0 +1,135 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// actor_disguise_officier.cpp + +#include "actor.h" + +void Actor::InitDisguiseOfficer(GlobalFuncs_t *func) +{ + func->ThinkState = &Actor::Think_DisguiseOfficer; + func->BeginState = &Actor::Begin_DisguiseOfficer; + func->EndState = &Actor::End_DisguiseOfficer; + func->ResumeState = &Actor::Resume_DisguiseOfficer; + func->SuspendState = &Actor::Suspend_DisguiseOfficer; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; + func->IsState = &Actor::IsDisguiseState; +} + +void Actor::Begin_DisguiseOfficer(void) +{ + m_csMood = STRING_BORED; + assert(m_Enemy); + + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } + + if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR); + m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; + + TransitionState(ACTOR_STATE_DISGUISE_PAPERS); + } else { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } +} + +void Actor::End_DisguiseOfficer(void) +{ + m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500); +} + +void Actor::Resume_DisguiseOfficer(void) +{ + Begin_DisguiseOfficer(); +} + +void Actor::Suspend_DisguiseOfficer(void) +{ + End_DisguiseOfficer(); +} + +void Actor::Think_DisguiseOfficer(void) +{ + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + NoPoint(); + ContinueAnimation(); + UpdateEnemy(1500); + + assert(m_Enemy); + + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } + + if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET) && m_State != ACTOR_STATE_DISGUISE_ENEMY) { + TransitionState(ACTOR_STATE_DISGUISE_ENEMY, 0); + } + + if (level.m_bAlarm == qtrue) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + return; + } + + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + + switch (m_State) { + case ACTOR_STATE_DISGUISE_ENEMY: + m_pszDebugState = "enemy"; + State_Disguise_Enemy(); + break; + case ACTOR_STATE_DISGUISE_HALT: + m_pszDebugState = "halt"; + State_Disguise_Halt(); + break; + case ACTOR_STATE_DISGUISE_PAPERS: + m_pszDebugState = "papers"; + State_Disguise_Fake_Papers(); + break; + default: + { + Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State); + char assertStr[16317] = {0}; + Q_strncpyz(assertStr, "\"invalid think state\"\n\tMessage: ", sizeof(assertStr)); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); + assert(!assertStr); + } + break; + } + + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE); + } + + PostThink(true); +} diff --git a/code/fgame/actor_disguise_officier.cpp b/code/fgame/actor_disguise_officier.cpp deleted file mode 100644 index 2508b20b..00000000 --- a/code/fgame/actor_disguise_officier.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2015 the OpenMoHAA team - -This file is part of OpenMoHAA source code. - -OpenMoHAA source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -OpenMoHAA source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with OpenMoHAA source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -// actor_disguise_officier.cpp - -#include "actor.h" - - -void Actor::InitDisguiseOfficer - ( - GlobalFuncs_t *func - ) -{ - func->ThinkState = &Actor::Think_DisguiseOfficer; - func->BeginState = &Actor::Begin_DisguiseOfficer; - func->EndState = &Actor::End_DisguiseOfficer; - func->ResumeState = &Actor::Resume_DisguiseOfficer; - func->SuspendState = &Actor::Suspend_DisguiseOfficer; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; - func->IsState = &Actor::IsDisguiseState; -} - -void Actor::Begin_DisguiseOfficer - ( - void - ) -{ - vec2_t vDelta; - m_csMood = STRING_BORED; - assert(m_Enemy); - - if (m_Enemy) - { - if ( (EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm) - { - VectorSub2D(m_Enemy->origin, origin, vDelta); - - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } - - SetDesiredLookDir(m_Enemy->origin - origin); - - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR; - m_bNextForceStart = false; - - - m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; - TransitionState(1, 0); - } - else - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - } - else - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } -} - -void Actor::End_DisguiseOfficer - ( - void - ) -{ - m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500); -} - -void Actor::Resume_DisguiseOfficer - ( - void - ) -{ - Begin_DisguiseOfficer(); -} - -void Actor::Suspend_DisguiseOfficer - ( - void - ) -{ - End_DisguiseOfficer(); -} - -void Actor::Think_DisguiseOfficer - ( - void - ) -{ - if (RequireThink()) - { - UpdateEyeOrigin(); - NoPoint(); - ContinueAnimation(); - UpdateEnemy(1500); - assert(m_Enemy); - - if (!m_Enemy) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - return; - } - if (!EnemyIsDisguised() && !(m_Enemy->IsSubclassOfActor()) && m_State != 3) - { - TransitionState(3, 0); - } - if (level.m_bAlarm) - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - return; - } - vec2_t vDelta; - - VectorSub2D(m_Enemy->origin, origin, vDelta); - - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } - - SetDesiredLookDir(m_Enemy->origin - origin); - - if (m_State == 3) - { - m_pszDebugState = "enemy"; - State_Disguise_Enemy(); - } - else if (m_State > 3) - { - if (m_State != 4) - { - Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State); - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"invalid think state\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); - assert(!assertStr); - } - else - { - m_pszDebugState = "halt"; - Actor::State_Disguise_Halt(); - } - } - else - { - if (m_State == 1) - { - m_pszDebugState = "papers"; - State_Disguise_Fake_Papers(); - } - else - { - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"invalid think state\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); - assert(!assertStr); - } - } - CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL); - PostThink(true); - } -} diff --git a/code/fgame/actor_disguise_rover.cpp b/code/fgame/actor_disguise_rover.cpp index 1fe5aec8..d8773f24 100644 --- a/code/fgame/actor_disguise_rover.cpp +++ b/code/fgame/actor_disguise_rover.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,163 +24,116 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitDisguiseRover - ( - GlobalFuncs_t *func - ) +void Actor::InitDisguiseRover(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_DisguiseRover; - func->BeginState = &Actor::Begin_DisguiseRover; - func->EndState = &Actor::End_DisguiseRover; - func->ResumeState = &Actor::Resume_DisguiseRover; - func->SuspendState = &Actor::Suspend_DisguiseRover; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; - func->IsState = &Actor::IsDisguiseState; + func->ThinkState = &Actor::Think_DisguiseRover; + func->BeginState = &Actor::Begin_DisguiseRover; + func->EndState = &Actor::End_DisguiseRover; + func->ResumeState = &Actor::Resume_DisguiseRover; + func->SuspendState = &Actor::Suspend_DisguiseRover; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; + func->IsState = &Actor::IsDisguiseState; } -void Actor::Begin_DisguiseRover - ( - void - ) +void Actor::Begin_DisguiseRover(void) { + m_csMood = STRING_BORED; + assert(m_Enemy); - vec2_t vDelta; - m_csMood = STRING_BORED; - assert(m_Enemy); + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } - if (m_Enemy) - { - if ((EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm) - { - VectorSub2D(m_Enemy->origin, origin, vDelta); + if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR); + m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; - SetDesiredLookDir(m_Enemy->origin - origin); - - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR; - m_bNextForceStart = false; - - m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; - TransitionState(1, 0); - } - else - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - } - else - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } + TransitionState(ACTOR_STATE_DISGUISE_PAPERS); + } else { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } } -void Actor::End_DisguiseRover - ( - void - ) +void Actor::End_DisguiseRover(void) { - m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500); + m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500); } -void Actor::Resume_DisguiseRover - ( - void - ) +void Actor::Resume_DisguiseRover(void) { - Begin_DisguiseRover(); + Begin_DisguiseRover(); } -void Actor::Suspend_DisguiseRover - ( - void - ) +void Actor::Suspend_DisguiseRover(void) { - End_DisguiseRover(); + End_DisguiseRover(); } -void Actor::Think_DisguiseRover - ( - void - ) +void Actor::Think_DisguiseRover(void) { - if (!RequireThink()) - { - return; - } - UpdateEyeOrigin(); - NoPoint(); - ContinueAnimation(); - UpdateEnemy(1500); + if (!RequireThink()) { + return; + } - assert(m_Enemy != NULL); + UpdateEyeOrigin(); + NoPoint(); + ContinueAnimation(); + UpdateEnemy(1500); - if (!m_Enemy) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - return; - } + assert(m_Enemy); - if (!EnemyIsDisguised() && !m_Enemy->IsSubclassOfActor() && m_State != 3) - { - TransitionState(3, 0); - } + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } - if (level.m_bAlarm) - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - return; - } - - { - vec2_t facedir; - facedir[0] = m_Enemy->origin[0] - origin[0]; - facedir[1] = m_Enemy->origin[1] - origin[1]; - if (facedir[0] != 0 || facedir[1] != 0) - { - SetDesiredYawDir(facedir); - } + if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET) && m_State != ACTOR_STATE_DISGUISE_ENEMY) { + TransitionState(ACTOR_STATE_DISGUISE_ENEMY, 0); + } - } - - SetDesiredLookDir(m_Enemy->origin - origin); + if (level.m_bAlarm == qtrue) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + return; + } - if (m_State == 2) - { - m_pszDebugState = "accept"; - State_Disguise_Accept(); - } - else if(m_State > 2) - { - if (m_State == 3) - { - m_pszDebugState = "enemy"; - State_Disguise_Enemy(); - } - else if (m_State == 4) - { - m_pszDebugState = "halt"; - State_Disguise_Halt(); - } - else - { - assert(!"invalid think state"); - } - } - else if (m_State == 1) - { - m_pszDebugState = "papers"; - State_Disguise_Papers(); - } - else - { - assert(!"invalid think state"); - } + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); - CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL); - PostThink(true); + switch (m_State) { + case ACTOR_STATE_DISGUISE_ACCEPT: + m_pszDebugState = "accept"; + State_Disguise_Accept(); + break; + case ACTOR_STATE_DISGUISE_ENEMY: + m_pszDebugState = "enemy"; + State_Disguise_Enemy(); + break; + case ACTOR_STATE_DISGUISE_HALT: + m_pszDebugState = "halt"; + State_Disguise_Halt(); + break; + case ACTOR_STATE_DISGUISE_PAPERS: + m_pszDebugState = "papers"; + State_Disguise_Fake_Papers(); + break; + default: + { + Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State); + char assertStr[16317] = {0}; + Q_strncpyz(assertStr, "\"invalid think state\"\n\tMessage: ", sizeof(assertStr)); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); + assert(!assertStr); + } + break; + } + + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE); + } + + PostThink(true); } diff --git a/code/fgame/actor_disguise_salute.cpp b/code/fgame/actor_disguise_salute.cpp index 0a23e89f..75aa6041 100644 --- a/code/fgame/actor_disguise_salute.cpp +++ b/code/fgame/actor_disguise_salute.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,133 +24,85 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitDisguiseSalute - ( - GlobalFuncs_t *func - ) +void Actor::InitDisguiseSalute(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_DisguiseSalute; - func->BeginState = &Actor::Begin_DisguiseSalute; - func->EndState = &Actor::End_DisguiseSalute; - func->ResumeState = &Actor::Resume_DisguiseSalute; - func->SuspendState = &Actor::Suspend_DisguiseSalute; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; - func->IsState = &Actor::IsDisguiseState; + func->ThinkState = &Actor::Think_DisguiseSalute; + func->BeginState = &Actor::Begin_DisguiseSalute; + func->EndState = &Actor::End_DisguiseSalute; + func->ResumeState = &Actor::Resume_DisguiseSalute; + func->SuspendState = &Actor::Suspend_DisguiseSalute; + func->FinishedAnimation = &Actor::FinishedAnimation_DisguiseSalute; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; + func->IsState = &Actor::IsDisguiseState; } -void Actor::Begin_DisguiseSalute - ( - void - ) +void Actor::Begin_DisguiseSalute(void) { - vec2_t vDelta; - - Com_Printf("Saluting guy....\n"); - - m_csMood = STRING_BORED; - assert(m_Enemy); + Com_Printf("Saluting guy....\n"); + m_csMood = STRING_BORED; + assert(m_Enemy); - if (m_Enemy) - { - if ((EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm) - { - VectorSub2D(m_Enemy->origin, origin, vDelta); + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } + if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); - SetDesiredLookDir(m_Enemy->origin - origin); - - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_SALUTE_SCR; - m_bNextForceStart = false; - - - m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; - TransitionState(1, 0); - } - else - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - } - else - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_SALUTE_SCR); + } else { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } } -void Actor::End_DisguiseSalute - ( - void - ) +void Actor::End_DisguiseSalute(void) { - m_iNextDisguiseTime = level.inttime + m_iDisguisePeriod; + m_iNextDisguiseTime = level.inttime + m_iDisguisePeriod; } -void Actor::Resume_DisguiseSalute - ( - void - ) +void Actor::Resume_DisguiseSalute(void) { - Begin_DisguiseSalute(); + Begin_DisguiseSalute(); } -void Actor::Suspend_DisguiseSalute - ( - void - ) +void Actor::Suspend_DisguiseSalute(void) { - End_DisguiseSalute(); + End_DisguiseSalute(); } -void Actor::Think_DisguiseSalute - ( - void - ) +void Actor::Think_DisguiseSalute(void) { - NoPoint(); - ContinueAnimation(); - UpdateEnemy(2000); + NoPoint(); + ContinueAnimation(); + UpdateEnemy(2000); - assert(m_Enemy != NULL); + assert(m_Enemy != NULL); - if (m_Enemy) - { - if (!EnemyIsDisguised() && !m_Enemy->IsSubclassOfActor() && level.m_bAlarm) - { - { - vec2_t facedir; - facedir[0] = m_Enemy->origin[0] - origin[0]; - facedir[1] = m_Enemy->origin[1] - origin[1]; - if (facedir[0] != 0 || facedir[1] != 0) - { - SetDesiredYawDir(facedir); - } + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } - } - SetDesiredLookDir(m_Enemy->origin - origin); + if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET)) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + return; + } - PostThink(true); - } - else - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - } - else - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } + if (level.m_bAlarm == qtrue) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + return; + } + + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + + PostThink(true); } -void Actor::FinishedAnimation_DisguiseSalute - ( - void - ) +void Actor::FinishedAnimation_DisguiseSalute(void) { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); } diff --git a/code/fgame/actor_disguise_sentry.cpp b/code/fgame/actor_disguise_sentry.cpp index e833e1b5..345e18c2 100644 --- a/code/fgame/actor_disguise_sentry.cpp +++ b/code/fgame/actor_disguise_sentry.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,164 +24,118 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitDisguiseSentry - ( - GlobalFuncs_t *func - ) +void Actor::InitDisguiseSentry(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_DisguiseSentry; - func->BeginState = &Actor::Begin_DisguiseSentry; - func->EndState = &Actor::End_DisguiseSentry; - func->ResumeState = &Actor::Resume_DisguiseSentry; - func->SuspendState = &Actor::Suspend_DisguiseSentry; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; - func->IsState = &Actor::IsDisguiseState; + func->ThinkState = &Actor::Think_DisguiseSentry; + func->BeginState = &Actor::Begin_DisguiseSentry; + func->EndState = &Actor::End_DisguiseSentry; + func->ResumeState = &Actor::Resume_DisguiseSentry; + func->SuspendState = &Actor::Suspend_DisguiseSentry; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise; + func->IsState = &Actor::IsDisguiseState; } -void Actor::Begin_DisguiseSentry - ( - void - ) +void Actor::Begin_DisguiseSentry(void) { - vec2_t vDelta; + m_csMood = STRING_BORED; + assert(m_Enemy); + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } - m_csMood = STRING_BORED; + if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); - assert(m_Enemy); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_WAIT_SCR); + m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; - if (m_Enemy) - { - if ((EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm) - { - VectorSub2D(m_Enemy->origin, origin, vDelta); - - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } - - SetDesiredLookDir(m_Enemy->origin - origin); - - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DISGUISE_WAIT_SCR; - m_bNextForceStart = false; - - m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime; - TransitionState(1, 0); - } - else - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - } - else - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } + TransitionState(ACTOR_STATE_DISGUISE_WAIT); + } else { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } } -void Actor::End_DisguiseSentry - ( - void - ) +void Actor::End_DisguiseSentry(void) { - m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500); + m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500); } -void Actor::Resume_DisguiseSentry - ( - void - ) +void Actor::Resume_DisguiseSentry(void) { - Begin_DisguiseSentry(); + Begin_DisguiseSentry(); } -void Actor::Suspend_DisguiseSentry - ( - void - ) +void Actor::Suspend_DisguiseSentry(void) { - End_DisguiseSentry(); + End_DisguiseSentry(); } -void Actor::Think_DisguiseSentry - ( - void - ) +void Actor::Think_DisguiseSentry(void) { - if (RequireThink()) - { - UpdateEyeOrigin(); - NoPoint(); - ContinueAnimation(); - UpdateEnemy(1500); + if (!RequireThink()) { + return; + } - assert(m_Enemy != NULL); + UpdateEyeOrigin(); + NoPoint(); + ContinueAnimation(); + UpdateEnemy(1500); - if (!m_Enemy) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - return; - } - if (!EnemyIsDisguised() && !m_Enemy->IsSubclassOfActor() && m_State != 3) - { - TransitionState(3, 0); - } + assert(m_Enemy != NULL); - if (level.m_bAlarm) - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - else - { + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } + if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET) && m_State != ACTOR_STATE_DISGUISE_ENEMY) { + TransitionState(ACTOR_STATE_DISGUISE_ENEMY, 0); + } - { - vec2_t facedir; - facedir[0] = m_Enemy->origin[0] - origin[0]; - facedir[1] = m_Enemy->origin[1] - origin[1]; - if (facedir[0] != 0 || facedir[1] != 0) - { - SetDesiredYawDir(facedir); - } + if (level.m_bAlarm) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + return; + } - } + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); - SetDesiredLookDir(m_Enemy->origin - origin); + switch (m_State) { + case ACTOR_STATE_DISGUISE_WAIT: + m_pszDebugState = "wait"; + State_Disguise_Wait(); + break; + case ACTOR_STATE_DISGUISE_PAPERS: + m_pszDebugState = "papers"; + State_Disguise_Papers(); + break; + case ACTOR_STATE_DISGUISE_ACCEPT: + m_pszDebugState = "accept"; + State_Disguise_Accept(); + break; + case ACTOR_STATE_DISGUISE_ENEMY: + m_pszDebugState = "enemy"; + State_Disguise_Enemy(); + break; + case ACTOR_STATE_DISGUISE_HALT: + m_pszDebugState = "halt"; + State_Disguise_Halt(); + break; + case ACTOR_STATE_DISGUISE_DENY: + m_pszDebugState = "deny"; + State_Disguise_Deny(); + break; + default: + Com_Printf("Actor::Think_DisguiseSentry: invalid think state %i\n", m_State); + assert(!"invalid think state"); + break; + } - switch (m_State) - { - case 0: - m_pszDebugState = "wait"; - State_Disguise_Wait(); - break; - case 1: - m_pszDebugState = "papers"; - State_Disguise_Papers(); - break; - case 2: - m_pszDebugState = "accept"; - State_Disguise_Accept(); - break; - case 3: - m_pszDebugState = "enemy"; - State_Disguise_Enemy(); - break; - case 4: - m_pszDebugState = "halt"; - State_Disguise_Halt(); - break; - case 5: - m_pszDebugState = "deny"; - State_Disguise_Deny(); - break; - default: - Com_Printf("Actor::Think_DisguiseSentry: invalid think state %i\n", m_State); - assert(!"invalid think state"); - break; - } - CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL); - PostThink(true); - } - } + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE); + } + + PostThink(true); } diff --git a/code/fgame/actor_dog.cpp b/code/fgame/actor_dog.cpp index 46dcb909..023f4297 100644 --- a/code/fgame/actor_dog.cpp +++ b/code/fgame/actor_dog.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,176 +24,125 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitDogIdle - ( - GlobalFuncs_t *func - ) +void Actor::InitDogIdle(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Dog; - func->EndState = &Actor::End_Dog; - func->ThinkState = &Actor::Think_Dog_Idle; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->IsState = &Actor::IsDogState; + func->BeginState = &Actor::Begin_Dog; + func->EndState = &Actor::End_Dog; + func->ThinkState = &Actor::Think_Dog_Idle; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->IsState = &Actor::IsDogState; } -void Actor::InitDogAttack - ( - GlobalFuncs_t *func - ) +void Actor::InitDogAttack(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Dog; - func->EndState = &Actor::End_Dog; - func->ThinkState = &Actor::Think_Dog_Attack; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; - func->IsState = &Actor::IsDogState; + func->BeginState = &Actor::Begin_Dog; + func->EndState = &Actor::End_Dog; + func->ThinkState = &Actor::Think_Dog_Attack; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->IsState = &Actor::IsDogState; } -void Actor::InitDogCurious - ( - GlobalFuncs_t *func - ) +void Actor::InitDogCurious(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Dog; - func->EndState = &Actor::End_Dog; - func->ThinkState = &Actor::Think_Dog_Curious; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; - func->IsState = &Actor::IsDogState; + func->BeginState = &Actor::Begin_Dog; + func->EndState = &Actor::End_Dog; + func->ThinkState = &Actor::Think_Dog_Curious; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious; + func->IsState = &Actor::IsDogState; } -void Actor::Begin_Dog - ( - void - ) +bool Actor::IsDogState(int state) { - m_bDog = true; + return true; } -void Actor::End_Dog - ( - void - ) +void Actor::Begin_Dog(void) { - ; + m_bIsAnimal = true; } -void Actor::Think_Dog_Idle - ( - void - ) +void Actor::End_Dog(void) { - if( !RequireThink() ) - { - return; - } - - UpdateEyeOrigin(); - m_pszDebugState = "Dog_Idle"; - m_bHasDesiredLookAngles = false; - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DOG_IDLE_SCR; - CheckForThinkStateTransition(); - PostThink( false ); + ; } -void Actor::Think_Dog_Attack - ( - void - ) +void Actor::Think_Dog_Idle(void) { - if (!RequireThink()) - { - return; - } + if (!RequireThink()) { + return; + } - UpdateEyeOrigin(); - m_pszDebugState = "Dog_Attack"; + UpdateEyeOrigin(); + m_pszDebugState = "Dog_Idle"; - if (m_Enemy && !(m_Enemy->IsSubclassOfActor())) - { + NoPoint(); + ForwardLook(); - SetPath(m_Enemy->origin, NULL, 0, NULL, 0.0); - if (PathExists()) - { - vec2_t delta; - VectorSub2D(m_Enemy->origin, origin, delta); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_IDLE_SCR); - if (VectorLength2DSquared(delta) >= 8000) - { - FaceMotion(); - m_csNextAnimString = STRING_ANIM_DOG_CHASE_SCR; - m_eNextAnimMode = 2; - } - else - { - { - vec2_t facedir; - facedir[0] = m_Enemy->origin[0] - origin[0]; - facedir[1] = m_Enemy->origin[1] - origin[1]; - if (facedir[0] != 0 || facedir[1] != 0) - { - SetDesiredYawDir(facedir); - } - - } - SetDesiredLookDir(m_Enemy->origin - origin); - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DOG_ATTACK_SCR; - } - m_bNextForceStart = false; - CheckForThinkStateTransition(); - PostThink(false); - return; - } - - { - vec2_t facedir; - facedir[0] = m_Enemy->origin[0] - origin[0]; - facedir[1] = m_Enemy->origin[1] - origin[1]; - if (facedir[0] != 0 || facedir[1] != 0) - { - SetDesiredYawDir(facedir); - } - - } - SetDesiredLookDir(m_Enemy->origin - origin); - } - m_bNextForceStart = false; - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DOG_CURIOUS_SCR; - TransitionState(20, 0); - - CheckForThinkStateTransition(); - PostThink(false); + CheckForThinkStateTransition(); + PostThink(false); } -void Actor::Think_Dog_Curious - ( - void - ) +void Actor::Think_Dog_Attack(void) { - if (RequireThink()) - { - UpdateEyeOrigin(); - m_pszDebugState = "Dog_Curious"; + if (!RequireThink()) { + return; + } - if (m_Enemy && !m_Enemy->IsSubclassOfActor()) - { - vec2_t vDelta; - VectorSub2D(m_Enemy->origin, origin, vDelta); + UpdateEyeOrigin(); + m_pszDebugState = "Dog_Attack"; - if (vDelta[0] != 0 || vDelta[1] != 0) - { - SetDesiredYawDir(vDelta); - } + if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) { + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_CURIOUS_SCR); + TransitionState(20); - SetDesiredLookDir(m_Enemy->origin - origin); + CheckForThinkStateTransition(); + PostThink(false); + return; + } - } - m_bNextForceStart = false; - m_eNextAnimMode = 1; - m_csNextAnimString = STRING_ANIM_DOG_CURIOUS_SCR; + SetPath(m_Enemy->origin, NULL, 0, NULL, 0.0); - CheckForThinkStateTransition(); - PostThink(false); - } + if (PathExists()) { + vec2_t delta; + VectorSub2D(m_Enemy->origin, origin, delta); + + if (VectorLength2DSquared(delta) >= 8000) { + FaceMotion(); + DesiredAnimation(ANIM_MODE_PATH, STRING_ANIM_DOG_CHASE_SCR); + } else { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_ATTACK_SCR); + } + } else { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_CURIOUS_SCR); + TransitionState(20); + } + + CheckForThinkStateTransition(); + PostThink(false); +} + +void Actor::Think_Dog_Curious(void) +{ + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + m_pszDebugState = "Dog_Curious"; + + if (m_Enemy && !(m_Enemy->flags & FL_NOTARGET)) { + SetDesiredYawDest(m_Enemy->origin); + SetDesiredLookDir(m_Enemy->origin - origin); + } + + DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_CURIOUS_SCR); + + CheckForThinkStateTransition(); + PostThink(false); } diff --git a/code/fgame/actor_grenade.cpp b/code/fgame/actor_grenade.cpp index 7a75aed3..6a6d355b 100644 --- a/code/fgame/actor_grenade.cpp +++ b/code/fgame/actor_grenade.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,661 +25,530 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" #include "weaputils.h" -void Actor::InitGrenade - ( - GlobalFuncs_t *func - ) +bool Actor::Grenade_Acquire(eGrenadeState eNextState, const_str csReturnAnim) { - func->ThinkState = &Actor::Think_Grenade; - func->BeginState = &Actor::Begin_Grenade; - func->EndState = &Actor::End_Grenade; - func->ResumeState = &Actor::Resume_Grenade; - func->SuspendState = &Actor::End_Grenade; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Grenade; - func->FinishedAnimation = &Actor::FinishedAnimation_Grenade; - func->IsState = &Actor::IsGrenadeState; + vec3_t vDest; + bool bRetVal = false; + + if (m_bGrenadeBounced) { + m_bGrenadeBounced = false; + bRetVal = true; + + VectorSubtract(origin, m_vGrenadePos, vDest); + VectorNormalizeFast(vDest); + + VectorMA(m_vGrenadePos, 16, vDest, vDest); + + SetPath(vDest, NULL, 0, NULL, 0); + } + + if (!PathExists()) { + m_bGrenadeBounced = true; + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return false; + } + + if (PathComplete()) { + ForwardLook(); + + if (VectorLength2DSquared(m_pGrenade->velocity) >= Square(32)) { + Anim_Stand(); + } else { + m_pGrenade->velocity = vec_zero; + m_eGrenadeState = eNextState; + DesiredAnimation(ANIM_MODE_NORMAL, csReturnAnim); + } + } else { + Anim_RunToCasual(ANIM_MODE_PATH_GOAL); + VectorSub2D(origin, m_vGrenadePos, vDest); + + if (VectorLength2DSquared(vDest) > Square(32)) { + FaceMotion(); + } else { + SetDesiredYawDest(m_vGrenadePos); + } + } + + return bRetVal; } -bool Actor::Grenade_Acquire - ( - eGrenadeState eNextState, - const_str csReturnAnim - ) +void Actor::InitGrenade(GlobalFuncs_t *func) { - bool bRetVal = false; - Vector vDest; - if (m_bGrenadeBounced) - { - bRetVal = true; - vDest = origin - m_vGrenadePos; - vDest = vDest * 16 + m_vGrenadePos; - SetPath(vDest, NULL, 0, NULL, 0.0); - } - if (PathExists()) - { - if (PathComplete()) - { - m_bHasDesiredLookAngles = false; - if (m_pGrenade->velocity.lengthXYSquared() >= 1024) - { - Anim_Stand(); - } - else - { - m_pGrenade->velocity = vec_zero; - - m_eNextAnimMode = 1; - m_eGrenadeState = eNextState; - m_bNextForceStart = false; - m_csNextAnimString = csReturnAnim; - } - } - else - { - Anim_RunToCasual(3); - - vec2_t delta; - VectorSub2D(origin, m_vGrenadePos, delta); - - if (VectorLength2DSquared(delta) > 1024.0) - { - FaceMotion(); - } - else - { - { - vec2_t facedir; - facedir[0] = m_vGrenadePos[0] - origin[0]; - facedir[1] = m_vGrenadePos[1] - origin[1]; - if (facedir[0] != 0 || facedir[1] != 0) - { - SetDesiredYawDir(facedir); - } - - } - } - } - } - else - { - m_bGrenadeBounced = true; - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - bRetVal = false; - } - - return bRetVal; + func->ThinkState = &Actor::Think_Grenade; + func->BeginState = &Actor::Begin_Grenade; + func->EndState = &Actor::End_Grenade; + func->ResumeState = &Actor::Resume_Grenade; + func->SuspendState = &Actor::End_Grenade; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Grenade; + func->FinishedAnimation = &Actor::FinishedAnimation_Grenade; + func->IsState = &Actor::IsGrenadeState; } -void Actor::Grenade_Flee - ( - void - ) +void Actor::Grenade_Flee(void) { - //float origin_ratio; - float fMinCloseDistSquared; - float fCosAngle; - float fSinAngle; - float fAngle; - vec2_t vDirAway; - vec2_t vDirPreferred; + vec2_t vDirPreferred; + vec2_t vDirAway; + float fAngle, fSinAngle, fCosAngle; + float fMinCloseDistSquared; + vec2_t grenade_offset; + float origin_ratio; + PathInfo *current_node; - if (m_bGrenadeBounced) - { - fAngle = (rand() - 0x3FFFFFFF) * -0.00000000146291807926716; + if (m_bGrenadeBounced) { + fAngle = (rand() - 0x3FFFFFFF) / 683565275.f; + fSinAngle = sin(fAngle); + fCosAngle = cos(fAngle); - fSinAngle = sin(fAngle); - fCosAngle = cos(fAngle); + VectorSub2D(origin, m_vGrenadePos, vDirAway); - VectorSub2D(origin, m_vGrenadePos, vDirAway); + vDirPreferred[0] = vDirAway[0] * fCosAngle - vDirAway[1] * fSinAngle; + vDirPreferred[1] = vDirAway[0] * fSinAngle + vDirAway[1] * fCosAngle; - vDirPreferred[0] = vDirAway[0] * fCosAngle - fSinAngle * vDirAway[1]; - vDirPreferred[1] = vDirAway[0] * fSinAngle + vDirAway[1] * fCosAngle; + FindPathAway(m_vGrenadePos, vDirPreferred, 512); - FindPathAway(m_vGrenadePos, vDirPreferred, 512); + if (PathExists() && !PathComplete()) { + fMinCloseDistSquared = VectorLength2DSquared(vDirAway) * 0.64f; - if (PathExists() && !PathComplete()) - { - fMinCloseDistSquared = VectorLength2DSquared(vDirAway) * 0.63999999; - - if (fMinCloseDistSquared < 1024) - fMinCloseDistSquared = 0; + if (fMinCloseDistSquared < Square(64)) { + fMinCloseDistSquared = 0; + } - vec2_t grenade_offset; - for (auto current_node = CurrentPathNode(); current_node >= LastPathNode(); current_node--) - { - VectorSub2D(m_vGrenadePos, current_node->point, grenade_offset); - if (current_node->dist > 0 && DotProduct2D(grenade_offset, current_node->dir) <= current_node->dist) - { - if (Square(CrossProduct2D(grenade_offset, current_node->dir)) < fMinCloseDistSquared) - { - ClearPath(); - break; - } - } - } - } - m_bGrenadeBounced = false; - } + for (current_node = CurrentPathNode(); current_node >= LastPathNode(); current_node--) { + VectorSub2D(m_vGrenadePos, current_node->point, grenade_offset); - if (PathExists() && !PathComplete()) - { - Sentient *pOwner = NULL; - if (m_pGrenade && m_pGrenade->IsSubclassOfProjectile()) - pOwner = ((Projectile *)m_pGrenade.Pointer())->GetOwner(); + origin_ratio = DotProduct2D(grenade_offset, current_node->dir); + if (origin_ratio <= 0) { + continue; + } - if (pOwner && pOwner->m_Team == m_Team) - Anim_RunTo(3); - else - Anim_RunToFlee(3); - FaceMotion(); - } - else - { + if (origin_ratio > current_node->dist) { + continue; + } - if ((origin - m_vGrenadePos).lengthXYSquared() >= 100352 - || !G_SightTrace( - centroid, - vec_zero, - vec_zero, - m_vGrenadePos, - this, - m_pGrenade, - 33819417, - 0, - "Actor::Grenade_Flee")) - { - m_eGrenadeState = AI_GRENSTATE_FLEE_SUCCESS; - Anim_Attack(); - AimAtTargetPos(); - } - else - { - m_bHasDesiredLookAngles = false; - m_eGrenadeState = AI_GRENSTATE_FLEE_FAIL; - Anim_Cower(); - } - } + if (Square(CrossProduct2D(grenade_offset, current_node->dir)) < fMinCloseDistSquared) { + ClearPath(); + break; + } + } + } + + m_bGrenadeBounced = false; + } + + if (PathExists() && !PathComplete()) { + Sentient *pOwner = NULL; + + if (m_pGrenade && m_pGrenade->IsSubclassOfProjectile()) { + pOwner = static_cast(m_pGrenade.Pointer())->GetOwner(); + } + + if (pOwner && pOwner->m_Team == m_Team) { + Anim_RunTo(ANIM_MODE_PATH_GOAL); + } else { + Anim_RunToFlee(ANIM_MODE_PATH_GOAL); + } + + FaceMotion(); + } + else if ((origin - m_vGrenadePos).lengthXYSquared() >= 100352 + || !G_SightTrace( + centroid, vec_zero, vec_zero, m_vGrenadePos, this, m_pGrenade, MASK_CANSEE, 0, "Actor::Grenade_Flee" + )) { + m_eGrenadeState = AI_GRENSTATE_FLEE_SUCCESS; + Anim_Attack(); + AimAtTargetPos(); + } else { + m_eGrenadeState = AI_GRENSTATE_FLEE_FAIL; + ForwardLook(); + Anim_Cower(); + } } -void Actor::Grenade_ThrowAcquire - ( - void - ) +void Actor::Grenade_ThrowAcquire(void) { - if (!Grenade_Acquire(AI_GRENSTATE_THROW, STRING_ANIM_GRENADERETURN_SCR) - && !CanGetGrenadeFromAToB( - m_vGrenadePos, - m_vLastEnemyPos, - true, - &m_vGrenadeVel, - &m_eGrenadeMode)) - { - m_bGrenadeBounced = true; - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - } + if (Grenade_Acquire(AI_GRENSTATE_THROW, STRING_ANIM_GRENADERETURN_SCR)) { + return; + } + + if (CanGetGrenadeFromAToB(m_vGrenadePos, m_vLastEnemyPos, true, &m_vGrenadeVel, &m_eGrenadeMode)) { + return; + } + + m_eGrenadeState = AI_GRENSTATE_FLEE; + m_bGrenadeBounced = true; + Grenade_Flee(); } -void Actor::Grenade_Throw - ( - void - ) +void Actor::Grenade_Throw(void) { - m_bHasDesiredLookAngles = false; - - SetDesiredYawDir(m_vGrenadeVel); - - ContinueAnimation(); + ForwardLook(); + SetDesiredYawDir(m_vGrenadeVel); + ContinueAnimation(); } -void Actor::Grenade_KickAcquire - ( - void - ) +void Actor::Grenade_KickAcquire(void) { - Vector vFace = vec_zero; - if (!Grenade_Acquire(AI_GRENSTATE_KICK, STRING_ANIM_GRENADEKICK_SCR)) - { - VectorSub2D(m_vGrenadePos, origin, vFace); - if (CanKickGrenade(m_vGrenadePos, m_vLastEnemyPos, vFace, &m_vGrenadeVel)) - { - m_vKickDir = Vector(m_vGrenadeVel[0], m_vGrenadeVel[1], 0); - - VectorNormalizeFast(m_vKickDir); - } - else - { - m_bGrenadeBounced = true; - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - } - } + Vector vDelta; + + if (Grenade_Acquire(AI_GRENSTATE_KICK, STRING_ANIM_GRENADEKICK_SCR)) { + return; + } + + vDelta = m_vGrenadePos - origin; + vDelta.z = 0; + + if (CanKickGrenade(m_vGrenadePos, m_vLastEnemyPos, vDelta, &m_vGrenadeVel)) { + m_vKickDir = m_vGrenadeVel; + m_vKickDir.z = 0; + m_vKickDir.normalizefast(); + } else { + m_eGrenadeState = AI_GRENSTATE_FLEE; + m_bGrenadeBounced = true; + Grenade_Flee(); + } } -void Actor::Grenade_Kick - ( - void - ) +void Actor::Grenade_Kick(void) { - m_bHasDesiredLookAngles = false; - ContinueAnimation(); + ForwardLook(); + ContinueAnimation(); } -void Actor::Grenade_MartyrAcquire - ( - void - ) +void Actor::Grenade_MartyrAcquire(void) { - Vector vDest; - if (m_bGrenadeBounced) - { - m_bGrenadeBounced = false; + vec3_t vDest; - vDest = origin - m_vGrenadePos; - VectorNormalizeFast(vDest); + if (m_bGrenadeBounced) { + m_bGrenadeBounced = false; - vDest = vDest * 88 + m_vGrenadePos; + VectorSubtract(origin, m_vGrenadePos, vDest); + VectorNormalizeFast(vDest); + VectorMA(m_vGrenadePos, 88, vDest, vDest); - SetPath(vDest, NULL, 0, NULL, 0.0); - } + SetPath(vDest, NULL, 0, NULL, 0.0); + } - if (PathExists()) - { - if (PathComplete()) - { - m_bHasDesiredLookAngles = false; + if (!PathExists()) { + m_bGrenadeBounced = true; + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return; + } - vDest = vec_zero; - m_pGrenade->velocity = vec_zero; + if (PathComplete()) { + ForwardLook(); + m_pGrenade->velocity = vec_zero; - //weird ? m_pGrenade->velocity is vec_zero ??? - if (m_pGrenade->velocity.lengthXYSquared() < 1024) - { - m_pGrenade->velocity = vec_zero; + if (m_pGrenade->velocity.lengthXYSquared() < Square(32)) { + m_pGrenade->velocity = vec_zero; - m_eGrenadeState = AI_GRENSTATE_MARTYR; - m_iStateTime = level.inttime; - Grenade_Martyr(); - } - } - else - { - Anim_RunToCasual(3); - m_csPathGoalEndAnimScript = STRING_ANIM_GRENADEMARTYR_SCR; - if ((origin-m_vGrenadePos).lengthXYSquared() > 16384) - { - FaceMotion(); - } - else - { - if (m_vGrenadePos - origin != vec_zero) - { - SetDesiredYawDir(m_vGrenadePos - origin); - } - } - } - } - else - { - m_bGrenadeBounced = true; - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - } + m_eGrenadeState = AI_GRENSTATE_MARTYR; + m_iStateTime = level.inttime; + Grenade_Martyr(); + } + } else { + Anim_RunToCasual(ANIM_MODE_PATH_GOAL); + SetPathGoalEndAnim(STRING_ANIM_GRENADEMARTYR_SCR); + + VectorSub2D(origin, m_vGrenadePos, vDest); + if (VectorLength2DSquared(vDest) > Square(128)) { + FaceMotion(); + } else { + SetDesiredYawDest(m_vGrenadePos); + } + } } -void Actor::Grenade_Martyr - ( - void - ) +void Actor::Grenade_Martyr(void) { - if (m_pGrenade && level.inttime >= (m_iStateTime + 1000) - 0.5) - { - Projectile *m_pPGrenade = (Projectile *)m_pGrenade.Pointer(); + if (m_pGrenade && level.inttime >= (m_iStateTime + 1000) - 0.5) { + static_cast(m_pGrenade.Pointer())->SetMartyr(entnum); + } - m_pPGrenade->m_bHurtOwnerOnly = true; - m_pPGrenade->owner = entnum; - - } - - m_bHasDesiredLookAngles = false; - ContinueAnimation(); + ForwardLook(); + ContinueAnimation(); } -void Actor::Grenade_Wait - ( - void - ) +void Actor::Grenade_Wait(void) { - if (rand() & 0xF) - { - Anim_Cower(); - } - else - { - Anim_Stand(); - - Grenade_NextThinkState(); - } + if (rand() & 0xF) { + Anim_Cower(); + } else { + Anim_Stand(); + Grenade_NextThinkState(); + } } -void Actor::Grenade_NextThinkState - ( - void - ) +void Actor::Grenade_NextThinkState(void) { - if (m_Enemy && !(m_Enemy->IsSubclassOfActor())) - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - else - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); + if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + return; + } + + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); } -void Actor::Grenade_EventAttach - ( - Event *ev - ) +void Actor::Grenade_EventAttach(Event *ev) { - if (m_pGrenade) - { - eGrenadeTossMode eMode; - Vector vVel; - int tagnum = gi.Tag_NumForName(edict->tiki, "tag_weapon_right"); - if (tagnum >= 0) - { - vVel = vec_zero; - m_pGrenade->attach( - entnum, - tagnum, - qtrue, - vec3_origin); - } - m_pGrenade->avelocity = vec3_origin; + if (!m_pGrenade) { + return; + } - if (CanGetGrenadeFromAToB( - origin, - m_vLastEnemyPos, - true, - &vVel, - &eMode)) - { - m_vGrenadeVel = vVel; - m_eGrenadeMode = eMode; - } + int tagnum; + Vector vVel; + eGrenadeTossMode eMode; - SetDesiredYawDir(m_vGrenadeVel); - } + tagnum = gi.Tag_NumForName(edict->tiki, "tag_weapon_right"); + if (tagnum >= 0) { + m_pGrenade->attach(entnum, tagnum, qtrue, vec3_origin); + } + + m_pGrenade->avelocity = vec3_origin; + + if (CanGetGrenadeFromAToB(origin, m_vLastEnemyPos, true, &vVel, &eMode)) { + m_vGrenadeVel = vVel; + m_eGrenadeMode = eMode; + } + + SetDesiredYawDir(m_vGrenadeVel); } -void Actor::Grenade_EventDetach - ( - Event *ev - ) +void Actor::Grenade_EventDetach(Event *ev) { - if (m_pGrenade) - { - m_pGrenade->detach(); - m_pGrenade->setOrigin(GrenadeThrowPoint(origin, orientation[0], m_eGrenadeMode == AI_GREN_KICK ? STRING_ANIM_GRENADEKICK_SCR : STRING_ANIM_GRENADERETURN_SCR)); - m_pGrenade->velocity = m_vGrenadeVel; + if (!m_pGrenade) { + return; + } - m_pGrenade->edict->r.ownerNum = edict->s.number; - m_pGrenade->groundentity = NULL; - - } + const_str csAnim; + + m_pGrenade->detach(); + csAnim = m_eGrenadeMode == AI_GREN_KICK ? STRING_ANIM_GRENADEKICK_SCR : STRING_ANIM_GRENADERETURN_SCR; + + m_pGrenade->setOrigin(GrenadeThrowPoint(origin, orientation[0], csAnim)); + m_pGrenade->velocity = m_vGrenadeVel; + + m_pGrenade->edict->r.ownerNum = edict->s.number; + m_pGrenade->groundentity = NULL; } -void Actor::Begin_Grenade - ( - void - ) +void Actor::Begin_Grenade(void) { - DoForceActivate(); - m_csMood = STRING_ALERT; - m_csIdleMood = STRING_NERVOUS; + DoForceActivate(); + m_csMood = STRING_ALERT; + m_csIdleMood = STRING_NERVOUS; - if (m_pGrenade) - { - if (m_pGrenade->enemy) - { - m_eGrenadeState = AI_GRENSTATE_FLEE; - //LABEL_4: - Grenade_Flee(); - return; - } + if (!m_pGrenade) { + if (m_Enemy && (m_Enemy->flags & FL_NOTARGET)) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } else if (m_Team != TEAM_GERMAN) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } else { + if (!IsTeamMate(static_cast(G_GetEntity(0)))) { + ForceAttackPlayer(); + } + } - if (m_pGrenade->edict->r.ownerNum == entnum) - { - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - return; - } - bool bHasThrowTarget = true; - float fDistSquared; - Vector vDelta; - if (!m_Enemy) - { - Sentient *pEnemy = (Sentient *)G_GetEntity(m_pGrenade->edict->r.ownerNum); + return; + } - if (pEnemy && pEnemy->m_Team != m_Team) - { - SetEnemyPos(pEnemy->origin); - } - else - { - bHasThrowTarget = false; - } - } - if (!bHasThrowTarget) - { - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - return; - } - vDelta = m_vGrenadePos - origin; - vDelta.z = 0; - fDistSquared = vDelta.lengthXYSquared(); - if (fDistSquared >= 65536) - { - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - return; - } + if (m_pGrenade->enemy || m_pGrenade->edict->r.ownerNum == entnum) { + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return; + } - if (fDistSquared > 16384 && GrenadeWillHurtTeamAt(m_vGrenadePos)) - { - m_pGrenade->enemy = this; + if (m_pGrenade) { + vec3_t vDelta; + float fDistSquared; + bool bHasThrowTarget; - m_eGrenadeState = AI_GRENSTATE_MARTYR_ACQUIRE; - Grenade_MartyrAcquire(); - return; - } + bHasThrowTarget = true; + if (!m_Enemy) { + Sentient *pEnemy = static_cast(G_GetEntity(m_pGrenade->edict->r.ownerNum)); - if (GrenadeWillHurtTeamAt(m_vLastEnemyPos)) - { - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - return; - } + if (pEnemy && pEnemy->m_Team != m_Team) { + SetEnemyPos(pEnemy->origin); + } else { + bHasThrowTarget = false; + } + } - if (CanKickGrenade(m_vGrenadePos, m_vLastEnemyPos, vDelta, &m_vGrenadeVel)) - { - m_eGrenadeMode = AI_GREN_KICK; + if (!bHasThrowTarget) { + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return; + } - m_vKickDir = Vector(m_vGrenadeVel[0], m_vGrenadeVel[1], 0); - VectorNormalizeFast(m_vKickDir); + VectorSub2D(m_vGrenadePos, origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); - m_pGrenade->enemy = this; - - m_eGrenadeState = AI_GRENSTATE_KICK_ACQUIRE; - PostponeEvent(EV_Projectile_Explode, 0.25); - Grenade_KickAcquire(); - return; - } + if (fDistSquared >= Square(256)) { + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return; + } - if (!CanGetGrenadeFromAToB(m_vGrenadePos, m_vLastEnemyPos, true, &m_vGrenadeVel, &m_eGrenadeMode)) - { - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - return; - } + if (fDistSquared > 16384 && GrenadeWillHurtTeamAt(m_vGrenadePos)) { + m_pGrenade->enemy = this; - m_pGrenade->enemy = this; + m_eGrenadeState = AI_GRENSTATE_MARTYR_ACQUIRE; + Grenade_MartyrAcquire(); + return; + } - m_eGrenadeState = AI_GRENSTATE_THROW_ACQUIRE; - PostponeEvent(EV_Projectile_Explode, 0.75); - if (!Grenade_Acquire(AI_GRENSTATE_THROW, STRING_ANIM_GRENADERETURN_SCR) - && !Actor::CanGetGrenadeFromAToB(m_vGrenadePos, m_vLastEnemyPos, true, &m_vGrenadeVel, &m_eGrenadeMode)) - { - m_bGrenadeBounced = true; - m_eGrenadeState = AI_GRENSTATE_FLEE; - Grenade_Flee(); - return; - } - } - else - { - if (m_Enemy && !m_Enemy->IsSubclassOfActor()) - { - SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL); - } - else if (m_Team == TEAM_AMERICAN) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - } - else - { - if (!IsTeamMate((Sentient*)G_GetEntity(0))) - ForceAttackPlayer(); - } - } + if (GrenadeWillHurtTeamAt(m_vLastEnemyPos)) { + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return; + } + + Vector vFace = vDelta; + if (CanKickGrenade(m_vGrenadePos, m_vLastEnemyPos, vFace, &m_vGrenadeVel)) { + m_eGrenadeMode = AI_GREN_KICK; + + m_vKickDir = m_vGrenadeVel; + m_vKickDir.z = 0; + m_vKickDir.normalizefast(); + + m_pGrenade->enemy = this; + m_eGrenadeState = AI_GRENSTATE_KICK_ACQUIRE; + + PostponeEvent(EV_Projectile_Explode, 0.25); + Grenade_KickAcquire(); + return; + } + + if (!CanGetGrenadeFromAToB(m_vGrenadePos, m_vLastEnemyPos, true, &m_vGrenadeVel, &m_eGrenadeMode)) { + m_eGrenadeState = AI_GRENSTATE_FLEE; + Grenade_Flee(); + return; + } + + m_pGrenade->enemy = this; + + m_eGrenadeState = AI_GRENSTATE_THROW_ACQUIRE; + PostponeEvent(EV_Projectile_Explode, 0.75); + + Grenade_ThrowAcquire(); + } else if (m_Enemy && !m_Enemy->IsSubclassOfActor()) { + SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE); + } else if (m_Team == TEAM_AMERICAN) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } else { + if (!IsTeamMate((Sentient *)G_GetEntity(0))) { + ForceAttackPlayer(); + } + } } -void Actor::End_Grenade - ( - void - ) +void Actor::End_Grenade(void) { - m_pszDebugState = ""; + m_pszDebugState = ""; } -void Actor::Resume_Grenade - ( - void - ) +void Actor::Resume_Grenade(void) { - if (m_pGrenade) - Begin_Grenade(); - else - Grenade_NextThinkState(); + if (m_pGrenade) { + Begin_Grenade(); + } else { + Grenade_NextThinkState(); + } } -void Actor::Think_Grenade - ( - void - ) +void Actor::FinishedAnimation_Grenade(void) { - if (m_bEnableEnemy) - UpdateEnemy(200); - m_pszDebugState = ""; - NoPoint(); - - if (level.inttime - m_iFirstGrenadeTime > 8000) - { - Anim_Stand(); - Grenade_NextThinkState(); - PostThink(false); - return; - } - - if (!m_pGrenade) - { - if (m_eGrenadeState && m_eGrenadeState != AI_GRENSTATE_FLEE_FAIL) - { - // weird ? no such thing as 8 ? - // FIXME? - if (m_eGrenadeMode == (eGrenadeTossMode)8) - Anim_Attack(); - else - Anim_Stand(); - Grenade_NextThinkState(); - } - else - { - m_pszDebugState = "Wait"; - Grenade_Wait(); - } - PostThink(false); - return; - } - - switch (m_eGrenadeState) - { - case AI_GRENSTATE_FLEE: - case AI_GRENSTATE_FLEE_SUCCESS: - case AI_GRENSTATE_FLEE_FAIL: - m_pszDebugState = "RunAway"; - Grenade_Flee(); - break; - case AI_GRENSTATE_THROW_ACQUIRE: - m_pszDebugState = "ThrowAcquire"; - Grenade_ThrowAcquire(); - break; - case AI_GRENSTATE_THROW: - m_pszDebugState = "Throw"; - Grenade_Throw(); - break; - case AI_GRENSTATE_KICK_ACQUIRE: - m_pszDebugState = "KickAcquire"; - Grenade_KickAcquire(); - break; - case AI_GRENSTATE_KICK: - m_pszDebugState = "Kick"; - m_bHasDesiredLookAngles = false; - ContinueAnimation(); - break; - case AI_GRENSTATE_MARTYR_ACQUIRE: - m_pszDebugState = "MartyrAcquire"; - Grenade_MartyrAcquire(); - break; - case AI_GRENSTATE_MARTYR: - m_pszDebugState = "Martyr"; - Grenade_Martyr(); - break; - default: - m_pszDebugState = "***Invalid***"; - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"invalid grenade state\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); - assert(!assertStr); - break; - } - - PostThink(false); + switch (m_eGrenadeState) { + case AI_GRENSTATE_FLEE: + case AI_GRENSTATE_THROW_ACQUIRE: + case AI_GRENSTATE_KICK_ACQUIRE: + case AI_GRENSTATE_MARTYR_ACQUIRE: + case AI_GRENSTATE_MARTYR: + case AI_GRENSTATE_FLEE_SUCCESS: + case AI_GRENSTATE_FLEE_FAIL: + return; + case AI_GRENSTATE_THROW: + case AI_GRENSTATE_KICK: + Grenade_NextThinkState(); + break; + default: + char assertStr[16317] = {0}; + Q_strncpyz(assertStr, "\"invalid grenade state in FinishedAnimation()\"\n\tMessage: ", sizeof(assertStr)); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("state = %i", m_eGrenadeState)); + assert(!assertStr); + break; + } } -void Actor::FinishedAnimation_Grenade - ( - void - ) +void Actor::Think_Grenade(void) { - switch (m_eGrenadeState) - { - case AI_GRENSTATE_FLEE: - case AI_GRENSTATE_THROW_ACQUIRE: - case AI_GRENSTATE_KICK_ACQUIRE: - case AI_GRENSTATE_MARTYR_ACQUIRE: - case AI_GRENSTATE_MARTYR: - case AI_GRENSTATE_FLEE_SUCCESS: - case AI_GRENSTATE_FLEE_FAIL: - return; - case AI_GRENSTATE_THROW: - case AI_GRENSTATE_KICK: - Grenade_NextThinkState(); - break; - default: - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"invalid grenade state in FinishedAnimation()\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("state = %i", m_eGrenadeState)); - assert(!assertStr); - break; - } + if (m_bEnableEnemy) { + UpdateEnemy(200); + } + + m_pszDebugState = ""; + NoPoint(); + + if (level.inttime - m_iFirstGrenadeTime > 8000) { + Anim_Stand(); + Grenade_NextThinkState(); + PostThink(false); + return; + } + + if (m_pGrenade) { + switch (m_eGrenadeState) { + case AI_GRENSTATE_FLEE: + case AI_GRENSTATE_FLEE_SUCCESS: + case AI_GRENSTATE_FLEE_FAIL: + m_pszDebugState = "RunAway"; + Grenade_Flee(); + break; + case AI_GRENSTATE_THROW_ACQUIRE: + m_pszDebugState = "ThrowAcquire"; + Grenade_ThrowAcquire(); + break; + case AI_GRENSTATE_THROW: + m_pszDebugState = "Throw"; + Grenade_Throw(); + break; + case AI_GRENSTATE_KICK_ACQUIRE: + m_pszDebugState = "KickAcquire"; + Grenade_KickAcquire(); + break; + case AI_GRENSTATE_KICK: + m_pszDebugState = "Kick"; + m_bHasDesiredLookAngles = false; + ContinueAnimation(); + break; + case AI_GRENSTATE_MARTYR_ACQUIRE: + m_pszDebugState = "MartyrAcquire"; + Grenade_MartyrAcquire(); + break; + case AI_GRENSTATE_MARTYR: + m_pszDebugState = "Martyr"; + Grenade_Martyr(); + break; + default: + m_pszDebugState = "***Invalid***"; + char assertStr[16317] = {0}; + strcpy(assertStr, "\"invalid grenade state\"\n\tMessage: "); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); + assert(!assertStr); + break; + } + } else if (m_eGrenadeState && m_eGrenadeState != AI_GRENSTATE_FLEE_FAIL) { + if (m_eGrenadeMode == AI_GRENSTATE_FLEE_SUCCESS) { + Anim_Attack(); + } else { + Anim_Stand(); + } + Grenade_NextThinkState(); + } else { + m_pszDebugState = "Wait"; + Grenade_Wait(); + } + + PostThink(false); } diff --git a/code/fgame/actor_idle.cpp b/code/fgame/actor_idle.cpp index 72d90f28..8b15dba8 100644 --- a/code/fgame/actor_idle.cpp +++ b/code/fgame/actor_idle.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,105 +24,57 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitIdle - ( - GlobalFuncs_t *func - ) +void Actor::InitIdle(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Idle; - func->ThinkState = &Actor::Think_Idle; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->IsState = &Actor::IsIdleState; + func->BeginState = &Actor::Begin_Idle; + func->ThinkState = &Actor::Think_Idle; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->IsState = &Actor::IsIdleState; } -void Actor::Begin_Idle - ( - void - ) +void Actor::Begin_Idle(void) { - glbs.Printf("Begin_Idle\n"); - m_csMood = m_csIdleMood; - ClearPath(); + m_csMood = m_csIdleMood; + ClearPath(); } -void Actor::Think_Idle - ( - void - ) +void Actor::IdleThink(void) { - if (RequireThink()) - { - UpdateEyeOrigin(); - m_pszDebugState = ""; - CheckForThinkStateTransition(); - IdleThink(); - } + IdlePoint(); + IdleLook(); + + if (PathExists() && PathComplete()) { + ClearPath(); + } + + if (m_bAutoAvoidPlayer && !PathExists()) { + SetPathToNotBlockSentient(static_cast(G_GetEntity(0))); + } + + if (PathExists()) { + Anim_WalkTo(ANIM_MODE_PATH); + if (PathDist() > 128.0) { + FaceMotion(); + } else { + IdleTurn(); + } + } else { + Anim_Idle(); + IdleTurn(); + } + + PostThink(true); } -void Actor::IdleThink -( - void -) +void Actor::Think_Idle(void) { - IdlePoint(); - IdleLook(); - if (PathExists() && PathComplete()) - { - ClearPath(); - } - if (m_bAutoAvoidPlayer && !PathExists()) - { - SetPathToNotBlockSentient((Sentient *)G_GetEntity(0)); - } + if (!RequireThink()) { + return; + } - if (PathExists()) - { - Anim_WalkTo(2); - if (PathDist() <= 128.0) - IdleTurn(); - else - FaceMotion(); - } - else - { - Anim_Idle(); - IdleTurn(); - } + UpdateEyeOrigin(); + m_pszDebugState = ""; - PostThink(true); - -} - - -/* -=============== -Actor::PassesTransitionConditions_Idle - -Should actor transition think state to idle ? -=============== -*/ -bool Actor::PassesTransitionConditions_Idle -( - void -) -{ - glbs.Printf("PassesTransitionConditions_Idle\n"); - - UpdateEnemy(500); - - if (m_bLockThinkState) - return false; - - if (!m_Enemy && !m_iCuriousTime) - return true; - - return false; -} - -bool Actor::IsIdleState -( - int state -) -{ - return state == THINKSTATE_IDLE; + CheckForThinkStateTransition(); + IdleThink(); } \ No newline at end of file diff --git a/code/fgame/actor_killed.cpp b/code/fgame/actor_killed.cpp index 366f7cde..bea83635 100644 --- a/code/fgame/actor_killed.cpp +++ b/code/fgame/actor_killed.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,67 +24,49 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitDead - ( - GlobalFuncs_t *func - ) +void Actor::InitDead(GlobalFuncs_t *func) { - func->IsState = &Actor::IsKilledState; + func->IsState = &Actor::IsKilledState; } -void Actor::InitKilled - ( - GlobalFuncs_t *func - ) +void Actor::InitKilled(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Killed; - func->ThinkState = &Actor::Think_Killed; - func->FinishedAnimation = &Actor::FinishedAnimation_Killed; - func->IsState = &Actor::IsKilledState; + func->BeginState = &Actor::Begin_Killed; + func->ThinkState = &Actor::Think_Killed; + func->FinishedAnimation = &Actor::FinishedAnimation_Killed; + func->IsState = &Actor::IsKilledState; } -void Actor::Begin_Killed - ( - void - ) +void Actor::Begin_Killed(void) { - Event e1(EV_Actor_DeathEmbalm); // ebx + ClearPath(); + ResetBoneControllers(); - ClearPath(); - ResetBoneControllers(); - - PostEvent( - e1, - 0.05f); - TransitionState(700, 0); + PostEvent(EV_Actor_DeathEmbalm, 0.05f); + TransitionState(ACTOR_STATE_KILLED_BEGIN, 0); } -void Actor::Think_Killed - ( - void - ) +void Actor::Think_Killed(void) { - Unregister(STRING_ANIMDONE); - if (m_State == 700) - { - m_pszDebugState = "begin"; - NoPoint(); - m_bHasDesiredLookAngles = false; - StopTurning(); - Anim_Killed(); - PostThink(false); - } - else - { - m_pszDebugState = "end"; - } + Unregister(STRING_ANIMDONE); + + if (m_State != ACTOR_STATE_KILLED_BEGIN) { + m_pszDebugState = "end"; + return; + } + + m_pszDebugState = "begin"; + + NoPoint(); + ForwardLook(); + StopTurning(); + + Anim_Killed(); + PostThink(false); } -void Actor::FinishedAnimation_Killed - ( - void - ) +void Actor::FinishedAnimation_Killed(void) { - BecomeCorpse(); - TransitionState(701, 0); + BecomeCorpse(); + TransitionState(ACTOR_STATE_KILLED_END); } diff --git a/code/fgame/actor_machinegunner.cpp b/code/fgame/actor_machinegunner.cpp index ddb52d66..f79690f3 100644 --- a/code/fgame/actor_machinegunner.cpp +++ b/code/fgame/actor_machinegunner.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,337 +24,289 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" #include "weapturret.h" +#include "bg_local.h" -extern Vector MINS; -extern Vector MAXS; - -void Actor::InitMachineGunner - ( - GlobalFuncs_t *func - ) +void Actor::InitMachineGunner(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_MachineGunner; - func->EndState = &Actor::End_MachineGunner; - func->ThinkState = &Actor::Think_MachineGunner; - func->IsState = &Actor::IsMachineGunnerState; - func->FinishedAnimation = &Actor::FinishedAnimation_MachineGunner; + func->BeginState = &Actor::Begin_MachineGunner; + func->EndState = &Actor::End_MachineGunner; + func->ThinkState = &Actor::Think_MachineGunner; + func->IsState = &Actor::IsMachineGunnerState; + func->FinishedAnimation = &Actor::FinishedAnimation_MachineGunner; } -void Actor::Begin_MachineGunner - ( - void - ) +bool Actor::IsMachineGunnerState(int state) { - m_csMood = STRING_ALERT; - m_csIdleMood = STRING_NERVOUS; - - if (m_pTurret) - { - Sentient *pOwner; - m_pTurret->m_bHadOwner = true; - pOwner = m_pTurret->GetOwner(); - if (pOwner) - { - Com_Printf( - "^~^~^ Actor (entnum %d, radnum %d, targetname '%s') cannot use turret (entnum %d, radnum %d, targetname '%s')" - " since it is already being used by Actor (entnum %d, radnum %d, targetname '%s')\n", - entnum, - radnum, - targetname.c_str(), - m_pTurret->entnum, - m_pTurret->radnum, - m_pTurret->TargetName().c_str(), - pOwner->entnum, - pOwner->radnum, - pOwner->TargetName().c_str()); - } - else - { - Holster(); - - m_pTurret->TurretBeginUsed(this); - TransitionState(1200, 0); - } - } - else - { - Com_Printf( - "^~^~^ Actor (entnum %d, radnum %d, targetname '%s') has no turret specified\n", - entnum, - radnum, - targetname.c_str()); - } -} -void Actor::End_MachineGunner - ( - void - ) -{ - if (!GetWeapon(WEAPON_MAIN)) - giveItem("models/weapons/mp40.tik"); - - Unholster(); - if (m_pTurret) - { - if (m_pTurret->GetOwner() == this) - { - m_pTurret->TurretEndUsed(); - } - } -} -void Actor::BecomeTurretGuy - ( - void - ) -{ - SetThinkIdle(THINK_IDLE); - - SetThink(THINKSTATE_ATTACK, THINK_TURRET); - SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE); - SetThink(THINKSTATE_GRENADE, THINK_GRENADE); - - if (CurrentThink() == THINK_IDLE && Turret_DecideToSelectState()) - { - TransitionState(100, 0); - } + return true; } -void Actor::Think_MachineGunner - ( - void - ) +void Actor::Begin_MachineGunner(void) { - if (RequireThink()) - { - if (m_pTurret && m_pTurret->GetOwner() == this && !m_bNoPlayerCollision) - { - if (!m_bEnableEnemy) - { - ThinkHoldGun(); - return; - } + m_csMood = STRING_ALERT; + m_csIdleMood = STRING_NERVOUS; - if (level.inttime < m_iEnemyCheckTime + 200) - { - ThinkHoldGun(); - return; - } - - m_iEnemyCheckTime = level.inttime; + if (!m_pTurret) { + Com_Printf( + "^~^~^ Actor (entnum %d, radnum %d, targetname '%s') has no turret specified\n", + entnum, + radnum, + targetname.c_str() + ); - if (m_pTurret->CanTarget(G_GetEntity(0)->centroid)) - { - ThinkHoldGun(); - return; - } - if (!m_pGrenade || m_fGrenadeAwareness < rand() * 0.000000046566129) - { - if (!G_SightTrace( - EyePosition(), - vec_zero, - vec_zero, - G_GetEntity(0)->centroid, - this, - G_GetEntity(0), - 33819417, - qfalse, - "Actor::Think_MachineGunner")) - { - ThinkHoldGun(); - return; - } - if (m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_IDLE) - { - BecomeTurretGuy(); - return; - } + return; + } - if (m_Enemy && !m_Enemy->IsSubclassOfActor() && !EnemyIsDisguised() && m_PotentialEnemies.GetCurrentVisibility() >= 1) - { - BecomeTurretGuy(); - return; - } + Sentient *pOwner; + m_pTurret->m_bHadOwner = true; + pOwner = m_pTurret->GetOwner(); + if (m_pTurret->GetOwner()) { + Com_Printf( + "^~^~^ Actor (entnum %d, radnum %d, targetname '%s') cannot use turret (entnum %d, radnum %d, " + "targetname '%s')" + " since it is already being used by Actor (entnum %d, radnum %d, targetname '%s')\n", + entnum, + radnum, + targetname.c_str(), + m_pTurret->entnum, + m_pTurret->radnum, + m_pTurret->targetname.c_str(), + m_pTurret->GetOwner()->entnum, + m_pTurret->GetOwner()->radnum, + m_pTurret->GetOwner()->targetname.c_str() + ); + } else { + Holster(); - if (!m_Enemy || !m_Enemy->IsSubclassOfActor() || EnemyIsDisguised() || m_PotentialEnemies.GetCurrentVisibility() > 1) - { - ThinkHoldGun(); - return; - } - - SetCuriousAnimHint(6); - } - } - BecomeTurretGuy(); - } + m_pTurret->TurretBeginUsed(this); + TransitionState(ACTOR_STATE_MACHINE_GUNNER_READY); + } } -void Actor::ThinkHoldGun - ( - void - ) +void Actor::End_MachineGunner(void) { - Vector end; - trace_t trace; - float temp; - float temp2; - float machine_gunner_hands_up_stand; - float heightDiff; - float right; - //vec3_t newOrigin; - Vector offset; - Vector start; - //vec3_t new_angles; - Vector vForward; - - UpdateEyeOrigin(); - m_pszDebugState = ""; - if (m_State == 1200) - { - if (m_pTurret->IsFiring()) - { - if (m_pTurret->aim_target == G_GetEntity(0)) - { - m_bNoSurprise = true; - } - m_csNextAnimString = STRING_ANIM_MG42_SHOOT_SCR; - } - else - { - m_csNextAnimString = STRING_ANIM_MG42_IDLE_SCR; - } - } - else - { - m_csNextAnimString = STRING_ANIM_MG42_RELOAD_SCR; - m_bAnimScriptSet = false; - } - m_eNextAnimMode = 8; - m_bNextForceStart = false; - - CheckUnregister(); - - StopTurning(); - - setAngles(Vector(0,m_pTurret->angles[1],0)); - - vForward = Vector(m_pTurret->orientation[0]) * -39 + m_pTurret->origin; - - if (m_State == 1201) - { - heightDiff = 71.6f; - } - else - { - heightDiff = 71.8f; - } - - machine_gunner_hands_up_stand = origin[2] - (m_pTurret->origin[2] - heightDiff); - - - if (machine_gunner_hands_up_stand < 0) - { - if (m_State == 1201) - { - temp = (machine_gunner_hands_up_stand - m_pTurret->origin[2]) / 39; - if (temp >= -1.0 && temp <= 1.0) - { - right = atan2(temp / sqrt(temp*-temp + 1), 1) * 180 / M_PI; - m_pTurret->setAngles(Vector(right, m_pTurret->angles[1], m_pTurret->angles[2])); - } - } - else - { - m_fCrouchWeight = machine_gunner_hands_up_stand / 17.1; - if (m_fCrouchWeight < -1.0) - { - m_fCrouchWeight = -1.0; - } - - } - temp2 = m_fCrouchWeight * 2.6; - offset.x = (-(-9.3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.x; - offset.y = (-(-9.3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.y; - } - else - { - m_fCrouchWeight = machine_gunner_hands_up_stand / (heightDiff - 38.7); - if (m_fCrouchWeight > 1.0) - { - m_fCrouchWeight = 1.0; - } - - temp2 = m_fCrouchWeight * -1.6; - offset.x = (-(-3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.x; - offset.y = (-(-3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.y; - } - - start.x = (temp2 + 10.3) * orientation[1][0] + offset.x; - start.y = (temp2 + 10.3) * orientation[1][1] + offset.y; - - if (m_fCrouchWeight >= 0.5) - m_csCurrentPosition = STRING_CROUCH; - else - m_csCurrentPosition = STRING_STAND; - - UpdateAimMotion(); - UpdateAnim(); - start.z = origin.z + 18.0; - - end = start; - end.z = origin.z - 94.0; - - trace = G_Trace(start, MINS, MAXS, end, this, 1107437825, qfalse, "Actor::ThinkHoldGun"); - - if (trace.fraction != 1.0 && !trace.startsolid && !trace.allsolid && trace.ent) - SafeSetOrigin(trace.endpos); - - velocity = vec_zero; - - UpdateBoneControllers(); - UpdateFootsteps(); + if (!GetWeapon(WEAPON_MAIN)) { + giveItem("models/weapons/mp40.tik"); + } + Unholster(); + if (m_pTurret) { + m_pTurret->m_bHadOwner = true; + if (m_pTurret->GetOwner() == this) { + m_pTurret->TurretEndUsed(); + } + } } -void Actor::FinishedAnimation_MachineGunner - ( - void - ) +void Actor::ThinkHoldGun_TurretGun(void) { - if (!m_bAnimScriptSet && m_State == 1201) - { - TransitionState(1200, 0); - Unregister(STRING_ANIMDONE); - } + Vector vForward; + vec3_t new_angles; + vec3_t offset; + vec3_t newOrigin; + float right; + float heightDiff; + float machine_gunner_hands_up_stand; + float temp; + trace_t trace; + Vector end; + + if (m_State != ACTOR_STATE_MACHINE_GUNNER_READY) { + DesiredAnimation(ANIM_MODE_FROZEN, STRING_ANIM_MG42_RELOAD_SCR); + m_bAnimScriptSet = false; + } else if (m_pTurret->IsFiring()) { + if (m_pTurret->aim_target == G_GetEntity(0)) { + m_bNoSurprise = true; + } + + DesiredAnimation(ANIM_MODE_FROZEN, STRING_ANIM_MG42_SHOOT_SCR); + } else { + DesiredAnimation(ANIM_MODE_FROZEN, STRING_ANIM_MG42_IDLE_SCR); + } + + CheckUnregister(); + StopTurning(); + + VectorSet(new_angles, 0, m_pTurret->angles[1], 0); + setAngles(new_angles); + + VectorScale(m_pTurret->orientation[0], -39, offset); + VectorAdd(m_pTurret->origin, offset, newOrigin); + + if (m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) { + heightDiff = 71.6f; + } else { + heightDiff = 71.8f; + } + + newOrigin[2] -= heightDiff; + machine_gunner_hands_up_stand = origin[2] - newOrigin[2]; + + if (machine_gunner_hands_up_stand < 0) { + if (m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) { + m_fCrouchWeight = 0; + + temp = (origin[2] + 71.6f - m_pTurret->origin[2]) / 39.0f; + if (temp >= -1.0 && temp <= 1.0) { + m_pTurret->angles[0] = RAD2DEG(atan(temp / sqrt(temp * -temp + 1))); + m_pTurret->setAngles(m_pTurret->angles); + } + } else { + m_fCrouchWeight = machine_gunner_hands_up_stand / 17.1f; + if (m_fCrouchWeight < -1.0f) { + m_fCrouchWeight = -1.0f; + } + } + + VectorScale2D(orientation[0], -(23.4 - m_fCrouchWeight * 9.3), offset); + VectorAdd2D(newOrigin, offset, newOrigin); + VectorScale2D(orientation[1], 10.3 + m_fCrouchWeight * 2.6, offset); + VectorAdd2D(newOrigin, offset, newOrigin); + } else { + m_fCrouchWeight = machine_gunner_hands_up_stand / (heightDiff - 38.7); + if (m_fCrouchWeight > 1.0) { + m_fCrouchWeight = 1.0; + } + + VectorScale2D(orientation[0], -(23.4 - m_fCrouchWeight * 3.0), offset); + VectorAdd2D(newOrigin, offset, newOrigin); + VectorScale2D(orientation[1], 10.3 - m_fCrouchWeight * 1.6, offset); + VectorAdd2D(newOrigin, offset, newOrigin); + } + + if (m_fCrouchWeight >= 0.5) { + m_csCurrentPosition = STRING_CROUCH; + } else { + m_csCurrentPosition = STRING_STAND; + } + + UpdateAimMotion(); + UpdateAnim(); + + newOrigin[2] = origin[2] + 18.0; + + end[0] = newOrigin[0]; + end[1] = newOrigin[1]; + end[2] = origin[2] - 94.0; + trace = G_Trace(newOrigin, MINS, MAXS, end, this, MASK_PATHSOLID, qfalse, "Actor::ThinkHoldGun_TurretGun"); + + if (trace.fraction != 1.0 && !trace.startsolid && !trace.allsolid && trace.ent) { + SafeSetOrigin(trace.endpos); + } + + VectorClear(velocity); + UpdateBoneControllers(); + UpdateFootsteps(); } -bool Actor::MachineGunner_CanSee - ( - Entity *ent, - float fov, - float vision_distance - ) +void Actor::Think_MachineGunner_TurretGun(void) { - float delta[2]; + if (!m_bEnableEnemy) { + ThinkHoldGun_TurretGun(); + return; + } - delta[0] = ent->centroid[0] - centroid[0]; - delta[1] = ent->centroid[1] - centroid[1]; - if ((vision_distance <= 0.0f) || (delta[0] * delta[0] + delta[1] * delta[1]) <= (vision_distance * vision_distance)) - { - if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum) && - ((fov <= 0.0f || fov >= 360.0f) || - (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0)))))) - { - return G_SightTrace(centroid, - vec_zero, - vec_zero, - ent->centroid, - m_pTurret, - ent, - MASK_CANSEE, - 0, - "Actor::MachineGunner_CanSee"); - } - } + if (level.inttime < m_iEnemyCheckTime + 200) { + ThinkHoldGun_TurretGun(); + return; + } - return false; + UpdateEnemyInternal(); + + if (m_Team == TEAM_AMERICAN) { + // Added in 2.30 + ThinkHoldGun_TurretGun(); + return; + } + + if (m_pTurret->AI_CanTarget(G_GetEntity(0)->centroid)) { + ThinkHoldGun_TurretGun(); + return; + } + + if (m_pGrenade && rand() / 21474836.f <= m_fGrenadeAwareness) { + BecomeTurretGuy(); + return; + } + + if (!G_SightTrace( + EyePosition(), + vec_zero, + vec_zero, + static_cast(G_GetEntity(0))->EyePosition(), + this, + G_GetEntity(0), + MASK_CANSEE, + qfalse, + "Actor::Think_MachineGunner" + )) { + ThinkHoldGun_TurretGun(); + return; + } + + if (m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_IDLE) { + BecomeTurretGuy(); + return; + } + + if (m_Enemy && !(m_Enemy->flags & FL_NOTARGET) && !EnemyIsDisguised() && m_PotentialEnemies.IsEnemyConfirmed()) { + BecomeTurretGuy(); + return; + } + + if (m_Enemy && m_iCuriousTime || (m_Enemy && !EnemyIsDisguised() && !m_PotentialEnemies.IsEnemyConfirmed())) { + m_iCuriousAnimHint = 6; + BecomeTurretGuy(); + return; + } + + ThinkHoldGun_TurretGun(); +} + +void Actor::Think_MachineGunner(void) +{ + if (!RequireThink()) { + return; + } + + if (m_pTurret && m_pTurret->GetOwner() == this && !m_bNoPlayerCollision) { + UpdateEyeOrigin(); + Think_MachineGunner_TurretGun(); + } else { + BecomeTurretGuy(); + } +} + +void Actor::FinishedAnimation_MachineGunner(void) +{ + if (!m_bAnimScriptSet && m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) { + TransitionState(ACTOR_STATE_MACHINE_GUNNER_READY, 0); + Unregister(STRING_ANIMDONE); + } +} + +bool Actor::MachineGunner_CanSee(Entity *ent, float fov, float vision_distance) +{ + float delta[2]; + + delta[0] = ent->centroid[0] - centroid[0]; + delta[1] = ent->centroid[1] - centroid[1]; + if ((vision_distance <= 0.0f) + || (delta[0] * delta[0] + delta[1] * delta[1]) <= (vision_distance * vision_distance)) { + if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum) + && ((fov <= 0.0f || fov >= 360.0f) || (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0)))))) { + return G_SightTrace( + centroid, + vec_zero, + vec_zero, + ent->centroid, + m_pTurret, + ent, + MASK_CANSEE, + 0, + "Actor::MachineGunner_CanSee" + ); + } + } + + return false; } diff --git a/code/fgame/actor_noclip.cpp b/code/fgame/actor_noclip.cpp index 738580cb..749cdb91 100644 --- a/code/fgame/actor_noclip.cpp +++ b/code/fgame/actor_noclip.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,87 +24,62 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitNoClip - ( - GlobalFuncs_t *func - ) +void Actor::InitNoClip(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_NoClip; - func->IsState = &Actor::IsIdleState; + func->ThinkState = &Actor::Think_NoClip; + func->IsState = &Actor::IsIdleState; } -bool Actor::IsNoClipState - ( - int state - ) +void Actor::Think_NoClip(void) { - return state == THINKSTATE_NOCLIP; -} - -void Actor::Think_NoClip - ( - void - ) -{ - //FIXME: not sure of naming - bool done = false; - Vector newOrigin = vec_zero; - Vector total_offset; - Vector total_offset_unit; - float total_dist; - //vec3_t frame_offset; - float frame_dist; - - m_pszDebugState = ""; - - ContinueAnimationAllowNoPath(); - - CheckUnregister(); - UpdateAngles(); - UpdateAnim(); - - total_offset = m_NoClipDest - origin; - total_dist = VectorNormalize2(total_offset, total_offset_unit); - - frame_dist = level.frametime * m_maxspeed; - - if (frame_dist >= frame_delta.lengthSquared()) - { - frame_dist = frame_delta.lengthSquared(); - } - - if (frame_dist < total_dist) - { - newOrigin = total_offset_unit * frame_dist + origin; - - } - else - { - done = true; - newOrigin = m_NoClipDest; - } - - SafeSetOrigin(newOrigin); - - velocity = total_offset_unit / level.frametime; - - if (velocity.lengthSquared() < 1) - { - done = true; - velocity = vec_zero; - } - groundentity = NULL; - - if (done) - { - Com_Printf( - "(entnum %d, radnum %d) failsafe finished\n", - entnum, - radnum); - EndCurrentThinkState(); - } - - UpdateBoneControllers(); - UpdateFootsteps(); - + float frame_dist; + vec3_t frame_offset; + float total_dist; + vec3_t total_offset; + Vector newOrigin; + bool done = false; + + m_pszDebugState = ""; + + ContinueAnimationAllowNoPath(); + + CheckUnregister(); + UpdateAngles(); + UpdateAnim(); + + VectorSubtract(m_NoClipDest, origin, total_offset); + total_dist = VectorNormalize2(total_offset, frame_offset); + frame_dist = VectorLength(frame_delta); + + if (frame_dist > m_maxspeed * level.frametime) { + frame_dist = m_maxspeed * level.frametime; + } + + if (frame_dist < total_dist) { + VectorScale(frame_offset, frame_dist, frame_offset); + VectorAdd(origin, frame_offset, newOrigin); + } else { + VectorCopy(m_NoClipDest, newOrigin); + done = true; + } + + SafeSetOrigin(newOrigin); + + velocity[0] = frame_offset[0] / level.frametime; + velocity[1] = frame_offset[1] / level.frametime; + velocity[2] = frame_offset[2] / level.frametime; + + if (VectorLengthSquared(velocity) < 1) { + VectorClear(velocity); + done = true; + } + groundentity = NULL; + + if (done) { + Com_Printf("(entnum %d, radnum %d) failsafe finished\n", entnum, radnum); + EndCurrentThinkState(); + } + + UpdateBoneControllers(); + UpdateFootsteps(); } diff --git a/code/fgame/actor_pain.cpp b/code/fgame/actor_pain.cpp index ca8e8e2f..4deb13bf 100644 --- a/code/fgame/actor_pain.cpp +++ b/code/fgame/actor_pain.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,55 +24,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitPain - ( - GlobalFuncs_t *func - ) +void Actor::InitPain(GlobalFuncs_t *func) { - func->BeginState = &Actor::Begin_Pain; - func->ThinkState = &Actor::Think_Pain; - func->FinishedAnimation = &Actor::FinishedAnimation_Pain; - func->IsState = &Actor::IsPainState; + func->BeginState = &Actor::Begin_Pain; + func->ThinkState = &Actor::Think_Pain; + func->FinishedAnimation = &Actor::FinishedAnimation_Pain; + func->IsState = &Actor::IsPainState; } -void Actor::Begin_Pain - ( - void - ) +void Actor::Begin_Pain(void) { - m_PainState = 500; + m_PainState = ACTOR_STATE_PAIN_INITIAL; } -void Actor::Think_Pain - ( - void - ) +void Actor::Think_Pain(void) { - NoPoint(); + NoPoint(); + ForwardLook(); + UpdateEyeOrigin(); - m_bHasDesiredLookAngles = false; + if (m_PainState == ACTOR_STATE_PAIN_INITIAL) { + m_pszDebugState = "initial"; + Anim_StartPain(); + m_PainState = ACTOR_STATE_PAIN_MAIN; + } else if (m_PainState == ACTOR_STATE_PAIN_MAIN) { + m_pszDebugState = "main"; + Anim_Pain(); + } - UpdateEyeOrigin(); - - if (m_PainState == 500) - { - m_pszDebugState = "initial"; - Anim_StartPain(); - m_PainState = 501; - } - else if (m_PainState == 501) - { - m_pszDebugState = "main"; - Anim_Pain(); - } - PostThink(false); + PostThink(false); } -void Actor::FinishedAnimation_Pain - ( - void - ) +void Actor::FinishedAnimation_Pain(void) { - if (m_PainState != 500) - EndCurrentThinkState(); + if (m_PainState != ACTOR_STATE_PAIN_START) { + EndCurrentThinkState(); + } } diff --git a/code/fgame/actor_patrol.cpp b/code/fgame/actor_patrol.cpp index 77e57e08..bcf9f4ac 100644 --- a/code/fgame/actor_patrol.cpp +++ b/code/fgame/actor_patrol.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,92 +24,77 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitPatrol - ( - GlobalFuncs_t *func - ) +void Actor::InitPatrol(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Patrol; - func->BeginState = &Actor::Begin_Patrol; - func->EndState = &Actor::End_Patrol; - func->ResumeState = &Actor::Resume_Patrol; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->ShowInfo = &Actor::ShowInfo_Patrol; - func->IsState = &Actor::IsIdleState; + func->ThinkState = &Actor::Think_Patrol; + func->BeginState = &Actor::Begin_Patrol; + func->EndState = &Actor::End_Patrol; + func->ResumeState = &Actor::Resume_Patrol; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->ShowInfo = &Actor::ShowInfo_Patrol; + func->IsState = &Actor::IsIdleState; } -void Actor::Begin_Patrol - ( - void - ) +void Actor::Begin_Patrol(void) { - m_csMood = STRING_BORED; - StopTurning(); - ClearPath(); + m_csMood = STRING_BORED; + StopTurning(); + ClearPath(); } -void Actor::End_Patrol - ( - void - ) +void Actor::End_Patrol(void) { - - parm.movefail = true; + parm.movefail = true; } -void Actor::Resume_Patrol - ( - void - ) +void Actor::Resume_Patrol(void) {} + +void Actor::Think_Patrol(void) { - ; + bool bMoveInRadius; + + if (!RequireThink()) { + return; + } + + parm.movefail = false; + + UpdateEyeOrigin(); + NoPoint(); + + m_pszDebugState = ""; + m_csPatrolCurrentAnim = STRING_ANIM_PATROL_SCR; + bMoveInRadius = MoveToPatrolCurrentNode(); + + if (m_fLookAroundFov > 1.0) { + LookAround(m_fLookAroundFov); + } + + CheckForThinkStateTransition(); + + if (!m_patrolCurrentNode) { + SetThinkIdle(THINK_IDLE); + m_bScriptGoalValid = false; + + parm.movedone = true; + Unregister(STRING_MOVEDONE); + } else if (bMoveInRadius) { + ClearPatrolCurrentNode(); + SetThinkIdle(THINK_IDLE); + // Added in OPM + // Not sure why it was not cleared originally. + // Once you reach your goal, there is no point + // in leaving it set to true + m_bScriptGoalValid = false; + + parm.movedone = true; + Unregister(STRING_MOVEDONE); + } + + PostThink(true); } -void Actor::Think_Patrol - ( - void - ) +void Actor::ShowInfo_Patrol(void) { - if (Actor::RequireThink()) - { - parm.movefail = false; - - UpdateEyeOrigin(); - NoPoint(); - - m_pszDebugState = ""; - m_csPatrolCurrentAnim = STRING_ANIM_PATROL_SCR; - - if (m_fLookAroundFov > 1.0) - LookAround(m_fLookAroundFov); - - CheckForThinkStateTransition(); - if (m_patrolCurrentNode) - { - if (!MoveToPatrolCurrentNode()) - { - PostThink(true); - return; - } - } - else - { - SetThinkIdle(THINK_IDLE); - m_bScriptGoalValid = false; - } - parm.movedone = true; - - Unregister(STRING_MOVEDONE); - - PostThink(true); - return; - } -} - -void Actor::ShowInfo_Patrol - ( - void - ) -{ - ShowInfo_PatrolCurrentNode(); + ShowInfo_PatrolCurrentNode(); } diff --git a/code/fgame/actor_runandshoot.cpp b/code/fgame/actor_runandshoot.cpp new file mode 100644 index 00000000..1939dbb2 --- /dev/null +++ b/code/fgame/actor_runandshoot.cpp @@ -0,0 +1,175 @@ +/* +=========================================================================== +Copyright (C) 2023 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// actor_runandshoot.cpp +// +// Added in 2.30 +// + +#include "actor.h" + +void Actor::InitRunAndShoot(GlobalFuncs_t *func) +{ + func->ThinkState = &Actor::Think_RunAndShoot; + func->BeginState = &Actor::Begin_RunAndShoot; + func->EndState = &Actor::End_RunAndShoot; + func->ResumeState = &Actor::Resume_RunAndShoot; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->ShowInfo = &Actor::ShowInfo_RunAndShoot; + func->IsState = &Actor::IsAttackState; +} + +void Actor::Begin_RunAndShoot(void) +{ + if (m_patrolCurrentNode) { + m_State = ACTOR_STATE_RUN_AND_SHOOT_RUNNING; + } else { + m_State = ACTOR_STATE_RUN_AND_SHOOT_RUN; + } +} + +void Actor::End_RunAndShoot(void) +{ + m_vHome = origin; + m_pTetherEnt = NULL; +} + +void Actor::Resume_RunAndShoot(void) {} + +void Actor::Think_RunAndShoot(void) +{ + if (m_State == ACTOR_STATE_RUN_AND_SHOOT_RUNNING) { + State_RunAndShoot_Running(); + } else if (m_State == ACTOR_STATE_RUN_AND_SHOOT_RUN) { + SetThink(THINKSTATE_ATTACK, THINK_COVER); + } +} + +void Actor::ShowInfo_RunAndShoot(void) {} + +void Actor::State_RunAndShoot_Running(void) +{ + Entity *player; + bool bMoveDone; + + if (!RequireThink()) { + return; + } + + parm.movefail = false; + UpdateEyeOrigin(); + NoPoint(); + + m_pszDebugState = ""; + bMoveDone = RunAndShoot_MoveToPatrolCurrentNode(); + + CheckForThinkStateTransition(); + player = G_GetEntity(0); + if (player) { + vec2_t delta; + + VectorSub2D(player->origin, origin, delta); + + if (VectorLength2DSquared(delta) < Square(150)) { + ClearPatrolCurrentNode(); + } + } + + if (!m_patrolCurrentNode) { + if (m_Enemy) { + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + } else { + SetThinkIdle(THINK_IDLE); + } + + m_bScriptGoalValid = false; + parm.movedone = true; + + Unregister(STRING_MOVEDONE); + } else if (bMoveDone) { + ClearPatrolCurrentNode(); + + if (m_Enemy) { + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + } else { + SetThinkIdle(THINK_IDLE); + } + + parm.movedone = true; + + Unregister(STRING_MOVEDONE); + } + + Unregister(STRING_MOVE); + + CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE); + PostThink(true); +} + +bool Actor::RunAndShoot_MoveToPatrolCurrentNode(void) +{ + UpdatePatrolCurrentNode(); + + if (!m_patrolCurrentNode || m_bPatrolWaitTrigger) { + IdleLook(); + Anim_Idle(); + return false; + } + + SetPath(m_patrolCurrentNode->origin, "Actor::RunAndShoot_MoveToPatrolCurrentNode", 0, NULL, 0); + + if (!PathExists()) { + IdleLook(); + Anim_Idle(); + + parm.movefail = true; + return false; + } + + if (MoveOnPathWithSquad()) { + if (m_Enemy) { + DesiredAnimation(ANIM_MODE_PATH, STRING_ANIM_RUNTO_INOPEN_SCR); + AimAtTargetPos(); + } else { + DesiredAnimation(ANIM_MODE_PATH, STRING_ANIM_CROUCH_RUN_SCR); + FaceMotion(); + } + } else if (m_Enemy) { + AimAtTargetPos(); + Anim_Attack(); + } else { + Anim_Stand(); + IdleLook(); + } + + if (m_fMoveDoneRadiusSquared) { + if (PathComplete()) { + return true; + } + + if (m_Path.HasCompleteLookahead() && !m_patrolCurrentNode->Next()) { + return VectorLength2DSquared(PathDelta()) <= m_fMoveDoneRadiusSquared; + } + } + + return false; +} diff --git a/code/fgame/actor_runner.cpp b/code/fgame/actor_runner.cpp index 9aaab8f3..d0c906b9 100644 --- a/code/fgame/actor_runner.cpp +++ b/code/fgame/actor_runner.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,90 +24,74 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitRunner - ( - GlobalFuncs_t *func - ) +void Actor::InitRunner(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Runner; - func->BeginState = &Actor::Begin_Runner; - func->EndState = &Actor::End_Runner; - func->ResumeState = &Actor::Resume_Runner; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; - func->ShowInfo = &Actor::ShowInfo_Runner; - func->IsState = &Actor::IsIdleState; + func->ThinkState = &Actor::Think_Runner; + func->BeginState = &Actor::Begin_Runner; + func->EndState = &Actor::End_Runner; + func->ResumeState = &Actor::Resume_Runner; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle; + func->ShowInfo = &Actor::ShowInfo_Runner; + func->IsState = &Actor::IsIdleState; } -void Actor::Begin_Runner - ( - void - ) +void Actor::Begin_Runner(void) { - m_csMood = STRING_NERVOUS; - m_csIdleMood = STRING_NERVOUS; - StopTurning(); - ClearPath(); + m_csMood = STRING_NERVOUS; + m_csIdleMood = STRING_NERVOUS; + StopTurning(); + ClearPath(); } -void Actor::End_Runner - ( - void - ) +void Actor::End_Runner(void) { - parm.movefail = true; + parm.movefail = true; } -void Actor::Resume_Runner - ( - void - ) +void Actor::Resume_Runner(void) {} + +void Actor::Think_Runner(void) { - ; + bool bMoveInRadius; + + if (!RequireThink()) { + return; + } + + parm.movefail = false; + + UpdateEyeOrigin(); + NoPoint(); + m_pszDebugState = ""; + + bMoveInRadius = MoveToPatrolCurrentNode(); + CheckForThinkStateTransition(); + + if (!m_patrolCurrentNode) { + SetThinkIdle(THINK_IDLE); + m_bScriptGoalValid = false; + + parm.movedone = true; + Unregister(STRING_MOVEDONE); + } else if (bMoveInRadius) { + ClearPatrolCurrentNode(); + SetThinkIdle(THINK_IDLE); + // Added in OPM + // Not sure why it was not cleared originally. + // Once you reach your goal, there is no point + // in leaving it set to true + m_bScriptGoalValid = false; + + parm.movedone = true; + Unregister(STRING_MOVEDONE); + } + + Unregister(STRING_MOVE); + + PostThink(true); } -void Actor::Think_Runner - ( - void - ) +void Actor::ShowInfo_Runner(void) { - if (RequireThink()) - { - parm.movefail = false; - - UpdateEyeOrigin(); - NoPoint(); - m_pszDebugState = ""; - - CheckForThinkStateTransition(); - - if (m_patrolCurrentNode) - { - if (!MoveToPatrolCurrentNode()) - { - Unregister(STRING_MOVE); - PostThink(true); - return; - } - } - else - { - SetThinkIdle(THINK_IDLE); - m_bScriptGoalValid = false; - } - - parm.movedone = true; - Unregister(STRING_MOVEDONE); - - Unregister(STRING_MOVE); - PostThink(true); - return; - } -} - -void Actor::ShowInfo_Runner - ( - void - ) -{ - ShowInfo_PatrolCurrentNode(); + ShowInfo_PatrolCurrentNode(); } diff --git a/code/fgame/actor_turret.cpp b/code/fgame/actor_turret.cpp index 25fbee14..8db46a58 100644 --- a/code/fgame/actor_turret.cpp +++ b/code/fgame/actor_turret.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,1112 +24,866 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitTurret -( - GlobalFuncs_t *func +void Actor::InitTurret(GlobalFuncs_t *func) +{ + func->ThinkState = &Actor::Think_Turret; + func->BeginState = &Actor::Begin_Turret; + func->EndState = &Actor::End_Turret; + func->SuspendState = &Actor::Suspend_Turret; + func->RestartState = NULL; + func->FinishedAnimation = &Actor::FinishedAnimation_Turret; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->PostShoot = &Actor::InterruptPoint_Turret; + func->ReceiveAIEvent = &Actor::ReceiveAIEvent_Turret; + func->IsState = &Actor::IsAttackState; + func->PathnodeClaimRevoked = &Actor::PathnodeClaimRevoked_Turret; +} + +bool Actor::Turret_IsRetargeting(void) const +{ + return m_State > ACTOR_STATE_TURRET_SHOOT && m_State < ACTOR_STATE_TURRET_NUM_STATES; +} + +bool Actor::Turret_DecideToSelectState(void) +{ + switch (m_State) { + case ACTOR_STATE_TURRET_COMBAT: + if (level.inttime > m_iStateTime + 5000) { + InterruptPoint_Turret(); + } + return false; + case ACTOR_STATE_TURRET_REACQUIRE: + case ACTOR_STATE_TURRET_GRENADE: + case ACTOR_STATE_TURRET_TAKE_SNIPER_NODE: + case ACTOR_STATE_TURRET_FAKE_ENEMY: + case ACTOR_STATE_TURRET_SHOOT: + return false; + } + + return !Turret_IsRetargeting(); +} + +void Actor::Turret_SelectState(void) +{ + float fDistSquared; + vec2_t vDelta; + + if (!m_Enemy) { + TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, (rand() & 0x7FF) + 250); + return; + } + + VectorSub2D(origin, m_vHome, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (m_State == ACTOR_STATE_TURRET_RUN_HOME && fDistSquared > (m_fLeashSquared * 0.64 + 64.0)) { + if (PathExists() && !PathComplete()) { + return; + } + } else if (fDistSquared <= m_fLeashSquared * 1.21 + 256.0) { + m_iRunHomeTime = 0; + } else if (!m_iRunHomeTime) { + m_iRunHomeTime = level.inttime + (rand() & 0xFFF) + 1000; + } else if (level.inttime >= m_iRunHomeTime) { + m_iRunHomeTime = 0; + + ClearPath(); + SetPath(m_vHome, NULL, 0, NULL, 0.0); + ShortenPathToAvoidSquadMates(); + + if (!PathExists()) { + Com_Printf( + "^~^~^ (entnum %i, radnum %d, targetname '%s') cannot reach his leash home\n", + entnum, + radnum, + targetname.c_str() + ); + } else if (!PathComplete()) { + TransitionState(ACTOR_STATE_TURRET_RUN_HOME, 0); + return; + } + } + + VectorSub2D(origin, m_Enemy->origin, vDelta); + fDistSquared = VectorLength2DSquared(vDelta); + + if (m_State == ACTOR_STATE_TURRET_RUN_AWAY && fDistSquared < m_fMinDistanceSquared * 2.25) { + return; + } + + if (fDistSquared < m_fMinDistanceSquared) { + ClearPath(); + TransitionState(ACTOR_STATE_TURRET_RUN_AWAY, 0); + return; + } + + if (fDistSquared > m_fMaxDistanceSquared) { + if (m_Team == TEAM_GERMAN && (m_Enemy->origin - m_vHome).lengthSquared() >= Square(m_fLeash + m_fMaxDistance) + && !CanSeeEnemy(200)) { + ClearPath(); + TransitionState(ACTOR_STATE_TURRET_WAIT, 0); + } else if (m_State != ACTOR_STATE_TURRET_CHARGE) { + ClearPath(); + TransitionState(ACTOR_STATE_TURRET_CHARGE, 0); + } + } else { + if (DecideToThrowGrenade(m_vLastEnemyPos + m_Enemy->velocity, &m_vGrenadeVel, &m_eGrenadeMode, false)) { + SetDesiredYawDir(m_vGrenadeVel); + + DesiredAnimation( + ANIM_MODE_NORMAL, + m_eGrenadeMode == AI_GREN_TOSS_ROLL ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR + ); + TransitionState(ACTOR_STATE_TURRET_GRENADE, 0); + return; + } + + if (m_State != ACTOR_STATE_TURRET_COMBAT && m_State != ACTOR_STATE_TURRET_SNIPER_NODE + && m_State != ACTOR_STATE_TURRET_WAIT && m_State != ACTOR_STATE_TURRET_SHOOT) { + ClearPath(); + TransitionState(ACTOR_STATE_TURRET_COMBAT); + } + } +} + +bool Actor::Turret_CheckRetarget(void) +{ + if (level.inttime < m_iStateTime + 5000 || level.inttime < m_iLastHitTime + 5000) { + return false; + } + + Turret_BeginRetarget(); + + return true; +} + +void Actor::Begin_Turret(void) +{ + DoForceActivate(); + m_csMood = STRING_ALERT; + + ClearPath(); + + if (m_Enemy) { + TransitionState(ACTOR_STATE_TURRET_COVER_INSTEAD, 0); + } else { + TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, (rand() & 0x7FF) + 250); + } +} + +void Actor::End_Turret(void) +{ + if (m_pCoverNode && m_State != ACTOR_STATE_TURRET_BECOME_COVER) { + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + } + TransitionState(-1, 0); +} + +void Actor::Suspend_Turret(void) +{ + if (!m_Enemy) { + TransitionState(ACTOR_STATE_TURRET_COVER_INSTEAD, 0); + } else if (m_State == ACTOR_STATE_TURRET_GRENADE || m_State == ACTOR_STATE_TURRET_INTRO_AIM) { + Turret_BeginRetarget(); + } +} + +void Actor::State_Turret_Combat(void) +{ + if (CanSeeEnemy(200)) { + ClearPath(); + Anim_Attack(); + AimAtTargetPos(); + Turret_CheckRetarget(); + return; + } + + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { + SetPathWithLeash(m_vLastEnemyPos, NULL, 0); + ShortenPathToAvoidSquadMates(); + } + + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { + FindPathNearWithLeash(m_vLastEnemyPos, m_fMinDistanceSquared * 4); + if (!ShortenPathToAttack(0.0)) { + ClearPath(); + } + ShortenPathToAvoidSquadMates(); + } + + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { + m_pszDebugState = "combat->chill"; + Turret_BeginRetarget(); + return; + } + + m_pszDebugState = "combat->move"; + if (!MovePathWithLeash()) { + m_pszDebugState = "combat->move->aim"; + Turret_BeginRetarget(); + return; + } + + Turret_CheckRetarget(); +} + +void Actor::Turret_BeginRetarget(void) +{ + SetEnemyPos(m_Enemy->origin); + AimAtEnemyBehavior(); + + // Replaced in 2.0 + // Use the Retarget_Suppress state instead of the Retarget_Sniper_Node state + if (g_target_game >= target_game_e::TG_MOHTA) { + TransitionState(ACTOR_STATE_TURRET_RETARGET_SUPPRESS, 0); + } else { + TransitionState(ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE, 0); + } +} + +void Actor::Turret_NextRetarget(void) +{ + vec2_t vDelta; + + m_State++; + if (m_State < ACTOR_STATE_TURRET_NUM_STATES) { + TransitionState(m_State); + return; + } + + VectorSub2D(origin, m_vHome, vDelta); + + if (VectorLength2DSquared(vDelta) >= m_fLeashSquared) { + SetPath(m_vHome, NULL, 0, NULL, 0.0); + ShortenPathToAvoidSquadMates(); + + if (PathExists() && !PathComplete()) { + TransitionState(ACTOR_STATE_TURRET_RUN_HOME, 0); + State_Turret_RunHome(true); + return; + } + } + + if (m_Team == TEAM_AMERICAN) { + if (!CanSeeEnemy(200)) { + m_PotentialEnemies.FlagBadEnemy(m_Enemy); + UpdateEnemy(-1); + } + + if (!m_Enemy) { + Anim_Stand(); + return; + } + + TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + State_Turret_Combat(); + } else if (CanSeeEnemy(200)) { + m_pszDebugState = "Retarget->Combat"; + TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + State_Turret_Combat(); + } else { + TransitionState(ACTOR_STATE_TURRET_WAIT, 0); + State_Turret_Wait(); + } +} + +void Actor::Turret_SideStep(int iStepSize, vec3_t vDir) +{ + AimAtEnemyBehavior(); + StrafeToAttack(iStepSize, vDir); + + if (PathExists() && !PathComplete() && PathAvoidsSquadMates()) { + TransitionState(ACTOR_STATE_TURRET_REACQUIRE); + return; + } + + StrafeToAttack(-iStepSize, vDir); + + if (PathExists() && !PathComplete() && PathAvoidsSquadMates()) { + TransitionState(ACTOR_STATE_TURRET_REACQUIRE); + return; + } + + Turret_NextRetarget(); +} + +void Actor::State_Turret_Shoot(void) +{ + assert(g_target_game > target_game_e::TG_MOH); + + if (CanSeeEnemy(200) || FriendlyInLineOfFire(m_Enemy)) { + TransitionState(ACTOR_STATE_TURRET_COMBAT); + State_Turret_Combat(); + return; + } + + if (level.inttime >= m_iStateTime + 15000) { + Turret_SelectState(); + if (m_State == ACTOR_STATE_TURRET_SHOOT) { + Turret_BeginRetarget(); + } + } +} + +void Actor::State_Turret_Retarget_Suppress(void) +{ + trace_t trace; + + assert(g_target_game > target_game_e::TG_MOH); + + if (rand() % 100 >= m_iSuppressChance) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + if (level.inttime >= m_iLastEnemyVisibleTime + 15000) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + if (FriendlyInLineOfFire(m_Enemy)) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + trace = G_Trace( + EyePosition(), + vec_zero, + vec_zero, + m_Enemy->EyePosition(), + this, + MASK_CANSEE, + qfalse, + "Actor::State_Turret_Retarget_Suppress" + ); + if (trace.fraction <= 0.5f) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + if (trace.fraction != 1.f && trace.plane.normal[2] >= 0.7f) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + TransitionState(ACTOR_STATE_TURRET_SHOOT); + State_Turret_Shoot(); +} + +void Actor::State_Turret_Retarget_Sniper_Node(void) +{ + PathNode *pSniperNode; + bool bTryAgain; + + AimAtEnemyBehavior(); + if (m_pCoverNode) { + m_pCoverNode->Relinquish(); + m_pCoverNode = NULL; + } + + pSniperNode = FindSniperNodeAndSetPath(&bTryAgain); + if (pSniperNode) { + m_pCoverNode = pSniperNode; + pSniperNode->Claim(this); + TransitionState(ACTOR_STATE_TURRET_TAKE_SNIPER_NODE); + State_Turret_TakeSniperNode(); + } else if (bTryAgain) { + ContinueAnimation(); + } else { + Turret_NextRetarget(); + } +} + +void Actor::State_Turret_Retarget_Step_Side_Small(void) +{ + Turret_SideStep((rand() & 64) - 32, orientation[1]); +} + +void Actor::State_Turret_Retarget_Path_Exact(void) +{ + AimAtEnemyBehavior(); + SetPathWithLeash(m_vLastEnemyPos, NULL, 0); + + if (!ShortenPathToAttack(128)) { + Turret_NextRetarget(); + return; + } + + ShortenPathToAvoidSquadMates(); + + if (!PathExists()) { + Turret_NextRetarget(); + return; + } + + TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); +} + +void Actor::State_Turret_Retarget_Path_Near(void) +{ + AimAtEnemyBehavior(); + FindPathNearWithLeash(m_vLastEnemyPos, m_fMinDistanceSquared); + + if (ShortenPathToAttack(128)) { + TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); + } else { + Turret_NextRetarget(); + } +} + +void Actor::State_Turret_Retarget_Step_Side_Medium(void) +{ + Turret_SideStep((rand() & 256) - 128, orientation[1]); +} + +void Actor::State_Turret_Retarget_Step_Side_Large(void) +{ + Turret_SideStep((rand() & 512) - 256, orientation[1]); +} + +void Actor::State_Turret_Retarget_Step_Face_Medium(void) +{ + Turret_SideStep((rand() & 256) - 128, orientation[0]); +} + +void Actor::State_Turret_Retarget_Step_Face_Large(void) +{ + Turret_SideStep((rand() & 512) - 256, orientation[0]); +} + +void Actor::State_Turret_Reacquire(void) +{ + if (!PathExists() || PathComplete()) { + m_pszDebugState = "Retarget->Cheat"; + SetEnemyPos(m_Enemy->origin); + TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + State_Turret_Combat(); + return; + } + + if (CanMovePathWithLeash()) { + Anim_RunToInOpen(ANIM_MODE_PATH_GOAL); + FaceEnemyOrMotion(level.inttime - m_iStateTime); + } else { + Turret_BeginRetarget(); + } +} + +void Actor::State_Turret_TakeSniperNode(void) +{ + if (!PathExists() || PathComplete()) { + AimAtEnemyBehavior(); + TransitionState(ACTOR_STATE_TURRET_SNIPER_NODE, 0); + return; + } + + FaceMotion(); + Anim_RunToDanger(ANIM_MODE_PATH_GOAL); +} + +void Actor::State_Turret_SniperNode(void) +{ + AimAtTargetPos(); + Anim_Sniper(); + + if (Turret_CheckRetarget()) { + m_pCoverNode->Relinquish(); + m_pCoverNode->MarkTemporarilyBad(); + m_pCoverNode = NULL; + } +} + +bool Actor::State_Turret_RunHome(bool bAttackOnFail) +{ + SetPath(m_vHome, NULL, 0, NULL, 0.0); + ShortenPathToAvoidSquadMates(); + + if (!PathExists() || PathComplete()) { + Com_Printf( + "^~^~^ (entnum %i, radnum %i, targetname '%s') cannot reach his leash home\n", + entnum, + radnum, + targetname.c_str() + ); + if (bAttackOnFail) { + m_pszDebugState = "home->combat"; + State_Turret_Combat(); + } + return false; + } + + FaceMotion(); + Anim_RunToInOpen(ANIM_MODE_PATH); + return true; +} + +void Actor::State_Turret_RunAway(void) +{ + if (!PathExists() || PathComplete()) { + FindPathAwayWithLeash(m_vLastEnemyPos, origin - m_Enemy->origin, 1.5 * m_fMinDistance); + } + + if (!PathExists() || PathComplete()) { + m_pszDebugState = "runaway->combat"; + State_Turret_Combat(); + return; + } + + if (!CanMovePathWithLeash()) { + m_pszDebugState = "runaway->leash->combat"; + State_Turret_Combat(); + return; + } + + Anim_RunAwayFiring(ANIM_MODE_PATH); + FaceEnemyOrMotion(level.inttime - m_iStateTime); +} + +void Actor::State_Turret_Charge(void) +{ + SetPathWithLeash(m_vLastEnemyPos, NULL, 0); + ShortenPathToAvoidSquadMates(); + + if (!PathExists()) { + m_pszDebugState = "charge->near"; + FindPathNearWithLeash(m_vLastEnemyPos, m_fMaxDistanceSquared); + + if (!ShortenPathToAttack(0)) { + ClearPath(); + } + } + + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { + ClearPath(); + + if (CanSeeEnemy(500)) { + m_pszDebugState = "charge->combat"; + State_Turret_Combat(); + return; + } + + m_pszDebugState = "charge->chill"; + + ForwardLook(); + Anim_Idle(); + + if (m_Team == TEAM_AMERICAN || m_PotentialEnemies.HasAlternateEnemy()) { + m_PotentialEnemies.FlagBadEnemy(m_Enemy); + UpdateEnemy(-1); + } + + if (m_Enemy) { + Turret_CheckRetarget(); + } + } else if (!MovePathWithLeash()) { + m_pszDebugState = "charge->leash->combat"; + TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + State_Turret_Combat(); + return; + } +} + +void Actor::State_Turret_Grenade(void) +{ + GenericGrenadeTossThink(); +} + +void Actor::State_Turret_FakeEnemy(void) +{ + AimAtTargetPos(); + Anim_Aim(); + + if (level.inttime >= m_iStateTime) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + } +} + +void Actor::State_Turret_Wait(void) +{ + PathNode *pNode; + + if (CanSeeEnemy(500) || CanShootEnemy(500)) { + if (Turret_TryToBecomeCoverGuy()) { + m_pszDebugState = "Wait->CoverInstead"; + ContinueAnimation(); + } else { + m_pszDebugState = "Wait->Combat"; + TransitionState(ACTOR_STATE_TURRET_COMBAT); + State_Turret_Combat(); + } + return; + } + + if (level.inttime >= m_iLastEnemyVisibleTime + 25000) { + m_iLastEnemyVisibleTime = level.inttime; + m_vLastEnemyPos = m_Enemy->origin; + Turret_BeginRetarget(); + } + + if (level.inttime >= m_iLastFaceDecideTime + 1500) { + m_iLastFaceDecideTime = level.inttime + (rand() & 0x1FF); + + pNode = PathManager.FindCornerNodeForExactPath(this, m_Enemy, 0); + + if (pNode) { + SetDesiredYawDest(pNode->m_PathPos); + m_eDontFaceWallMode = 6; + } else { + AimAtTargetPos(); + DontFaceWall(); + } + } + + if (m_eDontFaceWallMode == 7 || m_eDontFaceWallMode == 8) { + Anim_Stand(); + } else { + Anim_Aim(); + } +} + +void Actor::Think_Turret(void) +{ + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + NoPoint(); + UpdateEnemy(200); + + if (m_Enemy && m_State == ACTOR_STATE_TURRET_COVER_INSTEAD) { + if (!m_bTurretNoInitialCover && Turret_TryToBecomeCoverGuy()) { + m_pszDebugState = "CoverInstead"; + + CheckUnregister(); + UpdateAngles(); + DoMove(); + UpdateBoneControllers(); + UpdateFootsteps(); + return; + } + + m_bTurretNoInitialCover = false; + Turret_SelectState(); + + if (m_State == ACTOR_STATE_TURRET_COMBAT && !CanSeeEnemy(0)) { + Turret_BeginRetarget(); + } + + SetLeashHome(origin); + + if (level.inttime < m_iEnemyChangeTime + 200 && AttackEntryAnimation()) { + TransitionState(ACTOR_STATE_TURRET_INTRO_AIM); + m_bLockThinkState = true; + } + } + + if (level.inttime > m_iStateTime + 3000) { + Turret_SelectState(); + } + + if (m_State == ACTOR_STATE_TURRET_INTRO_AIM) { + m_pszDebugState = "IntroAnim"; + AimAtTargetPos(); + ContinueAnimation(); + + if (m_State == ACTOR_STATE_TURRET_WAIT) { + PostThink(false); + } else { + PostThink(true); + } + return; + } + + m_bLockThinkState = false; + + if (!m_Enemy && m_State != ACTOR_STATE_TURRET_FAKE_ENEMY && m_State != ACTOR_STATE_TURRET_RUN_HOME) { + TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, (rand() + 250) & 0x7FF); + } + + if (!m_Enemy && m_State != ACTOR_STATE_TURRET_FAKE_ENEMY) { + if (m_State != ACTOR_STATE_TURRET_RUN_HOME + || (origin - m_vHome).lengthXYSquared() <= (m_fLeashSquared * 0.64f + 64.0f) + || !State_Turret_RunHome(false)) { + m_pszDebugState = "Idle"; + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + IdleThink(); + } else { + m_pszDebugState = "Idle->RunHome"; + PostThink(true); + } + return; + } + + if (m_Enemy && m_State == ACTOR_STATE_TURRET_FAKE_ENEMY) { + Turret_BeginRetarget(); + } + + if (Turret_DecideToSelectState()) { + Turret_SelectState(); + } + + switch (m_State) { + case ACTOR_STATE_TURRET_COMBAT: + m_pszDebugState = "Combat"; + State_Turret_Combat(); + break; + case ACTOR_STATE_TURRET_REACQUIRE: + m_pszDebugState = "Reacquire"; + State_Turret_Reacquire(); + break; + case ACTOR_STATE_TURRET_TAKE_SNIPER_NODE: + m_pszDebugState = "TakeSniperNode"; + State_Turret_TakeSniperNode(); + break; + case ACTOR_STATE_TURRET_SNIPER_NODE: + m_pszDebugState = "SniperNode"; + State_Turret_SniperNode(); + break; + case ACTOR_STATE_TURRET_RUN_HOME: + m_pszDebugState = "RunHome"; + State_Turret_RunHome(true); + break; + case ACTOR_STATE_TURRET_RUN_AWAY: + m_pszDebugState = "RunAway"; + State_Turret_RunAway(); + break; + case ACTOR_STATE_TURRET_CHARGE: + m_pszDebugState = "Charge"; + State_Turret_Charge(); + break; + case ACTOR_STATE_TURRET_GRENADE: + m_pszDebugState = "Grenade"; + State_Turret_Grenade(); + break; + case ACTOR_STATE_TURRET_FAKE_ENEMY: + m_pszDebugState = "FakeEnemy"; + State_Turret_FakeEnemy(); + break; + case ACTOR_STATE_TURRET_BECOME_COVER: + m_pszDebugState = "BecomeCover"; + ContinueAnimation(); + break; + case ACTOR_STATE_TURRET_WAIT: + m_pszDebugState = "Wait"; + State_Turret_Wait(); + break; + case ACTOR_STATE_TURRET_SHOOT: + m_pszDebugState = "Shoot"; + State_Turret_Shoot(); + break; + case ACTOR_STATE_TURRET_RETARGET_SUPPRESS: + m_pszDebugState = "Retarget_Suppress"; + State_Turret_Retarget_Suppress(); + break; + case ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE: + m_pszDebugState = "Retarget_Sniper_Node"; + State_Turret_Retarget_Sniper_Node(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_SMALL: + m_pszDebugState = "Retarget_Step_Side_Small"; + State_Turret_Retarget_Step_Side_Small(); + break; + case ACTOR_STATE_TURRET_RETARGET_PATH_EXACT: + m_pszDebugState = "Retarget_Path_Exact"; + State_Turret_Retarget_Path_Exact(); + break; + case ACTOR_STATE_TURRET_RETARGET_PATH_NEAR: + m_pszDebugState = "Retarget_Path_Near"; + State_Turret_Retarget_Path_Near(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_MEDIUM: + m_pszDebugState = "Retarget_Step_Side_Medium"; + State_Turret_Retarget_Step_Side_Medium(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_LARGE: + m_pszDebugState = "Retarget_Step_Side_Large"; + State_Turret_Retarget_Step_Side_Large(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_FACE_MEDIUM: + m_pszDebugState = "Retarget_Step_Face_Medium"; + State_Turret_Retarget_Step_Face_Medium(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE: + m_pszDebugState = "Retarget_Step_Face_Large"; + State_Turret_Retarget_Step_Face_Large(); + break; + default: + Com_Printf("Actor::Think_Turret: invalid think state %i\n", m_State); + assert(!"invalid think state"); + break; + } + + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_BADPLACE, THINKLEVEL_IDLE); + } + + if (m_State == ACTOR_STATE_TURRET_WAIT) { + PostThink(false); + } else { + PostThink(true); + } +} + +void Actor::ReceiveAIEvent_Turret( + vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared ) { - func->ThinkState = &Actor::Think_Turret; - func->BeginState = &Actor::Begin_Turret; - func->EndState = &Actor::End_Turret; - func->SuspendState = &Actor::Suspend_Turret; - func->RestartState = NULL; - func->FinishedAnimation = &Actor::FinishedAnimation_Turret; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; - func->PostShoot = &Actor::InterruptPoint_Turret; - func->ReceiveAIEvent = &Actor::ReceiveAIEvent_Turret; - func->IsState = &Actor::IsAttackState; - func->PathnodeClaimRevoked = &Actor::PathnodeClaimRevoked_Turret; + if (iType == AI_EVENT_WEAPON_IMPACT && m_Enemy && fDistSquared <= Square(128)) { + Turret_TryToBecomeCoverGuy(); + return; + } + + DefaultReceiveAIEvent(origin, iType, originator, fDistSquared, fMaxDistSquared); } -void Actor::Begin_Turret -( - void -) +bool Actor::Turret_TryToBecomeCoverGuy(void) { - DoForceActivate(); - m_csMood = STRING_ALERT; + PathNode *pOldCover = m_pCoverNode; - ClearPath(); + Cover_FindCover(true); - if (m_Enemy) - { - TransitionState(110, 0); - } - else - { - TransitionState(109, (rand() & 0x7FF) + 250); - } + if (m_pCoverNode) { + TransitionState(ACTOR_STATE_TURRET_BECOME_COVER, 0); + SetThink(THINKSTATE_ATTACK, THINK_COVER); + return true; + } + + if (pOldCover) { + m_pCoverNode = pOldCover; + m_pCoverNode->Claim(this); + } + + return false; } -void Actor::End_Turret -( - void -) +void Actor::FinishedAnimation_Turret(void) { - if (m_pCoverNode && m_State != 111) - { - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - } - TransitionState(-1, 0); + if (m_State == ACTOR_STATE_TURRET_GRENADE || m_State == ACTOR_STATE_TURRET_INTRO_AIM + || m_State == ACTOR_STATE_TURRET_SHOOT) { + Turret_SelectState(); + } } -void Actor::Suspend_Turret -( - void -) +void Actor::InterruptPoint_Turret(void) { - if (!m_Enemy) - { - TransitionState(110, 0); - } - else - { - if (m_State <= 108) - { - SetEnemyPos(m_Enemy->origin); - AimAtEnemyBehavior(); - TransitionState(113, 0); - } - } + if (m_Enemy && !Turret_TryToBecomeCoverGuy() && m_State == ACTOR_STATE_TURRET_COMBAT) { + m_iStateTime = level.inttime; + Turret_SelectState(); + } } -void Actor::Think_Turret -( - void -) +void Actor::PathnodeClaimRevoked_Turret(void) { - - - if (RequireThink()) - { - UpdateEyeOrigin(); - NoPoint(); - UpdateEnemy(200); - - if (m_Enemy && m_State == 110) - { - if (!m_bTurretNoInitialCover && Turret_TryToBecomeCoverGuy()) - { - m_pszDebugState = "CoverInstead"; - CheckUnregister(); - UpdateAngles(); - DoMove(); - UpdateBoneControllers(); - UpdateFootsteps(); - return; - } - - m_bTurretNoInitialCover = false; - - Turret_SelectState(); - - if (m_State == 100 && !CanSeeEnemy(0)) - { - Turret_BeginRetarget(); - } - - SetLeashHome(origin); - - if (level.inttime < m_iEnemyChangeTime + 200) - { - if (AttackEntryAnimation()) - { - m_bLockThinkState = true; - TransitionState(108, 0); - } - } - } - - if (level.inttime > m_iStateTime + 3000) - Turret_SelectState(); - - if (m_State == 108) - { - m_pszDebugState = "IntroAnim"; - AimAtTargetPos(); - ContinueAnimation(); - } - else - { - m_bLockThinkState = false; - if (!m_Enemy && m_State != 109 && m_State != 104) - { - TransitionState(109, ((rand() + 250) & 0x7FF)); - } - if (!m_Enemy) - { - if (m_State != 109) - { - if (m_State != 104 - || (origin - m_vHome).lengthXYSquared() <= 0.64f * m_fLeashSquared + 64.0f - || !State_Turret_RunHome(false)) - { - m_pszDebugState = "Idle"; - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - IdleThink(); - } - else - { - m_pszDebugState = "Idle->RunHome"; - PostThink(true); - } - return; - } - } - if (m_Enemy && m_State == 109) - { - Turret_BeginRetarget(); - } - - if (Turret_DecideToSelectState()) - Turret_SelectState(); - - switch (m_State) - { - case 100: - m_pszDebugState = "Combat"; - State_Turret_Combat(); - break; - case 101: - m_pszDebugState = "Reacquire"; - State_Turret_Reacquire(); - break; - case 102: - m_pszDebugState = "TakeSniperNode"; - if (!PathExists() || PathComplete()) - { - AimAtEnemyBehavior(); - TransitionState(103, 0); - } - else - { - FaceMotion(); - Anim_RunToDanger(3); - } - break; - case 103: - m_pszDebugState = "SniperNode"; - State_Turret_SniperNode(); - break; - case 104: - m_pszDebugState = "RunHome"; - State_Turret_RunHome(true); - break; - case 105: - m_pszDebugState = "RunAway"; - State_Turret_RunAway(); - break; - case 106: - m_pszDebugState = "Charge"; - State_Turret_Charge(); - break; - case 107: - m_pszDebugState = "Grenade"; - State_Turret_Grenade(); - break; - case 109: - m_pszDebugState = "FakeEnemy"; - State_Turret_FakeEnemy(); - break; - case 111: - m_pszDebugState = "BecomeCover"; - ContinueAnimation(); - break; - case 112: - m_pszDebugState = "Wait"; - State_Turret_Wait(); - break; - case 113: - m_pszDebugState = "Retarget_Sniper_Node"; - State_Turret_Retarget_Sniper_Node(); - break; - case 114: - m_pszDebugState = "Retarget_Step_Side_Small"; - State_Turret_Retarget_Step_Side_Small(); - break; - case 115: - m_pszDebugState = "Retarget_Path_Exact"; - State_Turret_Retarget_Path_Exact(); - break; - case 116: - m_pszDebugState = "Retarget_Path_Near"; - State_Turret_Retarget_Path_Near(); - break; - case 117: - m_pszDebugState = "Retarget_Step_Side_Medium"; - State_Turret_Retarget_Step_Side_Medium(); - break; - case 118: - m_pszDebugState = "Retarget_Step_Side_Large"; - State_Turret_Retarget_Step_Side_Large(); - break; - case 119: - m_pszDebugState = "Retarget_Step_Face_Medium"; - State_Turret_Retarget_Step_Face_Medium(); - break; - case 120: - m_pszDebugState = "Retarget_Step_Face_Large"; - State_Turret_Retarget_Step_Face_Large(); - break; - default: - Com_Printf("Actor::Think_Turret: invalid think state %i\n", m_State); - assert(!"invalid think state"); - break; - } - CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL); - } - if (m_State == 112) - { - PostThink(false); - } - else - { - PostThink(true); - } - } -} - -void Actor::FinishedAnimation_Turret -( - void -) -{ - if (m_State <= 108) - { - Turret_SelectState(); - } -} - -void Actor::ReceiveAIEvent_Turret -( - vec3_t event_origin, - int iType, - Entity *originator, - float fDistSquared, - float fMaxDistSquared -) -{ - if (iType == AI_EVENT_WEAPON_IMPACT) - { - if (m_Enemy && fDistSquared <= Square(128)) - { - Turret_TryToBecomeCoverGuy(); - } - } - else - { - DefaultReceiveAIEvent( - origin, - iType, - originator, - fDistSquared, - fMaxDistSquared); - } -} - -void Actor::InterruptPoint_Turret -( - void -) -{ - if (m_Enemy && !Turret_TryToBecomeCoverGuy() && m_State == 100) - { - m_iStateTime = level.inttime; - Turret_SelectState(); - } -} - -void Actor::PathnodeClaimRevoked_Turret -( - void -) -{ - if (m_Enemy == NULL) - { - TransitionState(110, 0); - } - else - { - Turret_BeginRetarget(); - } -} - -bool Actor::Turret_IsRetargeting -( - void -) const -{ - return m_State <= 120; -} - -bool Actor::Turret_DecideToSelectState -( - void -) -{ - switch (m_State) - { - case 100: - if (level.inttime > m_iStateTime + 5000) - { - InterruptPoint_Turret(); - } - return false; - case 101: - case 107: - case 102: - case 109: - return false; - } - return !Turret_IsRetargeting(); -} - -void Actor::Turret_SelectState -( - void -) -{ - vec2_t vDelta; - float fDistSquared; - if (!m_Enemy) - { - TransitionState(109, rand() & 0x7FF + 250); - return; - } - - VectorSub2D(origin, m_vHome, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - - if (m_State == 104 && fDistSquared > m_fLeashSquared * 0.64 + 64.0) - { - if (PathExists() && !PathComplete()) - return; - } - else if (fDistSquared <= m_fLeashSquared * 1.21 + 256.0) - { - m_iRunHomeTime = 0; - } - else if (m_iRunHomeTime == 0) - { - m_iRunHomeTime = level.inttime + (rand() & 0xFFF) + 1000; - } - else if (level.inttime >= m_iRunHomeTime) - { - m_iRunHomeTime = 0; - - ClearPath(); - SetPath(m_vHome, NULL, 0, NULL, 0.0); - ShortenPathToAvoidSquadMates(); - - if (PathExists() && !PathComplete()) - { - TransitionState(104, 0); - return; - } - else - { - Com_Printf( - "^~^~^ (entnum %i, radnum %d, targetname '%s') cannot reach his leash home\n", - entnum, - radnum, - targetname.c_str()); - } - } - - VectorSub2D(origin, m_Enemy->origin, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - - if (m_State == 105) - { - if (m_fMinDistanceSquared * 2.25 > fDistSquared) - return; - } - - if (m_fMinDistanceSquared > fDistSquared) - { - ClearPath(); - TransitionState(105, 0); - return; - } - - if (fDistSquared > m_fMaxDistanceSquared) - { - bool bSmthing = false; - if (m_Team == TEAM_GERMAN) - { - if ((m_Enemy->origin - m_vHome).lengthSquared() >= Square(m_fLeash + m_fMaxDistance) && !CanSeeEnemy(200)) - bSmthing = true; - } - if (bSmthing) - { - ClearPath(); - TransitionState(112, 0); - } - else - { - if (m_State == 106) - return; - ClearPath(); - TransitionState(106, 0); - } - return; - } - - if (DecideToThrowGrenade(m_Enemy->velocity + m_vLastEnemyPos, &m_vGrenadeVel, &m_eGrenadeMode)) - { - m_bNextForceStart = false; - SetDesiredYawDir(m_vGrenadeVel); - - m_eNextAnimMode = 1; - m_csNextAnimString = (m_eGrenadeMode == AI_GREN_TOSS_ROLL) ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR; - TransitionState(107, 0); - return; - } - - if (m_State != 100 && m_State != 103 && m_State != 112) - { - ClearPath(); - TransitionState(100, 0); - } -} - -bool Actor::Turret_CheckRetarget -( - void -) -{ - if (level.inttime < m_iStateTime + 5000 || level.inttime < m_iLastHitTime + 5000) - return false; - - Turret_BeginRetarget(); - - return true; -} - -bool Actor::Turret_TryToBecomeCoverGuy -( - void -) -{ - PathNode* pOldCover = m_pCoverNode; - Cover_FindCover(true); - if (m_pCoverNode) - { - TransitionState(111, 0); - SetThink(THINKSTATE_ATTACK, THINK_COVER); - return true; - } - else - { - if (pOldCover) - { - m_pCoverNode = pOldCover; - m_pCoverNode->Claim(this); - } - return false; - } -} - -void Actor::Turret_BeginRetarget -( - void -) -{ - SetEnemyPos(m_Enemy->origin); - AimAtEnemyBehavior(); - - TransitionState(113, 0); - -} - -void Actor::Turret_NextRetarget -( - void -) -{ - vec2_t vDelta; - float fDistSquared; - - - m_State++; - - if (Turret_IsRetargeting()) - { - m_iStateTime = level.inttime; - return; - } - - VectorSub2D(origin, m_vHome, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - - if (fDistSquared >= m_fLeashSquared) - { - SetPath(m_vHome, NULL, 0, NULL, 0.0); - ShortenPathToAvoidSquadMates(); - if (PathExists() && !PathComplete()) - { - TransitionState(104, 0); - State_Turret_RunHome(true); - return; - } - } - - if (m_Team == TEAM_AMERICAN) - { - if (!CanSeeEnemy(200)) - { - m_PotentialEnemies.FlagBadEnemy(m_Enemy); - UpdateEnemy(-1); - } - if (!m_Enemy) - { - Anim_Stand(); - return; - } - TransitionState(100, 0); - State_Turret_Combat(); - - } - else - { - if (CanSeeEnemy(200)) - { - m_pszDebugState = "Retarget->Combat"; - TransitionState(100, 0); - State_Turret_Combat(); - } - else - { - TransitionState(112, 0); - State_Turret_Wait(); - } - } -} - -void Actor::Turret_SideStep -( - int iStepSize, - vec3_t vDir -) -{ - AimAtEnemyBehavior(); - //v3 = iStepSize; - StrafeToAttack(iStepSize, vDir); - if ((PathExists() - && !PathComplete() - && PathAvoidsSquadMates()) - || ((StrafeToAttack(-iStepSize, vDir), - PathExists()) - && !PathComplete() - && PathAvoidsSquadMates())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Combat -( - void -) -{ - if (CanSeeEnemy(200)) - { - ClearPath(); - Anim_Attack(); - AimAtTargetPos(); - Turret_CheckRetarget(); - return; - } - if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) - { - SetPathWithLeash(m_vLastEnemyPos, NULL, 0); - ShortenPathToAvoidSquadMates(); - } - if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) - { - FindPathNearWithLeash(m_vLastEnemyPos, 4.0 * m_fMinDistanceSquared); - if (!ShortenPathToAttack(0.0)) - ClearPath(); - ShortenPathToAvoidSquadMates(); - } - if (!PathExists() - || PathComplete() - || !PathAvoidsSquadMates()) - { - m_pszDebugState = "combat->chill"; - Turret_BeginRetarget(); - } - else - { - m_pszDebugState = "combat->move"; - if (!MovePathWithLeash()) - { - m_pszDebugState = "combat->move->aim"; - Turret_BeginRetarget(); - } - else - { - Turret_CheckRetarget(); - } - } - -} - -void Actor::State_Turret_Reacquire -( - void -) -{ - /*Sentient *v1; // ecx - float v2; // ST08_4 - float v3; // ST0C_4 - Sentient *v4; // ecx - float v5; // ST08_4 - float v6; // ST0C_4 - */ - if (PathExists() && !PathComplete()) - { - if (CanMovePathWithLeash()) - { - Anim_RunToInOpen(3); - FaceEnemyOrMotion(level.inttime - m_iStateTime); - } - else - { - Turret_BeginRetarget(); - } - } - else - { - m_pszDebugState = "Retarget->Cheat"; - SetEnemyPos(m_Enemy->origin); - TransitionState(100, 0); - State_Turret_Combat(); - } -} - -void Actor::State_Turret_TakeSniperNode -( - void -) -{ - if (PathExists() && !PathComplete()) - { - FaceMotion(); - Anim_RunToDanger(3); - } - else - { - AimAtEnemyBehavior(); - TransitionState(103, 0); - } -} - -void Actor::State_Turret_SniperNode -( - void -) -{ - AimAtTargetPos(); - Anim_Sniper(); - if (Turret_CheckRetarget()) - { - m_pCoverNode->Relinquish(); - m_pCoverNode->MarkTemporarilyBad(); - m_pCoverNode = NULL; - } -} - -bool Actor::State_Turret_RunHome -( - bool bAttackOnFail -) -{ - - SetPath(m_vHome, NULL, 0, NULL, 0.0); - ShortenPathToAvoidSquadMates(); - if (!PathExists() || PathComplete()) - { - Com_Printf( - "^~^~^ (entnum %i, radnum %i, targetname '%s') cannot reach his leash home\n", - entnum, - radnum, - targetname.c_str()); - if (bAttackOnFail) - { - m_pszDebugState = "home->combat"; - State_Turret_Combat(); - } - return false; - } - else - { - FaceMotion(); - Anim_RunToInOpen(2); - return true; - } -} - -void Actor::State_Turret_RunAway -( - void -) -{ - if (!PathExists() || PathComplete()) - { - FindPathAwayWithLeash(m_vLastEnemyPos, origin - m_Enemy->origin, 1.5 * m_fMinDistance); - } - if (!PathExists() || PathComplete()) - { - m_pszDebugState = "runaway->combat"; - State_Turret_Combat(); - return; - } - if (!CanMovePathWithLeash()) - { - m_pszDebugState = "runaway->leash->combat"; - State_Turret_Combat(); - return; - } - Anim_RunAwayFiring(2); - FaceEnemyOrMotion(level.inttime - m_iStateTime); -} - -void Actor::State_Turret_Charge -( - void -) -{ - SetPathWithLeash(m_vLastEnemyPos, NULL, 0); - ShortenPathToAvoidSquadMates(); - if (!PathExists()) - { - m_pszDebugState = "charge->near"; - FindPathNearWithLeash(m_vLastEnemyPos, m_fMaxDistanceSquared); - if (!ShortenPathToAttack(0)) - ClearPath(); - } - if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) - { - ClearPath(); - if (CanSeeEnemy(500)) - { - m_pszDebugState = "charge->combat"; - State_Turret_Combat(); - return; - } - m_bHasDesiredLookAngles = false; - m_pszDebugState = "charge->chill"; - Anim_Idle(); - if (m_Team != TEAM_AMERICAN) - { - //v1 = &this->m_PotentialEnemies; - if (!m_PotentialEnemies.HasAlternateEnemy()) - { - - if (m_Enemy) - Turret_CheckRetarget(); - return; - } - } - m_PotentialEnemies.FlagBadEnemy(m_Enemy); - UpdateEnemy(-1); - if (m_Enemy) - Turret_CheckRetarget(); - return; - } - if (!MovePathWithLeash()) - { - m_pszDebugState = "charge->leash->combat"; - TransitionState(100, 0); - State_Turret_Combat(); - return; - } -} - -void Actor::State_Turret_Grenade -( - void -) -{ - GenericGrenadeTossThink(); -} - -void Actor::State_Turret_FakeEnemy -( - void -) -{ - AimAtTargetPos(); - Anim_Aim(); - if (level.inttime >= m_iStateTime) - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); -} - -void Actor::State_Turret_Wait -( - void -) -{ - PathNode *pNode; - if (CanSeeEnemy(500) || CanShootEnemy(500)) - { - bool bSmth; - - pNode = m_pCoverNode; - Cover_FindCover(true); - - if (m_pCoverNode) - { - TransitionState(111, 0); - SetThink(THINKSTATE_ATTACK, THINK_COVER); - bSmth = true; - } - else - { - if (pNode) - { - m_pCoverNode = pNode; - m_pCoverNode->Claim(this); - } - bSmth = false; - } - if (bSmth) - { - m_pszDebugState = "Wait->CoverInstead"; - ContinueAnimation(); - } - else - { - m_pszDebugState = "Wait->Combat"; - TransitionState(100, 0); - State_Turret_Combat(); - } - } - else - { - if (level.inttime >= m_iLastFaceDecideTime + 1500) - { - m_iLastFaceDecideTime = level.inttime + (rand() & 0x1FF); - - - - - - - pNode = PathManager.FindCornerNodeForExactPath(this, m_Enemy, 0); - - if (pNode) - { - if (pNode->m_PathPos - origin != vec_zero) - { - SetDesiredYawDir(pNode->m_PathPos - origin); - } - m_eDontFaceWallMode = 6; - } - else - { - AimAtTargetPos(); - DontFaceWall(); - } - } - if (m_eDontFaceWallMode > 8) - Anim_Aim(); - else - Anim_Stand(); - } -} - -void Actor::State_Turret_Retarget_Sniper_Node -( - void -) -{ - PathNode *pSniperNode; - bool bTryAgain; - - AimAtEnemyBehavior(); - if (m_pCoverNode) - { - m_pCoverNode->Relinquish(); - m_pCoverNode = NULL; - } - pSniperNode = FindSniperNodeAndSetPath(&bTryAgain); - if (pSniperNode) - { - m_pCoverNode = pSniperNode; - pSniperNode->Claim(this); - TransitionState(102, 0); - - State_Turret_TakeSniperNode(); - } - else if (bTryAgain) - { - ContinueAnimation(); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Path_Exact -( - void -) -{ - AimAtEnemyBehavior(); - SetPathWithLeash(m_vLastEnemyPos, NULL, 0); - if (ShortenPathToAttack(128) - && (ShortenPathToAvoidSquadMates(), PathExists())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Path_Near -( - void -) -{ - AimAtEnemyBehavior(); - FindPathNearWithLeash(m_vLastEnemyPos, m_fMinDistanceSquared); - if (ShortenPathToAttack(128)) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Step_Side_Small -( - void -) -{ - int iRand; // esi - - iRand = (rand() & 64) - 32; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[1]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[1]), - PathExists()) - && !PathComplete() - && PathAvoidsSquadMates())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Step_Side_Medium -( - void -) -{ - int iRand; // esi - - iRand = (rand() & 256) - 128; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[1]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[1]), - PathExists()) - && !PathComplete() - && PathAvoidsSquadMates())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Step_Side_Large -( - void -) -{ - int iRand; // esi - - iRand = (rand() & 512) - 256; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[1]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[1]), - PathExists()) - && !PathComplete() - && PathAvoidsSquadMates())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Step_Face_Medium -( - void -) -{ - int iRand; // esi - - iRand = (rand() & 256) - 128; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[0]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[0]), - PathExists()) - && !PathComplete() - && PathAvoidsSquadMates())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } -} - -void Actor::State_Turret_Retarget_Step_Face_Large -( - void -) -{ - int iRand; // esi - - iRand = (rand() & 512) - 256; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[0]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[0]), - PathExists()) - && !PathComplete() - && PathAvoidsSquadMates())) - { - TransitionState(101, 0); - } - else - { - Turret_NextRetarget(); - } + if (!m_Enemy) { + TransitionState(ACTOR_STATE_TURRET_COVER_INSTEAD, 0); + } else { + Turret_BeginRetarget(); + } } diff --git a/code/fgame/actor_weaponless.cpp b/code/fgame/actor_weaponless.cpp index f4251243..ebc03f8e 100644 --- a/code/fgame/actor_weaponless.cpp +++ b/code/fgame/actor_weaponless.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,168 +24,128 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" -void Actor::InitWeaponless - ( - GlobalFuncs_t *func - ) +void Actor::InitWeaponless(GlobalFuncs_t *func) { - func->ThinkState = &Actor::Think_Weaponless; - func->BeginState = &Actor::Begin_Weaponless; - func->SuspendState = &Actor::Suspend_Weaponless; - func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; - func->FinishedAnimation = &Actor::FinishedAnimation_Weaponless; - func->IsState = &Actor::IsAttackState; + func->ThinkState = &Actor::Think_Weaponless; + func->BeginState = &Actor::Begin_Weaponless; + func->SuspendState = &Actor::Suspend_Weaponless; + func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack; + func->FinishedAnimation = &Actor::FinishedAnimation_Weaponless; + func->IsState = &Actor::IsAttackState; } -void Actor::Begin_Weaponless - ( - void - ) +void Actor::Begin_Weaponless(void) { + DoForceActivate(); - DoForceActivate(); + m_csMood = STRING_ALERT; + m_csIdleMood = STRING_NERVOUS; - m_csMood = STRING_ALERT; - m_csIdleMood = STRING_NERVOUS; + if (level.inttime < m_iEnemyChangeTime + 200) { + SetLeashHome(origin); + if (AttackEntryAnimation()) { + m_bLockThinkState = true; - if (level.inttime < m_iEnemyChangeTime + 200) - { - SetLeashHome(origin); - if (AttackEntryAnimation()) - { - m_bLockThinkState = true; - - TransitionState(902, 0); - } - } - TransitionState(900, 0); + TransitionState(ACTOR_STATE_WEAPONLESS_LOOP, 0); + } + } + TransitionState(ACTOR_STATE_WEAPONLESS_START, 0); } -void Actor::Suspend_Weaponless - ( - void - ) +void Actor::Suspend_Weaponless(void) { - if (m_State <= 902) - { - TransitionState(900, 0); - } - + if (m_State == ACTOR_STATE_WEAPONLESS_GRENADE || m_State == ACTOR_STATE_WEAPONLESS_LOOP) { + TransitionState(ACTOR_STATE_WEAPONLESS_START, 0); + } } -void Actor::Think_Weaponless - ( - void - ) +void Actor::State_Weaponless_Normal(void) { + int iStateTime; + if (m_bScriptGoalValid) { + SetPath(m_vScriptGoal, NULL, 0, NULL, 0); + } - if (RequireThink()) - { - UpdateEyeOrigin(); - NoPoint(); - UpdateEnemy(500); + if (PathExists() && !PathComplete()) { + FaceMotion(); + Anim_RunToDanger(ANIM_MODE_PATH_GOAL); + return; + } + m_bScriptGoalValid = false; - if (m_State == 902) - { - ContinueAnimation(); - } - else - { - m_bLockThinkState = false; - if (!m_Enemy) - { - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL); - IdleThink(); - return; - } - if (m_State == 900) - { - State_Weaponless_Normal(); - } - else if (m_State == 901) - { - State_Weaponless_Grenade(); - } - else - { - Com_Printf("Think_Weaponless: invalid think state %i\n", m_State); - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"invalid think state\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); - assert(!assertStr); - } - CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL); - } - PostThink(true); - if (GetWeapon(WEAPON_MAIN)) - SetThink(THINKSTATE_ATTACK, THINK_TURRET); - } + AimAtTargetPos(); + Anim_Stand(); + + if (level.inttime < m_iStateTime) { + return; + } + + if (DecideToThrowGrenade(m_Enemy->origin + m_Enemy->velocity, &m_vGrenadeVel, &m_eGrenadeMode, false)) { + SetDesiredYawDir(m_vGrenadeVel); + DesiredAnimation( + ANIM_MODE_NORMAL, + m_eGrenadeMode == AI_GREN_TOSS_ROLL ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR + ); + TransitionState(ACTOR_STATE_WEAPONLESS_GRENADE); + } else { + TransitionState(ACTOR_STATE_WEAPONLESS_START, 1000); + } } -void Actor::FinishedAnimation_Weaponless - ( - void - ) +void Actor::Think_Weaponless(void) { - if (m_State <= 902) - { - TransitionState(900, 4000); - } + if (!RequireThink()) { + return; + } + + UpdateEyeOrigin(); + NoPoint(); + UpdateEnemy(500); + + if (m_State == ACTOR_STATE_WEAPONLESS_LOOP) { + ContinueAnimation(); + } else { + m_bLockThinkState = false; + + if (!m_Enemy) { + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + IdleThink(); + return; + } + + if (m_State == ACTOR_STATE_WEAPONLESS_START) { + State_Weaponless_Normal(); + } else if (m_State == ACTOR_STATE_WEAPONLESS_GRENADE) { + State_Weaponless_Grenade(); + } else { + Com_Printf("Think_Weaponless: invalid think state %i\n", m_State); + char assertStr[16317] = {0}; + Q_strncpyz(assertStr, "\"invalid think state\"\n\tMessage: ", sizeof(assertStr)); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State)); + assert(!assertStr); + } + + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE); + } + } + + PostThink(true); + + if (GetWeapon(WEAPON_MAIN)) { + SetThink(THINKSTATE_ATTACK, THINK_TURRET); + } } -void Actor::State_Weaponless_Normal - ( - void - ) +void Actor::FinishedAnimation_Weaponless(void) { - int iStateTime; - if (m_bScriptGoalValid) - SetPath( - m_vScriptGoal, - NULL, - 0, - NULL, - 0); - if (PathExists() && !PathComplete()) - { - FaceMotion(); - Anim_RunToDanger(3); - } - else - { - m_bScriptGoalValid = false; - - AimAtTargetPos(); - - Anim_Stand(); - if (level.inttime >= m_iStateTime) - { - if (DecideToThrowGrenade(m_Enemy->velocity + m_Enemy->origin, &m_vGrenadeVel, &m_eGrenadeMode)) - { - SetDesiredYawDir(m_vGrenadeVel); - - m_State = 901; - m_eNextAnimMode = 1; - m_bNextForceStart = false; - m_csNextAnimString = (m_eGrenadeMode == AI_GREN_TOSS_ROLL) ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR; - iStateTime = level.inttime; - } - else - { - m_State = 900; - iStateTime = level.inttime + 1000; - } - m_iStateTime = iStateTime; - } - } + if (m_State == ACTOR_STATE_WEAPONLESS_GRENADE || m_State == ACTOR_STATE_WEAPONLESS_LOOP) { + TransitionState(ACTOR_STATE_WEAPONLESS_NORMAL, 4000); + } } - -void Actor::State_Weaponless_Grenade -( - void -) +void Actor::State_Weaponless_Grenade(void) { - GenericGrenadeTossThink(); + GenericGrenadeTossThink(); } diff --git a/code/fgame/actorenemy.cpp b/code/fgame/actorenemy.cpp index 43340b76..86733706 100644 --- a/code/fgame/actorenemy.cpp +++ b/code/fgame/actorenemy.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,694 +23,538 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // actorenemy.cpp: #include "actorenemy.h" -#include "world.h" +#include "worldspawn.h" #include "sentient.h" #include "actor.h" -ActorEnemy::ActorEnemy() +float ActorEnemy::UpdateLMRF(Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible) { - m_pEnemy = NULL; - m_vLastKnownPos = vec_zero; + float fMaxRange, fRange, fRangeScale, fNormalizedRange; + float fForward; + float fFovScale; + float fMinSightTime; + float fLMRF; + float fFarPlane; + Vector vDelta; + float fObfuscation; + + *pbInFovAndRange = false; + *pbVisible = false; + + vDelta = pSelf->VirtualEyePosition() - GetEnemy()->origin; + vDelta[2] = 0; + + fRange = vDelta.lengthXYSquared(); + fMaxRange = pSelf->m_fSight; + + if (world->farplane_distance > 0) { + fFarPlane = world->farplane_distance * 0.828f; + + if (fMaxRange > fFarPlane) { + fMaxRange = fFarPlane; + } + } + + if (fRange > Square(fMaxRange)) { + return 8.0; + } + + fForward = sqrt(fRange); + + fMinSightTime = -DotProduct2D(pSelf->m_vEyeDir, vDelta); + if (fMinSightTime < 0) { + return 8.0; + } + + fMinSightTime += 128; + if (pSelf->m_fFovDot * fForward > fMinSightTime) { + return 8.0; + } + + *pbInFovAndRange = true; + if (!pSelf->CanSee(m_pEnemy, 0, 0, false)) { + return 8.0; + } + + // Added in 2.0. + // Check for obfuscation + fObfuscation = G_VisualObfuscation(pSelf->VirtualEyePosition(), m_pEnemy->EyePosition()); + if (fObfuscation >= 1.f) { + return 8.0; + } + + *pbVisible = true; + + fFovScale = (fMinSightTime / (fForward + 128.0) * -1.3 - (pSelf->m_fFovDot * 0.2 - 1.5)) / (1.0 - pSelf->m_fFovDot); + fRangeScale = fForward / fMaxRange; + fNormalizedRange = (((fRangeScale * 16.0 + -16.0) * fRangeScale + -1.0) * fRangeScale + 7.0) * fRangeScale; + fNormalizedRange = fNormalizedRange / 3.0; + + fLMRF = Square(m_pEnemy->stealthMovementScale * fNormalizedRange) * (fForward + 128.0) / fMinSightTime; + fLMRF *= pSelf->m_fNoticeTimeScale * g_ai_noticescale->value; + if (fLMRF < fFovScale) { + return fFovScale; + } + + return fLMRF; } -ActorEnemy::~ActorEnemy() +float ActorEnemy::UpdateVisibility(Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible) { - //no need + float fLMRF, fFrameTime; + + fFrameTime = level.time - m_fLastLookTime; + + m_fLastLookTime = level.time; + + fLMRF = UpdateLMRF(pSelf, pbInFovAndRange, pbVisible); + if (fLMRF < 8.0) { + m_fVisibility += fFrameTime / fLMRF; + } else if (m_fVisibility < 1.0) { + m_fVisibility -= fFrameTime * 0.25; + if (m_fVisibility < 0.0) { + m_fVisibility = 0.0; + } + } + + m_fTotalVisibility = m_fVisibility + GetEnemy()->m_fPlayerSightLevel; + if (m_fTotalVisibility > 1) { + m_fVisibility = 1; + m_fTotalVisibility = 1; + } + return m_fTotalVisibility; } -float ActorEnemy::UpdateVisibility - ( - Actor *pSelf, - bool *pbInFovAndRange, - bool *pbVisible - ) +int ActorEnemy::UpdateThreat(Actor *pSelf) { - float fLMRF, fFrameTime; + static float fRangeThreatSquared[] = { + Square(2048), + Square(1400), + Square(1100), + Square(916), + Square(784), + Square(683), + Square(600), + Square(529), + Square(466), + Square(410), + Square(357), + Square(305), + Square(254), + Square(200), + Square(137) + }; + static int iWeaponThreat[7][5] = { + {5, 3, 1, 1, 1}, + {8, 6, 4, 2, 1}, + {10, 9, 7, 8, 4}, + {12, 10, 8, 4, 3}, + {12, 12, 9, 7, 4}, + {12, 10, 5, 2, 1}, + {10, 12, 10, 7, 5} + }; + int iWeapon; + int iZone; + Vector vDelta; + int i; - fFrameTime = level.time - m_fLastLookTime; + m_iThreat = 0; + m_fCurrentRangeSquared = 1e38f; - m_fLastLookTime = level.time; + if (m_pEnemy->m_bIsDisguised || m_fTotalVisibility < 0.999f || level.inttime < m_iNextEnemyTime) { + return m_iThreat; + } - fLMRF = UpdateLMRF(pSelf, pbInFovAndRange, pbVisible); - if (fLMRF < 8.0) - { - m_fVisibility += fFrameTime / fLMRF; - } - else - { - if (m_fVisibility < 1.0) - { - m_fVisibility -= fFrameTime * 0.25; - if (m_fVisibility < 0.0) - m_fVisibility = 0.0; - } - } + m_iThreat = 10000; + if (m_bVisible) { + m_iThreat = 10500; + } - m_fTotalVisibility = m_fVisibility + GetEnemy()->m_fPlayerSightLevel; - if (m_fTotalVisibility > 1) - { - m_fVisibility = 1; - m_fTotalVisibility = 1; - } - return m_fTotalVisibility; + vDelta = m_pEnemy->origin - pSelf->origin; + m_fCurrentRangeSquared = vDelta.lengthSquared(); + + if (m_fCurrentRangeSquared < Square(256)) { + iZone = 0; + } else if (m_fCurrentRangeSquared < Square(768)) { + iZone = 1; + } else if (m_fCurrentRangeSquared < Square(1280)) { + iZone = 2; + } else if (m_fCurrentRangeSquared < Square(2048)) { + iZone = 3; + } else { + iZone = 4; + } + + Weapon *pEnemyWeapon = m_pEnemy->GetActiveWeapon(WEAPON_MAIN); + iWeapon = 0; + + if (pEnemyWeapon) { + int iWeapClass = pEnemyWeapon->GetWeaponClass(); + if (iWeapClass & WEAPON_CLASS_PISTOL) { + iWeapon = 1; + } else if (iWeapClass & WEAPON_CLASS_RIFLE) { + iWeapon = 2; + } else if (iWeapClass & WEAPON_CLASS_SMG) { + iWeapon = 3; + } else if (iWeapClass & WEAPON_CLASS_MG) { + iWeapon = 4; + } else if (iWeapClass & WEAPON_CLASS_GRENADE) { + iWeapon = 5; + } else { + iWeapon = 6; + } + } + + for (i = 0; i < ARRAY_LEN(fRangeThreatSquared) && fRangeThreatSquared[i] > m_fCurrentRangeSquared; i++) {} + + m_iThreat += iWeaponThreat[iWeapon][iZone] + m_pEnemy->m_iThreatBias + i; + + float fMinSafeDistSquared = 1.21 * pSelf->m_fMinDistanceSquared + 16384; + + if (m_fCurrentRangeSquared < fMinSafeDistSquared) { + m_iThreat += 500 - (sqrt(m_fCurrentRangeSquared / fMinSafeDistSquared) * 500); + } + + vec2_t vLine; + VectorSub2D(m_vLastKnownPos, pSelf->origin, vLine); + float fDot = DotProduct2D(vLine, m_vLastKnownPos); + Sentient *pSquadMate; + for (pSquadMate = m_pEnemy->m_pNextSquadMate; pSquadMate != m_pEnemy; pSquadMate = pSquadMate->m_pNextSquadMate) { + if (fDot > DotProduct2D(vLine, pSquadMate->origin)) { + m_iThreat -= 4; + } + } + + if (m_pEnemy->IsSubclassOfActor()) { + Actor *pActorEnemy = static_cast(m_pEnemy.Pointer()); + if (pActorEnemy->m_ThinkState == THINKSTATE_PAIN) { + m_iThreat -= 2; + } + } + + fDot = vDelta * pSelf->orientation[0]; + if (fDot > 0) { + if (m_fCurrentRangeSquared * 0.5 >= Square(fDot) && m_fCurrentRangeSquared * 0.5 > Square(fDot)) { + m_iThreat++; + } + } else { + if (m_fCurrentRangeSquared * 0.5 > Square(fDot)) { + m_iThreat++; + } + } + int iEnemyDiscount = m_pEnemy->m_iAttackerCount; + + if (m_pEnemy == pSelf->m_Enemy) { + iEnemyDiscount -= 2; + if (level.inttime < pSelf->m_iEnemyChangeTime + 1000) { + m_iThreat += 5; + } + } + + if (iEnemyDiscount > 4) { + iEnemyDiscount = 4; + } + m_iThreat -= iEnemyDiscount; + + if (m_pEnemy == pSelf->m_pLastAttacker) { + m_iThreat += 5; + } + if (m_pEnemy == pSelf->m_FavoriteEnemy) { + m_iThreat += 250; + } + return m_iThreat; } -int ActorEnemy::UpdateThreat - ( - Actor *pSelf - ) -{ - //FIXME: macro - static float fRangeThreatSquared[15]; - static int iWeaponThreat[7][5]; - int iWeapon; - int iZone; - Vector vDelta; - - m_iThreat = 0; - m_fCurrentRangeSquared = 1e38f; - - if (m_pEnemy->m_bIsDisguised || m_fTotalVisibility < 1) - return m_iThreat; - - m_iThreat = 10000; - if (m_bVisible == true) - m_iThreat = 10500; - - vDelta = m_pEnemy->origin - pSelf->origin; - m_fCurrentRangeSquared = vDelta.lengthSquared(); - - if (m_fCurrentRangeSquared >= 65536.0) - { - if (m_fCurrentRangeSquared >= 589824.0) - { - if (m_fCurrentRangeSquared >= 1638400.0) - { - if (m_fCurrentRangeSquared >= 4194304.0) - iZone = 4; - else - iZone = 3; - } - else - { - iZone = 2; - } - } - else - { - iZone = 1; - } - } - else - { - iZone = 0; - } - - Weapon *pEnemyWeapon = m_pEnemy->GetActiveWeapon(WEAPON_MAIN); - iWeapon = 0; - - if (pEnemyWeapon) - { - int iWeapClass = pEnemyWeapon->GetWeaponClass(); - if (iWeapClass & WEAPON_CLASS_PISTOL) - { - iWeapon = 1; - } - else if (iWeapClass & WEAPON_CLASS_RIFLE) - { - iWeapon = 2; - } - else if (iWeapClass & WEAPON_CLASS_SMG) - { - iWeapon = 3; - } - else if (iWeapClass & WEAPON_CLASS_MG) - { - iWeapon = 4; - } - else if(iWeapClass & WEAPON_CLASS_GRENADE) - { - iWeapon = 5; - } - else - { - iWeapon = 6; - } - } - - int i=0; - if (m_fCurrentRangeSquared > 4194304) - { - for (; i < 15 && fRangeThreatSquared[i] > m_fCurrentRangeSquared; i++) - { - } - } - - m_iThreat += iWeaponThreat[iZone][iWeapon] + m_pEnemy->m_iThreatBias + i; - - float fMinSafeDistSquared = 1.21 * pSelf->m_fMinDistanceSquared + 16384; - - if (m_fCurrentRangeSquared < fMinSafeDistSquared) - { - m_iThreat -= (sqrt(m_fCurrentRangeSquared / fMinSafeDistSquared) * 500) + 500; - } - - Vector vLine = m_vLastKnownPos - pSelf->origin; - float fDot = DotProduct2D(vLine, m_vLastKnownPos); - for (Sentient *pSquadMate = m_pEnemy->m_pNextSquadMate; pSquadMate != m_pEnemy; pSquadMate = pSquadMate->m_pNextSquadMate) - { - if (fDot > DotProduct2D(vLine, pSquadMate->origin)) - { - m_iThreat -= 4; - } - } - - Actor *pAEnemy = (Actor *)m_pEnemy.Pointer(); - if (pAEnemy->IsSubclassOfActor() && pAEnemy->m_ThinkState == THINKSTATE_PAIN) - { - m_iThreat -= 2; - } - - fDot = Vector::Dot(vDelta, pSelf->orientation[0]); - if (fDot <= 0 ) - { - if (m_fCurrentRangeSquared * 0.5 > Square(fDot)) - { - m_iThreat++; - } - } - else - { - if (m_fCurrentRangeSquared * 0.5 >= Square(fDot)) - { - if (m_fCurrentRangeSquared * 0.5 > Square(fDot)) - { - m_iThreat++; - } - } - } - int iEnemyDiscount = m_pEnemy->m_iAttackerCount; - - if (m_pEnemy == pSelf->m_Enemy) - { - iEnemyDiscount -= 2; - if (level.inttime < pSelf->m_iEnemyChangeTime + 1000) - m_iThreat += 5; - } - - if (iEnemyDiscount > 4) - iEnemyDiscount = 4; - m_iThreat -= iEnemyDiscount; - - if (m_pEnemy == pSelf->m_pLastAttacker) - { - m_iThreat += 5; - } - if (m_pEnemy == pSelf->m_FavoriteEnemy) - m_iThreat += 250; - return m_iThreat; -} - -Sentient *ActorEnemy::GetEnemy - ( - void - ) const -{ - return m_pEnemy; -} - -float ActorEnemy::GetVisibility - ( - void - ) const -{ - return m_fVisibility; -} - -int ActorEnemy::GetThreat - ( - void - ) const -{ - return m_iThreat; -} - -float ActorEnemy::GetRangeSquared - ( - void - ) const -{ - return m_fCurrentRangeSquared; -} - -float ActorEnemy::UpdateLMRF - ( - Actor *pSelf, - bool *pbInFovAndRange, - bool *pbVisible - ) -{ - //FIXME: variable names, I did my best - Vector vDelta; - float fFarPlane, fLMRF, /*fMinSightTime,*/ fFovScale, fForward, /*fNormalizedRange,*/ fRangeScale, fRange/*, fMaxRange*/ ; - float fTmp1, fTmp2, fTmp3; - - *pbInFovAndRange = false; - *pbVisible = false; - - vDelta = pSelf->EyePosition() - GetEnemy()->origin; - - fFarPlane = world->farplane_distance; - - fRange = pSelf->m_fSight; - - if (fFarPlane > 0) - { - fRange = fFarPlane * 0.828; - if (pSelf->m_fSight <= fRange) - fRange = pSelf->m_fSight; - } - - - if (vDelta.lengthXYSquared() > Square(fRange)) - { - return 8.0; - } - - fForward = vDelta.lengthXY(); - - if (-DotProduct2D(vDelta, pSelf->m_vEyeDir) < 0) - { - return 8.0; - } - - fTmp2 = 128.0 - DotProduct2D(vDelta, pSelf->m_vEyeDir); - - if (fForward * pSelf->m_fFovDot > fTmp2) - { - return 8.0; - } - - *pbInFovAndRange = true; - - if (!pSelf->CanSee(m_pEnemy, 0, 0, false)) - { - return 8.0; - } - - *pbVisible = true; - fTmp1 = fForward + 128.0; - *pbVisible = true; - fTmp3 = fTmp1 / fTmp2; - fRangeScale = fForward - / fRange - * (((fForward / fRange * 16.0 + -16.0) * (fForward / fRange) + -1.0) * (fForward / fRange) + 7.0) - / 3.0 - * GetEnemy()->stealthMovementScale; - fFovScale = (1 / fTmp3 * -1.3 - (pSelf->m_fFovDot * 0.2 - 1.5)) / (1.0 - pSelf->m_fFovDot); - fLMRF = g_ai_noticescale->value * pSelf->m_fNoticeTimeScale * (fTmp3 * fRangeScale + fTmp3 * fRangeScale); - if (fFovScale > fLMRF) - fLMRF = fFovScale; - return fLMRF; -} - - ActorEnemySet::ActorEnemySet() { - m_pCurrentEnemy = NULL; - m_iCheckCount = 0; - - if (m_pCurrentEnemy) - { - //delete m_pCurrentEnemy; - m_pCurrentEnemy = NULL; - } - - m_iCurrentThreat = 0; - m_fCurrentVisibility = 0.0; + m_iCheckCount = 0; + m_pCurrentEnemy = NULL; + m_iCurrentThreat = 0; + m_fCurrentVisibility = 0.0; } -ActorEnemySet::~ActorEnemySet() +ActorEnemy *ActorEnemySet::AddPotentialEnemy(Sentient *pEnemy) { + ActorEnemy NewEnemy; + if (pEnemy->IsDead() || pEnemy->m_iThreatBias == THREATBIAS_IGNOREME) { + return NULL; + } + + for (int i = 0; i < m_Enemies.NumObjects(); i++) { + ActorEnemy *pActorEnemy = &m_Enemies[i]; + if (pActorEnemy->m_pEnemy == pEnemy) { + pActorEnemy->m_iAddTime = level.inttime; + return pActorEnemy; + } + } + + NewEnemy.m_iAddTime = level.inttime; + NewEnemy.m_iNextEnemyTime = 0; + NewEnemy.m_fLastLookTime = level.time; + NewEnemy.m_fVisibility = 0.0; + NewEnemy.m_fTotalVisibility = 0.0; + NewEnemy.m_iThreat = 0; + NewEnemy.m_pEnemy = pEnemy; + NewEnemy.m_fCurrentRangeSquared = 1e38f; + NewEnemy.m_vLastKnownPos = vec_zero; + NewEnemy.m_iLastSightChangeTime = 0; + NewEnemy.m_bVisible = false; + + int index = m_Enemies.AddObject(NewEnemy); + return m_Enemies.AddressOfObjectAt(index); } -ActorEnemy *ActorEnemySet::AddPotentialEnemy - ( - Sentient *pEnemy - ) +void ActorEnemySet::FlagBadEnemy(Sentient *pEnemy) { - ActorEnemy NewEnemy; - - if (pEnemy->IsDead() || pEnemy->m_iThreatBias == THREATBIAS_IGNOREME) - { - return NULL; - } + ActorEnemy *pActorEnemy = NULL; - for (int i = 0; i < m_Enemies.NumObjects(); i++) - { - ActorEnemy *pActorEnemy = &m_Enemies[i]; - if (pActorEnemy->m_pEnemy == pEnemy) - { - pActorEnemy->m_iAddTime = level.inttime; - return pActorEnemy; - } - } + for (int i = 1; i <= m_Enemies.NumObjects(); i++) { + if (m_Enemies.ObjectAt(i).m_pEnemy == pEnemy) { + pActorEnemy = m_Enemies.AddressOfObjectAt(i); + break; + } + } - NewEnemy.m_fVisibility = 0.0; - NewEnemy.m_fTotalVisibility = 0.0; - NewEnemy.m_iAddTime = level.inttime; - NewEnemy.m_fLastLookTime = level.time; - NewEnemy.m_iThreat = 0; + if (!pActorEnemy) { + return; + } - NewEnemy.m_pEnemy = pEnemy; + // Added in 2.0. + // Set the reaction time + pActorEnemy->m_iNextEnemyTime = level.inttime + 5000; - NewEnemy.m_fCurrentRangeSquared = 1e38f; + pActorEnemy->m_fLastLookTime = level.time; + pActorEnemy->m_fVisibility = 0.0; + pActorEnemy->m_fTotalVisibility = 0.0; + pActorEnemy->m_iThreat = 0; + pActorEnemy->m_iLastSightChangeTime = level.inttime; + pActorEnemy->m_bVisible = false; - NewEnemy.m_iLastSightChangeTime = 0; - NewEnemy.m_vLastKnownPos = vec_zero; - - NewEnemy.m_bVisible = false; - - - - return &m_Enemies[m_Enemies.AddObject(NewEnemy)-1]; + if (pEnemy == m_pCurrentEnemy) { + m_pCurrentEnemy = NULL; + m_fCurrentVisibility = 0.0; + m_iCurrentThreat = 0; + } } -void ActorEnemySet::FlagBadEnemy - ( - Sentient *pEnemy - ) +void ActorEnemySet::CheckEnemies(Actor *pSelf) { - ActorEnemy *pActorEnemy; - for (int i = 0; i < m_Enemies.NumObjects(); i++) - { - pActorEnemy = &m_Enemies[i]; - if (pActorEnemy->m_pEnemy == pEnemy) - { - break; - } + float fVisibility; + int iThreat; + int i; + int nChecked; + bool bInFovAndRange; + bool bVisible; + float fRangeSquared; - if (i+1 == m_Enemies.NumObjects()) - return; - } + ActorEnemy *pActorEnemy; - pActorEnemy->m_iThreat = 0; - pActorEnemy->m_fVisibility = 0.0; - pActorEnemy->m_fTotalVisibility = 0.0; - pActorEnemy->m_fLastLookTime = level.time; + for (i = 1; i <= m_Enemies.NumObjects();) { + pActorEnemy = &m_Enemies[i - 1]; + if (!pActorEnemy->GetEnemy() || pActorEnemy->GetEnemy()->m_Team == pSelf->m_Team + || pActorEnemy->GetEnemy()->IsDead() || level.inttime > pActorEnemy->m_iAddTime + 10000 + || pActorEnemy->GetEnemy()->m_iThreatBias == THREATBIAS_IGNOREME || pActorEnemy->GetEnemy()->IsDisabled()) { + m_Enemies.RemoveObjectAt(i); + } else { + i++; + } + } - pActorEnemy->m_bVisible = false; - pActorEnemy->m_iLastSightChangeTime = level.inttime; + if (!m_Enemies.NumObjects()) { + m_iCurrentThreat = 0; + m_pCurrentEnemy = NULL; + return; + } - if (pEnemy == m_pCurrentEnemy) - { - if (m_pCurrentEnemy) - { - //delete m_pCurrentEnemy; - m_pCurrentEnemy = NULL; - } - m_fCurrentVisibility = 0.0; - m_iCurrentThreat = 0; - } + bInFovAndRange = false; + for (nChecked = 0; nChecked < m_Enemies.NumObjects() && !bInFovAndRange; nChecked++) { + m_iCheckCount++; + if (m_iCheckCount > m_Enemies.NumObjects()) { + m_iCheckCount = 1; + } + + pActorEnemy = &m_Enemies[m_iCheckCount - 1]; + + fVisibility = pActorEnemy->UpdateVisibility(pSelf, &bInFovAndRange, &bVisible); + if (fVisibility > 0) { + if (fVisibility >= m_fCurrentVisibility) { + m_fCurrentVisibility = fVisibility; + m_pCurrentEnemy = pActorEnemy->GetEnemy(); + } else if (pActorEnemy->m_pEnemy == m_pCurrentEnemy) { + m_fCurrentVisibility = fVisibility; + } + + if (g_showawareness->integer) { + Com_Printf( + "ent #%3i: enemy #%i: awareness = %5.1f%%, threat = %i\n", + pSelf->entnum, + pActorEnemy->GetEnemy()->entnum, + (fVisibility * 100.0), + 0 + ); + } + } else if (pActorEnemy->m_pEnemy == m_pCurrentEnemy) { + m_iCurrentThreat = 0; + m_pCurrentEnemy = NULL; + m_fCurrentVisibility = 0; + } + + if (bVisible) { + if (!pActorEnemy->m_bVisible) { + pActorEnemy->m_bVisible = true; + pActorEnemy->m_iLastSightChangeTime = level.inttime; + } + pActorEnemy->m_vLastKnownPos = pActorEnemy->m_pEnemy->origin; + } else if (pActorEnemy->m_bVisible) { + pActorEnemy->m_bVisible = false; + pActorEnemy->m_iLastSightChangeTime = level.inttime; + } + } + + if (m_pCurrentEnemy && m_pCurrentEnemy->IsDead()) { + m_pCurrentEnemy = NULL; + m_iCurrentThreat = 0; + m_fCurrentVisibility = 0; + } + + m_iCurrentThreat = 0; + fRangeSquared = 1e37f; + + if (m_fCurrentVisibility >= 0.999f) { + for (i = 1; i <= m_Enemies.NumObjects(); i++) { + pActorEnemy = &m_Enemies.ObjectAt(i); + pActorEnemy->UpdateThreat(pSelf); + iThreat = pActorEnemy->GetThreat(); + + if (m_iCurrentThreat >= iThreat) { + if (m_iCheckCount != iThreat) { + continue; + } + + if (pActorEnemy->GetRangeSquared() < fRangeSquared) { + continue; + } + } + + m_iCurrentThreat = pActorEnemy->GetThreat(); + m_pCurrentEnemy = pActorEnemy->GetEnemy(); + fRangeSquared = pActorEnemy->m_fCurrentRangeSquared; + } + } + + if ((!m_pCurrentEnemy || !m_pCurrentEnemy->m_bIsDisguised) && m_iCurrentThreat <= 0) { + m_pCurrentEnemy = NULL; + m_iCurrentThreat = 0; + m_fCurrentVisibility = 0; + } } -void ActorEnemySet::CheckEnemies - ( - Actor *pSelf - ) +bool ActorEnemySet::HasAlternateEnemy(void) const { - float fRangeSquared; - bool bVisible; - bool bInFovAndRange; - //int nChecked; - //int iThreat; - float fVisibility; + for (int i = 1; i <= m_Enemies.NumObjects(); i++) { + const ActorEnemy& actorEnemy = m_Enemies.ObjectAt(i); - ActorEnemy *pActorEnemy; - - - for (int i = 1; i <= m_Enemies.NumObjects();i++) - { - pActorEnemy = &m_Enemies[i-1]; - if (!pActorEnemy->m_pEnemy - || pActorEnemy->m_pEnemy->m_Team == pSelf->m_Team - || pActorEnemy->m_pEnemy->IsDead() - || level.inttime > pActorEnemy->m_iAddTime + 10000 - || pActorEnemy->m_pEnemy->m_iThreatBias == THREATBIAS_IGNOREME) - { - m_Enemies.RemoveObjectAt(i); - i--;//decrease i in order to not miss next object in container. - } - } - - if (!m_Enemies.NumObjects()) - { - m_iCurrentThreat = 0; - if (m_pCurrentEnemy) - { - //delete m_pCurrentEnemy; - m_pCurrentEnemy = NULL; - } - } - else - { - for (int i = 0; i < m_Enemies.NumObjects(); i++) - { - m_iCheckCount++; - if (m_iCheckCount > m_Enemies.NumObjects()) - m_iCheckCount = 1; - - pActorEnemy = &m_Enemies[m_iCheckCount-1]; - - fVisibility = pActorEnemy->UpdateVisibility(pSelf, &bInFovAndRange, &bVisible); - if (fVisibility <= 0.0) - { - if (pActorEnemy->m_pEnemy == m_pCurrentEnemy) - { - m_iCurrentThreat = 0; - m_pCurrentEnemy = NULL; - m_fCurrentVisibility = 0.0; - } - } - else - { - if (fVisibility < m_fCurrentVisibility) - { - if (pActorEnemy->m_pEnemy == m_pCurrentEnemy) - { - m_fCurrentVisibility = fVisibility; - } - } - else - { - m_pCurrentEnemy = pActorEnemy->m_pEnemy; - m_fCurrentVisibility = fVisibility; - } - - if (g_showawareness->integer) - { - Com_Printf( - "ent #%3i: enemy #%i: awareness = %5.1f%%, threat = %i\n", - pSelf->entnum, - pActorEnemy->m_pEnemy->entnum, - (fVisibility * 100.0), - 0); - } - } - - if (bVisible) - { - if (!pActorEnemy->m_bVisible) - { - pActorEnemy->m_bVisible = true; - pActorEnemy->m_iLastSightChangeTime = level.inttime; - } - pActorEnemy->m_vLastKnownPos = pActorEnemy->m_pEnemy->origin; - } - else if (pActorEnemy->m_bVisible) - { - pActorEnemy->m_bVisible = false; - pActorEnemy->m_iLastSightChangeTime = level.inttime; - } - - if (bInFovAndRange) - { - break; - } - } - - if (m_pCurrentEnemy && m_pCurrentEnemy->IsDead()) - { - m_pCurrentEnemy = NULL; - m_iCurrentThreat = 0; - m_fCurrentVisibility = 0.0; - } - - m_iCurrentThreat = 0; - - fRangeSquared = 1e37f; - - if (m_fCurrentVisibility >= 1) - { - for (int i = 1;i <= m_Enemies.NumObjects(); i++) - { - pActorEnemy = &m_Enemies[i-1]; - pActorEnemy->UpdateThreat(pSelf); - if (m_iCurrentThreat < pActorEnemy->m_iThreat || (m_iCheckCount == pActorEnemy->m_iThreat && fRangeSquared > pActorEnemy->m_fCurrentRangeSquared)) - { - m_iCurrentThreat = pActorEnemy->m_iThreat; - m_pCurrentEnemy = pActorEnemy->m_pEnemy; - fRangeSquared = pActorEnemy->m_fCurrentRangeSquared; - } - } - } - - if ((!m_pCurrentEnemy || !m_pCurrentEnemy->m_bIsDisguised) && m_iCurrentThreat <= 0) - { - m_pCurrentEnemy = NULL; - m_iCurrentThreat = 0; - m_fCurrentVisibility = 0.0; - } - } + if (actorEnemy.GetVisibility() >= 0.999f && actorEnemy.GetEnemy() != m_pCurrentEnemy) { + return true; + } + } + return false; } -Sentient *ActorEnemySet::GetCurrentEnemy - ( - void - ) const +void ActorEnemySet::RemoveAll(void) { - return m_pCurrentEnemy; + m_Enemies.ClearObjectList(); + m_iCheckCount = 0; + m_pCurrentEnemy = NULL; + m_fCurrentVisibility = 0.0; + m_iCurrentThreat = 0; } -float ActorEnemySet::GetCurrentVisibility - ( - void - ) const +void ActorEnemySet::ConfirmEnemy(Actor *pSelf, Sentient *pEnemy) { - return m_fCurrentVisibility; + ActorEnemy *pActorEnemy; + + pSelf->m_bEnemyIsDisguised = false; + pActorEnemy = ActorEnemySet::AddPotentialEnemy(pEnemy); + if (!pActorEnemy) { + return; + } + + // Added in 2.0. + // Ignore if below reaction time + if (level.inttime < pActorEnemy->m_iNextEnemyTime) { + return; + } + + pActorEnemy->m_fVisibility = 1.0; + pActorEnemy->m_fTotalVisibility = 1.0; + pActorEnemy->m_vLastKnownPos = pEnemy->origin; + + if (m_fCurrentVisibility < 1.0) { + m_iCurrentThreat = pActorEnemy->UpdateThreat(pSelf); + m_fCurrentVisibility = 1.0; + m_pCurrentEnemy = pEnemy; + } } -int ActorEnemySet::GetCurrentThreat - ( - void - ) const +void ActorEnemySet::ConfirmEnemyIfCanSeeSharerOrEnemy(Actor *pSelf, Actor *pSharer, Sentient *pEnemy) { - return m_iCurrentThreat; + ActorEnemy *pActorEnemy; + + pSelf->m_bEnemyIsDisguised = false; + pActorEnemy = ActorEnemySet::AddPotentialEnemy(pEnemy); + if (!pActorEnemy) { + return; + } + + // Added in 2.0. + // Ignore if below reaction time + if (level.inttime < pActorEnemy->m_iNextEnemyTime) { + return; + } + + if (pActorEnemy->m_fTotalVisibility >= 1.f) { + pActorEnemy->m_vLastKnownPos = pEnemy->origin; + return; + } + + if (!pActorEnemy->m_bVisible + && !pSelf->CanSee(pSharer, pSelf->m_bSilent ? 90 : 0, world->farplane_distance * 0.828f, false)) { + return; + } + + pActorEnemy->m_fVisibility = 1.0; + pActorEnemy->m_fTotalVisibility = 1.0; + pActorEnemy->m_vLastKnownPos = pEnemy->origin; + + if (m_fCurrentVisibility < 1.0) { + m_iCurrentThreat = pActorEnemy->UpdateThreat(pSelf); + m_fCurrentVisibility = 1.0; + m_pCurrentEnemy = pEnemy; + } } -qboolean ActorEnemySet::IsEnemyConfirmed - ( - void - ) const +bool ActorEnemySet::CaresAboutPerfectInfo(Sentient *pEnemy) { - // not found in ida - return false; -} + ActorEnemy *pActorEnemy = ActorEnemySet::AddPotentialEnemy(pEnemy); + if (!pActorEnemy) { + return false; + } -bool ActorEnemySet::HasAlternateEnemy - ( - void - ) const -{ - ActorEnemy *pActorEnemy; - for (int i = 0; i < m_Enemies.NumObjects(); i++) - { - pActorEnemy = &m_Enemies[i]; - if (pActorEnemy->m_pEnemy != m_pCurrentEnemy) - { - return true; - } - } - return false; -} + // Added in 2.0. + // Ignore if below reaction time + if (level.inttime < pActorEnemy->m_iNextEnemyTime) { + return false; + } -void ActorEnemySet::RemoveAll - ( - void - ) -{ - m_Enemies.ClearObjectList(); - m_iCheckCount = 0; - if (m_pCurrentEnemy) - { - //delete m_pCurrentEnemy; - m_pCurrentEnemy = NULL; - } - m_fCurrentVisibility = 0.0; - m_iCurrentThreat = 0; -} + if (pActorEnemy->m_fTotalVisibility < 1.0f) { + return true; + } -void ActorEnemySet::ConfirmEnemy - ( - Actor *pSelf, - Sentient *pEnemy - ) -{ - pSelf->m_bEnemyIsDisguised = false; - ActorEnemy *pActorEnemy = ActorEnemySet::AddPotentialEnemy(pEnemy); - if (pActorEnemy) - { - pActorEnemy->m_fVisibility = 1.0; - pActorEnemy->m_fTotalVisibility = 1.0; - pActorEnemy->m_vLastKnownPos = pEnemy->origin; - if (m_fCurrentVisibility < 1.0) - { - m_iCurrentThreat = pActorEnemy->UpdateThreat(pSelf); - m_fCurrentVisibility = 1.0; - m_pCurrentEnemy = pEnemy; - } - } -} + if ((pEnemy->origin - pActorEnemy->m_vLastKnownPos).lengthSquared() <= Square(512)) { + return false; + } -void ActorEnemySet::ConfirmEnemyIfCanSeeSharerOrEnemy - ( - Actor *pSelf, - Actor *pSharer, - Sentient *pEnemy - ) -{ - pSelf->m_bEnemyIsDisguised = false; - ActorEnemy *pActorEnemy = ActorEnemySet::AddPotentialEnemy(pEnemy); - if (pActorEnemy) - { - if (pActorEnemy->m_fTotalVisibility > 0) - { - pActorEnemy->m_vLastKnownPos = pEnemy->origin; - return; - } - if (!pActorEnemy->m_bVisible) - { - if (!pSelf->CanSee( - pSharer, - pSelf->m_bSilent ? 90.0f : 0, - 0.828 * world->farplane_distance, false)) - return; - } - pActorEnemy->m_fVisibility = 1.0; - pActorEnemy->m_fTotalVisibility = 1.0; - pActorEnemy->m_vLastKnownPos = pEnemy->origin; - if (m_fCurrentVisibility < 1.0) - { - m_iCurrentThreat = pActorEnemy->UpdateThreat(pSelf); - m_fCurrentVisibility = 1.0; - m_pCurrentEnemy = pEnemy; - } - } -} - -bool ActorEnemySet::CaresAboutPerfectInfo - ( - Sentient *pEnemy - ) -{ - ActorEnemy *pActorEnemy = ActorEnemySet::AddPotentialEnemy(pEnemy); - if (pActorEnemy) - { - if (pActorEnemy->m_fTotalVisibility < 1.0 || (pEnemy->origin - pActorEnemy->m_vLastKnownPos).lengthSquared() > 262144) - { - return true; - } - } - return false; + return true; } diff --git a/code/fgame/actorenemy.h b/code/fgame/actorenemy.h index 270322ad..3029379b 100644 --- a/code/fgame/actorenemy.h +++ b/code/fgame/actorenemy.h @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // actorenemy.h -#ifndef __ACTORENEMY_H__ -#define __ACTORENEMY_H__ +#pragma once #include "g_local.h" #include "class.h" @@ -32,92 +31,125 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class Actor; class Sentient; -class ActorEnemy : public Class { +class ActorEnemy : public Class +{ public: - int m_iAddTime; - float m_fLastLookTime; - float m_fVisibility; - float m_fTotalVisibility; - int m_iThreat; - SafePtr m_pEnemy; - float m_fCurrentRangeSquared; - Vector m_vLastKnownPos; - int m_iLastSightChangeTime; - bool m_bVisible; + int m_iAddTime; + int m_iNextEnemyTime; // Added in 2.0 + float m_fLastLookTime; + float m_fVisibility; + float m_fTotalVisibility; + int m_iThreat; + SafePtr m_pEnemy; + float m_fCurrentRangeSquared; + Vector m_vLastKnownPos; + int m_iLastSightChangeTime; + bool m_bVisible; - ActorEnemy(); - virtual ~ActorEnemy(); - float UpdateVisibility( Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible ); - int UpdateThreat( Actor *pSelf ); - Sentient *GetEnemy( void ) const; - float GetVisibility( void ) const; - int GetThreat( void ) const; - float GetRangeSquared( void ) const; + float UpdateVisibility(Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible); + int UpdateThreat(Actor *pSelf); + Sentient *GetEnemy(void) const; + float GetVisibility(void) const; + int GetThreat(void) const; + float GetRangeSquared(void) const; - void Archive( Archiver & ) override; + void Archive(Archiver&) override; protected: - float UpdateLMRF( Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible ); + float UpdateLMRF(Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible); }; -inline void ActorEnemy::Archive - ( - Archiver& arc - ) +inline void ActorEnemy::Archive(Archiver& arc) { - Class::Archive( arc ); + Class::Archive(arc); - arc.ArchiveInteger( &m_iAddTime ); - arc.ArchiveFloat( &m_fLastLookTime ); - arc.ArchiveFloat( &m_fVisibility ); - arc.ArchiveFloat( &m_fTotalVisibility ); - arc.ArchiveInteger( &m_iThreat ); - arc.ArchiveSafePointer( &m_pEnemy ); - arc.ArchiveFloat( &m_fCurrentRangeSquared ); - arc.ArchiveVector( &m_vLastKnownPos ); - arc.ArchiveInteger( &m_iLastSightChangeTime ); - arc.ArchiveBool( &m_bVisible ); + arc.ArchiveInteger(&m_iAddTime); + arc.ArchiveFloat(&m_fLastLookTime); + arc.ArchiveFloat(&m_fVisibility); + arc.ArchiveFloat(&m_fTotalVisibility); + arc.ArchiveInteger(&m_iThreat); + arc.ArchiveSafePointer(&m_pEnemy); + arc.ArchiveFloat(&m_fCurrentRangeSquared); + arc.ArchiveVector(&m_vLastKnownPos); + arc.ArchiveInteger(&m_iLastSightChangeTime); + arc.ArchiveBool(&m_bVisible); } -class ActorEnemySet : public Class { +inline Sentient *ActorEnemy::GetEnemy(void) const +{ + return m_pEnemy; +} + +inline float ActorEnemy::GetVisibility(void) const +{ + return m_fVisibility; +} + +inline int ActorEnemy::GetThreat(void) const +{ + return m_iThreat; +} + +inline float ActorEnemy::GetRangeSquared(void) const +{ + return m_fCurrentRangeSquared; +} + +class ActorEnemySet : public Class +{ protected: - Container m_Enemies; - int m_iCheckCount; - SafePtr m_pCurrentEnemy; - float m_fCurrentVisibility; - int m_iCurrentThreat; + Container m_Enemies; + int m_iCheckCount; + SafePtr m_pCurrentEnemy; + float m_fCurrentVisibility; + int m_iCurrentThreat; + public: - ActorEnemySet(); - virtual ~ActorEnemySet(); + ActorEnemySet(); - ActorEnemy *AddPotentialEnemy( Sentient *pEnemy ); - void FlagBadEnemy( Sentient *pEnemy ); - void CheckEnemies( Actor *pSelf ); - Sentient *GetCurrentEnemy( void ) const; - float GetCurrentVisibility( void ) const; - int GetCurrentThreat( void ) const; - qboolean IsEnemyConfirmed( void ) const; - bool HasAlternateEnemy( void ) const; - void RemoveAll( void ); - void ConfirmEnemy( Actor *pSelf, Sentient *pEnemy ); - void ConfirmEnemyIfCanSeeSharerOrEnemy( Actor *pSelf, Actor *pSharer, Sentient *pEnemy ); - bool CaresAboutPerfectInfo( Sentient *pEnemy ); + ActorEnemy *AddPotentialEnemy(Sentient *pEnemy); + void FlagBadEnemy(Sentient *pEnemy); + void CheckEnemies(Actor *pSelf); + Sentient *GetCurrentEnemy(void) const; + float GetCurrentVisibility(void) const; + int GetCurrentThreat(void) const; + qboolean IsEnemyConfirmed(void) const; + bool HasAlternateEnemy(void) const; + void RemoveAll(void); + void ConfirmEnemy(Actor *pSelf, Sentient *pEnemy); + void ConfirmEnemyIfCanSeeSharerOrEnemy(Actor *pSelf, Actor *pSharer, Sentient *pEnemy); + bool CaresAboutPerfectInfo(Sentient *pEnemy); - void Archive( Archiver& arc ) override; + void Archive(Archiver& arc) override; }; -inline void ActorEnemySet::Archive - ( - Archiver& arc - ) +inline Sentient *ActorEnemySet::GetCurrentEnemy(void) const { - Class::Archive( arc ); - - m_Enemies.Archive( arc, ArchiveClass< ActorEnemy > ); - arc.ArchiveInteger( &m_iCheckCount ); - arc.ArchiveSafePointer( &m_pCurrentEnemy ); - arc.ArchiveFloat( &m_fCurrentVisibility ); - arc.ArchiveInteger( &m_iCurrentThreat ); + return m_pCurrentEnemy; } -#endif /* actorenemy.h */ \ No newline at end of file +inline float ActorEnemySet::GetCurrentVisibility(void) const +{ + return m_fCurrentVisibility; +} + +inline int ActorEnemySet::GetCurrentThreat(void) const +{ + return m_iCurrentThreat; +} + +inline qboolean ActorEnemySet::IsEnemyConfirmed(void) const +{ + return m_fCurrentVisibility > 0.999f; +} + +inline void ActorEnemySet::Archive(Archiver& arc) +{ + Class::Archive(arc); + + m_Enemies.Archive(arc); + arc.ArchiveInteger(&m_iCheckCount); + arc.ArchiveSafePointer(&m_pCurrentEnemy); + arc.ArchiveFloat(&m_fCurrentVisibility); + arc.ArchiveInteger(&m_iCurrentThreat); +} diff --git a/code/fgame/actorpath.cpp b/code/fgame/actorpath.cpp index 6fead750..0c90e846 100644 --- a/code/fgame/actorpath.cpp +++ b/code/fgame/actorpath.cpp @@ -26,633 +26,528 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ActorPath::ActorPath() { - m_FallHeight = 96; - m_path = NULL; - m_pathlen = 0; - m_fLookAhead = 4096.0f; - m_bChangeLookAhead = true; + m_FallHeight = 96; + m_path = NULL; + m_pathlen = 0; + m_fLookAhead = 4096; + m_bChangeLookAhead = true; - Clear(); + Clear(); } ActorPath::~ActorPath() { - if( m_path ) - delete m_path; + if (m_path) { + delete[] m_path; + } } -void ActorPath::Clear - ( - void - ) +void ActorPath::Clear(void) { - m_startpathpos = 0; - m_pathpos = 0; - m_Side = false; - m_Time = -10000000; - m_delta[ 0 ] = 0; - m_delta[ 1 ] = 0; + m_startpathpos = NULL; + m_pathpos = NULL; + m_Side = false; + m_Time = -10000000; + VectorClear2D(m_delta); + m_TotalDist = PathManager.total_dist; } -bool ActorPath::DoesTheoreticPathExist - ( - float *start, - float *end, - class SimpleActor *ent, - float maxPath, - float *vLeashHome, - float fLeashDistSquared - ) +void ActorPath::ForceShortLookahead(void) { - return PathSearch::FindPath( start, end, ent, maxPath, NULL, 0, m_FallHeight ) != 0; + m_fLookAhead = 4096.0f; } -void ActorPath::FindPath - ( - float *start, - float *end, - Entity *ent, - float maxPath, - float *vLeashHome, - float fLeashDistSquared - ) +float ActorPath::PathLookAhead(float total_area, Vector& end, float *origin) { - int depth = PathManager.FindPath( start, end, ent, maxPath, vLeashHome, fLeashDistSquared, m_FallHeight ); + float area = total_area; + float s; + float t; + vec2_t normal; + vec2_t delta; + Vector pos; + float fallheight; + PathInfo *current_path = m_pathpos; - if( depth ) - { - if( depth > m_pathlen ) - { - if( m_path ) - delete[] m_path; + pos = current_path->point; - m_pathlen = 10 * (( depth - 1 ) / 10) + 10; - m_path = new PathInfo[ m_pathlen ]; - } + while (1) { + if (current_path == m_path) { + end = current_path->point; + m_HasCompleteLookahead = true; + return area; + } - m_startpathpos = PathManager.GeneratePath( m_path ); - m_pathpos = m_startpathpos; - m_TotalDist = PathManager.total_dist; - m_Side = false; - m_Time = level.inttime; - UpdatePos( start ); - } - else - { - Clear(); - } + fallheight = current_path->point[2] - origin[2]; + + if (fallheight > 94.0f || fallheight < -94.0f) { + end = current_path->point; + m_HasCompleteLookahead = false; + return area; + } + + current_path--; + + // calculate the normal + normal[0] = current_path->point[1] - pos[1]; + normal[1] = pos[0] - current_path->point[0]; + VectorNormalize2D(normal); + VectorSub2D(current_path->point, origin, delta); + + t = fabs(DotProduct2D(delta, normal)) * current_path->dist; + + if (t >= area) { + break; + } + + area -= t; + pos = current_path->point; + } + + t = area / t; + s = 1.0f - t; + + end[0] = pos[0] * s + current_path->point[0] * t; + end[1] = pos[1] * s + current_path->point[1] * t; + end[2] = pos[2] * s + current_path->point[2] * t; + + m_HasCompleteLookahead = false; + return 0; } -void ActorPath::FindPathAway - ( - float *start, - float *avoid, - float *vPreferredDir, - Entity *ent, - float fMinSafeDist, - float *vLeashHome, - float fLeashDistSquared - ) +bool ActorPath::DoesTheoreticPathExist( + float *start, float *end, class SimpleActor *ent, float maxPath, float *vLeashHome, float fLeashDistSquared +) { - int depth = PathManager.FindPathAway( start, avoid, vPreferredDir, ent, fMinSafeDist, vLeashHome, fLeashDistSquared, m_FallHeight ); - - if( depth ) - { - if( depth > m_pathlen ) - { - if( m_path ) - delete m_path; - - m_pathlen = 10 * ( depth - 1 ) / 10 + 10; - m_path = new PathInfo[ m_pathlen ]; - } - - m_startpathpos = PathManager.GeneratePathAway( m_path ); - m_pathpos = m_startpathpos; - m_TotalDist = PathManager.total_dist; - m_Side = false; - m_Time = level.inttime; - UpdatePos( start ); - } - else - { - Clear(); - } + return PathSearch::FindPath(start, end, ent, maxPath, NULL, 0, m_FallHeight) != 0; } -void ActorPath::FindPathNear - ( - float *start, - float *nearby, - Entity *ent, - float maxPath, - float fRadiusSquared, - float *vLeashHome, - float fLeashDistSquared - ) +void ActorPath::FindPath( + float *start, float *end, Entity *ent, float maxPath, float *vLeashHome, float fLeashDistSquared +) { - int depth = PathManager.FindPathNear( start, nearby, ent, maxPath, fRadiusSquared, vLeashHome, fLeashDistSquared, m_FallHeight ); + int depth; - if( depth ) - { - if( depth > m_pathlen ) - { - if( m_path ) - delete m_path; + depth = PathManager.FindPath(start, end, ent, maxPath, vLeashHome, fLeashDistSquared, m_FallHeight); - m_pathlen = 10 * ( depth - 1 ) / 10 + 10; - m_path = new PathInfo[ m_pathlen ]; - } + if (!depth) { + Clear(); + return; + } - m_startpathpos = PathManager.GeneratePathNear( m_path ); - m_pathpos = m_startpathpos; - m_TotalDist = PathManager.total_dist; - m_Side = false; - m_Time = level.inttime; - UpdatePos( start ); - } - else - { - Clear(); - } + if (depth > m_pathlen) { + if (m_path) { + delete[] m_path; + } + + m_pathlen = 10 * ((depth - 1) / 10) + 10; + m_path = new PathInfo[m_pathlen]; + } + + m_startpathpos = PathManager.GeneratePath(m_path); + m_pathpos = m_startpathpos; + m_TotalDist = PathManager.total_dist; + m_Side = false; + m_Time = level.inttime; + UpdatePos(start); } -void ActorPath::ReFindPath - ( - float *start, - Entity *ent - ) +void ActorPath::FindPathAway( + float *start, + float *avoid, + float *vPreferredDir, + Entity *ent, + float fMinSafeDist, + float *vLeashHome, + float fLeashDistSquared +) { - int depth = PathManager.FindPath( start, m_path->point, ent, 0, NULL, 0, m_FallHeight ); + int depth; - if( depth ) - { - if( depth > m_pathlen ) - { - if( m_path ) - delete m_path; + depth = PathManager.FindPathAway( + start, avoid, vPreferredDir, ent, fMinSafeDist, vLeashHome, fLeashDistSquared, m_FallHeight + ); - m_pathlen = 10 * ( depth - 1 ) / 10 + 10; - m_path = new PathInfo[ m_pathlen ]; - } + if (!depth) { + Clear(); + return; + } - m_startpathpos = PathManager.GeneratePath( m_path ); - m_pathpos = m_startpathpos; - m_TotalDist = PathManager.total_dist; - m_Side = false; - m_Time = level.inttime; - UpdatePos( start ); - } - else - { - Clear(); - } + if (depth > m_pathlen) { + if (m_path) { + delete[] m_path; + } + + m_pathlen = 10 * (depth - 1) / 10 + 10; + m_path = new PathInfo[m_pathlen]; + } + + m_startpathpos = PathManager.GeneratePathAway(m_path); + m_pathpos = m_startpathpos; + m_TotalDist = PathManager.total_dist; + m_Side = false; + m_Time = level.inttime; + UpdatePos(start); } -float ActorPath::PathLookAhead - ( - float total_area, - Vector& end, - float *origin - ) +void ActorPath::FindPathNear( + float *start, + float *nearby, + Entity *ent, + float maxPath, + float fRadiusSquared, + float *vLeashHome, + float fLeashDistSquared +) { - float area = total_area; - float s; - float t; - float normal[ 2 ]; - float delta[ 2 ]; - Vector pos; - float fallheight; - PathInfo *current_path = m_pathpos; + int depth; - while( 1 ) - { - pos = current_path->point; + depth = PathManager.FindPathNear( + start, nearby, ent, maxPath, fRadiusSquared, vLeashHome, fLeashDistSquared, m_FallHeight + ); - if( current_path == m_path ) - break; + if (!depth) { + Clear(); + return; + } - fallheight = current_path->point[ 2 ] - origin[ 2 ]; + if (depth > m_pathlen) { + if (m_path) { + delete[] m_path; + } - if( fallheight > 94.0f || fallheight < -94.0f ) - { - VectorCopy( current_path->point, end ); - m_HasCompleteLookahead = false; - return area; - } + m_pathlen = 10 * (depth - 1) / 10 + 10; + m_path = new PathInfo[m_pathlen]; + } - current_path--; - - normal[ 0 ] = current_path->point[ 1 ] - pos[ 1 ]; - normal[ 1 ] = pos[ 0 ] - current_path->point[ 0 ]; - - VectorNormalize2D( normal ); - - delta[ 0 ] = current_path->point[ 0 ] - origin[ 0 ]; - delta[ 1 ] = current_path->point[ 1 ] - origin[ 1 ]; - - t = fabs( DotProduct2D( delta, normal ) ) * current_path->dist; - - if( t >= area ) - { - t = area / t; - s = 1.0f - t; - - end[ 0 ] = current_path->point[ 0 ] * t + pos[ 0 ] * s; - end[ 1 ] = current_path->point[ 1 ] * t + pos[ 1 ] * s; - end[ 2 ] = current_path->point[ 2 ] * t + pos[ 2 ] * s; - m_HasCompleteLookahead = false; - return 0; - } - - area -= t; - } - - VectorCopy( current_path->point, end ); - m_HasCompleteLookahead = true; - - return area; + m_startpathpos = PathManager.GeneratePathNear(m_path); + m_pathpos = m_startpathpos; + m_TotalDist = PathManager.total_dist; + m_Side = false; + m_Time = level.inttime; + UpdatePos(start); } -void ActorPath::UpdatePos - ( - float *origin, - float fNodeRadius - ) +void ActorPath::ReFindPath(float *start, Entity *ent) { - Vector end; - float s = 0; - float t = 0; - vec2_t delta; - float current_dot = 0; - float previous_dot = 0; - Vector pos; - PathInfo *current_path = NULL; - vec2_t dir; - Vector end2; - vec2_t delta2; - vec2_t dir2; + int depth; + vec3_t point; + // this is a critical bug in all versions of mohaa, it passes directly m_path->point + // but m_path can be deleted afterwards, leaving a dangling pointer to the path_end + // global variable + VectorCopy(m_path->point, point); - if( m_pathpos == m_path ) - { - end = m_pathpos->point; - m_bChangeLookAhead = true; - m_HasCompleteLookahead = true; - m_delta[ 0 ] = end[ 0 ] - origin[ 0 ]; - m_delta[ 1 ] = end[ 1 ] - origin[ 1 ]; - VectorNormalize2D2( m_delta, dir ); - } - else if( m_fLookAhead >= 4096.0f ) - { - if( m_fLookAhead - 4096.0f >= PathLookAhead( m_fLookAhead, end, origin ) ) - { - Vector mins = Vector( -15, -15, 0 ); - Vector maxs = Vector( 15, 15, 60 ); - Vector e = end + Vector( 0, 0, 32 ); + depth = PathManager.FindPath(start, point, ent, 0, NULL, 0, m_FallHeight); - pos = origin + Vector( 0, 0, 32 ); + if (!depth) { + Clear(); + return; + } - if( G_SightTrace( - pos, - mins, - maxs, - e, - ( gentity_t * )NULL, // g_entities[ 0 ].entity - 0, - MASK_PLAYERSOLID, - false, - "Actor::UpdatePos 2" ) != true ) - { - if( m_bChangeLookAhead ) - { - m_fLookAhead -= 2048.0f; - m_bChangeLookAhead = false; - } - else - { - m_fLookAhead *= 0.5f; - } + if (depth > m_pathlen) { + if (m_path) { + delete[] m_path; + } - if( m_fLookAhead < 4096.0f ) - { - m_fLookAhead = 4096.0f; - } + m_pathlen = 10 * (depth - 1) / 10 + 10; + m_path = new PathInfo[m_pathlen]; + } - PathLookAhead( 4096.0f, end, origin ); - goto __setdelta; - } - } - - m_fLookAhead += 1024.0f; - - if( m_fLookAhead > 65536.0f ) - m_fLookAhead = 65536.0f; - - m_bChangeLookAhead = true; - -__setdelta: - - m_delta[ 0 ] = end[ 0 ] - origin[ 0 ]; - m_delta[ 1 ] = end[ 1 ] - origin[ 1 ]; - - VectorNormalize2D2( m_delta, dir ); - } - else if( PathLookAhead( 4096.0f, end, origin ) < 4096.0f - m_fLookAhead ) - { - PathLookAhead( m_fLookAhead, end2, origin ); - - Vector mins = Vector( -15, -15, 0 ); - Vector maxs = Vector( 15, 15, 60 ); - Vector e = end2 + Vector( 0, 0, 32 ); - - pos = origin + Vector( 0, 0, 32 ); - - if( G_SightTrace( - pos, - mins, - maxs, - e, - ( gentity_t * )NULL, - 0, - MASK_MONSTERSOLID, - false, - "Actor::UpdatePos 1" ) != true ) - { - m_fLookAhead += 1024.0f; - - if( m_fLookAhead > 4096.0f ) - m_fLookAhead = 4096.0f; - } - else - { - m_fLookAhead -= 1024.0f; - - if( m_fLookAhead < 1024.0f ) - m_fLookAhead = 1024.0f; - - PathLookAhead( m_fLookAhead, end2, origin ); - } - - delta[ 0 ] = end2[ 0 ] - origin[ 0 ]; - delta[ 1 ] = end2[ 1 ] - origin[ 1 ]; - VectorNormalize2D2( delta, dir2 ); - - m_delta[ 0 ] = end[ 0 ] - origin[ 0 ]; - m_delta[ 1 ] = end[ 1 ] - origin[ 1 ]; - VectorNormalize2D2( m_delta, dir ); - - if( DotProduct2D( dir, dir2 ) > 0.7f ) - { - m_delta[ 0 ] = delta[ 0 ]; - m_delta[ 1 ] = delta[ 1 ]; - } - - m_bChangeLookAhead = true; - } - else - { - m_fLookAhead -= 1024.0f; - - if( m_fLookAhead < 1024.0f ) - m_fLookAhead = 1024.0f; - - m_delta[ 0 ] = end[ 0 ] - origin[ 0 ]; - m_delta[ 1 ] = end[ 1 ] - origin[ 1 ]; - VectorNormalize2D2( m_delta, dir ); - - m_bChangeLookAhead = true; - } - - current_path = m_pathpos; - - while( 1 ) - { - delta2[ 0 ] = current_path->point[ 0 ] - origin[ 0 ]; - delta2[ 1 ] = current_path->point[ 1 ] - origin[ 1 ]; - current_dot = DotProduct2D( delta2, dir ) - fNodeRadius; - - if( current_dot >= 0.0f ) - break; - - previous_dot = current_dot; - - if( current_path == LastNode() ) - break; - - current_path--; - } - - if( current_path != m_pathpos ) - { - m_pathpos = current_path + 1; - - t = previous_dot / ( previous_dot - current_dot ); - s = 1.0f - t; - - /*m_pathpos->point[ 0 ] = m_pathpos->point[ 0 ] * s + current_path->point[ 0 ] * t; - m_pathpos->point[ 1 ] = m_pathpos->point[ 1 ] * s + current_path->point[ 1 ] * t; - m_pathpos->point[ 2 ] = m_pathpos->point[ 2 ] * s + current_path->point[ 2 ] * t;*/ - - VectorCopy( current_path->point, m_pathpos->point ); - - current_path->dist *= s; - - m_Side = true; - } - else - { - m_Side = false; - } + m_startpathpos = PathManager.GeneratePath(m_path); + m_pathpos = m_startpathpos; + m_TotalDist = PathManager.total_dist; + m_Side = false; + m_Time = level.inttime; + UpdatePos(start); } -bool ActorPath::Complete - ( - const float *origin - ) const +void ActorPath::UpdatePos(float *origin, float fNodeRadius) { - if( !m_HasCompleteLookahead ) - return false; + Vector end; + float s = 0; + float t = 0; + vec2_t delta; + float current_dot = 0; + float previous_dot = 0; + Vector pos; + PathInfo *current_path = NULL; + vec2_t dir; + Vector end2; + vec2_t delta2; + vec2_t dir2; - if( !m_path ) - return true; + if (m_pathpos == m_path) { + end = m_pathpos->point; + m_bChangeLookAhead = true; + m_HasCompleteLookahead = true; + VectorSub2D(end, origin, m_delta); + VectorNormalize2D2(m_delta, dir); + } else if (m_fLookAhead >= 4096.0f) { + if (PathLookAhead(m_fLookAhead, end, origin) > (m_fLookAhead - 4096.0f) + || G_SightTrace( + origin + Vector(0, 0, 32), + Vector(-15, -15, 0), + Vector(15, 15, 60), + end + Vector(0, 0, 32), + g_entities[0].entity, + NULL, + MASK_ACTORPATH, + false, + "Actor::UpdatePos 2" + )) { + m_fLookAhead += 1024.0f; - if( fabs( origin[ 0 ] - m_path->point[ 0 ] ) < 16.0f && - fabs( origin[ 1 ] - m_path->point[ 1 ] ) < 16.0f ) - { - return true; - } + if (m_fLookAhead > Square(256)) { + m_fLookAhead = Square(256); + } - return false; + m_bChangeLookAhead = true; + } else { + if (m_bChangeLookAhead) { + m_fLookAhead -= 2048.0f; + m_bChangeLookAhead = false; + } else { + m_fLookAhead /= 2.f; + } + + if (m_fLookAhead < 4096.0f) { + m_fLookAhead = 4096.0f; + } + + PathLookAhead(m_fLookAhead, end, origin); + } + + VectorSub2D(end, origin, m_delta); + VectorNormalize2D2(m_delta, dir); + } else if (PathLookAhead(4096.0f, end, origin) < 4096.0f - m_fLookAhead) { + PathLookAhead(m_fLookAhead, end2, origin); + + if (!G_SightTrace( + origin + Vector(0, 0, 32), + Vector(-15, -15, 0), + Vector(15, 15, 60), + end2 + Vector(0, 0, 32), + g_entities[0].entity, + 0, + MASK_ACTORPATH, + false, + "Actor::UpdatePos 1" + )) { + m_fLookAhead -= 1024.0f; + + if (m_fLookAhead < 1024.0f) { + m_fLookAhead = 1024.0f; + } + + PathLookAhead(m_fLookAhead, end2, origin); + } else { + m_fLookAhead += 1024.0f; + + if (m_fLookAhead > 4096.0f) { + m_fLookAhead = 4096.0f; + } + } + + VectorSub2D(end2, origin, delta); + VectorNormalize2D2(delta, dir2); + + VectorSub2D(end, origin, delta); + VectorNormalize2D2(m_delta, dir); + + if (DotProduct2D(dir, dir2) > 0.7f) { + VectorCopy2D(delta, m_delta); + VectorCopy2D(dir2, dir); + } + + m_bChangeLookAhead = true; + } else { + m_fLookAhead -= 1024.0f; + + if (m_fLookAhead < 1024.0f) { + m_fLookAhead = 1024.0f; + } + + VectorSub2D(end, origin, m_delta); + VectorNormalize2D2(m_delta, dir); + + m_bChangeLookAhead = true; + } + + // Added in OPM. + // The check was added to make sure to stop if it's the last node + for (current_path = m_pathpos; current_path >= LastNode(); current_path--) { + VectorSub2D(current_path->point, origin, delta2); + //current_dot = DotProduct2D(delta2, dir) - fNodeRadius; + // Removed in 2.0 + // fNodeRadius is now unused? + current_dot = DotProduct2D(delta2, dir); + + if (current_dot >= 0) { + break; + } + + previous_dot = current_dot; + } + + if (current_path != m_pathpos) { + m_pathpos = current_path + 1; + + t = previous_dot / (previous_dot - current_dot); + s = 1.0f - t; + + m_pathpos->point[0] = m_pathpos->point[0] * s + current_path->point[0] * t; + m_pathpos->point[1] = m_pathpos->point[1] * s + current_path->point[1] * t; + m_pathpos->point[2] = m_pathpos->point[2] * s + current_path->point[2] * t; + + current_path->dist *= s; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + + m_Side = true; + } else { + m_Side = false; + } + + // Added in 2.0. + // Make sure to clear the delta if it's invalid (NaN, infinite...) + if (!isfinite(m_delta[0]) || !isfinite(m_delta[1])) { + VectorClear2D(m_delta); + } } -PathInfo *ActorPath::StartNode - ( - void - ) const +bool ActorPath::Complete(const float *origin) const { - return m_startpathpos; + if (!m_HasCompleteLookahead) { + return false; + } + + if (fabs(origin[0] - m_path->point[0]) < 16.0f && fabs(origin[1] - m_path->point[1]) < 16.0f) { + return true; + } + + return false; } -PathInfo *ActorPath::CurrentNode - ( - void - ) const +void ActorPath::TrimPathFromEnd(int nNodesPop) { - return m_pathpos; + int iLastPos; + + iLastPos = m_path - m_pathpos; + if (iLastPos < 0) { + Clear(); + return; + } + + m_pathpos -= nNodesPop; + for (int i = 0; i < iLastPos; i++) { + m_path[i] = m_path[i + nNodesPop]; + } } -int ActorPath::CurrentNodeIndex - ( - void - ) const +void ActorPath::Shorten(float fDistRemove) { - return m_pathpos ? m_pathpos - m_path : -1; + while (m_path->dist >= fDistRemove) { + fDistRemove -= m_path->dist; + TrimPathFromEnd(1); + if (!m_pathpos) { + return; + } + } + + m_path->point[0] += m_path->dir[0] * -fDistRemove; + m_path->point[1] += m_path->dir[1] * -fDistRemove; + // Fixed in OPM. + // This is a bug in mohaa as it can write past the end of the class instance + //m_path->point[2] += m_path->dir[2] * -fDistRemove; + m_path->dist -= fDistRemove; + assert(m_path->dist > -1e+07 && m_path->dist < 1e+07); } -PathInfo *ActorPath::NextNode - ( - void - ) const +PathInfo *ActorPath::StartNode(void) const { - return m_pathpos == m_path ? NULL : m_pathpos - 1; + return m_startpathpos; } -PathInfo *ActorPath::LastNode - ( - void - ) const +PathInfo *ActorPath::CurrentNode(void) const { - return m_path; + return m_pathpos; } -Vector ActorPath::CurrentPathDir - ( - void - ) const +int ActorPath::CurrentNodeIndex(void) const { - return Vector( m_pathpos->dir[ 0 ], m_pathpos->dir[ 1 ], 0 ); + return m_pathpos ? m_pathpos - m_path : -1; } -float *ActorPath::CurrentPathGoal - ( - void - ) const +PathInfo *ActorPath::NextNode(void) const { - return m_pathpos->point; + return m_pathpos == m_path ? NULL : m_pathpos - 1; } -int ActorPath::Time - ( - void - ) const +PathInfo *ActorPath::LastNode(void) const { - return m_Time; + return m_path; } -Vector ActorPath::CurrentDelta - ( - void - ) const +const float *ActorPath::CurrentPathDir(void) const { - return Vector( m_delta[ 0 ], m_delta[ 1 ], 0 ); + if (m_pathpos == m_path) { + return m_delta; + } else { + return m_pathpos[-1].dir; + } } -bool ActorPath::IsAccurate - ( - void - ) const +const float *ActorPath::CurrentPathGoal(void) const { - return m_pathpos->bAccurate; + return m_path->point; } -float ActorPath::TotalDist - ( - void - ) const +int ActorPath::Time(void) const { - return m_TotalDist; + return m_Time; } -void ActorPath::SetFallHeight - ( - float fHeight - ) +const float *ActorPath::CurrentDelta(void) const { - m_FallHeight = fHeight; + return m_delta; } -float ActorPath::GetFallHeight - ( - void - ) const +bool ActorPath::IsAccurate(void) const { - return m_FallHeight; + if (m_pathpos == m_path) { + return false; + } + + if (!m_pathpos[-1].bAccurate) { + return false; + } + + if (!m_Side) { + return false; + } + + return true; } -void ActorPath::TrimPathFromEnd - ( - int nNodesPop - ) +void ActorPath::SetFallHeight(float fHeight) { - int iLastPos = m_path - m_pathpos; - - if( iLastPos - nNodesPop > 0 ) - { - for( int i = 0; i < iLastPos; i++ ) - { - m_path[ i ] = m_path[ i + nNodesPop ]; - } - } - else - { - Clear(); - } + m_FallHeight = fHeight; } -void ActorPath::Shorten - ( - float fDistRemove - ) +float ActorPath::GetFallHeight(void) const { - if( m_path->dist > fDistRemove ) - { - m_path->point[ 0 ] += m_path->dir[ 0 ] * -fDistRemove; - m_path->point[ 1 ] += m_path->dir[ 1 ] * -fDistRemove; - m_path->point[ 2 ] += m_path->point[ 2 ] * -fDistRemove; - m_path->dist -= fDistRemove; - } - else - { - while( fDistRemove - m_path->dist > m_path->dist ) - { - TrimPathFromEnd( 1 ); - - if( !m_pathpos ) - return; - } - } + return m_FallHeight; } -bool ActorPath::HasCompleteLookahead - ( - void - ) const +bool ActorPath::HasCompleteLookahead(void) const { - return m_HasCompleteLookahead; + return m_HasCompleteLookahead; } -bool ActorPath::IsSide - ( - void - ) const +float ActorPath::TotalDist(void) const { - return m_Side; + return m_TotalDist; } -void ActorPath::ForceShortLookahead - ( - void - ) +bool ActorPath::IsSide(void) const { - m_fLookAhead = 4096.0f; + return m_Side; } diff --git a/code/fgame/actorpath.h b/code/fgame/actorpath.h index 095faa8a..ced7fcc6 100644 --- a/code/fgame/actorpath.h +++ b/code/fgame/actorpath.h @@ -22,138 +22,145 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // actorpath.h: Actor path -#ifndef __ACTORPATH_H__ -#define __ACTORPATH_H__ - +#pragma once #define MIN_FALLHEIGHT 18 #define MAX_FALLHEIGHT 1024 -class ActorPath { - // path list - PathInfo *m_path; - int m_pathlen; - // path position - PathInfo *m_pathpos; +class ActorPath +{ + // path list + PathInfo *m_path; + int m_pathlen; - // starting path position - PathInfo *m_startpathpos; - vec2_t m_delta; - bool m_Side; - int m_Time; - float m_TotalDist; - short int m_FallHeight; - bool m_HasCompleteLookahead; - float m_fLookAhead; - bool m_bChangeLookAhead; + // path position + PathInfo *m_pathpos; + + // starting path position + PathInfo *m_startpathpos; + vec2_t m_delta; + bool m_Side; + int m_Time; + float m_TotalDist; + short int m_FallHeight; + bool m_HasCompleteLookahead; + float m_fLookAhead; + bool m_bChangeLookAhead; private: - float PathLookAhead( float total_area, Vector& end, float *origin ); + float PathLookAhead(float total_area, Vector& end, float *origin); public: - ActorPath(); - ~ActorPath(); + ActorPath(); + ~ActorPath(); - void Clear( void ); - bool DoesTheoreticPathExist( float *start, float *end, class SimpleActor *ent, float maxPath, float *vLeashHome, float fLeashDistSquared ); - void FindPath( float *start, float *end, Entity *ent, float maxPath, float *vLeashHome, float fLeashDistSquared ); - void FindPathAway( float *start, float *avoid, float *vPreferredDir, Entity *ent, float fMinSafeDist, float *vLeashHome, float fLeashDistSquared ); - void FindPathNear( float *start, float *nearby, Entity *ent, float maxPath, float fRadiusSquared, float *vLeashHome, float fLeashDistSquared ); - void ReFindPath( float *start, Entity *ent ); - void UpdatePos( float *origin, float fNodeRadius = 0.0f ); - bool Complete( const float *origin ) const; - PathInfo *StartNode( void ) const; - PathInfo *CurrentNode( void ) const; - int CurrentNodeIndex( void ) const; - PathInfo *NextNode( void ) const; - PathInfo *LastNode( void ) const; - Vector CurrentPathDir( void ) const; - float *CurrentPathGoal( void ) const; - int Time( void ) const; - Vector CurrentDelta( void ) const; - bool IsAccurate( void ) const; - float TotalDist( void ) const; - void SetFallHeight( float fHeight ); - float GetFallHeight( void ) const; - void TrimPathFromEnd( int nNodesPop ); - void Shorten( float fDistRemove ); - bool HasCompleteLookahead( void ) const; - bool IsSide( void ) const; - void ForceShortLookahead( void ); + void Clear(void); + bool DoesTheoreticPathExist( + float *start, float *end, class SimpleActor *ent, float maxPath, float *vLeashHome, float fLeashDistSquared + ); + void FindPath(float *start, float *end, Entity *ent, float maxPath, float *vLeashHome, float fLeashDistSquared); + void FindPathAway( + float *start, + float *avoid, + float *vPreferredDir, + Entity *ent, + float fMinSafeDist, + float *vLeashHome, + float fLeashDistSquared + ); + void FindPathNear( + float *start, + float *nearby, + Entity *ent, + float maxPath, + float fRadiusSquared, + float *vLeashHome, + float fLeashDistSquared + ); + void ReFindPath(float *start, Entity *ent); + void UpdatePos(float *origin, float fNodeRadius = 0.0f); + bool Complete(const float *origin) const; + PathInfo *StartNode(void) const; + PathInfo *CurrentNode(void) const; + int CurrentNodeIndex(void) const; + PathInfo *NextNode(void) const; + PathInfo *LastNode(void) const; + const float *CurrentPathDir(void) const; + const float *CurrentPathGoal(void) const; + int Time(void) const; + const float *CurrentDelta(void) const; + bool IsAccurate(void) const; + float TotalDist(void) const; + void SetFallHeight(float fHeight); + float GetFallHeight(void) const; + void TrimPathFromEnd(int nNodesPop); + void Shorten(float fDistRemove); + bool HasCompleteLookahead(void) const; + void ForceShortLookahead(void); - virtual void Archive( Archiver& arc ); + virtual void Archive(Archiver& arc); + + bool IsSide(void) const; }; -inline void ActorPath::Archive - ( - Archiver& arc - ) +inline void ActorPath::Archive(Archiver& arc) { - int pos; - int startpathpos; + int index; + int i; - arc.ArchiveInteger( &m_pathlen ); + arc.ArchiveInteger(&m_pathlen); - if( m_pathlen ) - { - if( arc.Loading() ) - { - m_path = new PathInfo[ m_pathlen ]; - } + if (m_pathlen) { + if (arc.Loading()) { + m_path = new PathInfo[m_pathlen]; + } - if( m_pathlen > 0 ) - { - for( int i = 0; i < m_pathlen; i++ ) - { - m_path->Archive( arc ); - } - } + for (i = 0; i < m_pathlen; i++) { + m_path[i].Archive(arc); + } - if( !arc.Saving() ) - { - arc.ArchiveInteger( &pos ); - if( pos == -1 ) - m_pathpos = NULL; - else - m_pathpos = &m_path[ pos ]; + if (!arc.Saving()) { + arc.ArchiveInteger(&index); + if (index == -1) { + m_pathpos = NULL; + } else { + m_pathpos = &m_path[index]; + } - arc.ArchiveInteger( &startpathpos ); - if( startpathpos == -1 ) - m_startpathpos = NULL; - else - m_startpathpos = &m_path[ pos ]; - } - else - { - if( m_pathpos ) - pos = m_pathpos - m_path; - else - pos = -1; + arc.ArchiveInteger(&index); + if (index == -1) { + m_startpathpos = NULL; + } else { + m_startpathpos = &m_path[index]; + } + } else { + if (m_pathpos) { + index = m_pathpos - m_path; + } else { + index = -1; + } - arc.ArchiveInteger( &pos ); + arc.ArchiveInteger(&index); - if( m_startpathpos ) - pos = m_startpathpos - m_path; - else - pos = -1; + if (m_startpathpos) { + index = m_startpathpos - m_path; + } else { + index = -1; + } - arc.ArchiveInteger( &pos ); - } - } - else if( arc.Loading() ) - { - m_pathpos = 0; - } + arc.ArchiveInteger(&index); + } + } else if (arc.Loading()) { + m_pathpos = 0; + } - arc.ArchiveVec2( m_delta ); - arc.ArchiveBool( &m_Side ); - arc.ArchiveInteger( &m_Time ); - arc.ArchiveFloat( &m_TotalDist ); - arc.ArchiveShort( &m_FallHeight ); - arc.ArchiveShort( &m_FallHeight ); - arc.ArchiveBool( &m_HasCompleteLookahead ); - arc.ArchiveFloat( &m_fLookAhead ); - arc.ArchiveBool( &m_bChangeLookAhead ); + arc.ArchiveVec2(m_delta); + arc.ArchiveBool(&m_Side); + arc.ArchiveInteger(&m_Time); + arc.ArchiveFloat(&m_TotalDist); + arc.ArchiveShort(&m_FallHeight); + arc.ArchiveShort(&m_FallHeight); + arc.ArchiveBool(&m_HasCompleteLookahead); + arc.ArchiveFloat(&m_fLookAhead); + arc.ArchiveBool(&m_bChangeLookAhead); } - -#endif /* actorpath.h */ diff --git a/code/fgame/ammo.cpp b/code/fgame/ammo.cpp index 64667f7a..de9b8c53 100644 --- a/code/fgame/ammo.cpp +++ b/code/fgame/ammo.cpp @@ -21,163 +21,172 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // ammo.cpp: Base class for all ammunition for entities derived from the Weapon class. -// +// // AmmoEntity is the Class which represents ammo that the player "sees" and " // picks up" in the game // -// Ammo is the Class which is used to keep track of how much ammo a player has +// Ammo is the Class which is used to keep track of how much ammo a player has // in his inventory #include "ammo.h" #include "player.h" +#include "g_phys.h" -CLASS_DECLARATION( Item, AmmoEntity, NULL ) - { - { NULL, NULL } - }; +Event EV_AmmoEntity_PostSpawn +( + "ammoentity_postspawn", + EV_DEFAULT, + NULL, + NULL, + "Ammo Entity Post Spawn" +); -AmmoEntity::AmmoEntity - ( - ) +CLASS_DECLARATION(Item, AmmoEntity, NULL) { + {&EV_AmmoEntity_PostSpawn, &AmmoEntity::EventPostSpawn}, + {NULL, NULL } +}; - { - if ( LoadingSavegame ) - { - // all data will be setup by the archive function - return; - } - setName( "UnknownAmmo" ); - amount = 0; - } +AmmoEntity::AmmoEntity() +{ + if (LoadingSavegame) { + // all data will be setup by the archive function + return; + } + setName("UnknownAmmo"); + amount = 0; -Item *AmmoEntity::ItemPickup - ( - Entity *other, - qboolean add_to_inventory - ) + PostEvent(EV_AmmoEntity_PostSpawn, EV_POSTSPAWN); +} - { - Sentient *player; - str realname; - AliasListNode_t *ret; +Item *AmmoEntity::ItemPickup(Entity *other, qboolean add_to_inventory) +{ + Sentient *player; + Weapon *pWeap; - if ( !other->isSubclassOf( Player ) ) - return NULL; + if (!other->IsSubclassOfPlayer()) { + return NULL; + } - player = ( Sentient * )other; + player = (Sentient *)other; - // Play pickup sound - realname = GetRandomAlias( "snd_pickup", &ret ); - if ( realname.length() > 1 ) - player->Sound( realname, CHAN_ITEM ); + if (player->AmmoCount(item_name.c_str()) == player->MaxAmmoCount(item_name.c_str())) { + // don't pickup if the player already has max ammo + return NULL; + } - // Cancel some events - CancelEventsOfType( EV_Item_DropToFloor ); - CancelEventsOfType( EV_Item_Respawn ); - CancelEventsOfType( EV_FadeOut ); + // Play pickup sound + player->Sound(sPickupSound, CHAN_ITEM); - // Hide the model - setSolidType( SOLID_NOT ); - hideModel(); + // Cancel some events + CancelEventsOfType(EV_Item_DropToFloor); + CancelEventsOfType(EV_Item_Respawn); + CancelEventsOfType(EV_FadeOut); - // Respawn? - if ( !Respawnable() ) - PostEvent( EV_Remove, FRAMETIME ); - else - PostEvent( EV_Item_Respawn, RespawnTime() ); + // Hide the model + setSolidType(SOLID_NOT); + hideModel(); - // Give the ammo to the player - player->GiveAmmo( item_name, amount ); - return NULL; // This doesn't create any items - } + // Respawn? + if (!Respawnable()) { + PostEvent(EV_Remove, FRAMETIME); + } else { + PostEvent(EV_Item_Respawn, RespawnTime()); + } + // Notify scripts about the pickup + Unregister(STRING_PICKUP); + + // Tell the player about the ammo being picked + gi.SendServerCommand( + other->edict - g_entities, + "print \"" HUD_MESSAGE_YELLOW "%s\"", + gi.LV_ConvertString(va("Got %d %s Rounds", amount, item_name.c_str())) + ); + + // Give the ammo to the player + player->GiveAmmo(item_name, amount); + + // Make the weapon reload if the weapon has an empty clip + pWeap = player->GetActiveWeapon(WEAPON_MAIN); + if (pWeap && !pWeap->HasAmmoInClip(FIRE_PRIMARY) && pWeap->CheckReload(FIRE_PRIMARY)) { + pWeap->SetShouldReload(qtrue); + } + + return NULL; // This doesn't create any items +} + +void AmmoEntity::EventPostSpawn(Event *ev) +{ + vec3_t fullmins; + vec3_t fullmaxs; + + setMoveType(MOVETYPE_TOSS); + if (edict->tiki) { + gi.TIKI_CalculateBounds(edict->tiki, edict->s.scale, fullmins, fullmaxs); + setSize(fullmins, fullmaxs); + link(); + } + + droptofloor(256); +} // This is the Class that is used to keep track of ammo in the player's inventory. // It is not an entit, just a name and an amount. -CLASS_DECLARATION( Class, Ammo, NULL ) - { - {NULL, NULL} - }; +CLASS_DECLARATION(Class, Ammo, NULL) { + {NULL, NULL} +}; -Ammo::Ammo - ( - ) +Ammo::Ammo() + : amount(0) + , maxamount(0) + , name_index(0) +{ + if (LoadingSavegame) { + // all data will be setup by the archive function + return; + } + setName("UnknownAmmo"); + setAmount(0); + setMaxAmount(100); +} - { - if ( LoadingSavegame ) - { - // all data will be setup by the archive function - return; - } - setName( "UnknownAmmo" ); - setAmount( 0 ); - setMaxAmount( 100 ); - } +void Ammo::setAmount(int a) +{ + amount = a; -void Ammo::setAmount - ( - int a - ) + if ((maxamount > 0) && (amount > maxamount)) { + amount = maxamount; + } +} - { - amount = a; +int Ammo::getAmount(void) +{ + return amount; +} - if ( ( maxamount > 0 ) && ( amount > maxamount ) ) - amount = maxamount; - } +void Ammo::setMaxAmount(int a) +{ + maxamount = a; +} -int Ammo::getAmount - ( - void - ) +int Ammo::getMaxAmount(void) +{ + return maxamount; +} - { - return amount; - } +void Ammo::setName(str n) +{ + name = n; + name_index = gi.itemindex(name) + CS_WEAPONS; +} -void Ammo::setMaxAmount - ( - int a - ) +str Ammo::getName(void) +{ + return name; +} - { - maxamount = a; - } - -int Ammo::getMaxAmount - ( - void - ) - - { - return maxamount; - } - -void Ammo::setName - ( - str n - ) - - { - name = n; - name_index = gi.itemindex( name ) + CS_WEAPONS; - } - -str Ammo::getName - ( - void - ) - - { - return name; - } - -int Ammo::getIndex - ( - void - ) - - { - return name_index; - } +int Ammo::getIndex(void) +{ + return name_index; +} diff --git a/code/fgame/ammo.h b/code/fgame/ammo.h index 3b8b3b9e..24cb172c 100644 --- a/code/fgame/ammo.h +++ b/code/fgame/ammo.h @@ -22,62 +22,56 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ammo.h: Base class for all ammunition for entities derived from the Weapon class. -#ifndef __AMMO_H__ -#define __AMMO_H__ +#pragma once #include "g_local.h" #include "item.h" class AmmoEntity : public Item - { - public: - CLASS_PROTOTYPE( AmmoEntity ); +{ +public: + CLASS_PROTOTYPE(AmmoEntity); - AmmoEntity(); - Item *ItemPickup( Entity *other, qboolean add_to_inventory ) override; - }; + AmmoEntity(); + Item *ItemPickup(Entity *other, qboolean add_to_inventory) override; + void EventPostSpawn(Event *ev); +}; class Ammo : public Class - { - int amount; - int maxamount; - str name; - int name_index; +{ + int amount; + int maxamount; + str name; + int name_index; - public: - CLASS_PROTOTYPE( Ammo ); +public: + CLASS_PROTOTYPE(Ammo); - Ammo(); - Ammo(str name, int amount, int name_index ); + Ammo(); + Ammo(str name, int amount, int name_index); - void setAmount( int a ); - int getAmount( void ); - void setMaxAmount( int a ); - int getMaxAmount( void ); - void setName( str name); - str getName( void ); - int getIndex( void ); - void Archive( Archiver &arc ) override; - }; + void setAmount(int a); + int getAmount(void); + void setMaxAmount(int a); + int getMaxAmount(void); + void setName(str name); + str getName(void); + int getIndex(void); + void Archive(Archiver& arc) override; +}; -inline void Ammo::Archive - ( - Archiver &arc - ) +inline void Ammo::Archive(Archiver& arc) +{ + Class::Archive(arc); - { - Class::Archive( arc ); - - arc.ArchiveInteger( &amount ); - arc.ArchiveInteger( &maxamount ); - arc.ArchiveString( &name ); - // - // name_index not archived, because it is auto-generated by gi.itemindex - // - if ( arc.Loading() ) - { - setName( name ); - } - } - -#endif /* ammo.h */ + arc.ArchiveInteger(&amount); + arc.ArchiveInteger(&maxamount); + arc.ArchiveString(&name); + arc.ArchiveInteger(&name_index); + // + // name_index not archived, because it is auto-generated by gi.itemindex + // + if (arc.Loading()) { + setName(name); + } +} diff --git a/code/fgame/animate.cpp b/code/fgame/animate.cpp index b24b26cb..5855f110 100644 --- a/code/fgame/animate.cpp +++ b/code/fgame/animate.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -32,48 +32,35 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA extern Event EV_Entity_Start; // Leg Animation events -Event EV_SetAnim("anim", EV_ZERO, "s", "animName", "Exec anim commands on server or client.", EV_NORMAL); -Event EV_SetSyncTime("setsynctime", EV_ZERO, "f", "synctime", "Set sync time for entity."); -Event EV_SetFrame( - "setframe", +Event EV_SetAnim +( + "anim", EV_ZERO, - "iS", - "frameNumber animName", - "Set the frame on the legs, if anim is not specified, current is assumed.", + "s", + "animName", + "Exec anim commands on server or client.", EV_NORMAL ); -Event EV_AnimDone("animdone", EV_ZERO, NULL, NULL, "Legs animation has finished, not for script use.", EV_NORMAL); -Event EV_FrameDelta( - "setmovedelta", EV_ZERO, "vf", "moveDelta moveTime", "movement from animation, not for script use.", EV_NORMAL -); -Event EV_Torso_Anim("torso_anim", EV_ZERO, "s", "animName", "set the torso animation to animName.", EV_NORMAL); -Event EV_Torso_SetFrame( - "torso_setframe", +Event EV_SetSyncTime +( + "setsynctime", EV_ZERO, - "iS", - "frameNumber animName", - "Set the frame on the torso, if anim is not specified, current is assumed.", + "f", + "synctime", + "Set sync time for entity.", EV_NORMAL ); -Event EV_Torso_AnimDone( - "torso_animdone", EV_ZERO, NULL, NULL, "Torso animation has finished, not for script use.", EV_NORMAL +Event EV_Animate_IsLoopingAnim +( + "isloopinganim", + EV_DEFAULT, + "s", + "anim_name", + "returns 1 if the anim is a looping anim, or 0 otherwise", + EV_RETURN ); -Event EV_Torso_StopAnimating( - "torso_stopanimating", - EV_ZERO, - NULL, - NULL, - "stop the torso from animating. Animation will end at the end of current cycle.", - EV_NORMAL -); -Event EV_NewAnim( - "animate_newanim", EV_ZERO, "ii", "animNum slot", "Start a new animation, not for script use.", EV_NORMAL -); -Event EV_ViewAnim("viewanim", EV_DEFAULT, "s", "anim", "testing"); -Event EV_Animate_IsLoopingAnim( - "isloopinganim", EV_DEFAULT, "s", "anim_name", "returns 1 if the anim is a looping anim, or 0 otherwise", EV_RETURN -); -Event EV_Animate_SetYawfromBone( +Event EV_Animate_SetYawfromBone +( "setyawfrombone", EV_DEFAULT, "s", @@ -81,7 +68,8 @@ Event EV_Animate_SetYawfromBone( "Set the yaw of the model based on the current animation time", EV_NORMAL ); -Event EV_Animate_PlayerSpawn( +Event EV_Animate_PlayerSpawn +( "playerspawn", EV_DEFAULT, "sFVFF", @@ -101,10 +89,33 @@ Event EV_Animate_PlayerSpawn( "one second later.", EV_NORMAL ); -Event EV_Animate_PlayerSpawn_Utility( - "testmojo", EV_DEFAULT, "sv", "model_name vector_offset", "INTERNAL EVENT", EV_NORMAL +Event EV_Animate_PlayerSpawn_Utility +( + "testmojo", + EV_DEFAULT, + "sv", + "model_name vector_offset", + "INTERNAL EVENT", + EV_NORMAL +); +Event EV_Animate_PauseAnim +( + "pauseanims", + EV_DEFAULT, + "i", + "pause", + "Pause (or unpause) animations", + EV_NORMAL +); +Event EV_Animate_Client_Sound +( + "_client_sound", + EV_DEFAULT, + NULL, + NULL, + NULL, + EV_NORMAL ); -Event EV_Animate_PauseAnim("pauseanims", EV_DEFAULT, "i", "pause", "Pause (or unpause) animations"); CLASS_DECLARATION(Entity, Animate, "animate") { {&EV_SetControllerAngles, &Animate::SetControllerAngles }, @@ -115,16 +126,54 @@ CLASS_DECLARATION(Entity, Animate, "animate") { {&EV_Animate_PlayerSpawn, &Animate::EventPlayerSpawn }, {&EV_Animate_PlayerSpawn_Utility, &Animate::EventPlayerSpawnUtility}, {&EV_Animate_PauseAnim, &Animate::EventPauseAnim }, + {&EV_Animate_Client_Sound, &Animate::ClientSound }, {NULL, NULL } }; +static size_t GetLongestClientCmdLength(const tiki_cmd_t& cmds) +{ + size_t ii; + size_t longest = 0; + + for (ii = 0; ii < cmds.num_cmds; ii++) { + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + size_t length = strlen(single_cmd.args[0]); + if (length > longest) { + longest = length; + } + } + + return longest; +} + +static size_t GetLongestClientCmdAllFramesLength(dtiki_t *tiki, int animnum, int numframes) +{ + tiki_cmd_t cmds; + size_t longest = 0; + int i; + + for (i = 0; i < numframes; i++) { + // we want normal frame commands to occur right on the frame + if (gi.Frame_Commands_Client(tiki, animnum, i, &cmds)) { + size_t length = GetLongestClientCmdLength(cmds); + if (length > longest) { + longest = length; + } + } + } + + return longest; +} + Animate::Animate() { - entflags |= EF_ANIMATE; + entflags |= ECF_ANIMATE; + + syncTime = 0.0f; + syncRate = 1.0f; pauseSyncTime = 0.0f; - syncTime = 0.0f; - syncRate = 1.0f; + is_paused = false; frame_delta = vec_zero; angular_delta = 0; @@ -149,7 +198,7 @@ Animate::Animate() Animate::~Animate() { - entflags &= ~EF_ANIMATE; + entflags &= ~ECF_ANIMATE; } void Animate::ForwardExec(Event *ev) @@ -164,7 +213,6 @@ void Animate::ForwardExec(Event *ev) ); } - NewAnim(ev->GetString(1), 0); RestartAnimSlot(0); } @@ -217,11 +265,10 @@ void Animate::NewAnim(int animnum, int slot, float weight) animFlags[slot] = ANIM_LOOP | ANIM_NODELTA | ANIM_NOEXIT; if (!(gi.Anim_FlagsSkel(edict->tiki, animnum) & ANIM_LOOP)) { - animFlags[slot] &= ~ANIM_LOOP; + SetOnceType(slot); } - edict->s.frameInfo[slot].weight = weight; - + SetWeight(slot, weight); animtimes[slot] = gi.Anim_Time(edict->tiki, animnum); frametimes[slot] = gi.Anim_Frametime(edict->tiki, animnum); @@ -229,7 +276,8 @@ void Animate::NewAnim(int animnum, int slot, float weight) edict->s.eType = ET_MODELANIM; } - qboolean hascommands = gi.Anim_HasCommands(edict->tiki, animnum); + qboolean hascommands = + gi.Anim_HasCommands(edict->tiki, animnum) || gi.Anim_HasCommands_Client(edict->tiki, animnum); // enter this animation if (newanim) { @@ -241,18 +289,53 @@ void Animate::NewAnim(int animnum, int slot, float weight) int ii, j; for (ii = 0; ii < cmds.num_cmds; ii++) { - ev = new AnimationEvent(cmds.cmds[ii].args[0]); + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; - ev->SetAnimationNumber(animnum); - ev->SetAnimationFrame(0); + AnimationEvent ev(single_cmd.args[0], single_cmd.num_args); - for (j = 1; j < cmds.cmds[ii].num_args; j++) { - ev->AddToken(cmds.cmds[ii].args[j]); + ev.SetAnimationNumber(animnum); + ev.SetAnimationFrame(0); + + for (j = 1; j < single_cmd.num_args; j++) { + ev.AddToken(single_cmd.args[j]); } ProcessEvent(ev); } } + + if (gi.Frame_Commands_Client(edict->tiki, animnum, TIKI_FRAME_ENTRY, &cmds)) { + size_t longest = GetLongestClientCmdLength(cmds); + int ii, j; + + if (longest) { + char *cmdName = (char *)alloca(longest + 8 + 1); + + for (ii = 0; ii < cmds.num_cmds; ii++) { + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + int eventNum; + + Q_strncpyz(cmdName, "_client_", longest + 8 + 1); + Q_strncpyz(cmdName + 8, single_cmd.args[0], longest + 1); + + eventNum = Event::FindEventNum(cmdName); + + AnimationEvent ev(eventNum, single_cmd.num_args); + if (!ev.eventnum) { + continue; + } + + ev.SetAnimationNumber(animnum); + ev.SetAnimationFrame(0); + + for (j = 1; j < single_cmd.num_args; j++) { + ev.AddToken(single_cmd.args[j]); + } + + ProcessEvent(ev); + } + } + } } if (!hascommands) { @@ -272,37 +355,75 @@ void Animate::NewAnim(int animnum, int slot, float weight) int ii, j; for (ii = 0; ii < cmds.num_cmds; ii++) { - ev = new AnimationEvent(cmds.cmds[ii].args[0]); + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + + ev = new AnimationEvent(single_cmd.args[0], single_cmd.num_args); ev->SetAnimationNumber(animnum); ev->SetAnimationFrame(i); - for (j = 1; j < cmds.cmds[ii].num_args; j++) { - ev->AddToken(cmds.cmds[ii].args[j]); + for (j = 1; j < single_cmd.num_args; j++) { + ev->AddToken(single_cmd.args[j]); } PostEvent(ev, time, 1 << slot); } } } + + time = 0.0f; + + const size_t longestAllFrames = GetLongestClientCmdAllFramesLength(edict->tiki, animnum, numframes); + if (longestAllFrames) { + char *cmdName = (char *)alloca(longestAllFrames + 8 + 1); + + for (i = 0; i < numframes; i++, time += frametimes[slot]) { + // we want normal frame commands to occur right on the frame + if (gi.Frame_Commands_Client(edict->tiki, animnum, i, &cmds)) { + int ii, j; + + for (ii = 0; ii < cmds.num_cmds; ii++) { + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + int eventNum; + + Q_strncpyz(cmdName, "_client_", longestAllFrames + 8 + 1); + Q_strncpyz(cmdName + 8, single_cmd.args[0], longestAllFrames + 1); + + eventNum = Event::FindEventNum(cmdName); + + AnimationEvent ev(eventNum, single_cmd.num_args); + if (!ev.eventnum) { + continue; + } + + ev.SetAnimationNumber(animnum); + ev.SetAnimationFrame(i); + + for (j = 1; j < single_cmd.num_args; j++) { + ev.AddToken(single_cmd.args[j]); + } + + PostEvent(ev, time, 1 << slot); + } + } + } + } } void Animate::NewAnim(int animnum, Event& newevent, int slot, float weight) { - if (animnum == -1) { + if (animnum != -1) { + NewAnim(animnum, slot); + SetAnimDoneEvent(newevent, slot); + } else { PostEvent(newevent, level.frametime); } - - NewAnim(animnum, slot); - SetAnimDoneEvent(newevent, slot); } void Animate::NewAnim(int animnum, Event *newevent, int slot, float weight) { - if (animnum == -1) { - if (newevent) { - PostEvent(newevent, level.frametime); - } + if (animnum == -1 && newevent) { + PostEvent(newevent, level.frametime); } NewAnim(animnum, slot); @@ -311,7 +432,7 @@ void Animate::NewAnim(int animnum, Event *newevent, int slot, float weight) void Animate::NewAnim(const char *animname, int slot, float weight) { - int animnum = gi.Anim_Random(edict->tiki, animname); + int animnum = gi.Anim_NumForName(edict->tiki, animname); if (animnum != -1) { NewAnim(animnum, slot); @@ -320,19 +441,25 @@ void Animate::NewAnim(const char *animname, int slot, float weight) void Animate::NewAnim(const char *animname, Event *endevent, int slot, float weight) { - int animnum = gi.Anim_Random(edict->tiki, animname); + int animnum = gi.Anim_NumForName(edict->tiki, animname); if (animnum != -1) { - NewAnim(animnum, endevent, slot); + NewAnim(animnum, slot, weight); + SetAnimDoneEvent(endevent, slot); + } else if (endevent) { + PostEvent(endevent, level.frametime); } } void Animate::NewAnim(const char *animname, Event& endevent, int slot, float weight) { - int animnum = gi.Anim_Random(edict->tiki, animname); + int animnum = gi.Anim_NumForName(edict->tiki, animname); if (animnum != -1) { - NewAnim(animnum, endevent, slot); + NewAnim(animnum, slot, weight); + SetAnimDoneEvent(endevent, slot); + } else { + PostEvent(endevent, level.frametime); } } @@ -381,9 +508,8 @@ void Animate::StopAnimating(int slot) edict->s.frameInfo[slot].index = 1; } - edict->s.frameInfo[slot].weight = 0.0f; - animFlags[slot] = ANIM_LOOP | ANIM_NODELTA | ANIM_NOEXIT | ANIM_PAUSED; + SetWeight(slot, 0); animtimes[slot] = 0.0f; SlotChanged(slot); @@ -403,7 +529,8 @@ void Animate::DoExitCommands(int slot) int ii, j; for (ii = 0; ii < cmds.num_cmds; ii++) { - tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + ev = new AnimationEvent(single_cmd.args[0], single_cmd.num_args); ev->SetAnimationNumber(edict->s.frameInfo[slot].index); @@ -417,6 +544,38 @@ void Animate::DoExitCommands(int slot) } } + if (gi.Frame_Commands_Client(edict->tiki, edict->s.frameInfo[slot].index, TIKI_FRAME_EXIT, &cmds)) { + size_t longest = GetLongestClientCmdLength(cmds); + if (longest) { + char *cmdName = (char *)alloca(longest + 8 + 1); + int ii, j; + + for (ii = 0; ii < cmds.num_cmds; ii++) { + const tiki_singlecmd_t& single_cmd = cmds.cmds[ii]; + int eventNum; + + Q_strncpyz(cmdName, "_client_", longest + 8 + 1); + Q_strncpyz(cmdName + 8, single_cmd.args[0], longest + 1); + + eventNum = Event::FindEventNum(cmdName); + + AnimationEvent ev(eventNum, single_cmd.num_args); + if (!ev.eventnum) { + continue; + } + + ev.SetAnimationNumber(edict->s.frameInfo[slot].index); + ev.SetAnimationFrame(0); + + for (j = 1; j < single_cmd.num_args; j++) { + ev.AddToken(single_cmd.args[j]); + } + + PostEvent(ev, 0); + } + } + } + animFlags[slot] |= ANIM_NOEXIT; } @@ -437,7 +596,7 @@ int Animate::NumAnims(void) const char *Animate::AnimName(int slot) { - return gi.Anim_NameForNum(edict->tiki, edict->s.frameInfo[slot].index); + return gi.Anim_NameForNum(edict->tiki, CurrentAnim(slot)); } void Animate::AnimFinished(int slot) @@ -465,31 +624,31 @@ void Animate::PreAnimate(void) void Animate::PostAnimate(void) { - float startTime; - float deltaSyncTime; - float total_weight; - float total_angular_delta; - Vector vFrameDelta; - bool hasAction = false; + float startTime; + float deltaSyncTime; + float total_weight; + float total_angular_delta; + float beforeFrameTime; + Vector vFrameDelta; + bool hasAction = false; if (!edict->tiki) { return; } - deltaSyncTime = syncTime; + deltaSyncTime = syncTime; + beforeFrameTime = level.frametime / 10.f; if (!pauseSyncTime) { syncTime = 1.0f / syncRate * level.frametime + deltaSyncTime; } - total_weight = 0; + total_weight = 0; total_angular_delta = 0; for (int i = 0; i < MAX_FRAMEINFOS; i++) { - if (edict->s.frameInfo[i].weight > 0.0f) { - if (!(animFlags[i] & ANIM_NOACTION)) { - hasAction = true; - } + if (edict->s.frameInfo[i].weight > 0.0f && !(animFlags[i] & ANIM_NOACTION)) { + hasAction = true; } if (animFlags[i] & ANIM_PAUSED) { @@ -509,84 +668,92 @@ void Animate::PostAnimate(void) animFlags[i] |= ANIM_FINISHED; RestartAnimSlot(i); } else { - if (!(animFlags[i] & ANIM_NODELTA)) { - if (gi.Anim_HasDelta(edict->tiki, edict->s.frameInfo[i].index)) { - float vDelta[3]; - float angleDelta; + if (!(animFlags[i] & ANIM_NODELTA) && gi.Anim_HasDelta(edict->tiki, edict->s.frameInfo[i].index)) { + vec3_t vDelta; + float angleDelta; - // - // Get the animation's delta position from start time - // - gi.Anim_DeltaOverTime(edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, vDelta); - vFrameDelta += Vector(vDelta) * edict->s.frameInfo[i].weight; - total_weight += edict->s.frameInfo[i].weight; + // + // Get the animation's delta position from start time + // + gi.Anim_DeltaOverTime( + edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, vDelta + ); + VectorScale(vDelta, edict->s.frameInfo[i].weight, vDelta); + vFrameDelta += vDelta; + total_weight += edict->s.frameInfo[i].weight; - // - // Get the animation's delta angle from start time - // - gi.Anim_AngularDeltaOverTime(edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, &angleDelta); - total_angular_delta += angleDelta * edict->s.frameInfo[i].weight; - - } + // + // Get the animation's delta angle from start time + // + gi.Anim_AngularDeltaOverTime( + edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, &angleDelta + ); + angleDelta *= edict->s.frameInfo[i].weight; + total_angular_delta += angleDelta; } animFlags[i] &= ~ANIM_NODELTA; - float animTime; if (animFlags[i] & ANIM_SYNC) { - animTime = animtimes[i]; + if (edict->s.frameInfo[i].time < animtimes[i]) { + continue; + } } else { - animTime = animtimes[i] - 0.01f; - } - - if (edict->s.frameInfo[i].time >= animTime) { - if (animFlags[i] & ANIM_LOOP) { - animFlags[i] |= ANIM_FINISHED; - - do { - edict->s.frameInfo[i].time -= animtimes[i]; - } while (edict->s.frameInfo[i].time >= animtimes[i]); - - if (edict->s.frameInfo[i].time < 0) { - edict->s.frameInfo[i].time = 0; - } - - } else { - if (startTime != animtimes[i]) { - animFlags[i] |= ANIM_FINISHED; - } - - edict->s.frameInfo[i].time = animtimes[i]; + // Fixed in OPM + // Previously, beforeFrameTime was a constant of 0.01. + // It caused issues when the number of server frames per second + // was higher. Some animation events were not executing properly. + if (edict->s.frameInfo[i].time < (animtimes[i] - beforeFrameTime)) { + continue; } } - } - if (total_weight) { - vFrameDelta *= 1.f / total_weight; - total_angular_delta *= 1.f / total_weight; - } + if (IsRepeatType(i)) { + animFlags[i] |= ANIM_FINISHED; - MatrixTransformVector(vFrameDelta, orientation, frame_delta); - angular_delta = total_angular_delta; + do { + edict->s.frameInfo[i].time -= animtimes[i]; + } while (edict->s.frameInfo[i].time >= animtimes[i]); - while (syncTime > 1.0f) { - syncTime -= 1.0f; - } + if (edict->s.frameInfo[i].time < 0) { + edict->s.frameInfo[i].time = 0; + } - total_weight = level.frametime * 4.0f; + } else { + if (startTime != animtimes[i]) { + animFlags[i] |= ANIM_FINISHED; + } - if (hasAction) { - edict->s.actionWeight += total_weight; - - if (edict->s.actionWeight > 1.0f) { - edict->s.actionWeight = 1.0f; + edict->s.frameInfo[i].time = animtimes[i]; } - } else { - edict->s.actionWeight -= total_weight; + } + } - if (edict->s.actionWeight < 0.0f) { - edict->s.actionWeight = 0.0f; - } + if (total_weight) { + vFrameDelta *= 1.f / total_weight; + total_angular_delta *= 1.f / total_weight; + } + + MatrixTransformVector(vFrameDelta, orientation, frame_delta); + angular_delta = total_angular_delta; + + while (syncTime >= 1.0f) { + syncTime -= 1.0f; + } + + total_weight = level.frametime * 4.0f; + + if (hasAction) { + edict->s.actionWeight += total_weight; + + if (edict->s.actionWeight > 1.0f) { + edict->s.actionWeight = 1.0f; + } + } else { + edict->s.actionWeight -= total_weight; + + if (edict->s.actionWeight < 0.0f) { + edict->s.actionWeight = 0.0f; } } } @@ -630,8 +797,8 @@ void Animate::Pause(int slot, int pause) if (pause) { animFlags[slot] |= ANIM_PAUSED; } else { - if ((animFlags[slot] & ANIM_PAUSED)) { - if ((animFlags[slot] & ANIM_SYNC)) { + if (animFlags[slot] & ANIM_PAUSED) { + if (animFlags[slot] & ANIM_SYNC) { SlotChanged(animFlags[slot]); } @@ -643,14 +810,14 @@ void Animate::Pause(int slot, int pause) void Animate::UseSyncTime(int slot, int sync) { if (sync) { - if (animFlags[slot] & ANIM_SYNC) { - return; + if (!(animFlags[slot] & ANIM_SYNC)) { + animFlags[slot] |= ANIM_SYNC; + SlotChanged(slot); } - - animFlags[slot] = (animFlags[slot] | (ANIM_SYNC | ANIM_NODELTA)) & ~ANIM_FINISHED; } else { if (animFlags[slot] & ANIM_SYNC) { - animFlags[slot] = (animFlags[slot] | ANIM_NODELTA) & ~(ANIM_FINISHED | ANIM_SYNC); + animFlags[slot] &= ~ANIM_SYNC; + SlotChanged(slot); } } } @@ -880,6 +1047,11 @@ void Animate::DumpAnimInfo(void) MPrintf("actionWeight: %f\n", edict->s.actionWeight); } +void Animate::ClientSound(Event *ev) +{ + PlayNonPvsSound(ev->GetString(1)); +} + void Animate::EventPauseAnim(Event *ev) { is_paused = ev->GetInteger(1) ? true : false; diff --git a/code/fgame/animate.h b/code/fgame/animate.h index 479a5d72..724a640f 100644 --- a/code/fgame/animate.h +++ b/code/fgame/animate.h @@ -21,8 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // animate.h -- Animate class -#ifndef __ANIMATE_H__ -#define __ANIMATE_H__ +#pragma once #if defined(GAME_DLL) # include "entity.h" @@ -132,6 +131,8 @@ public: virtual void DumpAnimInfo(); void SlotChanged(int slot); + void ClientSound(Event *ev); + // FIXME: delete this, fakk2 remnant int NumFrames(int slot = 0); }; @@ -168,22 +169,24 @@ inline void Animate::PauseSyncTime(int pause) inline void Animate::Archive(Archiver& arc) { + int i; + Entity::Archive(arc); - for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) { + for (i = 0; i < MAX_FRAMEINFOS; i++) { arc.ArchiveInteger(&animFlags[i]); } arc.ArchiveFloat(&syncTime); arc.ArchiveFloat(&syncRate); arc.ArchiveInteger(&pauseSyncTime); arc.ArchiveBool(&is_paused); - for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) { + for (i = 0; i < MAX_FRAMEINFOS; i++) { arc.ArchiveEventPointer(&doneEvents[i]); } - for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) { + for (i = 0; i < MAX_FRAMEINFOS; i++) { arc.ArchiveFloat(&animtimes[i]); } - for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) { + for (i = 0; i < MAX_FRAMEINFOS; i++) { arc.ArchiveFloat(&frametimes[i]); } arc.ArchiveVector(&frame_delta); @@ -209,5 +212,3 @@ inline int Animate::NumFrames(int slot) { return gi.Anim_NumFrames(edict->tiki, edict->s.frameInfo[slot].index); } - -#endif /* animate.h */ diff --git a/code/fgame/animationevent.cpp b/code/fgame/animationevent.cpp index 245f930b..6b0cee1e 100644 --- a/code/fgame/animationevent.cpp +++ b/code/fgame/animationevent.cpp @@ -29,13 +29,20 @@ CLASS_DECLARATION(Event, AnimationEvent, NULL) { {NULL, NULL} }; -AnimationEvent::AnimationEvent(str command, int numArgs) +AnimationEvent::AnimationEvent(const char* command, int numArgs) : Event(command, numArgs) { anim_number = 0; anim_frame = 0; } +AnimationEvent::AnimationEvent(int eventNum, int numArgs) + : Event(eventNum, numArgs) +{ + anim_number = 0; + anim_frame = 0; +} + AnimationEvent::AnimationEvent(const Event& ev) : Event(ev) { diff --git a/code/fgame/animationevent.h b/code/fgame/animationevent.h index 357a6e52..3260c152 100644 --- a/code/fgame/animationevent.h +++ b/code/fgame/animationevent.h @@ -35,7 +35,8 @@ public: void *operator new(size_t size); void operator delete(void *ptr); - AnimationEvent(str command, int numArgs = 0); + AnimationEvent(const char* command, int numArgs = 0); + AnimationEvent(int eventNum, int numArgs = 0); AnimationEvent(const Event& ev); AnimationEvent(); diff --git a/code/fgame/archive.cpp b/code/fgame/archive.cpp index f66c2f02..a151ee7e 100644 --- a/code/fgame/archive.cpp +++ b/code/fgame/archive.cpp @@ -28,347 +28,369 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #ifdef GAME_DLL -#include "../fgame/entity.h" +# include "../fgame/entity.h" #endif -enum -{ - ARC_NULL, ARC_Vector, ARC_Vec2, ARC_Vec3, ARC_Vec4, ARC_Integer, ARC_Unsigned, ARC_Byte, ARC_Char, ARC_Short, ARC_UnsignedShort, - ARC_Float, ARC_Double, ARC_Boolean, ARC_String, ARC_Raw, ARC_Object, ARC_ObjectPointer, - ARC_SafePointer, ARC_EventPointer, ARC_Quat, ARC_Entity, ARC_Bool, - ARC_Position, ARC_Size, - ARC_NUMTYPES +enum { + ARC_NULL, + ARC_Vector, + ARC_Vec2, + ARC_Vec3, + ARC_Vec4, + ARC_Integer, + ARC_Unsigned, + ARC_Byte, + ARC_Char, + ARC_Short, + ARC_UnsignedShort, + ARC_Float, + ARC_Double, + ARC_Boolean, + ARC_String, + ARC_Raw, + ARC_Object, + ARC_ObjectPointer, + ARC_SafePointer, + ARC_EventPointer, + ARC_Quat, + ARC_Entity, + ARC_Bool, + ARC_Position, + ARC_Size, + ARC_NUMTYPES }; -static const char *typenames[] = -{ - "NULL", "vector", "vec2", "vec3", "vec4", "int", "unsigned", "byte", "char", "short", "unsigned short", - "float", "double", "qboolean", "string", "raw data", "object", "objectpointer", - "safepointer", "eventpointer", "quaternion", "entity", "bool", - "position", "size" -}; +static const char *typenames[] = { + "NULL", "vector", "vec2", "vec3", "vec4", "int", "unsigned", "byte", + "char", "short", "unsigned short", "float", "double", "qboolean", "string", "raw data", + "object", "objectpointer", "safepointer", "eventpointer", "quaternion", "entity", "bool", "position", + "size"}; -#define ArchiveHeader ( *( int * )"MHAA" ) -#define ArchiveVersion 14 // This must be changed any time the format changes! -#define ArchiveInfo "MOHAA Archive Version 14" // This must be changed any time the format changes! +#define ArchiveHeader (LittleLong(*(int *)"MHAA")) +#define ArchiveVersion 14 // This must be changed any time the format changes! +#define ArchiveInfo "OPENMOHAA Archive Version 14" // This must be changed any time the format changes! -CLASS_DECLARATION( Class, FileRead, NULL ) +ArchiveFile::ArchiveFile() { - { NULL, NULL } -}; - -FileRead::FileRead() -{ - length = 0; - buffer = NULL; - pos = 0; + length = 0; + buffer = 0; + pos = 0; + bufferlength = 0; + writing = 0; + opened = 0; } -FileRead::~FileRead() +ArchiveFile::~ArchiveFile() { - Close(); + Close(); } -void FileRead::Close - ( - bool bDoCompression - ) +void ArchiveFile::Close() { - if( bDoCompression ) - { - byte *tempbuf; - size_t out_len; + if (writing) { + gi.FS_WriteFile(filename.c_str(), buffer, length); + } - tempbuf = ( byte * )glbs.Malloc( ( length >> 6 ) + length + 27 ); + if (buffer) { + gi.Free((void *)buffer); + buffer = NULL; + } - // Set the signature - tempbuf[ 0 ] = 'C'; - tempbuf[ 1 ] = 'S'; - tempbuf[ 2 ] = 'V'; - tempbuf[ 3 ] = 'G'; - *( size_t * )( tempbuf + 4 ) = length; - - // Compress the data - if( g_lz77.Compress( buffer, length, tempbuf + 8, &out_len ) ) - { - glbs.Error( ERR_DROP, "Compression of SaveGame Failed!\n" ); - return; - } - - glbs.FS_WriteFile( filename.c_str(), tempbuf, out_len + 8 ); - glbs.Free( tempbuf ); - } - - if( buffer ) - { - glbs.Free( ( void * )buffer ); - buffer = NULL; - } - - filename = ""; - length = 0; - pos = 0; + writing = false; + filename = ""; + length = 0; + pos = 0; } -const char *FileRead::Filename -( -void -) +const char *ArchiveFile::Filename(void) { - return filename.c_str(); + return filename.c_str(); } -size_t FileRead::Length -( -void -) +qboolean ArchiveFile::Compress() { - return length; +#ifdef Q3_BIG_ENDIAN + // FIXME: Decompressing crashes on big-endian architectures + return false; +#endif + + byte *tempbuf; + size_t out_len; + size_t tempbuf_len; + + tempbuf_len = (length >> 6) + length + 27; + tempbuf = (byte *)gi.Malloc(tempbuf_len); + + // Set the signature + tempbuf[0] = 'C'; + tempbuf[1] = 'S'; + tempbuf[2] = 'V'; + tempbuf[3] = 'G'; + *(size_t *)(tempbuf + 4) = length; + + // Compress the data + if (g_lz77.Compress(buffer, length, tempbuf + 8, &out_len)) { + gi.Error(ERR_DROP, "Compression of SaveGame Failed!\n"); + return false; + } + + gi.Free(buffer); + buffer = tempbuf; + length = out_len + 8; + bufferlength = tempbuf_len; + + return true; } -size_t FileRead::Pos -( -void -) +size_t ArchiveFile::Length(void) { - return pos - buffer; + return length; } -qboolean FileRead::Seek -( -size_t newpos -) +size_t ArchiveFile::Pos(void) { - if( !buffer ) - { - return false; - } - - if( newpos > length ) - { - return false; - } - - pos = buffer + newpos; - - return true; + return pos - buffer; } -qboolean FileRead::Open - ( - const char *name - ) +size_t ArchiveFile::Tell(void) { - byte *tempbuf; - assert( name ); - - assert( !buffer ); - Close(); - - if( !name ) - { - return false; - } - - length = glbs.FS_ReadFile( name, ( void ** )&tempbuf, qtrue ); - if( length == ( size_t )( -1 ) ) - { - return false; - } - // create our own space - buffer = ( byte * )glbs.Malloc( length ); - // copy the file over to our space - memcpy( buffer, tempbuf, length ); - // free the file - glbs.FS_FreeFile( tempbuf ); - // set the file name - filename = name; - - pos = buffer; - - char FileHeader[ 4 ]; - Read( FileHeader, sizeof( FileHeader ) ); - - if( FileHeader[ 0 ] != 'C' || FileHeader[ 1 ] != 'S' || FileHeader[ 2 ] != 'V' || FileHeader[ 3 ] != 'G' ) - { - pos = buffer; - } - else - { - uint32_t new_len; - size_t iCSVGLength; - - Read( &new_len, sizeof(uint32_t) ); - tempbuf = ( byte * )glbs.Malloc( new_len ); - - if( g_lz77.Decompress( pos, length - 8, tempbuf, &iCSVGLength ) || iCSVGLength != new_len ) - { - glbs.Error( ERR_DROP, "Decompression of save game failed\n" ); - return false; - } - - glbs.Free( buffer ); - - buffer = tempbuf; - length = iCSVGLength; - pos = buffer; - } - - return true; + return pos - buffer; } -qboolean FileRead::Read - ( - void *dest, - size_t size - ) +qboolean ArchiveFile::Seek(size_t newpos) { - assert( dest ); - assert( buffer ); - assert( pos ); + if (!buffer) { + return false; + } - if( !dest ) - { - return false; - } + if (newpos > length) { + return false; + } - if( size <= 0 ) - { - return false; - } + pos = buffer + newpos; - if( ( pos + size ) > ( buffer + length ) ) - { - return false; - } - - memcpy( dest, pos, size ); - pos += size; - - return true; + return true; } -CLASS_DECLARATION( Class, Archiver, NULL ) +qboolean ArchiveFile::OpenRead(const char *name) { - { NULL, NULL } -}; + byte *tempbuf; + assert(name); + + assert(!buffer); + Close(); + + if (!name) { + return false; + } + + length = gi.FS_ReadFile(name, (void **)&tempbuf, qtrue); + if (length == (size_t)(-1) || length == 0) { + return false; + } + // create our own space + buffer = (byte *)gi.Malloc(length); + bufferlength = length; + // copy the file over to our space + memcpy(buffer, tempbuf, length); + // free the file + gi.FS_FreeFile(tempbuf); + // set the file name + filename = name; + + pos = buffer; + writing = false; + opened = true; + + char FileHeader[4]; + Read(FileHeader, sizeof(FileHeader)); + + if (FileHeader[0] != 'C' || FileHeader[1] != 'S' || FileHeader[2] != 'V' || FileHeader[3] != 'G') { + pos = buffer; + } else { + uint32_t new_len; + size_t iCSVGLength; + + new_len = 0; + Read(&new_len, sizeof(uint32_t)); + new_len = LittleLong(new_len); + tempbuf = (byte *)gi.Malloc(new_len); + + if (g_lz77.Decompress(pos, length - 8, tempbuf, &iCSVGLength) || iCSVGLength != new_len) { + gi.Error(ERR_DROP, "Decompression of save game failed\n"); + return false; + } + + gi.Free(buffer); + + buffer = tempbuf; + length = iCSVGLength; + bufferlength = length; + pos = buffer; + } + + return true; +} + +qboolean ArchiveFile::OpenWrite(const char *name) +{ + this->length = 0; + // 4 MiB buffer + this->bufferlength = 4 * 1024 * 1024; + this->buffer = (byte *)gi.Malloc(bufferlength); + this->filename = name; + this->pos = buffer; + this->writing = true; + this->opened = true; + + return true; +} + +qboolean ArchiveFile::Read(void *dest, size_t size) +{ + if (!size) { + return false; + } + + if ((pos + size) > (buffer + length)) { + return false; + } + + memcpy(dest, pos, size); + pos += size; + + return true; +} + +qboolean ArchiveFile::Write(const void *source, size_t size) +{ + if ((pos + size) > (buffer + bufferlength)) { + byte *oldbuf; + + do { + bufferlength *= 2; + } while ((pos + size) > (buffer + bufferlength)); + + oldbuf = buffer; + // reallocate a bigger buffer + buffer = (byte *)gi.Malloc(bufferlength); + memcpy(buffer, oldbuf, length); + // free the old buffer + gi.Free(oldbuf); + // set the position with the new buffer + pos = buffer + (pos - oldbuf); + } + + memcpy(pos, source, size); + pos += size; + + if (length < (pos - buffer)) { + length = (pos - buffer); + } + + return true; +} Archiver::Archiver() { - file = 0; - fileerror = false; - harderror = true; - m_iNumBytesIO = 0; - silent = false; - assert( ( sizeof( typenames ) / sizeof( typenames[ 0 ] ) ) == ARC_NUMTYPES ); + archivemode = ARCHIVE_WRITE; + fileerror = false; + harderror = true; + Reset(); + silent = false; + + assert((sizeof(typenames) / sizeof(typenames[0])) == ARC_NUMTYPES); } Archiver::~Archiver() { - if( file ) - { - Close(); - } - - readfile.Close(); + if (archivemode != ARCHIVE_NONE) { + Close(); + } } -void Archiver::FileError - ( - const char *fmt, - ... - ) +void Archiver::FileError(const char *fmt, ...) { - va_list argptr; - char text[ 1024 ]; + va_list argptr; + char text[1024]; - va_start( argptr, fmt ); - vsprintf( text, fmt, argptr ); - va_end( argptr ); + va_start(argptr, fmt); + Q_vsnprintf(text, sizeof(text), fmt, argptr); + va_end(argptr); - fileerror = true; - Close(); - if( archivemode == ARCHIVE_READ ) - { - if( harderror ) - { - glbs.Error( ERR_DROP, "Error while loading %s : %s\n", filename.c_str(), text ); - } - else if( !silent ) - { - glbs.Printf( "Error while loading %s : %s\n", filename.c_str(), text ); - } - } - else - { - if( harderror ) - { - glbs.Error( ERR_DROP, "Error while writing to %s : %s\n", filename.c_str(), text ); - } - else if( !silent ) - { - glbs.Printf( "Error while writing to %s : %s\n", filename.c_str(), text ); - } - } + fileerror = true; + Close(); + if (archivemode == ARCHIVE_READ) { + if (harderror) { + gi.Error(ERR_DROP, "Error while loading %s : %s\n", filename.c_str(), text); + } else if (!silent) { + gi.Printf("Error while loading %s : %s\n", filename.c_str(), text); + } + } else if (archivemode == ARCHIVE_WRITE) { + if (harderror) { + gi.Error(ERR_DROP, "Error while writing to %s : %s\n", filename.c_str(), text); + } else if (!silent) { + gi.Printf("Error while writing to %s : %s\n", filename.c_str(), text); + } + } else { + if (harderror) { + gi.Error(ERR_DROP, "Error while neither reading nor writing: %s\n", text); + } else { + gi.Printf("Error while neither reading nor writing: %s\n", text); + } + } } -void Archiver::Close - ( - void - ) +void Archiver::Close(void) { - if( file ) - { - if( archivemode == ARCHIVE_WRITE ) - { - int numobjects; + if (archivemode == ARCHIVE_NONE) { + // nothing to process + return; + } - // write out the number of classpointers - glbs.FS_Seek( file, numclassespos, FS_SEEK_SET ); - numclassespos = glbs.FS_Tell( file ); - numobjects = classpointerList.NumObjects(); - ArchiveInteger( &numobjects ); - } + if (archivemode == ARCHIVE_WRITE) { + int numobjects; + size_t pos; - glbs.FS_FCloseFile( file ); - file = 0; + // write out the number of classpointers + pos = archivefile.Tell(); + archivefile.Seek(numclassespos); + numobjects = classpointerList.NumObjects(); + ArchiveInteger(&numobjects); + // compress the file + archivefile.Seek(pos); + archivefile.Compress(); + } - readfile.Close(); - // Re-open and compress the file - readfile.Open( filename.c_str() ); - readfile.Close( true ); - } + archivefile.Close(); - readfile.Close(); + if (archivemode == ARCHIVE_READ) { + int i, num; + pointer_fixup_t *fixup; - if( archivemode == ARCHIVE_READ ) - { - int i, num; - Class * classptr; - pointer_fixup_t *fixup; + num = fixupList.NumObjects(); + for (i = 1; i <= num; i++) { + fixup = fixupList.ObjectAt(i); + if (fixup->type == pointer_fixup_ptr) { + LightClass **fixupptr; + fixupptr = (LightClass **)fixup->ptr; + *fixupptr = classpointerList.ObjectAt(fixup->index); + } else if (fixup->type == pointer_fixup_normal) { + Class **fixupptr; + fixupptr = (Class **)fixup->ptr; + *fixupptr = static_cast(classpointerList.ObjectAt(fixup->index)); + } else if (fixup->type == pointer_fixup_safe) { + SafePtrBase *fixupptr; + fixupptr = (SafePtrBase *)fixup->ptr; + fixupptr->InitSafePtr(static_cast(classpointerList.ObjectAt(fixup->index))); + } + delete fixup; + } + fixupList.FreeObjectList(); + classpointerList.FreeObjectList(); + } - num = fixupList.NumObjects(); - for( i = 1; i <= num; i++ ) - { - fixup = fixupList.ObjectAt( i ); - classptr = classpointerList.ObjectAt( fixup->index ); - if( fixup->type == pointer_fixup_normal ) - { - Class ** fixupptr; - fixupptr = ( Class ** )fixup->ptr; - *fixupptr = classptr; - } - else if( fixup->type == pointer_fixup_safe ) - { - SafePtrBase * fixupptr; - fixupptr = ( SafePtrBase * )fixup->ptr; - fixupptr->InitSafePtr( classptr ); - } - delete fixup; - } - fixupList.FreeObjectList(); - classpointerList.FreeObjectList(); - } + archivemode = ARCHIVE_NONE; } /**************************************************************************************** @@ -377,245 +399,90 @@ File Read/Write functions *****************************************************************************************/ -qboolean Archiver::Read -( -const char *name, -qboolean harderror -) +qboolean Archiver::Read(const char *name, qboolean harderror) { - unsigned header; - unsigned version; - str info; - int num; - int i; - Class *null; + unsigned header; + unsigned version; + str info; + int num; + int i; + Class *null; - this->harderror = harderror; + this->harderror = harderror; + this->fileerror = false; + this->archivemode = ARCHIVE_READ; + this->filename = name; - assert( name ); - if( !name ) - { - FileError( "NULL pointer for filename in Archiver::Read.\n" ); - return false; - } + if (!archivefile.OpenRead(filename.c_str())) { + if (harderror) { + FileError("Couldn't open file."); + } + return false; + } - fileerror = false; + ArchiveUnsigned(&header); + if (header != ArchiveHeader) { + archivefile.Close(); + FileError("Not a valid MOHAA archive."); + return false; + } - archivemode = ARCHIVE_READ; + ArchiveUnsigned(&version); + if (version > ArchiveVersion) { + archivefile.Close(); + FileError("Archive is from version %u. Check http://www.x-null.net for an update.", version); + return false; + } - filename = name; + if (version < ArchiveVersion) { + archivefile.Close(); + FileError("Archive is out of date."); + return false; + } - if( !readfile.Open( filename.c_str() ) ) - { - if( harderror ) - { - FileError( "Couldn't open file." ); - } - fileerror = true; - return false; - } + ArchiveString(&info); + gi.DPrintf("%s\n", info.c_str()); - ArchiveUnsigned( &header ); - if( header != ArchiveHeader ) - { - readfile.Close(); - FileError( "Not a valid MOHAA archive." ); - return false; - } + // setup out class pointers + ArchiveInteger(&num); + classpointerList.Resize(num); + null = NULL; + for (i = 1; i <= num; i++) { + classpointerList.AddObject(null); + } - ArchiveUnsigned( &version ); - if( version > ArchiveVersion ) - { - readfile.Close(); - FileError( "Archive is from version %u. Check http://www.x-null.net for an update.", version ); - return false; - } - - if( version < ArchiveVersion ) - { - readfile.Close(); - FileError( "Archive is out of date." ); - return false; - } - - ArchiveString( &info ); - - // setup out class pointers - ArchiveInteger( &num ); - classpointerList.Resize( num ); - null = NULL; - for( i = 1; i <= num; i++ ) - { - classpointerList.AddObject( null ); - } - - return true; + return true; } -qboolean Archiver::Create - ( - const char *name, - qboolean harderror - ) +qboolean Archiver::Create(const char *name, qboolean harderror) { - unsigned header; - unsigned version; - str info; - int numZero = 0; + unsigned header; + unsigned version; + str info; + int numZero = 0; - this->harderror = harderror; + this->harderror = harderror; + this->fileerror = false; + this->archivemode = ARCHIVE_WRITE; + this->filename = name; - assert( name ); - if( !name ) - { - FileError( "NULL pointer for filename in Archiver::Create.\n" ); - return false; - } + if (!archivefile.OpenWrite(filename.c_str())) { + FileError("Couldn't open file."); + return false; + } - fileerror = false; + header = ArchiveHeader; + ArchiveUnsigned(&header); + version = ArchiveVersion; + ArchiveUnsigned(&version); + info = ArchiveInfo; + ArchiveString(&info); - archivemode = ARCHIVE_WRITE; + numclassespos = archivefile.Tell(); + ArchiveInteger(&numZero); + Reset(); - filename = name; - - file = glbs.FS_FOpenFileWrite( filename.c_str() ); - if( !file ) - { - FileError( "Couldn't open file." ); - return false; - } - - header = ArchiveHeader; - ArchiveUnsigned( &header ); - version = ArchiveVersion; - ArchiveUnsigned( &version ); - info = ArchiveInfo; - ArchiveString( &info ); - - numclassespos = glbs.FS_Tell( file ); - ArchiveInteger( &numZero ); - - m_iNumBytesIO = 0; - - return true; -} - - -inline void Archiver::CheckRead -( -void -) -{ - assert( archivemode == ARCHIVE_READ ); - if( !fileerror && ( archivemode != ARCHIVE_READ ) ) - { - FileError( "File read during a write operation." ); - } -} - -inline void Archiver::CheckWrite -( -void -) -{ - assert( archivemode == ARCHIVE_WRITE ); - if( !fileerror && ( archivemode != ARCHIVE_WRITE ) ) - { - FileError( "File write during a read operation." ); - } -} - -inline fileSize_t Archiver::ReadSize -( -void -) -{ - fileSize_t s; - - s = 0; - if( !fileerror ) - { - readfile.Read( &s, sizeof( s ) ); - } - - return s; -} - -inline void Archiver::CheckSize -( -int type, -fileSize_t size -) -{ - fileSize_t s; - - if( !fileerror ) - { - s = ReadSize(); - - if( size != s ) - { - FileError( "Invalid data size of %d on %s.", s, typenames[ type ] ); - } - } -} - -inline void Archiver::WriteSize(fileSize_t size) -{ - glbs.FS_Write( &size, sizeof( size ), file ); -} - -inline int Archiver::ReadType -( -void -) -{ - int t; - - if( !fileerror ) - { - readfile.Read( &t, sizeof( t ) ); - - return t; - } - - return ARC_NULL; -} - -inline void Archiver::WriteType - ( - int type - ) -{ - glbs.FS_Write( &type, sizeof( type ), file ); -} - - -inline void Archiver::CheckType - ( - int type - ) -{ - int t; - - assert( ( type >= 0 ) && ( type < ARC_NUMTYPES ) ); - - if( !fileerror ) - { - t = ReadType(); - if( t != type ) - { - if( t < ARC_NUMTYPES ) - { - FileError( "Expecting %s, Should be %s", typenames[ type ], typenames[ t ] ); - assert( 0 ); - } - else - { - FileError( "Expecting %s, Should be %i (Unknown type)", typenames[ type ], t ); - } - } - } + return true; } /**************************************************************************************** @@ -626,628 +493,704 @@ File Archive functions //#define ARCHIVE_USE_TYPES 1 -inline void Archiver::ArchiveData - ( - int type, - void *data, - size_t size - ) -{ - if( archivemode == ARCHIVE_READ ) - { -#ifndef NDEBUG - CheckRead(); -#endif -#ifdef ARCHIVE_USE_TYPES - CheckType( type ); -#endif - - if( !fileerror && size ) - { - m_iNumBytesIO += size; - readfile.Read( data, size ); - } - } - else - { -#ifndef NDEBUG - CheckWrite(); -#endif -#ifdef ARCHIVE_USE_TYPES - WriteType( type ); -#endif - - if( !fileerror && size ) - { - m_iNumBytesIO += size; - glbs.FS_Write( data, size, file ); - } - } +template +void ArchiveSwapValue(v* value) { + LittleSwap(value, sizeof(v)); } - -#define ARCHIVE( func, type ) \ -void Archiver::Archive##func \ - ( \ - type * v \ - ) \ - \ -{ \ - ArchiveData( ARC_##func, v, sizeof( type ) ); \ +template +void ArchiveSwapValue(v* value, size_t size) { + for (size_t i = 0; i < size; i++) { + LittleSwap(&value[i], sizeof(value[i])); + } } -ARCHIVE( Vector, Vector ); -ARCHIVE( Integer, int ); -ARCHIVE( Unsigned, unsigned ); -ARCHIVE( Size, long ); -ARCHIVE( Byte, byte ); -ARCHIVE( Char, char ); -ARCHIVE( Short, short ); -ARCHIVE( UnsignedShort, unsigned short ); -ARCHIVE( Float, float ); -ARCHIVE( Double, double ); -ARCHIVE( Boolean, qboolean ); -ARCHIVE( Quat, Quat ); -ARCHIVE( Bool, bool ); -ARCHIVE( Position, int ); +template<> +void ArchiveSwapValue(Vector* value) { + for (int i = 0; i < 3; i++) { + (*value)[i] = LittleFloat((*value)[i]); + } +} -void Archiver::ArchiveSvsTime - ( - int *time - ) +template<> +void ArchiveSwapValue(Quat* value) { + for (int i = 0; i < 4; i++) { + (*value)[i] = LittleFloat((*value)[i]); + } +} + +#define ARCHIVE(func, type) \ + void Archiver::Archive##func(type *v) \ + { \ + if (archivemode == ARCHIVE_WRITE) { \ + type nv = *v; \ + ArchiveSwapValue(&nv); \ + ArchiveData(ARC_##func, &nv, sizeof(type)); \ + } else { \ + ArchiveData(ARC_##func, v, sizeof(type)); \ + ArchiveSwapValue(v); \ + } \ + } + +ARCHIVE(Vector, Vector); +ARCHIVE(Integer, int); +ARCHIVE(Unsigned, unsigned); +ARCHIVE(Byte, byte); +ARCHIVE(Char, char); +ARCHIVE(Short, short); +ARCHIVE(UnsignedShort, unsigned short); +ARCHIVE(Float, float); +ARCHIVE(Double, double); +ARCHIVE(Boolean, qboolean); +ARCHIVE(Quat, Quat); +ARCHIVE(Bool, bool); +ARCHIVE(Position, int); +ARCHIVE(Size, long); + +void Archiver::ArchiveSvsTime(int *time) { #ifdef GAME_DLL - if( archivemode == ARCHIVE_READ ) - { - ArchiveInteger( time ); - glbs.AddSvsTimeFixup( time ); - } - else - { - *time -= level.svsTime; - ArchiveInteger( time ); - *time += level.svsTime; - } + if (archivemode == ARCHIVE_READ) { + ArchiveInteger(time); + gi.AddSvsTimeFixup(time); + } else { + *time -= level.svsTime; + ArchiveInteger(time); + *time += level.svsTime; + } #endif } -void Archiver::ArchiveVec2 - ( - vec2_t vec - ) +void Archiver::ArchiveVec2(vec2_t vec) { - ArchiveData( ARC_Vec2, vec, sizeof( vec2_t ) ); + if (archivemode == ARCHIVE_WRITE) { + vec2_t nv = { vec[0], vec[1] }; + ArchiveSwapValue(nv, 2); + ArchiveData(ARC_Vec2, nv, sizeof(vec2_t)); + } else { + ArchiveData(ARC_Vec2, vec, sizeof(vec2_t)); + ArchiveSwapValue(vec, 2); + } } -void Archiver::ArchiveVec3 - ( - vec3_t vec - ) +void Archiver::ArchiveVec3(vec3_t vec) { - ArchiveData( ARC_Vec3, vec, sizeof( vec3_t ) ); + if (archivemode == ARCHIVE_WRITE) { + vec3_t nv = { vec[0], vec[1], vec[2]}; + ArchiveSwapValue(nv, 3); + ArchiveData(ARC_Vec3, nv, sizeof(vec3_t)); + } else { + ArchiveData(ARC_Vec3, vec, sizeof(vec3_t)); + ArchiveSwapValue(vec, 3); + } } -void Archiver::ArchiveVec4 - ( - vec4_t vec - ) +void Archiver::ArchiveVec4(vec4_t vec) { - ArchiveData( ARC_Vec4, vec, sizeof( vec4_t ) ); + if (archivemode == ARCHIVE_WRITE) { + vec4_t nv = { vec[0], vec[1], vec[2], vec[3] }; + ArchiveSwapValue(nv, 4); + ArchiveData(ARC_Vec4, nv, sizeof(vec4_t)); + } else { + ArchiveData(ARC_Vec4, vec, sizeof(vec4_t)); + ArchiveSwapValue(vec, 4); + } } -void Archiver::ArchiveObjectPointer -( -Class ** ptr -) +void Archiver::ArchiveObjectPointer(LightClass **ptr) { - int index = 0; + int index = 0; - if( archivemode == ARCHIVE_READ ) - { - pointer_fixup_t *fixup; - ArchiveData( ARC_ObjectPointer, &index, sizeof( index ) ); + if (archivemode == ARCHIVE_READ) { + pointer_fixup_t *fixup; - // Check for a NULL pointer - assert( ptr ); - if( !ptr ) - { - FileError( "NULL pointer in ArchiveObjectPointer." ); - } + ArchiveData(ARC_ObjectPointer, &index, sizeof(index)); + index = LittleLong(index); - // - // see if the variable was NULL - // - if( index == ARCHIVE_NULL_POINTER ) - { - *ptr = NULL; - } - else - { - // init the pointer with NULL until we can fix it - *ptr = NULL; + // + // see if the variable was NULL + // + if (index == ARCHIVE_NULL_POINTER) { + *ptr = NULL; + } else { + // init the pointer with NULL until we can fix it + *ptr = NULL; - fixup = new pointer_fixup_t; - fixup->ptr = ( void ** )ptr; - fixup->index = index; - fixup->type = pointer_fixup_normal; - fixupList.AddObject( fixup ); - } - } - else - { - if( *ptr ) - { - index = classpointerList.AddUniqueObject( *ptr ); - } - else - { - index = ARCHIVE_NULL_POINTER; - } - ArchiveData( ARC_ObjectPointer, &index, sizeof( index ) ); - } + fixup = new pointer_fixup_t; + fixup->ptr = (void **)ptr; + fixup->index = index; + fixup->type = pointer_fixup_ptr; + fixupList.AddObject(fixup); + } + } else { + if (*ptr) { + index = classpointerList.AddUniqueObject(*ptr); + } else { + index = ARCHIVE_NULL_POINTER; + } + + index = LittleLong(index); + ArchiveData(ARC_ObjectPointer, &index, sizeof(index)); + } } -void Archiver::ArchiveObjectPosition( void *obj ) +void Archiver::ArchiveObjectPointer(Class **ptr) { - int index = 0; + int index = 0; - if( archivemode == ARCHIVE_READ ) - { - ArchivePosition( &index ); - classpointerList.AddObjectAt( index, ( Class * )obj ); - } - else - { - index = classpointerList.AddUniqueObject( ( Class * )obj ); - ArchivePosition( &index ); - } + if (archivemode == ARCHIVE_READ) { + pointer_fixup_t *fixup; + + ArchiveData(ARC_ObjectPointer, &index, sizeof(index)); + index = LittleLong(index); + + // + // see if the variable was NULL + // + if (index == ARCHIVE_NULL_POINTER) { + *ptr = NULL; + } else { + // init the pointer with NULL until we can fix it + *ptr = NULL; + + fixup = new pointer_fixup_t; + fixup->ptr = (void **)ptr; + fixup->index = index; + fixup->type = pointer_fixup_normal; + fixupList.AddObject(fixup); + } + } else { + if (*ptr) { + index = classpointerList.AddUniqueObject(*ptr); + } else { + index = ARCHIVE_NULL_POINTER; + } + + index = LittleLong(index); + ArchiveData(ARC_ObjectPointer, &index, sizeof(index)); + } } -void Archiver::ArchiveSafePointer -( -SafePtrBase * ptr -) +void Archiver::ArchiveSafePointer(SafePtrBase *ptr) { - int index = 0; + int index = 0; - if( archivemode == ARCHIVE_READ ) - { - pointer_fixup_t *fixup; + if (archivemode == ARCHIVE_READ) { + pointer_fixup_t *fixup; - ArchiveData( ARC_SafePointer, &index, sizeof( index ) ); + ArchiveData(ARC_SafePointer, &index, sizeof(index)); + index = LittleLong(index); - // Check for a NULL pointer - assert( ptr ); - if( !ptr ) - { - FileError( "NULL pointer in ReadSafePointer." ); - } + // + // see if the variable was NULL + // + if (index == ARCHIVE_NULL_POINTER) { + ptr->InitSafePtr(NULL); + } else { + // init the pointer with NULL until we can fix it + ptr->InitSafePtr(NULL); - // - // see if the variable was NULL - // - if( index == ARCHIVE_NULL_POINTER ) - { - ptr->InitSafePtr( NULL ); - } - else - { - // init the pointer with NULL until we can fix it - ptr->InitSafePtr( NULL ); + // Add new fixup + fixup = new pointer_fixup_t; + fixup->ptr = (void **)ptr; + fixup->index = index; + fixup->type = pointer_fixup_safe; + fixupList.AddObject(fixup); + } + } else { + if (ptr->Pointer()) { + Class *obj; - // Add new fixup - fixup = new pointer_fixup_t; - fixup->ptr = ( void ** )ptr; - fixup->index = index; - fixup->type = pointer_fixup_safe; - fixupList.AddObject( fixup ); - } - } - else - { - if( ptr->Pointer() ) - { - Class * obj; - - obj = ptr->Pointer(); - index = classpointerList.AddUniqueObject( obj ); - } - else - { - index = ARCHIVE_NULL_POINTER; - } - ArchiveData( ARC_SafePointer, &index, sizeof( index ) ); - } + obj = ptr->Pointer(); + index = classpointerList.AddUniqueObject(obj); + } else { + index = ARCHIVE_NULL_POINTER; + } + index = LittleLong(index); + ArchiveData(ARC_SafePointer, &index, sizeof(index)); + } } -void Archiver::ArchiveEventPointer -( -Event ** ev -) +void Archiver::ArchiveEventPointer(Event **ev) { - int index; - - if( archivemode == ARCHIVE_READ ) - { -#ifndef NDEBUG - CheckRead(); -#endif -#ifdef ARCHIVE_USE_TYPES - CheckType( ARC_EventPointer ); -#endif - ArchiveInteger( &index ); - - if( !fileerror ) - { - if( index == ARCHIVE_POINTER_VALID ) - { - *ev = new Event; - ( *ev )->Archive( *this ); - } - else - { - ( *ev ) = NULL; - } - } - } - else - { -#ifndef NDEBUG - CheckWrite(); -#endif - if( *ev ) - { - index = ARCHIVE_POINTER_VALID; - } - else - { - index = ARCHIVE_NULL_POINTER; - } + int index; #ifdef ARCHIVE_USE_TYPES - WriteType( ARC_EventPointer ); + CheckType(ARC_EventPointer); #endif - ArchiveInteger( &index ); - if( *ev ) - { - ( *ev )->Archive( *this ); - } - } + if (archivemode == ARCHIVE_READ) { +#ifndef NDEBUG + CheckRead(); +#endif + ArchiveInteger(&index); + + if (!fileerror) { + if (index == ARCHIVE_POINTER_VALID) { + *ev = new Event; + (*ev)->Archive(*this); + } else { + (*ev) = NULL; + } + } + } else { +#ifndef NDEBUG + CheckWrite(); +#endif + if (*ev) { + index = ARCHIVE_POINTER_VALID; + } else { + index = ARCHIVE_NULL_POINTER; + } + + ArchiveInteger(&index); + if (*ev) { + (*ev)->Archive(*this); + } + } } -void Archiver::ArchiveRaw -( -void *data, -size_t size -) +void Archiver::ArchiveRaw(void *data, size_t size) { - ArchiveData( ARC_Raw, data, size ); + ArchiveData(ARC_Raw, data, size); } -void Archiver::ArchiveString -( -str * string -) +void Archiver::ArchiveString(str *string) { - if( archivemode == ARCHIVE_READ ) - { - fileSize_t s; - char *data; +#ifdef ARCHIVE_USE_TYPES + CheckType(ARC_String); +#endif + + if (archivemode == ARCHIVE_READ) { + fileSize_t s; + char *data; #ifndef NDEBUG - CheckRead(); -#endif -#ifdef ARCHIVE_USE_TYPES - CheckType( ARC_String ); + CheckRead(); #endif + if (!fileerror) { + s = ReadSize(); + if (!fileerror) { + data = new char[s + 1]; + if (data) { + if (s) { + archivefile.Read(data, s); + } + data[s] = 0; - if( !fileerror ) - { - s = ReadSize(); - if( !fileerror ) - { - data = new char[ s + 1 ]; - if( data ) - { - if( s ) - { - readfile.Read( data, s ); - } - data[ s ] = 0; + *string = data; - *string = data; - - delete[] data; - } - } - } - } - else - { + delete[] data; + } + } + } + } else { #ifndef NDEBUG - CheckWrite(); + CheckWrite(); #endif -#ifdef ARCHIVE_USE_TYPES - WriteType( ARC_String ); -#endif - WriteSize( (fileSize_t)string->length() ); - glbs.FS_Write( ( void * )string->c_str(), string->length(), file ); - } + WriteSize(string->length()); + archivefile.Write(string->c_str(), string->length()); + } } -void Archiver::ArchiveConfigString( int cs ) +Class *Archiver::ReadObject(void) { -#ifdef GAME_DLL - str s; + ClassDef *cls; + Class *obj; + str classname; + size_t objstart; + size_t endpos; + int index; + size_t size; + qboolean isent; + int type; - if( archivemode == ARCHIVE_READ ) - { - ArchiveString( &s ); - glbs.setConfigstring( cs, s.c_str() ); - } - else - { - s = glbs.getConfigstring( cs ); - ArchiveString( &s ); - } -#endif -} + CheckRead(); -Class * Archiver::ReadObject - ( - void - ) -{ - ClassDef *cls; - Class *obj; - str classname; - size_t objstart; - size_t endpos; - int index; - size_t size; - qboolean isent; - int type; + type = ReadType(); + if ((type != ARC_Object) && (type != ARC_Entity)) { + FileError("Expecting %s or %s", typenames[ARC_Object], typenames[ARC_Entity]); + } - CheckRead(); + size = ReadSize(); + ArchiveString(&classname); - type = ReadType(); - if( ( type != ARC_Object ) && ( type != ARC_Entity ) ) - { - FileError( "Expecting %s or %s", typenames[ ARC_Object ], typenames[ ARC_Entity ] ); - } + cls = getClass(classname.c_str()); + if (!cls) { + FileError("Invalid class %s.", classname.c_str()); + } - size = ReadSize(); - ArchiveString( &classname ); +#if defined(GAME_DLL) + isent = checkInheritance(&Entity::ClassInfo, cls); + if (type == ARC_Entity) { + if (!isent) { + FileError("Non-Entity class object '%s' saved as an Entity based object.", classname.c_str()); + } - cls = getClass( classname.c_str() ); - if( !cls ) - { - FileError( "Invalid class %s.", classname.c_str() ); - } - -#if defined ( GAME_DLL ) - isent = checkInheritance( &Entity::ClassInfo, cls ); - if( type == ARC_Entity ) - { - if( !isent ) - { - FileError( "Non-Entity class object '%s' saved as an Entity based object.", classname.c_str() ); - } - - ArchiveInteger( &level.spawn_entnum ); - // - // make sure to setup spawnflags properly - // - ArchiveInteger( &level.spawnflags ); - } - else if( isent ) - { - FileError( "Entity class object '%s' saved as non-Entity based object.", classname.c_str() ); - } + ArchiveInteger(&level.spawn_entnum); + // + // make sure to setup spawnflags properly + // + ArchiveInteger(&level.spawnflags); + } else if (isent) { + FileError("Entity class object '%s' saved as non-Entity based object.", classname.c_str()); + } #else - isent = false; + isent = false; #endif - ArchiveInteger( &index ); - objstart = readfile.Pos(); + ArchiveInteger(&index); + objstart = archivefile.Pos(); + obj = (Class *)cls->newInstance(); + if (!obj) { + FileError("Failed to on new instance of class %s.", classname.c_str()); + } else { + obj->Archive(*this); + } - obj = ( Class * )cls->newInstance(); - if( !obj ) - { - FileError( "Failed to on new instance of class %s.", classname.c_str() ); - } - else - { - obj->Archive( *this ); - } + if (!fileerror) { + endpos = archivefile.Pos(); + if ((endpos - objstart) > size) { + FileError("Object read past end of object's data"); + } else if ((endpos - objstart) < size) { + FileError("Object didn't read entire data from file"); + } + } - if( !fileerror ) - { - endpos = readfile.Pos(); - if( ( endpos - objstart ) > size ) - { - FileError( "Object read past end of object's data" ); - } - else if( ( endpos - objstart ) < size ) - { - FileError( "Object didn't read entire data from file" ); - } - } + // + // register this pointer with our list + // + classpointerList.AddObjectAt(index, obj); - // - // register this pointer with our list - // - classpointerList.AddObjectAt( index, obj ); - - return obj; + return obj; } -void Archiver::ArchiveObject - ( - Class *obj - ) +void Archiver::ArchiveObject(Class *obj) { - str classname; - int index; - fileSize_t size; - qboolean isent; + str classname; + int index; + fileSize_t size; + qboolean isent; - if( archivemode == ARCHIVE_READ ) - { - ClassDef *cls; - size_t objstart; - size_t endpos; - int type; + if (archivemode == ARCHIVE_READ) { + ClassDef *cls; + size_t objstart; + size_t endpos; + int type; - CheckRead(); - type = ReadType(); - if( ( type != ARC_Object ) && ( type != ARC_Entity ) ) - { - FileError( "Expecting %s or %s", typenames[ ARC_Object ], typenames[ ARC_Entity ] ); - } + CheckRead(); + type = ReadType(); + if ((type != ARC_Object) && (type != ARC_Entity)) { + FileError("Expecting %s or %s", typenames[ARC_Object], typenames[ARC_Entity]); + } - size = ReadSize(); - ArchiveString( &classname ); + size = ReadSize(); + ArchiveString(&classname); - cls = getClass( classname.c_str() ); - if( !cls ) - { - FileError( "Invalid class %s.", classname.c_str() ); - } + cls = getClass(classname.c_str()); + if (!cls) { + FileError("Invalid class %s.", classname.c_str()); + } - if( obj->classinfo() != cls ) - { - FileError( "Archive has a '%s' object, but was expecting a '%s' object.", classname.c_str(), obj->getClassname() ); - } + if (obj->classinfo() != cls) { + FileError( + "Archive has a '%s' object, but was expecting a '%s' object.", classname.c_str(), obj->getClassname() + ); + } -#if defined ( GAME_DLL ) - isent = obj->isSubclassOf( Entity ); - if( type == ARC_Entity ) - { - int entnum; - if( !isent ) - { - FileError( "Non-Entity class object '%s' saved as an Entity based object.", classname.c_str() ); - } +#if defined(GAME_DLL) + isent = obj->isSubclassOf(Entity); + if (type == ARC_Entity) { + int entnum; + if (!isent) { + FileError("Non-Entity class object '%s' saved as an Entity based object.", classname.c_str()); + } - ArchiveInteger( &entnum ); - ( ( Entity * )obj )->entnum = entnum; - // - // make sure to setup spawnflags properly - // - ArchiveInteger( &level.spawnflags ); - } - else if( isent ) - { - FileError( "Entity class object '%s' saved as non-Entity based object.", classname.c_str() ); - } + ArchiveInteger(&entnum); + ((Entity *)obj)->entnum = entnum; + // + // make sure to setup spawnflags properly + // + ArchiveInteger(&level.spawnflags); + } else if (isent) { + FileError("Entity class object '%s' saved as non-Entity based object.", classname.c_str()); + } #else - isent = false; + isent = false; #endif - ArchiveInteger( &index ); - objstart = readfile.Pos(); + ArchiveInteger(&index); + objstart = archivefile.Pos(); - obj->Archive( *this ); + obj->Archive(*this); - if( !fileerror ) - { - endpos = readfile.Pos(); - if( ( endpos - objstart ) > size ) - { - FileError( "Object read past end of object's data" ); - } - else if( ( endpos - objstart ) < size ) - { - FileError( "Object didn't read entire data from file" ); - } - } + if (!fileerror) { + endpos = archivefile.Pos(); + if ((endpos - objstart) > size) { + FileError("Object read past end of object's data"); + } else if ((endpos - objstart) < size) { + FileError("Object didn't read entire data from file"); + } + } - // - // register this pointer with our list - // - classpointerList.AddObjectAt( index, obj ); - } - else - { - long sizepos; - long objstart = 0; - long endpos; + // + // register this pointer with our list + // + classpointerList.AddObjectAt(index, obj); + } else { + long sizepos; + long objstart = 0; + long endpos; - assert( obj ); - if( !obj ) - { - FileError( "NULL object in WriteObject" ); - } + assert(obj); + if (!obj) { + FileError("NULL object in WriteObject"); + } -#if defined ( GAME_DLL ) - isent = obj->isSubclassOf( Entity ); +#if defined(GAME_DLL) + isent = obj->isSubclassOf(Entity); #else - isent = false; + isent = false; #endif - CheckWrite(); - if( isent ) - { - WriteType( ARC_Entity ); - } - else - { - WriteType( ARC_Object ); - } + CheckWrite(); + if (isent) { + WriteType(ARC_Entity); + } else { + WriteType(ARC_Object); + } - sizepos = glbs.FS_Tell( file ); - size = 0; - WriteSize( size ); + sizepos = archivefile.Tell(); + size = 0; + WriteSize(size); - classname = obj->getClassname(); - ArchiveString( &classname ); + classname = obj->getClassname(); + ArchiveString(&classname); -#if defined ( GAME_DLL ) - if( isent ) - { - // Write out the entity number - ArchiveInteger( &( ( Entity * )obj )->entnum ); - // - // make sure to setup spawnflags properly - // - ArchiveInteger( &( ( Entity * )obj )->spawnflags ); - } +#if defined(GAME_DLL) + if (isent) { + // Write out the entity number + ArchiveInteger(&((Entity *)obj)->entnum); + // + // make sure to setup spawnflags properly + // + ArchiveInteger(&((Entity *)obj)->spawnflags); + } #endif - // write out pointer index for this class pointer - index = classpointerList.AddUniqueObject( obj ); - ArchiveInteger( &index ); + // write out pointer index for this class pointer + index = classpointerList.AddUniqueObject(obj); + ArchiveInteger(&index); - if( !fileerror ) - { - objstart = glbs.FS_Tell( file ); - obj->Archive( *this ); - } + if (!fileerror) { + objstart = archivefile.Tell(); + obj->Archive(*this); + } - if( !fileerror ) - { - endpos = glbs.FS_Tell( file ); - size = endpos - objstart; - glbs.FS_Seek( file, sizepos, FS_SEEK_SET ); - WriteSize( size ); + if (!fileerror) { + endpos = archivefile.Tell(); + size = endpos - objstart; + archivefile.Seek(sizepos); + WriteSize(size); - if( !fileerror ) - { - glbs.FS_Seek( file, endpos, FS_SEEK_SET ); - } - } - } + if (!fileerror) { + archivefile.Seek(archivefile.Length()); + } + } + } } -qboolean Archiver::ObjectPositionExists( void *obj ) +void Archiver::ArchiveObject(SafePtrBase* obj) { - return classpointerList.IndexOfObject( ( Class * )obj ) != 0; + ArchiveSafePointer(obj); } -void Archiver::SetSilent( bool bSilent ) +void Archiver::ArchiveObjectPosition(LightClass *obj) { - silent = bSilent; + int index = 0; + + if (archivemode == ARCHIVE_READ) { + ArchivePosition(&index); + classpointerList.AddObjectAt(index, (Class *)obj); + } else { + index = classpointerList.AddUniqueObject((Class *)obj); + ArchivePosition(&index); + } +} + +qboolean Archiver::ObjectPositionExists(void *obj) +{ + return classpointerList.IndexOfObject((Class *)obj) != 0; +} + +void Archiver::CheckRead(void) +{ + assert(archivemode == ARCHIVE_READ); + if (!fileerror && (archivemode != ARCHIVE_READ)) { + FileError("File read during a write operation."); + } +} + +void Archiver::CheckWrite(void) +{ + assert(archivemode == ARCHIVE_WRITE); + if (!fileerror && (archivemode != ARCHIVE_WRITE)) { + FileError("File write during a read operation."); + } +} + +qboolean Archiver::Read(str& name, qboolean harderror) +{ + return Read(name.c_str(), harderror); +} + +qboolean Archiver::Create(str& name, qboolean harderror) +{ + return Create(name.c_str(), harderror); +} + +qboolean Archiver::Loading(void) +{ + return (archivemode == ARCHIVE_READ) ? qtrue : qfalse; +} + +qboolean Archiver::Saving(void) +{ + return (archivemode == ARCHIVE_WRITE) ? qtrue : qfalse; +} + +qboolean Archiver::NoErrors(void) +{ + return fileerror ? qfalse : qtrue; +} + +size_t Archiver::Counter() const +{ + return m_iNumBytesIO; +} + +void Archiver::Reset() +{ + m_iNumBytesIO = 0; +} + +fileSize_t Archiver::ReadSize(void) +{ + fileSize_t s; + + s = 0; + if (!fileerror) { + archivefile.Read(&s, sizeof(s)); + LittleSwap(&s, sizeof(s)); + } + + return s; +} + +void Archiver::CheckSize(int type, fileSize_t size) +{ + fileSize_t s; + + if (!fileerror) { + s = ReadSize(); + + if (size != s) { + FileError("Invalid data size of %d on %s.", s, typenames[type]); + } + } +} + +void Archiver::WriteSize(fileSize_t size) +{ + LittleSwap(&size, sizeof(size)); + archivefile.Write(&size, sizeof(fileSize_t)); +} + +int Archiver::ReadType(void) +{ + int t; + + if (!fileerror) { + archivefile.Read(&t, sizeof(t)); + t = LittleLong(t); + + return t; + } + + return ARC_NULL; +} + +void Archiver::WriteType(int type) +{ + int nt = LittleLong(type); + archivefile.Write(&nt, sizeof(nt)); +} + +void Archiver::CheckType(int type) +{ + int t; + + assert((type >= 0) && (type < ARC_NUMTYPES)); + + if (archivemode == ARCHIVE_READ) { + if (!fileerror) { + t = ReadType(); + if (t != type) { + if (t < ARC_NUMTYPES) { + FileError("Expecting %s, Should be %s", typenames[type], typenames[t]); + assert(0); + } + else { + FileError("Expecting %s, Should be %i (Unknown type)", typenames[type], t); + } + } + } + } else { + WriteType(type); + } +} + +void Archiver::ArchiveData(int type, void *data, size_t size) +{ +#ifdef ARCHIVE_USE_TYPES + CheckType(type); +#endif + + if (archivemode == ARCHIVE_READ) { +#ifndef NDEBUG + CheckRead(); +#endif + if (!fileerror && size) { + m_iNumBytesIO += size; + archivefile.Read(data, size); + } + } else { +#ifndef NDEBUG + CheckWrite(); +#endif + + if (!fileerror && size) { + m_iNumBytesIO += size; + archivefile.Write(data, size); + } + } +} + +void Archiver::ArchiveConfigString(int cs) +{ + str s; + + if (archivemode == ARCHIVE_READ) { + ArchiveString(&s); + gi.setConfigstring(cs, s.c_str()); + } else { + s = gi.getConfigstring(cs); + ArchiveString(&s); + } +} + +void Archiver::SetSilent(bool bSilent) +{ + silent = bSilent; } diff --git a/code/fgame/archive.h b/code/fgame/archive.h index 39e7ad2e..0e584fd8 100644 --- a/code/fgame/archive.h +++ b/code/fgame/archive.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,390 +22,329 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // archive.h: OpenMoHAA Archiver -#ifndef __ARCHIVE_H__ -#define __ARCHIVE_H__ +#pragma once #include "g_local.h" #include "class.h" #include "str.h" #include "vector.h" -#define ARCHIVE_NULL_POINTER ( -654321 ) -#define ARCHIVE_POINTER_VALID ( 0 ) -#define ARCHIVE_POINTER_NULL ( ARCHIVE_NULL_POINTER ) -#define ARCHIVE_POINTER_SELF_REFERENTIAL ( -123456 ) +#define ARCHIVE_NULL_POINTER (-654321) +#define ARCHIVE_POINTER_VALID (0) +#define ARCHIVE_POINTER_NULL (ARCHIVE_NULL_POINTER) +#define ARCHIVE_POINTER_SELF_REFERENTIAL (-123456) #define ARCHIVE_USE_TYPES -#define ARCHIVE_WRITE 0 -#define ARCHIVE_READ 1 +typedef enum { + ARCHIVE_NONE, + ARCHIVE_WRITE, + ARCHIVE_READ +} archivemode_e; -enum -{ - pointer_fixup_normal, - pointer_fixup_safe +enum { + pointer_fixup_ptr, + pointer_fixup_normal, + pointer_fixup_safe }; -typedef struct -{ - void **ptr; - int index; - int type; +typedef struct { + void **ptr; + int index; + int type; } pointer_fixup_t; using fileSize_t = uint32_t; -class FileRead : public Class +class ArchiveFile { protected: - str filename; - size_t length; - byte *buffer; - byte *pos; + str filename; + size_t length; + byte *buffer; + byte *pos; + size_t bufferlength; + bool writing; + bool opened; public: - CLASS_PROTOTYPE( FileRead ); - - FileRead(); - ~FileRead(); - void Close( bool bDoCompression = false ); - const char *Filename( void ); - size_t Length( void ); - size_t Pos( void ); - qboolean Seek( size_t newpos ); - qboolean Open( const char *name ); - qboolean Read( void *dest, size_t size ); + ArchiveFile(); + ~ArchiveFile(); + void Close(); + const char *Filename(void); + qboolean Compress(); + size_t Length(void); + size_t Pos(void); + size_t Tell(void); + qboolean Seek(size_t newpos); + qboolean OpenRead(const char *name); + qboolean OpenWrite(const char *name); + qboolean Read(void *dest, size_t size); + qboolean Write(const void *source, size_t size); }; -class Archiver : public Class +class Archiver { private: - Container classpointerList; - Container fixupList; + Container classpointerList; + Container fixupList; protected: - str filename; - qboolean fileerror; - fileHandle_t file; - FileRead readfile; - int archivemode; - int numclassespos; - qboolean harderror; - size_t m_iNumBytesIO; - qboolean silent; + str filename; + qboolean fileerror; + ArchiveFile archivefile; + int archivemode; + int numclassespos; + qboolean harderror; + size_t m_iNumBytesIO; + qboolean silent; - void CheckRead( void ); - void CheckType( int type ); - int ReadType( void ); - fileSize_t ReadSize( void ); - void CheckSize( int type, fileSize_t size ); - void ArchiveData( int type, void *data, size_t size ); + void CheckRead(void); + void CheckType(int type); + int ReadType(void); + fileSize_t ReadSize(void); + void CheckSize(int type, fileSize_t size); + void ArchiveData(int type, void *data, size_t size); - void CheckWrite( void ); - void WriteType( int type ); - void WriteSize(fileSize_t size ); + void CheckWrite(void); + void WriteType(int type); + void WriteSize(fileSize_t size); public: - CLASS_PROTOTYPE( Archiver ); + Archiver(); + ~Archiver(); + void FileError(const char *fmt, ...); + void Close(void); - Archiver(); - ~Archiver(); - void FileError( const char *fmt, ... ); - void Close( void ); + qboolean Read(str& name, qboolean harderror = qtrue); + qboolean Read(const char *name, qboolean harderror = qtrue); + Class *ReadObject(void); - qboolean Read( str &name, qboolean harderror = qtrue ); - qboolean Read( const char *name, qboolean harderror = qtrue ); - Class *ReadObject( void ); + qboolean Create(str& name, qboolean harderror = qtrue); + qboolean Create(const char *name, qboolean harderror = qtrue); - qboolean Create( str &name, qboolean harderror = qtrue ); - qboolean Create( const char *name, qboolean harderror = qtrue ); + qboolean Loading(void); + qboolean Saving(void); + qboolean NoErrors(void); - qboolean Loading( void ); - qboolean Saving( void ); - qboolean NoErrors( void ); + void ArchiveVector(Vector *vec); + void ArchiveQuat(Quat *quat); + void ArchiveInteger(int *num); + void ArchiveUnsigned(unsigned *unum); + void ArchiveSize(long *unum); + void ArchiveByte(byte *num); + void ArchiveChar(char *ch); + void ArchiveShort(short *num); + void ArchiveUnsignedShort(unsigned short *num); + void ArchiveFloat(float *num); + void ArchiveDouble(double *num); + void ArchiveBoolean(qboolean *boolean); + void ArchiveString(str *string); + void ArchiveObjectPointer(LightClass **ptr); + void ArchiveObjectPointer(Class **ptr); + void ArchiveObjectPosition(LightClass *obj); + void ArchiveSafePointer(SafePtrBase *ptr); + void ArchiveEventPointer(Event **ev); + void ArchiveBool(bool *boolean); + void ArchivePosition(int *pos); + void ArchiveSvsTime(int *time); + void ArchiveVec2(vec2_t vec); + void ArchiveVec3(vec3_t vec); + void ArchiveVec4(vec4_t vec); - void ArchiveVector( Vector * vec ); - void ArchiveQuat( Quat * quat ); - void ArchiveInteger( int * num ); - void ArchiveUnsigned( unsigned * unum ); - void ArchiveSize( long * unum ); - void ArchiveByte( byte * num ); - void ArchiveChar( char * ch ); - void ArchiveShort( short * num ); - void ArchiveUnsignedShort( unsigned short * num ); - void ArchiveFloat( float * num ); - void ArchiveDouble( double * num ); - void ArchiveBoolean( qboolean * boolean ); - void ArchiveString( str * string ); - void ArchiveConfigString( int cs ); - void ArchiveObjectPointer( Class ** ptr ); - void ArchiveObjectPosition( void *obj ); - void ArchiveSafePointer( SafePtrBase * ptr ); - void ArchiveEventPointer( Event ** ev ); - void ArchiveBool( bool * boolean ); - void ArchivePosition( int * pos ); - void ArchiveSvsTime( int * time ); - void ArchiveVec2( vec2_t vec ); - void ArchiveVec3( vec3_t vec ); - void ArchiveVec4( vec4_t vec ); + void ArchiveRaw(void *data, size_t size); + void ArchiveObject(Class *obj); + void ArchiveObject(SafePtrBase *obj); // Added in OPM - void ArchiveRaw( void *data, size_t size ); - void ArchiveObject( Class *obj ); + qboolean ObjectPositionExists(void *obj); - qboolean ObjectPositionExists( void * obj ); - - void SetSilent( bool bSilent ); + void Reset(); + size_t Counter() const; + void ArchiveConfigString(int cs); + void SetSilent(bool bSilent); }; -inline qboolean Archiver::Read -( -str &name, -qboolean harderror -) +template +inline void Container::Archive(Archiver& arc, void (*ArchiveFunc)(Archiver& arc, Type *obj)) { - return Read( name.c_str(), harderror ); -} + Type *obj; + int num; + int i; -inline qboolean Archiver::Create -( -str &name, -qboolean harderror -) -{ - return Create( name.c_str(), harderror ); -} + if (arc.Loading()) { + arc.ArchiveInteger(&num); + Resize(num); -inline qboolean Archiver::Loading -( -void -) -{ - return (archivemode == ARCHIVE_READ) ? qtrue : qfalse; -} + if (num > numobjects) { + numobjects = num; + } -inline qboolean Archiver::Saving -( -void -) -{ - return (archivemode == ARCHIVE_WRITE) ? qtrue : qfalse; -} + for (i = 0; i < num; i++) { + obj = new (objlist + i) Type(); + ArchiveFunc(arc, obj); + } + } else { + num = numobjects; + arc.ArchiveInteger(&num); -inline qboolean Archiver::NoErrors -( -void -) -{ - return fileerror ? qfalse : qtrue; -} - -template< class Type > -inline void Container::Archive - ( - Archiver& arc, - void( *ArchiveFunc )( Archiver& arc, Type *obj ) - ) -{ - int num; - int i; - - if( arc.Loading() ) - { - arc.ArchiveInteger( &num ); - Resize( num ); - } - else - { - num = numobjects; - arc.ArchiveInteger( &num ); - } - - for( i = 1; i <= num; i++ ) - { - if( num > numobjects ) { - numobjects = num; - } - - ArchiveFunc( arc, &objlist[ i - 1 ] ); - } + for (i = 0; i < num; i++) { + ArchiveFunc(arc, &objlist[i]); + } + } } template<> -inline void Container::Archive -( -Archiver &arc -) +inline void Container::Archive(Archiver& arc) { - int i, num; + int i, num; - if( arc.Loading() ) - { - ClearObjectList(); - arc.ArchiveInteger( &num ); - Resize( num ); - } - else - { - num = numobjects; - arc.ArchiveInteger( &num ); - } - for( i = 1; i <= num; i++ ) - { - arc.ArchiveString( AddressOfObjectAt( i ) ); - } + if (arc.Loading()) { + ClearObjectList(); + arc.ArchiveInteger(&num); + Resize(num); + } else { + num = numobjects; + arc.ArchiveInteger(&num); + } + for (i = 1; i <= num; i++) { + arc.ArchiveString(AddressOfObjectAt(i)); + } } template<> -inline void Container::Archive -( -Archiver &arc -) +inline void Container::Archive(Archiver& arc) { - int i, num; + int i, num; - if( arc.Loading() ) - { - ClearObjectList(); - arc.ArchiveInteger( &num ); - Resize( num ); - } - else - { - num = numobjects; - arc.ArchiveInteger( &num ); - } - for( i = 1; i <= num; i++ ) - { - arc.ArchiveVector( AddressOfObjectAt( i ) ); - } + if (arc.Loading()) { + ClearObjectList(); + arc.ArchiveInteger(&num); + Resize(num); + } else { + num = numobjects; + arc.ArchiveInteger(&num); + } + for (i = 1; i <= num; i++) { + arc.ArchiveVector(AddressOfObjectAt(i)); + } } template<> -inline void Container::Archive -( -Archiver &arc -) +inline void Container::Archive(Archiver& arc) { - int i, num; + int i, num; - if( arc.Loading() ) - { - ClearObjectList(); - arc.ArchiveInteger( &num ); - Resize( num ); - } - else - { - num = numobjects; - arc.ArchiveInteger( &num ); - } - for( i = 1; i <= num; i++ ) - { - arc.ArchiveInteger( AddressOfObjectAt( i ) ); - } + if (arc.Loading()) { + ClearObjectList(); + arc.ArchiveInteger(&num); + Resize(num); + } else { + num = numobjects; + arc.ArchiveInteger(&num); + } + for (i = 1; i <= num; i++) { + arc.ArchiveInteger(AddressOfObjectAt(i)); + } } template<> -inline void Container::Archive -( -Archiver &arc -) +inline void Container::Archive(Archiver& arc) { - int i, num; + int i, num; - if( arc.Loading() ) - { - ClearObjectList(); - arc.ArchiveInteger( &num ); - Resize( num ); - } - else - { - num = numobjects; - arc.ArchiveInteger( &num ); - } - for( i = 1; i <= num; i++ ) - { - arc.ArchiveFloat( AddressOfObjectAt( i ) ); - } + if (arc.Loading()) { + ClearObjectList(); + arc.ArchiveInteger(&num); + Resize(num); + } else { + num = numobjects; + arc.ArchiveInteger(&num); + } + for (i = 1; i <= num; i++) { + arc.ArchiveFloat(AddressOfObjectAt(i)); + } } -template< typename c > -inline void ArchiveClass - ( - Archiver& arc, - c *obj - ) +template +inline void ArchiveClass(Archiver& arc, c *obj) { - arc.ArchiveObject( obj ); + arc.ArchiveObject(obj); +} + +template +void Container::Archive(Archiver& arc) +{ + Archive(arc, ArchiveClass); } #ifndef NO_ARCHIVE -template< typename key, typename value > -void con_set< key, value >::Archive - ( - Archiver& arc - ) +template +void con_set::Archive(Archiver& arc) { - Entry *e; - int hash; - int i; + Entry *e = NULL; + int hash; + int i; - arc.ArchiveUnsigned( &tableLength ); - arc.ArchiveUnsigned( &threshold ); - arc.ArchiveUnsigned( &count ); - arc.ArchiveUnsignedShort( &tableLengthIndex ); + arc.ArchiveUnsigned(&tableLength); + arc.ArchiveUnsigned(&threshold); + arc.ArchiveUnsigned(&count); + arc.ArchiveUnsignedShort(&tableLengthIndex); - if( arc.Loading() ) - { - if( tableLength != 1 ) - { - table = new Entry *[ tableLength ](); - memset( table, 0, tableLength * sizeof( Entry * ) ); - } + if (arc.Loading()) { + if (tableLength != 1) { + table = new (NewTable(tableLength)) Entry *[tableLength](); + memset(table, 0, tableLength * sizeof(Entry *)); + } - for( i = 0; i < count; i++ ) - { - e = new Entry; - e->Archive( arc ); + for (i = 0; i < count; i++) { + e = new Entry; + e->Archive(arc); - hash = HashCode< key >( e->key ) % tableLength; + hash = HashCode(e->GetKey()) % tableLength; - e->next = table[ hash ]; - table[ hash ] = e; - } - } - else - { - for( i = tableLength - 1; i >= 0; i-- ) - { - for( e = table[ i ]; e != NULL; e = e->next ) - { - e->Archive( arc ); - } - } - } + e->next = table[hash]; + table[hash] = e; + } + + defaultEntry = e; + } else { +# ifndef NDEBUG + int total; + + total = 0; + + for (i = 0; i < tableLength; i++) { + for (e = table[i]; e != NULL; e = e->next) { + e->Archive(arc); + total++; + } + } + // it must match the number of elements + assert(total == count); +# else + for (i = 0; i < tableLength; i++) { + for (e = table[i]; e != NULL; e = e->next) { + e->Archive(arc); + } + } +# endif + } } -template< typename key, typename value > -void con_map< key, value >::Archive - ( - Archiver& arc - ) +template +void con_map::Archive(Archiver& arc) { - m_con_set.Archive( arc ); + m_con_set.Archive(arc); } #endif -#define ArchiveEnum( thing, type ) \ - { \ - int tempInt; \ - \ - tempInt = ( int )( thing ); \ - arc.ArchiveInteger( &tempInt ); \ - ( thing ) = ( type )tempInt; \ - } - -#endif // __ARCHIVE_H__ +#define ArchiveEnum(thing, type) \ + { \ + int tempInt; \ + \ + tempInt = (int)(thing); \ + arc.ArchiveInteger(&tempInt); \ + (thing) = (type)tempInt; \ + } diff --git a/code/fgame/armor.h b/code/fgame/armor.h index e1b97a5c..ee2f838e 100644 --- a/code/fgame/armor.h +++ b/code/fgame/armor.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // armor.h: Standard armor that prevents a percentage of damage per hit. -#ifndef __ARMOR_H__ -#define __ARMOR_H__ +#pragma once #include "weapon.h" @@ -40,5 +39,3 @@ class Armor : public Item qboolean Pickupable( Entity *other ) override; }; - -#endif /* armor.h */ diff --git a/code/fgame/barrels.cpp b/code/fgame/barrels.cpp index e23a0096..7d85a04b 100644 --- a/code/fgame/barrels.cpp +++ b/code/fgame/barrels.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /***************************************************************************** /*QUAKED func_barrel (0 0.25 0.5) ? INDESTRUCTABLE Brush model barrel object -Bashing only makes thunk or gong sounds (depending on wether it's full or not) +Bashing only makes thunk or gong sounds (depending on whether it's full or not) Bullets and explosions effects are dependant apon the type of barrel. "barreltype" sets the type of barrel that it is. Valid settings are: - "water" makes the barrel be filled with water. @@ -45,562 +45,444 @@ Does nothing special at all. It's just a poor empty barrel. aww :( ******************************************************************************/ Event EV_Barrel_Think - ( +( "_barrel_think", EV_DEFAULT, NULL, NULL, "think function for a barrel." - ); +); Event EV_Barrel_Setup - ( +( "_barrel_setup", EV_DEFAULT, NULL, NULL, "Does the post spawn setup of the barrel" - ); +); Event EV_Barrel_SetType - ( +( "barreltype", EV_DEFAULT, "s", "type", "Sets the barrel's type" - ); +); -CLASS_DECLARATION( Entity, BarrelObject, "func_barrel" ) -{ - { &EV_Barrel_Setup, &BarrelObject::BarrelSetup }, - { &EV_Barrel_Think, &BarrelObject::BarrelThink }, - { &EV_Barrel_SetType, &BarrelObject::BarrelSetType }, - { &EV_Damage, &BarrelObject::BarrelDamaged }, - { &EV_Killed, &BarrelObject::BarrelKilled }, - { NULL, NULL } +CLASS_DECLARATION(Entity, BarrelObject, "func_barrel") { + {&EV_Barrel_Setup, &BarrelObject::BarrelSetup }, + {&EV_Barrel_Think, &BarrelObject::BarrelThink }, + {&EV_Barrel_SetType, &BarrelObject::BarrelSetType}, + {&EV_Damage, &BarrelObject::BarrelDamaged}, + {&EV_Killed, &BarrelObject::BarrelKilled }, + {NULL, NULL } }; BarrelObject::BarrelObject() { + AddWaitTill(STRING_DEATH); - AddWaitTill(STRING_DEATH); + if (LoadingSavegame) { + return; + } - if (LoadingSavegame) - { - return; - } + edict->s.eType = ET_GENERAL; - edict->s.eType = ET_GENERAL; + m_iBarrelType = 0; + m_fFluidAmount = 0; + m_fHeightFluid = 0; - m_iBarrelType = 0; - m_fFluidAmount = 0; - m_fHeightFluid = 0; + for (int i = 0; i < MAX_BARREL_LEAKS; i++) { + m_bLeaksActive[i] = 0; + } - for( int i = 0; i < MAX_BARREL_LEAKS; i++ ) - { - m_bLeaksActive[ i ] = 0; - } + m_fDamageSoundTime = 0; + mass = 500; + max_health = 75; + health = 75; + deadflag = DEAD_NO; + takedamage = DAMAGE_YES; + m_vJitterAngles = vec_zero; - m_fDamageSoundTime = 0; - mass = 500; - max_health = 75; - health = 75; - deadflag = DEAD_NO; - takedamage = DAMAGE_YES; - m_vJitterAngles = vec_zero; - - PostEvent( EV_Barrel_Setup, EV_POSTSPAWN ); + PostEvent(EV_Barrel_Setup, EV_POSTSPAWN); } -int BarrelObject::PickBarrelLeak - ( - void - ) +int BarrelObject::PickBarrelLeak(void) { - int iHighest; - float fHighestHeight; + int iHighest; + float fHighestHeight; - for( int i = 0; i < MAX_BARREL_LEAKS; i++ ) - { - if( !m_bLeaksActive[ i ] ) { - return i; - } - } + for (int i = 0; i < MAX_BARREL_LEAKS; i++) { + if (!m_bLeaksActive[i]) { + return i; + } + } - fHighestHeight = m_vLeaks[ 0 ][ 2 ]; - iHighest = 0; + fHighestHeight = m_vLeaks[0][2]; + iHighest = 0; - for( int i = 1; i < MAX_BARREL_LEAKS; i++ ) - { - if( m_vLeaks[ 0 ][ 2 ] > fHighestHeight ) - { - fHighestHeight = m_vLeaks[ 0 ][ 2 ]; - iHighest = i; - } - } + for (int i = 1; i < MAX_BARREL_LEAKS; i++) { + if (m_vLeaks[0][2] > fHighestHeight) { + fHighestHeight = m_vLeaks[0][2]; + iHighest = i; + } + } - return iHighest; + return iHighest; } -void BarrelObject::BarrelSetup - ( - Event *ev - ) +void BarrelObject::BarrelSetup(Event *ev) { - setMoveType( MOVETYPE_PUSH ); - setSolidType( SOLID_BSP ); + setMoveType(MOVETYPE_PUSH); + setSolidType(SOLID_BSP); - m_vStartAngles = angles; - m_fJitterScale = 64.0f / size[ 2 ]; + m_vStartAngles = angles; + m_fJitterScale = 64.0f / size[2]; - m_fFluidAmount = size[ 0 ] * size[ 1 ] * size[ 2 ] / 150.0f; - m_fHeightFluid = m_fFluidAmount / size[ 2 ]; + m_fFluidAmount = size[0] * size[1] * size[2] / 150.0f; + m_fHeightFluid = m_fFluidAmount / size[2]; - // Position the barrel correctly - CheckGround(); + // Position the barrel correctly + CheckGround(); } -void BarrelObject::BarrelSetType - ( - Event *ev - ) +void BarrelObject::BarrelSetType(Event *ev) { - str sType = ev->GetString( 1 ); + str sType = ev->GetString(1); - if( !sType.icmp( "oil" ) ) - { - health = 75; - m_iBarrelType = BARREL_OIL; + if (!sType.icmp("oil")) { + health = 75; + m_iBarrelType = BARREL_OIL; - CacheResource( "models/fx/barrel_empty_destroyed.tik" ); - CacheResource( "models/fx/barrel_oil_destroyed.tik" ); - } - else if( !sType.icmp( "water" ) ) - { - health = 75; - m_iBarrelType = BARREL_WATER; + CacheResource("models/fx/barrel_empty_destroyed.tik"); + CacheResource("models/fx/barrel_oil_destroyed.tik"); + } else if (!sType.icmp("water")) { + health = 75; + m_iBarrelType = BARREL_WATER; - CacheResource( "models/fx/barrel_empty_destroyed.tik" ); - CacheResource( "models/fx/barrel_water_destroyed.tik" ); - } - else if( !sType.icmp( "gas" ) ) - { - spawnflags &= ~BARREL_INDESTRUCTABLE; - health = 75; - m_iBarrelType = BARREL_GAS; + CacheResource("models/fx/barrel_empty_destroyed.tik"); + CacheResource("models/fx/barrel_water_destroyed.tik"); + } else if (!sType.icmp("gas")) { + spawnflags &= ~BARREL_INDESTRUCTABLE; + health = 75; + m_iBarrelType = BARREL_GAS; - CacheResource( "models/fx/barrel_gas_destroyed.tik" ); - } - else - { - health = 75; - m_iBarrelType = BARREL_EMPTY; + CacheResource("models/fx/barrel_gas_destroyed.tik"); + } else { + health = 75; + m_iBarrelType = BARREL_EMPTY; - CacheResource( "models/fx/barrel_empty_destroyed.tik" ); - } + CacheResource("models/fx/barrel_empty_destroyed.tik"); + } - max_health = health; + max_health = health; } -void BarrelObject::BarrelThink - ( - Event *ev - ) +void BarrelObject::BarrelThink(Event *ev) { - int i; - int iBiggestLeak; - float fFluidTop; + int i; + int iBiggestLeak; + float fFluidTop; - iBiggestLeak = 0; + iBiggestLeak = 0; - fFluidTop = m_fFluidAmount / m_fHeightFluid + ( mins[ 2 ] + origin[ 2 ] ); - for( i = 0; i < MAX_BARREL_LEAKS; i++ ) - { - if( !m_bLeaksActive[ i ] ) { - continue; - } + fFluidTop = m_fFluidAmount / m_fHeightFluid + (mins[2] + origin[2]); + for (i = 0; i < MAX_BARREL_LEAKS; i++) { + if (!m_bLeaksActive[i]) { + continue; + } - // Send infos to clients - if( m_vLeaks[ i ][ 2 ] <= fFluidTop ) - { - gi.SetBroadcastVisible( m_vLeaks[ i ], m_vLeaks[ i ] ); + // Send infos to clients + if (m_vLeaks[i][2] > fFluidTop) { + gi.SetBroadcastVisible(m_vLeaks[i], m_vLeaks[i]); - if( m_vLeaks[ i ][ 2 ] <= fFluidTop - 1.3f ) - { - if( m_vLeaks[ i ][ 2 ] <= fFluidTop - 3.0f ) - { - // big leak + if (m_iBarrelType == BARREL_OIL) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3)); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7)); + } - if( m_iBarrelType == BARREL_OIL ) - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_1)); - } - else - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_5)); - } + gi.MSG_WriteCoord(m_vLeaks[i][0]); + gi.MSG_WriteCoord(m_vLeaks[i][1]); + gi.MSG_WriteCoord(m_vLeaks[i][2]); + gi.MSG_WriteDir(m_vLeakNorms[i]); + gi.MSG_EndCGM(); - m_fFluidAmount -= 1.0f; - iBiggestLeak |= 4; - } - else - { - // medium leak + m_bLeaksActive[i] = qfalse; + } else { + gi.SetBroadcastVisible(m_vLeaks[i], m_vLeaks[i]); - if( m_iBarrelType == BARREL_OIL ) - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_2)); - } - else - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_6)); - } + if (m_vLeaks[i][2] > fFluidTop - 1.3f) { + // small leak - m_fFluidAmount -= 0.75f; - iBiggestLeak |= 2; - } - } - else - { - // small leak + if (m_iBarrelType == BARREL_OIL) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3)); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7)); + } - if( m_iBarrelType == BARREL_OIL ) - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3)); - } - else - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7)); - } + m_fFluidAmount -= 0.5f; + iBiggestLeak |= 1; + } else if (m_vLeaks[i][2] > fFluidTop - 3.0f) { + // medium leak - m_fFluidAmount -= 0.5f; - iBiggestLeak |= 1; - } + if (m_iBarrelType == BARREL_OIL) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_2)); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_6)); + } - gi.MSG_WriteCoord( m_vLeaks[ i ][ 0 ] ); - gi.MSG_WriteCoord( m_vLeaks[ i ][ 1 ] ); - gi.MSG_WriteCoord( m_vLeaks[ i ][ 2 ] ); - gi.MSG_WriteDir( m_vLeakNorms[ i ] ); - gi.MSG_EndCGM(); - } - else - { - gi.SetBroadcastVisible( m_vLeaks[ i ], m_vLeaks[ i ] ); + m_fFluidAmount -= 0.75f; + iBiggestLeak |= 2; + } else { + // big leak - if( m_iBarrelType == BARREL_OIL ) - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3)); - } - else - { - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7)); - } + if (m_iBarrelType == BARREL_OIL) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_1)); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_5)); + } - gi.MSG_WriteCoord( m_vLeaks[ i ][ 0 ] ); - gi.MSG_WriteCoord( m_vLeaks[ i ][ 1 ] ); - gi.MSG_WriteCoord( m_vLeaks[ i ][ 2 ] ); - gi.MSG_WriteDir( m_vLeakNorms[ i ] ); - gi.MSG_EndCGM(); + m_fFluidAmount -= 1.0f; + iBiggestLeak |= 4; + } - m_bLeaksActive[ i ] = qfalse; - } - } + gi.MSG_WriteCoord(m_vLeaks[i][0]); + gi.MSG_WriteCoord(m_vLeaks[i][1]); + gi.MSG_WriteCoord(m_vLeaks[i][2]); + gi.MSG_WriteDir(m_vLeakNorms[i]); + gi.MSG_EndCGM(); + } + } - if( m_vJitterAngles[ 0 ] == 0.0f && m_vJitterAngles[ 2 ] == 0.0f ) - { - if( !VectorCompare( angles, m_vStartAngles ) ) - { - setAngles( m_vStartAngles ); - } - } + if (m_vJitterAngles[0] == 0.0f && m_vJitterAngles[2] == 0.0f) { + if (!VectorCompare(angles, m_vStartAngles)) { + setAngles(m_vStartAngles); + } + } + else { + Vector ang; - setAngles( Vector( m_vStartAngles[ 0 ] + m_vJitterAngles[ 0 ], m_vStartAngles[ 1 ], m_vStartAngles[ 2 ] + m_vJitterAngles[ 2 ] ) ); + ang = m_vStartAngles; + ang[0] += m_vJitterAngles[0]; + ang[2] += m_vJitterAngles[2]; + setAngles(ang); - if( m_vJitterAngles[ 0 ] > 0.0f ) - { - m_vJitterAngles[ 0 ] -= 1.f / 3.f * m_fJitterScale; + if (m_vJitterAngles[0] < 0) { + m_vJitterAngles[0] += 1.f / 3.f * m_fJitterScale; - if( m_vJitterAngles[ 0 ] > 0.0f ) - { - m_vJitterAngles[ 0 ] = 0.0f; - } - } - else if( m_vJitterAngles[ 0 ] < 0.0f ) - { - m_vJitterAngles[ 0 ] += 1.f / 3.f * m_fJitterScale; + if (m_vJitterAngles[0] > 0) { + m_vJitterAngles[0] = 0; + } + } else if (m_vJitterAngles[0] > 0) { + m_vJitterAngles[0] -= 1.f / 3.f * m_fJitterScale; - if( m_vJitterAngles[ 0 ] < 0.0f ) - { - m_vJitterAngles[ 0 ] = 0.0f; - } - } + if (m_vJitterAngles[0] < 0) { + m_vJitterAngles[0] = 0; + } + } - m_vJitterAngles[ 0 ] = -m_vJitterAngles[ 0 ]; + m_vJitterAngles[0] = -m_vJitterAngles[0]; - if( m_vJitterAngles[ 2 ] > 0.0f ) - { - m_vJitterAngles[ 2 ] -= 1.f / 3.f * m_fJitterScale; + if (m_vJitterAngles[2] < 0) { + m_vJitterAngles[2] += 1.f / 3.f * m_fJitterScale; - if( m_vJitterAngles[ 2 ] > 0.0f ) - { - m_vJitterAngles[ 2 ] = 0.0f; - } - } - else if( m_vJitterAngles[ 2 ] < 0.0f ) - { - m_vJitterAngles[ 2 ] += 1.f / 3.f * m_fJitterScale; + if (m_vJitterAngles[2] > 0) { + m_vJitterAngles[2] = 0; + } + } else if (m_vJitterAngles[2] > 0) { + m_vJitterAngles[2] -= 1.f / 3.f * m_fJitterScale; - if( m_vJitterAngles[ 2 ] < 0.0f ) - { - m_vJitterAngles[ 2 ] = 0.0f; - } - } + if (m_vJitterAngles[2] < 0) { + m_vJitterAngles[2] = 0; + } + } - m_vJitterAngles[ 2 ] = -m_vJitterAngles[ 2 ]; + m_vJitterAngles[2] = -m_vJitterAngles[2]; + } - // Check for at least one active leak to play a sound - for( i = 0; i < MAX_BARREL_LEAKS; i++ ) - { - if( m_bLeaksActive[ i ] ) { - break; - } - } + // Check for at least one active leak to play a sound + for (i = 0; i < MAX_BARREL_LEAKS; i++) { + if (m_bLeaksActive[i]) { + break; + } + } - // Play a leak sound - if( i != MAX_BARREL_LEAKS && iBiggestLeak ) - { - if( !( iBiggestLeak & 4 ) ) - { - if( iBiggestLeak & 2 ) - { - // medium leak - LoopSound( "liquid_leak", 0.60f, -1.0f, -1.0f, 0.90f ); - } - else - { - // small leak - LoopSound( "liquid_leak", 0.30f, -1.0f, -1.0f, 0.80f ); - } - } - else - { - // big leak - LoopSound( "liquid_leak", 1.0f, -1.0f, -1.0f, 1.0f ); - } - } + // Play a leak sound + if (i != MAX_BARREL_LEAKS && iBiggestLeak) { + if (iBiggestLeak & 4) { + // big leak + LoopSound("liquid_leak", 1, -1, -1, 1); + } else if (iBiggestLeak & 2) { + // medium leak + LoopSound("liquid_leak", 0.6, -1, -1, 0.9); + } else { + // small leak + LoopSound("liquid_leak", 0.3, -1, -1, 0.8); + } + } - if( i == MAX_BARREL_LEAKS ) { - StopLoopSound(); - } + if (i == MAX_BARREL_LEAKS) { + StopLoopSound(); + } - if( m_vJitterAngles[ 0 ] || m_vJitterAngles[ 2 ] || i < MAX_BARREL_LEAKS ) - { - m_fLastEffectTime += 0.075f; + if (m_vJitterAngles[0] || m_vJitterAngles[2] || i < MAX_BARREL_LEAKS) { + m_fLastEffectTime += 0.075f; - if( level.time >= m_fLastEffectTime ) - { - m_fLastEffectTime = level.time + 0.075f; - } + if (m_fLastEffectTime <= level.time) { + m_fLastEffectTime = level.time + 0.075f; + } - PostEvent( EV_Barrel_Think, m_fLastEffectTime - level.time ); - } + PostEvent(EV_Barrel_Think, m_fLastEffectTime - level.time); + } } -void BarrelObject::BarrelDamaged - ( - Event *ev - ) +void BarrelObject::BarrelDamaged(Event *ev) { - Vector vDir; - Vector vForward; - Vector vRight; - int iDamage; - int iMeansOfDeath; - Vector vHitPos; - Vector vHitDirection; - Vector vHitNormal; + Vector vDir; + Vector vForward; + Vector vRight; + int iDamage; + int iMeansOfDeath; + Vector vHitPos; + Vector vHitDirection; + Vector vHitNormal; - if( !takedamage ) - { - return; - } + if (!takedamage) { + return; + } - iDamage = ev->GetInteger( 2 ); - iMeansOfDeath = ev->GetInteger( 9 ); - vHitPos = ev->GetVector( 4 ); - vHitDirection = ev->GetVector( 5 ); - vHitNormal = ev->GetVector( 6 ); + iDamage = ev->GetInteger(2); + iMeansOfDeath = ev->GetInteger(9); + vHitPos = ev->GetVector(4); + vHitDirection = ev->GetVector(5); + vHitNormal = ev->GetVector(6); - vDir = ( vHitDirection - vHitNormal ) * 0.5f; - AngleVectors( angles, vForward, vRight, NULL ); + vDir = (vHitDirection - vHitNormal) * 0.5f; + AngleVectors(angles, vForward, vRight, NULL); - m_vJitterAngles[ 0 ] += DotProduct( vDir, vForward ) * m_fJitterScale * 0.0275f * ( float )iDamage; - m_vJitterAngles[ 2 ] += DotProduct( vDir, vRight ) * m_fJitterScale * 0.0275f * ( float )iDamage; + m_vJitterAngles[0] += DotProduct(vDir, vForward) * m_fJitterScale * 0.0275f * (float)iDamage; + m_vJitterAngles[2] += DotProduct(vDir, vRight) * m_fJitterScale * 0.0275f * (float)iDamage; - if( m_vJitterAngles[ 0 ] > m_fJitterScale * 1.5f ) - { - m_vJitterAngles[ 0 ] = m_fJitterScale * 1.5f; - } - else if( m_vJitterAngles[ 0 ] < -( m_fJitterScale * 1.5f ) ) - { - m_vJitterAngles[ 0 ] = -( m_fJitterScale * 1.5f ); - } + if (m_vJitterAngles[0] > m_fJitterScale * 1.5f) { + m_vJitterAngles[0] = m_fJitterScale * 1.5f; + } else if (m_vJitterAngles[0] < -(m_fJitterScale * 1.5f)) { + m_vJitterAngles[0] = -(m_fJitterScale * 1.5f); + } - if( m_vJitterAngles[ 2 ] > m_fJitterScale * 1.5f ) - { - m_vJitterAngles[ 2 ] = m_fJitterScale * 1.5f; - } - else if( m_vJitterAngles[ 2 ] < -( m_fJitterScale * 1.5f ) ) - { - m_vJitterAngles[ 2 ] = -( m_fJitterScale * 1.5f ); - } + if (m_vJitterAngles[2] > m_fJitterScale * 1.5f) { + m_vJitterAngles[2] = m_fJitterScale * 1.5f; + } else if (m_vJitterAngles[2] < -(m_fJitterScale * 1.5f)) { + m_vJitterAngles[2] = -(m_fJitterScale * 1.5f); + } - if( !( spawnflags & BARREL_INDESTRUCTABLE ) ) - { - if( ( iMeansOfDeath == MOD_VEHICLE || iMeansOfDeath == MOD_ROCKET || - iMeansOfDeath == MOD_GRENADE || iMeansOfDeath == MOD_EXPLODEWALL || - iMeansOfDeath == MOD_EXPLOSION || m_iBarrelType == BARREL_GAS ) && - iMeansOfDeath != MOD_BASH - ) - { - if( iDamage >= health ) - { - PostEvent( EV_Killed, 0.01f ); - takedamage = DAMAGE_NO; - return; - } + if (!(spawnflags & BARREL_INDESTRUCTABLE)) { + if ((iMeansOfDeath == MOD_VEHICLE || iMeansOfDeath == MOD_ROCKET || iMeansOfDeath == MOD_GRENADE + || iMeansOfDeath == MOD_EXPLODEWALL || iMeansOfDeath == MOD_EXPLOSION || m_iBarrelType == BARREL_GAS) + && iMeansOfDeath != MOD_BASH) { + if (iDamage >= health) { + PostEvent(EV_Killed, 0.01f); + takedamage = DAMAGE_NO; + return; + } - if( m_iBarrelType == BARREL_GAS ) - { - iDamage /= 2; + if (m_iBarrelType == BARREL_GAS) { + iDamage /= 2; - health -= iDamage; - if( health < 1.0f ) - health = 1.0f; - } - } - } + health -= iDamage; + if (health < 1.0f) { + health = 1.0f; + } + } + } + } - if( !EventPending( EV_Barrel_Think ) ) - { - m_fLastEffectTime = level.time - 0.075f; - ProcessEvent( EV_Barrel_Think ); - } + if (!EventPending(EV_Barrel_Think)) { + m_fLastEffectTime = level.time - 0.075f; + ProcessEvent(EV_Barrel_Think); + } - if( m_iBarrelType <= BARREL_WATER ) - { - int index = PickBarrelLeak(); + if (m_iBarrelType <= BARREL_WATER) { + int index = PickBarrelLeak(); - if( vHitPos[ 2 ] <= m_fFluidAmount / m_fHeightFluid + origin[ 2 ] + mins[ 2 ] ) - { - m_bLeaksActive[ index ] = qtrue; - m_vLeaks[ index ] = vHitPos; - m_vLeakNorms[ index ] = vHitNormal; + if (vHitPos[2] <= m_fFluidAmount / m_fHeightFluid + origin[2] + mins[2]) { + m_bLeaksActive[index] = qtrue; + m_vLeaks[index] = vHitPos; + m_vLeakNorms[index] = vHitNormal; - gi.SetBroadcastVisible( vHitPos, vHitPos ); + gi.SetBroadcastVisible(vHitPos, vHitPos); - if( m_iBarrelType == BARREL_OIL ) - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_4)); - else - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_8)); - } - else - { - gi.SetBroadcastVisible( vHitPos, vHitPos ); + if (m_iBarrelType == BARREL_OIL) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_4)); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_8)); + } + } else { + gi.SetBroadcastVisible(vHitPos, vHitPos); - if( m_iBarrelType == BARREL_OIL ) - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3)); - else - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7)); - } + if (m_iBarrelType == BARREL_OIL) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3)); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7)); + } + } - gi.MSG_WriteCoord( vHitPos[ 0 ] ); - gi.MSG_WriteCoord( vHitPos[ 1 ] ); - gi.MSG_WriteCoord( vHitPos[ 2 ] ); - gi.MSG_WriteDir( vHitNormal ); - gi.MSG_EndCGM(); - } + gi.MSG_WriteCoord(vHitPos[0]); + gi.MSG_WriteCoord(vHitPos[1]); + gi.MSG_WriteCoord(vHitPos[2]); + gi.MSG_WriteDir(vHitNormal); + gi.MSG_EndCGM(); + } } -void BarrelObject::BarrelKilled - ( - Event *ev - ) +void BarrelObject::BarrelKilled(Event *ev) { - float fFluidTop; - Vector vPos; - str sModel; + float fFluidTop; + Vector vPos; + str sModel; - setSolidType( SOLID_NOT ); - PostEvent( EV_Remove, 0.05f ); + setSolidType(SOLID_NOT); + PostEvent(EV_Remove, 0.05f); - vPos[ 2 ] = ( mins[ 2 ] + origin[ 2 ] ); - fFluidTop = m_fFluidAmount / m_fHeightFluid + vPos[ 2 ]; + vPos[2] = (mins[2] + origin[2]); + fFluidTop = m_fFluidAmount / m_fHeightFluid + vPos[2]; - if( m_iBarrelType == BARREL_GAS ) - { - RadiusDamage( - centroid, - this, - this, - 200, - this, - MOD_EXPLOSION, - 350, - 24 ); + if (m_iBarrelType == BARREL_GAS) { + RadiusDamage(centroid, this, this, 200, this, MOD_EXPLOSION, 350, 24); - sModel = "models/fx/barrel_gas_destroyed.tik"; - } - else if( m_iBarrelType == BARREL_WATER ) - { - if( vPos[ 2 ] + 0.25f * maxs[ 2 ] <= fFluidTop ) - { - sModel = "models/fx/barrel_water_destroyed.tik"; - } - else - { - sModel = "models/fx/barrel_empty_destroyed.tik"; - } - } - else if( m_iBarrelType == BARREL_OIL ) - { - if( vPos[ 2 ] + 0.25f * maxs[ 2 ] > fFluidTop ) - { - sModel = "models/fx/barrel_empty_destroyed.tik"; - } - else - { - RadiusDamage( - centroid, - this, - this, - 200, - this, - MOD_EXPLOSION, - 350, - 24 ); + sModel = "models/fx/barrel_gas_destroyed.tik"; + } else if (m_iBarrelType == BARREL_WATER) { + if (vPos[2] + 0.25f * maxs[2] <= fFluidTop) { + sModel = "models/fx/barrel_water_destroyed.tik"; + } else { + sModel = "models/fx/barrel_empty_destroyed.tik"; + } + } else if (m_iBarrelType == BARREL_OIL) { + if (vPos[2] + 0.25f * maxs[2] > fFluidTop) { + sModel = "models/fx/barrel_empty_destroyed.tik"; + } else { + RadiusDamage(centroid, this, this, 200, this, MOD_EXPLOSION, 350, 24); - sModel = "models/fx/barrel_oil_destroyed.tik"; - } - } - else - { - sModel = "models/fx/barrel_empty_destroyed.tik"; - } + sModel = "models/fx/barrel_oil_destroyed.tik"; + } + } else { + sModel = "models/fx/barrel_empty_destroyed.tik"; + } - Animate *exp = new Animate; + Animate *exp = new Animate; - // Spawn an explosion effect - exp->edict->s.renderfx |= RF_DONTDRAW; - exp->setModel( sModel ); + // Spawn an explosion effect + exp->edict->s.renderfx |= RF_DONTDRAW; + exp->setModel(sModel); - vPos = origin + ( maxs + mins ) * 0.5f; + vPos = origin + (maxs + mins) * 0.5f; - exp->setAngles( Vector( -90, 0, 0 ) ); - exp->setOrigin( vPos ); - exp->NewAnim( "idle" ); + exp->setAngles(Vector(-90, 0, 0)); + exp->setOrigin(vPos); + exp->NewAnim("idle"); - exp->PostEvent( EV_Remove, 0.1f ); - exp->Unregister( STRING_DEATH ); + exp->PostEvent(EV_Remove, 0.1f); + exp->Unregister(STRING_DEATH); } diff --git a/code/fgame/barrels.h b/code/fgame/barrels.h index 78caaf43..18f67451 100644 --- a/code/fgame/barrels.h +++ b/code/fgame/barrels.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,73 +22,66 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // barrels.h : Barrels -#ifndef __BARRELOBJECT_H__ -#define __BARRELOBJECT_H__ +#pragma once #include "entity.h" -#define BARREL_INDESTRUCTABLE 1 -#define MAX_BARREL_LEAKS 4 +#define BARREL_INDESTRUCTABLE 1 +#define MAX_BARREL_LEAKS 4 -enum -{ - BARREL_EMPTY, - BARREL_OIL, - BARREL_WATER, - BARREL_GAS +enum { + BARREL_EMPTY, + BARREL_OIL, + BARREL_WATER, + BARREL_GAS }; -class BarrelObject : public Entity { - int m_iBarrelType; - float m_fFluidAmount; - float m_fHeightFluid; - qboolean m_bLeaksActive[ MAX_BARREL_LEAKS ]; - Vector m_vLeaks[ MAX_BARREL_LEAKS ]; - Vector m_vLeakNorms[ MAX_BARREL_LEAKS ]; - Vector m_vJitterAngles; - Vector m_vStartAngles; - float m_fJitterScale; - float m_fLastEffectTime; - float m_fDamageSoundTime; +class BarrelObject : public Entity +{ + int m_iBarrelType; + float m_fFluidAmount; + float m_fHeightFluid; + qboolean m_bLeaksActive[MAX_BARREL_LEAKS]; + Vector m_vLeaks[MAX_BARREL_LEAKS]; + Vector m_vLeakNorms[MAX_BARREL_LEAKS]; + Vector m_vJitterAngles; + Vector m_vStartAngles; + float m_fJitterScale; + float m_fLastEffectTime; + float m_fDamageSoundTime; public: - CLASS_PROTOTYPE( BarrelObject ); + CLASS_PROTOTYPE(BarrelObject); - BarrelObject(); + BarrelObject(); - int PickBarrelLeak( void ); + int PickBarrelLeak(void); - void BarrelSetup( Event *ev ); - void BarrelSetType( Event *ev ); - void BarrelThink( Event *ev ); - void BarrelDamaged( Event *ev ); - void BarrelKilled( Event *ev ); + void BarrelSetup(Event *ev); + void BarrelSetType(Event *ev); + void BarrelThink(Event *ev); + void BarrelDamaged(Event *ev); + void BarrelKilled(Event *ev); - void Archive( Archiver& arc ) override; + void Archive(Archiver& arc) override; }; -inline void BarrelObject::Archive - ( - Archiver& arc - ) +inline void BarrelObject::Archive(Archiver& arc) { - Entity::Archive( arc ); + Entity::Archive(arc); - arc.ArchiveInteger( &m_iBarrelType ); - arc.ArchiveFloat( &m_fFluidAmount ); - arc.ArchiveFloat( &m_fHeightFluid ); - arc.ArchiveVector( &m_vJitterAngles ); - arc.ArchiveVector( &m_vStartAngles ); - arc.ArchiveFloat( &m_fJitterScale ); - arc.ArchiveFloat( &m_fLastEffectTime ); - arc.ArchiveFloat( &m_fDamageSoundTime ); + arc.ArchiveInteger(&m_iBarrelType); + arc.ArchiveFloat(&m_fFluidAmount); + arc.ArchiveFloat(&m_fHeightFluid); + arc.ArchiveVector(&m_vJitterAngles); + arc.ArchiveVector(&m_vStartAngles); + arc.ArchiveFloat(&m_fJitterScale); + arc.ArchiveFloat(&m_fLastEffectTime); + arc.ArchiveFloat(&m_fDamageSoundTime); - for( int i = MAX_BARREL_LEAKS - 1; i >= 0; i-- ) - { - arc.ArchiveBoolean( &m_bLeaksActive[ i ] ); - arc.ArchiveVector( &m_vLeaks[ i ] ); - arc.ArchiveVector( &m_vLeakNorms[ i ] ); - } + for (int i = MAX_BARREL_LEAKS - 1; i >= 0; i--) { + arc.ArchiveBoolean(&m_bLeaksActive[i]); + arc.ArchiveVector(&m_vLeaks[i]); + arc.ArchiveVector(&m_vLeakNorms[i]); + } } - -#endif // __BARRELOBJECT_H__ diff --git a/code/fgame/baseimp.h b/code/fgame/baseimp.h index 5eaff5e9..205a3ca1 100644 --- a/code/fgame/baseimp.h +++ b/code/fgame/baseimp.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __BASEIMP_H__ -#define __BASEIMP_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -86,5 +85,3 @@ void CacheResource( const char *name ); #ifdef __cplusplus } #endif - -#endif diff --git a/code/fgame/beam.cpp b/code/fgame/beam.cpp index c298a826..6163ce32 100644 --- a/code/fgame/beam.cpp +++ b/code/fgame/beam.cpp @@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "beam.h" #include "../qcommon/qfiles.h" #include "game.h" +#include /*****************************************************************************/ /*QUAKED func_beam (0 0.25 .5) (-8 -8 -8) (8 8 8) START_ON PERSIST WAVE NOISE @@ -103,7 +104,7 @@ Event EV_FuncBeam_Minoffset EV_DEFAULT, "f", "min_offset", - "Set the minimun offset the beam can travel above, below, forward or back of it's endpoints", + "Set the minimum offset the beam can travel above, below, forward or back of it's endpoints", EV_NORMAL ); Event EV_FuncBeam_Overlap @@ -765,19 +766,19 @@ void FuncBeam::Activate } void FuncBeam::UpdateEndpoint - ( - Event *ev - ) + ( + Event* ev + ) - { - if ( end ) - { - Event *ev1 = new Event( ev ); +{ + if (end) + { + Event* ev1 = new Event(std::move(*ev)); - VectorCopy( end->origin, edict->s.origin2 ); - PostEvent( ev1, level.frametime ); - } - } + VectorCopy(end->origin, edict->s.origin2); + PostEvent(ev1, level.frametime); + } +} void FuncBeam::UpdateOrigin ( @@ -786,8 +787,8 @@ void FuncBeam::UpdateOrigin { if ( origin_target ) - { - Event *ev1 = new Event( ev ); + { + Event* ev1 = new Event(std::move(*ev)); setOrigin( origin_target->centroid ); PostEvent( ev1, level.frametime ); diff --git a/code/fgame/beam.h b/code/fgame/beam.h index 5cea8b7d..abd72ee7 100644 --- a/code/fgame/beam.h +++ b/code/fgame/beam.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // beam.h: Beam -#ifndef __BEAM_H__ -#define __BEAM_H__ +#pragma once #include "g_local.h" #include "scriptslave.h" @@ -123,5 +122,3 @@ inline void FuncBeam::Archive SetBeamShader( shader ); } } - -#endif // __BEAM_H__ diff --git a/code/fgame/bg_local.h b/code/fgame/bg_local.h index 143d2f5d..93ed4584 100644 --- a/code/fgame/bg_local.h +++ b/code/fgame/bg_local.h @@ -22,67 +22,68 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // bg_local.h -- local definitions for the bg (both games) files -#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes +#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes -#define JUMP_VELOCITY 270 +#define JUMP_VELOCITY 270 -#define TIMER_LAND 130 -#define TIMER_GESTURE (34*66+50) +#define TIMER_LAND 130 +#define TIMER_GESTURE (34 * 66 + 50) -#define OVERCLIP 1.001f +#define OVERCLIP 1.001f -#define HEAD_TAG 0 -#define TORSO_TAG 1 -#define ARMS_TAG 2 -#define PELVIS_TAG 3 -#define MOUTH_TAG 4 +#define HEAD_TAG 0 +#define TORSO_TAG 1 +#define ARMS_TAG 2 +#define PELVIS_TAG 3 +#define MOUTH_TAG 4 // all of the locals will be zeroed before each // pmove, just to make damn sure we don't have // any differences when running on client or server typedef struct { - vec3_t forward, left, up; - vec3_t flat_forward, flat_left, flat_up; - float frametime; + vec3_t forward, left, up; + vec3_t flat_forward, flat_left, flat_up; + float frametime; - int msec; + int msec; - qboolean walking; - qboolean groundPlane; - trace_t groundTrace; + qboolean walking; + qboolean groundPlane; + trace_t groundTrace; - float impactSpeed; + float impactSpeed; - vec3_t previous_origin; - vec3_t previous_velocity; - int previous_waterlevel; + vec3_t previous_origin; + vec3_t previous_velocity; + int previous_waterlevel; } pml_t; -extern pmove_t *pm; -extern pml_t pml; +extern pmove_t *pm; +extern pml_t pml; // movement parameters -extern float pm_stopspeed; -extern float pm_duckScale; -extern float pm_swimScale; -extern float pm_wadeScale; +extern float pm_stopspeed; +extern float pm_duckScale; +extern float pm_swimScale; +extern float pm_wadeScale; -extern float pm_accelerate; -extern float pm_airaccelerate; -extern float pm_wateraccelerate; -extern float pm_flyaccelerate; +extern float pm_accelerate; +extern float pm_airaccelerate; +extern float pm_wateraccelerate; +extern float pm_flyaccelerate; -extern float pm_friction; -extern float pm_waterfriction; -extern float pm_flightfriction; +extern float pm_friction; +extern float pm_waterfriction; +extern float pm_flightfriction; -extern int c_pmove; +extern const vec3_t MINS; +extern const vec3_t MAXS; -void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce ); -void PM_AddTouchEnt( int entityNum ); -void PM_AddEvent( int newEvent ); - -qboolean PM_SlideMove( qboolean gravity ); -void PM_StepSlideMove( qboolean gravity ); +extern int c_pmove; +void PM_ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce); +void PM_AddTouchEnt(int entityNum); +void PM_AddEvent(int newEvent); +qboolean PM_SlideMove(qboolean gravity); +void PM_StepSlideMove(qboolean gravity); diff --git a/code/fgame/bg_misc.cpp b/code/fgame/bg_misc.cpp index 246b1e44..b7f63276 100644 --- a/code/fgame/bg_misc.cpp +++ b/code/fgame/bg_misc.cpp @@ -31,9 +31,7 @@ BG_EvaluateTrajectoryDelta For determining velocity at a given time ================ */ -void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ) { - -} +void BG_EvaluateTrajectoryDelta(const trajectory_t *tr, int atTime, vec3_t result) {} // FIXME: OLD Q3 CODE #if 0 @@ -50,9 +48,9 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play { gitem_t *item; -#ifdef MISSIONPACK +# ifdef MISSIONPACK int upperBound; -#endif +# endif if ( ent->modelindex < 1 || ent->modelindex >= bg_numItems ) { Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: index out of range" ); @@ -71,7 +69,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play return qtrue; case IT_ARMOR: -#ifdef MISSIONPACK +# ifdef MISSIONPACK if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT ) { return qfalse; } @@ -87,22 +85,22 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play if ( ps->stats[STAT_ARMOR] >= upperBound ) { return qfalse; } -#else +# else if ( ps->stats[STAT_ARMOR] >= ps->stats[STAT_MAX_HEALTH] * 2 ) { return qfalse; } -#endif +# endif return qtrue; case IT_HEALTH: // small and mega healths will go over the max, otherwise // don't pick up if already at max -#ifdef MISSIONPACK +# ifdef MISSIONPACK if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) { upperBound = ps->stats[STAT_MAX_HEALTH]; } else -#endif +# endif if ( item->quantity == 5 || item->quantity == 100 ) { if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] * 2 ) { return qfalse; @@ -118,7 +116,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play case IT_POWERUP: return qtrue; // powerups are always picked up -#ifdef MISSIONPACK +# ifdef MISSIONPACK case IT_PERSISTANT_POWERUP: // can only hold one item at a time if ( ps->stats[STAT_PERSISTANT_POWERUP] ) { @@ -134,10 +132,10 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play } return qtrue; -#endif +# endif case IT_TEAM: // team items, such as flags -#ifdef MISSIONPACK +# ifdef MISSIONPACK if( gametype == GT_1FCTF ) { // neutral flag can always be picked up if( item->giTag == PW_NEUTRALFLAG ) { @@ -153,7 +151,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play } } } -#endif +# endif if( gametype == GT_CTF ) { // ent->modelindex2 is non-zero on items if they are dropped // we need to know this because we can pick up our dropped flag (and return it) @@ -171,11 +169,11 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play } } -#ifdef MISSIONPACK +# ifdef MISSIONPACK if( gametype == GT_HARVESTER ) { return qtrue; } -#endif +# endif return qfalse; case IT_HOLDABLE: @@ -188,11 +186,11 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play case IT_BAD: Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: IT_BAD" ); default: -#ifndef Q3_VM -#ifndef NDEBUG +# ifndef Q3_VM +# ifndef NDEBUG Com_Printf("BG_CanItemBeGrabbed: unknown enum %d\n", item->giType ); -#endif -#endif +# endif +# endif break; } @@ -297,8 +295,7 @@ void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t resu BG_TouchJumpPad ======================== */ -void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) { -} +void BG_TouchJumpPad(playerState_t *ps, entityState_t *jumppad) {} /* ======================== @@ -308,43 +305,41 @@ This is done after each set of usercmd_t on the server, and after local prediction on the client ======================== */ -void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap ) +void BG_PlayerStateToEntityState(playerState_t *ps, entityState_t *s, qboolean snap) { - if ( ps->pm_type == PM_NOCLIP ) { - s->eType = 0;//ET_INVISIBLE; - //} else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) { - // s->eType = 0;//ET_INVISIBLE; - } else { - s->eType = ET_PLAYER; - } + if (ps->pm_type == PM_NOCLIP) { + s->eType = 0; //ET_INVISIBLE; + //} else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) { + // s->eType = 0;//ET_INVISIBLE; + } else { + s->eType = ET_PLAYER; + } - s->number = ps->clientNum; + s->number = ps->clientNum; - VectorCopy( ps->origin, s->origin ); - if ( snap ) { - SnapVector( s->origin ); - } - // set the trDelta for flag direction - VectorCopy( ps->velocity, s->pos.trDelta ); + VectorCopy(ps->origin, s->origin); + if (snap) { + SnapVector(s->origin); + } + // set the trDelta for flag direction + VectorCopy(ps->velocity, s->pos.trDelta); - VectorCopy( ps->viewangles, s->angles ); - if ( snap ) { - SnapVector( s->angles ); - } + VectorCopy(ps->viewangles, s->angles); + if (snap) { + SnapVector(s->angles); + } - //s->angles2[YAW] = ps->movementDir; - s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number - // so corpses can also reference the proper config - //s->eFlags = ps->eFlags; - //if ( ps->stats[STAT_HEALTH] <= 0 ) { - // s->eFlags |= EF_DEAD; - //} else { - // s->eFlags &= ~EF_DEAD; - //} - - - s->groundEntityNum = ps->groundEntityNum; + //s->angles2[YAW] = ps->movementDir; + s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number + // so corpses can also reference the proper config + //s->eFlags = ps->eFlags; + //if ( ps->stats[STAT_HEALTH] <= 0 ) { + // s->eFlags |= EF_DEAD; + //} else { + // s->eFlags &= ~EF_DEAD; + //} + s->groundEntityNum = ps->groundEntityNum; } /* @@ -355,37 +350,35 @@ This is done after each set of usercmd_t on the server, and after local prediction on the client ======================== */ -void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap ) +void BG_PlayerStateToEntityStateExtraPolate(playerState_t *ps, entityState_t *s, int time, qboolean snap) { - if ( ps->pm_type == PM_NOCLIP ) { - s->eType = 0;//ET_INVISIBLE; - //} else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) { - // s->eType = 0;//ET_INVISIBLE; - } else { - s->eType = ET_PLAYER; - } + if (ps->pm_type == PM_NOCLIP) { + s->eType = 0; //ET_INVISIBLE; + //} else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) { + // s->eType = 0;//ET_INVISIBLE; + } else { + s->eType = ET_PLAYER; + } - s->number = ps->clientNum; + s->number = ps->clientNum; - VectorCopy( ps->origin, s->origin ); - if ( snap ) { - SnapVector( s->origin ); - } - // set the trDelta for flag direction and linear prediction - VectorCopy( ps->velocity, s->pos.trDelta ); - // set the time for linear prediction - s->pos.trTime = time; + VectorCopy(ps->origin, s->origin); + if (snap) { + SnapVector(s->origin); + } + // set the trDelta for flag direction and linear prediction + VectorCopy(ps->velocity, s->pos.trDelta); + // set the time for linear prediction + s->pos.trTime = time; - VectorCopy( ps->viewangles, s->angles ); - if ( snap ) { - SnapVector( s->angles ); - } - s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number - // so corpses can also reference the proper config - - - s->groundEntityNum = ps->groundEntityNum; + VectorCopy(ps->viewangles, s->angles); + if (snap) { + SnapVector(s->angles); + } + s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number + // so corpses can also reference the proper config + s->groundEntityNum = ps->groundEntityNum; } /* @@ -398,30 +391,30 @@ and after local prediction on the client */ int BG_MapCGMToProtocol(int protocol, int messageNumber) { - int newMessageNumber = messageNumber; + int newMessageNumber = messageNumber; - if (protocol >= PROTOCOL_MOHTA_MIN) { - // no need translation - return messageNumber; - } + if (protocol >= PROTOCOL_MOHTA_MIN) { + // no need translation + return messageNumber; + } - if (messageNumber > 40) { - // unsupported... - return messageNumber; - } + if (messageNumber > 40) { + // unsupported... + return messageNumber; + } - if (messageNumber >= 17) { - return messageNumber - 3; - } + if (messageNumber >= 17) { + return messageNumber - 3; + } - if (messageNumber == 15 || messageNumber == 16) { - // return explosion effect number 2 - return 14; - } + if (messageNumber == 15 || messageNumber == 16) { + // return explosion effect number 2 + return 14; + } - if (messageNumber > 10) { - return messageNumber - 1; - } + if (messageNumber > 10) { + return messageNumber - 1; + } - return newMessageNumber; + return newMessageNumber; } \ No newline at end of file diff --git a/code/fgame/bg_pmove.cpp b/code/fgame/bg_pmove.cpp index 7e152df3..613bc78b 100644 --- a/code/fgame/bg_pmove.cpp +++ b/code/fgame/bg_pmove.cpp @@ -1,6 +1,7 @@ /* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2024 the OpenMoHAA team This file is part of Quake III Arena source code. @@ -27,28 +28,31 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "bg_public.h" #include "bg_local.h" -pmove_t *pm; -pml_t pml; +pmove_t *pm; +pml_t pml; // movement parameters -float pm_stopspeed = 50.0f; -float pm_duckScale = 0.25f; -float pm_swimScale = 1.0f; -float pm_wadeScale = 0.70f; +float pm_stopspeed = 50.0f; +float pm_duckScale = 0.25f; +float pm_swimScale = 1.0f; +float pm_wadeScale = 0.70f; -float pm_accelerate = 8.0f; -float pm_airaccelerate = 1.0f; -float pm_wateraccelerate = 8.0f; +float pm_accelerate = 8.0f; +float pm_airaccelerate = 1.0f; +float pm_wateraccelerate = 8.0f; -float pm_friction = 6.0f; -float pm_waterfriction = 2.0f; -float pm_slipperyfriction = 0.25f; -float pm_strafespeed = 0.85f; -float pm_backspeed = 0.80f; -float pm_flightfriction = 3.0f; -float PM_NOCLIPfriction = 5.0f; +float pm_friction = 6.0f; +float pm_waterfriction = 2.0f; +float pm_slipperyfriction = 0.25f; +float pm_strafespeed = 0.85f; +float pm_backspeed = 0.80f; +float pm_flightfriction = 3.0f; +float PM_NOCLIPfriction = 5.0f; -int c_pmove = 0; +const vec3_t MINS = {-15, -15, 0}; +const vec3_t MAXS = {15, 15, 94}; + +int c_pmove = 0; /* =============== @@ -56,36 +60,35 @@ PM_AddEvent =============== */ -void PM_AddEvent( int newEvent ) { - -} +void PM_AddEvent(int newEvent) {} /* =============== PM_AddTouchEnt =============== */ -void PM_AddTouchEnt( int entityNum ) { - int i; +void PM_AddTouchEnt(int entityNum) +{ + int i; - if ( entityNum == ENTITYNUM_WORLD ) { - return; - } + if (entityNum == ENTITYNUM_WORLD) { + return; + } - if ( pm->numtouch == MAXTOUCH ) { - return; - } + if (pm->numtouch == MAXTOUCH) { + return; + } - // see if it is already added - for ( i = 0 ; i < pm->numtouch ; i++ ) { - if ( pm->touchents[ i ] == entityNum ) { - return; - } - } + // see if it is already added + for (i = 0; i < pm->numtouch; i++) { + if (pm->touchents[i] == entityNum) { + return; + } + } - // add it - pm->touchents[pm->numtouch] = entityNum; - pm->numtouch++; + // add it + pm->touchents[pm->numtouch] = entityNum; + pm->numtouch++; } /* @@ -93,25 +96,15 @@ void PM_AddTouchEnt( int entityNum ) { PM_StartTorsoAnim =================== */ -static void PM_StartTorsoAnim( int anim ) { +static void PM_StartTorsoAnim(int anim) {} -} -static void PM_StartLegsAnim( int anim ) { +static void PM_StartLegsAnim(int anim) {} -} +static void PM_ContinueLegsAnim(int anim) {} -static void PM_ContinueLegsAnim( int anim ) { - -} - -static void PM_ContinueTorsoAnim( int anim ) { - -} - -static void PM_ForceLegsAnim( int anim ) { - -} +static void PM_ContinueTorsoAnim(int anim) {} +static void PM_ForceLegsAnim(int anim) {} /* ================== @@ -120,48 +113,44 @@ PM_ClipVelocity Slide off of the impacting surface ================== */ -void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce ) +void PM_ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce) { - float backoff; - float dir_z; - float normal2[ 3 ]; + float backoff; + float dir_z; + float normal2[3]; - if( normal[ 2 ] >= pm_wadeScale ) - { - if( in[ 0 ] == 0.0f && in[ 1 ] == 0.0f ) - { - VectorClear( out ); - return; - } + if (normal[2] >= pm_wadeScale) { + if (in[0] == 0.0f && in[1] == 0.0f) { + VectorClear(out); + return; + } - normal2[ 0 ] = in[ 0 ] * DotProduct2D( in, normal ); - normal2[ 1 ] = in[ 1 ] * DotProduct2D( in, normal ); - normal2[ 2 ] = normal[ 2 ] * DotProduct2D( in, in ); + normal2[0] = in[0] * DotProduct2D(in, normal); + normal2[1] = in[1] * DotProduct2D(in, normal); + normal2[2] = normal[2] * DotProduct2D(in, in); - VectorNormalize( normal2 ); + VectorNormalize(normal2); - dir_z = -normal2[ 2 ]; + dir_z = -normal2[2]; - out[ 0 ] = in[ 0 ]; - out[ 1 ] = in[ 1 ]; - out[ 2 ] = DotProduct2D( in, normal2 ) / dir_z; - } - else - { - backoff = DotProduct( in, normal ); + out[0] = in[0]; + out[1] = in[1]; + out[2] = DotProduct2D(in, normal2) / dir_z; + } else { + backoff = DotProduct(in, normal); - if( backoff < 0 ) - backoff *= overbounce; - else - backoff /= overbounce; + if (backoff < 0) { + backoff *= overbounce; + } else { + backoff /= overbounce; + } - out[ 0 ] = in[ 0 ] - normal[ 0 ] * backoff; - out[ 1 ] = in[ 1 ] - normal[ 1 ] * backoff; - out[ 2 ] = in[ 2 ] - normal[ 2 ] * backoff; - } + out[0] = in[0] - normal[0] * backoff; + out[1] = in[1] - normal[1] * backoff; + out[2] = in[2] - normal[2] * backoff; + } } - /* ================== PM_Friction @@ -169,76 +158,65 @@ PM_Friction Handles both ground friction and water friction ================== */ -static void PM_Friction( void ) { - vec3_t vec; - float *vel; - float speed, newspeed, control; - float drop; +static void PM_Friction(void) +{ + vec3_t vec; + float *vel; + float speed, newspeed, control; + float drop; - vel = pm->ps->velocity; + vel = pm->ps->velocity; - VectorCopy( vel, vec ); - if( pml.walking ) - { - // ignore slope movement - vec[ 2 ] = 0; - } + VectorCopy(vel, vec); + if (pml.walking) { + // ignore slope movement + vec[2] = 0; + } - speed = VectorLength( vec ); - if( speed < 1 ) - { - // allow sinking underwater - vel[ 0 ] = 0; - vel[ 1 ] = 0; + speed = VectorLength(vec); + if (speed < 1) { + // allow sinking underwater + vel[0] = 0; + vel[1] = 0; - return; - } + return; + } - drop = 0; + drop = 0; - if( pml.walking ) - { - control = ( speed < pm_stopspeed ) ? pm_stopspeed : speed; + if (pml.walking) { + control = (speed < pm_stopspeed) ? pm_stopspeed : speed; - // if getting knocked back, no friction - if( pml.groundTrace.surfaceFlags & SURF_SLICK ) - { - drop += control * pm_slipperyfriction * pml.frametime; - } - else - { - drop += control * pm_friction * pml.frametime; - } - } + // if getting knocked back, no friction + if (pml.groundTrace.surfaceFlags & SURF_SLICK) { + drop += control * pm_slipperyfriction * pml.frametime; + } else { + drop += control * pm_friction * pml.frametime; + } + } - // apply water friction even if just wading - if( pm->waterlevel ) - { - if( pm->watertype & CONTENTS_SLIME ) - { - drop += speed * pm_waterfriction * 5 * pm->waterlevel * pml.frametime; - } - else - { - drop += speed * pm_waterfriction * pm->waterlevel * pml.frametime; - } - } + // apply water friction even if just wading + if (pm->waterlevel) { + if (pm->watertype & CONTENTS_SLIME) { + drop += speed * pm_waterfriction * 5 * pm->waterlevel * pml.frametime; + } else { + drop += speed * pm_waterfriction * pm->waterlevel * pml.frametime; + } + } - // scale the velocity - newspeed = speed - drop; - if( newspeed < 0 ) - { - newspeed = 0; - } + // scale the velocity + newspeed = speed - drop; + if (newspeed < 0) { + newspeed = 0; + } - newspeed /= speed; + newspeed /= speed; - vel[ 0 ] = vel[ 0 ] * newspeed; - vel[ 1 ] = vel[ 1 ] * newspeed; - vel[ 2 ] = vel[ 2 ] * newspeed; + vel[0] = vel[0] * newspeed; + vel[1] = vel[1] * newspeed; + vel[2] = vel[2] * newspeed; } - /* ============== PM_Accelerate @@ -246,27 +224,25 @@ PM_Accelerate Handles user intended acceleration ============== */ -static void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel ) +static void PM_Accelerate(vec3_t wishdir, float wishspeed, float accel) { - vec3_t wishVelocity; - vec3_t pushDir; - float pushLen; - float canPush; + vec3_t wishVelocity; + vec3_t pushDir; + float pushLen; + float canPush; - VectorScale( wishdir, wishspeed, wishVelocity ); - VectorSubtract( wishVelocity, pm->ps->velocity, pushDir ); - pushLen = VectorNormalize( pushDir ); + VectorScale(wishdir, wishspeed, wishVelocity); + VectorSubtract(wishVelocity, pm->ps->velocity, pushDir); + pushLen = VectorNormalize(pushDir); - canPush = accel*pml.frametime*wishspeed; - if (canPush > pushLen) { - canPush = pushLen; - } + canPush = accel * pml.frametime * wishspeed; + if (canPush > pushLen) { + canPush = pushLen; + } - VectorMA( pm->ps->velocity, canPush, pushDir, pm->ps->velocity ); + VectorMA(pm->ps->velocity, canPush, pushDir, pm->ps->velocity); } - - /* ============ PM_CmdScale @@ -276,30 +252,30 @@ This allows the clients to use axial -127 to 127 values for all directions without getting a sqrt(2) distortion in speed. ============ */ -static float PM_CmdScale( usercmd_t *cmd ) { - int max; - float total; - float scale; - float fmove, smove; +static float PM_CmdScale(usercmd_t *cmd) +{ + int max; + float total; + float scale; + float fmove, smove; - PM_GetMove( &fmove, &smove ); + PM_GetMove(&fmove, &smove); - max = fabs( fmove ); - if(fabs( smove ) > max ) { - max = fabs( smove ); - } - if (fabs( cmd->upmove ) > max ) { - max = fabs( cmd->upmove ); - } - if ( !max ) { - return 0; - } + max = fabs(fmove); + if (fabs(smove) > max) { + max = fabs(smove); + } + if (fabs(cmd->upmove) > max) { + max = fabs(cmd->upmove); + } + if (!max) { + return 0; + } - total = sqrt( ( float )( fmove * fmove - + smove * smove + cmd->upmove * cmd->upmove ) ); - scale = ( float )pm->ps->speed * max / ( 127.0 * total ); + total = sqrt((float)(fmove * fmove + smove * smove + cmd->upmove * cmd->upmove)); + scale = (float)pm->ps->speed * max / (127.0 * total); - return scale; + return scale; } //============================================================================ @@ -310,33 +286,29 @@ PM_CheckTerminalVelocity ============= */ #define TERMINAL_VELOCITY 1200 -void PM_CheckTerminalVelocity - ( - void - ) + +void PM_CheckTerminalVelocity(void) { - float oldspeed; - float speed; + float oldspeed; + float speed; - // - // how fast were we falling - // - oldspeed = -pml.previous_velocity[ 2 ]; + // + // how fast were we falling + // + oldspeed = -pml.previous_velocity[2]; - // - // how fast are we falling - // - speed = -pm->ps->velocity[ 2 ]; + // + // how fast are we falling + // + speed = -pm->ps->velocity[2]; - if( speed <= 0 ) - { - return; - } + if (speed <= 0) { + return; + } - if( ( oldspeed <= TERMINAL_VELOCITY ) && ( speed > TERMINAL_VELOCITY ) ) - { - pm->pmoveEvent = EV_TERMINAL_VELOCITY; - } + if ((oldspeed <= TERMINAL_VELOCITY) && (speed > TERMINAL_VELOCITY)) { + pm->pmoveEvent = EV_TERMINAL_VELOCITY; + } } /* @@ -396,18 +368,13 @@ PM_GetMove =================== */ -void PM_GetMove - ( - float *pfForward, - float *pfRight - ) +void PM_GetMove(float *pfForward, float *pfRight) { - *pfForward = pm->cmd.forwardmove; - if( *pfForward < 0 ) - { - *pfForward *= pm_backspeed; - } - *pfRight = pm->cmd.rightmove * pm_strafespeed; + *pfForward = pm->cmd.forwardmove; + if (*pfForward < 0) { + *pfForward *= pm_backspeed; + } + *pfRight = pm->cmd.rightmove * pm_strafespeed; } /* @@ -416,184 +383,161 @@ PM_AirMove =================== */ -static void PM_AirMove( void ) +static void PM_AirMove(void) { - vec3_t wishvel; - float fmove; - float smove; - vec3_t wishdir; - float wishspeed; - float scale; - usercmd_t cmd; + vec3_t wishvel; + float fmove; + float smove; + vec3_t wishdir; + float wishspeed; + float scale; + usercmd_t cmd; - PM_GetMove( &fmove, &smove ); + PM_GetMove(&fmove, &smove); - pm->ps->pm_time = 0; + pm->ps->pm_time = 0; - cmd = pm->cmd; - scale = PM_CmdScale( &cmd ); + cmd = pm->cmd; + scale = PM_CmdScale(&cmd); - wishvel[ 0 ] = pml.flat_forward[ 0 ] * fmove - pml.flat_left[ 0 ] * smove; - wishvel[ 1 ] = pml.flat_forward[ 1 ] * fmove - pml.flat_left[ 1 ] * smove; - wishvel[ 2 ] = 0; + wishvel[0] = pml.flat_forward[0] * fmove - pml.flat_left[0] * smove; + wishvel[1] = pml.flat_forward[1] * fmove - pml.flat_left[1] * smove; + wishvel[2] = 0; - VectorCopy( wishvel, wishdir ); - wishspeed = VectorNormalize( wishdir ); - wishspeed *= scale; + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + wishspeed *= scale; - // not on ground, so little effect on velocity - PM_Accelerate( wishdir, wishspeed, pm_airaccelerate ); + // not on ground, so little effect on velocity + PM_Accelerate(wishdir, wishspeed, pm_airaccelerate); - // we may have a ground plane that is very steep, even - // though we don't have a groundentity - // slide along the steep plane - if( pml.groundPlane ) - { - PM_ClipVelocity( pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP ); - } + // we may have a ground plane that is very steep, even + // though we don't have a groundentity + // slide along the steep plane + if (pml.groundPlane) { + PM_ClipVelocity(pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP); + } - PM_StepSlideMove( qtrue ); + PM_StepSlideMove(qtrue); - PM_CheckTerminalVelocity(); + PM_CheckTerminalVelocity(); } -static vec3_t min3x3 = { -8, 0, 0 }; -static vec3_t max3x3 = { 4, 4, 8 }; -static vec3_t base_rightfoot_pos = { -5.25301f, -3.10885f, 0 }; -static vec3_t base_leftfoot_pos = { -0.123711f, 10.4893f, 0 }; +static vec3_t min3x3 = {-8, 0, 0}; +static vec3_t max3x3 = {4, 4, 8}; +static vec3_t base_rightfoot_pos = {-5.25301f, -3.10885f, 0}; +static vec3_t base_leftfoot_pos = {-0.123711f, 10.4893f, 0}; -qboolean PM_FeetOnGround - ( - vec3_t pos - ) +qboolean PM_FeetOnGround(vec3_t pos) { - vec3_t start; - vec3_t end; - trace_t trace; + vec3_t start; + vec3_t end; + trace_t trace; - VectorCopy( pos, start ); - VectorCopy( pos, end ); - end[ 2 ] -= 16.01f; + VectorCopy(pos, start); + VectorCopy(pos, end); + end[2] -= 16.01f; - pm->trace( &trace, start, min3x3, max3x3, end, pm->ps->clientNum, pm->tracemask, true, false ); + pm->trace(&trace, start, min3x3, max3x3, end, pm->ps->clientNum, pm->tracemask, true, false); - return trace.fraction != 1.0f; + return trace.fraction != 1.0f; } -qboolean PM_FindBestFallPos - ( - vec3_t pos, - vec3_t bestdir - ) -{ - trace_t trace; - vec3_t ang; - vec3_t dir; - vec3_t start; - vec3_t end; - vec3_t move; - int i; - qboolean set; - float radius; +qboolean PM_FindBestFallPos(vec3_t pos, vec3_t bestdir) +{ + trace_t trace; + vec3_t ang; + vec3_t dir; + vec3_t start; + vec3_t end; + vec3_t move; + int i; + qboolean set; + float radius; - VectorClear( bestdir ); + VectorClear(bestdir); - set = qfalse; + set = qfalse; - radius = pm->maxs[ 0 ] - pm->mins[ 0 ] + 1.0f; + radius = pm->maxs[0] - pm->mins[0] + 1.0f; - VectorCopy( pos, start ); - start[ 2 ] -= 16.1f; + VectorCopy(pos, start); + start[2] -= 16.1f; - VectorSet( ang, 0, pm->ps->viewangles[ 1 ], 0 ); - for( i = 0; i < 16; i++, ang[ 1 ] += 22.5f ) - { - AngleVectorsLeft( ang, dir, NULL, NULL ); - VectorMA( pos, radius, dir, move ); + VectorSet(ang, 0, pm->ps->viewangles[1], 0); + for (i = 0; i < 16; i++, ang[1] += 22.5f) { + AngleVectorsLeft(ang, dir, NULL, NULL); + VectorMA(pos, radius, dir, move); - pm->trace( &trace, pos, pm->mins, pm->maxs, move, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); + pm->trace(&trace, pos, pm->mins, pm->maxs, move, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); - VectorCopy( trace.endpos, end ); - end[ 2 ] = start[ 2 ]; + VectorCopy(trace.endpos, end); + end[2] = start[2]; - pm->trace( &trace, trace.endpos, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - if( trace.fraction == 1.0f ) - { - VectorCopy( trace.endpos, end ); - pm->trace( &trace, end, pm->mins, pm->maxs, start, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); + pm->trace(&trace, trace.endpos, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + if (trace.fraction == 1.0f) { + VectorCopy(trace.endpos, end); + pm->trace(&trace, end, pm->mins, pm->maxs, start, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); - if( trace.fraction < 1.0f ) - { - VectorAdd( bestdir, trace.plane.normal, bestdir ); - set = qtrue; - } - } - } + if (trace.fraction < 1.0f) { + VectorAdd(bestdir, trace.plane.normal, bestdir); + set = qtrue; + } + } + } - if( !set || !VectorNormalize( bestdir ) ) - { - return qfalse; - } + if (!set || !VectorNormalize(bestdir)) { + return qfalse; + } - return qtrue; + return qtrue; } -void PM_CheckFeet - ( - vec3_t vWishdir - ) +void PM_CheckFeet(vec3_t vWishdir) { - vec3_t temp; - trace_t trace; + vec3_t temp; + trace_t trace; - if( pm->stepped ) - { - pm->ps->feetfalling = 0; - return; - } + if (pm->stepped) { + pm->ps->feetfalling = 0; + return; + } - if( !pm->ps->walking ) - { - return; - } + if (!pm->ps->walking) { + return; + } - VectorMA( pm->ps->origin, 0.2f, pm->ps->velocity, temp ); - temp[ 2 ] = pm->ps->origin[ 2 ] + 2; - if( PM_FeetOnGround( pm->ps->origin ) || PM_FeetOnGround( temp ) ) - { - pm->ps->feetfalling = 0; - return; - } + VectorMA(pm->ps->origin, 0.2f, pm->ps->velocity, temp); + temp[2] = pm->ps->origin[2] + 2; + if (PM_FeetOnGround(pm->ps->origin) || PM_FeetOnGround(temp)) { + pm->ps->feetfalling = 0; + return; + } - if( pm->ps->feetfalling > 0 ) - { - pm->ps->feetfalling--; - } + if (pm->ps->feetfalling > 0) { + pm->ps->feetfalling--; + } - if( !pm->ps->feetfalling ) - { - if( !PM_FindBestFallPos( pm->ps->origin, pm->ps->falldir ) ) { - return; - } + if (!pm->ps->feetfalling) { + if (!PM_FindBestFallPos(pm->ps->origin, pm->ps->falldir)) { + return; + } - pm->ps->feetfalling = 5; - } + pm->ps->feetfalling = 5; + } - VectorMA( pm->ps->origin, 15.0f * pml.frametime, pm->ps->falldir, temp ); + VectorMA(pm->ps->origin, 15.0f * pml.frametime, pm->ps->falldir, temp); - pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, temp, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - if( trace.fraction == 0 ) - { - pm->ps->feetfalling = 0; - return; - } + pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, temp, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + if (trace.fraction == 0) { + pm->ps->feetfalling = 0; + return; + } - if( ( vWishdir[ 0 ] == 0.0f && vWishdir[ 1 ] == 0.0f ) || - DotProduct( vWishdir, pm->ps->falldir ) > 0.0f ) - { - pm->ps->walking = qfalse; - VectorCopy( trace.endpos, pm->ps->origin ); - } + if ((vWishdir[0] == 0.0f && vWishdir[1] == 0.0f) || DotProduct(vWishdir, pm->ps->falldir) > 0.0f) { + pm->ps->walking = qfalse; + VectorCopy(trace.endpos, pm->ps->origin); + } } /* @@ -602,90 +546,81 @@ PM_WalkMove =================== */ -static void PM_WalkMove( void ) { - int i; - vec3_t wishvel; - float fmove, smove; - vec3_t wishdir; - float wishspeed; - float scale; - usercmd_t cmd; - float accelerate; +static void PM_WalkMove(void) +{ + int i; + vec3_t wishvel; + float fmove, smove; + vec3_t wishdir; + float wishspeed; + float scale; + usercmd_t cmd; + float accelerate; - PM_Friction(); + PM_Friction(); - PM_GetMove( &fmove, &smove ); + PM_GetMove(&fmove, &smove); - cmd = pm->cmd; - scale = PM_CmdScale( &cmd ); + cmd = pm->cmd; + scale = PM_CmdScale(&cmd); - if( ( pm->cmd.buttons & BUTTON_RUN ) && fmove && !smove ) - { - pm->ps->pm_time += pml.msec; - } - else - { - pm->ps->pm_time = 0; - } + if ((pm->cmd.buttons & BUTTON_RUN) && fmove && !smove) { + pm->ps->pm_time += pml.msec; + } else { + pm->ps->pm_time = 0; + } - // project the forward and right directions onto the ground plane - PM_ClipVelocity( pml.flat_forward, pml.groundTrace.plane.normal, pml.flat_forward, OVERCLIP ); - PM_ClipVelocity( pml.flat_left, pml.groundTrace.plane.normal, pml.flat_left, OVERCLIP ); - // - VectorNormalize( pml.flat_forward ); - VectorNormalize( pml.flat_left ); + // project the forward and right directions onto the ground plane + PM_ClipVelocity(pml.flat_forward, pml.groundTrace.plane.normal, pml.flat_forward, OVERCLIP); + PM_ClipVelocity(pml.flat_left, pml.groundTrace.plane.normal, pml.flat_left, OVERCLIP); + // + VectorNormalize(pml.flat_forward); + VectorNormalize(pml.flat_left); - for( i = 0; i < 3; i++ ) - { - wishvel[ i ] = pml.flat_forward[ i ] * fmove - pml.flat_left[ i ] * smove; - } + for (i = 0; i < 3; i++) { + wishvel[i] = pml.flat_forward[i] * fmove - pml.flat_left[i] * smove; + } - VectorCopy( wishvel, wishdir ); - wishspeed = VectorNormalize( wishdir ); - wishspeed *= scale; + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + wishspeed *= scale; - // clamp the speed lower if wading or walking on the bottom - if( pm->waterlevel ) - { - float waterScale; + // clamp the speed lower if wading or walking on the bottom + if (pm->waterlevel) { + float waterScale; - if( pm->waterlevel == 1.0f ) - { - waterScale = 0.80f; - } - else - { - waterScale = 0.5f; - } + if (pm->waterlevel == 1.0f) { + waterScale = 0.80f; + } else { + waterScale = 0.5f; + } - if( wishspeed > pm->ps->speed * waterScale ) { - wishspeed = pm->ps->speed * waterScale; - } - } + if (wishspeed > pm->ps->speed * waterScale) { + wishspeed = pm->ps->speed * waterScale; + } + } - if( pml.groundTrace.surfaceFlags & SURF_SLICK ) { - accelerate = pm_airaccelerate; - } else { - accelerate = pm_accelerate; - } + if (pml.groundTrace.surfaceFlags & SURF_SLICK) { + accelerate = pm_airaccelerate; + } else { + accelerate = pm_accelerate; + } - PM_Accelerate( wishdir, wishspeed, accelerate ); + PM_Accelerate(wishdir, wishspeed, accelerate); - if( pml.groundTrace.surfaceFlags & SURF_SLICK ) { - pm->ps->velocity[ 2 ] -= pm->ps->gravity * pml.frametime; - } + if (pml.groundTrace.surfaceFlags & SURF_SLICK) { + pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime; + } - // slide along the ground plane - PM_ClipVelocity( pm->ps->velocity, pml.groundTrace.plane.normal, - pm->ps->velocity, OVERCLIP ); + // slide along the ground plane + PM_ClipVelocity(pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP); - // don't do anything if standing still - if( pm->ps->velocity[ 0 ] || pm->ps->velocity[ 1 ] ) - { - PM_StepSlideMove( qtrue ); - } + // don't do anything if standing still + if (pm->ps->velocity[0] || pm->ps->velocity[1]) { + PM_StepSlideMove(qtrue); + } - PM_CheckFeet( wishdir ); + PM_CheckFeet(wishdir); } /* @@ -693,100 +628,105 @@ static void PM_WalkMove( void ) { PM_DeadMove ============== */ -static void PM_DeadMove( void ) { - float forward; +static void PM_DeadMove(void) +{ + float forward; - if ( !pml.walking ) { - return; - } + if (!pml.walking) { + return; + } - // extra friction + // extra friction - forward = VectorLength (pm->ps->velocity); - forward -= 20; - if ( forward <= 0 ) { - VectorClear (pm->ps->velocity); - } else { - VectorNormalize (pm->ps->velocity); - VectorScale (pm->ps->velocity, forward, pm->ps->velocity); - } + forward = VectorLength(pm->ps->velocity); + forward -= 20; + if (forward <= 0) { + VectorClear(pm->ps->velocity); + } else { + VectorNormalize(pm->ps->velocity); + VectorScale(pm->ps->velocity, forward, pm->ps->velocity); + } } - /* =============== PM_NoclipMove =============== */ -static void PM_NoclipMove( void ) +static void PM_NoclipMove(void) { - float speed; - float drop; - float friction; - float control; - float newspeed; - int i; - vec3_t wishvel; - float fmove; - float smove; - vec3_t wishdir; - float wishspeed; - float scale; + float speed; + float drop; + float friction; + float control; + float newspeed; + int i; + vec3_t wishvel; + float fmove; + float smove; + vec3_t wishdir; + float wishspeed; + float scale; - pm->ps->viewheight = DEFAULT_VIEWHEIGHT; - pm->ps->groundEntityNum = ENTITYNUM_NONE; + pm->ps->viewheight = DEFAULT_VIEWHEIGHT; + pm->ps->groundEntityNum = ENTITYNUM_NONE; - // friction + // friction - speed = VectorLength( pm->ps->velocity ); - if( speed < 1 ) - { - VectorCopy( vec3_origin, pm->ps->velocity ); - } - else - { - drop = 0; + speed = VectorLength(pm->ps->velocity); + if (speed < 1) { + VectorCopy(vec3_origin, pm->ps->velocity); + } else { + drop = 0; - // extra friction - friction = pm_friction * 1.5; + // extra friction + friction = pm_friction * 1.5; - control = speed < pm_stopspeed ? pm_stopspeed : speed; - drop += control * friction * pml.frametime; + control = speed < pm_stopspeed ? pm_stopspeed : speed; + drop += control * friction * pml.frametime; - // scale the velocity - newspeed = speed - drop; - if( newspeed < 0 ) - { - newspeed = 0; - } - newspeed /= speed; + // scale the velocity + newspeed = speed - drop; + if (newspeed < 0) { + newspeed = 0; + } + newspeed /= speed; - VectorScale( pm->ps->velocity, newspeed, pm->ps->velocity ); - } + VectorScale(pm->ps->velocity, newspeed, pm->ps->velocity); + } - // accelerate - // allow the player to move twice as fast in noclip - scale = PM_CmdScale( &pm->cmd ) * 2; + // accelerate + // allow the player to move twice as fast in noclip + scale = PM_CmdScale(&pm->cmd) * 2; - PM_GetMove( &fmove, &smove ); + PM_GetMove(&fmove, &smove); - pm->ps->pm_time = 0; + pm->ps->pm_time = 0; - for( i = 0; i < 3; i++ ) - { - wishvel[ i ] = pml.flat_forward[ i ] * fmove - pml.flat_left[ i ] * smove; - } + for (i = 0; i < 3; i++) { + wishvel[i] = pml.flat_forward[i] * fmove - pml.flat_left[i] * smove; + } - wishvel[ 2 ] += pm->cmd.upmove; + wishvel[2] += pm->cmd.upmove; - VectorCopy( wishvel, wishdir ); - wishspeed = VectorNormalize( wishdir ); - wishspeed *= scale; + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + wishspeed *= scale; - PM_Accelerate( wishdir, wishspeed, pm_accelerate ); + PM_Accelerate(wishdir, wishspeed, pm_accelerate); - // move - VectorMA( pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin ); + // move + VectorMA(pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin); + + // Added in 2.0 + // If the player is out of bounds in noclip mode, + // teleport it back to the (0,0,0) coordinates + for (i = 0; i < 3; i++) { + if (fabs(pm->ps->origin[i]) >= MAX_MAP_BOUNDS - 512) { + VectorClear(pm->ps->origin); + break; + } + } } //============================================================================ @@ -798,74 +738,62 @@ PM_CrashLand Check for hard landings that generate sound events ================= */ -static void PM_CrashLand( void ) +static void PM_CrashLand(void) { - float delta; - float dist; - float vel; - float acc; - float t; - float a, b, c, den; + float delta; + float dist; + float vel; + float acc; + float t; + float a, b, c, den; - // calculate the exact velocity on landing - dist = pm->ps->origin[ 2 ] - pml.previous_origin[ 2 ]; - vel = pml.previous_velocity[ 2 ]; - acc = -pm->ps->gravity; + // calculate the exact velocity on landing + dist = pm->ps->origin[2] - pml.previous_origin[2]; + vel = pml.previous_velocity[2]; + acc = -pm->ps->gravity; - a = acc / 2; - b = vel; - c = -dist; + a = acc / 2; + b = vel; + c = -dist; - den = b * b - 4 * a * c; - if( den < 0 ) - { - return; - } + den = b * b - 4 * a * c; + if (den < 0) { + return; + } - //t = ( -b - sqrt( den ) ) / ( 2 * a ); - t = sqrt( den ) + vel; + //t = ( -b - sqrt( den ) ) / ( 2 * a ); + t = sqrt(den) + vel; - //delta = vel + t * acc; - delta = vel - t; - delta = delta * delta * 0.0001; + //delta = vel + t * acc; + delta = vel - t; + delta = delta * delta * 0.0001; - // reduce falling damage if there is standing water - if( pm->waterlevel == 2 ) - { - delta *= 0.25f; - } + // reduce falling damage if there is standing water + if (pm->waterlevel == 2) { + delta *= 0.25f; + } - if( pm->waterlevel == 1 ) - { - delta *= 0.5f; - } + if (pm->waterlevel == 1) { + delta *= 0.5f; + } - if( delta < 1 ) - { - return; - } + if (delta < 1) { + return; + } - // SURF_NODAMAGE is used for bounce pads where you don't ever - // want to take damage or play a crunch sound - if( !( pml.groundTrace.surfaceFlags & SURF_NODAMAGE ) ) - { - if( delta > 100 ) - { - pm->pmoveEvent = EV_FALL_FATAL; - } - else if( delta > 80 ) - { - pm->pmoveEvent = EV_FALL_FAR; - } - else if( delta > 40 ) - { - pm->pmoveEvent = EV_FALL_MEDIUM; - } - else if( delta > 20 ) - { - pm->pmoveEvent = EV_FALL_SHORT; - } - } + // SURF_NODAMAGE is used for bounce pads where you don't ever + // want to take damage or play a crunch sound + if (!(pml.groundTrace.surfaceFlags & SURF_NODAMAGE)) { + if (delta > 100) { + pm->pmoveEvent = EV_FALL_FATAL; + } else if (delta > 80) { + pm->pmoveEvent = EV_FALL_FAR; + } else if (delta > 40) { + pm->pmoveEvent = EV_FALL_MEDIUM; + } else if (delta > 20) { + pm->pmoveEvent = EV_FALL_SHORT; + } + } } /* @@ -889,43 +817,45 @@ void PM_CheckStuck(void) { PM_CorrectAllSolid ============= */ -static int PM_CorrectAllSolid( trace_t *trace ) +static int PM_CorrectAllSolid(trace_t *trace) { - int i, j, k; - vec3_t point; + int i, j, k; + vec3_t point; - if ( pm->debugLevel ) { - Com_Printf("%i:allsolid\n", c_pmove); - } + if (pm->debugLevel) { + Com_Printf("%i:allsolid\n", c_pmove); + } - // jitter around - for (i = -1; i <= 1; i++) { - for (j = -1; j <= 1; j++) { - for (k = -1; k <= 1; k++) { - VectorCopy(pm->ps->origin, point); - point[0] += (float) i; - point[1] += (float) j; - point[2] += (float) k; - pm->trace( trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, false ); - if ( !trace->allsolid && !trace->startsolid ) { - point[0] = pm->ps->origin[0]; - point[1] = pm->ps->origin[1]; - point[2] = pm->ps->origin[2] - 0.25; + // jitter around + for (i = -1; i <= 1; i++) { + for (j = -1; j <= 1; j++) { + for (k = -1; k <= 1; k++) { + VectorCopy(pm->ps->origin, point); + point[0] += (float)i; + point[1] += (float)j; + point[2] += (float)k; + pm->trace(trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, false); + if (!trace->allsolid && !trace->startsolid) { + point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] - 0.25; - pm->trace( trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, false ); - pml.groundTrace = *trace; - pm->ps->groundTrace = *trace; - return qtrue; - } - } - } - } + pm->trace( + trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, false + ); + pml.groundTrace = *trace; + pm->ps->groundTrace = *trace; + return qtrue; + } + } + } + } - //pm->ps->groundEntityNum = ENTITYNUM_NONE; - //pml.groundPlane = qfalse; - //pml.walking = qfalse; + //pm->ps->groundEntityNum = ENTITYNUM_NONE; + //pml.groundPlane = qfalse; + //pml.walking = qfalse; - return qfalse; + return qfalse; } /* @@ -933,146 +863,140 @@ static int PM_CorrectAllSolid( trace_t *trace ) PM_GroundTrace ============= */ -static void PM_GroundTrace( void ) { - vec3_t point; - trace_t trace; +static void PM_GroundTrace(void) +{ + vec3_t point; + trace_t trace; - point[ 0 ] = pm->ps->origin[ 0 ]; - point[ 1 ] = pm->ps->origin[ 1 ]; - point[ 2 ] = pm->ps->origin[ 2 ] - 0.25f; + point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] - 0.25f; - pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); + pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); - pml.groundTrace = trace; - pm->ps->groundTrace = trace; + pml.groundTrace = trace; + pm->ps->groundTrace = trace; - // do something corrective if the trace starts in a solid... - if ( trace.allsolid || trace.startsolid ) - { - if( !PM_CorrectAllSolid( &trace ) ) { - trace.fraction = 1.0f; - } - } + // do something corrective if the trace starts in a solid... + if (trace.allsolid || trace.startsolid) { + if (!PM_CorrectAllSolid(&trace)) { + trace.fraction = 1.0f; + } + } - // if the trace didn't hit anything, we are in free fall - if ( trace.fraction == 1.0 ) - { - pm->ps->groundEntityNum = ENTITYNUM_NONE; - pml.groundPlane = qfalse; - pml.walking = qfalse; + // if the trace didn't hit anything, we are in free fall + if (trace.fraction == 1.0) { + pm->ps->groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = qfalse; + pml.walking = qfalse; - pm->ps->walking = pml.walking; - pm->ps->groundPlane = pml.groundPlane; - return; - } + pm->ps->walking = pml.walking; + pm->ps->groundPlane = pml.groundPlane; + return; + } - // check if getting thrown off the ground - if( pm->ps->velocity[ 2 ] > 0.0f && DotProduct( pm->ps->velocity, trace.plane.normal ) > 150.0f ) - { - if ( pm->debugLevel ) { - Com_Printf("%i:kickoff\n", c_pmove); - } + // check if getting thrown off the ground + if (pm->ps->velocity[2] > 0.0f && DotProduct(pm->ps->velocity, trace.plane.normal) > 150.0f) { + if (pm->debugLevel) { + Com_Printf("%i:kickoff\n", c_pmove); + } - pm->ps->groundEntityNum = ENTITYNUM_NONE; - pml.groundPlane = qfalse; - pml.walking = qfalse; + pm->ps->groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = qfalse; + pml.walking = qfalse; - pm->ps->walking = pml.walking; - pm->ps->groundPlane = pml.groundPlane; - return; - } + pm->ps->walking = pml.walking; + pm->ps->groundPlane = pml.groundPlane; + return; + } - // slopes that are too steep will not be considered onground - if( trace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - vec3_t oldvel; - float d; + // slopes that are too steep will not be considered onground + if (trace.plane.normal[2] < MIN_WALK_NORMAL) { + vec3_t oldvel; + float d; - if ( pm->debugLevel ) { - Com_Printf("%i:steep\n", c_pmove); - } + if (pm->debugLevel) { + Com_Printf("%i:steep\n", c_pmove); + } - VectorCopy( pm->ps->velocity, oldvel ); - VectorSet( pm->ps->velocity, 0, 0, -1.0f / pml.frametime ); - PM_SlideMove( qfalse ); + VectorCopy(pm->ps->velocity, oldvel); + VectorSet(pm->ps->velocity, 0, 0, -1.0f / pml.frametime); + PM_SlideMove(qfalse); - d = VectorLength( pm->ps->velocity ); - VectorCopy( oldvel, pm->ps->velocity ); + d = VectorLength(pm->ps->velocity); + VectorCopy(oldvel, pm->ps->velocity); - if( d > ( 0.1f / pml.frametime ) ) - { - pm->ps->groundEntityNum = ENTITYNUM_NONE; - pml.groundPlane = qtrue; - pml.walking = qfalse; + if (d > (0.1f / pml.frametime)) { + pm->ps->groundEntityNum = ENTITYNUM_NONE; + pml.groundPlane = qtrue; + pml.walking = qfalse; - pm->ps->walking = pml.walking; - pm->ps->groundPlane = pml.groundPlane; - return; - } - } + pm->ps->walking = pml.walking; + pm->ps->groundPlane = pml.groundPlane; + return; + } + } - pml.groundPlane = qtrue; - pml.walking = qtrue; + pml.groundPlane = qtrue; + pml.walking = qtrue; - if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) - { - // just hit the ground - if ( pm->debugLevel ) { - Com_Printf( "%i:Land\n", c_pmove ); - } + if (pm->ps->groundEntityNum == ENTITYNUM_NONE) { + // just hit the ground + if (pm->debugLevel) { + Com_Printf("%i:Land\n", c_pmove); + } - PM_CrashLand(); - } + PM_CrashLand(); + } - pm->ps->groundEntityNum = trace.entityNum; + pm->ps->groundEntityNum = trace.entityNum; - PM_AddTouchEnt( trace.entityNum ); + PM_AddTouchEnt(trace.entityNum); - pm->ps->walking = pml.walking; - pm->ps->groundPlane = pml.groundPlane; + pm->ps->walking = pml.walking; + pm->ps->groundPlane = pml.groundPlane; } - /* ============= PM_SetWaterLevel FIXME: avoid this twice? certainly if not moving ============= */ -static void PM_SetWaterLevel( void ) { - vec3_t point; - int cont; - int sample1; - int sample2; +static void PM_SetWaterLevel(void) +{ + vec3_t point; + int cont; + int sample1; + int sample2; - // - // get waterlevel, accounting for ducking - // - pm->waterlevel = 0; - pm->watertype = 0; + // + // get waterlevel, accounting for ducking + // + pm->waterlevel = 0; + pm->watertype = 0; - point[0] = pm->ps->origin[0]; - point[1] = pm->ps->origin[1]; - point[2] = pm->ps->origin[2] + MINS_Z + 1; - cont = pm->pointcontents( point, pm->ps->clientNum ); + point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] + MINS_Z + 1; + cont = pm->pointcontents(point, pm->ps->clientNum); - if ( cont & MASK_WATER ) { - sample2 = pm->ps->viewheight - MINS_Z; - sample1 = sample2 / 2; - - pm->watertype = cont; - pm->waterlevel = 1; - point[2] = pm->ps->origin[2] + MINS_Z + sample1; - cont = pm->pointcontents (point, pm->ps->clientNum ); - if ( cont & MASK_WATER ) { - pm->waterlevel = 2; - point[2] = pm->ps->origin[2] + MINS_Z + sample2; - cont = pm->pointcontents (point, pm->ps->clientNum ); - if ( cont & MASK_WATER ){ - pm->waterlevel = 3; - } - } - } + if (cont & MASK_WATER) { + sample2 = pm->ps->viewheight - MINS_Z; + sample1 = sample2 / 2; + pm->watertype = cont; + pm->waterlevel = 1; + point[2] = pm->ps->origin[2] + MINS_Z + sample1; + cont = pm->pointcontents(point, pm->ps->clientNum); + if (cont & MASK_WATER) { + pm->waterlevel = 2; + point[2] = pm->ps->origin[2] + MINS_Z + sample2; + cont = pm->pointcontents(point, pm->ps->clientNum); + if (cont & MASK_WATER) { + pm->waterlevel = 3; + } + } + } } /* @@ -1082,159 +1006,134 @@ PM_CheckDuck Sets mins, maxs, and pm->ps->viewheight ============== */ -static void PM_CheckDuck( void ) +static void PM_CheckDuck(void) { - pm->mins[ 0 ] = -15.0f; - pm->mins[ 1 ] = -15.0f; + pm->mins[0] = -15.0f; + pm->mins[1] = -15.0f; - pm->maxs[ 0 ] = 15.0f; - pm->maxs[ 1 ] = 15.0f; + pm->maxs[0] = 15.0f; + pm->maxs[1] = 15.0f; - pm->mins[ 2 ] = MINS_Z; + pm->mins[2] = MINS_Z; - if( pm->ps->pm_type == PM_DEAD ) - { - pm->maxs[ 2 ] = DEAD_MINS_Z; - pm->ps->viewheight = CROUCH_VIEWHEIGHT; - return; - } + if (pm->ps->pm_type == PM_DEAD) { + pm->maxs[2] = DEAD_MINS_Z; + pm->ps->viewheight = CROUCH_VIEWHEIGHT; + return; + } - if (pm->protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { - // - // Prone was removed in 2.0 - // - if (pm->ps->pm_flags & PMF_DUCKED) - { - pm->maxs[2] = 54.f; - pm->ps->viewheight = CROUCH_VIEWHEIGHT; - } - else if (pm->ps->pm_flags & PMF_VIEW_JUMP_START) - { - pm->maxs[2] = 94.0f; - pm->ps->viewheight = JUMP_START_VIEWHEIGHT; - } - else - { - pm->maxs[2] = 94.0f; - pm->ps->viewheight = DEFAULT_VIEWHEIGHT; - } - } else { - if ((pm->ps->pm_flags & (PMF_DUCKED | PMF_VIEW_PRONE)) == (PMF_DUCKED | PMF_VIEW_PRONE)) - { - pm->maxs[2] = 54.0f; - pm->ps->viewheight = CROUCH_VIEWHEIGHT; - } - else if (pm->ps->pm_flags & PMF_DUCKED) - { - pm->maxs[2] = 60.0f; - pm->ps->viewheight = CROUCH_VIEWHEIGHT; - } - else if (pm->ps->pm_flags & PMF_VIEW_PRONE) - { - pm->maxs[2] = 20.0f; - pm->ps->viewheight = PRONE_VIEWHEIGHT; - } - else if (pm->ps->pm_flags & PMF_VIEW_DUCK_RUN) - { - pm->maxs[2] = 94.0f; - pm->mins[2] = 54.0f; - pm->ps->viewheight = DEFAULT_VIEWHEIGHT; - } - else if (pm->ps->pm_flags & PMF_VIEW_JUMP_START) - { - pm->maxs[2] = 94.0f; - pm->ps->viewheight = JUMP_START_VIEWHEIGHT; - } - else - { - pm->maxs[2] = 94.0f; - pm->ps->viewheight = DEFAULT_VIEWHEIGHT; - } - } + if (pm->protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + // + // Prone was removed in 2.0 + // + if (pm->ps->pm_flags & PMF_DUCKED) { + pm->maxs[2] = 54.f; + pm->ps->viewheight = CROUCH_VIEWHEIGHT; + } else if (pm->ps->pm_flags & PMF_VIEW_JUMP_START) { + pm->maxs[2] = 94.0f; + pm->ps->viewheight = JUMP_START_VIEWHEIGHT; + } else { + pm->maxs[2] = 94.0f; + pm->ps->viewheight = DEFAULT_VIEWHEIGHT; + } + } else { + if ((pm->ps->pm_flags & (PMF_DUCKED | PMF_VIEW_PRONE)) == (PMF_DUCKED | PMF_VIEW_PRONE)) { + pm->maxs[2] = 54.0f; + pm->ps->viewheight = CROUCH_VIEWHEIGHT; + } else if (pm->ps->pm_flags & PMF_DUCKED) { + pm->maxs[2] = 60.0f; + pm->ps->viewheight = CROUCH_VIEWHEIGHT; + } else if (pm->ps->pm_flags & PMF_VIEW_PRONE) { + pm->maxs[2] = 20.0f; + pm->ps->viewheight = PRONE_VIEWHEIGHT; + } else if (pm->ps->pm_flags & PMF_VIEW_DUCK_RUN) { + pm->maxs[2] = 94.0f; + pm->mins[2] = 54.0f; + pm->ps->viewheight = DEFAULT_VIEWHEIGHT; + } else if (pm->ps->pm_flags & PMF_VIEW_JUMP_START) { + pm->maxs[2] = 94.0f; + pm->ps->viewheight = JUMP_START_VIEWHEIGHT; + } else { + pm->maxs[2] = 94.0f; + pm->ps->viewheight = DEFAULT_VIEWHEIGHT; + } + } } - - //=================================================================== - /* =============== PM_Footsteps =============== */ -static void PM_Footsteps( void ) { - float bobmove; - int old; - qboolean footstep; +static void PM_Footsteps(void) +{ + float bobmove; + int old; + qboolean footstep; - // - // calculate speed and cycle to be used for - // all cyclic walking effects - // - pm->xyspeed = sqrt( pm->ps->velocity[0] * pm->ps->velocity[0] - + pm->ps->velocity[1] * pm->ps->velocity[1] ); + // + // calculate speed and cycle to be used for + // all cyclic walking effects + // + pm->xyspeed = sqrt(pm->ps->velocity[0] * pm->ps->velocity[0] + pm->ps->velocity[1] * pm->ps->velocity[1]); - if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) { + if (pm->ps->groundEntityNum == ENTITYNUM_NONE) { + // if ( pm->ps->powerups[PW_INVULNERABILITY] ) { + // PM_ContinueLegsAnim( LEGS_IDLECR ); + // } + // airborne leaves position in cycle intact, but doesn't advance + if (pm->waterlevel > 1) { + // PM_ContinueLegsAnim( LEGS_SWIM ); + } + return; + } -// if ( pm->ps->powerups[PW_INVULNERABILITY] ) { -// PM_ContinueLegsAnim( LEGS_IDLECR ); -// } - // airborne leaves position in cycle intact, but doesn't advance - if ( pm->waterlevel > 1 ) { -// PM_ContinueLegsAnim( LEGS_SWIM ); - } - return; - } + // if not trying to move + if (!pm->cmd.forwardmove && !pm->cmd.rightmove) { + if (pm->xyspeed < 5) { + pm->ps->bobCycle = 0; // start at beginning of cycle again + if (pm->ps->pm_flags & PMF_DUCKED) { + // PM_ContinueLegsAnim( LEGS_IDLECR ); + } else { + // PM_ContinueLegsAnim( LEGS_IDLE ); + } + } + return; + } - // if not trying to move - if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { - if ( pm->xyspeed < 5 ) { - pm->ps->bobCycle = 0; // start at beginning of cycle again - if ( pm->ps->pm_flags & PMF_DUCKED ) { -// PM_ContinueLegsAnim( LEGS_IDLECR ); - } else { -// PM_ContinueLegsAnim( LEGS_IDLE ); - } - } - return; - } + footstep = qfalse; + if (!(pm->cmd.buttons & BUTTON_RUN)) { + bobmove = 0.4f; // faster speeds bob faster - footstep = qfalse; + footstep = qtrue; + } else { + bobmove = 0.3f; // walking bobs slow + } + // check for footstep / splash sounds + old = pm->ps->bobCycle; + pm->ps->bobCycle = (int)(old + bobmove * pml.msec) & 255; - if( !( pm->cmd.buttons & BUTTON_RUN ) ) - { - bobmove = 0.4f; // faster speeds bob faster - - footstep = qtrue; - } else { - bobmove = 0.3f; // walking bobs slow - } - - // check for footstep / splash sounds - old = pm->ps->bobCycle; - pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255; - - // if we just crossed a cycle boundary, play an apropriate footstep event - if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 ) { - if ( pm->waterlevel == 0 ) { - // on ground will only play sounds if running - if ( footstep && !pm->noFootsteps ) { -// PM_AddEvent( PM_FootstepForSurface() ); - } - } else if ( pm->waterlevel == 1 ) { - // splashing -// PM_AddEvent( EV_FOOTSPLASH ); - } else if ( pm->waterlevel == 2 ) { - // wading / swimming at surface -// PM_AddEvent( EV_SWIM ); - } else if ( pm->waterlevel == 3 ) { - // no sound when completely underwater - - } - } + // if we just crossed a cycle boundary, play an apropriate footstep event + if (((old + 64) ^ (pm->ps->bobCycle + 64)) & 128) { + if (pm->waterlevel == 0) { + // on ground will only play sounds if running + if (footstep && !pm->noFootsteps) { + // PM_AddEvent( PM_FootstepForSurface() ); + } + } else if (pm->waterlevel == 1) { + // splashing + // PM_AddEvent( EV_FOOTSPLASH ); + } else if (pm->waterlevel == 2) { + // wading / swimming at surface + // PM_AddEvent( EV_SWIM ); + } else if (pm->waterlevel == 3) { + // no sound when completely underwater + } + } } /* @@ -1244,62 +1143,51 @@ PM_WaterEvents Generate sound events for entering and leaving water ============== */ -static void PM_WaterEvents( void ) +static void PM_WaterEvents(void) { - // FIXME? - // - // if just entered a water volume, play a sound - // - if( !pml.previous_waterlevel && pm->waterlevel ) - { - pm->pmoveEvent = EV_WATER_TOUCH; - } + // FIXME? + // + // if just entered a water volume, play a sound + // + if (!pml.previous_waterlevel && pm->waterlevel) { + pm->pmoveEvent = EV_WATER_TOUCH; + } - // - // if just completely exited a water volume, play a sound - // - if( pml.previous_waterlevel && !pm->waterlevel ) - { - pm->pmoveEvent = EV_WATER_LEAVE; - } + // + // if just completely exited a water volume, play a sound + // + if (pml.previous_waterlevel && !pm->waterlevel) { + pm->pmoveEvent = EV_WATER_LEAVE; + } - // - // check for head just going under water - // - if( ( pml.previous_waterlevel != 3 ) && ( pm->waterlevel == 3 ) ) - { - pm->pmoveEvent = EV_WATER_UNDER; - } + // + // check for head just going under water + // + if ((pml.previous_waterlevel != 3) && (pm->waterlevel == 3)) { + pm->pmoveEvent = EV_WATER_UNDER; + } - // - // check for head just coming out of water - // - if( ( pml.previous_waterlevel == 3 ) && ( pm->waterlevel != 3 ) ) - { - pm->pmoveEvent = EV_WATER_CLEAR; - } + // + // check for head just coming out of water + // + if ((pml.previous_waterlevel == 3) && (pm->waterlevel != 3)) { + pm->pmoveEvent = EV_WATER_CLEAR; + } } - /* =============== PM_BeginWeaponChange =============== */ -static void PM_BeginWeaponChange( int weapon ) { - -} - +static void PM_BeginWeaponChange(int weapon) {} /* =============== PM_FinishWeaponChange =============== */ -static void PM_FinishWeaponChange( void ) { - -} - +static void PM_FinishWeaponChange(void) {} /* ============== @@ -1307,18 +1195,18 @@ PM_TorsoAnimation ============== */ -static void PM_TorsoAnimation( void ) { - //if ( pm->ps->weaponstate == WEAPON_READY ) { - // if ( pm->ps->weapon == WP_GAUNTLET ) { - // PM_ContinueTorsoAnim( TORSO_STAND2 ); - // } else { - // PM_ContinueTorsoAnim( TORSO_STAND ); - // } - // return; - //} +static void PM_TorsoAnimation(void) +{ + //if ( pm->ps->weaponstate == WEAPON_READY ) { + // if ( pm->ps->weapon == WP_GAUNTLET ) { + // PM_ContinueTorsoAnim( TORSO_STAND2 ); + // } else { + // PM_ContinueTorsoAnim( TORSO_STAND ); + // } + // return; + //} } - /* ============== PM_Weapon @@ -1326,9 +1214,7 @@ PM_Weapon Generates weapon events and modifes the weapon counter ============== */ -static void PM_Weapon( void ) { - -} +static void PM_Weapon(void) {} /* ================ @@ -1336,19 +1222,16 @@ PM_Animate ================ */ -static void PM_Animate( void ) { - -} - +static void PM_Animate(void) {} /* ================ PM_DropTimers ================ */ -static void PM_DropTimers( void ) +static void PM_DropTimers(void) { - pm->ps->pm_flags &= ~PMF_RESPAWNED; + pm->ps->pm_flags &= ~PMF_RESPAWNED; } /* @@ -1359,47 +1242,39 @@ This can be used as another entry point when only the viewangles are being updated isntead of a full move ================ */ -void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) +void PM_UpdateViewAngles(playerState_t *ps, const usercmd_t *cmd) { - short temp; - int i; + short temp; + int i; - if( ps->pm_flags & PMF_FROZEN ) - { - // no view changes at all - return; - } + if (ps->pm_flags & PMF_FROZEN) { + // no view changes at all + return; + } - if( ps->stats[ STAT_HEALTH ] <= 0 ) - { - // no view changes at all - return; - } + if (ps->stats[STAT_HEALTH] <= 0) { + // no view changes at all + return; + } - // circularly clamp the angles with deltas - for( i = 0; i < 3; i++ ) - { - temp = cmd->angles[ i ] + ps->delta_angles[ i ]; - if( i == PITCH ) - { - // don't let the player look up or down more than 90 degrees - if( temp > 16000 ) - { - ps->delta_angles[ i ] = 16000 - cmd->angles[ i ]; - temp = 16000; - } - else if( temp < -16000 ) - { - ps->delta_angles[ i ] = -16000 - cmd->angles[ i ]; - temp = -16000; - } - } + // circularly clamp the angles with deltas + for (i = 0; i < 3; i++) { + temp = cmd->angles[i] + ps->delta_angles[i]; + if (i == PITCH) { + // don't let the player look up or down more than 90 degrees + if (temp > 16000) { + ps->delta_angles[i] = 16000 - cmd->angles[i]; + temp = 16000; + } else if (temp < -16000) { + ps->delta_angles[i] = -16000 - cmd->angles[i]; + temp = -16000; + } + } - ps->viewangles[ i ] = SHORT2ANGLE( temp ); - } + ps->viewangles[i] = SHORT2ANGLE(temp); + } } - /* ================ PmoveSingle @@ -1407,237 +1282,216 @@ PmoveSingle ================ */ -void PmoveSingle( pmove_t *pmove ) +void PmoveSingle(pmove_t *pmove) { - vec3_t tempVec; - qboolean walking; + vec3_t tempVec; + qboolean walking; - pm = pmove; + pm = pmove; - // this counter lets us debug movement problems with a journal - // by setting a conditional breakpoint fot the previous frame - c_pmove++; + // this counter lets us debug movement problems with a journal + // by setting a conditional breakpoint fot the previous frame + c_pmove++; - // clear results - pm->numtouch = 0; - pm->watertype = 0; - pm->waterlevel = 0; + // clear results + pm->numtouch = 0; + pm->watertype = 0; + pm->waterlevel = 0; - if( pm->ps->stats[ STAT_HEALTH ] <= 0 ) { - pm->tracemask &= ~( CONTENTS_BODY | CONTENTS_NOBOTCLIP ); // corpses can fly through bodies - } + if (pm->ps->stats[STAT_HEALTH] <= 0) { + pm->tracemask &= ~(CONTENTS_BODY | CONTENTS_NOBOTCLIP); // corpses can fly through bodies + } - if( pmove->cmd.buttons & BUTTON_TALK ) - { - pmove->cmd.forwardmove = 0; - pmove->cmd.rightmove = 0; - pmove->cmd.upmove = 0; - pmove->cmd.buttons = BUTTON_TALK; - pm->ps->fLeanAngle = 0.0f; - } + if (pmove->cmd.buttons & BUTTON_TALK) { + pmove->cmd.forwardmove = 0; + pmove->cmd.rightmove = 0; + pmove->cmd.upmove = 0; + pmove->cmd.buttons = BUTTON_TALK; + pm->ps->fLeanAngle = 0.0f; + } - if( pm->ps->pm_type == PM_CLIMBWALL ) - { - pm->ps->fLeanAngle = 0.0f; - pm->cmd.buttons &= ~( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ); - } + if (pm->ps->pm_type == PM_CLIMBWALL) { + pm->ps->fLeanAngle = 0.0f; + pm->cmd.buttons &= ~(BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT); + } - // clear all pmove local vars - memset( &pml, 0, sizeof( pml ) ); + // clear all pmove local vars + memset(&pml, 0, sizeof(pml)); - // determine the time - pml.msec = pmove->cmd.serverTime - pm->ps->commandTime; - if ( pml.msec < 1 ) { - pml.msec = 1; - } else if ( pml.msec > 200 ) { - pml.msec = 200; - } + // determine the time + pml.msec = pmove->cmd.serverTime - pm->ps->commandTime; + if (pml.msec < 1) { + pml.msec = 1; + } else if (pml.msec > 200) { + pml.msec = 200; + } - pm->ps->commandTime = pmove->cmd.serverTime; + pm->ps->commandTime = pmove->cmd.serverTime; - // save old org in case we get stuck - VectorCopy( pm->ps->origin, pml.previous_origin ); + // save old org in case we get stuck + VectorCopy(pm->ps->origin, pml.previous_origin); - // save old velocity for crashlanding - VectorCopy( pm->ps->velocity, pml.previous_velocity ); + // save old velocity for crashlanding + VectorCopy(pm->ps->velocity, pml.previous_velocity); - pml.frametime = pml.msec * 0.001; + pml.frametime = pml.msec * 0.001; - if ((pm->cmd.buttons & (BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT) && - (pm->cmd.buttons & (BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT)) != (BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT)) && - (!pm->cmd.forwardmove || pm->alwaysAllowLean) && - (!pm->cmd.rightmove || pm->alwaysAllowLean) && - (!pm->cmd.upmove || pm->alwaysAllowLean)) - { - if( pm->cmd.buttons & BUTTON_LEAN_LEFT ) - { - if( pm->ps->fLeanAngle <= -pm->leanMax) - { - pm->ps->fLeanAngle = -pm->leanMax; - } - else - { - float fAngle = pml.frametime * ( -pm->leanMax - pm->ps->fLeanAngle ) * pm->leanAdd; - float fLeanAngle = pml.frametime * -pm->leanSpeed; + if ((pm->cmd.buttons & (BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT) + && (pm->cmd.buttons & (BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT)) != (BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT)) + && (!pm->cmd.forwardmove || pm->alwaysAllowLean) && (!pm->cmd.rightmove || pm->alwaysAllowLean) + && (!pm->cmd.upmove || pm->alwaysAllowLean)) { + if (pm->cmd.buttons & BUTTON_LEAN_LEFT) { + if (pm->ps->fLeanAngle <= -pm->leanMax) { + pm->ps->fLeanAngle = -pm->leanMax; + } else { + float fAngle = pml.frametime * (-pm->leanMax - pm->ps->fLeanAngle) * pm->leanAdd; + float fLeanAngle = pml.frametime * -pm->leanSpeed; - if( fAngle <= fLeanAngle ) { - fLeanAngle = fAngle; - } + if (fAngle <= fLeanAngle) { + fLeanAngle = fAngle; + } - pm->ps->fLeanAngle += fLeanAngle; - } - } - else - { - if( pm->ps->fLeanAngle >= pm->leanMax ) - { - pm->ps->fLeanAngle = pm->leanMax; - } - else - { - float fAngle = pm->leanMax - pm->ps->fLeanAngle; - float fLeanAngle = pml.frametime * pm->leanSpeed; - float fMult = pml.frametime * fAngle * pm->leanAdd; + pm->ps->fLeanAngle += fLeanAngle; + } + } else { + if (pm->ps->fLeanAngle >= pm->leanMax) { + pm->ps->fLeanAngle = pm->leanMax; + } else { + float fAngle = pm->leanMax - pm->ps->fLeanAngle; + float fLeanAngle = pml.frametime * pm->leanSpeed; + float fMult = pml.frametime * fAngle * pm->leanAdd; - if( fLeanAngle <= fMult ) - { - fLeanAngle = fMult; - } - else - { - fLeanAngle = fMult; - } + if (fLeanAngle <= fMult) { + fLeanAngle = fMult; + } else { + fLeanAngle = fMult; + } - pm->ps->fLeanAngle += fLeanAngle; - } - } - } - else if( pm->ps->fLeanAngle ) - { - float fAngle = pm->ps->fLeanAngle * pml.frametime * pm->leanRecoverSpeed; + pm->ps->fLeanAngle += fLeanAngle; + } + } + } else if (pm->ps->fLeanAngle) { + float fAngle = pm->ps->fLeanAngle * pml.frametime * pm->leanRecoverSpeed; - if( pm->ps->fLeanAngle <= 0.0f ) - { - float fLeanAngle = pml.frametime * -pm->leanSpeed; + if (pm->ps->fLeanAngle <= 0.0f) { + float fLeanAngle = pml.frametime * -pm->leanSpeed; - if( fAngle <= fLeanAngle ) - { - fLeanAngle = fAngle; - } + if (fLeanAngle >= fAngle) { + fLeanAngle = fAngle; + } - pm->ps->fLeanAngle -= fLeanAngle; - } - else - { - float fLeanAngle = pml.frametime * pm->leanSpeed; + pm->ps->fLeanAngle -= fLeanAngle; + if (pm->ps->fLeanAngle > 0) { + pm->ps->fLeanAngle = 0; + } + } else { + float fLeanAngle = pml.frametime * pm->leanSpeed; - if(fAngle >= fLeanAngle) { - fLeanAngle = fAngle; - } + if (fLeanAngle <= fAngle) { + fLeanAngle = fAngle; + } - pm->ps->fLeanAngle -= fLeanAngle; - } - } + pm->ps->fLeanAngle -= fLeanAngle; + if (pm->ps->fLeanAngle < 0) { + pm->ps->fLeanAngle = 0; + } + } + } - if (pm->ps->pm_flags & PMF_NO_LEAN) { - pm->ps->fLeanAngle = 0; - } + if (pm->ps->pm_flags & PMF_NO_LEAN) { + pm->ps->fLeanAngle = 0; + } - // update the viewangles - PM_UpdateViewAngles( pm->ps, &pm->cmd ); + // update the viewangles + PM_UpdateViewAngles(pm->ps, &pm->cmd); - AngleVectorsLeft( pm->ps->viewangles, pml.forward, pml.left, pml.up ); - VectorClear( tempVec ); - tempVec[ YAW ] = pm->ps->viewangles[ YAW ]; - AngleVectorsLeft( tempVec, pml.flat_forward, pml.flat_left, pml.flat_up ); + AngleVectorsLeft(pm->ps->viewangles, pml.forward, pml.left, pml.up); + VectorClear(tempVec); + tempVec[YAW] = pm->ps->viewangles[YAW]; + AngleVectorsLeft(tempVec, pml.flat_forward, pml.flat_left, pml.flat_up); - if ( pm->ps->pm_type >= PM_DEAD ) - { - pm->cmd.forwardmove = 0; - pm->cmd.rightmove = 0; - pm->cmd.upmove = 0; - pm->ps->fLeanAngle = 0.0f; - } + if (pm->ps->pm_type >= PM_DEAD) { + pm->cmd.forwardmove = 0; + pm->cmd.rightmove = 0; + pm->cmd.upmove = 0; + pm->ps->fLeanAngle = 0.0f; + } - if ( pm->ps->pm_type == PM_NOCLIP ) - { - PM_NoclipMove(); - PM_DropTimers(); - return; - } + if (pm->ps->pm_type == PM_NOCLIP) { + PM_NoclipMove(); + PM_DropTimers(); + return; + } - if( ( pm->ps->pm_flags & PMF_NO_MOVE ) || ( pm->ps->pm_flags & PMF_FROZEN ) ) - { - PM_CheckDuck(); - return; - } + if ((pm->ps->pm_flags & PMF_NO_MOVE) || (pm->ps->pm_flags & PMF_FROZEN)) { + PM_CheckDuck(); + return; + } - // set watertype, and waterlevel - PM_SetWaterLevel(); - pml.previous_waterlevel = pmove->waterlevel; + // set watertype, and waterlevel + PM_SetWaterLevel(); + pml.previous_waterlevel = pmove->waterlevel; - // set mins, maxs, and viewheight - PM_CheckDuck(); + // set mins, maxs, and viewheight + PM_CheckDuck(); - // set groundentity - PM_GroundTrace(); + // set groundentity + PM_GroundTrace(); - if ( pm->ps->pm_type == PM_DEAD ) { - PM_DeadMove(); - } + if (pm->ps->pm_type == PM_DEAD) { + PM_DeadMove(); + } - PM_DropTimers(); + PM_DropTimers(); - if ( pml.walking ) { - // walking on ground - PM_WalkMove(); - } else { - // airborne - PM_AirMove(); - } + if (pml.walking) { + // walking on ground + PM_WalkMove(); + } else { + // airborne + PM_AirMove(); + } - walking = pml.walking; + walking = pml.walking; - // set groundentity, watertype, and waterlevel - PM_GroundTrace(); - PM_SetWaterLevel(); + // set groundentity, watertype, and waterlevel + PM_GroundTrace(); + PM_SetWaterLevel(); - // don't fall down stairs or do really short falls - if( !pml.walking && ( walking || ( ( pml.previous_velocity[ 2 ] >= 0 ) && ( pm->ps->velocity[ 2 ] <= 0 ) ) ) ) - { - vec3_t point; - trace_t trace; + // don't fall down stairs or do really short falls + if (!pml.walking && (walking || ((pml.previous_velocity[2] >= 0) && (pm->ps->velocity[2] <= 0)))) { + vec3_t point; + trace_t trace; - point[ 0 ] = pm->ps->origin[ 0 ]; - point[ 1 ] = pm->ps->origin[ 1 ]; - point[ 2 ] = pm->ps->origin[ 2 ] - STEPSIZE; + point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] - STEPSIZE; - pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - if( ( trace.fraction < 1.0f ) && ( !trace.allsolid ) ) - { - VectorCopy( trace.endpos, pm->ps->origin ); + pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + if ((trace.fraction < 1.0f) && (!trace.allsolid)) { + VectorCopy(trace.endpos, pm->ps->origin); - // allow client to smooth out the step - pm->stepped = qtrue; + // allow client to smooth out the step + pm->stepped = qtrue; - // requantify the player's position - PM_GroundTrace(); - PM_SetWaterLevel(); - } - } + // requantify the player's position + PM_GroundTrace(); + PM_SetWaterLevel(); + } + } - // entering / leaving water splashes - PM_WaterEvents(); + // entering / leaving water splashes + PM_WaterEvents(); } -void Pmove_GroundTrace( pmove_t *pmove ) +void Pmove_GroundTrace(pmove_t *pmove) { - memset( &pml, 0, sizeof( pml ) ); - pml.msec = 1; - pml.frametime = 0.001f; - pm = pmove; - PM_CheckDuck(); - PM_GroundTrace(); + memset(&pml, 0, sizeof(pml)); + pml.msec = 1; + pml.frametime = 0.001f; + pm = pmove; + PM_CheckDuck(); + PM_GroundTrace(); } /* @@ -1647,219 +1501,234 @@ Pmove Can be called by either the server or the client ================ */ -void Pmove( pmove_t *pmove ) { - int finalTime; - - finalTime = pmove->cmd.serverTime; - - if( finalTime < pmove->ps->commandTime ) { - return; // should not happen - } - - if( finalTime > pmove->ps->commandTime + 1000 ) { - pmove->ps->commandTime = finalTime - 1000; - } - - // chop the move up if it is too long, to prevent framerate - // dependent behavior - while( pmove->ps->commandTime != finalTime ) { - int msec; - - msec = finalTime - pmove->ps->commandTime; - - if( pmove->pmove_fixed ) - { - if( msec > pmove->pmove_msec ) - { - msec = pmove->pmove_msec; - } - } - else if( msec > 66 ) { - msec = 66; - } - - pmove->cmd.serverTime = pmove->ps->commandTime + msec; - PmoveSingle( pmove ); - } -} -static void PmoveAdjustViewAngleSettings_OnLadder( vec_t *vViewAngles, vec_t *vAngles, playerState_t *pPlayerState, entityState_t *pEntState ) +void Pmove(pmove_t *pmove) { - float fDelta; - float deltayaw; - float yawAngle; - float temp; + int finalTime; - vAngles[ 0 ] = 0.0f; - vAngles[ 2 ] = 0.0f; + finalTime = pmove->cmd.serverTime; - if( vViewAngles[ 0 ] > 73.0f ) { - vViewAngles[ 0 ] = 73.0f; - } + if (finalTime < pmove->ps->commandTime) { + return; // should not happen + } - deltayaw = AngleSubtract( vViewAngles[ 1 ], vAngles[ 1 ] ); + if (finalTime > pmove->ps->commandTime + 1000) { + pmove->ps->commandTime = finalTime - 1000; + } - yawAngle = 70.0f; - if( deltayaw <= 70.0f ) - { - yawAngle = deltayaw; - if( deltayaw < -70.0f ) - { - yawAngle = -70.0f; - } - } + // chop the move up if it is too long, to prevent framerate + // dependent behavior + while (pmove->ps->commandTime != finalTime) { + int msec; - vViewAngles[ 1 ] = vAngles[ 1 ] + yawAngle; + msec = finalTime - pmove->ps->commandTime; - fDelta = sqrt( yawAngle * yawAngle + vViewAngles[ 0 ] * vViewAngles[ 0 ] ); + if (pmove->pmove_fixed) { + if (msec > pmove->pmove_msec) { + msec = pmove->pmove_msec; + } + } else if (msec > 66) { + msec = 66; + } - if( vViewAngles[ 0 ] <= 0.0f ) { - temp = 80.0f; - } else { - temp = 73.0f; - } - - if( fDelta > temp ) - { - float deltalimit = temp * 1.0f / fDelta; - vViewAngles[ 0 ] *= deltalimit; - vViewAngles[ 1 ] = yawAngle * deltalimit + vAngles[ 1 ]; - } + pmove->cmd.serverTime = pmove->ps->commandTime + msec; + PmoveSingle(pmove); + } } -void PmoveAdjustAngleSettings( vec_t *vViewAngles, vec_t *vAngles, playerState_t *pPlayerState, entityState_t *pEntState ) +static void PmoveAdjustViewAngleSettings_OnLadder( + vec_t *vViewAngles, vec_t *vAngles, playerState_t *pPlayerState, entityState_t *pEntState +) { - vec3_t temp, temp2; - vec3_t armsAngles, torsoAngles, headAngles; - float fTmp; + float fDelta; + float deltayaw; + float yawAngle; + float temp; - if( pPlayerState->pm_type == PM_CLIMBWALL ) - { - PmoveAdjustViewAngleSettings_OnLadder( vViewAngles, vAngles, pPlayerState, pEntState ); - VectorSet( pEntState->bone_angles[ TORSO_TAG ], 0, 0, 0 ); - VectorSet( pEntState->bone_angles[ ARMS_TAG ], 0, 0, 0 ); - VectorSet( pEntState->bone_angles[ PELVIS_TAG ], 0, 0, 0 ); - QuatSet( pEntState->bone_quat[ TORSO_TAG ], 0, 0, 0, 1 ); - QuatSet( pEntState->bone_quat[ ARMS_TAG ], 0, 0, 0, 1 ); - QuatSet( pEntState->bone_quat[ PELVIS_TAG ], 0, 0, 0, 1 ); + vAngles[0] = 0.0f; + vAngles[2] = 0.0f; - AnglesSubtract( vViewAngles, vAngles, headAngles ); - VectorScale( headAngles, 0.5f, pEntState->bone_angles[ HEAD_TAG ] ); + if (vViewAngles[0] > 73.0f) { + vViewAngles[0] = 73.0f; + } - EulerToQuat( headAngles, pEntState->bone_quat[ HEAD_TAG ] ); - return; - } + deltayaw = AngleSubtract(vViewAngles[1], vAngles[1]); - if( pPlayerState->pm_type != PM_DEAD ) - { - fTmp = AngleMod( vViewAngles[ 1 ] ); - VectorSet( vAngles, 0, fTmp, 0 ); + yawAngle = 70.0f; + if (deltayaw <= 70.0f) { + yawAngle = deltayaw; + if (deltayaw < -70.0f) { + yawAngle = -70.0f; + } + } - if( !( pPlayerState->pm_flags & PMF_VIEW_PRONE ) || ( pPlayerState->pm_flags & PMF_DUCKED ) ) - { - fTmp = AngleMod( vViewAngles[ 0 ] ); + vViewAngles[1] = vAngles[1] + yawAngle; - VectorSet( temp, fTmp, 0, pPlayerState->fLeanAngle * 0.60f ); - VectorSet( temp2, fTmp, 0, pPlayerState->fLeanAngle ); + fDelta = sqrt(yawAngle * yawAngle + vViewAngles[0] * vViewAngles[0]); - if( fTmp > 180.0f ) { - temp2[ 0 ] = fTmp - 360.0f; - } + if (vViewAngles[0] <= 0.0f) { + temp = 80.0f; + } else { + temp = 73.0f; + } - temp2[ 0 ] = 0.90f * temp2[ 0 ] * 0.70f; + if (fDelta > temp) { + float deltalimit = temp * 1.0f / fDelta; + vViewAngles[0] *= deltalimit; + vViewAngles[1] = yawAngle * deltalimit + vAngles[1]; + } +} - AnglesSubtract( temp, temp2, headAngles ); - VectorCopy( headAngles, pEntState->bone_angles[ HEAD_TAG ] ); - EulerToQuat( pEntState->bone_angles[ HEAD_TAG ], pEntState->bone_quat[ HEAD_TAG ] ); +void PmoveAdjustAngleSettings(vec_t *vViewAngles, vec_t *vAngles, playerState_t *pPlayerState, entityState_t *pEntState) +{ + vec3_t temp, temp2; + vec3_t armsAngles, torsoAngles, headAngles; + float fTmp; - if( temp2[ 0 ] <= 0.0f ) - { - fTmp = -0.1f; - } - else{ - fTmp = 0.3f; - } + if (pPlayerState->pm_type == PM_DEAD) { + // set the default angles + VectorSet(pEntState->bone_angles[HEAD_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[TORSO_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[ARMS_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[PELVIS_TAG], 0, 0, 0); + QuatSet(pEntState->bone_quat[HEAD_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[TORSO_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[ARMS_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[PELVIS_TAG], 0, 0, 0, 1); + } else if (pPlayerState->pm_type == PM_CLIMBWALL) { + PmoveAdjustViewAngleSettings_OnLadder(vViewAngles, vAngles, pPlayerState, pEntState); + VectorSet(pEntState->bone_angles[TORSO_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[ARMS_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[PELVIS_TAG], 0, 0, 0); + QuatSet(pEntState->bone_quat[TORSO_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[ARMS_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[PELVIS_TAG], 0, 0, 0, 1); - VectorSet( temp, fTmp * temp2[ 0 ], 0, pPlayerState->fLeanAngle * 0.8f ); - VectorCopy( temp, pEntState->bone_angles[ PELVIS_TAG ] ); - EulerToQuat( pEntState->bone_angles[ PELVIS_TAG ], pEntState->bone_quat[ PELVIS_TAG ] ); + AnglesSubtract(vViewAngles, vAngles, headAngles); + VectorScale(headAngles, 0.5f, pEntState->bone_angles[HEAD_TAG]); - float fDelta = ( 1.0f - fTmp ) * temp2[ 0 ]; + EulerToQuat(headAngles, pEntState->bone_quat[HEAD_TAG]); + } else { + if (pPlayerState->pm_flags & PMF_TURRET) { + vAngles[2] = 0; + // Added in 2.0 + // Clients checking this flag will draw an icon + // above the head of teammates + pEntState->eFlags |= EF_PLAYER_ARTILLERY; + } else { + fTmp = AngleMod(vViewAngles[1]); + VectorSet(vAngles, 0, fTmp, 0); + pEntState->eFlags &= ~EF_PLAYER_ARTILLERY; + } - if( vViewAngles[ 0 ] <= 0.0f ) - { - VectorSet( torsoAngles, fDelta * 0.60f, 0, pPlayerState->fLeanAngle * 0.2f * -0.1f ); - VectorSet( armsAngles, fDelta * 0.40f, 0, pPlayerState->fLeanAngle * 0.2f * 1.1f ); - } - else - { - VectorSet( torsoAngles, fDelta * 0.70f, 0, pPlayerState->fLeanAngle * 0.2f * -0.1f ); - VectorSet( armsAngles, fDelta * 0.30f, 0, pPlayerState->fLeanAngle * 0.2f * 1.1f ); - } + if (pPlayerState->pm_flags & PMF_TURRET) { + // set the default angles + VectorSet(pEntState->bone_angles[TORSO_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[ARMS_TAG], 0, 0, 0); + VectorSet(pEntState->bone_angles[PELVIS_TAG], 0, 0, 0); + QuatSet(pEntState->bone_quat[TORSO_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[ARMS_TAG], 0, 0, 0, 1); + QuatSet(pEntState->bone_quat[PELVIS_TAG], 0, 0, 0, 1); - VectorCopy( torsoAngles, pEntState->bone_angles[ TORSO_TAG ] ); - EulerToQuat( pEntState->bone_angles[ TORSO_TAG ], pEntState->bone_quat[ TORSO_TAG ] ); + AnglesSubtract(vViewAngles, vAngles, headAngles); + // Added in 2.0 + // Prevent rotating the player head like a monster + if (headAngles[1] > 90) { + headAngles[1] = 90; + } + if (headAngles[1] < -90) { + headAngles[1] = -90; + } - VectorCopy( armsAngles, pEntState->bone_angles[ ARMS_TAG ] ); - EulerToQuat( pEntState->bone_angles[ ARMS_TAG ], pEntState->bone_quat[ ARMS_TAG ] ); - return; - } - } + VectorCopy(headAngles, pEntState->bone_angles[HEAD_TAG]); + EulerToQuat(pEntState->bone_angles[HEAD_TAG], pEntState->bone_quat[HEAD_TAG]); + return; + } - // set the default angles - VectorSet( pEntState->bone_angles[ HEAD_TAG ], 0, 0, 0 ); - VectorSet( pEntState->bone_angles[ TORSO_TAG ], 0, 0, 0 ); - VectorSet( pEntState->bone_angles[ ARMS_TAG ], 0, 0, 0 ); - VectorSet( pEntState->bone_angles[ PELVIS_TAG ], 0, 0, 0 ); - QuatSet( pEntState->bone_quat[ HEAD_TAG ], 0, 0, 0, 1 ); - QuatSet( pEntState->bone_quat[ TORSO_TAG ], 0, 0, 0, 1 ); - QuatSet( pEntState->bone_quat[ ARMS_TAG ], 0, 0, 0, 1 ); - QuatSet( pEntState->bone_quat[ PELVIS_TAG ], 0, 0, 0, 1 ); + fTmp = AngleMod(vViewAngles[0]); + + VectorSet(temp, fTmp, 0, pPlayerState->fLeanAngle * 0.60f); + VectorSet(temp2, fTmp, 0, pPlayerState->fLeanAngle); + + if (fTmp > 180.0f) { + temp2[0] = fTmp - 360.0f; + } + + temp2[0] = 0.90f * temp2[0] * 0.70f; + + AnglesSubtract(temp, temp2, headAngles); + VectorCopy(headAngles, pEntState->bone_angles[HEAD_TAG]); + EulerToQuat(pEntState->bone_angles[HEAD_TAG], pEntState->bone_quat[HEAD_TAG]); + + if (temp2[0] <= 0.0f) { + fTmp = -0.1f; + } else { + fTmp = 0.3f; + } + + VectorSet(temp, fTmp * temp2[0], 0, pPlayerState->fLeanAngle * 0.8f); + VectorCopy(temp, pEntState->bone_angles[PELVIS_TAG]); + EulerToQuat(pEntState->bone_angles[PELVIS_TAG], pEntState->bone_quat[PELVIS_TAG]); + + float fDelta = (1.0f - fTmp) * temp2[0]; + + if (vViewAngles[0] <= 0.0f) { + VectorSet(torsoAngles, fDelta * 0.60f, 0, pPlayerState->fLeanAngle * 0.2f * -0.1f); + VectorSet(armsAngles, fDelta * 0.40f, 0, pPlayerState->fLeanAngle * 0.2f * 1.1f); + } else { + VectorSet(torsoAngles, fDelta * 0.70f, 0, pPlayerState->fLeanAngle * 0.2f * -0.1f); + VectorSet(armsAngles, fDelta * 0.30f, 0, pPlayerState->fLeanAngle * 0.2f * 1.1f); + } + + VectorCopy(torsoAngles, pEntState->bone_angles[TORSO_TAG]); + EulerToQuat(pEntState->bone_angles[TORSO_TAG], pEntState->bone_quat[TORSO_TAG]); + + VectorCopy(armsAngles, pEntState->bone_angles[ARMS_TAG]); + EulerToQuat(pEntState->bone_angles[ARMS_TAG], pEntState->bone_quat[ARMS_TAG]); + } } // Used to set arms angles accordingly, calculated client-side // Without it, the arms will look like it has latency -void PmoveAdjustAngleSettings_Client( vec_t *vViewAngles, vec_t *vAngles, playerState_t *pPlayerState, entityState_t *pEntState ) +void PmoveAdjustAngleSettings_Client( + vec_t *vViewAngles, vec_t *vAngles, playerState_t *pPlayerState, entityState_t *pEntState +) { vec3_t torsoAngles; - int i; + int i; - if (pPlayerState->pm_type == PM_DEAD) - { - for (i = 0; i < NUM_BONE_CONTROLLERS; i++) { + if (pPlayerState->pm_type == PM_DEAD) { + for (i = 0; i < NUM_BONE_CONTROLLERS; i++) { VectorClear(pEntState->bone_angles[i]); QuatClear(pEntState->bone_quat[i]); - } - } - else if (pPlayerState->pm_type == PM_CLIMBWALL) - { - vec3_t headAngles; + } + } else if (pPlayerState->pm_type == PM_CLIMBWALL) { + vec3_t headAngles; PmoveAdjustViewAngleSettings_OnLadder(vViewAngles, vAngles, pPlayerState, pEntState); - VectorSet(torsoAngles, AngleMod(vViewAngles[0]), 0.0, pPlayerState->fLeanAngle * 0.7); + VectorSet(torsoAngles, AngleMod(vViewAngles[0]), 0.0, pPlayerState->fLeanAngle * 0.7); - if (torsoAngles[0] > 180.0) { - torsoAngles[0] -= 180.0; - } + if (torsoAngles[0] > 180.0) { + torsoAngles[0] -= 180.0; + } - torsoAngles[0] += 8.0; + torsoAngles[0] += 8.0; VectorClear(pEntState->bone_angles[TORSO_TAG]); QuatClear(pEntState->bone_quat[TORSO_TAG]); VectorClear(pEntState->bone_angles[PELVIS_TAG]); QuatClear(pEntState->bone_quat[PELVIS_TAG]); - VectorCopy(torsoAngles, pEntState->bone_angles[ARMS_TAG]); - EulerToQuat(pEntState->bone_angles[ARMS_TAG], pEntState->bone_quat[ARMS_TAG]); + VectorCopy(torsoAngles, pEntState->bone_angles[ARMS_TAG]); + EulerToQuat(pEntState->bone_angles[ARMS_TAG], pEntState->bone_quat[ARMS_TAG]); - // head angles + // head angles AnglesSubtract(vViewAngles, vAngles, headAngles); headAngles[0] *= 0.5; - AnglesSubtract(headAngles, torsoAngles, headAngles); + AnglesSubtract(headAngles, torsoAngles, headAngles); VectorCopy(headAngles, pEntState->bone_angles[HEAD_TAG]); EulerToQuat(pEntState->bone_angles[HEAD_TAG], pEntState->bone_quat[HEAD_TAG]); - } - else { - // Clear the head, torso and pelvis + } else { + // Clear the head, torso and pelvis VectorClear(pEntState->bone_angles[HEAD_TAG]); QuatClear(pEntState->bone_quat[HEAD_TAG]); VectorClear(pEntState->bone_angles[TORSO_TAG]); @@ -1867,8 +1736,8 @@ void PmoveAdjustAngleSettings_Client( vec_t *vViewAngles, vec_t *vAngles, player VectorClear(pEntState->bone_angles[PELVIS_TAG]); QuatClear(pEntState->bone_quat[PELVIS_TAG]); - VectorSet(vAngles, 0, AngleMod(vViewAngles[1]), 0); - VectorSet(torsoAngles, AngleMod(vViewAngles[0]), 0, pPlayerState->fLeanAngle * 0.7); + VectorSet(vAngles, 0, AngleMod(vViewAngles[1]), 0); + VectorSet(torsoAngles, AngleMod(vViewAngles[0]), 0, pPlayerState->fLeanAngle * 0.7); if (torsoAngles[0] > 180.0) { torsoAngles[0] -= 360.0; @@ -1877,5 +1746,5 @@ void PmoveAdjustAngleSettings_Client( vec_t *vViewAngles, vec_t *vAngles, player torsoAngles[0] += 8.0; VectorCopy(torsoAngles, pEntState->bone_angles[ARMS_TAG]); EulerToQuat(pEntState->bone_angles[ARMS_TAG], pEntState->bone_quat[ARMS_TAG]); - } + } } diff --git a/code/fgame/bg_public.h b/code/fgame/bg_public.h index 7c0404b4..840d1ffd 100644 --- a/code/fgame/bg_public.h +++ b/code/fgame/bg_public.h @@ -1,6 +1,7 @@ /* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2024 the OpenMoHAA team This file is part of Quake III Arena source code. @@ -25,34 +26,25 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // because games can change separately from the main system version, we need a // second version that must match between game and cgame -#ifndef __BG_PUBLIC_H__ -#define __BG_PUBLIC_H__ +#pragma once -#define GAME_VERSION "mohaa-base-1" +#define GAME_VERSION "mohaa-base-1" -#define DEFAULT_GRAVITY 800 +static const int MINS_X = -15; +static const int MINS_Y = -15; +static const int MINS_Z = 0; // IneQuation: bounding box and viewheights to match MoHAA +static const int MAXS_X = 15; +static const int MAXS_Y = 15; +static const int MAXS_Z = 94; +static const int DEAD_MINS_Z = 32; +static const int CROUCH_MAXS_Z = 49; -#define SCORE_NOT_PRESENT -9999 // for the CS_SCORES[12] when only one player is present - -#define VOTE_TIME 30000 // 30 seconds before vote times out - -#define MINS_Z 0 -#define MINS_X -15 -#define MINS_Y -15 -#define MAXS_X 15 -#define MAXS_Y 15 - -#define MINS_Z 0 // IneQuation: bounding box and viewheights to match MoHAA -#define MAXS_Z 96 - -#define DEAD_MINS_Z 32 -#define CROUCH_MAXS_Z 49 -#define DEFAULT_VIEWHEIGHT 82 -#define CROUCH_RUN_VIEWHEIGHT 64 -#define JUMP_START_VIEWHEIGHT 52 -#define CROUCH_VIEWHEIGHT 48 -#define PRONE_VIEWHEIGHT 16 -#define DEAD_VIEWHEIGHT 8 +static const unsigned int DEFAULT_VIEWHEIGHT = 82; +static const unsigned int CROUCH_RUN_VIEWHEIGHT = 64; +static const unsigned int JUMP_START_VIEWHEIGHT = 52; +static const unsigned int CROUCH_VIEWHEIGHT = 48; +static const unsigned int PRONE_VIEWHEIGHT = 16; +static const unsigned int DEAD_VIEWHEIGHT = 8; // // config strings are a general means of communicating variable length strings @@ -140,10 +132,10 @@ extern "C" { GT_MAX_GAME_TYPE } gametype_t; -// -// scale to use when evaluating entityState_t::constantLight scale -// -#define CONSTANTLIGHT_RADIUS_SCALE 8 + // + // scale to use when evaluating entityState_t::constantLight scale + // + static const float CONSTANTLIGHT_RADIUS_SCALE = 8; typedef enum { GENDER_MALE, @@ -151,30 +143,31 @@ extern "C" { GENDER_NEUTER } gender_t; - // su44: vma indexes are sent as 4 bits - // see playerState_t::iViewModelAnim - typedef enum { - VMA_IDLE, - VMA_CHARGE, - VMA_FIRE, - VMA_FIRE_SECONDARY, - VMA_RECHAMBER, - VMA_RELOAD, - VMA_RELOAD_SINGLE, - VMA_RELOAD_END, - VMA_PULLOUT, - VMA_PUTAWAY, - VMA_LADDERSTEP, - VMA_ENABLE, - VMA_CUSTOMANIMATION, - VMA_NUMANIMATIONS - } viewmodelanim_t; + enum vmAnim_e { + VM_ANIM_DISABLED, + VM_ANIM_IDLE, + VM_ANIM_CHARGE, + VM_ANIM_FIRE, + VM_ANIM_FIRE_SECONDARY, + VM_ANIM_RECHAMBER, + VM_ANIM_RELOAD, + VM_ANIM_RELOAD_SINGLE, + VM_ANIM_RELOAD_END, + VM_ANIM_PULLOUT, + VM_ANIM_PUTAWAY, + VM_ANIM_LADDERSTEP, + VM_ANIM_IDLE_0, + VM_ANIM_IDLE_1, + VM_ANIM_IDLE_2, + }; -// su44: playerState_t::activeItems[8] slots -// they are sent as 16 bits -// TODO: find out rest of them -#define ITEM_AMMO 0 // current ammo -#define ITEM_WEAPON 1 // current mainhand weapon + // su44: playerState_t::activeItems[8] slots + // they are sent as 16 bits + // TODO: find out rest of them + enum itemtype_e { + ITEM_AMMO, + ITEM_WEAPON + }; /* =================================================================================== @@ -187,17 +180,12 @@ movement on the server game. =================================================================================== */ -#define MAX_CLIP_PLANES 5 -#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes + static const unsigned int MAX_CLIP_PLANES = 5; + static const float MIN_WALK_NORMAL = 0.7f; // can't walk on very steep slopes -#define STEPSIZE 18 + static const float STEPSIZE = 18; -#define WATER_TURBO_SPEED 1.35f -#define WATER_TURBO_TIME 1200 -#define MINIMUM_RUNNING_TIME 800 -#define MINIMUM_WATER_FOR_TURBO 90 - -#define OVERCLIP 1.001f + static const float OVERCLIP = 1.001f; // su44: our pmtype_t enum must be the same // as in MoHAA, because playerState_t::pm_type @@ -251,8 +239,9 @@ movement on the server game. #endif // moh pm_flags -#define PMF_DUCKED (1 << 0) -#define PMF_VIEW_PRONE (1 << 1) +#define PMF_DUCKED (1 << 0) +#define PMF_VIEW_PRONE (1 << 1) +#define PMF_DAMAGE_ANGLES (1 << 1) // in protocol >= 15 // // 2 Flags removed in team tactics // @@ -269,25 +258,28 @@ movement on the server game. #define PMF_LEVELEXIT (1 << 11) #define PMF_NO_GRAVITY (1 << 12) #define PMF_NO_HUD (1 << 13) -#define PMF_UNKNOWN (1 << 14) +#define PMF_TURRET (1 << 14) #define PMF_NO_LEAN (1 << 15) -// moveposflags -#define MPF_POSITION_STANDING (1 << 0) -#define MPF_POSITION_CROUCHING (1 << 1) -#define MPF_POSITION_PRONE (1 << 2) -#define MPF_POSITION_OFFGROUND (1 << 3) + // moveposflags + enum moveposflags_e { + MPF_POSITION_STANDING = (1 << 0), + MPF_POSITION_CROUCHING = (1 << 1), + MPF_POSITION_PRONE = (1 << 2), + MPF_POSITION_OFFGROUND = (1 << 3), + MPF_MOVEMENT_WALKING = (1 << 4), + MPF_MOVEMENT_RUNNING = (1 << 5), + MPF_MOVEMENT_FALLING = (1 << 6), + }; -#define MPF_MOVEMENT_WALKING (1 << 4) -#define MPF_MOVEMENT_RUNNING (1 << 5) -#define MPF_MOVEMENT_FALLING (1 << 6) +#define MAXTOUCH 32 -#define MAXTOUCH 32 - -#define MOVERESULT_NONE 0 // nothing blocking -#define MOVERESULT_TURNED 1 // move blocked, but player turned to avoid it -#define MOVERESULT_BLOCKED 2 // move blocked by slope or wall -#define MOVERESULT_HITWALL 3 // player ran into wall + enum moveresult_e { + MOVERESULT_NONE, // nothing blocking + MOVERESULT_TURNED, // move blocked, but player turned to avoid it + MOVERESULT_BLOCKED, // move blocked by slope or wall + MOVERESULT_HITWALL // player ran into wall + }; typedef struct { // state (in / out) @@ -339,7 +331,7 @@ movement on the server game. // // Openmohaa addition // - int protocol; + int protocol; float leanSpeed; float leanRecoverSpeed; float leanAdd; @@ -359,35 +351,33 @@ movement on the server game. //=================================================================================== -#define MAX_LETTERBOX_SIZE 0x7fff + static const unsigned int MAX_LETTERBOX_SIZE = 0x7fff; -#define ITEM_NAME_AMMO 0 -#define ITEM_NAME_WEAPON 1 - -#define WEAPON_CLASS_PISTOL (1 << 0) -#define WEAPON_CLASS_RIFLE (1 << 1) -#define WEAPON_CLASS_SMG (1 << 2) -#define WEAPON_CLASS_MG (1 << 3) -#define WEAPON_CLASS_GRENADE (1 << 4) -#define WEAPON_CLASS_HEAVY (1 << 5) -#define WEAPON_CLASS_CANNON (1 << 6) -#define WEAPON_CLASS_ITEM (1 << 7) -#define WEAPON_CLASS_ITEM1 (1 << 8) -#define WEAPON_CLASS_ITEM2 (1 << 9) -#define WEAPON_CLASS_ITEM3 (1 << 10) -#define WEAPON_CLASS_ITEM4 (1 << 11) -#define WEAPON_CLASS_ANY_ITEM \ - (WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4) - -#define WEAPON_CLASS_PRIMARY (!(WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE)) -#define WEAPON_CLASS_SECONDARY (WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE) -#define WEAPON_CLASS_THROWABLE (WEAPON_CLASS_GRENADE | WEAPON_CLASS_ITEM) -#define WEAPON_CLASS_MISC \ - (WEAPON_CLASS_CANNON | WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 \ - | WEAPON_CLASS_ITEM4) -#define WEAPON_CLASS_ITEMINDEX (WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4) - -#define STAT_DEAD_YAW 5 // su44: Is there a DEAD_YAW stat in MoHAA? + enum weaponclass_e { + WEAPON_CLASS_PISTOL = (1 << 0), + WEAPON_CLASS_RIFLE = (1 << 1), + WEAPON_CLASS_SMG = (1 << 2), + WEAPON_CLASS_MG = (1 << 3), + WEAPON_CLASS_GRENADE = (1 << 4), + WEAPON_CLASS_HEAVY = (1 << 5), + WEAPON_CLASS_CANNON = (1 << 6), + WEAPON_CLASS_ITEM = (1 << 7), + WEAPON_CLASS_ITEM1 = (1 << 8), + WEAPON_CLASS_ITEM2 = (1 << 9), + WEAPON_CLASS_ITEM3 = (1 << 10), + WEAPON_CLASS_ITEM4 = (1 << 11), + WEAPON_CLASS_ANY_ITEM = + (WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4), + WEAPON_CLASS_ITEM_SLOT_BITS = + (WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4), + WEAPON_CLASS_PRIMARY = (!(WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE)), + WEAPON_CLASS_SECONDARY = (WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE), + WEAPON_CLASS_THROWABLE = (WEAPON_CLASS_GRENADE | WEAPON_CLASS_ITEM), + WEAPON_CLASS_MISC = + (WEAPON_CLASS_CANNON | WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 + | WEAPON_CLASS_ITEM4), + WEAPON_CLASS_ITEMINDEX = (WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4) + }; // player_state->persistant[] indexes // these fields are the only part of player_state that isn't @@ -400,6 +390,7 @@ movement on the server game. // entityState_t->eFlags // su44: eFlags used in MoHAA +#define EF_EVERYFRAME 0x00000008 #define EF_CLIMBWALL 0x00000010 #define EF_UNARMED 0x00000020 // su44: this player has his weapon holstered #define EF_LINKANGLES 0x00000040 @@ -407,6 +398,8 @@ movement on the server game. #define EF_AXIS 0x00000100 // su44: this player is in axis team #define EF_ANY_TEAM (EF_ALLIES | EF_AXIS) #define EF_DEAD 0x00000200 // don't draw a foe marker over players with EF_DEAD +#define EF_NO_LERP 0x00001000 // don't lerp animations + // // Team assault flags // @@ -431,33 +424,11 @@ movement on the server game. #define EF_AWARD_ASSIST 0x00020000 // draw a assist sprite #define EF_AWARD_DENIED 0x00040000 // denied #define EF_TEAMVOTED 0x00080000 // already cast a team vote -#define EF_EVERYFRAME 0x00100000 // def commands will be run every client frame #define EF_ANTISBJUICE 0x00200000 // anti sucknblow juice #define EF_DONT_PROCESS_COMMANDS 0x00400000 // don't process client commands for this entity -// these defines could be deleted sometime when code/game/ is cleared of Q3A stuff -#define TEAM_FREE 0 -#define TEAM_RED 4 -#define TEAM_BLUE 3 -#define TEAM_NUM_TEAMS 5 - //=================================================================================== -// flip the togglebit every time an animation -// changes so a restart of the same anim can be detected -#define ANIM_TOGGLEBIT (1 << 9) -#define ANIM_BLEND (1 << 10) -#define ANIM_NUMBITS 11 - -// server side anim bits -#define ANIM_SERVER_EXITCOMMANDS_PROCESSED (1 << 12) - -#define ANIM_MASK (~(ANIM_TOGGLEBIT | ANIM_BLEND | ANIM_SERVER_EXITCOMMANDS_PROCESSED)) - -// if FRAME_EXPLICIT is set, don't auto animate -#define FRAME_EXPLICIT 512 -#define FRAME_MASK (~FRAME_EXPLICIT) - // // Tag specific flags // @@ -558,8 +529,8 @@ movement on the server game. STAT_MAXCLIPAMMO, STAT_INZOOM, STAT_CROSSHAIR, - STAT_LAST_PAIN, - STAT_NEXTHEALTH, // was unused until 2.0 + STAT_LAST_PAIN, + STAT_NEXTHEALTH, // was unused until 2.0 STAT_BOSSHEALTH, STAT_CINEMATIC, STAT_ADDFADE, @@ -570,9 +541,9 @@ movement on the server game. STAT_OBJECTIVECENTER, STAT_TEAM, STAT_KILLS, - STAT_DEATHS, - STAT_VEHICLE_HEALTH, // was unused until 2.0 - STAT_VEHICLE_MAX_HEALTH, // was unused until 2.0 + STAT_DEATHS, + STAT_VEHICLE_HEALTH, // was unused until 2.0 + STAT_VEHICLE_MAX_HEALTH, // was unused until 2.0 STAT_HIGHEST_SCORE, STAT_ATTACKERCLIENT, STAT_INFOCLIENT, @@ -589,7 +560,8 @@ movement on the server game. TEAM_SPECTATOR, TEAM_FREEFORALL, TEAM_ALLIES, - TEAM_AXIS + TEAM_AXIS, + TEAM_MAX } teamtype_t; typedef enum { @@ -598,9 +570,6 @@ movement on the server game. SWT_FUSE_WET } stopWatchType_t; -// How many players on the overlay -#define TEAM_MAXOVERLAY 32 - //--------------------------------------------------------- // g_dmflags->integer flags @@ -635,28 +604,41 @@ movement on the server game. #define DF_WEAPON_NO_SHOTGUN (1 << 27) #define DF_WEAPON_NO_LANDMINE (1 << 28) -#define DM_FLAG(flag) (g_gametype->integer && ((int)dmflags->integer & (flag))) +#define DM_FLAG(flag) (g_gametype->integer != GT_SINGLE_PLAYER && ((int)dmflags->integer & (flag))) -// content masks -#define MASK_ALL (-1) -#define MASK_SOLID (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) + // + // Content masks + // + +#define MASK_ALL (-1) +#define MASK_SOLID \ + (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX | CONTENTS_FENCE) #define MASK_SAFESOLID (CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) #define MASK_USABLE (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_BODY) -#define MASK_PLAYERSOLID \ - (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_UNKNOWN2 \ - | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) -#define MASK_PLAYERSTART (CONTENTS_SOLID|CONTENTS_BBOX|CONTENTS_NOBOTCLIP|CONTENTS_UNKNOWN2|CONTENTS_BODY) -#define MASK_VIEWSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_FENCE | CONTENTS_TRIGGER) -#define MASK_DEADSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_CORPSE | CONTENTS_NOTTEAM2 | CONTENTS_FENCE) -#define MASK_MONSTERSOLID (CONTENTS_SOLID | CONTENTS_MONSTERCLIP | CONTENTS_BODY) -#define MASK_WATER (CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME) -#define MASK_OPAQUE (CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA) -#define MASK_SHOT \ - (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE \ - | CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER) -#define MASK_SHOT_TRIG \ - (CONTENTS_SOLID | CONTENTS_CLAYPIDGEON | CONTENTS_WATER | CONTENTS_BBOX | CONTENTS_NOBOTCLIP \ - | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER) +#define MASK_PLAYERSOLID \ + (CONTENTS_TRIGGER | CONTENTS_BODY | CONTENTS_PLAYERCLIP | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP \ + | CONTENTS_BBOX | CONTENTS_SOLID) +#define MASK_GUNTARGET \ + (CONTENTS_SOLID | CONTENTS_LADDER | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_CLAYPIDGEON | CONTENTS_BBOX \ + | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_UNKNOWN3 | CONTENTS_FENCE | CONTENTS_BODY | CONTENTS_CORPSE \ + | CONTENTS_TRIGGER) +#define MASK_FOOTSHADOW (CONTENTS_FENCE | CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_SOLID) +#define MASK_PLAYERSTART (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_BODY) +#define MASK_VIEWSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_FENCE | CONTENTS_TRIGGER) +#define MASK_DEADSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_CORPSE | CONTENTS_NOTTEAM2 | CONTENTS_FENCE) +#define MASK_MONSTERSOLID \ + (CONTENTS_SOLID | CONTENTS_MONSTERCLIP | CONTENTS_BODY | CONTENTS_TRIGGER | CONTENTS_UNKNOWN2 | CONTENTS_BBOX) +#define MASK_WATER (CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME) +#define MASK_OPAQUE (CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA) +#define MASK_SHOT \ + (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP \ + | CONTENTS_BODY | CONTENTS_TRIGGER) +#define MASK_SHOT_TRIG \ + (CONTENTS_SOLID | CONTENTS_CLAYPIDGEON | CONTENTS_WATER | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \ + | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER) +#define MASK_SHOT_FLUID \ + (CONTENTS_SOLID | CONTENTS_WATER | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE \ + | CONTENTS_WEAPONCLIP | CONTENTS_SHOOTONLY | CONTENTS_BODY | CONTENTS_TRIGGER) #define MASK_PROJECTILE \ (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_UNKNOWN2 \ | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) @@ -666,24 +648,38 @@ movement on the server game. #define MASK_PATHSOLID \ (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_BODY | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_BBOX \ | CONTENTS_MONSTERCLIP) +#define MASK_LOOK (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FENCE) #define MASK_CAMERASOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_BODY | MASK_WATER) #define MASK_BEAM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE) #define MASK_LADDER \ - (CONTENTS_SOLID | CONTENTS_LADDER | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE) + (CONTENTS_SOLID | CONTENTS_LADDER | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) #define MASK_AUTOCALCLIFE (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_FENCE) #define MASK_EXPLOSION (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_WEAPONCLIP) #define MASK_SOUND (CONTENTS_SOLID | CONTENTS_TRANSLUCENT) -#define MASK_VEHICLE (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_VEHICLECLIP | CONTENTS_BODY | CONTENTS_TRIGGER) +#define MASK_VEHICLE \ + (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_VEHICLECLIP \ + | CONTENTS_BODY | CONTENTS_TRIGGER) +#define MASK_VEHICLE_TIRES (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_FENCE | CONTENTS_VEHICLECLIP | CONTENTS_TRIGGER) #define MASK_CLICK \ - (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN3 | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) -#define MASK_CANSEE \ - (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_WEAPONCLIP | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_SLIME \ - | CONTENTS_LAVA | CONTENTS_BBOX) -#define MASK_ITEM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_FENCE) -#define MASK_TRANSITION \ - (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_UNKNOWN2 | CONTENTS_NOTTEAM1 | CONTENTS_WEAPONCLIP) + (CONTENTS_VEHICLECLIP | CONTENTS_WEAPONCLIP | CONTENTS_MONSTERCLIP | CONTENTS_PLAYERCLIP | CONTENTS_SOLID) +#define MASK_CANSEE \ + (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \ + | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY) +#define MASK_CANSEE_NOENTS (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FENCE | CONTENTS_WEAPONCLIP) +#define MASK_USE \ + (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP \ + | CONTENTS_BODY | CONTENTS_TRIGGER) +#define MASK_CLICKITEM (MASK_SOLID | CONTENTS_UNKNOWN3) +#define MASK_ITEM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_FENCE) +#define MASK_TRANSITION \ + (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_UNKNOWN2 \ + | CONTENTS_BBOX) #define MASK_TARGETPATH \ (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_MONSTERCLIP | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_BBOX) +#define MASK_ACTORPATH (CONTENTS_SOLID | CONTENTS_FENCE | CONTENTS_MONSTERCLIP | CONTENTS_TRIGGER) +#define MASK_GRENADEPATH \ + (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP \ + | CONTENTS_BODY | CONTENTS_TRIGGER) #define MASK_LINE (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX) #define MASK_VEHICLETURRET \ (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_VEHICLECLIP | CONTENTS_MONSTERCLIP \ @@ -700,52 +696,41 @@ movement on the server game. #define MASK_BATTLELANGUAGE \ (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_PLAYERCLIP \ | CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER) -#define MASK_SCRIPT_SLAVE (CONTENTS_LADDER|CONTENTS_CLAYPIDGEON|CONTENTS_BBOX|CONTENTS_NOBOTCLIP|CONTENTS_UNKNOWN2|CONTENTS_UNKNOWN3|CONTENTS_BODY|CONTENTS_CORPSE) +#define MASK_SCRIPT_SLAVE \ + (CONTENTS_LADDER | CONTENTS_CLAYPIDGEON | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \ + | CONTENTS_UNKNOWN3 | CONTENTS_BODY | CONTENTS_CORPSE) +#define MASK_CARRYABLETURRET \ + (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_BODY) +#define MASK_AITURRET \ + (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \ + | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY) +#define MASK_TRANSPARENT (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_FENCE) +#define MASK_MOVEVEHICLE \ + (CONTENTS_LADDER | CONTENTS_CLAYPIDGEON | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN3 | CONTENTS_BODY \ + | CONTENTS_CORPSE) +#define MASK_MOVEINFO (CONTENTS_SOLID | CONTENTS_FENCE) +#define MASK_AI_CANSEE \ + (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_UNKNOWN2 | CONTENTS_FENCE \ + | CONTENTS_WEAPONCLIP) +#define MASK_CORNER_NODE \ + (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_UNKNOWN2 | CONTENTS_WEAPONCLIP | CONTENTS_BODY) +#define MASK_IGNORE_ENTS \ + (CONTENTS_CORPSE | CONTENTS_BODY | CONTENTS_UNKNOWN3 | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX \ + | CONTENTS_CLAYPIDGEON | CONTENTS_LADDER) - // mohaa mask - /* -#define MASK_ALL -1 -#define MASK_SOLID 1 - -#define MASK_COLLISION 0x26000B21 -#define MASK_PERMANENTMARK 0x40000001 -#define MASK_AUTOCALCLIFE 0x40002021 -#define MASK_EXPLOSION 0x40040001 -#define MASK_TREADMARK 0x42012B01 -#define MASK_THIRDPERSON 0x42012B39 -#define MASK_FOOTSTEP 0x42022901 -#define MASK_BEAM 0x42042B01 -#define MASK_VISIBLE 0x42042B01 -#define MASK_VEHICLE 0x42042B01 -#define MASK_BULLET 0x42042B21 -#define MASK_SHOT 0x42042BA1 -#define MASK_CROSSHAIRSHADER 0x42092B01 -#define MASK_TRACER 0x42142B21 -*/ +// +// Marks +// +#define MASK_MARK (CONTENTS_TRIGGER | CONTENTS_SOLID) +#define MASK_TREADMARK \ + (CONTENTS_TRIGGER | CONTENTS_BODY | CONTENTS_PLAYERCLIP | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP \ + | CONTENTS_BBOX | CONTENTS_SOLID) void BG_EvaluateTrajectoryDelta(const trajectory_t *tr, int atTime, vec3_t result); void BG_PlayerStateToEntityState(playerState_t *ps, entityState_t *s, qboolean snap); void BG_PlayerStateToEntityStateExtraPolate(playerState_t *ps, entityState_t *s, int time, qboolean snap); - enum vmAnim_e { - VM_ANIM_DISABLED, - VM_ANIM_IDLE, - VM_ANIM_CHARGE, - VM_ANIM_FIRE, - VM_ANIM_FIRE_SECONDARY, - VM_ANIM_RECHAMBER, - VM_ANIM_RELOAD, - VM_ANIM_RELOAD_SINGLE, - VM_ANIM_RELOAD_END, - VM_ANIM_PULLOUT, - VM_ANIM_PUTAWAY, - VM_ANIM_LADDERSTEP, - VM_ANIM_IDLE_0, - VM_ANIM_IDLE_1, - VM_ANIM_IDLE_2, - }; - enum cg_message_ver_15_e { CGM_NONE, CGM_BULLET_1, @@ -785,10 +770,10 @@ movement on the server game. CGM_HUDDRAW_ALPHA, CGM_HUDDRAW_STRING, CGM_HUDDRAW_FONT, - CGM_NOTIFY_KILL, CGM_NOTIFY_HIT, + CGM_NOTIFY_KILL, CGM_VOICE_CHAT, - CGM_UNKNOWN_1, + CGM_FENCEPOST, }; enum cg_message_ver_6_e { @@ -827,8 +812,8 @@ movement on the server game. CGM6_HUDDRAW_ALPHA, CGM6_HUDDRAW_STRING, CGM6_HUDDRAW_FONT, - CGM6_NOTIFY_KILL, CGM6_NOTIFY_HIT, + CGM6_NOTIFY_KILL, CGM6_VOICE_CHAT, }; @@ -839,10 +824,10 @@ movement on the server game. #endif typedef enum { - OBJ_FLAG_NONE, - OBJ_FLAG_HIDDEN = 1, - OBJ_FLAG_CURRENT = 2, - OBJ_FLAG_COMPLETED = 4 + OBJ_FLAG_NONE, + OBJ_FLAG_HIDDEN = 1, + OBJ_FLAG_CURRENT = 2, + OBJ_FLAG_COMPLETED = 4 } objective_flags_t; typedef enum { @@ -851,5 +836,3 @@ typedef enum { OBJ_STATUS_CURRENT, OBJ_STATUS_COMPLETED } objective_status_t; - -#endif /* bg_public.h */ diff --git a/code/fgame/bg_slidemove.cpp b/code/fgame/bg_slidemove.cpp index 59e79211..60d07da8 100644 --- a/code/fgame/bg_slidemove.cpp +++ b/code/fgame/bg_slidemove.cpp @@ -41,191 +41,186 @@ PM_SlideMove Returns qtrue if the velocity was clipped in some way ================== */ -#define MAX_CLIP_PLANES 5 -qboolean PM_SlideMove( qboolean gravity ) +#define MAX_CLIP_PLANES 5 + +qboolean PM_SlideMove(qboolean gravity) { - int bumpcount, numbumps; - vec3_t dir; - float d; - int numplanes; - vec3_t planes[ MAX_CLIP_PLANES ]; - vec3_t primal_velocity; - vec3_t clipVelocity; - int i, j, k; - trace_t trace; - vec3_t end; - float time_left; - float into; - vec3_t endVelocity; - vec3_t endClipVelocity; + int bumpcount, numbumps; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[MAX_CLIP_PLANES]; + vec3_t clipVelocity; + int i, j, k; + trace_t trace; + vec3_t end; + float time_left; + float into; + vec3_t endVelocity; + vec3_t endClipVelocity; - numbumps = 4; + numbumps = 4; - VectorCopy( pm->ps->velocity, primal_velocity ); + VectorCopy(pm->ps->velocity, endVelocity); - if( gravity ) { - VectorCopy( pm->ps->velocity, endVelocity ); - endVelocity[ 2 ] -= pm->ps->gravity * pml.frametime; - pm->ps->velocity[ 2 ] = ( pm->ps->velocity[ 2 ] + endVelocity[ 2 ] ) * 0.5; - primal_velocity[ 2 ] = endVelocity[ 2 ]; - if( pml.groundPlane ) { - // slide along the ground plane - PM_ClipVelocity( pm->ps->velocity, pml.groundTrace.plane.normal, - pm->ps->velocity, OVERCLIP ); - } - } + if (gravity) { + endVelocity[2] -= pm->ps->gravity * pml.frametime; + pm->ps->velocity[2] = (pm->ps->velocity[2] + endVelocity[2]) * 0.5; + if (pml.groundPlane) { + // slide along the ground plane + PM_ClipVelocity(pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP); + } + } - time_left = pml.frametime; + time_left = pml.frametime; - // never turn against the ground plane - if( pml.groundPlane ) { - numplanes = 1; - VectorCopy( pml.groundTrace.plane.normal, planes[ 0 ] ); - } - else { - numplanes = 0; - } + // never turn against the ground plane + if (pml.groundPlane) { + numplanes = 1; + VectorCopy(pml.groundTrace.plane.normal, planes[0]); + } else { + numplanes = 0; + } - // never turn against original velocity - VectorNormalize2( pm->ps->velocity, planes[ numplanes ] ); - numplanes++; + // never turn against original velocity + VectorNormalize2(pm->ps->velocity, planes[numplanes]); + numplanes++; - for( bumpcount = 0; bumpcount < numbumps; bumpcount++ ) { + for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { + // calculate position we are trying to move to + VectorMA(pm->ps->origin, time_left, pm->ps->velocity, end); - // calculate position we are trying to move to - VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end ); + // see if we can make it there + pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); - // see if we can make it there - pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); + if (trace.allsolid) { + // entity is completely trapped in another solid + pm->ps->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration + return qtrue; + } - if( trace.allsolid ) { - // entity is completely trapped in another solid - pm->ps->velocity[ 2 ] = 0; // don't build up falling damage, but allow sideways acceleration - return qtrue; - } + if (trace.fraction > 0) { + // actually covered some distance + VectorCopy(trace.endpos, pm->ps->origin); + } - if( trace.fraction > 0 ) { - // actually covered some distance - VectorCopy( trace.endpos, pm->ps->origin ); - } + if (trace.fraction == 1) { + break; // moved the entire distance + } - if( trace.fraction == 1 ) { - break; // moved the entire distance - } + if ((trace.plane.normal[2] < MIN_WALK_NORMAL) && (trace.plane.normal[2] > 0) + && DotProduct(trace.plane.normal, pm->ps->velocity) <= 0) { + // treat steep walls as vertical + trace.plane.normal[2] = 0; + VectorNormalizeFast(trace.plane.normal); + } - if( ( trace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) && ( trace.plane.normal[ 2 ] > 0 ) ) - { - // treat steep walls as vertical - trace.plane.normal[ 2 ] = 0; - VectorNormalizeFast( trace.plane.normal ); - } + // save entity for contact + PM_AddTouchEnt(trace.entityNum); - // save entity for contact - PM_AddTouchEnt( trace.entityNum ); + time_left -= time_left * trace.fraction; - time_left -= time_left * trace.fraction; + if (numplanes >= MAX_CLIP_PLANES) { + // this shouldn't really happen + VectorClear(pm->ps->velocity); + return qtrue; + } - if( numplanes >= MAX_CLIP_PLANES ) { - // this shouldn't really happen - VectorClear( pm->ps->velocity ); - return qtrue; - } + // + // if this is the same plane we hit before, nudge velocity + // out along it, which fixes some epsilon issues with + // non-axial planes + // + for (i = 0; i < numplanes; i++) { + if (DotProduct(trace.plane.normal, planes[i]) > 0.99) { + VectorAdd(trace.plane.normal, pm->ps->velocity, pm->ps->velocity); + break; + } + } + if (i < numplanes) { + continue; + } + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; - // - // if this is the same plane we hit before, nudge velocity - // out along it, which fixes some epsilon issues with - // non-axial planes - // - for( i = 0; i < numplanes; i++ ) { - if( DotProduct( trace.plane.normal, planes[ i ] ) > 0.99 ) { - VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity ); - break; - } - } - if( i < numplanes ) { - continue; - } - VectorCopy( trace.plane.normal, planes[ numplanes ] ); - numplanes++; + // + // modify velocity so it parallels all of the clip planes + // - // - // modify velocity so it parallels all of the clip planes - // + // find a plane that it enters + for (i = 0; i < numplanes; i++) { + into = DotProduct(pm->ps->velocity, planes[i]); + if (into >= 0.1) { + continue; // move doesn't interact with the plane + } - // find a plane that it enters - for( i = 0; i < numplanes; i++ ) { - into = DotProduct( pm->ps->velocity, planes[ i ] ); - if( into >= 0.1 ) { - continue; // move doesn't interact with the plane - } + // see how hard we are hitting things + if (-into > pml.impactSpeed) { + pml.impactSpeed = -into; + } - // see how hard we are hitting things - if( -into > pml.impactSpeed ) { - pml.impactSpeed = -into; - } + // slide along the plane + PM_ClipVelocity(pm->ps->velocity, planes[i], clipVelocity, OVERCLIP); - // slide along the plane - PM_ClipVelocity( pm->ps->velocity, planes[ i ], clipVelocity, OVERCLIP ); + // slide along the plane + PM_ClipVelocity(endVelocity, planes[i], endClipVelocity, OVERCLIP); - // slide along the plane - PM_ClipVelocity( endVelocity, planes[ i ], endClipVelocity, OVERCLIP ); + // see if there is a second plane that the new move enters + for (j = 0; j < numplanes; j++) { + if (j == i) { + continue; + } + if (DotProduct(clipVelocity, planes[j]) >= 0.1) { + continue; // move doesn't interact with the plane + } - // see if there is a second plane that the new move enters - for( j = 0; j < numplanes; j++ ) { - if( j == i ) { - continue; - } - if( DotProduct( clipVelocity, planes[ j ] ) >= 0.1 ) { - continue; // move doesn't interact with the plane - } + // try clipping the move to the plane + PM_ClipVelocity(clipVelocity, planes[j], clipVelocity, OVERCLIP); + PM_ClipVelocity(endClipVelocity, planes[j], endClipVelocity, OVERCLIP); - // try clipping the move to the plane - PM_ClipVelocity( clipVelocity, planes[ j ], clipVelocity, OVERCLIP ); - PM_ClipVelocity( endClipVelocity, planes[ j ], endClipVelocity, OVERCLIP ); + // see if it goes back into the first clip plane + if (DotProduct(clipVelocity, planes[i]) >= 0) { + continue; + } - // see if it goes back into the first clip plane - if( DotProduct( clipVelocity, planes[ i ] ) >= 0 ) { - continue; - } + // slide the original velocity along the crease + CrossProduct(planes[i], planes[j], dir); + VectorNormalize(dir); + d = DotProduct(dir, pm->ps->velocity); + VectorScale(dir, d, clipVelocity); - // slide the original velocity along the crease - CrossProduct( planes[ i ], planes[ j ], dir ); - VectorNormalize( dir ); - d = DotProduct( dir, pm->ps->velocity ); - VectorScale( dir, d, clipVelocity ); + CrossProduct(planes[i], planes[j], dir); + VectorNormalize(dir); + d = DotProduct(dir, endVelocity); + VectorScale(dir, d, endClipVelocity); - CrossProduct( planes[ i ], planes[ j ], dir ); - VectorNormalize( dir ); - d = DotProduct( dir, endVelocity ); - VectorScale( dir, d, endClipVelocity ); + // see if there is a third plane the the new move enters + for (k = 0; k < numplanes; k++) { + if (k == i || k == j) { + continue; + } + if (DotProduct(clipVelocity, planes[k]) >= 0.1) { + continue; // move doesn't interact with the plane + } - // see if there is a third plane the the new move enters - for( k = 0; k < numplanes; k++ ) { - if( k == i || k == j ) { - continue; - } - if( DotProduct( clipVelocity, planes[ k ] ) >= 0.1 ) { - continue; // move doesn't interact with the plane - } + // stop dead at a tripple plane interaction + VectorClear(pm->ps->velocity); + return qtrue; + } + } - // stop dead at a tripple plane interaction - VectorClear( pm->ps->velocity ); - return qtrue; - } - } + // if we have fixed all interactions, try another move + VectorCopy(clipVelocity, pm->ps->velocity); + VectorCopy(endClipVelocity, endVelocity); + break; + } + } - // if we have fixed all interactions, try another move - VectorCopy( clipVelocity, pm->ps->velocity ); - VectorCopy( endClipVelocity, endVelocity ); - break; - } - } + if (gravity) { + VectorCopy(endVelocity, pm->ps->velocity); + } - if( gravity ) { - VectorCopy( endVelocity, pm->ps->velocity ); - } - - return ( bumpcount != 0 ); + return (bumpcount != 0); } /* @@ -234,89 +229,80 @@ PM_StepSlideMove ================== */ -void PM_StepSlideMove( qboolean gravity ) +void PM_StepSlideMove(qboolean gravity) { - vec3_t start_o; - vec3_t start_v; - vec3_t nostep_o; - vec3_t nostep_v; - trace_t trace; - qboolean bWasOnGoodGround; - vec3_t up; - vec3_t down; + vec3_t start_o; + vec3_t start_v; + vec3_t nostep_o; + vec3_t nostep_v; + trace_t trace; + qboolean bWasOnGoodGround; + vec3_t up; + vec3_t down; - VectorCopy( pm->ps->origin, start_o ); - VectorCopy( pm->ps->velocity, start_v ); + VectorCopy(pm->ps->origin, start_o); + VectorCopy(pm->ps->velocity, start_v); - if ( PM_SlideMove( gravity ) == 0 ) { - return; // we got exactly where we wanted to go first try - } + if (PM_SlideMove(gravity) == 0) { + return; // we got exactly where we wanted to go first try + } - VectorCopy( start_o, down ); - down[ 2 ] -= STEPSIZE; - pm->trace( &trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - VectorSet( up, 0, 0, 1 ); + VectorCopy(start_o, down); + down[2] -= STEPSIZE; + pm->trace(&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + VectorSet(up, 0, 0, 1); - // never step up when you still have up velocity - if( pm->ps->velocity[ 2 ] > 0 && ( trace.fraction == 1.0f || - DotProduct( trace.plane.normal, up ) < MIN_WALK_NORMAL ) ) { - return; - } + // never step up when you still have up velocity + if (pm->ps->velocity[2] > 0 && (trace.fraction == 1.0f || DotProduct(trace.plane.normal, up) < MIN_WALK_NORMAL)) { + return; + } - if( pml.groundPlane && pml.groundTrace.plane.normal[ 2 ] >= MIN_WALK_NORMAL ) - { - bWasOnGoodGround = true; - } - else - { - bWasOnGoodGround = false; - } + if (pml.groundPlane && pml.groundTrace.plane.normal[2] >= MIN_WALK_NORMAL) { + bWasOnGoodGround = true; + } else { + bWasOnGoodGround = false; + } - VectorCopy( start_o, up ); - up[ 2 ] += STEPSIZE; + VectorCopy(start_o, up); + up[2] += STEPSIZE; - // test the player position if they were a stepheight higher - pm->trace( &trace, up, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - if( trace.allsolid ) - { - up[ 2 ] -= 9.0f; - pm->trace( &trace, up, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - if( trace.allsolid ) - { - return; - } - } + // test the player position if they were a stepheight higher + pm->trace(&trace, up, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + if (trace.allsolid) { + up[2] -= 9.0f; + pm->trace(&trace, up, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + if (trace.allsolid) { + return; + } + } - VectorCopy( pm->ps->origin, nostep_o ); - VectorCopy( pm->ps->velocity, nostep_v ); + VectorCopy(pm->ps->origin, nostep_o); + VectorCopy(pm->ps->velocity, nostep_v); - // try slidemove from this position - VectorCopy( up, pm->ps->origin ); - VectorCopy( start_v, pm->ps->velocity ); + // try slidemove from this position + VectorCopy(up, pm->ps->origin); + VectorCopy(start_v, pm->ps->velocity); - PM_SlideMove( gravity ); + PM_SlideMove(gravity); - // push down the final amount - VectorCopy( pm->ps->origin, down ); - down[ 2 ] -= STEPSIZE; + // push down the final amount + VectorCopy(pm->ps->origin, down); + down[2] -= STEPSIZE; - pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, qtrue, qfalse ); - if( !trace.allsolid ) - { - if( bWasOnGoodGround && trace.fraction < 1.0 && trace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - VectorCopy( nostep_o, pm->ps->origin ); - VectorCopy( nostep_v, pm->ps->velocity ); - return; - } + pm->trace(&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask, qtrue, qfalse); + if (!trace.allsolid) { + if (bWasOnGoodGround && trace.fraction < 1.0 && trace.plane.normal[2] < MIN_WALK_NORMAL) { + VectorCopy(nostep_o, pm->ps->origin); + VectorCopy(nostep_v, pm->ps->velocity); + return; + } - VectorCopy( trace.endpos, pm->ps->origin ); - } + VectorCopy(trace.endpos, pm->ps->origin); + } - if ( trace.fraction < 1.0f ) { - PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); - } + if (trace.fraction < 1.0f) { + PM_ClipVelocity(pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP); + } - pm->stepped = qtrue; + pm->stepped = qtrue; } - diff --git a/code/fgame/bg_voteoptions.cpp b/code/fgame/bg_voteoptions.cpp index ce1b49e8..8c9e20bb 100644 --- a/code/fgame/bg_voteoptions.cpp +++ b/code/fgame/bg_voteoptions.cpp @@ -21,5 +21,721 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "bg_voteoptions.h" +#include "../qcommon/script.h" -// FIXME: unimplemented +#if defined(GAME_DLL) +# define VO_FS_FreeFile gi.FS_FreeFile +# define VO_FS_ReadFile(a, b) gi.FS_ReadFile(a, b, true) +# define VO_SendRemoteCommand(s) // ? +# define VO_ExecuteCommand(s) gi.Cmd_Execute(EXEC_NOW, s) +# define VO_Cvar_Set(name, value) gi.cvar_set(name, value) +# define VO_Cvar_Get(name, value, flags) gi.Cvar_Get(name, value, flags) +# define VO_LV_ConvertString(s) gi.LV_ConvertString(s) +#elif defined(CGAME_DLL) +# define VO_FS_FreeFile cgi.FS_FreeFile +# define VO_FS_ReadFile(a, b) cgi.FS_ReadFile(a, b, qtrue) +# define VO_SendRemoteCommand(s) cgi.SendClientCommand(s) +# define VO_ExecuteCommand(s) cgi.Cmd_Execute(EXEC_NOW, s) +# define VO_Cvar_Set(name, value) cgi.Cvar_Set(name, value) +# define VO_Cvar_Get(name, value, flags) cgi.Cvar_Get(name, value, flags) +# define VO_LV_ConvertString(s) cgi.LV_ConvertString(s) +#else +# pragma error("VoteOptions can must be used with fgame or cgame") +#endif + +CLASS_DECLARATION(Class, VoteOptions, NULL) { + {NULL, NULL} +}; + +VoteOptionListItem::VoteOptionListItem() + : m_pNext(NULL) +{} + +SingleVoteOption::SingleVoteOption() + : m_optionType(VOTE_NO_CHOICES) + , m_pListItem(NULL) + , m_pNext(NULL) +{} + +SingleVoteOption::~SingleVoteOption() +{ + VoteOptionListItem *item; + VoteOptionListItem *next; + + for (item = m_pListItem; item; item = next) { + next = item->m_pNext; + delete item; + } +} + +VoteOptions::VoteOptions() +{ + m_pHeadOption = NULL; +} + +VoteOptions::~VoteOptions() +{ + ClearOptions(); +} + +void VoteOptions::ClearOptions() +{ + SingleVoteOption *option; + SingleVoteOption *next; + + for (option = m_pHeadOption; option; option = next) { + next = option->m_pNext; + delete option; + } + + m_pHeadOption = NULL; +} + +void VoteOptions::SetupVoteOptions(const char *configFileName) +{ + char *buffer; + int compressedLength; + long length; + + length = VO_FS_ReadFile(configFileName, (void **)&buffer); + if (length == -1 || !length) { + Com_Printf("WARNING: Couldn't find voting options file: %s\n", configFileName); + return; + } + + // compress the buffer before setting up + compressedLength = COM_Compress(buffer); + SetupVoteOptions(configFileName, compressedLength, buffer); + VO_FS_FreeFile(buffer); +} + +void VoteOptions::SetupVoteOptions(const char *configFileName, int length, const char *buffer) +{ + if (length >= MAX_VOTEOPTIONS_BUFFER_LENGTH) { + Com_Error( + ERR_DROP, + "VoteOptions: Options file '%s' is too big. Max size is %lu bytes\n", + configFileName, + MAX_VOTEOPTIONS_BUFFER_LENGTH + ); + return; + } + + m_sFileName = configFileName; + m_sBuffer = buffer; + + ParseVoteOptions(); +} + +void VoteOptions::ParseVoteOptions() +{ + SingleVoteOption *option; + SingleVoteOption *newOption; + VoteOptionListItem *listItem; + VoteOptionListItem *newListItem; + str token; + Script script; + + ClearOptions(); + script.LoadFile(m_sFileName.c_str(), m_sBuffer.length(), m_sBuffer.c_str()); + + option = m_pHeadOption; + + while (script.TokenAvailable(true)) { + token = script.GetToken(true); + + if (!str::icmp(token, "{")) { + Com_Error( + ERR_DROP, + "Vote Options %s: Found choices list without option header on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + if (!str::icmp(token, "}")) { + Com_Error( + ERR_DROP, + "Vote Options %s: Illegal end of choices list without list being started on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + if (!token.length()) { + Com_Error( + ERR_DROP, + "Vote Options %s: Empty option name on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + newOption = new SingleVoteOption(); + + if (option) { + option->m_pNext = newOption; + } else { + m_pHeadOption = newOption; + } + option = newOption; + + newOption->m_sOptionName = token; + + if (!script.TokenAvailable(false)) { + Com_Error( + ERR_DROP, + "Vote Options %s: Option without a command specified on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + newOption->m_sCommand = script.GetToken(false); + + if (script.TokenAvailable(false)) { + token = script.GetToken(false); + + if (!str::icmp(token, "nochoices")) { + newOption->m_optionType = VOTE_NO_CHOICES; + } else if (!str::icmp(token, "list")) { + newOption->m_optionType = VOTE_OPTION_LIST; + } else if (!str::icmp(token, "text")) { + newOption->m_optionType = VOTE_OPTION_TEXT; + } else if (!str::icmp(token, "integer")) { + newOption->m_optionType = VOTE_OPTION_INTEGER; + } else if (!str::icmp(token, "float")) { + newOption->m_optionType = VOTE_OPTION_FLOAT; + } else if (!str::icmp(token, "client")) { + newOption->m_optionType = VOTE_OPTION_CLIENT; + } else if (!str::icmp(token, "clientnotself")) { + newOption->m_optionType = VOTE_OPTION_CLIENT_NOT_SELF; + } else { + Com_Error( + ERR_DROP, + "Vote Options %s: Illegal option type '%s' specified on line %d.\n" + " Valid types are nochoices, list, text, & number.\n", + m_sFileName.c_str(), + token.c_str(), + script.GetLineNumber() + ); + return; + } + } + + if (newOption->m_optionType == VOTE_OPTION_LIST) { + if (!script.TokenAvailable(true) || Q_stricmp(script.GetToken(true), "{")) { + Com_Error( + ERR_DROP, + "Vote Options %s: Missing '{'. No choices list specified for list option on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + listItem = NULL; + + while (script.TokenAvailable(true)) { + token = script.GetToken(true); + + if (!str::icmp(token, "}")) { + break; + } + + newListItem = new VoteOptionListItem(); + + if (listItem) { + listItem->m_pNext = newListItem; + } else { + newOption->m_pListItem = newListItem; + } + listItem = newListItem; + newListItem->m_sItemName = token; + + if (!script.TokenAvailable(false)) { + Com_Error( + ERR_DROP, + "Vote Options %s: List choice without vote string specified on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + newListItem->m_sCommand = script.GetToken(false); + } + } else if (script.TokenAvailable(true)) { + token = script.GetToken(true); + + if (!str::icmp(token, "{")) { + Com_Error( + ERR_DROP, + "Vote Options %s: Choices list specified for non-list option on line %d.\n", + m_sFileName.c_str(), + script.GetLineNumber() + ); + return; + } + + script.UnGetToken(); + } + } +} + +const char *VoteOptions::GetVoteOptionsFile(int *outLen) const +{ + if (outLen) { + *outLen = m_sBuffer.length(); + } + + return m_sBuffer.c_str(); +} + +bool VoteOptions::GetVoteOptionsMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) const +{ + SingleVoteOption *option; + int optionIndex; + + if (index < 1) { + return false; + } + + optionIndex = 1; + for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) { + optionIndex++; + } + + if (!option) { + return false; + } + + *outOptionCommand = option->m_sCommand; + *outOptionType = option->m_optionType; + + return true; +} + +bool VoteOptions::GetVoteOptionSub(int index, int listIndex, str *outCommand) const +{ + SingleVoteOption *option; + VoteOptionListItem *item; + int optionIndex; + int itemIndex; + + if (index < 1 || listIndex < 1) { + return false; + } + + optionIndex = 1; + for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) { + optionIndex++; + } + + if (!option) { + return false; + } + + if (option->m_optionType != VOTE_OPTION_LIST) { + return false; + } + + itemIndex = 1; + for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) { + itemIndex++; + } + + if (!item) { + return false; + } + + *outCommand = item->m_sCommand; + + return true; +} + +bool VoteOptions::GetVoteOptionMainName(int index, str *outVoteName) const +{ + SingleVoteOption *option; + int optionIndex; + + if (index < 1) { + return false; + } + + optionIndex = 1; + for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) { + optionIndex++; + } + + if (!option) { + return false; + } + + *outVoteName = option->m_sOptionName; + + return true; +} + +bool VoteOptions::GetVoteOptionSubName(int index, int listIndex, str *outName) const +{ + SingleVoteOption *option; + VoteOptionListItem *item; + int optionIndex; + int itemIndex; + + if (index < 1 || listIndex < 1) { + return false; + } + + optionIndex = 1; + for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) { + optionIndex++; + } + + if (!option) { + return false; + } + + if (option->m_optionType != VOTE_OPTION_LIST) { + return false; + } + + itemIndex = 1; + for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) { + itemIndex++; + } + + if (!item) { + return false; + } + + *outName = item->m_sItemName; + + return true; +} + +#if defined(CGAME_DLL) + +static str g_sVoteString; +static VoteOptions g_voteOptions; + +void CG_VoteOptions_StartReadFromServer(const char *string) +{ + g_sVoteString = string; +} + +void CG_VoteOptions_ContinueReadFromServer(const char *string) +{ + if (g_sVoteString.length() >= MAX_VOTEOPTIONS_BUFFER_LENGTH) { + return; + } + + g_sVoteString += string; +} + +void CG_VoteOptions_FinishReadFromServer(const char *string) +{ + int i; + + if (g_sVoteString.length() >= MAX_VOTEOPTIONS_BUFFER_LENGTH) { + return; + } + + g_sVoteString += va("%s\n", string); + if (!str::cmp(g_sVoteString, "\n")) { + VO_SendRemoteCommand("wait 250;gvo\n"); + return; + } + + for (i = 0; i < g_sVoteString.length(); i++) { + if (g_sVoteString[i] == 1) { + g_sVoteString[i] = '"'; + } + } + + g_voteOptions.SetupVoteOptions("ServerVoteOptions", g_sVoteString.length(), g_sVoteString.c_str()); + g_sVoteString = ""; + g_voteOptions.SetupMainOptionsList(); +} + +void CG_PushCallVote_f(void) +{ + g_voteOptions.SetupMainOptionsList(); +} + +void CG_PushCallVoteSubList_f(void) +{ + g_voteOptions.SetupSubOptionsList(atoi(cgi.Argv(1))); +} + +void CG_PushCallVoteSubText_f(void) +{ + str command; + str name; + voteoptiontype_t type; + + if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) { + return; + } + + if (type != voteoptiontype_t::VOTE_OPTION_TEXT) { + return; + } + + g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name); + VO_ExecuteCommand("forcemenu votesubtext\n"); + VO_Cvar_Set("ui_votesubtitle", name.c_str()); + VO_Cvar_Set("ui_votestringentry", ""); +} + +void CG_PushCallVoteSubInteger_f(void) +{ + str command; + str name; + voteoptiontype_t type; + + if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) { + return; + } + + if (type != voteoptiontype_t::VOTE_OPTION_INTEGER) { + return; + } + + g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name); + VO_ExecuteCommand("forcemenu votesubinteger\n"); + VO_Cvar_Set("ui_votesubtitle", name.c_str()); + VO_Cvar_Set("ui_votestringentry", ""); +} + +void CG_PushCallVoteSubFloat_f(void) +{ + str command; + str name; + voteoptiontype_t type; + + if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) { + return; + } + + if (type != voteoptiontype_t::VOTE_OPTION_FLOAT) { + return; + } + + g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name); + VO_ExecuteCommand("forcemenu votesubfloat\n"); + VO_Cvar_Set("ui_votesubtitle", name.c_str()); + VO_Cvar_Set("ui_votestringentry", ""); +} + +void CG_PushCallVoteSubClient_f(void) +{ + str command; + str name; + int index; + int i; + voteoptiontype_t type; + + index = atoi(cgi.Argv(1)); + + if (!g_voteOptions.GetVoteOptionsMain(index, &command, &type)) { + return; + } + + if (type != voteoptiontype_t::VOTE_OPTION_CLIENT && type != voteoptiontype_t::VOTE_OPTION_CLIENT_NOT_SELF) { + return; + } + + g_voteOptions.GetVoteOptionMainName(index, &name); + VO_ExecuteCommand("forcemenu votesubclient\n"); + VO_Cvar_Set("ui_votesubtitle", name.c_str()); + VO_ExecuteCommand("globalwidgetcommand voteclientlist deleteallitems\n"); + + for (i = 0; i < cgs.maxclients; i++) { + if (type == VOTE_OPTION_CLIENT_NOT_SELF && cg.snap && i == cg.snap->ps.clientNum) { + continue; + } + + if (!strlen(cg.clientinfo[i].name)) { + continue; + } + + VO_ExecuteCommand( + va("globalwidgetcommand voteclientlist additem \"%i: %s\" \"callvote %i %i;popmenu 0\"\n", + i, + cg.clientinfo[i].name, + index, + i) + ); + } + + VO_ExecuteCommand( + va("globalwidgetcommand voteclientlist additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]")) + ); +} + +void CG_PushVote_f(void) +{ + VO_Cvar_Set("ui_votesubtitle", cgs.voteString); + VO_ExecuteCommand("forcemenu votecast\n"); +} + +void CG_CallEntryVote_f(void) +{ + str command; + str name; + const char *entry; + int index; + voteoptiontype_t type; + + index = VO_Cvar_Get("ui_votetype", "0", 0)->integer; + + if (!g_voteOptions.GetVoteOptionsMain(index, &command, &type)) { + return; + } + + if (type != voteoptiontype_t::VOTE_OPTION_TEXT && type != voteoptiontype_t::VOTE_OPTION_INTEGER + && type != voteoptiontype_t::VOTE_OPTION_FLOAT) { + return; + } + + entry = VO_Cvar_Get("ui_votestringentry", "", 0)->string; + VO_ExecuteCommand(va("callvote %i \"%s\"\n", index, entry)); +} + +void VoteOptions::SetupMainOptionsList(void) +{ + SingleVoteOption *option; + int count; + + VO_ExecuteCommand("forcemenu votemain\n"); + VO_ExecuteCommand("globalwidgetcommand votelistmain deleteallitems\n"); + + if (!IsSetup()) { + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0\"\n", + VO_LV_ConvertString("Retrieving voting options from server...")) + ); + VO_SendRemoteCommand("gvo\n"); + return; + } + + count = 1; + + for (option = m_pHeadOption; option; option = option->m_pNext, count++) { + switch (option->m_optionType) { + case VOTE_NO_CHOICES: + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"callvote %i;popmenu 0\"\n", + option->m_sOptionName.c_str(), + count) + ); + break; + case VOTE_OPTION_LIST: + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;pushcallvotesublist %i\"\n", + option->m_sOptionName.c_str(), + count) + ); + break; + case VOTE_OPTION_TEXT: + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype " + "%i;pushcallvotesubtext %i\"\n", + option->m_sOptionName.c_str(), + count, + count) + ); + break; + case VOTE_OPTION_INTEGER: + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype " + "%i;pushcallvotesubinteger %i\"\n", + option->m_sOptionName.c_str(), + count, + count) + ); + break; + case VOTE_OPTION_FLOAT: + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype " + "%i;pushcallvotesubfloat %i\"\n", + option->m_sOptionName.c_str(), + count, + count) + ); + break; + case VOTE_OPTION_CLIENT: + case VOTE_OPTION_CLIENT_NOT_SELF: + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype " + "%i;pushcallvotesubclient %i\"\n", + option->m_sOptionName.c_str(), + count, + count) + ); + break; + } + } + + VO_ExecuteCommand( + va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]")) + ); +} + +void VoteOptions::SetupSubOptionsList(int index) +{ + SingleVoteOption *option; + VoteOptionListItem *item; + int count; + int numItems; + + if (index < 1) { + return; + } + + count = 1; + for (option = m_pHeadOption; count < index && option; option = option->m_pNext) { + count++; + } + + if (!option) { + return; + } + + if (option->m_optionType != VOTE_OPTION_LIST || !option->m_pListItem) { + return; + } + + VO_ExecuteCommand("forcemenu votesublist\n"); + VO_Cvar_Set("ui_votesubtitle", option->m_sOptionName.c_str()); + VO_ExecuteCommand("globalwidgetcommand votelistsub deleteallitems\n"); + + if (IsSetup()) { + numItems = 1; + + for (item = option->m_pListItem; item; item = item->m_pNext, numItems++) { + VO_ExecuteCommand( + va("globalwidgetcommand votelistsub additem \"%s\" \"callvote %i %i;popmenu 0\"\n", + item->m_sItemName.c_str(), + index, + numItems) + ); + } + + VO_ExecuteCommand( + va("globalwidgetcommand votelistsub additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]")) + ); + } else { + VO_ExecuteCommand( + "globalwidgetcommand votelistsub additem \"Retrieving voting options from server...\" \"popmenu 0\"\n" + ); + VO_SendRemoteCommand("gvo\n"); + } +} +#endif diff --git a/code/fgame/bg_voteoptions.h b/code/fgame/bg_voteoptions.h index 665203b6..8c69377e 100644 --- a/code/fgame/bg_voteoptions.h +++ b/code/fgame/bg_voteoptions.h @@ -22,9 +22,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #pragma once -#include "listener.h" +#ifdef __cplusplus +# include "listener.h" +#endif + #include "g_public.h" +#ifdef __cplusplus + +static const unsigned long MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH = 2024; +static const unsigned long MAX_VOTEOPTIONS_BUFFER_LENGTH = 0x100000; + typedef enum voteoptiontype_e { /** No input. */ VOTE_NO_CHOICES, @@ -44,18 +52,27 @@ typedef enum voteoptiontype_e { class VoteOptionListItem { +public: str m_sItemName; str m_sCommand; class VoteOptionListItem *m_pNext; + +public: + VoteOptionListItem(); }; class SingleVoteOption { - str m_sVoteName; - str m_sCommand; - voteoptiontype_t m_optionType; - VoteOptionListItem *m_pListItem; - class SingleVoteOption *m_pNext; +public: + str m_sOptionName; + str m_sCommand; + voteoptiontype_t m_optionType; + VoteOptionListItem *m_pListItem; + SingleVoteOption *m_pNext; + +public: + SingleVoteOption(); + ~SingleVoteOption(); }; class VoteOptions : public Class @@ -63,14 +80,56 @@ class VoteOptions : public Class public: CLASS_PROTOTYPE(VoteOptions); -public: +private: str m_sFileName; str m_sBuffer; SingleVoteOption *m_pHeadOption; - int field_5; - float field_6; - float field_7; - float field_8; - float field_9; - float field_10; + +public: + VoteOptions(); + ~VoteOptions(); + + bool IsSetup() const; + + void ClearOptions(); + void SetupVoteOptions(const char *configFileName); + void SetupVoteOptions(const char *configFileName, int length, const char *buffer); + void ParseVoteOptions(); + const char *GetVoteOptionsFile(int *outLen) const; + bool GetVoteOptionsMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) const; + bool GetVoteOptionSub(int index, int listIndex, str *outCommand) const; + bool GetVoteOptionMainName(int index, str *outVoteName) const; + bool GetVoteOptionSubName(int index, int listIndex, str *outName) const; + + void SetupMainOptionsList(); + void SetupSubOptionsList(int index); }; + +inline bool VoteOptions::IsSetup() const +{ + return m_pHeadOption != NULL; +} + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CGAME_DLL) + void CG_VoteOptions_StartReadFromServer(const char *string); + void CG_VoteOptions_ContinueReadFromServer(const char *string); + void CG_VoteOptions_FinishReadFromServer(const char *string); + void CG_PushCallVote_f(void); + void CG_PushCallVoteSubList_f(void); + void CG_PushCallVoteSubText_f(void); + void CG_PushCallVoteSubInteger_f(void); + void CG_PushCallVoteSubFloat_f(void); + void CG_PushCallVoteSubClient_f(void); + void CG_PushVote_f(void); + void CG_CallEntryVote_f(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/code/fgame/body.h b/code/fgame/body.h index 0abcb57a..b086ae89 100644 --- a/code/fgame/body.h +++ b/code/fgame/body.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // body.h: Dead bodies -#ifndef __BODY_H__ -#define __BODY_H__ +#pragma once #include "animate.h" @@ -39,5 +38,3 @@ public: CLASS_PROTOTYPE( Body ); Body(); }; - -#endif //__BODY_H__ diff --git a/code/fgame/botlib.h b/code/fgame/botlib.h index c49455ab..d96340a4 100644 --- a/code/fgame/botlib.h +++ b/code/fgame/botlib.h @@ -13,8 +13,7 @@ * *****************************************************************************/ -#ifndef __BOTLIB_H__ -#define __BOTLIB_H__ +#pragma once #define BOTLIB_API_VERSION 2 @@ -503,4 +502,3 @@ name: default: module(s): description: "max_levelitems" "256" be_ai_goal.c maximum number of level items */ -#endif diff --git a/code/fgame/bspline.cpp b/code/fgame/bspline.cpp index 61baf80c..11e41355 100644 --- a/code/fgame/bspline.cpp +++ b/code/fgame/bspline.cpp @@ -30,934 +30,712 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "g_phys.h" #include "scriptexception.h" -void BSpline::Set - ( - Vector *control_points_, - int num_control_points_, - splinetype_t type - ) - - { - int i; - - SetType( type ); - - has_orientation = false; - - if ( control_points ) - { - delete [] control_points; - control_points = NULL; - } - - num_control_points = num_control_points_; - if ( num_control_points ) - { - control_points = new BSplineControlPoint[ num_control_points ]; - assert( control_points ); - - for( i = 0; i < num_control_points; i++ ) - { - control_points[ i ].Set( control_points_[ i ] ); - } - } - } - -void BSpline::Set - ( - Vector *control_points_, - Vector *control_orients_, - float *control_speeds_, - int num_control_points_, - splinetype_t type - ) - - { - int i; - - SetType( type ); - - has_orientation = true; - - if ( control_points ) - { - delete [] control_points; - control_points = NULL; - } - - num_control_points = num_control_points_; - if ( num_control_points ) - { - control_points = new BSplineControlPoint[ num_control_points ]; - assert( control_points ); - - for( i = 0; i < num_control_points; i++ ) - { - control_points[ i ].Set( control_points_[ i ], control_orients_[ i ], control_speeds_[ i ] ); - } - } - } - -void BSpline::Clear - ( - void - ) - - { - if( control_points ) - { - delete [] control_points; - control_points = NULL; - } - num_control_points = 0; - has_orientation = false; - } - -inline float BSpline::EvalNormal - ( - float u, - Vector& pos, - Vector& orient - ) - - { - int segment_id; - float B[ 4 ]; - float tmp; - float u_2; - float u_3; - Vector ang; - float roll; - float speed; - - segment_id = ( int )u; - if ( segment_id < 0 ) - { - segment_id = 0; - } - if ( segment_id > num_control_points - 4 ) - { - segment_id = num_control_points - 4; - } - u -= ( float )segment_id; - - u_2 = u * u; - u_3 = u * u_2; - - tmp = 1 - u; - B[ 0 ] = ( tmp * tmp * tmp ) * ( 1.0f / 6.0f ); - B[ 1 ] = ( 3.0f * u_3 - 6.0f * u_2 + 4.0f ) * ( 1.0f / 6.0f ); - B[ 2 ] = ( -3.0f * u_3 + 3.0f * u_2 + 3.0f * u + 1 ) * ( 1.0f / 6.0f ); - B[ 3 ] = u_3 * ( 1.0f / 6.0f ); - - pos = - *control_points[ 0 + segment_id ].GetPosition() * B[ 0 ] + - *control_points[ 1 + segment_id ].GetPosition() * B[ 1 ] + - *control_points[ 2 + segment_id ].GetPosition() * B[ 2 ] + - *control_points[ 3 + segment_id ].GetPosition() * B[ 3 ]; - - ang = - *control_points[ 0 + segment_id ].GetOrientation() * B[ 0 ] + - *control_points[ 1 + segment_id ].GetOrientation() * B[ 1 ] + - *control_points[ 2 + segment_id ].GetOrientation() * B[ 2 ] + - *control_points[ 3 + segment_id ].GetOrientation() * B[ 3 ]; - - roll = - *control_points[ 0 + segment_id ].GetRoll() * B[ 0 ] + - *control_points[ 1 + segment_id ].GetRoll() * B[ 1 ] + - *control_points[ 2 + segment_id ].GetRoll() * B[ 2 ] + - *control_points[ 3 + segment_id ].GetRoll() * B[ 3 ]; - - speed = - *control_points[ 0 + segment_id ].GetSpeed() * B[ 0 ] + - *control_points[ 1 + segment_id ].GetSpeed() * B[ 1 ] + - *control_points[ 2 + segment_id ].GetSpeed() * B[ 2 ] + - *control_points[ 3 + segment_id ].GetSpeed() * B[ 3 ]; - - orient = ang.toAngles(); - orient[ ROLL ] = roll; - - return speed; - } - -inline float BSpline::EvalLoop - ( - float t, - Vector& pos, - Vector& orient - ) - - { - Vector retval; - Vector ang; - float speed; - float roll; - int segment_id; - int next_id; - float B[ 4 ]; - float tmp; - float u; - float u_2; - float u_3; - int i; - int j; - - segment_id = ( int )floor( t ); - u = t - floor( t ); - - segment_id %= num_control_points; - if ( segment_id < 0 ) - { - segment_id += num_control_points; - } - - u_2 = u * u; - u_3 = u * u_2; - - tmp = 1 - u; - B[ 0 ] = ( tmp * tmp * tmp ) * ( 1.0f / 6.0f ); - B[ 1 ] = ( 3.0f * u_3 - 6.0f * u_2 + 4.0f ) * ( 1.0f / 6.0f ); - B[ 2 ] = ( -3.0f * u_3 + 3.0f * u_2 + 3.0f * u + 1 ) * ( 1.0f / 6.0f ); - B[ 3 ] = u_3 * ( 1.0f / 6.0f ); - - speed = 0; - roll = 0; - - for( i = 0, j = segment_id; i < 4; i++, j++ ) - { - if ( j >= num_control_points ) - { - j -= ( num_control_points - loop_control_point ); - } - - retval += *control_points[ j ].GetPosition() * B[ i ]; - ang += *control_points[ j ].GetOrientation() * B[ i ]; - speed += *control_points[ j ].GetSpeed() * B[ i ]; - roll += *control_points[ j ].GetRoll() * B[ i ]; - } - - pos = retval; - - next_id = segment_id + 1; - if ( next_id >= num_control_points ) - { - next_id -= ( num_control_points - loop_control_point ); - } - orient = ang.toAngles(); - orient[ ROLL ] = roll; - - return speed; - } - -inline float BSpline::EvalClamp - ( - float t, - Vector& pos, - Vector& orient - ) - - { - Vector retval; - Vector ang; - int segment_id; - int next_id; - float B[ 4 ]; - float tmp; - float u; - float u_2; - float u_3; - int i; - int j; - float speed; - float roll; - - segment_id = ( int )floor( t ); - u = t - floor( t ); - - u_2 = u * u; - u_3 = u * u_2; - - tmp = 1 - u; - B[ 0 ] = ( tmp * tmp * tmp ) * ( 1.0f / 6.0f ); - B[ 1 ] = ( 3.0f * u_3 - 6.0f * u_2 + 4.0f ) * ( 1.0f / 6.0f ); - B[ 2 ] = ( -3.0f * u_3 + 3.0f * u_2 + 3.0f * u + 1 ) * ( 1.0f / 6.0f ); - B[ 3 ] = u_3 * ( 1.0f / 6.0f ); - - speed = 0; - roll = 0; - for( i = 0; i < 4; i++, segment_id++ ) - { - j = segment_id; - if ( j < 0 ) - { - j = 0; - } - else if ( j >= num_control_points ) - { - j = num_control_points - 1; - } - - retval += *control_points[ j ].GetPosition() * B[ i ]; - ang += *control_points[ j ].GetOrientation() * B[ i ]; - speed += *control_points[ j ].GetSpeed() * B[ i ]; - roll += *control_points[ j ].GetRoll() * B[ i ]; - } - - pos = retval; - - next_id = segment_id + 1; - if ( segment_id < 0 ) - { - segment_id = 0; - } - if ( segment_id >= num_control_points ) - { - segment_id = num_control_points - 1; - } - if ( next_id < 0 ) - { - next_id = 0; - } - if ( next_id >= num_control_points ) - { - next_id = num_control_points - 1; - } - orient = ang.toAngles(); - orient[ ROLL ] = roll; - - return speed; - } - - -Vector BSpline::Eval - ( - float u - ) - - { - Vector pos; - Vector orient; - - switch( curvetype ) - { - default: - case SPLINE_NORMAL : - EvalNormal( u, pos, orient ); - break; - - case SPLINE_CLAMP: - EvalClamp( u, pos, orient ); - break; - - case SPLINE_LOOP: - if ( u < 0 ) - { - EvalClamp( u, pos, orient ); - } - else - { - EvalLoop( u, pos, orient ); - } - break; - } - return pos; - } - -float BSpline::Eval - ( - float u, - Vector &pos, - Vector &orient - ) - - { - switch( curvetype ) - { - default: - case SPLINE_NORMAL : - return EvalNormal( u, pos, orient ); - break; - - case SPLINE_CLAMP: - return EvalClamp( u, pos, orient ); - break; - - case SPLINE_LOOP: - if ( u < 0 ) - { - return EvalClamp( u, pos, orient ); - } - else - { - return EvalLoop( u, pos, orient ); - } - break; - } - } - -void BSpline::DrawControlSegments - ( - void - ) - - { - int i; - - G_BeginLine(); - for( i = 0; i < num_control_points; i++ ) - { - G_Vertex( *control_points[ i ].GetPosition() ); - } - G_EndLine(); - } - -void BSpline::DrawCurve - ( - int num_subdivisions - ) - - { - float u; - float du; - - if ( !num_control_points ) - { - return; - } - - du = 1.0f / ( float )num_subdivisions; - - G_BeginLine(); - for( u = -2.0f; u <= ( float )num_control_points; u += du ) - { - G_Vertex( ( Vector )Eval( u ) ); - } - G_EndLine(); - } - -void BSpline::DrawCurve - ( - Vector offset, - int num_subdivisions - ) - - { - float u; - float du; - - du = 1.0f / ( float )num_subdivisions; - - G_BeginLine(); - for( u = -2.0f; u <= ( float )num_control_points; u += du ) - { - G_Vertex( offset + ( Vector )Eval( u ) ); - } - G_EndLine(); - } - -void BSpline::AppendControlPoint - ( - const Vector& new_control_point - ) - - { - BSplineControlPoint *old_control_points; - int i; - - old_control_points = control_points; - num_control_points++; - - control_points = new BSplineControlPoint[num_control_points]; - assert( control_points ); - - if ( old_control_points ) - { - for( i = 0; i < num_control_points - 1; i++ ) - { - control_points[ i ] = old_control_points[ i ]; - } - delete [] old_control_points; - } - - control_points[ num_control_points - 1 ].Set( new_control_point ); - } - -void BSpline::AppendControlPoint - ( - const Vector& new_control_point, - const float& speed - ) - - { - BSplineControlPoint *old_control_points; - int i; - - old_control_points = control_points; - num_control_points++; - - control_points = new BSplineControlPoint[num_control_points]; - assert( control_points ); - - if ( old_control_points ) - { - for( i = 0; i < num_control_points - 1; i++ ) - { - control_points[ i ] = old_control_points[ i ]; - } - delete [] old_control_points; - } - - control_points[ num_control_points - 1 ].Set( new_control_point, speed ); - } - -void BSpline::AppendControlPoint - ( - const Vector& new_control_point, - const Vector& new_control_orient, - const float& new_control_speed - ) - - { - BSplineControlPoint *old_control_points; - int i; - - has_orientation = true; - - old_control_points = control_points; - num_control_points++; - - control_points = new BSplineControlPoint[num_control_points]; - assert( control_points ); - - if ( old_control_points ) - { - for( i = 0; i < num_control_points - 1; i++ ) - { - control_points[ i ] = old_control_points[ i ]; - } - delete [] old_control_points; - } - - control_points[ num_control_points - 1 ].Set( new_control_point, new_control_orient, new_control_speed ); - } - -void BSpline::SetLoopPoint - ( - const Vector& pos - ) - { - int i; - - for( i = 0; i < num_control_points; i++ ) - { - if ( pos == *control_points[ i ].GetPosition() ) - { - loop_control_point = i; - break; - } - } - } - -int BSpline::PickControlPoint - ( - const Vector& window_point, - float pick_size - ) - - { - int i; - float closest_dist_2; - int closest_index; - float dist_2; - Vector delta; - - closest_index = -1; - closest_dist_2 = 1000000.0f; - for( i = 0; i < num_control_points; i++ ) - { - delta = window_point - *control_points[ i ].GetPosition(); - dist_2 = delta * delta; - if ( dist_2 < closest_dist_2 ) - { - closest_dist_2 = dist_2; - closest_index = i; - } - } - - if ( pick_size * pick_size >= closest_dist_2 ) - { - return closest_index; - } - else - { - return -1; - } - } +void BSpline::Set(Vector *control_points_, int num_control_points_, splinetype_t type) +{ + int i; + + SetType(type); + + has_orientation = false; + + if (control_points) { + delete[] control_points; + control_points = NULL; + } + + num_control_points = num_control_points_; + if (num_control_points) { + control_points = new BSplineControlPoint[num_control_points]; + assert(control_points); + + for (i = 0; i < num_control_points; i++) { + control_points[i].Set(control_points_[i]); + } + } +} + +void BSpline::Set( + Vector *control_points_, + Vector *control_orients_, + float *control_speeds_, + int num_control_points_, + splinetype_t type +) +{ + int i; + + SetType(type); + + has_orientation = true; + + if (control_points) { + delete[] control_points; + control_points = NULL; + } + + num_control_points = num_control_points_; + if (num_control_points) { + control_points = new BSplineControlPoint[num_control_points]; + assert(control_points); + + for (i = 0; i < num_control_points; i++) { + control_points[i].Set(control_points_[i], control_orients_[i], control_speeds_[i]); + } + } +} + +void BSpline::Clear(void) +{ + if (control_points) { + delete[] control_points; + control_points = NULL; + } + num_control_points = 0; + has_orientation = false; +} + +inline float BSpline::EvalNormal(float u, Vector& pos, Vector& orient) +{ + int segment_id; + float B[4]; + float tmp; + float u_2; + float u_3; + Vector ang; + float roll; + float speed; + + segment_id = (int)u; + if (segment_id < 0) { + segment_id = 0; + } + if (segment_id > num_control_points - 4) { + segment_id = num_control_points - 4; + } + u -= (float)segment_id; + + u_2 = u * u; + u_3 = u * u_2; + + tmp = 1 - u; + B[0] = (tmp * tmp * tmp) * (1.0f / 6.0f); + B[1] = (3.0f * u_3 - 6.0f * u_2 + 4.0f) * (1.0f / 6.0f); + B[2] = (-3.0f * u_3 + 3.0f * u_2 + 3.0f * u + 1) * (1.0f / 6.0f); + B[3] = u_3 * (1.0f / 6.0f); + + pos = *control_points[0 + segment_id].GetPosition() * B[0] + *control_points[1 + segment_id].GetPosition() * B[1] + + *control_points[2 + segment_id].GetPosition() * B[2] + *control_points[3 + segment_id].GetPosition() * B[3]; + + ang = *control_points[0 + segment_id].GetOrientation() * B[0] + + *control_points[1 + segment_id].GetOrientation() * B[1] + + *control_points[2 + segment_id].GetOrientation() * B[2] + + *control_points[3 + segment_id].GetOrientation() * B[3]; + + roll = *control_points[0 + segment_id].GetRoll() * B[0] + *control_points[1 + segment_id].GetRoll() * B[1] + + *control_points[2 + segment_id].GetRoll() * B[2] + *control_points[3 + segment_id].GetRoll() * B[3]; + + speed = *control_points[0 + segment_id].GetSpeed() * B[0] + *control_points[1 + segment_id].GetSpeed() * B[1] + + *control_points[2 + segment_id].GetSpeed() * B[2] + *control_points[3 + segment_id].GetSpeed() * B[3]; + + orient = ang.toAngles(); + orient[ROLL] = roll; + + return speed; +} + +inline float BSpline::EvalLoop(float t, Vector& pos, Vector& orient) +{ + Vector retval; + Vector ang; + float speed; + float roll; + int segment_id; + int next_id; + float B[4]; + float tmp; + float u; + float u_2; + float u_3; + int i; + int j; + + segment_id = (int)floor(t); + u = t - floor(t); + + segment_id %= num_control_points; + if (segment_id < 0) { + segment_id += num_control_points; + } + + u_2 = u * u; + u_3 = u * u_2; + + tmp = 1 - u; + B[0] = (tmp * tmp * tmp) * (1.0f / 6.0f); + B[1] = (3.0f * u_3 - 6.0f * u_2 + 4.0f) * (1.0f / 6.0f); + B[2] = (-3.0f * u_3 + 3.0f * u_2 + 3.0f * u + 1) * (1.0f / 6.0f); + B[3] = u_3 * (1.0f / 6.0f); + + speed = 0; + roll = 0; + + for (i = 0, j = segment_id; i < 4; i++, j++) { + if (j >= num_control_points) { + j -= (num_control_points - loop_control_point); + } + + retval += *control_points[j].GetPosition() * B[i]; + ang += *control_points[j].GetOrientation() * B[i]; + speed += *control_points[j].GetSpeed() * B[i]; + roll += *control_points[j].GetRoll() * B[i]; + } + + pos = retval; + + next_id = segment_id + 1; + if (next_id >= num_control_points) { + next_id -= (num_control_points - loop_control_point); + } + orient = ang.toAngles(); + orient[ROLL] = roll; + + return speed; +} + +inline float BSpline::EvalClamp(float t, Vector& pos, Vector& orient) +{ + Vector retval; + Vector ang; + int segment_id; + int next_id; + float B[4]; + float tmp; + float u; + float u_2; + float u_3; + int i; + int j; + float speed; + float roll; + + segment_id = (int)floor(t); + u = t - floor(t); + + u_2 = u * u; + u_3 = u * u_2; + + tmp = 1 - u; + B[0] = (tmp * tmp * tmp) * (1.0f / 6.0f); + B[1] = (3.0f * u_3 - 6.0f * u_2 + 4.0f) * (1.0f / 6.0f); + B[2] = (-3.0f * u_3 + 3.0f * u_2 + 3.0f * u + 1) * (1.0f / 6.0f); + B[3] = u_3 * (1.0f / 6.0f); + + speed = 0; + roll = 0; + for (i = 0; i < 4; i++, segment_id++) { + j = segment_id; + if (j < 0) { + j = 0; + } else if (j >= num_control_points) { + j = num_control_points - 1; + } + + retval += *control_points[j].GetPosition() * B[i]; + ang += *control_points[j].GetOrientation() * B[i]; + speed += *control_points[j].GetSpeed() * B[i]; + roll += *control_points[j].GetRoll() * B[i]; + } + + pos = retval; + + next_id = segment_id + 1; + if (segment_id < 0) { + segment_id = 0; + } + if (segment_id >= num_control_points) { + segment_id = num_control_points - 1; + } + if (next_id < 0) { + next_id = 0; + } + if (next_id >= num_control_points) { + next_id = num_control_points - 1; + } + orient = ang.toAngles(); + orient[ROLL] = roll; + + return speed; +} + +Vector BSpline::Eval(float u) +{ + Vector pos; + Vector orient; + + switch (curvetype) { + default: + case SPLINE_NORMAL: + EvalNormal(u, pos, orient); + break; + + case SPLINE_CLAMP: + EvalClamp(u, pos, orient); + break; + + case SPLINE_LOOP: + if (u < 0) { + EvalClamp(u, pos, orient); + } else { + EvalLoop(u, pos, orient); + } + break; + } + return pos; +} + +float BSpline::Eval(float u, Vector& pos, Vector& orient) +{ + switch (curvetype) { + default: + case SPLINE_NORMAL: + return EvalNormal(u, pos, orient); + break; + + case SPLINE_CLAMP: + return EvalClamp(u, pos, orient); + break; + + case SPLINE_LOOP: + if (u < 0) { + return EvalClamp(u, pos, orient); + } else { + return EvalLoop(u, pos, orient); + } + break; + } +} + +void BSpline::DrawControlSegments(void) +{ + int i; + + G_BeginLine(); + for (i = 0; i < num_control_points; i++) { + G_Vertex(*control_points[i].GetPosition()); + } + G_EndLine(); +} + +void BSpline::DrawCurve(int num_subdivisions) +{ + float u; + float du; + + if (!num_control_points) { + return; + } + + du = 1.0f / (float)num_subdivisions; + + G_BeginLine(); + for (u = -2.0f; u <= (float)num_control_points; u += du) { + G_Vertex((Vector)Eval(u)); + } + G_EndLine(); +} + +void BSpline::DrawCurve(Vector offset, int num_subdivisions) +{ + float u; + float du; + + du = 1.0f / (float)num_subdivisions; + + G_BeginLine(); + for (u = -2.0f; u <= (float)num_control_points; u += du) { + G_Vertex(offset + (Vector)Eval(u)); + } + G_EndLine(); +} + +void BSpline::AppendControlPoint(const Vector& new_control_point) +{ + BSplineControlPoint *old_control_points; + int i; + + old_control_points = control_points; + num_control_points++; + + control_points = new BSplineControlPoint[num_control_points]; + assert(control_points); + + if (old_control_points) { + for (i = 0; i < num_control_points - 1; i++) { + control_points[i] = old_control_points[i]; + } + delete[] old_control_points; + } + + control_points[num_control_points - 1].Set(new_control_point); +} + +void BSpline::AppendControlPoint(const Vector& new_control_point, const float& speed) +{ + BSplineControlPoint *old_control_points; + int i; + + old_control_points = control_points; + num_control_points++; + + control_points = new BSplineControlPoint[num_control_points]; + assert(control_points); + + if (old_control_points) { + for (i = 0; i < num_control_points - 1; i++) { + control_points[i] = old_control_points[i]; + } + delete[] old_control_points; + } + + control_points[num_control_points - 1].Set(new_control_point, speed); +} + +void BSpline::AppendControlPoint( + const Vector& new_control_point, const Vector& new_control_orient, const float& new_control_speed +) +{ + BSplineControlPoint *old_control_points; + int i; + + has_orientation = true; + + old_control_points = control_points; + num_control_points++; + + control_points = new BSplineControlPoint[num_control_points]; + assert(control_points); + + if (old_control_points) { + for (i = 0; i < num_control_points - 1; i++) { + control_points[i] = old_control_points[i]; + } + delete[] old_control_points; + } + + control_points[num_control_points - 1].Set(new_control_point, new_control_orient, new_control_speed); +} + +void BSpline::SetLoopPoint(const Vector& pos) +{ + int i; + + for (i = 0; i < num_control_points; i++) { + if (pos == *control_points[i].GetPosition()) { + loop_control_point = i; + break; + } + } +} + +int BSpline::PickControlPoint(const Vector& window_point, float pick_size) +{ + int i; + float closest_dist_2; + int closest_index; + float dist_2; + Vector delta; + + closest_index = -1; + closest_dist_2 = 1000000.0f; + for (i = 0; i < num_control_points; i++) { + delta = window_point - *control_points[i].GetPosition(); + dist_2 = delta * delta; + if (dist_2 < closest_dist_2) { + closest_dist_2 = dist_2; + closest_index = i; + } + } + + if (pick_size * pick_size >= closest_dist_2) { + return closest_index; + } else { + return -1; + } +} Event EV_SplinePath_Create - ( - "SplinePath_create", - EV_DEFAULT, - NULL, - NULL, - "Creates the spline path from the target list.", - EV_NORMAL - ); +( + "SplinePath_create", + EV_DEFAULT, + NULL, + NULL, + "Creates the spline path from the target list.", + EV_NORMAL +); Event EV_SplinePath_Loop - ( - "loop", - EV_CONSOLE, - "s", - "loop_name", - "Sets the loop name.", - EV_NORMAL - ); +( + "loop", + EV_CONSOLE, + "s", + "loop_name", + "Sets the loop name.", + EV_NORMAL +); Event EV_SplinePath_Speed - ( - "speed", - EV_DEFAULT, - "f", - "speed", - "Sets the path speed.", - EV_NORMAL - ); +( + "speed", + EV_DEFAULT, + "f", + "speed", + "Sets the path speed.", + EV_NORMAL +); Event EV_SplinePath_SetTriggerTarget - ( - "triggertarget", - EV_DEFAULT, - "s", - "target", - "Sets the trigger target.", - EV_NORMAL - ); +( + "triggertarget", + EV_DEFAULT, + "s", + "target", + "Sets the trigger target.", + EV_NORMAL +); Event EV_SplinePath_SetWatch - ( - "watch", - EV_CONSOLE, - "s", - "watchEntity", - "Sets the entity to watch at this node.", - EV_NORMAL - ); +( + "watch", + EV_CONSOLE, + "s", + "watchEntity", + "Sets the entity to watch at this node.", + EV_NORMAL +); Event EV_SplinePath_SetFov - ( - "fov", - EV_CONSOLE, - "f", - "cameraFOV", - "Sets the fov at this node.", - EV_NORMAL - ); +( + "fov", + EV_CONSOLE, + "f", + "cameraFOV", + "Sets the fov at this node.", + EV_NORMAL +); Event EV_SplinePath_SetFadeTime - ( - "fadetime", - EV_DEFAULT, - "f", - "fadeTime", - "Sets the fadetime at this node.", - EV_NORMAL - ); +( + "fadetime", + EV_DEFAULT, + "f", + "fadeTime", + "Sets the fadetime at this node.", + EV_NORMAL +); -CLASS_DECLARATION( Entity, SplinePath, "info_splinepath" ) - { - { &EV_SplinePath_Create, &SplinePath::CreatePath }, - { &EV_SplinePath_Loop, &SplinePath::SetLoop }, - { &EV_SplinePath_Speed, &SplinePath::SetSpeed }, - { &EV_SplinePath_SetTriggerTarget, &SplinePath::SetTriggerTarget }, - { &EV_SplinePath_SetWatch, &SplinePath::SetWatch }, - { &EV_SplinePath_SetFov, &SplinePath::SetFov }, - { &EV_SplinePath_SetFadeTime, &SplinePath::SetFadeTime }, - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, SplinePath, "info_splinepath") { + {&EV_SplinePath_Create, &SplinePath::CreatePath }, + {&EV_SplinePath_Loop, &SplinePath::SetLoop }, + {&EV_SplinePath_Speed, &SplinePath::SetSpeed }, + {&EV_SplinePath_SetTriggerTarget, &SplinePath::SetTriggerTarget}, + {&EV_SplinePath_SetWatch, &SplinePath::SetWatch }, + {&EV_SplinePath_SetFov, &SplinePath::SetFov }, + {&EV_SplinePath_SetFadeTime, &SplinePath::SetFadeTime }, + {NULL, NULL } +}; SplinePath::SplinePath() { - entflags |= EF_SPLINEPATH; + entflags |= ECF_SPLINEPATH; - AddWaitTill(STRING_REACH); + AddWaitTill(STRING_REACH); + owner = this; + next = NULL; + loop = NULL; + speed = 1; + doWatch = false; + watchEnt = ""; + fov = 0; + fadeTime = -1; - owner = this; - next = NULL; - loop = NULL; - speed = 1; - doWatch = false; - watchEnt = ""; - fov = 0; - fadeTime = -1; + setMoveType(MOVETYPE_NONE); + setSolidType(SOLID_NOT); + hideModel(); - setMoveType( MOVETYPE_NONE ); - setSolidType( SOLID_NOT ); - hideModel(); - - if( !LoadingSavegame ) - { - PostEvent( EV_SplinePath_Create, FRAMETIME ); - } + if (!LoadingSavegame) { + PostEvent(EV_SplinePath_Create, FRAMETIME); + } } SplinePath::~SplinePath() - { - // disconnect from the chain - if ( owner != this ) - { - owner->SetNext( next ); - } - else if ( next ) - { - next->SetPrev( NULL ); - next = NULL; - } +{ + // disconnect from the chain + if (owner != this) { + owner->SetNext(next); + } else if (next) { + next->SetPrev(NULL); + next = NULL; + } - assert( owner == this ); - assert( next == NULL ); - } + assert(owner == this); + assert(next == NULL); -void SplinePath::SetLoop - ( - Event *ev - ) + entflags &= ~ECF_SPLINEPATH; +} - { - loop_name = ev->GetString( 1 ); - } +void SplinePath::SetLoop(Event *ev) +{ + loop_name = ev->GetString(1); +} -void SplinePath::SetSpeed - ( - Event *ev - ) +void SplinePath::SetSpeed(Event *ev) +{ + speed = ev->GetFloat(1); +} - { - speed = ev->GetFloat( 1 ); - } +void SplinePath::SetTriggerTarget(Event *ev) +{ + SetTriggerTarget(ev->GetString(1)); +} -void SplinePath::SetTriggerTarget - ( - Event *ev - ) +void SplinePath::CreatePath(Event *ev) +{ + const char *target; + Entity *ent; - { - SetTriggerTarget( ev->GetString( 1 ) ); - } + // Make the path from the targetlist. + target = Target(); + if (target[0]) { + ent = (Entity *)G_FindTarget(NULL, target); + if (ent && ent->IsSubclassOfSplinePath()) { + next = (SplinePath *)ent; -void SplinePath::CreatePath - ( - Event *ev - ) + if (next->owner != next) { + // Fixed in OPM + // If the target already has an owner, make sure to properly remove the owner + next->owner->SetNext(NULL); + } - { - const char *target; - Entity *ent; + next->owner = this; + } else if (ent) { + ScriptError("SplinePath::CreatePath: target '%s' for '%s' not found (cannot connect to class '%s')\n", target, targetname.c_str(), ent->getClassname()); + } else { + ScriptError("SplinePath::CreatePath: target %s not found\n", target); + } + } + if (loop_name.length()) { + ent = (Entity *)G_FindTarget(NULL, loop_name.c_str()); + if (ent) { + loop = (SplinePath *)ent; + } + } +} - // Make the path from the targetlist. - target = Target(); - if ( target[ 0 ] ) - { - ent = ( Entity * )G_FindTarget( NULL, target ); - if ( ent ) - { - next = ( SplinePath * )ent; - next->owner = this; - } - else - { - ScriptError( "SplinePath::CreatePath: target %s not found\n", target ); - } - } - if ( loop_name.length() ) - { - ent = ( Entity * )G_FindTarget( NULL, loop_name.c_str() ); - if ( ent ) - { - loop = ( SplinePath * )ent; - } - } - } +SplinePath *SplinePath::GetNext(void) +{ + return next; +} -SplinePath *SplinePath::GetNext - ( - void - ) - - { - return next; - } +SplinePath *SplinePath::GetPrev(void) +{ + if (owner == this) { + return NULL; + } -SplinePath *SplinePath::GetPrev - ( - void - ) - - { - if ( owner == this ) - { - return NULL; - } + return owner; +} - return owner; - } +void SplinePath::SetNext(SplinePath *node) +{ + if (next) { + // remove ourselves from the chain + next->owner = next; + } -void SplinePath::SetNext - ( - SplinePath *node - ) - - { - if ( next ) - { - // remove ourselves from the chain - next->owner = next; - } + next = node; + if (next) { + // disconnect next from it's previous node + if (next->owner != next) { + next->owner->next = NULL; + } + next->owner = this; + } +} - next = node; - if ( next ) - { - // disconnect next from it's previous node - if ( next->owner != next ) - { - next->owner->next = NULL; - } - next->owner = this; - } - } +void SplinePath::SetPrev(SplinePath *node) +{ + if (owner != this) { + owner->next = NULL; + } -void SplinePath::SetPrev - ( - SplinePath *node - ) - - { - if ( owner != this ) - { - owner->next = NULL; - } + if (node && (node != this)) { + // safely remove the node from its chain + if (node->next) { + node->next->owner = node->next; + } + node->next = this; + owner = node; + } else { + owner = this; + } +} - if ( node && ( node != this ) ) - { - // safely remove the node from its chain - if ( node->next ) - { - node->next->owner = node->next; - } - node->next = this; - owner = node; - } - else - { - owner = this; - } - } +SplinePath *SplinePath::GetLoop(void) +{ + return loop; +} -SplinePath *SplinePath::GetLoop - ( - void - ) - - { - return loop; - } +void SplinePath::SetWatch(const char *name) +{ + if (watchEnt != name) { + watchEnt = name; + if (watchEnt.length()) { + doWatch = true; + } else { + doWatch = false; + } + } +} -void SplinePath::SetWatch - ( - const char *name - ) +void SplinePath::SetWatch(Event *ev) +{ + SetWatch(ev->GetString(1)); +} - { - if ( watchEnt != name ) - { - watchEnt = name; - if ( watchEnt.length() ) - { - doWatch = true; - } - else - { - doWatch = false; - } - } - } +void SplinePath::NoWatch(void) +{ + doWatch = true; + watchEnt = "none"; +} -void SplinePath::SetWatch - ( - Event *ev - ) +str SplinePath::GetWatch(void) +{ + return watchEnt; +} - { - SetWatch( ev->GetString( 1 ) ); - } +void SplinePath::SetFov(float newFov) +{ + fov = newFov; +} +void SplinePath::SetFov(Event *ev) +{ + fov = ev->GetFloat(1); +} -void SplinePath::NoWatch - ( - void - ) +float SplinePath::GetFov(void) +{ + return fov; +} - { - doWatch = true; - watchEnt = "none"; - } +void SplinePath::SetFadeTime(float newFadeTime) +{ + fadeTime = newFadeTime; +} -str SplinePath::GetWatch - ( - void - ) +void SplinePath::SetFadeTime(Event *ev) +{ + fadeTime = ev->GetFloat(1); +} - { - return watchEnt; - } - -void SplinePath::SetFov - ( - float newFov - ) - - { - fov = newFov; - } - -void SplinePath::SetFov - ( - Event *ev - ) - - { - fov = ev->GetFloat( 1 ); - } - -float SplinePath::GetFov - ( - void - ) - - { - return fov; - } - -void SplinePath::SetFadeTime - ( - float newFadeTime - ) - - { - fadeTime = newFadeTime; - } - -void SplinePath::SetFadeTime - ( - Event *ev - ) - - { - fadeTime = ev->GetFloat( 1 ); - } - -float SplinePath::GetFadeTime - ( - void - ) - - { - return fadeTime; - } +float SplinePath::GetFadeTime(void) +{ + return fadeTime; +} diff --git a/code/fgame/bspline.h b/code/fgame/bspline.h index e0cf70eb..50a69d82 100644 --- a/code/fgame/bspline.h +++ b/code/fgame/bspline.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // bspline.h: Uniform non-rational bspline class. // -#ifndef __BSPLINE_H__ -#define __BSPLINE_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -580,5 +579,3 @@ inline void SplinePath::SetTriggerTarget { triggertarget = name; } - -#endif /* __BSPLINE_H__ */ diff --git a/code/fgame/camera.cpp b/code/fgame/camera.cpp index a0397a41..83ac8b20 100644 --- a/code/fgame/camera.cpp +++ b/code/fgame/camera.cpp @@ -38,617 +38,585 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA CameraManager CameraMan; -void CameraMoveState::Initialize( Camera * camera ) - { - assert( camera ); - pos = camera->origin; - angles = camera->angles; - movedir = vec_zero; - followEnt = NULL; - orbitEnt = NULL; - - followingpath = false; - cameraTime = 0; - lastTime = 0; - newTime = 0; - cameraPath.Clear(); - splinePath = NULL; - currentNode = NULL; - loopNode = NULL; - } - -void CameraWatchState::Initialize( Camera * camera ) - { - assert( camera ); - watchAngles = camera->angles; - watchEnt = NULL; - watchNodes = true; - watchPath = false; - } - -void CameraState::Initialize( Camera * camera ) - { - assert( camera ); - move.Initialize( camera ); - watch.Initialize( camera ); - fov = camera->Fov(); - } - -void CameraMoveState::DoNodeEvents - ( - Camera * camera - ) +void CameraMoveState::Initialize(Camera *camera) { - SplinePath *node; - Entity *ent; - Event *event; + assert(camera); + pos = camera->origin; + angles = camera->angles; + movedir = vec_zero; + followEnt = NULL; + orbitEnt = NULL; - assert( camera ); - - node = currentNode; - if( node ) - { - float fadeTime; - float newFov; - - fadeTime = node->GetFadeTime(); - if( fadeTime == -1 ) - { - fadeTime = camera->fadeTime; - } - - if( node->doWatch ) - { - camera->Watch( node->GetWatch(), fadeTime ); - } - - newFov = node->GetFov(); - if( newFov ) - { - camera->SetFOV( newFov, fadeTime ); - } - - camera->Unregister( STRING_REACH ); - - if( node->triggertarget != "" ) - { - ent = NULL; - do - { - ent = G_FindTarget( ent, node->triggertarget.c_str() ); - if( !ent ) - { - break; - } - event = new Event( EV_Activate ); - event->AddEntity( camera ); - ent->PostEvent( event, 0 ); - } while( 1 ); - } - } + followingpath = false; + cameraTime = 0; + lastTime = 0; + newTime = 0; + cameraPath.Clear(); + splinePath = NULL; + currentNode = NULL; + loopNode = NULL; } -void CameraMoveState::Evaluate - ( - Camera * camera - ) - { - Vector oldpos; - float speed_multiplier; +void CameraWatchState::Initialize(Camera *camera) +{ + assert(camera); + watchAngles = camera->angles; + watchEnt = NULL; + watchNodes = true; + watchPath = false; +} - assert( camera ); +void CameraState::Initialize(Camera *camera) +{ + assert(camera); + move.Initialize(camera); + watch.Initialize(camera); + fov = camera->Fov(); +} - oldpos = pos; - // - // check for node events - // we explicitly skip the first node because we process that - // when we begin the follow path command - // - if ( ( lastTime != newTime ) && currentNode ) - { - if ( newTime > 1 ) - { - DoNodeEvents( camera ); - } - currentNode = currentNode->GetNext(); - if ( !currentNode ) - { - currentNode = loopNode; - } - } - lastTime = newTime; +void CameraMoveState::DoNodeEvents(Camera *camera) +{ + SplinePath *node; + Entity *ent; + Event *event; - // - // evaluate position - // - if ( followingpath ) - { - speed_multiplier = cameraPath.Eval( cameraTime, pos, angles ); + assert(camera); - cameraTime += level.frametime * camera->camera_speed * speed_multiplier; + node = currentNode; + if (node) { + float fadeTime; + float newFov; - if ( orbitEnt ) - { - pos += orbitEnt->origin; - if ( camera->orbit_dotrace ) - { - trace_t trace; - Vector start, back; + fadeTime = node->GetFadeTime(); + if (fadeTime == -1) { + fadeTime = camera->fadeTime; + } - start = orbitEnt->origin; - start[ 2 ] += orbitEnt->maxs[ 2 ]; + if (node->doWatch) { + camera->Watch(node->GetWatch(), fadeTime); + } - back = start - pos; - back.normalize(); + newFov = node->GetFov(); + if (newFov) { + camera->SetFOV(newFov, fadeTime); + } - trace = G_Trace( start, vec_zero, vec_zero, pos, orbitEnt, camera->follow_mask, false, "Camera::EvaluatePosition" ); + camera->Unregister(STRING_REACH); - if ( trace.fraction < 1.0f ) - { - pos = trace.endpos; - // step in a bit towards the followEng - pos += back * 16; - } + if (node->triggertarget != "") { + ent = NULL; + do { + ent = G_FindTarget(ent, node->triggertarget.c_str()); + if (!ent) { + break; + } + event = new Event(EV_Activate); + event->AddEntity(camera); + ent->PostEvent(event, 0); + } while (1); + } + } +} + +void CameraMoveState::Evaluate(Camera *camera) +{ + Vector oldpos; + float speed_multiplier; + + assert(camera); + + oldpos = pos; + // + // check for node events + // we explicitly skip the first node because we process that + // when we begin the follow path command + // + if ((lastTime != newTime) && currentNode) { + if (newTime > 1) { + DoNodeEvents(camera); + } + currentNode = currentNode->GetNext(); + if (!currentNode) { + currentNode = loopNode; + } + } + lastTime = newTime; + + // + // evaluate position + // + if (followingpath) { + speed_multiplier = cameraPath.Eval(cameraTime, pos, angles); + + cameraTime += level.frametime * camera->camera_speed * speed_multiplier; + + if (orbitEnt) { + pos += orbitEnt->origin; + if (camera->orbit_dotrace) { + trace_t trace; + Vector start, back; + + start = orbitEnt->origin; + start[2] += orbitEnt->maxs[2]; + + back = start - pos; + back.normalize(); + + trace = G_Trace( + start, vec_zero, vec_zero, pos, orbitEnt, camera->follow_mask, false, "Camera::EvaluatePosition" + ); + + if (trace.fraction < 1.0f) { + pos = trace.endpos; + // step in a bit towards the followEng + pos += back * 16; + } } - } - } - else - { - if ( followEnt ) - { - trace_t trace; - Vector start, end, ang, back; + } + } else { + if (followEnt) { + trace_t trace; + Vector start, end, ang, back; - start = followEnt->origin; - start[ 2 ] += followEnt->maxs[ 2 ]; + start = followEnt->origin; + start[2] += followEnt->maxs[2]; - if ( camera->follow_yaw_fixed ) - { - ang = vec_zero; - } - else - { - if ( followEnt->isSubclassOf( Player ) ) - { - Entity * ent; - ent = followEnt; - ( ( Player * )ent )->GetPlayerView( NULL, &ang ); - } - else - { - ang = followEnt->angles; - } - } - ang.y += camera->follow_yaw; - ang.AngleVectors( &back, NULL, NULL ); + if (camera->follow_yaw_fixed) { + ang = vec_zero; + } else { + if (followEnt->isSubclassOf(Player)) { + Entity *ent; + ent = followEnt; + ((Player *)ent)->GetPlayerView(NULL, &ang); + } else { + ang = followEnt->angles; + } + } + ang.y += camera->follow_yaw; + ang.AngleVectors(&back, NULL, NULL); - end = start - back * camera->follow_dist; - end[ 2 ] += 24; + end = start - back * camera->follow_dist; + end[2] += 24; - trace = G_Trace( start, vec_zero, vec_zero, end, followEnt, camera->follow_mask, false, "Camera::EvaluatePosition - Orbit" ); + trace = G_Trace( + start, + vec_zero, + vec_zero, + end, + followEnt, + camera->follow_mask, + false, + "Camera::EvaluatePosition - Orbit" + ); - pos = trace.endpos; - // step in a bit towards the followEnt - pos += back * 16; - } - } + pos = trace.endpos; + // step in a bit towards the followEnt + pos += back * 16; + } + } - // - // update times for node events - // - newTime = cameraTime + 2.0f; + // + // update times for node events + // + newTime = cameraTime + 2.0f; - if ( newTime < 0 ) - { - newTime = 0; - } - // - // set movedir - // - movedir = pos - oldpos; - } + if (newTime < 0) { + newTime = 0; + } + // + // set movedir + // + movedir = pos - oldpos; +} -void CameraWatchState::Evaluate - ( - Camera * camera, - CameraMoveState * move - ) - { - assert( camera ); - assert( move ); - // - // evaluate orientation - // - if ( watchEnt ) - { - Vector watchPos; +void CameraWatchState::Evaluate(Camera *camera, CameraMoveState *move) +{ + assert(camera); + assert(move); + // + // evaluate orientation + // + if (watchEnt) { + Vector watchPos; + watchPos.x = watchEnt->origin.x; + watchPos.y = watchEnt->origin.y; + watchPos.z = watchEnt->absmax.z; + watchPos -= camera->origin; + watchPos.normalize(); + watchAngles = watchPos.toAngles(); + } else if (watchNodes) { + watchAngles = move->angles; + } else if (watchPath) { + float length; + Vector delta; - watchPos.x = watchEnt->origin.x; - watchPos.y = watchEnt->origin.y; - watchPos.z = watchEnt->absmax.z; - watchPos -= camera->origin; - watchPos.normalize(); - watchAngles = watchPos.toAngles(); - } - else if ( watchNodes ) - { - watchAngles = move->angles; - } - else if ( watchPath ) - { - float length; - Vector delta; - - delta = move->movedir; - length = delta.length(); - if ( length > 0.05f ) - { - delta *= 1.0f / length; - watchAngles = delta.toAngles(); - } - } - watchAngles[ 0 ] = AngleMod( watchAngles[ 0 ] ); - watchAngles[ 1 ] = AngleMod( watchAngles[ 1 ] ); - watchAngles[ 2 ] = AngleMod( watchAngles[ 2 ] ); - } - -void CameraState::Evaluate - ( - Camera * camera - ) - { - move.Evaluate( camera ); - watch.Evaluate( camera, &move ); - } + delta = move->movedir; + length = delta.length(); + if (length > 0.05f) { + delta *= 1.0f / length; + watchAngles = delta.toAngles(); + } + } + watchAngles[0] = AngleMod(watchAngles[0]); + watchAngles[1] = AngleMod(watchAngles[1]); + watchAngles[2] = AngleMod(watchAngles[2]); +} +void CameraState::Evaluate(Camera *camera) +{ + move.Evaluate(camera); + watch.Evaluate(camera, &move); +} Event EV_Camera_CameraThink - ( - "camera_think", - EV_DEFAULT, - NULL, - NULL, - "Called each frame to allow the camera to adjust its position.", - EV_NORMAL - ); +( + "camera_think", + EV_DEFAULT, + NULL, + NULL, + "Called each frame to allow the camera to adjust its position.", + EV_NORMAL +); Event EV_Camera_StartMoving - ( - "start", - EV_DEFAULT, - NULL, - NULL, - "Start camera moving.", - EV_NORMAL - ); +( + "start", + EV_DEFAULT, + NULL, + NULL, + "Start camera moving.", + EV_NORMAL +); Event EV_Camera_Pause - ( - "pause", - EV_DEFAULT, - NULL, - NULL, - "Pause the camera.", - EV_NORMAL - ); +( + "pause", + EV_DEFAULT, + NULL, + NULL, + "Pause the camera.", + EV_NORMAL +); Event EV_Camera_Continue - ( - "continue", - EV_DEFAULT, - NULL, - NULL, - "Continue the camera movement.", - EV_NORMAL - ); +( + "continue", + EV_DEFAULT, + NULL, + NULL, + "Continue the camera movement.", + EV_NORMAL +); Event EV_Camera_StopMoving - ( "stop", - EV_CONSOLE, - NULL, - NULL, - "Stop the camera movement.", - EV_NORMAL - ); +( + "stop", + EV_CONSOLE, + NULL, + NULL, + "Stop the camera movement.", + EV_NORMAL +); Event EV_Camera_SetSpeed - ( - "speed", - EV_DEFAULT, - "f", - "speed", - "Sets the camera speed.", - EV_NORMAL - ); +( + "speed", + EV_DEFAULT, + "f", + "speed", + "Sets the camera speed.", + EV_NORMAL +); Event EV_Camera_SetFOV - ( - "fov", - EV_CONSOLE, - "fF", - "fov fadeTime", - "Sets the camera's field of view (fov).\n" - "if fadeTime is specified, camera will fade over that time\n" - "if fov is less than 3, than an auto_fov will be assumed\n" - "the value of fov will be the ratio used for keeping a watch\n" - "entity in the view at the right scale", - EV_NORMAL - ); +( + "fov", + EV_CONSOLE, + "fF", + "fov fadeTime", + "Sets the camera's field of view (fov).\n" + "if fadeTime is specified, camera will fade over that time\n" + "if fov is less than 3, than an auto_fov will be assumed\n" + "the value of fov will be the ratio used for keeping a watch\n" + "entity in the view at the right scale", + EV_NORMAL +); // // FOLLOW EVENTS // Event EV_Camera_Follow - ( - "follow", - EV_DEFAULT, - "eE", - "targetEnt targetWatchEnt", - "Makes the camera follow an entity and optionally watch an entity.", - EV_NORMAL - ); +( + "follow", + EV_DEFAULT, + "eE", + "targetEnt targetWatchEnt", + "Makes the camera follow an entity and optionally watch an entity.", + EV_NORMAL +); Event EV_Camera_SetFollowDistance - ( - "follow_distance", - EV_DEFAULT, - "f", - "distance", - "Sets the camera follow distance.", - EV_NORMAL - ); +( + "follow_distance", + EV_DEFAULT, + "f", + "distance", + "Sets the camera follow distance.", + EV_NORMAL +); Event EV_Camera_SetFollowYaw - ( - "follow_yaw", - EV_DEFAULT, - "f", - "yaw", - "Sets the yaw offset of the camera following an entity.", - EV_NORMAL - ); +( + "follow_yaw", + EV_DEFAULT, + "f", + "yaw", + "Sets the yaw offset of the camera following an entity.", + EV_NORMAL +); Event EV_Camera_AbsoluteYaw - ( - "follow_yaw_absolute", - EV_DEFAULT, - NULL, - NULL, - "Makes the follow camera yaw absolute.", - EV_NORMAL - ); +( + "follow_yaw_absolute", + EV_DEFAULT, + NULL, + NULL, + "Makes the follow camera yaw absolute.", + EV_NORMAL +); Event EV_Camera_RelativeYaw - ( - "follow_yaw_relative", - EV_DEFAULT, - NULL, - NULL, - "Makes the follow camera yaw relative (not absolute).", - EV_NORMAL - ); +( + "follow_yaw_relative", + EV_DEFAULT, + NULL, + NULL, + "Makes the follow camera yaw relative (not absolute).", + EV_NORMAL +); // // ORBIT Events // Event EV_Camera_Orbit - ( - "orbit", - EV_DEFAULT, - "eE", - "targetEnt targetWatchEnt", - "Makes the camera orbit around an entity and optionally watch an entity.", - EV_NORMAL - ); +( + "orbit", + EV_DEFAULT, + "eE", + "targetEnt targetWatchEnt", + "Makes the camera orbit around an entity and optionally watch an entity.", + EV_NORMAL +); Event EV_Camera_SetOrbitHeight - ( - "orbit_height", - EV_DEFAULT, - "f", - "height", - "Sets the orbit camera's height.", - EV_NORMAL - ); +( + "orbit_height", + EV_DEFAULT, + "f", + "height", + "Sets the orbit camera's height.", + EV_NORMAL +); // // Watch Events // Event EV_Camera_Watch - ( - "watch", - EV_CONSOLE, - "eF", - "watchEnt fadeTime", - "Makes the camera watch an entity.\n" - "if fadeTime is specified, camera will fade over that time", - EV_NORMAL - ); +( + "watch", + EV_CONSOLE, + "eF", + "watchEnt fadeTime", + "Makes the camera watch an entity.\n" + "if fadeTime is specified, camera will fade over that time", + EV_NORMAL +); Event EV_Camera_WatchPath - ( - "watchpath", - EV_CONSOLE, - "F", - "fadeTime", - "Makes the camera look along the path of travel.\n" - "if fadeTime is specified, camera will fade over that time", - EV_NORMAL - ); +( + "watchpath", + EV_CONSOLE, + "F", + "fadeTime", + "Makes the camera look along the path of travel.\n" + "if fadeTime is specified, camera will fade over that time", + EV_NORMAL +); Event EV_Camera_WatchNodes - ( - "watchnode", - EV_CONSOLE, - "F", - "fadeTime", - "Makes the camera watch based on what is stored\n" - "in the camera nodes.\n" - "if fadeTime is specified, camera will fade over that time", - EV_NORMAL - ); +( + "watchnode", + EV_CONSOLE, + "F", + "fadeTime", + "Makes the camera watch based on what is stored\n" + "in the camera nodes.\n" + "if fadeTime is specified, camera will fade over that time", + EV_NORMAL +); Event EV_Camera_NoWatch - ( - "nowatch", - EV_CONSOLE, - "F", - "fadeTime", - "Stop watching an entity or looking along a path.\n" - "Camera is now static as far as orientation.\n" - "if fadeTime is specified, camera will fade over that time", - EV_NORMAL - ); +( + "nowatch", + EV_CONSOLE, + "F", + "fadeTime", + "Stop watching an entity or looking along a path.\n" + "Camera is now static as far as orientation.\n" + "if fadeTime is specified, camera will fade over that time", + EV_NORMAL +); Event EV_Camera_WatchString - ( - "watchstring", +( + "watchstring", EV_CONSOLE, "sF", "string fadeTime", "Makes the camera watch based on a string.\n" "if fadeTime is specified, camera will fade over that time", - EV_NORMAL - ); + EV_NORMAL +); // // Camera positioning events // Event EV_Camera_LookAt - ( - "lookat", - EV_DEFAULT, - "e", - "ent", - "Makes the camera look at an entity.", - EV_NORMAL - ); +( + "lookat", + EV_DEFAULT, + "e", + "ent", + "Makes the camera look at an entity.", + EV_NORMAL +); Event EV_Camera_TurnTo - ( - "turnto", - EV_DEFAULT, - "v", - "angle", - "Makes the camera look in the specified direction.", - EV_NORMAL - ); +( + "turnto", + EV_DEFAULT, + "v", + "angle", + "Makes the camera look in the specified direction.", + EV_NORMAL +); Event EV_Camera_MoveToEntity - ( - "moveto", - EV_DEFAULT, - "e", - "ent", - "Move the camera's position to that of the specified entities.", - EV_NORMAL - ); +( + "moveto", + EV_DEFAULT, + "e", + "ent", + "Move the camera's position to that of the specified entities.", + EV_NORMAL +); Event EV_Camera_MoveToPos - ( - "movetopos", - EV_DEFAULT, - "v", - "position", - "Move the camera's position to the specified position.", - EV_NORMAL - ); +( + "movetopos", + EV_DEFAULT, + "v", + "position", + "Move the camera's position to the specified position.", + EV_NORMAL +); // // Camera Transitioning events // Event EV_Camera_FadeTime - ( - "fadetime", - EV_DEFAULT, - "f", - "fadetime", - "Sets the fade time for camera transitioning.", - EV_NORMAL - ); +( + "fadetime", + EV_DEFAULT, + "f", + "fadetime", + "Sets the fade time for camera transitioning.", + EV_NORMAL +); Event EV_Camera_Cut - ( - "cut", - EV_DEFAULT, - NULL, - NULL, - "switch camera states immediately, do not transition", - EV_NORMAL - ); +( + "cut", + EV_DEFAULT, + NULL, + NULL, + "switch camera states immediately, do not transition", + EV_NORMAL +); Event EV_Camera_SetNextCamera - ( - "nextcamera", - EV_DEFAULT, - "s", - "nextCamera", - "Sets the next camera to use.", - EV_NORMAL - ); +( + "nextcamera", + EV_DEFAULT, + "s", + "nextCamera", + "Sets the next camera to use.", + EV_NORMAL +); Event EV_Camera_SetAutoState - ( - "auto_state", - EV_DEFAULT, - "sSSSSS", - "state1 state2 state3 state4 state5 state6", - "Sets the states the player needs to be in for this camera to activate.", - EV_NORMAL - ); +( + "auto_state", + EV_DEFAULT, + "sSSSSS", + "state1 state2 state3 state4 state5 state6", + "Sets the states the player needs to be in for this camera to activate.", + EV_NORMAL +); Event EV_Camera_SetAutoRadius - ( - "auto_radius", - EV_DEFAULT, - "f", - "newRadius", - "Sets the radius of the automatic camera.", - EV_NORMAL - ); +( + "auto_radius", + EV_DEFAULT, + "f", + "newRadius", + "Sets the radius of the automatic camera.", + EV_NORMAL +); Event EV_Camera_SetAutoActive - ( - "auto_active", - EV_DEFAULT, - "b", - "newActiveState", - "Whether or not the auto camera is active.", - EV_NORMAL - ); +( + "auto_active", + EV_DEFAULT, + "b", + "newActiveState", + "Whether or not the auto camera is active.", + EV_NORMAL +); Event EV_Camera_SetAutoStartTime - ( - "auto_starttime", - EV_DEFAULT, - "f", - "newTime", - "Sets how long it takes for the camera to be switched to.", - EV_NORMAL - ); +( + "auto_starttime", + EV_DEFAULT, + "f", + "newTime", + "Sets how long it takes for the camera to be switched to.", + EV_NORMAL +); Event EV_Camera_SetAutoStopTime - ( - "auto_stoptime", - EV_DEFAULT, - "f", - "newTime", - "Sets how long it takes for the camera switch back to the player.", - EV_NORMAL - ); +( + "auto_stoptime", + EV_DEFAULT, + "f", + "newTime", + "Sets how long it takes for the camera switch back to the player.", + EV_NORMAL +); Event EV_Camera_SetMaximumAutoFOV - ( - "auto_maxfov", - EV_DEFAULT, - "f", - "maxFOV", - "Sets the maximum FOV that should be used when automatically calculating FOV.", - EV_NORMAL - ); +( + "auto_maxfov", + EV_DEFAULT, + "f", + "maxFOV", + "Sets the maximum FOV that should be used when automatically calculating FOV.", + EV_NORMAL +); Event EV_Camera_SetShowQuakes ( - "showquakes", - EV_DEFAULT, - "b", - "showquakes", - "Sets the camera to show or not show earthquake effects from the player triggered either from the earthquake command, or a viewjitter." + "showquakes", + EV_DEFAULT, + "b", + "showquakes", + "Sets the camera to show or not show earthquake effects from the player triggered either from the earthquake " + "command, or a viewjitter." ); -// +// // general setup functions // Event EV_Camera_SetupCamera - ( - "_setupcamera", - EV_DEFAULT, - NULL, - NULL, - "setup the camera, post spawn.", - EV_NORMAL - ); +( + "_setupcamera", + EV_DEFAULT, + NULL, + NULL, + "setup the camera, post spawn.", + EV_NORMAL +); /*****************************************************************************/ /* func_camera (0 0.25 0.5) (-8 -8 0) (8 8 16) ORBIT START_ON AUTOMATIC NO_TRACE NO_WATCH LEVEL_EXIT @@ -689,1612 +657,1206 @@ LEVEL_EXIT if the camera is being used, the level exit state will be set ******************************************************************************/ -CLASS_DECLARATION(Entity, Camera, "func_camera") -{ - { &EV_Camera_CameraThink, &Camera::CameraThink }, - { &EV_Activate, &Camera::StartMoving }, - { &EV_Camera_StartMoving, &Camera::StartMoving }, - { &EV_Camera_StopMoving, &Camera::StopMoving }, - { &EV_Camera_Pause, &Camera::Pause }, - { &EV_Camera_Continue, &Camera::Continue }, - { &EV_Camera_SetSpeed, &Camera::SetSpeed }, - { &EV_Camera_SetFollowDistance, &Camera::SetFollowDistance }, - { &EV_Camera_SetFollowYaw, &Camera::SetFollowYaw }, - { &EV_Camera_AbsoluteYaw, &Camera::AbsoluteYaw }, - { &EV_Camera_RelativeYaw, &Camera::RelativeYaw }, - { &EV_Camera_SetOrbitHeight, &Camera::SetOrbitHeight }, - { &EV_Camera_SetFOV, &Camera::SetFOV }, - { &EV_Camera_Orbit, &Camera::OrbitEvent }, - { &EV_Camera_Follow, &Camera::FollowEvent }, - { &EV_Camera_Watch, &Camera::WatchEvent }, - { &EV_Camera_WatchPath, &Camera::WatchPathEvent }, - { &EV_Camera_WatchNodes, &Camera::WatchNodesEvent }, - { &EV_Camera_NoWatch, &Camera::NoWatchEvent }, - { &EV_Camera_LookAt, &Camera::LookAt }, - { &EV_Camera_TurnTo, &Camera::TurnTo }, - { &EV_Camera_MoveToEntity, &Camera::MoveToEntity }, - { &EV_Camera_MoveToPos, &Camera::MoveToPos }, - { &EV_Camera_Cut, &Camera::Cut }, - { &EV_Camera_FadeTime, &Camera::FadeTime }, - { &EV_Camera_SetNextCamera, &Camera::SetNextCamera }, - { &EV_Camera_SetupCamera, &Camera::SetupCamera }, - { &EV_SetAngles, &Camera::SetAnglesEvent }, - { &EV_Camera_SetAutoState, &Camera::SetAutoStateEvent }, - { &EV_Camera_SetAutoRadius, &Camera::SetAutoRadiusEvent }, - { &EV_Camera_SetAutoStartTime, &Camera::SetAutoStartTimeEvent }, - { &EV_Camera_SetAutoStopTime, &Camera::SetAutoStopTimeEvent }, - { &EV_Camera_SetMaximumAutoFOV, &Camera::SetMaximumAutoFOVEvent }, - { &EV_Camera_SetAutoActive, &Camera::SetAutoActiveEvent }, - { &EV_Camera_WatchString, &Camera::WatchStringEvent }, - { &EV_Camera_SetShowQuakes, &Camera::EventShowQuakes }, +CLASS_DECLARATION(Entity, Camera, "func_camera") { + {&EV_Camera_CameraThink, &Camera::CameraThink }, + {&EV_Activate, &Camera::StartMoving }, + {&EV_Camera_StartMoving, &Camera::StartMoving }, + {&EV_Camera_StopMoving, &Camera::StopMoving }, + {&EV_Camera_Pause, &Camera::Pause }, + {&EV_Camera_Continue, &Camera::Continue }, + {&EV_Camera_SetSpeed, &Camera::SetSpeed }, + {&EV_Camera_SetFollowDistance, &Camera::SetFollowDistance }, + {&EV_Camera_SetFollowYaw, &Camera::SetFollowYaw }, + {&EV_Camera_AbsoluteYaw, &Camera::AbsoluteYaw }, + {&EV_Camera_RelativeYaw, &Camera::RelativeYaw }, + {&EV_Camera_SetOrbitHeight, &Camera::SetOrbitHeight }, + {&EV_Camera_SetFOV, &Camera::SetFOV }, + {&EV_Camera_Orbit, &Camera::OrbitEvent }, + {&EV_Camera_Follow, &Camera::FollowEvent }, + {&EV_Camera_Watch, &Camera::WatchEvent }, + {&EV_Camera_WatchPath, &Camera::WatchPathEvent }, + {&EV_Camera_WatchNodes, &Camera::WatchNodesEvent }, + {&EV_Camera_NoWatch, &Camera::NoWatchEvent }, + {&EV_Camera_LookAt, &Camera::LookAt }, + {&EV_Camera_TurnTo, &Camera::TurnTo }, + {&EV_Camera_MoveToEntity, &Camera::MoveToEntity }, + {&EV_Camera_MoveToPos, &Camera::MoveToPos }, + {&EV_Camera_Cut, &Camera::Cut }, + {&EV_Camera_FadeTime, &Camera::FadeTime }, + {&EV_Camera_SetNextCamera, &Camera::SetNextCamera }, + {&EV_Camera_SetupCamera, &Camera::SetupCamera }, + {&EV_SetAngles, &Camera::SetAnglesEvent }, + {&EV_Camera_SetAutoState, &Camera::SetAutoStateEvent }, + {&EV_Camera_SetAutoRadius, &Camera::SetAutoRadiusEvent }, + {&EV_Camera_SetAutoStartTime, &Camera::SetAutoStartTimeEvent }, + {&EV_Camera_SetAutoStopTime, &Camera::SetAutoStopTimeEvent }, + {&EV_Camera_SetMaximumAutoFOV, &Camera::SetMaximumAutoFOVEvent}, + {&EV_Camera_SetAutoActive, &Camera::SetAutoActiveEvent }, + {&EV_Camera_WatchString, &Camera::WatchStringEvent }, + {&EV_Camera_SetShowQuakes, &Camera::EventShowQuakes }, - { NULL, NULL } + {NULL, NULL } }; Camera::Camera() { - Vector ang; + Vector ang; - entflags |= EF_CAMERA; + entflags |= ECF_CAMERA; - AddWaitTill(STRING_START); - AddWaitTill(STRING_TRIGGER); + AddWaitTill(STRING_START); + AddWaitTill(STRING_TRIGGER); - camera_fov = 90; - camera_speed = 1; - orbit_height = 128; - orbit_dotrace = qtrue; - follow_yaw = 0; - follow_yaw_fixed = false; - follow_dist = 128; - follow_mask = MASK_SOLID; - auto_fov = 0; - automatic_maxFOV = 90; + camera_fov = 80; + camera_speed = 1; + orbit_height = 128; + orbit_dotrace = qtrue; + follow_yaw = 0; + follow_yaw_fixed = false; + follow_dist = 128; + follow_mask = MASK_SOLID; + auto_fov = 0; + automatic_maxFOV = 80; - watchTime = 0; - followTime = 0; - fovTime = 0; + watchTime = 0; + followTime = 0; + fovTime = 0; - fadeTime = 2.0f; + fadeTime = 2.0f; + fovFadeTime = 1.0f; + followFadeTime = 1.0f; + watchFadeTime = 1.0f; + m_bShowquakes = false; - setSolidType( SOLID_NOT ); - setMoveType( MOVETYPE_NONE ); + setSolidType(SOLID_NOT); + setMoveType(MOVETYPE_NONE); - showcamera = sv_showcameras->integer; - if( showcamera ) - { - setModel( "func_camera.tik" ); - showModel(); - } - else - { - hideModel(); - } + showcamera = sv_showcameras->integer; + if (showcamera) { + setModel("func_camera.tik"); + showModel(); + } else { + hideModel(); + } - automatic_active = qtrue; - automatic_radius = 512; - automatic_states.ClearObjectList(); - automatic_startTime = 0.7f; - automatic_stopTime = 0.7f; + automatic_active = qtrue; + automatic_radius = 512; + automatic_states.ClearObjectList(); + automatic_startTime = 0.7f; + automatic_stopTime = 0.7f; - if( !LoadingSavegame ) - { - PostEvent( EV_Camera_SetupCamera, EV_POSTSPAWN ); - } + if (!LoadingSavegame) { + PostEvent(EV_Camera_SetupCamera, EV_POSTSPAWN); + } } -void Camera::SetupCamera - ( - Event *ev - ) - - { - currentstate.Initialize( this ); - newstate.Initialize( this ); - - if ( spawnflags & START_ON ) - { - PostEvent( EV_Camera_StartMoving, 0 ); - } - if ( spawnflags & AUTOMATIC ) - { - level.AddAutomaticCamera( this ); - } - } - -qboolean Camera::IsAutomatic - ( - void - ) - { - return ( spawnflags & AUTOMATIC ); - } - -qboolean Camera::IsLevelExit - ( - void - ) - { - return ( spawnflags & LEVEL_EXIT ); - } - -float Camera::CalculateScore - ( - Entity * player, - str state - ) - { - int i; - float range; - float score; - qboolean found; - - if ( !automatic_active ) - { - return 10; - } - - range = Vector( player->origin - origin ).length() / automatic_radius; - // bias the range so that we don't immediately jump out of the camera if we are out of range - range -= 0.1f; - - score = range; - - // - // early exit if our score exceeds 1 - // - if ( score > 1.0f ) - return score; - - // find out if we match a state - found = qfalse; - for( i = 1; i <= automatic_states.NumObjects(); i++ ) - { - str *auto_state; - - auto_state = &automatic_states.ObjectAt( i ); - if ( !state.icmpn( state, auto_state->c_str(), auto_state->length() ) ) - { - found = qtrue; - break; - } - } - - // if we are comparing states and we haven't found a valid one... - if ( automatic_states.NumObjects() && !found ) - { - // if we aren't in the right state, push our score out significantly - score += 2.0f; - return score; - } - - // perform a trace to the player if necessary - if ( !( spawnflags & NO_TRACE ) && !( spawnflags & NO_WATCH ) ) - { - trace_t trace; - - trace = G_Trace( origin, vec_zero, vec_zero, player->centroid, player, follow_mask, false, "Camera::CalculateScore" ); - if ( trace.startsolid || trace.allsolid || trace.fraction < 1.0f ) - { - // if we are blocked, push our score out, but not too much since this may be a temporary thing - if ( trace.startsolid || trace.allsolid ) - { - score += 2.0f; - return score; - } - else - { - score += 1.0f - trace.fraction; - } - } - } - - // perform a dot product test for no watch cameras - if ( spawnflags & NO_WATCH ) - { - trace_t trace; - float limit; - float threshold; - float dot; - Vector dir; - - dir = player->centroid - origin; - dir.normalize(); - dot = dir * orientation[ 0 ]; - - threshold = cos( DEG2RAD( ( camera_fov * 0.25f ) ) ); - if ( dot <= threshold ) - { - limit = cos( DEG2RAD( ( camera_fov * 0.45f ) ) ); - if ( dot <= limit ) - { - // we are outside the viewing cone - score += 2.0f; - return score; - } - else - { - // our score is a scale between the two values - score += ( threshold - dot ) / ( limit ); - } - } - - trace = G_Trace( origin, vec_zero, vec_zero, player->origin, player, follow_mask, false, "Camera::CalculateScore" ); - if ( trace.startsolid || trace.allsolid || trace.fraction < 1.0f ) - { - // if we are blocked, push our score out, but not too much since this may be a temporary thing - if ( trace.startsolid || trace.allsolid ) - { - score += 2.0f; - return score; - } - else - { - score += 1.0f - trace.fraction; - } - } - } - - return score; - } - -float Camera::AutomaticStart - ( - Entity * player - ) +void Camera::SetupCamera(Event *ev) { - if( !( spawnflags & NO_WATCH ) && player ) - { - Watch( player, 0 ); - Cut( NULL ); - } + currentstate.Initialize(this); + newstate.Initialize(this); - Unregister( STRING_START ); - return automatic_startTime; + if (spawnflags & START_ON) { + PostEvent(EV_Camera_StartMoving, 0); + } + if (spawnflags & AUTOMATIC) { + level.AddAutomaticCamera(this); + } } -float Camera::AutomaticStop - ( - Entity * player - ) - { - Stop(); - return automatic_stopTime; - } - -void Camera::UpdateStates - ( - void - ) - - { - if ( followTime && watchTime ) - { - newstate.Evaluate( this ); - } - else if ( watchTime ) - { - newstate.watch.Evaluate( this, ¤tstate.move ); - } - else if ( followTime ) - { - newstate.move.Evaluate( this ); - } - currentstate.Evaluate( this ); - } - - -Vector Camera::CalculatePosition - ( - void - ) - - { - int i; - float t; - Vector pos; - - // - // calcualte position - // - if ( followTime ) - { - t = followTime - level.time; - // - // are we still fading? - // - if ( t <= 0 ) - { - // - // if not zero out the fade - // - t = 0; - currentstate.move = newstate.move; - newstate.move.Initialize( this ); - followTime = 0; - pos = currentstate.move.pos; - } - else - { - // - // if we are lerp over followFadeTime - // - t = ( followFadeTime - t ) / followFadeTime; - - for ( i = 0; i < 3; i++ ) - { - pos[ i ] = currentstate.move.pos[ i ] + ( t * ( newstate.move.pos[ i ] - currentstate.move.pos[ i ] ) ); - } - } - } - else - { - pos = currentstate.move.pos; - } - - return pos; - } - - -Vector Camera::CalculateOrientation - ( - void - ) +qboolean Camera::IsAutomatic(void) { - int i; - float t; - Vector ang; - - // - // calculate orientation - // - if( watchTime ) - { - t = watchTime - level.time; - // - // are we still fading? - // - if( t <= 0 ) - { - // - // if not zero out the fade - // - t = 0; - currentstate.watch = newstate.watch; - newstate.watch.Initialize( this ); - watchTime = 0; - ang = currentstate.watch.watchAngles; - } - else - { - t = ( watchFadeTime - t ) / watchFadeTime; - - for( i = 0; i<3; i++ ) - { - ang[ i ] = LerpAngleFromCurrent - ( - currentstate.watch.watchAngles[ i ], - newstate.watch.watchAngles[ i ], - this->angles[ i ], - t - ); - } - /* - warning("", "%.2f a x%.0f y%.0f z%.0f c x%.0f y%.0f z%.0f n x%.0f y%.0f z%.0f\n", - t, - ang[ 0 ], - ang[ 1 ], - ang[ 2 ], - currentstate.watch.watchAngles[ 0 ], - currentstate.watch.watchAngles[ 1 ], - currentstate.watch.watchAngles[ 2 ], - newstate.watch.watchAngles[ 0 ], - newstate.watch.watchAngles[ 1 ], - newstate.watch.watchAngles[ 2 ] - ); - */ - } - } - else - { - ang = currentstate.watch.watchAngles; - } - - return ang; + return (spawnflags & AUTOMATIC); } -float Camera::CalculateFov - ( - void - ) - - { - float fov; - float t; - - // - // calculate fov - // - // check if we have an auto_fov - if ( auto_fov > 0 ) - { - if ( currentstate.watch.watchEnt ) - { - float distance; - float size; - float new_fov; - Entity * ent; - - ent = currentstate.watch.watchEnt; - size = ent->maxs[ 2 ] - ent->mins[ 2 ]; - size = ent->edict->r.radius / 2; - // cap the size - if ( size < 16 ) - size = 16; - distance = Vector( ent->centroid - origin ).length(); - new_fov = RAD2DEG( 2.0f * atan2( size, distance * auto_fov ) ); - if ( new_fov > automatic_maxFOV ) - new_fov = automatic_maxFOV; - else if ( new_fov < 5 ) - new_fov = 5; - return new_fov; - } - else - { - return 90; - } - } - // if we get here, we don't have an auto_fov, or we have an invalid watch target - if ( fovTime ) - { - t = fovTime - level.time; - // - // are we still fading? - // - if ( t <= 0 ) - { - // - // if not zero out the fade - // - t = 0; - currentstate.fov = newstate.fov; - fovTime = 0; - fov = currentstate.fov; - } - else - { - // - // if we are lerp over fovFadeTime - // - t = ( fovFadeTime - t ) / fovFadeTime; - fov = currentstate.fov + ( t * ( newstate.fov - currentstate.fov ) ); - } - } - else - { - fov = currentstate.fov; - } - - return fov; - } - -void Camera::CameraThink - ( - Event *ev - ) +qboolean Camera::IsLevelExit(void) { - UpdateStates(); - - if( edict->s.parent == ENTITYNUM_NONE ) - { - setOrigin( CalculatePosition() ); - setAngles( CalculateOrientation() ); - } - else - { - setOrigin(); - - if( edict->s.attach_use_angles ) - { - orientation_t orient; - Vector ang; - Entity *ent = G_GetEntity( edict->s.parent ); - - ent->GetTag( edict->s.tag_num & TAG_MASK, &orient ); - MatrixToEulerAngles( orient.axis, ang ); - - setAngles( ang ); - } - else - { - setAngles( CalculateOrientation() ); - } - } - - camera_fov = CalculateFov(); - - if( m_bShowquakes && level.earthquake_magnitude ) - { - Vector randomness; - - // smooth earthquake - randomness[ 0 ] = G_CRandom( 1.0f ); - randomness[ 1 ] = G_CRandom( 1.0f ); - randomness[ 2 ] = G_CRandom( 1.0f ); - - angles += randomness * level.earthquake_magnitude; - } - - // - // debug info - // - if( sv_showcameras->integer != showcamera ) - { - showcamera = sv_showcameras->integer; - if( showcamera ) - { - showModel(); - } - else - { - hideModel(); - } - } - - if( sv_showcameras->integer != showcamera ) - { - showcamera = sv_showcameras->integer; - if( showcamera ) - { - showModel(); - } - else - { - hideModel(); - } - } - if( showcamera && currentstate.move.followingpath ) - { - G_Color3f( 1, 1, 0 ); - if( currentstate.move.orbitEnt ) - { - currentstate.move.cameraPath.DrawCurve( currentstate.move.orbitEnt->origin, 10 ); - } - else - { - currentstate.move.cameraPath.DrawCurve( 10 ); - } - } - - CancelEventsOfType( EV_Camera_CameraThink ); - PostEvent( EV_Camera_CameraThink, 0.05f ); + return (spawnflags & LEVEL_EXIT); } -void Camera::LookAt - ( - Event *ev - ) +float Camera::CalculateScore(Entity *player, str state) +{ + int i; + float range; + float score; + qboolean found; - { - Vector pos, delta; - Entity * ent; + if (!automatic_active) { + return 10; + } - ent = ev->GetEntity( 1 ); + range = Vector(player->origin - origin).length() / automatic_radius; + // bias the range so that we don't immediately jump out of the camera if we are out of range + range -= 0.1f; - if ( !ent ) - return; + score = range; - pos.x = ent->origin.x; - pos.y = ent->origin.y; - pos.z = ent->absmax.z; - delta = pos - origin; - delta.normalize(); + // + // early exit if our score exceeds 1 + // + if (score > 1.0f) { + return score; + } - currentstate.watch.watchAngles = delta.toAngles(); - setAngles( currentstate.watch.watchAngles ); - } + // find out if we match a state + found = qfalse; + for (i = 1; i <= automatic_states.NumObjects(); i++) { + str *auto_state; -void Camera::TurnTo - ( - Event *ev - ) - - { - currentstate.watch.watchAngles = ev->GetVector( 1 ); - setAngles( currentstate.watch.watchAngles ); - } - -void Camera::MoveToEntity - ( - Event *ev - ) - - { - Entity * ent; - - ent = ev->GetEntity( 1 ); - if ( ent ) - currentstate.move.pos = ent->origin; - setOrigin( currentstate.move.pos ); - } - -void Camera::MoveToPos - ( - Event *ev - ) - - { - currentstate.move.pos = ev->GetVector( 1 ); - setOrigin( currentstate.move.pos ); - } - -void Camera::Stop - ( - void - ) - - { - if ( followTime ) - { - currentstate.move = newstate.move; - newstate.move.Initialize( this ); - } - if ( watchTime ) - { - currentstate.watch = newstate.watch; - newstate.watch.Initialize( this ); - } - CancelEventsOfType( EV_Camera_CameraThink ); - - watchTime = 0; - followTime = 0; - } - -void Camera::CreateOrbit - ( - Vector pos, - float radius, - Vector &forward, - Vector &left - ) - - { - newstate.move.cameraPath.Clear(); - newstate.move.cameraPath.SetType( SPLINE_LOOP ); - - newstate.move.cameraPath.AppendControlPoint( pos + radius * forward ); - newstate.move.cameraPath.AppendControlPoint( pos + radius * left ); - newstate.move.cameraPath.AppendControlPoint( pos - radius * forward ); - newstate.move.cameraPath.AppendControlPoint( pos - radius * left ); - } - -void Camera::CreatePath - ( - SplinePath *path, - splinetype_t type - ) - - { - SplinePath *node; - SplinePath *loop; - - newstate.move.cameraPath.Clear(); - newstate.move.cameraPath.SetType( type ); - - newstate.move.splinePath = path; - newstate.move.currentNode = path; - newstate.move.loopNode = NULL; - - node = path; - while( node != NULL ) - { - newstate.move.cameraPath.AppendControlPoint( node->origin, node->angles, node->speed ); - loop = node->GetLoop(); - if ( loop && ( type == SPLINE_LOOP ) ) - { - newstate.move.loopNode = loop; - newstate.move.cameraPath.SetLoopPoint( loop->origin ); - } - node = node->GetNext(); - - if ( node == path ) - { - break; - } - } - - if ( ( type == SPLINE_LOOP ) && ( !newstate.move.loopNode ) ) - { - newstate.move.loopNode = path; - } - } - -void Camera::FollowPath - ( - SplinePath *path, - qboolean loop, - Entity * watch - ) - - { - // make sure we process any setup events before continuing - ProcessPendingEvents(); - - Stop(); - if ( loop ) - { - CreatePath( path, SPLINE_LOOP ); - } - else - { - CreatePath( path, SPLINE_CLAMP ); - } - - newstate.move.cameraTime = -2; - newstate.move.lastTime = 0; - newstate.move.newTime = 0; - newstate.move.currentNode = path; - // evaluate the first node events - newstate.move.DoNodeEvents( this ); - - if ( watch ) - { - newstate.watch.watchEnt = watch; - } - else - { - Watch( newstate.move.currentNode->GetWatch(), newstate.move.currentNode->GetFadeTime() ); - } - - followFadeTime = fadeTime; - watchFadeTime = fadeTime; - - newstate.move.followingpath = true; - followTime = level.time + followFadeTime; - watchTime = level.time + watchFadeTime; - - PostEvent( EV_Camera_CameraThink, FRAMETIME ); - } - -void Camera::Orbit - ( - Entity *ent, - float dist, - Entity *watch, - float yaw_offset, - qboolean dotrace - ) - - { - Vector ang, forward, left; - - // make sure we process any setup events before continuing - ProcessPendingEvents(); - - Stop(); - - if ( watch ) - { - ang = watch->angles; - ang.y += yaw_offset; - } - else - { - ang = vec_zero; - ang.y += yaw_offset; - } - ang.AngleVectors( &forward, &left, NULL ); - - orbit_dotrace = dotrace; - - CreateOrbit( Vector( 0, 0, orbit_height ), dist, forward, left ); - newstate.move.cameraTime = -2; - newstate.move.lastTime = 0; - newstate.move.newTime = 0; - - newstate.move.orbitEnt = ent; - - followFadeTime = fadeTime; - watchFadeTime = fadeTime; - - newstate.move.followingpath = true; - followTime = level.time + followFadeTime; - watchTime = level.time + watchFadeTime; - newstate.move.currentNode = NULL; - - if ( watch ) - { - newstate.watch.watchEnt = watch; - } - else - { - newstate.watch.watchEnt = ent; - } - - PostEvent( EV_Camera_CameraThink, FRAMETIME ); - } - -void Camera::FollowEntity - ( - Entity *ent, - float dist, - int mask, - Entity *watch - ) - - { - // make sure we process any setup events before continuing - ProcessPendingEvents(); - - assert( ent ); - - Stop(); - - if ( ent ) - { - newstate.move.followEnt = ent; - newstate.move.followingpath = false; - - followFadeTime = fadeTime; - watchFadeTime = fadeTime; - - newstate.move.cameraTime = -2; - newstate.move.lastTime = 0; - newstate.move.newTime = 0; - newstate.move.currentNode = NULL; - - followTime = level.time + followFadeTime; - watchTime = level.time + watchFadeTime; - if ( watch ) - { - newstate.watch.watchEnt = watch; - } - else - { - newstate.watch.watchEnt = ent; - } - follow_dist = dist; - follow_mask = mask; - PostEvent( EV_Camera_CameraThink, 0 ); - } - } - -void Camera::StartMoving - ( - Event *ev - ) - - { - Entity *targetEnt; - Entity *targetWatchEnt; - Entity *ent; - SplinePath *path; - - if ( ev->NumArgs() > 0 ) - { - targetEnt = ev->GetEntity( 1 ); - } - else - { - targetEnt = NULL; - } - - if ( ev->NumArgs() > 1 ) - { - targetWatchEnt = ev->GetEntity( 2 ); - } - else - { - targetWatchEnt = NULL; - } - - if ( ( spawnflags & START_ON ) && ( !Q_stricmp( Target(), "" ) ) ) - { - gi.Error( ERR_DROP, "Camera '%s' with START_ON selected, but no target specified.", TargetName().c_str() ); - } - - if ( !targetEnt ) - { - ent = ( Entity * )G_FindTarget( NULL, Target() ); - if ( !ent ) - { - // - // we took this out just because of too many warnings, oh well - //warning("StartMoving", "Can't find target for camera\n" ); - // - // I put it back in as an error. Fuck em! Yeeeeeha! - // - gi.Error( ERR_DROP, "Can't find target '%s' for camera\n", Target().c_str() ); - return; - } - } - else - { - ent = targetEnt; - } - - if ( ent->isSubclassOf( SplinePath ) ) - { - path = ( SplinePath * )ent; - FollowPath( path, spawnflags & ORBIT, targetWatchEnt ); - } - else - { - if ( spawnflags & ORBIT ) - { - Orbit( ent, follow_dist, targetWatchEnt ); - } - else - { - FollowEntity( ent, follow_dist, follow_mask, targetWatchEnt ); - } - } - } - -void Camera::SetAutoStateEvent - ( - Event *ev - ) - - { - int i; - - for( i = 1; i <= ev->NumArgs(); i++ ) - { - char *buffer; - char com_token[ MAX_QPATH ]; - char com_buffer[MAX_STRING_CHARS]; - - strcpy( com_buffer, ev->GetString( i ) ); - buffer = com_buffer; - // get the rest of the line - while( 1 ) - { - strcpy( com_token, COM_ParseExt( &buffer, qfalse ) ); - if (!com_token[0]) + auto_state = &automatic_states.ObjectAt(i); + if (!state.icmpn(state, auto_state->c_str(), auto_state->length())) { + found = qtrue; break; + } + } - automatic_states.AddUniqueObject( str( com_token ) ); - } - } - } + // if we are comparing states and we haven't found a valid one... + if (automatic_states.NumObjects() && !found) { + // if we aren't in the right state, push our score out significantly + score += 2.0f; + return score; + } -void Camera::SetMaximumAutoFOVEvent - ( - Event *ev - ) + // perform a trace to the player if necessary + if (!(spawnflags & NO_TRACE) && !(spawnflags & NO_WATCH)) { + trace_t trace; - { - automatic_maxFOV = ev->GetFloat( 1 ); - } + trace = + G_Trace(origin, vec_zero, vec_zero, player->centroid, player, follow_mask, false, "Camera::CalculateScore"); + if (trace.startsolid || trace.allsolid || trace.fraction < 1.0f) { + // if we are blocked, push our score out, but not too much since this may be a temporary thing + if (trace.startsolid || trace.allsolid) { + score += 2.0f; + return score; + } else { + score += 1.0f - trace.fraction; + } + } + } -void Camera::SetAutoRadiusEvent - ( - Event *ev - ) + // perform a dot product test for no watch cameras + if (spawnflags & NO_WATCH) { + trace_t trace; + float limit; + float threshold; + float dot; + Vector dir; - { - automatic_radius = ev->GetFloat( 1 ); - } + dir = player->centroid - origin; + dir.normalize(); + dot = dir * orientation[0]; -void Camera::SetAutoActiveEvent - ( - Event *ev - ) + threshold = cos(DEG2RAD((camera_fov * 0.25f))); + if (dot <= threshold) { + limit = cos(DEG2RAD((camera_fov * 0.45f))); + if (dot <= limit) { + // we are outside the viewing cone + score += 2.0f; + return score; + } else { + // our score is a scale between the two values + score += (threshold - dot) / (limit); + } + } - { - automatic_active = ev->GetBoolean( 1 ); - } + trace = + G_Trace(origin, vec_zero, vec_zero, player->origin, player, follow_mask, false, "Camera::CalculateScore"); + if (trace.startsolid || trace.allsolid || trace.fraction < 1.0f) { + // if we are blocked, push our score out, but not too much since this may be a temporary thing + if (trace.startsolid || trace.allsolid) { + score += 2.0f; + return score; + } else { + score += 1.0f - trace.fraction; + } + } + } -void Camera::SetAutoStartTimeEvent - ( - Event *ev - ) + return score; +} - { - automatic_startTime = ev->GetFloat( 1 ); - } +float Camera::AutomaticStart(Entity *player) +{ + if (!(spawnflags & NO_WATCH) && player) { + Watch(player, 0); + Cut(NULL); + } -void Camera::SetAutoStopTimeEvent - ( - Event *ev - ) + Unregister(STRING_START); + return automatic_startTime; +} - { - automatic_stopTime = ev->GetFloat( 1 ); - } +float Camera::AutomaticStop(Entity *player) +{ + Stop(); + return automatic_stopTime; +} +void Camera::UpdateStates(void) +{ + if (followTime && watchTime) { + newstate.Evaluate(this); + } else if (watchTime) { + newstate.watch.Evaluate(this, ¤tstate.move); + } else if (followTime) { + newstate.move.Evaluate(this); + } + currentstate.Evaluate(this); +} -void Camera::StopMoving - ( - Event *ev - ) +Vector Camera::CalculatePosition(void) +{ + int i; + float t; + Vector pos; - { - Stop(); - } + // + // calcualte position + // + if (followTime) { + t = followTime - level.time; + // + // are we still fading? + // + if (t <= 0) { + // + // if not zero out the fade + // + t = 0; + currentstate.move = newstate.move; + newstate.move.Initialize(this); + followTime = 0; + pos = currentstate.move.pos; + } else { + // + // if we are lerp over followFadeTime + // + t = (followFadeTime - t) / followFadeTime; -void Camera::Pause - ( - Event *ev - ) + for (i = 0; i < 3; i++) { + pos[i] = currentstate.move.pos[i] + (t * (newstate.move.pos[i] - currentstate.move.pos[i])); + } + } + } else { + pos = currentstate.move.pos; + } - { - CancelEventsOfType( EV_Camera_CameraThink ); - } + return pos; +} -void Camera::Continue - ( - Event *ev - ) +Vector Camera::CalculateOrientation(void) +{ + int i; + float t; + Vector ang; - { - CancelEventsOfType( EV_Camera_CameraThink ); - PostEvent( EV_Camera_CameraThink, 0 ); - } + // + // calculate orientation + // + if (watchTime) { + t = watchTime - level.time; + // + // are we still fading? + // + if (t <= 0) { + // + // if not zero out the fade + // + t = 0; + currentstate.watch = newstate.watch; + newstate.watch.Initialize(this); + watchTime = 0; + ang = currentstate.watch.watchAngles; + } else { + t = (watchFadeTime - t) / watchFadeTime; -void Camera::SetAnglesEvent - ( - Event *ev - ) + for (i = 0; i < 3; i++) { + ang[i] = LerpAngleFromCurrent( + currentstate.watch.watchAngles[i], newstate.watch.watchAngles[i], this->angles[i], t + ); + } + /* + warning("", "%.2f a x%.0f y%.0f z%.0f c x%.0f y%.0f z%.0f n x%.0f y%.0f z%.0f\n", + t, + ang[ 0 ], + ang[ 1 ], + ang[ 2 ], + currentstate.watch.watchAngles[ 0 ], + currentstate.watch.watchAngles[ 1 ], + currentstate.watch.watchAngles[ 2 ], + newstate.watch.watchAngles[ 0 ], + newstate.watch.watchAngles[ 1 ], + newstate.watch.watchAngles[ 2 ] + ); + */ + } + } else { + ang = currentstate.watch.watchAngles; + } - { - Vector ang; + return ang; +} - ang = ev->GetVector( 1 ); - setAngles( ang ); - } +float Camera::CalculateFov(void) +{ + float fov; + float t; -void Camera::SetSpeed - ( - Event *ev - ) + // + // calculate fov + // + // check if we have an auto_fov + if (auto_fov > 0) { + if (currentstate.watch.watchEnt) { + float distance; + float size; + float new_fov; + Entity *ent; - { - camera_speed = ev->GetFloat( 1 ); - } + ent = currentstate.watch.watchEnt; + size = ent->maxs[2] - ent->mins[2]; + size = ent->edict->r.radius / 2; + // cap the size + if (size < 16) { + size = 16; + } + distance = Vector(ent->centroid - origin).length(); + new_fov = RAD2DEG(2.0f * atan2(size, distance * auto_fov)); + if (new_fov > automatic_maxFOV) { + new_fov = automatic_maxFOV; + } else if (new_fov < 5) { + new_fov = 5; + } + return new_fov; + } else { + return 90; + } + } + // if we get here, we don't have an auto_fov, or we have an invalid watch target + if (fovTime) { + t = fovTime - level.time; + // + // are we still fading? + // + if (t <= 0) { + // + // if not zero out the fade + // + t = 0; + currentstate.fov = newstate.fov; + fovTime = 0; + fov = currentstate.fov; + } else { + // + // if we are lerp over fovFadeTime + // + t = (fovFadeTime - t) / fovFadeTime; + fov = currentstate.fov + (t * (newstate.fov - currentstate.fov)); + } + } else { + fov = currentstate.fov; + } -void Camera::SetFollowDistance - ( - Event *ev - ) + return fov; +} - { - follow_dist = ev->GetFloat( 1 ); - } +void Camera::CameraThink(Event *ev) +{ + UpdateStates(); -void Camera::SetOrbitHeight - ( - float height - ) + if (edict->s.parent == ENTITYNUM_NONE) { + setOrigin(CalculatePosition()); + setAngles(CalculateOrientation()); + } else { + setOrigin(); - { - orbit_height = height; - } + if (edict->s.attach_use_angles) { + orientation_t orient; + Vector ang; + Entity *ent = G_GetEntity(edict->s.parent); -void Camera::SetOrbitHeight - ( - Event *ev - ) + ent->GetTag(edict->s.tag_num & TAG_MASK, &orient); + MatrixToEulerAngles(orient.axis, ang); - { - orbit_height = ev->GetFloat( 1 ); - } + setAngles(ang); + } else { + setAngles(CalculateOrientation()); + } + } -void Camera::SetFollowYaw - ( - Event *ev - ) + camera_fov = CalculateFov(); - { - follow_yaw = ev->GetFloat( 1 ); - } + if (g_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + // + // client protocol below version 15 doesn't handle + // damage angles properly + // + if (m_bShowquakes && level.earthquake_magnitude) { + Vector randomness; -void Camera::AbsoluteYaw - ( - Event *ev - ) + // smooth earthquake + randomness[0] = G_CRandom(1.0f); + randomness[1] = G_CRandom(1.0f); + randomness[2] = G_CRandom(1.0f); - { - follow_yaw_fixed = true; - } + angles += randomness * level.earthquake_magnitude; + } + } -void Camera::RelativeYaw - ( - Event *ev - ) + // + // debug info + // + if (sv_showcameras->integer != showcamera) { + showcamera = sv_showcameras->integer; + if (showcamera) { + showModel(); + } else { + hideModel(); + } + } - { - follow_yaw_fixed = false; - } + if (sv_showcameras->integer != showcamera) { + showcamera = sv_showcameras->integer; + if (showcamera) { + showModel(); + } else { + hideModel(); + } + } + if (showcamera && currentstate.move.followingpath) { + G_Color3f(1, 1, 0); + if (currentstate.move.orbitEnt) { + currentstate.move.cameraPath.DrawCurve(currentstate.move.orbitEnt->origin, 10); + } else { + currentstate.move.cameraPath.DrawCurve(10); + } + } -void Camera::SetNextCamera - ( - Event *ev - ) + CancelEventsOfType(EV_Camera_CameraThink); + PostEvent(EV_Camera_CameraThink, 0.05f); +} - { - nextCamera = ev->GetString( 1 ); - } +void Camera::LookAt(Event *ev) +{ + Vector pos, delta; + Entity *ent; -void Camera::Cut - ( - Event *ev - ) - { - int j; + ent = ev->GetEntity(1); - if ( followTime ) - { - currentstate.move = newstate.move; - newstate.move.Initialize( this ); - followTime = 0; - } - if ( watchTime ) - { - currentstate.watch = newstate.watch; - newstate.watch.Initialize( this ); - watchTime = 0; - } - if ( fovTime ) - { - currentstate.fov = newstate.fov; - newstate.fov = camera_fov; - fovTime = 0; - } - CancelEventsOfType( EV_Camera_CameraThink ); - ProcessEvent( EV_Camera_CameraThink ); + if (!ent) { + return; + } - // - // let any clients know that this camera has just cut - // - for( j = 0; j < game.maxclients; j++ ) - { - gentity_t *other; - Player *client; + pos.x = ent->origin.x; + pos.y = ent->origin.y; + pos.z = ent->absmax.z; + delta = pos - origin; + delta.normalize(); - other = &g_entities[ j ]; - if ( other->inuse && other->client ) - { - client = ( Player * )other->entity; - client->CameraCut( this ); - } - } - } + currentstate.watch.watchAngles = delta.toAngles(); + setAngles(currentstate.watch.watchAngles); +} -void Camera::FadeTime - ( - Event *ev - ) +void Camera::TurnTo(Event *ev) +{ + currentstate.watch.watchAngles = ev->GetVector(1); + setAngles(currentstate.watch.watchAngles); +} - { - fadeTime = ev->GetFloat( 1 ); - } +void Camera::MoveToEntity(Event *ev) +{ + Entity *ent; -void Camera::OrbitEvent - ( - Event *ev - ) + ent = ev->GetEntity(1); + if (ent) { + currentstate.move.pos = ent->origin; + } + setOrigin(currentstate.move.pos); +} - { - Entity *ent; +void Camera::MoveToPos(Event *ev) +{ + currentstate.move.pos = ev->GetVector(1); + setOrigin(currentstate.move.pos); +} - spawnflags |= ORBIT; - ent = ev->GetEntity( 1 ); - if ( ent ) - { - Event * event; +void Camera::Stop(void) +{ + if (followTime) { + currentstate.move = newstate.move; + newstate.move.Initialize(this); + } + if (watchTime) { + currentstate.watch = newstate.watch; + newstate.watch.Initialize(this); + } + CancelEventsOfType(EV_Camera_CameraThink); - event = new Event( EV_Camera_StartMoving ); - event->AddEntity( ent ); - if ( ev->NumArgs() > 1 ) - { - event->AddEntity( ev->GetEntity( 2 ) ); - } - Stop(); - ProcessEvent( event ); - } - } + watchTime = 0; + followTime = 0; +} -void Camera::FollowEvent - ( - Event *ev - ) +void Camera::CreateOrbit(Vector pos, float radius, Vector& forward, Vector& left) +{ + newstate.move.cameraPath.Clear(); + newstate.move.cameraPath.SetType(SPLINE_LOOP); - { - Entity *ent; + newstate.move.cameraPath.AppendControlPoint(pos + radius * forward); + newstate.move.cameraPath.AppendControlPoint(pos + radius * left); + newstate.move.cameraPath.AppendControlPoint(pos - radius * forward); + newstate.move.cameraPath.AppendControlPoint(pos - radius * left); +} - spawnflags &= ~ORBIT; - ent = ev->GetEntity( 1 ); - if ( ent ) - { - Event * event; +void Camera::CreatePath(SplinePath *path, splinetype_t type) +{ + SplinePath *node; + SplinePath *loop; - event = new Event( EV_Camera_StartMoving ); - event->AddEntity( ent ); - if ( ev->NumArgs() > 1 ) - { - event->AddEntity( ev->GetEntity( 2 ) ); - } - Stop(); - ProcessEvent( event ); - } - } + newstate.move.cameraPath.Clear(); + newstate.move.cameraPath.SetType(type); -void Camera::SetFOV - ( - Event *ev - ) + newstate.move.splinePath = path; + newstate.move.currentNode = path; + newstate.move.loopNode = NULL; - { - float time; + node = path; + while (node != NULL) { + newstate.move.cameraPath.AppendControlPoint(node->origin, node->angles, node->speed); + loop = node->GetLoop(); + if (loop && (type == SPLINE_LOOP)) { + newstate.move.loopNode = loop; + newstate.move.cameraPath.SetLoopPoint(loop->origin); + } + node = node->GetNext(); - if ( ev->NumArgs() > 1 ) - { - time = ev->GetFloat( 2 ); - } - else - { - time = fadeTime; - } + if (node == path) { + break; + } + } - SetFOV( ev->GetFloat( 1 ), time ); - } + if ((type == SPLINE_LOOP) && (!newstate.move.loopNode)) { + newstate.move.loopNode = path; + } +} -void Camera::WatchEvent - ( - Event *ev - ) +void Camera::FollowPath(SplinePath *path, qboolean loop, Entity *watch) +{ + // make sure we process any setup events before continuing + ProcessPendingEvents(); + Stop(); + if (loop) { + CreatePath(path, SPLINE_LOOP); + } else { + CreatePath(path, SPLINE_CLAMP); + } + + newstate.move.cameraTime = -2; + newstate.move.lastTime = 0; + newstate.move.newTime = 0; + newstate.move.currentNode = path; + // evaluate the first node events + newstate.move.DoNodeEvents(this); + + if (watch) { + newstate.watch.watchEnt = watch; + } else { + Watch(newstate.move.currentNode->GetWatch(), newstate.move.currentNode->GetFadeTime()); + } + + followFadeTime = fadeTime; + watchFadeTime = fadeTime; + + newstate.move.followingpath = true; + followTime = level.time + followFadeTime; + watchTime = level.time + watchFadeTime; + + PostEvent(EV_Camera_CameraThink, FRAMETIME); +} + +void Camera::Orbit(Entity *ent, float dist, Entity *watch, float yaw_offset, qboolean dotrace) +{ + Vector ang, forward, left; + + // make sure we process any setup events before continuing + ProcessPendingEvents(); + + Stop(); + + if (watch) { + ang = watch->angles; + ang.y += yaw_offset; + } else { + ang = vec_zero; + ang.y += yaw_offset; + } + ang.AngleVectors(&forward, &left, NULL); + + orbit_dotrace = dotrace; + + CreateOrbit(Vector(0, 0, orbit_height), dist, forward, left); + newstate.move.cameraTime = -2; + newstate.move.lastTime = 0; + newstate.move.newTime = 0; + + newstate.move.orbitEnt = ent; + + followFadeTime = fadeTime; + watchFadeTime = fadeTime; + + newstate.move.followingpath = true; + followTime = level.time + followFadeTime; + watchTime = level.time + watchFadeTime; + newstate.move.currentNode = NULL; + + if (watch) { + newstate.watch.watchEnt = watch; + } else { + newstate.watch.watchEnt = ent; + } + + PostEvent(EV_Camera_CameraThink, FRAMETIME); +} + +void Camera::FollowEntity(Entity *ent, float dist, int mask, Entity *watch) +{ + // make sure we process any setup events before continuing + ProcessPendingEvents(); + + assert(ent); + + Stop(); + + if (ent) { + newstate.move.followEnt = ent; + newstate.move.followingpath = false; + + followFadeTime = fadeTime; + watchFadeTime = fadeTime; + + newstate.move.cameraTime = -2; + newstate.move.lastTime = 0; + newstate.move.newTime = 0; + newstate.move.currentNode = NULL; + + followTime = level.time + followFadeTime; + watchTime = level.time + watchFadeTime; + if (watch) { + newstate.watch.watchEnt = watch; + } else { + newstate.watch.watchEnt = ent; + } + follow_dist = dist; + follow_mask = mask; + PostEvent(EV_Camera_CameraThink, 0); + } +} + +void Camera::StartMoving(Event *ev) +{ + Entity *targetEnt; + Entity *targetWatchEnt; + Entity *ent; + SplinePath *path; + + if (ev->NumArgs() > 0) { + targetEnt = ev->GetEntity(1); + } else { + targetEnt = NULL; + } + + if (ev->NumArgs() > 1) { + targetWatchEnt = ev->GetEntity(2); + } else { + targetWatchEnt = NULL; + } + + if ((spawnflags & START_ON) && (!Q_stricmp(Target(), ""))) { + gi.Error(ERR_DROP, "Camera '%s' with START_ON selected, but no target specified.", TargetName().c_str()); + } + + if (!targetEnt) { + ent = (Entity *)G_FindTarget(NULL, Target()); + if (!ent) { + // + // we took this out just because of too many warnings, oh well + //warning("StartMoving", "Can't find target for camera\n" ); + // + // I put it back in as an error. Fuck em! Yeeeeeha! + // + gi.Error(ERR_DROP, "Can't find target '%s' for camera\n", Target().c_str()); + return; + } + } else { + ent = targetEnt; + } + + if (ent->isSubclassOf(SplinePath)) { + path = (SplinePath *)ent; + FollowPath(path, spawnflags & ORBIT, targetWatchEnt); + } else { + if (spawnflags & ORBIT) { + Orbit(ent, follow_dist, targetWatchEnt); + } else { + FollowEntity(ent, follow_dist, follow_mask, targetWatchEnt); + } + } +} + +void Camera::SetAutoStateEvent(Event *ev) +{ + int i; + + for (i = 1; i <= ev->NumArgs(); i++) { + char *buffer; + char com_token[MAX_QPATH]; + char com_buffer[MAX_STRING_CHARS]; + + Q_strncpyz(com_buffer, ev->GetString(i), sizeof(com_buffer)); + buffer = com_buffer; + // get the rest of the line + while (1) { + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); + if (!com_token[0]) { + break; + } + + automatic_states.AddUniqueObject(str(com_token)); + } + } +} + +void Camera::SetMaximumAutoFOVEvent(Event *ev) +{ + automatic_maxFOV = ev->GetFloat(1); +} + +void Camera::SetAutoRadiusEvent(Event *ev) +{ + automatic_radius = ev->GetFloat(1); +} + +void Camera::SetAutoActiveEvent(Event *ev) +{ + automatic_active = ev->GetBoolean(1); +} + +void Camera::SetAutoStartTimeEvent(Event *ev) +{ + automatic_startTime = ev->GetFloat(1); +} + +void Camera::SetAutoStopTimeEvent(Event *ev) +{ + automatic_stopTime = ev->GetFloat(1); +} + +void Camera::StopMoving(Event *ev) +{ + Stop(); +} + +void Camera::Pause(Event *ev) +{ + CancelEventsOfType(EV_Camera_CameraThink); +} + +void Camera::Continue(Event *ev) +{ + CancelEventsOfType(EV_Camera_CameraThink); + PostEvent(EV_Camera_CameraThink, 0); +} + +void Camera::SetAnglesEvent(Event *ev) +{ + Vector ang; + + ang = ev->GetVector(1); + setAngles(ang); +} + +void Camera::SetSpeed(Event *ev) +{ + camera_speed = ev->GetFloat(1); +} + +void Camera::SetFollowDistance(Event *ev) +{ + follow_dist = ev->GetFloat(1); +} + +void Camera::SetOrbitHeight(float height) +{ + orbit_height = height; +} + +void Camera::SetOrbitHeight(Event *ev) +{ + orbit_height = ev->GetFloat(1); +} + +void Camera::SetFollowYaw(Event *ev) +{ + follow_yaw = ev->GetFloat(1); +} + +void Camera::AbsoluteYaw(Event *ev) +{ + follow_yaw_fixed = true; +} + +void Camera::RelativeYaw(Event *ev) +{ + follow_yaw_fixed = false; +} + +void Camera::SetNextCamera(Event *ev) +{ + nextCamera = ev->GetString(1); +} + +void Camera::Cut(Event *ev) +{ + int j; + + if (followTime) { + currentstate.move = newstate.move; + newstate.move.Initialize(this); + followTime = 0; + } + if (watchTime) { + currentstate.watch = newstate.watch; + newstate.watch.Initialize(this); + watchTime = 0; + } + if (fovTime) { + currentstate.fov = newstate.fov; + newstate.fov = camera_fov; + fovTime = 0; + } + CancelEventsOfType(EV_Camera_CameraThink); + ProcessEvent(EV_Camera_CameraThink); + + // + // let any clients know that this camera has just cut + // + for (j = 0; j < game.maxclients; j++) { + gentity_t *other; + Player *client; + + other = &g_entities[j]; + if (other->inuse && other->client) { + client = (Player *)other->entity; + client->CameraCut(this); + } + } +} + +void Camera::FadeTime(Event *ev) +{ + fadeTime = ev->GetFloat(1); +} + +void Camera::OrbitEvent(Event *ev) +{ + Entity *ent; + + spawnflags |= ORBIT; + ent = ev->GetEntity(1); + if (ent) { + Event *event; + + event = new Event(EV_Camera_StartMoving); + event->AddEntity(ent); + if (ev->NumArgs() > 1) { + event->AddEntity(ev->GetEntity(2)); + } + Stop(); + ProcessEvent(event); + } +} + +void Camera::FollowEvent(Event *ev) +{ + Entity *ent; + + spawnflags &= ~ORBIT; + ent = ev->GetEntity(1); + if (ent) { + Event *event; + + event = new Event(EV_Camera_StartMoving); + event->AddEntity(ent); + if (ev->NumArgs() > 1) { + event->AddEntity(ev->GetEntity(2)); + } + Stop(); + ProcessEvent(event); + } +} + +void Camera::SetFOV(Event *ev) { float time; - if (ev->NumArgs() > 1) - { + if (ev->NumArgs() > 1) { time = ev->GetFloat(2); - } - else - { + } else { time = fadeTime; } - // fixed since mohaab v2.30 - // use the entity instead + SetFOV(ev->GetFloat(1), time); +} + +void Camera::WatchEvent(Event *ev) +{ + float time; + + if (ev->NumArgs() > 1) { + time = ev->GetFloat(2); + } else { + time = fadeTime; + } + + // fixed since mohaab v2.30 + // use the entity instead Watch(ev->GetEntity(1), time); } -void Camera::WatchStringEvent(Event* ev) { +void Camera::WatchStringEvent(Event *ev) +{ float time; - if (ev->NumArgs() > 1) - { + if (ev->NumArgs() > 1) { time = ev->GetFloat(2); - } - else - { + } else { time = fadeTime; } Watch(ev->GetString(1), time); } -void Camera::EventShowQuakes(Event* ev) +void Camera::EventShowQuakes(Event *ev) { - if (ev->NumArgs() > 0) - { + if (ev->NumArgs() > 0) { m_bShowquakes = ev->GetBoolean(1); } else { m_bShowquakes = qtrue; } } -Entity * GetWatchEntity - ( - str watch - ) +Entity *GetWatchEntity(str watch) +{ + const char *name; + Entity *ent; - { - const char *name; - Entity * ent; + // + // if empty just return + // + if (watch == "") { + return NULL; + } - // - // if empty just return - // - if ( watch == "" ) - { - return NULL; - } + // + // ignore all the reserved words + // + if ((watch == "path") || (watch == "none") || (watch == "node")) { + return NULL; + } - // - // ignore all the reserved words - // - if ( - ( watch == "path" ) || - ( watch == "none" ) || - ( watch == "node" ) - ) - { - return NULL; - } + name = watch.c_str(); - name = watch.c_str(); + if (name[0] == '*') { + if (!IsNumeric(&name[1])) { + gi.DPrintf("GetWatchEntity :: Expecting a numeric value but found '%s'.", &name[1]); + return NULL; + } else { + ent = G_GetEntity(atoi(&name[1])); + if (!ent) { + gi.DPrintf("GetWatchEntity :: Entity with targetname of '%s' not found", &name[1]); + return NULL; + } + } + } else if (name[0] == '$') { + ent = (Entity *)G_FindTarget(NULL, &name[1]); + if (!ent) { + gi.DPrintf("GetWatchEntity :: Entity with targetname of '%s' not found", &name[1]); + return NULL; + } + } else { + gi.DPrintf("GetWatchEntity :: Entity with targetname of '%s' not found", name); + return NULL; + } - if ( name[ 0 ] == '*' ) - { - if ( !IsNumeric( &name[ 1 ] ) ) - { - gi.DPrintf( "GetWatchEntity :: Expecting a numeric value but found '%s'.", &name[ 1 ] ); - return NULL; - } - else - { - ent = G_GetEntity( atoi( &name[ 1 ] ) ); - if ( !ent ) - { - gi.DPrintf( "GetWatchEntity :: Entity with targetname of '%s' not found", &name[ 1 ] ); - return NULL; - } - } - } - else if ( name[ 0 ] == '$' ) - { - ent = ( Entity * )G_FindTarget( NULL, &name[ 1 ] ); - if ( !ent ) - { - gi.DPrintf( "GetWatchEntity :: Entity with targetname of '%s' not found", &name[ 1 ] ); - return NULL; - } - } - else - { - gi.DPrintf( "GetWatchEntity :: Entity with targetname of '%s' not found", name ); - return NULL; - } + return ent; +} - return ent; - } +void Camera::Watch(str watch, float time) +{ + // make sure we process any setup events before continuing + ProcessPendingEvents(); -void Camera::Watch - ( - str watch, - float time - ) + // + // if empty just return + // + if (watch == "") { + return; + } - { - // make sure we process any setup events before continuing - ProcessPendingEvents(); + // + // clear out the watch variables + // + watchFadeTime = time; + newstate.watch.watchPath = false; + newstate.watch.watchNodes = false; + newstate.watch.watchEnt = NULL; + watchTime = level.time + watchFadeTime; + // + // really a watchpath command + // + if (watch == "path") { + newstate.watch.watchPath = true; + } + // + // really a watchnodes command + // + else if (watch == "node") { + newstate.watch.watchNodes = true; + } + // + // really a watchnodes command + // + else if (watch == "none") { + // intentionally blank + } + // + // just a normal watch command + // + else { + Entity *ent = GetWatchEntity(watch); + newstate.watch.watchEnt = ent; + } +} - // - // if empty just return - // - if ( watch == "" ) - return; +void Camera::Watch(Entity *ent, float time) +{ + // + // clear out the watch variables + // + watchFadeTime = time; + newstate.watch.watchPath = false; + newstate.watch.watchNodes = false; + watchTime = level.time + watchFadeTime; + newstate.watch.watchEnt = ent; +} - // - // clear out the watch variables - // - watchFadeTime = time; - newstate.watch.watchPath = false; - newstate.watch.watchNodes = false; - newstate.watch.watchEnt = NULL; - watchTime = level.time + watchFadeTime; - // - // really a watchpath command - // - if ( watch == "path" ) - { - newstate.watch.watchPath = true; - } - // - // really a watchnodes command - // - else if ( watch == "node" ) - { - newstate.watch.watchNodes = true; - } - // - // really a watchnodes command - // - else if ( watch == "none" ) - { - // intentionally blank - } - // - // just a normal watch command - // - else - { - Entity * ent = GetWatchEntity( watch ); - newstate.watch.watchEnt = ent; - } - } +void Camera::SetFOV(float fov, float time) +{ + // if it is less than 3, then we are setting an auto_fov state + if (fov < 3) { + auto_fov = fov; + } else { + // if we are explicitly setting the fov, turn the auto_fov off + auto_fov = 0; -void Camera::Watch - ( - Entity * ent, - float time - ) + fovFadeTime = time; + fovTime = level.time + fovFadeTime; + currentstate.fov = newstate.fov; + newstate.fov = fov; + } +} - { - // - // clear out the watch variables - // - watchFadeTime = time; - newstate.watch.watchPath = false; - newstate.watch.watchNodes = false; - watchTime = level.time + watchFadeTime; - newstate.watch.watchEnt = ent; - } +void Camera::WatchPathEvent(Event *ev) +{ + if (ev->NumArgs() > 1) { + watchFadeTime = ev->GetFloat(2); + } else { + watchFadeTime = fadeTime; + } + watchTime = level.time + watchFadeTime; + newstate.watch.watchEnt = NULL; + newstate.watch.watchNodes = false; + newstate.watch.watchPath = true; +} -void Camera::SetFOV - ( - float fov, - float time - ) +void Camera::WatchNodesEvent(Event *ev) +{ + if (ev->NumArgs() > 1) { + watchFadeTime = ev->GetFloat(2); + } else { + watchFadeTime = fadeTime; + } + watchTime = level.time + watchFadeTime; + newstate.watch.watchEnt = NULL; + newstate.watch.watchPath = false; + newstate.watch.watchNodes = true; +} - { - // if it is less than 3, then we are setting an auto_fov state - if ( fov < 3 ) - { - auto_fov = fov; - } - else - { - // if we are explicitly setting the fov, turn the auto_fov off - auto_fov = 0; +void Camera::NoWatchEvent(Event *ev) +{ + if (ev->NumArgs() > 1) { + watchFadeTime = ev->GetFloat(2); + } else { + watchFadeTime = fadeTime; + } + watchTime = level.time + watchFadeTime; + newstate.watch.watchEnt = NULL; + newstate.watch.watchPath = false; + newstate.watch.watchNodes = false; +} - fovFadeTime = time; - fovTime = level.time + fovFadeTime; - currentstate.fov = newstate.fov; - newstate.fov = fov; - } - } +void SetCamera(Entity *ent, float switchTime) +{ + int j; + gentity_t *other; + Camera *cam; + Player *client; -void Camera::WatchPathEvent - ( - Event *ev - ) + if (ent && !ent->isSubclassOf(Camera)) { + return; + } - { - if ( ev->NumArgs() > 1 ) - { - watchFadeTime = ev->GetFloat( 2 ); - } - else - { - watchFadeTime = fadeTime; - } + cam = (Camera *)ent; + for (j = 0; j < game.maxclients; j++) { + other = &g_entities[j]; + if (other->inuse && other->client) { + client = (Player *)other->entity; + client->SetCamera(cam, switchTime); + } + } +} - watchTime = level.time + watchFadeTime; - newstate.watch.watchEnt = NULL; - newstate.watch.watchNodes = false; - newstate.watch.watchPath = true; - } +str& Camera::NextCamera(void) +{ + return nextCamera; +} -void Camera::WatchNodesEvent - ( - Event *ev - ) +float Camera::Fov(void) +{ + return camera_fov; +} - { - if ( ev->NumArgs() > 1 ) - { - watchFadeTime = ev->GetFloat( 2 ); - } - else - { - watchFadeTime = fadeTime; - } - watchTime = level.time + watchFadeTime; - newstate.watch.watchEnt = NULL; - newstate.watch.watchPath = false; - newstate.watch.watchNodes = true; - } +void Camera::Reset(Vector org, Vector ang) +{ + setOrigin(org); + setAngles(ang); + currentstate.Initialize(this); + newstate.Initialize(this); +} -void Camera::NoWatchEvent - ( - Event *ev - ) +void Camera::bind(Entity *master, qboolean use_my_angles) +{ + Entity::bind(master, use_my_angles); - { - if ( ev->NumArgs() > 1 ) - { - watchFadeTime = ev->GetFloat( 2 ); - } - else - { - watchFadeTime = fadeTime; - } - watchTime = level.time + watchFadeTime; - newstate.watch.watchEnt = NULL; - newstate.watch.watchPath = false; - newstate.watch.watchNodes = false; - } + currentstate.move.pos = localorigin; +} -void SetCamera - ( - Entity *ent, - float switchTime - ) - - { - int j; - gentity_t *other; - Camera *cam; - Player *client; - - if ( ent && !ent->isSubclassOf( Camera ) ) - { - return; - } - - cam = ( Camera * )ent; - for( j = 0; j < game.maxclients; j++ ) - { - other = &g_entities[ j ]; - if ( other->inuse && other->client ) - { - client = ( Player * )other->entity; - client->SetCamera( cam, switchTime ); - } - } - } - -str &Camera::NextCamera - ( - void - ) - - { - return nextCamera; - } - -float Camera::Fov - ( - void - ) - - { - return camera_fov; - } - -void Camera::Reset - ( - Vector org, - Vector ang - ) - - { - setOrigin( org ); - setAngles( ang ); - currentstate.Initialize( this ); - newstate.Initialize( this ); - } - -void Camera::bind - ( - Entity *master, - qboolean use_my_angles - ) - - { - Entity::bind( master, use_my_angles ); - - currentstate.move.pos = localorigin; - } - -void Camera::unbind - ( - void - ) - - { - Entity::unbind(); - - currentstate.move.pos = origin; - } +void Camera::unbind(void) +{ + Entity::unbind(); + currentstate.move.pos = origin; +} /****************************************************************************** @@ -2303,1368 +1865,1131 @@ void Camera::unbind ******************************************************************************/ Event EV_CameraManager_NewPath - ( - "new", - EV_CONSOLE, - NULL, - NULL, - "Starts a new path.", - EV_NORMAL - ); +( + "new", + EV_CONSOLE, + NULL, + NULL, + "Starts a new path.", + EV_NORMAL +); Event EV_CameraManager_SetPath - ( - "setpath", - EV_CONSOLE, - "e", - "path", - "Sets the new path.", - EV_NORMAL - ); +( + "setpath", + EV_CONSOLE, + "e", + "path", + "Sets the new path.", + EV_NORMAL +); Event EV_CameraManager_SetTargetName - ( - "settargetname", - EV_CONSOLE, - "s", - "targetname", - "Set the targetname.", - EV_NORMAL - ); +( + "settargetname", + EV_CONSOLE, + "s", + "targetname", + "Set the targetname.", + EV_NORMAL +); Event EV_CameraManager_SetTarget - ( - "settarget", - EV_CONSOLE, - "s", - "target", - "Set the trigger target.", - EV_NORMAL - ); +( + "settarget", + EV_CONSOLE, + "s", + "target", + "Set the trigger target.", + EV_NORMAL +); Event EV_CameraManager_AddPoint - ( - "add", - EV_CONSOLE, - NULL, - NULL, - "Add a new point to the camera path where the player is standing.", - EV_NORMAL - ); +( + "add", + EV_CONSOLE, + NULL, + NULL, + "Add a new point to the camera path where the player is standing.", + EV_NORMAL +); Event EV_CameraManager_DeletePoint - ( - "delete", - EV_CONSOLE, - NULL, - NULL, - "Delete the current path node.", - EV_NORMAL - ); +( + "delete", + EV_CONSOLE, + NULL, + NULL, + "Delete the current path node.", + EV_NORMAL +); Event EV_CameraManager_MovePlayer - ( - "moveplayer", - EV_CONSOLE, - NULL, - NULL, - "Move the player to the current path node position.", - EV_NORMAL - ); +( + "moveplayer", + EV_CONSOLE, + NULL, + NULL, + "Move the player to the current path node position.", + EV_NORMAL +); Event EV_CameraManager_ReplacePoint - ( - "replace", - EV_CONSOLE, - NULL, - NULL, - "Replace the current path node position/angle with the player's.", - EV_NORMAL - ); +( + "replace", + EV_CONSOLE, + NULL, + NULL, + "Replace the current path node position/angle with the player's.", + EV_NORMAL +); Event EV_CameraManager_NextPoint - ( - "next", - EV_CONSOLE, - NULL, - NULL, - "Go to the next path node.", - EV_NORMAL - ); +( + "next", + EV_CONSOLE, + NULL, + NULL, + "Go to the next path node.", + EV_NORMAL +); Event EV_CameraManager_PreviousPoint - ( - "prev", - EV_CONSOLE, - NULL, - NULL, - "Go to the previous path node.", - EV_NORMAL - ); +( + "prev", + EV_CONSOLE, + NULL, + NULL, + "Go to the previous path node.", + EV_NORMAL +); Event EV_CameraManager_ShowPath - ( - "show", - EV_CONSOLE, - "E", - "path", - "Shows the specified path.", - EV_NORMAL - ); +( + "show", + EV_CONSOLE, + "E", + "path", + "Shows the specified path.", + EV_NORMAL +); Event EV_CameraManager_ShowingPath - ( - "_showing_path", - EV_CONSOLE, - NULL, - NULL, - "Internal event for showing the path.", - EV_NORMAL - ); +( + "_showing_path", + EV_CONSOLE, + NULL, + NULL, + "Internal event for showing the path.", + EV_NORMAL +); Event EV_CameraManager_HidePath - ( - "hide", - EV_CONSOLE, - NULL, - NULL, - "Hides the paths.", - EV_NORMAL - ); +( + "hide", + EV_CONSOLE, + NULL, + NULL, + "Hides the paths.", + EV_NORMAL +); Event EV_CameraManager_PlayPath - ( - "play", - EV_CONSOLE, - "E", - "path", - "Play the current path or the specified one once.", - EV_NORMAL - ); +( + "play", + EV_CONSOLE, + "E", + "path", + "Play the current path or the specified one once.", + EV_NORMAL +); Event EV_CameraManager_LoopPath - ( - "loop", - EV_CONSOLE, - "E", - "path", - "Loop the current path or the specified one.", - EV_NORMAL - ); +( + "loop", + EV_CONSOLE, + "E", + "path", + "Loop the current path or the specified one.", + EV_NORMAL +); Event EV_CameraManager_StopPlayback - ( - "stop", - EV_CONSOLE, - NULL, - NULL, - "Stop the camera playing path.", - EV_NORMAL - ); +( + "stop", + EV_CONSOLE, + NULL, + NULL, + "Stop the camera playing path.", + EV_NORMAL +); Event EV_CameraManager_Watch - ( - "watch", - EV_CONSOLE, - "s", - "watch", - "Set the current path node to watch something.", - EV_NORMAL - ); +( + "watch", + EV_CONSOLE, + "s", + "watch", + "Set the current path node to watch something.", + EV_NORMAL +); Event EV_CameraManager_NoWatch - ( - "nowatch", - EV_CONSOLE, - NULL, - NULL, - "Set the current path node to watch nothing.", - EV_NORMAL - ); +( + "nowatch", + EV_CONSOLE, + NULL, + NULL, + "Set the current path node to watch nothing.", + EV_NORMAL +); Event EV_CameraManager_Fov - ( - "setfov", - EV_CONSOLE, - "s", - "newFOV", - "Set the fov at the current path node.", - EV_NORMAL - ); +( + "setfov", + EV_CONSOLE, + "s", + "newFOV", + "Set the fov at the current path node.", + EV_NORMAL +); Event EV_CameraManager_FadeTime - ( - "setfadetime", - EV_CONSOLE, - "f", - "newFadeTime", - "Set the fadetime of the current path node.", - EV_NORMAL - ); +( + "setfadetime", + EV_CONSOLE, + "f", + "newFadeTime", + "Set the fadetime of the current path node.", + EV_NORMAL +); Event EV_CameraManager_Speed - ( - "setspeed", - EV_CONSOLE, - "f", - "speed", - "Set the speed of the camera at the current path node.", - EV_NORMAL - ); +( + "setspeed", + EV_CONSOLE, + "f", + "speed", + "Set the speed of the camera at the current path node.", + EV_NORMAL +); Event EV_CameraManager_Save - ( - "save", - EV_CONSOLE, - "s", - "filename", - "Saves the camera path.", - EV_NORMAL - ); +( + "save", + EV_CONSOLE, + "s", + "filename", + "Saves the camera path.", + EV_NORMAL +); Event EV_CameraManager_Load - ( - "load", - EV_CONSOLE, - "s", - "filename", - "Loads a camera path.", - EV_NORMAL - ); +( + "load", + EV_CONSOLE, + "s", + "filename", + "Loads a camera path.", + EV_NORMAL +); Event EV_CameraManager_SaveMap - ( - "savemap", - EV_CONSOLE, - "s", - "filename", - "Saves the camera path to a map file.", - EV_NORMAL - ); +( + "savemap", + EV_CONSOLE, + "s", + "filename", + "Saves the camera path to a map file.", + EV_NORMAL +); Event EV_CameraManager_UpdateInput - ( - "updateinput", - EV_CONSOLE, - NULL, - NULL, - "Updates the current node with user interface values.", - EV_NORMAL - ); +( + "updateinput", + EV_CONSOLE, + NULL, + NULL, + "Updates the current node with user interface values.", + EV_NORMAL +); Event EV_CameraManager_NextPath - ( - "nextpath", - EV_CONSOLE, - NULL, - NULL, - "Go to the next path.", - EV_NORMAL - ); +( + "nextpath", + EV_CONSOLE, + NULL, + NULL, + "Go to the next path.", + EV_NORMAL +); Event EV_CameraManager_PreviousPath - ( - "prevpath", - EV_CONSOLE, - NULL, - NULL, - "Go to the previous path.", - EV_NORMAL - ); +( + "prevpath", + EV_CONSOLE, + NULL, + NULL, + "Go to the previous path.", + EV_NORMAL +); Event EV_CameraManager_RenamePath - ( - "renamepath", - EV_CONSOLE, - "s", - "newName", - "Rename the path to the new name.", - EV_NORMAL - ); +( + "renamepath", + EV_CONSOLE, + "s", + "newName", + "Rename the path to the new name.", + EV_NORMAL +); -CLASS_DECLARATION( Listener, CameraManager, NULL ) - { - { &EV_CameraManager_NewPath, &CameraManager::NewPath }, - { &EV_CameraManager_SetPath, &CameraManager::SetPath }, - { &EV_CameraManager_SetTargetName, &CameraManager::SetTargetName }, - { &EV_CameraManager_SetTarget, &CameraManager::SetTarget }, - { &EV_CameraManager_SetPath, &CameraManager::SetPath }, - { &EV_CameraManager_AddPoint, &CameraManager::AddPoint }, - { &EV_CameraManager_ReplacePoint, &CameraManager::ReplacePoint }, - { &EV_CameraManager_DeletePoint, &CameraManager::DeletePoint }, - { &EV_CameraManager_MovePlayer, &CameraManager::MovePlayer }, - { &EV_CameraManager_NextPoint, &CameraManager::NextPoint }, - { &EV_CameraManager_PreviousPoint, &CameraManager::PreviousPoint }, - { &EV_CameraManager_ShowPath, &CameraManager::ShowPath }, - { &EV_CameraManager_ShowingPath, &CameraManager::ShowingPath }, - { &EV_CameraManager_HidePath, &CameraManager::HidePath }, - { &EV_CameraManager_PlayPath, &CameraManager::PlayPath }, - { &EV_CameraManager_LoopPath, &CameraManager::LoopPath }, - { &EV_CameraManager_StopPlayback, &CameraManager::StopPlayback }, - { &EV_CameraManager_Watch, &CameraManager::Watch }, - { &EV_CameraManager_NoWatch, &CameraManager::NoWatch }, - { &EV_CameraManager_Fov, &CameraManager::Fov }, - { &EV_CameraManager_FadeTime, &CameraManager::FadeTime }, - { &EV_CameraManager_Speed, &CameraManager::Speed }, - { &EV_CameraManager_Save, &CameraManager::Save }, - { &EV_CameraManager_Load, &CameraManager::Load }, - { &EV_CameraManager_SaveMap, &CameraManager::SaveMap }, - { &EV_CameraManager_UpdateInput, &CameraManager::UpdateEvent }, - { &EV_CameraManager_NextPath, &CameraManager::NextPath }, - { &EV_CameraManager_PreviousPath, &CameraManager::PreviousPath }, - { &EV_CameraManager_RenamePath, &CameraManager::RenamePath }, - { NULL, NULL } - }; +CLASS_DECLARATION(Listener, CameraManager, NULL) { + {&EV_CameraManager_NewPath, &CameraManager::NewPath }, + {&EV_CameraManager_SetPath, &CameraManager::SetPath }, + {&EV_CameraManager_SetTargetName, &CameraManager::SetTargetName}, + {&EV_CameraManager_SetTarget, &CameraManager::SetTarget }, + {&EV_CameraManager_SetPath, &CameraManager::SetPath }, + {&EV_CameraManager_AddPoint, &CameraManager::AddPoint }, + {&EV_CameraManager_ReplacePoint, &CameraManager::ReplacePoint }, + {&EV_CameraManager_DeletePoint, &CameraManager::DeletePoint }, + {&EV_CameraManager_MovePlayer, &CameraManager::MovePlayer }, + {&EV_CameraManager_NextPoint, &CameraManager::NextPoint }, + {&EV_CameraManager_PreviousPoint, &CameraManager::PreviousPoint}, + {&EV_CameraManager_ShowPath, &CameraManager::ShowPath }, + {&EV_CameraManager_ShowingPath, &CameraManager::ShowingPath }, + {&EV_CameraManager_HidePath, &CameraManager::HidePath }, + {&EV_CameraManager_PlayPath, &CameraManager::PlayPath }, + {&EV_CameraManager_LoopPath, &CameraManager::LoopPath }, + {&EV_CameraManager_StopPlayback, &CameraManager::StopPlayback }, + {&EV_CameraManager_Watch, &CameraManager::Watch }, + {&EV_CameraManager_NoWatch, &CameraManager::NoWatch }, + {&EV_CameraManager_Fov, &CameraManager::Fov }, + {&EV_CameraManager_FadeTime, &CameraManager::FadeTime }, + {&EV_CameraManager_Speed, &CameraManager::Speed }, + {&EV_CameraManager_Save, &CameraManager::Save }, + {&EV_CameraManager_Load, &CameraManager::Load }, + {&EV_CameraManager_SaveMap, &CameraManager::SaveMap }, + {&EV_CameraManager_UpdateInput, &CameraManager::UpdateEvent }, + {&EV_CameraManager_NextPath, &CameraManager::NextPath }, + {&EV_CameraManager_PreviousPath, &CameraManager::PreviousPath }, + {&EV_CameraManager_RenamePath, &CameraManager::RenamePath }, + {NULL, NULL } +}; -Player *CameraManager_GetPlayer - ( - void - ) +Player *CameraManager_GetPlayer(void) +{ + assert(g_entities[0].entity && g_entities[0].entity->isSubclassOf(Player)); + if (!g_entities[0].entity || !(g_entities[0].entity->isSubclassOf(Player))) { + gi.Printf("No player found.\n"); + return NULL; + } - { - assert( g_entities[ 0 ].entity && g_entities[ 0 ].entity->isSubclassOf( Player ) ); - if ( !g_entities[ 0 ].entity || !( g_entities[ 0 ].entity->isSubclassOf( Player ) ) ) - { - gi.Printf( "No player found.\n" ); - return NULL; - } - - return ( Player * )g_entities[ 0 ].entity; - } + return (Player *)g_entities[0].entity; +} CameraManager::CameraManager() - { - pathList.ClearObjectList(); - path = NULL; - current = NULL; - cameraPath_dirty = qtrue; - speed = 1; - watch = 0; - cam = NULL; - } - -void CameraManager::UpdateUI - ( - void - ) - { - int num; - SplinePath *next; - float temp; - - // - // set path name - // - gi.cvar_set( "cam_filename", pathName ); - if ( current ) - { - - gi.cvar_set( "cam_origin", va( "%.2f %.2f %.2f", current->origin[ 0 ], current->origin[ 1 ], current->origin[ 2 ] ) ); - gi.cvar_set( "cam_angles_yaw", va( "%.1f", current->angles[ YAW ] ) ); - gi.cvar_set( "cam_angles_pitch", va( "%.1f", current->angles[ PITCH ] ) ); - gi.cvar_set( "cam_angles_roll", va( "%.1f", current->angles[ ROLL ] ) ); - gi.cvar_set( "cam_thread", current->thread.c_str() ); - gi.cvar_set( "cam_target", current->triggertarget.c_str() ); - gi.cvar_set( "cam_watch", current->watchEnt.c_str() ); - temp = current->GetFov(); - if ( temp ) - { - gi.cvar_set( "cam_fov", va( "%.1f", temp ) ); - } - else - { - gi.cvar_set( "cam_fov", "Default" ); - } - temp = current->GetFadeTime(); - if ( temp != -1 ) - { - gi.cvar_set( "cam_fadetime", va( "%.2f", temp ) ); - } - else - { - gi.cvar_set( "cam_fadetime", "Default" ); - } - gi.cvar_set( "cam_speed", va( "%.1f", current->speed ) ); - - // - // set node num - // - num = 0; - next = path; - while ( next && ( next != current ) ) - { - next = next->GetNext(); - num++; - } - gi.cvar_set( "cam_nodenum", va( "%d", num ) ); - } - } - -void CameraManager::UpdateEvent - ( - Event *ev - ) - { - Vector tempvec; - cvar_t * cvar; - - if ( !current ) - { - return; - } - - // get origin - cvar = gi.Cvar_Get( "cam_origin", "", 0 ); - sscanf( cvar->string, "%f %f %f", &tempvec[ 0 ], &tempvec[ 1 ], &tempvec[ 2 ] ); - current->setOrigin( tempvec ); - - // get angles yaw - cvar = gi.Cvar_Get( "cam_angles_yaw", "", 0 ); - current->angles[ YAW ] = cvar->value; - - // get angles pitch - cvar = gi.Cvar_Get( "cam_angles_pitch", "", 0 ); - current->angles[ PITCH ] = cvar->value; - - // get angles roll - cvar = gi.Cvar_Get( "cam_angles_roll", "", 0 ); - current->angles[ ROLL ] = cvar->value; - - current->setAngles( current->angles ); - - // get target - cvar = gi.Cvar_Get( "cam_target", "", 0 ); - current->SetTriggerTarget( cvar->string ); - - // get watch - cvar = gi.Cvar_Get( "cam_watch", "", 0 ); - current->SetWatch( cvar->string ); - - // get fov - cvar = gi.Cvar_Get( "cam_fov", "", 0 ); - current->SetFov( cvar->value ); - - // get fadetime - cvar = gi.Cvar_Get( "cam_fadetime", "", 0 ); - current->SetFadeTime( cvar->value ); - - // get speed - cvar = gi.Cvar_Get( "cam_speed", "", 0 ); - current->speed = cvar->value; - } - -void CameraManager::SetPathName - ( - str name - ) - - { - pathName = name; - UpdateUI(); - } - -void CameraManager::NewPath - ( - Event *ev - ) - - { - if ( path ) - { - cameraPath_dirty = qtrue; - path = NULL; - current = NULL; - } - SetPathName( "untitled" ); - ShowPath(); - } - -void CameraManager::RenamePath - ( - Event *ev - ) - - { - str name; - - if ( !ev->NumArgs() ) - { - cvar_t * cvar; - - // - // get the path name from the cvar - // - cvar = gi.Cvar_Get( "cam_filename", "", 0 ); - if ( cvar->string[ 0 ] ) - { - name = cvar->string; - } - else - { - ScriptError( "Usage: cam renamepath [pathname]" ); - return; - } - } - else - { - name = ev->GetString( 1 ); - } - - if ( pathList.ObjectInList( name ) ) - { - // remove the old name - pathList.RemoveObject( name ); - } - SetPathName( name ); - pathList.AddUniqueObject( name ); - } - -void CameraManager::SetPath - ( - str pathName - ) - - { - Entity * ent; - SplinePath *node; - - ent = ( Entity * )G_FindTarget( NULL, pathName ); - - if ( !ent ) - { - warning( "SetPath", "Could not find path named '%s'.", pathName.c_str() ); - return; - } - - if ( !ent->isSubclassOf( SplinePath ) ) - { - warning( "SetPath", "'%s' is not a camera path.", pathName.c_str() ); - return; - } - node = ( SplinePath * )ent; - - SetPathName( pathName ); - cameraPath_dirty = qtrue; - path = node; - current = node; - UpdateUI(); - } - -void CameraManager::SetPath - ( - Event *ev - ) - - { - if ( !ev->NumArgs() ) - { - ScriptError( "Usage: cam setpath [pathname]" ); - return; - } - - SetPath( ev->GetString( 1 ) ); - } - -void CameraManager::SetTargetName - ( - Event *ev - ) - - { - if ( ev->NumArgs() != 1 ) - { - ScriptError( "Usage: cam targetname [name]" ); - return; - } - - if ( !path ) - { - ScriptError( "Camera path not set." ); - return; - } - - path->SetTargetName( ev->GetString( 1 ) ); - UpdateUI(); - } - -void CameraManager::SetTarget - ( - Event *ev - ) - - { - if ( ev->NumArgs() != 1 ) - { - ScriptError( "Usage: cam target [name]" ); - return; - } - - if ( !current ) - { - ScriptError( "Camera path not set." ); - return; - } - - current->SetTriggerTarget( ev->GetString( 1 ) ); - UpdateUI(); - } - -void CameraManager::AddPoint - ( - Event *ev - ) - - { - Player *player; - SplinePath *prev; - SplinePath *next; - Vector ang; - Vector pos; - - player = CameraManager_GetPlayer(); - if ( player ) - { - prev = current; - if ( current ) - { - next = current->GetNext(); - } - else - { - next = NULL; - } - - player->GetPlayerView( &pos, &ang ); - - current = new SplinePath; - current->setOrigin( pos ); - current->setAngles( ang ); - current->speed = speed; - current->SetPrev( prev ); - current->SetNext( next ); - - if ( !path ) - { - path = current; - } - - ShowPath(); - } - cameraPath_dirty = qtrue; - UpdateUI(); - } - -void CameraManager::ReplacePoint - ( - Event *ev - ) - - { - Player *player; - Vector ang; - Vector pos; - - player = CameraManager_GetPlayer(); - if ( current && player ) - { - player->GetPlayerView( &pos, &ang ); - - current->setOrigin( pos ); - current->setAngles( ang ); - current->speed = speed; - } - cameraPath_dirty = qtrue; - UpdateUI(); - } - -void CameraManager::DeletePoint - ( - Event *ev - ) - - { - SplinePath *node; - - if ( current ) - { - node = current->GetNext(); - if ( !node ) - { - node = current->GetPrev(); - } - - if ( ( SplinePath * )path == ( SplinePath * )current ) - { - path = current->GetNext(); - } - - delete current; - current = node; - } - cameraPath_dirty = qtrue; - UpdateUI(); - } - -void CameraManager::MovePlayer - ( - Event *ev - ) - - { - Player *player; - Vector pos; - - player = CameraManager_GetPlayer(); - if ( current && player ) - { - player->GetPlayerView( &pos, NULL ); - - player->setOrigin( current->origin - pos + player->origin ); - player->SetViewAngles( current->angles ); - player->SetFov( current->fov ); - } - } - -void CameraManager::NextPoint - ( - Event *ev - ) - - { - SplinePath *next; - - if ( current ) - { - next = current->GetNext(); - if ( next ) - { - current = next; - } - } - UpdateUI(); - } - -void CameraManager::PreviousPoint - ( - Event *ev - ) - - { - SplinePath *prev; - - if ( current ) - { - prev = current->GetPrev(); - if ( prev ) - { - current = prev; - } - } - UpdateUI(); - } - -void CameraManager::NextPath - ( - Event *ev - ) - - { - int index; - - // - // find current path in container of paths - // - index = pathList.IndexOfObject( pathName ); - if ( index < pathList.NumObjects() ) - index++; - - if ( index > 0 ) - { - SetPath( pathList.ObjectAt( index ) ); - UpdateUI(); - } - } - -void CameraManager::PreviousPath - ( - Event *ev - ) - - { - int index; - - // - // find current path in container of paths - // - index = pathList.IndexOfObject( pathName ); - if ( index > 1 ) - index--; - - if ( index > 0 ) - { - SetPath( pathList.ObjectAt( index ) ); - UpdateUI(); - } - } - -void CameraManager::ShowingPath - ( - Event *ev - ) - - { - int count; - SplinePath *node; - SplinePath *prev; - Vector mins( -8, -8, -8 ); - Vector maxs( 8, 8, 8 ); - - prev = NULL; - for( node = path; node != NULL; node = node->GetNext() ) - { - if ( prev ) - { - G_LineStipple( 4, ( unsigned short )( 0xF0F0F0F0 >> ( 7 - ( level.framenum & 7 ) ) ) ); - G_DebugLine( prev->origin, node->origin, 0.4f, 0.4f, 0.4f, 0.1f ); - G_LineStipple( 1, 0xffff ); - } - - if ( current == node ) - { - G_DrawDebugNumber( node->origin + Vector( 0, 0, 20 ), node->speed, 0.5, 0, 1, 0, 1 ); - if ( current->GetFov() ) - G_DrawDebugNumber( node->origin + Vector( 0, 0, 30 ), node->GetFov(), 0.5, 0, 0, 1, 0 ); - G_DebugBBox( node->origin, mins, maxs, 1, 1, 0, 1 ); - } - else - { - G_DebugBBox( node->origin, mins, maxs, 1, 0, 0, 1 ); - } - - // - // draw watch - // - if ( node->doWatch ) - { - Entity *watchEnt; - Vector ang; - Vector delta; - Vector left; - Vector up; - Vector endpoint; - - watchEnt = GetWatchEntity( node->GetWatch() ); - if ( watchEnt ) - { - delta.x = watchEnt->origin.x; - delta.y = watchEnt->origin.y; - delta.z = watchEnt->absmax.z; - delta -= node->origin; - delta.normalize(); - ang = delta.toAngles(); - ang.AngleVectors( NULL, &left, &up ); - - G_LineWidth( 1 ); - endpoint = node->origin + delta * 48; - G_DebugLine( node->origin, endpoint, 0.5, 1, 1, 1 ); - G_DebugLine( endpoint, endpoint + (left * 8) - (delta * 8), 0.5, 1, 1, 1 ); - G_DebugLine( endpoint, endpoint - (left * 8) - (delta * 8), 0.5, 1, 1, 1 ); - G_DebugLine( endpoint, endpoint - (up * 8) - (delta * 8), 0.5, 1, 1, 1 ); - G_DebugLine( endpoint, endpoint + (up * 8) - (delta * 8), 0.5, 1, 1, 1 ); +{ + pathList.ClearObjectList(); + path = NULL; + current = NULL; + cameraPath_dirty = qtrue; + speed = 1; + watch = 0; + cam = NULL; +} + +void CameraManager::UpdateUI(void) +{ + int num; + SplinePath *next; + float temp; + + // + // set path name + // + gi.cvar_set("cam_filename", pathName); + if (current) { + gi.cvar_set("cam_origin", va("%.2f %.2f %.2f", current->origin[0], current->origin[1], current->origin[2])); + gi.cvar_set("cam_angles_yaw", va("%.1f", current->angles[YAW])); + gi.cvar_set("cam_angles_pitch", va("%.1f", current->angles[PITCH])); + gi.cvar_set("cam_angles_roll", va("%.1f", current->angles[ROLL])); + gi.cvar_set("cam_thread", current->thread.c_str()); + gi.cvar_set("cam_target", current->triggertarget.c_str()); + gi.cvar_set("cam_watch", current->watchEnt.c_str()); + temp = current->GetFov(); + if (temp) { + gi.cvar_set("cam_fov", va("%.1f", temp)); + } else { + gi.cvar_set("cam_fov", "Default"); + } + temp = current->GetFadeTime(); + if (temp != -1) { + gi.cvar_set("cam_fadetime", va("%.2f", temp)); + } else { + gi.cvar_set("cam_fadetime", "Default"); + } + gi.cvar_set("cam_speed", va("%.1f", current->speed)); + + // + // set node num + // + num = 0; + next = path; + while (next && (next != current)) { + next = next->GetNext(); + num++; + } + gi.cvar_set("cam_nodenum", va("%d", num)); + } +} + +void CameraManager::UpdateEvent(Event *ev) +{ + Vector tempvec; + cvar_t *cvar; + + if (!current) { + return; + } + + // get origin + cvar = gi.Cvar_Get("cam_origin", "", 0); + sscanf(cvar->string, "%f %f %f", &tempvec[0], &tempvec[1], &tempvec[2]); + current->setOrigin(tempvec); + + // get angles yaw + cvar = gi.Cvar_Get("cam_angles_yaw", "", 0); + current->angles[YAW] = cvar->value; + + // get angles pitch + cvar = gi.Cvar_Get("cam_angles_pitch", "", 0); + current->angles[PITCH] = cvar->value; + + // get angles roll + cvar = gi.Cvar_Get("cam_angles_roll", "", 0); + current->angles[ROLL] = cvar->value; + + current->setAngles(current->angles); + + // get target + cvar = gi.Cvar_Get("cam_target", "", 0); + current->SetTriggerTarget(cvar->string); + + // get watch + cvar = gi.Cvar_Get("cam_watch", "", 0); + current->SetWatch(cvar->string); + + // get fov + cvar = gi.Cvar_Get("cam_fov", "", 0); + current->SetFov(cvar->value); + + // get fadetime + cvar = gi.Cvar_Get("cam_fadetime", "", 0); + current->SetFadeTime(cvar->value); + + // get speed + cvar = gi.Cvar_Get("cam_speed", "", 0); + current->speed = cvar->value; +} + +void CameraManager::SetPathName(str name) +{ + pathName = name; + UpdateUI(); +} + +void CameraManager::NewPath(Event *ev) +{ + if (path) { + cameraPath_dirty = qtrue; + path = NULL; + current = NULL; + } + SetPathName("untitled"); + ShowPath(); +} + +void CameraManager::RenamePath(Event *ev) +{ + str name; + + if (!ev->NumArgs()) { + cvar_t *cvar; + + // + // get the path name from the cvar + // + cvar = gi.Cvar_Get("cam_filename", "", 0); + if (cvar->string[0]) { + name = cvar->string; + } else { + ScriptError("Usage: cam renamepath [pathname]"); + return; + } + } else { + name = ev->GetString(1); + } + + if (pathList.ObjectInList(name)) { + // remove the old name + pathList.RemoveObject(name); + } + SetPathName(name); + pathList.AddUniqueObject(name); +} + +void CameraManager::SetPath(str pathName) +{ + Entity *ent; + SplinePath *node; + + ent = (Entity *)G_FindTarget(NULL, pathName); + + if (!ent) { + warning("SetPath", "Could not find path named '%s'.", pathName.c_str()); + return; + } + + if (!ent->isSubclassOf(SplinePath)) { + warning("SetPath", "'%s' is not a camera path.", pathName.c_str()); + return; + } + node = (SplinePath *)ent; + + SetPathName(pathName); + cameraPath_dirty = qtrue; + path = node; + current = node; + UpdateUI(); +} + +void CameraManager::SetPath(Event *ev) +{ + if (!ev->NumArgs()) { + ScriptError("Usage: cam setpath [pathname]"); + return; + } + + SetPath(ev->GetString(1)); +} + +void CameraManager::SetTargetName(Event *ev) +{ + if (ev->NumArgs() != 1) { + ScriptError("Usage: cam targetname [name]"); + return; + } + + if (!path) { + ScriptError("Camera path not set."); + return; + } + + path->SetTargetName(ev->GetString(1)); + UpdateUI(); +} + +void CameraManager::SetTarget(Event *ev) +{ + if (ev->NumArgs() != 1) { + ScriptError("Usage: cam target [name]"); + return; + } + + if (!current) { + ScriptError("Camera path not set."); + return; + } + + current->SetTriggerTarget(ev->GetString(1)); + UpdateUI(); +} + +void CameraManager::AddPoint(Event *ev) +{ + Player *player; + SplinePath *prev; + SplinePath *next; + Vector ang; + Vector pos; + + player = CameraManager_GetPlayer(); + if (player) { + prev = current; + if (current) { + next = current->GetNext(); + } else { + next = NULL; + } + + player->GetPlayerView(&pos, &ang); + + current = new SplinePath; + current->setOrigin(pos); + current->setAngles(ang); + current->speed = speed; + current->SetPrev(prev); + current->SetNext(next); + + if (!path) { + path = current; + } + + ShowPath(); + } + cameraPath_dirty = qtrue; + UpdateUI(); +} + +void CameraManager::ReplacePoint(Event *ev) +{ + Player *player; + Vector ang; + Vector pos; + + player = CameraManager_GetPlayer(); + if (current && player) { + player->GetPlayerView(&pos, &ang); + + current->setOrigin(pos); + current->setAngles(ang); + current->speed = speed; + } + cameraPath_dirty = qtrue; + UpdateUI(); +} + +void CameraManager::DeletePoint(Event *ev) +{ + SplinePath *node; + + if (current) { + node = current->GetNext(); + if (!node) { + node = current->GetPrev(); + } + + if ((SplinePath *)path == (SplinePath *)current) { + path = current->GetNext(); + } + + delete current; + current = node; + } + cameraPath_dirty = qtrue; + UpdateUI(); +} + +void CameraManager::MovePlayer(Event *ev) +{ + Player *player; + Vector pos; + + player = CameraManager_GetPlayer(); + if (current && player) { + player->GetPlayerView(&pos, NULL); + + player->setOrigin(current->origin - pos + player->origin); + player->SetViewAngles(current->angles); + player->SetFov(current->fov); + } +} + +void CameraManager::NextPoint(Event *ev) +{ + SplinePath *next; + + if (current) { + next = current->GetNext(); + if (next) { + current = next; + } + } + UpdateUI(); +} + +void CameraManager::PreviousPoint(Event *ev) +{ + SplinePath *prev; + + if (current) { + prev = current->GetPrev(); + if (prev) { + current = prev; + } + } + UpdateUI(); +} + +void CameraManager::NextPath(Event *ev) +{ + int index; + + // + // find current path in container of paths + // + index = pathList.IndexOfObject(pathName); + if (index < pathList.NumObjects()) { + index++; + } + + if (index > 0) { + SetPath(pathList.ObjectAt(index)); + UpdateUI(); + } +} + +void CameraManager::PreviousPath(Event *ev) +{ + int index; + + // + // find current path in container of paths + // + index = pathList.IndexOfObject(pathName); + if (index > 1) { + index--; + } + + if (index > 0) { + SetPath(pathList.ObjectAt(index)); + UpdateUI(); + } +} + +void CameraManager::ShowingPath(Event *ev) +{ + int count; + SplinePath *node; + SplinePath *prev; + Vector mins(-8, -8, -8); + Vector maxs(8, 8, 8); + + prev = NULL; + for (node = path; node != NULL; node = node->GetNext()) { + if (prev) { + G_LineStipple(4, (unsigned short)(0xF0F0F0F0 >> (7 - (level.framenum & 7)))); + G_DebugLine(prev->origin, node->origin, 0.4f, 0.4f, 0.4f, 0.1f); + G_LineStipple(1, 0xffff); + } + + if (current == node) { + G_DrawDebugNumber(node->origin + Vector(0, 0, 20), node->speed, 0.5, 0, 1, 0, 1); + if (current->GetFov()) { + G_DrawDebugNumber(node->origin + Vector(0, 0, 30), node->GetFov(), 0.5, 0, 0, 1, 0); } - } - - G_LineWidth( 3 ); - G_DebugLine( node->origin, node->origin + Vector( node->orientation[ 0 ] ) * 16, 1, 0, 0, 1 ); - G_DebugLine( node->origin, node->origin + Vector( node->orientation[ 1 ] ) * 16, 0, 1, 0, 1 ); - G_DebugLine( node->origin, node->origin + Vector( node->orientation[ 2 ] ) * 16, 0, 0, 1, 1 ); - G_LineWidth( 1 ); - - prev = node; - } - - if ( cameraPath_dirty ) - { - cameraPath_dirty = qfalse; - cameraPath.Clear(); - cameraPath.SetType( SPLINE_CLAMP ); - - node = path; - while( node != NULL ) - { - cameraPath.AppendControlPoint( node->origin, node->angles, node->speed ); - node = node->GetNext(); - - if ( node == path ) - { - break; - } - } - } - - // draw the curve itself - G_Color3f( 1, 1, 0 ); - cameraPath.DrawCurve( 10 ); - - // draw all the nodes - for( node = path, count = -1; node != NULL; node = node->GetNext(), count++ ) - { - Vector dir, angles; - - dir = cameraPath.Eval( ( float )count - 0.9f ) - cameraPath.Eval( count - 1 ); - angles = dir.toAngles(); - if ( node->doWatch || node->GetFov() || ( node->thread != "" ) || ( node->triggertarget != "" ) ) - { - G_DebugOrientedCircle( cameraPath.Eval( count - 1 ), 5, 0, 1, 1, 1, angles ); - } - else - { - G_DebugOrientedCircle( cameraPath.Eval( count - 1 ), 2, 0, 0, 1, 0.2f, angles ); - } - // if we are the first node, we need to skip the count so that we properly go to the next node - if ( count == -1 ) - { - count = 0; - } - } - - - PostEvent( EV_CameraManager_ShowingPath, FRAMETIME ); - } - -void CameraManager::ShowPath - ( - void - ) - - { - CancelEventsOfType( EV_CameraManager_ShowingPath ); - PostEvent( EV_CameraManager_ShowingPath, FRAMETIME ); - UpdateUI(); - } - -void CameraManager::ShowPath - ( - Event *ev - ) - - { - if ( ev->NumArgs() ) - { - SetPath( ev->GetString( 1 ) ); - } - ShowPath(); - } - -void CameraManager::HidePath - ( - Event *ev - ) - - { - CancelEventsOfType( EV_CameraManager_ShowingPath ); - UpdateUI(); - } - -void CameraManager::StopPlayback - ( - Event *ev - ) - - { - if ( cam ) - { - cam->Stop(); - SetCamera( NULL, 0 ); - } - } - -void CameraManager::PlayPath - ( - Event *ev - ) - - { - if ( cam ) - { - SetCamera( NULL, 0 ); - } - - if ( ev->NumArgs() ) - { - SetPath( ev->GetString( 1 ) ); - } - - if ( path ) - { - if ( !cam ) - { - cam = new Camera; - cam->SetTargetName( "_loadedcamera" ); - cam->ProcessPendingEvents(); - } - - cam->Reset( path->origin, path->angles ); - cam->FollowPath( path, false, NULL ); - cam->Cut( NULL ); - SetCamera( cam, 0 ); - } - } - -void CameraManager::LoopPath - ( - Event *ev - ) - - { - if ( cam ) - { - SetCamera( NULL, 0 ); - } - - if ( ev->NumArgs() ) - { - SetPath( ev->GetString( 1 ) ); - } - - if ( path ) - { - if ( !cam ) - { - cam = new Camera; - cam->SetTargetName( "_loadedcamera" ); - cam->ProcessPendingEvents(); - } - - cam->Reset( path->origin, path->angles ); - cam->FollowPath( path, true, NULL ); - cam->Cut( NULL ); - SetCamera( cam, 0 ); - } - } - -void CameraManager::Watch - ( - Event *ev - ) - - { - if ( current ) - { - current->SetWatch( ev->GetString( 1 ) ); - } - UpdateUI(); - } - -void CameraManager::NoWatch - ( - Event *ev - ) - - { - if ( current ) - { - current->NoWatch(); - } - UpdateUI(); - } - -void CameraManager::Fov - ( - Event *ev - ) - - { - if ( current ) - { - current->SetFov( ev->GetFloat( 1 ) ); - } - UpdateUI(); - } - -void CameraManager::FadeTime - ( - Event *ev - ) - - { - if ( current ) - { - current->SetFadeTime( ev->GetFloat( 1 ) ); - } - UpdateUI(); - } - - -void CameraManager::Speed - ( - Event *ev - ) - - { - speed = ev->GetFloat( 1 ); - if ( current ) - { - current->speed = speed; - } - cameraPath_dirty = qtrue; - UpdateUI(); - } - -void CameraManager::SavePath - ( - str pathName - ) - { - SplinePath *node; - str buf; - str filename; - int num; - int index; - - num = 0; - for( node = path; node != NULL; node = node->GetNext() ) - { - num++; - } - - if ( num == 0 ) - { - warning( "CameraManager::SavePath", "Can't save. No points in path." ); - return; - } - - filename = "cams/"; - filename += pathName; - filename += ".cam"; - - path->SetTargetName( pathName ); - - gi.Printf( "Saving camera path to '%s'...\n", filename.c_str() ); - - buf = ""; - buf += va( "//\n" ); - buf += va( "// Camera Path \"%s\", %d Nodes.\n", pathName.c_str(), num ); - buf += va( "//\n" ); - - index = 0; - for( node = path; node != NULL; node = node->GetNext() ) - { - // - // start off the spawn command - // - buf += "spawn SplinePath"; - // - // set the targetname - // - if ( !index ) - { - buf += va( " targetname %s", pathName.c_str() ); - } - else - { - buf += va( " targetname camnode_%s_%d", pathName.c_str(), index ); - } - // - // set the target - // - if ( index < ( num - 1 ) ) - { - buf += va( " target camnode_%s_%d", pathName.c_str(), index + 1 ); - } - // - // set the trigger target - // - if ( node->triggertarget != "" ) - { - buf += va( " triggertarget %s", node->triggertarget.c_str() ); - } - // - // set the thread - // - if ( node->thread != "" ) - { - buf += va( " thread %s", node->thread.c_str() ); - } - // - // set the origin - // - buf += va( " origin \"%.2f %.2f %.2f\"", node->origin.x, node->origin.y, node->origin.z ); - // - // set the angles - // - buf += va( " angles \"%.1f %.1f %.1f\"", AngleMod( node->angles.x ), AngleMod( node->angles.y ), AngleMod( node->angles.z ) ); - // - // set the speed - // - buf += va( " speed %.1f", node->speed ); - // - // set the watch - // - if ( node->doWatch && node->watchEnt != "" ) - { - buf += va( " watch %s", node->watchEnt.c_str() ); - } - // - // set the fov - // - if ( node->GetFov() ) - { - buf += va( " fov %.1f", node->GetFov() ); - } - // - // set the fadetime - // - if ( node->GetFadeTime() ) - { - buf += va( " fadetime %.1f", node->GetFadeTime() ); - } - - buf += "\n"; - index++; - } - buf += "end\n"; - - gi.FS_WriteFile( filename.c_str(), ( void *)buf.c_str(), buf.length() + 1 ); - gi.Printf( "done.\n" ); - } - -void CameraManager::Save - ( - Event *ev - ) - - { - str filename; - str name; - - if ( ev->NumArgs() != 1 ) - { - cvar_t * cvar; - - // - // get the path name from the cvar - // - cvar = gi.Cvar_Get( "cam_filename", "", 0 ); - if ( cvar->string[ 0 ] ) - { - name = cvar->string; - } - else - { - ScriptError( "Usage: cam save [filename]" ); - return; - } - } - else - { - name = ev->GetString( 1 ); - } - SavePath( name ); - pathList.AddUniqueObject( name ); - } - -void CameraManager::Load - ( - Event *ev - ) - - { - qboolean show; - str filename; - str name; - - if ( ev->NumArgs() != 1 ) - { - cvar_t * cvar; - - // - // get the path name from the cvar - // - cvar = gi.Cvar_Get( "cam_filename", "", 0 ); - if ( cvar->string[ 0 ] ) - { - show = true; - name = cvar->string; - } - else - { - ScriptError( "Usage: cam load [filename]" ); - return; - } - } - else - { - show = false; - name = ev->GetString( 1 ); - } - - if ( pathList.ObjectInList( name ) && show ) - { - gi.Printf( "Camera path '%s' already loaded...\n", name.c_str() ); - return; - } - - filename = "cams/"; - filename += name; - filename += ".cam"; - - gi.Printf( "Loading camera path from '%s'...", filename.c_str() ); - } - - -void CameraManager::SaveMap - ( - Event *ev - ) - - { - SplinePath *node; - str buf; - str filename; - int num; - int index; - - if ( ev->NumArgs() != 1 ) - { - ScriptError( "Usage: cam savemap [filename]" ); - return; - } - - num = 0; - for( node = path; node != NULL; node = node->GetNext() ) - { - num++; - } - - if ( num == 0 ) - { - ScriptError( "Can't save. No points in path." ); - return; - } - - filename = "cams/"; - filename += ev->GetString( 1 ); - filename += ".map"; - - if ( !path->targetname.length() ) - { - path->SetTargetName( ev->GetString( 1 ) ); - gi.Printf( "Targetname set to '%s'\n", path->targetname.c_str() ); - } - - gi.Printf( "Saving camera path to map '%s'...\n", filename.c_str() ); - - buf = ""; - index = 0; - for( node = path; node != NULL; node = node->GetNext() ) - { - buf += va( "// pathnode %d\n", index ); - buf += "{\n"; - buf += va( "\"classname\" \"info_splinepath\"\n" ); - if ( index < ( num - 1 ) ) - { - buf += va( "\"target\" \"camnode_%s_%d\"\n", ev->GetString( 1 ).c_str(), index + 1 ); - } - if ( !index ) - { - buf += va( "\"targetname\" \"%s\"\n", ev->GetString( 1 ).c_str() ); - } - else - { - buf += va( "\"targetname\" \"camnode_%s_%d\"\n", ev->GetString( 1 ).c_str(), index ); - } - if ( node->triggertarget != "" ) - { - buf += va( "\"triggertarget\" \"%s\"\n", node->triggertarget.c_str() ); - } - if ( node->thread != "" ) - { - buf += va( "\"thread\" \"%s\"\n", node->thread.c_str() ); - } - buf += va( "\"origin\" \"%d %d %d\"\n", ( int )node->origin.x, ( int )node->origin.y, ( int )node->origin.z ); - buf += va( "\"angles\" \"%d %d %d\"\n", ( int )AngleMod( node->angles.x ), ( int )AngleMod( node->angles.y ), ( int )AngleMod( node->angles.z ) ); - buf += va( "\"speed\" \"%.3f\"\n", node->speed ); - buf += "}\n"; - index++; - } - - gi.FS_WriteFile( filename.c_str(), ( void * )buf.c_str(), buf.length() + 1 ); - gi.Printf( "done.\n" ); - } - + G_DebugBBox(node->origin, mins, maxs, 1, 1, 0, 1); + } else { + G_DebugBBox(node->origin, mins, maxs, 1, 0, 0, 1); + } + + // + // draw watch + // + if (node->doWatch) { + Entity *watchEnt; + Vector ang; + Vector delta; + Vector left; + Vector up; + Vector endpoint; + + watchEnt = GetWatchEntity(node->GetWatch()); + if (watchEnt) { + delta.x = watchEnt->origin.x; + delta.y = watchEnt->origin.y; + delta.z = watchEnt->absmax.z; + delta -= node->origin; + delta.normalize(); + ang = delta.toAngles(); + ang.AngleVectors(NULL, &left, &up); + + G_LineWidth(1); + endpoint = node->origin + delta * 48; + G_DebugLine(node->origin, endpoint, 0.5, 1, 1, 1); + G_DebugLine(endpoint, endpoint + (left * 8) - (delta * 8), 0.5, 1, 1, 1); + G_DebugLine(endpoint, endpoint - (left * 8) - (delta * 8), 0.5, 1, 1, 1); + G_DebugLine(endpoint, endpoint - (up * 8) - (delta * 8), 0.5, 1, 1, 1); + G_DebugLine(endpoint, endpoint + (up * 8) - (delta * 8), 0.5, 1, 1, 1); + } + } + + G_LineWidth(3); + G_DebugLine(node->origin, node->origin + Vector(node->orientation[0]) * 16, 1, 0, 0, 1); + G_DebugLine(node->origin, node->origin + Vector(node->orientation[1]) * 16, 0, 1, 0, 1); + G_DebugLine(node->origin, node->origin + Vector(node->orientation[2]) * 16, 0, 0, 1, 1); + G_LineWidth(1); + + prev = node; + } + + if (cameraPath_dirty) { + cameraPath_dirty = qfalse; + cameraPath.Clear(); + cameraPath.SetType(SPLINE_CLAMP); + + node = path; + while (node != NULL) { + cameraPath.AppendControlPoint(node->origin, node->angles, node->speed); + node = node->GetNext(); + + if (node == path) { + break; + } + } + } + + // draw the curve itself + G_Color3f(1, 1, 0); + cameraPath.DrawCurve(10); + + // draw all the nodes + for (node = path, count = -1; node != NULL; node = node->GetNext(), count++) { + Vector dir, angles; + + dir = cameraPath.Eval((float)count - 0.9f) - cameraPath.Eval(count - 1); + angles = dir.toAngles(); + if (node->doWatch || node->GetFov() || (node->thread != "") || (node->triggertarget != "")) { + G_DebugOrientedCircle(cameraPath.Eval(count - 1), 5, 0, 1, 1, 1, angles); + } else { + G_DebugOrientedCircle(cameraPath.Eval(count - 1), 2, 0, 0, 1, 0.2f, angles); + } + // if we are the first node, we need to skip the count so that we properly go to the next node + if (count == -1) { + count = 0; + } + } + + PostEvent(EV_CameraManager_ShowingPath, FRAMETIME); +} + +void CameraManager::ShowPath(void) +{ + CancelEventsOfType(EV_CameraManager_ShowingPath); + PostEvent(EV_CameraManager_ShowingPath, FRAMETIME); + UpdateUI(); +} + +void CameraManager::ShowPath(Event *ev) +{ + if (ev->NumArgs()) { + SetPath(ev->GetString(1)); + } + ShowPath(); +} + +void CameraManager::HidePath(Event *ev) +{ + CancelEventsOfType(EV_CameraManager_ShowingPath); + UpdateUI(); +} + +void CameraManager::StopPlayback(Event *ev) +{ + if (cam) { + cam->Stop(); + SetCamera(NULL, 0); + } +} + +void CameraManager::PlayPath(Event *ev) +{ + if (cam) { + SetCamera(NULL, 0); + } + + if (ev->NumArgs()) { + SetPath(ev->GetString(1)); + } + + if (path) { + if (!cam) { + cam = new Camera; + cam->SetTargetName("_loadedcamera"); + cam->ProcessPendingEvents(); + } + + cam->Reset(path->origin, path->angles); + cam->FollowPath(path, false, NULL); + cam->Cut(NULL); + SetCamera(cam, 0); + } +} + +void CameraManager::LoopPath(Event *ev) +{ + if (cam) { + SetCamera(NULL, 0); + } + + if (ev->NumArgs()) { + SetPath(ev->GetString(1)); + } + + if (path) { + if (!cam) { + cam = new Camera; + cam->SetTargetName("_loadedcamera"); + cam->ProcessPendingEvents(); + } + + cam->Reset(path->origin, path->angles); + cam->FollowPath(path, true, NULL); + cam->Cut(NULL); + SetCamera(cam, 0); + } +} + +void CameraManager::Watch(Event *ev) +{ + if (current) { + current->SetWatch(ev->GetString(1)); + } + UpdateUI(); +} + +void CameraManager::NoWatch(Event *ev) +{ + if (current) { + current->NoWatch(); + } + UpdateUI(); +} + +void CameraManager::Fov(Event *ev) +{ + if (current) { + current->SetFov(ev->GetFloat(1)); + } + UpdateUI(); +} + +void CameraManager::FadeTime(Event *ev) +{ + if (current) { + current->SetFadeTime(ev->GetFloat(1)); + } + UpdateUI(); +} + +void CameraManager::Speed(Event *ev) +{ + speed = ev->GetFloat(1); + if (current) { + current->speed = speed; + } + cameraPath_dirty = qtrue; + UpdateUI(); +} + +void CameraManager::SavePath(str pathName) +{ + SplinePath *node; + str buf; + str filename; + int num; + int index; + + num = 0; + for (node = path; node != NULL; node = node->GetNext()) { + num++; + } + + if (num == 0) { + warning("CameraManager::SavePath", "Can't save. No points in path."); + return; + } + + filename = "cams/"; + filename += pathName; + filename += ".cam"; + + path->SetTargetName(pathName); + + gi.Printf("Saving camera path to '%s'...\n", filename.c_str()); + + buf = ""; + buf += va("//\n"); + buf += va("// Camera Path \"%s\", %d Nodes.\n", pathName.c_str(), num); + buf += va("//\n"); + + index = 0; + for (node = path; node != NULL; node = node->GetNext()) { + // + // start off the spawn command + // + buf += "spawn SplinePath"; + // + // set the targetname + // + if (!index) { + buf += va(" targetname %s", pathName.c_str()); + } else { + buf += va(" targetname camnode_%s_%d", pathName.c_str(), index); + } + // + // set the target + // + if (index < (num - 1)) { + buf += va(" target camnode_%s_%d", pathName.c_str(), index + 1); + } + // + // set the trigger target + // + if (node->triggertarget != "") { + buf += va(" triggertarget %s", node->triggertarget.c_str()); + } + // + // set the thread + // + if (node->thread != "") { + buf += va(" thread %s", node->thread.c_str()); + } + // + // set the origin + // + buf += va(" origin \"%.2f %.2f %.2f\"", node->origin.x, node->origin.y, node->origin.z); + // + // set the angles + // + buf += va( + " angles \"%.1f %.1f %.1f\"", AngleMod(node->angles.x), AngleMod(node->angles.y), AngleMod(node->angles.z) + ); + // + // set the speed + // + buf += va(" speed %.1f", node->speed); + // + // set the watch + // + if (node->doWatch && node->watchEnt != "") { + buf += va(" watch %s", node->watchEnt.c_str()); + } + // + // set the fov + // + if (node->GetFov()) { + buf += va(" fov %.1f", node->GetFov()); + } + // + // set the fadetime + // + if (node->GetFadeTime()) { + buf += va(" fadetime %.1f", node->GetFadeTime()); + } + + buf += "\n"; + index++; + } + buf += "end\n"; + + gi.FS_WriteFile(filename.c_str(), (void *)buf.c_str(), buf.length() + 1); + gi.Printf("done.\n"); +} + +void CameraManager::Save(Event *ev) +{ + str filename; + str name; + + if (ev->NumArgs() != 1) { + cvar_t *cvar; + + // + // get the path name from the cvar + // + cvar = gi.Cvar_Get("cam_filename", "", 0); + if (cvar->string[0]) { + name = cvar->string; + } else { + ScriptError("Usage: cam save [filename]"); + return; + } + } else { + name = ev->GetString(1); + } + SavePath(name); + pathList.AddUniqueObject(name); +} + +void CameraManager::Load(Event *ev) +{ + qboolean show; + str filename; + str name; + + if (ev->NumArgs() != 1) { + cvar_t *cvar; + + // + // get the path name from the cvar + // + cvar = gi.Cvar_Get("cam_filename", "", 0); + if (cvar->string[0]) { + show = true; + name = cvar->string; + } else { + ScriptError("Usage: cam load [filename]"); + return; + } + } else { + show = false; + name = ev->GetString(1); + } + + if (pathList.ObjectInList(name) && show) { + gi.Printf("Camera path '%s' already loaded...\n", name.c_str()); + return; + } + + filename = "cams/"; + filename += name; + filename += ".cam"; + + gi.Printf("Loading camera path from '%s'...", filename.c_str()); +} + +void CameraManager::SaveMap(Event *ev) +{ + SplinePath *node; + str buf; + str filename; + int num; + int index; + + if (ev->NumArgs() != 1) { + ScriptError("Usage: cam savemap [filename]"); + return; + } + + num = 0; + for (node = path; node != NULL; node = node->GetNext()) { + num++; + } + + if (num == 0) { + ScriptError("Can't save. No points in path."); + return; + } + + filename = "cams/"; + filename += ev->GetString(1); + filename += ".map"; + + if (!path->targetname.length()) { + path->SetTargetName(ev->GetString(1)); + gi.Printf("Targetname set to '%s'\n", path->targetname.c_str()); + } + + gi.Printf("Saving camera path to map '%s'...\n", filename.c_str()); + + buf = ""; + index = 0; + for (node = path; node != NULL; node = node->GetNext()) { + buf += va("// pathnode %d\n", index); + buf += "{\n"; + buf += va("\"classname\" \"info_splinepath\"\n"); + if (index < (num - 1)) { + buf += va("\"target\" \"camnode_%s_%d\"\n", ev->GetString(1).c_str(), index + 1); + } + if (!index) { + buf += va("\"targetname\" \"%s\"\n", ev->GetString(1).c_str()); + } else { + buf += va("\"targetname\" \"camnode_%s_%d\"\n", ev->GetString(1).c_str(), index); + } + if (node->triggertarget != "") { + buf += va("\"triggertarget\" \"%s\"\n", node->triggertarget.c_str()); + } + if (node->thread != "") { + buf += va("\"thread\" \"%s\"\n", node->thread.c_str()); + } + buf += va("\"origin\" \"%d %d %d\"\n", (int)node->origin.x, (int)node->origin.y, (int)node->origin.z); + buf += + va("\"angles\" \"%d %d %d\"\n", + (int)AngleMod(node->angles.x), + (int)AngleMod(node->angles.y), + (int)AngleMod(node->angles.z)); + buf += va("\"speed\" \"%.3f\"\n", node->speed); + buf += "}\n"; + index++; + } + + gi.FS_WriteFile(filename.c_str(), (void *)buf.c_str(), buf.length() + 1); + gi.Printf("done.\n"); +} diff --git a/code/fgame/camera.h b/code/fgame/camera.h index e26277b4..fafde254 100644 --- a/code/fgame/camera.h +++ b/code/fgame/camera.h @@ -21,10 +21,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // camera.h: Camera. Duh. -// +// -#ifndef __CAMERA_H__ -#define __CAMERA_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -34,13 +33,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CAMERA_SWITCHTIME 0.5f -#define ORBIT ( 1 << 0 ) -#define START_ON ( 1 << 1 ) -#define AUTOMATIC ( 1 << 2 ) -#define NO_TRACE ( 1 << 3 ) -#define NO_WATCH ( 1 << 4 ) -#define LEVEL_EXIT ( 1 << 5 ) - +#define ORBIT (1 << 0) +#define START_ON (1 << 1) +#define AUTOMATIC (1 << 2) +#define NO_TRACE (1 << 3) +#define NO_WATCH (1 << 4) +#define LEVEL_EXIT (1 << 5) extern Event EV_Camera_CameraThink; extern Event EV_Camera_StartMoving; @@ -69,408 +67,386 @@ extern Event EV_Camera_Cut; class Camera; class CameraMoveState : public Class - { - public: - Vector pos; - Vector movedir; // direction of travel - Vector angles; // angles from spline camera +{ +public: + Vector pos; + Vector movedir; // direction of travel + Vector angles; // angles from spline camera - BSpline cameraPath; - SplinePathPtr splinePath; - SplinePathPtr currentNode; - SplinePathPtr loopNode; + BSpline cameraPath; + SplinePathPtr splinePath; + SplinePathPtr currentNode; + SplinePathPtr loopNode; - float cameraTime; - int lastTime; - int newTime; + float cameraTime; + int lastTime; + int newTime; - qboolean followingpath; - EntityPtr followEnt; - EntityPtr orbitEnt; + qboolean followingpath; + EntityPtr followEnt; + EntityPtr orbitEnt; - void operator=( CameraMoveState &newstate ); - void Evaluate( Camera * camera ); - void Initialize( Camera * camera ); - void DoNodeEvents( Camera * camera ); - void Archive( Archiver &arc ) override; - }; + void operator=(CameraMoveState& newstate); + void Evaluate(Camera *camera); + void Initialize(Camera *camera); + void DoNodeEvents(Camera *camera); + void Archive(Archiver& arc) override; +}; -inline void CameraMoveState::operator= - ( - CameraMoveState &newstate - ) +inline void CameraMoveState::operator=(CameraMoveState& newstate) - { - movedir = newstate.movedir; - pos = newstate.pos; - angles = newstate.angles; +{ + movedir = newstate.movedir; + pos = newstate.pos; + angles = newstate.angles; - cameraPath = newstate.cameraPath; - splinePath = newstate.splinePath; - currentNode = newstate.currentNode; - loopNode = newstate.loopNode; + cameraPath = newstate.cameraPath; + splinePath = newstate.splinePath; + currentNode = newstate.currentNode; + loopNode = newstate.loopNode; - cameraTime = newstate.cameraTime; - lastTime = newstate.lastTime; - newTime = newstate.newTime; + cameraTime = newstate.cameraTime; + lastTime = newstate.lastTime; + newTime = newstate.newTime; - followEnt = newstate.followEnt; - orbitEnt = newstate.orbitEnt; + followEnt = newstate.followEnt; + orbitEnt = newstate.orbitEnt; - followingpath = newstate.followingpath; - } + followingpath = newstate.followingpath; +} -inline void CameraMoveState::Archive - ( - Archiver &arc - ) - { - arc.ArchiveVector( &movedir ); - arc.ArchiveVector( &pos ); - arc.ArchiveVector( &angles ); +inline void CameraMoveState::Archive(Archiver& arc) +{ + arc.ArchiveVector(&movedir); + arc.ArchiveVector(&pos); + arc.ArchiveVector(&angles); - cameraPath.Archive( arc ); + cameraPath.Archive(arc); - arc.ArchiveSafePointer( &splinePath ); - arc.ArchiveSafePointer( ¤tNode ); - arc.ArchiveSafePointer( &loopNode ); + arc.ArchiveSafePointer(&splinePath); + arc.ArchiveSafePointer(¤tNode); + arc.ArchiveSafePointer(&loopNode); - arc.ArchiveFloat( &cameraTime ); - arc.ArchiveInteger( &lastTime ); - arc.ArchiveInteger( &newTime ); + arc.ArchiveFloat(&cameraTime); + arc.ArchiveInteger(&lastTime); + arc.ArchiveInteger(&newTime); - arc.ArchiveSafePointer( &followEnt ); - arc.ArchiveSafePointer( &orbitEnt ); + arc.ArchiveSafePointer(&followEnt); + arc.ArchiveSafePointer(&orbitEnt); - arc.ArchiveBoolean( &followingpath ); - } + arc.ArchiveBoolean(&followingpath); +} -class CameraWatchState : public Class - { - public: - Vector watchAngles; +class CameraWatchState : public Class +{ +public: + Vector watchAngles; - EntityPtr watchEnt; - qboolean watchNodes; - qboolean watchPath; + EntityPtr watchEnt; + qboolean watchNodes; + qboolean watchPath; - void Evaluate( Camera * camera, CameraMoveState * move ); - void Initialize( Camera * camera ); - void Archive( Archiver &arc ) override; - }; + void Evaluate(Camera *camera, CameraMoveState *move); + void Initialize(Camera *camera); + void Archive(Archiver& arc) override; +}; -inline void CameraWatchState::Archive - ( - Archiver &arc - ) - { - arc.ArchiveVector( &watchAngles ); - arc.ArchiveSafePointer( &watchEnt ); - arc.ArchiveBoolean( &watchNodes ); - arc.ArchiveBoolean( &watchPath ); - } +inline void CameraWatchState::Archive(Archiver& arc) +{ + arc.ArchiveVector(&watchAngles); + arc.ArchiveSafePointer(&watchEnt); + arc.ArchiveBoolean(&watchNodes); + arc.ArchiveBoolean(&watchPath); +} -class CameraState : public Class - { - public: - CameraMoveState move; - CameraWatchState watch; - float fov; +class CameraState : public Class +{ +public: + CameraMoveState move; + CameraWatchState watch; + float fov; - void Evaluate( Camera * camera ); - void Initialize( Camera * camera ); - void Archive( Archiver &arc ) override; - }; + void Evaluate(Camera *camera); + void Initialize(Camera *camera); + void Archive(Archiver& arc) override; +}; -inline void CameraState::Archive - ( - Archiver &arc - ) - { - move.Archive( arc ); - watch.Archive( arc ); - arc.ArchiveFloat( &fov ); - } +inline void CameraState::Archive(Archiver& arc) +{ + move.Archive(arc); + watch.Archive(arc); + arc.ArchiveFloat(&fov); +} class Camera : public Entity - { - private: - friend class CameraState; - friend class CameraWatchState; - friend class CameraMoveState; - // - // follow parameters - // - float follow_yaw; - qboolean follow_yaw_fixed; - float follow_dist; - int follow_mask; - - // camera speed - float camera_speed; - // current camera fov - float camera_fov; - // orbit height - float orbit_height; - // orbit_dotrace - qboolean orbit_dotrace; - // whether or not auto calculate fov, a non-zero value means yes - float auto_fov; - - // automatic variables - float automatic_startTime; - float automatic_stopTime; - float automatic_radius; - float automatic_maxFOV; - qboolean automatic_active; - Container automatic_states; - - // Miscellaneous - Vector m_vPosOffset; - - protected: - CameraState currentstate; - CameraState newstate; - - float watchTime; // if non-zero, camera view is transitioning - float followTime; // if non-zero, camera position is tranisitioning - float fovTime; // if non-zero, fov is being lerped - - float fadeTime; // time to transition over - float fovFadeTime; // time for fov transition - float followFadeTime; // time for fov transition - float watchFadeTime; // time for fov transition - - bool m_bShowquakes; - - str nextCamera; - - qboolean showcamera; - - void SetupCamera( Event *ev ); - void CameraThink( Event *ev ); - void CreateOrbit( Vector pos, float radius, Vector &forward, Vector &left ); - void CreatePath( SplinePath *path, splinetype_t type ); - void UpdateStates( void ); - Vector CalculatePosition( void ); - Vector CalculateOrientation( void ); - float CalculateFov( void ); - virtual void bind( Entity *master, qboolean use_my_angles = false ); - void unbind( void ) override; - - public: - CLASS_PROTOTYPE( Camera ); - - Camera(); - void Stop( void ); - void FollowPath( SplinePath *path, qboolean loop, Entity *watch ); - void Orbit( Entity *ent, float dist, Entity *watch, float yaw_offset = 0, qboolean dotrace = qtrue ); - void FollowEntity( Entity *ent, float dist, int mask, Entity *watch = NULL ); - void Watch( str watch, float time ); - void Watch( Entity *ent, float time ); - void SetFOV( float fov, float time ); - - void StartMoving( Event *ev ); - void StopMoving( Event *ev ); - void Pause( Event *ev ); - void Continue( Event *ev ); - void SetAnglesEvent( Event *ev ); - void SetSpeed( Event *ev ); - void SetFollowDistance( Event *ev ); - void SetOrbitHeight( float height ); - void SetOrbitHeight( Event *ev ); - void SetFollowYaw( Event *ev ); - void AbsoluteYaw( Event *ev ); - void RelativeYaw( Event *ev ); - void SetFOV( Event *ev ); - void OrbitEvent( Event *ev ); - void FollowEvent( Event *ev ); - void WatchEvent( Event *ev ); - void WatchStringEvent( Event *ev ); - void WatchPathEvent( Event *ev ); - void WatchNodesEvent( Event *ev ); - void NoWatchEvent(Event* ev); - void EventShowQuakes(Event* ev); - void LookAt( Event *ev ); - void MoveToEntity( Event *ev ); - void MoveToPos( Event *ev ); - void Cut( Event *ev ); - void FadeTime( Event *ev ); - void TurnTo( Event *ev ); - void SetNextCamera( Event *ev ); - float CalculateScore( Entity * player, str state ); - float AutomaticStart( Entity * player ); - float AutomaticStop( Entity * player ); - qboolean IsAutomatic( void ); - qboolean IsLevelExit( void ); - void SetAutoStateEvent( Event * ev ); - void SetAutoRadiusEvent( Event * ev ); - void SetAutoStartTimeEvent( Event * ev ); - void SetAutoStopTimeEvent( Event * ev ); - void SetMaximumAutoFOVEvent( Event * ev ); - void SetAutoActiveEvent( Event * ev ); - - str& NextCamera( void ); - float Fov( void ); - - void Reset( Vector org, Vector ang ); - - Vector GetPositionOffset( void ); - void SetPositionOffset( Vector vNewOfs ); - - void Archive( Archiver &arc ) override; - }; - -inline Vector Camera::GetPositionOffset - ( - void - ) { - return m_vPosOffset; +private: + friend class CameraState; + friend class CameraWatchState; + friend class CameraMoveState; + // + // follow parameters + // + float follow_yaw; + qboolean follow_yaw_fixed; + float follow_dist; + int follow_mask; + + // camera speed + float camera_speed; + // current camera fov + float camera_fov; + // orbit height + float orbit_height; + // orbit_dotrace + qboolean orbit_dotrace; + // whether or not auto calculate fov, a non-zero value means yes + float auto_fov; + + // automatic variables + float automatic_startTime; + float automatic_stopTime; + float automatic_radius; + float automatic_maxFOV; + qboolean automatic_active; + Container automatic_states; + + // Miscellaneous + Vector m_vPosOffset; + +protected: + CameraState currentstate; + CameraState newstate; + + float watchTime; // if non-zero, camera view is transitioning + float followTime; // if non-zero, camera position is tranisitioning + float fovTime; // if non-zero, fov is being lerped + + float fadeTime; // time to transition over + float fovFadeTime; // time for fov transition + float followFadeTime; // time for fov transition + float watchFadeTime; // time for fov transition + + bool m_bShowquakes; + + str nextCamera; + + qboolean showcamera; + + void SetupCamera(Event *ev); + void CameraThink(Event *ev); + void CreateOrbit(Vector pos, float radius, Vector &forward, Vector &left); + void CreatePath(SplinePath *path, splinetype_t type); + void UpdateStates(void); + Vector CalculatePosition(void); + Vector CalculateOrientation(void); + float CalculateFov(void); + virtual void bind(Entity *master, qboolean use_my_angles = false) override; + void unbind(void) override; + +public: + CLASS_PROTOTYPE(Camera); + + Camera(); + void Stop(void); + void FollowPath(SplinePath *path, qboolean loop, Entity *watch); + void Orbit(Entity *ent, float dist, Entity *watch, float yaw_offset = 0, qboolean dotrace = qtrue); + void FollowEntity(Entity *ent, float dist, int mask, Entity *watch = NULL); + void Watch(str watch, float time); + void Watch(Entity *ent, float time); + void SetFOV(float fov, float time); + + void StartMoving(Event *ev); + void StopMoving(Event *ev); + void Pause(Event *ev); + void Continue(Event *ev); + void SetAnglesEvent(Event *ev); + void SetSpeed(Event *ev); + void SetFollowDistance(Event *ev); + void SetOrbitHeight(float height); + void SetOrbitHeight(Event *ev); + void SetFollowYaw(Event *ev); + void AbsoluteYaw(Event *ev); + void RelativeYaw(Event *ev); + void SetFOV(Event *ev); + void OrbitEvent(Event *ev); + void FollowEvent(Event *ev); + void WatchEvent(Event *ev); + void WatchStringEvent(Event *ev); + void WatchPathEvent(Event *ev); + void WatchNodesEvent(Event *ev); + void NoWatchEvent(Event *ev); + void EventShowQuakes(Event *ev); + void LookAt(Event *ev); + void MoveToEntity(Event *ev); + void MoveToPos(Event *ev); + void Cut(Event *ev); + void FadeTime(Event *ev); + void TurnTo(Event *ev); + void SetNextCamera(Event *ev); + float CalculateScore(Entity *player, str state); + float AutomaticStart(Entity *player); + float AutomaticStop(Entity *player); + qboolean IsAutomatic(void); + qboolean IsLevelExit(void); + void SetAutoStateEvent(Event *ev); + void SetAutoRadiusEvent(Event *ev); + void SetAutoStartTimeEvent(Event *ev); + void SetAutoStopTimeEvent(Event *ev); + void SetMaximumAutoFOVEvent(Event *ev); + void SetAutoActiveEvent(Event *ev); + + str & NextCamera(void); + float Fov(void); + + void Reset(Vector org, Vector ang); + + bool ShowQuakes(void) const; + Vector GetPositionOffset(void); + void SetPositionOffset(Vector vNewOfs); + + void Archive(Archiver& arc) override; +}; + +inline bool Camera::ShowQuakes(void) const +{ + return m_bShowquakes; } -inline void Camera::SetPositionOffset - ( - Vector vNewOfs - ) +inline Vector Camera::GetPositionOffset(void) { - m_vPosOffset = vNewOfs; + return m_vPosOffset; } -inline void Camera::Archive - ( - Archiver &arc - ) - { - Entity::Archive( arc ); +inline void Camera::SetPositionOffset(Vector vNewOfs) +{ + m_vPosOffset = vNewOfs; +} - arc.ArchiveFloat( &follow_yaw ); - arc.ArchiveBoolean( &follow_yaw_fixed ); - arc.ArchiveFloat( &follow_dist ); - arc.ArchiveInteger( &follow_mask ); +inline void Camera::Archive(Archiver& arc) +{ + Entity::Archive(arc); - arc.ArchiveFloat( &camera_speed ); - arc.ArchiveFloat( &camera_fov ); - arc.ArchiveFloat( &orbit_height ); - arc.ArchiveBoolean( &orbit_dotrace ); - arc.ArchiveFloat( &auto_fov ); + arc.ArchiveFloat(&follow_yaw); + arc.ArchiveBoolean(&follow_yaw_fixed); + arc.ArchiveFloat(&follow_dist); + arc.ArchiveInteger(&follow_mask); - arc.ArchiveFloat( &automatic_startTime ); - arc.ArchiveFloat( &automatic_stopTime ); - arc.ArchiveFloat( &automatic_radius ); - arc.ArchiveFloat( &automatic_maxFOV ); - arc.ArchiveBoolean( &automatic_active ); + arc.ArchiveFloat(&camera_speed); + arc.ArchiveFloat(&camera_fov); + arc.ArchiveFloat(&orbit_height); + arc.ArchiveBoolean(&orbit_dotrace); + arc.ArchiveFloat(&auto_fov); - automatic_states.Archive( arc ); + arc.ArchiveFloat(&automatic_startTime); + arc.ArchiveFloat(&automatic_stopTime); + arc.ArchiveFloat(&automatic_radius); + arc.ArchiveFloat(&automatic_maxFOV); + arc.ArchiveBoolean(&automatic_active); - // currentstate - currentstate.Archive( arc ); - // newstate - newstate.Archive( arc ); + automatic_states.Archive(arc); - arc.ArchiveFloat( &watchTime ); - arc.ArchiveFloat( &followTime ); - arc.ArchiveFloat( &fovTime ); - arc.ArchiveFloat( &fadeTime ); - arc.ArchiveFloat( &fovFadeTime ); - arc.ArchiveFloat( &followFadeTime ); - arc.ArchiveFloat( &watchFadeTime ); + // currentstate + currentstate.Archive(arc); + // newstate + newstate.Archive(arc); - arc.ArchiveString( &nextCamera ); + arc.ArchiveFloat(&watchTime); + arc.ArchiveFloat(&followTime); + arc.ArchiveFloat(&fovTime); + arc.ArchiveFloat(&fadeTime); + arc.ArchiveFloat(&fovFadeTime); + arc.ArchiveFloat(&followFadeTime); + arc.ArchiveFloat(&watchFadeTime); - arc.ArchiveBoolean( &showcamera ); + arc.ArchiveString(&nextCamera); - if ( arc.Loading() ) - { - if ( spawnflags & AUTOMATIC ) - { - level.AddAutomaticCamera( this ); - } - } - } + arc.ArchiveBoolean(&showcamera); -void SetCamera( Entity *ent, float switchTime ); -Entity * GetWatchEntity( str watch ); + if (arc.Loading()) { + if (spawnflags & AUTOMATIC) { + level.AddAutomaticCamera(this); + } + } +} + +void SetCamera(Entity *ent, float switchTime); +Entity *GetWatchEntity(str watch); typedef SafePtr CameraPtr; class CameraManager : public Listener - { - protected: - Container pathList; - BSpline cameraPath; - SplinePathPtr path; - SplinePathPtr current; - float speed; - int watch; - str pathName; - CameraPtr cam; - qboolean cameraPath_dirty; +{ +protected: + Container pathList; + BSpline cameraPath; + SplinePathPtr path; + SplinePathPtr current; + float speed; + int watch; + str pathName; + CameraPtr cam; + qboolean cameraPath_dirty; - void NewPath( Event *ev ); - void SetPath( Event *ev ); - void SetTargetName( Event *ev ); - void SetTarget( Event *ev ); - void AddPoint( Event *ev ); - void ReplacePoint( Event *ev ); - void DeletePoint( Event *ev ); - void MovePlayer( Event *ev ); - void NextPoint( Event *ev ); - void PreviousPoint( Event *ev ); - void ShowingPath( Event *ev ); - void ShowPath( Event *ev ); - void HidePath( Event *ev ); - void StopPlayback( Event *ev ); - void PlayPath( Event *ev ); - void LoopPath( Event *ev ); - void Watch( Event *ev ); - void NoWatch( Event *ev ); - void Fov( Event *ev ); - void FadeTime( Event *ev ); - void Speed( Event *ev ); - void Save( Event *ev ); - void Load( Event *ev ); - void SaveMap( Event *ev ); - void UpdateEvent( Event *ev ); - void NextPath( Event *ev ); - void PreviousPath( Event *ev ); - void RenamePath( Event *ev ); + void NewPath(Event *ev); + void SetPath(Event *ev); + void SetTargetName(Event *ev); + void SetTarget(Event *ev); + void AddPoint(Event *ev); + void ReplacePoint(Event *ev); + void DeletePoint(Event *ev); + void MovePlayer(Event *ev); + void NextPoint(Event *ev); + void PreviousPoint(Event *ev); + void ShowingPath(Event *ev); + void ShowPath(Event *ev); + void HidePath(Event *ev); + void StopPlayback(Event *ev); + void PlayPath(Event *ev); + void LoopPath(Event *ev); + void Watch(Event *ev); + void NoWatch(Event *ev); + void Fov(Event *ev); + void FadeTime(Event *ev); + void Speed(Event *ev); + void Save(Event *ev); + void Load(Event *ev); + void SaveMap(Event *ev); + void UpdateEvent(Event *ev); + void NextPath(Event *ev); + void PreviousPath(Event *ev); + void RenamePath(Event *ev); - void ShowPath( void ); - void UpdateUI( void ); - void SetPathName( str name ); - void SavePath( str pathName ); + void ShowPath(void); + void UpdateUI(void); + void SetPathName(str name); + void SavePath(str pathName); - public: - CLASS_PROTOTYPE( CameraManager ); +public: + CLASS_PROTOTYPE(CameraManager); - CameraManager(); - void SetPath( str pathName ); - void Archive( Archiver &arc ) override; - }; + CameraManager(); + void SetPath(str pathName); + void Archive(Archiver& arc) override; +}; -inline void CameraManager::Archive - ( - Archiver &arc - ) +inline void CameraManager::Archive(Archiver& arc) - { - Listener::Archive( arc ); +{ + Listener::Archive(arc); - pathList.Archive( arc ); + pathList.Archive(arc); - // no need to archive the cameraPath - arc.ArchiveSafePointer( &path ); - arc.ArchiveSafePointer( ¤t ); - arc.ArchiveFloat( &speed ); - arc.ArchiveInteger( &watch ); - arc.ArchiveString( &pathName ); - arc.ArchiveSafePointer( &cam ); + // no need to archive the cameraPath + arc.ArchiveSafePointer(&path); + arc.ArchiveSafePointer(¤t); + arc.ArchiveFloat(&speed); + arc.ArchiveInteger(&watch); + arc.ArchiveString(&pathName); + arc.ArchiveSafePointer(&cam); - // make sure the cameraPath gets rebuilt - cameraPath_dirty = qtrue; - } + // make sure the cameraPath gets rebuilt + cameraPath_dirty = qtrue; +} extern CameraManager CameraMan; - -#endif /* camera.h */ diff --git a/code/fgame/characterstate.cpp b/code/fgame/characterstate.cpp index 50f558d8..e0c672ff 100644 --- a/code/fgame/characterstate.cpp +++ b/code/fgame/characterstate.cpp @@ -77,7 +77,7 @@ Conditional::Conditional() Expression::Expression() {} -Expression::Expression(Expression& exp) +Expression::Expression(const Expression& exp) { int i; @@ -373,7 +373,7 @@ void State::ParseAndProcessCommand(str command, Entity *target) script.SkipToEOL(); break; } - strcpy(args[argc], script.GetToken(false)); + Q_strncpyz(args[argc], script.GetToken(false), sizeof(args[argc])); argv[argc] = args[argc]; argc++; } diff --git a/code/fgame/characterstate.h b/code/fgame/characterstate.h index 884136e2..afc4d604 100644 --- a/code/fgame/characterstate.h +++ b/code/fgame/characterstate.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // characterstate.h: Character state -#ifndef __CHARACTERSTATE_H__ -#define __CHARACTERSTATE_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -185,7 +184,7 @@ private: public: Expression(); - Expression(Expression& exp); + Expression(const Expression& exp); Expression(Script& script, State& state); void operator=(const Expression& exp); @@ -359,5 +358,3 @@ StateMap *GetStatemap( qboolean cache_only = false ); void CacheStatemap(str filename, Condition *conditions); - -#endif /* !__CHARACTERSTATE_H__ */ diff --git a/code/fgame/crateobject.cpp b/code/fgame/crateobject.cpp index e651f996..2b161b2e 100644 --- a/code/fgame/crateobject.cpp +++ b/code/fgame/crateobject.cpp @@ -45,491 +45,405 @@ NOTSTACKED prevents the crate from causing crates above it to fall. Great for cr Event EV_Crate_Think ( - "_crate_think", - EV_DEFAULT, - NULL, - NULL, - "think function for a crate." + "_crate_think", + EV_DEFAULT, + NULL, + NULL, + "think function for a crate." ); Event EV_Crate_Falling ( - "_crate_falling", - EV_DEFAULT, - NULL, - NULL, - "crate's falling." + "_crate_falling", + EV_DEFAULT, + NULL, + NULL, + "crate's falling." ); Event EV_Crate_Setup ( - "_cratesetup", - EV_DEFAULT, - NULL, - NULL, - "Does the post spawn setup of the crate" + "_cratesetup", + EV_DEFAULT, + NULL, + NULL, + "Does the post spawn setup of the crate" ); Event EV_Crate_Start_Falling ( - "_cratestartfalling", - EV_DEFAULT, - NULL, - NULL, - "Makes a crate start falling" + "_cratestartfalling", + EV_DEFAULT, + NULL, + NULL, + "Makes a crate start falling" ); Event EV_Crate_SetDebris ( - "debristype", - EV_DEFAULT, - "i", - "type", - "Sets the debris type of the crate" + "debristype", + EV_DEFAULT, + "i", + "type", + "Sets the debris type of the crate" ); -CLASS_DECLARATION( Entity, CrateObject, "func_crate" ) -{ - { &EV_Crate_Setup, &CrateObject::CrateSetup }, - { &EV_Crate_Falling, &CrateObject::CrateFalling }, - { &EV_Damage, &CrateObject::CrateDamaged }, - { &EV_Killed, &CrateObject::CrateKilled }, - { &EV_Crate_Start_Falling, &CrateObject::StartFalling }, - { &EV_Crate_Think, &CrateObject::CrateThink }, - { &EV_Crate_SetDebris, &CrateObject::CrateDebrisType }, - { NULL, NULL } +CLASS_DECLARATION(Entity, CrateObject, "func_crate") { + {&EV_Crate_Setup, &CrateObject::CrateSetup }, + {&EV_Crate_Falling, &CrateObject::CrateFalling }, + {&EV_Damage, &CrateObject::CrateDamaged }, + {&EV_Killed, &CrateObject::CrateKilled }, + {&EV_Crate_Start_Falling, &CrateObject::StartFalling }, + {&EV_Crate_Think, &CrateObject::CrateThink }, + {&EV_Crate_SetDebris, &CrateObject::CrateDebrisType}, + {NULL, NULL } }; CrateObject::CrateObject() { - entflags |= EF_CRATEOBJECT; + entflags |= ECF_CRATEOBJECT; - AddWaitTill(STRING_DEATH); + AddWaitTill(STRING_DEATH); - if( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - edict->s.eType = ET_GENERAL; + edict->s.eType = ET_GENERAL; - m_fMoveTime = 0.0f; + m_fMoveTime = 0.0f; - health = 100.0f; - max_health = 100.0f; - deadflag = 0; - takedamage = DAMAGE_YES; + health = 100.0f; + max_health = 100.0f; + deadflag = 0; + takedamage = DAMAGE_YES; - mass = 1200; + mass = 1200; - m_iDebrisType = 0; + m_iDebrisType = 0; - PostEvent( EV_Crate_Setup, EV_POSTSPAWN ); + PostEvent(EV_Crate_Setup, EV_POSTSPAWN); } - -void CrateObject::TellNeighborsToFall - ( - void - ) +void CrateObject::TellNeighborsToFall(void) { - Entity *pEnt; - Entity *pNext; - Vector vMins; - Vector vMaxs; + Entity *pEnt; + Entity *pNext; + Vector vMins; + Vector vMaxs; - vMins[ 0 ] = mins[ 0 ] + origin[ 0 ] + 6.0f; - vMins[ 1 ] = mins[ 1 ] + origin[ 1 ] + 6.0f; - vMins[ 2 ] = mins[ 2 ] + origin[ 2 ] + 6.0f; + vMins = origin + mins + Vector(6, 6, 6); + vMaxs = origin + maxs + Vector(-6, -6, 12); - vMaxs[ 0 ] = maxs[ 0 ] + origin[ 0 ] - 6.0f; - vMaxs[ 1 ] = maxs[ 1 ] + origin[ 1 ] - 6.0f; - vMaxs[ 2 ] = maxs[ 2 ] + origin[ 2 ] + 12.0f; + for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) { + pNext = G_NextEntity(pEnt); + if (pEnt == this) { + continue; + } + if (!pEnt->IsSubclassOfCrateObject()) { + continue; + } - for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext ) - { - pNext = G_NextEntity( pEnt ); + if (vMins[0] > pEnt->absmax[0] || vMins[1] > pEnt->absmax[1] || vMins[2] > pEnt->absmax[2] + || pEnt->absmin[0] > vMaxs[0] || pEnt->absmin[1] > vMaxs[1] || pEnt->absmin[2] > vMaxs[2]) { + continue; + } - for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext ) - { - pNext = G_NextEntity( pEnt ); - - if( pEnt != this && pEnt->IsSubclassOfCrateObject() ) - { - if( vMins[ 0 ] <= absmax[ 0 ] && - vMins[ 1 ] <= absmax[ 1 ] && - vMins[ 2 ] <= absmax[ 2 ] && - absmin[ 0 ] <= vMaxs[ 0 ] && - absmin[ 1 ] <= vMaxs[ 1 ] && - absmin[ 2 ] <= vMaxs[ 2 ] ) - { - if( !pEnt->EventPending( EV_Crate_Start_Falling ) ) - { - float time = level.frametime + level.frametime; - pEnt->PostEvent( EV_Crate_Start_Falling, time ); - } - } - } - } - } + if (!pEnt->EventPending(EV_Crate_Start_Falling)) { + pEnt->PostEvent(EV_Crate_Start_Falling, level.frametime * 2); + } + } } -void CrateObject::TellNeighborsToJitter - ( - Vector vJitterAdd - ) +void CrateObject::TellNeighborsToJitter(Vector vJitterAdd) { + Entity *pEnt; + Entity *pNext; + Vector vMins; + Vector vMaxs; - Entity *pEnt; - Entity *pNext; - Vector vMins; - Vector vMaxs; + vMins = origin + mins + Vector(6, 6, 6); + vMaxs = origin + maxs + Vector(-6, -6, 12); - vMins[ 0 ] = mins[ 0 ] + origin[ 0 ] + 6.0f; - vMins[ 1 ] = mins[ 1 ] + origin[ 1 ] + 6.0f; - vMins[ 2 ] = mins[ 2 ] + origin[ 2 ] + 6.0f; + for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) { + CrateObject *crate = (CrateObject *)pEnt; - vMaxs[ 0 ] = maxs[ 0 ] + origin[ 0 ] - 6.0f; - vMaxs[ 1 ] = maxs[ 1 ] + origin[ 1 ] - 6.0f; - vMaxs[ 2 ] = maxs[ 2 ] + origin[ 2 ] + 12.0f; + pNext = G_NextEntity(pEnt); - for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext ) - { - CrateObject *crate = ( CrateObject * )pEnt; + if (pEnt == this) { + continue; + } + if (!pEnt->IsSubclassOfCrateObject()) { + continue; + } - pNext = G_NextEntity( pEnt ); + if (vMins[0] > pEnt->absmax[0] || vMins[1] > pEnt->absmax[1] || vMins[2] > pEnt->absmax[2] + || pEnt->absmin[0] > vMaxs[0] || pEnt->absmin[1] > vMaxs[1] || pEnt->absmin[2] > vMaxs[2]) { + continue; + } - if( pEnt == this ) - { - continue; - } + crate->m_vJitterAngles[0] += vJitterAdd[0]; - if( !pEnt->IsSubclassOfCrateObject() ) - { - continue; - } + if (crate->m_vJitterAngles[0] > m_fJitterScale * 1.25f + || -(m_fJitterScale * 1.25f) <= crate->m_vJitterAngles[0]) { + crate->m_vJitterAngles[0] = m_fJitterScale * 1.25f; + } - if( vMins[ 0 ] > absmax[ 0 ] || - vMins[ 1 ] > absmax[ 1 ] || - vMins[ 2 ] > absmax[ 2 ] || - absmin[ 0 ] > vMaxs[ 0 ] || - absmin[ 1 ] > vMaxs[ 1 ] || - absmin[ 2 ] > vMaxs[ 2 ] ) - { - continue; - } + crate->m_vJitterAngles[2] += vJitterAdd[2]; - crate->m_vJitterAngles[ 0 ] = m_vJitterAngles[ 0 ] + vJitterAdd[ 0 ]; + if (crate->m_vJitterAngles[2] > m_fJitterScale * 1.25f) { + break; + } - if( crate->m_vJitterAngles[ 0 ] > m_fJitterScale * 1.25f || - -( m_fJitterScale * 1.25f ) <= crate->m_vJitterAngles[ 0 ] ) - { - crate->m_vJitterAngles[ 0 ] = m_fJitterScale * 1.25f; - } + if (-(m_fJitterScale * 1.25f) <= crate->m_vJitterAngles[2]) { + m_vJitterAngles[2] = -(m_fJitterScale * 1.25f); + } - crate->m_vJitterAngles[ 2 ] += vJitterAdd[ 2 ]; - - if( crate->m_vJitterAngles[ 2 ] > m_fJitterScale * 1.25f ) { - break; - } - - if( -( m_fJitterScale * 1.25f ) <= crate->m_vJitterAngles[ 2 ] ) - { - m_vJitterAngles[ 2 ] = -( m_fJitterScale * 1.25f ); - } - - if( !crate->EventPending( EV_Crate_Think ) ) - { - crate->ProcessEvent( EV_Crate_Think ); - } - } + if (!crate->EventPending(EV_Crate_Think)) { + crate->ProcessEvent(EV_Crate_Think); + } + } } -void CrateObject::CrateSetup - ( - Event *ev - ) +void CrateObject::CrateSetup(Event *ev) { - Vector vMins; - Vector vMaxs; - Entity *pEnt; - Entity *pNext; + Vector vMins; + Vector vMaxs; + Entity *pEnt; + Entity *pNext; - mass = 20 * ( size[ 0 ] * 0.625f * size[ 1 ] * 0.625f * size[ 2 ] * 0.625f ); + mass = 20 * ((size[0] / 16) * (size[1] / 16) * (size[2] / 16)); - m_vStartAngles = angles; - m_fJitterScale = 64.0f / size[ 2 ]; + m_vStartAngles = angles; + m_fJitterScale = 64.0f / size[2]; - setMoveType( MOVETYPE_PUSH ); - setSolidType( SOLID_BSP ); + setMoveType(MOVETYPE_PUSH); + setSolidType(SOLID_BSP); - vMins[ 0 ] = mins[ 0 ] + origin[ 0 ] + 12.0f; - vMins[ 1 ] = mins[ 1 ] + origin[ 1 ] + 12.0f; - vMins[ 2 ] = mins[ 2 ] + origin[ 2 ] + 18.0f; + vMins = origin + mins + Vector(12, 12, 18); + vMaxs = origin + maxs - Vector(12, 12, 18); - vMaxs[ 0 ] = maxs[ 0 ] + origin[ 0 ] - 12.0f; - vMaxs[ 1 ] = maxs[ 1 ] + origin[ 1 ] - 12.0f; - vMaxs[ 2 ] = maxs[ 2 ] + origin[ 2 ] - 18.0f; + for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) { + pNext = G_NextEntity(pEnt); - for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext ) - { - pNext = G_NextEntity( pEnt ); + if (pEnt->entnum <= entnum) { + continue; + } - if( pEnt->entnum > entnum && pEnt->IsSubclassOfCrateObject() ) - { - if( vMins[ 0 ] <= absmax[ 0 ] && - vMins[ 1 ] <= absmax[ 1 ] && - vMins[ 2 ] <= absmax[ 2 ] && - absmin[ 0 ] <= vMaxs[ 0 ] && - absmin[ 1 ] <= vMaxs[ 1 ] && - absmin[ 2 ] <= vMaxs[ 2 ] ) - { - Com_Printf( "^~^~^ WARNING: func_crate entities %i and %i have overlapping volumes near (%g %g %g) to (%g %g %g)\n", - entnum, pEnt->entnum, vMins[ 0 ], vMins[ 1 ], vMins[ 2 ], vMaxs[ 0 ], vMaxs[ 1 ], vMaxs[ 2 ] ); - } - } - } + if (!pEnt->IsSubclassOfCrateObject()) { + continue; + } + + if (vMins[0] <= pEnt->absmax[0] && vMins[1] <= pEnt->absmax[1] && vMins[2] <= pEnt->absmax[2] + && vMaxs[0] >= pEnt->absmin[0] && vMaxs[1] >= pEnt->absmin[1] && vMaxs[2] >= pEnt->absmin[2]) { + Com_Printf( + "^~^~^ WARNING: func_crate entities %i and %i have overlapping volumes near (%g %g %g) to (%g %g %g)\n", + entnum, + pEnt->entnum, + vMins[0], + vMins[1], + vMins[2], + vMaxs[0], + vMaxs[1], + vMaxs[2] + ); + } + } } -void CrateObject::CrateDebrisType - ( - Event *ev - ) +void CrateObject::CrateDebrisType(Event *ev) { - m_iDebrisType = ev->GetInteger( 1 ); + m_iDebrisType = ev->GetInteger(1); - if( m_iDebrisType >= 0 ) - { - CacheResource( va( "models/fx/crates/debris_%i.tik", m_iDebrisType ) ); - } + if (m_iDebrisType >= 0) { + CacheResource(va("models/fx/crates/debris_%i.tik", m_iDebrisType)); + } } -void CrateObject::StartFalling - ( - Event *ev - ) +void CrateObject::StartFalling(Event *ev) { - setMoveType( MOVETYPE_FLY ); - m_fMoveTime = 0; + m_fMoveTime = 0; - PostEvent( EV_Crate_Think, level.frametime ); + setMoveType(MOVETYPE_TOSS); + setSolidType(SOLID_BBOX); - if( !( spawnflags & CRATE_NOTSTACKEDON ) ) - { - TellNeighborsToFall(); - } + PostEvent(EV_Crate_Think, level.frametime); + + if (!(spawnflags & CRATE_NOTSTACKEDON)) { + TellNeighborsToFall(); + } } -void CrateObject::CrateFalling - ( - Event *ev - ) +void CrateObject::CrateFalling(Event *ev) { - if( velocity != vec_zero || !groundentity || edict->solid != SOLID_BSP ) - { - m_fMoveTime = level.time + 2.0f; - } + if (velocity != vec_zero || !groundentity || edict->solid != SOLID_BSP) { + m_fMoveTime = level.time + 2.0f; + } - if( level.time <= m_fMoveTime ) - { - PostEvent( EV_Crate_Think, level.frametime ); - } - else - { - setMoveType( MOVETYPE_PUSH ); - setSolidType( SOLID_BSP ); - } + if (m_fMoveTime >= level.time) { + PostEvent(EV_Crate_Think, level.frametime); + return; + } + + setMoveType(MOVETYPE_PUSH); + setSolidType(SOLID_BSP); } -void CrateObject::CrateDamaged - ( - Event *ev - ) +void CrateObject::CrateDamaged(Event *ev) { - Vector vDir; - Vector vForward; - Vector vRight; - Vector vJitterAdd; - int iDamage; - int iMeansOfDeath; - Vector vHitPos; - Vector vHitDirection; - Vector vHitNormal; + Vector vDir; + Vector vForward; + Vector vRight; + Vector vJitterAdd; + int iDamage; + int iMeansOfDeath; + Vector vHitPos; + Vector vHitDirection; + Vector vHitNormal; - if( !takedamage ) - { - return; - } + if (!takedamage) { + return; + } - iDamage = ev->GetInteger( 2 ); - iMeansOfDeath = ev->GetInteger( 9 ); - vHitPos = ev->GetVector( 4 ); - vHitDirection = ev->GetVector( 5 ); - vHitNormal = ev->GetVector( 6 ); + iDamage = ev->GetInteger(2); + iMeansOfDeath = ev->GetInteger(9); + vHitPos = ev->GetVector(4); + vHitDirection = ev->GetVector(5); + vHitNormal = ev->GetVector(6); - vDir = ( vHitDirection - vHitNormal ) * 0.5f; - AngleVectors( angles, vForward, vRight, NULL ); + vDir = (vHitDirection - vHitNormal) * 0.5f; + AngleVectors(angles, vForward, vRight, NULL); - vJitterAdd[ 0 ] = DotProduct( vDir, vForward ) * m_fJitterScale * 0.025f * ( float )iDamage; - vJitterAdd[ 2 ] = DotProduct( vDir, vRight ) * m_fJitterScale * 0.025f * ( float )iDamage; + vJitterAdd[0] = DotProduct(vDir, vForward) * m_fJitterScale * 0.025f * (float)iDamage; + vJitterAdd[2] = DotProduct(vDir, vRight) * m_fJitterScale * 0.025f * (float)iDamage; - m_vJitterAngles += Vector( vJitterAdd[ 0 ], 0, vJitterAdd[ 2 ] ); + m_vJitterAngles += Vector(vJitterAdd[0], 0, vJitterAdd[2]); - if( m_vJitterAngles[ 0 ] > m_fJitterScale * 1.25f || - -( m_fJitterScale * 1.25f ) > m_vJitterAngles[ 0 ] ) - { - m_vJitterAngles[ 0 ] = m_fJitterScale * 1.25f; - } + if (m_vJitterAngles[0] > m_fJitterScale * 1.25f || -(m_fJitterScale * 1.25f) > m_vJitterAngles[0]) { + m_vJitterAngles[0] = m_fJitterScale * 1.25f; + } - if( m_vJitterAngles[ 2 ] > m_fJitterScale * 1.25f ) - { - m_vJitterAngles[ 2 ] = m_fJitterScale * 1.25f; - } - else if( m_vJitterAngles[ 2 ] >= -( m_fJitterScale * 1.25f ) ) - { - m_vJitterAngles[ 2 ] = -( m_fJitterScale * 1.25f ); - } + if (m_vJitterAngles[2] > m_fJitterScale * 1.25f) { + m_vJitterAngles[2] = m_fJitterScale * 1.25f; + } else if (m_vJitterAngles[2] >= -(m_fJitterScale * 1.25f)) { + m_vJitterAngles[2] = -(m_fJitterScale * 1.25f); + } - vJitterAdd[ 1 ] = 0.0f; - vJitterAdd *= -0.5f; - - TellNeighborsToJitter( vJitterAdd ); - - if( !EventPending( EV_Crate_Think ) ) - { - ProcessEvent( EV_Crate_Think ); - } - - if( spawnflags & CRATE_INDESTRUCTABLE ) { - return; - } - - if( iMeansOfDeath >= MOD_VEHICLE ) - { - if( iMeansOfDeath == MOD_BASH ) - { - iDamage *= 2; - } - } - else - { - iDamage /= 2; - } - - health -= iDamage; - - if( health <= 0.0f ) - { - Event *event = new Event( EV_Killed ); - event->AddEntity( ev->GetEntity( 1 ) ); - event->AddInteger( iDamage ); - ev->AddEntity( ev->GetEntity( 3 ) ); - - ProcessEvent( event ); - } + vJitterAdd[1] = 0.0f; + vJitterAdd *= -0.5f; + + TellNeighborsToJitter(vJitterAdd); + + if (!EventPending(EV_Crate_Think)) { + ProcessEvent(EV_Crate_Think); + } + + if (spawnflags & CRATE_INDESTRUCTABLE) { + return; + } + + if (iMeansOfDeath >= MOD_VEHICLE) { + if (iMeansOfDeath == MOD_BASH) { + iDamage *= 2; + } + } else { + iDamage /= 2; + } + + health -= iDamage; + + if (health <= 0.0f) { + Event *event = new Event(EV_Killed); + event->AddEntity(ev->GetEntity(1)); + event->AddInteger(iDamage); + ev->AddEntity(ev->GetEntity(3)); + + ProcessEvent(event); + } } -void CrateObject::CrateKilled - ( - Event *ev - ) +void CrateObject::CrateKilled(Event *ev) { - Vector vCenter; - Entity *attacker = ev->GetEntity( 1 ); + Vector vCenter; + Entity *attacker = ev->GetEntity(1); - if( attacker->IsSubclassOfPlayer() ) - { - Player *p = ( Player * )attacker; - p->m_iNumObjectsDestroyed++; - } + if (attacker->IsSubclassOfPlayer()) { + Player *p = (Player *)attacker; + p->m_iNumObjectsDestroyed++; + } - setSolidType( SOLID_NOT ); - hideModel(); + setSolidType(SOLID_NOT); + hideModel(); - takedamage = DAMAGE_NO; + takedamage = DAMAGE_NO; - if( !( spawnflags & CRATE_NOTSTACKEDON ) ) - { - TellNeighborsToFall(); - } + if (!(spawnflags & CRATE_NOTSTACKEDON)) { + TellNeighborsToFall(); + } - vCenter = origin + ( maxs + mins ) * 0.5f; + vCenter = origin + (maxs + mins) * 0.5f; - // Tell clients around that a crate is destroyed - gi.SetBroadcastVisible( origin, origin ); - gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_CRATE_DEBRIS)); - gi.MSG_WriteCoord( vCenter[ 0 ] ); - gi.MSG_WriteCoord( vCenter[ 1 ] ); - gi.MSG_WriteCoord( vCenter[ 2 ] ); - gi.MSG_WriteByte( m_iDebrisType ); - gi.MSG_EndCGM(); + // Tell clients around that a crate is destroyed + gi.SetBroadcastVisible(origin, origin); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_CRATE_DEBRIS)); + gi.MSG_WriteCoord(vCenter[0]); + gi.MSG_WriteCoord(vCenter[1]); + gi.MSG_WriteCoord(vCenter[2]); + gi.MSG_WriteByte(m_iDebrisType); + gi.MSG_EndCGM(); - health = 0; - deadflag = DEAD_DEAD; + health = 0; + deadflag = DEAD_DEAD; - PostEvent( EV_Remove, 0 ); + PostEvent(EV_Remove, 0); - // Notify scripts - Unregister( STRING_DEATH ); + // Notify scripts + Unregister(STRING_DEATH); } -void CrateObject::CrateThink - ( - Event *ev - ) +void CrateObject::CrateThink(Event *ev) { - // Shake the create if it's on fire + // Shake the create if it's on fire - if( m_vJitterAngles[ 0 ] || m_vJitterAngles[ 2 ] ) - { - setAngles( Vector( m_vStartAngles[ 0 ] * 2.0f, m_vStartAngles[ 1 ], m_vStartAngles[ 2 ] * 2.0f ) ); + if (m_vJitterAngles[0] || m_vJitterAngles[2]) { + setAngles(Vector(m_vStartAngles[0] * 2.0f, m_vStartAngles[1], m_vStartAngles[2] * 2.0f)); - if( m_vJitterAngles[ 0 ] > 0.0f ) - { - m_vJitterAngles[ 0 ] -= 1 / 3 * m_fJitterScale; + if (m_vJitterAngles[0] > 0) { + m_vJitterAngles[0] -= 1.0 / 3.0 * m_fJitterScale; - if( m_vJitterAngles[ 0 ] > 0.0f ) - { - m_vJitterAngles[ 0 ] = 0.0f; - } - } - else if( m_vJitterAngles[ 0 ] < 0.0f ) - { - m_vJitterAngles[ 0 ] += 1 / 3 * m_fJitterScale; + if (m_vJitterAngles[0] < 0) { + m_vJitterAngles[0] = 0; + } + } else if (m_vJitterAngles[0] < 0) { + m_vJitterAngles[0] += 1.0 / 3.0 * m_fJitterScale; - if( m_vJitterAngles[ 0 ] < 0.0f ) - { - m_vJitterAngles[ 0 ] = 0.0f; - } - } + if (m_vJitterAngles[0] > 0) { + m_vJitterAngles[0] = 0; + } + } - m_vJitterAngles[ 0 ] = -m_vJitterAngles[ 0 ]; + m_vJitterAngles[0] = -m_vJitterAngles[0]; - if( m_vJitterAngles[ 2 ] > 0.0f ) - { - m_vJitterAngles[ 2 ] -= 1 / 3 * m_fJitterScale; + if (m_vJitterAngles[2] > 0) { + m_vJitterAngles[2] -= 1 / 3 * m_fJitterScale; - if( m_vJitterAngles[ 2 ] > 0.0f ) - { - m_vJitterAngles[ 2 ] = 0.0f; - } - } - else if( m_vJitterAngles[ 2 ] < 0.0f ) - { - m_vJitterAngles[ 2 ] += 1 / 3 * m_fJitterScale; + if (m_vJitterAngles[2] < 0) { + m_vJitterAngles[2] = 0; + } + } else if (m_vJitterAngles[2] < 0) { + m_vJitterAngles[2] += 1.0 / 3.0 * m_fJitterScale; - if( m_vJitterAngles[ 2 ] < 0.0f ) - { - m_vJitterAngles[ 2 ] = 0.0f; - } - } + if (m_vJitterAngles[2] > 0) { + m_vJitterAngles[2] = 0; + } + } - m_vJitterAngles[ 2 ] = -m_vJitterAngles[ 2 ]; + m_vJitterAngles[2] = -m_vJitterAngles[2]; + } else if (!VectorCompare(angles, m_vStartAngles)) { + setAngles(m_vStartAngles); + } - PostEvent( EV_Crate_Think, 0.05f ); - } - else if( !VectorCompare( angles, m_vStartAngles ) ) - { - setAngles( m_vStartAngles ); - } + if (m_vJitterAngles[0] || m_vJitterAngles[2]) { + PostEvent(EV_Crate_Think, 0.05f); + } } diff --git a/code/fgame/crateobject.h b/code/fgame/crateobject.h index 7d33708d..0fe5e737 100644 --- a/code/fgame/crateobject.h +++ b/code/fgame/crateobject.h @@ -22,53 +22,49 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // crateobject.h : Crates -#ifndef __CRATEOBJECT_H__ -#define __CRATEOBJECT_H__ +#pragma once #include "entity.h" -#define CRATE_INDESTRUCTABLE 1 -#define CRATE_NOTSTACKEDON 2 +#define CRATE_INDESTRUCTABLE 1 +#define CRATE_NOTSTACKEDON 2 -class CrateObject : public Entity { - float m_fMoveTime; - int m_iDebrisType; - Vector m_vJitterAngles; - Vector m_vStartAngles; - float m_fJitterScale; +class CrateObject : public Entity +{ + float m_fMoveTime; + int m_iDebrisType; + Vector m_vJitterAngles; + Vector m_vStartAngles; + float m_fJitterScale; private: - void TellNeighborsToFall( void ); - void TellNeighborsToJitter( Vector vJitterAdd ); + void TellNeighborsToFall(void); + void TellNeighborsToJitter(Vector vJitterAdd); public: - CLASS_PROTOTYPE( CrateObject ); + CLASS_PROTOTYPE(CrateObject); - CrateObject(); + CrateObject(); - void CrateSetup( Event *ev ); - void CrateDebrisType( Event *ev ); - void StartFalling( Event *ev ); - void CrateFalling( Event *ev ); - void CrateDamaged( Event *ev ); - void CrateKilled( Event *ev ); - void CrateThink( Event *ev ); - void Archive( Archiver& arc ) override; + void CrateSetup(Event *ev); + void CrateDebrisType(Event *ev); + void StartFalling(Event *ev); + void CrateFalling(Event *ev); + void CrateDamaged(Event *ev); + void CrateKilled(Event *ev); + void CrateThink(Event *ev); + void Archive(Archiver& arc) override; }; -inline void CrateObject::Archive - ( - Archiver& arc - ) +inline void CrateObject::Archive(Archiver& arc) { - Entity::Archive( arc ); + Entity::Archive(arc); - arc.ArchiveFloat( &m_fMoveTime ); - arc.ArchiveInteger( &m_iDebrisType ); + arc.ArchiveFloat(&m_fMoveTime); + arc.ArchiveInteger(&m_iDebrisType); - arc.ArchiveVector( &m_vJitterAngles ); - arc.ArchiveVector( &m_vStartAngles ); - arc.ArchiveFloat( &m_fJitterScale ); + arc.ArchiveVector(&m_vJitterAngles); + arc.ArchiveVector(&m_vStartAngles); + arc.ArchiveFloat(&m_fJitterScale); } -#endif // __CRATEOBJECT_H__ diff --git a/code/fgame/crc32.h b/code/fgame/crc32.h index 703aca60..0b0547e5 100644 --- a/code/fgame/crc32.h +++ b/code/fgame/crc32.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2008 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // crc32.h: CRC32 Encryption (used by the Archiver) -#ifndef __CRC32_H__ -#define __CRC32_H8_ +#pragma once static unsigned int crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, @@ -84,5 +83,3 @@ unsigned int crc32( unsigned int crc, const void *buf, size_t size ) return crc ^ ~0U; } - -#endif // __CRC32_H__ diff --git a/code/fgame/damagemodel.cpp b/code/fgame/damagemodel.cpp index fd66bb37..029ace6c 100644 --- a/code/fgame/damagemodel.cpp +++ b/code/fgame/damagemodel.cpp @@ -22,5 +22,296 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "damagemodel.h" -// FIXME: unimplemented +static const unsigned int DAMAGEMODEL_NOTSOLID = 1; +Event EV_DamageModel_Setup +( + "_setup", + EV_DEFAULT, + NULL, + NULL, + "Sets up an object.", + EV_NORMAL +); +Event EV_DamageModel_KillTrace +( + "killtrace", + EV_DEFAULT, + "vvff", + "offset direction radius distance", + "kills all objects along the trace\n" + "offset - initial offset from origin\n" + "direction - angular offset orientation for trace\n" + "radius - thickness of trace\n" + "distance - how far to trace", + EV_NORMAL +); +Event EV_DamageModel_SpawnOrientedBoundingBox +( + "orientedbbox", + EV_DEFAULT, + "vvf", + "mins maxs yawoffset", + "spawn an oriented bounding box with the given dimensions and an angular offset\n" + "mins - min dimensions of box\n" + "maxs - max dimensions of box\n" + "yawoffset - angular offset orientation of box", + EV_NORMAL +); +Event EV_DamageModel_KillThread +( + "killthread", + EV_DEFAULT, + "s", + "thread", + "Set the thread to execute when this model is killed", + EV_NORMAL +); + +CLASS_DECLARATION(Animate, DamageModel, "DamageModel") { + {&EV_Damage, &DamageModel::Damaged }, + {&EV_Killed, &DamageModel::Killed }, + {&EV_DamageModel_Setup, &DamageModel::Setup }, + {&EV_DamageModel_KillTrace, &DamageModel::KillTrace }, + {&EV_DamageModel_SpawnOrientedBoundingBox, &DamageModel::SpawnOrientedBoundingBox}, + {&EV_DamageModel_KillThread, &DamageModel::EventSetKillThread }, + {NULL, NULL } +}; + +DamageModel::DamageModel() +{ + if (LoadingSavegame) { + return; + } + + setSolidType(SOLID_BBOX); + takedamage = DAMAGE_YES; + boundingBoxEnt = NULL; + + health = 50; + flags |= FL_ROTATEDBOUNDS; + + PostEvent(EV_DamageModel_Setup, EV_POSTSPAWN); +} + +DamageModel::~DamageModel() +{ + if (boundingBoxEnt) { + boundingBoxEnt->PostEvent(EV_Remove, 0); + boundingBoxEnt = NULL; + } +} + +void DamageModel::Setup(Event *ev) +{ + max_health = health; + deadflag = DEAD_NO; + + // set the animation + NewAnim("idle"); + + link(); +} + +void DamageModel::Damaged(Event *ev) +{ + Event *newev; + int damage; + str animname; + + newev = new Event(EV_SetAnim); + newev->AddString("idle"); + + damage = ev->GetInteger(2); + if (damage < health * 0.25) { + animname = "pain_small"; + } else if (damage < health * 0.66) { + animname = "pain_medium"; + } else { + animname = "pain_large"; + } + + switch (ev->GetInteger(9)) { + case MOD_CRUSH: + case MOD_CRUSH_EVERY_FRAME: + case MOD_EXPLOSION: + case MOD_EXPLODEWALL: + case MOD_GRENADE: + case MOD_ROCKET: + case MOD_VEHICLE: + case MOD_AAGUN: + DamageEvent(ev); + if (damage >= health) { + return; + } + break; + default: + break; + } + + if (!HasAnim(animname)) { + animname = "pain"; + } + + NewAnim("pain", newev); +} + +void DamageModel::Killed(Event *ev) +{ + Entity *inflictor; + Vector delta; + float yaw; + int num; + str anim; + + takedamage = DAMAGE_NO; + deadflag = DEAD_DEAD; + setSolidType(SOLID_NOT); + + inflictor = ev->GetEntity(3); + delta = origin - inflictor->origin; + yaw = AngleSubtract(delta.toYaw(), angles.y); + + num = (fmod(yaw + 360, 360) + 22.f) / 45.f; + anim = "death_" + str(num); + // execute the kill thread + label.Execute(this); + + if (!HasAnim(anim)) { + anim = "death"; + } + + if (spawnflags & DAMAGEMODEL_NOTSOLID) { + NewAnim(anim, EV_BecomeNonSolid); + } else { + NewAnim(anim); + } + + if (killtarget.c_str() && strcmp(killtarget, "")) { + Entity *ent = NULL; + + // remove all entities with the kill target name + for (ent = G_FindTarget(NULL, killtarget); ent; ent = G_FindTarget(ent, killtarget)) { + ent->PostEvent(EV_Remove, 0); + } + } +} + +void DamageModel::KillTrace(Event *ev) +{ + Vector offset; + Vector direction; + float radius; + float distance; + Vector transformed; + Vector forward; + Vector localFwd; + Vector mins, maxs; + Vector end; + trace_t trace; + Entity *ent; + int i; + + if (spawnflags & DAMAGEMODEL_NOTSOLID) { + return; + } + + offset = ev->GetVector(1); + direction = ev->GetVector(2); + radius = ev->GetFloat(3); + distance = ev->GetFloat(4); + + MatrixTransformVector(offset, orientation, transformed); + transformed += origin; + + direction.AngleVectorsLeft(&forward, NULL, NULL); + MatrixTransformVector(forward, orientation, localFwd); + + end = transformed + localFwd * distance; + mins = Vector(-radius, -radius, -radius); + maxs = Vector(radius, radius, radius); + ent = this; + + for (i = 0; i < 11; i++) { + float damage; + + if (transformed == end) { + break; + } + + trace = G_Trace(transformed, mins, maxs, end, ent, MASK_SOLID, qfalse, "KillTrace"); + + if (trace.fraction >= 1 || trace.entityNum == ENTITYNUM_WORLD) { + break; + } + + transformed = trace.endpos; + if (!trace.ent) { + continue; + } + + ent = trace.ent->entity; + if (!ent) { + continue; + } + + if (ent->takedamage == DAMAGE_NO) { + continue; + } + + if (ent->isSubclassOf(DamageModel)) { + damage = health * 0.5; + if (damage < 20) { + damage = 20; + } + } else { + damage = health + 1; + } + + ent->Damage(this, this, damage, trace.endpos, localFwd, trace.plane.normal, 0, 0, MOD_CRUSH, HITLOC_GENERAL); + } +} + +void DamageModel::SpawnOrientedBoundingBox(Event *ev) +{ + Vector mins, maxs; + float yawoffset; + + if (spawnflags & DAMAGEMODEL_NOTSOLID) { + return; + } + + mins = ev->GetVector(1) * edict->s.scale; + maxs = ev->GetVector(2) * edict->s.scale; + yawoffset = ev->GetFloat(3); + + boundingBoxEnt = new Entity(); + boundingBoxEnt->edict->r.svFlags |= SVF_SENDPVS; + boundingBoxEnt->edict->s.eFlags |= EF_LINKANGLES; + boundingBoxEnt->edict->r.contents = CONTENTS_SOLID; + boundingBoxEnt->setSolidType(SOLID_BBOX); + + boundingBoxEnt->angles = angles; + boundingBoxEnt->angles.y = fmod(angles.y + yawoffset, 360); + boundingBoxEnt->setAngles(boundingBoxEnt->angles); + boundingBoxEnt->setSize(mins, maxs); + boundingBoxEnt->setOrigin(origin); + boundingBoxEnt->DisconnectPaths(); +} + +void DamageModel::EventSetKillThread(Event *ev) +{ + if (ev->IsFromScript()) { + label.SetThread(ev->GetValue(1)); + } else { + label.Set(ev->GetString(1)); + } +} + +void DamageModel::Archive(Archiver& arc) +{ + Animate::Archive(arc); + + label.Archive(arc); + arc.ArchiveSafePointer(&boundingBoxEnt); +} diff --git a/code/fgame/damagemodel.h b/code/fgame/damagemodel.h index 64b139d4..2190568d 100644 --- a/code/fgame/damagemodel.h +++ b/code/fgame/damagemodel.h @@ -21,3 +21,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once + +#include "animate.h" + +class DamageModel : public Animate +{ +private: + ScriptThreadLabel label; + EntityPtr boundingBoxEnt; + +private: + CLASS_PROTOTYPE(DamageModel); + +public: + DamageModel(); + ~DamageModel(); + + void Setup(Event *ev); + void Damaged(Event *ev); + void Killed(Event *ev) override; + void KillTrace(Event *ev); + void SpawnOrientedBoundingBox(Event *ev); + void EventSetKillThread(Event *ev); + + void Archive(Archiver& arc) override; +}; diff --git a/code/fgame/debuglines.cpp b/code/fgame/debuglines.cpp index 7aa7dfa2..e75c6e09 100644 --- a/code/fgame/debuglines.cpp +++ b/code/fgame/debuglines.cpp @@ -21,371 +21,345 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // debuglines.cpp: -// +// #include "debuglines.h" #include "game.h" #define NUM_CIRCLE_SEGMENTS 24 -debugline_t *DebugLines = NULL; -debugstring_t *DebugStrings = NULL; -Vector currentVertex( 0, 0, 0 ); -Vector vertColor( 1, 1, 1 ); -float vertAlpha = 1; -float vertexIndex = 0; -float linewidth = 1; +debugline_t *DebugLines = NULL; +debugstring_t *DebugStrings = NULL; +Vector currentVertex(0, 0, 0); +Vector vertColor(1, 1, 1); +float vertAlpha = 1; +float vertexIndex = 0; +float linewidth = 1; unsigned short lineStippleFactor = 1; -unsigned short linePattern = 0xffff; -int g_iFirstLine; -int g_iCurrFrameLineCounter; -int g_iFrameLineCount[ 100 ]; +unsigned short linePattern = 0xffff; +int g_iFirstLine; +int g_iCurrFrameLineCounter; +int g_iFrameLineCount[100]; -void G_InitDebugLines - ( - void - ) +void G_InitDebugLines(void) { - if( g_numdebuglinedelays->integer <= 0 ) - { - *gi.DebugLines = DebugLines; - *gi.numDebugLines = 0; - g_iFirstLine = 0; + if (g_numdebuglinedelays->integer <= 0) { + *gi.DebugLines = DebugLines; + *gi.numDebugLines = 0; + g_iFirstLine = 0; - for( int i = 0; i < 100; i++ ) - { - g_iFrameLineCount[ i ] = 0; - } + for (int i = 0; i < 100; i++) { + g_iFrameLineCount[i] = 0; + } - g_iCurrFrameLineCounter = 0; - } - else - { - int iNumDelays = g_numdebuglinedelays->integer; - int iCount; + g_iCurrFrameLineCounter = 0; + } else { + int iNumDelays = g_numdebuglinedelays->integer; + int iCount; - if( iNumDelays > 99 ) - iNumDelays = 99; + if (iNumDelays > 99) { + iNumDelays = 99; + } - iCount = g_iFrameLineCount[ ( g_iCurrFrameLineCounter - iNumDelays + 100 ) % 100 ]; - if( iCount ) - { - g_iFirstLine += iCount; - *gi.numDebugLines -= iCount; - g_iFrameLineCount[ ( g_iCurrFrameLineCounter - iNumDelays + 100 ) % 100 ] = 0; - } + iCount = g_iFrameLineCount[(g_iCurrFrameLineCounter - (iNumDelays - 100)) % 100]; + if (iCount) { + g_iFirstLine += iCount; + *gi.numDebugLines -= iCount; + g_iFrameLineCount[(g_iCurrFrameLineCounter - (iNumDelays - 100)) % 100] = 0; + } - g_iCurrFrameLineCounter = ( g_iCurrFrameLineCounter + 1 ) % 100; - *gi.DebugLines = &DebugLines[ g_iFirstLine ]; - } + g_iCurrFrameLineCounter = (g_iCurrFrameLineCounter + 1) % 100; + *gi.DebugLines = &DebugLines[g_iFirstLine]; + } - currentVertex = vec_zero; - vertColor = Vector( 1, 1, 1 ); - vertAlpha = 1; - vertexIndex = 0; + currentVertex = vec_zero; + vertColor = Vector(1, 1, 1); + vertAlpha = 1; + vertexIndex = 0; - linewidth = 1; - lineStippleFactor = 1; - linePattern = 0xffff; + linewidth = 1; + lineStippleFactor = 1; + linePattern = 0xffff; } -void G_InitDebugStrings - ( - void - ) +void G_InitDebugStrings(void) { - *gi.DebugStrings = DebugStrings; - *gi.numDebugStrings = 0; + *gi.DebugStrings = DebugStrings; + *gi.numDebugStrings = 0; } -void G_AllocDebugLines - ( - void - ) +void G_AllocDebugLines(void) { - // we do a malloc here so that we don't interfere with the game's memory footprint - DebugLines = ( debugline_t * )malloc( ( int )g_numdebuglines->integer * sizeof( debugline_t ) ); + // we do a malloc here so that we don't interfere with the game's memory footprint + DebugLines = (debugline_t *)malloc((int)g_numdebuglines->integer * sizeof(debugline_t)); - G_InitDebugLines(); + G_InitDebugLines(); - for( int i = 0; i < 100; i++ ) - { - g_iFrameLineCount[ i ] = 0; - } + for (int i = 0; i < 100; i++) { + g_iFrameLineCount[i] = 0; + } - g_iCurrFrameLineCounter = 0; + g_iCurrFrameLineCounter = 0; } -void G_AllocDebugStrings - ( - void - ) +void G_AllocDebugStrings(void) { - DebugStrings = ( debugstring_t * )malloc( ( int )g_numdebugstrings->integer * sizeof( debugstring_t ) ); + DebugStrings = (debugstring_t *)malloc((int)g_numdebugstrings->integer * sizeof(debugstring_t)); - G_InitDebugStrings(); + G_InitDebugStrings(); } -void G_DeAllocDebugLines - ( - void - ) +void G_DeAllocDebugLines(void) { - if( DebugLines ) - { - // we do a free here, because we used malloc above - free( DebugLines ); - DebugLines = NULL; - *gi.DebugLines = DebugLines; - *gi.numDebugLines = 0; - } + if (DebugLines) { + // we do a free here, because we used malloc above + free(DebugLines); + DebugLines = NULL; + *gi.DebugLines = DebugLines; + *gi.numDebugLines = 0; + } } -void G_ShiftDebugLines - ( - void - ) +void G_ShiftDebugLines(void) { - int iNewPos; - int iOldPos; + int iNewPos; + int iOldPos; - for( iNewPos = 0; iNewPos < *gi.numDebugLines && iNewPos < g_numdebuglines->integer; iNewPos++ ) - { - iOldPos = g_iFirstLine + iNewPos; + for (iNewPos = 0; iNewPos < *gi.numDebugLines && iNewPos < g_numdebuglines->integer; iNewPos++) { + iOldPos = g_iFirstLine + iNewPos; - DebugLines[ iNewPos ] = DebugLines[ iOldPos ]; - } + DebugLines[iNewPos] = DebugLines[iOldPos]; + } - g_iFirstLine = 0; - *gi.DebugLines = DebugLines; + g_iFirstLine = 0; + *gi.DebugLines = DebugLines; } -void G_DeAllocDebugStrings - ( - void - ) +void G_DeAllocDebugStrings(void) { - if( DebugStrings ) - { - // we do a free here, because we used malloc above - free( DebugStrings ); - DebugStrings = NULL; - *gi.DebugStrings = DebugStrings; - *gi.numDebugStrings = 0; - } + if (DebugStrings) { + // we do a free here, because we used malloc above + free(DebugStrings); + DebugStrings = NULL; + *gi.DebugStrings = DebugStrings; + *gi.numDebugStrings = 0; + } } -void G_DebugLine - ( - Vector start, - Vector end, - float r, - float g, - float b, - float alpha - ) +void G_DebugLine(Vector start, Vector end, float r, float g, float b, float alpha) { - debugline_t *line; - static int printTime = 0; + debugline_t *line; + static int printTime = 0; - if( !g_numdebuglines->integer ) - { - return; - } + if (!g_numdebuglines->integer) { + return; + } - if( *gi.numDebugLines >= g_numdebuglines->integer ) - { - if( level.svsTime >= printTime ) - { - printTime = level.svsTime + 5000; - gi.DPrintf( "G_DebugLine: Exceeded MAX_DEBUG_LINES\n" ); - } + if (*gi.numDebugLines >= g_numdebuglines->integer) { + if (level.svsTime >= printTime) { + printTime = level.svsTime + 5000; + gi.DPrintf("G_DebugLine: Exceeded MAX_DEBUG_LINES\n"); + } - return; - } + return; + } - if( g_numdebuglinedelays->integer > 0 && g_iFirstLine > 0 && g_iFirstLine + *gi.numDebugLines + 1 >= g_numdebuglines->integer ) - { - G_ShiftDebugLines(); - } + if (g_numdebuglinedelays->integer > 0 && g_iFirstLine > 0 + && g_iFirstLine + *gi.numDebugLines + 1 >= g_numdebuglines->integer) { + G_ShiftDebugLines(); + } - line = &DebugLines[ *gi.numDebugLines ]; - ( *gi.numDebugLines )++; - g_iFrameLineCount[ g_iCurrFrameLineCounter ]++; + line = &DebugLines[g_iFirstLine + *gi.numDebugLines]; + (*gi.numDebugLines)++; + g_iFrameLineCount[g_iCurrFrameLineCounter]++; - VectorCopy( start, line->start ); - VectorCopy( end, line->end ); - VectorSet( line->color, r, g, b ); - line->alpha = alpha; + VectorCopy(start, line->start); + VectorCopy(end, line->end); + VectorSet(line->color, r, g, b); + line->alpha = alpha; - line->width = linewidth; - line->factor = lineStippleFactor; - line->pattern = linePattern; + line->width = linewidth; + line->factor = lineStippleFactor; + line->pattern = linePattern; } -void G_LineStipple - ( - int factor, - unsigned short pattern - ) +void G_LineStipple(int factor, unsigned short pattern) +{ + lineStippleFactor = factor; + linePattern = pattern; +} - { - lineStippleFactor = factor; - linePattern = pattern; - } +void G_LineWidth(float width) +{ + linewidth = width; +} -void G_LineWidth - ( - float width - ) - - { - linewidth = width; - } +void G_Color3f(float r, float g, float b) +{ + vertColor = Vector(r, g, b); +} -void G_Color3f - ( - float r, - float g, - float b - ) +void G_Color3v(Vector color) +{ + vertColor = color; +} - { - vertColor = Vector( r, g, b ); - } +void G_Color4f(float r, float g, float b, float alpha) +{ + vertColor = Vector(r, g, b); + vertAlpha = alpha; +} -void G_Color3v - ( - Vector color - ) +void G_Color3vf(Vector color, float alpha) +{ + vertColor = color; + vertAlpha = alpha; +} - { - vertColor = color; - } +void G_BeginLine(void) +{ + currentVertex = vec_zero; + vertexIndex = 0; +} -void G_Color4f - ( - float r, - float g, - float b, - float alpha - ) +void G_Vertex(Vector v) +{ + vertexIndex++; + if (vertexIndex > 1) { + G_DebugLine(currentVertex, v, vertColor[0], vertColor[1], vertColor[2], vertAlpha); + } + currentVertex = v; +} - { - vertColor = Vector( r, g, b ); - vertAlpha = alpha; - } +void G_EndLine(void) +{ + currentVertex = vec_zero; + vertexIndex = 0; +} -void G_Color3vf - ( - Vector color, - float alpha - ) +void G_DebugBBox(Vector org, Vector mins, Vector maxs, float r, float g, float b, float alpha) +{ + int i; + Vector points[8]; - { - vertColor = color; - vertAlpha = alpha; - } - -void G_BeginLine - ( - void - ) - - { - currentVertex = vec_zero; - vertexIndex = 0; - } - -void G_Vertex - ( - Vector v - ) - - { - vertexIndex++; - if ( vertexIndex > 1 ) - { - G_DebugLine( currentVertex, v, vertColor[ 0 ], vertColor[ 1 ], vertColor[ 2 ], vertAlpha ); - } - currentVertex = v; - } - -void G_EndLine - ( - void - ) - - { - currentVertex = vec_zero; - vertexIndex = 0; - } - -void G_DebugBBox - ( - Vector org, - Vector mins, - Vector maxs, - float r, - float g, - float b, - float alpha - ) - { - int i; - Vector points[8]; - - /* + /* ** compute a full bounding box */ - for ( i = 0; i < 8; i++ ) - { - Vector tmp; + for (i = 0; i < 8; i++) { + Vector tmp; - if ( i & 1 ) - tmp[0] = org[0] + mins[0]; - else - tmp[0] = org[0] + maxs[0]; + if (i & 1) { + tmp[0] = org[0] + mins[0]; + } else { + tmp[0] = org[0] + maxs[0]; + } - if ( i & 2 ) - tmp[1] = org[1] + mins[1]; - else - tmp[1] = org[1] + maxs[1]; + if (i & 2) { + tmp[1] = org[1] + mins[1]; + } else { + tmp[1] = org[1] + maxs[1]; + } - if ( i & 4 ) - tmp[2] = org[2] + mins[2]; - else - tmp[2] = org[2] + maxs[2]; + if (i & 4) { + tmp[2] = org[2] + mins[2]; + } else { + tmp[2] = org[2] + maxs[2]; + } - points[i] = tmp; - } + points[i] = tmp; + } - G_Color4f( r, g, b, alpha ); + G_Color4f(r, g, b, alpha); - G_BeginLine(); - G_Vertex( points[0] ); - G_Vertex( points[1] ); - G_Vertex( points[3] ); - G_Vertex( points[2] ); - G_Vertex( points[0] ); - G_EndLine(); + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[1]); + G_Vertex(points[3]); + G_Vertex(points[2]); + G_Vertex(points[0]); + G_EndLine(); - G_BeginLine(); - G_Vertex( points[4] ); - G_Vertex( points[5] ); - G_Vertex( points[7] ); - G_Vertex( points[6] ); - G_Vertex( points[4] ); - G_EndLine(); + G_BeginLine(); + G_Vertex(points[4]); + G_Vertex(points[5]); + G_Vertex(points[7]); + G_Vertex(points[6]); + G_Vertex(points[4]); + G_EndLine(); - for ( i = 0; i < 4; i++ ) - { - G_BeginLine(); - G_Vertex( points[i] ); - G_Vertex( points[4 + i] ); - G_EndLine(); - } - } + G_Color4f(0, 0, 1, alpha); + + for (i = 0; i < 4; i++) { + G_BeginLine(); + G_Vertex(points[i]); + G_Vertex(points[4 + i]); + G_EndLine(); + } +} + +void G_DebugRotatedBBox(Vector org, Vector ang, Vector mins, Vector maxs, float r, float g, float b, float alpha) { + int i; + Vector tmp; + Vector points[8]; + vec3_t axis[3]; + + AnglesToAxis(ang, axis); + + /* + ** compute a full bounding box + */ + for (i = 0; i < 8; i++) { + Vector tmp; + + if (i & 1) { + tmp[0] = mins[0]; + } else { + tmp[0] = maxs[0]; + } + + if (i & 2) { + tmp[1] = mins[1]; + } else { + tmp[1] = maxs[1]; + } + + if (i & 4) { + tmp[2] = mins[2]; + } else { + tmp[2] = maxs[2]; + } + + MatrixTransformVector(tmp, axis, points[i]); + points[i] += org; + } + + G_Color4f(r, g, b, alpha); + + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[1]); + G_Vertex(points[3]); + G_Vertex(points[2]); + G_Vertex(points[0]); + G_EndLine(); + + G_BeginLine(); + G_Vertex(points[4]); + G_Vertex(points[5]); + G_Vertex(points[7]); + G_Vertex(points[6]); + G_Vertex(points[4]); + G_EndLine(); + + G_Color4f(0, 0, 1, alpha); + + for (i = 0; i < 4; i++) { + G_BeginLine(); + G_Vertex(points[i]); + G_Vertex(points[4 + i]); + G_EndLine(); + } +} // // LED style digits @@ -401,500 +375,408 @@ void G_DebugBBox // ****3*** 12** // 11 -static int Numbers[ 12 ][ 8 ] = - { - { 1, 3, 4, 5, 6, 7, 0, 0 }, // 0 - { 4, 5, 0, 0, 0, 0, 0, 0 }, // 1 - { 1, 4, 2, 7, 3, 0, 0, 0 }, // 2 - { 1, 4, 2, 5, 3, 0, 0, 0 }, // 3 - { 6, 4, 2, 5, 0, 0, 0, 0 }, // 4 - { 1, 6, 2, 5, 3, 0, 0, 0 }, // 5 - { 1, 6, 2, 5, 7, 3, 0, 0 }, // 6 - { 1, 8, 0, 0, 0, 0, 0, 0 }, // 7 - { 1, 2, 3, 4, 5, 6, 7, 0 }, // 8 - { 1, 6, 4, 2, 5, 3, 0, 0 }, // 9 - { 9, 10, 11, 12, 0, 0, 0, 0 }, // . - { 2, 0, 0, 0, 0, 0, 0, 0 }, // - - }; +static int Numbers[12][8] = { + {1, 3, 4, 5, 6, 7, 0, 0}, // 0 + {4, 5, 0, 0, 0, 0, 0, 0}, // 1 + {1, 4, 2, 7, 3, 0, 0, 0}, // 2 + {1, 4, 2, 5, 3, 0, 0, 0}, // 3 + {6, 4, 2, 5, 0, 0, 0, 0}, // 4 + {1, 6, 2, 5, 3, 0, 0, 0}, // 5 + {1, 6, 2, 5, 7, 3, 0, 0}, // 6 + {1, 8, 0, 0, 0, 0, 0, 0}, // 7 + {1, 2, 3, 4, 5, 6, 7, 0}, // 8 + {1, 6, 4, 2, 5, 3, 0, 0}, // 9 + {9, 10, 11, 12, 0, 0, 0, 0}, // . + {2, 0, 0, 0, 0, 0, 0, 0}, // - +}; -static float Lines[ 13 ][ 4 ] = - { - { 0, 0, 0, 0 }, // Unused - { -4, 8, 4, 8 }, // 1 - { -4, 4, 4, 4 }, // 2 - { -4, 0, 4, 0 }, // 3 - { 4, 8, 4, 4 }, // 4 - { 4, 4, 4, 0 }, // 5 - { -4, 8, -4, 4 }, // 6 - { -4, 4, -4, 0 }, // 7 - { 4, 8, -4, 0 }, // 8 +static float Lines[13][4] = { + {0, 0, 0, 0}, // Unused + {-4, 8, 4, 8}, // 1 + {-4, 4, 4, 4}, // 2 + {-4, 0, 4, 0}, // 3 + {4, 8, 4, 4}, // 4 + {4, 4, 4, 0}, // 5 + {-4, 8, -4, 4}, // 6 + {-4, 4, -4, 0}, // 7 + {4, 8, -4, 0}, // 8 - { -1, 2, 1, 2 }, // 9 - { 1, 2, 1, 0 }, // 10 - { -1, 0, 1, 0 }, // 11 - { -1, 0, -1, 2 }, // 12 - }; + {-1, 2, 1, 2}, // 9 + {1, 2, 1, 0}, // 10 + {-1, 0, 1, 0}, // 11 + {-1, 0, -1, 2}, // 12 +}; -void G_DrawDebugNumber - ( - Vector org, - float number, - float scale, - float r, - float g, - float b, - int precision - ) +void G_DrawDebugNumber(Vector org, float number, float scale, float r, float g, float b, int precision) { - int i; - int j; - int l; - int num; - Vector up; - Vector left; - Vector pos; - Vector start; - Vector ang; - str text; - Vector delta; - char format[ 20 ]; + int i; + int j; + int l; + int num; + Vector up; + Vector left; + Vector pos; + Vector start; + Vector ang; + str text; + Vector delta; + char format[20]; - // only draw entity numbers within a certain radius - delta = Vector( g_entities[ 0 ].s.origin ) - org; - if( ( delta * delta ) > ( 1000 * 1000 ) ) - { - return; - } + // only draw entity numbers within a certain radius + delta = Vector(g_entities[0].s.origin) - org; + if ((delta * delta) > (1000 * 1000)) { + return; + } - G_Color4f( r, g, b, 1.0 ); + G_Color4f(r, g, b, 1.0); - ang = game.clients[ 0 ].ps.viewangles; - ang.AngleVectorsLeft( NULL, &left, &up ); + ang = game.clients[0].ps.viewangles; + ang.AngleVectorsLeft(NULL, &left, &up); - up *= scale; - left *= scale; + up *= scale; + left *= scale; - if( precision > 0 ) - { - sprintf( format, "%%.%df", precision ); - text = va( format, number ); - } - else - { - text = va( "%d", ( int )number ); - } + if (precision > 0) { + Com_sprintf(format, sizeof(format), "%%.%df", precision); + text = va(format, number); + } else { + text = va("%d", (int)number); + } - start = org + ( text.length() - 1 ) * 5 * left; + start = org + (text.length() - 1) * 5 * left; - for( i = 0; i < text.length(); i++ ) - { - if( text[ i ] == '.' ) - { - num = 10; - } - else if( text[ i ] == '-' ) - { - num = 11; - } - else - { - num = text[ i ] - '0'; - } + for (i = 0; i < text.length(); i++) { + if (text[i] == '.') { + num = 10; + } else if (text[i] == '-') { + num = 11; + } else { + num = text[i] - '0'; + } - for( j = 0; j < 8; j++ ) - { - l = Numbers[ num ][ j ]; - if( l == 0 ) - { - break; - } + for (j = 0; j < 8; j++) { + l = Numbers[num][j]; + if (l == 0) { + break; + } - G_BeginLine(); + G_BeginLine(); - pos = start - Lines[ l ][ 0 ] * left + Lines[ l ][ 1 ] * up; - G_Vertex( pos ); + pos = start - Lines[l][0] * left + Lines[l][1] * up; + G_Vertex(pos); - pos = start - Lines[ l ][ 2 ] * left + Lines[ l ][ 3 ] * up; - G_Vertex( pos ); + pos = start - Lines[l][2] * left + Lines[l][3] * up; + G_Vertex(pos); - G_EndLine(); - } + G_EndLine(); + } - start -= 10 * left; - } + start -= 10 * left; + } } -void G_DebugCircle - ( - float *org, - float radius, - float r, - float g, - float b, - float alpha, - qboolean horizontal - ) - { - int i; - float ang; - Vector angles; - Vector forward; - Vector left; - Vector pos; - Vector delta; - - // only draw circles within a certain radius - delta = Vector( g_entities[ 0 ].s.origin ) - org; - if ( ( delta * delta ) > ( ( 1000 + radius ) * ( 1000 + radius ) ) ) - { - return; - } - - G_Color4f( r, g, b, alpha ); - - if ( horizontal ) - { - forward = "1 0 0"; - left = "0 -1 0"; - } - else - { - angles = game.clients[ 0 ].ps.viewangles; - angles.AngleVectors( NULL, &left, &forward ); - } - - G_BeginLine(); - for( i = 0; i <= NUM_CIRCLE_SEGMENTS; i++ ) - { - ang = DEG2RAD( i * 360 / NUM_CIRCLE_SEGMENTS ); - pos = org + ( sin( ang ) * radius * forward ) - ( cos( ang ) * radius * left ); - G_Vertex( pos ); - } - G_EndLine(); - } - -void G_DebugOrientedCircle - ( - Vector org, - float radius, - float r, - float g, - float b, - float alpha, - Vector angles - ) - { - int i; - float ang; - Vector forward; - Vector left; - Vector pos; - Vector delta; - - // only draw circles within a certain radius - delta = Vector( g_entities[ 0 ].s.origin ) - org; - if ( ( delta * delta ) > ( ( 1000 + radius ) * ( 1000 + radius ) ) ) - { - return; - } - - G_Color4f( r, g, b, alpha ); - - angles.AngleVectors( NULL, &left, &forward ); - - G_BeginLine(); - for( i = 0; i <= NUM_CIRCLE_SEGMENTS; i++ ) - { - ang = DEG2RAD( i * 360 / NUM_CIRCLE_SEGMENTS ); - pos = org + ( sin( ang ) * radius * forward ) - ( cos( ang ) * radius * left ); - G_Vertex( pos ); - } - G_EndLine(); - - // - // Draw the cross sign - // - G_BeginLine(); - ang = DEG2RAD( 45 * 360 / NUM_CIRCLE_SEGMENTS ); - pos = org + ( sin( ang ) * radius * forward ) - ( cos( ang ) * radius * left ); - G_Vertex( pos ); - ang = DEG2RAD( 225 * 360 / NUM_CIRCLE_SEGMENTS ); - pos = org + ( sin( ang ) * radius * forward ) - ( cos( ang ) * radius * left ); - G_Vertex( pos ); - - G_BeginLine(); - ang = DEG2RAD( 315 * 360 / NUM_CIRCLE_SEGMENTS ); - pos = org + ( sin( ang ) * radius * forward ) - ( cos( ang ) * radius * left ); - G_Vertex( pos ); - ang = DEG2RAD( 135 * 360 / NUM_CIRCLE_SEGMENTS ); - pos = org + ( sin( ang ) * radius * forward ) - ( cos( ang ) * radius * left ); - G_Vertex( pos ); - } - -void G_DebugPyramid - ( - Vector org, - float radius, - float r, - float g, - float b, - float alpha - ) - { - Vector delta; - Vector points[ 4 ]; - - // only draw pyramids within a certain radius - delta = Vector( g_entities[ 0 ].s.origin ) - org; - if ( ( delta * delta ) > ( ( 1000 + radius ) * ( 1000 + radius ) ) ) - { - return; - } - - G_Color4f( r, g, b, alpha ); - - points[ 0 ] = org; - points[ 0 ].z += radius; - - points[ 1 ] = org; - points[ 1 ].z -= radius; - points[ 2 ] = points[ 1 ]; - points[ 3 ] = points[ 1 ]; - - points[ 1 ].x += cos( DEG2RAD( 0 ) ) * radius; - points[ 1 ].y += sin( DEG2RAD( 0 ) ) * radius; - points[ 2 ].x += cos( DEG2RAD( 120 ) ) * radius; - points[ 2 ].y += sin( DEG2RAD( 120 ) ) * radius; - points[ 3 ].x += cos( DEG2RAD( 240 ) ) * radius; - points[ 3 ].y += sin( DEG2RAD( 240 ) ) * radius; - - G_BeginLine(); - G_Vertex( points[ 0 ] ); - G_Vertex( points[ 1 ] ); - G_Vertex( points[ 2 ] ); - G_Vertex( points[ 0 ] ); - G_EndLine(); - - G_BeginLine(); - G_Vertex( points[ 0 ] ); - G_Vertex( points[ 2 ] ); - G_Vertex( points[ 3 ] ); - G_Vertex( points[ 0 ] ); - G_EndLine(); - - G_BeginLine(); - G_Vertex( points[ 0 ] ); - G_Vertex( points[ 3 ] ); - G_Vertex( points[ 1 ] ); - G_Vertex( points[ 0 ] ); - G_EndLine(); - - G_BeginLine(); - G_Vertex( points[ 1 ] ); - G_Vertex( points[ 2 ] ); - G_Vertex( points[ 3 ] ); - G_Vertex( points[ 1 ] ); - G_EndLine(); - } - -void G_DrawCoordSystem - ( - Vector pos, - Vector forward, - Vector right, - Vector up, - int length - ) - - { - if ( g_showaxis->integer ) - { - G_DebugLine( pos, pos + forward * length, 1,0,0,1 ); - G_DebugLine( pos, pos + right * length, 0,1,0,1 ); - G_DebugLine( pos, pos + up * length, 0,0,1,1 ); - } - } - -void G_DrawCSystem - ( - Vector pos, - Vector forward, - Vector right, - Vector up, - int length - ) +void G_DebugCircle(float *org, float radius, float r, float g, float b, float alpha, qboolean horizontal) { - G_DebugLine( pos, pos + forward * length, 1.0, 0, 0, 1 ); - G_DebugLine( pos, pos + right * length, 0, 1.0, 0, 1 ); - G_DebugLine( pos, pos + up * length, 0, 0, 1.0, 1 ); + int i; + float ang; + Vector angles; + Vector forward; + Vector left; + Vector pos; + Vector delta; + + // only draw circles within a certain radius + delta = Vector(g_entities[0].s.origin) - org; + if ((delta * delta) > ((1000 + radius) * (1000 + radius))) { + return; + } + + G_Color4f(r, g, b, alpha); + + if (horizontal) { + forward = "1 0 0"; + left = "0 -1 0"; + } else { + angles = game.clients[0].ps.viewangles; + angles.AngleVectors(NULL, &left, &forward); + } + + G_BeginLine(); + for (i = 0; i <= NUM_CIRCLE_SEGMENTS; i++) { + ang = DEG2RAD(i * 360 / NUM_CIRCLE_SEGMENTS); + pos = org + (sin(ang) * radius * forward) - (cos(ang) * radius * left); + G_Vertex(pos); + } + G_EndLine(); } -void G_DebugArrow - ( - Vector org, - Vector dir, - float length, - float r, - float g, - float b, - float alpha - ) - { - Vector right; - Vector up; - Vector startpoint; - Vector endpoint; +void G_DebugOrientedCircle(Vector org, float radius, float r, float g, float b, float alpha, Vector angles) +{ + int i; + float ang; + Vector forward; + Vector left; + Vector pos; + Vector delta; - PerpendicularVector( right, dir ); - up.CrossProduct( right, dir ); + // only draw circles within a certain radius + delta = Vector(g_entities[0].s.origin) - org; + if ((delta * delta) > ((1000 + radius) * (1000 + radius))) { + return; + } - startpoint = org; + G_Color4f(r, g, b, alpha); - endpoint = startpoint + dir * length; - length /= 6; - G_DebugLine( startpoint, endpoint, r, g, b, alpha ); - G_DebugLine( endpoint, endpoint - (right * length) - (dir * length), r, g, b, alpha ); - G_DebugLine( endpoint, endpoint + (right * length) - (dir * length), r, g, b, alpha ); - G_DebugLine( endpoint, endpoint - (up * length) - (dir * length), r, g, b, alpha ); - G_DebugLine( endpoint, endpoint + (up * length) - (dir * length), r, g, b, alpha ); - } + angles.AngleVectors(NULL, &left, &forward); -void G_DebugHighlightFacet - ( - Vector org, - Vector mins, - Vector maxs, - facet_t facet, - float r, - float g, - float b, - float alpha - ) - { - int i; - Vector points[8]; + G_BeginLine(); + for (i = 0; i <= NUM_CIRCLE_SEGMENTS; i++) { + ang = DEG2RAD(i * 360 / NUM_CIRCLE_SEGMENTS); + pos = org + (sin(ang) * radius * forward) - (cos(ang) * radius * left); + G_Vertex(pos); + } + G_EndLine(); - /* + // + // Draw the cross sign + // + G_BeginLine(); + ang = DEG2RAD(45 * 360 / NUM_CIRCLE_SEGMENTS); + pos = org + (sin(ang) * radius * forward) - (cos(ang) * radius * left); + G_Vertex(pos); + ang = DEG2RAD(225 * 360 / NUM_CIRCLE_SEGMENTS); + pos = org + (sin(ang) * radius * forward) - (cos(ang) * radius * left); + G_Vertex(pos); + + G_BeginLine(); + ang = DEG2RAD(315 * 360 / NUM_CIRCLE_SEGMENTS); + pos = org + (sin(ang) * radius * forward) - (cos(ang) * radius * left); + G_Vertex(pos); + ang = DEG2RAD(135 * 360 / NUM_CIRCLE_SEGMENTS); + pos = org + (sin(ang) * radius * forward) - (cos(ang) * radius * left); + G_Vertex(pos); +} + +void G_DebugPyramid(Vector org, float radius, float r, float g, float b, float alpha) +{ + Vector delta; + Vector points[4]; + + // only draw pyramids within a certain radius + delta = Vector(g_entities[0].s.origin) - org; + if ((delta * delta) > ((1000 + radius) * (1000 + radius))) { + return; + } + + G_Color4f(r, g, b, alpha); + + points[0] = org; + points[0].z += radius; + + points[1] = org; + points[1].z -= radius; + points[2] = points[1]; + points[3] = points[1]; + + points[1].x += cos(DEG2RAD(0)) * radius; + points[1].y += sin(DEG2RAD(0)) * radius; + points[2].x += cos(DEG2RAD(120)) * radius; + points[2].y += sin(DEG2RAD(120)) * radius; + points[3].x += cos(DEG2RAD(240)) * radius; + points[3].y += sin(DEG2RAD(240)) * radius; + + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[1]); + G_Vertex(points[2]); + G_Vertex(points[0]); + G_EndLine(); + + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[2]); + G_Vertex(points[3]); + G_Vertex(points[0]); + G_EndLine(); + + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[3]); + G_Vertex(points[1]); + G_Vertex(points[0]); + G_EndLine(); + + G_BeginLine(); + G_Vertex(points[1]); + G_Vertex(points[2]); + G_Vertex(points[3]); + G_Vertex(points[1]); + G_EndLine(); +} + +void G_DrawCoordSystem(Vector pos, Vector forward, Vector right, Vector up, int length) +{ + if (g_showaxis->integer) { + G_DebugLine(pos, pos + forward * length, 1, 0, 0, 1); + G_DebugLine(pos, pos + right * length, 0, 1, 0, 1); + G_DebugLine(pos, pos + up * length, 0, 0, 1, 1); + } +} + +void G_DrawCSystem(Vector pos, Vector forward, Vector right, Vector up, int length) +{ + G_DebugLine(pos, pos + forward * length, 1.0, 0, 0, 1); + G_DebugLine(pos, pos + right * length, 0, 1.0, 0, 1); + G_DebugLine(pos, pos + up * length, 0, 0, 1.0, 1); +} + +void G_DebugArrow(Vector org, Vector dir, float length, float r, float g, float b, float alpha) +{ + Vector right; + Vector up; + Vector startpoint; + Vector endpoint; + + PerpendicularVector(right, dir); + up.CrossProduct(right, dir); + + startpoint = org; + + endpoint = startpoint + dir * length; + length /= 6; + G_DebugLine(startpoint, endpoint, r, g, b, alpha); + G_DebugLine(endpoint, endpoint - (right * length) - (dir * length), r, g, b, alpha); + G_DebugLine(endpoint, endpoint + (right * length) - (dir * length), r, g, b, alpha); + G_DebugLine(endpoint, endpoint - (up * length) - (dir * length), r, g, b, alpha); + G_DebugLine(endpoint, endpoint + (up * length) - (dir * length), r, g, b, alpha); +} + +void G_DebugHighlightFacet(Vector org, Vector mins, Vector maxs, facet_t facet, float r, float g, float b, float alpha) +{ + int i; + Vector points[8]; + + /* ** compute a full bounding box */ - for ( i = 0; i < 8; i++ ) - { - Vector tmp; + for (i = 0; i < 8; i++) { + Vector tmp; - if ( i & 1 ) - tmp[0] = org[0] + mins[0]; - else - tmp[0] = org[0] + maxs[0]; + if (i & 1) { + tmp[0] = org[0] + mins[0]; + } else { + tmp[0] = org[0] + maxs[0]; + } - if ( i & 2 ) - tmp[1] = org[1] + mins[1]; - else - tmp[1] = org[1] + maxs[1]; + if (i & 2) { + tmp[1] = org[1] + mins[1]; + } else { + tmp[1] = org[1] + maxs[1]; + } - if ( i & 4 ) - tmp[2] = org[2] + mins[2]; - else - tmp[2] = org[2] + maxs[2]; + if (i & 4) { + tmp[2] = org[2] + mins[2]; + } else { + tmp[2] = org[2] + maxs[2]; + } - points[i] = tmp; - } + points[i] = tmp; + } - G_Color4f( r, g, b, alpha ); + G_Color4f(r, g, b, alpha); - switch( facet ) - { - case north: - G_BeginLine(); - G_Vertex( points[0] ); - G_Vertex( points[5] ); - G_EndLine(); - G_BeginLine(); - G_Vertex( points[1] ); - G_Vertex( points[4] ); - G_EndLine(); - break; - case south: - G_BeginLine(); - G_Vertex( points[2] ); - G_Vertex( points[7] ); - G_EndLine(); - G_BeginLine(); - G_Vertex( points[3] ); - G_Vertex( points[6] ); - G_EndLine(); - break; - case east: - G_BeginLine(); - G_Vertex( points[0] ); - G_Vertex( points[6] ); - G_EndLine(); - G_BeginLine(); - G_Vertex( points[4] ); - G_Vertex( points[2] ); - G_EndLine(); - break; - case west: - G_BeginLine(); - G_Vertex( points[1] ); - G_Vertex( points[7] ); - G_EndLine(); - G_BeginLine(); - G_Vertex( points[5] ); - G_Vertex( points[3] ); - G_EndLine(); - break; - case up: - G_BeginLine(); - G_Vertex( points[0] ); - G_Vertex( points[3] ); - G_EndLine(); - G_BeginLine(); - G_Vertex( points[1] ); - G_Vertex( points[2] ); - G_EndLine(); - break; - case down: - G_BeginLine(); - G_Vertex( points[4] ); - G_Vertex( points[7] ); - G_EndLine(); - G_BeginLine(); - G_Vertex( points[5] ); - G_Vertex( points[6] ); - G_EndLine(); - break; - } - } + switch (facet) { + case north: + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[5]); + G_EndLine(); + G_BeginLine(); + G_Vertex(points[1]); + G_Vertex(points[4]); + G_EndLine(); + break; + case south: + G_BeginLine(); + G_Vertex(points[2]); + G_Vertex(points[7]); + G_EndLine(); + G_BeginLine(); + G_Vertex(points[3]); + G_Vertex(points[6]); + G_EndLine(); + break; + case east: + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[6]); + G_EndLine(); + G_BeginLine(); + G_Vertex(points[4]); + G_Vertex(points[2]); + G_EndLine(); + break; + case west: + G_BeginLine(); + G_Vertex(points[1]); + G_Vertex(points[7]); + G_EndLine(); + G_BeginLine(); + G_Vertex(points[5]); + G_Vertex(points[3]); + G_EndLine(); + break; + case up: + G_BeginLine(); + G_Vertex(points[0]); + G_Vertex(points[3]); + G_EndLine(); + G_BeginLine(); + G_Vertex(points[1]); + G_Vertex(points[2]); + G_EndLine(); + break; + case down: + G_BeginLine(); + G_Vertex(points[4]); + G_Vertex(points[7]); + G_EndLine(); + G_BeginLine(); + G_Vertex(points[5]); + G_Vertex(points[6]); + G_EndLine(); + break; + } +} - void G_DebugString(Vector pos, float scale, float r, float g, float b, const char* pszText, ...) - { - debugstring_t* string; - va_list va; - char szTemp[32768]; +void G_DebugString(Vector pos, float scale, float r, float g, float b, const char *pszText, ...) +{ + debugstring_t *string; + va_list va; + char szTemp[32768]; - if (!g_numdebugstrings) { - return; - } + if (!g_numdebugstrings) { + return; + } - if (*gi.numDebugStrings < g_numdebugstrings->integer) { - string = (debugstring_t*)&DebugStrings[*gi.numDebugStrings]; + if (*gi.numDebugStrings < g_numdebugstrings->integer) { + string = (debugstring_t *)&DebugStrings[*gi.numDebugStrings]; - (*gi.numDebugStrings)++; + (*gi.numDebugStrings)++; - va_start(va, pszText); - vsprintf(szTemp, pszText, va); - va_end(va); + va_start(va, pszText); + Q_vsnprintf(szTemp, sizeof(szTemp), pszText, va); + va_end(va); - VectorCopy(pos, string->pos); - string->scale = scale; - string->color[0] = r; - string->color[1] = g; - string->color[2] = b; - string->color[3] = 1.0f; - strncpy(string->szText, szTemp, sizeof(string->szText)); - string->szText[sizeof(string->szText) - 1] = 0; - } - else { - gi.DPrintf("G_DebugString: Exceeded g_numdebugstrings\n"); - } - } + VectorCopy(pos, string->pos); + string->scale = scale; + string->color[0] = r; + string->color[1] = g; + string->color[2] = b; + string->color[3] = 1.0f; + strncpy(string->szText, szTemp, sizeof(string->szText)); + string->szText[sizeof(string->szText) - 1] = 0; + } else { + gi.DPrintf("G_DebugString: Exceeded g_numdebugstrings\n"); + } +} diff --git a/code/fgame/debuglines.h b/code/fgame/debuglines.h index 9d497460..e0656332 100644 --- a/code/fgame/debuglines.h +++ b/code/fgame/debuglines.h @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // debuglines.h: -#ifndef __DEBUGLINES_H__ -#define __DEBUGLINES_H__ +#pragma once #include "g_local.h" @@ -40,6 +39,7 @@ void G_BeginLine( void ); void G_Vertex( Vector v ); void G_EndLine( void ); void G_DebugBBox( Vector org, Vector mins, Vector maxs, float r, float g, float b, float alpha ); +void G_DebugRotatedBBox(Vector org, Vector ang, Vector mins, Vector maxs, float r, float g, float b, float alpha); void G_DrawDebugNumber( Vector org, float number, float scale, float r, float g, float b, int precision = 0 ); void G_DebugCircle( float *org, float radius, float r, float g, float b, float alpha, qboolean horizontal = qfalse ); void G_DebugOrientedCircle( Vector org, float radius, float r, float g, float b, float alpha, Vector angles ); @@ -67,5 +67,3 @@ void G_DebugHighlightFacet( Vector org, Vector mins, Vector maxs, facet_t facet, extern debugline_t *DebugLines; extern debugstring_t *DebugStrings; - -#endif /* !__DEBUGLINES_H__ */ diff --git a/code/fgame/decals.h b/code/fgame/decals.h index 7786cf06..1ca2997a 100644 --- a/code/fgame/decals.h +++ b/code/fgame/decals.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // decals.h: Decal entities -#ifndef __DECAL_H__ -#define __DECAL_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -57,5 +56,3 @@ inline void Decal::Archive setShader( shader ); } } - -#endif // __DECAL_H__ diff --git a/code/fgame/dm_manager.cpp b/code/fgame/dm_manager.cpp index af479dec..dcd87a6d 100644 --- a/code/fgame/dm_manager.cpp +++ b/code/fgame/dm_manager.cpp @@ -33,7 +33,7 @@ cvar_t *g_tempallieswinsinrow; DM_Manager dmManager; -static int g_teamSpawnClock; +static CTeamSpawnClock g_teamSpawnClock; typedef struct spawnsort_s { PlayerStart *spawnpoint; @@ -42,8 +42,8 @@ typedef struct spawnsort_s { static qboolean SpotWouldTelefrag(float *origin) { - static Vector mins = Vector(-16, -16, 1); - static Vector maxs = Vector(16, 16, 97); + static Vector mins = Vector(-15, -15, 1); + static Vector maxs = Vector(15, 15, 96); trace_t trace; trace = G_Trace(Vector(origin), mins, maxs, Vector(origin), NULL, MASK_PLAYERSTART, qfalse, "SpotWouldTelefrag"); @@ -58,15 +58,12 @@ static qboolean SpotWouldTelefrag(float *origin) static int compare_spawnsort(const void *pe1, const void *pe2) { float fDelta = ((spawnsort_t *)pe1)->fMetric - ((spawnsort_t *)pe2)->fMetric; - - if (fDelta >= -0.001f) { - if (fDelta <= 0.001f) { - return 0; - } else { - return -1; - } - } else { + if (fDelta < -0.001) { return 1; + } else if (fDelta > 0.001) { + return -1; + } else { + return 0; } } @@ -83,61 +80,61 @@ static PlayerStart *GetRandomSpawnpointFromList(spawnsort_t *pSpots, int nSpots) qsort(pSpots, nSpots, sizeof(spawnsort_t), compare_spawnsort); - if (pSpots[0].fMetric > 0.0f) { - if (nSpots > 5) { - nSpots = 5; - } - - fMinPosMetric = pSpots[0].fMetric * nSpots; - fTotalMetric = fMinPosMetric; - - if (nSpots <= 1) { - fChosen = fMinPosMetric; - } else { - i = 0; - fTotalMetric = 0.0f; - - for (i = 0; i < nSpots; i++) { - if (pSpots[i].fMetric <= 0.0f) { - break; - } - - fChosen = pSpots[i].fMetric * (nSpots - i); - fTotalMetric += fChosen; - - i++; - } - - if (i < nSpots) { - fChosen = fMinPosMetric; - } - - fMinPosMetric = fTotalMetric; - } - - fTotalMetric = (fMinPosMetric - i * fChosen * 0.90f) * G_Random(); - for (i = 0; i < nSpots - 1; i++) { - fTotalMetric -= (nSpots - i) * pSpots[i].fMetric - (fChosen * 0.90f); - if (fTotalMetric <= 0.0f) { - break; - } - } - - return pSpots[i].spawnpoint; - } else { + if (pSpots[0].fMetric <= 0) { // return the spot anyway return pSpots[0].spawnpoint; } + + if (nSpots > 5) { + nSpots = 5; + } + + fMinPosMetric = pSpots[0].fMetric * nSpots; + fTotalMetric = fMinPosMetric; + + if (nSpots > 1) { + i = 0; + fTotalMetric = 0.0f; + + for (i = 0; i < nSpots; i++) { + if (pSpots[i].fMetric <= 0.0f) { + break; + } + + fChosen = pSpots[i].fMetric * (nSpots - i); + fTotalMetric += fChosen; + + i++; + } + + if (i < nSpots) { + fChosen = fMinPosMetric; + } + + fMinPosMetric = fTotalMetric; + } else { + fChosen = fMinPosMetric; + } + + fTotalMetric = (fMinPosMetric - i * fChosen * 0.9) * G_Random(); + for (i = 0; i < nSpots - 1; i++) { + fTotalMetric -= (nSpots - i) * pSpots[i].fMetric - (fChosen * 0.9); + if (fTotalMetric <= 0) { + break; + } + } + + return pSpots[i].spawnpoint; } -float SpawnpointMetric_Ffa(const float *origin, DM_Team *dmTeam, const Player *player) +float SpawnpointMetric_Ffa(const vec3_t origin, DM_Team *dmTeam, const Player *player) { - float fMinEnemyDistSquared = 23170.0f * 23170.0f; + float fMinEnemyDistSquared = Square(23170.f); int i; int nPlayers = dmManager.PlayerCount(); float fDist; - for (i = 1; i < nPlayers; i++) { + for (i = 1; i <= nPlayers; i++) { Player *teammate = dmManager.GetPlayer(i); if (teammate == player || teammate->IsDead() || teammate->IsSpectator()) { continue; @@ -150,12 +147,12 @@ float SpawnpointMetric_Ffa(const float *origin, DM_Team *dmTeam, const Player *p } } - return fMinEnemyDistSquared - (G_Random(0.25f) + 1.0f) * (1024.0f * 1024.0f); + return fMinEnemyDistSquared - Square(1024) * (G_Random(0.25) + 1.0); } -float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player *player) +float SpawnpointMetric_Team(const vec3_t origin, DM_Team *dmTeam, const Player *player) { - float fMinEnemyDistSquared = 23170.0f * 23170.0f; + float fMinEnemyDistSquared = Square(23170.f); float fSumFriendDistSquared = 0.0f; float fDistSquared; float fMetric; @@ -163,7 +160,7 @@ float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player * int nPlayers = dmManager.PlayerCount(); int nFriends = 0; - for (i = 1; i < nPlayers; i++) { + for (i = 1; i <= nPlayers; i++) { Player *teammate = dmManager.GetPlayer(i); if (teammate == player || teammate->IsDead() || teammate->IsSpectator()) { continue; @@ -174,25 +171,23 @@ float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player * if (teammate->GetDM_Team() == dmTeam) { nFriends++; fSumFriendDistSquared += fDistSquared; - } else { - if (fMinEnemyDistSquared > fDistSquared) { - fMinEnemyDistSquared = fDistSquared; - } + } else if (fMinEnemyDistSquared > fDistSquared) { + fMinEnemyDistSquared = fDistSquared; } } - fMetric = fMinEnemyDistSquared - (G_Random(0.25f) + 1.0f) * (1024.0f * 1024.0f); + fMetric = fMinEnemyDistSquared - Square(1024) * (G_Random(0.25) + 1.0); if (nFriends) { - fMetric += 0.25f * ((23170.0f * 23170.0f) - fSumFriendDistSquared / nFriends); + fMetric += Square(23170) * 0.25 - fSumFriendDistSquared / nFriends; } return fMetric; } -float SpawnpointMetric_Objective(const float *origin, DM_Team *dmTeam, const Player *player) +float SpawnpointMetric_Objective(const vec3_t origin, DM_Team *dmTeam, const Player *player) { - return rand() * 0.0000000005f; + return rand() / (float)RAND_MAX; } CLASS_DECLARATION(Listener, DM_Team, NULL) { @@ -201,7 +196,6 @@ CLASS_DECLARATION(Listener, DM_Team, NULL) { DM_Team::DM_Team() { - m_countdown = 0; m_teamwins = 0; m_wins_in_a_row = 0; m_teamnumber = -1; @@ -216,11 +210,15 @@ void DM_Team::Reset(void) { m_spawnpoints.ClearObjectList(); m_players.ClearObjectList(); + + if (g_gametype->integer == GT_TEAM) { + m_teamwins = 0; + } } void DM_Team::AddPlayer(Player *player) { - m_players.AddObject(player); + m_players.AddUniqueObject(player); } void DM_Team::RemovePlayer(Player *player) @@ -268,7 +266,8 @@ void DM_Team::AddKills(Player *player, int numKills) if (m_teamnumber > TEAM_FREEFORALL) { m_iKills += numKills; - if ((g_gametype->integer >= GT_TEAM_ROUNDS && g_gametype->integer <= GT_TOW) || g_gametype->integer == GT_LIBERATION) { + if ((g_gametype->integer >= GT_TEAM_ROUNDS && g_gametype->integer <= GT_TOW) + || g_gametype->integer == GT_LIBERATION) { player->AddDeaths(numKills); } else { m_teamwins += numKills; @@ -282,7 +281,8 @@ void DM_Team::AddDeaths(Player *player, int numDeaths) return; } - if ((g_gametype->integer >= GT_TEAM_ROUNDS && g_gametype->integer <= GT_TOW) || g_gametype->integer == GT_LIBERATION) { + if ((g_gametype->integer >= GT_TEAM_ROUNDS && g_gametype->integer <= GT_TOW) + || g_gametype->integer == GT_LIBERATION) { return; } @@ -454,12 +454,12 @@ PlayerStart *DM_Team::GetRandomSpawnpointWithMetric( vNewSpawn, player->mins, player->maxs, vEnd, player, MASK_PLAYERSOLID, qfalse, "TempSpawnPoint" ); - if (!trace.allsolid && !trace.startsolid && trace.fraction != 1.0f && trace.fraction != 1.0f - && trace.plane.dist >= 0.8f) { + if (!trace.allsolid && !trace.startsolid && trace.fraction != 1.0f && trace.plane.dist >= 0.8f) { points[numSpots].spawnpoint = new PlayerStart; points[numSpots].spawnpoint->setOrigin(trace.endpos); points[numSpots].spawnpoint->setAngles(spot->angles); points[numSpots].fMetric = MetricFunction(vNewSpawn, this, player); + numSpots++; if (numSpots >= (sizeof(points) / sizeof(points[0]))) { break; @@ -472,8 +472,8 @@ PlayerStart *DM_Team::GetRandomSpawnpointWithMetric( spot = GetRandomSpawnpointFromList(points, numSpots); for (int i = 0; i < numSpots; i++) { // delete all created spawnpoint - if (points[numSpots].spawnpoint != spot) { - delete points[numSpots].spawnpoint; + if (points[i].spawnpoint != spot) { + delete points[i].spawnpoint; } } @@ -492,6 +492,7 @@ PlayerStart *DM_Team::GetRandomSpawnpointWithMetric( if (!SpotWouldTelefrag(spot->origin)) { points[numSpots].spawnpoint = spot; points[numSpots].fMetric = MetricFunction(spot->origin, this, player); + numSpots++; if (numSpots >= (sizeof(points) / sizeof(points[0]))) { break; @@ -521,30 +522,30 @@ bool DM_Team::IsDead(void) const { Player *player; - if (IsEmpty()) { - if (dmManager.IsGameActive()) { - return true; - } - - return false; + if (m_players.NumObjects() == 0) { + return dmManager.IsGameActive(); } if (!m_bHasSpawnedPlayers) { return false; } - if (dmManager.AllowRespawn()) { + if (g_gametype->integer == GT_TOW || g_gametype->integer == GT_LIBERATION) { + if (dmManager.AllowTeamRespawn(m_teamnumber)) { + return false; + } + } else if (dmManager.AllowRespawn()) { return false; } for (int i = m_players.NumObjects(); i > 0; i--) { player = m_players.ObjectAt(i); - if (player->IsSpectator()) { + if (player->IsDead()) { continue; } - if (!player->IsDead()) { + if (!player->IsSpectator()) { return false; } } @@ -575,10 +576,7 @@ int DM_Team::TotalPlayersKills(void) const for (int i = 1; i <= m_players.NumObjects(); i++) { player = m_players.ObjectAt(i); - - if (!player->IsDead() && !player->IsSpectator()) { - iKills += player->GetNumKills(); - } + iKills += player->GetNumKills(); } return iKills; @@ -586,7 +584,7 @@ int DM_Team::TotalPlayersKills(void) const bool DM_Team::IsEmpty(void) const { - return m_players.NumObjects() <= 0; + return !m_players.NumObjects() || !m_bHasSpawnedPlayers; } int DM_Team::NumNotReady(void) const @@ -597,7 +595,7 @@ int DM_Team::NumNotReady(void) const for (int i = 1; i <= m_players.NumObjects(); i++) { player = m_players.ObjectAt(i); - if (player->IsReady() && !player->IsDead()) { + if (player->IsReady()) { i++; } } @@ -605,76 +603,6 @@ int DM_Team::NumNotReady(void) const return num; } -void DM_Team::InitSpawnPoints(void) -{ - int i; - - if (m_teamnumber == TEAM_SPECTATOR) { - for (i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i--) { - PlayerStart *spawnpoint = (PlayerStart *)level.m_SimpleArchivedEntities.ObjectAt(i); - const char *classname = spawnpoint->getClassID(); - - if (!Q_stricmp(classname, "info_player_deathmatch")) { - m_spawnpoints.AddObject(spawnpoint); - } else if (!Q_stricmp(classname, "info_player_intermission")) { - m_spawnpoints.AddObject(spawnpoint); - } - } - - return; - } - - if (g_gametype->integer <= GT_FFA) { - for (i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i--) { - PlayerStart *spawnpoint = (PlayerStart *)level.m_SimpleArchivedEntities.ObjectAt(i); - const char *classname = spawnpoint->getClassID(); - - if (!Q_stricmp(classname, "info_player_deathmatch")) { - m_spawnpoints.AddObject(spawnpoint); - } - } - - if (m_spawnpoints.NumObjects() <= 1) { - // Try with team spawnpoints - for (i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i--) { - PlayerStart *spawnpoint = (PlayerStart *)level.m_SimpleArchivedEntities.ObjectAt(i); - const char *classname = spawnpoint->getClassID(); - - if (!Q_stricmp(classname, "info_player_allied")) { - m_spawnpoints.AddObject(spawnpoint); - } else if (!Q_stricmp(classname, "info_player_axis")) { - m_spawnpoints.AddObject(spawnpoint); - } - } - } - } else if (g_gametype->integer >= GT_TEAM) { - if (m_teamnumber >= TEAM_ALLIES) { - for (i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i--) { - PlayerStart *spawnpoint = (PlayerStart *)level.m_SimpleArchivedEntities.ObjectAt(i); - const char *classname = spawnpoint->getClassID(); - - if (m_teamnumber == TEAM_ALLIES && !Q_stricmp(classname, "info_player_allied")) { - m_spawnpoints.AddObject(spawnpoint); - } else if (m_teamnumber == TEAM_AXIS && !Q_stricmp(classname, "info_player_axis")) { - m_spawnpoints.AddObject(spawnpoint); - } - } - } - - if (!m_spawnpoints.NumObjects()) { - // Try with info_player_deathmatch - for (int i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i--) { - PlayerStart *spawnpoint = (PlayerStart *)level.m_SimpleArchivedEntities.ObjectAt(i); - const char *classname = spawnpoint->getClassID(); - - if (!Q_stricmp(classname, "info_player_deathmatch")) { - m_spawnpoints.AddObject(spawnpoint); - } - } - } - } -} - void DM_Team::UpdateTeamStatus(void) { for (int i = 1; i <= m_players.NumObjects(); i++) { @@ -696,7 +624,11 @@ Event EV_DM_Manager_DoRoundTransition ); Event EV_DM_Manager_FinishRoundTransition ( - "finishroundtransition", EV_DEFAULT, NULL, NULL, "delayed function call to do the actual restart for the next round" + "finishroundtransition", + EV_DEFAULT, + NULL, + NULL, + "delayed function call to do the actual restart for the next round" ); CLASS_DECLARATION(Listener, DM_Manager, NULL) { @@ -727,16 +659,21 @@ DM_Manager::DM_Manager() m_team_axis.setNumber(TEAM_AXIS); m_team_axis.setIndex(TEAM_AXIS); + m_fRoundTime = 0; + m_fRoundEndTime = 0; + m_bAllowRespawns = true; + m_bRoundBasedGame = false; m_iTeamWin = 0; + m_iDefaultRoundLimit = 0; m_csTeamClockSide = STRING_AXIS; m_csTeamBombPlantSide = STRING_DRAW; - m_fRoundEndTime = 0.0f; - m_bAllowRespawns = qtrue; - m_bRoundBasedGame = qfalse; - m_iDefaultRoundLimit = 0; - m_iNumTargetsToDestroy = 0; + m_iNumTargetsToDestroy = 1; m_iNumTargetsDestroyed = 0; m_iNumBombsPlanted = 0; + m_bAllowAxisRespawn = true; + m_bAllowAlliedRespawn = true; + m_bRoundActive = false; + m_iTotalMapTime = 0; } DM_Manager::~DM_Manager() {} @@ -758,8 +695,10 @@ void DM_Manager::Reset(void) // m_bAllowAxisRespawn = true; m_bAllowAlliedRespawn = true; - g_teamSpawnClock = sv_team_spawn_interval->validate; - level.m_bIgnoreClock = false; + + // Reset the team spawn clock + g_teamSpawnClock.Reset(); + level.m_bIgnoreClock = false; if (g_gametype->integer == GT_TOW) { g_TOWObjectiveMan.Reset(); @@ -1088,30 +1027,74 @@ void DM_Manager::PrintAllClients(str s) void DM_Manager::InitGame(void) { - m_teams.ClearObjectList(); + int i; - m_teams.AddObject(&m_team_spectator); - - if (g_gametype->integer >= GT_TEAM) { - m_teams.AddObject(&m_team_allies); - m_teams.AddObject(&m_team_axis); - } else { - m_teams.AddObject(&m_team_freeforall); + if (fraglimit) { + if (fraglimit->integer < 0) { + gi.cvar_set("fraglimit", "0"); + } + if (fraglimit->integer > 10000) { + gi.cvar_set("fraglimit", "10000"); + } + fraglimit = gi.Cvar_Get("fraglimit", "0", CVAR_SERVERINFO); } - m_team_spectator.InitSpawnPoints(); - m_team_allies.InitSpawnPoints(); - m_team_axis.InitSpawnPoints(); - m_team_freeforall.InitSpawnPoints(); - - if (g_gametype->integer < 0 || g_gametype->integer >= GT_MAX_GAME_TYPE) { - Com_Printf("Unknown game mode"); + if (timelimit) { + if (timelimit->integer < 0) { + gi.cvar_set("timelimit", "0"); + } + // 180 minutes maximum + if (timelimit->integer > 10800) { + gi.cvar_set("timelimit", "10800"); + } + timelimit = gi.Cvar_Get("timelimit", "0", CVAR_SERVERINFO); + } + + for (i = 1; i <= level.m_SimpleArchivedEntities.NumObjects(); i++) { + SimpleArchivedEntity *const ent = level.m_SimpleArchivedEntities.ObjectAt(i); + const char *const classname = ent->getClassID(); + + if (!Q_stricmp(classname, "info_player_deathmatch")) { + PlayerStart *const spawnpoint = static_cast(ent); + m_team_spectator.m_spawnpoints.AddObject(spawnpoint); + m_team_freeforall.m_spawnpoints.AddObject(spawnpoint); + + if (g_gametype->integer == GT_FFA) { + m_team_allies.m_spawnpoints.AddObject(spawnpoint); + m_team_axis.m_spawnpoints.AddObject(spawnpoint); + } + } else if (!Q_stricmp(classname, "info_player_allied")) { + if (g_gametype->integer >= GT_TEAM) { + PlayerStart *const spawnpoint = static_cast(ent); + m_team_allies.m_spawnpoints.AddObject(spawnpoint); + } + } else if (!Q_stricmp(classname, "info_player_axis")) { + if (g_gametype->integer >= GT_TEAM) { + PlayerStart *const spawnpoint = static_cast(ent); + m_team_axis.m_spawnpoints.AddObject(spawnpoint); + } + } else if (!Q_stricmp(classname, "info_player_intermission")) { + PlayerStart *const spawnpoint = static_cast(ent); + m_team_freeforall.m_spawnpoints.AddObject(spawnpoint); + } + } + + if (g_gametype->integer > GT_SINGLE_PLAYER) { + if (g_gametype->integer < GT_MAX_GAME_TYPE) { + m_teams.ClearObjectList(); + m_teams.AddObject(&m_team_spectator); + m_teams.AddObject(&m_team_allies); + m_teams.AddObject(&m_team_axis); + } else { + Com_Printf("Unknown game mode"); + } } - m_bIgnoringClockForBomb = false; m_fRoundTime = 0; m_fRoundEndTime = 0; m_iTeamWin = 0; + m_bIgnoringClockForBomb = false; + m_iNumTargetsDestroyed = 0; m_iNumBombsPlanted = 0; if (g_gametype->integer >= 0 && g_gametype->integer < GT_MAX_GAME_TYPE) { @@ -1120,10 +1103,10 @@ void DM_Manager::InitGame(void) m_bRoundBasedGame = false; } else { if (g_gametype->integer == GT_TOW || g_gametype->integer == GT_LIBERATION) { - m_bAllowRespawns = true; + m_bAllowRespawns = true; m_bRoundBasedGame = true; } else { - m_bAllowRespawns = false; + m_bAllowRespawns = false; m_bRoundBasedGame = true; } @@ -1233,7 +1216,9 @@ bool DM_Manager::CheckEndMatch() G_BeginIntermission2(); return true; } - } else if (timelimit->integer && level.inttime >= 60000 * timelimit->integer) { + } + + if (timelimit->integer && level.inttime >= timelimit->integer * 60000) { G_BeginIntermission2(); return true; } else { @@ -1257,7 +1242,7 @@ bool DM_Manager::CheckEndMatch() if (AllowRespawn() || (!m_team_axis.IsDead() && !m_team_allies.IsDead())) { int roundLimit = GetRoundLimit(); - if (roundLimit > 0 && level.time >= m_iDefaultRoundLimit * 60 + m_fRoundTime) { + if (roundLimit > 0 && level.time >= roundLimit * 60 + m_fRoundTime) { if (m_csTeamBombPlantSide != STRING_DRAW) { if (m_bIgnoringClockForBomb) { if (m_iNumBombsPlanted > 0) { @@ -1266,7 +1251,7 @@ bool DM_Manager::CheckEndMatch() m_bIgnoringClockForBomb = false; } else if (m_iNumBombsPlanted > 0) { - G_PrintToAllClients("A bomb is still set!"); + G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("A Bomb is Still Set!"))); m_bIgnoringClockForBomb = true; return false; } @@ -1340,7 +1325,7 @@ bool DM_Manager::CheckEndMatch() return true; } else if (m_iNumBombsPlanted >= m_iNumTargetsToDestroy - m_iNumTargetsDestroyed) { if (!m_bIgnoringClockForBomb) { - G_PrintToAllClients("A bomb is still set!"); + G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("A Bomb is Still Set!"))); m_bIgnoringClockForBomb = true; } } else { @@ -1424,26 +1409,26 @@ void DM_Manager::EventDoRoundTransition(Event *ev) } if (m_iTeamWin == TEAM_AXIS) { - G_CenterPrintToAllClients(va("\n\n\n%s\n", gi.LV_ConvertString("Axis win!\n"))); - G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("Axis win!\n"))); + G_CenterPrintToAllClients(va("\n\n\n%s\n", gi.LV_ConvertString("Axis win!"))); + G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("Axis win!"))); // Play the axis victory sound world->Sound("den_victory_v"); - Unregister(STRING_AXISWIN); + level.Unregister(STRING_AXISWIN); } else if (m_iTeamWin == TEAM_ALLIES) { - G_CenterPrintToAllClients(va("\n\n\n%s\n", gi.LV_ConvertString("Allies win!\n"))); - G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("Allies win!\n"))); + G_CenterPrintToAllClients(va("\n\n\n%s\n", gi.LV_ConvertString("Allies win!"))); + G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("Allies win!"))); // Play the allies victory sound world->Sound("dfr_victory_v"); - Unregister(STRING_ALLIESWIN); + level.Unregister(STRING_ALLIESWIN); } else { - G_CenterPrintToAllClients(va("\n\n\n%s\n", gi.LV_ConvertString("It's a draw!\n"))); - G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("It's a draw!\n"))); + G_CenterPrintToAllClients(va("\n\n\n%s\n", gi.LV_ConvertString("It's a draw!"))); + G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("It's a draw!"))); - Unregister(STRING_DRAW); + level.Unregister(STRING_DRAW); } G_DisplayScoresToAllClients(); @@ -1483,7 +1468,7 @@ void DM_Manager::EventFinishRoundTransition(Event *ev) gi.SendConsoleCommand("restart\n"); - g_teamSpawnClock = sv_team_spawn_interval->value; + g_teamSpawnClock.Reset(); } int DM_Manager::PlayerCount(void) const @@ -1554,6 +1539,7 @@ void DM_Manager::StartRound(void) } m_fRoundEndTime = 0.0f; + m_bRoundActive = true; // respawn all players for (i = 0, ent = g_entities; i < game.maxclients; i++, ent++) { @@ -1576,18 +1562,33 @@ void DM_Manager::StartRound(void) void DM_Manager::EndRound() { - if (m_fRoundEndTime <= 0.0f) { + m_bRoundActive = false; + + if (m_fRoundEndTime <= 0) { m_fRoundEndTime = level.time; - PostEvent(EV_DM_Manager_DoRoundTransition, 2.0f); + PostEvent(EV_DM_Manager_DoRoundTransition, 2); } } bool DM_Manager::AllowRespawn() const { - return m_bAllowRespawns - || (g_gametype->integer > GT_TEAM - && ((!m_team_axis.m_players.NumObjects() && !m_team_axis.m_bHasSpawnedPlayers) - || (!m_team_allies.m_players.NumObjects() && !m_team_allies.m_bHasSpawnedPlayers))); + if (GameAllowsRespawns()) { + return true; + } + + if (g_gametype->integer <= GT_TEAM) { + return false; + } + + if (!m_team_axis.m_players.NumObjects() && !m_team_axis.m_bHasSpawnedPlayers) { + return true; + } + + if (!m_team_allies.m_players.NumObjects() && !m_team_allies.m_bHasSpawnedPlayers) { + return true; + } + + return false; } bool DM_Manager::WaitingForPlayers(void) const @@ -1596,15 +1597,15 @@ bool DM_Manager::WaitingForPlayers(void) const return false; } - if (!m_team_axis.m_players.NumObjects() || !m_team_axis.m_bHasSpawnedPlayers) { + if (m_team_axis.IsEmpty() || m_team_allies.IsEmpty()) { return true; - } else if (!m_team_allies.m_players.NumObjects() || !m_team_allies.m_bHasSpawnedPlayers) { + } + + if (!m_team_axis.IsReady() || !m_team_allies.IsReady()) { return true; - } else if (!g_forceready->integer && m_team_axis.NumNotReady()) { - return true; - } else if (!g_forceready->integer && m_team_allies.NumNotReady()) { - return true; - } else if (m_team_axis.IsDead() || m_team_allies.IsDead()) { + } + + if (m_team_axis.IsDead() || m_team_allies.IsDead()) { return true; } @@ -1613,31 +1614,39 @@ bool DM_Manager::WaitingForPlayers(void) const bool DM_Manager::IsGameActive(void) const { - return !m_bRoundBasedGame || m_fRoundTime > 0.0f; + return !GameHasRounds() || m_fRoundTime > 0; } float DM_Manager::GetMatchStartTime(void) { + int totalnotready; + if (g_gametype->integer <= GT_TEAM) { return m_fRoundTime; } - if (m_fRoundTime <= 0.0f) { - if (!m_team_allies.m_players.NumObjects() || !m_team_allies.m_bHasSpawnedPlayers) { - return -1.0f; - } - - if (!m_team_axis.m_players.NumObjects() || !m_team_axis.m_bHasSpawnedPlayers) { - return -1.0f; - } - - int num = m_team_allies.NumNotReady() + m_team_axis.NumNotReady(); - if (num > 0) { - return (float)~num; + if (g_gametype->integer == GT_TEAM_ROUNDS || g_gametype->integer == GT_OBJECTIVE + || g_gametype->integer == GT_LIBERATION) { + if (m_fRoundTime > 0 && (m_team_allies.IsEmpty() || m_team_allies.IsEmpty())) { + m_fRoundTime = 0; + return -1; } } - return m_fRoundTime; + if (m_fRoundTime > 0) { + return m_fRoundTime; + } + + if (m_team_allies.IsEmpty() || m_team_axis.IsEmpty()) { + return -1; + } + + totalnotready = m_team_allies.NumNotReady() + m_team_axis.NumNotReady(); + if (totalnotready > 0) { + return -1 - totalnotready; + } else { + return m_fRoundTime; + } } int DM_Manager::GetRoundLimit() const @@ -1708,10 +1717,10 @@ void DM_Manager::SetBombsPlanted(int num) void DM_Manager::StopTeamRespawn(eController controller) { - if (controller == CONTROLLER_AXIS) { - m_bAllowAxisRespawn = false; - } else if (controller == CONTROLLER_ALLIES) { + if (controller == CONTROLLER_ALLIES) { m_bAllowAlliedRespawn = false; + } else if (controller == CONTROLLER_AXIS) { + m_bAllowAxisRespawn = false; } } @@ -1728,8 +1737,6 @@ bool DM_Manager::AllowTeamRespawn(int teamnum) const int DM_Manager::GetTeamSpawnTimeLeft() const { - int timeLeft; - if (sv_team_spawn_interval->integer <= 0) { return -1; } @@ -1738,16 +1745,11 @@ int DM_Manager::GetTeamSpawnTimeLeft() const return 0; } - timeLeft = ceil(g_teamSpawnClock - level.time); - if (timeLeft <= -1) { - g_teamSpawnClock = level.time + sv_team_spawn_interval->value; + if (g_gametype->integer == GT_TEAM || g_gametype->integer == GT_TOW || g_gametype->integer == GT_LIBERATION) { + return g_teamSpawnClock.GetSecondsLeft(); } - if (timeLeft < 0) { - timeLeft = 0; - } - - return timeLeft; + return 0; } DM_Team *DM_Manager::GetTeam(str name) @@ -1793,22 +1795,22 @@ void DM_Manager::InsertEntry(const char *entry) size_t len = strlen(entry); if (scoreLength + len < MAX_STRING_CHARS) { - strcpy(scoreString + scoreLength, entry); + Q_strncpyz(scoreString + scoreLength, entry, sizeof(scoreString) - scoreLength); scoreLength += len; scoreEntries++; } } -void DM_Manager::InsertEntryNoCount(const char* entry) +void DM_Manager::InsertEntryNoCount(const char *entry) { - size_t len = strlen(entry); + size_t len = strlen(entry); - if (scoreLength + len < MAX_STRING_CHARS) { - strcpy(scoreString + scoreLength, entry); + if (scoreLength + len < MAX_STRING_CHARS) { + Q_strncpyz(scoreString + scoreLength, entry, sizeof(scoreString) - scoreLength); - scoreLength += len; - } + scoreLength += len; + } } void DM_Manager::InsertEmpty(void) @@ -1841,7 +1843,7 @@ void DM_Manager::BuildTeamInfo_ver6(DM_Team *dmTeam) for (int i = iNumPlayers; i > 0; i--) { pTeamPlayer = dmTeam->m_players.ObjectAt(i); - if (pTeamPlayer->IsSubclassOfBot()) { + if (pTeamPlayer->edict->r.svFlags & SVF_BOT) { continue; } @@ -1868,7 +1870,7 @@ void DM_Manager::BuildTeamInfo_ver6(DM_Team *dmTeam) Com_sprintf(entry, sizeof(entry), "%i %i \"\" \"\" \"\" \"\" ", -1, dmTeam->m_teamnumber); } } else { - Com_sprintf(entry, sizeof(entry), "%i \"\" \"\" \"\" \"\" \"\" ", -1 - dmTeam->m_teamnumber); + Com_sprintf(entry, sizeof(entry), "%i \"\" \"\" \"\" \"\" ", -1 - dmTeam->m_teamnumber); } InsertEntry(entry); @@ -1886,7 +1888,7 @@ void DM_Manager::BuildTeamInfo_ver15(DM_Team *dmTeam) for (int i = iNumPlayers; i > 0; i--) { pTeamPlayer = dmTeam->m_players.ObjectAt(i); - if (pTeamPlayer->IsSubclassOfBot()) { + if (pTeamPlayer->edict->r.svFlags & SVF_BOT) { continue; } @@ -1898,11 +1900,11 @@ void DM_Manager::BuildTeamInfo_ver15(DM_Team *dmTeam) iPing /= iNumPlayers; } - if (g_gametype->integer >= GT_TEAM_ROUNDS) { - iKills = dmTeam->m_wins_in_a_row; - iDeaths = dmTeam->m_teamwins; + if (g_gametype->integer == GT_TEAM_ROUNDS || g_gametype->integer == GT_OBJECTIVE || g_gametype->integer == GT_TOW) { + iKills = dmTeam->m_teamwins; + iDeaths = dmTeam->m_wins_in_a_row; } else { - iKills = dmTeam->m_iKills; + iKills = dmTeam->m_teamwins; iDeaths = dmTeam->m_iDeaths; } @@ -1920,7 +1922,7 @@ void DM_Manager::BuildTeamInfo_ver15(DM_Team *dmTeam) iPing ); } else { - Com_sprintf(entry, sizeof(entry), "%i %i \"\" \"\" \"\" \"\" \"\" ", -1, dmTeam->m_teamnumber); + Com_sprintf(entry, sizeof(entry), "%i %i \"\" \"\" \"\" \"\" ", -1, dmTeam->m_teamnumber); } } else { Com_sprintf(entry, sizeof(entry), "%i \"\" \"\" \"\" \"\" ", -1 - dmTeam->m_teamnumber); @@ -1960,7 +1962,7 @@ void DM_Manager::BuildPlayerTeamInfo(DM_Team *dmTeam, int *iPlayerList, DM_Team pTeamPlayer->GetNumKills(), pTeamPlayer->GetNumDeaths(), G_TimeString(level.svsFloatTime - pTeamPlayer->edict->client->pers.enterTime), - pTeamPlayer->IsSubclassOfBot() ? "bot" : va("%d", pTeamPlayer->client->ps.ping) + (pTeamPlayer->edict->r.svFlags & SVF_BOT) ? "bot" : va("%d", pTeamPlayer->client->ps.ping) ); } else { Com_sprintf( @@ -1971,7 +1973,7 @@ void DM_Manager::BuildPlayerTeamInfo(DM_Team *dmTeam, int *iPlayerList, DM_Team pTeamPlayer->GetNumKills(), pTeamPlayer->GetNumDeaths(), G_TimeString(level.svsFloatTime - pTeamPlayer->edict->client->pers.enterTime), - pTeamPlayer->IsSubclassOfBot() ? "bot" : va("%d", pTeamPlayer->client->ps.ping) + (pTeamPlayer->edict->r.svFlags & SVF_BOT) ? "bot" : va("%d", pTeamPlayer->client->ps.ping) ); } @@ -1981,5 +1983,37 @@ void DM_Manager::BuildPlayerTeamInfo(DM_Team *dmTeam, int *iPlayerList, DM_Team bool DM_Manager::IsAlivePlayer(Player *player) const { - return !player->IsDead() && !player->IsSpectator() && !player->IsInJail() || player->GetDM_Team() == &m_team_spectator; + return !player->IsDead() && !player->IsSpectator() && !player->IsInJail() + || player->GetDM_Team() == &m_team_spectator; +} + +CTeamSpawnClock::CTeamSpawnClock() +{ + nextSpawnTime = 0; +} + +void CTeamSpawnClock::Reset() +{ + nextSpawnTime = sv_team_spawn_interval->value; +} + +void CTeamSpawnClock::Restart() +{ + nextSpawnTime = level.time + sv_team_spawn_interval->value; +} + +int CTeamSpawnClock::GetSecondsLeft() +{ + int timeLeft; + + timeLeft = ceil(nextSpawnTime - level.time); + if (timeLeft <= -1) { + Restart(); + } + + if (timeLeft < 0) { + return 0; + } + + return timeLeft; } diff --git a/code/fgame/dm_manager.h b/code/fgame/dm_manager.h index 88d6d658..087ea5b0 100644 --- a/code/fgame/dm_manager.h +++ b/code/fgame/dm_manager.h @@ -45,7 +45,6 @@ public: int m_teamnumber; int m_index; - int m_countdown; int m_teamwins; int m_wins_in_a_row; @@ -95,8 +94,6 @@ public: PlayerStart *GetRandomTeamSpawnpoint(Player *player); PlayerStart *GetRandomObjectiveSpawnpoint(Player *player); - void InitSpawnPoints(void); - protected: PlayerStart *FarthestSpawnPoint(void); PlayerStart *GetRandomSpawnpoint(void); @@ -139,7 +136,7 @@ inline int DM_Team::getIndex(void) inline bool DM_Team::IsReady(void) const { - return !NumNotReady(); + return g_forceready->integer || NumNotReady() == 0; } class SimpleAmmoType : public Class @@ -182,8 +179,9 @@ private: int m_iNumBombsPlanted; int m_iTotalMapTime; - bool m_bAllowAxisRespawn; bool m_bAllowAlliedRespawn; + bool m_bAllowAxisRespawn; + bool m_bRoundActive; // scoreboard data char scoreString[MAX_STRING_CHARS]; @@ -227,6 +225,7 @@ public: void TeamWin(int teamnum); void StartRound(void); void EndRound(void); + bool RoundActive(void) const; bool GameHasRounds(void) const; bool GameAllowsRespawns(void) const; void SetGameAllowsRespawns(bool bAllow); @@ -280,6 +279,11 @@ inline DM_Team *DM_Manager::GetTeamAxis(void) return &m_team_axis; } +inline bool DM_Manager::RoundActive(void) const +{ + return m_bRoundActive; +} + inline bool DM_Manager::GameHasRounds(void) const { return m_bRoundBasedGame; @@ -296,3 +300,15 @@ inline void DM_Manager::SetGameAllowsRespawns(bool bAllow) } extern DM_Manager dmManager; + +class CTeamSpawnClock { +private: + float nextSpawnTime; + +public: + CTeamSpawnClock(); + void Reset(); + void Restart(); + + int GetSecondsLeft(); +}; diff --git a/code/fgame/doors.cpp b/code/fgame/doors.cpp index 0f4c756c..fe95e0a5 100644 --- a/code/fgame/doors.cpp +++ b/code/fgame/doors.cpp @@ -39,229 +39,237 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Event EV_Door_OpenStartSound ( - "sound_open_start", - EV_DEFAULT, - "s", - "sound_open_start", - "Sets the sound to use when the door starts to opens." + "sound_open_start", + EV_DEFAULT, + "s", + "sound_open_start", + "Sets the sound to use when the door starts to opens." ); Event EV_Door_OpenEndSound ( - "sound_open_end", - EV_DEFAULT, - "s", - "sound_open_end", - "Sets the sound to use when the door stops to opens." + "sound_open_end", + EV_DEFAULT, + "s", + "sound_open_end", + "Sets the sound to use when the door stops to opens." ); Event EV_Door_CloseStartSound ( - "sound_close_start", - EV_DEFAULT, - "s", - "sound_close", - "Sets the sound to use when the door closes." + "sound_close_start", + EV_DEFAULT, + "s", + "sound_close", + "Sets the sound to use when the door closes." ); Event EV_Door_CloseEndSound ( - "sound_close_end", - EV_DEFAULT, - "s", - "sound_close", - "Sets the sound to use when the door closes." + "sound_close_end", + EV_DEFAULT, + "s", + "sound_close", + "Sets the sound to use when the door closes." ); Event EV_Door_MessageSound - ( - "sound_message", - EV_DEFAULT, - "s", - "sound_message", - "Sets the sound to use when the door displays a message.", - EV_NORMAL - ); +( + "sound_message", + EV_DEFAULT, + "s", + "sound_message", + "Sets the sound to use when the door displays a message.", + EV_NORMAL +); Event EV_Door_LockedSound - ( - "sound_locked", - EV_DEFAULT, - "s", - "sound_locked", - "Sets the sound to use when the door is locked.", - EV_NORMAL - ); +( + "sound_locked", + EV_DEFAULT, + "s", + "sound_locked", + "Sets the sound to use when the door is locked.", + EV_NORMAL +); Event EV_Door_SetWait - ( - "wait", - EV_DEFAULT, - "f", - "wait", - "Sets the amount of time to wait before automatically shutting.", - EV_NORMAL - ); +( + "wait", + EV_DEFAULT, + "f", + "wait", + "Sets the amount of time to wait before automatically shutting.", + EV_NORMAL +); Event EV_Door_SetDmg - ( - "dmg", - EV_DEFAULT, - "i", - "damage", - "Sets the amount of damage the door will do to entities that get stuck in it.", - EV_NORMAL - ); +( + "dmg", + EV_DEFAULT, + "i", + "damage", + "Sets the amount of damage the door will do to entities that get stuck in it.", + EV_NORMAL +); Event EV_Door_TriggerFieldTouched - ( - "door_triggerfield", - EV_DEFAULT, - "e", - "other", - "Is called when a doors trigger field is touched.", - EV_NORMAL - ); +( + "door_triggerfield", + EV_DEFAULT, + "e", + "other", + "Is called when a doors trigger field is touched.", + EV_NORMAL +); Event EV_Door_TryOpen - ( - "tryToOpen", - EV_DEFAULT, - "e", - "other", - "Tries to open the door.", - EV_NORMAL - ); +( + "tryToOpen", + EV_DEFAULT, + "e", + "other", + "Tries to open the door.", + EV_NORMAL +); Event EV_Door_Close - ( - "close", - EV_DEFAULT, - NULL, - NULL, - "Closes the door.", - EV_NORMAL - ); +( + "close", + EV_DEFAULT, + NULL, + NULL, + "Closes the door.", + EV_NORMAL +); Event EV_Door_Open - ( - "open", - EV_DEFAULT, - "e", - "other", - "Opens the door.", - EV_NORMAL - ); +( + "open", + EV_DEFAULT, + "e", + "other", + "Opens the door.", + EV_NORMAL +); Event EV_Door_DoClose - ( - "doclose", - EV_DEFAULT, - NULL, - NULL, - "Closes the door (special doors).", - EV_NORMAL - ); +( + "doclose", + EV_DEFAULT, + NULL, + NULL, + "Closes the door (special doors).", + EV_NORMAL +); Event EV_Door_DoOpen - ( - "doopen", - EV_DEFAULT, - "e", - "other", - "Opens the door (special doors).", - EV_NORMAL - ); +( + "doopen", + EV_DEFAULT, + "e", + "other", + "Opens the door (special doors).", + EV_NORMAL +); Event EV_Door_CloseEnd - ( - "doorclosed", - EV_DEFAULT, - NULL, - NULL, - "Called when the door finishes closing.", - EV_NORMAL - ); +( + "doorclosed", + EV_DEFAULT, + NULL, + NULL, + "Called when the door finishes closing.", + EV_NORMAL +); Event EV_Door_OpenEnd - ( - "dooropened", - EV_DEFAULT, - NULL, - NULL, - "Called when the door finishes opening.", - EV_NORMAL - ); +( + "dooropened", + EV_DEFAULT, + NULL, + NULL, + "Called when the door finishes opening.", + EV_NORMAL +); +Event EV_Door_IsOpen // Added in 2.30 +( + "isOpen", + EV_DEFAULT, + NULL, + NULL, + "Check to see if door is open (non-zero return value)", + EV_GETTER +); Event EV_Door_Fire - ( - "toggledoor", - EV_DEFAULT, - "e", - "other", - "Toggles the state of the door (open/close).", - EV_NORMAL - ); +( + "toggledoor", + EV_DEFAULT, + "e", + "other", + "Toggles the state of the door (open/close).", + EV_NORMAL +); Event EV_Door_Link - ( - "linkdoor", - EV_DEFAULT, - NULL, - NULL, - "Link doors together.", - EV_NORMAL - ); +( + "linkdoor", + EV_DEFAULT, + NULL, + NULL, + "Link doors together.", + EV_NORMAL +); Event EV_Door_SetTime - ( - "time", - EV_DEFAULT, - "f", - "traveltime", - "Sets the time it takes for the door to open an close.", - EV_NORMAL - ); +( + "time", + EV_DEFAULT, + "f", + "traveltime", + "Sets the time it takes for the door to open an close.", + EV_NORMAL +); Event EV_Door_Lock - ( - "lock", - EV_DEFAULT, - NULL, - NULL, - "Lock the door.", - EV_NORMAL - ); +( + "lock", + EV_DEFAULT, + NULL, + NULL, + "Lock the door.", + EV_NORMAL +); Event EV_Door_Unlock - ( - "unlock", - EV_DEFAULT, - NULL, - NULL, - "Unlock the door.", - EV_NORMAL - ); +( + "unlock", + EV_DEFAULT, + NULL, + NULL, + "Unlock the door.", + EV_NORMAL +); Event EV_Door_TrySolid - ( - "trysolid", - EV_DEFAULT, - NULL, - NULL, - "Trys to make the door solid.", - EV_NORMAL - ); +( + "trysolid", + EV_DEFAULT, + NULL, + NULL, + "Trys to make the door solid.", + EV_NORMAL +); Event EV_Door_AlwaysAway - ( - "alwaysaway", - EV_DEFAULT, - "B", - "bAlwaysAway", - "Makes the door always open away from the person opening it.", - EV_NORMAL - ); -Event EV_Door_DoorType - ( - "doortype", - EV_DEFAULT, - "s", - "door_type", - "Sets the defaults for this door\n" - "Door Defaults: wood(default)\n" - "metal" - ); +( + "alwaysaway", + EV_DEFAULT, + "B", + "bAlwaysAway", + "Makes the door always open away from the person opening it.", + EV_NORMAL +); +Event EV_Door_DoorType( + "doortype", + EV_DEFAULT, + "s", + "door_type", + "Sets the defaults for this door\n" + "Door Defaults: wood(default)\n" + "metal" +); -#define DOOR_START_OPEN 1 -#define DOOR_OPEN_DIRECTION 2 -#define DOOR_DONT_LINK 4 -#define DOOR_TOGGLE 32 -#define DOOR_AUTO_OPEN 64 -#define DOOR_TARGETED 128 +#define DOOR_START_OPEN 1 +#define DOOR_OPEN_DIRECTION 2 +#define DOOR_DONT_LINK 4 +#define DOOR_TOGGLE 32 +#define DOOR_AUTO_OPEN 64 +#define DOOR_TARGETED 128 -#define STATE_OPEN 1 -#define STATE_OPENING 2 -#define STATE_CLOSING 3 -#define STATE_CLOSED 4 +#define STATE_OPEN 1 +#define STATE_OPENING 2 +#define STATE_CLOSING 3 +#define STATE_CLOSED 4 /* @@ -276,1068 +284,972 @@ Door.enemy chains from the master door through all doors linked in the chain. */ -CLASS_DECLARATION( ScriptSlave, Door, "func_door" ) -{ - { &EV_Door_OpenStartSound, &Door::SetOpenStartSound }, - { &EV_Door_OpenEndSound, &Door::SetOpenEndSound }, - { &EV_Door_CloseStartSound, &Door::SetCloseStartSound }, - { &EV_Door_CloseEndSound, &Door::SetCloseEndSound }, - { &EV_Door_MessageSound, &Door::SetMessageSound }, - { &EV_Door_LockedSound, &Door::SetLockedSound }, - { &EV_Door_SetWait, &Door::SetWait }, - { &EV_Door_SetDmg, &Door::SetDmg }, - { &EV_Door_TriggerFieldTouched, &Door::FieldTouched }, - { &EV_Trigger_Effect, &Door::TryOpen }, - { &EV_Activate, &Door::TryOpen }, - { &EV_Door_TryOpen, &Door::TryOpen }, - { &EV_Door_Close, &Door::Close }, - { &EV_Door_Open, &Door::Open }, - { &EV_Door_CloseEnd, &Door::CloseEnd }, - { &EV_Door_OpenEnd, &Door::OpenEnd }, - { &EV_Door_Fire, &Door::DoorFire }, - { &EV_Door_Link, &Door::LinkDoors }, - { &EV_Door_SetTime, &Door::SetTime }, - { &EV_Use, &Door::DoorUse }, - { &EV_Killed, &Door::DoorFire }, - { &EV_Blocked, &Door::DoorBlocked }, - { &EV_Door_Lock, &Door::LockDoor }, - { &EV_Door_Unlock, &Door::UnlockDoor }, - { &EV_SetAngle, &Door::SetDir }, - { &EV_Door_TrySolid, &Door::EventTrySolid }, - { &EV_Door_AlwaysAway, &Door::EventAlwaysAway }, - { &EV_Door_DoorType, &Door::EventDoorType }, - { &EV_Touch, NULL }, - { NULL, NULL } +CLASS_DECLARATION(ScriptSlave, Door, "NormalDoor") { + {&EV_Door_OpenStartSound, &Door::SetOpenStartSound }, + {&EV_Door_OpenEndSound, &Door::SetOpenEndSound }, + {&EV_Door_CloseStartSound, &Door::SetCloseStartSound}, + {&EV_Door_CloseEndSound, &Door::SetCloseEndSound }, + {&EV_Door_MessageSound, &Door::SetMessageSound }, + {&EV_Door_LockedSound, &Door::SetLockedSound }, + {&EV_Door_SetWait, &Door::SetWait }, + {&EV_Door_SetDmg, &Door::SetDmg }, + {&EV_Door_TriggerFieldTouched, &Door::FieldTouched }, + {&EV_Trigger_Effect, &Door::TryOpen }, + {&EV_Activate, &Door::TryOpen }, + {&EV_Door_TryOpen, &Door::TryOpen }, + {&EV_Door_Close, &Door::Close }, + {&EV_Door_Open, &Door::Open }, + {&EV_Door_CloseEnd, &Door::CloseEnd }, + {&EV_Door_OpenEnd, &Door::OpenEnd }, + {&EV_Door_IsOpen, &Door::GetIsOpen }, // Added in 2.30 + {&EV_Door_Fire, &Door::DoorFire }, + {&EV_Door_Link, &Door::LinkDoors }, + {&EV_Door_SetTime, &Door::SetTime }, + {&EV_Use, &Door::DoorUse }, + {&EV_Killed, &Door::DoorFire }, + {&EV_Blocked, &Door::DoorBlocked }, + {&EV_Door_Lock, &Door::LockDoor }, + {&EV_Door_Unlock, &Door::UnlockDoor }, + {&EV_SetAngle, &Door::SetDir }, + {&EV_Door_TrySolid, &Door::EventTrySolid }, + {&EV_Door_AlwaysAway, &Door::EventAlwaysAway }, + {&EV_Door_DoorType, &Door::EventDoorType }, + {&EV_Touch, NULL }, + {NULL, NULL } }; Door::Door() - { - float t; - - entflags |= EF_DOOR; - if ( LoadingSavegame ) - { - return; - } - - nextdoor = 0; - trigger = 0; - locked = false; - master = this; - lastblocktime = 0; - diropened = 0; - m_bAlwaysAway = true; - - dir = G_GetMovedir( 0 ); - t = dir[ 0 ]; - dir[ 0 ] = -dir[ 1 ]; - dir[ 1 ] = t; - - showModel(); - - SetOpenStartSound( "door_wood_open_move" ); - SetOpenEndSound( "door_wood_open_stop" ); - - SetCloseStartSound( "door_wood_close_move" ); - SetCloseEndSound( "door_wood_close_stop" ); - - SetLockedSound( "door_wood_locked" ); - - traveltime = 1.0f; - speed = 1.0f / traveltime; - - wait = ( spawnflags & DOOR_TOGGLE ) ? 0 : 3; - dmg = 0; - - setSize( mins, maxs ); - - setOrigin( localorigin ); - - // DOOR_START_OPEN is to allow an entity to be lighted in the closed position - // but spawn in the open position - if ( spawnflags & DOOR_START_OPEN ) - { - state = STATE_OPEN; - PostEvent( EV_Door_Open, EV_POSTSPAWN ); - } - else - { - state = STATE_CLOSED; - } - previous_state = state; - - if ( health ) - { - takedamage = DAMAGE_YES; - } - - // LinkDoors can't be done until all of the doors have been spawned, so - // the sizes can be detected properly. - nextdoor = 0; - PostEvent( EV_Door_Link, EV_LINKDOORS ); - - // Default to work with monsters and players - respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS; - if ( spawnflags & 8 ) - { - respondto &= ~TRIGGER_PLAYERS; - } - if ( spawnflags & 16 ) - { - respondto &= ~TRIGGER_MONSTERS; - } - - next_locked_time = 0; - } - -void Door::SetDir( Event *ev ) { - float t; - float angle; + float t; - angle = ev->GetFloat( 1 ); - dir = G_GetMovedir( angle ); - t = dir[ 0 ]; - dir[ 0 ] = -dir[ 1 ]; - dir[ 1 ] = t; + entflags |= ECF_DOOR; + if (LoadingSavegame) { + return; + } + + nextdoor = 0; + trigger = 0; + locked = false; + master = this; + lastblocktime = 0; + diropened = 0; + m_bAlwaysAway = true; + + dir = G_GetMovedir(0); + t = dir[0]; + dir[0] = -dir[1]; + dir[1] = t; + + showModel(); + + SetDoorType("wood"); + + wait = (spawnflags & DOOR_TOGGLE) ? 0 : 3; + dmg = 0; + + setSize(mins, maxs); + + setLocalOrigin(localorigin); + + // DOOR_START_OPEN is to allow an entity to be lighted in the closed position + // but spawn in the open position + if (spawnflags & DOOR_START_OPEN) { + state = STATE_OPEN; + PostEvent(EV_Door_Open, EV_POSTSPAWN); + } else { + state = STATE_CLOSED; + } + previous_state = state; + + if (health) { + takedamage = DAMAGE_YES; + } + + // LinkDoors can't be done until all of the doors have been spawned, so + // the sizes can be detected properly. + nextdoor = 0; + PostEvent(EV_Door_Link, EV_LINKDOORS); + + // Default to work with monsters and players + respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS; + if (spawnflags & 8) { + respondto &= ~TRIGGER_PLAYERS; + } + if (spawnflags & 16) { + respondto &= ~TRIGGER_MONSTERS; + } + + next_locked_time = 0; } -void Door::SetOpenStartSound( str sound ) +void Door::SetDoorType(str s) { - sound_open_start = sound; - if( sound_open_start.length() > 1 ) - { - CacheResource( sound_open_start.c_str() ); - } + SetOpenStartSound("door_" + s + "_open_move"); + SetOpenEndSound("door_" + s + "_open_stop"); + + SetCloseStartSound("door_" + s + "_close_move"); + SetCloseEndSound("door_" + s + "_close_stop"); + + SetLockedSound("door_" + s + "_locked"); + + if (s == "wood") { + traveltime = 1.0; + } else if (s == "metal") { + traveltime = 1.5; + } + + speed = 1.0 / traveltime; } -void Door::SetOpenEndSound( str sound ) +void Door::EventDoorType(Event *ev) { - sound_open_end = sound; - if( sound_open_end.length() > 1 ) - { - CacheResource( sound_open_end.c_str() ); - } + str s = ev->GetString(1); + + if (s != "wood" && s != "metal") { + ScriptError("Invalid Door Type."); + } + + SetDoorType(s); } -void Door::SetCloseStartSound( str sound ) +void Door::SetDir(Event *ev) { - sound_close_start = sound; - if( sound_close_start.length() > 1 ) - { - CacheResource( sound_close_start.c_str() ); - } + float t; + float angle; + + angle = ev->GetFloat(1); + dir = G_GetMovedir(angle); + t = dir[0]; + dir[0] = -dir[1]; + dir[1] = t; } -void Door::SetCloseEndSound( str sound ) +void Door::SetOpenStartSound(str sound) { - sound_close_end = sound; - if( sound_close_end.length() > 1 ) - { - CacheResource( sound_close_end.c_str() ); - } + sound_open_start = sound; + if (sound_open_start.length() > 1) { + CacheResource(sound_open_start.c_str()); + } } -void Door::SetMessageSound - ( - str sound - ) - - { - sound_message = sound; - if ( sound_message.length() > 1 ) - { - CacheResource( sound_message.c_str() ); - } - } - -void Door::SetLockedSound - ( - str sound - ) - - { - sound_locked = sound; - if ( sound_locked.length() > 1 ) - { - CacheResource( sound_locked.c_str() ); - } - } - -void Door::SetOpenStartSound( Event *ev ) +void Door::SetOpenEndSound(str sound) { - SetOpenStartSound( ev->GetString( 1 ) ); + sound_open_end = sound; + if (sound_open_end.length() > 1) { + CacheResource(sound_open_end.c_str()); + } } -void Door::SetOpenEndSound( Event *ev ) +void Door::SetCloseStartSound(str sound) { - SetOpenEndSound( ev->GetString( 1 ) ); + sound_close_start = sound; + if (sound_close_start.length() > 1) { + CacheResource(sound_close_start.c_str()); + } } -void Door::SetCloseStartSound( Event *ev ) +void Door::SetCloseEndSound(str sound) { - SetCloseStartSound( ev->GetString( 1 ) ); + sound_close_end = sound; + if (sound_close_end.length() > 1) { + CacheResource(sound_close_end.c_str()); + } } -void Door::SetCloseEndSound( Event *ev ) +void Door::SetMessageSound(str sound) + { - SetCloseEndSound( ev->GetString( 1 ) ); + sound_message = sound; + if (sound_message.length() > 1) { + CacheResource(sound_message.c_str()); + } } -void Door::SetMessageSound - ( - Event *ev - ) +void Door::SetLockedSound(str sound) { - SetMessageSound( ev->GetString( 1 ) ); + sound_locked = sound; + if (sound_locked.length() > 1) { + CacheResource(sound_locked.c_str()); + } } -void Door::SetLockedSound - ( - Event *ev - ) +void Door::SetOpenStartSound(Event *ev) { - SetLockedSound( ev->GetString( 1 ) ); + SetOpenStartSound(ev->GetString(1)); } -void Door::SetWait - ( - Event *ev - ) +void Door::SetOpenEndSound(Event *ev) { - wait = ev->GetFloat( 1 ); + SetOpenEndSound(ev->GetString(1)); } -void Door::SetDmg - ( - Event *ev - ) +void Door::SetCloseStartSound(Event *ev) { - dmg = ev->GetInteger( 1 ); + SetCloseStartSound(ev->GetString(1)); } -void Door::EventAlwaysAway - ( - Event *ev - ) +void Door::SetCloseEndSound(Event *ev) { - qboolean bAlwaysAway = true; - - if( ev->NumArgs() > 0 ) - bAlwaysAway = ev->GetInteger( 1 ); - - m_bAlwaysAway = bAlwaysAway != 0; + SetCloseEndSound(ev->GetString(1)); } -void Door::EventTrySolid - ( - Event *ev - ) +void Door::SetMessageSound(Event *ev) { - Entity *check; - gentity_t *ent; - int touch[ MAX_GENTITIES ]; - int num; - - if( edict->r.contents == 1 ) - return; - - num = gi.AreaEntities( absmin, absmax, touch, MAX_GENTITIES ); - if( num > 0 ) - { - for( int i = 0; i < num; i++ ) - { - ent = &g_entities[ touch[ i ] ]; - check = ent->entity; - - if( check->getMoveType() > MOVETYPE_STOP ) - { - if( edict->r.contents != CONTENTS_SHOOTONLY && - edict->solid && - IsTouching( check ) ) - { - PostEvent( EV_Door_TrySolid, 1.0f ); - return; - } - } - } - } - - edict->r.contents = CONTENTS_SOLID; - setSolidType( SOLID_BSP ); + SetMessageSound(ev->GetString(1)); } -void Door::EventDoorType - ( - Event *ev - ) +void Door::SetLockedSound(Event *ev) { - str s = ev->GetString( 1 ); - - if( s != "wood" && s != "metal" ) - { - ScriptError( "Invalid Door Type." ); - } - - SetOpenStartSound( "door_" + s + "_open_move" ); - SetOpenEndSound( "door_" + s + "_open_stop" ); - - SetCloseStartSound( "door_" + s + "_close_move" ); - SetCloseEndSound( "door_" + s + "_close_stop" ); - - SetLockedSound( "door_" + s + "_locked" ); + SetLockedSound(ev->GetString(1)); } -qboolean Door::isOpen - ( - void - ) +void Door::SetWait(Event *ev) { - return ( state == STATE_OPEN ); + wait = ev->GetFloat(1); } -qboolean Door::isCompletelyClosed - ( - void - ) +void Door::SetDmg(Event *ev) { - return ( state == STATE_CLOSED ); + dmg = ev->GetInteger(1); } -void Door::OpenEnd - ( - Event *ev - ) +void Door::EventAlwaysAway(Event *ev) { - if( edict->r.contents != CONTENTS_SOLID ) - { - PostEvent( EV_Door_TrySolid, 1.0f ); - } + qboolean bAlwaysAway = true; - if( sound_open_end.length() > 1 ) - { - BroadcastAIEvent(); - Sound( sound_open_end, CHAN_VOICE ); - } - else - { - StopSound( CHAN_VOICE ); - } + if (ev->NumArgs() > 0) { + bAlwaysAway = ev->GetInteger(1); + } - previous_state = state; - SetState( STATE_OPEN ); - if( spawnflags & DOOR_TOGGLE ) - { - // don't close automatically - return; - } - - if( ( wait > 0 ) && ( master == this ) ) - { - PostEvent( EV_Door_Close, wait ); - } + m_bAlwaysAway = bAlwaysAway != 0; } -void Door::CloseEnd - ( - Event *ev - ) +void Door::EventTrySolid(Event *ev) { - if( sound_close_end.length() > 1 ) - { - BroadcastAIEvent(); - Sound( sound_close_end, CHAN_VOICE ); - } - else - { - StopSound( CHAN_VOICE ); - } + Entity *check; + gentity_t *ent; + int touch[MAX_GENTITIES]; + int num; - if( master == this ) - { - gi.AdjustAreaPortalState( this->edict, false ); - } + if (getContents() == 1) { + return; + } - edict->r.contents = CONTENTS_SOLID; - setSolidType( SOLID_BSP ); + num = gi.AreaEntities(absmin, absmax, touch, MAX_GENTITIES); + if (num > 0) { + for (int i = 0; i < num; i++) { + ent = &g_entities[touch[i]]; + check = ent->entity; - previous_state = state; - SetState( STATE_CLOSED ); -} - -void Door::Close - ( - Event *ev - ) -{ - Door *door; - - CancelEventsOfType( EV_Door_Close ); - - previous_state = state; - SetState( STATE_CLOSING ); - - ProcessEvent( EV_Door_DoClose ); - - if( sound_close_start.length() > 1 ) - { - BroadcastAIEvent(); - Sound( sound_close_start, CHAN_VOICE ); - } - if( master == this ) - { - if( max_health ) - { - takedamage = DAMAGE_YES; - health = max_health; - } - - // trigger all paired doors - door = ( Door * )G_GetEntity( nextdoor ); - assert( door->isSubclassOf( Door ) ); - while( door && ( door != this ) ) - { - door->ProcessEvent( EV_Door_Close ); - door = ( Door * )G_GetEntity( door->nextdoor ); - assert( door->isSubclassOf( Door ) ); - } - } -} - -void Door::Open - ( - Event *ev - ) -{ - Door *door; - Event *e; - Entity *other; - - if( ev->NumArgs() < 1 ) - { - ScriptError( "No entity specified to open door. Door may open the wrong way." ); - other = world; - } - else - { - other = ev->GetEntity( 1 ); - } - - if( state == STATE_OPENING ) - { - // already going up - return; - } - - if( state == STATE_OPEN ) - { - // reset top wait time - if( wait > 0 ) - { - CancelEventsOfType( EV_Door_Close ); - PostEvent( EV_Door_Close, wait ); - } - return; - } - - previous_state = state; - SetState( STATE_OPENING ); - - e = new Event( EV_Door_DoOpen ); - e->AddEntity( other ); - ProcessEvent( e ); - - if( sound_open_start.length() > 1 ) - { - BroadcastAIEvent(); - Sound( sound_open_start, CHAN_VOICE ); - } - if( master == this ) - { - // trigger all paired doors - door = ( Door * )G_GetEntity( nextdoor ); - assert( door->isSubclassOf( Door ) ); - while( door && ( door != this ) ) - { - e = new Event( EV_Door_Open ); - e->AddEntity( other ); - door->ProcessEvent( e ); - door = ( Door * )G_GetEntity( door->nextdoor ); - assert( door->isSubclassOf( Door ) ); - } - - if( previous_state == STATE_CLOSED ) - { - gi.AdjustAreaPortalState( this->edict, true ); - } - } -} - -void Door::DoorUse - ( - Event *ev - ) - - { - Entity *other; - qboolean respond; - Event *e; - - other = ev->GetEntity( 1 ); - - respond = ( ( ( respondto & TRIGGER_PLAYERS ) && other->isClient() ) || - ( ( respondto & TRIGGER_MONSTERS ) && other->isSubclassOf( Actor ) ) ); - - if ( !respond ) - { - return; - } - - // only allow use when not triggerd by other events - if ( health || ( spawnflags & ( DOOR_AUTO_OPEN | DOOR_TARGETED ) ) ) - { - if ( other->isSubclassOf( Sentient ) && ( state == STATE_CLOSED ) ) - { - if ( health ) - { - gi.SendServerCommand( 0, "print \"This door is jammed.\"" ); + if (check->getMoveType() != MOVETYPE_NONE + && check->getMoveType() != MOVETYPE_NOCLIP + && check->getMoveType() != MOVETYPE_PUSH + && check->getMoveType() != MOVETYPE_STOP) { + if (edict->r.contents != CONTENTS_SHOOTONLY && edict->solid && IsTouching(check)) { + PostEvent(EV_Door_TrySolid, 1.0f); + return; + } } - else if ( spawnflags & DOOR_TARGETED ) - { - Sound( "door_triggered", CHAN_VOICE ); - } - } + } + } - if ( spawnflags & DOOR_AUTO_OPEN && locked && other->isSubclassOf( Player ) && sound_locked.length() ) - { - other->Sound( sound_locked, CHAN_VOICE ); - } - - return; - } - - assert( master ); - if ( !master ) - { - // bulletproofing - master = this; - } - - if ( master->state == STATE_CLOSED ) - { - e = new Event( EV_Door_TryOpen ); - e->AddEntity( other ); - master->ProcessEvent( e ); - } - else if ( master->state == STATE_OPEN ) - { - e = new Event( EV_Door_Close ); - e->AddEntity( other ); - master->ProcessEvent( e ); - } - } - -void Door::DoorFire - ( - Event *ev - ) - - { - Event *e; - Entity *other; - - other = ev->GetEntity( 1 ); - - assert( master == this ); - if ( master != this ) - { - gi.Error( ERR_DROP, "DoorFire: master != self" ); - } - - // no more messages - SetMessage( NULL ); - - // reset health in case we were damage triggered - health = max_health; - - // will be reset upon return - takedamage = DAMAGE_NO; - - if ( ( spawnflags & ( DOOR_TOGGLE | DOOR_START_OPEN ) ) && ( state == STATE_OPENING || state == STATE_OPEN ) ) - { - spawnflags &= ~DOOR_START_OPEN; - ProcessEvent( EV_Door_Close ); - } - else - { - e = new Event( EV_Door_Open ); - e->AddEntity( other ); - ProcessEvent( e ); - } - } - -void Door::DoorBlocked - ( - Event *ev - ) -{ - Event *e; - Entity *other; - - assert( master ); - if( ( master ) && ( master != this ) ) - { - master->ProcessEvent( new Event( ev ) ); - return; - } - - if( lastblocktime > level.time ) - { - return; - } - - lastblocktime = level.time + 0.3; - - other = ev->GetEntity( 1 ); - - if( other->IsSubclassOfActor() ) - { - edict->r.contents = CONTENTS_WEAPONCLIP; - setSolidType( SOLID_BSP ); - } - else - { - if( dmg ) - { - other->Damage( this, this, ( int )dmg, origin, vec_zero, vec_zero, 0, 0, MOD_CRUSH ); - } - - // - // if we killed him, lets keep on going - // - if( other->deadflag ) - { - return; - } - - if( state == STATE_OPENING || state == STATE_OPEN ) - { - spawnflags &= ~DOOR_START_OPEN; - ProcessEvent( EV_Door_Close ); - } - else - { - e = new Event( EV_Door_Open ); - e->AddEntity( other ); - ProcessEvent( e ); - } - } + setContents(CONTENTS_SOLID); + setSolidType(SOLID_BSP); } -void Door::FieldTouched - ( - Event *ev - ) - - { - Entity *other; - - other = ev->GetEntity( 1 ); - - if ( !other ) - return; - - if ( ( state != STATE_OPEN ) && !( spawnflags & DOOR_AUTO_OPEN ) && !other->isSubclassOf( Actor ) ) - return; - - TryOpen( ev ); - } - -qboolean Door::CanBeOpenedBy - ( - Entity *ent - ) - - { - assert( master ); - if ( ( master ) && ( master != this ) ) - { - return master->CanBeOpenedBy( ent ); - } - - if ( !locked ) - { - return true; - } - - return false; - } - -void Door::TryOpen - ( - Event *ev - ) - - { - Entity *other; - Event *event; - - //FIXME - // hack so that doors aren't triggered by guys when game starts. - // have to fix delay that guys go through before setting up their threads - if ( level.time < 0.4 ) - { - return; - } - - other = ev->GetEntity( 1 ); - - assert( master ); - if ( master && ( this != master ) ) - { - event = new Event( EV_Door_TryOpen ); - event->AddEntity( other ); - master->ProcessEvent( event ); - return; - } - - if ( !other || other->deadflag ) - { - return; - } - - if ( locked ) - { - if ( next_locked_time <= level.time ) - { - if ( sound_locked.length() > 1 && !other->isSubclassOf( Actor ) ) - { - other->Sound( sound_locked, CHAN_VOICE ); - } - else if ( other->isSubclassOf( Player ) ) - { - other->Sound( "snd_locked", CHAN_VOICE ); - // gi.centerprintf ( other->edict, "This door is locked." ); - } - } - - // Always increment next locked time - - next_locked_time = level.time + 0.5; - - // locked doors don't open for anyone - return; - } - - if ( !CanBeOpenedBy( other ) ) - { - return; - } - - if ( Message().length() ) - { - gi.centerprintf( other->edict, Message().c_str() ); - Sound( sound_message, CHAN_VOICE ); - } - - event = new Event( EV_Door_Fire ); - event->AddEntity( other ); - ProcessEvent( event ); - } - -void Door::SpawnTriggerField - ( - Vector fmins, - Vector fmaxs - ) - - { - TouchField *trig; - Vector min; - Vector max; - - min = fmins - Vector( "60 60 8" ); - max = fmaxs + Vector( "60 60 8" ); - - trig = new TouchField; - trig->Setup( this, EV_Door_TriggerFieldTouched, min, max, respondto ); - - trigger = trig->entnum; - } - - - -void Door::LinkDoors - ( - Event *ev - ) +qboolean Door::isOpen(void) { - Entity *entptr; - Door *ent; - Door *next; - Vector cmins; - Vector cmaxs; - int iNumTouching; - int i; + return (state == STATE_OPEN); +} - setSolidType( SOLID_BSP ); - setMoveType( MOVETYPE_PUSH ); +qboolean Door::isCompletelyClosed(void) +{ + return (state == STATE_CLOSED); +} - if( nextdoor ) - { - // already linked by another door - return; - } +void Door::GetIsOpen(Event *ev) +{ + ev->AddInteger(!isCompletelyClosed()); +} - // master doors own themselves - master = this; +void Door::OpenEnd(Event *ev) +{ + if (getContents() != CONTENTS_SOLID) { + PostEvent(EV_Door_TrySolid, 1.0f); + } - if( spawnflags & DOOR_DONT_LINK ) - { - // don't want to link this door - nextdoor = entnum; - return; - } - iNumTouching = 0; + if (sound_open_end.length() > 1) { + BroadcastAIEvent(); + Sound(sound_open_end, CHAN_VOICE); + } else { + StopSound(CHAN_VOICE); + } + + // Added in 2.30 + // Notify scripts that the door has finished opening + Unregister(STRING_DONE); - for (ent = this; ent; ent = (Door *)G_FindClass(ent, getClassID())) - { - if (DoorTouches(ent) && ent != this) - { - iNumTouching++; - } - } + previous_state = state; + SetState(STATE_OPEN); + if (spawnflags & DOOR_TOGGLE) { + // don't close automatically + return; + } - if (!iNumTouching) - { - for (ent = (Door *)G_FindClass(NULL, getClassID()); ent; ent = (Door *)G_FindClass(ent, getClassID())) - { - if (DoorTouches(ent) && ent != this) - { - iNumTouching++; - } + if ((wait > 0) && (master == this)) { + PostEvent(EV_Door_Close, wait); + } +} + +void Door::CloseEnd(Event *ev) +{ + // Fixed in 2.0 + // Since this version, the area portal state is changed before sound + if (master == this) { + gi.AdjustAreaPortalState(this->edict, false); + } + + if (sound_close_end.length() > 1) { + BroadcastAIEvent(); + Sound(sound_close_end, CHAN_VOICE); + } else { + StopSound(CHAN_VOICE); + } + + setContents(CONTENTS_SOLID); + setSolidType(SOLID_BSP); + + previous_state = state; + SetState(STATE_CLOSED); + + // Added in 2.30 + // Notify scripts that the door has finished closing + Unregister(STRING_DONE); +} + +void Door::Close(Event *ev) +{ + Door *door; + + if (!(getContents() & CONTENTS_SOLID)) { + CancelEventsOfType(EV_Door_TrySolid); + PostEvent(EV_Door_TrySolid, 0); + // try again + PostEvent(new Event(*ev), 0.1f); + return; + } + + CancelEventsOfType(EV_Door_Close); + + previous_state = state; + SetState(STATE_CLOSING); + + ProcessEvent(EV_Door_DoClose); + + if (sound_close_start.length() > 1) { + BroadcastAIEvent(); + Sound(sound_close_start, CHAN_VOICE); + } else { + StopSound(CHAN_VOICE); + } + + if (master == this) { + if (max_health) { + takedamage = DAMAGE_YES; + health = max_health; } - if (iNumTouching != 0) - { + // trigger all paired doors + door = (Door *)G_GetEntity(nextdoor); + assert(door->isSubclassOf(Door)); + while (door && (door != this)) { + door->ProcessEvent(EV_Door_Close); + door = (Door *)G_GetEntity(door->nextdoor); + assert(door->isSubclassOf(Door)); + } + } +} + +void Door::Open(Event *ev) +{ + Door *door; + Event *e; + Entity *other; + + if (ev->NumArgs() < 1) { + ScriptError("No entity specified to open door. Door may open the wrong way."); + other = world; + } else { + other = ev->GetEntity(1); + } + + if (state == STATE_OPENING) { + // already going up + return; + } + + if (state == STATE_OPEN) { + // reset top wait time + if (wait > 0) { + CancelEventsOfType(EV_Door_Close); + PostEvent(EV_Door_Close, wait); + } + return; + } + + previous_state = state; + SetState(STATE_OPENING); + + e = new Event(EV_Door_DoOpen); + e->AddEntity(other); + ProcessEvent(e); + + if (sound_open_start.length() > 1) { + BroadcastAIEvent(); + Sound(sound_open_start, CHAN_VOICE); + } else { + StopSound(CHAN_VOICE); + } + + if (master == this) { + // trigger all paired doors + door = (Door *)G_GetEntity(nextdoor); + assert(door->isSubclassOf(Door)); + while (door && (door != this)) { + e = new Event(EV_Door_Open); + e->AddEntity(other); + door->ProcessEvent(e); + door = (Door *)G_GetEntity(door->nextdoor); + assert(door->isSubclassOf(Door)); + } + + if (previous_state == STATE_CLOSED) { + gi.AdjustAreaPortalState(this->edict, true); + } + } +} + +void Door::DoorUse(Event *ev) + +{ + Entity *other; + qboolean respond; + Event *e; + + other = ev->GetEntity(1); + + respond = + (((respondto & TRIGGER_PLAYERS) && other->isClient()) + || ((respondto & TRIGGER_MONSTERS) && other->IsSubclassOfActor())); + + if (!respond) { + return; + } + + // only allow use when not triggerd by other events + if (health || (spawnflags & (DOOR_AUTO_OPEN | DOOR_TARGETED)) || other->IsSubclassOfActor()) { + if (other->IsSubclassOfSentient() && (state == STATE_CLOSED)) { + if (health) { + gi.SendServerCommand(other->edict - g_entities, "print \"%s.\"", gi.LV_ConvertString("This door is jammed")); + } else if (spawnflags & DOOR_TARGETED) { + Sound("door_triggered", CHAN_VOICE); + } + } + + if (spawnflags & DOOR_AUTO_OPEN && locked && other->IsSubclassOfPlayer() && sound_locked.length()) { + other->Sound(sound_locked, CHAN_VOICE); + } + + return; + } + + assert(master); + if (!master) { + // bulletproofing + master = this; + } + + if (master->state == STATE_CLOSED) { + e = new Event(EV_Door_TryOpen); + e->AddEntity(other); + master->ProcessEvent(e); + } else if (master->state == STATE_OPEN) { + e = new Event(EV_Door_Close); + e->AddEntity(other); + master->ProcessEvent(e); + } +} + +void Door::DoorFire(Event *ev) +{ + Event *e; + Entity *other; + + other = ev->GetEntity(1); + + assert(master == this); + if (master != this) { + gi.Error(ERR_DROP, "DoorFire: master != self"); + } + + // no more messages + SetMessage(NULL); + + // reset health in case we were damage triggered + health = max_health; + + // will be reset upon return + takedamage = DAMAGE_NO; + + if ((spawnflags & (DOOR_TOGGLE | DOOR_START_OPEN)) && (state == STATE_OPENING || state == STATE_OPEN)) { + spawnflags &= ~DOOR_START_OPEN; + ProcessEvent(EV_Door_Close); + } else { + e = new Event(EV_Door_Open); + e->AddEntity(other); + ProcessEvent(e); + } +} + +void Door::DoorBlocked(Event *ev) +{ + Event *e; + Entity *other; + + assert(master); + if ((master) && (master != this)) { + master->ProcessEvent(*ev); + return; + } + + if (lastblocktime > level.time) { + return; + } + + lastblocktime = level.time + 0.3; + + other = ev->GetEntity(1); + + if (other->IsSubclassOfActor()) { + setContents(CONTENTS_WEAPONCLIP); + setSolidType(SOLID_BSP); + } else { + if (dmg) { + other->Damage(this, this, (int)dmg, origin, vec_zero, vec_zero, 0, 0, MOD_CRUSH); + } + + // + // if we killed him, lets keep on going + // + if (other->deadflag) { return; } - } - cmins = absmin; - cmaxs = absmax; + if (state == STATE_OPENING || state == STATE_OPEN) { + spawnflags &= ~DOOR_START_OPEN; - ent = this; - for( entptr = this; entptr; entptr = ( Entity * )G_FindClass( entptr, getClassID() ) ) - { - next = ( Door * )entptr; - if( !ent->DoorTouches( next ) ) - { - continue; - } + const bool bIsMoving = EventPending(EV_MoveDone); + ProcessEvent(EV_Door_Close); - if( next->nextdoor ) - { - error( "Door::LinkDoors", "cross connected doors. Targetname = %s entity %d\n", TargetName().c_str(), entnum ); - } - - ent->nextdoor = next->entnum; - ent = next; - - for( i = 0; i < 3; i++ ) - { - if( ent->absmin[ i ] < cmins[ i ] ) - { - cmins[ i ] = ent->absmin[ i ]; - } - if( ent->absmax[ i ] > cmaxs[ i ] ) - { - cmaxs[ i ] = ent->absmax[ i ]; - } - } - - // set master door - ent->master = this; - - if( ent->health ) - { - health = ent->health; - } - - if( ent->Targeted() ) - { - if( !Targeted() ) - { - SetTargetName( ent->TargetName() ); - } - else if( strcmp( TargetName(), ent->TargetName() ) ) - { - // not a critical error, but let them know about it. - gi.DPrintf( "cross connected doors\n" ); - - ent->SetTargetName( TargetName() ); - } - } - - if( ent->Message().length() ) - { - if( Message().length() && !strcmp( Message().c_str(), ent->Message().c_str() ) ) - { - // not a critical error, but let them know about it. - gi.DPrintf( "Different messages on linked doors. Targetname = %s", TargetName().c_str() ); - } - - // only master should have a message - SetMessage( ent->Message().c_str() ); - ent->SetMessage( NULL ); - } - } - - // make the chain a loop - ent->nextdoor = entnum; - - // open up any portals we control - if( spawnflags & DOOR_START_OPEN ) - { - gi.AdjustAreaPortalState( this->edict, true ); - } - - // shootable or targeted doors don't need a trigger - if( health || ( spawnflags & DOOR_TARGETED ) ) - { - // Don't let the player trigger the door - return; - } - - // Don't spawn trigger field when set to toggle - if( !( spawnflags & DOOR_TOGGLE ) ) - { - SpawnTriggerField( cmins, cmaxs ); - } + if (bIsMoving) { + // Added in OPM + // Reopen to the other side so sentients can still pass. + // This avoid entities like players trying to prevent the door + // from opening in multiplayer + diropened = -diropened; + e = new Event(EV_Door_Open); + e->AddEntity(other); + ProcessEvent(e); + } + } else { + e = new Event(EV_Door_Open); + e->AddEntity(other); + ProcessEvent(e); + } + } } -void Door::SetTime - ( - Event *ev - ) - - { - traveltime = ev->GetFloat( 1 ); - if ( traveltime < FRAMETIME ) - { - traveltime = FRAMETIME; - } - - speed = 1.0f / traveltime; - } - -void Door::LockDoor - ( - Event *ev - ) +void Door::FieldTouched(Event *ev) { - if( !level.PreSpawned() ) - ScriptError( "Cannot lock door before level prespawn" ); + Entity *other; + Actor* otherActor; + float dist; - SetLocked( true ); + other = ev->GetEntity(1); + + if (!other) { + return; + } + + if (!other->IsSubclassOfActor()) { + if ((spawnflags & DOOR_TOGGLE) || (state != STATE_OPEN && !(spawnflags & DOOR_AUTO_OPEN))) { + return; + } + + TryOpen(ev); + return; + } + + otherActor = static_cast(other); + + otherActor->m_Path.ForceShortLookahead(); + + if (state == STATE_OPENING) { + otherActor->m_maxspeed = speed * 64; + } + + if (((spawnflags & DOOR_TOGGLE) || (state != STATE_OPEN && !(spawnflags & DOOR_AUTO_OPEN))) && (state == STATE_OPEN || state == STATE_OPENING)) { + return; + } + + dist = VectorLength2D(other->velocity) * 0.25f; + if (other->absmin[0] > absmax[0] + dist) { + return; + } + if (other->absmin[1] > absmax[1] + dist) { + return; + } + if (other->absmin[2] > absmax[2]) { + return; + } + + if (other->absmax[0] < absmin[0] - dist) { + return; + } + if (other->absmax[1] < absmin[1] - dist) { + return; + } + if (other->absmax[2] < absmin[2]) { + return; + } + + TryOpen(ev); } -void Door::UnlockDoor - ( - Event *ev - ) +qboolean Door::CanBeOpenedBy(Entity *ent) { - SetLocked( false ); + assert(master); + if ((master) && (master != this)) { + return master->CanBeOpenedBy(ent); + } + + if (!locked) { + return true; + } + + return false; } -qboolean Door::DoorTouches - ( - Door *e1 - ) +void Door::TryOpen(Event *ev) { - if( e1->absmin.x > absmax.x ) - { - return false; - } - if( e1->absmin.y > absmax.y ) - { - return false; - } - if( e1->absmin.z > absmax.z ) - { - return false; - } - if( e1->absmax.x < absmin.x ) - { - return false; - } - if( e1->absmax.y < absmin.y ) - { - return false; - } - if( e1->absmax.z < absmin.z ) - { - return false; - } + Entity *other; + Event *event; - return true; + // hack so that doors aren't triggered by guys when game starts. + // have to fix delay that guys go through before setting up their threads + if (level.time < 0.4) { + return; + } + + other = ev->GetEntity(1); + + assert(master); + if (master && (this != master)) { + event = new Event(EV_Door_TryOpen); + event->AddEntity(other); + master->ProcessEvent(event); + return; + } + + if (!other || other->deadflag) { + return; + } + + if (locked) { + if (next_locked_time <= level.time) { + if (sound_locked.length() > 1 && !other->IsSubclassOfActor()) { + other->Sound(sound_locked, CHAN_VOICE); + } else if (other->IsSubclassOfPlayer()) { + other->Sound("snd_locked", CHAN_VOICE); + // gi.centerprintf ( other->edict, "This door is locked." ); + } + } + + // Always increment next locked time + + next_locked_time = level.time + 0.5; + + // locked doors don't open for anyone + return; + } + + if (!CanBeOpenedBy(other)) { + return; + } + + if (Message().length()) { + gi.centerprintf(other->edict, Message().c_str()); + Sound(sound_message, CHAN_VOICE); + } + + event = new Event(EV_Door_Fire); + event->AddEntity(other); + ProcessEvent(event); } -void Door::UpdatePathConnection - ( - void - ) +void Door::SpawnTriggerField(Vector fmins, Vector fmaxs) { - if( BlocksAIMovement() ) - { - DisconnectPaths(); - } - else - { - ConnectPaths(); - } + TouchField *trig; + Vector min; + Vector max; + + min = fmins - Vector("60 60 8"); + max = fmaxs + Vector("60 60 8"); + + trig = new TouchField; + trig->Setup(this, EV_Door_TriggerFieldTouched, min, max, respondto); + + trigger = trig->entnum; } -void Door::SetLocked - ( - qboolean newLocked - ) +void Door::LinkDoors(Event *ev) { - if( locked == newLocked ) - return; + Entity *entptr; + Door *ent; + Door *next; + Vector cmins; + Vector cmaxs; + int iNumTouching; + int i; - locked = newLocked; + setSolidType(SOLID_BSP); + setMoveType(MOVETYPE_PUSH); - UpdatePathConnection(); + if (nextdoor) { + // already linked by another door + return; + } + + // master doors own themselves + master = this; + + if (spawnflags & DOOR_DONT_LINK) { + // don't want to link this door + nextdoor = entnum; + return; + } + iNumTouching = 0; + + for (ent = this; ent; ent = (Door *)G_FindClass(ent, getClassID())) { + if (DoorTouches(ent) && ent != this) { + iNumTouching++; + } + } + + if (!iNumTouching) { + for (ent = (Door *)G_FindClass(NULL, getClassID()); ent; ent = (Door *)G_FindClass(ent, getClassID())) { + if (DoorTouches(ent) && ent != this) { + iNumTouching++; + } + } + + if (iNumTouching != 0) { + return; + } + } + + cmins = absmin; + cmaxs = absmax; + + ent = this; + for (entptr = this; entptr; entptr = (Entity *)G_FindClass(entptr, getClassID())) { + next = (Door *)entptr; + if (!ent->DoorTouches(next)) { + continue; + } + + if (next->nextdoor) { + error( + "Door::LinkDoors", "cross connected doors. Targetname = %s entity %d\n", TargetName().c_str(), entnum + ); + } + + ent->nextdoor = next->entnum; + ent = next; + + for (i = 0; i < 3; i++) { + if (ent->absmin[i] < cmins[i]) { + cmins[i] = ent->absmin[i]; + } + if (ent->absmax[i] > cmaxs[i]) { + cmaxs[i] = ent->absmax[i]; + } + } + + // set master door + ent->master = this; + + if (ent->health) { + health = ent->health; + } + + if (ent->Targeted()) { + if (!Targeted()) { + SetTargetName(ent->TargetName()); + } else if (strcmp(TargetName(), ent->TargetName())) { + // not a critical error, but let them know about it. + gi.DPrintf("cross connected doors\n"); + + ent->SetTargetName(TargetName()); + } + } + + if (ent->Message().length()) { + if (Message().length() && !strcmp(Message().c_str(), ent->Message().c_str())) { + // not a critical error, but let them know about it. + gi.DPrintf("Different messages on linked doors. Targetname = %s", TargetName().c_str()); + } + + // only master should have a message + SetMessage(ent->Message().c_str()); + ent->SetMessage(NULL); + } + } + + // make the chain a loop + ent->nextdoor = entnum; + + // open up any portals we control + if (spawnflags & DOOR_START_OPEN) { + gi.AdjustAreaPortalState(this->edict, true); + } + + // shootable or targeted doors don't need a trigger + if (health || (spawnflags & DOOR_TARGETED)) { + // Don't let the player trigger the door + return; + } + + SpawnTriggerField(cmins, cmaxs); } -void Door::SetState - ( - int newState - ) +void Door::SetTime(Event *ev) { - if( state == newState ) - return; + traveltime = ev->GetFloat(1); + if (traveltime < FRAMETIME) { + traveltime = FRAMETIME; + } - state = newState; - - UpdatePathConnection(); + speed = 1.0f / traveltime; } -qboolean Door::BlocksAIMovement - ( - void - ) const +void Door::LockDoor(Event *ev) { - return ( locked || state == STATE_OPEN ); + if (!level.PreSpawned()) { + ScriptError("Cannot lock door before level prespawn"); + } + + SetLocked(true); } -qboolean Door::AIDontFace - ( - void - ) const +void Door::UnlockDoor(Event *ev) { - return ( locked || state == STATE_OPEN ); + SetLocked(false); +} + +qboolean Door::DoorTouches(Door *e1) +{ + if (e1->absmin.x > absmax.x) { + return false; + } + if (e1->absmin.y > absmax.y) { + return false; + } + if (e1->absmin.z > absmax.z) { + return false; + } + if (e1->absmax.x < absmin.x) { + return false; + } + if (e1->absmax.y < absmin.y) { + return false; + } + if (e1->absmax.z < absmin.z) { + return false; + } + + return true; +} + +void Door::UpdatePathConnection(void) +{ + if (BlocksAIMovement()) { + DisconnectPaths(); + } else { + ConnectPaths(); + } +} + +void Door::SetLocked(qboolean newLocked) +{ + if (locked == newLocked) { + return; + } + + locked = newLocked; + + UpdatePathConnection(); +} + +void Door::SetState(int newState) +{ + if (state == newState) { + return; + } + + state = newState; + + UpdatePathConnection(); +} + +qboolean Door::BlocksAIMovement(void) const +{ + return (locked || state == STATE_OPEN); +} + +qboolean Door::AIDontFace(void) const +{ + return (locked || state == STATE_OPEN); +} + +static const char* stateString[4] = +{ + "open", + "opening", + "closing", + "closed" +}; + +void Door::ShowInfo(float fDot, float fDist) +{ + int i; + char szText[512]; + + if (fDot <= 0.95f || fDist >= 1024 || fDist <= 64) { + return; + } + + i = Com_sprintf(szText, sizeof(szText), "%i:%i", entnum, radnum); + if (TargetName().c_str() && TargetName()[0]) { + i = Com_sprintf(szText + i, sizeof(szText) - i, ":%s", TargetName().c_str()); + } + + if (health != 0) { + i = Com_sprintf(szText + i, sizeof(szText) - i, ":%.1f", health); + } + + G_DebugString(origin + Vector(0, 0, (mins.z + maxs.z) * 0.5f), 1, 1, 1, 1, szText); + G_DebugString(origin + Vector(0, 0, (mins.z + maxs.z) * 0.5f + 18), 1, 1, 1, 1, stateString[state - 1]); } /*****************************************************************************/ @@ -1370,125 +1282,108 @@ TARGETED door is only operational from triggers or script ******************************************************************************/ Event EV_RotatingDoor_OpenAngle - ( - "openangle", - EV_DEFAULT, - "f", - "open_angle", - "Sets the open angle of the door.", - EV_NORMAL - ); +( + "openangle", + EV_DEFAULT, + "f", + "open_angle", + "Sets the open angle of the door.", + EV_NORMAL +); -CLASS_DECLARATION( Door, RotatingDoor, "func_rotatingdoor" ) -{ - { &EV_Door_DoClose, &RotatingDoor::DoClose }, - { &EV_Door_DoOpen, &RotatingDoor::DoOpen }, - { &EV_RotatingDoor_OpenAngle, &RotatingDoor::OpenAngle }, - { NULL, NULL } +CLASS_DECLARATION(Door, RotatingDoor, "func_rotatingdoor") { + {&EV_Door_DoClose, &RotatingDoor::DoClose }, + {&EV_Door_DoOpen, &RotatingDoor::DoOpen }, + {&EV_RotatingDoor_OpenAngle, &RotatingDoor::OpenAngle}, + {NULL, NULL } }; -void RotatingDoor::DoOpen( Event *ev ) +void RotatingDoor::DoOpen(Event *ev) { - Vector ang; + Vector ang; - if( previous_state == STATE_CLOSED ) - { - if( ev->NumArgs() > 0 ) - { - Entity *other; - Vector p; + if (previous_state == STATE_CLOSED) { + if (ev->NumArgs() > 0) { + Entity *other; + Vector p; - other = ev->GetEntity( 1 ); + other = ev->GetEntity(1); - if( other ) - { - Vector vMMOrigin ( mins + maxs ); - Vector vMMCenter = vMMOrigin * 0.5f; - Vector vDoorDir; - Vector vPerpDir; + if (other) { + Vector vMMOrigin(mins + maxs); + Vector vMMCenter = vMMOrigin * 0.5f; + Vector vDoorDir; + Vector vPerpDir; - vMMOrigin = vMMOrigin - vMMCenter; - vMMOrigin.normalize(); + vMMOrigin = vMMOrigin - vMMCenter; + vMMOrigin.normalize(); - vDoorDir[ 0 ] = dir[ 1 ]; - vDoorDir[ 1 ] = -dir[ 0 ]; - vDoorDir[ 2 ] = dir[ 2 ]; + vDoorDir[0] = dir[1]; + vDoorDir[1] = -dir[0]; + vDoorDir[2] = dir[2]; - p = other->origin - origin; + p = other->origin - origin; - vPerpDir = p; - vPerpDir[ 2 ] = 0.f; - vPerpDir.normalize(); + vPerpDir = p; + vPerpDir[2] = 0.f; + vPerpDir.normalize(); - if( m_bAlwaysAway ) - { - diropened = DotProduct( vPerpDir, vDoorDir ); + if (m_bAlwaysAway) { + diropened = DotProduct(vPerpDir, vDoorDir); - if( DotProduct( dir, vMMOrigin ) > 0.0f ) { - diropened = -diropened; - } - } - else - { - diropened = DotProduct( dir, vMMOrigin ); - } - } - else - { - ScriptError( "Door trying to be opened with a NULL entity." ); - } - } - else - { - diropened = 0 - init_door_direction; - } - } - else - { - diropened = -init_door_direction; - } + if (DotProduct(dir, vMMOrigin) > 0.0f) { + diropened = -diropened; + } + } else { + diropened = DotProduct(dir, vMMOrigin); + } + } else { + ScriptError("Door trying to be opened with a NULL entity."); + } + } else { + diropened = 0 - init_door_direction; + } + } - if( diropened < 0.0f ) - { - ang = startangle + Vector( 0.0f, angle, 0.0f ); - } - else - { - ang = startangle - Vector( 0.0f, angle, 0.0f ); - } + if (diropened < 0.0f) { + ang = startangle + Vector(0.0f, angle, 0.0f); + } else { + ang = startangle - Vector(0.0f, angle, 0.0f); + } - MoveTo( origin, ang, fabs( speed*angle ), EV_Door_OpenEnd ); + if (localangles.yaw() + 360 <= ang.yaw()) { + localangles.setYaw(localangles.yaw() + 360); + } else if (localangles.yaw() - 360 >= ang.yaw()) { + localangles.setYaw(localangles.yaw() - 360); + } + + MoveTo(origin, ang, fabs(speed * angle), EV_Door_OpenEnd); + + setContents(CONTENTS_SOLID); + setSolidType(SOLID_BSP); } -void RotatingDoor::DoClose - ( - Event *ev - ) +void RotatingDoor::DoClose(Event *ev) { - MoveTo( origin, startangle, fabs( speed*angle ), EV_Door_CloseEnd ); + MoveTo(origin, startangle, fabs(speed * angle), EV_Door_CloseEnd); } -void RotatingDoor::OpenAngle - ( - Event *ev - ) - - { - angle = ev->GetFloat( 1 ); - } +void RotatingDoor::OpenAngle(Event *ev) +{ + angle = ev->GetFloat(1); +} RotatingDoor::RotatingDoor() - { - if ( LoadingSavegame ) - { - return; - } - startangle = angles; +{ + if (LoadingSavegame) { + return; + } + startangle = angles; - angle = 90; + angle = 90; - init_door_direction = (spawnflags & DOOR_OPEN_DIRECTION); - } + init_door_direction = (spawnflags & DOOR_OPEN_DIRECTION); +} /*****************************************************************************/ /*QUAKED func_door (0 0.25 0.5) ? START_OPEN x DOOR_DONT_LINK NOT_PLAYERS NOT_MONSTERS TOGGLE AUTO_OPEN TARGETED @@ -1521,129 +1416,107 @@ TARGETED door is only operational from triggers or script ******************************************************************************/ Event EV_SlidingDoor_Setup - ( - "setup", - EV_CODEONLY, - NULL, - NULL, - "Sets up the sliding door.", - EV_NORMAL - ); +( + "setup", + EV_CODEONLY, + NULL, + NULL, + "Sets up the sliding door.", + EV_NORMAL +); Event EV_SlidingDoor_SetLip - ( - "lip", - EV_DEFAULT, - "f", - "lip", - "Sets the lip of the sliding door.", - EV_NORMAL - ); +( + "lip", + EV_DEFAULT, + "f", + "lip", + "Sets the lip of the sliding door.", + EV_NORMAL +); Event EV_SlidingDoor_SetSpeed - ( - "speed", - EV_DEFAULT, - "f", - "speed", - "Sets the speed of the sliding door.", - EV_NORMAL - ); +( + "speed", + EV_DEFAULT, + "f", + "speed", + "Sets the speed of the sliding door.", + EV_NORMAL +); -CLASS_DECLARATION( Door, SlidingDoor, "func_door" ) - { - { &EV_Door_DoClose, &SlidingDoor::DoClose }, - { &EV_Door_DoOpen, &SlidingDoor::DoOpen }, - { &EV_SlidingDoor_Setup, &SlidingDoor::Setup }, - { &EV_SlidingDoor_SetLip, &SlidingDoor::SetLip }, - { &EV_SlidingDoor_SetSpeed, &SlidingDoor::SetSpeed }, - { &EV_SetAngle, &SlidingDoor::SetMoveDir }, - { NULL, NULL } - }; +CLASS_DECLARATION(Door, SlidingDoor, "func_door") { + {&EV_Door_DoClose, &SlidingDoor::DoClose }, + {&EV_Door_DoOpen, &SlidingDoor::DoOpen }, + {&EV_SlidingDoor_Setup, &SlidingDoor::Setup }, + {&EV_SlidingDoor_SetLip, &SlidingDoor::SetLip }, + {&EV_SlidingDoor_SetSpeed, &SlidingDoor::SetSpeed }, + {&EV_SetAngle, &SlidingDoor::SetMoveDir}, + {NULL, NULL } +}; -void SlidingDoor::SetMoveDir - ( - Event *ev - ) +void SlidingDoor::SetMoveDir(Event *ev) - { - float t; - float angle; +{ + float t; + float angle; - angle = ev->GetFloat( 1 ); - movedir = G_GetMovedir( angle ); - dir = movedir; - t = dir[ 0 ]; - dir[ 0 ] = -dir[ 1 ]; - dir[ 1 ] = t; - } + angle = ev->GetFloat(1); + movedir = G_GetMovedir(angle); + dir = movedir; + t = dir[0]; + dir[0] = -dir[1]; + dir[1] = t; +} -void SlidingDoor::DoOpen - ( - Event *ev - ) +void SlidingDoor::DoOpen(Event *ev) +{ + MoveTo(pos2, angles, speed * totalmove, EV_Door_OpenEnd); +} - { - MoveTo( pos2, angles, speed*totalmove, EV_Door_OpenEnd ); - } +void SlidingDoor::DoClose(Event *ev) -void SlidingDoor::DoClose - ( - Event *ev - ) +{ + MoveTo(pos1, angles, speed * totalmove, EV_Door_CloseEnd); +} - { - MoveTo( pos1, angles, speed*totalmove, EV_Door_CloseEnd ); - } +void SlidingDoor::SetLip(Event *ev) -void SlidingDoor::SetLip - ( - Event *ev - ) +{ + lip = ev->GetFloat(1); + CancelEventsOfType(EV_SlidingDoor_Setup); + PostEvent(EV_SlidingDoor_Setup, EV_POSTSPAWN); +} - { - lip = ev->GetFloat( 1 ); - CancelEventsOfType( EV_SlidingDoor_Setup ); - PostEvent( EV_SlidingDoor_Setup, EV_POSTSPAWN ); - } +void SlidingDoor::SetSpeed(Event *ev) -void SlidingDoor::SetSpeed - ( - Event *ev - ) +{ + basespeed = ev->GetFloat(1); + CancelEventsOfType(EV_SlidingDoor_Setup); + PostEvent(EV_SlidingDoor_Setup, EV_POSTSPAWN); +} - { - basespeed = ev->GetFloat( 1 ); - CancelEventsOfType( EV_SlidingDoor_Setup ); - PostEvent( EV_SlidingDoor_Setup, EV_POSTSPAWN ); - } +void SlidingDoor::Setup(Event *ev) -void SlidingDoor::Setup - ( - Event *ev - ) +{ + totalmove = fabs(movedir * size) - lip; + pos1 = origin; + pos2 = pos1 + movedir * totalmove; - { - totalmove = fabs( movedir * size ) - lip; - pos1 = origin; - pos2 = pos1 + movedir * totalmove; - - if ( basespeed ) - { - speed = basespeed / totalmove; - } - } + if (basespeed) { + speed = basespeed / totalmove; + } +} SlidingDoor::SlidingDoor() - { - if ( LoadingSavegame ) - { - return; - } - lip = 8; - basespeed = 0; - movedir = G_GetMovedir( 0 ); +{ + if (LoadingSavegame) { + return; + } + lip = 8; + basespeed = 0; + movedir = G_GetMovedir(0); - PostEvent( EV_SlidingDoor_Setup, EV_POSTSPAWN ); - } + PostEvent(EV_SlidingDoor_Setup, EV_POSTSPAWN); +} /*****************************************************************************/ /*QUAKED script_door (0 0.5 1) ? START_OPEN x DOOR_DONT_LINK NOT_PLAYERS NOT_MONSTERS TOGGLE AUTO_OPEN TARGETED @@ -1680,169 +1553,140 @@ TARGETED door is only operational from triggers or script ******************************************************************************/ Event EV_ScriptDoor_DoInit - ( - "doinit", - EV_DEFAULT, - NULL, - NULL, - "Sets up the script door.", - EV_NORMAL - ); +( + "doinit", + EV_DEFAULT, + NULL, + NULL, + "Sets up the script door.", + EV_NORMAL +); Event EV_ScriptDoor_SetOpenThread - ( - "openthread", - EV_DEFAULT, - "s", - "openthread", - "Set the thread to run when the door is opened (required).", - EV_NORMAL - ); +( + "openthread", + EV_DEFAULT, + "s", + "openthread", + "Set the thread to run when the door is opened (required).", + EV_NORMAL +); Event EV_ScriptDoor_SetCloseThread - ( - "closethread", - EV_DEFAULT, - "s", - "closethread", - "Set the thread to run when the door is closed (required).", - EV_NORMAL - ); +( + "closethread", + EV_DEFAULT, + "s", + "closethread", + "Set the thread to run when the door is closed (required).", + EV_NORMAL +); Event EV_ScriptDoor_SetInitThread - ( - "initthread", - EV_DEFAULT, - "s", - "initthread", - "Set the thread to run when the door is initialized (optional).", - EV_NORMAL - ); +( + "initthread", + EV_DEFAULT, + "s", + "initthread", + "Set the thread to run when the door is initialized (optional).", + EV_NORMAL +); -CLASS_DECLARATION( Door, ScriptDoor, "script_door" ) - { - { &EV_ScriptDoor_DoInit, &ScriptDoor::DoInit }, - { &EV_Door_DoClose, &ScriptDoor::DoClose }, - { &EV_Door_DoOpen, &ScriptDoor::DoOpen }, - { &EV_ScriptDoor_SetInitThread, &ScriptDoor::SetInitThread }, - { &EV_ScriptDoor_SetOpenThread, &ScriptDoor::SetOpenThread }, - { &EV_ScriptDoor_SetCloseThread, &ScriptDoor::SetCloseThread }, - { &EV_SetAngle, &ScriptDoor::SetMoveDir }, - { NULL, NULL } - }; +CLASS_DECLARATION(Door, ScriptDoor, "script_door") { + {&EV_ScriptDoor_DoInit, &ScriptDoor::DoInit }, + {&EV_Door_DoClose, &ScriptDoor::DoClose }, + {&EV_Door_DoOpen, &ScriptDoor::DoOpen }, + {&EV_ScriptDoor_SetInitThread, &ScriptDoor::SetInitThread }, + {&EV_ScriptDoor_SetOpenThread, &ScriptDoor::SetOpenThread }, + {&EV_ScriptDoor_SetCloseThread, &ScriptDoor::SetCloseThread}, + {&EV_SetAngle, &ScriptDoor::SetMoveDir }, + {NULL, NULL } +}; -void ScriptDoor::SetMoveDir - ( - Event *ev - ) +void ScriptDoor::SetMoveDir(Event *ev) - { - float t; - float angle; +{ + float t; + float angle; - angle = ev->GetFloat( 1 ); - movedir = G_GetMovedir( angle ); - dir = movedir; - t = dir[ 0 ]; - dir[ 0 ] = -dir[ 1 ]; - dir[ 1 ] = t; - } + angle = ev->GetFloat(1); + movedir = G_GetMovedir(angle); + dir = movedir; + t = dir[0]; + dir[0] = -dir[1]; + dir[1] = t; +} -void ScriptDoor::SetOpenThread - ( - Event *ev - ) - { - openlabel.SetThread( ev->GetValue( 1 ) ); - } +void ScriptDoor::SetOpenThread(Event *ev) +{ + openlabel.SetThread(ev->GetValue(1)); +} -void ScriptDoor::SetCloseThread - ( - Event *ev - ) - { - closelabel.SetThread( ev->GetValue( 1 ) ); - } +void ScriptDoor::SetCloseThread(Event *ev) +{ + closelabel.SetThread(ev->GetValue(1)); +} -void ScriptDoor::DoInit - ( - Event *ev - ) - { - startorigin = origin; - doorsize = fabs( movedir * size ); +void ScriptDoor::DoInit(Event *ev) +{ + startorigin = origin; + doorsize = fabs(movedir * size); - if( initlabel.IsSet() ) - { - initlabel.Execute( this ); - } - } + if (initlabel.IsSet()) { + initlabel.Execute(this); + } +} -void ScriptDoor::DoOpen - ( - Event *ev - ) +void ScriptDoor::DoOpen(Event *ev) +{ + if (openlabel.IsSet()) { + openlabel.Execute(this); + } - { - if( openlabel.IsSet() ) - { - openlabel.Execute( this ); - } + if (previous_state == STATE_CLOSED) { + diropened = 0; + if (ev->NumArgs() > 0) { + Entity *other; + Vector p; - if ( previous_state == STATE_CLOSED ) - { - diropened = 0; - if ( ev->NumArgs() > 0 ) - { - Entity *other; - Vector p; + other = ev->GetEntity(1); + p = other->origin - origin; + p.z = 0; + diropened = dir * p; + } + } +} - other = ev->GetEntity( 1 ); - p = other->origin - origin; - p.z = 0; - diropened = dir * p; - } - } - } +void ScriptDoor::DoClose(Event *ev) +{ + if (closelabel.IsSet()) { + closelabel.Execute(this); + } +} -void ScriptDoor::DoClose - ( - Event *ev - ) - { - if( closelabel.IsSet() ) - { - closelabel.Execute( this ); - } - } +void ScriptDoor::SetInitThread(Event *ev) -void ScriptDoor::SetInitThread - ( - Event *ev - ) - - { - initlabel.SetThread( ev->GetValue( 1 ) ); - } +{ + initlabel.SetThread(ev->GetValue(1)); +} ScriptDoor::ScriptDoor() { - AddWaitTill(STRING_OPEN); - AddWaitTill(STRING_CLOSE); + AddWaitTill(STRING_OPEN); + AddWaitTill(STRING_CLOSE); - if ( LoadingSavegame ) - { - return; - } - startangle = angles; + if (LoadingSavegame) { + return; + } + startangle = angles; - // - // clear out the sounds if necessary - // scripted doors typically have their own sounds - // - sound_open_start = ""; - sound_open_end = ""; - sound_close_start = ""; - sound_close_end = ""; + // + // clear out the sounds if necessary + // scripted doors typically have their own sounds + // + sound_open_start = ""; + sound_open_end = ""; + sound_close_start = ""; + sound_close_end = ""; - movedir = G_GetMovedir( 0 ); + movedir = G_GetMovedir(0); - PostEvent( EV_ScriptDoor_DoInit, EV_POSTSPAWN ); + PostEvent(EV_ScriptDoor_DoInit, EV_POSTSPAWN); } diff --git a/code/fgame/doors.h b/code/fgame/doors.h index 076df7e1..588028d5 100644 --- a/code/fgame/doors.h +++ b/code/fgame/doors.h @@ -22,10 +22,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // doors.h: Doors are environment objects that slide open when activated by triggers // or when used by the player. -// +// -#ifndef __DOORS_H__ -#define __DOORS_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -48,219 +47,208 @@ class Door; typedef SafePtr DoorPtr; class Door : public ScriptSlave - { - protected: - str sound_open_start; - str sound_open_end; - str sound_close_start; - str sound_close_end; - str sound_message; - str sound_locked; - float lastblocktime; - float angle; - Vector dir; - float diropened; - int state; - int previous_state; - int trigger; - int nextdoor; - DoorPtr master; - float next_locked_time; - bool m_bAlwaysAway; +{ +protected: + str sound_open_start; + str sound_open_end; + str sound_close_start; + str sound_close_end; + str sound_message; + str sound_locked; + float lastblocktime; + float angle; + Vector dir; + float diropened; + int state; + int previous_state; + int trigger; + int nextdoor; + DoorPtr master; + float next_locked_time; + bool m_bAlwaysAway; - void SetDir( Event *ev ); - void OpenEnd( Event *ev ); - void CloseEnd( Event *ev ); - void Close( Event *ev ); - void Open( Event *ev ); - void DoorUse( Event *ev ); - void DoorFire( Event *ev ); - void DoorBlocked( Event *ev ); - void FieldTouched( Event *ev ); - void TryOpen( Event *ev ); - void SpawnTriggerField( Vector fmins, Vector fmaxs ); - qboolean DoorTouches( Door *e1 ); - void LinkDoors( Event *ev ); - void SetTime( Event *ev ); - void LockDoor( Event *ev ); - void UnlockDoor( Event *ev ); - void SetOpenStartSound( str sound ); - void SetOpenStartSound( Event *ev ); - void SetOpenEndSound( str sound ); - void SetOpenEndSound( Event *ev ); - void SetCloseStartSound( Event *ev ); - void SetCloseStartSound( str sound ); - void SetCloseEndSound( Event *ev ); - void SetCloseEndSound( str sound ); - void SetMessageSound( str sound ); - void SetMessageSound( Event *ev ); - void SetLockedSound( str sound ); - void SetLockedSound( Event *ev ); - void SetWait( Event *ev ); - void SetDmg( Event *ev ); - void EventTrySolid( Event *ev ); - void EventAlwaysAway( Event *ev ); - void EventDoorType( Event *ev ); + void SetDir(Event *ev); + void OpenEnd(Event *ev); + void CloseEnd(Event *ev); + void Close(Event *ev); + void Open(Event *ev); + void DoorUse(Event *ev); + void DoorFire(Event *ev); + void DoorBlocked(Event *ev); + void FieldTouched(Event *ev); + void TryOpen(Event *ev); + void SpawnTriggerField(Vector fmins, Vector fmaxs); + qboolean DoorTouches(Door *e1); + void LinkDoors(Event *ev); + void SetTime(Event *ev); + void LockDoor(Event *ev); + void UnlockDoor(Event *ev); + void SetOpenStartSound(str sound); + void SetOpenStartSound(Event *ev); + void SetOpenEndSound(str sound); + void SetOpenEndSound(Event *ev); + void SetCloseStartSound(Event *ev); + void SetCloseStartSound(str sound); + void SetCloseEndSound(Event *ev); + void SetCloseEndSound(str sound); + void SetMessageSound(str sound); + void SetMessageSound(Event *ev); + void SetLockedSound(str sound); + void SetLockedSound(Event *ev); + void SetWait(Event *ev); + void SetDmg(Event *ev); + void EventTrySolid(Event *ev); + void EventAlwaysAway(Event *ev); + void EventDoorType(Event *ev); - qboolean BlocksAIMovement( void ) const override; - qboolean AIDontFace( void ) const override; + void SetDoorType(str s); + qboolean BlocksAIMovement(void) const override; + qboolean AIDontFace(void) const override; + void ShowInfo(float fDot, float fDist) override; - void UpdatePathConnection( void ); - void SetLocked( qboolean newLocked ); - void SetState( int newState ); + void UpdatePathConnection(void); + void SetLocked(qboolean newLocked); + void SetState(int newState); - public: - CLASS_PROTOTYPE( Door ); +public: + CLASS_PROTOTYPE(Door); - qboolean locked; + qboolean locked; - Door(); - qboolean isOpen( void ); - qboolean isCompletelyClosed( void ); - qboolean CanBeOpenedBy( Entity *ent ); - void Archive( Archiver &arc ) override; - }; + Door(); + qboolean isOpen(void); + qboolean isCompletelyClosed(void); + void GetIsOpen(Event *ev); // Added in 2.30 + qboolean CanBeOpenedBy(Entity *ent); + void Archive(Archiver &arc) override; +}; -inline void Door::Archive - ( - Archiver &arc - ) - { - ScriptSlave::Archive( arc ); +inline void Door::Archive(Archiver& arc) +{ + ScriptSlave::Archive(arc); - arc.ArchiveString( &sound_open_start ); - arc.ArchiveString( &sound_open_end ); - arc.ArchiveString( &sound_close_start ); - arc.ArchiveString( &sound_close_end ); - arc.ArchiveString( &sound_message ); - arc.ArchiveString( &sound_locked ); - if ( arc.Loading() ) - { - SetOpenStartSound( sound_open_start ); - SetOpenEndSound( sound_open_end ); - SetCloseStartSound( sound_close_start ); - SetCloseEndSound( sound_close_end ); - SetMessageSound( sound_message ); - SetLockedSound( sound_locked ); - } - arc.ArchiveFloat( &lastblocktime ); - arc.ArchiveFloat( &angle ); - arc.ArchiveVector( &dir ); - arc.ArchiveFloat( &diropened ); - arc.ArchiveInteger( &state ); - arc.ArchiveInteger( &previous_state ); - arc.ArchiveInteger( &trigger ); - arc.ArchiveInteger( &nextdoor ); - arc.ArchiveSafePointer( &master ); - arc.ArchiveBoolean( &locked ); - arc.ArchiveFloat( &next_locked_time ); - } + arc.ArchiveString(&sound_open_start); + arc.ArchiveString(&sound_open_end); + arc.ArchiveString(&sound_close_start); + arc.ArchiveString(&sound_close_end); + arc.ArchiveString(&sound_message); + arc.ArchiveString(&sound_locked); + if (arc.Loading()) { + SetOpenStartSound(sound_open_start); + SetOpenEndSound(sound_open_end); + SetCloseStartSound(sound_close_start); + SetCloseEndSound(sound_close_end); + SetMessageSound(sound_message); + SetLockedSound(sound_locked); + } + arc.ArchiveFloat(&lastblocktime); + arc.ArchiveFloat(&angle); + arc.ArchiveVector(&dir); + arc.ArchiveFloat(&diropened); + arc.ArchiveInteger(&state); + arc.ArchiveInteger(&previous_state); + arc.ArchiveInteger(&trigger); + arc.ArchiveInteger(&nextdoor); + arc.ArchiveSafePointer(&master); + arc.ArchiveFloat(&next_locked_time); + arc.ArchiveBoolean(&locked); + arc.ArchiveBool(&m_bAlwaysAway); +} class RotatingDoor : public Door - { - protected: - float angle; - Vector startangle; - int init_door_direction; +{ +protected: + float angle; + Vector startangle; + int init_door_direction; - public: - CLASS_PROTOTYPE( RotatingDoor ); +public: + CLASS_PROTOTYPE(RotatingDoor); - void DoOpen( Event *ev ); - void DoClose( Event *ev ); - void OpenAngle( Event *ev ); - void Archive( Archiver &arc ) override; + void DoOpen(Event *ev); + void DoClose(Event *ev); + void OpenAngle(Event *ev); + void Archive(Archiver& arc) override; - RotatingDoor(); - }; + RotatingDoor(); +}; -inline void RotatingDoor::Archive - ( - Archiver &arc - ) - { - Door::Archive( arc ); +inline void RotatingDoor::Archive(Archiver& arc) +{ + Door::Archive(arc); - arc.ArchiveFloat( &angle ); - arc.ArchiveVector( &startangle ); - arc.ArchiveInteger( &init_door_direction ); - } + arc.ArchiveFloat(&angle); + arc.ArchiveVector(&startangle); + arc.ArchiveInteger(&init_door_direction); +} class SlidingDoor : public Door - { - protected: - float totalmove; - float lip; - Vector pos1; - Vector pos2; - float basespeed; - Vector movedir; +{ +protected: + float totalmove; + float lip; + Vector pos1; + Vector pos2; + float basespeed; + Vector movedir; - public: - CLASS_PROTOTYPE( SlidingDoor ); +public: + CLASS_PROTOTYPE(SlidingDoor); - void SetMoveDir( Event *ev ); - void Setup( Event *ev ); - void SetLip( Event *ev ); - void SetSpeed( Event *ev ); - void DoOpen( Event *ev ); - void DoClose( Event *ev ); - void Archive( Archiver &arc ) override; + void SetMoveDir(Event *ev); + void Setup(Event *ev); + void SetLip(Event *ev); + void SetSpeed(Event *ev); + void DoOpen(Event *ev); + void DoClose(Event *ev); + void Archive(Archiver& arc) override; - SlidingDoor(); - }; + SlidingDoor(); +}; -inline void SlidingDoor::Archive - ( - Archiver &arc - ) - { - Door::Archive( arc ); +inline void SlidingDoor::Archive(Archiver& arc) +{ + Door::Archive(arc); - arc.ArchiveFloat( &totalmove ); - arc.ArchiveFloat( &lip ); - arc.ArchiveVector( &pos1 ); - arc.ArchiveVector( &pos2 ); - arc.ArchiveVector( &movedir ); - arc.ArchiveFloat( &basespeed ); - } + arc.ArchiveFloat(&totalmove); + arc.ArchiveFloat(&lip); + arc.ArchiveVector(&pos1); + arc.ArchiveVector(&pos2); + arc.ArchiveVector(&movedir); + arc.ArchiveFloat(&basespeed); +} class ScriptDoor : public Door - { - protected: - ScriptThreadLabel initlabel; - ScriptThreadLabel openlabel; - ScriptThreadLabel closelabel; - float doorsize; - Vector startangle; - Vector startorigin; - Vector movedir; +{ +protected: + ScriptThreadLabel initlabel; + ScriptThreadLabel openlabel; + ScriptThreadLabel closelabel; + float doorsize; + Vector startangle; + Vector startorigin; + Vector movedir; - public: - CLASS_PROTOTYPE( ScriptDoor ); +public: + CLASS_PROTOTYPE(ScriptDoor); - void SetMoveDir( Event *ev ); - void DoInit( Event *ev ); - void DoOpen( Event *ev ); - void DoClose( Event *ev ); - void SetOpenThread( Event *ev ); - void SetCloseThread( Event *ev ); - void SetInitThread( Event *ev ); - void Archive( Archiver &arc ) override; - ScriptDoor(); - }; + void SetMoveDir(Event *ev); + void DoInit(Event *ev); + void DoOpen(Event *ev); + void DoClose(Event *ev); + void SetOpenThread(Event *ev); + void SetCloseThread(Event *ev); + void SetInitThread(Event *ev); + void Archive(Archiver& arc) override; + ScriptDoor(); +}; -inline void ScriptDoor::Archive - ( - Archiver &arc - ) - { - Door::Archive( arc ); +inline void ScriptDoor::Archive(Archiver& arc) +{ + Door::Archive(arc); - arc.ArchiveFloat( &doorsize ); - arc.ArchiveVector( &startangle ); - arc.ArchiveVector( &startorigin ); - arc.ArchiveVector( &movedir ); - } - -#endif /* doors.h */ + arc.ArchiveFloat(&doorsize); + arc.ArchiveVector(&startangle); + arc.ArchiveVector(&startorigin); + arc.ArchiveVector(&movedir); +} diff --git a/code/fgame/earthquake.cpp b/code/fgame/earthquake.cpp index 4d008b6a..835e5603 100644 --- a/code/fgame/earthquake.cpp +++ b/code/fgame/earthquake.cpp @@ -133,7 +133,7 @@ ViewJitter::ViewJitter() m_fDuration = 0; - m_bDoneDeath = qfalse; + m_bDoneDeath = false; } ViewJitter::ViewJitter( Vector vOrigin, float fRadius, float fEdgeEffect, Vector vStrength, float fDuration, Vector vTimeDecay, float fStartDecay ) @@ -154,7 +154,7 @@ ViewJitter::ViewJitter( Vector vOrigin, float fRadius, float fEdgeEffect, Vector m_fDuration = fDuration; - m_bDoneDeath = false; + m_bDoneDeath = true; m_fTimeRunning = 0; PostEvent( EV_ViewJitter_Think, fStartDecay ); diff --git a/code/fgame/earthquake.h b/code/fgame/earthquake.h index 98157027..0a6b1721 100644 --- a/code/fgame/earthquake.h +++ b/code/fgame/earthquake.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,8 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // The earthquake effect is visible to the user as the shaking of his screen. // -#ifndef __EARTHQUAKE_H__ -#define __EARTHQUAKE_H__ +#pragma once #include "g_local.h" #include "trigger.h" @@ -75,5 +74,3 @@ inline void ViewJitter::Archive arc.ArchiveBoolean( &m_bDoneDeath ); arc.ArchiveFloat( &m_fTimeRunning ); } - -#endif diff --git a/code/fgame/effectentity.h b/code/fgame/effectentity.h index 63c0c984..2379abee 100644 --- a/code/fgame/effectentity.h +++ b/code/fgame/effectentity.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // actor.cpp: Base class for character AI. -#ifndef __EFFECTENTITY_H__ -#define __EFFECTENTITY_H__ +#pragma once #include "animate.h" @@ -34,5 +33,3 @@ public: EffectEntity(); }; - -#endif // __EFFECTENTITY_H__ diff --git a/code/fgame/entity.cpp b/code/fgame/entity.cpp index 482d9a9a..6dfecf6b 100644 --- a/code/fgame/entity.cpp +++ b/code/fgame/entity.cpp @@ -58,6 +58,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "g_phys.h" #include "debuglines.h" #include +#include // Generic entity events Event EV_SoundDone( @@ -676,7 +677,7 @@ Event EV_GetMins NULL, NULL, "Get the mins of the bounding box of the entity to mins.", - EV_RETURN + EV_GETTER ); Event EV_GetMaxs ( @@ -685,7 +686,7 @@ Event EV_GetMaxs NULL, NULL, "Get the maxs of the bounding box of the entity to maxs.", - EV_RETURN + EV_GETTER ); Event EV_SetAlpha ( @@ -767,7 +768,7 @@ Event EV_SetLight EV_DEFAULT, "ffff", "red green blue radius", - "Create a dynmaic light on this entity.", + "Create a dynamic light on this entity.", EV_NORMAL ); @@ -777,7 +778,7 @@ Event EV_LightOn EV_DEFAULT, NULL, NULL, - "Turn the configured dynmaic light on this entity on.", + "Turn the configured dynamic light on this entity on.", EV_NORMAL ); Event EV_LightOff @@ -804,7 +805,7 @@ Event EV_LightRed EV_DEFAULT, "f", "red", - "Set the red component of the dynmaic light on this entity.", + "Set the red component of the dynamic light on this entity.", EV_NORMAL ); Event EV_LightGreen @@ -813,7 +814,7 @@ Event EV_LightGreen EV_DEFAULT, "f", "red", - "Set the red component of the dynmaic light on this entity.", + "Set the red component of the dynamic light on this entity.", EV_NORMAL ); Event EV_LightBlue @@ -822,7 +823,7 @@ Event EV_LightBlue EV_DEFAULT, "f", "red", - "Set the red component of the dynmaic light on this entity.", + "Set the red component of the dynamic light on this entity.", EV_NORMAL ); Event EV_LightRadius @@ -831,7 +832,7 @@ Event EV_LightRadius EV_DEFAULT, "f", "red", - "Set the red component of the dynmaic light on this entity.", + "Set the red component of the dynamic light on this entity.", EV_NORMAL ); @@ -1216,6 +1217,8 @@ Event EV_CanSee "returns 1 if the entities can see eachother, 0 if not", EV_RETURN ); + +// Added in 2.0 Event EV_CanSeeNoEnts ( "canseenoents", @@ -1225,6 +1228,7 @@ Event EV_CanSeeNoEnts "returns 1 if the entities can see eachother, 0 if not; ignores any entities between them", EV_RETURN ); + Event EV_Entity_InPVS ( "inpvs", @@ -1384,7 +1388,7 @@ Event EV_Entity_SinglePlayerCommand "sp", EV_DEFAULT, "sSSS", - "command parms", + "command parm1 parm2 ...", "Makes a command be executed only in single player", EV_NORMAL ); @@ -1393,7 +1397,7 @@ Event EV_Entity_MultiPlayerCommand "dm", EV_DEFAULT, "sSSS", - "command parms", + "command parm1 parm2 ...", "Makes a command be executed only in multiplayer", EV_NORMAL ); @@ -1402,7 +1406,7 @@ Event EV_Entity_RealismModeCommand "realism", EV_DEFAULT, "sSSS", - "command parms", + "command parm1 parm2 ...", "Makes a command be executed only in realism mode", EV_NORMAL ); @@ -1411,7 +1415,7 @@ Event EV_Entity_SPRealismModeCommand "sprealism", EV_DEFAULT, "sSSS", - "command parms", + "command parm1 parm2 ...", "Makes a command be executed only in single player realism mode", EV_NORMAL ); @@ -1420,7 +1424,7 @@ Event EV_Entity_DMRealismModeCommand "dmrealism", EV_DEFAULT, "sSSS", - "command parms", + "command parm1 parm2 ...", "Makes a command be executed only in multiplayer realism mode", EV_NORMAL ); @@ -1431,7 +1435,7 @@ Event EV_Entity_GetLocalYawFromVector NULL, NULL, "Turn a worldspace vector into a local space yaw", - EV_GETTER + EV_RETURN ); Event EV_ShootableOnly ( @@ -1470,6 +1474,7 @@ Event EV_Entity_SetDHack "Enable or disable depth hack.", EV_NORMAL ); +/* Event EV_Entity_GetZone ( "getzone", @@ -1497,6 +1502,8 @@ Event EV_Entity_IsInZone "Returns 1 if the entity is in the specified zone. 0 otherwise", EV_RETURN ); +*/ +#ifdef OPM_FEATURES Event EV_Entity_SetHintRequireLookAt ( "setuselookat", @@ -1525,6 +1532,7 @@ Event EV_Entity_SetShader "Sets a shader for the entity. An empty string will revert to the normal entity shader.", EV_NORMAL ); +#endif CLASS_DECLARATION(SimpleEntity, Entity, NULL) { {&EV_Damage, &Entity::DamageEvent }, @@ -1623,6 +1631,7 @@ CLASS_DECLARATION(SimpleEntity, Entity, NULL) { {&EV_IsTouching, &Entity::IsTouching }, {&EV_IsInside, &Entity::IsInside }, {&EV_CanSee, &Entity::CanSee }, + {&EV_CanSeeNoEnts, &Entity::CanSeeNoEnts }, // Added in 2.0 {&EV_Entity_InPVS, &Entity::EventInPVS }, {&EV_SetShaderData, &Entity::SetShaderData }, {&EV_GetVelocity, &Entity::GetVelocity }, @@ -1644,8 +1653,8 @@ CLASS_DECLARATION(SimpleEntity, Entity, NULL) { {&EV_ConnectPaths, &Entity::EventConnectPaths }, {&EV_DisconnectPaths, &Entity::EventDisconnectPaths }, {&EV_Remove, &Entity::Remove }, - {&EV_Delete, &Entity::Remove }, - {&EV_ScriptRemove, &Entity::Remove }, + {&EV_Delete, &Listener::ScriptRemove }, + {&EV_ScriptRemove, &Listener::ScriptRemove }, {&EV_VolumeDamage, &Entity::EventVolumeDamage }, {&EV_GetNormalHealth, &Entity::EventGetNormalHealth }, {&EV_NormalDamage, &Entity::EventNormalDamage }, @@ -1666,13 +1675,17 @@ CLASS_DECLARATION(SimpleEntity, Entity, NULL) { {&EV_ShootableOnly, &Entity::EventShootableOnly }, {&EV_SetShaderTime, &Entity::SetShaderTime }, {&EV_NoTarget, &Entity::NoTarget }, + /* {&EV_Entity_GetZone, &Entity::GetZone }, {&EV_Entity_Zone, &Entity::GetZone }, {&EV_Entity_IsInZone, &Entity::IsInZone }, + */ {&EV_Entity_SetDHack, &Entity::SetDepthHack }, +#ifdef OPM_FEATURES {&EV_Entity_SetHintRequireLookAt, &Entity::SetHintRequireLookAt }, {&EV_Entity_SetHintString, &Entity::SetHintString }, {&EV_Entity_SetShader, &Entity::SetShader }, +#endif {NULL, NULL } }; @@ -1685,7 +1698,7 @@ Entity::Entity() entnum = edict->s.number; radnum = -1; - entflags |= EF_ENTITY; + entflags |= ECF_ENTITY; AddWaitTill(STRING_DAMAGE); AddWaitTill(STRING_SPAWN); @@ -1712,7 +1725,7 @@ Entity::Entity() groundcontents = 0; velocity = vec_zero; avelocity = vec_zero; - edict->clipmask = MASK_USABLE; + edict->clipmask = MASK_SOLID; m_iNumGlues = 0; m_bGlueAngles = true; @@ -1778,10 +1791,9 @@ Entity::Entity() m_iNumBlockedPaths = 0; m_BlockedPaths = NULL; +#ifdef OPM_FEATURES m_bHintRequiresLookAt = true; - - // Misc - m_bBindChilds = false; +#endif } Entity::~Entity() @@ -1845,23 +1857,21 @@ Entity::~Entity() } if (m_BlockedPaths) { - delete m_BlockedPaths; - m_BlockedPaths = 0; + delete[] m_BlockedPaths; + m_BlockedPaths = NULL; } level.FreeEdict(edict); - entflags &= ~EF_ENTITY; + entflags &= ~ECF_ENTITY; } void Entity::ClassnameEvent(Event *ev) - { strncpy(edict->entname, ev->GetString(1), sizeof(edict->entname) - 1); } void Entity::SpawnFlagsEvent(Event *ev) - { // spawning variables spawnflags = ev->GetInteger(1); @@ -1987,27 +1997,28 @@ const char *Entity::getModel() const void Entity::setModel(const str& mdl) { - if (strcmp(mdl, "")) { - if (*mdl == '*') { - model = mdl; + int animnum; + int i; - gi.SetBrushModel(edict, mdl); - if ((edict->solid == SOLID_BSP) && !edict->s.modelindex) { - const char *name; + if (mdl != "" && mdl[0] == '*') { + model = mdl; - name = getClassID(); - if (!name) { - name = getClassname(); - } - gi.DPrintf("%s with SOLID_BSP and no model - '%s'(%d)\n", name, targetname.c_str(), entnum); + gi.SetBrushModel(edict, mdl); + if ((edict->solid == SOLID_BSP) && !edict->s.modelindex) { + const char* name; - // Make it non-solid so that the collision code doesn't kick us out. - setSolidType(SOLID_NOT); + name = getClassID(); + if (!name) { + name = getClassname(); } + gi.DPrintf("%s with SOLID_BSP and no model - '%s'(%d)\n", name, targetname.c_str(), entnum); - SetSize(); - return; + // Make it non-solid so that the collision code doesn't kick us out. + setSolidType(SOLID_NOT); } + + SetSize(); + return; } model = CanonicalTikiName(mdl); @@ -2020,42 +2031,32 @@ void Entity::setModel(const str& mdl) mins = vec_zero; maxs = vec_zero; - for (int i = 0; i < MAX_FRAMEINFOS; i++) { - edict->s.frameInfo[i].index = 0; - edict->s.frameInfo[i].time = 0; - edict->s.frameInfo[i].weight = 0; + // make sure to clear all frame infos when switching models + // so the entity doesn't end up with 'broken' animations + for (i = 0; i < MAX_FRAMEINFOS; i++) { + ClearAnimSlot(i); } - if (!strcmp(mdl, "")) { - mins = edict->r.mins; - maxs = edict->r.maxs; - - size = maxs - mins; - edict->r.radius = size.length() * 0.5f; - edict->radius2 = edict->r.radius * edict->r.radius; + if (mdl == "") { + SetSize(); return; } - edict->s.frameInfo[0].index = gi.Anim_NumForName(edict->tiki, "idle"); - if (edict->s.frameInfo[0].index < 0) { - edict->s.frameInfo[0].index = 0; + // search for the default idle animation + animnum = gi.Anim_NumForName(edict->tiki, "idle"); + if (animnum < 0) { + animnum = 0; } - edict->s.frameInfo[0].weight = 1.0f; - edict->s.frameInfo[0].time = 0; - + // play the default idle animation + StartAnimSlot(0, animnum, 1); + // process all TIKI init commands ProcessInitCommands(); - - mins = edict->r.mins; - maxs = edict->r.maxs; - - size = maxs - mins; - edict->r.radius = size.length() * 0.5f; - edict->radius2 = edict->r.radius * edict->r.radius; + SetSize(); if (edict->tiki && !mins.length() && !maxs.length()) { vec3_t tempmins, tempmaxs; - gi.CalculateBounds(edict->tiki, edict->s.scale, tempmins, tempmaxs); + gi.TIKI_CalculateBounds(edict->tiki, edict->s.scale, tempmins, tempmaxs); setSize(tempmins, tempmaxs); } } @@ -2097,7 +2098,7 @@ void Entity::ProcessInitCommands(void) int i, j; Event *event; for (i = 0; i < a->num_server_initcmds; i++) { - event = new Event(a->server_initcmds[i].args[0]); + event = new Event(a->server_initcmds[i].args[0], a->server_initcmds[i].num_args); for (j = 1; j < a->server_initcmds[i].num_args; j++) { event->AddToken(a->server_initcmds[i].args[j]); @@ -2134,49 +2135,21 @@ void Entity::SetTeamEvent(Event *ev) void Entity::TriggerEvent(Event *ev) { - const char *name; - Event *event; - Entity *ent; - ConSimple *tlist; - int i; - int num; + SimpleEntity *ent; + ScriptVariable arrayVar; + int i; - name = ev->GetString(1); - - // Check for object commands - if (name && name[0] == '$') { - str sName = str(name + 1); - - tlist = world->GetTargetList(sName); - num = tlist->NumObjects(); - for (i = 1; i <= num; i++) { - ent = (Entity *)tlist->ObjectAt(i).Pointer(); - - assert(ent); - - event = new Event(EV_Activate); + arrayVar = ev->GetValue(1); + arrayVar.CastConstArrayValue(); + for (i = arrayVar.arraysize(); i > 0; i--) { + const ScriptVariable *variable = arrayVar[i]; + ent = variable->simpleEntityValue(); + if (ent) { + Event* event = new Event(EV_Activate); event->AddEntity(this); ent->ProcessEvent(event); } - } else if (name[0] == '*') // Check for entnum commands - { - if (!IsNumeric(&name[1])) { - gi.Printf("Expecting numeric value for * command, but found '%s'\n", &name[1]); - } else { - ent = G_GetEntity(atoi(&name[1])); - if (ent) { - event = new Event(EV_Activate); - - event->AddEntity(this); - ent->ProcessEvent(event); - } else { - gi.Printf("Entity not found for * command\n"); - } - } - return; - } else { - gi.Printf("Invalid entity reference '%s'.\n", name); } } @@ -2269,7 +2242,7 @@ void Entity::setSize(Vector min, Vector max) vec3_t fullmins, fullmaxs; Vector delta; - gi.CalculateBounds(edict->tiki, edict->s.scale, fullmins, fullmaxs); + gi.TIKI_CalculateBounds(edict->tiki, edict->s.scale, fullmins, fullmaxs); delta = Vector(fullmaxs) - Vector(fullmins); edict->r.radius = delta.length() * 0.5; @@ -2298,7 +2271,7 @@ void Entity::link(void) absmin = edict->r.absmin; absmax = edict->r.absmax; centroid = (absmin + absmax) * 0.5; - centroid.copyTo(edict->r.currentOrigin); + centroid.copyTo(edict->r.centroid); // If this has a parent, then set the areanum the same // as the parent's @@ -2630,14 +2603,11 @@ qboolean Entity::droptofloor(float maxfall) trace = G_Trace(start, mins, maxs, end, this, edict->clipmask, false, "Entity::droptofloor"); if (trace.fraction == 1 || trace.startsolid || trace.allsolid || !trace.ent) { - groundentity = world->edict; return false; } setOrigin(trace.endpos); - groundentity = trace.ent; - return true; } @@ -2703,16 +2673,35 @@ void Entity::DamageEvent(Event *ev) Vector momentum; Vector position, direction, normal; int knockback, damageflags, meansofdeath, location; - Event *event; + Event event; float m; + EntityPtr This; - if ((takedamage == DAMAGE_NO) || (movetype == MOVETYPE_NOCLIP)) { + // Use a safe pointer because it might be deleted in Unregister + This = this; + + if ((takedamage == DAMAGE_NO) || (movetype == MOVETYPE_NOCLIP) || health <= 0) { return; } attacker = ev->GetEntity(1); damage = ev->GetInteger(2); inflictor = ev->GetEntity(3); + meansofdeath = ev->GetInteger(9); + + if (Immune(meansofdeath)) { + return; + } + + if (!attacker) { + ScriptError("attacker is NULL"); + return; + } + + if (!inflictor) { + ScriptError("inflictor is NULL"); + return; + } position = ev->GetVector(4); direction = ev->GetVector(5); @@ -2720,40 +2709,36 @@ void Entity::DamageEvent(Event *ev) knockback = ev->GetInteger(7); damageflags = ev->GetInteger(8); - meansofdeath = ev->GetInteger(9); location = ev->GetInteger(10); // figure momentum add if ((inflictor != world) && (movetype != MOVETYPE_NONE) && (movetype != MOVETYPE_STATIONARY) - && (movetype != MOVETYPE_BOUNCE) && (movetype != MOVETYPE_PUSH) && (movetype != MOVETYPE_STOP)) { + && (movetype != MOVETYPE_BOUNCE) && (movetype != MOVETYPE_PUSH) && (movetype != MOVETYPE_STOP) + && (movetype != MOVETYPE_VEHICLE)) { dir = origin - (inflictor->origin + (inflictor->mins + inflictor->maxs) * 0.5); dir.normalize(); - if (mass < 50) { - m = 50; + if (mass < 20) { + m = 20; } else { m = mass; } - momentum = dir * damage * (1700.0 / m); + momentum = dir * damage * (1000.0 / m); velocity += momentum; } - // check for godmode or invincibility - if (flags & FL_GODMODE) { - return; - } - - // team play damage avoidance - //if ( ( global->teamplay == 1 ) && ( edict->team > 0 ) && ( edict->team == attacker->edict->team ) ) - // { - // return; - // } - - if (!g_gametype->integer && IsSubclassOfPlayer()) { + if (!deathmatch->integer && IsSubclassOfPlayer()) { damage *= 0.15; } + // check for godmode or invincibility + if (!(flags & FL_GODMODE)) { + // do the damage + health -= damage; + } + + /* if (deadflag) { // Check for gib. if (inflictor->IsSubclassOfProjectile()) { @@ -2770,54 +2755,83 @@ void Entity::DamageEvent(Event *ev) return; } + */ - // do the damage - health -= damage; if (health <= 0) { if (attacker) { - event = new Event(EV_GotKill); - event->AddEntity(this); - event->AddInteger(damage); - event->AddEntity(inflictor); - event->AddInteger(meansofdeath); - event->AddInteger(0); + const EntityPtr attackerPtr = attacker; - attacker->ProcessEvent(event); + event = Event(EV_GotKill, 5); + event.AddEntity(this); + event.AddInteger(damage); + event.AddEntity(inflictor); + event.AddInteger(meansofdeath); + event.AddInteger(0); + + attackerPtr->ProcessEvent(event); + if (attackerPtr) { + attackerPtr->delegate_gotKill.Execute(event); + } } - event = new Event(EV_Killed); - event->AddEntity(attacker); - event->AddFloat(damage); - event->AddEntity(inflictor); - event->AddVector(position); - event->AddVector(direction); - event->AddVector(normal); - event->AddInteger(knockback); - event->AddInteger(damageflags); - event->AddInteger(meansofdeath); - event->AddInteger(location); + if (!This) { + return; + } + + event = Event(EV_Killed, 10); + event.AddEntity(attacker); + event.AddFloat(damage); + event.AddEntity(inflictor); + event.AddVector(position); + event.AddVector(direction); + event.AddVector(normal); + event.AddInteger(knockback); + event.AddInteger(damageflags); + event.AddInteger(meansofdeath); + event.AddInteger(location); ProcessEvent(event); + if (!This) { + return; + } + + // Notify scripts + Unregister(STRING_DAMAGE); + if (!This) { + return; + } + + delegate_killed.Execute(event); return; } - event = new Event(EV_Pain); - event->AddEntity(attacker); - event->AddFloat(damage); - event->AddEntity(inflictor); - event->AddVector(position); - event->AddVector(direction); - event->AddVector(normal); - event->AddInteger(knockback); - event->AddInteger(damageflags); - event->AddInteger(meansofdeath); - event->AddInteger(location); + event = Event(EV_Pain, 10); + event.AddEntity(attacker); + event.AddFloat(damage); + event.AddEntity(inflictor); + event.AddVector(position); + event.AddVector(direction); + event.AddVector(normal); + event.AddInteger(knockback); + event.AddInteger(damageflags); + event.AddInteger(meansofdeath); + event.AddInteger(location); ProcessEvent(event); + if (!This) { + return; + } + + // Notify scripts + Unregister(STRING_DAMAGE); + if (!This) { + return; + } + + delegate_damage.Execute(event); } qboolean Entity::IsTouching(Entity *e1) - { if (e1->absmin.x > absmax.x) { return false; @@ -2848,58 +2862,73 @@ qboolean Entity::IsInside(Entity *e1) qboolean Entity::FovCheck(float *delta, float fovdot) { - float deltadot = delta[0] * orientation[0][0] + delta[1] * orientation[0][1]; + float deltadot = DotProduct2D(delta, orientation[0]); if (fovdot < 0.0f) { if (deltadot >= 0.0f) { return true; } - return (delta[0] * delta[0] + delta[1] * delta[1]) * fovdot * fovdot > (deltadot * deltadot); + return VectorLength2DSquared(delta) * Square(fovdot) > Square(deltadot); } else { if (deltadot < 0.0f) { return false; } - return (deltadot * deltadot) > (delta[0] * delta[0] + delta[1] * delta[1]) * fovdot * fovdot; + return VectorLength2DSquared(delta) * Square(fovdot) < Square(deltadot); } } bool Entity::CanSee(Entity *ent, float fov, float vision_distance, bool bNoEnts) { - float delta[2]; + vec2_t delta; + int mask; - delta[0] = ent->centroid[0] - centroid[0]; - delta[1] = ent->centroid[1] - centroid[1]; + VectorSub2D(ent->centroid, centroid, delta); - if ((vision_distance <= 0.0f) - || (delta[0] * delta[0] + delta[1] * delta[1]) <= (vision_distance * vision_distance)) { - if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum) - && ((fov <= 0.0f || fov >= 360.0f) || (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0)))))) { - return G_SightTrace( - centroid, vec_zero, vec_zero, ent->centroid, this, ent, MASK_CANSEE, 0, "Entity::CanSee" - ); - } + if (vision_distance > 0 && Square(vision_distance) < VectorLength2DSquared(delta)) { + return false; } - return false; + if (!AreasConnected(ent)) { + return false; + } + + if (fov > 0 && fov < 360 && !FovCheck(delta, cos(DEG2RAD(fov / 2.f)))) { + return false; + } + + if (bNoEnts) { + mask = MASK_CANSEE_NOENTS; + } else { + mask = MASK_CANSEE; + } + + return G_SightTrace(centroid, vec_zero, vec_zero, ent->centroid, this, ent, mask, qfalse, "Sentient::CanSee"); } bool Entity::CanSee(const Vector& org, float fov, float vision_distance, bool bNoEnts) { - float delta[2]; + vec2_t delta; + int mask; - delta[0] = org[0] - centroid[0]; - delta[1] = org[1] - centroid[1]; + VectorSub2D(org, centroid, delta); - if ((vision_distance <= 0.0f) - || (delta[0] * delta[0] + delta[1] * delta[1]) <= (vision_distance * vision_distance)) { - if ((fov <= 0.0f || fov >= 360.0f) || (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0))))) { - return G_SightTrace(centroid, vec_zero, vec_zero, org, this, NULL, MASK_CANSEE, 0, "Entity::CanSee"); - } + if (vision_distance > 0 && Square(vision_distance) < VectorLength2DSquared(delta)) { + return false; } - return false; + if (fov > 0 && fov < 360 && !FovCheck(delta, cos(DEG2RAD(fov / 2.f)))) { + return false; + } + + if (bNoEnts) { + mask = MASK_CANSEE_NOENTS; + } else { + mask = MASK_CANSEE; + } + + return G_SightTrace(centroid, vec_zero, vec_zero, org, this, NULL, mask, qfalse, "Sentient::CanSee"); } void Entity::FadeNoRemove(Event *ev) @@ -2983,7 +3012,6 @@ void Entity::FadeIn(Event *ev) if (ev->NumArgs() > 0) { rate = ev->GetFloat(1); - assert(rate); if (rate > 0) { rate = FRAMETIME / rate; } @@ -3019,7 +3047,6 @@ void Entity::Fade(Event *ev) if (ev->NumArgs() > 0) { rate = ev->GetFloat(1); - assert(rate); if (rate > 0) { rate = FRAMETIME / rate; } @@ -3076,7 +3103,7 @@ void Entity::Sink(Event *ev) } if (target < myalpha) { - Event *event = new Event(ev); + Event *event = new Event(std::move(*ev)); PostEvent(event, FRAMETIME); } @@ -3184,6 +3211,15 @@ void Entity::LoopSound(Event *ev) return; } + if (level.spawning) { + // If the server is currently spawning + // repost the event as loopsound wouldn't work properly + // on the client + Event* newev = new Event(*ev); + PostEvent(newev, level.frametime); + return; + } + // Get parameters sound_name = ev->GetString(1); @@ -3234,10 +3270,10 @@ void Entity::LoopSound(str sound_name, float volume, float min_dist, float max_d // Add the looping sound to the entity edict->s.loopSound = gi.soundindex(name, aliasstreamed); - edict->s.loopSoundVolume = aliasvolume; - edict->s.loopSoundMinDist = aliasmin_dist; - edict->s.loopSoundMaxDist = aliasmax_dist; - edict->s.loopSoundPitch = aliaspitch; + edict->s.loopSoundVolume = volume < 0 ? (aliasvolume) : (aliasvolume * volume); + edict->s.loopSoundMinDist = min_dist < 0 ? (aliasmin_dist) : (min_dist); + edict->s.loopSoundMaxDist = max_dist < 0 ? (aliasmax_dist) : (max_dist); + edict->s.loopSoundPitch = pitch < 0 ? (aliaspitch) : (aliaspitch * pitch); // Local sound will always be heard edict->s.loopSoundFlags = aliaschannel == CHAN_LOCAL; @@ -3264,7 +3300,7 @@ void Entity::ProcessSoundEvent(Event *ev, qboolean checkSubtitle) { str sound_name; str wait; - int waitTillDone = 0; + bool waitTillDone = false; float volume; int channel = 0; @@ -3284,30 +3320,24 @@ void Entity::ProcessSoundEvent(Event *ev, qboolean checkSubtitle) wait = ev->GetString(2); } - if (Q_stricmp(wait.c_str(), "wait")) { - if (!Q_stricmp(wait.c_str(), "volume")) { - if (ev->NumArgs() != 3) { - ScriptError("Entity::Sound: volume not followed by a float"); - } - - volume = ev->GetFloat(3); - } - } else { - waitTillDone = 1; + if (!Q_stricmp(wait.c_str(), "wait")) { + waitTillDone = true; if (ev->NumArgs() == 3) { volume = ev->GetFloat(3); } + } else if (!Q_stricmp(wait.c_str(), "volume")) { + if (ev->NumArgs() != 3) { + ScriptError("Entity::Sound: volume not followed by a float"); + } + + volume = ev->GetFloat(3); } if (volume == DEFAULT_VOL) { - if (wait.length()) { - channel = atoi(wait.c_str()); - } - - Sound(sound_name, channel, volume, 0, NULL, 0, 0, waitTillDone, checkSubtitle, -1.0f); + Sound(sound_name, CHAN_AUTO, volume, 0, NULL, 0, 0, waitTillDone, checkSubtitle, -1.0f); } else { - Sound(sound_name, -1.0f, volume, -1.0f, NULL, -1.0f, 1, waitTillDone, checkSubtitle, -1.0f); + Sound(sound_name, -1, volume, -1.0f, NULL, -1.0f, 1, waitTillDone, checkSubtitle, -1.0f); } } @@ -3317,7 +3347,7 @@ void Entity::Sound(Event *ev) Event *event = new Event(EV_Sound); for (int i = 1; i <= ev->NumArgs(); i++) { - event->AddValue(ev->GetValue(1)); + event->AddValue(ev->GetValue(i)); } PostEvent(event, level.frametime); @@ -3569,13 +3599,18 @@ void Entity::Sound( static cvar_t *g_subtitle = NULL; static bool _tmp = false; int num; + int aliaschannel; + float aliasvolume; + float aliasmin_dist; + float aliasmax_dist; + float aliaspitch; if (!_tmp) { g_subtitle = gi.Cvar_Get("g_subtitle", "0", CVAR_ARCHIVE); _tmp = true; } - if (doCallback && g_gametype->integer) { + if (doCallback && g_gametype->integer != GT_SINGLE_PLAYER) { Com_Printf("^~^~^ Callback of sound '%s' ignored.\n", sound_name.c_str()); doCallback = 0; } @@ -3590,79 +3625,104 @@ void Entity::Sound( } if (!name) { - name = sound_name.c_str(); + name = gi.GlobalAlias_FindRandom(sound_name.c_str(), &ret); } // Play the sound - if (name != NULL) { - if (ret) { - if (channel < 0) { - channel = ret->channel; - } + if (name && ret) { + aliaschannel = ret->channel; + aliasvolume = G_Random() * ret->volumeMod + ret->volume; + aliaspitch = G_Random() * ret->pitchMod + ret->pitch; + aliasmin_dist = ret->dist; + aliasmax_dist = ret->maxDist; - num = entnum; - if (sound_origin) { - VectorCopy(*sound_origin, org); - num = ENTITYNUM_NONE; - } else { - VectorCopy(edict->s.origin, org); - - if (doCallback) { - num |= S_FLAG_DO_CALLBACK; - } - } - - if (argstype == 0) { - volume = G_Random() * ret->volumeMod + ret->volume; - pitch = G_Random() * ret->pitchMod + ret->pitch; - min_dist = ret->dist; - max_dist = ret->maxDist; - } else if (argstype == 1) { - if (volume >= 0.0f) { - volume = G_Random() * ret->volumeMod + volume; - } else { - pitch = G_Random() * ret->pitchMod + ret->pitch; - } - - if (pitch >= 0.0f) { - pitch = G_Random() * ret->pitchMod + pitch; - } else { - pitch = G_Random() * ret->pitchMod + ret->pitch; - } - } else { - if (volume <= 0.0f) { - volume = G_Random() * ret->volumeMod + ret->volume; - } - - if (pitch >= 0.0f) { - pitch = G_Random() * ret->pitchMod + pitch; - } else { - pitch = G_Random() * ret->pitchMod + ret->pitch; - } - - if (min_dist < 0.0f) { - min_dist = ret->dist; - } - - if (max_dist < 0.0f) { - max_dist = ret->maxDist; - } - } - - if ((!checkSubtitle || g_subtitle->integer) && ret->subtitle) { - Entity *p = G_GetEntity(0); - - if (g_subtitle->integer == 2 || max_dist * max_dist > DistanceSquared(org, p->edict->s.origin)) { - cvar_t *curSubtitle = gi.Cvar_Get("curSubtitle", "0", 0); - - gi.cvar_set(va("subtitle%d", curSubtitle->integer), va("%s", ret->subtitle)); - gi.cvar_set("curSubtitle", va("%d", curSubtitle->integer + 1)); - } - } - - gi.Sound(&org, num, channel, name, volume, min_dist, pitch, max_dist, ret->streamed); + if (channel < 0) { + channel = ret->channel; } + + num = entnum; + if (sound_origin) { + VectorCopy(*sound_origin, org); + num = ENTITYNUM_NONE; + } else { + VectorCopy(edict->s.origin, org); + + if (doCallback) { + num |= S_FLAG_DO_CALLBACK; + } + } + + switch (argstype) { + case 0: + volume = aliasvolume; + pitch = aliaspitch; + min_dist = aliasmin_dist; + max_dist = aliasmax_dist; + channel = aliaschannel; + break; + case 1: + if (volume >= 0.0f) { + volume = volume * aliasvolume; + } else { + volume = aliasvolume; + } + + if (pitch >= 0.0f) { + pitch = pitch * aliaspitch; + } else { + pitch = aliaspitch; + } + + if (min_dist < 0.0f) { + min_dist = aliasmin_dist; + } + + if (max_dist < 0.0f) { + max_dist = aliasmax_dist; + } + + if (channel < 0) { + channel = aliaschannel; + } + break; + default: + if (volume < 0.0) { + volume = aliasvolume; + } + if (pitch < 0.0) { + pitch = aliaspitch; + } + if (min_dist < 0.0) { + min_dist = aliasmin_dist; + } + if (max_dist < 0.0) { + max_dist = aliasmax_dist; + } + if (channel < 0) { + channel = aliaschannel; + } + break; + } + + if (g_gametype->integer == GT_SINGLE_PLAYER && (ret->forcesubtitle || !checkSubtitle || g_subtitle->integer) && ret->subtitle) { + Entity *p = G_GetEntity(0); + + if (p && (g_subtitle->integer == 2 || Square(max_dist) > DistanceSquared(org, p->edict->s.origin))) { + cvar_t *curSubtitle = gi.Cvar_Get("curSubtitle", "0", 0); + int curSub; + + gi.cvar_set(va("subtitle%d", curSubtitle->integer), va("%s", ret->subtitle)); + curSub = curSubtitle->integer + 1; + if (curSubtitle->integer + 1 < 0) { + curSub = curSubtitle->integer + MAX_SUBTITLES; + } + + gi.cvar_set("curSubtitle", va("%d", (curSubtitle->integer + 1) - MAX_SUBTITLES * (curSub >> 2))); + } + } + + gi.Sound(&org, num, channel, name, volume, min_dist, pitch, max_dist, ret->streamed); } else { gi.DPrintf( "ERROR: Entity::Sound: %s needs an alias in ubersound.scr or uberdialog.scr - Please fix.\n", @@ -4059,7 +4119,11 @@ void Entity::SVFlags(Event *ev) void Entity::BroadcastAIEvent(int iType, float rad) { - G_BroadcastAIEvent(this, origin, iType, rad); + if (flags & FL_NOTARGET) { + return; + } + + G_BroadcastAIEvent(this, centroid, iType, rad); } void Entity::BroadcastAIEvent(Event *ev) @@ -4187,7 +4251,7 @@ void Entity::SurfaceCommand(const char *surf_name, const char *token) int numsurfaces; if (edict->tiki) { - numsurfaces = gi.NumSurfaces(edict->tiki); + numsurfaces = gi.TIKI_NumSurfaces(edict->tiki); } else { numsurfaces = 0; } @@ -4220,9 +4284,9 @@ void Entity::SurfaceCommand(const char *surf_name, const char *token) void Entity::SurfaceModelEvent(Event *ev) { - const char *surf_name; - const char *token; - int i; + str surf_name; + str token; + int i; surf_name = ev->GetString(1); @@ -4235,7 +4299,7 @@ void Entity::SurfaceModelEvent(Event *ev) void Entity::AttachEvent(Event *ev) { Entity *parent; - const char *bone; + str bone; int tagnum; qboolean use_angles = qtrue; Vector offset; @@ -4259,14 +4323,14 @@ void Entity::AttachEvent(Event *ev) if (tagnum >= 0) { attach(parent->entnum, tagnum, use_angles, offset); } else { - warning("AttachEvent", "Tag %s not found", bone); + warning("AttachEvent", "Tag %s not found", bone.c_str()); } } void Entity::AttachModelEvent(Event *ev) { Animate *obj; - const char *bone; + str bone; str modelname; int tagnum; float remove_time, fade_time, fade_delay; @@ -4343,24 +4407,30 @@ void Entity::AttachModelEvent(Event *ev) if (obj->attach(this->entnum, tagnum, true, offset)) { obj->NewAnim("idle"); } else { - delete obj; + warning("AttachModelEvent", "Could not attach model %s to tag \"%s\" on entnum #%d (targetname = %s)", modelname.c_str(), bone.c_str(), entnum, targetname.c_str()); + if (g_iInThinks) { + PostEvent(EV_Remove, 0); + } else { + delete obj; + } return; } } else { - warning("AttachModelEvent", "Tag %s not found", bone); + warning("AttachModelEvent", "Tag %s not found", bone.c_str()); + obj->NewAnim("idle"); } } void Entity::RemoveAttachedModelEvent(Event *ev) { - const char *tag_name; - int tag_num; - int num; - int i; - Entity *ent; - float fade_rate = 0; - Event *fade_event; - str model_name; + str tag_name; + int tag_num; + int num; + int i; + Entity *ent; + float fade_rate = 0; + Event *fade_event; + str model_name; tag_name = ev->GetString(1); tag_num = gi.Tag_NumForName(edict->tiki, tag_name); @@ -4530,7 +4600,7 @@ void Entity::Censor(Event *ev) oldsize = size.length(); setSolidType(SOLID_NOT); setModel("censored.tik"); - gi.CalculateBounds(edict->tiki, 1, mins, maxs); + gi.TIKI_CalculateBounds(edict->tiki, 1, mins, maxs); delta = maxs - mins; newsize = delta.length(); edict->s.scale = oldsize / newsize; @@ -4577,7 +4647,7 @@ void Entity::Explosion(Event *ev) void Entity::Shader(Event *ev) { - const char *token; + str token; if (gi.modeltiki(model)) { gi.Printf("shader event being called on TIKI model\n"); @@ -4661,7 +4731,7 @@ qboolean Entity::isBoundTo(Entity *master) return false; } -void Entity::bind(Entity *master, qboolean use_my_angles, qboolean bBindChilds) +void Entity::bind(Entity *master, qboolean use_my_angles) { float mat[3][3]; float local[3][3]; @@ -4678,8 +4748,6 @@ void Entity::bind(Entity *master, qboolean use_my_angles, qboolean bBindChilds) return; } - m_bBindChilds = bBindChilds; - // unbind myself from my master unbind(); @@ -4842,17 +4910,10 @@ void Entity::EventUnbind(Event *ev) void Entity::BindEvent(Event *ev) { Entity *ent; - bool bBindChilds; ent = ev->GetEntity(1); if (ent) { - if (ev->NumArgs() > 1) { - bBindChilds = ev->GetBoolean(2); - } else { - bBindChilds = false; - } - - bind(ent, false, bBindChilds); + bind(ent, false); } } @@ -5029,7 +5090,7 @@ void Entity::TouchTriggersEvent(Event *ev) void Entity::DeathSinkStart(Event *ev) { - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { PostEvent(EV_Remove, 5.0f); } else { // Start the sinking @@ -5041,7 +5102,7 @@ void Entity::DeathSink(Event *ev) { // Sink just a little - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { origin[2] -= 0.2f; setOrigin(origin); @@ -5092,7 +5153,7 @@ qboolean Entity::CheckEventFlags(Event *event) ent = (Entity *)this; gi.SendServerCommand( - ent->edict - g_entities, "print \"Command '%s' not available from console\n\"", event->getName().c_str() + ent->edict - g_entities, "print \"Command '%s' not available from console\n\"", event->getName() ); } @@ -5240,9 +5301,6 @@ void Entity::glue(Entity *master, qboolean use_my_angles, qboolean can_duck) m_pGlueMaster = master; m_bGlueDuckable = can_duck == qtrue; master->m_iNumGlues++; - - setAngles(master->angles); - setOrigin(master->origin); } void Entity::unglue(void) @@ -5289,7 +5347,7 @@ void Entity::GetTagPositionAndOrientation(int tagnum, orientation_t *new_or) VectorCopy(origin, new_or->origin); for (i = 0; i < 3; i++) { - VectorMA(new_or->origin, tag_or.origin[i], tag_or.axis[i], new_or->origin); + VectorMA(new_or->origin, tag_or.origin[i], axis[i], new_or->origin); } MatrixMultiply(tag_or.axis, axis, new_or->axis); @@ -5433,7 +5491,7 @@ void Entity::MPrintf(const char *fmt, ...) va_list argptr; char msg[MAXPRINTMSG]; - if (g_monitorNum->integer == entnum && g_monitor->string == targetname) { + if (g_monitorNum->integer == entnum || g_monitor->string[0] && g_monitor->string == targetname) { va_start(argptr, fmt); Q_vsnprintf(msg, sizeof(msg), fmt, argptr); va_end(argptr); @@ -5551,13 +5609,13 @@ void Entity::ShowInfo(float fDot, float fDist) int i; char szText[512]; if (fDot > 0.94999999 && fDist < 1024.0 && fDist > 64.0) { - i = sprintf(szText, "%i:%i", entnum, radnum); + i = Com_sprintf(szText, sizeof(szText), "%i:%i", entnum, radnum); if (targetname.length()) { - i = sprintf(&szText[i], ":%s", targetname.c_str()); + i = Com_sprintf(szText + i, sizeof(szText) - i, ":%s", targetname.c_str()); } if (health != 0) { - sprintf(&szText[i], ":%.1f", health); + Com_sprintf(szText + i, sizeof(szText) - i, ":%.1f", health); } G_DebugString(Vector(origin.x + 0, origin.y + 0, origin.z + maxs.z + 65), 1.0, 1.0, 1.0, 1.0, szText); @@ -5596,7 +5654,7 @@ void Entity::ConnectPaths(void) m_iNumBlockedPaths = 0; if (m_BlockedPaths) { - delete m_BlockedPaths; + delete[] m_BlockedPaths; m_BlockedPaths = NULL; } } @@ -5675,6 +5733,14 @@ void Entity::Delete(void) // Delete the entity the next frame if (g_iInThinks) { + if (ProcessingEvents) { + // Fixed in OPM + // Add a slight delay because otherwise this would cause an infinite loop + // when processing pending events + PostEvent(EV_Remove, 0.001); + return; + } + PostEvent(EV_Remove, 0); } else { delete this; @@ -5740,8 +5806,13 @@ void Entity::Archive(Archiver& arc) arc.ArchiveInteger(&spawnflags); arc.ArchiveString(&model); - if (arc.Loading() && model.length()) { - setModel(model); + if (arc.Loading() && AutoArchiveModel()) { + if (model.length() && model[0] == '*') { + // set the brush model + edict->s.modelindex = atoi(model.c_str() + 1); + } else { + setModel(); + } } arc.ArchiveVector(&mins); @@ -5806,6 +5877,11 @@ void Entity::Archive(Archiver& arc) ArchiveEnum(takedamage, damage_t); + arc.ArchiveSafePointer(&enemy); + arc.ArchiveFloat(&pain_finished); + arc.ArchiveFloat(&damage_debounce_time); + arc.ArchiveInteger(&damage_type); + arc.ArchiveInteger(&m_iNumGlues); for (i = 0; i < MAX_GLUE_CHILDREN; i++) { @@ -5815,6 +5891,7 @@ void Entity::Archive(Archiver& arc) arc.ArchiveObjectPointer((Class **)&m_pGlueMaster); arc.ArchiveBool(&m_bGlueAngles); + arc.ArchiveBool(&m_bGlueDuckable); arc.ArchiveBoolean(&detach_at_death); arc.ArchiveFloat(&stealthMovementScale); @@ -5888,7 +5965,7 @@ void Entity::DrawBoundingBox(int showbboxes) switch (showbboxes) { case 1: if (edict->s.solid) { - G_DebugBBox(origin, mins, maxs, 1, 1, 0, 1); + G_DebugRotatedBBox(origin, angles, mins, maxs, 1, 1, 0, 1); } break; case 2: @@ -5898,29 +5975,165 @@ void Entity::DrawBoundingBox(int showbboxes) break; case 3: if (edict->tiki && !(edict->s.renderfx & RF_DONTDRAW)) { - G_DebugBBox(origin, mins, maxs, 1, 1, 0, 1); + G_DebugRotatedBBox(origin, angles, mins, maxs, 1, 1, 0, 1); } break; case 4: - G_DebugBBox(origin, mins, maxs, 1, 1, 0, 1); + G_DebugRotatedBBox(origin, angles, mins, maxs, 1, 1, 0, 1); break; - case 5: - default: - if (IsSubclassOfAnimate() && edict->tiki) { - Animate *anim; - vec3_t mins, maxs; + case 7: + if (edict->tiki && !(edict->s.renderfx & RF_DONTDRAW)) { + Vector vMins, vMaxs; - anim = (Animate *)this; - // FIXME - G_DebugBBox(origin, mins, maxs, 0, 1, 0, 1); - } else { - G_DebugBBox(origin, mins, maxs, 1, 1, 0, 1); + gi.TIKI_CalculateBounds(edict->tiki, edict->s.scale, vMins, vMaxs); + if (!VectorCompare(vMins, vec_zero) || !VectorCompare(vMaxs, vec_zero)) { + if (edict->s.parent != ENTITYNUM_NONE && edict->s.tag_num >= 0) { + int i; + Vector vAng; + orientation_t oTag, oBox; + Entity* pParent; + + pParent = G_GetEntity(edict->s.parent); + AnglesToAxis(pParent->angles, pParent->orientation); + oTag = G_TIKI_Orientation(pParent->edict, edict->s.tag_num & TAG_MASK); + + VectorCopy(pParent->origin, oBox.origin); + for (i = 0; i < 3; i++) { + VectorMA(oBox.origin, oTag.origin[i], pParent->orientation[i], oBox.origin); + } + + MatrixMultiply(oTag.axis, pParent->orientation, oBox.axis); + MatrixToEulerAngles(oBox.axis, vAng); + G_DebugRotatedBBox(oBox.origin, vAng, vMins, vMaxs, 0, 1, 1, 1); + } else { + G_DebugRotatedBBox(origin, angles, vMins, vMaxs, 0, 1, 1, 1); + } + } } break; + case 8: + if (edict->tiki && !(edict->s.renderfx & RF_DONTDRAW)) { + G_DebugRotatedBBox(origin, angles, mins, maxs, 1, 1, 0, 1); + G_DebugBBox(origin, Vector(-4, -4, -4), Vector(4, 4, 4), 0, 1, 1, 1); + } + break; + default: + break; + } + + if ((showbboxes >= 9 && showbboxes <= 28) || (showbboxes >= -28 && showbboxes <= -9)) { + qboolean bDoPlayer = qfalse; + + if (showbboxes >= 0) { + bDoPlayer = qfalse; + } else { + showbboxes = -showbboxes; + bDoPlayer = qtrue; + } + + if (edict->s.solid == SOLID_NOT) { + return; + } + + if ((edict != g_entities && !bDoPlayer) || (edict == g_entities && bDoPlayer)) { + int i, j; + int iTagNum; + int iCap; + float fRadius; + const char *pszTagName; + vec3_t vOffset; + vec3_t vPos; + vec3_t vColor; + orientation_t orTag; + orientation_t orPosition; + + if (!IsSubclassOfSentient() || !edict->tiki) { + G_DebugBBox(origin, mins, maxs, 1.0, 1.0, 0.0, 1.0); + return; + } + + AnglesToAxis(angles, orientation); + + if (showbboxes <= 9 && showbboxes >= -9) { + i = 0; + iCap = 19; + } else { + i = showbboxes - 10; + if (i >= 18) { + return; + } + + iCap = i + 1; + } + + for (; i < iCap; i++) { + pszTagName = gi.CM_GetHitLocationInfo(i, &fRadius, vOffset); + + if (sv_testloc_num->integer - 1 == i || (sv_testloc_num->integer && (showbboxes > 9 || showbboxes < -9))) { + fRadius = sv_testloc_radius->value; + vOffset[0] = sv_testloc_offset_x->value; + vOffset[1] = sv_testloc_offset_y->value; + vOffset[2] = sv_testloc_offset_z->value; + vColor[0] = 1.0; + vColor[1] = 0.5; + vColor[2] = 0.0; + } else { + vColor[0] = 0.0; + vColor[1] = 0.5; + vColor[2] = 1.0; + } + + iTagNum = gi.Tag_NumForName(edict->tiki, pszTagName); + if (iTagNum < 0) { + return; + } + + orTag = G_TIKI_Orientation(edict, iTagNum & TAG_MASK); + VectorCopy(origin, orPosition.origin); + + for (j = 0; j < 3; j++) { + VectorMA(orPosition.origin, orTag.origin[j], orientation[j], orPosition.origin); + } + + MatrixMultiply(orTag.axis, orientation, orPosition.axis); + MatrixTransformVector(vOffset, orPosition.axis, vPos); + VectorAdd(orPosition.origin, vPos, vPos); + + G_DebugCircle(vPos, fRadius, vColor[0], vColor[1], vColor[2], 1.0); + + pszTagName = gi.CM_GetHitLocationInfoSecondary(i, &fRadius, vOffset); + vColor[0] = 0.5; + vColor[1] = 0.0; + vColor[2] = 1.0; + + if (!pszTagName || sv_testloc_num->integer - 1 == i || (sv_testloc_num->integer && (showbboxes > 9 || showbboxes < -9))) { + if (!sv_testloc_secondary->integer) { + continue; + } + + if (sv_testloc_num->integer - 1 != i && (!sv_testloc_num->integer || (showbboxes <= 9 && showbboxes >= -9))) { + continue; + } + + fRadius = sv_testloc_radius2->value; + vOffset[0] = sv_testloc_offset2_x->value; + vOffset[1] = sv_testloc_offset2_y->value; + vOffset[2] = sv_testloc_offset2_z->value; + vColor[0] = 1.0; + vColor[1] = 0.0; + vColor[2] = 0.5; + } + + MatrixTransformVector(vOffset, orPosition.axis, vPos); + VectorAdd(orPosition.origin, vPos, vPos); + + G_DebugCircle(vPos, fRadius, vColor[0], vColor[1], vColor[2], 1.0); + } + } } } -qboolean Entity::IsDead(void) +qboolean Entity::IsDead(void) const { return deadflag != DEAD_NO; } @@ -6039,7 +6252,7 @@ void Entity::EventGetRotatedBbox(Event *ev) void Entity::EventSinglePlayerCommand(Event *ev) { if (g_gametype->integer == GT_SINGLE_PLAYER && !g_realismmode->integer) { - Event *newev = new Event(ev->GetToken(1)); + Event *newev = new Event(ev->GetToken(1), ev->NumArgs() - 1); for (int i = 2; i <= ev->NumArgs(); i++) { newev->AddToken(ev->GetToken(i)); @@ -6052,7 +6265,7 @@ void Entity::EventSinglePlayerCommand(Event *ev) void Entity::EventMultiPlayerCommand(Event *ev) { if (g_gametype->integer != GT_SINGLE_PLAYER && !g_realismmode->integer) { - Event *newev = new Event(ev->GetToken(1)); + Event *newev = new Event(ev->GetToken(1), ev->NumArgs() - 1); for (int i = 2; i <= ev->NumArgs(); i++) { newev->AddToken(ev->GetToken(i)); @@ -6065,7 +6278,7 @@ void Entity::EventMultiPlayerCommand(Event *ev) void Entity::EventRealismModeCommand(Event *ev) { if (g_realismmode->integer) { - Event *newev = new Event(ev->GetToken(1)); + Event *newev = new Event(ev->GetToken(1), ev->NumArgs() - 1); for (int i = 2; i <= ev->NumArgs(); i++) { newev->AddToken(ev->GetToken(i)); @@ -6077,8 +6290,8 @@ void Entity::EventRealismModeCommand(Event *ev) void Entity::EventSPRealismModeCommand(Event *ev) { - if (g_realismmode->integer && g_gametype->integer == GT_SINGLE_PLAYER) { - Event *newev = new Event(ev->GetToken(1)); + if (g_gametype->integer == GT_SINGLE_PLAYER && g_realismmode->integer) { + Event *newev = new Event(ev->GetToken(1), ev->NumArgs() - 1); for (int i = 2; i <= ev->NumArgs(); i++) { newev->AddToken(ev->GetToken(i)); @@ -6090,8 +6303,8 @@ void Entity::EventSPRealismModeCommand(Event *ev) void Entity::EventDMRealismModeCommand(Event *ev) { - if (g_realismmode->integer && g_gametype->integer != GT_SINGLE_PLAYER) { - Event *newev = new Event(ev->GetToken(1)); + if (g_gametype->integer != GT_SINGLE_PLAYER && g_realismmode->integer) { + Event *newev = new Event(ev->GetToken(1), ev->NumArgs() - 1); for (int i = 2; i <= ev->NumArgs(); i++) { newev->AddToken(ev->GetToken(i)); @@ -6154,7 +6367,9 @@ void Entity::NoTarget(Event *ev) void Entity::GetZone(Event *ev) { - // FIXME: stub + ev->AddInteger(edict->r.areanum); + + // FIXME: Implement OPM feature STUB(); #if 0 @@ -6170,7 +6385,13 @@ void Entity::GetZone(Event *ev) void Entity::IsInZone(Event *ev) { - // FIXME: stub + if (edict->r.areanum == ev->GetInteger(1)) { + ev->AddInteger(1); + } else { + ev->AddInteger(0); + } + + // FIXME: Implement OPM feature STUB(); #if 0 @@ -6207,6 +6428,7 @@ void Entity::SetDepthHack(Event *ev) } } +#ifdef OPM_FEATURES void Entity::ProcessHint(gentity_t *client, bool bShow) { Player *player = (Player *)client->entity; @@ -6245,15 +6467,48 @@ void Entity::SetHintString(Event *ev) m_HintString = ev->GetString(1); } -void Entity::SetShader(Event *ev) +void Entity::SetShader(Event* ev) { str shadername = ev->GetString(1); - qboolean fReset = false; + qboolean fReset = false; if (!shadername.length()) { shadername = "default"; - fReset = true; + fReset = true; } gi.SendServerCommand(-1, "setshader %d %s %d", entnum, shadername.c_str(), fReset); } +#endif + +void Entity::PlayNonPvsSound(const str& soundName, float volume) +{ + AliasListNode_t* ret; + str name; + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + // Ignore in single-player + return; + } + + if (!sv_netoptimize->integer) { + // don't use sound indexes for nothing + return; + } + + if (edict->r.num_nonpvs_sounds >= MAX_NONPVS_SOUNDS) { + return; + } + + name = GetRandomAlias(soundName, &ret); + if (name.length() && ret) { + nonpvs_sound_t* npvs = &edict->r.nonpvs_sounds[edict->r.num_nonpvs_sounds]; + + npvs->index = gi.pvssoundindex(name.c_str(), ret->streamed); + npvs->volume = G_Random() * ret->volumeMod + ret->volume * volume; + npvs->minDist = ret->dist; + npvs->maxDist = ret->maxDist; + npvs->pitch = G_Random() * ret->pitchMod + ret->pitch; + edict->r.num_nonpvs_sounds++; + } +} diff --git a/code/fgame/entity.h b/code/fgame/entity.h index d0b87e56..3291a791 100644 --- a/code/fgame/entity.h +++ b/code/fgame/entity.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -43,8 +43,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // not be ignored at any cost). // -#ifndef __ENTITY_H__ -#define __ENTITY_H__ +#pragma once #include "g_local.h" #include "class.h" @@ -52,6 +51,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "script.h" #include "listener.h" #include "simpleentity.h" +#include "../qcommon/delegate.h" // modification flags #define FLAG_IGNORE 0 @@ -69,6 +69,23 @@ typedef enum { torso, } bodypart_t; +enum eAIEvent { + AI_EVENT_NONE, + AI_EVENT_WEAPON_FIRE, + AI_EVENT_WEAPON_IMPACT, + AI_EVENT_EXPLOSION, + AI_EVENT_AMERICAN_VOICE, + AI_EVENT_GERMAN_VOICE, + AI_EVENT_AMERICAN_URGENT, + AI_EVENT_GERMAN_URGENT, + AI_EVENT_MISC, + AI_EVENT_MISC_LOUD, + AI_EVENT_FOOTSTEP, + AI_EVENT_GRENADE, + AI_EVENT_BADPLACE, // Added in 2.0 + AI_EVENT_MAX +}; + //deadflag #define DEAD_NO 0 #define DEAD_DYING 1 @@ -270,10 +287,21 @@ public: // immune list Container immunities; +#ifdef OPM_FEATURES + // + // Added in OPM + //==== // miscellaneous - qboolean m_bBindChilds; bool m_bHintRequiresLookAt; str m_HintString; + //==== +#endif + + MulticastDelegate delegate_damage; + MulticastDelegate delegate_killed; + MulticastDelegate delegate_gotKill; + +public: Entity(); virtual ~Entity(); @@ -286,10 +314,10 @@ public: virtual void ShowInfo(float fDot, float fDist); - qboolean DistanceTo(Vector pos); - qboolean DistanceTo(Entity *ent); - qboolean WithinDistance(Vector pos, float dist); - qboolean WithinDistance(Entity *ent, float dist); + qboolean DistanceTo(Vector pos) const; + qboolean DistanceTo(Entity *ent) const; + qboolean WithinDistance(Vector pos, float dist) const; + qboolean WithinDistance(Entity *ent, float dist) const; Vector GetControllerAngles(int num); void SetControllerAngles(int num, vec3_t angles); @@ -481,10 +509,10 @@ public: void RenderEffects(Event *ev); void SVFlags(Event *ev); - void BroadcastAIEvent(int iType = 8, float rad = SOUND_RADIUS); + void BroadcastAIEvent(int iType = AI_EVENT_MISC, float rad = SOUND_RADIUS); void BroadcastAIEvent(Event *ev); void Kill(Event *ev); - void Killed(Event *ev); + virtual void Killed(Event *ev); void SurfaceModelEvent(Event *ev); void SurfaceCommand(const char *surf_name, const char *token); virtual void Postthink(void); @@ -523,7 +551,7 @@ public: void joinTeam(Entity *teammember); void quitTeam(void); qboolean isBoundTo(Entity *master); - virtual void bind(Entity *master, qboolean use_my_angles = qfalse, qboolean bBindChilds = qfalse); + virtual void bind(Entity *master, qboolean use_my_angles = qfalse); virtual void unbind(void); virtual void glue(Entity *master, qboolean use_my_angles = qtrue, qboolean can_duck = qfalse); virtual void unglue(void); @@ -572,7 +600,7 @@ public: void VolumeDamage(float damage); void EventVolumeDamage(Event *ev); - virtual qboolean IsDead(); + virtual qboolean IsDead() const; virtual void AddImmunity(Event *ev); virtual void RemoveImmunity(Event *ev); qboolean Immune(int meansofdeath); @@ -593,8 +621,9 @@ public: void EventSetHealthOnly(Event *ev); void GetYaw(Event *ev); - virtual void PreAnimate(void) {}; - virtual void PostAnimate(void) {}; + virtual void PreAnimate(void); + virtual void PostAnimate(void); + virtual bool HasVehicle(void) const; void EventGetEntnum(Event *ev); void EventGetClassname(Event *ev); void EventSetRadnum(Event *ev); @@ -621,18 +650,30 @@ public: void GetZone(Event *ev); void IsInZone(Event *ev); void SetDepthHack(Event *ev); +#ifdef OPM_FEATURES void SetHintRequireLookAt(Event *ev); void SetHintString(Event *ev); - void SetShader(Event *ev); + void SetShader(Event* ev); +#endif + void PlayNonPvsSound(const str& soundName, float volume = 1); }; +inline void Entity::PreAnimate(void) {} + +inline void Entity::PostAnimate(void) {} + +inline bool Entity::HasVehicle(void) const +{ + return false; +} + inline int Entity::getSolidType(void) { return edict->solid; } -inline qboolean Entity::DistanceTo(Vector pos) +inline qboolean Entity::DistanceTo(Vector pos) const { Vector delta; @@ -641,7 +682,7 @@ inline qboolean Entity::DistanceTo(Vector pos) return delta.length() != 0 ? qtrue : qfalse; } -inline qboolean Entity::DistanceTo(Entity *ent) +inline qboolean Entity::DistanceTo(Entity *ent) const { Vector delta; @@ -656,7 +697,7 @@ inline qboolean Entity::DistanceTo(Entity *ent) return delta.length() != 0 ? qtrue : qfalse; } -inline qboolean Entity::WithinDistance(Vector pos, float dist) +inline qboolean Entity::WithinDistance(Vector pos, float dist) const { Vector delta; @@ -666,7 +707,7 @@ inline qboolean Entity::WithinDistance(Vector pos, float dist) return ((delta * delta) < (dist * dist)) ? qtrue : qfalse; } -inline qboolean Entity::WithinDistance(Entity *ent, float dist) +inline qboolean Entity::WithinDistance(Entity *ent, float dist) const { Vector delta; @@ -815,6 +856,9 @@ inline str Entity::GetRandomAlias(str name, AliasListNode_t **ret) return realname; } -#include "world.h" +inline bool Entity::AreasConnected(const Entity *other) +{ + return gi.AreasConnected(edict->r.areanum, other->edict->r.areanum) != 0; +} -#endif +#include "worldspawn.h" diff --git a/code/fgame/explosion.cpp b/code/fgame/explosion.cpp index 3f42d199..72a7b620 100644 --- a/code/fgame/explosion.cpp +++ b/code/fgame/explosion.cpp @@ -487,7 +487,7 @@ void ExplodeObject::SetDebrisModel const char *ptr; // there could be multiple space delimited models, so we need to search for the spaces. - strcpy( string, ev->GetString( 1 ) ); + Q_strncpyz( string, ev->GetString( 1 ), sizeof( string ) ); ptr = strtok( string, " " ); while ( ptr ) { diff --git a/code/fgame/explosion.h b/code/fgame/explosion.h index 19618004..4d123c49 100644 --- a/code/fgame/explosion.h +++ b/code/fgame/explosion.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -26,8 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // explosions each time they are activated. // -#ifndef __EXPLOSION_H__ -#define __EXPLOSION_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -136,5 +135,3 @@ inline void ExplodeObject::Archive arc.ArchiveInteger( &debrisamount ); debrismodels.Archive( arc ); } - -#endif /* explosion.h */ diff --git a/code/fgame/fixedturret.cpp b/code/fgame/fixedturret.cpp index 6395d260..20d4f21e 100644 --- a/code/fgame/fixedturret.cpp +++ b/code/fgame/fixedturret.cpp @@ -21,6 +21,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "fixedturret.h" +#include "g_phys.h" +#include "weapturret.h" +#include "dm_manager.h" +#include "player.h" CLASS_DECLARATION(VehicleTank, FixedTurret, NULL) { {NULL, NULL} @@ -28,41 +32,105 @@ CLASS_DECLARATION(VehicleTank, FixedTurret, NULL) { FixedTurret::FixedTurret() { - // FIXME: unimplemented + locked = false; + driver.flags |= SLOT_UNUSED; } void FixedTurret::Archive(Archiver& arc) { - // FIXME: unimplemented + VehicleTank::Archive(arc); + + arc.ArchiveVector(&lastEntOrigin); + arc.ArchiveVector(&lastEntAngles); } qboolean FixedTurret::Drive(usercmd_t *ucmd) { - // FIXME: unimplemented - return qfalse; + qboolean result; + setMoveType(MOVETYPE_NONE); + + result = VehicleTank::Drive(ucmd); + + moveimpulse = 0; + turnimpulse = 0; + jumpimpulse = 0; + + return result; } void FixedTurret::DetachRemoteOwner() { - // FIXME: unimplemented + TurretGun* turret; + + Vehicle::DetachRemoteOwner(); + + turret = static_cast(Turrets[0].ent.Pointer()); + turret->RemoveUserCamera(); } void FixedTurret::EventDamage(Event *ev) { - // FIXME: unimplemented + meansOfDeath_t mod = static_cast(ev->GetInteger(9)); + + // ignore damage when the round isn't active in TOW + if (g_gametype->integer == GT_TOW && !dmManager.RoundActive()) { + return; + } + + // ignore bullets + switch (mod) { + case MOD_BULLET: + case MOD_BASH: + case MOD_FAST_BULLET: + case MOD_VEHICLE: + case MOD_SHOTGUN: + return; + default: + break; + } + + // ignore grenades in single player mode + if (g_gametype->integer == GT_SINGLE_PLAYER && mod == MOD_GRENADE) { + return; + } + + Vehicle::EventDamage(ev); + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + if (driver.ent && driver.ent->IsSubclassOfPlayer()) { + Player* player = static_cast(driver.ent.Pointer()); + player->m_iNumHitsTaken++; + } + } + + if (health <= 0 && driver.ent && driver.ent->IsSubclassOfPlayer()) { + Player* player = static_cast(driver.ent.Pointer()); + + DetachDriverSlot(0, vec_zero, NULL); + DetachRemoteOwner(); + + player->takedamage = DAMAGE_YES; + player->PostEvent(EV_Kill, 0.1f); + } } void FixedTurret::AttachDriverSlot(int slot, Entity *ent, Vector vExitPosition) { - // FIXME: unimplemented + lastEntOrigin = ent->origin; + lastEntAngles = ent->angles; + Vehicle::AttachDriverSlot(slot, ent, vExitPosition); } void FixedTurret::DetachDriverSlot(int slot, Vector vExitPosition, Vector *vExitAngles) { - // FIXME: unimplemented + Vehicle::DetachDriverSlot(slot, lastEntOrigin, &lastEntAngles); } void FixedTurret::EventSetCollisionModel(Event *ev) { - // FIXME: unimplemented + Vehicle::EventSetCollisionModel(ev); + + if (m_pCollisionEntity) { + m_pCollisionEntity->DisconnectPaths(); + } } diff --git a/code/fgame/fixedturret.h b/code/fgame/fixedturret.h index 2e96c107..c3e9ae67 100644 --- a/code/fgame/fixedturret.h +++ b/code/fgame/fixedturret.h @@ -26,6 +26,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class FixedTurret : public VehicleTank { +private: + Vector lastEntOrigin; + Vector lastEntAngles; + public: CLASS_PROTOTYPE(FixedTurret); diff --git a/code/fgame/g_bot.cpp b/code/fgame/g_bot.cpp index 0942f0ce..5ee6d165 100644 --- a/code/fgame/g_bot.cpp +++ b/code/fgame/g_bot.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -26,224 +26,772 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "playerbot.h" #include "g_bot.h" -static gentity_t* firstBot = NULL; -static saved_bot_t* saved_bots = NULL; -static unsigned int current_bot_count = 0; +static saved_bot_t *saved_bots = NULL; +static unsigned int num_saved_bots = 0; +static unsigned int botId = 0; -void G_BotBegin - ( - gentity_t *ent - ) +Container alliedModelList; +Container germanModelList; + +/* +=========== +IsAlliedPlayerModel + +Return whether or not the specified filename is for allies +============ +*/ +bool IsAlliedPlayerModel(const char *filename) { - level.m_bSpawnBot = true; - G_ClientBegin( ent, NULL ); + return !Q_stricmpn(filename, "allied_", 7) || !Q_stricmpn(filename, "american_", 9); } -void G_BotThink - ( - gentity_t *ent, - int msec - ) +/* +=========== +IsGermanPlayerModel + +Return whether or not the specified filename is for axis +============ +*/ +bool IsGermanPlayerModel(const char *filename) { - usercmd_t ucmd; - usereyes_t eyeinfo; - PlayerBot *bot; - - assert( ent ); - assert( ent->entity ); - assert( ent->entity->IsSubclassOfBot() ); - - bot = ( PlayerBot * )ent->entity; - - bot->UpdateBotStates(); - bot->GetUsercmd( &ucmd ); - bot->GetEyeInfo( &eyeinfo ); - - G_ClientThink( ent, &ucmd, &eyeinfo ); + return !Q_stricmpn(filename, "german_", 7) || !Q_stricmpn(filename, "IT_", 3) || !Q_stricmpn(filename, "SC_", 3); } -gentity_t* G_GetFirstBot() +/* +=========== +IsPlayerModel + +Return whether or not the specified filename +is a player model that can be chosen +============ +*/ +bool IsPlayerModel(const char *filename) { - return firstBot; + size_t len = strlen(filename); + + if (len >= 8 && !Q_stricmp(&filename[len - 8], "_fps.tik")) { + return false; + } + + if (!IsAlliedPlayerModel(filename) && !IsGermanPlayerModel(filename)) { + return false; + } + + return true; } -void G_AddBot(unsigned int num, saved_bot_t* saved) +/* +=========== +ClearModelList + +Clear the allied and axis model list +============ +*/ +void ClearModelList() { - int n; - int i; - int clientNum = -1; - gentity_t *e; - char botName[ MAX_NETNAME ]; - char challenge[ MAX_STRING_TOKENS ]; - char userinfo[MAX_INFO_STRING]{ 0 }; - Event* teamEv; + alliedModelList.FreeObjectList(); + germanModelList.FreeObjectList(); +} - num = Q_min(num, sv_maxbots->integer); - for( n = 0; n < num; n++ ) - { - for( i = maxclients->integer; i < game.maxclients; i++ ) - { - e = &g_entities[ i ]; +/* +=========== +InitModelList - if( !e->inuse && e->client ) - { - clientNum = i; - break; - } - } +Initialize the list of allied and axis player models +that bots can use +============ +*/ +void InitModelList() +{ + char **fileList; + int numFiles; + int i; + size_t numAlliedModels = 0, numGermanModels = 0; + byte *p; - if( clientNum == -1 ) - { - gi.Printf( "No free slot for a bot\n" ); - return; - } + ClearModelList(); - if( gi.Argc() > 2 ) - { - Q_strncpyz( botName, gi.Argv( 2 ), sizeof( botName ) ); - } - else - { - sprintf( botName, "bot%d", clientNum - maxclients->integer + 1 ); - } + fileList = gi.FS_ListFiles("models/player", ".tik", qfalse, &numFiles); - sprintf( challenge, "%d", clientNum - maxclients->integer + 1 ); + for (i = 0; i < numFiles; i++) { + const char *filename = fileList[i]; - e->s.clientNum = clientNum; - e->s.number = clientNum; - - if (saved) { - strncpy(userinfo, saved->pers.userinfo, ARRAY_LEN(userinfo)); - } else { - Info_SetValueForKey(userinfo, "name", botName); - Info_SetValueForKey(userinfo, "dm_playermodel", "allied_pilot"); - Info_SetValueForKey(userinfo, "dm_playergermanmodel", "german_afrika_officer"); - Info_SetValueForKey(userinfo, "fov", "80"); - Info_SetValueForKey(userinfo, "protocol", "8"); - Info_SetValueForKey(userinfo, "ip", "0.0.0.0"); - Info_SetValueForKey(userinfo, "qport", "0"); - Info_SetValueForKey(userinfo, "challenge", challenge); - Info_SetValueForKey(userinfo, "snaps", "1"); - Info_SetValueForKey(userinfo, "rate", "1"); - Info_SetValueForKey(userinfo, "dmprimary", "smg"); - } - - current_bot_count++; - - G_BotConnect( clientNum, userinfo ); - - if (saved) { - e->client->pers = saved->pers; - } - - if( !firstBot ) - firstBot = e; - - G_BotBegin( e ); - - if (saved) { - /* - switch (saved->team) - { - case TEAM_ALLIES: - teamEv = new Event(EV_Player_JoinDMTeam); - teamEv->AddString("allies"); - break; - case TEAM_AXIS: - teamEv = new Event(EV_Player_JoinDMTeam); - teamEv->AddString("axis"); - break; - default: - teamEv = new Event(EV_Player_AutoJoinDMTeam); - break; - } - */ - } else { - teamEv = new Event(EV_Player_AutoJoinDMTeam); - e->entity->PostEvent(teamEv, level.frametime); - - Event* ev = new Event(EV_Player_PrimaryDMWeapon); - ev->AddString("smg"); - - e->entity->PostEvent(ev, level.frametime); + if (!IsPlayerModel(filename)) { + continue; } - } + + if (IsAlliedPlayerModel(filename)) { + numAlliedModels++; + } else { + numGermanModels++; + } + } + + alliedModelList.Resize(numAlliedModels); + germanModelList.Resize(numGermanModels); + + for (i = 0; i < numFiles; i++) { + const char *filename = fileList[i]; + size_t len = strlen(filename); + + if (!IsPlayerModel(filename)) { + continue; + } + + if (IsAlliedPlayerModel(filename)) { + alliedModelList.AddObject(str(filename, 0, len - 4)); + } else { + germanModelList.AddObject(str(filename, 0, len - 4)); + } + } + + gi.FS_FreeFileList(fileList); } -void G_RemoveBot(unsigned int num) +/* +=========== +G_BotBegin + +Begin spawning a new bot entity +============ +*/ +void G_BotBegin(gentity_t *ent) { - num = Q_min(atoi(gi.Argv(1)), sv_maxbots->integer); + Player *player; + BotController *controller; - for( int n = 0; n < num; n++ ) - { - gentity_t *e = &g_entities[ game.maxclients - 1 - n ]; - if( e->inuse && e->client ) - { - G_ClientDisconnect( e ); - current_bot_count--; - } - } + level.spawn_entnum = ent->s.number; + player = new Player; + + G_ClientBegin(ent, NULL); + + controller = botManager.getControllerManager().createController(player); + //player->setController(controller); } -void G_SaveBots() { - unsigned int n; +/* +=========== +G_BotThink + +Called each server frame to make bots think +============ +*/ +void G_BotThink(gentity_t *ent, int msec) +{ + /* + usercmd_t ucmd; + usereyes_t eyeinfo; + PlayerBot *bot; + + assert(ent); + assert(ent->entity); + assert(ent->entity->IsSubclassOfBot()); + + bot = (PlayerBot *)ent->entity; + + bot->UpdateBotStates(); + bot->GetUsercmd(&ucmd); + bot->GetEyeInfo(&eyeinfo); + + G_ClientThink(ent, &ucmd, &eyeinfo); + */ +} + +/* +=========== +G_FindFreeEntityForBot + +Find a free client slot +============ +*/ +gentity_t *G_FindFreeEntityForBot() +{ + gentity_t *ent; + int minNum = 0; + int i; + + if (sv_sharedbots->integer) { + minNum = 0; + } else { + minNum = maxclients->integer; + } + + for (i = minNum; i < game.maxclients; i++) { + ent = &g_entities[i]; + if (!ent->inuse && ent->client && !ent->client->pers.userinfo[0]) { + return ent; + } + } + + return NULL; +} + +/* +=========== +G_ChangeParent + +Fix parenting for entities that use the old number +============ +*/ +void G_ChangeParent(int oldNum, int newNum) +{ + gentity_t *ent; + int i; + + for (i = 0; i < game.maxentities; i++) { + ent = &g_entities[i]; + if (!ent->inuse || !ent->entity) { + continue; + } + + if (ent->s.parent == oldNum) { + ent->s.parent = newNum; + } + if (ent->r.ownerNum == oldNum) { + ent->r.ownerNum = newNum; + } + } +} + +/* +=========== +G_BotShift + +If the specified slot is used, the bot will be relocated +to the next free entity slot +============ +*/ +void G_BotShift(int clientNum) +{ + gentity_t *ent; + gentity_t *newEnt; + + ent = &g_entities[clientNum]; + if (!ent->inuse || !ent->client || !ent->entity) { + return; + } + + if (!botManager.getControllerManager().findController(ent->entity)) { + return; + } + + newEnt = G_FindFreeEntityForBot(); + if (!newEnt) { + G_RemoveBot(ent); + return; + } + + // + // Allocate the new entity + // + level.spawn_entnum = newEnt - g_entities; + level.AllocEdict(ent->entity); + + // + // Copy all fields + // + newEnt->s = ent->s; + newEnt->s.number = newEnt - g_entities; + memcpy(newEnt->client, ent->client, sizeof(*newEnt->client)); + newEnt->r = ent->r; + newEnt->solid = ent->solid; + newEnt->tiki = ent->tiki; + AxisCopy(ent->mat, newEnt->mat); + + newEnt->freetime = ent->freetime; + newEnt->spawntime = ent->spawntime; + newEnt->radius2 = ent->radius2; + memcpy(newEnt->entname, ent->entname, sizeof(newEnt->entname)); + newEnt->clipmask = ent->clipmask; + newEnt->entity = ent->entity; + newEnt->entity->edict = newEnt; + newEnt->entity->client = newEnt->client; + newEnt->entity->entnum = newEnt->s.number; + newEnt->client->ps.clientNum = newEnt->s.number; + + G_ChangeParent(ent->s.number, newEnt->s.number); + + // + // Free the old entity so the real client will use it + // + level.FreeEdict(ent); + memset(ent->client, 0, sizeof(*ent->client)); + + G_SetClientConfigString(newEnt); +} + +/* +=========== +G_GetFirstBot + +Return the first bot +============ +*/ +gentity_t *G_GetFirstBot() +{ + gentity_t *ent; + unsigned int n; + + for (n = 0; n < game.maxclients; n++) { + ent = &g_entities[n]; + if (G_IsBot(ent)) { + return ent; + } + } + + return NULL; +} + +/* +=========== +G_IsBot + +Return whether or not the gentity is a bot +============ +*/ +bool G_IsBot(gentity_t *ent) +{ + if (!ent->inuse || !ent->client) { + return false; + } + + if (!ent->entity || !botManager.getControllerManager().findController(ent->entity)) { + return false; + } + + return true; +} + +/* +=========== +G_IsPlayer + +Return whether or not the gentity is a player +============ +*/ +bool G_IsPlayer(gentity_t *ent) +{ + if (!ent->inuse || !ent->client) { + return false; + } + + if (!ent->entity || botManager.getControllerManager().findController(ent->entity)) { + return false; + } + + return true; +} + +/* +=========== +G_GetRandomAlliedPlayerModel +============ +*/ +const char *G_GetRandomAlliedPlayerModel() +{ + if (!alliedModelList.NumObjects()) { + return ""; + } + + const unsigned int index = rand() % alliedModelList.NumObjects(); + return alliedModelList[index]; +} + +/* +=========== +G_GetRandomGermanPlayerModel +============ +*/ +const char *G_GetRandomGermanPlayerModel() +{ + if (!germanModelList.NumObjects()) { + return ""; + } + + const unsigned int index = rand() % germanModelList.NumObjects(); + return germanModelList[index]; +} + +/* +=========== +G_AddBot + +Add the specified bot, optionally its saved state +============ +*/ +void G_AddBot(const saved_bot_t *saved) +{ + int i; + int clientNum; + gentity_t *e; + char botName[MAX_NETNAME]; + char challenge[MAX_STRING_TOKENS]; + Event *teamEv; + char userinfo[MAX_INFO_STRING] {0}; + + e = G_FindFreeEntityForBot(); + if (!e) { + gi.Printf("No free slot for a bot\n"); + return; + } + + clientNum = e - g_entities; + + // increase the unique ID + botId++; + + if (saved) { + G_BotConnect(clientNum, qfalse, saved->userinfo); + G_BotBegin(e); + return; + } + + if (gi.Argc() > 2) { + Q_strncpyz(botName, gi.Argv(2), sizeof(botName)); + } else { + Com_sprintf(botName, sizeof(botName), "bot%d", botId); + } + + Info_SetValueForKey(userinfo, "name", botName); + + // + // Choose a random model + // + Info_SetValueForKey(userinfo, "dm_playermodel", G_GetRandomAlliedPlayerModel()); + Info_SetValueForKey(userinfo, "dm_playergermanmodel", G_GetRandomGermanPlayerModel()); + + Info_SetValueForKey(userinfo, "fov", "80"); + Info_SetValueForKey(userinfo, "ip", "localhost"); + + // Connect the bot for the first time + // setup user info and stuff + G_BotConnect(clientNum, qtrue, userinfo); + + G_BotBegin(e); +} + +/* +=========== +G_AddBots + +Add the specified number of bots +============ +*/ +void G_AddBots(unsigned int num) +{ + int n; + + for (n = 0; n < num; n++) { + G_AddBot(NULL); + } +} + +/* +=========== +G_RemoveBot + +Remove the specified bot +============ +*/ +void G_RemoveBot(gentity_t *ent) +{ + if (ent->entity) { + BotController *controller = botManager.getControllerManager().findController(ent->entity); + + botManager.getControllerManager().removeController(controller); + } + + G_ClientDisconnect(ent); +} + +/* +=========== +G_RemoveBots + +Remove the specified number of bots +============ +*/ +void G_RemoveBots(unsigned int num) +{ + unsigned int removed = 0; + unsigned int n; + unsigned int teamCount[2] {0}; + bool bNoMoreToRemove = false; + + teamCount[0] = dmManager.GetTeamAllies()->m_players.NumObjects(); + teamCount[1] = dmManager.GetTeamAxis()->m_players.NumObjects(); + + while (!bNoMoreToRemove) { + bNoMoreToRemove = true; + + // First remove bots that are in the team + // with the higest player count + for (n = 0; n < game.maxclients && removed < num; n++) { + gentity_t *e = &g_entities[n]; + if (!G_IsBot(e)) { + continue; + } + + Player *player = static_cast(e->entity); + if (player->GetTeam() == TEAM_ALLIES || player->GetTeam() == TEAM_AXIS) { + unsigned int teamIndex = (player->GetTeam() - TEAM_ALLIES); + if (teamCount[teamIndex] < teamCount[1 - teamIndex]) { + // Not enough players in that team, don't remove the bot + continue; + } + + teamCount[teamIndex]--; + bNoMoreToRemove = false; + } + + G_RemoveBot(e); + removed++; + } + } + + // + // Remove all bots that haven't been removed earlier + // + for (n = 0; n < game.maxclients && removed < num; n++) { + gentity_t *e = &g_entities[n]; + if (!G_IsBot(e)) { + continue; + } + + G_RemoveBot(e); + removed++; + } +} + +/* +=========== +G_SaveBots + +Save bot persistent data +============ +*/ +void G_SaveBots() +{ + unsigned int count; + unsigned int n; if (saved_bots) { delete[] saved_bots; - saved_bots = NULL; + saved_bots = NULL; } - if (!current_bot_count) { - return; - } + const BotControllerManager& manager = botManager.getControllerManager(); + unsigned int numSpawnedBots = manager.getControllers().NumObjects(); - saved_bots = new saved_bot_t[current_bot_count]; - for (n = 0; n < current_bot_count; n++) { - gentity_t* e = &g_entities[game.maxclients - sv_maxbots->integer + n]; - saved_bot_t& saved = saved_bots[n]; + if (!numSpawnedBots) { + return; + } - if (e->inuse && e->client) - { - Player* player = static_cast(e->entity); + saved_bots = new saved_bot_t[numSpawnedBots]; + num_saved_bots = 0; - saved.bValid = true; - //saved.team = player->GetTeam(); - saved.pers = player->client->pers; - } - } + count = manager.getControllers().NumObjects(); + assert(count <= numSpawnedBots); + + for (n = 1; n <= count; n++) { + const BotController *controller = manager.getControllers().ObjectAt(n); + Player *player = controller->getControlledEntity(); + if (!player) { + // this shouldn't happen + continue; + } + + saved_bot_t& saved = saved_bots[num_saved_bots++]; + memcpy(saved.userinfo, player->client->pers.userinfo, sizeof(saved.userinfo)); + } } -void G_RestoreBots() { - unsigned int n; +/* +=========== +G_RestoreBots + +Restore bot persistent data, such as their team +============ +*/ +void G_RestoreBots() +{ + unsigned int n; if (!saved_bots) { - return; + return; } - for (n = 0; n < sv_numbots->integer; n++) { - saved_bot_t& saved = saved_bots[n]; + for (n = 0; n < num_saved_bots; n++) { + const saved_bot_t& saved = saved_bots[n]; - G_AddBot(1, &saved); - } + G_AddBot(&saved); + } - delete[] saved_bots; - saved_bots = NULL; + delete[] saved_bots; + saved_bots = NULL; } -void G_ResetBots() { - G_SaveBots(); +/* +=========== +G_CountPlayingClients - current_bot_count = 0; +Count the number of real clients that are playing +============ +*/ +int G_CountPlayingClients() +{ + gentity_t *other; + unsigned int n; + unsigned int count = 0; + + for (n = 0; n < game.maxclients; n++) { + other = &g_entities[n]; + if (G_IsPlayer(other)) { + Player *p = static_cast(other->entity); + // Ignore spectators + if (p->GetTeam() != teamtype_t::TEAM_NONE && p->GetTeam() != teamtype_t::TEAM_SPECTATOR) { + count++; + } + } + } + + return count; } -void G_SpawnBots() { - if (saved_bots) { - G_RestoreBots(); - } +/* +=========== +G_CountClients - if (sv_numbots->integer > current_bot_count) { - G_AddBot(sv_numbots->integer - current_bot_count); - } else if (sv_numbots->integer < current_bot_count) { - G_RemoveBot(current_bot_count - sv_numbots->integer); - } +Count the number of real clients +============ +*/ +int G_CountClients() +{ + gentity_t *other; + unsigned int n; + unsigned int count = 0; + + for (n = 0; n < game.maxclients; n++) { + other = &g_entities[n]; + if (G_IsBot(other)) { + continue; + } + + if (other->client && other->client->pers.userinfo[0]) { + count++; + } + } + + return count; +} + +/* +=========== +G_RestartBots + +Save bots +============ +*/ +void G_RestartBots() +{ + G_SaveBots(); +} + +/* +=========== +G_ResetBots + +Save and reset the bot count +============ +*/ +void G_ResetBots() +{ + botManager.Cleanup(); + + botId = 0; +} + +/* +=========== +G_BotInit + +Called to initialize bots +============ +*/ +void G_BotInit() +{ + InitModelList(); + botManager.Init(); +} + +/* +=========== +G_BotFrame + +Called each frame to manage bots +============ +*/ +void G_BotFrame() +{ + botManager.Frame(); +} + +/* +=========== +G_BotPostInit + +Called after the server has spawned +============ +*/ +void G_BotPostInit() +{ + G_RestoreBots(); + + G_SpawnBots(); +} + +/* +=========== +G_SpawnBots + +Called each frame to manage bot spawning +============ +*/ +void G_SpawnBots() +{ + unsigned int numClients; + unsigned int numBotsToSpawn; + unsigned int numSpawnedBots; + + // + // Check the minimum bot count + // + numClients = G_CountPlayingClients(); + if (numClients < sv_minPlayers->integer) { + numBotsToSpawn = sv_minPlayers->integer - numClients + sv_numbots->integer; + } else { + numBotsToSpawn = sv_numbots->integer; + } + + if (sv_sharedbots->integer) { + unsigned int numClients = G_CountClients(); + + // + // Cap to the maximum number of possible clients + // + numBotsToSpawn = Q_min(numBotsToSpawn, maxclients->integer - numClients + sv_maxbots->integer); + } else { + numBotsToSpawn = Q_min(numBotsToSpawn, sv_maxbots->integer); + } + + numSpawnedBots = botManager.getControllerManager().getControllers().NumObjects(); + + // + // Spawn bots + // + if (numBotsToSpawn > numSpawnedBots) { + G_AddBots(numBotsToSpawn - numSpawnedBots); + } else if (numBotsToSpawn < numSpawnedBots) { + G_RemoveBots(numSpawnedBots - numBotsToSpawn); + } } diff --git a/code/fgame/g_bot.h b/code/fgame/g_bot.h index f81addb1..5db1b88a 100644 --- a/code/fgame/g_bot.h +++ b/code/fgame/g_bot.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,18 +23,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #pragma once struct saved_bot_t { - client_persistant_t pers; - bool bValid; - - saved_bot_t() - : bValid(false) - {} + char userinfo[MAX_INFO_STRING]; }; -void G_BotBegin(gentity_t* ent); -void G_BotThink(gentity_t* ent, int msec); -gentity_t* G_GetFirstBot(); -void G_AddBot(unsigned int num, saved_bot_t* saved = NULL); -void G_RemoveBot(unsigned int num); -void G_ResetBots(); -void G_SpawnBots(); \ No newline at end of file +void G_BotBegin(gentity_t *ent); +void G_BotThink(gentity_t *ent, int msec); +void G_BotShift(int clientNum); +gentity_t *G_GetFirstBot(); +void G_AddBot(const saved_bot_t *saved = NULL); +void G_AddBots(unsigned int num); +void G_RemoveBot(gentity_t *ent); +void G_RemoveBots(unsigned int num); +bool G_IsBot(gentity_t *ent); +bool G_IsPlayer(gentity_t *ent); +void G_ResetBots(); +void G_RestartBots(); +void G_BotInit(); +void G_BotFrame(); +void G_BotPostInit(); +void G_SpawnBots(); +const char *G_GetRandomAlliedPlayerModel(); +const char *G_GetRandomGermanPlayerModel(); \ No newline at end of file diff --git a/code/fgame/g_client.cpp b/code/fgame/g_client.cpp index c11b7f24..3a69d78d 100644 --- a/code/fgame/g_client.cpp +++ b/code/fgame/g_client.cpp @@ -25,6 +25,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "playerbot.h" #include "playerstart.h" #include "scriptmaster.h" +#include "g_spawn.h" +#include "g_bot.h" // g_client.c -- client functions that don't happen every frame @@ -578,6 +580,10 @@ Chooses a player start, deathmatch start, etc PlayerStart *SelectSpawnPoint(Player *player) { PlayerStart *spot = NULL; + PlayerStart *spawnpoint; + const char *classID; + int i; + int nFound; switch (g_gametype->integer) { case GT_SINGLE_PLAYER: @@ -602,15 +608,41 @@ PlayerStart *SelectSpawnPoint(Player *player) // find a single player start spot if (!spot) { - while ((spot = (PlayerStart *)G_FindArchivedClass(spot, "info_player_start")) != NULL) { - if (level.spawnpoint.icmp(spot->TargetName()) == 0) { - break; + for (i = 1; i <= level.m_SimpleArchivedEntities.NumObjects(); i++) { + SimpleArchivedEntity *arc = level.m_SimpleArchivedEntities.ObjectAt(i); + + classID = arc->classinfo()->classID; + if (!Q_stricmp(classID, "info_player_start")) { + spawnpoint = static_cast(arc); + if (!str::icmp(level.spawnpoint, spawnpoint->TargetName())) { + spot = spawnpoint; + break; + } } } if (!spot && !level.spawnpoint.length()) { - // there wasn't a spawnpoint without a target, so use any - spot = (PlayerStart *)G_FindArchivedClass(NULL, "info_player_start"); + nFound = 0; + + for (i = 1; i <= level.m_SimpleArchivedEntities.NumObjects(); i++) { + SimpleArchivedEntity *arc = level.m_SimpleArchivedEntities.ObjectAt(i); + + classID = arc->classinfo()->classID; + // Fixed in OPM + // If there is no free spot, just use any random player start + // OG wants info_player_start directly + if (arc->isSubclassOf(PlayerStart)) { + int randVal; + + spawnpoint = static_cast(arc); + nFound++; + + randVal = rand(); + if (randVal == randVal / nFound * nFound) { + spot = spawnpoint; + } + } + } } if (!spot) { @@ -725,6 +757,7 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u) char *s; gclient_t *client; int clientnum; + char oldname[MAX_NAME_LENGTH]; if (!ent) { return; @@ -740,10 +773,19 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u) clientnum = ent - g_entities; - if (gi.SanitizeName(s, client->pers.netname)) { + Q_strncpyz(oldname, client->pers.netname, sizeof(oldname)); + if (gi.SanitizeName(s, client->pers.netname, sizeof(client->pers.netname))) { gi.Printf("WARNING: had to sanitize the name for client %i\n", clientnum); } + if (strcmp(oldname, client->pers.netname)) { + // + // Added in OPM + // Print name changes + // + gi.Printf("Client %i changed name from '%s' to '%s'\n", clientnum, oldname, client->pers.netname); + } + s = Info_ValueForKey(u, "dm_playermodel"); if (!s) { @@ -762,7 +804,7 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u) Q_strncpyz(client->pers.dm_playergermanmodel, s, sizeof(client->pers.dm_playergermanmodel)); - gi.setConfigstring(CS_PLAYERS + clientnum, va("name\\%s", client->pers.netname)); + G_SetClientConfigString(ent); if (ent->entity) { float fov; @@ -786,7 +828,7 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u) Q_strncpyz(client->pers.userinfo, u, sizeof(client->pers.userinfo)); } -void G_BotConnect(int clientNum, const char* userinfo) +void G_BotConnect(int clientNum, qboolean firstTime, const char *userinfo) { gclient_t *client; gentity_t *ent; @@ -795,13 +837,24 @@ void G_BotConnect(int clientNum, const char* userinfo) ent->client = game.clients + clientNum; ent->s.number = clientNum; + ent->r.svFlags |= SVF_BOT; client = ent->client; // read the session data memset(client, 0, sizeof(*client)); - G_InitSessionData(client, userinfo); + if (firstTime) { + memset(client, 0, sizeof(*client)); + if (!game.autosaved) { + G_InitClientPersistant(client, userinfo); + } + } else { + G_ReadClientSessionData(client); + } + // + // Use "localhost" as some code relies on it to check whether or not it should be kicked + // Q_strncpyz(client->pers.ip, "localhost", sizeof(client->pers.ip)); client->pers.port = 0; @@ -828,17 +881,15 @@ to the server machine, but qfalse on map changes and tournement restarts. ============ */ -const char *G_ClientConnect(int clientNum, qboolean firstTime) +const char *G_ClientConnect(int clientNum, qboolean firstTime, qboolean differentMap) { char *ip, *port, *value; gclient_t *client; gentity_t *ent; char userinfo[MAX_INFO_STRING]; - gi.DPrintf("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\n"); - if (!g_gametype->integer) { - return NULL; - } + // Added in OPM + G_BotShift(clientNum); ent = &g_entities[clientNum]; @@ -852,6 +903,7 @@ const char *G_ClientConnect(int clientNum, qboolean firstTime) port = Info_ValueForKey(userinfo, "port"); // FIXME: what is fucking wrong with G_FilterPacket... + // NOTE: IP banning is directly handled by the server //if ( G_FilterPacket( value ) ) { // return "Banned IP"; //} @@ -862,7 +914,8 @@ const char *G_ClientConnect(int clientNum, qboolean firstTime) if ((strcmp(ip, "localhost") != 0)) { // check for a password value = Info_ValueForKey(userinfo, "password"); - if (password->string[0] && Q_stricmp(password->string, "none") && strcmp(password->string, value) != 0) { + if (strcmp(sv_privatePassword->string, value) != 0 && *password->string + && strcmp(password->string, value) != 0) { return "Invalid password"; } } @@ -872,10 +925,23 @@ const char *G_ClientConnect(int clientNum, qboolean firstTime) // read or initialize the session data if (firstTime) { - memset(client, 0, sizeof(*client)); - G_InitSessionData(client, userinfo); + if (g_gametype->integer != GT_SINGLE_PLAYER || !cl_running->integer || clientNum != 0) { + // Added in OPM + // Accept remote clients but ignore the listen server + // so the client flags that were put during prespawn stay + memset(client, 0, sizeof(*client)); + } + if (!game.autosaved) { + G_InitClientPersistant(client, userinfo); + } } else { - G_ReadSessionData(client); + G_ReadClientSessionData(client); + // Added in 2.1 + // Let clients choose their primary weapon + // on map change + if (differentMap) { + client->pers.dm_primary[0] = 0; + } } Q_strncpyz(client->pers.ip, ip, sizeof(client->pers.ip)); @@ -895,7 +961,7 @@ const char *G_ClientConnect(int clientNum, qboolean firstTime) #endif // don't do the "xxx connected" messages if they were caried over from previous level - if (firstTime && g_gametype->integer) { + if (firstTime && g_gametype->integer != GT_SINGLE_PLAYER) { if (dedicated->integer) { gi.Printf("%s is preparing for deployment\n", client->pers.netname); } @@ -931,12 +997,7 @@ void G_ClientBegin(gentity_t *ent, usercmd_t *cmd) // a spawn point will completely reinitialize the entity level.spawn_entnum = ent->s.number; - if (level.m_bSpawnBot) { - level.m_bSpawnBot = false; - PlayerBot *player = new PlayerBot; - } else { - Player *player = new Player; - } + Player *player = new Player; } if (level.intermissiontime && ent->entity) { @@ -944,7 +1005,7 @@ void G_ClientBegin(gentity_t *ent, usercmd_t *cmd) } else { ent->client->pers.enterTime = level.svsFloatTime; - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { // send effect if in a multiplayer game if (dedicated->integer) { gi.Printf("%s has entered the battle\n", ent->client->pers.netname); @@ -1011,10 +1072,17 @@ void G_ClientDisconnect(gentity_t *ent) G_PrintToAllClients(va("%s has left the battle\n", ent->client->pers.netname), 2); + assert(ent->entity->IsSubclassOfPlayer()); ((Player *)ent->entity)->Disconnect(); - delete ent->entity; + if (g_iInThinks) { + ent->entity->PostEvent(EV_Remove, 0); + } else { + delete ent->entity; + } ent->entity = NULL; + + G_InitClientPersistant(ent->client); } catch (const char *error) { diff --git a/code/fgame/g_local.h b/code/fgame/g_local.h index fcf18650..ab4644ee 100644 --- a/code/fgame/g_local.h +++ b/code/fgame/g_local.h @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // g_local.h -- local definitions for game module -#ifndef __G_LOCAL_H__ -#define __G_LOCAL_H__ +#pragma once #include "q_shared.h" #include "bg_public.h" @@ -133,15 +132,6 @@ typedef struct { #define MAX_NETNAME 32 #define MAX_VOTE_COUNT 3 -typedef enum { - CS_FREE, - CS_ZOMBIE, - CS_CONNECTED, - CS_PRIMED, - CS_ACTIVE - -} clientState_t; - // // g_spawn.c // @@ -212,6 +202,7 @@ void G_PrintDeathMessage( ); void G_PrintDeathMessage_Old(const char *pszString); void G_WarnPlayer(class Player *player, const char *format, ...); +int G_NumClients(void); int G_WeaponIndex(const char *name); @@ -417,14 +408,14 @@ void G_RunThink(gentity_t *ent); void QDECL G_LogPrintf(const char *fmt, ...); void SendScoreboardMessageToAllClients(void); void QDECL G_Printf(const char *fmt, ...); -void QDECL G_Error(const char *fmt, ...); -void QDECL G_Error(errorParm_t type, const char *fmt, ...); +void QDECL G_Error(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2))); +void QDECL G_Error(errorParm_t type, const char *fmt, ...) __attribute__((noreturn, format(printf, 2, 3))); // // g_client.c // -void G_BotConnect(int clientNum, const char* userinfo); -const char *G_ClientConnect(int clientNum, qboolean firstTime); +void G_BotConnect(int clientNum, qboolean firstTime, const char* userinfo); +const char *G_ClientConnect(int clientNum, qboolean firstTime, qboolean differentMap); void G_ClientUserinfoChanged(gentity_t *ent, const char *userinfo); void G_ClientDisconnect(gentity_t *ent); void G_ClientBegin(gentity_t *ent, usercmd_t *cmd); @@ -437,6 +428,8 @@ void G_ClientCommand(gentity_t *ent); void G_ClientThink(gentity_t *ent, usercmd_t *cmd, usereyes_t *eyeinfo); void ClientEndFrame(gentity_t *ent); void G_ClientEndServerFrames(void); +void G_ClientDoBlends(void); +void FindIntermissionPoint(void); void G_RunClient(gentity_t *ent); // @@ -456,8 +449,8 @@ void Svcmd_GameMem_f(void); // // g_session.c // -void G_ReadSessionData(gclient_t *client); -void G_InitSessionData(gclient_t *client, const char *userinfo); +void G_ReadClientSessionData(gclient_t *client); +void G_InitClientPersistant(gclient_t *client, const char *userinfo); void G_InitWorldSession(void); void G_WriteSessionData(void); @@ -530,5 +523,3 @@ extern gentity_t *g_entities; #define FOFS(x) ((size_t) & (((gentity_t *)0)->x)) #include "g_utils.h" - -#endif /* g_local.h */ diff --git a/code/fgame/g_main.cpp b/code/fgame/g_main.cpp index 67b30501..ccb0e3f7 100644 --- a/code/fgame/g_main.cpp +++ b/code/fgame/g_main.cpp @@ -1,24 +1,25 @@ /* =========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2024 the OpenMoHAA team -This file is part of Quake III Arena source code. +This file is part of OpenMoHAA source code. -Quake III Arena source code is free software; you can redistribute it +OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. -Quake III Arena source code is distributed in the hope that it will be +OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software +along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ + // #include "g_local.h" @@ -34,6 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "lightstyleclass.h" #include "lodthing.h" #include "viewthing.h" +#include "smokesprite.h" #include "playerbot.h" #include "g_bot.h" #include @@ -61,11 +63,12 @@ gentity_t free_edicts; int sv_numtraces = 0; int sv_numpmtraces = 0; -int g_protocol = 0; -gentity_t *g_entities; -qboolean g_iInThinks = 0; -qboolean g_bBeforeThinks = qfalse; -static float g_fMsecPerClock = 0; +int g_protocol = 0; +target_game_e g_target_game = target_game_e::TG_INVALID; +gentity_t *g_entities; +qboolean g_iInThinks = 0; +qboolean g_bBeforeThinks = qfalse; +static float g_fMsecPerClock = 0; usercmd_t *current_ucmd; usereyes_t *current_eyeinfo; @@ -80,37 +83,52 @@ void (*SV_Free)(void *ptr); qboolean LevelArchiveValid(Archiver& arc); void ClosePlayerLogFile(void); +/* +=============== +G_Printf +=============== +*/ void QDECL G_Printf(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); - vsprintf(text, fmt, argptr); + Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); gi.Printf(text); } +/* +=============== +G_Error +=============== +*/ void QDECL G_Error(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); - vsprintf(text, fmt, argptr); + Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); gi.Error(ERR_DROP, text); } +/* +=============== +G_Error +=============== +*/ void QDECL G_Error(int type, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); - vsprintf(text, fmt, argptr); + Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); // need to manually crash otherwise visual studio fuck up with the stack pointer... @@ -209,9 +227,13 @@ void G_AllocGameData(void) void G_DeAllocGameData(void) { - // Initialize debug lines + // Free up debug lines G_DeAllocDebugLines(); + // Added in OPM + // Free up debug strings + G_DeAllocDebugStrings(); + // free up the entities if (g_entities) { gi.Free(g_entities); @@ -237,7 +259,8 @@ void G_InitGame(int levelTime, int randomSeed) G_Printf("gamename: %s\n", GAMEVERSION); G_Printf("gamedate: %s\n", __DATE__); - g_protocol = gi.Cvar_Get("com_protocol", "", 0)->integer; + g_protocol = gi.Cvar_Get("com_protocol", "", 0)->integer; + g_target_game = (target_game_e)gi.Cvar_Get("com_target_game", "0", 0)->integer; srand(randomSeed); @@ -247,21 +270,17 @@ void G_InitGame(int levelTime, int randomSeed) // set some level globals level.svsStartTime = levelTime; - level.specialgame = sv_specialgame->integer ? true : false; - if (level.specialgame) { - gi.cvar_set("protocol", "9"); - } G_InitConsoleCommands(); Director.Reset(); Actor::Init(); - PlayerBot::Init(); + G_BotInit(); sv_numtraces = 0; sv_numpmtraces = 0; - if (developer->integer && !g_gametype->integer) { + if (developer->integer && g_gametype->integer == GT_SINGLE_PLAYER) { Viewmodel.Init(); LODModel.Init(); } @@ -276,6 +295,12 @@ void G_InitGame(int levelTime, int randomSeed) L_InitEvents(); G_AllocGameData(); + + if (g_target_game < TG_MOHTA) { + // Added in OPM + // This frees alias list to avoid filling up memory + gi.GlobalAlias_Clear(); + } } /* @@ -287,8 +312,6 @@ G_SpawnEntities void G_SpawnEntities(char *entities, int svsTime) { level.SpawnEntities(entities, svsTime); - - G_SpawnBots(); } /* @@ -320,7 +343,7 @@ void QDECL Com_Error(int level, const char *error, ...) char text[1024]; va_start(argptr, error); - vsprintf(text, error, argptr); + Q_vsnprintf(text, sizeof(text), error, argptr); va_end(argptr); G_Error("%s", text); @@ -332,7 +355,7 @@ void QDECL Com_Printf(const char *msg, ...) char text[1024]; va_start(argptr, msg); - vsprintf(text, msg, argptr); + Q_vsnprintf(text, sizeof(text), msg, argptr); va_end(argptr); gi.DPrintf("%s", text); @@ -359,7 +382,13 @@ Called when server finished initializating */ void G_ServerSpawned(void) { - level.ServerSpawned(); + try { + level.ServerSpawned(); + + G_BotPostInit(); + } catch (const ScriptException& e) { + G_ExitWithError(e.string.c_str()); + } } /* @@ -392,7 +421,7 @@ void G_AddGEntity(gentity_t *edict, qboolean showentnums) } // remove the entity in case of invalid server flags - if ((edict->r.svFlags & SVF_NOTSINGLECLIENT) && (edict->r.svFlags & SVF_CAPSULE)) { + if ((edict->r.svFlags & SVF_SENDONCE) && (edict->r.svFlags & SVF_SENT)) { ent->PostEvent(EV_Remove, 0); } @@ -425,7 +454,6 @@ void G_RunFrame(int levelTime, int frameTime) qboolean showentnums; unsigned long long start; unsigned long long end; - int i; static int processed[MAX_GENTITIES] = {0}; static int processedFrameID = 0; @@ -455,16 +483,9 @@ void G_RunFrame(int levelTime, int frameTime) if (level.intermissiontime || level.died_already) { L_ProcessPendingEvents(); + G_ClientDoBlends(); - for (i = 0, edict = g_entities; i < game.maxclients; i++, edict++) { - if (!edict->inuse || !edict->client || !edict->entity) { - continue; - } - - edict->entity->CalcBlend(); - } - - if (g_gametype->integer && g_maxintermission->value != 0.0f) { + if (g_gametype->integer != GT_SINGLE_PLAYER && g_maxintermission->value != 0.0f) { if (level.time - level.intermissiontime > g_maxintermission->value) { level.exitintermission = true; } @@ -477,27 +498,28 @@ void G_RunFrame(int levelTime, int frameTime) gi.DPrintf2("====SERVER FRAME==========================================================================\n"); } - g_bBeforeThinks = true; - Director.iPaused = -1; + g_bBeforeThinks = true; + Director.AllowPause(false); // Process most of the events before the physics are run // so that we can affect the physics immediately L_ProcessPendingEvents(); - Director.iPaused = 1; + Director.AllowPause(true); + Director.Pause(); Director.SetTime(level.inttime); // // treat each object in turn // - for (edict = active_edicts.next, num = 0; edict != &active_edicts; edict = edict->next, num++) { + for (edict = active_edicts.next; edict != &active_edicts; edict = edict->next) { assert(edict); assert(edict->inuse); assert(edict->entity); - Actor *actor = (Actor *)edict->entity; + Actor *actor = static_cast(edict->entity); if (actor->IsSubclassOfActor()) { - actor->m_bUpdateAnimDoneFlags = 0; + actor->m_bUpdateAnimDoneFlags = false; if (actor->m_bAnimating) { actor->PreAnimate(); } @@ -519,9 +541,13 @@ void G_RunFrame(int levelTime, int frameTime) PathManager.ShowNodes(); - showentnums = (sv_showentnums->integer && (!g_gametype->integer || sv_cheats->integer)); + showentnums = (sv_showentnums->integer && (g_gametype->integer == GT_SINGLE_PLAYER || sv_cheats->integer)); g_iInThinks++; + + G_UpdateSmokeSprites(); + level.UpdateBadPlaces(); + processedFrameID++; if (g_entinfo->integer) { @@ -540,28 +566,16 @@ void G_RunFrame(int levelTime, int frameTime) start = clock(); } - for (edict = active_edicts.next; edict != &active_edicts; edict = edict->next) { - if (edict->entity->IsSubclassOfBot()) { - G_BotThink(edict, frameTime); - } - } + G_BotFrame(); for (edict = active_edicts.next; edict != &active_edicts; edict = edict->next) { - num = edict->s.parent; - - if (num != ENTITYNUM_NONE) { - while (1) { - if (processed[num] == processedFrameID) { - break; - } - - processed[num] = processedFrameID; - G_AddGEntity(edict, showentnums); - - if (edict->s.parent == ENTITYNUM_NONE) { - break; - } + for (num = edict->s.parent; num != ENTITYNUM_NONE; num = g_entities[num].s.parent) { + if (processed[num] == processedFrameID) { + break; } + + processed[num] = processedFrameID; + G_AddGEntity(&g_entities[num], showentnums); } if (processed[edict - g_entities] != processedFrameID) { @@ -618,13 +632,16 @@ void G_RunFrame(int levelTime, int frameTime) } } - level.framenum++; - // reset out count of the number of game traces sv_numtraces = 0; sv_numpmtraces = 0; - G_ClientDrawBoundingBoxes(); + level.framenum++; + + if (developer->integer) { + G_ClientDrawBoundingBoxes(); + G_ClientDrawTags(); + } G_UpdateMatchEndTime(); G_CheckExitRules(); @@ -632,7 +649,7 @@ void G_RunFrame(int levelTime, int frameTime) gi.setConfigstring(CS_WARMUP, va("%.0f", dmManager.GetMatchStartTime())); - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { level.CheckVote(); } @@ -646,8 +663,54 @@ void G_RunFrame(int levelTime, int frameTime) } } - // Add or delete bots that were added using addbot/removebot - G_SpawnBots(); + if (g_shownpc->integer) { + if (g_shownpc->integer > 1) { + g_shownpc->integer--; + } else { + int numActiveAllies = 0; + int numActiveAxis = 0; + int numAllies = 0; + int numAxis = 0; + + for (edict = active_edicts.next; edict != &active_edicts; edict = edict->next) { + Actor *actor; + + if (edict->entity->IsSubclassOfActor()) { + actor = static_cast(edict->entity); + + if (actor->health > 0) { + if (actor->m_Team == TEAM_AMERICAN) { + numAllies++; + if (actor->m_bDoAI) { + numActiveAllies++; + } + } else { + numAxis++; + if (actor->m_bDoAI) { + numActiveAxis++; + } + } + } + } + } + + gi.locationprintf( + &g_entities[0], + 94, + 28, + va("NPCS: Allies %d(%d) Axis %d(%d)", numActiveAllies, numAllies, numActiveAxis, numAxis) + ); + g_shownpc->integer = 60; + } + } + + if (level.Spawned()) { + // + // Added in OPM + // + // Add or delete bots that were added using addbot/removebot + G_SpawnBots(); + } } catch (const char *error) { @@ -667,7 +730,7 @@ void G_ClientDrawBoundingBoxes(void) Vector eye; // don't show bboxes during deathmatch - if ((!sv_showbboxes->integer) || (g_gametype->integer && !sv_cheats->integer)) { + if ((!sv_showbboxes->integer) || (g_gametype->integer != GT_SINGLE_PLAYER && !sv_cheats->integer)) { return; } @@ -685,20 +748,92 @@ void G_ClientDrawBoundingBoxes(void) } } +/* +================= +G_ClientDrawTags + +Added in 2.0. + +This draws tag position and orientation +for entities in a radius of 1000 units. +================= +*/ +void G_ClientDrawTags(void) +{ + Entity *player; + Entity *ent; + const char *tagName; + Vector origin; + orientation_t ori; + int numTags; + int i; + + if (!sv_showtags->string || !sv_showtags->string[0]) { + return; + } + + if (sv_showtags->string[0] != '*' && !sv_showtags->string[1] && sv_showtags->integer == 0) { + // The variable is defined but set to 0 + return; + } + + if (g_gametype->integer != GT_SINGLE_PLAYER && !sv_cheats->integer) { + return; + } + + player = G_GetEntity(0); + origin = player->origin; + + for (ent = findradius(NULL, origin, 1000); ent; ent = findradius(ent, origin, 1000)) { + if (!ent->edict->tiki) { + continue; + } + + if (ent == player) { + continue; + } + + numTags = gi.TIKI_NumTags(ent->edict->tiki); + for (i = 0; i < numTags; i++) { + tagName = gi.Tag_NameForNum(ent->edict->tiki, i); + + if (Q_stricmp(sv_showtags->string, "*")) { + // + // If it's not a wildcard, check to see if + // the tag name partially matches + // + if (Q_stricmpn(tagName, sv_showtags->string, strlen(sv_showtags->string))) { + continue; + } + } + + ent->GetTagPositionAndOrientation(i, &ori); + + G_DebugString(ori.origin + Vector(0, 0, 8), 1, 1, 1, 0, "%s", tagName); + G_DebugCircle(ori.origin, 10, 1, 1, 1, 1, true); + G_DebugLine(ori.origin, ori.origin + Vector(ori.axis[0]) * 32, 1, 0, 0, 1); + G_DebugLine(ori.origin, ori.origin + Vector(ori.axis[1]) * 32, 0, 1, 0, 1); + G_DebugLine(ori.origin, ori.origin + Vector(ori.axis[2]) * 32, 0, 0, 1, 1); + } + } +} + // Used to tell the server about the edict pose, such as the player pose // so that G_Trace with tracedeep will set the location void G_UpdatePoseInternal(gentity_t *edict) { - if (edict->s.number == ENTITYNUM_NONE || level.frame_skel_index != level.skel_index[edict->s.number]) { - gi.TIKI_SetPoseInternal( - edict->tiki, - edict->s.number, - edict->s.frameInfo, - edict->s.bone_tag, - edict->s.bone_quat, - edict->s.actionWeight - ); + if (edict->s.number != ENTITYNUM_NONE) { + if (level.skel_index[edict->s.number] == level.frame_skel_index) { + // no need to update + return; + } + + level.skel_index[edict->s.number] = level.frame_skel_index; } + + gi.TIKI_SetPoseInternal( + edict->tiki, edict->s.number, edict->s.frameInfo, edict->s.bone_tag, edict->s.bone_quat, edict->s.actionWeight + ); } orientation_t G_TIKI_Orientation(gentity_t *edict, int num) @@ -726,40 +861,66 @@ qboolean G_TIKI_IsOnGround(gentity_t *edict, int num, float threshold) void G_PrepFrame(void) {} -void G_RegisterSounds(void) +void G_RegisterSoundsForFile(const char *name) { int startTime; int endTime; - Com_Printf("\n\n-----------PARSING UBERSOUND (SERVER)------------\n"); + Com_Printf("\n\n-----------PARSING '%s' (SERVER)------------\n", name); Com_Printf( "Any SetCurrentTiki errors means that tiki wasn't prefetched and tiki-specific sounds for it won't work. To " "fix prefetch the tiki. Ignore if you don't use that tiki on this level.\n" ); startTime = gi.Milliseconds(); - G_Command_ProcessFile("ubersound/ubersound.scr", qfalse); + G_Command_ProcessFile(name, qfalse); endTime = gi.Milliseconds(); Com_Printf("Parse/Load time: %f seconds.\n", (float)(endTime - startTime) / 1000.0); - Com_Printf("-------------UBERSOUND DONE (SERVER)---------------\n\n"); - Com_Printf("\n\n-----------PARSING UBERDIALOG (SERVER)------------\n"); - Com_Printf( - "Any SetCurrentTiki errors means that tiki wasn't prefetched and tiki-specific sounds for it won't work. To " - "fix prefetch the tiki. Ignore if you don't use that tiki on this level.\n" - ); + Com_Printf("-------------PARSING '%s' DONE (SERVER)---------------\n\n", name); +} - startTime = gi.Milliseconds(); - G_Command_ProcessFile("ubersound/uberdialog.scr", qfalse); - endTime = gi.Milliseconds(); +int qsort_compare_strings(const void *s1, const void *s2) +{ + return Q_stricmp(*(const char **)s1, *(const char **)s2); +} - Com_Printf("Parse/Load time: %f seconds.\n", (float)(endTime - startTime) / 1000.0); - Com_Printf("-------------UBERDIALOG DONE (SERVER)---------------\n\n"); +void G_RegisterSounds(void) +{ + char **fileList; + int numFiles; + int i; + + if (g_target_game >= TG_MOHTA) { + gi.GlobalAlias_Clear(); + } else if (!dedicated->integer) { + // In 1.11 and below, the entire ubersound folder is parsed + // only in dedicated mode + return; + } + + fileList = gi.FS_ListFiles("ubersound/", "scr", qfalse, &numFiles); + qsort(fileList, numFiles, sizeof(char *), &qsort_compare_strings); + + for (i = 0; i < numFiles; i++) { + // Added in 2.0 + // Since 2.0, all files in the ubersound folder + // are parsed + G_RegisterSoundsForFile(va("ubersound/%s", fileList[i])); + } + + gi.FS_FreeFileList(fileList); } void G_Restart(void) { G_InitWorldSession(); + + // Added in 2.0 + G_ResetSmokeSprites(); + + // Added in OPM + G_RestartBots(); } void G_SetFrameNumber(int framenum) @@ -835,6 +996,7 @@ qboolean G_Command_ProcessFile(const char *filename, qboolean quiet) const char *bufstart; const char *token; int numTokens = 0; + char tempName[65]; if (gi.FS_ReadFile(filename, (void **)&buffer, quiet) == -1) { return qfalse; @@ -846,6 +1008,9 @@ qboolean G_Command_ProcessFile(const char *filename, qboolean quiet) bufstart = buffer; + Com_sprintf(tempName, sizeof(tempName), "m%s", filename); + gi.LoadResource(tempName); + while (1) { // grab each line as we go token = COM_ParseExt(&buffer, qtrue); @@ -882,14 +1047,14 @@ qboolean G_Command_ProcessFile(const char *filename, qboolean quiet) gi.FS_FreeFile((void *)bufstart); + Com_sprintf(tempName, sizeof(tempName), "o%s", filename); + gi.LoadResource(tempName); + return qtrue; } qboolean G_AllowPaused(void) { -#ifdef _DEBUG - return false; -#endif return (!level.exitintermission) && (level.intermissiontime == 0.0f) && (!level.died_already); } @@ -969,11 +1134,11 @@ void G_ArchivePersistant(const char *name, qboolean loading) arc.ArchiveInteger(&version); if (version < PERSISTANT_VERSION) { - gi.Printf("Persistant data from an older version (%d) of MOHAA.\n", version); + gi.Printf("Persistent data from an older version (%d) of MOHAA.\n", version); arc.Close(); return; } else if (version > PERSISTANT_VERSION) { - gi.DPrintf("Persistant data from newer version %d of MOHAA.\n", version); + gi.DPrintf("Persistent data from newer version %d of MOHAA.\n", version); arc.Close(); return; } @@ -1156,7 +1321,9 @@ G_ArchiveLevel ================= */ -qboolean G_ArchiveLevel(const char *filename, qboolean autosave, qboolean loading) +qboolean G_ArchiveLevel( + const char *filename, byte **savedCgameState, size_t *savedCgameStateSize, qboolean autosave, qboolean loading +) { try { int i; @@ -1200,19 +1367,34 @@ qboolean G_ArchiveLevel(const char *filename, qboolean autosave, qboolean loadin L_ArchiveEvents(arc); } + if (!arc.Saving()) { + arc.ArchiveInteger(&num); + *savedCgameStateSize = num; + + if (*savedCgameStateSize) { + *savedCgameState = (byte *)gi.Malloc(*savedCgameStateSize); + } else { + *savedCgameState = NULL; + } + } else { + num = (int)*savedCgameStateSize; + arc.ArchiveInteger(&num); + } + arc.ArchiveRaw(*savedCgameState, *savedCgameStateSize); + if (arc.Saving()) { str s; num = 0; for (cvar = gi.NextCvar(NULL); cvar != NULL; cvar = gi.NextCvar(cvar)) { - if (cvar->flags & CVAR_ROM) { + if (cvar->flags & CVAR_SAVEGAME) { num++; } } arc.ArchiveInteger(&num); for (cvar = gi.NextCvar(NULL); cvar != NULL; cvar = gi.NextCvar(cvar)) { - if (cvar->flags & CVAR_ROM) { + if (cvar->flags & CVAR_SAVEGAME) { s = cvar->name; arc.ArchiveString(&s); @@ -1263,11 +1445,12 @@ qboolean G_ArchiveLevel(const char *filename, qboolean autosave, qboolean loadin if (arc.Saving()) { // count the entities num = 0; - for (i = 0; i < globals.num_entities; i++) { - edict = &g_entities[i]; - if (edict->inuse && edict->entity && !(edict->entity->flags & FL_DONTSAVE)) { - num++; + for (edict = active_edicts.next; edict != &active_edicts; edict = edict->next) { + if (edict == world->edict || !edict->entity || (edict->entity->flags & FL_DONTSAVE)) { + continue; } + + num++; } } @@ -1279,11 +1462,12 @@ qboolean G_ArchiveLevel(const char *filename, qboolean autosave, qboolean loadin // write out the world arc.ArchiveObject(world); - for (i = 0; i < globals.num_entities; i++) { - edict = &g_entities[i]; - if (edict->inuse && edict->entity && !(edict->entity->flags & FL_DONTSAVE)) { - arc.ArchiveObject(edict->entity); + for (edict = active_edicts.next; edict != &active_edicts; edict = edict->next) { + if (edict == world->edict || !edict->entity || (edict->entity->flags & FL_DONTSAVE)) { + continue; } + + arc.ArchiveObject(edict->entity); } } else { // Tell the server about our data @@ -1302,23 +1486,35 @@ qboolean G_ArchiveLevel(const char *filename, qboolean autosave, qboolean loadin } } + // + // simple archived entities + // + if (!arc.Loading()) { + num = level.m_SimpleArchivedEntities.NumObjects(); + } + arc.ArchiveInteger(&num); + + if (arc.Saving()) { + for (i = 1; i <= num; i++) { + arc.ArchiveObject(level.m_SimpleArchivedEntities.ObjectAt(i)); + } + } else { + for (i = 1; i <= num; i++) { + arc.ReadObject(); + } + } + ArchiveAliases(arc); + // Added in 2.0 + G_ArchiveSmokeSprites(arc); + currentArc = &arc; gi.ArchiveLevel(arc.Loading()); currentArc = NULL; PathSearch::ArchiveDynamic(arc); - arc.Close(); - - if (arc.Loading()) { - LoadingSavegame = false; - gi.Printf(HUD_MESSAGE_YELLOW "%s\n", gi.LV_ConvertString("Game Loaded")); - } else { - gi.Printf(HUD_MESSAGE_YELLOW "%s\n", gi.LV_ConvertString("Game Saved")); - } - if (arc.Loading()) { // Make sure all code that needs to setup the player after they have been loaded is run @@ -1332,6 +1528,15 @@ qboolean G_ArchiveLevel(const char *filename, qboolean autosave, qboolean loadin } } + if (arc.Loading()) { + arc.Close(); + LoadingSavegame = false; + gi.Printf(HUD_MESSAGE_YELLOW "%s\n", gi.LV_ConvertString("Game Loaded")); + } else { + arc.Close(); + gi.Printf(HUD_MESSAGE_YELLOW "%s\n", gi.LV_ConvertString("Game Saved")); + } + return qtrue; } @@ -1347,10 +1552,10 @@ G_WriteLevel ================= */ -void G_WriteLevel(const char *filename, qboolean autosave) +void G_WriteLevel(const char *filename, qboolean autosave, byte **savedCgameState, size_t *savedCgameStateSize) { game.autosaved = autosave; - G_ArchiveLevel(filename, autosave, qfalse); + G_ArchiveLevel(filename, savedCgameState, savedCgameStateSize, autosave, qfalse); game.autosaved = false; } @@ -1369,11 +1574,11 @@ calling ReadLevel. No clients are connected yet. ================= */ -qboolean G_ReadLevel(const char *filename) +qboolean G_ReadLevel(const char *filename, byte **savedCgameState, size_t *savedCgameStateSize) { qboolean status; - status = G_ArchiveLevel(filename, qfalse, qtrue); + status = G_ArchiveLevel(filename, savedCgameState, savedCgameStateSize, qfalse, qtrue); // if the level load failed make sure that these variables are not set if (!status) { LoadingSavegame = false; @@ -1480,32 +1685,95 @@ void G_ClientEndServerFrames(void) } } -void G_ClientDoBlends() +/* +=============== +G_ClientDoBlends +=============== +*/ +void G_ClientDoBlends(void) { - // FIXME: unimplemented + gentity_t *edict; + int i; + + for (i = 0, edict = g_entities; i < game.maxclients; i++, edict++) { + if (!edict->inuse || !edict->client || !edict->entity) { + continue; + } + + edict->entity->CalcBlend(); + } } -void FindIntermissionPoint() +/* +=============== +FindIntermissionPoint +=============== +*/ +void FindIntermissionPoint(void) { - // FIXME: unimplemented + SimpleEntity *sent; + SimpleEntity *starget; + vec3_t dir; + + sent = static_cast(G_FindClass(NULL, "info_player_intermission")); + if (!sent) { + level.m_intermission_origin = vec_zero; + level.m_intermission_angle = vec_zero; + return; + } + + level.m_intermission_origin = sent->origin; + level.m_intermission_angle = sent->angles; + + if (!sent->target.length()) { + return; + } + + starget = static_cast(G_FindTarget(NULL, sent->Target())); + if (!starget) { + return; + } + + VectorSubtract(starget->origin, level.m_intermission_origin, dir); + vectoangles(dir, level.m_intermission_angle); } +/* +=============== +G_MoveClientToIntermission +=============== +*/ void G_MoveClientToIntermission(Entity *ent) { G_DisplayScores(ent); ent->flags |= FL_IMMOBILE; } +/* +=============== +G_DisplayScores +=============== +*/ void G_DisplayScores(Entity *ent) { ent->client->ps.pm_flags |= PMF_INTERMISSION; } +/* +=============== +G_HideScores +=============== +*/ void G_HideScores(Entity *ent) { ent->client->ps.pm_flags &= ~PMF_INTERMISSION; } +/* +=============== +G_BeginIntermission2 +=============== +*/ void G_BeginIntermission2(void) { gentity_t *client; @@ -1534,13 +1802,15 @@ void G_BeginIntermission2(void) continue; } - ent = client->entity; - - G_DisplayScores(ent); - ent->flags |= FL_IMMOBILE; + G_MoveClientToIntermission(client->entity); } } +/* +=============== +G_BeginIntermission +=============== +*/ void G_BeginIntermission(const char *map_name, INTTYPE_e transtype, bool no_fade) { Entity *camera; @@ -1549,7 +1819,7 @@ void G_BeginIntermission(const char *map_name, INTTYPE_e transtype, bool no_fade gentity_t *client; int i; - if (level.intermissiontime || g_gametype->integer) { + if (level.intermissiontime || g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -1588,6 +1858,11 @@ void G_BeginIntermission(const char *map_name, INTTYPE_e transtype, bool no_fade } } +/* +=============== +G_ExitLevel +=============== +*/ void G_ExitLevel(void) { static const char *seps = " ,\n\r"; @@ -1608,13 +1883,13 @@ void G_ExitLevel(void) Com_sprintf(command, sizeof(command), "stopsound\n"); gi.SendConsoleCommand(command); - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { if (strlen(sv_nextmap->string)) { // The nextmap cvar was set (possibly by a vote - so go ahead and use it) level.nextmap = sv_nextmap->string; gi.cvar_set("nextmap", ""); - } else // Use the next map in the maplist - { + } else { + // Use the next map in the maplist char *s, *f, *t; f = NULL; @@ -1624,19 +1899,17 @@ void G_ExitLevel(void) if (!Q_stricmp(t, level.mapname.c_str())) { // it's in the list, go to the next one t = strtok(NULL, seps); - if (t == NULL) // end of list, go to first one - { - if (f == NULL) // there isn't a first one, same level - { - level.nextmap = level.mapname; - } else { - level.nextmap = f; - } - } else { + if (t) { level.nextmap = t; + } else if (f) { + // end of list, go to first one + level.nextmap = f; + } else { + // there isn't a first one, same level + level.nextmap = level.mapname; } - free(s); - goto out; + + break; } // set the first map @@ -1647,23 +1920,22 @@ void G_ExitLevel(void) } free(s); } - out: + // level.nextmap should be set now, but if it isn't use the same map if (level.nextmap.length() == 0) { // Stay on the same map since no nextmap was set Com_sprintf(command, sizeof(command), "restart\n"); gi.SendConsoleCommand(command); - } - else if (level.nextmap == level.mapname) { + } else if (level.nextmap == level.mapname) { // Stay on the same map if it's the same as the current map Com_sprintf(command, sizeof(command), "restart\n"); gi.SendConsoleCommand(command); - } else if (!Q_stricmpn(level.nextmap, "vstr", 4) ) { + } else if (!Q_stricmpn(level.nextmap, "vstr", 4)) { // alias on another map - strcpy(command, level.nextmap); + Q_strncpyz(command, level.nextmap, sizeof(command)); gi.SendConsoleCommand(command); - } else // use the level.nextmap variable - { + } else { + // use the level.nextmap variable Com_sprintf(command, sizeof(command), "gamemap \"%s\"\n", level.nextmap.c_str()); gi.SendConsoleCommand(command); } @@ -1690,6 +1962,11 @@ void G_ExitLevel(void) G_ClientEndServerFrames(); } +/* +=============== +G_CheckIntermissionExit +=============== +*/ void G_CheckIntermissionExit(void) { if (!level.exitintermission && g_maxintermission->value > level.time - level.intermissiontime) { @@ -1707,11 +1984,21 @@ void G_CheckIntermissionExit(void) } } +/* +=============== +G_ExitIntermission +=============== +*/ void G_ExitIntermission(void) { level.exitintermission = qtrue; } +/* +=============== +G_CheckStartRules +=============== +*/ void G_CheckStartRules(void) { if ((!dmManager.IsGameActive()) && (!dmManager.WaitingForPlayers())) { @@ -1719,9 +2006,14 @@ void G_CheckStartRules(void) } } +/* +=============== +G_CheckExitRules +=============== +*/ void G_CheckExitRules(void) { - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { if (level.intermissiontime == 0.0f) { dmManager.CheckEndMatch(); } else { @@ -1730,6 +2022,11 @@ void G_CheckExitRules(void) } } +/* +=============== +G_DisplayScoresToAllClients +=============== +*/ void G_DisplayScoresToAllClients(void) { gentity_t *ent; @@ -1744,6 +2041,11 @@ void G_DisplayScoresToAllClients(void) } } +/* +=============== +G_HideScoresToAllClients +=============== +*/ void G_HideScoresToAllClients(void) { gentity_t *ent; @@ -1757,107 +2059,3 @@ void G_HideScoresToAllClients(void) G_HideScores(ent->entity); } } - -#ifndef WIN32 - -# include -# include - -struct sigaction origSignalActions[NSIG]; - -int backtrace(void **buffer, int size) -{ - return 0; -} - -char **backtrace_symbols(void *const *buffer, int size) -{ - return nullptr; -} - -void backtrace_symbols_fd(void *const *buffer, int size, int fd) {} - -void resetsighandlers(void) -{ - sigaction(SIGSEGV, &origSignalActions[SIGSEGV], NULL); - sigaction(SIGFPE, &origSignalActions[SIGFPE], NULL); - sigaction(SIGILL, &origSignalActions[SIGILL], NULL); - sigaction(SIGBUS, &origSignalActions[SIGBUS], NULL); - sigaction(SIGABRT, &origSignalActions[SIGABRT], NULL); - sigaction(SIGSYS, &origSignalActions[SIGSYS], NULL); -} - -void sighandler(int sig, siginfo_t *info, void *secret) -{ - void *trace[100]; - char **messages = (char **)NULL; - int i, trace_size = 0; - //ucontext_t *uc = (ucontext_t *)secret; - - char *signame = strsignal(sig); - - /* Do something useful with siginfo_t */ - if (sig == SIGSEGV) { - printf("Got signal %d - %s, faulty address is %p\n", sig, signame, info->si_addr); - - if (gi.Printf != NULL) { - gi.Printf("Got signal %d - %s, faulty address is %p\n", sig, signame, info->si_addr); - } - } else { - if (gi.Printf != NULL) { - gi.Printf("Got signal %d - %s\n", sig, signame); - } else { - printf("Got signal %d - %s\n", sig, signame); - } - } - - trace_size = backtrace(trace, 100); - - /* overwrite sigaction with caller's address */ - //trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP]; - - messages = (char **)(long)backtrace_symbols(trace, trace_size); - - printf("Execution path:\n"); - - if (gi.Printf != NULL) { - gi.Printf("Execution path:\n"); - } - - for (i = 1; i < trace_size; ++i) { /* skip first stack frame (points here) */ - printf(" --> %s\n", messages[i]); - - if (gi.Printf != NULL) { - gi.Printf(" --> %s\n", messages[i]); - } - } - - resetsighandlers( - ); // reset original MOHAA or default signal handlers, so no more signals are handled by this handler (a signal is considered to be a fatal program error, the original implementations should exit) - - raise(sig); -} - -void initsighandlers(void) -{ - /* Install our signal handlers */ - struct sigaction sa; - - sa.sa_sigaction = sighandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART | SA_SIGINFO; - - sigaction(SIGSEGV, &sa, &origSignalActions[SIGSEGV]); - sigaction(SIGFPE, &sa, &origSignalActions[SIGFPE]); - sigaction(SIGILL, &sa, &origSignalActions[SIGILL]); - sigaction(SIGBUS, &sa, &origSignalActions[SIGBUS]); - sigaction(SIGABRT, &sa, &origSignalActions[SIGABRT]); - sigaction(SIGSYS, &sa, &origSignalActions[SIGSYS]); -} - -void __attribute__((constructor)) load(void) -{ - initsighandlers(); -} - -#endif diff --git a/code/fgame/g_main.h b/code/fgame/g_main.h index 98f40509..7f57e781 100644 --- a/code/fgame/g_main.h +++ b/code/fgame/g_main.h @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // g_main.h -- Global header file for g_main.cpp -#ifndef __G_MAIN_H__ -#define __G_MAIN_H__ +#pragma once #include "g_local.h" #include "gamecvars.h" @@ -35,6 +34,7 @@ extern qboolean LoadingServer; extern game_import_t gi; extern game_export_t globals; extern int g_protocol; +extern target_game_e g_target_game; extern qboolean g_iInThinks; extern qboolean g_bBeforeThinks; @@ -53,5 +53,4 @@ void G_ExitWithError(const char *error); void G_AllocGameData(void); void G_DeAllocGameData(void); void G_ClientDrawBoundingBoxes(void); - -#endif /* g_main.h */ +void G_ClientDrawTags(void); diff --git a/code/fgame/g_mmove.cpp b/code/fgame/g_mmove.cpp index 7d7ecbaa..785324c4 100644 --- a/code/fgame/g_mmove.cpp +++ b/code/fgame/g_mmove.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -28,591 +28,548 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "game.h" typedef struct { - qboolean validGroundTrace; - trace_t groundTrace; - float previous_origin[ 3 ]; - float previous_velocity[ 3 ]; + qboolean validGroundTrace; + trace_t groundTrace; + float previous_origin[3]; + float previous_velocity[3]; } mml_t; mmove_t *mm; -mml_t mml; +mml_t mml; -void MM_ClipVelocity - ( - float *in, - float *normal, - float *out, - float overbounce - ) +void MM_ClipVelocity(float *in, float *normal, float *out, float overbounce) { - float backoff; - float dir_z; - float normal2[ 3 ]; + float backoff; + float dir_z; + float normal2[3]; - if( normal[ 2 ] >= 0.70f ) - { - if( in[ 0 ] == 0.0f && in[ 1 ] == 0.0f ) - { - VectorClear( out ); - return; - } + if (normal[2] >= MIN_WALK_NORMAL) { + if (in[0] == 0.0f && in[1] == 0.0f) { + VectorClear(out); + return; + } - normal2[ 0 ] = in[ 0 ] + DotProduct2D( in, normal ); - normal2[ 1 ] = in[ 1 ] + DotProduct2D( in, normal ); - normal2[ 2 ] = normal[ 2 ] * DotProduct2D( in, in ); + normal2[0] = in[0] * DotProduct2D(in, normal); + normal2[1] = in[1] * DotProduct2D(in, normal); + normal2[2] = normal[2] * DotProduct2D(in, in); - VectorNormalize( normal2 ); + VectorNormalize(normal2); - dir_z = -normal2[ 2 ]; + dir_z = -normal2[2]; - out[ 0 ] = in[ 0 ]; - out[ 1 ] = in[ 1 ]; - out[ 2 ] = DotProduct2D( in, normal2 ) / dir_z; - } - else - { - backoff = DotProduct( in, normal ); + out[0] = in[0]; + out[1] = in[1]; + out[2] = DotProduct2D(in, normal2) / dir_z; + } else { + backoff = DotProduct(in, normal); - if( backoff < 0 ) - backoff *= overbounce; - else - backoff /= overbounce; + if (backoff < 0) { + backoff *= overbounce; + } else { + backoff /= overbounce; + } - out[ 0 ] = in[ 0 ] - normal[ 0 ] * backoff; - out[ 1 ] = in[ 1 ] - normal[ 1 ] * backoff; - out[ 2 ] = in[ 2 ] - normal[ 2 ] * backoff; - } + out[0] = in[0] - normal[0] * backoff; + out[1] = in[1] - normal[1] * backoff; + out[2] = in[2] - normal[2] * backoff; + } } -qboolean MM_AddTouchEnt - ( - int entityNum - ) +qboolean MM_AddTouchEnt(int entityNum) { - int i; - qboolean blockEnt; - Entity *ent; + int i; + qboolean blockEnt; + Entity *ent; - if( entityNum == ENTITYNUM_NONE || entityNum == ENTITYNUM_WORLD ) { - return qtrue; - } + if (entityNum == ENTITYNUM_NONE || entityNum == ENTITYNUM_WORLD) { + return qtrue; + } - ent = G_GetEntity( entityNum ); + ent = G_GetEntity(entityNum); - blockEnt = ent->BlocksAIMovement(); + blockEnt = ent->BlocksAIMovement(); - if( !blockEnt ) - { - if( ent->IsSubclassOfPlayer() ) - { - mm->hit_temp_obstacle |= 1; - } - else if( ent->IsSubclassOfDoor() ) - { - mm->hit_temp_obstacle |= 2; - } - } + if (!blockEnt) { + if (ent->IsSubclassOfPlayer()) { + mm->hit_temp_obstacle |= 1; + } else if (ent->IsSubclassOfDoor()) { + mm->hit_temp_obstacle |= 2; + } + } - // see if it is already added - for( i = 0; i < mm->numtouch; i++ ) - { - if( mm->touchents[ i ] == entityNum ) - return blockEnt; - } + if (mm->numtouch == MAXTOUCH) { + return blockEnt; + } - // add it - mm->touchents[ mm->numtouch ] = entityNum; - mm->numtouch++; + // see if it is already added + for (i = 0; i < mm->numtouch; i++) { + if (mm->touchents[i] == entityNum) { + return blockEnt; + } + } - return blockEnt; + // add it + mm->touchents[mm->numtouch] = entityNum; + mm->numtouch++; + + return blockEnt; } -qboolean MM_SlideMove - ( - qboolean gravity - ) +qboolean MM_SlideMove(qboolean gravity) { - int bumpcount; - vec3_t dir; - float d; - int numplanes; - vec3_t planes[ 5 ]; - vec3_t clipVelocity; - int i; - int j; - int k; - trace_t trace; - vec3_t end; - float time_left; - qboolean bBlockEnt; + int bumpcount; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[5]; + vec3_t clipVelocity; + int i; + int j; + int k; + trace_t trace; + vec3_t end; + float time_left; + qboolean bBlockEnt; - if( gravity ) - { - mm->velocity[ 2 ] = mm->velocity[ 2 ] - mm->frametime * sv_gravity->integer; - if( mm->groundPlane ) - MM_ClipVelocity( mm->velocity, mm->groundPlaneNormal, mm->velocity, OVERCLIP ); - } + if (gravity) { + mm->velocity[2] = mm->velocity[2] - mm->frametime * sv_gravity->integer; + if (mm->groundPlane) { + MM_ClipVelocity(mm->velocity, mm->groundPlaneNormal, mm->velocity, OVERCLIP); + } + } - time_left = mm->frametime; + time_left = mm->frametime; - if( mm->groundPlane ) { - numplanes = 1; - VectorCopy( mm->groundPlaneNormal, planes[ 0 ] ); - } else { - numplanes = 0; - } + if (mm->groundPlane) { + numplanes = 1; + VectorCopy(mm->groundPlaneNormal, planes[0]); + } else { + numplanes = 0; + } - // never turn against original velocity - VectorNormalize2( mm->velocity, planes[ numplanes ] ); - numplanes++; + // never turn against original velocity + VectorNormalize2(mm->velocity, planes[numplanes]); + numplanes++; - for( bumpcount = 0; bumpcount < 4; bumpcount++ ) - { - // calculate position we are trying to move to - VectorMA( mm->origin, time_left, mm->velocity, end ); + for (bumpcount = 0; bumpcount < 4; bumpcount++) { + // calculate position we are trying to move to + VectorMA(mm->origin, time_left, mm->velocity, end); - // see if we can make it there - gi.trace( &trace, mm->origin, mm->mins, mm->maxs, end, mm->entityNum, mm->tracemask, qtrue, qfalse ); + // see if we can make it there + gi.trace(&trace, mm->origin, mm->mins, mm->maxs, end, mm->entityNum, mm->tracemask, qtrue, qfalse); - if( trace.allsolid ) - break; + if (trace.allsolid) { + break; + } - if( trace.fraction > 0 ) { - // actually covered some distance - VectorCopy( trace.endpos, mm->origin ); - } + if (trace.fraction > 0) { + // actually covered some distance + VectorCopy(trace.endpos, mm->origin); + } - if( trace.fraction == 1 ) - return bumpcount != 0; + if (trace.fraction == 1) { + return bumpcount != 0; + } - // save entity for contact - bBlockEnt = MM_AddTouchEnt( trace.entityNum ); + // save entity for contact + bBlockEnt = MM_AddTouchEnt(trace.entityNum); - if( trace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - if( trace.plane.normal[ 2 ] > -0.999f && bBlockEnt && mm->groundPlane ) - { - if( !mm->hit_obstacle ) - { - mm->hit_obstacle = true; - VectorCopy( mm->origin, mm->hit_origin ); - } + if (trace.plane.normal[2] < MIN_WALK_NORMAL) { + if (trace.plane.normal[2] > -0.999f && bBlockEnt && mm->groundPlane) { + if (!mm->hit_obstacle) { + mm->hit_obstacle = true; + VectorCopy(mm->origin, mm->hit_origin); + } - VectorAdd( mm->obstacle_normal, trace.plane.normal, mm->obstacle_normal ); - } - } - else - { - memcpy( &mml.groundTrace, &trace, sizeof( mml.groundTrace ) ); - mml.validGroundTrace = true; - } + VectorAdd(mm->obstacle_normal, trace.plane.normal, mm->obstacle_normal); + } + } else { + memcpy(&mml.groundTrace, &trace, sizeof(mml.groundTrace)); + mml.validGroundTrace = true; + } - time_left -= time_left * trace.fraction; + time_left -= time_left * trace.fraction; - if( numplanes >= MAX_CLIP_PLANES ) - { - VectorClear( mm->velocity ); - return qtrue; - } + if (numplanes >= MAX_CLIP_PLANES) { + VectorClear(mm->velocity); + return qtrue; + } - // - // if this is the same plane we hit before, nudge velocity - // out along it, which fixes some epsilon issues with - // non-axial planes - // - for( i = 0; i < numplanes; i++ ) - { - if( DotProduct( trace.plane.normal, planes[ i ] ) > 0.99 ) - { - VectorAdd( trace.plane.normal, mm->velocity, mm->velocity ); - break; - } - } + // + // if this is the same plane we hit before, nudge velocity + // out along it, which fixes some epsilon issues with + // non-axial planes + // + for (i = 0; i < numplanes; i++) { + if (DotProduct(trace.plane.normal, planes[i]) > 0.99) { + VectorAdd(trace.plane.normal, mm->velocity, mm->velocity); + break; + } + } - if( i >= numplanes ) - { - // - // modify velocity so it parallels all of the clip planes - // + if (i >= numplanes) { + // + // modify velocity so it parallels all of the clip planes + // + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; - // find a plane that it enters - for( i = 0; i < numplanes; i++ ) - { - if( DotProduct( mm->velocity, planes[ i ] ) >= 0.1 ) { - continue; // move doesn't interact with the plane - } + // find a plane that it enters + for (i = 0; i < numplanes; i++) { + if (DotProduct(mm->velocity, planes[i]) >= 0.1) { + continue; // move doesn't interact with the plane + } - // slide along the plane - MM_ClipVelocity( mm->velocity, planes[ i ], clipVelocity, OVERCLIP ); + // slide along the plane + MM_ClipVelocity(mm->velocity, planes[i], clipVelocity, OVERCLIP); - // see if there is a second plane that the new move enters - for( j = 0; j < numplanes; j++ ) - { - if( j == i ) { - continue; - } + // see if there is a second plane that the new move enters + for (j = 0; j < numplanes; j++) { + if (j == i) { + continue; + } - // slide along the plane - MM_ClipVelocity( mm->velocity, planes[ j ], clipVelocity, OVERCLIP ); + if (DotProduct(clipVelocity, planes[j]) >= 0.1) { + continue; // move doesn't interact with the plane + } - if( DotProduct( clipVelocity, planes[ j ] ) >= 0.0f ) { - continue; // move doesn't interact with the plane - } + // slide along the plane + MM_ClipVelocity(clipVelocity, planes[j], clipVelocity, OVERCLIP); - // slide the original velocity along the crease - CrossProduct( planes[ i ], planes[ j ], dir ); - VectorNormalize( dir ); - d = DotProduct( dir, mm->velocity ); - VectorScale( dir, d, clipVelocity ); + if (DotProduct(clipVelocity, planes[i]) >= 0) { + continue; // move doesn't interact with the plane + } - // see if there is a third plane the the new move enters - for( k = 0; k < numplanes; k++ ) - { - if( k == i || k == j ) { - continue; - } + // slide the original velocity along the crease + CrossProduct(planes[i], planes[j], dir); + VectorNormalize(dir); + d = DotProduct(dir, mm->velocity); + VectorScale(dir, d, clipVelocity); - if( DotProduct( clipVelocity, planes[ k ] ) >= 0.1f ) { - continue; // move doesn't interact with the plane - } + // see if there is a third plane the the new move enters + for (k = 0; k < numplanes; k++) { + if (k == i || k == j) { + continue; + } - // stop dead at a tripple plane interaction - VectorClear( mm->velocity ); - return qtrue; - } - } + if (DotProduct(clipVelocity, planes[k]) >= 0.1) { + continue; // move doesn't interact with the plane + } - // if we have fixed all interactions, try another move - VectorCopy( clipVelocity, mm->velocity ); - break; - } - } - } + // stop dead at a tripple plane interaction + VectorClear(mm->velocity); + return qtrue; + } + } - if( mm->velocity[ 0 ] || mm->velocity[ 1 ] ) - { - if( mm->groundPlane ) - { - VectorCopy( mm->velocity, dir ); - VectorNegate( dir, dir ); - VectorNormalize( dir ); + // if we have fixed all interactions, try another move + VectorCopy(clipVelocity, mm->velocity); + break; + } + } + } - if( MM_AddTouchEnt( trace.entityNum ) ) - { - if( !mm->hit_obstacle ) - { - mm->hit_obstacle = true; - VectorCopy( mm->origin, mm->hit_origin ); - } + if (mm->velocity[0] || mm->velocity[1]) { + if (mm->groundPlane) { + VectorCopy(mm->velocity, dir); + VectorNegate(dir, dir); + VectorNormalize(dir); - VectorAdd( mm->obstacle_normal, dir, mm->obstacle_normal ); - } - } + if (MM_AddTouchEnt(trace.entityNum)) { + if (!mm->hit_obstacle) { + mm->hit_obstacle = true; + VectorCopy(mm->origin, mm->hit_origin); + } - VectorClear( mm->velocity ); - return true; - } + VectorAdd(mm->obstacle_normal, dir, mm->obstacle_normal); + } + } - mm->velocity[ 2 ] = 0; - return false; + VectorClear(mm->velocity); + return true; + } + + mm->velocity[2] = 0; + return false; } -void MM_GroundTraceInternal - ( - void - ) +void MM_GroundTraceInternal(void) { - if( mml.groundTrace.fraction == 1.0f ) - { - mm->groundPlane = qfalse; - mm->walking = qfalse; - return; - } + if (mml.groundTrace.fraction == 1.0f) { + mm->groundPlane = qfalse; + mm->walking = qfalse; + return; + } - if( mm->velocity[ 2 ] > 0.0f ) - { - if( DotProduct( mm->velocity, mml.groundTrace.plane.normal ) > 10.0f ) - { - mm->groundPlane = qfalse; - mm->walking = qfalse; - return; - } - } + if (mm->velocity[2] > 0.0f) { + if (DotProduct(mm->velocity, mml.groundTrace.plane.normal) > 10.0f) { + mm->groundPlane = qfalse; + mm->walking = qfalse; + return; + } + } - // slopes that are too steep will not be considered onground - if( mml.groundTrace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - vec3_t oldvel; - float d; + // slopes that are too steep will not be considered onground + if (mml.groundTrace.plane.normal[2] < MIN_WALK_NORMAL) { + vec3_t oldvel; + float d; - VectorCopy( mm->velocity, oldvel ); - VectorSet( mm->velocity, 0, 0, -1.0f / mm->frametime ); - MM_SlideMove( qfalse ); + VectorCopy(mm->velocity, oldvel); + VectorSet(mm->velocity, 0, 0, -1.0f / mm->frametime); + MM_SlideMove(qfalse); - d = VectorLength( mm->velocity ); - VectorCopy( oldvel, mm->velocity ); + d = VectorLength(mm->velocity); + VectorCopy(oldvel, mm->velocity); - if( d > ( 0.1f / mm->frametime ) ) - { - mm->groundPlane = qtrue; - mm->walking = qfalse; - VectorCopy( mml.groundTrace.plane.normal, mm->groundPlaneNormal ); - return; - } - } + if (d > (0.1f / mm->frametime)) { + mm->groundPlane = qtrue; + mm->walking = qfalse; + VectorCopy(mml.groundTrace.plane.normal, mm->groundPlaneNormal); + return; + } + } - mm->groundPlane = qtrue; - mm->walking = qtrue; - VectorCopy( mml.groundTrace.plane.normal, mm->groundPlaneNormal ); + mm->groundPlane = qtrue; + mm->walking = qtrue; + VectorCopy(mml.groundTrace.plane.normal, mm->groundPlaneNormal); - MM_AddTouchEnt( mml.groundTrace.entityNum ); + MM_AddTouchEnt(mml.groundTrace.entityNum); } -void MM_GroundTrace - ( - void - ) +void MM_GroundTrace(void) { - float point[ 3 ]; + float point[3]; - point[ 0 ] = mm->origin[ 0 ]; - point[ 1 ] = mm->origin[ 1 ]; - point[ 2 ] = mm->origin[ 2 ] - 0.25f; + point[0] = mm->origin[0]; + point[1] = mm->origin[1]; + point[2] = mm->origin[2] - 0.25f; - gi.trace( &mml.groundTrace, mm->origin, mm->mins, mm->maxs, point, mm->entityNum, mm->tracemask, qtrue, qfalse ); - MM_GroundTraceInternal(); + gi.trace(&mml.groundTrace, mm->origin, mm->mins, mm->maxs, point, mm->entityNum, mm->tracemask, qtrue, qfalse); + MM_GroundTraceInternal(); } -void MM_StepSlideMove - ( - void - ) +void MM_StepSlideMove(void) { - vec3_t start_o; - vec3_t start_v; - vec3_t nostep_o; - vec3_t nostep_v; - trace_t trace; - qboolean bWasOnGoodGround; - vec3_t up; - vec3_t down; - qboolean start_hit_wall; - vec3_t start_wall_normal; - qboolean first_hit_wall; - vec3_t first_wall_normal; - vec3_t start_hit_origin; - vec3_t first_hit_origin; - trace_t nostep_groundTrace; + vec3_t start_o; + vec3_t start_v; + vec3_t nostep_o; + vec3_t nostep_v; + trace_t trace; + qboolean bWasOnGoodGround; + vec3_t up; + vec3_t down; + qboolean start_hit_wall; + vec3_t start_wall_normal; + qboolean first_hit_wall; + vec3_t first_wall_normal; + vec3_t start_hit_origin; + vec3_t first_hit_origin; + trace_t nostep_groundTrace; + qboolean nostep_validGroundTrace; - VectorCopy( mm->origin, start_o ); - VectorCopy( mm->velocity, start_v ); - start_hit_wall = mm->hit_obstacle; - VectorCopy( mm->hit_origin, start_hit_origin ); - VectorCopy( mm->obstacle_normal, start_wall_normal ); + VectorCopy(mm->origin, start_o); + VectorCopy(mm->velocity, start_v); + start_hit_wall = mm->hit_obstacle; + VectorCopy(mm->hit_origin, start_hit_origin); + VectorCopy(mm->obstacle_normal, start_wall_normal); - if( MM_SlideMove( qtrue ) == 0 ) - { - if( !mml.validGroundTrace ) - MM_GroundTrace(); + if (MM_SlideMove(qtrue) == 0) { + if (mml.validGroundTrace) { + MM_GroundTraceInternal(); + } else { + MM_GroundTrace(); + } - return; - } + return; + } - VectorCopy( start_o, down ); - down[ 2 ] -= STEPSIZE; - gi.trace( &trace, start_o, mm->mins, mm->maxs, down, mm->entityNum, mm->tracemask, qtrue, qfalse ); - VectorSet( up, 0, 0, 1 ); + VectorCopy(start_o, down); + down[2] -= STEPSIZE; + gi.trace(&trace, start_o, mm->mins, mm->maxs, down, mm->entityNum, mm->tracemask, qtrue, qfalse); + VectorSet(up, 0, 0, 1); - // never step up when you still have up velocity - if( mm->velocity[ 2 ] > 0 && ( trace.fraction == 1.0f || - DotProduct( trace.plane.normal, up ) < MIN_WALK_NORMAL ) ) - { - if( !mml.validGroundTrace ) - MM_GroundTrace(); - else - MM_GroundTraceInternal(); + // never step up when you still have up velocity + if (mm->velocity[2] > 0 && (trace.fraction == 1.0f || DotProduct(trace.plane.normal, up) < MIN_WALK_NORMAL)) { + if (mml.validGroundTrace) { + MM_GroundTraceInternal(); + } else { + MM_GroundTrace(); + } - return; - } + return; + } - if( mm->groundPlane && mm->groundPlaneNormal[ 2 ] >= MIN_WALK_NORMAL ) - bWasOnGoodGround = qtrue; - else - bWasOnGoodGround = qfalse; + if (mm->groundPlane && mm->groundPlaneNormal[2] >= MIN_WALK_NORMAL) { + bWasOnGoodGround = qtrue; + } else { + bWasOnGoodGround = qfalse; + } - VectorCopy( mm->origin, nostep_o ); - VectorCopy( mm->velocity, nostep_v ); - memcpy( &nostep_groundTrace, &mml.groundTrace, sizeof( trace_t ) ); + VectorCopy(start_o, up); + up[2] += 18; - VectorCopy( start_o, mm->origin ); - VectorCopy( start_v, mm->velocity ); + VectorCopy(mm->origin, nostep_o); + VectorCopy(mm->velocity, nostep_v); + memcpy(&nostep_groundTrace, &mml.groundTrace, sizeof(trace_t)); + // Fixed in OPM + // Save the valid ground trace + nostep_validGroundTrace = mml.validGroundTrace; - first_hit_wall = mm->hit_obstacle; - VectorCopy( mm->hit_origin, first_hit_origin ); - VectorCopy( mm->obstacle_normal, first_wall_normal ); + VectorCopy(up, mm->origin); + VectorCopy(start_v, mm->velocity); - mm->hit_obstacle = start_hit_wall; - VectorCopy( start_hit_origin, mm->hit_origin ); - VectorCopy( start_wall_normal, mm->obstacle_normal ); - MM_SlideMove( qtrue ); + first_hit_wall = mm->hit_obstacle; + VectorCopy(mm->hit_origin, first_hit_origin); + VectorCopy(mm->obstacle_normal, first_wall_normal); - VectorCopy( mm->origin, down ); - down[ 2 ] -= STEPSIZE * 2; + mm->hit_obstacle = start_hit_wall; + VectorCopy(start_hit_origin, mm->hit_origin); + VectorCopy(start_wall_normal, mm->obstacle_normal); + MM_SlideMove(qtrue); - // test the player position if they were a stepheight higher - gi.trace( &trace, up, mm->mins, mm->maxs, up, mm->entityNum, mm->tracemask, qtrue, qfalse ); - if( trace.entityNum > ENTITYNUM_NONE ) - { - VectorCopy( nostep_o, mm->origin ); - VectorCopy( nostep_v, mm->velocity ); - memcpy( &mml.groundTrace, &nostep_groundTrace, sizeof( mml.groundTrace ) ); - mm->hit_obstacle = first_hit_wall; - VectorCopy( first_hit_origin, mm->hit_origin ); - VectorCopy( first_wall_normal, mm->obstacle_normal ); + VectorCopy(mm->origin, down); + down[2] -= STEPSIZE * 2; - if( !mml.validGroundTrace ) - MM_GroundTrace(); - else - MM_GroundTraceInternal(); + // test the player position if they were a stepheight higher + gi.trace(&trace, mm->origin, mm->mins, mm->maxs, down, mm->entityNum, mm->tracemask, qtrue, qfalse); + if (trace.entityNum != ENTITYNUM_WORLD && trace.entityNum != ENTITYNUM_NONE) { + VectorCopy(nostep_o, mm->origin); + VectorCopy(nostep_v, mm->velocity); + memcpy(&mml.groundTrace, &nostep_groundTrace, sizeof(mml.groundTrace)); + // Fixed in OPM + // Do not use the ground trace as it's invalid and would have an invalid entity number + mml.validGroundTrace = nostep_validGroundTrace; - return; - } - - if( !trace.allsolid ) - { - memcpy( &mml.groundTrace, &trace, sizeof( mml.groundTrace ) ); - mml.validGroundTrace = qtrue; + mm->hit_obstacle = first_hit_wall; + VectorCopy(first_hit_origin, mm->hit_origin); + VectorCopy(first_wall_normal, mm->obstacle_normal); - if( bWasOnGoodGround && trace.fraction && trace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - VectorCopy( nostep_o, mm->origin ); - VectorCopy( nostep_v, mm->velocity ); + if (mml.validGroundTrace) { + MM_GroundTraceInternal(); + } else { + MM_GroundTrace(); + } - if( first_hit_wall ) - { - mm->hit_obstacle = first_hit_wall; - VectorCopy( first_hit_origin, mm->hit_origin ); - VectorCopy( first_wall_normal, mm->obstacle_normal ); - } + return; + } - MM_GroundTraceInternal(); - return; - } + if (!trace.allsolid) { + memcpy(&mml.groundTrace, &trace, sizeof(mml.groundTrace)); + mml.validGroundTrace = qtrue; - VectorCopy( trace.endpos, mm->origin ); - } + if (bWasOnGoodGround && trace.fraction < 1 && trace.plane.normal[2] < MIN_WALK_NORMAL) { + VectorCopy(nostep_o, mm->origin); + VectorCopy(nostep_v, mm->velocity); - if( trace.fraction < 1.0f ) - MM_ClipVelocity( mm->velocity, trace.plane.normal, mm->velocity, OVERCLIP ); + if (first_hit_wall) { + mm->hit_obstacle = first_hit_wall; + VectorCopy(first_hit_origin, mm->hit_origin); + VectorCopy(first_wall_normal, mm->obstacle_normal); + } - if( !mml.validGroundTrace ) - MM_GroundTrace(); - else - MM_GroundTraceInternal(); + MM_GroundTraceInternal(); + return; + } + + VectorCopy(trace.endpos, mm->origin); + } + + if (trace.fraction < 1) { + MM_ClipVelocity(mm->velocity, trace.plane.normal, mm->velocity, OVERCLIP); + } + + if (mml.validGroundTrace) { + MM_GroundTraceInternal(); + } else { + MM_GroundTrace(); + } } -void MM_ClipVelocity2D - ( - float *in, - float *normal, - float *out, - float overbounce - ) +void MM_ClipVelocity2D(float *in, float *normal, float *out, float overbounce) { - float backoff; - float dir_z; - float normal2[ 3 ]; + float backoff; + float dir_z; + float normal2[3]; - if( normal[ 2 ] >= 0.70f ) - { - if( in[ 0 ] == 0.0f && in[ 1 ] == 0.0f ) - { - VectorClear( out ); - return; - } + if (normal[2] >= MIN_WALK_NORMAL) { + if (in[0] == 0.0f && in[1] == 0.0f) { + VectorClear(out); + return; + } - normal2[ 0 ] = in[ 0 ] + DotProduct2D( in, normal ); - normal2[ 1 ] = in[ 1 ] + DotProduct2D( in, normal ); - normal2[ 2 ] = normal[ 2 ] * DotProduct2D( in, in ); + normal2[0] = in[0] * DotProduct2D(in, normal); + normal2[1] = in[1] * DotProduct2D(in, normal); + normal2[2] = normal[2] * DotProduct2D(in, in); - VectorNormalize( normal2 ); + VectorNormalize(normal2); - dir_z = -normal2[ 2 ]; + dir_z = -normal2[2]; - out[ 0 ] = in[ 0 ]; - out[ 1 ] = in[ 1 ]; - out[ 2 ] = DotProduct2D( in, normal2 ) / -normal2[ 2 ]; - } - else - { - backoff = DotProduct2D( in, normal ); + out[0] = in[0]; + out[1] = in[1]; + out[2] = DotProduct2D(in, normal2) / dir_z; + } else { + backoff = DotProduct2D(in, normal); - if( backoff < 0 ) - backoff *= overbounce; - else - backoff /= overbounce; + if (backoff < 0) { + backoff *= overbounce; + } else { + backoff /= overbounce; + } - out[ 0 ] = in[ 0 ] - normal[ 0 ] * backoff; - out[ 1 ] = in[ 1 ] - normal[ 1 ] * backoff; - out[ 2 ] = -( backoff * normal[ 2 ] ); - } + out[0] = in[0] - normal[0] * backoff; + out[1] = in[1] - normal[1] * backoff; + out[2] = -(backoff * normal[2]); + } } -void MmoveSingle - ( - mmove_t *mmove - ) +void MmoveSingle(mmove_t *mmove) { - float point[ 3 ]; - trace_t trace; + float point[3]; + trace_t trace; - mm = mmove; + mm = mmove; - mmove->hit_obstacle = false; - mmove->numtouch = false; - VectorCopy( vec_origin, mmove->obstacle_normal ); - mmove->hit_temp_obstacle = false; + mmove->numtouch = 0; + mm->hit_obstacle = false; + VectorCopy(vec3_origin, mm->obstacle_normal); + mm->hit_temp_obstacle = false; - memset( &mml, 0, sizeof( mml_t ) ); + memset(&mml, 0, sizeof(mml_t)); - VectorCopy( mmove->origin, mml.previous_origin ); - VectorCopy( mmove->velocity, mml.previous_velocity ); + VectorCopy(mm->origin, mml.previous_origin); + VectorCopy(mm->velocity, mml.previous_velocity); - if( mmove->walking ) - { - if( mmove->desired_speed < 1.0f ) - { - MM_GroundTrace(); - return; - } + if (mm->walking) { + if (mm->desired_speed < 1.0f) { + VectorClear2D(mm->velocity); + MM_GroundTrace(); + return; + } - float wishdir[ 3 ]; + vec3_t wishdir; - MM_ClipVelocity2D( mm->desired_dir, mm->groundPlaneNormal, wishdir, OVERCLIP ); - VectorNormalize( wishdir ); + MM_ClipVelocity2D(mm->desired_dir, mm->groundPlaneNormal, wishdir, OVERCLIP); + VectorNormalize(wishdir); - mm->velocity[ 0 ] = mm->desired_speed * wishdir[ 0 ]; - mm->velocity[ 1 ] = mm->desired_speed * wishdir[ 1 ]; - } - else if( mmove->groundPlane ) - { - MM_ClipVelocity( mmove->velocity, mmove->groundPlaneNormal, mmove->velocity, OVERCLIP ); - } + mm->velocity[0] = mm->desired_speed * wishdir[0]; + mm->velocity[1] = mm->desired_speed * wishdir[1]; + } else if (mm->groundPlane) { + MM_ClipVelocity(mm->velocity, mm->groundPlaneNormal, mm->velocity, OVERCLIP); + } - MM_StepSlideMove(); + MM_StepSlideMove(); - if( !mm->walking && mml.previous_velocity[ 2 ] >= 0.0f && mm->velocity[ 2 ] <= 0.0f ) - { - point[ 0 ] = mmove->origin[ 0 ]; - point[ 1 ] = mmove->origin[ 1 ]; - point[ 2 ] = mmove->origin[ 2 ] - 18.0f; + if (!mm->walking && mml.previous_velocity[2] >= 0.0f && mm->velocity[2] <= 0.0f) { + point[0] = mm->origin[0]; + point[1] = mm->origin[1]; + point[2] = mm->origin[2] - 18.0f; - gi.trace( &trace, mm->origin, mm->mins, mm->maxs, point, mm->entityNum, mm->tracemask, qtrue, qfalse ); + gi.trace(&trace, mm->origin, mm->mins, mm->maxs, point, mm->entityNum, mm->tracemask, qtrue, qfalse); - if( trace.fraction < 1.0f && !trace.allsolid ) - { - MM_GroundTrace(); - return; - } - } + if (trace.fraction < 1.0f && !trace.allsolid) { + VectorCopy(trace.endpos, mm->origin); + MM_GroundTrace(); + } + } } diff --git a/code/fgame/g_phys.cpp b/code/fgame/g_phys.cpp index 8bf95644..3ca3115c 100644 --- a/code/fgame/g_phys.cpp +++ b/code/fgame/g_phys.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "sentient.h" #include "actor.h" #include "player.h" +#include "debuglines.h" /* @@ -47,7 +48,7 @@ solid_edge items only clip against bsp models. */ -pushed_t pushed[ MAX_GENTITIES ]; +pushed_t pushed[MAX_GENTITIES]; pushed_t *pushed_p; Entity *obstacle; @@ -58,123 +59,101 @@ G_FixEntityPosition ============ */ -Entity *G_FixEntityPosition - ( - Entity *ent - ) +Entity *G_FixEntityPosition(Entity *ent) { - int mask; - trace_t trace; - Vector start; - float radius; + int mask; + trace_t trace; + Vector start; + float radius; - if( ent->size.x > ent->size.z ) - { - radius = ent->size.z * 0.5f; - } - else - { - radius = ent->size.x * 0.5f; - } + if (ent->size.x > ent->size.z) { + radius = ent->size.z * 0.5f; + } else { + radius = ent->size.x * 0.5f; + } - mask = ent->edict->clipmask; - if( !mask ) - { - mask = MASK_SOLID; - } + mask = ent->edict->clipmask; + if (!mask) { + mask = MASK_SOLID; + } - start = ent->origin; - start.z += radius; - if( ent->IsSubclassOfPlayer() ) - { - trace = G_Trace( start, ent->mins, ent->maxs, ent->origin, ent, mask, true, "G_FixEntityPosition1" ); - } - else - { - trace = G_Trace( start, ent->mins, ent->maxs, ent->origin, ent, mask, false, "G_FixEntityPosition2" ); - } + start = ent->origin; + start.z += radius; + if (ent->IsSubclassOfSentient()) { + trace = G_Trace(start, ent->mins, ent->maxs, ent->origin, ent, mask, true, "G_FixEntityPosition1"); + } else { + trace = G_Trace(start, ent->mins, ent->maxs, ent->origin, ent, mask, false, "G_FixEntityPosition2"); + } - if( trace.startsolid ) - { - //return g_entities->entity; - assert( trace.ent ); - assert( trace.ent->entity ); - return trace.ent->entity; - } + if (trace.startsolid) { + if (!trace.ent) { + // Fixed in OPM + // I don't understand why they just prefer the game crashing + // rather than ignoring the entity + return NULL; + } + //assert( trace.ent ); + //assert( trace.ent->entity ); + return trace.ent->entity; + } - ent->setOrigin( trace.endpos ); + ent->setOrigin(trace.endpos); - return NULL; + return NULL; } - /* ============ G_TestEntityPosition ============ */ -Entity *G_TestEntityPosition - ( - Entity *ent - ) +Entity *G_TestEntityPosition(Entity *ent) { - int mask; - trace_t trace; + int mask; + trace_t trace; - mask = ent->edict->clipmask; - if( !mask ) - mask = MASK_SOLID; + mask = ent->edict->clipmask; + if (!mask) { + mask = MASK_SOLID; + } - if( ent->IsSubclassOfPlayer() ) - { - trace = G_Trace( ent->origin, ent->mins, ent->maxs, ent->origin, ent, mask, true, "G_TestEntityPosition1" ); - } - else - { - trace = G_Trace( ent->origin, ent->mins, ent->maxs, ent->origin, ent, mask, false, "G_TestEntityPosition2" ); - } + if (ent->IsSubclassOfPlayer()) { + trace = G_Trace(ent->origin, ent->mins, ent->maxs, ent->origin, ent, mask, true, "G_TestEntityPosition1"); + } else { + trace = G_Trace(ent->origin, ent->mins, ent->maxs, ent->origin, ent, mask, false, "G_TestEntityPosition2"); + } - if( trace.startsolid ) - { - //return g_entities->entity; - assert( trace.ent ); - assert( trace.ent->entity ); - return trace.ent->entity; - } + if (trace.startsolid) { + //return g_entities->entity; + assert(trace.ent); + assert(trace.ent->entity); + return trace.ent->entity; + } - return NULL; + return NULL; } - /* ================ G_CheckVelocity ================ */ -void G_CheckVelocity - ( - Entity *ent - ) +void G_CheckVelocity(Entity *ent) +{ + int i; - { - int i; - - // - // bound velocity - // - for( i = 0; i < 3; i++ ) - { - if ( ent->velocity[ i ] > sv_maxvelocity->value ) - { - ent->velocity[ i ] = sv_maxvelocity->value; - } - else if ( ent->velocity[ i ] < -sv_maxvelocity->value ) - { - ent->velocity[ i ] = -sv_maxvelocity->value; - } - } - } + // + // bound velocity + // + for (i = 0; i < 3; i++) { + if (ent->velocity[i] > sv_maxvelocity->value) { + ent->velocity[i] = sv_maxvelocity->value; + } else if (ent->velocity[i] < -sv_maxvelocity->value) { + ent->velocity[i] = -sv_maxvelocity->value; + } + } +} /* ================== @@ -183,54 +162,30 @@ G_Impact Two entities have touched, so run their touch functions ================== */ -void G_Impact - ( - Entity *e1, - trace_t *trace - ) +void G_Impact(Entity *e1, trace_t *trace) { - gentity_t *e2; - Event *ev; - SafePtr< Entity > safe1; - SafePtr< Entity > safe2; + gentity_t *e2; + Event *ev; - e2 = trace->ent; + e2 = trace->ent; - safe1 = e1; - safe2 = e2->entity; + level.impact_trace = *trace; - level.impact_trace = *trace; + // touch anything, including the world + if (e1->edict->solid != SOLID_NOT) { + ev = new Event(EV_Touch); + ev->AddEntity(e2->entity); + e1->ProcessEvent(ev); + } - // touch anything, including the world - if( e1->edict->solid != SOLID_NOT ) - { - ev = new Event( EV_Touch ); - ev->AddEntity( e2->entity ); - e1->ProcessEvent( ev ); + // entity could have been removed, so check if he's in use before sending the event + if (e2->entity && (e2->solid != SOLID_NOT) && (!(e2->r.contents & CONTENTS_SHOOTONLY)) && (e2->entity != world)) { + ev = new Event(EV_Touch); + ev->AddEntity(e1); + e2->entity->ProcessEvent(ev); + } - if( safe1 ) { - safe1->Unregister( "touch" ); - } - } - - // entity could have been removed, so check if he's in use before sending the event - if( - e2->entity && - ( e2->solid != SOLID_NOT ) && - ( !( e2->r.contents & CONTENTS_SHOOTONLY ) ) && - ( e2->entity != world ) - ) - { - ev = new Event( EV_Touch ); - ev->AddEntity( e1 ); - e2->entity->ProcessEvent( ev ); - - if( safe2 ) { - safe2->Unregister( "touch" ); - } - } - - memset( &level.impact_trace, 0, sizeof( level.impact_trace ) ); + memset(&level.impact_trace, 0, sizeof(level.impact_trace)); } /* @@ -239,36 +194,29 @@ G_TestEntityPosition ============ */ -Entity *G_TestEntityPosition - ( - Entity *ent, - Vector vOrg - ) +Entity *G_TestEntityPosition(Entity *ent, Vector vOrg) { - int mask; - trace_t trace; + int mask; + trace_t trace; - mask = ent->edict->clipmask; - if( !mask ) - mask = MASK_SOLID; + mask = ent->edict->clipmask; + if (!mask) { + mask = MASK_SOLID; + } - if( ent->IsSubclassOfPlayer() ) - { - trace = G_Trace( vOrg, ent->mins, ent->maxs, vOrg, ent, mask, true, "G_TestEntityPosition1" ); - } - else - { - trace = G_Trace( vOrg, ent->mins, ent->maxs, vOrg, ent, mask, false, "G_TestEntityPosition2" ); - } + if (ent->IsSubclassOfSentient()) { + trace = G_Trace(vOrg, ent->mins, ent->maxs, vOrg, ent, mask, true, "G_TestEntityPosition1"); + } else { + trace = G_Trace(vOrg, ent->mins, ent->maxs, vOrg, ent, mask, false, "G_TestEntityPosition2"); + } - if( trace.startsolid ) - { - assert( trace.ent ); - assert( trace.ent->entity ); - return trace.ent->entity; - } + if (trace.startsolid) { + assert(trace.ent); + assert(trace.ent->entity); + return trace.ent->entity; + } - return NULL; + return NULL; } /* @@ -281,46 +229,34 @@ returns the blocked flags (1 = floor, 2 = step / wall) */ #define STOP_EPSILON 0.1 -int G_ClipVelocity - ( - Vector& in, - Vector& normal, - Vector& out, - float overbounce - ) +int G_ClipVelocity(Vector& in, Vector& normal, Vector& out, float overbounce) +{ + int i; + int blocked; + float backoff; - { - int i; - int blocked; - float backoff; + blocked = 0; - blocked = 0; + if (normal[2] > 0) { + // floor + blocked |= 1; + } + if (!normal[2]) { + // step + blocked |= 2; + } - if ( normal[ 2 ] > 0 ) - { - // floor - blocked |= 1; - } - if ( !normal[ 2 ] ) - { - // step - blocked |= 2; - } + backoff = (in * normal) * overbounce; - backoff = ( in * normal ) * overbounce; - - out = in - normal * backoff; - for( i = 0; i < 3; i++ ) - { - if ( out[ i ] > -STOP_EPSILON && out[ i ] < STOP_EPSILON ) - { - out[ i ] = 0; - } - } - - return blocked; - } + out = in - normal * backoff; + for (i = 0; i < 3; i++) { + if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) { + out[i] = 0; + } + } + return blocked; +} /* ============ @@ -335,218 +271,179 @@ Returns the clipflags if the velocity was modified (hit something solid) */ #define MAX_CLIP_PLANES 5 -int G_FlyMove - ( - Entity *ent, - Vector basevel, - float time, - int mask - ) +int G_FlyMove(Entity *ent, Vector basevel, float time, int mask) { - Entity *hit; - gentity_t *edict; - int bumpcount, numbumps; - Vector dir; - float d; - int numplanes; - vec3_t planes[ MAX_CLIP_PLANES ]; - Vector primal_velocity, original_velocity, new_velocity; - int i, j; - trace_t trace; - Vector end; - float time_left; - int blocked; + Entity *hit; + gentity_t *edict; + int bumpcount, numbumps; + Vector dir; + float d; + int numplanes; + vec3_t planes[MAX_CLIP_PLANES]; + Vector primal_velocity, original_velocity, new_velocity; + int i, j; + trace_t trace; + Vector end; + float time_left; + int blocked; #if 0 Vector move; Vector v; #endif - edict = ent->edict; + edict = ent->edict; - numbumps = 4; + numbumps = 4; - blocked = 0; - original_velocity = ent->velocity; - primal_velocity = ent->velocity; - numplanes = 0; + blocked = 0; + original_velocity = ent->velocity; + primal_velocity = ent->velocity; + numplanes = 0; #if 1 - time_left = time; + time_left = time; #else - time_left = 1.0;//time; + time_left = 1.0; //time; - v = ent->total_delta; - v[ 1 ] = -v[ 1 ]; // sigh... - MatrixTransformVector( v, ent->orientation, move ); - move += ent->velocity * time; - ent->total_delta = vec_zero; + v = ent->total_delta; + v[1] = -v[1]; // sigh... + MatrixTransformVector(v, ent->orientation, move); + move += ent->velocity * time; + ent->total_delta = vec_zero; #endif - ent->groundentity = NULL; - for( bumpcount = 0; bumpcount < numbumps; bumpcount++ ) - { + ent->groundentity = NULL; + for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { #if 1 - end = ent->origin + time_left * ( ent->velocity + basevel ); + end = ent->origin + time_left * (ent->velocity + basevel); #else - end = ent->origin + time_left * move; + end = ent->origin + time_left * move; #endif - trace = G_Trace( ent->origin, ent->mins, ent->maxs, end, ent, mask, false, "G_FlyMove" ); + trace = G_Trace(ent->origin, ent->mins, ent->maxs, end, ent, mask, false, "G_FlyMove"); - if( - ( trace.allsolid ) || - ( - ( trace.startsolid ) && - ( ent->movetype == MOVETYPE_VEHICLE ) - ) - ) - { - // entity is trapped in another solid - ent->velocity = vec_zero; - return 3; - } + if ((trace.allsolid) || ((trace.startsolid) && (ent->movetype == MOVETYPE_VEHICLE))) { + // entity is trapped in another solid + ent->velocity = vec_zero; + return 3; + } - if( trace.fraction > 0 ) - { - // actually covered some distance - ent->setOrigin( trace.endpos ); - original_velocity = ent->velocity; - numplanes = 0; - } + if (trace.fraction > 0) { + // actually covered some distance + ent->setOrigin(trace.endpos); + original_velocity = ent->velocity; + numplanes = 0; + } - if( trace.fraction == 1 ) - { - // moved the entire distance - break; - } + if (trace.fraction == 1) { + // moved the entire distance + break; + } - assert( trace.ent ); - hit = trace.ent->entity; + assert(trace.ent); + hit = trace.ent->entity; - if( trace.plane.normal[ 2 ] > 0.7 ) - { - // floor - blocked |= 1; - if( hit->getSolidType() == SOLID_BSP ) - { - ent->groundentity = hit->edict; - ent->groundplane = trace.plane; - ent->groundcontents = trace.contents; - } - } + if (trace.plane.normal[2] > 0.7) { + // floor + blocked |= 1; + if (hit->getSolidType() == SOLID_BSP) { + ent->groundentity = hit->edict; + ent->groundplane = trace.plane; + ent->groundcontents = trace.contents; + } + } - if( !trace.plane.normal[ 2 ] ) - { - // step - blocked |= 2; - } + if (!trace.plane.normal[2]) { + // step + blocked |= 2; + } - // - // run the impact function - // - G_Impact( ent, &trace ); - if( !edict->inuse ) - { - break; // removed by the impact function - } + // + // run the impact function + // + G_Impact(ent, &trace); + if (!edict->inuse) { + break; // removed by the impact function + } - time_left -= time_left * trace.fraction; + time_left -= time_left * trace.fraction; - // cliped to another plane - if( numplanes >= MAX_CLIP_PLANES ) - { - // this shouldn't really happen - ent->velocity = vec_zero; - return 3; - } + // cliped to another plane + if (numplanes >= MAX_CLIP_PLANES) { + // this shouldn't really happen + ent->velocity = vec_zero; + return 3; + } - VectorCopy( trace.plane.normal, planes[ numplanes ] ); - numplanes++; + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; - // - // modify original_velocity so it parallels all of the clip planes - // - for( i = 0; i < numplanes; i++ ) - { - Vector normal = planes[ i ]; + // + // modify original_velocity so it parallels all of the clip planes + // + for (i = 0; i < numplanes; i++) { + Vector normal = planes[i]; - G_ClipVelocity( original_velocity, normal, new_velocity, 1.01f ); - for( j = 0; j < numplanes; j++ ) - { - if( j != i ) - { - if( ( new_velocity * planes[ j ] ) < 0 ) - { - // not ok - break; - } - } - } + G_ClipVelocity(original_velocity, normal, new_velocity, 1.01f); + for (j = 0; j < numplanes; j++) { + if (j != i) { + if ((new_velocity * planes[j]) < 0) { + // not ok + break; + } + } + } - if( j == numplanes ) - { - break; - } - } + if (j == numplanes) { + break; + } + } - if( i != numplanes ) - { - // go along this plane - ent->velocity = new_velocity; - } - else - { - // go along the crease - if( numplanes != 2 ) - { - ent->velocity = vec_zero; - return 7; - } - CrossProduct( planes[ 0 ], planes[ 1 ], dir ); - d = dir * ent->velocity; - ent->velocity = dir * d; - } + if (i != numplanes) { + // go along this plane + ent->velocity = new_velocity; + } else { + // go along the crease + if (numplanes != 2) { + ent->velocity = vec_zero; + return 7; + } + CrossProduct(planes[0], planes[1], dir); + d = dir * ent->velocity; + ent->velocity = dir * d; + } - // - // if original velocity is against the original velocity, stop dead - // to avoid tiny occilations in sloping corners - // - if( ( ent->velocity * primal_velocity ) <= 0 ) - { - ent->velocity = vec_zero; - return blocked; - } - } + // + // if original velocity is against the original velocity, stop dead + // to avoid tiny occilations in sloping corners + // + if ((ent->velocity * primal_velocity) <= 0) { + ent->velocity = vec_zero; + return blocked; + } + } - return blocked; + return blocked; } - /* ============ G_AddGravity ============ */ -void G_AddGravity - ( - Entity *ent - ) +void G_AddGravity(Entity *ent) +{ + float grav; - { - float grav; + if (ent->waterlevel > 2) { + grav = ent->gravity * 60 * level.frametime; + } else { + grav = ent->gravity * sv_gravity->value * level.frametime; + } - if ( ent->waterlevel > 2 ) - { - grav = ent->gravity * 60 * level.frametime; - } - else - { - grav = ent->gravity * sv_gravity->value * level.frametime; - } - - ent->velocity[ 2 ] -= grav; - } + ent->velocity[2] -= grav; +} /* =============================================================================== @@ -563,59 +460,48 @@ G_PushEntity Does not change the entities velocity at all ============ */ -trace_t G_PushEntity - ( - Entity *ent, - Vector push - ) +trace_t G_PushEntity(Entity *ent, Vector push) { - trace_t trace; - Vector start; - Vector end; - int mask; - gentity_t *edict; + trace_t trace; + Vector start; + Vector end; + int mask; + gentity_t *edict; - start = ent->origin; - end = start + push; + start = ent->origin; + end = start + push; retry: - if( ent->edict->clipmask ) - { - mask = ent->edict->clipmask; - } - else - { - mask = MASK_SOLID; - } + if (ent->edict->clipmask) { + mask = ent->edict->clipmask; + } else { + mask = MASK_SOLID; + } - trace = G_Trace( start, ent->mins, ent->maxs, end, ent, mask, true, "G_PushEntity" ); + trace = G_Trace(start, ent->mins, ent->maxs, end, ent, mask, true, "G_PushEntity"); - edict = ent->edict; + edict = ent->edict; - ent->setOrigin( trace.endpos ); + ent->setOrigin(trace.endpos); - if( trace.fraction != 1.0 ) - { - G_Impact( ent, &trace ); + if (trace.fraction != 1.0) { + G_Impact(ent, &trace); - // if the pushed entity went away and the pusher is still there - if( ( !trace.ent || !trace.ent->inuse ) && edict->inuse ) - { - // move the pusher back and try again - ent->setOrigin( start ); - goto retry; - } - } + // if the pushed entity went away and the pusher is still there + if ((!trace.ent || !trace.ent->inuse) && edict->inuse) { + // move the pusher back and try again + ent->setOrigin(start); + goto retry; + } + } - if( edict && ( edict != ent->edict ) ) - { - if( ent->flags & FL_TOUCH_TRIGGERS ) - { - G_TouchTriggers( ent ); - } - } + if (edict && (edict != ent->edict)) { + if (ent->flags & FL_TOUCH_TRIGGERS) { + G_TouchTriggers(ent); + } + } - return trace; + return trace; } /* @@ -623,37 +509,28 @@ retry: G_SlideEntity ============ */ -trace_t G_SlideEntity - ( - Entity *ent, - Vector push - ) +trace_t G_SlideEntity(Entity *ent, Vector push) +{ + trace_t trace; + Vector start; + Vector end; + int mask; - { - trace_t trace; - Vector start; - Vector end; - int mask; + start = ent->origin; + end = start + push; - start = ent->origin; - end = start + push; + if (ent->edict->clipmask) { + mask = ent->edict->clipmask; + } else { + mask = MASK_SOLID; + } - if ( ent->edict->clipmask ) - { - mask = ent->edict->clipmask; - } - else - { - mask = MASK_SOLID; - } + trace = G_Trace(start, ent->mins, ent->maxs, end, ent, mask, false, "G_SlideEntity"); - trace = G_Trace( start, ent->mins, ent->maxs, end, ent, mask, false, "G_SlideEntity" ); - - ent->setOrigin( trace.endpos ); - - return trace; - } + ent->setOrigin(trace.endpos); + return trace; +} /* ================ @@ -709,185 +586,157 @@ Objects need to be moved back on a failed push, otherwise riders would continue to slide. ============ */ -qboolean G_Push - ( - Entity *pusher, - Vector pushermove, - Vector pusheramove - ) +qboolean G_Push(Entity *pusher, Vector pushermove, Vector pusheramove) +{ + Entity *check, *block; + gentity_t *edict; + Vector move, amove; + Vector mins, maxs; + Vector save; + pushed_t *p; + Vector org, org2, move2, neworg; + Vector norm; + float mat[3][3]; + pushed_t *pusher_p; + float radius; + int i, num; + int j; + int touch[MAX_GENTITIES]; + Event *ev; - { - Entity *check, *block; - gentity_t *edict; - Vector move, amove; - Vector mins, maxs; - Vector save; - pushed_t *p; - Vector org, org2, move2, neworg; - Vector norm; - float mat[ 3 ][ 3 ]; - pushed_t *pusher_p; - float radius; - int i, num; - int touch[ MAX_GENTITIES ]; - Event *ev; + // save the pusher's original position + pusher_p = pushed_p; + pushed_p->ent = pusher; + pushed_p->localorigin = pusher->localorigin; + pushed_p->origin = pusher->origin; + pushed_p->localangles = pusher->localangles; + pushed_p->angles = pusher->angles; - // save the pusher's original position - pusher_p = pushed_p; - pushed_p->ent = pusher; - pushed_p->localorigin = pusher->localorigin; - pushed_p->origin = pusher->origin; - pushed_p->localangles = pusher->localangles; - pushed_p->angles = pusher->angles; + if (pusher->client) { + pushed_p->deltayaw = pusher->client->ps.delta_angles[YAW]; + } - if( pusher->client ) - { - pushed_p->deltayaw = pusher->client->ps.delta_angles[ YAW ]; - } + pushed_p++; - pushed_p++; + if (pushed_p >= &pushed[MAX_GENTITIES]) { + gi.Error(ERR_FATAL, "Pushed too many entities."); + } - if( pushed_p >= &pushed[ MAX_GENTITIES ] ) - { - gi.Error( ERR_FATAL, "Pushed too many entities." ); - } + if (pusher->IsSubclassOfPlayer()) { + pusher->setAngles(); + pusher->setOrigin(); + } else { + // move the pusher to it's final position + pusher->addAngles(pusheramove); + pusher->addOrigin(pushermove); + } - if( pusher->IsSubclassOfPlayer() ) - { - pusher->setAngles(); - pusher->setOrigin(); - } - else - { - // move the pusher to it's final position - pusher->addAngles( pusheramove ); - pusher->addOrigin( pushermove ); - } + if (pusher->edict->solid == SOLID_NOT) { + // Doesn't push anything + return true; + } + // change the move to worldspace + move = pusher->origin - pusher_p->origin; + amove = pusher->angles - pusher_p->angles; - if( pusher->edict->solid == SOLID_NOT ) - { - // Doesn't push anything - return true; - } + // we need this for pushing things later + AnglesToAxis(amove, mat); - // change the move to worldspace - move = pusher->origin - pusher_p->origin; - amove = pusher->angles - pusher_p->angles; + // find the bounding box + mins = pusher->absmin; + maxs = pusher->absmax; - // we need this for pushing things later - AnglesToAxis( amove, mat ); + // Add in entities that are within the pusher - // find the bounding box - mins = pusher->absmin; - maxs = pusher->absmax; + num = gi.AreaEntities(mins, maxs, touch, MAX_GENTITIES); - // Add in entities that are within the pusher + for (i = 0; i < num; i++) { + edict = &g_entities[touch[i]]; + assert(edict); + assert(edict->inuse); + assert(edict->entity); + check = edict->entity; - num = gi.AreaEntities( mins, maxs, touch, MAX_GENTITIES ); + if ((check->movetype == MOVETYPE_PUSH) || (check->movetype == MOVETYPE_STOP) + || (check->movetype == MOVETYPE_NONE) || (check->movetype == MOVETYPE_NOCLIP)) { + continue; + } - for( i = 0; i < num; i++ ) - { - edict = &g_entities[ touch[ i ] ]; - assert( edict ); - assert( edict->inuse ); - assert( edict->entity ); - check = edict->entity; + if (check->edict->r.contents == CONTENTS_SHOOTONLY) { + continue; + } - if( ( check->movetype == MOVETYPE_PUSH ) || - ( check->movetype == MOVETYPE_STOP ) || - ( check->movetype == MOVETYPE_NONE ) || - ( check->movetype == MOVETYPE_NOCLIP ) ) - { - continue; - } + // if the entity is standing on the pusher, it will definitely be moved + if (check->groundentity != pusher->edict) { + // Only move triggers and non-solid objects if they're sitting on a moving object + if ((check->edict->solid == SOLID_TRIGGER) || (check->edict->solid == SOLID_NOT)) { + continue; + } - if( check->edict->r.contents == CONTENTS_SHOOTONLY ) - continue; + // see if the ent needs to be tested + if ((check->absmin[0] >= maxs[0]) || (check->absmin[1] >= maxs[1]) || (check->absmin[2] >= maxs[2]) + || (check->absmax[0] <= mins[0]) || (check->absmax[1] <= mins[1]) || (check->absmax[2] <= mins[2])) { + continue; + } - // if the entity is standing on the pusher, it will definitely be moved - if( check->groundentity != pusher->edict ) - { - // Only move triggers and non-solid objects if they're sitting on a moving object - if( ( check->edict->solid == SOLID_TRIGGER ) || ( check->edict->solid == SOLID_NOT ) ) - { - continue; - } + // see if the ent's bbox is inside the pusher's final position + if (!G_TestEntityPosition(check, check->origin)) { + continue; + } - // see if the ent needs to be tested - if( ( check->absmin[ 0 ] >= maxs[ 0 ] ) || - ( check->absmin[ 1 ] >= maxs[ 1 ] ) || - ( check->absmin[ 2 ] >= maxs[ 2 ] ) || - ( check->absmax[ 0 ] <= mins[ 0 ] ) || - ( check->absmax[ 1 ] <= mins[ 1 ] ) || - ( check->absmax[ 2 ] <= mins[ 2 ] ) ) - { - continue; - } + ev = new Event(EV_Touch); + ev->AddEntity(pusher); + check->ProcessEvent(ev); - // see if the ent's bbox is inside the pusher's final position - if( !G_TestEntityPosition( check, check->origin ) ) - { - continue; - } + ev = new Event(EV_Touch); + ev->AddEntity(check); + pusher->ProcessEvent(ev); + } - ev = new Event( EV_Touch ); - ev->AddEntity( pusher ); - check->ProcessEvent( ev ); + pushed_p->localorigin = check->localorigin; + pushed_p->localangles = check->localangles; + // move this entity + pushed_p->ent = check; + pushed_p->origin = check->origin; + pushed_p->angles = check->angles; + pushed_p++; - ev = new Event( EV_Touch ); - ev->AddEntity( check ); - pusher->ProcessEvent( ev ); - } + if (pushed_p >= &pushed[MAX_GENTITIES]) { + gi.Error(ERR_FATAL, "Pushed too many entities."); + } - pushed_p->localorigin = check->localorigin; - pushed_p->localangles = check->localangles; - // move this entity - pushed_p->ent = check; - pushed_p->origin = check->origin; - pushed_p->angles = check->angles; - pushed_p++; + // save off the origin + save = check->localorigin; - if( pushed_p >= &pushed[ MAX_GENTITIES ] ) - { - gi.Error( ERR_FATAL, "Pushed too many entities." ); - } + // try moving the contacted entity + move2 = move; - // save off the origin - save = check->localorigin; + // FIXME: doesn't rotate monsters? + if (check->client && amove[YAW]) { + Sentient *sent = (Sentient *)check; + Vector a = sent->GetViewAngles() + Vector(0, amove[YAW], 0); + sent->SetViewAngles(a); + } - // try moving the contacted entity - move2 = move; + // get the radius of the entity + if (check->size.x > check->size.z) { + radius = check->size.z * 0.5f; + } else { + radius = check->size.x * 0.5f; + } - // FIXME: doesn't rotate monsters? - /*if( check->client && amove[ YAW ] ) - { - Sentient *sent = ( Sentient * )check; - Vector a = sent->GetViewAngles() + Vector( 0, amove[ YAW ], 0 ); - sent->SetViewAngles( a ); - }*/ + // figure movement due to the pusher's amove + org = check->origin - pusher->origin; + org.z += radius; - // get the radius of the entity - if( check->size.x > check->size.z ) - { - radius = check->size.z * 0.5f; - } - else - { - radius = check->size.x * 0.5f; - } + MatrixTransformVector(org, mat, org2); - // figure movement due to the pusher's amove - org = check->origin - pusher->origin; - org.z += radius; + move2 += org2 - org; - MatrixTransformVector( org, mat, org2 ); + neworg = move2 + check->origin; - move2 += org2 - org; - - neworg = move2 + check->origin; - - /* + /* // This one seems to be better for the bind command if( G_TestEntityPosition( check, check->origin ) ) { @@ -906,66 +755,96 @@ qboolean G_Push } */ - if( G_TestEntityPosition( check, neworg ) ) - { - trace_t trace; - Vector end; - Vector fwd; - float length; + if (G_TestEntityPosition(check, neworg)) { + trace_t trace; + Vector end; + Vector fwd; + float length; - length = VectorNormalize2( move2, fwd ); + length = VectorNormalize2(move2, fwd); - end = check->origin + fwd * ( length + 64.0f ); + end = check->origin + fwd * (length + 64.0f); - if( check->IsSubclassOfPlayer() ) - { - trace = G_Trace( check->origin, check->mins, check->maxs, end, check, check->edict->clipmask, true, "G_Push" ); - } - else - { - trace = G_Trace( check->origin, check->mins, check->maxs, end, check, check->edict->clipmask, false, "G_Push" ); - } + if (check->IsSubclassOfSentient()) { + trace = G_Trace( + check->origin, check->mins, check->maxs, end, check, check->edict->clipmask, true, "G_Push" + ); + } else { + trace = G_Trace( + check->origin, check->mins, check->maxs, end, check, check->edict->clipmask, false, "G_Push" + ); + } - if( !trace.allsolid ) - { - if( check->IsSubclassOfPlayer() ) - { - trace = G_Trace( Vector( trace.endpos ), check->mins, check->maxs, neworg, check, check->edict->clipmask, true, "G_Push" ); - } - else - { - trace = G_Trace( Vector( trace.endpos ), check->mins, check->maxs, neworg, check, check->edict->clipmask, false, "G_Push" ); - } + if (!trace.allsolid) { + if (check->IsSubclassOfSentient()) { + trace = G_Trace( + Vector(trace.endpos), + check->mins, + check->maxs, + neworg, + check, + check->edict->clipmask, + true, + "G_Push" + ); + } else { + trace = G_Trace( + Vector(trace.endpos), + check->mins, + check->maxs, + neworg, + check, + check->edict->clipmask, + false, + "G_Push" + ); + } - move2 = trace.endpos - check->origin; - } - } + move2 = trace.endpos - check->origin; + } + } - check->addOrigin( check->getParentVector( move2 ) ); + check->addOrigin(check->getParentVector(move2)); - // may have pushed them off an edge - if( check->groundentity ) - { - if( check->groundentity != pusher->edict ) - check->groundentity = NULL; - } + // may have pushed them off an edge + if (check->groundentity) { + if (check->groundentity != pusher->edict) { + check->groundentity = NULL; + } + } else { + move2 *= 1.f / level.frametime; - block = G_TestEntityPosition( check, check->origin ); - if( block ) - { - block = G_FixEntityPosition( check ); - } - if( !block ) - { - // pushed ok - check->link(); + for (j = 0; j < 3; j++) { + if (!move2[j]) { + continue; + } - // impact? - continue; - } + if (move2[j] < 0) { + if (check->velocity[j] > move2[j]) { + check->velocity[j] = move2[j]; + } + } else { + if (check->velocity[j] < move2[j]) { + check->velocity[j] = move2[j]; + } + } + } + } - // try to snap it to a good position - /* + block = G_TestEntityPosition(check, check->origin); + if (block) { + block = G_FixEntityPosition(check); + } + if (!block) { + // pushed ok + check->link(); + + // impact? + continue; + } + + // try to snap it to a good position + /* if ( G_SnapPosition( check ) ) { // snapped ok. we don't have to link since G_SnapPosition does it for us. @@ -973,67 +852,55 @@ qboolean G_Push } */ - // if it is ok to leave in the old position, do it - // this is only relevent for riding entities, not pushed - check->setLocalOrigin( save ); - block = G_TestEntityPosition( check, check->origin ); - if( !block ) - { - pushed_p--; - continue; - } + // if it is ok to leave in the old position, do it + // this is only relevent for riding entities, not pushed + check->setLocalOrigin(save); + block = G_TestEntityPosition(check, check->origin); + if (!block) { + pushed_p--; + continue; + } - if( check->edict->solid == SOLID_NOT ) - continue; + if (check->edict->solid == SOLID_NOT) { + continue; + } - // L: don't make the pusher teleport through anything that block - if( block != pusher ) - { - pusher_p->ent->setOrigin( pusher_p->origin ); - continue; - } + // save off the obstacle so we can call the block function + obstacle = check; - // save off the obstacle so we can call the block function - obstacle = check; + // move back any entities we already moved + // go backwards, so if the same entity was pushed + // twice, it goes back to the original position + for (p = pushed_p - 1; p >= pushed; p--) { + p->ent->angles = p->angles; + p->ent->origin = p->origin; - // move back any entities we already moved - // go backwards, so if the same entity was pushed - // twice, it goes back to the original position - for( p = pushed_p - 1; p >= pushed; p-- ) - { - p->ent->angles = p->angles; - p->ent->origin = p->origin; + p->ent->localangles = p->localangles; + p->ent->localorigin = p->localorigin; - p->ent->localangles = p->localangles; - p->ent->localorigin = p->localorigin; + if (p->ent->client) { + p->ent->client->ps.delta_angles[YAW] = (int)p->deltayaw; + } + } - if( p->ent->client ) - { - p->ent->client->ps.delta_angles[ YAW ] = ( int )p->deltayaw; - } - } + // Only "really" move it in order so that the bound coordinate system is correct + for (p = pushed; p < pushed_p; p++) { + p->ent->setAngles(); + p->ent->setOrigin(); + } - // Only "really" move it in order so that the bound coordinate system is correct - for( p = pushed; p < pushed_p; p++ ) - { - p->ent->setAngles(); - p->ent->setOrigin(); - } + return false; + } - return false; - } + //FIXME: is there a better way to handle this? + // see if anything we moved has touched a trigger + for (p = pushed_p - 1; p >= pushed; p--) { + if (p->ent->flags & FL_TOUCH_TRIGGERS) { + G_TouchTriggers(p->ent); + } + } - //FIXME: is there a better way to handle this? - // see if anything we moved has touched a trigger - for( p = pushed_p - 1; p >= pushed; p-- ) - { - if( p->ent->flags & FL_TOUCH_TRIGGERS ) - { - G_TouchTriggers( p->ent ); - } - } - - return true; + return true; } /* @@ -1041,39 +908,37 @@ qboolean G_Push G_PushMove ================ */ -qboolean G_PushMove( Entity *ent, Vector move, Vector amove ) +qboolean G_PushMove(Entity *ent, Vector move, Vector amove) { - Entity *part; - Vector m, a; - Event *ev; + Entity *part; + Vector m, a; + Event *ev; - m = move; - a = amove; + m = move; + a = amove; - pushed_p = pushed; + pushed_p = pushed; - part = ent; + part = ent; - while( part ) - { - if( !G_Push( part, m, a ) ) - { - // move was blocked - // call the pusher's "blocked" function - // otherwise, just stay in place until the obstacle is gone - ev = new Event( EV_Blocked ); - ev->AddEntity( obstacle ); - part->ProcessEvent( ev ); - return false; - } + while (part) { + if (!G_Push(part, m, a)) { + // move was blocked + // call the pusher's "blocked" function + // otherwise, just stay in place until the obstacle is gone + ev = new Event(EV_Blocked); + ev->AddEntity(obstacle); + part->ProcessEvent(ev); + return false; + } - m = vec_zero; - a = vec_zero; + m = vec_zero; + a = vec_zero; - part = part->teamchain; - } + part = part->teamchain; + } - return true; + return true; } /* @@ -1084,65 +949,55 @@ Bmodel objects don't interact with each other, but push all box objects ================ */ -void G_Physics_Pusher - ( - Entity *ent - ) +void G_Physics_Pusher(Entity *ent) { - Vector move, amove; - Entity *part, *mv; - Event *ev; + Vector move, amove; + Entity *part, *mv; + Event *ev; - // team slaves are only moved by their captains - if( ent->flags & FL_TEAMSLAVE ) - { - return; - } + // team slaves are only moved by their captains + if (ent->flags & FL_TEAMSLAVE) { + return; + } - // Check if anyone on the team is moving - for( part = ent; part; part = part->teamchain ) - { - if( part->velocity != vec_zero || part->avelocity != vec_zero ) - { - break; - } - } + // Check if anyone on the team is moving + for (part = ent; part; part = part->teamchain) { + if (part->velocity != vec_zero || part->avelocity != vec_zero) { + break; + } + } - // make sure all team slaves can move before commiting - // any moves or calling any think functions - // if the move is blocked, all moved objects will be backed out - pushed_p = pushed; - while( part ) - { - move = part->velocity * level.frametime; - amove = part->avelocity * level.frametime; + // make sure all team slaves can move before commiting + // any moves or calling any think functions + // if the move is blocked, all moved objects will be backed out + pushed_p = pushed; + while (part) { + move = part->velocity * level.frametime; + amove = part->avelocity * level.frametime; - if( !G_Push( part, move, amove ) ) - { - // move was blocked - break; - } + if (!G_Push(part, move, amove)) { + // move was blocked + break; + } - part = part->teamchain; - } + part = part->teamchain; + } - if( part ) - { - // the move failed, bump all movedone times - for( mv = ent; mv; mv = mv->teamchain ) - { - mv->PostponeEvent( EV_MoveDone, FRAMETIME ); - } + if (part) { + // the move failed, bump all movedone times + for (mv = ent; mv; mv = mv->teamchain) { + mv->PostponeEvent(EV_MoveDone, FRAMETIME); + } - // if the pusher has a "blocked" function, call it - // otherwise, just stay in place until the obstacle is gone - ev = new Event( EV_Blocked ); - ev->AddEntity( obstacle ); - part->ProcessEvent( ev ); - } + // if the pusher has a "blocked" function, call it + // otherwise, just stay in place until the obstacle is gone + ev = new Event(EV_Blocked); + ev->AddEntity(obstacle); + part->ProcessEvent(ev); + } - ent->velocity += ent->accel; - ent->avelocity += ent->aaccel; + ent->velocity += ent->accel; + ent->avelocity += ent->aaccel; } //================================================================== @@ -1154,16 +1009,12 @@ G_Physics_Noclip A moving object that doesn't obey physics ============= */ -void G_Physics_Noclip - ( - Entity *ent - ) - - { - ent->angles += ent->avelocity * level.frametime; - ent->origin += ent->velocity * level.frametime; - ent->link(); - } +void G_Physics_Noclip(Entity *ent) +{ + ent->angles += ent->avelocity * level.frametime; + ent->origin += ent->velocity * level.frametime; + ent->link(); +} /* ============================================================================== @@ -1180,190 +1031,172 @@ G_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ -void G_Physics_Toss - ( - Entity *ent - ) +void G_Physics_Toss(Entity *ent) { - trace_t trace; - Vector move; - float backoff; - Entity *slave; - qboolean wasinwater; - qboolean isinwater; - Vector origin2; - Vector basevel; - gentity_t *edict; - qboolean onconveyor; + trace_t trace; + Vector move; + float backoff; + Entity *slave; + qboolean wasinwater; + qboolean isinwater; + Vector origin2; + Vector basevel; + gentity_t *edict; + qboolean onconveyor; - // if not a team captain, so movement will be handled elsewhere - if( ent->flags & FL_TEAMSLAVE ) - { - return; - } + // if not a team captain, so movement will be handled elsewhere + if (ent->flags & FL_TEAMSLAVE) { + return; + } - if( ent->velocity[ 2 ] > 0 ) - { - ent->groundentity = NULL; - } + if (ent->velocity[2] > 0) { + ent->groundentity = NULL; + } - // check for the groundentity going away - if( ent->groundentity && !ent->groundentity->inuse ) - { - ent->groundentity = NULL; - } + // check for the groundentity going away + if (ent->groundentity && !ent->groundentity->inuse) { + ent->groundentity = NULL; + } - onconveyor = ( basevel != vec_zero ); + onconveyor = (basevel != vec_zero); - // if onground, return without moving - if( ent->groundentity && ent->groundentity->entity->movetype == MOVETYPE_NONE && !onconveyor && ( ent->movetype != MOVETYPE_VEHICLE ) ) - { - if( ent->avelocity.length() ) - { - // move angles - ent->setAngles( ent->angles + ent->avelocity * level.frametime ); - } - ent->velocity = vec_zero; - return; - } + // if onground, return without moving + if (ent->groundentity && ent->groundentity->entity->movetype == MOVETYPE_NONE && !onconveyor + && (ent->movetype != MOVETYPE_VEHICLE)) { + if (ent->avelocity.length()) { + // move angles + ent->setAngles(ent->angles + ent->avelocity * level.frametime); + } + ent->velocity = vec_zero; + return; + } - origin2 = ent->origin; + origin2 = ent->origin; - G_CheckVelocity( ent ); + G_CheckVelocity(ent); - // add gravity - if( !onconveyor && ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE ) - { - G_AddGravity( ent ); - } + // add gravity + if (!onconveyor && ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE) { + G_AddGravity(ent); + } - // move angles - ent->setAngles( ent->angles + ent->avelocity * level.frametime ); + if (ent->avelocity.lengthSquared()) { + // move angles + ent->setAngles(ent->angles + ent->avelocity * level.frametime); + } - // move origin - move = ( ent->velocity + basevel ) * level.frametime; + // move origin + move = (ent->velocity + basevel) * level.frametime; - edict = ent->edict; - if( ent->movetype == MOVETYPE_VEHICLE ) - { - int mask; + edict = ent->edict; + if (ent->movetype == MOVETYPE_VEHICLE) { + int mask; - if( ent->edict->clipmask ) - { - mask = ent->edict->clipmask; - } - else - { - mask = MASK_MONSTERSOLID; - } - G_FlyMove( ent, basevel, FRAMETIME, mask ); - if( ent->flags & FL_TOUCH_TRIGGERS ) - { - G_TouchTriggers( ent ); - } - return; - } - else - { - trace = G_PushEntity( ent, move ); - } + if (ent->edict->clipmask) { + mask = ent->edict->clipmask; + } else { + mask = MASK_MONSTERSOLID; + } + G_FlyMove(ent, basevel, FRAMETIME, mask); + if (ent->flags & FL_TOUCH_TRIGGERS) { + G_TouchTriggers(ent); + } + return; + } else { + trace = G_PushEntity(ent, move); + } - if( ( trace.fraction == 0 ) && ( ent->movetype == MOVETYPE_SLIDE ) ) - { - // Check for slide by removing the downward velocity - Vector slide; + if ((trace.fraction == 0) && (ent->movetype == MOVETYPE_SLIDE || ent->movetype == MOVETYPE_BOUNCE)) { + // Check for slide by removing the downward velocity + Vector slide; - slide[ 0 ] = move[ 0 ] * 0.7f; - slide[ 1 ] = move[ 1 ] * 0.7f; - slide[ 2 ] = 0; - G_PushEntity( ent, slide ); - } + slide[0] = move[0] * level.frametime * 15; + slide[1] = move[1] * level.frametime * 15; + slide[2] = 0; + G_PushEntity(ent, slide); + } - if( !edict->inuse ) - { - return; - } + if (!edict->inuse) { + return; + } - if( trace.fraction < 1 ) - { - if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_GIB ) - { - backoff = 1.5; - } - else - { - backoff = 1; - } + if (trace.fraction < 1) { + if (ent->movetype == MOVETYPE_BOUNCE) { + backoff = 1.4f; + } else if (ent->movetype == MOVETYPE_GIB) { + backoff = 1.6f; + } else { + backoff = 1; + } - Vector normal = trace.plane.normal; + Vector normal = trace.plane.normal; - G_ClipVelocity( ent->velocity, normal, ent->velocity, backoff ); + G_ClipVelocity(ent->velocity, normal, ent->velocity, backoff); - // stop if on ground - if( trace.plane.normal[ 2 ] > 0.7 ) - { - if( ( ent->velocity[ 2 ] < 60 || ( ent->movetype != MOVETYPE_BOUNCE && ent->movetype != MOVETYPE_GIB ) ) && - ( ent->movetype != MOVETYPE_SLIDE ) ) - { - ent->groundentity = trace.ent; - ent->groundplane = trace.plane; - ent->groundcontents = trace.contents; - ent->velocity = vec_zero; - ent->avelocity = vec_zero; - ent->ProcessEvent( EV_Stop ); - } - else if( ent->movetype == MOVETYPE_GIB ) - { - // Stop spinning after we bounce on the ground - ent->avelocity = vec_zero; - } - } - } + if (ent->movetype == MOVETYPE_BOUNCE) { + // Reduce the velocity when bouncing + ent->velocity[0] -= ent->velocity[0] * level.frametime * 1.75f; + ent->velocity[1] -= ent->velocity[1] * level.frametime * 1.75f; + } - if( ( move[ 2 ] == 0 ) && onconveyor ) - { - // Check if we still have a ground - ent->CheckGround(); - } + // stop if on ground + if (trace.plane.normal[2] > 0.7) { + ent->groundentity = trace.ent; + ent->groundplane = trace.plane; + ent->groundcontents = trace.contents; - // check for water transition - wasinwater = ( ent->watertype & MASK_WATER ); - ent->watertype = gi.pointcontents( ent->origin, 0 ); - isinwater = ent->watertype & MASK_WATER; + if (((ent->movetype == MOVETYPE_GIB && ent->velocity[2] < 60) + || (ent->movetype == MOVETYPE_BOUNCE && ent->velocity.length() < 40)) + && (ent->movetype != MOVETYPE_SLIDE)) { + ent->velocity = vec_zero; + ent->avelocity = vec_zero; + ent->ProcessEvent(EV_Stop); + } else if (ent->movetype == MOVETYPE_TOSS || ent->movetype == MOVETYPE_GIB) { + // Stop spinning after we bounce on the ground + ent->avelocity = vec_zero; + ent->ProcessEvent(EV_Stop); + } + } + } - if( isinwater ) - { - ent->waterlevel = 1; - } - else - { - ent->waterlevel = 0; - } + if ((move[2] == 0) && onconveyor) { + // Check if we still have a ground + ent->CheckGround(); + } - if( ( edict->spawntime < ( level.time - FRAMETIME ) ) && ( ent->mass > 0 ) ) - { - if( !wasinwater && isinwater ) - { - ent->Sound( "impact_watersplash", CHAN_BODY, DEFAULT_VOL, DEFAULT_MIN_DIST, &origin2 ); - } - else if( wasinwater && !isinwater ) - { - ent->Sound( "impact_leavewater", CHAN_BODY, DEFAULT_VOL, DEFAULT_MIN_DIST, &origin2 ); - } - } + // check for water transition + wasinwater = (ent->watertype & MASK_WATER); + ent->watertype = gi.pointcontents(ent->origin, 0); + isinwater = ent->watertype & MASK_WATER; - // GAMEFIX - Is this necessary? - // move teamslaves - for( slave = ent->teamchain; slave; slave = slave->teamchain ) - { - slave->setLocalOrigin( slave->localorigin ); - slave->setAngles( slave->localangles ); - } + if (isinwater) { + ent->waterlevel = 1; + } else { + ent->waterlevel = 0; + } - if( ent->flags & FL_TOUCH_TRIGGERS ) - { - G_TouchTriggers( ent ); - } + if ((edict->spawntime < (level.time - FRAMETIME)) && (ent->mass > 0)) { + if (!wasinwater && isinwater) { + ent->Sound("impact_watersplash", CHAN_BODY, DEFAULT_VOL, DEFAULT_MIN_DIST, &origin2); + } else if (wasinwater && !isinwater) { + ent->Sound("impact_leavewater", CHAN_BODY, DEFAULT_VOL, DEFAULT_MIN_DIST, &origin2); + } + } + + // GAMEFIX - Is this necessary? + // move teamslaves + for (slave = ent->teamchain; slave; slave = slave->teamchain) { + slave->setLocalOrigin(slave->localorigin); + slave->setAngles(slave->localangles); + } + + if (ent->flags & FL_TOUCH_TRIGGERS) { + G_TouchTriggers(ent); + } + + if (ai_debug_grenades->integer && ent->movetype == MOVETYPE_BOUNCE) { + G_DebugLine(origin2, ent->origin, 1, 1, 0, 1); + } } /* @@ -1374,37 +1207,27 @@ STEPPING MOVEMENT =============================================================================== */ -void G_AddRotationalFriction - ( - Entity *ent - ) +void G_AddRotationalFriction(Entity *ent) +{ + int n; + float adjustment; - { - int n; - float adjustment; - - ent->angles += level.frametime * ent->avelocity; - adjustment = level.frametime * sv_stopspeed->value * sv_friction->value; - for( n = 0; n < 3; n++ ) - { - if ( ent->avelocity[ n ] > 0) - { - ent->avelocity[ n ] -= adjustment; - if ( ent->avelocity[ n ] < 0 ) - { - ent->avelocity[ n ] = 0; - } - } - else - { - ent->avelocity[ n ] += adjustment; - if ( ent->avelocity[ n ] > 0 ) - { - ent->avelocity[ n ] = 0; - } - } - } - } + ent->angles += level.frametime * ent->avelocity; + adjustment = level.frametime * sv_stopspeed->value * sv_friction->value; + for (n = 0; n < 3; n++) { + if (ent->avelocity[n] > 0) { + ent->avelocity[n] -= adjustment; + if (ent->avelocity[n] < 0) { + ent->avelocity[n] = 0; + } + } else { + ent->avelocity[n] += adjustment; + if (ent->avelocity[n] > 0) { + ent->avelocity[n] = 0; + } + } + } +} /* ============= @@ -1413,21 +1236,14 @@ G_CheckWater ============= */ -void G_CheckWater - ( - Entity *ent - ) +void G_CheckWater(Entity *ent) { - ent->watertype = gi.pointcontents( ent->origin, 0 ); - if( ent->watertype & MASK_WATER ) - { - ent->waterlevel = 1; - } - else - { - ent->waterlevel = 0; - } - + ent->watertype = gi.pointcontents(ent->origin, 0); + if (ent->watertype & MASK_WATER) { + ent->waterlevel = 1; + } else { + ent->waterlevel = 0; + } } /* @@ -1443,146 +1259,121 @@ FIXME: is this true? ============= */ -void G_Physics_Step - ( - Entity *ent - ) +void G_Physics_Step(Entity *ent) +{ + qboolean wasonground; + qboolean hitsound = false; + Vector vel; + float speed, newspeed, control; + float friction; + int mask; + Vector basevel; - { - qboolean wasonground; - qboolean hitsound = false; - Vector vel; - float speed, newspeed, control; - float friction; - int mask; - Vector basevel; + // airborn monsters should always check for ground + if (!ent->groundentity) { + ent->CheckGround(); + } - // airborn monsters should always check for ground - if ( !ent->groundentity ) - { - ent->CheckGround(); - } + if (ent->groundentity) { + wasonground = true; + } else { + wasonground = false; + } - if ( ent->groundentity ) - { - wasonground = true; - } - else - { - wasonground = false; - } + G_CheckVelocity(ent); - G_CheckVelocity( ent ); + if (ent->avelocity != vec_zero) { + G_AddRotationalFriction(ent); + } - if ( ent->avelocity != vec_zero ) - { - G_AddRotationalFriction( ent ); - } + // add gravity except: + // flying monsters + // swimming monsters who are in the water + if (!wasonground) { + if (!(ent->flags & FL_FLY)) { + if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { + if (ent->velocity[2] < sv_gravity->value * ent->gravity * -0.1f) { + hitsound = true; + } - // add gravity except: - // flying monsters - // swimming monsters who are in the water - if ( !wasonground ) - { - if( !( ent->flags & FL_FLY ) ) - { - if( !( ( ent->flags & FL_SWIM ) && ( ent->waterlevel > 2 ) ) ) - { - if ( ent->velocity[ 2 ] < sv_gravity->value * ent->gravity * -0.1f ) - { - hitsound = true; - } + // Testing water gravity. If this doesn't work, just restore the uncommented lines + //if ( ent->waterlevel == 0 ) + //{ + G_AddGravity(ent); + //} + } + } + } - // Testing water gravity. If this doesn't work, just restore the uncommented lines - //if ( ent->waterlevel == 0 ) - //{ - G_AddGravity( ent ); - //} - } - } - } + // friction for flying monsters that have been given vertical velocity + if ((ent->flags & FL_FLY) && (ent->velocity.z != 0)) { + speed = fabs(ent->velocity.z); + control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; + friction = sv_friction->value / 3; + newspeed = speed - (level.frametime * control * friction); + if (newspeed < 0) { + newspeed = 0; + } + newspeed /= speed; + ent->velocity.z *= newspeed; + } - // friction for flying monsters that have been given vertical velocity - if( ( ent->flags & FL_FLY ) && ( ent->velocity.z != 0 ) ) - { - speed = fabs( ent->velocity.z ); - control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; - friction = sv_friction->value / 3; - newspeed = speed - ( level.frametime * control * friction ); - if ( newspeed < 0 ) - { - newspeed = 0; - } - newspeed /= speed; - ent->velocity.z *= newspeed; - } + // friction for flying monsters that have been given vertical velocity + if ((ent->flags & FL_SWIM) && (ent->velocity.z != 0)) { + speed = fabs(ent->velocity.z); + control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; + newspeed = speed - (level.frametime * control * sv_waterfriction->value * ent->waterlevel); + if (newspeed < 0) { + newspeed = 0; + } + newspeed /= speed; + ent->velocity.z *= newspeed; + } - // friction for flying monsters that have been given vertical velocity - if( ( ent->flags & FL_SWIM ) && ( ent->velocity.z != 0 ) ) - { - speed = fabs( ent->velocity.z ); - control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; - newspeed = speed - ( level.frametime * control * sv_waterfriction->value * ent->waterlevel ); - if ( newspeed < 0 ) - { - newspeed = 0; - } - newspeed /= speed; - ent->velocity.z *= newspeed; - } + if (ent->velocity != vec_zero) { + // apply friction + // let dead monsters who aren't completely onground slide + if ((wasonground) || (ent->flags & (FL_SWIM | FL_FLY))) { + if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) { + vel = ent->velocity; + vel.z = 0; + speed = vel.length(); + if (speed) { + friction = sv_friction->value; - if ( ent->velocity != vec_zero ) - { - // apply friction - // let dead monsters who aren't completely onground slide - if( ( wasonground ) || ( ent->flags & ( FL_SWIM | FL_FLY ) ) ) - { - if ( !( ent->health <= 0.0 && !M_CheckBottom( ent ) ) ) - { - vel = ent->velocity; - vel.z = 0; - speed = vel.length(); - if ( speed ) - { - friction = sv_friction->value; + control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; + newspeed = speed - level.frametime * control * friction; - control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; - newspeed = speed - level.frametime * control * friction; + if (newspeed < 0) { + newspeed = 0; + } - if ( newspeed < 0 ) - { - newspeed = 0; - } + newspeed /= speed; - newspeed /= speed; + ent->velocity.x *= newspeed; + ent->velocity.y *= newspeed; + } + } + } + } - ent->velocity.x *= newspeed; - ent->velocity.y *= newspeed; - } - } - } - } + if ((basevel != vec_zero) || (ent->velocity != vec_zero)) { + mask = MASK_SOLID; - if ( ( basevel != vec_zero ) || ( ent->velocity != vec_zero ) ) - { - mask = MASK_SOLID; + G_FlyMove(ent, basevel, level.frametime, mask); - G_FlyMove( ent, basevel, level.frametime, mask ); + ent->link(); - ent->link(); + G_CheckWater(ent); + if (ent->flags & FL_TOUCH_TRIGGERS) { + G_TouchTriggers(ent); + } - G_CheckWater( ent ); - if( ent->flags & FL_TOUCH_TRIGGERS ) - { - G_TouchTriggers( ent ); - } - - if ( ent->groundentity && !wasonground && hitsound ) - { - ent->Sound( "impact_softland", CHAN_BODY, 0.5f ); - } - } - } + if (ent->groundentity && !wasonground && hitsound) { + ent->Sound("impact_softland", CHAN_BODY, 0.5f); + } + } +} //============================================================================ @@ -1592,68 +1383,60 @@ G_RunEntity ================ */ -void G_RunEntity( Entity *ent ) +void G_RunEntity(Entity *ent) { - gentity_t *edict; + gentity_t *edict; - edict = ent->edict; + edict = ent->edict; - if( !edict->inuse ) - { - return; - } + if (!edict->inuse) { + return; + } - if( ent->flags & FL_ANIMATE ) - { - ent->PreAnimate(); - } + if (ent->flags & FL_ANIMATE) { + ent->PreAnimate(); + } - if( ent->flags & FL_THINK ) - { - ent->Think(); - } + if (ent->flags & FL_THINK) { + ent->Think(); + } - if( ent->flags & FL_ANIMATE ) - { - ent->PostAnimate(); - } + if (ent->flags & FL_ANIMATE) { + ent->PostAnimate(); + } - // only run physics if in use and not bound and not immobilized - if( ( edict->s.parent == ENTITYNUM_NONE ) && !( ent->flags & FL_IMMOBILE ) && !( ent->flags & FL_PARTIAL_IMMOBILE ) ) - { - switch( ent->movetype ) - { - case MOVETYPE_NONE: - case MOVETYPE_STATIONARY: - case MOVETYPE_WALK: - case MOVETYPE_FLYMISSILE: - case MOVETYPE_SLIDE: - case MOVETYPE_GIB: - case MOVETYPE_VEHICLE: - case MOVETYPE_TURRET: - break; - case MOVETYPE_PUSH: - case MOVETYPE_STOP: - G_Physics_Pusher( ent ); - break; - case MOVETYPE_NOCLIP: - G_Physics_Noclip( ent ); - break; - case MOVETYPE_FLY: - G_FlyMove( ent, ent->velocity, level.frametime, MASK_LINE ); - break; - case MOVETYPE_TOSS: - case MOVETYPE_BOUNCE: - G_Physics_Toss( ent ); - break; - default: - gi.Error( ERR_DROP, "G_Physics: bad movetype %i", ent->movetype ); - } - } + // only run physics if in use and not bound and not immobilized + if ((edict->s.parent == ENTITYNUM_NONE) && !(ent->flags & FL_IMMOBILE) && !(ent->flags & FL_PARTIAL_IMMOBILE)) { + switch (ent->movetype) { + case MOVETYPE_NONE: + case MOVETYPE_STATIONARY: + case MOVETYPE_WALK: + case MOVETYPE_FLYMISSILE: + case MOVETYPE_SLIDE: + case MOVETYPE_GIB: + case MOVETYPE_VEHICLE: + case MOVETYPE_TURRET: + break; + case MOVETYPE_PUSH: + case MOVETYPE_STOP: + G_Physics_Pusher(ent); + break; + case MOVETYPE_NOCLIP: + G_Physics_Noclip(ent); + break; + case MOVETYPE_FLY: + G_FlyMove(ent, ent->velocity, level.frametime, MASK_LINE); + break; + case MOVETYPE_TOSS: + case MOVETYPE_BOUNCE: + G_Physics_Toss(ent); + break; + default: + gi.Error(ERR_DROP, "G_Physics: bad movetype %i", ent->movetype); + } + } - if( ent->flags & FL_POSTTHINK ) - { - ent->Postthink(); - } + if (ent->flags & FL_POSTTHINK) { + ent->Postthink(); + } } - diff --git a/code/fgame/g_phys.h b/code/fgame/g_phys.h index 6690ff68..64dc5f2f 100644 --- a/code/fgame/g_phys.h +++ b/code/fgame/g_phys.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2008 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,62 +22,56 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // g_phys.h: Header for g_phys.cpp -#ifndef __G_PHYS_H__ -#define __G_PHYS_H__ +#pragma once #include "g_local.h" #include "vector.h" class Entity; -typedef enum -{ - STEPMOVE_OK, - STEPMOVE_BLOCKED_BY_ENTITY, - STEPMOVE_BLOCKED_BY_WORLD, - STEPMOVE_BLOCKED_BY_WATER, - STEPMOVE_BLOCKED_BY_FALL, - STEPMOVE_BLOCKED_BY_DOOR, - STEPMOVE_STUCK +typedef enum { + STEPMOVE_OK, + STEPMOVE_BLOCKED_BY_ENTITY, + STEPMOVE_BLOCKED_BY_WORLD, + STEPMOVE_BLOCKED_BY_WATER, + STEPMOVE_BLOCKED_BY_FALL, + STEPMOVE_BLOCKED_BY_DOOR, + STEPMOVE_STUCK } stepmoveresult_t; // movetype values -typedef enum -{ - MOVETYPE_NONE, // never moves - MOVETYPE_STATIONARY, // never moves but does collide agains push objects - MOVETYPE_NOCLIP, // origin and angles change with no interaction - MOVETYPE_PUSH, // no clip to world, push on box contact - MOVETYPE_STOP, // no clip to world, stops on box contact - MOVETYPE_WALK, // gravity - MOVETYPE_FLY, - MOVETYPE_TOSS, // gravity - MOVETYPE_FLYMISSILE, // extra size to monsters - MOVETYPE_BOUNCE, - MOVETYPE_SLIDE, - MOVETYPE_GIB, - MOVETYPE_VEHICLE, - MOVETYPE_TURRET, - MOVETYPE_PORTABLE_TURRET +typedef enum { + MOVETYPE_NONE, // never moves + MOVETYPE_STATIONARY, // never moves but does collide agains push objects + MOVETYPE_NOCLIP, // origin and angles change with no interaction + MOVETYPE_PUSH, // no clip to world, push on box contact + MOVETYPE_STOP, // no clip to world, stops on box contact + MOVETYPE_WALK, // gravity + MOVETYPE_FLY, + MOVETYPE_TOSS, // gravity + MOVETYPE_FLYMISSILE, // extra size to monsters + MOVETYPE_BOUNCE, + MOVETYPE_SLIDE, + MOVETYPE_GIB, + MOVETYPE_VEHICLE, + MOVETYPE_TURRET, + MOVETYPE_PORTABLE_TURRET } movetype_t; -typedef struct -{ - Entity *ent; - Vector localorigin; - Vector origin; - Vector localangles; - Vector angles; - float deltayaw; +typedef struct { + Entity *ent; + Vector localorigin; + Vector origin; + Vector localangles; + Vector angles; + float deltayaw; } pushed_t; -extern pushed_t pushed[]; +extern pushed_t pushed[]; extern pushed_t *pushed_p; -void G_RunEntity( Entity *ent ); -void G_Impact( Entity *e1, trace_t *trace ); -qboolean G_PushMove( Entity *pusher, Vector move, Vector amove ); -void G_CheckWater( Entity *ent ); -Entity *G_TestEntityPosition( Entity *ent, Vector vOrg ); - -#endif /* g_phys.h */ +void G_RunEntity(Entity *ent); +void G_Impact(Entity *e1, trace_t *trace); +qboolean G_PushMove(Entity *pusher, Vector move, Vector amove); +void G_CheckWater(Entity *ent); +Entity *G_TestEntityPosition(Entity *ent, Vector vOrg); diff --git a/code/fgame/g_public.h b/code/fgame/g_public.h index 52fbe33a..e4f235d3 100644 --- a/code/fgame/g_public.h +++ b/code/fgame/g_public.h @@ -30,465 +30,553 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Version 11 is >= 0.05 and <= 1.00 // Version 12 is >= 1.10 // Version 15 is >= 2.0 -#define GAME_API_VERSION 15 +#define GAME_API_VERSION 15 // entity->svFlags // the server does not know how to interpret most of the values // in entityStates (level eType), so the game must explicitly flag // special server behaviors -#define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects +#define SVF_NOCLIENT (1<<0) // don't send entity to clients, even if it has effects +#define SVF_BOT (1<<1) +#define SVF_BROADCAST (1<<2) // send to all connected clients +#define SVF_PORTAL (1<<3) // merge a second pvs at origin2 into snapshots +#define SVF_SENDPVS (1<<4) // even though it doesn't have a sound or modelindex, still run it through the pvs +#define SVF_USE_CURRENT_ORIGIN (1<<5) // entity->currentOrigin instead of entity->s.origin + // for link position (missiles and movers) +#define SVF_NOTSINGLECLIENT (1<<6) // send entity to everyone but one client + // (entityShared_t->singleClient) +#define SVF_MONSTER (1<<7) // treat as CONTENTS_MONSTER for collision +#define SVF_SINGLECLIENT (1<<8) // only send to a single client (entityShared_t->singleClient) +#define SVF_USEBBOX (1<<9) // do not perform perfect collision use the bbox instead +#define SVF_NOFARPLANE (1<<10) // only send this entity to its parent +#define SVF_HIDEOWNER (1<<11) // hide the owner of the client +#define SVF_MONSTERCLIP (1<<12) // treat as CONTENTS_MONSTERCLIP for collision +#define SVF_PLAYERCLIP (1<<13) // treat as CONTENTS_PLAYERCLIP for collision +#define SVF_SENDONCE (1<<14) // Send this entity over the network at least one time +#define SVF_SENT (1<<15) // This flag is set when the entity has been sent over at least one time -// TTimo -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=551 -#define SVF_CLIENTMASK 0x00000002 +#define SVF_NOSERVERINFO (1<<16) // don't send CS_SERVERINFO updates to this client + // so that it can be updated for ping tools without + // lagging clients -#define SVF_BROADCAST 0x00000004 // send to all connected clients -#define SVF_MONSTER 0x00000008 // set if the entity is a bot -#define SVF_PORTAL 0x00000040 // merge a second pvs at origin2 into snapshots -#define SVF_USE_CURRENT_ORIGIN 0x00000080 // entity->r.currentOrigin instead of entity->s.origin - // for link position (missiles and movers) -#define SVF_SINGLECLIENT 0x00000100 // only send to a single client (entityShared_t->singleClient) -#define SVF_NOSERVERINFO 0x00000200 // don't send CS_SERVERINFO updates to this client - // so that it can be updated for ping tools without - // lagging clients -#define SVF_CAPSULE 0x00000400 // use capsule for collision detection instead of bbox -#define SVF_NOTSINGLECLIENT 0x00000800 // send entity to everyone but one client - // (entityShared_t->singleClient) - -#define SVF_USEBBOX 0x00001000 -#define SVF_SENDONCE 0x00004000 - -#define SVF_HIDEOWNER 0x00008000 -#define SVF_SENDPVS 0x00010000 - -typedef struct gclient_s gclient_t; -typedef struct dtiki_s dtiki_t; -typedef struct tiki_cmd_s tiki_cmd_t; +typedef struct gclient_s gclient_t; +typedef struct dtiki_s dtiki_t; +typedef struct tiki_cmd_s tiki_cmd_t; typedef struct dtikianim_s dtikianim_t; -typedef struct tiki_s tiki_t; +typedef struct tiki_s tiki_t; -typedef struct tikiAnim_s tikiAnim_t; -typedef struct baseshader_s baseshader_t; +typedef struct tikiAnim_s tikiAnim_t; +typedef struct baseshader_s baseshader_t; typedef struct AliasListNode_s AliasListNode_t; -typedef void( *xcommand_t ) ( void ); +typedef void (*xcommand_t)(void); + +#define MAX_NONPVS_SOUNDS 4 typedef struct { - // su44: sharedEntity_t::s is used instead of it - //entityState_t s; // communicated by server to clients + int index; + float volume; + float minDist; + float maxDist; + float pitch; +} nonpvs_sound_t; - qboolean linked; // qfalse if not in any good cluster - int linkcount; +typedef struct { + // su44: sharedEntity_t::s is used instead of it + //entityState_t s; // communicated by server to clients - int svFlags; // SVF_NOCLIENT, SVF_BROADCAST, etc + qboolean linked; // qfalse if not in any good cluster + int linkcount; - // only send to this client when SVF_SINGLECLIENT is set - // if SVF_CLIENTMASK is set, use bitmask for clients to send to (maxclients must be <= 32, up to the mod to enforce this) - int singleClient; + int svFlags; // SVF_NOCLIENT, SVF_BROADCAST, etc - int lastNetTime; + // only send to this client when SVF_SINGLECLIENT is set + // if SVF_CLIENTMASK is set, use bitmask for clients to send to (maxclients must be <= 32, up to the mod to enforce this) + int singleClient; - qboolean bmodel; // if false, assume an explicit mins / maxs bounding box - // only set by gi.SetBrushModel - vec3_t mins, maxs; - int contents; // CONTENTS_TRIGGER, CONTENTS_SOLID, CONTENTS_BODY, etc - // a non-solid entity should set to 0 + int lastNetTime; - vec3_t absmin, absmax; // derived from mins/maxs and origin + rotation + qboolean bmodel; // if false, assume an explicit mins / maxs bounding box + // only set by gi.SetBrushModel + vec3_t mins, maxs; + int contents; // CONTENTS_TRIGGER, CONTENTS_SOLID, CONTENTS_BODY, etc + // a non-solid entity should set to 0 - float radius; + vec3_t absmin, absmax; // derived from mins/maxs and origin + rotation + float radius; + // centroid will be used for all collision detection and world linking. + // it will not necessarily be the same as the trajectory evaluation for the current + // time, because each entity must be moved one at a time after time is advanced + // to avoid simultanious collision issues + vec3_t centroid; // centroid, to be used with radius - // currentOrigin will be used for all collision detection and world linking. - // it will not necessarily be the same as the trajectory evaluation for the current - // time, because each entity must be moved one at a time after time is advanced - // to avoid simultanious collision issues - vec3_t currentOrigin; + int areanum; - int areanum; + vec3_t currentAngles; - vec3_t currentAngles; + // when a trace call is made and passEntityNum != ENTITYNUM_NONE, + // an ent will be excluded from testing if: + // ent->s.number == passEntityNum (don't interact with self) + // ent->s.ownerNum = passEntityNum (don't interact with your own missiles) + // entity[ent->s.ownerNum].ownerNum = passEntityNum (don't interact with other missiles from owner) + int ownerNum; - // when a trace call is made and passEntityNum != ENTITYNUM_NONE, - // an ent will be excluded from testing if: - // ent->s.number == passEntityNum (don't interact with self) - // ent->s.ownerNum = passEntityNum (don't interact with your own missiles) - // entity[ent->s.ownerNum].ownerNum = passEntityNum (don't interact with other missiles from owner) - int ownerNum; + // whether or not this entity emitted a sound this frame + // (used for when the entity shouldn't be sent to clients) + nonpvs_sound_t nonpvs_sounds[MAX_NONPVS_SOUNDS]; + int num_nonpvs_sounds; } entityShared_t; // client data that stays across multiple respawns, but is cleared // on each level change or team change at ClientBegin() typedef struct { - char userinfo[ MAX_INFO_STRING ]; - char netname[ MAX_NAME_LENGTH ]; - char dm_playermodel[ MAX_QPATH ]; - char dm_playergermanmodel[ MAX_QPATH ]; - char dm_primary[ MAX_QPATH ]; + char userinfo[MAX_INFO_STRING]; + char netname[MAX_NAME_LENGTH]; + char dm_playermodel[MAX_QPATH]; + char dm_playergermanmodel[MAX_QPATH]; + char dm_primary[MAX_QPATH]; - float enterTime; + float enterTime; - teamtype_t teamnum; - int round_kills; + teamtype_t teamnum; + int round_kills; - char ip[ 17 ]; - int port; + char ip[17]; + int port; } client_persistant_t; - // this structure is cleared on each ClientSpawn(), // except for 'client->pers' and 'client->sess' struct gclient_s { - // ps MUST be the first element, because the server expects it - playerState_t ps; // communicated by server to clients + // ps MUST be the first element, because the server expects it + playerState_t ps; // communicated by server to clients #ifdef GAME_DLL - // the rest of the structure is private to game - int ping; - client_persistant_t pers; - float cmd_angles[ 3 ]; + // the rest of the structure is private to game + int ping; + client_persistant_t pers; + float cmd_angles[3]; - int lastActiveTime; - int activeWarning; + int lastActiveTime; + int activeWarning; - struct gentity_s *ent; - struct gclient_s *next; - struct gclient_s *prev; + struct gentity_s *ent; + struct gclient_s *next; + struct gclient_s *prev; #endif }; typedef struct gentity_s { - entityState_t s; // communicated by server to clients + entityState_t s; // communicated by server to clients - struct gclient_s *client; // NULL if not a client - qboolean inuse; + struct gclient_s *client; // NULL if not a client + qboolean inuse; - entityShared_t r; // shared by both the server system and game + entityShared_t r; // shared by both the server system and game - solid_t solid; - dtiki_t *tiki; - float mat[ 3 ][ 3 ]; + solid_t solid; + dtiki_t *tiki; + float mat[3][3]; - // Leave reminder to the game dll -#if defined( GAME_DLL ) - class Entity *entity; - float freetime; - float spawntime; - float radius2; - char entname[ 64 ]; - int clipmask; + // Leave reminder to the game dll +#if defined(GAME_DLL) + class Entity *entity; + float freetime; + float spawntime; + float radius2; + char entname[64]; + int clipmask; - struct gentity_s *next; - struct gentity_s *prev; + struct gentity_s *next; + struct gentity_s *prev; #endif } gentity_t; // movers are things like doors, plats, buttons, etc typedef enum { - MOVER_POS1, - MOVER_POS2, - MOVER_1TO2, - MOVER_2TO1 + MOVER_POS1, + MOVER_POS2, + MOVER_1TO2, + MOVER_2TO1 } moverState_t; -typedef struct profVar_s -{ - int start; - int clockCycles; - int calls; - float time; - float totTime; - float avgTime; - float low; - float high; +typedef struct profVar_s { + int start; + int clockCycles; + int calls; + float time; + float totTime; + float avgTime; + float low; + float high; } profVar_t; -typedef struct profGame_s -{ - profVar_t AI; - profVar_t MmoveSingle; - profVar_t thread_timingList; - profVar_t gamescripts; - profVar_t GProbe1; - profVar_t GProbe2; - profVar_t GProbe3; - profVar_t FindPath; - profVar_t vector_length; - profVar_t script_trace; - profVar_t internal_trace; - profVar_t PreAnimate; - profVar_t PostAnimate; +typedef struct profGame_s { + profVar_t AI; + profVar_t MmoveSingle; + profVar_t thread_timingList; + profVar_t gamescripts; + profVar_t GProbe1; + profVar_t GProbe2; + profVar_t GProbe3; + profVar_t FindPath; + profVar_t vector_length; + profVar_t script_trace; + profVar_t internal_trace; + profVar_t PreAnimate; + profVar_t PostAnimate; } profGame_t; //=============================================================== -typedef struct gameImport_s -{ - void ( *Printf )( const char *format, ... ); - void ( *DPrintf )( const char *format, ... ); - void ( *DPrintf2 )( const char *format, ... ); - void ( *DebugPrintf )( const char *format, ... ); - void ( *Error )( int level, const char *format, ... ); - int ( *Milliseconds )( ); - const char * ( *LV_ConvertString )( const char *string ); - const char * ( *CL_LV_ConvertString )( const char *string ); - void * ( *Malloc )( size_t size ); - void ( *Free )( void *ptr ); - cvar_t * ( *Cvar_Get )( const char *varName, const char *varValue, int varFlags ); - void ( *cvar_set )( const char *varName, const char *varValue ); - cvar_t *( *cvar_set2 )( const char *varName, const char *varValue, qboolean force ); - cvar_t *( *NextCvar )( cvar_t *var ); - int ( *Argc )( ); - char * ( *Argv )( int arg ); - char * ( *Args )( ); - void ( *AddCommand )( const char *cmdName, xcommand_t cmdFunction ); - int ( *FS_ReadFile )( const char *qpath, void **buffer, qboolean quiet ); - void ( *FS_FreeFile )( void *buffer ); - int ( *FS_WriteFile )( const char *qpath, const void *buffer, int size ); - fileHandle_t ( *FS_FOpenFileWrite )( const char *fileName ); - fileHandle_t ( *FS_FOpenFileAppend )( const char *fileName ); - const char *( *FS_PrepFileWrite )( const char *fileName ); - size_t( *FS_Write )( const void *buffer, size_t size, fileHandle_t fileHandle ); - size_t( *FS_Read )( void *buffer, size_t len, fileHandle_t fileHandle ); - void ( *FS_FCloseFile )( fileHandle_t fileHandle ); - int ( *FS_Tell )( fileHandle_t fileHandle ); - int ( *FS_Seek )( fileHandle_t fileHandle, long int offset, fsOrigin_t origin ); - void ( *FS_Flush )( fileHandle_t fileHandle ); - int ( *FS_FileNewer )( const char *source, const char *destination ); - void ( *FS_CanonicalFilename )( char *fileName ); - char **( *FS_ListFiles )( const char *qpath, const char *extension, qboolean wantSubs, int *numFiles ); - void ( *FS_FreeFileList )( char **list ); - const char *( *GetArchiveFileName )(const char *fileName, const char *extension ); - void ( *SendConsoleCommand )( const char *text ); - void ( *DebugGraph )( float value ); - void ( *SendServerCommand )( int client, const char *format, ... ); - void ( *DropClient )( int client, const char *reason ); - void ( *MSG_WriteBits )( int value, int bits ); - void ( *MSG_WriteChar )( int c ); - void ( *MSG_WriteByte )( int c ); - void ( *MSG_WriteSVC )( int c ); - void ( *MSG_WriteShort )( int c ); - void ( *MSG_WriteLong )( int c ); - void ( *MSG_WriteFloat )( float f ); - void ( *MSG_WriteString )( const char *s ); - void ( *MSG_WriteAngle8 )( float f ); - void ( *MSG_WriteAngle16 )(float f ); - void ( *MSG_WriteCoord )( float f ); - void ( *MSG_WriteDir )( vec3_t dir ); - void ( *MSG_StartCGM )( int type ); - void ( *MSG_EndCGM )( ); - void ( *MSG_SetClient )( int client ); - void ( *SetBroadcastVisible )( const vec3_t pos, const vec3_t posB ); - void ( *SetBroadcastHearable )(const vec3_t pos, const vec3_t posB ); - void ( *SetBroadcastAll )( ); - void ( *setConfigstring )( int index, const char *val ); - char *( *getConfigstring )( int index ); - void ( *SetUserinfo )( int index, const char *val ); - void ( *GetUserinfo )( int index, char *buffer, int bufferSize ); - void ( *SetBrushModel )( gentity_t *ent, const char *name ); - void ( *ModelBoundsFromName )(const char *name, vec3_t mins, vec3_t maxs ); - qboolean ( *SightTraceEntity )( gentity_t *touch, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int contentMask, qboolean cylinder ); - qboolean ( *SightTrace )( const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int passEntityNum2, int contentMask, qboolean cylinder ); - void ( *trace )( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask, qboolean cylinder, qboolean traceDeep ); - baseshader_t * ( *GetShader )( int shaderNum ); - int ( *pointcontents )( const vec3_t p, int passEntityNum ); - int ( *PointBrushnum )(const vec3_t p, clipHandle_t model ); - void ( *AdjustAreaPortalState )( gentity_t *ent, qboolean open ); - int ( *AreaForPoint )( vec3_t pos ); - qboolean ( *AreasConnected )( int area1, int area2); - qboolean ( *InPVS )( float *p1, float *p2 ); - void ( *linkentity )( gentity_t *gEnt ); - void ( *unlinkentity )( gentity_t *gEnt ); - int ( *AreaEntities )( const vec3_t mins, const vec3_t maxs, int *list, int maxcount ); - void ( *ClipToEntity )( trace_t *tr, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int entityNum, int contentMask ); - qboolean (*HitEntity)(gentity_t* pEnt, gentity_t* pOther); - int ( *imageindex )( const char *name ); - int ( *itemindex )( const char *name ); - int ( *soundindex )( const char *name, int streamed ); - dtiki_t *( *TIKI_RegisterModel )( const char *path ); - dtiki_t *( *modeltiki )( const char *name ); - dtikianim_t *( *modeltikianim )( const char *name ); - void ( *SetLightStyle )( int index, const char *data ); - const char *( *GameDir )( ); - qboolean ( *setmodel )( gentity_t *ent, const char *name ); - void ( *clearmodel )( gentity_t *ent ); - int ( *TIKI_NumAnims )( dtiki_t *tiki ); - int ( *NumSurfaces )( dtiki_t *tiki ); - int ( *NumTags )( dtiki_t *tiki ); - void( *CalculateBounds )( dtiki_t *tiki, float scale, vec3_t mins, vec3_t maxs ); - void *( *TIKI_GetSkeletor )( dtiki_t *tiki, int entNum ); - const char *( *Anim_NameForNum )( dtiki_t *tiki, int animNum ); - int ( *Anim_NumForName )( dtiki_t *tiki, const char *name ); - int ( *Anim_Random )( dtiki_t *tiki, const char *name ); - int ( *Anim_NumFrames )( dtiki_t *tiki, int animNum ); - float ( *Anim_Time )( dtiki_t *tiki, int animNum ); - float ( *Anim_Frametime )( dtiki_t *tiki, int animNum ); - float ( *Anim_CrossTime )( dtiki_t *tiki, int animNum ); - void ( *Anim_Delta )( dtiki_t *tiki, int animNum, float *delta ); - qboolean ( *Anim_HasDelta )( dtiki_t *tiki, int animNum ); - void ( *Anim_DeltaOverTime )( dtiki_t *tiki, int animNum, float time1, float time2, float *delta ); - void ( *Anim_AngularDeltaOverTime )( dtiki_t *tiki, int animNum, float time1, float time2, float *delta ); - int ( *Anim_Flags )( dtiki_t *tiki, int animNum ); - int ( *Anim_FlagsSkel )( dtiki_t *tiki, int animNum ); - qboolean ( *Anim_HasCommands )( dtiki_t *tiki, int animNum ); - int ( *NumHeadModels )( const char *model ); - void ( *GetHeadModel )( const char *model, int num, char *name ); - int ( *NumHeadSkins )( const char *model ); - void ( *GetHeadSkin )( const char *model, int num, char *name ); - qboolean ( *Frame_Commands )( dtiki_t *tiki, int animNum, int frameNum, tiki_cmd_t *tikiCmds ); - int ( *Surface_NameToNum )( dtiki_t *tiki, const char *name ); - const char * ( *Surface_NumToName )( dtiki_t *tiki, int surfacenum ); - int ( *Tag_NumForName )( dtiki_t *pmdl, const char *name ); - const char * ( *Tag_NameForNum )( dtiki_t *pmdl, int tagNum); - orientation_t ( *TIKI_OrientationInternal )( dtiki_t *tiki, int entNum, int tagNum, float scale ); - void *( *TIKI_TransformInternal )( dtiki_t *tiki, int entNum, int tagNum ); - qboolean ( *TIKI_IsOnGroundInternal )( dtiki_t *tiki, int entNum, int num, float threshold ); - void ( *TIKI_SetPoseInternal )( dtiki_t *tiki, int entNum, const frameInfo_t *frameInfo, int *boneTag, vec4_t *boneQuat, float actionWeight ); - const char *( *CM_GetHitLocationInfo )( int location, float *radius, float *offset ); - const char *( *CM_GetHitLocationInfoSecondary )( int location, float *radius, float *offset ); +typedef struct gameImport_s { + void (*Printf)(const char *format, ...); + void (*DPrintf)(const char *format, ...); + void (*DPrintf2)(const char *format, ...); + void (*DebugPrintf)(const char *format, ...); + void (*Error)(int level, const char *format, ...); + int (*Milliseconds)(); + const char *(*LV_ConvertString)(const char *string); - qboolean ( *Alias_Add )( dtiki_t *pmdl, const char *alias, const char *name, const char *parameters ); - const char *( *Alias_FindRandom )( dtiki_t *tiki, const char *alias, AliasListNode_t **ret ); - void ( *Alias_Dump )( dtiki_t *tiki ); - void ( *Alias_Clear )( dtiki_t *tiki ); - void ( *Alias_UpdateDialog )( dtikianim_t *tiki, const char *alias ); + // Added in 2.0 + const char *(*CL_LV_ConvertString)(const char *string); - const char *( *TIKI_NameForNum )( dtiki_t *tiki ); + void *(*Malloc)(size_t size); + void (*Free)(void *ptr); + cvar_t *(*Cvar_Get)(const char *varName, const char *varValue, int varFlags); + void (*cvar_set)(const char *varName, const char *varValue); + cvar_t *(*cvar_set2)(const char *varName, const char *varValue, qboolean force); + cvar_t *(*NextCvar)(cvar_t *var); + void (*Cvar_CheckRange)(cvar_t* var, float min, float max, qboolean integral); - qboolean ( *GlobalAlias_Add )( const char *alias, const char *name, const char *parameters ); - const char *( *GlobalAlias_FindRandom )( const char *alias, AliasListNode_t **ret ); - void ( *GlobalAlias_Dump )( ); - void ( *GlobalAlias_Clear )( ); + int (*Argc)(); + char *(*Argv)(int arg); + char *(*Args)(); + void (*AddCommand)(const char *cmdName, xcommand_t cmdFunction); + long (*FS_ReadFile)(const char *qpath, void **buffer, qboolean quiet); + void (*FS_FreeFile)(void *buffer); + int (*FS_WriteFile)(const char *qpath, const void *buffer, int size); + fileHandle_t (*FS_FOpenFileWrite)(const char *fileName); + fileHandle_t (*FS_FOpenFileAppend)(const char *fileName); + long (*FS_FOpenFile)(const char* qpath, fileHandle_t *file, qboolean uniqueFILE, qboolean quiet); + const char *(*FS_PrepFileWrite)(const char *fileName); + size_t (*FS_Write)(const void *buffer, size_t size, fileHandle_t fileHandle); + size_t (*FS_Read)(void *buffer, size_t len, fileHandle_t fileHandle); + void (*FS_FCloseFile)(fileHandle_t fileHandle); + int (*FS_Tell)(fileHandle_t fileHandle); + int (*FS_Seek)(fileHandle_t fileHandle, long int offset, int origin); + void (*FS_Flush)(fileHandle_t fileHandle); + int (*FS_FileNewer)(const char *source, const char *destination); + void (*FS_CanonicalFilename)(char *fileName); + char **(*FS_ListFiles)(const char *qpath, const char *extension, qboolean wantSubs, int *numFiles); + void (*FS_FreeFileList)(char **list); + const char *(*GetArchiveFileName)(const char *fileName, const char *extension); + void (*SendConsoleCommand)(const char *text); - void ( *centerprintf )( gentity_t *ent, const char *format, ... ); - void ( *locationprintf )( gentity_t *ent, int x, int y, const char *format, ... ); - void ( *Sound )( vec3_t *org, int entNum, int channel, const char *soundName, float volume, float minDist, float pitch, float maxDist, int streamed ); - void ( *StopSound )( int entNum, int channel ); - float ( *SoundLength )( int channel, const char *name ); - unsigned char * ( *SoundAmplitudes )( int channel, const char *name ); - int( *S_IsSoundPlaying )( int channel, const char *name ); - short unsigned int ( *CalcCRC )( unsigned char *start, int count ); + // Added in 2.0 + void (*ExecuteConsoleCommand)(int exec_when, const char *text); - debugline_t **DebugLines; - int *numDebugLines; - debugstring_t **DebugStrings; - int *numDebugStrings; + void (*DebugGraph)(float value); + void (*SendServerCommand)(int client, const char *format, ...); + void (*DropClient)(int client, const char *reason); + void (*MSG_WriteBits)(int value, int bits); + void (*MSG_WriteChar)(int c); + void (*MSG_WriteByte)(int c); + void (*MSG_WriteSVC)(int c); + void (*MSG_WriteShort)(int c); + void (*MSG_WriteLong)(int c); + void (*MSG_WriteFloat)(float f); + void (*MSG_WriteString)(const char *s); + void (*MSG_WriteAngle8)(float f); + void (*MSG_WriteAngle16)(float f); + void (*MSG_WriteCoord)(float f); + void (*MSG_WriteDir)(vec3_t dir); + void (*MSG_StartCGM)(int type); + void (*MSG_EndCGM)(); + void (*MSG_SetClient)(int client); + void (*SetBroadcastVisible)(const vec3_t pos, const vec3_t posB); + void (*SetBroadcastHearable)(const vec3_t pos, const vec3_t posB); + void (*SetBroadcastAll)(); + void (*setConfigstring)(int index, const char *val); + char *(*getConfigstring)(int index); + void (*SetUserinfo)(int index, const char *val); + void (*GetUserinfo)(int index, char *buffer, int bufferSize); + void (*SetBrushModel)(gentity_t *ent, const char *name); + void (*ModelBoundsFromName)(const char *name, vec3_t mins, vec3_t maxs); + qboolean (*SightTraceEntity)( + gentity_t *touch, + const vec3_t start, + const vec3_t mins, + const vec3_t maxs, + const vec3_t end, + int contentMask, + qboolean cylinder + ); + qboolean (*SightTrace)( + const vec3_t start, + const vec3_t mins, + const vec3_t maxs, + const vec3_t end, + int passEntityNum, + int passEntityNum2, + int contentMask, + qboolean cylinder + ); + void (*trace)( + trace_t *results, + const vec3_t start, + const vec3_t mins, + const vec3_t maxs, + const vec3_t end, + int passEntityNum, + int contentMask, + qboolean cylinder, + qboolean traceDeep + ); - void ( *LocateGameData )( gentity_t *gEnts, int numGEntities, int sizeofGEntity, playerState_t *clients, int sizeofGameClient ); - void ( *SetFarPlane )(int farPlane ); - void ( *SetSkyPortal )( qboolean skyPortal ); - void ( *Popmenu )( int client , int i ); - void ( *Showmenu )( int client, const char *name, qboolean force ); - void ( *Hidemenu )( int client, const char *name, qboolean force ); - void ( *Pushmenu )( int client, const char *name ); - void ( *HideMouseCursor )( int client ); - void ( *ShowMouseCursor )( int client ); - const char * ( *MapTime )( ); - void ( *LoadResource )( const char *name ); - void ( *ClearResource )( ); - int ( *Key_StringToKeynum )( const char *str ); - const char *( *Key_KeynumToBindString )( int keyNum ); - void ( *Key_GetKeysForCommand )( const char *command, int *key1, int *key2 ); - void ( *ArchiveLevel )( qboolean loading ); - void ( *AddSvsTimeFixup )( int *piTime ); - void ( *HudDrawShader )( int info, char *name ); - void ( *HudDrawAlign )( int info, int horizontalAlign, int verticalAlign ); - void ( *HudDrawRect )( int info, int x, int y, int width, int height ); - void ( *HudDrawVirtualSize )( int info, qboolean virtualScreen); - void ( *HudDrawColor )( int info, float *color ); - void ( *HudDrawAlpha )( int info, float alpha ); - void ( *HudDrawString )( int info, const char *string ); - void ( *HudDrawFont )( int info, const char *fontName ); - qboolean ( *SanitizeName )(const char *oldName, char *newName); + // Added in 2.0 + float (*CM_VisualObfuscation)(const vec3_t start, const vec3_t end); - cvar_t *fsDebug; + baseshader_t *(*GetShader)(int shaderNum); + int (*pointcontents)(const vec3_t p, int passEntityNum); + int (*PointBrushnum)(const vec3_t p, clipHandle_t model); + void (*AdjustAreaPortalState)(gentity_t *ent, qboolean open); + int (*AreaForPoint)(vec3_t pos); + qboolean (*AreasConnected)(int area1, int area2); + qboolean (*InPVS)(float *p1, float *p2); + void (*linkentity)(gentity_t *gEnt); + void (*unlinkentity)(gentity_t *gEnt); + int (*AreaEntities)(const vec3_t mins, const vec3_t maxs, int *list, int maxcount); + void (*ClipToEntity)( + trace_t *tr, + const vec3_t start, + const vec3_t mins, + const vec3_t maxs, + const vec3_t end, + int entityNum, + int contentMask + ); - // - // New functions will start from here - // + // Added in 2.0 + qboolean (*HitEntity)(gentity_t *pEnt, gentity_t *pOther); + + int (*imageindex)(const char *name); + int (*itemindex)(const char *name); + int (*soundindex)(const char *name, int streamed); + dtiki_t *(*TIKI_RegisterModel)(const char *path); + dtiki_t *(*modeltiki)(const char *name); + dtikianim_t *(*modeltikianim)(const char *name); + void (*SetLightStyle)(int index, const char *data); + const char *(*GameDir)(); + qboolean (*setmodel)(gentity_t *ent, const char *name); + void (*clearmodel)(gentity_t *ent); + int (*TIKI_NumAnims)(dtiki_t *tiki); + int (*TIKI_NumSurfaces)(dtiki_t *tiki); + int (*TIKI_NumTags)(dtiki_t *tiki); + void (*TIKI_CalculateBounds)(dtiki_t *tiki, float scale, vec3_t mins, vec3_t maxs); + void *(*TIKI_GetSkeletor)(dtiki_t *tiki, int entNum); + const char *(*Anim_NameForNum)(dtiki_t *tiki, int animNum); + int (*Anim_NumForName)(dtiki_t *tiki, const char *name); + int (*Anim_Random)(dtiki_t *tiki, const char *name); + int (*Anim_NumFrames)(dtiki_t *tiki, int animNum); + float (*Anim_Time)(dtiki_t *tiki, int animNum); + float (*Anim_Frametime)(dtiki_t *tiki, int animNum); + float (*Anim_CrossTime)(dtiki_t *tiki, int animNum); + void (*Anim_Delta)(dtiki_t *tiki, int animNum, float *delta); + + // Added in 2.0 + void (*Anim_AngularDelta)(dtiki_t *tiki, int animNum, float *delta); + + qboolean (*Anim_HasDelta)(dtiki_t *tiki, int animNum); + void (*Anim_DeltaOverTime)(dtiki_t *tiki, int animNum, float time1, float time2, float *delta); + + // Added in 2.0 + void (*Anim_AngularDeltaOverTime)(dtiki_t *tiki, int animNum, float time1, float time2, float *delta); + + int (*Anim_Flags)(dtiki_t *tiki, int animNum); + int (*Anim_FlagsSkel)(dtiki_t *tiki, int animNum); + qboolean (*Anim_HasCommands)(dtiki_t *tiki, int animNum); + qboolean (*Anim_HasCommands_Client)(dtiki_t *tiki, int animNum); + int (*NumHeadModels)(const char *model); + void (*GetHeadModel)(const char *model, int num, char *name); + int (*NumHeadSkins)(const char *model); + void (*GetHeadSkin)(const char *model, int num, char *name); + qboolean (*Frame_Commands)(dtiki_t *tiki, int animNum, int frameNum, tiki_cmd_t *tikiCmds); + qboolean (*Frame_Commands_Client)(dtiki_t *tiki, int animNum, int frameNum, tiki_cmd_t *tikiCmds); + int (*Surface_NameToNum)(dtiki_t *tiki, const char *name); + const char *(*Surface_NumToName)(dtiki_t *tiki, int surfacenum); + int (*Tag_NumForName)(dtiki_t *pmdl, const char *name); + const char *(*Tag_NameForNum)(dtiki_t *pmdl, int tagNum); + orientation_t (*TIKI_OrientationInternal)(dtiki_t *tiki, int entNum, int tagNum, float scale); + void *(*TIKI_TransformInternal)(dtiki_t *tiki, int entNum, int tagNum); + qboolean (*TIKI_IsOnGroundInternal)(dtiki_t *tiki, int entNum, int num, float threshold); + void (*TIKI_SetPoseInternal)( + dtiki_t *tiki, int entNum, const frameInfo_t *frameInfo, int *boneTag, vec4_t *boneQuat, float actionWeight + ); + const char *(*CM_GetHitLocationInfo)(int location, float *radius, float *offset); + const char *(*CM_GetHitLocationInfoSecondary)(int location, float *radius, float *offset); + + qboolean (*Alias_Add)(dtiki_t *pmdl, const char *alias, const char *name, const char *parameters); + const char *(*Alias_FindRandom)(dtiki_t *tiki, const char *alias, AliasListNode_t **ret); + void (*Alias_Dump)(dtiki_t *tiki); + void (*Alias_Clear)(dtiki_t *tiki); + void (*Alias_UpdateDialog)(dtikianim_t *tiki, const char *alias); + + const char *(*TIKI_NameForNum)(dtiki_t *tiki); + + qboolean (*GlobalAlias_Add)(const char *alias, const char *name, const char *parameters); + const char *(*GlobalAlias_FindRandom)(const char *alias, AliasListNode_t **ret); + void (*GlobalAlias_Dump)(); + void (*GlobalAlias_Clear)(); + + void (*centerprintf)(gentity_t *ent, const char *format, ...); + void (*locationprintf)(gentity_t *ent, int x, int y, const char *format, ...); + void (*Sound)( + vec3_t *org, + int entNum, + int channel, + const char *soundName, + float volume, + float minDist, + float pitch, + float maxDist, + int streamed + ); + void (*StopSound)(int entNum, int channel); + float (*SoundLength)(int channel, const char *name); + unsigned char *(*SoundAmplitudes)(int channel, const char *name); + int (*S_IsSoundPlaying)(int channel, const char *name); + short unsigned int (*CalcCRC)(unsigned char *start, int count); + + debugline_t **DebugLines; + int *numDebugLines; + debugstring_t **DebugStrings; + int *numDebugStrings; + + void (*LocateGameData)( + gentity_t *gEnts, int numGEntities, int sizeofGEntity, playerState_t *clients, int sizeofGameClient + ); + void (*SetFarPlane)(int farPlane); + void (*SetSkyPortal)(qboolean skyPortal); + void (*Popmenu)(int client, int i); + void (*Showmenu)(int client, const char *name, qboolean force); + void (*Hidemenu)(int client, const char *name, qboolean force); + void (*Pushmenu)(int client, const char *name); + void (*HideMouseCursor)(int client); + void (*ShowMouseCursor)(int client); + const char *(*MapTime)(); + void (*LoadResource)(const char *name); + void (*ClearResource)(); + int (*Key_StringToKeynum)(const char *str); + const char *(*Key_KeynumToBindString)(int keyNum); + void (*Key_GetKeysForCommand)(const char *command, int *key1, int *key2); + void (*ArchiveLevel)(qboolean loading); + void (*AddSvsTimeFixup)(int *piTime); + void (*HudDrawShader)(int info, const char *name); + void (*HudDrawAlign)(int info, int horizontalAlign, int verticalAlign); + void (*HudDrawRect)(int info, int x, int y, int width, int height); + void (*HudDrawVirtualSize)(int info, qboolean virtualScreen); + void (*HudDrawColor)(int info, float *color); + void (*HudDrawAlpha)(int info, float alpha); + void (*HudDrawString)(int info, const char *string); + void (*HudDrawFont)(int info, const char *fontName); + qboolean (*SanitizeName)(const char *oldName, char *newName, size_t bufferSize); + + // + // Added in OPM + // + + int (*pvssoundindex)(const char* name, int streamed); + + cvar_t *fsDebug; + + // + // New functions will start from here + // } game_import_t; typedef struct gameExport_s { - int apiversion; + int apiversion; - // the init function will only be called when a game starts, - // not each time a level is loaded. Persistant data for clients - // and the server can be allocated in init - void ( *Init )( int startTime, int randomSeed ); - void ( *Shutdown ) ( void ); - void ( *Cleanup ) ( qboolean samemap ); - void ( *Precache )( void ); + // the init function will only be called when a game starts, + // not each time a level is loaded. Persistant data for clients + // and the server can be allocated in init + void (*Init)(int startTime, int randomSeed); + void (*Shutdown)(void); + void (*Cleanup)(qboolean samemap); + void (*Precache)(void); - void ( *SetMap )( const char *mapName ); - void ( *Restart )( ); - void ( *SetTime )( int svsStartTime, int svsTime ); + void (*SetMap)(const char *mapName); + void (*Restart)(); + void (*SetTime)(int svsStartTime, int svsTime); - // each new level entered will cause a call to SpawnEntities - void ( *SpawnEntities ) ( char *entstring, int levelTime ); + // each new level entered will cause a call to SpawnEntities + void (*SpawnEntities)(char *entstring, int levelTime); - // return NULL if the client is allowed to connect, otherwise return - // a text string with the reason for denial - const char * ( *ClientConnect )( int clientNum, qboolean firstTime ); + // return NULL if the client is allowed to connect, otherwise return + // a text string with the reason for denial + const char *(*ClientConnect)(int clientNum, qboolean firstTime, qboolean differentMap); - void ( *ClientBegin )( gentity_t *ent, usercmd_t *cmd ); - void ( *ClientUserinfoChanged )( gentity_t *ent, const char *userinfo ); - void ( *ClientDisconnect )( gentity_t *ent ); - void ( *ClientCommand )( gentity_t *ent ); - void ( *ClientThink )( gentity_t *ent, usercmd_t *cmd, usereyes_t *eyeinfo ); + void (*ClientBegin)(gentity_t *ent, usercmd_t *cmd); + void (*ClientUserinfoChanged)(gentity_t *ent, const char *userinfo); + void (*ClientDisconnect)(gentity_t *ent); + void (*ClientCommand)(gentity_t *ent); + void (*ClientThink)(gentity_t *ent, usercmd_t *cmd, usereyes_t *eyeinfo); - void ( *BotBegin )( gentity_t *ent); - void ( *BotThink )( gentity_t *ent, int msec ); + void (*BotBegin)(gentity_t *ent); + void (*BotThink)(gentity_t *ent, int msec); - void ( *PrepFrame )( void ); - void ( *RunFrame )( int levelTime, int frameTime ); + void (*PrepFrame)(void); + void (*RunFrame)(int levelTime, int frameTime); - void ( *ServerSpawned )( void ); + void (*ServerSpawned)(void); - void ( *RegisterSounds )( ); - qboolean ( *AllowPaused )( ); + void (*RegisterSounds)(); + qboolean (*AllowPaused)(); - // ConsoleCommand will be called when a command has been issued - // that is not recognized as a builtin function. - // The game can issue gi.argc() / gi.argv() commands to get the command - // and parameters. Return qfalse if the game doesn't recognize it as a command. - qboolean ( *ConsoleCommand )( void ); + // ConsoleCommand will be called when a command has been issued + // that is not recognized as a builtin function. + // The game can issue gi.argc() / gi.argv() commands to get the command + // and parameters. Return qfalse if the game doesn't recognize it as a command. + qboolean (*ConsoleCommand)(void); - void ( *ArchivePersistant )( const char *name, qboolean loading ); + void (*ArchivePersistant)(const char *name, qboolean loading); - // ReadLevel is called after the default map information has been - // loaded with SpawnEntities, so any stored client spawn spots will - // be used when the clients reconnect. - void ( *WriteLevel )( const char *filename, qboolean autosave ); - qboolean ( *ReadLevel )( const char *filename ); - qboolean ( *LevelArchiveValid )( const char *filename ); + // ReadLevel is called after the default map information has been + // loaded with SpawnEntities, so any stored client spawn spots will + // be used when the clients reconnect. + void (*WriteLevel)(const char *filename, qboolean autosave, byte** savedCgameState, size_t* savedCgameStateSize); + qboolean (*ReadLevel)(const char *filename, byte** savedCgameState, size_t* savedCgameStateSize); + qboolean (*LevelArchiveValid)(const char *filename); - void ( *ArchiveInteger )( int *i ); - void ( *ArchiveFloat )( float *fl ); - void ( *ArchiveString )( char *s ); - void ( *ArchiveSvsTime )( int *pi ); - orientation_t ( *TIKI_Orientation )( gentity_t *edict, int num ); - void ( *DebugCircle )( float *org, float radius, float r, float g, float b, float alpha, qboolean horizontal ); - void ( *SetFrameNumber )( int frameNumber ); - void ( *SoundCallback )( int entNum, soundChannel_t channelNumber, const char *name ); + void (*ArchiveInteger)(int *i); + void (*ArchiveFloat)(float *fl); + void (*ArchiveString)(char *s); + void (*ArchiveSvsTime)(int *pi); + orientation_t (*TIKI_Orientation)(gentity_t *edict, int num); + void (*DebugCircle)(float *org, float radius, float r, float g, float b, float alpha, qboolean horizontal); + void (*SetFrameNumber)(int frameNumber); + void (*SoundCallback)(int entNum, soundChannel_t channelNumber, const char *name); - // - // global variables shared between game and server - // + // + // global variables shared between game and server + // - // The gentities array is allocated in the game dll so it - // can vary in size from one game to another. - // - // The size will be fixed when ge->Init() is called - // the server can't just use pointer arithmetic on gentities, because the - // server's sizeof(struct gentity_s) doesn't equal gentitySize - profGame_t *profStruct; - struct gentity_s *gentities; - int gentitySize; - int num_entities; // current number, <= max_entities - int max_entities; + // The gentities array is allocated in the game dll so it + // can vary in size from one game to another. + // + // The size will be fixed when ge->Init() is called + // the server can't just use pointer arithmetic on gentities, because the + // server's sizeof(struct gentity_s) doesn't equal gentitySize + profGame_t *profStruct; + struct gentity_s *gentities; + int gentitySize; + int num_entities; // current number, <= max_entities + int max_entities; - const char *errorMessage; + const char *errorMessage; } game_export_t; #ifdef __cplusplus @@ -496,13 +584,13 @@ extern "C" #endif #ifdef GAME_DLL -#ifdef WIN32 -__declspec(dllexport) -#else +# ifdef WIN32 + __declspec(dllexport) +# else __attribute__((visibility("default"))) +# endif #endif -#endif -game_export_t* GetGameAPI( game_import_t *import ); + game_export_t *GetGameAPI(game_import_t *import); #if 0 // diff --git a/code/fgame/g_session.cpp b/code/fgame/g_session.cpp index 7056c800..f133c2e5 100644 --- a/code/fgame/g_session.cpp +++ b/code/fgame/g_session.cpp @@ -58,9 +58,10 @@ G_ReadSessionData Called on a reconnect ================ */ -void G_ReadSessionData( gclient_t *client ) +void G_ReadClientSessionData( gclient_t *client ) { cvar_t *session; + int teamnum; if( g_bNewSession ) { return; @@ -68,11 +69,12 @@ void G_ReadSessionData( gclient_t *client ) session = gi.Cvar_Get(va("session%zi", client - game.clients), "", 0); - sscanf( session->string, "%s %i %i", client->pers.dm_primary, &client->pers.teamnum, &client->pers.round_kills); + sscanf( session->string, "%s %i %i", client->pers.dm_primary, &teamnum, &client->pers.round_kills); if( client->pers.dm_primary[ 0 ] == '-' ) { client->pers.dm_primary[ 0 ] = 0; } + client->pers.teamnum = (teamtype_t)teamnum; } @@ -83,8 +85,15 @@ G_InitSessionData Called on a first-time connect ================ */ -void G_InitSessionData( gclient_t *client, const char *userinfo ) +void G_InitClientPersistant( gclient_t *client, const char *userinfo ) { + // Clear the persistent data + client->pers = {}; + + // Added in OPM + // Reset the persistent session data. + // This fixes some bugs like the player getting score + // from previous maps G_WriteClientSessionData( client ); } @@ -96,16 +105,13 @@ G_InitWorldSession ================== */ void G_InitWorldSession( void ) { - char s[MAX_STRING_CHARS]; - int gt; + int gt; - cvar_t *v = gi.Cvar_Get( "session", "", 0 ); - - gt = atoi( s ); + cvar_t *v = gi.Cvar_Get( "session", "-1", 0 ); // if the gametype changed since the last session, don't use any // client sessions - if ( g_gametype->integer != gt ) { + if ( g_gametype->integer != v->integer ) { G_Printf( "Gametype changed, clearing session data.\n" ); } } diff --git a/code/fgame/g_spawn.cpp b/code/fgame/g_spawn.cpp index 58a438d4..6875eb29 100644 --- a/code/fgame/g_spawn.cpp +++ b/code/fgame/g_spawn.cpp @@ -22,56 +22,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // g_spawn.cpp : spawner for scripts. -#include "glb_local.h" +#include "g_local.h" #include "g_spawn.h" #include "../script/scriptvariable.h" #include "object.h" #include "../qcommon/tiki.h" -#ifdef GAME_DLL #include "../fgame/entity.h" #include "../fgame/actor.h" -#endif - -#if defined ( GAME_DLL ) -#define scriptcheck g_scriptcheck -#elif defined( CGAME_DLL ) -#define scriptcheck cg_scriptcheck -#else -#define scriptcheck g_scriptcheck -#endif extern Event EV_Entity_Start; -CLASS_DECLARATION( Class, SpawnArgs, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(Class, SpawnArgs, NULL) { + {NULL, NULL} }; -Container< SafePtr< Listener > > g_spawnlist; +Container> g_spawnlist; -SpawnArgs::SpawnArgs() +SpawnArgs::SpawnArgs() {} + +SpawnArgs::SpawnArgs(SpawnArgs& otherlist) { + int num; + int i; + + num = otherlist.NumArgs(); + keyList.Resize(num); + valueList.Resize(num); + for (i = 1; i <= num; i++) { + keyList.AddObject(otherlist.keyList.ObjectAt(i)); + valueList.AddObject(otherlist.valueList.ObjectAt(i)); + } } -SpawnArgs::SpawnArgs( SpawnArgs &otherlist ) +void SpawnArgs::Clear(void) { - int num; - int i; - - num = otherlist.NumArgs(); - keyList.Resize( num ); - valueList.Resize( num ); - for( i = 1; i <= num; i++ ) - { - keyList.AddObject( otherlist.keyList.ObjectAt( i ) ); - valueList.AddObject( otherlist.valueList.ObjectAt( i ) ); - } -} - -void SpawnArgs::Clear( void ) -{ - keyList.FreeObjectList(); - valueList.FreeObjectList(); + keyList.FreeObjectList(); + valueList.FreeObjectList(); } /* @@ -82,142 +68,129 @@ Parses spawnflags out of the given string, returning the new position. Clears out any previous args. ==================== */ -char *SpawnArgs::Parse( char *data, bool bAllowUtils ) +char *SpawnArgs::Parse(char *data, bool bAllowUtils) { - str keyname; - const char *com_token; - - Clear(); - - // parse the opening brace - com_token = COM_Parse( &data ); - if ( !data ) - { - return NULL; - } - - if ( com_token[ 0 ] != '{' ) - { - glbs.Error( ERR_DROP, "SpawnArgs::Parse : found %s when expecting {", com_token ); - } - - // go through all the dictionary pairs - while( 1 ) - { - // parse key - com_token = COM_Parse( &data ); - if ( com_token[ 0 ] == '}' ) - { - break; - } - - if ( !data ) - { - glbs.Error( ERR_DROP, "SpawnArgs::Parse : EOF without closing brace" ); - } - - keyname = com_token; - - // parse value - com_token = COM_Parse( &data ); - if ( !data ) - { - glbs.Error( ERR_DROP, "SpawnArgs::Parse : EOF without closing brace" ); - } - - if ( com_token[ 0 ] == '}' ) - { - glbs.Error( ERR_DROP, "SpawnArgs::Parse : closing brace without data" ); - } - - // keynames with a leading underscore are used for utility comments, - // and are immediately discarded by the game - if ( !bAllowUtils && keyname[ 0 ] == '_' ) - { - continue; - } - - setArg( keyname.c_str(), com_token ); - } - - return data; + str keyname; + const char *com_token; + + Clear(); + + // parse the opening brace + com_token = COM_Parse(&data); + if (!data) { + return NULL; + } + + if (com_token[0] != '{') { + gi.Error(ERR_DROP, "SpawnArgs::Parse : found %s when expecting {", com_token); + } + + // go through all the dictionary pairs + while (1) { + // parse key + com_token = COM_Parse(&data); + if (com_token[0] == '}') { + break; + } + + if (!data) { + gi.Error(ERR_DROP, "SpawnArgs::Parse : EOF without closing brace"); + } + + keyname = com_token; + + // parse value + com_token = COM_Parse(&data); + if (!data) { + gi.Error(ERR_DROP, "SpawnArgs::Parse : EOF without closing brace"); + } + + if (com_token[0] == '}') { + gi.Error(ERR_DROP, "SpawnArgs::Parse : closing brace without data"); + } + + // keynames with a leading underscore are used for utility comments, + // and are immediately discarded by the game + if (!bAllowUtils && keyname[0] == '_') { + continue; + } + + setArg(keyname.c_str(), com_token); + } + + return data; } -const char *SpawnArgs::getArg( const char *key, const char *defaultValue ) +const char *SpawnArgs::getArg(const char *key, const char *defaultValue) { - int i; - int num; - - num = keyList.NumObjects(); - for( i = 1; i <= num; i++ ) - { - if ( keyList.ObjectAt( i ) == key ) - { - return valueList.ObjectAt( i ); - } - } - - return defaultValue; + int i; + int num; + + num = keyList.NumObjects(); + for (i = 1; i <= num; i++) { + if (keyList.ObjectAt(i) == key) { + return valueList.ObjectAt(i); + } + } + + return defaultValue; } -void SpawnArgs::setArg( const char *key, const char *value ) +void SpawnArgs::setArg(const char *key, const char *value) { - int i; - int num; - - num = keyList.NumObjects(); - for( i = 1; i <= num; i++ ) - { - if ( keyList.ObjectAt( i ) == key ) - { - valueList.ObjectAt( i ) = value; - return; - } - } - - keyList.AddObject( str( key ) ); - valueList.AddObject( str( value ) ); + int i; + int num; + + num = keyList.NumObjects(); + for (i = 1; i <= num; i++) { + if (keyList.ObjectAt(i) == key) { + valueList.ObjectAt(i) = value; + return; + } + } + + keyList.AddObject(str(key)); + valueList.AddObject(str(value)); } -void SpawnArgs::operator=( SpawnArgs &otherlist ) +void SpawnArgs::operator=(SpawnArgs& otherlist) { - int num; - int i; - - Clear(); - - num = otherlist.NumArgs(); - keyList.Resize( num ); - valueList.Resize( num ); - - for( i = 1; i <= num; i++ ) - { - keyList.AddObject( otherlist.keyList.ObjectAt( i ) ); - valueList.AddObject( otherlist.valueList.ObjectAt( i ) ); - } + int num; + int i; + + Clear(); + + num = otherlist.NumArgs(); + keyList.Resize(num); + valueList.Resize(num); + + for (i = 1; i <= num; i++) { + keyList.AddObject(otherlist.keyList.ObjectAt(i)); + valueList.AddObject(otherlist.valueList.ObjectAt(i)); + } } -int SpawnArgs::NumArgs( void ) +int SpawnArgs::NumArgs(void) { - return keyList.NumObjects(); + return keyList.NumObjects(); } -const char *SpawnArgs::getKey( int index ) +const char *SpawnArgs::getKey(int index) { - return keyList.ObjectAt( index + 1 ); + return keyList.ObjectAt(index + 1); } -const char *SpawnArgs::getValue( int index ) +const char *SpawnArgs::getValue(int index) { - return valueList.ObjectAt( index + 1 ); + return valueList.ObjectAt(index + 1); } -void SpawnArgs::Archive( Archiver &arc ) +void SpawnArgs::Archive(Archiver& arc) { - Class::Archive( arc ); - - //keyList.Archive( arc ); - //valueList.Archive( arc ); + Class::Archive(arc); + + //keyList.Archive( arc ); + //valueList.Archive( arc ); } /* @@ -228,145 +201,108 @@ Finds the spawn function for the entity and returns ClassDef * =============== */ -ClassDef *SpawnArgs::getClassDef( qboolean *tikiWasStatic ) +ClassDef *SpawnArgs::getClassDef(qboolean *tikiWasStatic) { -#if defined ( GAME_DLL ) - const char *classname; - ClassDef *cls = NULL; - dtiki_t *tiki = NULL; - dtikianim_t *a = NULL; - - classname = getArg( "classname" ); - - if ( tikiWasStatic ) - { - *tikiWasStatic = false; - } - - // - // check normal spawn functions - // see if the class name is stored within the model - // - if ( classname ) - { - // - // explicitly inhibit lights - // - if ( !Q_stricmp( classname, "light" ) ) - { - // - // HACK HACK HACK - // hack to suppress a warning message - // - if ( tikiWasStatic ) - { - *tikiWasStatic = true; + const char *classname; + ClassDef *cls = NULL; + dtiki_t *tiki = NULL; + dtikianim_t *a = NULL; + + classname = getArg("classname"); + + if (tikiWasStatic) { + *tikiWasStatic = false; + } + + // + // check normal spawn functions + // see if the class name is stored within the model + // + if (classname) { + // + // explicitly inhibit lights + // + if (!Q_stricmp(classname, "light")) { + // + // HACK HACK HACK + // hack to suppress a warning message + // + if (tikiWasStatic) { + *tikiWasStatic = true; } - return NULL; - } - - cls = getClassForID( classname ); - if ( !cls ) - { - cls = getClass( classname ); - } - } - - if ( !cls ) - { - const char *model; - - // - // get Object in case we cannot find an alternative - // - cls = &Object::ClassInfo; - model = getArg( "model" ); - if ( model ) - { - int i; + return NULL; + } - model = CanonicalTikiName( model ); - tiki = gi.modeltiki( model ); + cls = getClassForID(classname); + if (!cls) { + cls = getClass(classname); + } + } - // - // get handle to def file - // - if ( tiki ) - { - const char * s; - - s = getArg( "make_static" ); + if (!cls) { + const char *model; - if ( s && atoi( s ) ) - { - // - // if make_static then we don't want to spawn - // - if ( tikiWasStatic ) - { - *tikiWasStatic = true; - } - - return NULL; - } + // + // get Object in case we cannot find an alternative + // + cls = &Object::ClassInfo; + model = getArg("model"); + if (model) { + int i; - a = tiki->a; - - if( a->num_server_initcmds ) - { - for( i = 0; i < a->num_server_initcmds; i++ ) - { - if( !Q_stricmp( a->server_initcmds[ i ].args[ 0 ], "classname" ) ) - { - cls = getClass( a->server_initcmds[ i ].args[ 1 ] ); - break; - } - } + model = CanonicalTikiName(model); + tiki = gi.modeltiki(model); - if( i == a->num_server_initcmds ) - { - glbs.DPrintf( "Classname %s used, but 'classname' was not found in Initialization commands, using Object.\n", classname ); - } - } - else - glbs.DPrintf( "Classname %s used, but TIKI had no Initialization commands, using Object.\n", classname ); + // + // get handle to def file + // + if (tiki) { + const char *s; + + s = getArg("make_static"); + + if (s && atoi(s)) { + // + // if make_static then we don't want to spawn + // + if (tikiWasStatic) { + *tikiWasStatic = true; + } + + return NULL; + } + + a = tiki->a; + + if (a->num_server_initcmds) { + for (i = 0; i < a->num_server_initcmds; i++) { + if (!Q_stricmp(a->server_initcmds[i].args[0], "classname")) { + cls = getClass(a->server_initcmds[i].args[1]); + break; + } + } + + if (i == a->num_server_initcmds) { + gi.DPrintf( + "Classname %s used, but 'classname' was not found in Initialization commands, using " + "Object.\n", + classname + ); + } + } else { + gi.DPrintf( + "Classname %s used, but TIKI had no Initialization commands, using Object.\n", classname + ); + } + } else { + gi.DPrintf("Classname %s used, but model was not a TIKI, using Object.\n", classname); } - else - glbs.DPrintf( "Classname %s used, but model was not a TIKI, using Object.\n", classname ); - } - else - { - glbs.DPrintf( "Classname %s' used, but no model was set, using Object.\n", classname ); - } - } - - return cls; -#else - const char *classname; - ClassDef *cls = NULL; - - classname = getArg( "classname" ); - - if ( tikiWasStatic ) - { - *tikiWasStatic = false; - } - - // - // check normal spawn functions - // see if the class name is stored within the model - // - if ( classname ) - { - cls = getClassForID( classname ); - if ( !cls ) - { - cls = getClass( classname ); - } - } + } else { + gi.DPrintf("Classname %s' used, but no model was set, using Object.\n", classname); + } + } - return cls; -#endif + return cls; } /* @@ -378,314 +314,282 @@ Returns pointer to Entity =============== */ -Listener *SpawnArgs::Spawn( void ) +Listener *SpawnArgs::Spawn(void) { - Listener *ent = ( Listener * )SpawnInternal(); - - if( ent ) - { - ent->ProcessPendingEvents(); - ent->ProcessEvent(EV_Entity_Start); - } - - return ent; -} - -Listener *SpawnArgs::SpawnInternal( void ) -{ - str classname; - ClassDef *cls; - Listener *obj; - Event *ev; - int i; - qboolean tikiWasStatic; // used to determine if entity was intentionally suppressed - const char *key, *value; - str keyname; -#ifdef WITH_SCRIPT_ENGINE - unsigned int eventnum; - EventDef *def; - ScriptVariable *var; - ScriptVariableList *varList; -#endif - -#if defined ( GAME_DLL ) - - if( !g_spawnentities->integer ) - { - value = getArg( "classname", NULL ); - - // only spawn a playerstart or the world - if( value ) - { - if( ( Q_stricmp( value, "info_player_start" ) && Q_stricmp( value, "worldspawn" ) ) ) - { - Com_Printf( "%s\n", value ); - return NULL; - } - } - } - - if( !g_spawnai->integer ) - { - value = getArg( "classname", NULL ); - - //dont spawn ai_* if g_spawnai is 0 - if( value ) - { - if( !Q_stricmpn( value, "ai_", 3 ) ) - { - Com_Printf( "%s\n", value ); - return NULL; - } - } - } - -#endif - - classname = getArg( "classname", "Unspecified" ); - cls = getClassDef( &tikiWasStatic ); - - if ( !cls ) - { - if ( !tikiWasStatic ) - { - glbs.DPrintf( "%s doesn't have a spawn function\n", classname.c_str() ); - - if( scriptcheck->integer ) { - glbs.Error( ERR_DROP, "Script check failed" ); - } - } - + SafePtr ent = (Listener *)SpawnInternal(); + if (!ent) { return NULL; } - - obj = ( Listener * )cls->newInstance(); - for( int i = g_spawnlist.NumObjects(); i > 0; i-- ) - { - if( g_spawnlist.ObjectAt( i ) == NULL ) - { - g_spawnlist.RemoveObjectAt( i ); - } + ent->ProcessPendingEvents(); + if (!ent) { + // Fixed in OPM + // Make sure to check the entity after processing events, + // the ent could be deleted due to a posted remove event + return NULL; } - g_spawnlist.AddObject( obj ); + ent->ProcessEvent(EV_Entity_Start); - // post spawnarg events - for( i = 0; i < NumArgs(); i++ ) - { - key = getKey( i ); - value = getValue( i ); - - if( *key == '#' ) - { - // don't count the prefix - keyname = ( key + 1 ); + return ent; +} +Listener *SpawnArgs::SpawnInternal(void) +{ + str classname; + ClassDef *cls; + Listener *obj; + Event *ev; + int i; + qboolean tikiWasStatic; // used to determine if entity was intentionally suppressed + const char *key, *value; + str keyname; + int t1, t2; #ifdef WITH_SCRIPT_ENGINE - // initialize the object vars - varList = obj->Vars(); - - var = varList->GetVariable( keyname ); - if( var ) - { - Com_Printf( - "^~^~^ variable '%s' already set with string value '%s' - failed to attempt to set with numeric value '%s'\n", - keyname.c_str(), - var->stringValue().c_str(), - value ); - - continue; - } - - eventnum = Event::FindSetterEventNum( keyname ); - - if( !eventnum || !( def = cls->GetDef( eventnum ) ) ) - { - if( strchr( keyname.c_str(), '.' ) ) - { - // it's a float - varList->SetVariable( keyname, ( float )atof( value ) ); - } - else - { - varList->SetVariable( keyname, atoi( value ) ); - } - } - else if( def->type != EV_SETTER ) - { - Com_Printf( "^~^~^ Cannot set a read-only variable '%s'\n", keyname.c_str() ); - } - else - { - ev = new Event( keyname, EV_SETTER ); - - if( strchr( keyname.c_str(), '.' ) ) - { - ev->AddFloat( atof( value ) ); - } - else - { - ev->AddInteger( atoi( value ) ); - } - - obj->PostEvent( ev, EV_SPAWNARG ); - } + unsigned int eventnum; + EventDef *def; + ScriptVariable *var; + ScriptVariableList *varList; #endif - } - else if( *key == '$' ) - { - keyname = ( key + 1 ); -#ifdef WITH_SCRIPT_ENGINE - varList = obj->Vars(); + if (!g_spawnentities->integer) { + value = getArg("classname", NULL); - var = varList->GetVariable( keyname ); - if( var ) - { - Com_Printf( - "^~^~^ variable '%s' already set with string value '%s' - failed to attempt to set with string value '%s'\n", - keyname.c_str(), - var->stringValue().c_str(), - value ); - - continue; - } - - eventnum = Event::FindSetterEventNum( keyname ); - - if( !eventnum || !( def = cls->GetDef( eventnum ) ) ) - { - varList->SetVariable( keyname, value ); - } - else if( def->type != EV_SETTER ) - { - Com_Printf( "^~^~^ Cannot set a read-only variable '%s'\n", keyname.c_str() ); - } - else - { - ev = new Event(eventnum); - ev->AddString( value ); - - obj->PostEvent( ev, EV_SPAWNARG ); - } -#endif - } - // if it is the "script" key, execute the script commands individually - else if( !Q_stricmp( key, "script" ) ) - { - char *ptr; - char * token; - - ptr = const_cast< char * >( getValue( i ) ); - while ( 1 ) - { - token = COM_ParseExt( &ptr, true ); - if ( !token[ 0 ] ) - break; - if ( strchr( token, ':' ) ) - { - glbs.DPrintf( "Label %s imbedded inside editor script for %s.\n", token, classname.c_str() ); - } - else - { - ev = new Event( token ); - while ( 1 ) - { - token = COM_ParseExt( &ptr, false ); - if ( !token[ 0 ] ) - break; - ev->AddToken( token ); - } - - obj->PostEvent( ev, EV_SPAWNARG ); - } + // only spawn a playerstart or the world + if (value) { + if ((Q_stricmp(value, "info_player_start") && Q_stricmp(value, "worldspawn"))) { + Com_Printf("%s\n", value); + return NULL; } - } - else - { - ev = new Event( key ); - ev->AddToken( value ); - - if( Q_stricmp( key, "model" ) == 0 ) - { -#if defined ( GAME_DLL ) - if( obj->isSubclassOf( SimpleActor ) ) - { - if( Q_stricmpn( value, "human", 5 ) && - Q_stricmpn( value, "models/human", 12 ) && - Q_stricmpn( value, "models//human", 13 ) && - Q_stricmpn( value, "animal", 6 ) && - Q_stricmpn( value, "models/animal", 13 ) ) - { - Com_Printf( "^~^~^ model '%s' cannot be an actor - please fix the .tik file\n", value ); + } + } - delete obj; - return NULL; - } + if (!g_spawnai->integer) { + value = getArg("classname", NULL); - obj->PostEvent( ev, EV_PRIORITY_SPAWNACTOR ); - } - else - { - obj->PostEvent( ev, EV_PRIORITY_SPAWNARG ); - } -#else - obj->PostEvent( ev, EV_PRIORITY_SPAWNARG ); + //dont spawn ai_* if g_spawnai is 0 + if (value) { + if (!Q_stricmpn(value, "ai_", 3)) { + Com_Printf("%s\n", value); + return NULL; + } + } + } + + t1 = gi.Milliseconds(); + + classname = getArg("classname", "Unspecified"); + cls = getClassDef(&tikiWasStatic); + + if (!cls) { + if (!tikiWasStatic) { + gi.DPrintf("%s doesn't have a spawn function\n", classname.c_str()); + + if (g_scriptcheck->integer) { + gi.Error(ERR_DROP, "Script check failed"); + } + } + + return NULL; + } + + if (checkInheritance(PathNode::classinfostatic(), cls)) { + // use the existing node that was loaded + obj = PathManager.GetSpawnNode(cls); + } else { + obj = (Listener *)cls->newInstance(); + } + + for (int i = g_spawnlist.NumObjects(); i > 0; i--) { + if (g_spawnlist.ObjectAt(i) == NULL) { + g_spawnlist.RemoveObjectAt(i); + } + } + + g_spawnlist.AddObject(obj); + + // post spawnarg events + for (i = 0; i < NumArgs(); i++) { + key = getKey(i); + value = getValue(i); + + if (*key == '#') { + // don't count the prefix + keyname = (key + 1); + +#ifdef WITH_SCRIPT_ENGINE + // initialize the object vars + varList = obj->Vars(); + + var = varList->GetVariable(keyname); + if (var) { + Com_Printf( + "^~^~^ variable '%s' already set with string value '%s' - failed to attempt to set with numeric " + "value '%s'\n", + keyname.c_str(), + var->stringValue().c_str(), + value + ); + + continue; + } + + eventnum = Event::FindSetterEventNum(keyname); + + if (!eventnum || !(def = cls->GetDef(eventnum))) { + if (strchr(keyname.c_str(), '.')) { + // it's a float + varList->SetVariable(keyname, (float)atof(value)); + } else { + varList->SetVariable(keyname, atoi(value)); + } + } else if (def->type != EV_SETTER) { + Com_Printf("^~^~^ Cannot set a read-only variable '%s'\n", keyname.c_str()); + } else { + ev = new Event(keyname, EV_SETTER); + + if (strchr(keyname.c_str(), '.')) { + ev->AddFloat(atof(value)); + } else { + ev->AddInteger(atoi(value)); + } + + obj->PostEvent(ev, EV_SPAWNARG); + } #endif - } - else - { -#if defined ( GAME_DLL ) - if( obj->isSubclassOf( SimpleActor ) ) - { - obj->PostEvent( ev, EV_SPAWNACTOR ); - } - else - { - obj->PostEvent( ev, EV_SPAWNARG ); - } -#else - obj->PostEvent( ev, EV_SPAWNARG ); + } else if (*key == '$') { + keyname = (key + 1); + +#ifdef WITH_SCRIPT_ENGINE + varList = obj->Vars(); + + var = varList->GetVariable(keyname); + if (var) { + Com_Printf( + "^~^~^ variable '%s' already set with string value '%s' - failed to attempt to set with string " + "value '%s'\n", + keyname.c_str(), + var->stringValue().c_str(), + value + ); + + continue; + } + + eventnum = Event::FindSetterEventNum(keyname); + + if (!eventnum || !(def = cls->GetDef(eventnum))) { + varList->SetVariable(keyname, value); + } else if (def->type != EV_SETTER) { + Com_Printf("^~^~^ Cannot set a read-only variable '%s'\n", keyname.c_str()); + } else { + ev = new Event(eventnum); + ev->AddString(value); + + obj->PostEvent(ev, EV_SPAWNARG); + } #endif - } - } - } - - if ( !obj ) - { - glbs.DPrintf( "%s failed on newInstance\n", classname.c_str() ); - return NULL; - } - - return obj; + } + // if it is the "script" key, execute the script commands individually + else if (!Q_stricmp(key, "script")) { + char *ptr; + char *token; + + ptr = const_cast(getValue(i)); + while (1) { + token = COM_ParseExt(&ptr, true); + if (!token[0]) { + break; + } + if (strchr(token, ':')) { + gi.DPrintf("Label %s imbedded inside editor script for %s.\n", token, classname.c_str()); + } else { + ev = new Event(token); + while (1) { + token = COM_ParseExt(&ptr, false); + if (!token[0]) { + break; + } + ev->AddToken(token); + } + + obj->PostEvent(ev, EV_SPAWNARG); + } + } + } else { + ev = new Event(key); + ev->AddToken(value); + + if (Q_stricmp(key, "model") == 0) { + if (obj->isSubclassOf(SimpleActor)) { + if (Q_stricmpn(value, "human", 5) && Q_stricmpn(value, "models/human", 12) + && Q_stricmpn(value, "models//human", 13) && Q_stricmpn(value, "animal", 6) + && Q_stricmpn(value, "models/animal", 13)) { + Com_Printf("^~^~^ model '%s' cannot be an actor - please fix the .tik file\n", value); + + delete obj; + return NULL; + } + + obj->PostEvent(ev, EV_PRIORITY_SPAWNACTOR); + } else { + obj->PostEvent(ev, EV_PRIORITY_SPAWNARG); + } + } else { + if (obj->isSubclassOf(SimpleActor)) { + obj->PostEvent(ev, EV_SPAWNACTOR); + } else { + obj->PostEvent(ev, EV_SPAWNARG); + } + } + } + } + + if (!obj) { + gi.DPrintf("%s failed on newInstance\n", classname.c_str()); + return NULL; + } + + t2 = gi.Milliseconds(); + if (t2 - t1 >= 100) { + // + // above 100 ms send a message to console + // + for (i = 0; i < NumArgs(); i++) { + key = getKey(i); + value = getValue(i); + + if (!Q_stricmp(key, "classname")) { + Com_Printf("spawn '%s': %5.2f seconds\n", value, (t2 - t1) / 1000.f); + break; + } + } + } + + return obj; } -ClassDef *FindClass( const char *name, qboolean *isModel ) +ClassDef *FindClass(const char *name, qboolean *isModel) { - ClassDef *cls; - - *isModel = false; - - // first lets see if it is a registered class name - cls = getClass( name ); - if ( !cls ) - { - SpawnArgs args; - - // if that didn't work lets try to resolve it as a model - args.setArg( "model", name ); - - cls = args.getClassDef(); - if ( cls ) - { - *isModel = true; - } - } - return cls; -} + ClassDef *cls; -#if defined ( GAME_DLL ) + *isModel = false; + + // first lets see if it is a registered class name + cls = getClass(name); + if (!cls) { + SpawnArgs args; + + // if that didn't work lets try to resolve it as a model + args.setArg("model", name); + + cls = args.getClassDef(); + if (cls) { + *isModel = true; + } + } + return cls; +} /* ============== @@ -695,16 +599,14 @@ This is only called when the game first initializes in single player, but is called after each death and level change in deathmatch ============== */ -void G_InitClientPersistant( gclient_t *client ) +void G_InitClientPersistant(gclient_t *client) { - memset( &client->pers, 0, sizeof( client->pers ) ); + memset(&client->pers, 0, sizeof(client->pers)); } -#endif - #if 0 -#include "../qcommon/tiki_local.h" // fixme! +# include "../qcommon/tiki_local.h" // fixme! qboolean G_SpawnString( const char *key, const char *defaultString, char **out ) { int i; @@ -868,11 +770,11 @@ void SP_team_CTF_blueplayer( gentity_t *ent ); void SP_team_CTF_redspawn( gentity_t *ent ); void SP_team_CTF_bluespawn( gentity_t *ent ); -#ifdef MISSIONPACK +# ifdef MISSIONPACK void SP_team_blueobelisk( gentity_t *ent ); void SP_team_redobelisk( gentity_t *ent ); void SP_team_neutralobelisk( gentity_t *ent ); -#endif +# endif void SP_item_botroam( gentity_t *ent ) { } spawn_t spawns[] = { @@ -940,11 +842,11 @@ spawn_t spawns[] = { {"info_player_axis", SP_team_CTF_redspawn}, {"info_player_allied", SP_team_CTF_bluespawn}, -#ifdef MISSIONPACK +# ifdef MISSIONPACK {"team_redobelisk", SP_team_redobelisk}, {"team_blueobelisk", SP_team_blueobelisk}, {"team_neutralobelisk", SP_team_neutralobelisk}, -#endif +# endif {"item_botroam", SP_item_botroam}, {NULL, 0} @@ -959,8 +861,8 @@ const char *G_FixTIKIPath(const char *in) { if(gi.FS_ReadFile( in, &buffer ) > 0) { return in; } - strcpy(path,"models/"); - strcat(path,in); + Q_strncpyz(path,"models/", sizeof(path)); + Q_strcat(path,sizeof(path),in); if( gi.FS_ReadFile( in, &buffer ) > 0 ) { return path; } @@ -1011,7 +913,7 @@ qboolean G_CallSpawn( gentity_t *ent ) { } *ptr2 = 0; } -#if 0 +# if 0 tiki = gi.TIKI_RegisterModel(ent->model); if(!tiki) { tiki = gi.TIKI_RegisterModel(va("models/%s",ent->model)); @@ -1027,7 +929,7 @@ qboolean G_CallSpawn( gentity_t *ent ) { gi.LinkEntity (ent); return qtrue; } -#else +# else ent->s.modelindex = G_ModelIndex( ( char * )G_FixTIKIPath( ent->model ) ); ent->s.eType = ET_MODELANIM; //if(ent->model[0]=='*') { @@ -1041,7 +943,7 @@ qboolean G_CallSpawn( gentity_t *ent ) { G_SetOrigin( ent, ent->s.origin ); gi.linkentity (ent); return qtrue; -#endif +# endif } G_Printf ("%s doesn't have a spawn function\n", ent->classname); @@ -1183,19 +1085,19 @@ void G_SpawnGEntityFromSpawnVars( void ) { } } -#ifdef MISSIONPACK +# ifdef MISSIONPACK G_SpawnInt( "notta", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } -#else +# else G_SpawnInt( "notq3a", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } -#endif +# endif if( G_SpawnString( "gametype", NULL, &value ) ) { if( g_gametype->integer >= GT_FFA && g_gametype->integer < GT_MAX_GAME_TYPE ) { @@ -1259,7 +1161,7 @@ qboolean G_ParseSpawnVars( void ) { level.numSpawnVars = 0; level.numSpawnVarChars = 0; -#if 0 +# if 0 // parse the opening brace if ( !gi.GetEntityToken( com_token, sizeof( com_token ) ) ) { // end of spawn string @@ -1295,7 +1197,7 @@ qboolean G_ParseSpawnVars( void ) { level.spawnVars[ level.numSpawnVars ][1] = G_AddSpawnVarToken( com_token ); level.numSpawnVars++; } -#endif +# endif return qtrue; } diff --git a/code/fgame/g_spawn.h b/code/fgame/g_spawn.h index f598b9fb..1016fb8c 100644 --- a/code/fgame/g_spawn.h +++ b/code/fgame/g_spawn.h @@ -29,51 +29,51 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // spawnflags // these are set with checkboxes on each entity in the map editor -#define SPAWNFLAG_NOT_EASY 0x00000100 -#define SPAWNFLAG_NOT_MEDIUM 0x00000200 -#define SPAWNFLAG_NOT_HARD 0x00000400 -#define SPAWNFLAG_NOT_DEATHMATCH 0x00000800 -#define SPAWNFLAG_DEVELOPMENT 0x00002000 -#define SPAWNFLAG_DETAIL 0x00004000 -#define SPAWNFLAG_NOCONSOLE 0x00008000 -#define SPAWNFLAG_NOPC 0x00010000 +#define SPAWNFLAG_NOT_EASY 0x00000100 +#define SPAWNFLAG_NOT_MEDIUM 0x00000200 +#define SPAWNFLAG_NOT_HARD 0x00000400 +#define SPAWNFLAG_NOT_DEATHMATCH 0x00000800 +#define SPAWNFLAG_DETAIL 0x00001000 +#define SPAWNFLAG_DEVELOPMENT 0x00002000 +#define SPAWNFLAG_NOCONSOLE 0x00008000 +#define SPAWNFLAG_NOPC 0x00010000 class Listener; class SpawnArgs : public Class { private: - Container keyList; - Container valueList; + Container keyList; + Container valueList; public: - CLASS_PROTOTYPE( SpawnArgs ); + CLASS_PROTOTYPE(SpawnArgs); - SpawnArgs(); - SpawnArgs( SpawnArgs &arglist ); + SpawnArgs(); + SpawnArgs(SpawnArgs& arglist); - void Clear( void ); + void Clear(void); - char *Parse( char *data, bool bAllowUtils = false ); - const char *getArg( const char *key, const char *defaultValue = NULL ); - void setArg( const char *key, const char *value ); + char *Parse(char *data, bool bAllowUtils = false); + const char *getArg(const char *key, const char *defaultValue = NULL); + void setArg(const char *key, const char *value); - int NumArgs( void ); - const char *getKey( int index ); - const char *getValue( int index ); - void operator=( SpawnArgs &a ); + int NumArgs(void); + const char *getKey(int index); + const char *getValue(int index); + void operator=(SpawnArgs &a); - ClassDef *getClassDef( qboolean *tikiWasStatic = NULL ); - Listener *Spawn( void ); - Listener *SpawnInternal( void ); + ClassDef *getClassDef(qboolean *tikiWasStatic = NULL); + Listener *Spawn(void); + Listener *SpawnInternal(void); - void Archive( Archiver &arc ) override; + void Archive(Archiver& arc) override; }; -extern Container< SafePtr< Listener > > g_spawnlist; +extern Container> g_spawnlist; -ClassDef *FindClass( const char *name, qboolean *isModel ); +ClassDef *FindClass(const char *name, qboolean *isModel); #ifdef GAME_DLL -void G_InitClientPersistant( gclient_t *client ); +void G_InitClientPersistant(gclient_t *client); #endif diff --git a/code/fgame/g_utils.cpp b/code/fgame/g_utils.cpp index 607d2324..c7ed568e 100644 --- a/code/fgame/g_utils.cpp +++ b/code/fgame/g_utils.cpp @@ -23,13 +23,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "g_local.h" #include "g_utils.h" #include "ctype.h" -#include "world.h" +#include "worldspawn.h" #include "scriptmaster.h" #include "scriptthread.h" #include "player.h" #include "playerbot.h" #include "playerstart.h" #include "debuglines.h" +#include "smokesprite.h" #include "../qcommon/tiki.h" const char *means_of_death_strings[MOD_TOTAL_NUMBER] = { @@ -45,8 +46,8 @@ const char *means_of_death_strings[MOD_TOTAL_NUMBER] = { "explosion", "explodewall", "electric", - "electric_water", - "thrown_object", + "electricwater", + "thrownobject", "grenade", "beam", "rocket", @@ -62,7 +63,8 @@ const char *means_of_death_strings[MOD_TOTAL_NUMBER] = { "bash", "shotgun", "aagun", - "landmine"}; + "landmine" +}; int MOD_string_to_int(const str& immune_string) { @@ -94,7 +96,6 @@ G_TouchTriggers ============ */ void G_TouchTriggers(Entity *ent) - { int i; int num; @@ -119,7 +120,7 @@ void G_TouchTriggers(Entity *ent) // Added in 2.0 // check if the ent is inside edict - if (hit->r.bmodel && gi.HitEntity(ent->edict, hit)) { + if (hit->r.bmodel && !gi.HitEntity(ent->edict, hit)) { continue; } @@ -140,7 +141,6 @@ to force all entities it covers to immediately touch it ============ */ void G_TouchSolids(Entity *ent) - { int i; int num; @@ -169,7 +169,6 @@ void G_TouchSolids(Entity *ent) } void G_ShowTrace(trace_t *trace, const gentity_t *passent, const char *reason) - { str text; str pass; @@ -235,7 +234,6 @@ void G_ShowSightTrace(gentity_t *passent1, gentity_t *passent2, const char *reas } void G_CalcBoundsOfMove(Vector& start, Vector& end, Vector& mins, Vector& maxs, Vector *minbounds, Vector *maxbounds) - { Vector bmin; Vector bmax; @@ -333,7 +331,7 @@ bool G_SightTrace( entnum2 = ent2->s.number; } - result = gi.SightTrace(start, mins, maxs, end, entnum, entnum2, contentmask, cylinder) ? true : false; + result = gi.SightTrace(start, mins, maxs, end, entnum, entnum2, contentmask, cylinder); if (sv_traceinfo->integer > 1) { G_ShowSightTrace(ent, ent2, reason); @@ -345,7 +343,7 @@ bool G_SightTrace( G_DebugLine(start, end, 1, 1, 0, 1); } - return result; + return result == true; } void G_PMDrawTrace( @@ -376,7 +374,6 @@ trace_t G_Trace( const char *reason, qboolean tracedeep ) - { int entnum; trace_t trace; @@ -418,7 +415,6 @@ trace_t G_Trace( const char *reason, qboolean tracedeep ) - { gentity_t *ent; int entnum; @@ -464,7 +460,6 @@ void G_TraceEntities( int contentmask, qboolean bIncludeTriggers ) - { trace_t trace; vec3_t boxmins; @@ -509,6 +504,23 @@ void G_TraceEntities( } } +float G_VisualObfuscation(const Vector& start, const Vector& end) +{ + float alpha; + + if (start == end) { + // no obfuscation + return 0; + } + + alpha = gi.CM_VisualObfuscation(start, end); + if (alpha >= 1.f) { + return alpha; + } + + return G_ObfuscationForSmokeSprites(alpha, start, end); +} + /* ======================================================================= @@ -525,7 +537,6 @@ Returns the distance to the nearest player from the given spot ================ */ float PlayersRangeFromSpot(Entity *spot) - { Entity *player; float bestplayerdistance; @@ -564,7 +575,6 @@ to other players ================ */ Entity *SelectRandomDeathmatchSpawnPoint(void) - { Entity *spot, *spot1, *spot2; int count = 0; @@ -623,7 +633,6 @@ SelectFarthestDeathmatchSpawnPoint ================ */ Entity *SelectFarthestDeathmatchSpawnPoint(void) - { Entity *bestspot; float bestdistance; @@ -653,7 +662,6 @@ Entity *SelectFarthestDeathmatchSpawnPoint(void) } Entity *SelectDeathmatchSpawnPoint(void) - { if (DM_FLAG(DF_SPAWN_FARTHEST)) { return SelectFarthestDeathmatchSpawnPoint(); @@ -674,7 +682,6 @@ is not a staircase. int c_yes, c_no; qboolean M_CheckBottom(Entity *ent) - { Vector mins, maxs, start, stop; trace_t trace; @@ -747,7 +754,6 @@ realcheck: } Entity *G_FindClass(Entity *ent, const char *classname) - { int entnum; gentity_t *from; @@ -771,7 +777,6 @@ Entity *G_FindClass(Entity *ent, const char *classname) } Entity *G_FindTarget(Entity *ent, const char *name) - { SimpleEntity *next; @@ -826,7 +831,6 @@ Entity *G_FindRandomTarget(const char *name) } Entity *G_NextEntity(Entity *ent) - { gentity_t *from; @@ -860,7 +864,6 @@ Entity *G_NextEntity(Entity *ent) // just constant angles. // Vector G_GetMovedir(float angle) - { if (angle == -1) { return Vector(0, 0, 1); @@ -899,6 +902,34 @@ void G_SetMovedir(vec3_t angles, vec3_t movedir) VectorClear(angles); } +/* +================= +G_GetAngle + +Return the yaw angle +================= +*/ +float G_GetAngle(Vector movedir) +{ + float angle; + + if (movedir == Vector(0, 0, 1)) { + return -1; + } + + if (movedir == Vector(0, 0, -1)) { + return -2; + } + + angle = RAD2DEG(atan(1.0) * 2 + atan(-movedir[0] / sqrt(-movedir[0] * movedir[0] + 1.0))); + + if (movedir[1] < 0) { + return (int)((360 - angle) * 10000) / 10000.0; + } + + return (int)(angle * 10000) / 10000.0; +} + /* ================= KillBox @@ -908,7 +939,6 @@ of ent. Ent should be unlinked before calling this! ================= */ qboolean KillBox(Entity *ent) - { int i; int num; @@ -960,9 +990,8 @@ qboolean KillBox(Entity *ent) } qboolean IsNumeric(const char *str) - { - int len; + size_t len; int i; qboolean dot; @@ -995,7 +1024,6 @@ findradius (org, radius) ================= */ Entity *findradius(Entity *startent, Vector org, float rad) - { Vector eorg; gentity_t *from; @@ -1050,7 +1078,6 @@ findclientinradius (org, radius) ================= */ Entity *findclientsinradius(Entity *startent, Vector org, float rad) - { Vector eorg; gentity_t *ed; @@ -1085,7 +1112,6 @@ Entity *findclientsinradius(Entity *startent, Vector org, float rad) } Vector G_CalculateImpulse(Vector start, Vector end, float speed, float gravity) - { float traveltime, vertical_speed; Vector dir, xydir, velocity; @@ -1103,7 +1129,6 @@ Vector G_CalculateImpulse(Vector start, Vector end, float speed, float gravity) } Vector G_PredictPosition(Vector start, Vector target, Vector targetvelocity, float speed) - { Vector projected; float traveltime; @@ -1118,13 +1143,128 @@ Vector G_PredictPosition(Vector start, Vector target, Vector targetvelocity, flo return projected; } +/* +============== +G_ArchiveTrace +============== +*/ +void G_ArchivePlayerState(Archiver& arc, playerState_t *ps) +{ + int i; + + // Movement + arc.ArchiveInteger(&ps->commandTime); + arc.ArchiveInteger(&ps->pm_type); + arc.ArchiveInteger(&ps->pm_flags); + arc.ArchiveInteger(&ps->pm_time); + arc.ArchiveVec3(ps->origin); + arc.ArchiveVec3(ps->velocity); + arc.ArchiveInteger(&ps->gravity); + arc.ArchiveInteger(&ps->speed); + arc.ArchiveInteger(&ps->delta_angles[0]); + arc.ArchiveInteger(&ps->delta_angles[1]); + arc.ArchiveInteger(&ps->delta_angles[2]); + + // Trace + arc.ArchiveInteger(&ps->groundEntityNum); + arc.ArchiveBoolean(&ps->walking); + arc.ArchiveBoolean(&ps->groundPlane); + arc.ArchiveInteger(&ps->feetfalling); + arc.ArchiveVec3(ps->falldir); + G_ArchiveTrace(arc, &ps->groundTrace); + arc.ArchiveVec3(ps->viewangles); + arc.ArchiveInteger(&ps->viewheight); + + // View + arc.ArchiveFloat(&ps->fLeanAngle); + arc.ArchiveInteger(&ps->iViewModelAnim); + arc.ArchiveInteger(&ps->iViewModelAnimChanged); + + // Stats + for (i = 0; i < ARRAY_LEN(ps->stats); i++) { + arc.ArchiveInteger(&ps->stats[i]); + } + for (i = 0; i < ARRAY_LEN(ps->activeItems); i++) { + arc.ArchiveInteger(&ps->activeItems[i]); + } + for (i = 0; i < ARRAY_LEN(ps->ammo_name_index); i++) { + arc.ArchiveInteger(&ps->ammo_name_index[i]); + } + for (i = 0; i < ARRAY_LEN(ps->ammo_amount); i++) { + arc.ArchiveInteger(&ps->ammo_amount[i]); + } + for (i = 0; i < ARRAY_LEN(ps->max_ammo_amount); i++) { + arc.ArchiveInteger(&ps->max_ammo_amount[i]); + } + + // Music + arc.ArchiveInteger(&ps->current_music_mood); + arc.ArchiveInteger(&ps->fallback_music_mood); + arc.ArchiveFloat(&ps->music_volume); + arc.ArchiveFloat(&ps->music_volume_fade_time); + arc.ArchiveInteger(&ps->reverb_type); + arc.ArchiveFloat(&ps->reverb_level); + + // View + arc.ArchiveVec4(ps->blend); + arc.ArchiveFloat(&ps->fov); + + // Camera + arc.ArchiveVec3(ps->camera_origin); + arc.ArchiveFloat(&ps->camera_time); + arc.ArchiveVec3(ps->camera_angles); + arc.ArchiveVec3(ps->camera_offset); + arc.ArchiveVec3(ps->camera_posofs); + arc.ArchiveInteger(&ps->camera_flags); + arc.ArchiveVec3(ps->damage_angles); + + if (arc.Loading()) { + VectorCopy(ps->origin, ps->vEyePos); + ps->vEyePos[2] += ps->viewheight; + } +} + +/* +============== +G_ArchiveTrace +============== +*/ +void G_ArchiveTrace(Archiver& arc, trace_t *trace) +{ + arc.ArchiveBoolean(&trace->allsolid); + arc.ArchiveBoolean(&trace->startsolid); + arc.ArchiveFloat(&trace->fraction); + arc.ArchiveVec3(trace->endpos); + arc.ArchiveVec3(trace->plane.normal); + arc.ArchiveFloat(&trace->plane.dist); + arc.ArchiveByte(&trace->plane.type); + arc.ArchiveByte(&trace->plane.signbits); + arc.ArchiveInteger(&trace->surfaceFlags); + arc.ArchiveInteger(&trace->shaderNum); + arc.ArchiveInteger(&trace->contents); + arc.ArchiveInteger(&trace->entityNum); + arc.ArchiveInteger(&trace->location); +} + +/* +============== +G_ArchiveClient +============== +*/ +void G_ArchiveClient(Archiver& arc, gclient_t *client) +{ + G_ArchivePlayerState(arc, &client->ps); + arc.ArchiveVec3(client->cmd_angles); + arc.ArchiveInteger(&client->lastActiveTime); + arc.ArchiveInteger(&client->activeWarning); +} + /* ============== G_ArchiveEdict ============== */ void G_ArchiveEdict(Archiver& arc, gentity_t *edict) - { int i; str tempStr; @@ -1136,7 +1276,10 @@ void G_ArchiveEdict(Archiver& arc, gentity_t *edict) // if (edict->client) { - arc.ArchiveRaw(edict->client, sizeof(*edict->client)); + // Removed in OPM + // Commented out because clients are already archived + // by Game::Archive() + //G_ArchiveClient(arc, edict->client); } arc.ArchiveInteger(&edict->s.beam_entnum); @@ -1178,7 +1321,9 @@ void G_ArchiveEdict(Archiver& arc, gentity_t *edict) arc.ArchiveString(&tempStr); if (tempStr.length()) { - edict->s.loopSound = gi.soundindex(tempStr.c_str(), true); + qboolean streamed = tempStr[tempStr.length() - 1] != '0'; + tempStr[tempStr.length() - 1] = 0; + edict->s.loopSound = gi.soundindex(tempStr.c_str(), streamed); } else { edict->s.loopSound = 0; } @@ -1228,7 +1373,7 @@ void G_ArchiveEdict(Archiver& arc, gentity_t *edict) edict->radius2 = edict->r.radius * edict->r.radius; } - arc.ArchiveVec3(edict->r.currentOrigin); + arc.ArchiveVec3(edict->r.centroid); arc.ArchiveVec3(edict->r.currentAngles); arc.ArchiveInteger(&edict->r.ownerNum); @@ -1312,7 +1457,6 @@ Sets the pos trajectory for a fixed position =============== */ void G_SetTrajectory(gentity_t *ent, vec3_t org) - { ent->s.pos.trTime = 0; VectorClear(ent->s.pos.trDelta); @@ -1328,7 +1472,6 @@ Sets the encoded constant light parameter for entities =============== */ void G_SetConstantLight(int *constantlight, float *red, float *green, float *blue, float *radius, int *lightStyle) - { int ir, ig, ib, iradius; @@ -1383,9 +1526,9 @@ char *CanonicalTikiName(const char *szInName) static char filename[1024]; if (*szInName && Q_stricmpn("models/", szInName, 7)) { - sprintf(filename, "models/%s", szInName); + Com_sprintf(filename, sizeof(filename), "models/%s", szInName); } else { - strcpy(filename, szInName); + Q_strncpyz(filename, szInName, sizeof(filename)); } gi.FS_CanonicalFilename(filename); @@ -1424,46 +1567,45 @@ void G_ProcessCacheInitCommands(dtiki_t *tiki) } void CacheResource(const char *stuff) - { AliasListNode_t *ret; qboolean streamed = qfalse; char filename[MAX_STRING_TOKENS]; + assert(stuff); if (!stuff) { return; } + if (gi.fsDebug->integer == 2) { + Com_Printf("server cache: %s\n", stuff); + } + if (!strchr(stuff, '.')) { // must be a global alias stuff = gi.GlobalAlias_FindRandom(stuff, &ret); if (!stuff) { - if (gi.fsDebug->integer) { + if (gi.fsDebug->integer == 2) { Com_Printf("alias not found\n"); } return; } streamed = ret->streamed; + if (gi.fsDebug->integer == 2) { + Com_Printf("=> %s\n", stuff); + } } - strcpy(filename, stuff); + Q_strncpyz(filename, stuff, sizeof(filename)); gi.FS_CanonicalFilename(filename); - if (strstr(filename, ".wav")) { - gi.soundindex(filename, streamed); - } else if (strstr(filename, ".mp3")) { + if (strstr(filename, ".wav") || strstr(filename, ".mp3")) { gi.soundindex(filename, streamed); } else if (strstr(filename, ".tik")) { dtiki_t *tiki; - if (*stuff && strncmp("models/", stuff, 7)) { - sprintf(filename, "models/%s", stuff); - } else { - strcpy(filename, stuff); - } - - gi.FS_CanonicalFilename(filename); + Q_strncpyz(filename, CanonicalTikiName(stuff), sizeof(filename)); tiki = gi.TIKI_RegisterModel(filename); @@ -1530,22 +1672,25 @@ void RestoreMusicVolume(float fade_time) } void ChangeSoundtrack(const char *soundtrack) - { level.saved_soundtrack = level.current_soundtrack; level.current_soundtrack = soundtrack; - gi.setConfigstring(CS_SOUNDTRACK, soundtrack); + // Force the soundtrack to be sent again by setting it to empty first + // so it gets sent to clients again especially when loading + // from a saved game + gi.setConfigstring(CS_MUSIC, ""); + gi.setConfigstring(CS_MUSIC, soundtrack); + gi.DPrintf("soundtrack switched to %s.\n", soundtrack); } void RestoreSoundtrack(void) - { if (level.saved_soundtrack.length()) { level.current_soundtrack = level.saved_soundtrack; level.saved_soundtrack = ""; - gi.setConfigstring(CS_SOUNDTRACK, level.current_soundtrack.c_str()); + gi.setConfigstring(CS_MUSIC, level.current_soundtrack.c_str()); gi.DPrintf("soundtrack restored %s.\n", level.current_soundtrack.c_str()); } } @@ -1624,14 +1769,30 @@ int G_AIEventTypeFromString(const char *pszType) float G_AIEventRadius(int iType) { static float fRadius[] = { - 2048.0f, 384.0f, 4096.0f, 1024.0f, 1024.0f, 1536.0f, 1536.0f, 1500.0f, 2250.0f, 512.0f, 384.0f, 0, 0, 0, 0}; + 0, + 2048, + 384, + 4096, + 1024, + 1024, + 1536, + 1536, + 1500, + 2250, + 512, + 384, + 32768, + 0, + 0, + 0 + }; - if (iType <= AI_EVENT_GRENADE) { - return fRadius[iType]; - } else { + if (iType >= AI_EVENT_MAX) { Com_Printf("G_AIEventRadius: invalid event type\n"); return 1500.0f; } + + return fRadius[iType]; } void G_BroadcastAIEvent(Entity *originator, Vector origin, char *pszType) @@ -1642,6 +1803,7 @@ void G_BroadcastAIEvent(Entity *originator, Vector origin, char *pszType) void G_BroadcastAIEvent(Entity *originator, Vector origin, int iType, float radius) { Sentient *ent; + Actor *act; Vector delta; str name; float r2; @@ -1650,8 +1812,8 @@ void G_BroadcastAIEvent(Entity *originator, Vector origin, int iType, float radi int iNumSentients; int iAreaNum; - if (iType < AI_EVENT_FOOTSTEP) { - ent = (Sentient *)G_GetEntity(0); + if (iType == AI_EVENT_MISC || iType == AI_EVENT_MISC_LOUD) { + ent = static_cast(G_GetEntity(0)); if (ent && ent->m_bIsDisguised) { return; @@ -1663,48 +1825,50 @@ void G_BroadcastAIEvent(Entity *originator, Vector origin, int iType, float radi } assert(originator); - if (originator && !(originator->flags & FL_NOTARGET)) { - r2 = Square(radius); - iNumSentients = SentientList.NumObjects(); - for (i = 1; i <= iNumSentients; i++) { - ent = SentientList.ObjectAt(i); - if ((ent == originator) || ent->deadflag) { - continue; - } - delta = origin - ent->centroid; - - // dot product returns length squared - dist2 = Square(delta); - - if (originator) { - iAreaNum = originator->edict->r.areanum; - } else { - iAreaNum = gi.AreaForPoint(origin); - } - - if ((dist2 <= r2) - && ((iAreaNum == ent->edict->r.areanum) || (gi.AreasConnected(iAreaNum, ent->edict->r.areanum)))) - - { - if (ent->IsSubclassOfActor()) { - Actor *act = (Actor *)ent; - - if (!act->IgnoreSound(iType)) { - act->ReceiveAIEvent(origin, iType, originator, dist2, r2); - } - } else if (ent->IsSubclassOfBot()) { - PlayerBot *bot = (PlayerBot *)ent; - - bot->NoticeEvent(origin, iType, originator, dist2, r2); - } - } + r2 = Square(radius); + iNumSentients = SentientList.NumObjects(); + for (i = 1; i <= iNumSentients; i++) { + ent = SentientList.ObjectAt(i); + if ((ent == originator) || ent->deadflag) { + continue; } -#if 0 - gi.DPrintf( "Broadcast event %s to %d entities\n", ev->getName(), count ); -#endif + if (!ent->IsSubclassOfActor()) { + continue; + } + + act = static_cast(ent); + if (act->IgnoreSound(iType)) { + continue; + } + + delta = origin - ent->centroid; + + // dot product returns length squared + dist2 = Square(delta); + + if (originator) { + iAreaNum = originator->edict->r.areanum; + } else { + iAreaNum = gi.AreaForPoint(origin); + } + + if (dist2 > r2) { + continue; + } + + if (iAreaNum != ent->edict->r.areanum && !gi.AreasConnected(iAreaNum, ent->edict->r.areanum)) { + continue; + } + + act->ReceiveAIEvent(origin, iType, originator, dist2, r2); } + + botManager.BroadcastEvent(originator, origin, iType, radius); +#if 0 + gi.DPrintf("Broadcast event %s to %d entities\n", ev->getName(), count); +#endif } void CloneEntity(Entity *dest, Entity *src) @@ -1747,7 +1911,6 @@ void CloneEntity(Entity *dest, Entity *src) } weaponhand_t WeaponHandNameToNum(str side) - { if (!side.length()) { gi.DPrintf("WeaponHandNameToNum : Weapon hand not specified\n"); @@ -1764,7 +1927,6 @@ weaponhand_t WeaponHandNameToNum(str side) } const char *WeaponHandNumToName(weaponhand_t hand) - { switch (hand) { case WEAPON_MAIN: @@ -1777,7 +1939,6 @@ const char *WeaponHandNumToName(weaponhand_t hand) } firemode_t WeaponModeNameToNum(str mode) - { if (!mode.length()) { gi.DPrintf("WeaponModeNameToNum : Weapon mode not specified\n"); @@ -1869,7 +2030,6 @@ str G_WeaponClassNumToName(int num) } void G_DebugTargets(Entity *e, str from) - { gi.DPrintf("DEBUGTARGETS:%s ", from.c_str()); @@ -1887,7 +2047,6 @@ void G_DebugTargets(Entity *e, str from) } void G_DebugDamage(float damage, Entity *victim, Entity *attacker, Entity *inflictor) - { gi.DPrintf( "Victim:%s Attacker:%s Inflictor:%s Damage:%f\n", @@ -1910,7 +2069,6 @@ void G_FadeOut(float delaytime) } void G_AutoFadeIn(void) - { level.m_fade_time_start = 1; level.m_fade_time = 1; @@ -1923,7 +2081,6 @@ void G_AutoFadeIn(void) } void G_ClearFade(void) - { level.m_fade_time = -1; level.m_fade_type = fadein; @@ -1942,29 +2099,10 @@ void G_RestartLevelWithDelay(float delaytime) { int i; - if (level.died_already) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { return; } - level.died_already = true; - - // Restart the level soon - for (i = 0; i < game.maxclients; i++) { - if (g_entities[i].inuse) { - if (g_entities[i].entity) { - g_entities[i].entity->PostEvent(EV_Player_Respawn, delaytime); - } - } - } -} - -// -// restarts the game after delaytime -// -void G_PlayerDied(float delaytime) -{ - int i; - if (level.died_already) { return; } @@ -1972,7 +2110,6 @@ void G_PlayerDied(float delaytime) level.died_already = true; // Restart the level soon - for (i = 0; i < game.maxclients; i++) { if (g_entities[i].inuse) { if (g_entities[i].entity) { @@ -1986,34 +2123,42 @@ void G_PlayerDied(float delaytime) } void G_MissionFailed(void) - { - // Make the music system play the failure music for this level - ChangeMusic("failure", "normal", true); - - G_PlayerDied(3); - - // tell the player they f'd up - gi.centerprintf(&g_entities[0], "@textures/menu/mission.tga"); + G_RestartLevelWithDelay(0); level.mission_failed = true; } void G_StartCinematic(void) - { level.cinematic = true; gi.cvar_set("sv_cinematic", "1"); } void G_StopCinematic(void) - { // clear out the skip thread level.cinematic = false; gi.cvar_set("sv_cinematic", "0"); } +int G_NumClients(void) +{ + gentity_t *ent; + int i; + int count = 0; + + for (i = 0, ent = g_entities; i < game.maxclients; ent++, i++) { + if (!ent->inuse || !ent->entity) { + continue; + } + + count++; + } + + return count; +} + void G_PrintToAllClients(const char *pszString, int iType) { if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { @@ -2026,9 +2171,9 @@ void G_PrintToAllClients(const char *pszString, int iType) } } else { if (iType == 0) { - gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", pszString); + gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\"", pszString); } else { - gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\n\"", pszString); + gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\"", pszString); } } } @@ -2087,9 +2232,12 @@ G_PrintDeathMessageEmulated(const char *s1, const char *s2, char *attackerName, result2 = NULL; if (type == tolower(type)) { + // Enemy hudColor = 4; } else { - hudColor = 5; + // Friend + //hudColor = 5; + hudColor = 4; } if (*s1 != 'x') { @@ -2102,7 +2250,11 @@ G_PrintDeathMessageEmulated(const char *s1, const char *s2, char *attackerName, return va("%c%s %s\n", hudColor, victimName, result1); } else if (tolower(type) == 'p') { if (*s2 == 'x') { - return va("%c%s %s %s\n", hudColor, victimName, result1, attackerName); + if (s2[1] && s2[2]) { + return va("%c%s %s %s %s\n", hudColor, victimName, result1, attackerName, s2 + 2); + } else { + return va("%c%s %s %s\n", hudColor, victimName, result1, attackerName); + } } else { return va("%c%s %s %s%s\n", hudColor, victimName, result1, attackerName, result2); } @@ -2135,9 +2287,9 @@ void G_PrintDeathMessage( pPlayer = static_cast(ent->entity); if ((pPlayer->GetTeam() == TEAM_ALLIES || pPlayer->GetTeam() == TEAM_AXIS) - && pPlayer->GetTeam() == victim->GetTeam() + && pPlayer->GetTeam() == victim->GetTeam() || pPlayer->GetTeam() != TEAM_ALLIES && pPlayer->GetTeam() != TEAM_AXIS - && victim->GetTeam() == TEAM_ALLIES) { + && victim->GetTeam() == TEAM_ALLIES) { gi.SendServerCommand( ent - g_entities, "printdeathmsg \"%s\"\"%s\"\"%s\"\"%s\" %c", @@ -2178,7 +2330,7 @@ void G_PrintDeathMessage_Old(const char *pszString) continue; } - gi.SendServerCommand(ent - g_entities, "print \"" HUD_MESSAGE_CHAT_RED "%s\"", pszString); + gi.SendServerCommand(ent - g_entities, "print \"%s\"", pszString); } } @@ -2211,7 +2363,7 @@ void G_WarnPlayer(Player *player, const char *format, ...) va_list va; va_start(va, format); - vsprintf(buffer, format, va); + Q_vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); gi.SendServerCommand(player->client->ps.clientNum, "print \"%s\"\n", buffer); @@ -2300,3 +2452,7 @@ gentity_t *G_GetGEntity(int ent_num) return ent; } + +unsigned int G_GetWeaponCommand(unsigned int buttons) { + return GetWeaponCommand(buttons, g_protocol >= PROTOCOL_MOHTA_MIN ? WEAPON_COMMAND_MAX_VER17 : WEAPON_COMMAND_MAX_VER6); +} diff --git a/code/fgame/g_utils.h b/code/fgame/g_utils.h index 8f897721..7d5fb4be 100644 --- a/code/fgame/g_utils.h +++ b/code/fgame/g_utils.h @@ -30,6 +30,9 @@ class SimpleEntity; class SimpleArchivedEntity; class ScriptThread; +void G_ArchivePlayerState(Archiver& arc, playerState_t* ps); +void G_ArchiveTrace(Archiver& arc, trace_t* trace); +void G_ArchiveClient(Archiver& arc, gclient_t* client); void G_ArchiveEdict(Archiver& arc, gentity_t *edict); void G_AllocDebugLines(void); @@ -112,6 +115,7 @@ void G_TraceEntities( int contentmask, qboolean bIncludeTriggers = qfalse ); +float G_VisualObfuscation(const Vector& start, const Vector& end); void SelectSpawnPoint(Vector& org, Vector& angles, str& thread); @@ -123,6 +127,7 @@ Entity *G_NextEntity(Entity *ent); qboolean M_CheckBottom(Entity *ent); Vector G_GetMovedir(float angle); +float G_GetAngle(Vector movedir); qboolean KillBox(Entity *ent); qboolean IsNumeric(const char *str); @@ -142,7 +147,6 @@ void G_MissionFailed(void); void G_FadeOut(float delaytime); void G_FadeSound(float delaytime); void G_RestartLevelWithDelay(float delaytime); -void G_PlayerDied(float delaytime); void G_AutoFadeIn(void); void G_ClearFade(void); void G_StartCinematic(void); @@ -323,3 +327,4 @@ const char *WeaponHandNumToName(weaponhand_t hand); weaponhand_t WeaponHandNameToNum(str side); void G_DebugTargets(Entity *e, str from); void G_DebugDamage(float damage, Entity *victim, Entity *attacker, Entity *inflictor); +unsigned int G_GetWeaponCommand(unsigned int buttons); diff --git a/code/fgame/g_vmove.cpp b/code/fgame/g_vmove.cpp index 153658e1..1cdbb4a8 100644 --- a/code/fgame/g_vmove.cpp +++ b/code/fgame/g_vmove.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -28,609 +28,621 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "movegrid.h" typedef struct { - qboolean validGroundTrace; - float previous_origin[ 3 ]; - float previous_velocity[ 3 ]; + qboolean validGroundTrace; + float previous_origin[3]; + float previous_velocity[3]; } vml_t; vmove_t *vm; -vml_t vml; +vml_t vml; -void VM_ClipVelocity - ( - float *in, - float *normal, - float *out, - float overbounce - ) +void VM_ClipVelocity(float *in, float *normal, float *out, float overbounce) { - float backoff; - float dir_z; - float normal2[ 3 ]; + float backoff; + float dir_z; + float normal2[3]; - if( normal[ 2 ] >= 0.70f ) - { - if( in[ 0 ] == 0.0f && in[ 1 ] == 0.0f ) - { - VectorClear( out ); - return; - } + if (normal[2] >= 0.70f) { + if (in[0] == 0.0f && in[1] == 0.0f) { + VectorClear(out); + return; + } - normal2[ 0 ] = in[ 0 ] + DotProduct2D( in, normal ); - normal2[ 1 ] = in[ 1 ] + DotProduct2D( in, normal ); - normal2[ 2 ] = normal[ 2 ] * DotProduct2D( in, in ); + normal2[0] = in[0] + DotProduct2D(in, normal); + normal2[1] = in[1] + DotProduct2D(in, normal); + normal2[2] = normal[2] * DotProduct2D(in, in); - VectorNormalize( normal2 ); + VectorNormalize(normal2); - dir_z = -normal2[ 2 ]; + dir_z = -normal2[2]; - out[ 0 ] = in[ 0 ]; - out[ 1 ] = in[ 1 ]; - out[ 2 ] = DotProduct2D( in, normal2 ) / dir_z; - } - else - { - backoff = DotProduct( in, normal ); + out[0] = in[0]; + out[1] = in[1]; + out[2] = DotProduct2D(in, normal2) / dir_z; + } else { + backoff = DotProduct(in, normal); - if( backoff < 0 ) - backoff *= overbounce; - else - backoff /= overbounce; + if (backoff < 0) { + backoff *= overbounce; + } else { + backoff /= overbounce; + } - out[ 0 ] = in[ 0 ] - normal[ 0 ] * backoff; - out[ 1 ] = in[ 1 ] - normal[ 1 ] * backoff; - out[ 2 ] = in[ 2 ] - normal[ 2 ] * backoff; - } + out[0] = in[0] - normal[0] * backoff; + out[1] = in[1] - normal[1] * backoff; + out[2] = in[2] - normal[2] * backoff; + } } -void VM_AddTouchEnt - ( - int entityNum - ) +void VM_AddTouchEnt(int entityNum) { - int i; + int i; - if( entityNum == ENTITYNUM_NONE || entityNum == ENTITYNUM_WORLD ) - { - return; - } + if (entityNum == ENTITYNUM_NONE || entityNum == ENTITYNUM_WORLD) { + return; + } - if( vm->numtouch > 32 ) - { - return; - } + if (vm->numtouch > 32) { + return; + } - // see if it is already added - for( i = 0; i < vm->numtouch; i++ ) - { - if( vm->touchents[ i ] == entityNum ) - return; - } + // see if it is already added + for (i = 0; i < vm->numtouch; i++) { + if (vm->touchents[i] == entityNum) { + return; + } + } - // add it - vm->touchents[ vm->numtouch ] = entityNum; - vm->numtouch++; + // add it + vm->touchents[vm->numtouch] = entityNum; + vm->numtouch++; } -qboolean VM_SlideMove - ( - qboolean gravity - ) +qboolean VM_SlideMove(qboolean gravity) { - int bumpcount; - vec3_t dir; - float d; - int numplanes; - vec3_t planes[ 5 ]; - vec3_t clipVelocity; - int i; - int j; - int k; - trace_t trace; - vec3_t end; - float time_left; + int bumpcount; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[5]; + vec3_t clipVelocity; + int i; + int j; + int k; + trace_t trace; + vec3_t end; + float time_left; + vec3_t endVelocity; + vec3_t endClipVelocity; - if( gravity ) - { - vm->vs->velocity[ 2 ] = vm->vs->velocity[ 2 ] - vm->frametime * sv_gravity->integer; - if( vm->vs->groundPlane ) - VM_ClipVelocity( vm->vs->velocity, vm->vs->groundTrace.plane.normal, vm->vs->velocity, OVERCLIP ); - } + VectorCopy(vm->vs->velocity, endVelocity); - time_left = vm->frametime; + if (gravity) { + endVelocity[2] = vm->vs->velocity[2] - vm->frametime * sv_gravity->integer; + vm->vs->velocity[2] = (vm->vs->velocity[2] + endVelocity[2]) * 0.5; + if (vm->vs->groundPlane) { + VM_ClipVelocity(vm->vs->velocity, vm->vs->groundTrace.plane.normal, vm->vs->velocity, OVERCLIP); + } + } - if( vm->vs->groundPlane ) { - numplanes = 1; - VectorCopy( vm->vs->groundTrace.plane.normal, planes[ 0 ] ); - } - else { - numplanes = 0; - } + time_left = vm->frametime; - // never turn against original velocity - VectorNormalize2( vm->vs->velocity, planes[ numplanes ] ); - numplanes++; + if (vm->vs->groundPlane) { + numplanes = 1; + VectorCopy(vm->vs->groundTrace.plane.normal, planes[0]); + } else { + numplanes = 0; + } - for( bumpcount = 0; bumpcount < 4; bumpcount++ ) - { - // calculate position we are trying to move to - VectorMA( vm->vs->origin, time_left, vm->vs->velocity, end ); + // never turn against original velocity + VectorNormalize2(vm->vs->velocity, planes[numplanes]); + numplanes++; - // see if we can make it there - gi.trace( &trace, vm->vs->origin, vm->mins, vm->maxs, end, vm->vs->entityNum, vm->tracemask, qtrue, qfalse ); + for (bumpcount = 0; bumpcount < 4; bumpcount++) { + // calculate position we are trying to move to + VectorMA(vm->vs->origin, time_left, vm->vs->velocity, end); - if( trace.allsolid ) - break; + // see if we can make it there + gi.trace(&trace, vm->vs->origin, vm->mins, vm->maxs, end, vm->vs->entityNum, vm->tracemask, qtrue, qfalse); - if( trace.fraction > 0 ) { - // actually covered some distance - VectorCopy( trace.endpos, vm->vs->origin ); - } + if (trace.allsolid) { + if (vm->vs->velocity[0] || vm->vs->velocity[1]) { + if (vm->vs->groundPlane) { + VectorCopy(vm->vs->velocity, dir); + VectorNegate(dir, dir); + VectorNormalize(dir); - if( trace.fraction == 1 ) - return bumpcount != 0; + if (!vm->vs->hit_obstacle) { + vm->vs->hit_obstacle = qtrue; + VectorCopy(vm->vs->origin, vm->vs->hit_origin); + } - memcpy( &vm->vs->groundTrace, &trace, sizeof( vm->vs->groundTrace ) ); - vml.validGroundTrace = true; + VectorAdd(vm->vs->obstacle_normal, dir, vm->vs->obstacle_normal); + } - // save entity for contact - VM_AddTouchEnt( trace.entityNum ); + VectorClear(vm->vs->velocity); + VM_AddTouchEnt(trace.entityNum); + return qtrue; + } - time_left -= time_left * trace.fraction; + vm->vs->velocity[2] = 0; + bumpcount = 0; + break; + } - if( numplanes >= MAX_CLIP_PLANES ) - { - VectorClear( vm->vs->velocity ); - return qtrue; - } + if (trace.fraction > 0) { + // actually covered some distance + VectorCopy(trace.endpos, vm->vs->origin); + } - // - // if this is the same plane we hit before, nudge velocity - // out along it, which fixes some epsilon issues with - // non-axial planes - // - for( i = 0; i < numplanes; i++ ) - { - if( DotProduct( trace.plane.normal, planes[ i ] ) > 0.99 ) - { - VectorAdd( trace.plane.normal, vm->vs->velocity, vm->vs->velocity ); - break; - } - } + if (trace.fraction == 1) { + break; + } - if( i >= numplanes ) - { - // - // modify velocity so it parallels all of the clip planes - // + if (trace.plane.normal[2] >= MIN_WALK_NORMAL) { + memcpy(&vm->vs->groundTrace, &trace, sizeof(vm->vs->groundTrace)); + vml.validGroundTrace = qtrue; + } else if (trace.plane.normal[2] > -0.999f && vm->vs->groundPlane) { + if (!vm->vs->hit_obstacle) { + vm->vs->hit_obstacle = qtrue; + VectorCopy(vm->vs->origin, vm->vs->hit_origin); + } - // find a plane that it enters - for( i = 0; i < numplanes; i++ ) - { - if( DotProduct( vm->vs->velocity, planes[ i ] ) >= 0.1 ) { - continue; // move doesn't interact with the plane - } + VectorAdd(vm->vs->obstacle_normal, trace.plane.normal, vm->vs->obstacle_normal); + } - // slide along the plane - VM_ClipVelocity( vm->vs->velocity, planes[ i ], clipVelocity, OVERCLIP ); + // save entity for contact + VM_AddTouchEnt(trace.entityNum); - // see if there is a second plane that the new move enters - for( j = 0; j < numplanes; j++ ) - { - if( j == i ) { - continue; - } + time_left -= time_left * trace.fraction; - // slide along the plane - VM_ClipVelocity( vm->vs->velocity, planes[ j ], clipVelocity, OVERCLIP ); + if (numplanes >= MAX_CLIP_PLANES) { + VectorClear(vm->vs->velocity); + return qtrue; + } - if( DotProduct( clipVelocity, planes[ j ] ) >= 0.0f ) { - continue; // move doesn't interact with the plane - } + // + // if this is the same plane we hit before, nudge velocity + // out along it, which fixes some epsilon issues with + // non-axial planes + // + for (i = 0; i < numplanes; i++) { + if (DotProduct(trace.plane.normal, planes[i]) > 0.99) { + VectorAdd(trace.plane.normal, vm->vs->velocity, vm->vs->velocity); + break; + } + } - // slide the original velocity along the crease - CrossProduct( planes[ i ], planes[ j ], dir ); - VectorNormalize( dir ); - d = DotProduct( dir, vm->vs->velocity ); - VectorScale( dir, d, clipVelocity ); + if (i >= numplanes) { + // + // modify velocity so it parallels all of the clip planes + // + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; - // see if there is a third plane the the new move enters - for( k = 0; k < numplanes; k++ ) - { - if( k == i || k == j ) { - continue; - } + // find a plane that it enters + for (i = 0; i < numplanes; i++) { + if (DotProduct(vm->vs->velocity, planes[i]) >= 0.1) { + continue; // move doesn't interact with the plane + } - if( DotProduct( clipVelocity, planes[ k ] ) >= 0.1f ) { - continue; // move doesn't interact with the plane - } + // slide along the plane + VM_ClipVelocity(vm->vs->velocity, planes[i], clipVelocity, OVERCLIP); + VM_ClipVelocity(endVelocity, planes[i], endClipVelocity, OVERCLIP); - // stop dead at a tripple plane interaction - VectorClear( vm->vs->velocity ); - return qtrue; - } - } + // see if there is a second plane that the new move enters + for (j = 0; j < numplanes; j++) { + if (j == i) { + continue; + } - // if we have fixed all interactions, try another move - VectorCopy( clipVelocity, vm->vs->velocity ); - break; - } - } - } + // slide along the plane + VM_ClipVelocity(clipVelocity, planes[j], clipVelocity, OVERCLIP); + VM_ClipVelocity(endClipVelocity, planes[j], endClipVelocity, OVERCLIP); - if( vm->vs->velocity[ 0 ] || vm->vs->velocity[ 1 ] ) - { - if( vm->vs->groundPlane ) - { - VectorCopy( vm->vs->velocity, dir ); - VectorNegate( dir, dir ); - VectorNormalize( dir ); + if (DotProduct(clipVelocity, planes[j]) >= 0.0f) { + continue; // move doesn't interact with the plane + } - VM_AddTouchEnt( trace.entityNum ); - VectorAdd( vm->vs->obstacle_normal, dir, vm->vs->obstacle_normal ); - } + // slide the original velocity along the crease + CrossProduct(planes[i], planes[j], dir); + VectorNormalize(dir); + d = DotProduct(dir, vm->vs->velocity); + VectorScale(dir, d, clipVelocity); + d = DotProduct(dir, endVelocity); + VectorScale(dir, d, endClipVelocity); - VectorClear( vm->vs->velocity ); - return true; - } + // see if there is a third plane the the new move enters + for (k = 0; k < numplanes; k++) { + if (k == i || k == j) { + continue; + } - vm->vs->velocity[ 2 ] = 0; - return false; + if (DotProduct(clipVelocity, planes[k]) >= 0.1f) { + continue; // move doesn't interact with the plane + } + + // stop dead at a tripple plane interaction + VectorClear(vm->vs->velocity); + return qtrue; + } + } + + // if we have fixed all interactions, try another move + VectorCopy(clipVelocity, vm->vs->velocity); + VectorCopy(endClipVelocity, endVelocity); + break; + } + } + } + + if (gravity) { + VectorCopy(endVelocity, vm->vs->velocity); + } + + return bumpcount != 0; } -static void VM_GroundTraceInternal2( void ); +static void VM_GroundTraceInternal2(void); -void VM_GroundTraceInternal - ( - void - ) +void VM_GroundTraceInternal(void) { - VM_GroundTraceInternal2(); - VM_AddTouchEnt( vm->vs->groundTrace.entityNum ); + if (vm->vs->groundTrace.fraction == 1) { + vm->vs->groundEntityNum = ENTITYNUM_NONE; + vm->vs->groundPlane = qfalse; + vm->vs->walking = qfalse; + return; + } + + if (vm->vs->velocity[2] > 0.0f && DotProduct(vm->vs->velocity, vm->vs->groundTrace.plane.normal) > 10.0f) { + vm->vs->groundEntityNum = ENTITYNUM_NONE; + vm->vs->groundPlane = qfalse; + vm->vs->walking = qfalse; + return; + } + + // slopes that are too steep will not be considered onground + if (vm->vs->groundTrace.plane.normal[2] < MIN_WALK_NORMAL) { + vec3_t oldvel; + float d; + + VectorCopy(vm->vs->velocity, oldvel); + VectorSet(vm->vs->velocity, 0, 0, -1.0f / vm->frametime); + VM_SlideMove(qfalse); + + d = VectorLength(vm->vs->velocity); + VectorCopy(oldvel, vm->vs->velocity); + + if (d > (0.1f / vm->frametime)) { + vm->vs->groundEntityNum = ENTITYNUM_NONE; + vm->vs->groundPlane = qtrue; + vm->vs->walking = qfalse; + return; + } + } + + vm->vs->groundPlane = qtrue; + vm->vs->walking = qtrue; + vm->vs->groundEntityNum = vm->vs->groundTrace.entityNum; + + VM_AddTouchEnt(vm->vs->groundTrace.entityNum); } -void VM_GroundTraceInternal2 - ( - void - ) +void VM_GroundTraceInternal2(void) { - if( vm->vs->groundTrace.fraction == 1.0f ) - { - vm->vs->groundEntityNum = ENTITYNUM_NONE; - vm->vs->groundPlane = qfalse; - vm->vs->walking = qfalse; - return; - } + if (vm->vs->groundTrace.fraction == 1.0f) { + vm->vs->groundEntityNum = ENTITYNUM_NONE; + vm->vs->groundPlane = qfalse; + vm->vs->walking = qfalse; + return; + } - if( vm->vs->velocity[ 2 ] > 0.0f ) - { - if( DotProduct( vm->vs->velocity, vm->vs->groundTrace.plane.normal ) > 10.0f ) - { - vm->vs->groundEntityNum = ENTITYNUM_NONE; - vm->vs->groundPlane = qfalse; - vm->vs->walking = qfalse; - return; - } - } + if (vm->vs->velocity[2] > 0.0f && DotProduct(vm->vs->velocity, vm->vs->groundTrace.plane.normal) > 10.0f) { + vm->vs->groundEntityNum = ENTITYNUM_NONE; + vm->vs->groundPlane = qfalse; + vm->vs->walking = qfalse; + return; + } - // slopes that are too steep will not be considered onground - if( vm->vs->groundTrace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - vec3_t oldvel; - float d; + // slopes that are too steep will not be considered onground + if (vm->vs->groundTrace.plane.normal[2] < MIN_WALK_NORMAL) { + vec3_t oldvel; + float d; - VectorCopy( vm->vs->velocity, oldvel ); - VectorSet( vm->vs->velocity, 0, 0, -1.0f / vm->frametime ); - VM_SlideMove( qfalse ); + VectorCopy(vm->vs->velocity, oldvel); + VectorSet(vm->vs->velocity, 0, 0, -1.0f / vm->frametime); + VM_SlideMove(qfalse); - d = VectorLength( vm->vs->velocity ); - VectorCopy( oldvel, vm->vs->velocity ); + d = VectorLength(vm->vs->velocity); + VectorCopy(oldvel, vm->vs->velocity); - if( d > ( 0.1f / vm->frametime ) ) - { - vm->vs->groundEntityNum = ENTITYNUM_NONE; - vm->vs->groundPlane = qtrue; - vm->vs->walking = qfalse; - return; - } - } + if (d > (0.1f / vm->frametime)) { + vm->vs->groundEntityNum = ENTITYNUM_NONE; + vm->vs->groundPlane = qtrue; + vm->vs->walking = qfalse; + return; + } + } - vm->vs->groundPlane = qtrue; - vm->vs->walking = qtrue; - vm->vs->groundEntityNum = vm->vs->groundTrace.entityNum; + vm->vs->groundPlane = qtrue; + vm->vs->walking = qtrue; + vm->vs->groundEntityNum = vm->vs->groundTrace.entityNum; } -void VM_GroundTrace - ( - void - ) +void VM_GroundTrace(void) { - float point[ 3 ]; + float point[3]; - point[ 0 ] = vm->vs->origin[ 0 ]; - point[ 1 ] = vm->vs->origin[ 1 ]; - point[ 2 ] = vm->vs->origin[ 2 ] - 0.25f; + point[0] = vm->vs->origin[0]; + point[1] = vm->vs->origin[1]; + point[2] = vm->vs->origin[2] - 0.25f; - gi.trace( &vm->vs->groundTrace, vm->vs->origin, vm->mins, vm->maxs, point, vm->vs->entityNum, vm->tracemask, qtrue, qfalse ); - VM_GroundTraceInternal(); + gi.trace( + &vm->vs->groundTrace, vm->vs->origin, vm->mins, vm->maxs, point, vm->vs->entityNum, vm->tracemask, qtrue, qfalse + ); + VM_GroundTraceInternal(); } -void VM_StepSlideMove - ( - void - ) +void VM_StepSlideMove(void) { - vec3_t start_o; - vec3_t start_v; - vec3_t nostep_o; - vec3_t nostep_v; - trace_t trace; - qboolean bWasOnGoodGround; - vec3_t up; - vec3_t down; - qboolean start_hit_wall; - vec3_t start_wall_normal; - qboolean first_hit_wall; - vec3_t first_wall_normal; - vec3_t start_hit_origin; - vec3_t first_hit_origin; - trace_t nostep_groundTrace; + vec3_t start_o; + vec3_t start_v; + vec3_t nostep_o; + vec3_t nostep_v; + trace_t trace; + qboolean bWasOnGoodGround; + vec3_t up; + vec3_t down; + qboolean start_hit_wall; + vec3_t start_wall_normal; + qboolean first_hit_wall; + vec3_t first_wall_normal; + vec3_t start_hit_origin; + vec3_t first_hit_origin; + trace_t nostep_groundTrace; - VectorCopy( vm->vs->origin, start_o ); - VectorCopy( vm->vs->velocity, start_v ); - start_hit_wall = vm->vs->hit_obstacle; - VectorCopy( vm->vs->hit_origin, start_hit_origin ); - VectorCopy( vm->vs->obstacle_normal, start_wall_normal ); + VectorCopy(vm->vs->origin, start_o); + VectorCopy(vm->vs->velocity, start_v); + start_hit_wall = vm->vs->hit_obstacle; + VectorCopy(vm->vs->hit_origin, start_hit_origin); + VectorCopy(vm->vs->obstacle_normal, start_wall_normal); - if( VM_SlideMove( qtrue ) == 0 ) - { - if( !vml.validGroundTrace ) - VM_GroundTrace(); + if (VM_SlideMove(vm->vs->useGravity) == 0) { + if (vml.validGroundTrace) { + VM_GroundTraceInternal(); + } else { + VM_GroundTrace(); + } + return; + } - return; - } + VectorCopy(start_o, down); + down[2] -= STEPSIZE; + gi.trace(&trace, start_o, vm->mins, vm->maxs, down, vm->vs->entityNum, vm->tracemask, qtrue, qfalse); + VectorSet(up, 0, 0, 1); - VectorCopy( start_o, down ); - down[ 2 ] -= STEPSIZE; - gi.trace( &trace, start_o, vm->mins, vm->maxs, down, vm->vs->entityNum, vm->tracemask, qtrue, qfalse ); - VectorSet( up, 0, 0, 1 ); + // never step up when you still have up velocity + if (vm->vs->velocity[2] > 0 && (trace.fraction == 1.0f || DotProduct(trace.plane.normal, up) < MIN_WALK_NORMAL)) { + if (vml.validGroundTrace) { + VM_GroundTraceInternal(); + } else { + VM_GroundTrace(); + } + return; + } - // never step up when you still have up velocity - if( vm->vs->velocity[ 2 ] > 0 && ( trace.fraction == 1.0f || - DotProduct( trace.plane.normal, up ) < MIN_WALK_NORMAL ) ) - { - if( !vml.validGroundTrace ) - VM_GroundTrace(); - else - VM_GroundTraceInternal(); + if (vm->vs->groundPlane && vm->vs->groundTrace.plane.normal[2] >= MIN_WALK_NORMAL) { + bWasOnGoodGround = qtrue; + } else { + bWasOnGoodGround = qfalse; + } - return; - } + VectorCopy(start_o, up); + up[2] += STEPSIZE; - if( vm->vs->groundPlane && vm->vs->groundTrace.plane.normal[ 2 ] >= MIN_WALK_NORMAL ) - bWasOnGoodGround = qtrue; - else - bWasOnGoodGround = qfalse; + VectorCopy(vm->vs->origin, nostep_o); + VectorCopy(vm->vs->velocity, nostep_v); + memcpy(&nostep_groundTrace, &vm->vs->groundTrace, sizeof(trace_t)); - VectorCopy( vm->vs->origin, nostep_o ); - VectorCopy( vm->vs->velocity, nostep_v ); - memcpy( &nostep_groundTrace, &vm->vs->groundTrace, sizeof( trace_t ) ); + VectorCopy(up, vm->vs->origin); + VectorCopy(start_v, vm->vs->velocity); - VectorCopy( start_o, vm->vs->origin ); - VectorCopy( start_v, vm->vs->velocity ); + first_hit_wall = vm->vs->hit_obstacle; + VectorCopy(vm->vs->hit_origin, first_hit_origin); + VectorCopy(vm->vs->obstacle_normal, first_wall_normal); - first_hit_wall = vm->vs->hit_obstacle; - VectorCopy( vm->vs->hit_origin, first_hit_origin ); - VectorCopy( vm->vs->obstacle_normal, first_wall_normal ); + vm->vs->hit_obstacle = start_hit_wall; + VectorCopy(start_hit_origin, vm->vs->hit_origin); + VectorCopy(start_wall_normal, vm->vs->obstacle_normal); + VM_SlideMove(vm->vs->useGravity); - vm->vs->hit_obstacle = start_hit_wall; - VectorCopy( start_hit_origin, vm->vs->hit_origin ); - VectorCopy( start_wall_normal, vm->vs->obstacle_normal ); - VM_SlideMove( qtrue ); + VectorCopy(vm->vs->origin, down); + down[2] -= STEPSIZE * 2; - VectorCopy( vm->vs->origin, down ); - down[ 2 ] -= STEPSIZE * 2; + // test the player position if they were a stepheight higher + gi.trace(&trace, vm->vs->origin, vm->mins, vm->maxs, down, vm->vs->entityNum, vm->tracemask, qtrue, qfalse); + if (trace.entityNum != ENTITYNUM_WORLD && trace.entityNum != ENTITYNUM_WORLD) { + VectorCopy(nostep_o, vm->vs->origin); + VectorCopy(nostep_v, vm->vs->velocity); + memcpy(&vm->vs->groundTrace, &nostep_groundTrace, sizeof(vm->vs->groundTrace)); + vm->vs->hit_obstacle = first_hit_wall; + VectorCopy(first_hit_origin, vm->vs->hit_origin); + VectorCopy(first_wall_normal, vm->vs->obstacle_normal); - // test the player position if they were a stepheight higher - gi.trace( &trace, vm->vs->origin, vm->mins, vm->maxs, down, vm->vs->entityNum, vm->tracemask, qtrue, qfalse ); - if( trace.entityNum > ENTITYNUM_NONE ) - { - VectorCopy( nostep_o, vm->vs->origin ); - VectorCopy( nostep_v, vm->vs->velocity ); - memcpy( &vm->vs->groundTrace, &nostep_groundTrace, sizeof( vm->vs->groundTrace ) ); - vm->vs->hit_obstacle = first_hit_wall; - VectorCopy( first_hit_origin, vm->vs->hit_origin ); - VectorCopy( first_wall_normal, vm->vs->obstacle_normal ); + if (vml.validGroundTrace) { + VM_GroundTraceInternal(); + } else { + VM_GroundTrace(); + } + return; + } - if( !vml.validGroundTrace ) - VM_GroundTrace(); - else - VM_GroundTraceInternal(); + if (!trace.allsolid) { + memcpy(&vm->vs->groundTrace, &trace, sizeof(vm->vs->groundTrace)); + vml.validGroundTrace = qtrue; - return; - } + if (bWasOnGoodGround && trace.fraction < 1 && trace.plane.normal[2] < MIN_WALK_NORMAL) { + VectorCopy(nostep_o, vm->vs->origin); + VectorCopy(nostep_v, vm->vs->velocity); - if( !trace.allsolid ) - { - memcpy( &vm->vs->groundTrace, &trace, sizeof( vm->vs->groundTrace ) ); - vml.validGroundTrace = qtrue; + if (first_hit_wall) { + vm->vs->hit_obstacle = first_hit_wall; + VectorCopy(first_hit_origin, vm->vs->hit_origin); + VectorCopy(first_wall_normal, vm->vs->obstacle_normal); + } - if( bWasOnGoodGround && trace.fraction && trace.plane.normal[ 2 ] < MIN_WALK_NORMAL ) - { - VectorCopy( nostep_o, vm->vs->origin ); - VectorCopy( nostep_v, vm->vs->velocity ); + VM_GroundTraceInternal(); + return; + } - if( first_hit_wall ) - { - vm->vs->hit_obstacle = first_hit_wall; - VectorCopy( first_hit_origin, vm->vs->hit_origin ); - VectorCopy( first_wall_normal, vm->vs->obstacle_normal ); - } + VectorCopy(trace.endpos, vm->vs->origin); + } - VM_GroundTraceInternal(); - return; - } + if (trace.fraction < 1) { + VM_ClipVelocity(vm->vs->velocity, trace.plane.normal, vm->vs->velocity, OVERCLIP); + } - VectorCopy( trace.endpos, vm->vs->origin ); - } - - if( trace.fraction < 1.0f ) - VM_ClipVelocity( vm->vs->velocity, trace.plane.normal, vm->vs->velocity, OVERCLIP ); - - if( !vml.validGroundTrace ) - VM_GroundTrace(); - else - VM_GroundTraceInternal(); + if (vml.validGroundTrace) { + VM_GroundTraceInternal(); + } else { + VM_GroundTrace(); + } } -void VM_Friction( void ) { - vec3_t vec; - float *vel; - float speed, newspeed, control; - float drop; - - vel = vm->vs->velocity; - - VectorCopy( vel, vec ); - if( vm->vs->walking ) - { - // ignore slope movement - vec[ 2 ] = 0; - } - - speed = VectorLength( vec ); - if( speed < 1 ) - { - // allow sinking underwater - vel[ 0 ] = 0; - vel[ 1 ] = 0; - - return; - } - - drop = 0; - - if( vm->vs->walking ) - { - control = ( speed < 50.0f ) ? 50.0f : speed; - - // if getting knocked back, no friction - drop += control * 6.0f * vm->frametime; - } - - // scale the velocity - newspeed = speed - drop; - if( newspeed < 0 ) - { - newspeed = 0; - } - - newspeed /= speed; - - vel[ 0 ] = vel[ 0 ] * newspeed; - vel[ 1 ] = vel[ 1 ] * newspeed; - vel[ 2 ] = vel[ 2 ] * newspeed; -} - -void VM_ClipVelocity2D - ( - float *in, - float *normal, - float *out, - float overbounce - ) +void VM_Friction(void) { - float backoff; - float dir_z; - float normal2[ 3 ]; + vec3_t vec; + float *vel; + float speed, newspeed, control; + float drop; - if( normal[ 2 ] >= 0.70f ) - { - if( in[ 0 ] == 0.0f && in[ 1 ] == 0.0f ) - { - VectorClear( out ); - return; - } + vel = vm->vs->velocity; - normal2[ 0 ] = in[ 0 ] + DotProduct2D( in, normal ); - normal2[ 1 ] = in[ 1 ] + DotProduct2D( in, normal ); - normal2[ 2 ] = normal[ 2 ] * DotProduct2D( in, in ); + VectorCopy(vel, vec); + if (vm->vs->walking) { + // ignore slope movement + vec[2] = 0; + } - VectorNormalize( normal2 ); + speed = VectorLength(vec); + if (speed < 1) { + // allow sinking underwater + vel[0] = 0; + vel[1] = 0; - dir_z = -normal2[ 2 ]; + return; + } - out[ 0 ] = in[ 0 ]; - out[ 1 ] = in[ 1 ]; - out[ 2 ] = DotProduct2D( in, normal2 ) / -normal2[ 2 ]; - } - else - { - backoff = DotProduct2D( in, normal ); + drop = 0; - if( backoff < 0 ) - backoff *= overbounce; - else - backoff /= overbounce; + if (vm->vs->walking) { + control = (speed < 50.0f) ? 50.0f : speed; - out[ 0 ] = in[ 0 ] - normal[ 0 ] * backoff; - out[ 1 ] = in[ 1 ] - normal[ 1 ] * backoff; - out[ 2 ] = -( backoff * normal[ 2 ] ); - } + // if getting knocked back, no friction + drop += control * 6.0f * vm->frametime; + } + + // scale the velocity + newspeed = speed - drop; + if (newspeed < 0) { + newspeed = 0; + } + + newspeed /= speed; + + vel[0] = vel[0] * newspeed; + vel[1] = vel[1] * newspeed; + vel[2] = vel[2] * newspeed; } -void VmoveSingle - ( - vmove_t *vmove - ) +void VM_ClipVelocity2D(float *in, float *normal, float *out, float overbounce) { - float point[ 3 ]; - trace_t trace; + float backoff; + float dir_z; + float normal2[3]; - vm = vmove; + if (normal[2] >= 0.70f) { + if (in[0] == 0.0f && in[1] == 0.0f) { + VectorClear(out); + return; + } - vmove->numtouch = 0; - vmove->vs->hit_obstacle = false; - VectorCopy( vec_origin, vmove->vs->obstacle_normal ); + normal2[0] = in[0] + DotProduct2D(in, normal); + normal2[1] = in[1] + DotProduct2D(in, normal); + normal2[2] = normal[2] * DotProduct2D(in, in); - memset( &vml, 0, sizeof( vml_t ) ); + VectorNormalize(normal2); - VectorCopy( vmove->vs->origin, vml.previous_origin ); - VectorCopy( vmove->vs->velocity, vml.previous_velocity ); + dir_z = -normal2[2]; - VM_GroundTraceInternal2(); + out[0] = in[0]; + out[1] = in[1]; + out[2] = DotProduct2D(in, normal2) / -normal2[2]; + } else { + backoff = DotProduct2D(in, normal); - if( vmove->vs->walking ) - { - float wishdir[ 3 ]; + if (backoff < 0) { + backoff *= overbounce; + } else { + backoff /= overbounce; + } - VM_Friction(); - VM_ClipVelocity2D( vm->vs->desired_dir, vm->vs->groundTrace.plane.normal, wishdir, OVERCLIP ); - VectorNormalize( wishdir ); - - vm->vs->velocity[ 0 ] = vm->desired_speed * wishdir[ 0 ]; - vm->vs->velocity[ 1 ] = vm->desired_speed * wishdir[ 1 ]; - } - else if( vmove->vs->groundPlane ) - { - VM_ClipVelocity( vm->vs->velocity, vm->vs->groundTrace.plane.normal, vm->vs->velocity, OVERCLIP ); - } - - VM_StepSlideMove(); - - if( !vm->vs->walking && vml.previous_velocity[ 2 ] >= 0.0f && vm->vs->velocity[ 2 ] <= 0.0f ) - { - point[ 0 ] = vm->vs->origin[ 0 ]; - point[ 1 ] = vm->vs->origin[ 1 ]; - point[ 2 ] = vm->vs->origin[ 2 ] - 18.0f; - - gi.trace( &trace, vm->vs->origin, vm->mins, vm->maxs, point, vm->vs->entityNum, vm->tracemask, qtrue, qfalse ); - - if( trace.fraction < 1.0f && !trace.allsolid ) - { - VM_GroundTrace(); - return; - } - } + out[0] = in[0] - normal[0] * backoff; + out[1] = in[1] - normal[1] * backoff; + out[2] = -(backoff * normal[2]); + } } +void VmoveSingle(vmove_t *vmove) +{ + float point[3]; + trace_t trace; + bool walking; + + vm = vmove; + + vmove->numtouch = 0; + vmove->vs->hit_obstacle = false; + VectorCopy(vec_origin, vmove->vs->obstacle_normal); + + memset(&vml, 0, sizeof(vml_t)); + + VectorCopy(vmove->vs->origin, vml.previous_origin); + VectorCopy(vmove->vs->velocity, vml.previous_velocity); + + VM_GroundTraceInternal2(); + + walking = vm->vs->walking; + if (walking) { + float wishdir[3]; + + VM_Friction(); + VM_ClipVelocity2D(vm->vs->desired_dir, vm->vs->groundTrace.plane.normal, wishdir, OVERCLIP); + VectorNormalize(wishdir); + + vm->vs->velocity[0] = vm->desired_speed * wishdir[0]; + vm->vs->velocity[1] = vm->desired_speed * wishdir[1]; + + if (!vm->vs->velocity[0] && !vm->vs->velocity[1]) { + VM_GroundTrace(); + return; + } + } else if (vm->vs->groundPlane) { + VM_ClipVelocity(vm->vs->velocity, vm->vs->groundTrace.plane.normal, vm->vs->velocity, OVERCLIP); + } + + VM_StepSlideMove(); + + if (!vm->vs->walking && (walking || (vml.previous_velocity[2] >= 0.0f && vm->vs->velocity[2] <= 0.0f))) { + point[0] = vm->vs->origin[0]; + point[1] = vm->vs->origin[1]; + point[2] = vm->vs->origin[2] - 18; + + gi.trace(&trace, vm->vs->origin, vm->mins, vm->maxs, point, vm->vs->entityNum, vm->tracemask, qtrue, qfalse); + + if (trace.fraction < 1 && !trace.allsolid) { + VectorCopy(trace.endpos, vm->vs->origin); + VM_GroundTrace(); + } + } +} diff --git a/code/fgame/game.cpp b/code/fgame/game.cpp index 6eaa288a..29d5c47b 100644 --- a/code/fgame/game.cpp +++ b/code/fgame/game.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,25 +24,116 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "game.h" #include "scriptmaster.h" -#include "world.h" +#include "worldspawn.h" #include "camera.h" #include "entity.h" #include "player.h" #include "dm_manager.h" +Event EV_Game_Detail +( + "skill", + EV_DEFAULT, + NULL, + NULL, + "game.skill", + EV_GETTER +); + +Event EV_Game_Skill +( + "detail", + EV_DEFAULT, + NULL, + NULL, + "game.detail", + EV_GETTER +); + Game game; +void Game::GetSkill(Event *ev) +{ + switch (skill->integer) { + case 0: + case 1: + ev->AddString("easy"); + break; + case 2: + ev->AddString("hard"); + break; + default: + ev->AddString("unknown"); + break; + } +} + +void Game::GetDetail(Event *ev) +{ + ev->AddFloat(detail->value); +} + +void Game::Init() +{ + clients = NULL; + autosaved = qfalse; + maxentities = 0; + maxclients = 0; +} + +void Game::Archive(Archiver& arc) +{ + static cvar_t *g_maxplayerhealth = gi.Cvar_Get("g_maxplayerhealth", "250", 0); + int i; + + if (arc.Saving()) { + Vars()->MakePrimitive(); + } + + Listener::Archive(arc); + + if (arc.Saving()) { + float fTmp; + int iTmp; + + fTmp = skill->value; + arc.ArchiveFloat(&fTmp); + + iTmp = g_maxplayerhealth->integer; + arc.ArchiveInteger(&iTmp); + } else { + float fTmp; + int iTmp; + + arc.ArchiveFloat(&fTmp); + gi.cvar_set("skill", va("%f", fTmp)); + arc.ArchiveInteger(&iTmp); + gi.cvar_set("g_maxplayerhealth", va("%d", iTmp)); + } + + arc.ArchiveBoolean(&autosaved); + arc.ArchiveInteger(&maxentities); + arc.ArchiveInteger(&maxclients); + + if (arc.Loading()) { + G_AllocGameData(); + } + + for (i = 0; i < maxclients; i++) { + G_ArchiveClient(arc, &clients[i]); + } +} + Game::Game() { - clients = NULL; - maxclients = 0; + Init(); } Game::~Game() {} -void Game::Archive(Archiver& arc) {} - CLASS_DECLARATION(Listener, Game, NULL) { - {NULL, NULL} + {&EV_Game_Skill, &Game::GetSkill }, + {&EV_Game_Detail, &Game::GetDetail}, + {NULL, NULL } }; diff --git a/code/fgame/game.h b/code/fgame/game.h index b97c59d0..61f7821a 100644 --- a/code/fgame/game.h +++ b/code/fgame/game.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -39,10 +39,16 @@ public: public: CLASS_PROTOTYPE(Game); - void Archive(Archiver& arc) override; +protected: + void GetSkill(Event *ev); + void GetDetail(Event *ev); +public: Game(); ~Game(); + + void Init(); + void Archive(Archiver& arc) override; }; class SimpleArchivedEntity; diff --git a/code/fgame/gamecmds.cpp b/code/fgame/gamecmds.cpp index 74e5f8ce..69f94876 100644 --- a/code/fgame/gamecmds.cpp +++ b/code/fgame/gamecmds.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,7 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // gamecmds.cpp: Game commands -// +// #include "gamecmds.h" #include "glb_local.h" @@ -36,179 +36,264 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "consoleevent.h" #include "g_bot.h" -typedef struct - { - const char *command; - qboolean ( *func )( gentity_t *ent ); - qboolean allclients; - } consolecmd_t; +typedef struct { + const char *command; + qboolean (*func)(gentity_t *ent); + qboolean allclients; +} consolecmd_t; -consolecmd_t G_ConsoleCmds[] = - { - // command name function available in multiplayer? - { "say", G_SayCmd, qtrue }, - { "eventlist", G_EventListCmd, qfalse }, - { "pendingevents", G_PendingEventsCmd, qfalse }, - { "eventhelp", G_EventHelpCmd, qfalse }, - { "dumpevents", G_DumpEventsCmd, qfalse }, - { "classevents", G_ClassEventsCmd, qfalse }, - { "dumpclassevents", G_DumpClassEventsCmd, qfalse }, - { "dumpallclasses", G_DumpAllClassesCmd, qtrue }, - { "classlist", G_ClassListCmd, qfalse }, - { "classtree", G_ClassTreeCmd, qfalse }, - { "cam", G_CameraCmd, qfalse }, - { "snd", G_SoundCmd, qfalse }, - { "showvar", G_ShowVarCmd, qfalse }, - { "script", G_ScriptCmd, qfalse }, - { "levelvars", G_LevelVarsCmd, qfalse }, - { "gamevars", G_GameVarsCmd, qfalse }, - { "compilescript", G_CompileScript, qfalse }, - { "addbot", G_AddBotCommand, qfalse }, - { "removebot", G_RemoveBotCommand, qfalse }, +typedef struct { + const char* prefix; + SafePtr master; +} commandmaster_t; + +consolecmd_t G_ConsoleCmds[] = { + // command name function available in multiplayer? + {"say", G_SayCmd, qtrue }, + {"eventlist", G_EventListCmd, qfalse}, + {"pendingevents", G_PendingEventsCmd, qfalse}, + {"eventhelp", G_EventHelpCmd, qfalse}, + {"dumpevents", G_DumpEventsCmd, qfalse}, + {"classevents", G_ClassEventsCmd, qfalse}, + {"dumpclassevents", G_DumpClassEventsCmd, qfalse}, + {"dumpallclasses", G_DumpAllClassesCmd, qtrue }, + {"classlist", G_ClassListCmd, qfalse}, + {"classtree", G_ClassTreeCmd, qfalse}, + {"cam", G_CameraCmd, qfalse}, + {"snd", G_SoundCmd, qfalse}, + {"showvar", G_ShowVarCmd, qfalse}, + {"levelvars", G_LevelVarsCmd, qfalse}, + {"gamevars", G_GameVarsCmd, qfalse}, + {"script", G_ScriptCmd, qfalse}, + // Added in 2.0 + {"reloadmap", G_ReloadMap, qfalse}, + // Added in OPM + //==== + {"compilescript", G_CompileScript, qfalse}, + {"addbot", G_AddBotCommand, qfalse}, + {"removebot", G_RemoveBotCommand, qfalse}, #ifdef _DEBUG - { "bot", G_BotCommand, qfalse }, + {"bot", G_BotCommand, qfalse}, #endif - { NULL, NULL, qfalse } - }; + //==== + {NULL, NULL, qfalse} +}; +Container commandMasters; -void G_InitConsoleCommands - ( - void - ) +void G_InitConsoleCommands(void) { - consolecmd_t *cmds; + consolecmd_t *cmds; - // - // the game server will interpret these commands, which will be automatically - // forwarded to the server after they are not recognized locally - // - gi.AddCommand( "give", NULL ); - gi.AddCommand( "god", NULL ); - gi.AddCommand( "notarget", NULL ); - gi.AddCommand( "noclip", NULL ); - gi.AddCommand( "kill", NULL ); - gi.AddCommand( "script", NULL ); + // + // the game server will interpret these commands, which will be automatically + // forwarded to the server after they are not recognized locally + // + gi.AddCommand("give", NULL); + gi.AddCommand("god", NULL); + gi.AddCommand("notarget", NULL); + gi.AddCommand("noclip", NULL); + gi.AddCommand("kill", NULL); + gi.AddCommand("script", NULL); + gi.AddCommand("ready", NULL); + gi.AddCommand("notready", NULL); + gi.AddCommand("invprev", NULL); + gi.AddCommand("invnext", NULL); + gi.AddCommand("weapprev", NULL); + gi.AddCommand("weapnext", NULL); + gi.AddCommand("reload", NULL); + gi.AddCommand("gameversion", NULL); + gi.AddCommand("fov", NULL); + gi.AddCommand("holster", NULL); + gi.AddCommand("safeholster", NULL); + gi.AddCommand("safezoom", NULL); + gi.AddCommand("zoomoff", NULL); + gi.AddCommand("join_team", NULL); + gi.AddCommand("spectator", NULL); + gi.AddCommand("primarydmweapon", NULL); + gi.AddCommand("secondarydmweapon", NULL); + gi.AddCommand("dmmessage", NULL); - for( cmds = G_ConsoleCmds; cmds->command != NULL; cmds++ ) - { - gi.AddCommand( cmds->command, NULL ); - } + for (cmds = G_ConsoleCmds; cmds->command != NULL; cmds++) { + gi.AddCommand(cmds->command, NULL); + } } -qboolean G_ConsoleCommand ( void ) +qboolean G_ConsoleCommand(void) { - gentity_t *ent; - qboolean result; - consolecmd_t *cmds; - const char *cmd; + gentity_t *ent; + qboolean result; + consolecmd_t *cmds; + const char *cmd; - result = qfalse; - try - { - ent = &g_entities[ 0 ]; + result = qfalse; + try { + ent = &g_entities[0]; - cmd = gi.Argv( 0 ); + cmd = gi.Argv(0); - for( cmds = G_ConsoleCmds; cmds->command != NULL; cmds++ ) - { - if( !Q_stricmp( cmd, cmds->command ) ) - { - return cmds->func( ent ); - } - } + for (cmds = G_ConsoleCmds; cmds->command != NULL; cmds++) { + if (!Q_stricmp(cmd, cmds->command)) { + return cmds->func(ent); + } + } - result = G_ProcessClientCommand( ent ); - } - catch( const char *error ) - { - G_ExitWithError( error ); - } + if (cl_running->integer) { + // Don't execute the command in multiplayer + // otherwise, the command will be executed "by" the first client + result = G_ProcessClientCommand(ent); + } + } catch (const char *error) { + G_ExitWithError(error); + } - return result; + return result; } -void G_ClientCommand( gentity_t *ent ) +void G_ClientCommand(gentity_t *ent) { - try - { - if ( ent && !G_ProcessClientCommand( ent ) ) - { - // anything that doesn't match a command will be a chat - //G_Say( ent, false, true ); - } - } + try { + if (ent && !G_ProcessClientCommand(ent)) { + // anything that doesn't match a command will be a chat + //G_Say( ent, false, true ); + } + } - catch( const char *error ) - { - G_ExitWithError( error ); - } + catch (const char *error) { + G_ExitWithError(error); + } } -qboolean G_ProcessClientCommand - ( - gentity_t *ent - ) +qboolean G_ProcessClientCommand(gentity_t *ent) { - const char *cmd; - consolecmd_t *cmds; - int i; - int n; - ConsoleEvent *ev; - Player *player; + const char *cmd; + consolecmd_t *cmds; + int i; + int n; + Player *player; + qboolean allowDev; - if( !ent || !ent->client || !ent->entity ) - { - // not fully in game yet - return qfalse; - } + if (!ent || !ent->client || !ent->entity) { + // not fully in game yet + return qfalse; + } - cmd = gi.Argv( 0 ); + // Added in 2.1 + // Prevent players from messing with the server with developer commands + allowDev = g_gametype->integer == GT_SINGLE_PLAYER; - player = ( Player * )ent->entity; - player->m_lastcommand = cmd; + cmd = gi.Argv(0); - for( cmds = G_ConsoleCmds; cmds->command != NULL; cmds++ ) - { - // if we have multiple clients and this command isn't allowed by multiple clients, skip it - if( ( game.maxclients > 1 ) && ( !cmds->allclients ) ) - { - continue; - } + player = (Player *)ent->entity; + player->m_lastcommand = cmd; - if( !Q_stricmp( cmd, cmds->command ) ) - { - return cmds->func( ent ); - } - } + for (cmds = G_ConsoleCmds; cmds->command != NULL; cmds++) { + // if we have multiple clients and this command isn't allowed by multiple clients, skip it + if ((game.maxclients > 1) && (!cmds->allclients)) { + continue; + } - if( Event::FindEventNum( cmd ) ) - { - ev = new ConsoleEvent( cmd ); - ev->SetConsoleEdict( ent ); + if (!Q_stricmp(cmd, cmds->command)) { + return cmds->func(ent); + } + } - n = gi.Argc(); + if (Event::Exists(cmd)) { + ConsoleEvent ev(cmd); + ev.SetConsoleEdict(ent); - for( i = 1; i < n; i++ ) - { - ev->AddToken( gi.Argv( i ) ); - } + n = gi.Argc(); - if( !Q_stricmpn( cmd, "lod_", 4 ) ) - { - return LODModel.ProcessEvent( ev ); - } - else if( !Q_stricmpn( cmd, "view", 4 ) ) - { - return Viewmodel.ProcessEvent( ev ); - } - else if( ent->entity->CheckEventFlags( ev ) ) - { - return ent->entity->ProcessEvent( ev ); - } - } + for (i = 1; i < n; i++) { + ev.AddToken(gi.Argv(i)); + } - return qfalse; + if (!Q_stricmpn(cmd, "lod_", 4)) { + if (!allowDev) { + return false; + } + return LODModel.ProcessEvent(ev); + } else if (!Q_stricmpn(cmd, "view", 4)) { + if (!allowDev) { + return false; + } + return Viewmodel.ProcessEvent(ev); + } else { + // + // Added in OPM + // + Listener* master = G_FindMaster(cmd); + if (master) { + return master->ProcessEvent(ev); + } + } + + if (ent->entity->CheckEventFlags(&ev)) { + return ent->entity->ProcessEvent(ev); + } + } + + return qfalse; +} + +/* +================== +G_CreateMaster +================== +*/ +void G_CreateMaster(const char* prefix, Listener* master) +{ + commandmaster_t commandMaster; + + int i; + + for (i = 1; i <= commandMasters.NumObjects(); i++) { + const commandmaster_t& commandMaster = commandMasters.ObjectAt(i); + if (!str::icmp(commandMaster.prefix, prefix)) { + return; + } + } + + commandMaster.prefix = prefix; + commandMaster.master = master; + commandMasters.AddObject(commandMaster); +} + +/* +================== +G_MasterMatches +================== +*/ +bool G_MasterMatches(const commandmaster_t& commandMaster, const char* command) { + const char* s1, *s2; + + s2 = commandMaster.prefix; + for (s1 = command; *s1 && *s2; s1++, s2++) { + if (tolower(*s1) != tolower(*s2)) { + return false; + } + } + + return *s1 == '_'; +} + +/* +================== +G_FindMaster +================== +*/ +Listener* G_FindMaster(const char* command) +{ + int i; + + for (i = 1; i <= commandMasters.NumObjects(); i++) { + const commandmaster_t& commandMaster = commandMasters.ObjectAt(i); + if (G_MasterMatches(commandMaster, command)) { + return commandMaster.master; + } + } + + return NULL; } /* @@ -216,522 +301,422 @@ qboolean G_ProcessClientCommand Cmd_Say_f ================== */ -void G_Say - ( - gentity_t *ent, - qboolean team, - qboolean arg0 - ) - - { - int j; - gentity_t *other; - const char *p; - char text[ 2048 ]; - - if ( gi.Argc() < 2 && !arg0 ) - { - return; - } - - if ( !ent->entity ) - { - // just in case we're not joined yet. - team = false; - } - - if ( !DM_FLAG( DF_MODELTEAMS | DF_SKINTEAMS ) ) - { - team = false; - } - - if ( team ) - { - Com_sprintf( text, sizeof( text ), "(%s): ", ent->client->pers.netname ); - } - else - { - Com_sprintf( text, sizeof( text ), "%s: ", ent->client->pers.netname ); - } - - if ( arg0 ) - { - strcat( text, gi.Argv( 0 ) ); - strcat( text, " " ); - strcat( text, gi.Args() ); - } - else - { - p = gi.Args(); - - if ( *p == '"' ) - { - p++; - strcat( text, p ); - text[ strlen( text ) - 1 ] = 0; - } - else - { - strcat( text, p ); - } - } - - // don't let text be too long for malicious reasons - if ( strlen( text ) > 150 ) - { - text[ 150 ] = 0; - } - - strcat( text, "\n" ); - - if ( dedicated->integer ) - { - gi.SendServerCommand( 0, "print \"%s\"", text ); - } - - for( j = 0; j < game.maxclients; j++ ) - { - other = &g_entities[ j ]; - if ( !other->inuse || !other->client || !other->entity ) - { - continue; - } - - gi.SendServerCommand( 0, "print \"%s\"", text ); - } - } - -qboolean G_CameraCmd - ( - gentity_t *ent - ) - - { - Event *ev; - const char *cmd; - int i; - int n; - - n = gi.Argc(); - if ( !n ) - { - gi.Printf( "Usage: cam [command] [arg 1]...[arg n]\n" ); - return qtrue; - } - - cmd = gi.Argv( 1 ); - if ( Event::GetEvent( cmd ) ) - { - ev = new Event( cmd ); - - for( i = 2; i < n; i++ ) - { - ev->AddToken( gi.Argv( i ) ); - } - - CameraMan.ProcessEvent( ev ); - } - else - { - gi.Printf( "Unknown camera command '%s'.\n", cmd ); - } - - return qtrue; - } - -qboolean G_SoundCmd - ( - gentity_t *ent - ) - - { - Event *ev; - const char *cmd; - int i; - int n; - - n = gi.Argc(); - if ( !n ) - { - gi.Printf( "Usage: snd [command] [arg 1]...[arg n]\n" ); - return qtrue; - } - - cmd = gi.Argv( 1 ); - if ( Event::GetEvent( cmd ) ) - { - ev = new Event( cmd ); - - for( i = 2; i < n; i++ ) - { - ev->AddToken( gi.Argv( i ) ); - } - - SoundMan.ProcessEvent( ev ); - } - else - { - gi.Printf( "Unknown sound command '%s'.\n", cmd ); - } - - return qtrue; - } - -qboolean G_SayCmd - ( - gentity_t *ent - ) - - { - G_Say( ent, false, false ); - - return qtrue; - } - -qboolean G_EventListCmd - ( - gentity_t *ent - ) - - { - const char *mask; - - mask = NULL; - if ( gi.Argc() > 1 ) - { - mask = gi.Argv( 1 ); - } - - //Event::ListCommands( mask ); - - return qtrue; - } - -qboolean G_PendingEventsCmd - ( - gentity_t *ent - ) - - { - const char *mask; - - mask = NULL; - if ( gi.Argc() > 1 ) - { - mask = gi.Argv( 1 ); - } - - //Event::PendingEvents( mask ); - - return qtrue; - } - -qboolean G_EventHelpCmd - ( - gentity_t *ent - ) - - { - const char *mask; - - mask = NULL; - if ( gi.Argc() > 1 ) - { - mask = gi.Argv( 1 ); - } - - //Event::ListDocumentation( mask, false ); - - return qtrue; - } - -qboolean G_DumpEventsCmd - ( - gentity_t *ent - ) - - { - const char *mask; - - mask = NULL; - if ( gi.Argc() > 1 ) - { - mask = gi.Argv( 1 ); - } - - //Event::ListDocumentation( mask, true ); - - return qtrue; - } - -qboolean G_ClassEventsCmd - ( - gentity_t *ent - ) - - { - const char *className; - - className = NULL; - if ( gi.Argc() < 2 ) - { - gi.Printf( "Usage: classevents [className]\n" ); - className = gi.Argv( 1 ); - } - else - { - className = gi.Argv( 1 ); - //ClassEvents( className ); - } - return qtrue; - } - -qboolean G_DumpClassEventsCmd - ( - gentity_t *ent - ) - - { - const char *className; - - className = NULL; - if ( gi.Argc() < 2 ) - { - gi.Printf( "Usage: dumpclassevents [className]\n" ); - className = gi.Argv( 1 ); - } - else - { - className = gi.Argv( 1 ); - //ClassEvents( className, qtrue ); - } - return qtrue; - } - -qboolean G_DumpAllClassesCmd - ( - gentity_t *ent - ) - - { - DumpAllClasses(); - return qtrue; - } - -qboolean G_ClassListCmd - ( - gentity_t *ent - ) - - { - //listAllClasses(); - - return qtrue; - } - -qboolean G_ClassTreeCmd - ( - gentity_t *ent - ) - - { - if ( gi.Argc() > 1 ) - { - //listInheritanceOrder( gi.Argv( 1 ) ); - } - else - { - gi.SendServerCommand( ent - g_entities, "print \"Syntax: classtree [classname].\n\"" ); - } - - return qtrue; - } - -qboolean G_ShowVarCmd - ( - gentity_t *ent - ) +void G_Say(gentity_t *ent, qboolean team, qboolean arg0) { - return qtrue; + int j; + gentity_t *other; + const char *p; + char text[2048]; + + if (gi.Argc() < 2 && !arg0) { + return; + } + + if (!ent->entity) { + // just in case we're not joined yet. + team = false; + } + + if (!DM_FLAG(DF_MODELTEAMS | DF_SKINTEAMS)) { + team = false; + } + + if (team) { + Com_sprintf(text, sizeof(text), "(%s): ", ent->client->pers.netname); + } else { + Com_sprintf(text, sizeof(text), "%s: ", ent->client->pers.netname); + } + + if (arg0) { + strcat(text, gi.Argv(0)); + strcat(text, " "); + strcat(text, gi.Args()); + } else { + p = gi.Args(); + + if (*p == '"') { + p++; + strcat(text, p); + text[strlen(text) - 1] = 0; + } else { + strcat(text, p); + } + } + + // don't let text be too long for malicious reasons + if (strlen(text) > 150) { + text[150] = 0; + } + + strcat(text, "\n"); + + if (dedicated->integer) { + gi.SendServerCommand(0, "print \"%s\"", text); + } + + for (j = 0; j < game.maxclients; j++) { + other = &g_entities[j]; + if (!other->inuse || !other->client || !other->entity) { + continue; + } + + gi.SendServerCommand(0, "print \"%s\"", text); + } } -qboolean G_ScriptCmd( gentity_t *ent ) +qboolean G_CameraCmd(gentity_t *ent) { - if( gi.Argc() > 1 ) - { - const char *script = gi.Argv( 1 ); - int recompile = false; + Event *ev; + const char *cmd; + int i; + int n; - if( gi.Argc() > 2 ) - { - sscanf( gi.Argv( 2 ), "%d", &recompile ); - } + n = gi.Argc(); + if (!n) { + gi.Printf("Usage: cam [command] [arg 1]...[arg n]\n"); + return qtrue; + } - Director.GetScript( script, recompile ); - Director.ExecuteThread( script ); + cmd = gi.Argv(1); + if (Event::Exists(cmd)) { + ev = new Event(cmd); - return qtrue; - } - else - { - gi.Printf( "Usage: script [filename] ([recompile])\n" ); - return qfalse; - } + for (i = 2; i < n; i++) { + ev->AddToken(gi.Argv(i)); + } + + CameraMan.ProcessEvent(ev); + } else { + gi.Printf("Unknown camera command '%s'.\n", cmd); + } + + return qtrue; } -void PrintVariableList - ( - ScriptVariableList * list - ) +qboolean G_SoundCmd(gentity_t *ent) { + Event *ev; + const char *cmd; + int i; + int n; + + n = gi.Argc(); + if (!n) { + gi.Printf("Usage: snd [command] [arg 1]...[arg n]\n"); + return qtrue; + } + + cmd = gi.Argv(1); + if (Event::Exists(cmd)) { + ev = new Event(cmd); + + for (i = 2; i < n; i++) { + ev->AddToken(gi.Argv(i)); + } + + SoundMan.ProcessEvent(ev); + } else { + gi.Printf("Unknown sound command '%s'.\n", cmd); + } + + return qtrue; } -qboolean G_LevelVarsCmd - ( - gentity_t *ent - ) - - { - gi.Printf( "Level Variables\n" ); - PrintVariableList( level.vars ); - - return qtrue; - } - -qboolean G_GameVarsCmd - ( - gentity_t *ent - ) - - { - gi.Printf( "Game Variables\n" ); - PrintVariableList( game.vars ); - - return qtrue; - } - -qboolean G_CompileScript - ( - gentity_t *ent - ) +qboolean G_SayCmd(gentity_t *ent) { - if( gi.Argc() <= 2 ) - { - gi.Printf( "Usage: compilescript [filename] [output file]\n" ); - return qfalse; - } + G_Say(ent, false, false); - CompileAssemble( gi.Argv( 1 ), gi.Argv( 2 ) ); - return qtrue; + return qtrue; } -qboolean G_AddBotCommand - ( - gentity_t *ent - ) +qboolean G_EventListCmd(gentity_t *ent) { - unsigned int numbots; - unsigned int totalnumbots; - int clientNum = -1; + const char *mask; - if( gi.Argc() <= 1 ) - { - gi.Printf( "Usage: addbot [numbots] [optional botname]\n" ); - return qfalse; - } + mask = NULL; + if (gi.Argc() > 1) { + mask = gi.Argv(1); + } - numbots = atoi( gi.Argv( 1 ) ); - if(numbots > sv_maxbots->integer) - { - gi.Printf( "addbot must be between 1-%d\n", sv_maxbots->integer ); - return qfalse; - } + Event::ListCommands( mask ); - totalnumbots = Q_min(numbots + sv_numbots->integer, sv_maxbots->integer); - - gi.cvar_set("sv_numbots", va("%d", totalnumbots)); - return qtrue; + return qtrue; } -qboolean G_RemoveBotCommand - ( - gentity_t *ent - ) +qboolean G_PendingEventsCmd(gentity_t *ent) +{ + const char *mask; + + mask = NULL; + if (gi.Argc() > 1) { + mask = gi.Argv(1); + } + + Event::PendingEvents( mask ); + + return qtrue; +} + +qboolean G_EventHelpCmd(gentity_t *ent) +{ + const char *mask; + + mask = NULL; + if (gi.Argc() > 1) { + mask = gi.Argv(1); + } + + Event::ListDocumentation( mask, false ); + + return qtrue; +} + +qboolean G_DumpEventsCmd(gentity_t *ent) +{ + const char *mask; + + mask = NULL; + if (gi.Argc() > 1) { + mask = gi.Argv(1); + } + + Event::ListDocumentation( mask, true ); + + return qtrue; +} + +qboolean G_ClassEventsCmd(gentity_t *ent) +{ + const char *className; + + className = NULL; + if (gi.Argc() < 2) { + gi.Printf("Usage: classevents [className]\n"); + className = gi.Argv(1); + } else { + className = gi.Argv(1); + ClassEvents( className, qfalse ); + } + return qtrue; +} + +qboolean G_DumpClassEventsCmd(gentity_t *ent) +{ + const char *className; + + className = NULL; + if (gi.Argc() < 2) { + gi.Printf("Usage: dumpclassevents [className]\n"); + className = gi.Argv(1); + } else { + className = gi.Argv(1); + ClassEvents( className, qtrue ); + } + return qtrue; +} + +qboolean G_DumpAllClassesCmd(gentity_t *ent) +{ + DumpAllClasses(); + return qtrue; +} + +qboolean G_ClassListCmd(gentity_t *ent) +{ + listAllClasses(); + + return qtrue; +} + +qboolean G_ClassTreeCmd(gentity_t *ent) +{ + if (gi.Argc() > 1) { + listInheritanceOrder( gi.Argv( 1 ) ); + } else { + gi.SendServerCommand(ent - g_entities, "print \"Syntax: classtree [classname].\n\""); + } + + return qtrue; +} + +qboolean G_ShowVarCmd(gentity_t *ent) +{ + return qtrue; +} + +void PrintVariableList(ScriptVariableList *list) {} + +qboolean G_LevelVarsCmd(gentity_t *ent) +{ + gi.Printf("Level Variables\n"); + PrintVariableList(level.vars); + + return qtrue; +} + +qboolean G_GameVarsCmd(gentity_t *ent) +{ + gi.Printf("Game Variables\n"); + PrintVariableList(game.vars); + + return qtrue; +} + +qboolean G_ScriptCmd(gentity_t *ent) +{ + const char *script; + const char *name; + Entity *scriptEnt; + ConsoleEvent *event; + int numArgs; + int i; + + numArgs = gi.Argc(); + + if (numArgs <= 1) { + gi.Printf("Usage: script [filename]\n"); + return qtrue; + } + + if (!sv_cheats->integer) { + gi.Printf("command not available\n"); + return qtrue; + } + + script = gi.Argv(1); + if (*script == '*') { + scriptEnt = static_cast(G_GetEntity(atoi(script + 1))); + } else { + scriptEnt = static_cast(G_FindTarget(0, script)); + } + + if (!scriptEnt) { + gi.Printf("Could not find entity %s\n", script); + return qtrue; + } + + name = gi.Argv(2); + if (!Event::Exists(name)) { + gi.Printf("Unknown command '%s'.\n", name); + return qtrue; + } + + event = new ConsoleEvent(name); + event->SetConsoleEdict(ent); + + for (i = 3; i < numArgs; i++) { + event->AddToken(gi.Argv(i)); + } + + return scriptEnt->ProcessEvent(event); +} + +qboolean G_ReloadMap(gentity_t* ent) +{ + char name[256]; + + Com_sprintf(name, sizeof(name), "gamemap \"%s\"\n", level.mapname.c_str()); + gi.SendConsoleCommand(name); + + return qtrue; +} + +qboolean G_CompileScript(gentity_t *ent) +{ + if (gi.Argc() <= 2) { + gi.Printf("Usage: compilescript [filename] [output file]\n"); + return qfalse; + } + + CompileAssemble(gi.Argv(1), gi.Argv(2)); + return qtrue; +} + +qboolean G_AddBotCommand(gentity_t *ent) +{ + unsigned int numbots; + unsigned int totalnumbots; + int clientNum = -1; + + if (gi.Argc() <= 1) { + gi.Printf("Usage: addbot [numbots] [optional botname]\n"); + return qfalse; + } + + numbots = atoi(gi.Argv(1)); + + if (numbots > game.maxclients) { + gi.Printf("addbot must be between 1-%d\n", game.maxclients); + return qfalse; + } + + totalnumbots = Q_min(numbots + sv_numbots->integer, game.maxclients); + + gi.cvar_set("sv_numbots", va("%d", totalnumbots)); + return qtrue; +} + +qboolean G_RemoveBotCommand(gentity_t *ent) { unsigned int numbots; unsigned int totalnumbots; - if( gi.Argc() <= 1 ) - { - gi.Printf( "Usage: removebot [numbots]\n" ); - return qfalse; + if (gi.Argc() <= 1) { + gi.Printf("Usage: removebot [numbots]\n"); + return qfalse; } - numbots = atoi(gi.Argv(1)); - totalnumbots = sv_numbots->integer - Q_min(numbots, sv_numbots->integer); + numbots = atoi(gi.Argv(1)); + totalnumbots = sv_numbots->integer - Q_min(numbots, sv_numbots->integer); gi.cvar_set("sv_numbots", va("%d", totalnumbots)); - return qtrue; + return qtrue; } #ifdef _DEBUG -qboolean G_BotCommand - ( - gentity_t *ent - ) +qboolean G_BotCommand(gentity_t *ent) { - const char *command; - PlayerBot *bot; + const char *command; + BotController *bot; - if( !G_GetFirstBot() || !G_GetFirstBot()->entity ) - { - gi.Printf( "No bot spawned.\n" ); - return qfalse; - } + if (botManager.getControllerManager().getControllers().NumObjects() < 1) { + gi.Printf("No bot spawned.\n"); + return qfalse; + } - if( gi.Argc() <= 1 ) - { - gi.Printf( "Usage: bot [cmd] (arg1) (arg2) (arg3) ...\n" ); - return qfalse; - } + if (gi.Argc() <= 1) { + gi.Printf("Usage: bot [cmd] (arg1) (arg2) (arg3) ...\n"); + return qfalse; + } - bot = ( PlayerBot * )G_GetFirstBot()->entity; + bot = botManager.getControllerManager().getControllers().ObjectAt(1); - command = gi.Argv( 1 ); + command = gi.Argv(1); - if( !Q_stricmp( command, "movehere" ) ) - { - bot->MoveTo( ent->entity->origin ); - } - else if( !Q_stricmp( command, "moveherenear" ) ) - { - float rad = 256.0f; + if (!Q_stricmp(command, "movehere")) { + bot->GetMovement().MoveTo(ent->entity->origin); + } else if (!Q_stricmp(command, "moveherenear")) { + float rad = 256.0f; - if( gi.Argc() > 2 ) - { - rad = atof( gi.Argv( 2 ) ); - } + if (gi.Argc() > 2) { + rad = atof(gi.Argv(2)); + } - bot->MoveNear( ent->entity->origin, rad ); - } - else if( !Q_stricmp( command, "avoidhere" ) ) - { - float rad = 256.0f; + bot->GetMovement().MoveNear(ent->entity->origin, rad); + } else if (!Q_stricmp(command, "avoidhere")) { + float rad = 256.0f; - if( gi.Argc() > 2 ) - { - rad = atof( gi.Argv( 2 ) ); - } + if (gi.Argc() > 2) { + rad = atof(gi.Argv(2)); + } - bot->AvoidPath( ent->entity->origin, rad ); - } - else if( !Q_stricmp( command, "telehere" ) ) - { - bot->setOrigin( ent->s.origin ); - } + bot->GetMovement().AvoidPath(ent->entity->origin, rad); + } else if (!Q_stricmp(command, "telehere")) { + bot->getControlledEntity()->setOrigin(ent->s.origin); + } - return qtrue; + return qtrue; } #endif diff --git a/code/fgame/gamecmds.h b/code/fgame/gamecmds.h index dd5bffbb..a45ebc73 100644 --- a/code/fgame/gamecmds.h +++ b/code/fgame/gamecmds.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,38 +22,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // gamecmds.h: Game Commands. -#ifndef __GAMECMDS_H__ -#define __GAMECMDS_H__ +#pragma once #include "g_local.h" -void G_InitConsoleCommands( void ); +void G_InitConsoleCommands(void); -qboolean G_ProcessClientCommand( gentity_t *ent ); +qboolean G_ProcessClientCommand(gentity_t *ent); -void G_Say( gentity_t *ent, qboolean team, qboolean arg0 ); -qboolean G_CameraCmd( gentity_t *ent ); -qboolean G_SoundCmd( gentity_t *ent ); -qboolean G_SayCmd( gentity_t *ent ); -qboolean G_EventListCmd( gentity_t *ent ); -qboolean G_PendingEventsCmd( gentity_t *ent ); -qboolean G_EventHelpCmd( gentity_t *ent ); -qboolean G_DumpEventsCmd( gentity_t *ent ); -qboolean G_ClassEventsCmd( gentity_t *ent ); -qboolean G_DumpClassEventsCmd( gentity_t *ent ); -qboolean G_DumpAllClassesCmd( gentity_t *ent ); -qboolean G_ClassListCmd( gentity_t *ent ); -qboolean G_ClassTreeCmd( gentity_t *ent ); -qboolean G_ShowVarCmd( gentity_t *ent ); -qboolean G_RestartCmd( gentity_t *ent ); -qboolean G_ScriptCmd( gentity_t *ent ); -qboolean G_LevelVarsCmd( gentity_t *ent ); -qboolean G_GameVarsCmd( gentity_t *ent ); -qboolean G_CompileScript( gentity_t *ent ); -qboolean G_AddBotCommand( gentity_t *ent ); -qboolean G_RemoveBotCommand( gentity_t *ent ); +//=============== +// Added in OPM +void G_CreateMaster(const char* prefix, class Listener* master); +Listener* G_FindMaster(const char* command); +//=============== + +void G_Say(gentity_t *ent, qboolean team, qboolean arg0); +qboolean G_CameraCmd(gentity_t *ent); +qboolean G_SoundCmd(gentity_t *ent); +qboolean G_SayCmd(gentity_t *ent); +qboolean G_EventListCmd(gentity_t *ent); +qboolean G_PendingEventsCmd(gentity_t *ent); +qboolean G_EventHelpCmd(gentity_t *ent); +qboolean G_DumpEventsCmd(gentity_t *ent); +qboolean G_ClassEventsCmd(gentity_t *ent); +qboolean G_DumpClassEventsCmd(gentity_t *ent); +qboolean G_DumpAllClassesCmd(gentity_t *ent); +qboolean G_ClassListCmd(gentity_t *ent); +qboolean G_ClassTreeCmd(gentity_t *ent); +qboolean G_ShowVarCmd(gentity_t *ent); +qboolean G_RestartCmd(gentity_t *ent); +qboolean G_LevelVarsCmd(gentity_t *ent); +qboolean G_GameVarsCmd(gentity_t* ent); +qboolean G_ScriptCmd(gentity_t* ent); +qboolean G_ReloadMap(gentity_t* ent); +qboolean G_CompileScript(gentity_t *ent); +qboolean G_AddBotCommand(gentity_t *ent); +qboolean G_RemoveBotCommand(gentity_t *ent); #ifdef _DEBUG -qboolean G_BotCommand( gentity_t *ent ); +qboolean G_BotCommand(gentity_t *ent); #endif - -#endif /* !__GAMECMDS_H__ */ \ No newline at end of file diff --git a/code/fgame/gamecvars.cpp b/code/fgame/gamecvars.cpp index 19e5ab49..2ce8fe5c 100644 --- a/code/fgame/gamecvars.cpp +++ b/code/fgame/gamecvars.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "gamecvars.h" cvar_t *developer; -cvar_t *sv_specialgame; cvar_t *deathmatch; cvar_t *dmflags; @@ -59,7 +58,7 @@ cvar_t *sv_rollspeed; cvar_t *sv_rollangle; cvar_t *sv_cheats; cvar_t *sv_showbboxes; -cvar_t *sv_showbtags; +cvar_t *sv_showtags; cvar_t *sv_testloc_num; cvar_t *sv_testloc_secondary; @@ -258,19 +257,52 @@ cvar_t *g_no_seasick; cvar_t *g_aistats; -cvar_t* g_obituarylocation; +// +// Added in OPM +// + +cvar_t *sv_netoptimize; + +cvar_t *g_obituarylocation; cvar_t *sv_scriptfiles; +// The maximum number of allocated bot clients cvar_t *sv_maxbots; +// The number of bots that should be spawned cvar_t *sv_numbots; +// The minimum number of players that should be present in-game. +// If the number of real players is below this number, +// the game will automatically add bots to fill the gap +cvar_t *sv_minPlayers; +// Whether or not the bots use a shared player slots +// NOTE: Setting this cvar is not recommended +// because when a client connects and the slot is used by a bot +// the bot will be relocated to a free entity slot +cvar_t *sv_sharedbots; + cvar_t *g_rankedserver; cvar_t *g_spectatefollow_firstperson; +cvar_t *cl_running; + +// Whether or instant messages are allowed +cvar_t *g_instamsg_allowed; +// Minimum delay, in milliseconds, between instant messages +cvar_t *g_instamsg_minDelay; +// Whether or not text messages are allowed +cvar_t *g_textmsg_allowed; +// Minimum delay, in milliseconds, between messages +cvar_t *g_textmsg_minDelay; + +// Whether or not to prevent teams from being unbalanced +cvar_t *g_teambalance; + void CVAR_Init(void) { + int i; + developer = gi.Cvar_Get("developer", "0", 0); - sv_specialgame = gi.Cvar_Get("sv_specialgame", "0", CVAR_LATCH | CVAR_SERVERINFO); precache = gi.Cvar_Get("sv_precache", "1", 0); @@ -309,7 +341,7 @@ void CVAR_Init(void) sv_traceinfo = gi.Cvar_Get("sv_traceinfo", "0", 0); sv_drawtrace = gi.Cvar_Get("sv_drawtrace", "0", 0); sv_showbboxes = gi.Cvar_Get("sv_showbboxes", "0", 0); - sv_showbtags = gi.Cvar_Get("sv_showtags", "0", 0); + sv_showtags = gi.Cvar_Get("sv_showtags", "0", 0); sv_testloc_num = gi.Cvar_Get("sv_testloc_num", "0", 0); sv_testloc_secondary = gi.Cvar_Get("sv_testloc_secondary", "0", 0); @@ -331,7 +363,7 @@ void CVAR_Init(void) sv_waterspeed = gi.Cvar_Get("sv_waterspeed", "400", 0); sv_cheats = gi.Cvar_Get("cheats", "0", CVAR_USERINFO | CVAR_SERVERINFO | CVAR_LATCH); - sv_fps = gi.Cvar_Get("sv_fps", "20", CVAR_SAVEGAME); + sv_fps = gi.Cvar_Get("sv_fps", "20", CVAR_SAVEGAME); sv_cinematic = gi.Cvar_Get("sv_cinematic", "0", CVAR_ROM); sv_maplist = gi.Cvar_Get("sv_maplist", "", CVAR_ARCHIVE | CVAR_SERVERINFO); @@ -347,8 +379,8 @@ void CVAR_Init(void) sv_sprinttime_dm = gi.Cvar_Get("sv_sprinttime_dm", "5.0", 0); sv_sprintmult_dm = gi.Cvar_Get("sv_sprintmult_dm", "1.20", 0); - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { - sv_sprinton = gi.Cvar_Get("sv_sprinton", "1", 0); + if (g_target_game >= target_game_e::TG_MOHTA) { + sv_sprinton = gi.Cvar_Get("sv_sprinton", "1", 0); } else { // mohaa doesn't have sprint support sv_sprinton = gi.Cvar_Get("sv_sprinton", "0", 0); @@ -358,11 +390,17 @@ void CVAR_Init(void) gi.cvar_set("sv_runspeed", "250"); } - sv_invulnerabletime = gi.Cvar_Get("sv_invulnerabletime", "3.0", CVAR_ARCHIVE | CVAR_SERVERINFO); - sv_team_spawn_interval = gi.Cvar_Get("sv_team_spawn_interval", "15", CVAR_ARCHIVE | CVAR_SERVERINFO); + if (g_target_game >= target_game_e::TG_MOHTA) { + sv_invulnerabletime = gi.Cvar_Get("sv_invulnerabletime", "3.0", CVAR_ARCHIVE | CVAR_SERVERINFO); + sv_team_spawn_interval = gi.Cvar_Get("sv_team_spawn_interval", "15", CVAR_ARCHIVE | CVAR_SERVERINFO); + } else { + sv_invulnerabletime = gi.Cvar_Get("sv_invulnerabletime", "0", CVAR_ARCHIVE | CVAR_SERVERINFO); + sv_team_spawn_interval = gi.Cvar_Get("sv_team_spawn_interval", "0", CVAR_ARCHIVE | CVAR_SERVERINFO); + } g_showmem = gi.Cvar_Get("g_showmem", "0", 0); g_timeents = gi.Cvar_Get("g_timeents", "0", 0); + g_timescripts = gi.Cvar_Get("g_timescripts", "0", 0); g_showaxis = gi.Cvar_Get("g_showaxis", "0", 0); g_showplayerstate = gi.Cvar_Get("g_showplayerstate", "0", 0); g_showplayeranim = gi.Cvar_Get("g_showplayeranim", "0", 0); @@ -426,8 +464,15 @@ void CVAR_Init(void) g_teamdamage = gi.Cvar_Get("g_teamdamage", "0", 0); g_healthdrop = gi.Cvar_Get("g_healthdrop", "1", 0); - g_healrate = gi.Cvar_Get("g_healrate", "10", 0); - g_allowvote = gi.Cvar_Get("g_allowvote", "1", 0); + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + g_healrate = gi.Cvar_Get("g_healrate", "10", 0); + } else { + // + // By default, no healrate on 1.11 and below + // + g_healrate = gi.Cvar_Get("g_healrate", "0", 0); + } + g_allowvote = gi.Cvar_Get("g_allowvote", "1", CVAR_SERVERINFO); g_maprotation_filter = gi.Cvar_Get("g_maprotation_filter", "ffa", 0); g_warmup = gi.Cvar_Get("g_warmup", "20", CVAR_ARCHIVE); g_doWarmup = gi.Cvar_Get("g_doWarmup", "1", 0); @@ -445,11 +490,14 @@ void CVAR_Init(void) g_teamkillwarn = gi.Cvar_Get("g_teamkillwarn", "3", CVAR_ARCHIVE); g_teamkillkick = gi.Cvar_Get("g_teamkillkick", "5", CVAR_ARCHIVE); g_teamswitchdelay = gi.Cvar_Get("g_teamswitchdelay", "15", CVAR_ARCHIVE); - if (developer->integer) { - g_shownpc = gi.Cvar_Get("g_shownpc", "1", 0); - } else { - g_shownpc = gi.Cvar_Get("g_shownpc", "0", 0); - } + g_shownpc = gi.Cvar_Get("g_shownpc", "0", 0); + + // Removed in OPM + //if (developer->integer) { + // g_shownpc = gi.Cvar_Get("g_shownpc", "1", 0); + //} else { + // g_shownpc = gi.Cvar_Get("g_shownpc", "0", 0); + //} s_debugmusic = gi.Cvar_Get("s_debugmusic", "0", 0); @@ -459,7 +507,7 @@ void CVAR_Init(void) gi.cvar_set("deathmatch", "1"); } - if (g_protocol >= PROTOCOL_MOHTA_MIN) { + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { if (gi.Cvar_Get("com_target_game", "", 0)->integer == target_game_e::TG_MOHTT) { // Set the server type to mohaab gi.cvar_set("g_servertype", va("%d", target_game_e::TG_MOHTT)); @@ -555,16 +603,12 @@ void CVAR_Init(void) g_voiceChatTime = gi.Cvar_Get("g_voiceChatTime", "2.5", 0); g_textChatTime = gi.Cvar_Get("g_textChatTime", "1", 0); g_debugsmoke = gi.Cvar_Get("g_debugsmoke", "0", CVAR_CHEAT); - gi.Cvar_Get("g_obj_alliedtext1", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_alliedtext2", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_alliedtext3", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_alliedtext4", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_alliedtext5", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_axistext1", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_axistext2", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_axistext3", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_axistext4", "", CVAR_SERVERINFO); - gi.Cvar_Get("g_obj_axistext5", "", CVAR_SERVERINFO); + + for (i = 1; i <= 5; i++) { + gi.Cvar_Get(va("g_obj_alliedtext%d", i), "", CVAR_SERVERINFO); + gi.Cvar_Get(va("g_obj_axistext%d", i), "", CVAR_SERVERINFO); + } + gi.Cvar_Get("g_scoreboardpic", "", CVAR_SERVERINFO); gi.Cvar_Get("g_scoreboardpicover", "", CVAR_SERVERINFO); @@ -589,16 +633,30 @@ void CVAR_Init(void) g_rifles_for_sweepers = gi.Cvar_Get("g_rifles_for_sweepers", "0", 0); g_no_seasick = gi.Cvar_Get("g_no_seasick", "0", 0); - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { - g_obituarylocation = gi.Cvar_Get("g_obituarylocation", "0", 0); + // + // Added in OPM + // Clear the text objectives and the scoreboard pic + // + for (i = 1; i <= 5; i++) { + gi.cvar_set(va("g_obj_alliedtext%d", i), ""); + gi.cvar_set(va("g_obj_axistext%d", i), ""); + } + gi.cvar_set("g_scoreboardpic", ""); + + sv_netoptimize = gi.Cvar_Get("sv_netoptimize", "0", 0); + + if (g_target_game >= target_game_e::TG_MOHTA) { + g_obituarylocation = gi.Cvar_Get("g_obituarylocation", "0", 0); } else { // Defaults to 1 on vanilla mohaa - g_obituarylocation = gi.Cvar_Get("g_obituarylocation", "1", 0); + g_obituarylocation = gi.Cvar_Get("g_obituarylocation", "1", 0); } sv_scriptfiles = gi.Cvar_Get("sv_scriptfiles", "0", 0); sv_maxbots = gi.Cvar_Get("sv_maxbots", "0", CVAR_LATCH); - sv_numbots = gi.Cvar_Get("sv_numbots", "0", CVAR_LATCH); + sv_sharedbots = gi.Cvar_Get("sv_sharedbots", "0", CVAR_LATCH); + sv_numbots = gi.Cvar_Get("sv_numbots", "0", 0); + sv_minPlayers = gi.Cvar_Get("sv_minPlayers", "0", 0); g_rankedserver = gi.Cvar_Get("g_rankedserver", "0", 0); g_spectatefollow_firstperson = gi.Cvar_Get("g_spectatefollow_firstperson", "0", 0); @@ -611,8 +669,12 @@ void CVAR_Init(void) gi.Printf("sv_maxbots reached max clients, lowering the value to %u\n", lowered); } - if (sv_numbots->integer > sv_maxbots->integer) { - gi.Printf("numbots overflow, setting to %d\n", sv_maxbots->integer); - gi.cvar_set("sv_numbots", sv_maxbots->string); - } + g_instamsg_allowed = gi.Cvar_Get("g_instamsg_allowed", "1", 0); + g_instamsg_minDelay = gi.Cvar_Get("g_instamsg_minDelay", "1000", 0); + g_textmsg_allowed = gi.Cvar_Get("g_textmsg_allowed", "1", 0); + g_textmsg_minDelay = gi.Cvar_Get("g_textmsg_minDelay", "1000", 0); + + g_teambalance = gi.Cvar_Get("g_teambalance", "0", 0); + + cl_running = gi.Cvar_Get("cl_running", "", 0); } diff --git a/code/fgame/gamecvars.h b/code/fgame/gamecvars.h index f77be121..1f03a1dd 100644 --- a/code/fgame/gamecvars.h +++ b/code/fgame/gamecvars.h @@ -31,7 +31,6 @@ extern "C" { #endif extern cvar_t *developer; -extern cvar_t *sv_specialgame; extern cvar_t *deathmatch; extern cvar_t *dmflags; @@ -64,7 +63,7 @@ extern cvar_t *sv_rollspeed; extern cvar_t *sv_rollangle; extern cvar_t *sv_cheats; extern cvar_t *sv_showbboxes; -extern cvar_t *sv_showbtags; +extern cvar_t *sv_showtags; extern cvar_t *sv_testloc_num; extern cvar_t *sv_testloc_secondary; @@ -263,15 +262,28 @@ extern cvar_t *g_no_seasick; extern cvar_t *g_aistats; -extern cvar_t* g_obituarylocation; +extern cvar_t *sv_netoptimize; + +extern cvar_t *g_obituarylocation; extern cvar_t *sv_scriptfiles; extern cvar_t *sv_maxbots; -extern cvar_t * sv_numbots; +extern cvar_t *sv_numbots; +extern cvar_t *sv_minPlayers; +extern cvar_t *sv_sharedbots; extern cvar_t *g_rankedserver; extern cvar_t *g_spectatefollow_firstperson; +extern cvar_t *cl_running; + +extern cvar_t *g_instamsg_allowed; +extern cvar_t *g_instamsg_minDelay; +extern cvar_t *g_textmsg_allowed; +extern cvar_t *g_textmsg_minDelay; + +extern cvar_t *g_teambalance; + void CVAR_Init(void); #ifdef __cplusplus diff --git a/code/fgame/gamescript.cpp b/code/fgame/gamescript.cpp index e915e8ba..fe5999c0 100644 --- a/code/fgame/gamescript.cpp +++ b/code/fgame/gamescript.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -33,436 +33,457 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static unsigned char *current_progBuffer = NULL; -str& AbstractScript::Filename( void ) +str& AbstractScript::Filename(void) { - return Director.GetString( m_Filename ); + return Director.GetString(m_Filename); } -const_str AbstractScript::ConstFilename( void ) +const_str AbstractScript::ConstFilename(void) { - return m_Filename; + return m_Filename; } -bool AbstractScript::GetSourceAt( size_t sourcePos, str *sourceLine, int &column, int &line ) +bool AbstractScript::GetSourceAt(size_t sourcePos, str *sourceLine, int& column, int& line) { - if( !m_SourceBuffer || sourcePos >= m_SourceLength ) { - return false; - } + size_t posLine; + size_t i; + size_t start; + char *p; + char old_token; + sourceinfo_t *minCachedInfo = NULL; - line = 1; - column = 0; - int posLine = 0; + if (!m_SourceBuffer || sourcePos >= m_SourceLength) { + return false; + } - char *p = m_SourceBuffer; - char old_token; + line = 1; + column = 0; + posLine = 0; + start = 0; - for( int i = 0; i < sourcePos; i++, p++ ) - { - column++; + p = m_SourceBuffer; - if( *p == '\n' ) - { - line++; - column = 0; - posLine = i + 1; - } - else if( *p == '\0' ) - { - break; - } - } + if (sourcePos > 128) { + // Start caching above certain values - while( *p != '\0' && *p != '\n' ) - { - p++; - } + for (i = 0; i < ARRAY_LEN(cachedInfo); i++) { + sourceinfo_t *info = &cachedInfo[i]; - old_token = *p; - *p = '\0'; + if (info->line && sourcePos > info->sourcePos + && (!minCachedInfo || info->sourcePos > minCachedInfo->sourcePos)) { + minCachedInfo = info; + } + } - if (sourceLine) { - *sourceLine = (m_SourceBuffer + posLine); - } + if (minCachedInfo) { + start = minCachedInfo->sourcePos; + line = minCachedInfo->line; + column = minCachedInfo->column; + posLine = minCachedInfo->startLinePos; + } + } - *p = old_token; + for (i = start; i < sourcePos; i++) { + p = m_SourceBuffer + i; + column++; - return true; + if (*p == '\n') { + line++; + column = 0; + if (i + 1 != sourcePos) { + posLine = i + 1; + } + } else if (*p == '\0') { + break; + } + } + + while (*p != '\0' && (*p != '\r' && *p != '\n')) { + p++; + } + + old_token = *p; + *p = '\0'; + + if (sourceLine) { + *sourceLine = (m_SourceBuffer + posLine); + } + + *p = old_token; + + cachedInfo[cachedInfoIndex].sourcePos = sourcePos; + cachedInfo[cachedInfoIndex].line = line; + cachedInfo[cachedInfoIndex].column = column; + cachedInfo[cachedInfoIndex].startLinePos = posLine; + cachedInfoIndex = (cachedInfoIndex + 1) % ARRAY_LEN(cachedInfo); + + return true; } -void AbstractScript::PrintSourcePos( sourceinfo_t *sourcePos, bool dev ) +bool AbstractScript::GetSourceAt(const unsigned char *sourcePos, str *sourceLine, int& column, int& line) { - int line; - int column; - str sourceLine; + const sourceinfo_t *codePos = m_ProgToSource->findKeyValue(sourcePos); - if( GetSourceAt( sourcePos->sourcePos, &sourceLine, column, line ) ) - { - PrintSourcePos( sourceLine, column, line, dev ); - } - else - { - glbs.DPrintf( "file '%s', source pos %d line %d column %d:\n", Filename().c_str(), sourcePos->sourcePos, sourcePos->line, sourcePos->column ); - } + if (!codePos) { + return false; + } + + return GetSourceAt(codePos->sourcePos, sourceLine, column, line); } -void AbstractScript::PrintSourcePos( size_t sourcePos, bool dev ) +void AbstractScript::PrintSourcePos(sourceinfo_t *sourcePos, bool dev) { - int line; - int column; - str sourceLine; + int line; + int column; + str sourceLine; - if( GetSourceAt( sourcePos, &sourceLine, column, line ) ) - { - PrintSourcePos( sourceLine, column, line, dev ); - } - else - { - glbs.DPrintf( "file '%s', source pos %d:\n", Filename().c_str(), sourcePos ); - } + if (GetSourceAt(sourcePos->sourcePos, &sourceLine, column, line)) { + PrintSourcePos(sourceLine, column, line, dev); + } else { + gi.DPrintf( + "file '%s', source pos %d line %d column %d:\n", + Filename().c_str(), + sourcePos->sourcePos, + sourcePos->line, + sourcePos->column + ); + } } -void AbstractScript::PrintSourcePos( unsigned char *m_pCodePos, bool dev ) +void AbstractScript::PrintSourcePos(size_t sourcePos, bool dev) { - if( !m_ProgToSource ) - { - return; - } + int line; + int column; + str sourceLine; - sourceinfo_t *codePos = m_ProgToSource->findKeyValue( m_pCodePos ); - - if( !codePos ) { - return; - } - - PrintSourcePos( codePos, dev ); + if (GetSourceAt(sourcePos, &sourceLine, column, line)) { + PrintSourcePos(sourceLine, column, line, dev); + } else { + gi.DPrintf("file '%s', source pos %d:\n", Filename().c_str(), sourcePos); + } } -void AbstractScript::PrintSourcePos( str sourceLine, int column, int line, bool dev ) +void AbstractScript::PrintSourcePos(unsigned char *m_pCodePos, bool dev) { - int i; - str markerLine = ""; + if (!m_ProgToSource) { + return; + } - for( i = 0; i < column; i++ ) - { - markerLine.append( sourceLine[ i ] ); - } + sourceinfo_t *codePos = m_ProgToSource->findKeyValue(m_pCodePos); - markerLine.append( "^" ); + if (!codePos) { + return; + } - glbs.DPrintf( "(%s, %d):\n%s\n%s\n", Filename().c_str(), line, sourceLine.c_str(), markerLine.c_str() ); + PrintSourcePos(codePos, dev); +} + +void AbstractScript::PrintSourcePos(str sourceLine, int column, int line, bool dev) +{ + int i; + str markerLine = ""; + + for (i = 0; i < column; i++) { + markerLine.append(sourceLine[i]); + } + + markerLine.append("^"); + + gi.DPrintf("(%s, %d):\n%s\n%s\n", Filename().c_str(), line, sourceLine.c_str(), markerLine.c_str()); } AbstractScript::AbstractScript() { - m_ProgToSource = NULL; - m_SourceBuffer = NULL; - m_SourceLength = 0; + m_ProgToSource = NULL; + m_SourceBuffer = NULL; + m_SourceLength = 0; + cachedInfoIndex = 0; } StateScript::StateScript() { - m_Parent = NULL; + m_Parent = NULL; } template<> -void con_set< const_str, script_label_t >::Entry::Archive( Archiver& arc ) +void con_set::Entry::Archive(Archiver& arc) { - unsigned int offset; + unsigned int offset; - Director.ArchiveString( arc, key ); + Director.ArchiveString(arc, key); - if( arc.Saving() ) - { - offset = value.codepos - current_progBuffer; - arc.ArchiveUnsigned( &offset ); - } - else - { - arc.ArchiveUnsigned( &offset ); - value.codepos = current_progBuffer + offset; - value.key = key; - } + if (arc.Saving()) { + offset = value.codepos - current_progBuffer; + arc.ArchiveUnsigned(&offset); + } else { + arc.ArchiveUnsigned(&offset); + value.codepos = current_progBuffer + offset; + value.key = key; + } - arc.ArchiveBool( &value.isprivate ); + arc.ArchiveBool(&value.isprivate); } -void StateScript::Archive( Archiver& arc ) +void StateScript::Archive(Archiver& arc) { - label_list.Archive( arc ); + label_list.Archive(arc); } -bool StateScript::AddLabel( const_str label, unsigned char *pos, bool private_section ) +bool StateScript::AddLabel(const_str label, unsigned char *pos, bool private_section) { - if( label_list.findKeyValue( label ) ) - { - return false; - } + if (label_list.findKeyValue(label)) { + return false; + } - script_label_t &s = label_list.addKeyValue( label ); + script_label_t& s = label_list.addKeyValue(label); - s.codepos = pos; - s.key = label; - s.isprivate = private_section; + s.codepos = pos; + s.key = label; + s.isprivate = private_section; - if( !label_list.findKeyValue(STRING_NULL) ) - { - label_list.addKeyValue(STRING_NULL) = s; - } + if (!label_list.findKeyValue(STRING_NULL)) { + label_list.addKeyValue(STRING_NULL) = s; + } - return true; + return true; } -bool StateScript::AddLabel( str label, unsigned char *pos, bool private_section ) +bool StateScript::AddLabel(str label, unsigned char *pos, bool private_section) { - return AddLabel( Director.AddString( label ), pos, private_section ); + return AddLabel(Director.AddString(label), pos, private_section); } -unsigned char *StateScript::FindLabel( const_str label ) +unsigned char *StateScript::FindLabel(const_str label) { - script_label_t *s; - ScriptClass *scriptClass; - GameScript *script; + script_label_t *s; + ScriptClass *scriptClass; + GameScript *script; - s = label_list.findKeyValue( label ); + s = label_list.findKeyValue(label); - if( s ) - { - // check if the label is a private function - if( s->isprivate ) - { - scriptClass = Director.CurrentScriptClass(); + if (s) { + // check if the label is a private function + if (s->isprivate) { + scriptClass = Director.CurrentScriptClass(); - if( scriptClass ) - { - script = scriptClass->GetScript(); + if (scriptClass) { + script = scriptClass->GetScript(); - // now check if the label's statescript matches this statescript - if( ( &script->m_State ) != this ) - { - ScriptError( "Cannot call a private function." ); - return NULL; - } - } - } + // now check if the label's statescript matches this statescript + if ((&script->m_State) != this) { + ScriptError("Cannot call a private function."); + return NULL; + } + } + } - return s->codepos; - } - else - { - return NULL; - } + return s->codepos; + } else { + return NULL; + } } -unsigned char *StateScript::FindLabel( str label ) +unsigned char *StateScript::FindLabel(str label) { - return FindLabel( Director.AddString( label ) ); + return FindLabel(Director.AddString(label)); } -const_str StateScript::NearestLabel( unsigned char *pos ) +const_str StateScript::NearestLabel(unsigned char *pos) { - unsigned int offset = pos - m_Parent->m_ProgBuffer; - unsigned int bestOfs = 0; - const_str label = STRING_NULL; - con_set_enum< const_str, script_label_t > en = label_list; - con_set_enum< const_str, script_label_t >::Entry* entry; + unsigned int offset = pos - m_Parent->m_ProgBuffer; + unsigned int bestOfs = 0; + const_str label = STRING_NULL; + con_set_enum en = label_list; + con_set_enum::Entry *entry; for (entry = en.NextElement(); entry; entry = en.NextElement()) { const script_label_t& l = entry->value; - if ((l.codepos - m_Parent->m_ProgBuffer) >= bestOfs) - { + if ((l.codepos - m_Parent->m_ProgBuffer) >= bestOfs) { bestOfs = l.codepos - m_Parent->m_ProgBuffer; - if (bestOfs > offset) - { + if (bestOfs > offset) { break; } label = l.key; } - } + } - return label; + return label; } GameScript::GameScript() { - m_Filename = STRING_NULL; - successCompile = false; + m_Filename = STRING_NULL; + successCompile = false; - m_ProgBuffer = NULL; - m_ProgLength = 0; - m_bPrecompiled = false; + m_ProgBuffer = NULL; + m_ProgLength = 0; + m_bPrecompiled = false; - requiredStackSize = 0; + requiredStackSize = 0; - m_State.m_Parent = this; + m_State.m_Parent = this; } -GameScript::GameScript( const char *filename ) +GameScript::GameScript(const char *filename) { - m_Filename = Director.AddString( filename ); - successCompile = false; + m_Filename = Director.AddString(filename); + successCompile = false; - m_ProgBuffer = NULL; - m_ProgLength = 0; - m_ProgToSource = NULL; - m_bPrecompiled = false; + m_ProgBuffer = NULL; + m_ProgLength = 0; + m_ProgToSource = NULL; + m_bPrecompiled = false; - m_SourceBuffer = NULL; - m_SourceLength = 0; + m_SourceBuffer = NULL; + m_SourceLength = 0; - requiredStackSize = 0; + requiredStackSize = 0; - m_State.m_Parent = this; + m_State.m_Parent = this; } GameScript::~GameScript() { - Close(); + Close(); } struct pfixup_t { - bool isString; - unsigned int *ptr; + bool isString; + unsigned int *ptr; }; -static Container< const_str > archivedEvents; -static Container< const_str > archivedStrings; -static Container< pfixup_t * > archivedPointerFixup; +static Container archivedEvents; +static Container archivedStrings; +static Container archivedPointerFixup; -void ArchiveOpcode( Archiver& arc, unsigned char *code ) +void ArchiveOpcode(Archiver& arc, unsigned char *code) { - unsigned int index; + unsigned int index; - arc.ArchiveByte( code ); + arc.ArchiveByte(code); - switch( *code ) - { - case OP_STORE_NIL: - case OP_STORE_NULL: - case OP_DONE: - break; + switch (*code) { + case OP_STORE_NIL: + case OP_STORE_NULL: + case OP_DONE: + break; - case OP_EXEC_CMD_COUNT1: - case OP_EXEC_CMD_METHOD_COUNT1: - case OP_EXEC_METHOD_COUNT1: - arc.ArchiveByte( code + 1 ); - goto __exec; + case OP_EXEC_CMD_COUNT1: + case OP_EXEC_CMD_METHOD_COUNT1: + case OP_EXEC_METHOD_COUNT1: + arc.ArchiveByte(code + 1); + goto __exec; - case OP_EXEC_CMD0: - case OP_EXEC_CMD1: - case OP_EXEC_CMD2: - case OP_EXEC_CMD3: - case OP_EXEC_CMD4: - case OP_EXEC_CMD5: - case OP_EXEC_CMD_METHOD0: - case OP_EXEC_CMD_METHOD1: - case OP_EXEC_CMD_METHOD2: - case OP_EXEC_CMD_METHOD3: - case OP_EXEC_CMD_METHOD4: - case OP_EXEC_CMD_METHOD5: - case OP_EXEC_METHOD0: - case OP_EXEC_METHOD1: - case OP_EXEC_METHOD2: - case OP_EXEC_METHOD3: - case OP_EXEC_METHOD4: - case OP_EXEC_METHOD5: - code--; -__exec: - if( !arc.Loading() ) - { - index = archivedEvents.AddUniqueObject( *reinterpret_cast< const_str * >( code + 2 ) ); - } + case OP_EXEC_CMD0: + case OP_EXEC_CMD1: + case OP_EXEC_CMD2: + case OP_EXEC_CMD3: + case OP_EXEC_CMD4: + case OP_EXEC_CMD5: + case OP_EXEC_CMD_METHOD0: + case OP_EXEC_CMD_METHOD1: + case OP_EXEC_CMD_METHOD2: + case OP_EXEC_CMD_METHOD3: + case OP_EXEC_CMD_METHOD4: + case OP_EXEC_CMD_METHOD5: + case OP_EXEC_METHOD0: + case OP_EXEC_METHOD1: + case OP_EXEC_METHOD2: + case OP_EXEC_METHOD3: + case OP_EXEC_METHOD4: + case OP_EXEC_METHOD5: + code--; + __exec: + if (!arc.Loading()) { + index = archivedEvents.AddUniqueObject(*reinterpret_cast(code + 2)); + } - arc.ArchiveUnsigned( &index ); + arc.ArchiveUnsigned(&index); - if( arc.Loading() ) - { - pfixup_t *p = new pfixup_t; + if (arc.Loading()) { + pfixup_t *p = new pfixup_t; - p->isString = false; - p->ptr = reinterpret_cast< unsigned int * >( code + 2 ); + p->isString = false; + p->ptr = reinterpret_cast(code + 2); - *reinterpret_cast< unsigned int * >( code + 2 ) = index; - archivedPointerFixup.AddObject( p ); - } - break; + *reinterpret_cast(code + 2) = index; + archivedPointerFixup.AddObject(p); + } + break; - case OP_LOAD_FIELD_VAR: - case OP_LOAD_GAME_VAR: - case OP_LOAD_GROUP_VAR: - case OP_LOAD_LEVEL_VAR: - case OP_LOAD_LOCAL_VAR: - case OP_LOAD_OWNER_VAR: - case OP_LOAD_PARM_VAR: - case OP_LOAD_SELF_VAR: - case OP_LOAD_STORE_GAME_VAR: - case OP_LOAD_STORE_GROUP_VAR: - case OP_LOAD_STORE_LEVEL_VAR: - case OP_LOAD_STORE_LOCAL_VAR: - case OP_LOAD_STORE_OWNER_VAR: - case OP_LOAD_STORE_PARM_VAR: - case OP_LOAD_STORE_SELF_VAR: - case OP_STORE_FIELD: - case OP_STORE_FIELD_REF: - case OP_STORE_GAME_VAR: - case OP_STORE_GROUP_VAR: - case OP_STORE_LEVEL_VAR: - case OP_STORE_LOCAL_VAR: - case OP_STORE_OWNER_VAR: - case OP_STORE_PARM_VAR: - case OP_STORE_SELF_VAR: - case OP_STORE_STRING: - if( !arc.Loading() ) - { - index = archivedStrings.AddUniqueObject( *reinterpret_cast< const_str * >( code + 1 ) ); - } + case OP_LOAD_FIELD_VAR: + case OP_LOAD_GAME_VAR: + case OP_LOAD_GROUP_VAR: + case OP_LOAD_LEVEL_VAR: + case OP_LOAD_LOCAL_VAR: + case OP_LOAD_OWNER_VAR: + case OP_LOAD_PARM_VAR: + case OP_LOAD_SELF_VAR: + case OP_LOAD_STORE_GAME_VAR: + case OP_LOAD_STORE_GROUP_VAR: + case OP_LOAD_STORE_LEVEL_VAR: + case OP_LOAD_STORE_LOCAL_VAR: + case OP_LOAD_STORE_OWNER_VAR: + case OP_LOAD_STORE_PARM_VAR: + case OP_LOAD_STORE_SELF_VAR: + case OP_STORE_FIELD: + case OP_STORE_FIELD_REF: + case OP_STORE_GAME_VAR: + case OP_STORE_GROUP_VAR: + case OP_STORE_LEVEL_VAR: + case OP_STORE_LOCAL_VAR: + case OP_STORE_OWNER_VAR: + case OP_STORE_PARM_VAR: + case OP_STORE_SELF_VAR: + case OP_STORE_STRING: + if (!arc.Loading()) { + index = archivedStrings.AddUniqueObject(*reinterpret_cast(code + 1)); + } - arc.ArchiveUnsigned( &index ); + arc.ArchiveUnsigned(&index); - if( arc.Loading() ) - { - pfixup_t *p = new pfixup_t; + if (arc.Loading()) { + pfixup_t *p = new pfixup_t; - p->isString = true; - p->ptr = reinterpret_cast< unsigned int * >( code + 1 ); + p->isString = true; + p->ptr = reinterpret_cast(code + 1); - *reinterpret_cast< unsigned int * >( code + 1 ) = index; - archivedPointerFixup.AddObject( p ); - } - break; + *reinterpret_cast(code + 1) = index; + archivedPointerFixup.AddObject(p); + } + break; - default: - if( OpcodeLength( *code ) > 1 ) - arc.ArchiveRaw( code + 1, OpcodeLength( *code ) - 1 ); - } + default: + if (OpcodeLength(*code) > 1) { + arc.ArchiveRaw(code + 1, OpcodeLength(*code) - 1); + } + } } template<> -void con_set< unsigned char *, sourceinfo_t >::Entry::Archive( Archiver& arc ) +void con_set::Entry::Archive(Archiver& arc) { - unsigned int offset; + unsigned int offset; - if( arc.Loading() ) - { - arc.ArchiveUnsigned( &offset ); - key = current_progBuffer + offset; - } - else - { - offset = key - current_progBuffer; - arc.ArchiveUnsigned( &offset ); - } + if (arc.Loading()) { + arc.ArchiveUnsigned(&offset); + key = current_progBuffer + offset; + } else { + offset = key - current_progBuffer; + arc.ArchiveUnsigned(&offset); + } - arc.ArchiveUnsigned( &value.sourcePos ); - arc.ArchiveInteger( &value.column ); - arc.ArchiveInteger( &value.line ); + arc.ArchiveUnsigned(&value.sourcePos); + arc.ArchiveInteger(&value.column); + arc.ArchiveInteger(&value.line); } -void GameScript::Archive( Archiver& arc ) +void GameScript::Archive(Archiver& arc) { - /* + /* int count = 0, i; unsigned char *p, *code_pos, *code_end; const_str s; @@ -509,7 +530,7 @@ void GameScript::Archive( Archiver& arc ) } else { - m_ProgBuffer = ( unsigned char * )glbs.Malloc( m_ProgLength ); + m_ProgBuffer = ( unsigned char * )gi.Malloc( m_ProgLength ); code_pos = m_ProgBuffer; code_end = m_ProgBuffer + m_ProgLength; @@ -607,14 +628,14 @@ void GameScript::Archive( Archiver& arc ) { fileHandle_t filehandle = NULL; - m_SourceLength = glbs.FS_ReadFile( Filename().c_str(), ( void ** )&m_SourceBuffer, true ); + m_SourceLength = gi.FS_ReadFile( Filename().c_str(), ( void ** )&m_SourceBuffer, true ); if( m_SourceLength > 0 ) { - m_SourceBuffer = ( char * )glbs.Malloc( m_SourceLength ); + m_SourceBuffer = ( char * )gi.Malloc( m_SourceLength ); - glbs.FS_Read( m_SourceBuffer, m_SourceLength, filehandle ); - glbs.FS_FCloseFile( filehandle ); + gi.FS_Read( m_SourceBuffer, m_SourceLength, filehandle ); + gi.FS_FCloseFile( filehandle ); } } @@ -623,580 +644,545 @@ void GameScript::Archive( Archiver& arc ) current_progBuffer = NULL;*/ } -void GameScript::Archive( Archiver& arc, GameScript *& scr ) +void GameScript::Archive(Archiver& arc, GameScript *& scr) { - str filename; + str filename; - if( arc.Saving() ) - { - if (scr) - { - filename = scr->Filename(); - } - else - { - filename = ""; - } + if (arc.Saving()) { + if (scr) { + filename = scr->Filename(); + } else { + filename = ""; + } - arc.ArchiveString(&filename); - } - else - { - arc.ArchiveString(&filename); + arc.ArchiveString(&filename); + } else { + arc.ArchiveString(&filename); - if (filename != "") - { - scr = Director.GetScript(filename); - } - else - { - scr = NULL; - } - } + if (filename != "") { + scr = Director.GetScript(filename); + } else { + scr = NULL; + } + } } -void GameScript::ArchiveCodePos( Archiver& arc, unsigned char **codePos ) +void GameScript::ArchiveCodePos(Archiver& arc, unsigned char **codePos) { - int pos = 0; - str filename; + int pos = 0; + str filename; - if( arc.Saving() ) { - GetCodePos(*codePos, filename, pos); - } + if (arc.Saving()) { + GetCodePos(*codePos, filename, pos); + } - arc.ArchiveInteger( &pos ); - arc.ArchiveString( &filename ); + arc.ArchiveInteger(&pos); + arc.ArchiveString(&filename); - if( arc.Loading() ) - { - SetCodePos(*codePos, filename, pos); - } + if (arc.Loading()) { + SetCodePos(*codePos, filename, pos); + } } -void GameScript::Close( void ) +void GameScript::Close(void) { - for( int i = m_CatchBlocks.NumObjects(); i > 0; i-- ) - { - delete m_CatchBlocks.ObjectAt( i ); - } + // Free up catch blocks + for (int i = m_CatchBlocks.NumObjects(); i > 0; i--) { + delete m_CatchBlocks.ObjectAt(i); + } - m_CatchBlocks.FreeObjectList(); + // Added in OPM + // Free up allocated state scripts + for (int i = m_StateScripts.NumObjects(); i > 0; i--) { + delete m_StateScripts.ObjectAt(i); + } - if( m_ProgToSource ) - { - delete m_ProgToSource; - m_ProgToSource = NULL; - } + m_CatchBlocks.FreeObjectList(); - if( m_ProgBuffer ) - { - glbs.Free( m_ProgBuffer ); - m_ProgBuffer = NULL; - } + if (m_ProgToSource) { + delete m_ProgToSource; + m_ProgToSource = NULL; + } - if( m_SourceBuffer ) - { - glbs.Free( m_SourceBuffer ); - m_SourceBuffer = NULL; - } + if (m_ProgBuffer) { + gi.Free(m_ProgBuffer); + m_ProgBuffer = NULL; + } - m_ProgLength = 0; - m_SourceLength = 0; - m_bPrecompiled = false; + if (m_SourceBuffer) { + gi.Free(m_SourceBuffer); + m_SourceBuffer = NULL; + } + + m_ProgLength = 0; + m_SourceLength = 0; + m_bPrecompiled = false; } -void GameScript::Load( const void *sourceBuffer, size_t sourceLength ) +void GameScript::Load(const void *sourceBuffer, size_t sourceLength) { - size_t nodeLength; - char *m_PreprocessedBuffer; + size_t nodeLength; + char *m_PreprocessedBuffer; - m_SourceBuffer = ( char * )glbs.Malloc( sourceLength + 2 ); - m_SourceLength = sourceLength; + m_SourceBuffer = (char *)gi.Malloc(sourceLength + 2); + m_SourceLength = sourceLength; - // Original mohaa doesn't reallocate the input string to append a newline - // This is a temporary workaround to handle the absolute disaster of newlines - // Both the lexer and grammar are extremely abhorrent at handling newlines followed by an EOF - m_SourceBuffer[ sourceLength ] = '\n'; - m_SourceBuffer[ sourceLength + 1] = 0; + // Original mohaa doesn't reallocate the input string to append a newline + // This is a temporary workaround to handle the absolute disaster of newlines + // Both the lexer and grammar are extremely abhorrent at handling newlines followed by an EOF + m_SourceBuffer[sourceLength] = '\n'; + m_SourceBuffer[sourceLength + 1] = 0; - memcpy( m_SourceBuffer, sourceBuffer, sourceLength ); + memcpy(m_SourceBuffer, sourceBuffer, sourceLength); - Compiler.Reset(); + Compiler.Reset(); - m_PreprocessedBuffer = Compiler.Preprocess( m_SourceBuffer ); - nodeLength = Compiler.Parse( this, m_PreprocessedBuffer, "script" ); - Compiler.Preclean( m_PreprocessedBuffer ); + m_PreprocessedBuffer = Compiler.Preprocess(m_SourceBuffer); + if (!Compiler.Parse(this, m_PreprocessedBuffer, "script", nodeLength)) { + gi.DPrintf2("^~^~^ Script file compile error: Couldn't parse '%s'\n", Filename().c_str()); + return Close(); + } - if( !nodeLength ) - { - glbs.DPrintf2( "^~^~^ Script file compile error: Couldn't parse '%s'\n", Filename().c_str() ); - return Close(); - } + if (nodeLength == 0) { + // No code, assume success + requiredStackSize = 0; + successCompile = true; + return; + } - m_ProgBuffer = ( unsigned char * )glbs.Malloc( nodeLength ); - m_ProgLength = Compiler.Compile( this, m_ProgBuffer ); + Compiler.Preclean(m_PreprocessedBuffer); - if( !m_ProgLength ) - { - glbs.DPrintf2( "^~^~^ Script file compile error: Couldn't compile '%s'\n", Filename().c_str() ); - return Close(); - } + m_ProgBuffer = (unsigned char *)gi.Malloc(nodeLength); - requiredStackSize = Compiler.m_iInternalMaxVarStackOffset + 9 * Compiler.m_iMaxExternalVarStackOffset + 1; + if (!Compiler.Compile(this, m_ProgBuffer, m_ProgLength)) { + gi.DPrintf2("^~^~^ Script file compile error: Couldn't compile '%s'\n", Filename().c_str()); + return Close(); + } - successCompile = true; + requiredStackSize = Compiler.m_iInternalMaxVarStackOffset + 9 * Compiler.m_iMaxExternalVarStackOffset + 1; + + successCompile = true; } -bool GameScript::GetCodePos( unsigned char *codePos, str& filename, int& pos ) +bool GameScript::GetCodePos(unsigned char *codePos, str& filename, int& pos) { - pos = codePos - m_ProgBuffer; + pos = codePos - m_ProgBuffer; - if( pos >= 0 && pos < m_ProgLength ) - { - filename = Filename(); - return true; - } - else - { - return false; - } + if (pos >= 0 && pos < m_ProgLength) { + filename = Filename(); + return true; + } else { + return false; + } } -bool GameScript::SetCodePos( unsigned char *&codePos, str& filename, int pos ) +bool GameScript::SetCodePos(unsigned char *& codePos, str& filename, int pos) { - if( Filename() == filename ) - { - codePos = m_ProgBuffer + pos; - return true; - } - else - { - return false; - } + if (Filename() == filename) { + codePos = m_ProgBuffer + pos; + return true; + } else { + return false; + } } -unsigned int GameScript::GetRequiredStackSize( void ) +unsigned int GameScript::GetRequiredStackSize(void) { - return requiredStackSize; + return requiredStackSize; } -qboolean GameScript::labelExists( const char *name ) +qboolean GameScript::labelExists(const char *name) { - str labelname; - - // if we got passed a NULL than that means just run the script so of course it exists - if ( !name ) - { - return true; - } + str labelname; - if( m_State.FindLabel( name ) ) - { - return true; - } + // if we got passed a NULL than that means just run the script so of course it exists + if (!name) { + return true; + } - return false; + if (m_State.FindLabel(name)) { + return true; + } + + return false; } -StateScript *GameScript::CreateCatchStateScript( unsigned char *try_begin_code_pos, unsigned char *try_end_code_pos ) +StateScript *GameScript::CreateCatchStateScript(unsigned char *try_begin_code_pos, unsigned char *try_end_code_pos) { - CatchBlock *catchBlock = new CatchBlock; + CatchBlock *catchBlock = new CatchBlock; - catchBlock->m_TryStartCodePos = try_begin_code_pos; - catchBlock->m_TryEndCodePos = try_end_code_pos; + catchBlock->m_TryStartCodePos = try_begin_code_pos; + catchBlock->m_TryEndCodePos = try_end_code_pos; - m_CatchBlocks.AddObject( catchBlock ); + m_CatchBlocks.AddObject(catchBlock); - return &catchBlock->m_StateScript; + return &catchBlock->m_StateScript; } -StateScript *GameScript::CreateSwitchStateScript( void ) +StateScript *GameScript::CreateSwitchStateScript(void) { - return new StateScript; + StateScript *stateScript = new StateScript; + + m_StateScripts.AddObject(stateScript); + + return stateScript; } -StateScript *GameScript::GetCatchStateScript( unsigned char *in, unsigned char *&out ) +StateScript *GameScript::GetCatchStateScript(unsigned char *in, unsigned char *& out) { - CatchBlock *catchBlock; - CatchBlock *bestCatchBlock = NULL; + CatchBlock *catchBlock; + CatchBlock *bestCatchBlock = NULL; - for( int i = m_CatchBlocks.NumObjects(); i > 0; i-- ) - { - catchBlock = m_CatchBlocks.ObjectAt( i ); + for (int i = m_CatchBlocks.NumObjects(); i > 0; i--) { + catchBlock = m_CatchBlocks.ObjectAt(i); - if( in >= catchBlock->m_TryStartCodePos && in < catchBlock->m_TryEndCodePos ) - { - if( !bestCatchBlock || catchBlock->m_TryEndCodePos < bestCatchBlock->m_TryEndCodePos ) - { - bestCatchBlock = catchBlock; - } - } - } + if (in >= catchBlock->m_TryStartCodePos && in < catchBlock->m_TryEndCodePos) { + if (!bestCatchBlock || catchBlock->m_TryEndCodePos < bestCatchBlock->m_TryEndCodePos) { + bestCatchBlock = catchBlock; + } + } + } - if( bestCatchBlock ) - { - out = bestCatchBlock->m_TryEndCodePos; + if (bestCatchBlock) { + out = bestCatchBlock->m_TryEndCodePos; - return &bestCatchBlock->m_StateScript; - } - else - { - return NULL; - } + return &bestCatchBlock->m_StateScript; + } else { + return NULL; + } } bool GameScript::ScriptCheck(void) { - if (g_scriptcheck->integer == 1) - { - return true; - } + if (g_scriptcheck->integer == 1) { + return true; + } - if (g_scriptcheck->integer == 2 || g_scriptcheck->integer == 3) - { - if (strstr(Filename().c_str(), "anim/") != Filename().c_str()) - { - return true; - } - } - if (g_scriptcheck->integer == 3) - { - if (strstr(Filename().c_str(), "global/") != Filename().c_str()) - { - return true; - } - } - return false; + if (g_scriptcheck->integer == 2 || g_scriptcheck->integer == 3) { + if (strstr(Filename().c_str(), "anim/") != Filename().c_str()) { + return true; + } + } + if (g_scriptcheck->integer == 3) { + if (strstr(Filename().c_str(), "global/") != Filename().c_str()) { + return true; + } + } + return false; } ScriptThreadLabel::ScriptThreadLabel() { - m_Script = NULL; - m_Label = STRING_EMPTY; + m_Script = NULL; + m_Label = STRING_EMPTY; } -ScriptThread *ScriptThreadLabel::Create( Listener *listener ) +ScriptThread *ScriptThreadLabel::Create(Listener *listener) const { - if( !m_Script ) { - return NULL; - } + ScriptClass *scriptClass; + ScriptThread *thread; - ScriptClass *scriptClass = new ScriptClass( m_Script, listener ); - ScriptThread *thread = Director.CreateScriptThread( scriptClass, m_Label ); + if (!m_Script) { + return NULL; + } - return thread; + scriptClass = NULL; + thread = NULL; + + try { + scriptClass = new ScriptClass(m_Script, listener); + thread = new ScriptThread(scriptClass, m_Script->m_State.FindLabel(m_Label)); + } catch (...) { + if (scriptClass) { + delete scriptClass; + } + + if (thread) { + delete thread; + } + + throw; + } + + return thread; } -void ScriptThreadLabel::Execute( Listener *listener ) -{ - if( !m_Script ) { - return; - } - - ScriptThread *thread = Create( listener ); - - if( thread ) - { - thread->Execute(); - } -} - -void ScriptThreadLabel::Execute( Listener *listener, Event &ev ) -{ - Execute( listener, &ev ); -} - -void ScriptThreadLabel::Execute( Listener *listener, Event *ev ) -{ - if( !m_Script ) { - return; - } - - ScriptThread *thread = Create( listener ); - - if( thread ) - { - thread->Execute( ev ); - } -} - -void ScriptThreadLabel::Execute(const SafePtr& listener, const SafePtr& param) +void ScriptThreadLabel::Execute(Listener *listener) const { if (!m_Script) { return; } - ScriptVariable params[2]; + ScriptThread *thread = Create(listener); - params[0].setListenerValue(listener); - params[1].setListenerValue(param); + if (thread) { + thread->Execute(); + } +} - ScriptClass* scriptClass = new ScriptClass(m_Script, listener); - ScriptThread* thread = Director.CreateScriptThread(scriptClass, m_Label); +void ScriptThreadLabel::Execute(Listener *listener, Event& ev) const +{ + if (!m_Script) { + return; + } - if (thread) - { - thread->Execute(params, 2); - } + ScriptThread *thread = Create(listener); + + if (thread) { + thread->Execute(ev); + } +} + +void ScriptThreadLabel::Execute(Listener *listener, Event *ev) const +{ + Execute(listener, *ev); +} + +void ScriptThreadLabel::Execute(Listener *pSelf, const SafePtr& listener, const SafePtr& param) + const +{ + if (!m_Script) { + return; + } + + ScriptVariable params[2]; + + params[0].setListenerValue(listener); + params[1].setListenerValue(param); + + ScriptClass *scriptClass = new ScriptClass(m_Script, pSelf); + ScriptThread *thread = Director.CreateScriptThread(scriptClass, m_Label); + + if (thread) { + thread->Execute(params, 2); + } +} + +void ScriptThreadLabel::Clear() +{ + m_Script = NULL; + m_Label = STRING_EMPTY; } void ScriptThreadLabel::Set(const char *label) { - str script; - char buffer[ 1023 ]; - char *p = buffer; - int i = 0; - bool foundLabel = false; + str script; + char buffer[1023]; + char *p = buffer; + int i = 0; + bool foundLabel = false; - if( !label || !*label ) - { - m_Script = NULL; - m_Label = STRING_EMPTY; - return; - } + if (!label || !*label) { + m_Script = NULL; + m_Label = STRING_EMPTY; + return; + } - strcpy( buffer, label ); + Q_strncpyz(buffer, label, sizeof(buffer)); - while( true ) - { - if( p[ 0 ] == ':' && p[ 1 ] == ':' ) - { - *p = '\0'; + while (true) { + if (p[0] == ':' && p[1] == ':') { + *p = '\0'; - script = buffer; - m_Label = Director.AddString( &p[ 2 ] ); - foundLabel = true; + script = buffer; + m_Label = Director.AddString(&p[2]); + foundLabel = true; - break; - } + break; + } - p++; - i++; + p++; + i++; - if (*p == '\0') - { - break; - } + if (*p == '\0') { + break; + } - if (i >= 1023) - { - //we didn't find label but this is how it works. - //the whole string is the label - m_Label = Director.AddString(buffer); - script = buffer; - foundLabel = true; - break; - } - - } + if (i >= 1023) { + //we didn't find label but this is how it works. + //the whole string is the label + m_Label = Director.AddString(buffer); + script = buffer; + foundLabel = true; + break; + } + } - if( !foundLabel ) - { - script = level.m_mapscript; - m_Label = Director.AddString(buffer); - } + if (!foundLabel) { + script = level.m_mapscript; + m_Label = Director.AddString(buffer); + } + m_Script = Director.GetGameScript(script); - m_Script = Director.GetGameScript( script ); + if (!m_Script->m_State.FindLabel(m_Label)) { + str l = Director.GetString(m_Label); - if( !m_Script->m_State.FindLabel( m_Label ) ) - { - str l = Director.GetString( m_Label ); + m_Script = NULL; + m_Label = STRING_EMPTY; - m_Script = NULL; - m_Label = STRING_EMPTY; - - ScriptError( "^~^~^ Could not find label '%s' in '%s'", l.c_str(), script.c_str() ); - } + ScriptError("^~^~^ Could not find label '%s' in '%s'", l.c_str(), script.c_str()); + } } void ScriptThreadLabel::Set(const_str label) { - return Set(Director.GetString(label)); + return Set(Director.GetString(label)); } -void ScriptThreadLabel::SetScript( const ScriptVariable& label ) +void ScriptThreadLabel::SetScript(const ScriptVariable& label) { - if( label.GetType() == VARIABLE_STRING || label.GetType() == VARIABLE_CONSTSTRING ) - { - m_Script = Director.GetGameScript( label.stringValue() ); - m_Label = STRING_EMPTY; - } - else if( label.GetType() == VARIABLE_CONSTARRAY && label.arraysize() > 1 ) - { - ScriptVariable *script = label[ 1 ]; - ScriptVariable *labelname = label[ 2 ]; + switch (label.GetType()) { + case VARIABLE_STRING: + m_Script = Director.GetGameScript(label.stringValue()); + m_Label = STRING_EMPTY; + break; + case VARIABLE_CONSTSTRING: + m_Script = Director.GetGameScript(label.constStringValue()); + m_Label = STRING_EMPTY; + break; + case VARIABLE_NONE: + m_Script = NULL; + m_Label = STRING_EMPTY; + break; + case VARIABLE_CONSTARRAY: + if (label.arraysize() > 1) { + ScriptVariable *script = label[1]; + ScriptVariable *labelname = label[2]; - m_Script = Director.GetGameScript( script->stringValue() ); - m_Label = labelname->constStringValue(); + if (script->GetType() == VARIABLE_CONSTSTRING) { + m_Script = Director.GetGameScript(script->constStringValue()); + } else { + m_Script = Director.GetGameScript(script->stringValue()); + } - if( !m_Script->m_State.FindLabel( m_Label ) ) - { - m_Script = NULL; - m_Label = STRING_EMPTY; + m_Label = labelname->constStringValue(); + break; + } + default: + ScriptError("ScriptThreadLabel::SetScript: bad label type '%s'", label.GetTypeName()); + break; + } - ScriptError( "^~^~^ Could not find label '%s' in '%s'", labelname->stringValue().c_str(), script->stringValue().c_str() ); - } - } - else - { - ScriptError( "ScriptThreadLabel::SetScript: bad label type '%s'", label.GetTypeName() ); - } + if (m_Script && !m_Script->m_State.FindLabel(m_Label)) { + const str& scriptName = m_Script->Filename(); + const str& labelName = Director.GetString(m_Label); + + m_Script = NULL; + m_Label = STRING_EMPTY; + + ScriptError("^~^~^ Could not find label '%s' in '%s'", scriptName.c_str(), labelName.c_str()); + } } -void ScriptThreadLabel::SetScript( const char *label ) +void ScriptThreadLabel::SetScript(const char *label) { - str script; - char buffer[1023]; - char *p = buffer; - int i = 0; - bool foundLabel = false; + str script; + char buffer[1023]; + char *p = buffer; + int i = 0; + bool foundLabel = false; - if (!label || !*label) - { - m_Script = NULL; - m_Label = STRING_EMPTY; - return; - } + if (!label || !*label) { + m_Script = NULL; + m_Label = STRING_EMPTY; + return; + } - strcpy(buffer, label); + Q_strncpyz(buffer, label, sizeof(buffer)); - script = buffer; - while (true) - { - if (p[0] == ':' && p[1] == ':') - { - *p = '\0'; + script = buffer; + while (true) { + if (p[0] == ':' && p[1] == ':') { + *p = '\0'; - m_Label = Director.AddString(&p[2]); - foundLabel = true; + m_Label = Director.AddString(&p[2]); + foundLabel = true; - break; - } + break; + } - p++; - i++; + p++; + i++; - if (*p == '\0') - { - m_Label = STRING_EMPTY; - foundLabel = true; - break; - } + if (*p == '\0') { + m_Label = STRING_EMPTY; + foundLabel = true; + break; + } - if (i >= 1023) - { - //we didn't find label so empty label - m_Label = STRING_EMPTY; - foundLabel = false; - break; - } + if (i >= 1023) { + //we didn't find label so empty label + m_Label = STRING_EMPTY; + foundLabel = false; + break; + } + } - } + m_Script = Director.GetGameScript(script); + if (!m_Script->m_State.FindLabel(m_Label)) { + str l = Director.GetString(m_Label); - m_Script = Director.GetGameScript(script); + m_Script = NULL; + m_Label = STRING_EMPTY; - if (!m_Script->m_State.FindLabel(m_Label)) - { - str l = Director.GetString(m_Label); - - m_Script = NULL; - m_Label = STRING_EMPTY; - - ScriptError("^~^~^ Could not find label '%s' in '%s'", l.c_str(), script.c_str()); - } + ScriptError("^~^~^ Could not find label '%s' in '%s'", l.c_str(), script.c_str()); + } } void ScriptThreadLabel::SetScript(const_str label) { - SetScript(Director.GetString(label)); + SetScript(Director.GetString(label)); } -void ScriptThreadLabel::SetThread( const ScriptVariable& label ) +void ScriptThreadLabel::SetThread(const ScriptVariable& label) { - ScriptThread *thread = NULL; + switch (label.GetType()) { + case VARIABLE_STRING: + case VARIABLE_CONSTSTRING: + m_Script = Director.CurrentScriptClass()->GetScript(); + m_Label = label.constStringValue(); + break; + case VARIABLE_NONE: + m_Script = NULL; + m_Label = STRING_EMPTY; + break; + case VARIABLE_CONSTARRAY: + if (label.arraysize() > 1) { + ScriptVariable *script = label[1]; + ScriptVariable *labelname = label[2]; - if( label.GetType() == VARIABLE_STRING || label.GetType() == VARIABLE_CONSTSTRING ) - { - m_Script = Director.CurrentScriptClass()->GetScript(); - m_Label = label.constStringValue(); - } - else if( label.GetType() == VARIABLE_CONSTARRAY && label.arraysize() > 1 ) - { - ScriptVariable *script = label[ 1 ]; - ScriptVariable *labelname = label[ 2 ]; + if (script->GetType() == VARIABLE_CONSTSTRING) { + m_Script = Director.GetGameScript(script->constStringValue()); + } else { + m_Script = Director.GetGameScript(script->stringValue()); + } - m_Script = Director.GetGameScript( script->stringValue() ); - m_Label = labelname->constStringValue(); - - if( !m_Script->m_State.FindLabel( m_Label ) ) - { - m_Script = NULL; - m_Label = STRING_EMPTY; - - ScriptError( "^~^~^ Could not find label '%s' in '%s'", labelname->stringValue().c_str(), script->stringValue().c_str() ); - } - } - else - { - ScriptError( "ScriptThreadLabel::SetThread bad label type '%s'", label.GetTypeName() ); - } -} - -bool ScriptThreadLabel::TrySet( const char *label ) -{ - try - { - Set( label ); - } - catch(const ScriptException& exc) - { - Com_Printf( "%s\n", exc.string.c_str() ); - return false; - } - - return true; -} - -bool ScriptThreadLabel::TrySet( const_str label ) -{ - try - { - Set( label ); - } - catch(const ScriptException& exc) - { - Com_Printf( "%s\n", exc.string.c_str() ); - return false; - } - - return true; -} - -bool ScriptThreadLabel::TrySetScript( const char *label ) -{ - try - { - SetScript( label ); - } - catch(const ScriptException &exc) - { - Com_Printf( "%s\n", exc.string.c_str() ); - return false; - } - - return true; -} - -bool ScriptThreadLabel::TrySetScript( const_str label ) -{ - try - { - SetScript(label); + m_Label = labelname->constStringValue(); + break; + } + default: + ScriptError("ScriptThreadLabel::SetThread: bad label type '%s'", label.GetTypeName()); + break; } - catch (const ScriptException& exc) - { + + if (m_Script && !m_Script->m_State.FindLabel(m_Label)) { + const str& scriptName = m_Script->Filename(); + const str& labelName = Director.GetString(m_Label); + + m_Script = NULL; + m_Label = STRING_EMPTY; + + ScriptError("^~^~^ Could not find label '%s' in '%s'", scriptName.c_str(), labelName.c_str()); + } +} + +bool ScriptThreadLabel::TrySet(const char *label) +{ + try { + Set(label); + } catch (const ScriptException& exc) { Com_Printf("%s\n", exc.string.c_str()); return false; } @@ -1204,40 +1190,69 @@ bool ScriptThreadLabel::TrySetScript( const_str label ) return true; } -void ScriptThreadLabel::GetScriptValue(ScriptVariable *var) +bool ScriptThreadLabel::TrySet(const_str label) { - //FIXME: macro: 2 ? - ScriptVariable var_array[2]; + try { + Set(label); + } catch (const ScriptException& exc) { + Com_Printf("%s\n", exc.string.c_str()); + return false; + } - if (m_Script) - { - var_array[0].setConstStringValue(m_Script->ConstFilename()); - var_array[1].setConstStringValue(m_Label); - var->setConstArrayValue(var_array, 2); - for (int i = 0; i < 2; i++) - { - var_array[i].Clear(); - } - } - else - { - var->Clear(); - } + return true; } -bool ScriptThreadLabel::IsSet( void ) +bool ScriptThreadLabel::TrySetScript(const char *label) { - return m_Script != NULL; + try { + SetScript(label); + } catch (const ScriptException& exc) { + Com_Printf("%s\n", exc.string.c_str()); + return false; + } + + return true; } -bool ScriptThreadLabel::IsFile(const_str filename) +bool ScriptThreadLabel::TrySetScript(const_str label) { - return m_Script && m_Script->ConstFilename() == filename && m_Label == STRING_EMPTY; + try { + SetScript(label); + } catch (const ScriptException& exc) { + Com_Printf("%s\n", exc.string.c_str()); + return false; + } + + return true; } -void ScriptThreadLabel::Archive( Archiver& arc ) +void ScriptThreadLabel::GetScriptValue(ScriptVariable *var) const { - GameScript::Archive(arc, m_Script); + if (!m_Script) { + var->Clear(); + return; + } - Director.ArchiveString( arc, m_Label ); + ScriptVariable var_array[2]; + + var_array[0].setConstStringValue(m_Script->ConstFilename()); + var_array[1].setConstStringValue(m_Label); + var->setConstArrayValue(var_array, 2); +} + +bool ScriptThreadLabel::IsSet(void) const +{ + return m_Script != NULL; +} + +bool ScriptThreadLabel::IsFile(const_str filename) const +{ + return m_Script && m_Script->ConstFilename() == filename && m_Label == STRING_EMPTY; +} + +void ScriptThreadLabel::Archive(Archiver& arc) +{ + GameScript::Archive(arc, m_Script); + + Director.ArchiveString(arc, m_Label); } diff --git a/code/fgame/gamescript.h b/code/fgame/gamescript.h index 527acfea..80af333b 100644 --- a/code/fgame/gamescript.h +++ b/code/fgame/gamescript.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // gamescript.h: Subclass of script that preprocesses labels -#ifndef __GAMESCRIPT_H__ -#define __GAMESCRIPT_H__ +#pragma once #include "class.h" #include "script.h" @@ -35,166 +34,172 @@ class ScriptVariable; class GameScript; typedef struct { - byte *codepos; // code position pointer - const_str key; // label name - bool isprivate; // new script engine implementation + byte *codepos; // code position pointer + const_str key; // label name + bool isprivate; // new script engine implementation } script_label_t; -typedef struct { - unsigned int sourcePos; - int column; - int line; -} sourceinfo_t; +struct sourceinfo_t { + unsigned int sourcePos; + unsigned int startLinePos; + int column; + int line; -class AbstractScript { + sourceinfo_t() + : sourcePos(0) + , column(0) + , line(0) + {} +}; + +class AbstractScript +{ public: - // File variables - const_str m_Filename; - char *m_SourceBuffer; - size_t m_SourceLength; + // File variables + const_str m_Filename; + char *m_SourceBuffer; + size_t m_SourceLength; - // Developper variable - con_set< uchar *, sourceinfo_t > *m_ProgToSource; + // Developper variable + con_set *m_ProgToSource; + + sourceinfo_t cachedInfo[16]; + size_t cachedInfoIndex; public: + AbstractScript(); - AbstractScript(); - - str& Filename( void ); - const_str ConstFilename( void ); - bool GetSourceAt( size_t sourcePos, str *sourceLine, int &column, int &line ); - void PrintSourcePos( sourceinfo_t *sourcePos, bool dev ); - void PrintSourcePos( size_t sourcePos, bool dev ); - void PrintSourcePos( unsigned char *m_pCodePos, bool dev ); - void PrintSourcePos( str sourceLine, int column, int line, bool dev ); + str& Filename(void); + const_str ConstFilename(void); + bool GetSourceAt(size_t sourcePos, str *sourceLine, int& column, int& line); + bool GetSourceAt(const unsigned char *sourcePos, str *sourceLine, int& column, int& line); + void PrintSourcePos(sourceinfo_t *sourcePos, bool dev); + void PrintSourcePos(size_t sourcePos, bool dev); + void PrintSourcePos(unsigned char *m_pCodePos, bool dev); + void PrintSourcePos(str sourceLine, int column, int line, bool dev); }; class StateScript : public Class { - friend class GameScript; + friend class GameScript; private: - // Label list - con_set< const_str, script_label_t > label_list; + // Label list + con_set label_list; public: - // Parent gamescript - GameScript *m_Parent; + // Parent gamescript + GameScript *m_Parent; public: - StateScript(); + StateScript(); - void Archive( Archiver& arc ) override; + void Archive(Archiver& arc) override; - bool AddLabel( str label, unsigned char *pos, bool private_section = false ); - bool AddLabel( const_str label, unsigned char *pos, bool private_section = false ); - unsigned char *FindLabel( str label ); - unsigned char *FindLabel( const_str label ); - const_str NearestLabel( unsigned char *pos ); + bool AddLabel(str label, unsigned char *pos, bool private_section = false); + bool AddLabel(const_str label, unsigned char *pos, bool private_section = false); + unsigned char *FindLabel(str label); + unsigned char *FindLabel(const_str label); + const_str NearestLabel(unsigned char *pos); }; -class CatchBlock { -public: - // program variable - StateScript m_StateScript; - - // code position variables - unsigned char *m_TryStartCodePos; - unsigned char *m_TryEndCodePos; -}; - -class GameScript : public AbstractScript { -protected: - // try/throw variable - Container m_CatchBlocks; - -public: - // program variables - StateScript m_State; - unsigned char *m_ProgBuffer; - size_t m_ProgLength; - - // compile variables - bool successCompile; - bool m_bPrecompiled; - - // stack variables - unsigned int requiredStackSize; - -public: - - GameScript(); - GameScript( const char *filename ); - ~GameScript(); - - void Archive( Archiver& arc ); - static void Archive( Archiver& arc, GameScript *&scr ); - void ArchiveCodePos( Archiver& arc, unsigned char **codePos ); - - void Close( void ); - void Load( const void *sourceBuffer, size_t sourceLength ); - - - bool GetCodePos( unsigned char *codePos, str& filename, int& pos ); - bool SetCodePos( unsigned char *&codePos, str& filename, int pos ); - - unsigned int GetRequiredStackSize( void ); - - qboolean labelExists( const char *name ); - - StateScript *CreateCatchStateScript( unsigned char *try_begin_code_pos, unsigned char *try_end_code_pos ); - StateScript *CreateSwitchStateScript( void ); - - StateScript *GetCatchStateScript( unsigned char *in, unsigned char *&out ); - - bool ScriptCheck( void ); -}; - -class ScriptThreadLabel { -private: - GameScript *m_Script; - const_str m_Label; - -public: - ScriptThreadLabel(); - - ScriptThread *Create( Listener *listener ); - void Execute( Listener *listener = NULL ); - void Execute( Listener *listener, Event &ev ); - void Execute( Listener *listener, Event *ev ); - void Execute(const SafePtr& listener, const SafePtr& param); - - void Set( const char *label ); - void Set( const_str label ); - void SetScript( const ScriptVariable& label ); - void SetScript( const char *label ); - void SetScript( const_str label ); - void SetThread( const ScriptVariable& label ); - - bool TrySet( const_str label ); - bool TrySet( const char *label ); - bool TrySetScript( const_str label ); - bool TrySetScript( const char *label ); - - bool IsSet(void); - bool IsFile(const_str filename); - - void GetScriptValue(ScriptVariable *var); - - - void Archive( Archiver& arc ); - - friend bool operator==(const ScriptThreadLabel& a, const ScriptThreadLabel& b); -}; - - -inline bool operator== -( - const ScriptThreadLabel& a, - const ScriptThreadLabel& b - ) +class CatchBlock { - return a.m_Label == b.m_Label && a.m_Script == b.m_Script; -} +public: + // program variable + StateScript m_StateScript; -#endif + // code position variables + unsigned char *m_TryStartCodePos; + unsigned char *m_TryEndCodePos; +}; + +class GameScript : public AbstractScript +{ +protected: + // try/throw variable + Container m_CatchBlocks; + Container m_StateScripts; + +public: + // program variables + StateScript m_State; + unsigned char *m_ProgBuffer; + size_t m_ProgLength; + + // compile variables + bool successCompile; + bool m_bPrecompiled; + + // stack variables + unsigned int requiredStackSize; + +public: + GameScript(); + GameScript(const char *filename); + ~GameScript(); + + void Archive(Archiver& arc); + static void Archive(Archiver& arc, GameScript *& scr); + void ArchiveCodePos(Archiver& arc, unsigned char **codePos); + + void Close(void); + void Load(const void *sourceBuffer, size_t sourceLength); + + bool GetCodePos(unsigned char *codePos, str& filename, int& pos); + bool SetCodePos(unsigned char *& codePos, str& filename, int pos); + + unsigned int GetRequiredStackSize(void); + + qboolean labelExists(const char *name); + + StateScript *CreateCatchStateScript(unsigned char *try_begin_code_pos, unsigned char *try_end_code_pos); + StateScript *CreateSwitchStateScript(void); + + StateScript *GetCatchStateScript(unsigned char *in, unsigned char *& out); + + bool ScriptCheck(void); +}; + +class ScriptThreadLabel +{ +private: + GameScript *m_Script; + const_str m_Label; + +public: + ScriptThreadLabel(); + + ScriptThread *Create(Listener *listener) const; + void Execute(Listener *listener = NULL) const; + void Execute(Listener *listener, Event& ev) const; + void Execute(Listener *listener, Event *ev) const; + void Execute(Listener *pSelf, const SafePtr& listener, const SafePtr& param) const; + + void Clear(); + void Set(const char *label); + void Set(const_str label); + void SetScript(const ScriptVariable& label); + void SetScript(const char *label); + void SetScript(const_str label); + void SetThread(const ScriptVariable& label); + + bool TrySet(const_str label); + bool TrySet(const char *label); + bool TrySetScript(const_str label); + bool TrySetScript(const char *label); + + bool IsSet(void) const; + bool IsFile(const_str filename) const; + + void GetScriptValue(ScriptVariable *var) const; + + void Archive(Archiver& arc); + + friend bool operator==(const ScriptThreadLabel& a, const ScriptThreadLabel& b); +}; + +inline bool operator==(const ScriptThreadLabel& a, const ScriptThreadLabel& b) +{ + return a.m_Label == b.m_Label && a.m_Script == b.m_Script; +} diff --git a/code/fgame/gibs.cpp b/code/fgame/gibs.cpp index e53b3546..6ee01738 100644 --- a/code/fgame/gibs.cpp +++ b/code/fgame/gibs.cpp @@ -147,7 +147,7 @@ void Gib::Splat ) { - if ( g_gametype->integer ) + if ( g_gametype->integer != GT_SINGLE_PLAYER ) return; if ( sprayed > 3 ) diff --git a/code/fgame/gibs.h b/code/fgame/gibs.h index 382d201d..364ee54e 100644 --- a/code/fgame/gibs.h +++ b/code/fgame/gibs.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // gibs.h: Gibs - nuff said -#ifndef __GIBS_H__ -#define __GIBS_H__ +#pragma once #include "g_local.h" #include "mover.h" @@ -88,5 +87,3 @@ void CreateGibs ); extern Event EV_ThrowGib; - -#endif // gibs.h diff --git a/code/fgame/glb_local.h b/code/fgame/glb_local.h index 673a55f3..588f975d 100644 --- a/code/fgame/glb_local.h +++ b/code/fgame/glb_local.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#ifndef __GLB_LOCAL_H__ -#define __GLB_LOCAL_H__ +#pragma once #if defined( GAME_DLL ) @@ -79,5 +78,3 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif #endif - -#endif /* glb_local.h */ diff --git a/code/fgame/gravpath.h b/code/fgame/gravpath.h index efa56b6f..d3a6380e 100644 --- a/code/fgame/gravpath.h +++ b/code/fgame/gravpath.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // gravpath.h: Gravity path - Used for underwater currents and wells. -#ifndef __GRAVPATH_H__ -#define __GRAVPATH_H__ +#pragma once #include "g_local.h" #include "class.h" @@ -202,5 +201,3 @@ inline void GravPathManager::Archive } extern GravPathManager gravPathManager; - -#endif /* gravpath.h */ diff --git a/code/fgame/grenadehint.h b/code/fgame/grenadehint.h index 48bc9803..0661f769 100644 --- a/code/fgame/grenadehint.h +++ b/code/fgame/grenadehint.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // grenadehint.h: Grenade hint for actors. -#ifndef __GRENADEHINT_H__ -#define __GRENADEHINT_H__ +#pragma once #include "g_local.h" #include "archive.h" @@ -53,5 +52,3 @@ inline void GrenadeHint::Archive arc.ArchiveObjectPointer( ( Class ** )&m_pNext ); } - -#endif diff --git a/code/fgame/health.cpp b/code/fgame/health.cpp index 9a7b33ab..a7d19f33 100644 --- a/code/fgame/health.cpp +++ b/code/fgame/health.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -// health.cpp: Health powerup +// health.cpp: Health powerup // #include "g_local.h" @@ -30,54 +30,158 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "health.h" #include "weaputils.h" #include "player.h" +#include "g_phys.h" -CLASS_DECLARATION( Item, Health, "health_020" ) -{ - { &EV_Item_Pickup, &Health::PickupHealth }, - { NULL, NULL } +Event EV_Health_PostSpawn("health_postspawn", EV_DEFAULT, NULL, NULL, "Health Post Spawn"); + +CLASS_DECLARATION(Item, Health, "health_020") { + {&EV_Item_Pickup, &Health::PickupHealth }, + {&EV_Health_PostSpawn, &Health::EventPostSpawn}, + {NULL, NULL } }; +SafePtr Health::mHealthQueue[MAX_HEALTH_QUEUE]; + Health::Health() { - if( DM_FLAG( DF_NO_HEALTH ) ) - { - PostEvent( EV_Remove, EV_REMOVE ); - return; - } + if (LoadingSavegame) { + return; + } - setAmount( 20 ); + if (DM_FLAG(DF_NO_HEALTH)) { + PostEvent(EV_Remove, EV_REMOVE); + return; + } + + setAmount(20); + + // Added in 2.0 + // Set the targetname to health by default + SetTargetName("health"); + + PostEvent(EV_Health_PostSpawn, EV_POSTSPAWN); } -void Health::PickupHealth - ( - Event *ev - ) +void Health::PickupHealth(Event *ev) { - Sentient *sen; - Entity *other; + Player *player; + Entity *other; - other = ev->GetEntity( 1 ); - if( !other || !other->IsSubclassOfSentient() ) - { - return; - } + other = ev->GetEntity(1); + if (!other || !other->IsSubclassOfPlayer()) { + return; + } - sen = ( Sentient * )other; + player = (Player *)other; - if( sen->health >= sen->max_health ) - return; + if (g_healrate->value && other->IsSubclassOfPlayer()) { + // Added in OPM + // OG doesn't check if the future health will be full + // which is problematic as other can pickup the item + // will healing + if (player->m_fHealRate + player->health >= player->max_health) { + // will be healing to 100% + return; + } + } else { + if (player->health >= player->max_health) { + return; + } + } - if( !ItemPickup( other, qfalse ) ) - { - return; - } + if (!ItemPickup(other, qfalse)) { + return; + } - sen->health += amount / 100.0 * sen->max_health; + if (g_healrate->value && other->IsSubclassOfPlayer()) { + if (player->m_fHealRate + player->health >= player->max_health) { + // will be healing to 100% + return; + } - if( sen->health > sen->max_health ) - { - sen->health = sen->max_health; - } + player->m_fHealRate += amount / 100.0 * player->max_health; + if (player->m_fHealRate + player->health > player->max_health) { + // make sure to not overflow + player->m_fHealRate = player->max_health - player->health + 0.1f; + } + } else { + player->health += amount / 100.0 * player->max_health; - gi.SendServerCommand( sen->edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s \"", gi.LV_ConvertString( va( "Recovered %d", amount ) ) ); + if (player->health > player->max_health) { + player->health = player->max_health; + } + } + + gi.SendServerCommand( + player->edict - g_entities, + "print \"" HUD_MESSAGE_YELLOW "%s\n\"", + gi.LV_ConvertString(va("Recovered %d Health", amount)) + ); +} + +void Health::EventPostSpawn(Event *ev) +{ + setMoveType(MOVETYPE_TOSS); + + if (edict->tiki) { + vec3_t mins, maxs; + + gi.TIKI_CalculateBounds(edict->tiki, edict->s.scale, mins, maxs); + + setSize(mins, maxs); + link(); + } + + droptofloor(256); +} + +void Health::CompressHealthQueue() +{ + int i, j; + + for (i = 0; i < MAX_HEALTH_QUEUE; i++) { + if (!mHealthQueue[i]) { + for (j = i + 1; j < MAX_HEALTH_QUEUE; j++) { + if (mHealthQueue[j]) { + mHealthQueue[i] = mHealthQueue[j]; + break; + } + } + } + } +} + +void Health::AddToHealthQueue() +{ + CompressHealthQueue(); + + if (mHealthQueue[MAX_HEALTH_QUEUE - 1]) { + mHealthQueue[MAX_HEALTH_QUEUE - 1]->Delete(); + mHealthQueue[0] = NULL; + CompressHealthQueue(); + } + + mHealthQueue[MAX_HEALTH_QUEUE - 1] = this; + + CompressHealthQueue(); +} + +void Health::ResetHealthQueue() {} + +void Health::ArchiveStatic(Archiver& arc) +{ + int i; + + for (i = 0; i < MAX_HEALTH_QUEUE; i++) { + arc.ArchiveSafePointer(&mHealthQueue[i]); + } +} + +void Health::DoRemoveProcess() +{ + if (g_gametype->integer != GT_SINGLE_PLAYER) { + DoRemoveProcess(); + } else { + AddToHealthQueue(); + } } diff --git a/code/fgame/health.h b/code/fgame/health.h index cb0011f0..a9064b62 100644 --- a/code/fgame/health.h +++ b/code/fgame/health.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,23 +21,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // health.h: Health powerup -// +// -#ifndef __HEALTH_H__ -#define __HEALTH_H__ +#pragma once #include "g_local.h" #include "item.h" #include "sentient.h" #include "item.h" +#define MAX_HEALTH_QUEUE 5 + class Health : public Item { public: - CLASS_PROTOTYPE( Health ); + CLASS_PROTOTYPE(Health); - Health(); - virtual void PickupHealth( Event *ev ); + Health(); + virtual void PickupHealth(Event *ev); + + void EventPostSpawn(Event *ev); + static void CompressHealthQueue(); + void AddToHealthQueue(); + static void ResetHealthQueue(); + + static void ArchiveStatic(Archiver& arc); + void DoRemoveProcess(); + +private: + static SafePtr mHealthQueue[MAX_HEALTH_QUEUE]; }; - -#endif /* health.h */ diff --git a/code/fgame/hud.cpp b/code/fgame/hud.cpp index 1417d75d..46a93c37 100644 --- a/code/fgame/hud.cpp +++ b/code/fgame/hud.cpp @@ -779,7 +779,7 @@ void Hud::TimerThink() #else if( !*shader ) { #endif - sprintf( buffer, string, minutes, seconds ); + Com_sprintf( buffer, sizeof( buffer ), string, minutes, seconds ); SetText( buffer ); } else { @@ -1001,7 +1001,6 @@ void Hud::MoveOverTime( float time ) void Hud::Refresh( int clientNumber ) { -#ifdef GAME_DLL SetBroadcast( clientNumber ); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_ALIGN )); @@ -1093,13 +1092,13 @@ void Hud::Refresh( int clientNumber ) gi.MSG_WriteBits( virtualSize, 1 ); gi.MSG_EndCGM(); +#ifdef OPM_FEATURES if( sv_specialgame->integer ) { if( isDimensional ) { SetBroadcast(); - /* gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_3D )); WriteNumber(); gi.MSG_WriteCoord( org[ 0 ] ); @@ -1111,19 +1110,16 @@ void Hud::Refresh( int clientNumber ) gi.MSG_WriteBits( !!always_show, 1 ); gi.MSG_WriteBits( !!depth, 1 ); gi.MSG_EndCGM(); - */ } if( fade_alpha ) { SetBroadcast(); - /* gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_FADE )); WriteNumber(); gi.MSG_WriteFloat( fade_alpha_current ); gi.MSG_EndCGM(); - */ SetBroadcast(); @@ -1137,7 +1133,6 @@ void Hud::Refresh( int clientNumber ) { SetBroadcast(); - /* gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_MOVE )); WriteNumber(); gi.MSG_WriteFloat( fade_move_current ); @@ -1150,12 +1145,10 @@ void Hud::Refresh( int clientNumber ) gi.MSG_WriteShort( ( short )fade_move_x_target ); gi.MSG_WriteShort( ( short )fade_move_y_target ); gi.MSG_EndCGM(); - */ } if( fade_timer_flags & TIMER_ACTIVE ) { - /* SetBroadcast(); gi.MSG_StartCGM( BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_TIMER )); @@ -1170,7 +1163,6 @@ void Hud::Refresh( int clientNumber ) } gi.MSG_EndCGM(); - */ } } #endif @@ -1232,11 +1224,15 @@ void Hud::SetBroadcast( int clientNumber ) void Hud::WriteNumber() { +#ifdef OPM_FEATURES if(sv_specialgame->integer ) { gi.MSG_WriteShort( number ); } else { gi.MSG_WriteByte( number ); } +#else + gi.MSG_WriteByte(number); +#endif } #endif diff --git a/code/fgame/hud.h b/code/fgame/hud.h index 155915cc..61b53a54 100644 --- a/code/fgame/hud.h +++ b/code/fgame/hud.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // hud.h: New HUD handler for MoHAA // -#ifndef __HUD_H__ -#define __HUD_H__ +#pragma once #include "listener.h" #include "container.h" @@ -208,5 +207,3 @@ public: }; extern Container< Hud * > hudElements; - -#endif /* __HUD_H__ */ diff --git a/code/fgame/huddraw.cpp b/code/fgame/huddraw.cpp index 89bb209f..79784439 100644 --- a/code/fgame/huddraw.cpp +++ b/code/fgame/huddraw.cpp @@ -28,11 +28,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA void HudWriteNumber( int num ) { +#ifdef OPM_FEATURES if(sv_specialgame->integer ) { gi.MSG_WriteShort( num ); } else { gi.MSG_WriteByte( num ); } +#else + gi.MSG_WriteByte(num); +#endif } void HudDrawShader( int info, const char *name ) @@ -41,7 +45,11 @@ void HudDrawShader( int info, const char *name ) gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_SHADER)); HudWriteNumber( info ); // c = info gi.MSG_WriteString(name); // s = name (shader_name) - gi.MSG_EndCGM(); + gi.MSG_EndCGM(); + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawShader(info, name); + } } void HudDrawAlign( int info, int horizontalAlign, int verticalAlign ) @@ -61,6 +69,10 @@ void HudDrawAlign( int info, int horizontalAlign, int verticalAlign ) gi.MSG_EndCGM(); + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawAlign(info, horizontalAlign, verticalAlign); + } + } void HudDrawRect(int info, int x, int y, int width, int height) @@ -73,7 +85,10 @@ void HudDrawRect(int info, int x, int y, int width, int height) gi.MSG_WriteShort(width); // c = probably "width" gi.MSG_WriteShort(height); // c = probably "height" gi.MSG_EndCGM(); - + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawRect(info, x, y, width, height); + } } void HudDrawVirtualSize(int info, int virtualScreen) @@ -81,20 +96,7 @@ void HudDrawVirtualSize(int info, int virtualScreen) gi.SetBroadcastAll(); gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_HUDDRAW_VIRTUALSIZE)); HudWriteNumber( info ); // c = info - - /*__asm - { - pushad - pushfd - mov eax, virtualScreen - NEG eax - SBB eax, eax - NEG eax - mov virtualScreen, eax - popfd - popad - }*/ - + gi.MSG_WriteBits(!!virtualScreen, 1); // value = ? bits = 1 // value = esi // esi = virtualScreen @@ -104,7 +106,10 @@ void HudDrawVirtualSize(int info, int virtualScreen) // call gi.MSG_EndCGM(); - + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawVirtualSize(info, virtualScreen); + } } void HudDrawColor(int info, float *color) @@ -121,7 +126,11 @@ void HudDrawColor(int info, float *color) gi.MSG_WriteByte(temp[0]); // c = color[2] gi.MSG_WriteByte(temp[1]); // c = color[1] - Values can be messed up. To be tested. gi.MSG_WriteByte(temp[2]); // c = color[3] / - gi.MSG_EndCGM(); + gi.MSG_EndCGM(); + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawColor(info, color); + } // Note: Each float value is multiplied by 255.0 and converted to long using ftol function, thats why it's using WriteByte } @@ -137,6 +146,10 @@ void HudDrawAlpha(int info, float alpha) gi.MSG_WriteByte(temp); // c = alpha gi.MSG_EndCGM(); + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawAlpha(info, alpha); + } + // Note: alpha is multiplied by 255.0 and converted to long using ftol function } @@ -149,6 +162,9 @@ void HudDrawString(int info, const char *string) gi.MSG_WriteString(string); // s = string (to show) gi.MSG_EndCGM(); + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawString(info, string); + } } void HudDrawFont(int info, const char *fontName) @@ -158,7 +174,10 @@ void HudDrawFont(int info, const char *fontName) HudWriteNumber( info ); // c = info gi.MSG_WriteString(fontName); // s = fontName (to use) gi.MSG_EndCGM(); - + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + gi.HudDrawFont(info, fontName); + } } void HudDraw3d( int index, vec3_t vector, int ent_num, qboolean bAlwaysShow, qboolean depth ) diff --git a/code/fgame/huddraw.h b/code/fgame/huddraw.h index d924394d..3d15bb82 100644 --- a/code/fgame/huddraw.h +++ b/code/fgame/huddraw.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // huddraw.cpp : This is a HudDraw Functions Code section with huddraw functions reversed for // altering clients HUD -#ifndef __HUDDRAW_H__ -#define __HUDDRAW_H__ +#pragma once #include "g_local.h" @@ -49,5 +48,3 @@ void iHudDrawAlpha( int cl_num, int info, float alpha ); void iHudDrawString( int cl_num, int info, const char *string ); void iHudDrawFont( int cl_num, int info, const char *fontName ); void iHudDrawTimer( int cl_num, int index, float duration, float fade_out_time ); - -#endif // __HUDDRAW_H__ diff --git a/code/fgame/inventoryitem.cpp b/code/fgame/inventoryitem.cpp index 08a47cfd..6bec826f 100644 --- a/code/fgame/inventoryitem.cpp +++ b/code/fgame/inventoryitem.cpp @@ -53,7 +53,7 @@ CLASS_DECLARATION( Weapon, InventoryItem, NULL ) InventoryItem::InventoryItem() { - entflags |= EF_INVENTORYITEM; + entflags |= ECF_INVENTORYITEM; if ( LoadingSavegame ) { @@ -65,7 +65,7 @@ InventoryItem::InventoryItem() InventoryItem::~InventoryItem() { - entflags &= ~EF_INVENTORYITEM; + entflags &= ~ECF_INVENTORYITEM; } void InventoryItem::ActivateItem @@ -77,7 +77,7 @@ void InventoryItem::ActivateItem { Vector pos, forward, right, up, vBarrel; - GetMuzzlePosition( &pos, &forward, &right, &up, &vBarrel ); + GetMuzzlePosition( pos, vBarrel, forward, right, up ); ClickItemAttack( pos, forward, diff --git a/code/fgame/inventoryitem.h b/code/fgame/inventoryitem.h index f9cbd738..b14129ce 100644 --- a/code/fgame/inventoryitem.h +++ b/code/fgame/inventoryitem.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // inventoryitem.h: Items that are visible in the player's inventory -#ifndef __INVITEM_H__ -#define __INVITEM_H__ +#pragma once #include "weapon.h" @@ -52,5 +51,3 @@ class AntiSBJuice : public InventoryItem void UseEvent( Event *ev ); }; - -#endif /* inventoryitem.h */ diff --git a/code/fgame/ipfilter.cpp b/code/fgame/ipfilter.cpp index 1e73af6e..c823702e 100644 --- a/code/fgame/ipfilter.cpp +++ b/code/fgame/ipfilter.cpp @@ -298,7 +298,7 @@ void SVCmd_WriteIP_f byte b[ 4 ]; int i; - sprintf( name, "%s/listip.cfg", GAMEVERSION ); + Com_sprintf( name, sizeof( name ), "%s/listip.cfg", GAMEVERSION ); gi.SendServerCommand( 0, "print \"Writing %s.\n\"", name ); f = fopen( name, "wb" ); diff --git a/code/fgame/ipfilter.h b/code/fgame/ipfilter.h index a09c9216..28fb7a69 100644 --- a/code/fgame/ipfilter.h +++ b/code/fgame/ipfilter.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,11 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ipfilter.h: DESCRIPTION: // -#ifndef __IPFILTER_H__ -#define __IPFILTER_H__ +#pragma once #include "g_local.h" qboolean SV_FilterPacket( const char *from ); - -#endif /* !__IPFILTER_H__ */ diff --git a/code/fgame/item.cpp b/code/fgame/item.cpp index 09fb1b5e..5c4a3bfc 100644 --- a/code/fgame/item.cpp +++ b/code/fgame/item.cpp @@ -123,7 +123,7 @@ const char *GetItemName(const char *prefix, qboolean *mohprefix) *mohprefix = false; } - return NULL; + return "Unarmed"; } const char *GetItemPrefix(const char *name, qboolean *mohprefix) @@ -142,7 +142,7 @@ const char *GetItemPrefix(const char *name, qboolean *mohprefix) *mohprefix = false; } - return NULL; + return "unarmed"; } Event EV_Item_Pickup @@ -291,6 +291,7 @@ Event EV_Item_SetPickupSound EV_NORMAL ); +#ifdef OPM_FEATURES Event EV_Item_ViewModelPrefix ( "viewmodelprefix", @@ -310,6 +311,7 @@ Event EV_Item_UpdatePrefix "internal event - update the custom viewmodel prefix", EV_NORMAL ); +#endif CLASS_DECLARATION(Trigger, Item, NULL) { {&EV_Trigger_Effect, &Item::ItemTouch }, @@ -332,8 +334,10 @@ CLASS_DECLARATION(Trigger, Item, NULL) { {&EV_Item_SetDMAmount, &Item::SetDMAmountEvent }, {&EV_Item_SetDMMaxAmount, &Item::SetDMMaxAmount }, {&EV_Item_SetPickupSound, &Item::SetPickupSound }, +#ifdef OPM_FEATURES {&EV_Item_ViewModelPrefix, &Item::EventViewModelPrefix }, {&EV_Item_UpdatePrefix, &Item::updatePrefix }, +#endif {NULL, NULL } }; @@ -341,7 +345,7 @@ Item::Item() { str fullname; - entflags |= EF_ITEM; + entflags |= ECF_ITEM; AddWaitTill(STRING_PICKUP); @@ -403,7 +407,7 @@ Item::~Item() owner = NULL; } - entflags &= ~EF_ITEM; + entflags &= ~ECF_ITEM; } void Item::RemoveFromOwner(void) @@ -414,15 +418,11 @@ void Item::RemoveFromOwner(void) void Item::Delete(void) { - if (g_iInThinks) { - if (owner) { - RemoveFromOwner(); - } - - PostEvent(EV_Remove, 0); - } else { - delete this; + if (g_iInThinks && owner) { + RemoveFromOwner(); } + + Animate::Delete(); } void Item::SetNoRemove(Event *ev) @@ -555,10 +555,12 @@ void Item::SetOwner(Sentient *ent) CancelEventsOfType(EV_Item_DropToFloor); CancelEventsOfType(EV_Remove); +#ifdef OPM_FEATURES Event *ev = new Event(EV_Item_UpdatePrefix); ev->AddEntity(ent); PostEvent(ev, EV_POSTSPAWN); +#endif } Sentient *Item::GetOwner(void) @@ -619,14 +621,6 @@ Item *Item::ItemPickup(Entity *other, qboolean add_to_inventory) } } - if (!no_remove) { - hideModel(); - - if (!Respawnable()) { - PostEvent(EV_Remove, FRAMETIME); - } - } - if (Respawnable()) { PostEvent(EV_Item_Respawn, RespawnTime()); } @@ -759,7 +753,7 @@ void Item::setName(const char *i) item_name = i; item_index = gi.itemindex(i); - strcpy(edict->entname, i); + Q_strncpyz(edict->entname, i, sizeof(edict->entname)); prefix = GetItemPrefix(item_name); if (prefix) { @@ -814,7 +808,7 @@ void Item::SetMaxAmount(Event *ev) void Item::SetDMAmountEvent(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } setAmount(ev->GetInteger(1)); @@ -822,7 +816,7 @@ void Item::SetDMAmountEvent(Event *ev) void Item::SetDMMaxAmount(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } setAmount(ev->GetInteger(1)); @@ -905,6 +899,22 @@ void Item::Landed(Event *ev) setMoveType(MOVETYPE_NONE); } +Listener *Item::GetScriptOwner() +{ + return owner; +} + +void Item::SetScriptOwner(Listener *newOwner) +{ + if (!newOwner || !newOwner->isSubclassOf(Sentient)) { + owner = NULL; + return; + } + + owner = static_cast(newOwner); +} + +#ifdef OPM_FEATURES void Item::EventViewModelPrefix(Event *ev) { int i; @@ -930,7 +940,7 @@ void Item::EventViewModelPrefix(Event *ev) void Item::updatePrefix(Event *ev) { - if (!level.specialgame) { + if (!sv_specialgame->integer) { return; } @@ -938,8 +948,6 @@ void Item::updatePrefix(Event *ev) return; } - // FIXME: delete - /* Entity *ent = ev->GetEntity( 1 ); gi.MSG_SetClient( ent->edict - g_entities ); @@ -948,8 +956,8 @@ void Item::updatePrefix(Event *ev) gi.MSG_WriteString( item_name.c_str() ); gi.MSG_WriteString( m_sVMprefix.c_str() ); gi.MSG_EndCGM(); - */ } +#endif CLASS_DECLARATION(Item, DynItem, NULL) { {&EV_Kill, &DynItem::UnlinkItem}, diff --git a/code/fgame/item.h b/code/fgame/item.h index 647f69f6..69516ca5 100644 --- a/code/fgame/item.h +++ b/code/fgame/item.h @@ -121,11 +121,21 @@ public: void Archive(Archiver& arc) override; +public: + // + // Added in OPM + // + + Listener *GetScriptOwner() override; + void SetScriptOwner(Listener *newOwner) override; + +#ifdef OPM_FEATURES // // Custom openmohaa stuff // void EventViewModelPrefix(Event *ev); void updatePrefix(Event *ev); +#endif }; inline void Item::Archive(Archiver& arc) diff --git a/code/fgame/level.cpp b/code/fgame/level.cpp index 9eccba5b..05ee31ac 100644 --- a/code/fgame/level.cpp +++ b/code/fgame/level.cpp @@ -33,12 +33,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "dm_manager.h" #include "player.h" #include "Entities.h" +#include "health.h" #include "scriptmaster.h" #include "scriptthread.h" #include "scriptvariable.h" #include "scriptexception.h" +#include + Level level; gclient_t *spawn_client = NULL; @@ -96,7 +99,8 @@ Event EV_Level_GetAlarm Event EV_Level_SetAlarm ( - "alarm", EV_DEFAULT, + "alarm", + EV_DEFAULT, "i", "alarm_status", "zero = global level alarm off," @@ -116,7 +120,7 @@ Event EV_Level_SetNoDropHealth Event EV_Level_SetNoDropWeapons ( - "nodropweapon", + "nodropweapons", EV_DEFAULT, "i", "alarm_status", @@ -194,8 +198,7 @@ Event EV_Level_SetDMRespawning EV_SETTER ); -Event EV_Level_SetDMRespawning2 -( +Event EV_Level_SetDMRespawning2( "dmrespawning", EV_DEFAULT, "i", @@ -204,8 +207,7 @@ Event EV_Level_SetDMRespawning2 "to 0 to disable respawns within a round" ); -Event EV_Level_GetDMRoundLimit -( +Event EV_Level_GetDMRoundLimit( "dmroundlimit", EV_DEFAULT, NULL, @@ -214,8 +216,7 @@ Event EV_Level_GetDMRoundLimit EV_GETTER ); -Event EV_Level_SetDMRoundLimit -( +Event EV_Level_SetDMRoundLimit( "dmroundlimit", EV_DEFAULT, "i", @@ -224,8 +225,7 @@ Event EV_Level_SetDMRoundLimit EV_SETTER ); -Event EV_Level_SetDMRoundLimit2 -( +Event EV_Level_SetDMRoundLimit2( "dmroundlimit", EV_DEFAULT, "i", @@ -254,8 +254,7 @@ Event EV_Level_SetClockSide EV_SETTER ); -Event EV_Level_SetClockSide2 -( +Event EV_Level_SetClockSide2( "clockside", EV_DEFAULT, "s", @@ -267,7 +266,8 @@ Event EV_Level_SetClockSide2 Event EV_Level_GetBombPlantTeam ( - "planting_team", EV_DEFAULT, + "planting_team", + EV_DEFAULT, NULL, NULL, "Gets which is planting the bomb," @@ -286,8 +286,7 @@ Event EV_Level_SetBombPlantTeam EV_SETTER ); -Event EV_Level_SetBombPlantTeam2 -( +Event EV_Level_SetBombPlantTeam2( "planting_team", EV_DEFAULT, "s", @@ -392,7 +391,7 @@ Event EV_Level_GetRoundBased EV_DEFAULT, NULL, NULL, - "Gets wether or not the game is currently round based or not", + "Gets whether or not the game is currently round based or not", EV_GETTER ); @@ -402,7 +401,7 @@ Event EV_Level_GetObjectiveBased EV_DEFAULT, NULL, NULL, - "Gets wether or not the game is currently objective based or not", + "Gets whether or not the game is currently objective based or not", EV_GETTER ); @@ -592,7 +591,8 @@ Event EV_Level_AddBadPlace EV_DEFAULT, "svfSF", "name origin radius [team] [duration]", - "Enables a 'bad place' for AI of team 'american', 'german', or (default) 'both' to avoid, and optionally gives it a duration", + "Enables a 'bad place' for AI of team 'american', 'german', or (default) 'both' to avoid, and optionally gives it " + "a duration", EV_NORMAL ); @@ -616,80 +616,106 @@ Event EV_Level_IgnoreClock EV_NORMAL ); +// +// Added in OPM +// +Event EV_Level_SetForceTeamObjectiveLocation +( + "force_team_objective", + EV_DEFAULT, + "i", + "force", + "Whether or not to force using a separate objective location for each team.\n" + "1 (forced on TOW/Liberation match): different location for each team\n" + "0 (default): teams use same location on non-TOW/non-Liberation match\n", + EV_SETTER +); +Event EV_Level_GetForceTeamObjectiveLocation +( + "force_team_objective", + EV_DEFAULT, + NULL, + NULL, + "Return 1 if each team has a separate objective location", + EV_GETTER +); + extern Event EV_Entity_Start; CLASS_DECLARATION(Listener, Level, NULL) { - {&EV_Level_GetTime, &Level::GetTime }, - {&EV_Level_GetTotalSecrets, &Level::GetTotalSecrets }, - {&EV_Level_GetFoundSecrets, &Level::GetFoundSecrets }, - {&EV_Level_PreSpawnSentient, &Level::PreSpawnSentient }, - {&EV_Level_GetAlarm, &Level::GetAlarm }, - {&EV_Level_SetAlarm, &Level::SetAlarm }, - {&EV_Level_SetNoDropHealth, &Level::SetNoDropHealth }, - {&EV_Level_SetNoDropWeapons, &Level::SetNoDropWeapons }, - {&EV_Level_GetRoundStarted, &Level::EventGetRoundStarted }, - {&EV_Level_GetLoopProtection, &Level::GetLoopProtection }, - {&EV_Level_SetLoopProtection, &Level::SetLoopProtection }, - {&EV_Level_GetPapersLevel, &Level::GetPapersLevel }, - {&EV_Level_SetPapersLevel, &Level::SetPapersLevel }, - {&EV_Level_GetDMRespawning, &Level::EventGetDMRespawning }, - {&EV_Level_SetDMRespawning, &Level::EventSetDMRespawning }, - {&EV_Level_SetDMRespawning2, &Level::EventSetDMRespawning }, - {&EV_Level_GetDMRoundLimit, &Level::EventGetDMRoundLimit }, - {&EV_Level_SetDMRoundLimit, &Level::EventSetDMRoundLimit }, - {&EV_Level_SetDMRoundLimit2, &Level::EventSetDMRoundLimit }, - {&EV_Level_GetClockSide, &Level::EventGetClockSide }, - {&EV_Level_SetClockSide, &Level::EventSetClockSide }, - {&EV_Level_SetClockSide2, &Level::EventSetClockSide }, - {&EV_Level_GetBombPlantTeam, &Level::EventGetBombPlantTeam }, - {&EV_Level_SetBombPlantTeam, &Level::EventSetBombPlantTeam }, - {&EV_Level_SetBombPlantTeam2, &Level::EventSetBombPlantTeam }, - {&EV_Level_GetTargetsToDestroy, &Level::EventGetTargetsToDestroy}, - {&EV_Level_SetTargetsToDestroy, &Level::EventSetTargetsToDestroy}, - {&EV_Level_SetTargetsToDestroy2, &Level::EventSetTargetsToDestroy}, - {&EV_Level_GetTargetsDestroyed, &Level::EventGetTargetsDestroyed}, - {&EV_Level_SetTargetsDestroyed, &Level::EventSetTargetsDestroyed}, - {&EV_Level_SetTargetsDestroyed2, &Level::EventSetTargetsDestroyed}, - {&EV_Level_GetBombsPlanted, &Level::EventGetBombsPlanted }, - {&EV_Level_SetBombsPlanted, &Level::EventSetBombsPlanted }, - {&EV_Level_SetBombsPlanted2, &Level::EventSetBombsPlanted }, - {&EV_Level_GetRoundBased, &Level::EventGetRoundBased }, - {&EV_Level_GetObjectiveBased, &Level::EventGetObjectiveBased }, - {&EV_Level_Rain_Density_Set, &Level::EventRainDensitySet }, - {&EV_Level_Rain_Density_Get, &Level::EventRainDensityGet }, - {&EV_Level_Rain_Speed_Set, &Level::EventRainSpeedSet }, - {&EV_Level_Rain_Speed_Get, &Level::EventRainSpeedGet }, - {&EV_Level_Rain_Speed_Vary_Set, &Level::EventRainSpeedVarySet }, - {&EV_Level_Rain_Speed_Vary_Get, &Level::EventRainSpeedVaryGet }, - {&EV_Level_Rain_Slant_Set, &Level::EventRainSlantSet }, - {&EV_Level_Rain_Slant_Get, &Level::EventRainSlantGet }, - {&EV_Level_Rain_Length_Set, &Level::EventRainLengthSet }, - {&EV_Level_Rain_Length_Get, &Level::EventRainLengthGet }, - {&EV_Level_Rain_Min_Dist_Set, &Level::EventRainMin_DistSet }, - {&EV_Level_Rain_Min_Dist_Get, &Level::EventRainMin_DistGet }, - {&EV_Level_Rain_Width_Set, &Level::EventRainWidthSet }, - {&EV_Level_Rain_Width_Get, &Level::EventRainWidthGet }, - {&EV_Level_Rain_Shader_Set, &Level::EventRainShaderSet }, - {&EV_Level_Rain_Shader_Get, &Level::EventRainShaderGet }, - {&EV_Level_Rain_NumShaders_Set, &Level::EventRainShaderSet }, - {&EV_Level_Rain_NumShaders_Get, &Level::EventRainShaderGet }, - {&EV_Level_AddBadPlace, &Level::EventAddBadPlace }, - {&EV_Level_RemoveBadPlace, &Level::EventRemoveBadPlace }, - {&EV_Level_IgnoreClock, &Level::EventIgnoreClock }, - {NULL, NULL } + {&EV_Level_GetTime, &Level::GetTime }, + {&EV_Level_GetTotalSecrets, &Level::GetTotalSecrets }, + {&EV_Level_GetFoundSecrets, &Level::GetFoundSecrets }, + {&EV_Level_PreSpawnSentient, &Level::PreSpawnSentient }, + {&EV_Level_GetAlarm, &Level::GetAlarm }, + {&EV_Level_SetAlarm, &Level::SetAlarm }, + {&EV_Level_SetNoDropHealth, &Level::SetNoDropHealth }, + {&EV_Level_SetNoDropWeapons, &Level::SetNoDropWeapons }, + {&EV_Level_GetRoundStarted, &Level::EventGetRoundStarted }, + {&EV_Level_GetLoopProtection, &Level::GetLoopProtection }, + {&EV_Level_SetLoopProtection, &Level::SetLoopProtection }, + {&EV_Level_GetPapersLevel, &Level::GetPapersLevel }, + {&EV_Level_SetPapersLevel, &Level::SetPapersLevel }, + {&EV_Level_GetDMRespawning, &Level::EventGetDMRespawning }, + {&EV_Level_SetDMRespawning, &Level::EventSetDMRespawning }, + {&EV_Level_SetDMRespawning2, &Level::EventSetDMRespawning }, + {&EV_Level_GetDMRoundLimit, &Level::EventGetDMRoundLimit }, + {&EV_Level_SetDMRoundLimit, &Level::EventSetDMRoundLimit }, + {&EV_Level_SetDMRoundLimit2, &Level::EventSetDMRoundLimit }, + {&EV_Level_GetClockSide, &Level::EventGetClockSide }, + {&EV_Level_SetClockSide, &Level::EventSetClockSide }, + {&EV_Level_SetClockSide2, &Level::EventSetClockSide }, + {&EV_Level_GetBombPlantTeam, &Level::EventGetBombPlantTeam }, + {&EV_Level_SetBombPlantTeam, &Level::EventSetBombPlantTeam }, + {&EV_Level_SetBombPlantTeam2, &Level::EventSetBombPlantTeam }, + {&EV_Level_GetTargetsToDestroy, &Level::EventGetTargetsToDestroy }, + {&EV_Level_SetTargetsToDestroy, &Level::EventSetTargetsToDestroy }, + {&EV_Level_SetTargetsToDestroy2, &Level::EventSetTargetsToDestroy }, + {&EV_Level_GetTargetsDestroyed, &Level::EventGetTargetsDestroyed }, + {&EV_Level_SetTargetsDestroyed, &Level::EventSetTargetsDestroyed }, + {&EV_Level_SetTargetsDestroyed2, &Level::EventSetTargetsDestroyed }, + {&EV_Level_GetBombsPlanted, &Level::EventGetBombsPlanted }, + {&EV_Level_SetBombsPlanted, &Level::EventSetBombsPlanted }, + {&EV_Level_SetBombsPlanted2, &Level::EventSetBombsPlanted }, + {&EV_Level_GetRoundBased, &Level::EventGetRoundBased }, + {&EV_Level_GetObjectiveBased, &Level::EventGetObjectiveBased }, + {&EV_Level_Rain_Density_Set, &Level::EventRainDensitySet }, + {&EV_Level_Rain_Density_Get, &Level::EventRainDensityGet }, + {&EV_Level_Rain_Speed_Set, &Level::EventRainSpeedSet }, + {&EV_Level_Rain_Speed_Get, &Level::EventRainSpeedGet }, + {&EV_Level_Rain_Speed_Vary_Set, &Level::EventRainSpeedVarySet }, + {&EV_Level_Rain_Speed_Vary_Get, &Level::EventRainSpeedVaryGet }, + {&EV_Level_Rain_Slant_Set, &Level::EventRainSlantSet }, + {&EV_Level_Rain_Slant_Get, &Level::EventRainSlantGet }, + {&EV_Level_Rain_Length_Set, &Level::EventRainLengthSet }, + {&EV_Level_Rain_Length_Get, &Level::EventRainLengthGet }, + {&EV_Level_Rain_Min_Dist_Set, &Level::EventRainMin_DistSet }, + {&EV_Level_Rain_Min_Dist_Get, &Level::EventRainMin_DistGet }, + {&EV_Level_Rain_Width_Set, &Level::EventRainWidthSet }, + {&EV_Level_Rain_Width_Get, &Level::EventRainWidthGet }, + {&EV_Level_Rain_Shader_Set, &Level::EventRainShaderSet }, + {&EV_Level_Rain_Shader_Get, &Level::EventRainShaderGet }, + {&EV_Level_Rain_NumShaders_Set, &Level::EventRainNumShadersSet }, + {&EV_Level_Rain_NumShaders_Get, &Level::EventRainNumShadersGet }, + {&EV_Level_AddBadPlace, &Level::EventAddBadPlace }, + {&EV_Level_RemoveBadPlace, &Level::EventRemoveBadPlace }, + {&EV_Level_IgnoreClock, &Level::EventIgnoreClock }, + {&EV_Level_SetForceTeamObjectiveLocation, &Level::SetForceTeamObjectiveLocation}, + {&EV_Level_GetForceTeamObjectiveLocation, &Level::GetForceTeamObjectiveLocation}, + {NULL, NULL } }; -void Level::GetTime(Event* ev) +void Level::GetTime(Event *ev) { ev->AddFloat(level.time); } -void Level::GetTotalSecrets(Event* ev) +void Level::GetTotalSecrets(Event *ev) { ev->AddInteger(total_secrets); } -void Level::GetFoundSecrets(Event* ev) +void Level::GetFoundSecrets(Event *ev) { ev->AddInteger(found_secrets); } @@ -759,26 +785,30 @@ void Level::Init(void) m_fade_color = vec_zero; m_fade_style = additive; - m_letterbox_dir = letterbox_out; - m_numArenas = 1; - m_fade_alpha = 0; m_letterbox_fraction = 0; + m_letterbox_time = -1; m_letterbox_time_start = 0; + m_letterbox_dir = letterbox_out; - m_voteTime = 0; - m_numVoters = 0; + m_numArenas = 1; + + m_voteTime = 0; + m_nextVoteTime = 0; + m_voteYes = 0; + m_voteNo = 0; + m_numVoters = 0; m_LoopProtection = true; m_LoopDrop = true; m_letterbox_time = -1.0f; - m_voteYes = 0; - m_voteNo = 0; - - m_vObjectiveLocation = vec_zero; + m_vObjectiveLocation = vec_zero; + m_vAlliedObjectiveLocation = vec_zero; + m_vAxisObjectiveLocation = vec_zero; + m_bForceTeamObjectiveLocation = false; svsEndTime = 0; @@ -786,16 +816,32 @@ void Level::Init(void) mHealthPopCount = 0; mbNoDropHealth = false; + mbNoDropWeapons = false; - spawning = false; + spawning = false; + m_bIgnoreClock = false; + svsStartFloatTime = 0; + + m_fLandmarkXDistMin = 0; + m_fLandmarkXDistMax = 0; + m_fLandmarkYDistMin = 0; + m_fLandmarkYDistMax = 0; + m_pLandmarks = NULL; + m_iMaxLandmarks = 0; + m_iLandmarksCount = 0; + + m_badPlaces.ClearObjectList(); + + m_pAIStats = NULL; - m_bSpawnBot = false; m_bScriptSpawn = false; m_bRejectSpawn = false; } void Level::CleanUp(qboolean samemap, qboolean resetConfigStrings) { + int i; + DisableListenerNotify++; if (g_gametype->integer != GT_SINGLE_PLAYER) { @@ -833,18 +879,24 @@ void Level::CleanUp(qboolean samemap, qboolean resetConfigStrings) if (active_edicts.next->entity) { delete active_edicts.next->entity; - } - else { + } else { FreeEdict(active_edicts.next); } } + // + // Remove all archived entities + // + for (i = m_SimpleArchivedEntities.NumObjects(); i > 0; i--) { + delete m_SimpleArchivedEntities.ObjectAt(i); + } + cinematic = false; - ai_on = true; + ai_on = true; near_exit = false; mission_failed = false; - died_already = false; + died_already = false; globals.num_entities = game.maxclients + 1; gi.LocateGameData(g_entities, game.maxclients + 1, sizeof(gentity_t), &game.clients[0].ps, sizeof(gclient_t)); @@ -881,6 +933,7 @@ void Level::CleanUp(qboolean samemap, qboolean resetConfigStrings) gi.cvar_set("bosshealth", "0"); Actor::ResetBodyQueue(); + Health::ResetHealthQueue(); if (world) { world->FreeTargetList(); @@ -916,12 +969,22 @@ void Level::CleanUp(qboolean samemap, qboolean resetConfigStrings) gi.setConfigstring(CS_RAIN_NUMSHADERS, "0"); gi.setConfigstring(CS_CURRENT_OBJECTIVE, ""); - for (int i = CS_OBJECTIVES; i < CS_OBJECTIVES + MAX_OBJECTIVES; i++) { - gi.setConfigstring(i, ""); + for (i = 0; i < MAX_OBJECTIVES; i++) { + gi.setConfigstring(CS_OBJECTIVES + i, ""); } + + gi.setConfigstring(CS_VOTE_TIME, ""); + gi.setConfigstring(CS_VOTE_STRING, ""); + gi.setConfigstring(CS_VOTE_YES, ""); + gi.setConfigstring(CS_VOTE_NO, ""); + gi.setConfigstring(CS_VOTE_UNDECIDED, ""); } DisableListenerNotify--; + + svsStartFloatTime = svsFloatTime; + + FreeLandmarks(); } /* @@ -954,14 +1017,38 @@ void Level::ResetEdicts(void) qboolean Level::inhibitEntity(int spawnflags) { - if (!developer->integer && (spawnflags & SPAWNFLAG_DEVELOPMENT)) { - return qtrue; - } - if (!detail->integer && (spawnflags & SPAWNFLAG_DETAIL)) { return qtrue; } + if (g_gametype->integer != GT_SINGLE_PLAYER) { + return (spawnflags & SPAWNFLAG_NOT_DEATHMATCH) ? qtrue : qfalse; + } + + if (!developer->integer && (spawnflags & SPAWNFLAG_DEVELOPMENT)) { + return qtrue; + } + + if (!Q_stricmp(mapname, "t3l2")) { + // Added in 2.0. + // FIXME: there should be a better way to handle + // specific maps + return (spawnflags & SPAWNFLAG_NOT_EASY) ? qtrue : qfalse; + } + + switch (skill->integer) { + case 0: + return (spawnflags & SPAWNFLAG_NOT_EASY) != 0; + + case 1: + return (spawnflags & SPAWNFLAG_NOT_MEDIUM) != 0; + + case 2: + case 3: + return (spawnflags & SPAWNFLAG_NOT_HARD); + } + + /* #ifdef _CONSOLE if (spawnflags & SPAWNFLAG_NOCONSOLE) #else @@ -970,29 +1057,7 @@ qboolean Level::inhibitEntity(int spawnflags) { return qtrue; } - - if (g_gametype->integer) { - if (spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { - return qtrue; - } - - return qfalse; - } - - switch (skill->integer) { - case 0: - return (spawnflags & SPAWNFLAG_NOT_EASY) != 0; - break; - - case 1: - return (spawnflags & SPAWNFLAG_NOT_MEDIUM) != 0; - break; - - case 2: - case 3: - return (spawnflags & SPAWNFLAG_NOT_HARD); - break; - } + */ return qfalse; } @@ -1009,28 +1074,34 @@ void Level::setSkill(int value) void Level::setTime(int levelTime) { - svsTime = levelTime; - inttime = levelTime - svsStartTime; + svsTime = levelTime; + inttime = levelTime - svsStartTime; svsFloatTime = levelTime / 1000.0f; - time = inttime / 1000.0f; + time = inttime / 1000.0f; } void Level::setFrametime(int frametime) { - intframetime = frametime; + intframetime = frametime; this->frametime = frametime / 1000.0f; } -void Level::SpawnEntities(char* entities, int svsTime) +void Level::SpawnEntities(char *entities, int svsTime) { - int inhibit, radnum = 0, count = 0; - const char* value; - SpawnArgs args; - Listener* listener; - Entity* ent; - int t1, t2; - int start, end; - char name[128]; + int inhibit, radnum = 0, count = 0; + const char *value; + SpawnArgs args; + Listener *listener; + Entity *ent; + int t1, t2; + int start, end; + char name[128]; + + if (gi.Cvar_Get("g_invulnoverride", "0", 0)->integer == 1) { + // Added in 2.30 + // Clear the invulnerable override when loading + gi.cvar_set("g_invulnoverride", "0"); + } Com_Printf("-------------------- Spawning Entities -----------------------\n"); @@ -1039,9 +1110,9 @@ void Level::SpawnEntities(char* entities, int svsTime) // set up time so functions still have valid times setTime(svsTime); - setFrametime(50); + setFrametime(50); - gi.LoadResource("*144"); + gi.LoadResource("*144"); setSkill(skill->integer); @@ -1049,35 +1120,38 @@ void Level::SpawnEntities(char* entities, int svsTime) sv_numtraces = 0; // parse world - entities = args.Parse(entities); + entities = args.Parse(entities); spawn_entnum = ENTITYNUM_WORLD; args.SpawnInternal(); - gi.LoadResource("*147"); + gi.LoadResource("*147"); // Set up for a new map - PathManager.LoadNodes(); + PathManager.LoadNodes(); - gi.LoadResource("*147a"); + gi.LoadResource("*147a"); Com_Printf("-------------------- Actual Spawning Entities -----------------------\n"); - start = gi.Milliseconds(); + start = gi.Milliseconds(); - // parse ents - inhibit = 0; + // parse ents + inhibit = 0; for (entities = args.Parse(entities); entities != NULL; entities = args.Parse(entities)) { // remove things (except the world) from different skill levels or deathmatch spawnflags = 0; - value = args.getArg("spawnflags"); + value = args.getArg("spawnflags"); if (value) { spawnflags = atoi(value); - if (inhibitEntity(spawnflags)) { - inhibit++; - continue; + value = args.getArg("classname"); + if (!value || (Q_stricmp(value, "info_pathnode") && Q_stricmp(value, "info_patharea"))) { + if (inhibitEntity(spawnflags)) { + inhibit++; + continue; + } } } @@ -1089,13 +1163,13 @@ void Level::SpawnEntities(char* entities, int svsTime) if (listener->isSubclassOf(Entity)) { count++; - ent = (Entity*)listener; + ent = (Entity *)listener; ent->radnum = radnum; Q_strncpyz(ent->edict->entname, ent->getClassID(), sizeof(ent->edict->entname)); ent->PostEvent(EV_Entity_Start, -1.0, 0); - sprintf(name, "i%d", radnum); + Com_sprintf(name, sizeof(name), "i%d", radnum); gi.LoadResource(name); } } @@ -1103,33 +1177,33 @@ void Level::SpawnEntities(char* entities, int svsTime) end = gi.Milliseconds(); - Com_Printf( - "-------------------- Actual Spawning Entities Done ------------------ %i ms\n", end - start - ); + Com_Printf("-------------------- Actual Spawning Entities Done ------------------ %i ms\n", end - start); - gi.LoadResource("*147b"); + gi.LoadResource("*147b"); world->UpdateConfigStrings(); - Event* ev = new Event(EV_Level_PreSpawnSentient); + Event *ev = new Event(EV_Level_PreSpawnSentient); PostEvent(ev, EV_SPAWNENTITIES); - L_ProcessPendingEvents(); + L_ProcessPendingEvents(); - gi.LoadResource("*148"); + gi.LoadResource("*148"); - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { dmManager.InitGame(); - } + } - gi.LoadResource("*148a"); + gi.LoadResource("*148a"); - if (game.maxclients == 1) { + // Added in OPM + // Check for single-player before pre-creating a player instance + if (game.maxclients == 1 && g_gametype->integer == GT_SINGLE_PLAYER) { spawn_entnum = 0; new Player; - } + } - gi.LoadResource("*148b"); + gi.LoadResource("*148b"); m_LoopProtection = false; RemoveWaitTill(STRING_PRESPAWN); @@ -1145,43 +1219,236 @@ void Level::SpawnEntities(char* entities, int svsTime) Com_Printf("%i entities inhibited\n", inhibit); Com_Printf("-------------------- Spawning Entities Done ------------------ %i ms\n", t2 - t1); + + // + // create landmarks + // + ComputeDMWaypoints(); } void Level::ComputeDMWaypoints() { - // FIXME: unimplemented + qboolean shouldSetDefaultLandmark; + float startXDistMin, startXDistMax; + float startYDistMin, startYDistMax; + int i; + + if (g_gametype->integer == GT_SINGLE_PLAYER) { + m_fLandmarkXDistMax = 1; + m_fLandmarkYDistMax = 1; + m_fLandmarkXDistMin = 0; + m_fLandmarkYDistMin = 0.0; + return; + } + + shouldSetDefaultLandmark = qfalse; + + // + // calculate the world bounds from entities + // + if (m_fLandmarkXDistMin == m_fLandmarkXDistMax && m_fLandmarkYDistMin == m_fLandmarkYDistMax + && m_fLandmarkXDistMax == m_fLandmarkYDistMax) { + shouldSetDefaultLandmark = qtrue; + + for (i = 0; i < game.maxentities; i++) { + gentity_t *ent = &g_entities[i]; + + if (ent->entity) { + AddLandmarkOrigin(ent->entity->origin); + shouldSetDefaultLandmark = qfalse; + } + } + } + + if (shouldSetDefaultLandmark) { + startXDistMax = 1; + startYDistMax = 1; + startXDistMin = 0; + startYDistMin = 0; + } else { + startYDistMax = m_fLandmarkYDistMax; + startYDistMin = m_fLandmarkYDistMin; + startXDistMax = m_fLandmarkXDistMax; + startXDistMin = m_fLandmarkXDistMin; + } + + m_fLandmarkXDistMin = startXDistMin + (startXDistMax - startXDistMin) / 3.f; + m_fLandmarkXDistMax = startXDistMin + (startXDistMax - startXDistMin) * 2.f / 3.f; + m_fLandmarkYDistMin = startYDistMin + (startYDistMax - startYDistMin) / 3.f; + m_fLandmarkYDistMax = startYDistMin + (startYDistMax - startYDistMin) * 2.f / 3.f; } void Level::AddLandmarkOrigin(const Vector& origin) { - // FIXME: unimplemented + float yaw; + vec3_t angles; + vec3_t dir; + float dist; + + yaw = origin.toYaw(); + + angles[0] = angles[2] = 0; + angles[1] = yaw + 90 - world->m_fNorth; + AngleVectors(angles, dir, NULL, NULL); + + dist = origin.lengthXY(); + VectorScale(dir, dist, dir); + + if (m_fLandmarkYDistMax == m_fLandmarkYDistMin && m_fLandmarkXDistMin == m_fLandmarkXDistMax + && m_fLandmarkYDistMax == m_fLandmarkXDistMin) { + m_fLandmarkYDistMin = dir[1]; + m_fLandmarkXDistMax = dir[0]; + m_fLandmarkYDistMax = dir[1] + 1.0; + m_fLandmarkXDistMin = dir[0] - 1.0; + } else { + if (m_fLandmarkYDistMin > dir[1]) { + m_fLandmarkYDistMin = dir[1]; + } + if (m_fLandmarkYDistMax < dir[1]) { + m_fLandmarkYDistMax = dir[1]; + } + if (m_fLandmarkXDistMax < dir[0]) { + m_fLandmarkXDistMax = dir[0]; + } + if (m_fLandmarkXDistMin > dir[0]) { + m_fLandmarkXDistMin = dir[0]; + } + } } void Level::AddLandmarkName(const str& name, const Vector& origin) { - // FIXME: unimplemented + landmark_t *landmark; + int i; + + if (m_pLandmarks) { + if (m_iLandmarksCount == m_iMaxLandmarks) { + // reallocate the landmark list with twice the size + landmark_t **oldLandmarks = m_pLandmarks; + + m_iMaxLandmarks *= 2; + m_pLandmarks = new landmark_t *[m_iMaxLandmarks]; + + for (i = 0; i < m_iLandmarksCount; i++) { + m_pLandmarks[i] = oldLandmarks[i]; + } + + delete[] oldLandmarks; + } + } else { + // create the landmark list for the first time + m_iMaxLandmarks = 8; + m_iLandmarksCount = 0; + m_pLandmarks = new landmark_t *[8]; + } + + // + // create a new landmark + // + landmark = m_pLandmarks[m_iLandmarksCount] = new landmark_t(); + landmark->m_sName = name; + landmark->m_vOrigin = origin; } void Level::FreeLandmarks() { - // FIXME: unimplemented + landmark_t *landmark; + + if (m_pLandmarks) { + int i; + + for (i = 0; i < m_iLandmarksCount; i++) { + landmark = m_pLandmarks[i]; + + if (landmark) { + delete landmark; + } + } + + delete[] m_pLandmarks; + m_pLandmarks = NULL; + m_iLandmarksCount = 0; + m_iMaxLandmarks = 0; + } } str Level::GetDynamicDMLocations(const Vector& origin) { - // FIXME: unimplemented - return ""; + str name = "nothing"; + int i; + float shortestDistSqr = 0; + + for (i = 0; i < m_iLandmarksCount; i++) { + landmark_t *landmark = m_pLandmarks[i]; + Vector delta = origin - landmark->m_vOrigin; + float distSqr = delta.lengthSquared(); + + if (i == 0 || distSqr < shortestDistSqr) { + shortestDistSqr = distSqr; + name = landmark->m_sName; + } + } + + return name; } str Level::GetDMLocation(const Vector& origin) { - // FIXME: unimplemented - return ""; + float yaw; + vec3_t angles; + vec3_t dir; + float dist; + + if (m_pLandmarks) { + // + // use the dynamic dm locations + // + return GetDynamicDMLocations(origin); + } + + yaw = origin.toYaw(); + + angles[0] = angles[2] = 0; + angles[1] = yaw + 90 - world->m_fNorth; + AngleVectors(angles, dir, NULL, NULL); + + dist = origin.lengthXY(); + VectorScale(dir, dist, dir); + + if (dir[0] >= m_fLandmarkXDistMin) { + if (dir[0] > m_fLandmarkXDistMax) { + if (dir[1] >= m_fLandmarkYDistMin) { + if (dir[1] > m_fLandmarkYDistMax) { + return "North East corner"; + } else { + return "East side"; + } + } else { + return "South East corner"; + } + } else if (dir[1] >= m_fLandmarkYDistMin) { + if (dir[1] > m_fLandmarkYDistMax) { + return "North side"; + } else { + return "center"; + } + } else { + return "South side"; + } + } else if (dir[1] >= m_fLandmarkYDistMin) { + if (dir[1] > m_fLandmarkYDistMax) { + return "North West corner"; + } else { + return "West side"; + } + } else { + return "South West corner"; + } } -void Level::PreSpawnSentient(Event* ev) +void Level::PreSpawnSentient(Event *ev) { - GameScript* script; + GameScript *script; // general initialization FindTeams(); @@ -1216,8 +1483,8 @@ bool Level::Spawned(void) void Level::ServerSpawned(void) { int i; - gclient_t* client; - gentity_t* ent; + gclient_t *client; + gentity_t *ent; for (i = 0, client = game.clients; i < game.maxclients; i++, client++) { client->ps.commandTime = svsTime; @@ -1235,36 +1502,34 @@ void Level::ServerSpawned(void) Director.Unpause(); Unregister(STRING_SPAWN); - } - else { + } else { Director.LoadMenus(); } spawning = false; } -void Level::SetMap(const char* themapname) +void Level::SetMap(const char *themapname) { - char* spawnpos; - int i; - str text; + const char *spawnpos; + int i; + str text; Init(); spawning = true; // set a specific spawnpoint if the map was started with a $ - spawnpos = strchr((char*)themapname, '$'); + spawnpos = strchr((char *)themapname, '$'); if (spawnpos) { - mapname = (const char*)(spawnpos - themapname); - spawnpoint = mapname; - } - else { - mapname = themapname; + mapname = str(themapname, 0, spawnpos - themapname); + spawnpoint = spawnpos + 1; + } else { + mapname = themapname; spawnpoint = ""; } - current_map = (char*)themapname; + current_map = (char *)themapname; level_name = mapname; for (i = 0; i < level_name.length(); i++) { @@ -1274,15 +1539,15 @@ void Level::SetMap(const char* themapname) } } - m_mapscript = "maps/" + level_name + ".scr"; + m_mapscript = "maps/" + level_name + ".scr"; m_precachescript = "maps/" + level_name + "_precache.scr"; - m_pathfile = "maps/" + level_name + ".pth"; - m_mapfile = "maps/" + level_name + ".bsp"; + m_pathfile = "maps/" + level_name + ".pth"; + m_mapfile = "maps/" + level_name + ".bsp"; } -void Level::LoadAllScripts(const char* name, const char* extension) +void Level::LoadAllScripts(const char *name, const char *extension) { - char** scriptFiles; + char **scriptFiles; char filename[MAX_QPATH]; int numScripts; @@ -1317,11 +1582,36 @@ void Level::Precache(void) m_LoopProtection = true; } - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { LoadAllScripts("anim", ".scr"); } LoadAllScripts("global", ".scr"); + InitVoteOptions(); + + // Added in OPM + // Cache all player models in multi-player + // This avoids using precache scripts + if (g_gametype->integer != GT_SINGLE_PLAYER) { + char **fileList; + int numFiles; + int i; + + fileList = gi.FS_ListFiles("models/player", ".tik", qfalse, &numFiles); + + for (i = 0; i < numFiles; i++) { + const char *filename = fileList[i]; + const size_t filelen = strlen(filename); + + if (!Q_stricmpn(filename, "allied_", 7) || !Q_stricmpn(filename, "american_", 9) + || !Q_stricmpn(filename, "german_", 7) || !Q_stricmpn(filename, "IT_", 3) + || !Q_stricmpn(filename, "SC_", 3)) { + CacheResource(va("models/player/%s", filename)); + } + } + + gi.FS_FreeFileList(fileList); + } } /* @@ -1337,12 +1627,12 @@ All but the last will have the teamchain field set to the next one */ void Level::FindTeams() { - gentity_t* ent, * ent2; - Entity* e, * e2; + gentity_t *ent, *ent2; + Entity *e, *e2; int i, j; int c, c2; - c = 0; + c = 0; c2 = 0; for (i = 1, ent = g_entities + i; i < globals.num_entities; i++, ent++) { if (!ent->inuse) { @@ -1380,14 +1670,14 @@ void Level::FindTeams() if (!strcmp(e->moveteam, e2->moveteam)) { c2++; - e2->teamchain = e->teamchain; - e->teamchain = e2; + e2->teamchain = e->teamchain; + e->teamchain = e2; e2->teammaster = e; e2->flags |= FL_TEAMSLAVE; // make sure that targets only point at the master if (e2->targetname) { - e->targetname = e2->targetname; + e->targetname = e2->targetname; e2->targetname = NULL; } } @@ -1464,6 +1754,10 @@ void Level::FreeEdict(gentity_t *ed) { gclient_t *client; + // clear the model so it decreases the user count + // and free memory if the model is not used anywhere + gi.clearmodel(ed); + // unlink from world gi.unlinkentity(ed); @@ -1512,71 +1806,230 @@ void Level::AddAutomaticCamera(Camera *cam) void Level::InitVoteOptions() { - // FIXME: unimplemented + if (g_gametype->integer == GT_SINGLE_PLAYER) { + return; + } + + m_voteOptions.SetupVoteOptions("callvote.cfg"); + // clear the vote time + gi.setConfigstring(CS_VOTE_TIME, ""); } -void Level::SendVoteOptionsFile(gentity_t* ent) +void Level::SendVoteOptionsFile(gentity_t *ent) { - // FIXME: unimplemented + const char *voteBuffer; + int voteLength; + int clientNum; + int i, j; + char buffer[2068]; + + clientNum = ent - g_entities; + + if (clientNum < 0 || clientNum >= game.maxclients) { + return; + } + + voteBuffer = m_voteOptions.GetVoteOptionsFile(&voteLength); + if (voteLength < MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH) { + Q_strncpyz(buffer, voteBuffer, voteLength + 1); + + for (i = 0; i < voteLength; i++) { + if (buffer[i] == '"') { + buffer[i] = 1; + } + } + + gi.SendServerCommand(clientNum, "vo0 \"\"\n"); + gi.SendServerCommand(clientNum, "vo2 \"%s\"\n", buffer); + } else { + const char *cmd; + int destLength; + int offset; + + offset = 0; + for (i = voteLength; i > 0; i -= MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH - 1) { + if (offset == 0) { + cmd = "vo0"; + destLength = MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH; + } else if (i >= MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH) { + cmd = "vo1"; + destLength = MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH; + } else { + cmd = "vo2"; + destLength = i; + } + + Q_strncpyz(buffer, &voteBuffer[offset], MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH); + + for (j = 0; j < destLength; j++) { + if (buffer[j] == '"') { + buffer[j] = 1; + } + } + + gi.SendServerCommand(clientNum, "%s \"%s\"\n", cmd, buffer); + offset += MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH - 1; + } + } } -bool Level::GetVoteOptionMain(int index, str* outOptionCommand, voteoptiontype_t* outOptionType) +bool Level::GetVoteOptionMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) { - // FIXME: unimplemented - return false; + return m_voteOptions.GetVoteOptionsMain(index, outOptionCommand, outOptionType); } -bool Level::GetVoteOptionSub(int index, int listIndex, str* outCommand) +bool Level::GetVoteOptionSub(int index, int listIndex, str *outCommand) { - // FIXME: unimplemented - return false; + return m_voteOptions.GetVoteOptionSub(index, listIndex, outCommand); } -bool Level::GetVoteOptionMainName(int index, str* outVoteName) +bool Level::GetVoteOptionMainName(int index, str *outVoteName) { - // FIXME: unimplemented - return false; + return m_voteOptions.GetVoteOptionMainName(index, outVoteName); } -bool Level::GetVoteOptionSubName(int index, int listIndex, str* outName) +bool Level::GetVoteOptionSubName(int index, int listIndex, str *outName) { - // FIXME: unimplemented - return false; + return m_voteOptions.GetVoteOptionSubName(index, listIndex, outName); } void Level::CheckVote(void) { - // FIXME: show the vote HUD like in SH and BT + gentity_t *ent; + int i; + int numVoters; + int oldVoteYes, oldVoteNo, oldNumVoters; + + if (m_nextVoteTime && m_nextVoteTime < inttime) { + m_nextVoteTime = 0; + + gi.SendConsoleCommand(va("%s\n", m_voteString.c_str())); + + if (sv_sprinton->integer == 1) { + if (sv_runspeed->integer == 250) { + gi.cvar_set("sv_runspeed", "287"); + } + } else if (sv_runspeed->integer == 287) { + gi.cvar_set("sv_runspeed", "250"); + } + + SetupMaplist(); + } if (!m_voteTime) { return; } - if (time - m_voteTime >= 30000.0f) { - dmManager.PrintAllClients("Vote failed.\n"); - m_voteTime = 0; - return; + oldVoteYes = level.m_voteYes; + oldVoteNo = level.m_voteNo; + oldNumVoters = level.m_numVoters; + + level.m_voteYes = 0; + level.m_voteNo = 0; + numVoters = 0; + + for (i = 0; i < game.maxclients; i++) { + Player *p; + + ent = &g_entities[i]; + if (!ent->inuse || !ent->client || !ent->entity) { + continue; + } + + p = static_cast(ent->entity); + if (p->client->ps.voted) { + if (p->HasVotedYes()) { + level.m_voteYes++; + } else { + level.m_voteNo++; + } + } + + numVoters++; } - if (m_voteYes > m_numVoters / 2) { - dmManager.PrintAllClients("Vote passed.\n"); + level.m_numVoters = numVoters; + if ((svsFloatTime - svsStartFloatTime) * 1000 - m_voteTime >= 30000) { + G_PrintToAllClients(va("%s: %s\n", gi.CL_LV_ConvertString("Vote Failed"), m_voteName.c_str())); + m_voteTime = 0; + gi.setConfigstring(CS_VOTE_TIME, ""); + } else if (m_voteYes > m_numVoters / 2) { // Pass arguments to console - gi.SendConsoleCommand(va("%s", level.m_voteString.c_str())); + G_PrintToAllClients(va("%s: %s\n", gi.CL_LV_ConvertString("Vote Passed"), m_voteName.c_str())); + m_nextVoteTime = level.inttime + 3000; + m_voteTime = 0; + gi.setConfigstring(CS_VOTE_TIME, ""); + } else if (m_voteNo >= m_numVoters / 2) { + G_PrintToAllClients(va("%s: %s\n", gi.CL_LV_ConvertString("Vote Failed"), m_voteName.c_str())); m_voteTime = 0; - return; - } + gi.setConfigstring(CS_VOTE_TIME, ""); + } else { + if (oldVoteYes != level.m_voteYes) { + gi.setConfigstring(CS_VOTE_YES, va("%i", level.m_voteYes)); + } - if (m_voteNo >= m_numVoters / 2) { - dmManager.PrintAllClients("Vote failed.\n"); - m_voteTime = 0; - return; + if (oldVoteNo != level.m_voteNo) { + gi.setConfigstring(CS_VOTE_NO, va("%i", level.m_voteNo)); + } + + if (oldNumVoters != level.m_numVoters || oldVoteYes != level.m_voteYes || oldVoteNo != level.m_voteNo) { + gi.setConfigstring(CS_VOTE_UNDECIDED, va("%i", level.m_numVoters - (level.m_voteYes + level.m_voteNo))); + } } } void Level::SetupMaplist() { - // FIXME: unimplemented + const char *p; + const char delim[2] = {';', 0}; + cvar_t *maplistVar; + int gameTypeNum; + char buffer[1024]; + char gameTypeBuffer[12]; + + if (!strstr(m_voteString.c_str(), "g_gametype")) { + return; + } + + Q_strncpyz(buffer, m_voteString.c_str(), sizeof(buffer)); + + for (p = strtok(buffer, delim); p; p = strtok(NULL, delim)) { + if (strstr(p, "g_gametype")) { + gameTypeBuffer[0] = p[strlen(p) - 1]; + gameTypeBuffer[1] = 0; + gameTypeNum = atoi(gameTypeBuffer); + } + } + + switch (gameTypeNum) { + case GT_FFA: + gi.ExecuteConsoleCommand(EXEC_NOW, "exec maplist_ffa.cfg"); + maplistVar = gi.Cvar_Get("ui_maplist_ffa", "", 0); + break; + case GT_TEAM: + gi.ExecuteConsoleCommand(EXEC_NOW, "exec maplist_team.cfg"); + maplistVar = gi.Cvar_Get("ui_maplist_team", "", 0); + break; + case GT_TEAM_ROUNDS: + gi.ExecuteConsoleCommand(EXEC_NOW, "exec maplist_round.cfg"); + maplistVar = gi.Cvar_Get("ui_maplist_round", "", 0); + break; + case GT_OBJECTIVE: + gi.ExecuteConsoleCommand(EXEC_NOW, "exec maplist_obj.cfg"); + maplistVar = gi.Cvar_Get("ui_maplist_obj", "", 0); + break; + case GT_TOW: + gi.ExecuteConsoleCommand(EXEC_NOW, "exec maplist_tow.cfg"); + maplistVar = gi.Cvar_Get("ui_maplist_tow", "", 0); + break; + case GT_LIBERATION: + gi.ExecuteConsoleCommand(EXEC_NOW, "exec maplist_lib.cfg"); + maplistVar = gi.Cvar_Get("ui_maplist_lib", "", 0); + break; + } + + gi.cvar_set("sv_maplist", maplistVar->string); } void Level::GetAlarm(Event *ev) @@ -1594,7 +2047,7 @@ void Level::SetNoDropHealth(Event *ev) mbNoDropHealth = ev->GetInteger(1); } -void Level::SetNoDropWeapons(Event* ev) +void Level::SetNoDropWeapons(Event *ev) { mbNoDropWeapons = ev->GetInteger(1); } @@ -1619,7 +2072,7 @@ void Level::SetPapersLevel(Event *ev) m_iPapersLevel = ev->GetInteger(1); } -void Level::EventGetRoundStarted(Event* ev) +void Level::EventGetRoundStarted(Event *ev) { ev->AddInteger(RoundStarted()); } @@ -1717,26 +2170,24 @@ void Level::EventGetRoundBased(Event *ev) ev->AddInteger(g_gametype->integer >= GT_TEAM_ROUNDS); } -void Level::EventGetObjectiveBased(Event* ev) +void Level::EventGetObjectiveBased(Event *ev) { ev->AddInteger(g_gametype->integer >= GT_OBJECTIVE); } str Level::GetRandomHeadModel(const char *model) { - //FIXME: macros - char s[1024]; - int num = random2() * gi.NumHeadModels(model); - gi.GetHeadModel(model, num, s); + char s[MAX_STRING_TOKENS]; + + gi.GetHeadModel(model, G_Random(gi.NumHeadModels(model)), s); return s; } str Level::GetRandomHeadSkin(const char *model) { - //FIXME: macros - char s[1024]; - int num = random2() * gi.NumHeadSkins(model); - gi.GetHeadSkin(model, num, s); + char s[MAX_STRING_TOKENS]; + + gi.GetHeadSkin(model, G_Random(gi.NumHeadSkins(model)), s); return s; } @@ -1744,7 +2195,7 @@ void Level::AddEarthquake(earthquake_t *e) { if (num_earthquakes == MAX_EARTHQUAKES) { if (earthquakes[0].m_Thread) { - earthquakes[0].m_Thread->Wait((float)(e->endtime - inttime) / 1000.0f - 0.5f); + earthquakes[0].m_Thread->Wait(e->endtime - inttime); } num_earthquakes--; @@ -1896,6 +2347,12 @@ void Level::EventRainShaderGet(Event *ev) void Level::EventRainNumShadersSet(Event *ev) { + if (g_protocol <= protocol_e::PROTOCOL_MOH) { + // There is a mistake in 1.11 and below where the NumShader event doesn't work + // Because the response points to EventRainShaderSet + return; + } + gi.setConfigstring(CS_RAIN_NUMSHADERS, ev->GetString(1)); } @@ -1904,30 +2361,159 @@ void Level::EventRainNumShadersGet(Event *ev) ev->AddString(gi.getConfigstring(CS_RAIN_NUMSHADERS)); } -void Level::EventAddBadPlace(Event* ev) +void Level::EventAddBadPlace(Event *ev) { - // FIXME: unimplemented + badplace_t bp; + int nArgs; + + nArgs = ev->NumArgs(); + if (nArgs != 3 && nArgs != 4 && nArgs != 5) { + throw ScriptException("badplace requires 3, 4, or 5 arguments"); + } + + if (ev->NumArgs() >= 5) { + bp.m_fLifespan = ev->GetFloat(5); + if (bp.m_fLifespan <= 0) { + throw ScriptException("life span must be greater than 0"); + } + } + + if (ev->NumArgs() >= 4) { + switch (ev->GetConstString(4)) { + case STRING_ALLIES: + case STRING_AMERICAN: + bp.m_iTeamSide = TEAM_ALLIES; + break; + case STRING_AXIS: + case STRING_GERMAN: + bp.m_iTeamSide = TEAM_AXIS; + break; + default: + throw ScriptException("badplace must belong to 'american' or 'german' or 'both'"); + } + } + + bp.m_fRadius = ev->GetFloat(3); + bp.m_vOrigin = ev->GetVector(2); + bp.m_name = ev->GetConstString(1); + + if (bp.m_name == STRING_EMPTY && bp.m_fLifespan == FLT_MAX) { + throw ScriptException("unnamed badplaces must have a specified duration"); + } + + if (bp.m_name != STRING_EMPTY) { + int i; + + // replace badplaces with the same name + for (i = 1; i <= m_badPlaces.NumObjects(); i++) { + const badplace_t& existing = m_badPlaces.ObjectAt(i); + + if (existing.m_name == bp.m_name) { + // remove the existing bad place at the pathway + PathSearch::UpdatePathwaysForBadPlace(existing.m_vOrigin, existing.m_fRadius, -1, existing.m_iTeamSide); + m_badPlaces.SetObjectAt(i, bp); + // add the new bad place + PathSearch::UpdatePathwaysForBadPlace(bp.m_vOrigin, bp.m_fRadius, 1, bp.m_iTeamSide); + G_BroadcastAIEvent(NULL, vec_zero, 12, -1); + return; + } + } + } + + // add the new bad place + m_badPlaces.AddObject(bp); + PathSearch::UpdatePathwaysForBadPlace(bp.m_vOrigin, bp.m_fRadius, 1, bp.m_iTeamSide); + // notify AI + G_BroadcastAIEvent(NULL, vec_zero, 12, -1); } -void Level::EventRemoveBadPlace(Event* ev) +void Level::EventRemoveBadPlace(Event *ev) { - // FIXME: unimplemented + const_str name; + int i; + + if (ev->NumArgs() != 1) { + throw ScriptException("removebadplace requires exactly 1 argument"); + } + + name = ev->GetConstString(1); + for (i = 1; i <= m_badPlaces.NumObjects(); i++) { + badplace_t& bp = m_badPlaces.ObjectAt(i); + + if (bp.m_name == name) { + PathSearch::UpdatePathwaysForBadPlace(bp.m_vOrigin, bp.m_fRadius, -1, bp.m_iTeamSide); + m_badPlaces.RemoveObjectAt(i); + G_BroadcastAIEvent(NULL, vec_zero, 12, -1); + return; + } + } + + Com_Printf("removebadplace: name '%s' not found", ev->GetString(1).c_str()); } -void Level::EventIgnoreClock(Event* ev) +void Level::EventIgnoreClock(Event *ev) { m_bIgnoreClock = ev->GetBoolean(1); } void Level::UpdateBadPlaces() { - // FIXME: unimplemented + qboolean removed; + int i; + + removed = qfalse; + + for (i = 1; i <= m_badPlaces.NumObjects(); i++) { + badplace_t& bp = m_badPlaces.ObjectAt(i); + if (level.time < bp.m_fLifespan) { + continue; + } else { + PathSearch::UpdatePathwaysForBadPlace(bp.m_vOrigin, bp.m_fRadius, -1, bp.m_iTeamSide); + m_badPlaces.RemoveObjectAt(i); + removed = qtrue; + i = 0; + } + } + + if (removed) { + // tell AI that a bad place was removed + G_BroadcastAIEvent(NULL, vec_zero, 12, -1); + } } -badplace_t* Level::GetNearestBadPlace(const Vector& org, float radius) const +int Level::GetNearestBadPlace(const Vector& org, float radius, int team) const { - // FIXME: unimplemented - return NULL; + float bestDistSqr; + int bestBpIndex; + int i; + + bestDistSqr = FLT_MAX; + bestBpIndex = 0; + + for (i = 1; i <= m_badPlaces.NumObjects(); i++) { + badplace_t& bp = m_badPlaces.ObjectAt(i); + + if (team & bp.m_iTeamSide) { + const Vector delta = bp.m_vOrigin - org; + float distSqr = delta.lengthSquared(); + float rad = bp.m_fRadius + radius; + + if (distSqr < bestDistSqr && distSqr < rad * rad) { + bestDistSqr = distSqr; + bestBpIndex = i; + } + } + } + + return bestBpIndex; +} + +static void ArchiveBadPlace(Archiver& arc, badplace_t *bp) +{ + Director.ArchiveString(arc, bp->m_name); + arc.ArchiveVector(&bp->m_vOrigin); + arc.ArchiveFloat(&bp->m_fRadius); + arc.ArchiveFloat(&bp->m_fLifespan); } void Level::Archive(Archiver& arc) @@ -1938,19 +2524,19 @@ void Level::Archive(Archiver& arc) Listener::Archive(arc); if (arc.Saving()) { - prespawn = classinfo()->WaitTillDefined("prespawn"); - spawn = classinfo()->WaitTillDefined("spawn"); + prespawn = WaitTillDefined(STRING_PRESPAWN); + spawn = WaitTillDefined(STRING_SPAWN); } arc.ArchiveBool(&prespawn); arc.ArchiveBool(&spawn); if (arc.Loading()) { - if (prespawn) { + if (!prespawn) { RemoveWaitTill(STRING_PRESPAWN); } - if (spawn) { + if (!spawn) { RemoveWaitTill(STRING_SPAWN); } } @@ -2012,16 +2598,19 @@ void Level::Archive(Archiver& arc) arc.ArchiveFloat(&m_letterbox_time_start); ArchiveEnum(m_letterbox_dir, letterboxdir_t); + m_badPlaces.Archive(arc, &ArchiveBadPlace); arc.ArchiveInteger(&m_iCuriousVoiceTime); arc.ArchiveInteger(&m_iAttackEntryAnimTime); arc.ArchiveInteger(&mHealthPopCount); arc.ArchiveBoolean(&m_bAlarm); arc.ArchiveBoolean(&mbNoDropHealth); + arc.ArchiveBoolean(&mbNoDropWeapons); arc.ArchiveInteger(&m_iPapersLevel); arc.ArchiveInteger(&m_LoopProtection); - memset(skel_index, 255, sizeof(skel_index)); + // clear skel indexes + memset(skel_index, 0xff, sizeof(skel_index)); if (arc.Loading()) { str saved = saved_soundtrack; @@ -2035,8 +2624,16 @@ void Level::Archive(Archiver& arc) arc.ArchiveObjectPointer((Class **)&m_HeadSentient[i]); } - // FIXME: Archive Actor::mBodyQueue - // FIXME: Archive Actor::mCurBody + arc.ArchiveVector(&m_vObjectiveLocation); + arc.ArchiveVector(&m_vAlliedObjectiveLocation); + arc.ArchiveVector(&m_vAxisObjectiveLocation); + + for (int i = 0; i < MAX_BODYQUEUE; i++) { + arc.ArchiveSafePointer(&Actor::mBodyQueue[i]); + } + + arc.ArchiveInteger(&Actor::mCurBody); + Health::ArchiveStatic(arc); arc.ArchiveConfigString(CS_CURRENT_OBJECTIVE); @@ -2053,4 +2650,117 @@ void Level::Archive(Archiver& arc) arc.ArchiveConfigString(CS_RAIN_WIDTH); arc.ArchiveConfigString(CS_RAIN_SHADER); arc.ArchiveConfigString(CS_RAIN_NUMSHADERS); + + arc.ArchiveFloat(&svsStartFloatTime); + arc.ArchiveFloat(&m_fLandmarkYDistMax); + arc.ArchiveFloat(&m_fLandmarkYDistMin); + arc.ArchiveFloat(&m_fLandmarkXDistMin); + arc.ArchiveFloat(&m_fLandmarkXDistMax); } + +void WriteStatS(FILE *pFile, const char *value) +{ + fprintf(pFile, "%s", value); +} + +void WriteStatI(FILE *pFile, int value) +{ + fprintf(pFile, "%d", value); +} + +void WriteStatF(FILE *pFile, float value) +{ + fprintf(pFile, "%.2f", value); +} + +void Level::OpenActorStats() +{ + str filename; + + if (!g_aistats->integer) { + return; + } + + filename = "aistats_" + mapname + ".csv"; + m_pAIStats = fopen(filename, "wt"); + + if (m_pAIStats) { + fprintf( + (FILE *)m_pAIStats, + "targetname,weapon,grenade ammo,health,accuracy,hearing,sight,fov,mindist,maxdist,leash,sound " + "awareness,noticescale,enemyshare,grenade aware,model\n" + ); + } +} + +void Level::WriteActorStats(Actor *actor) +{ + const char *name; + str itemName; + Weapon *weapon; + Ammo *ammo; + int ammoAmount; + FILE *pFile; + + if (!g_aistats->integer) { + return; + } + + if (!m_pAIStats) { + OpenActorStats(); + } + + pFile = (FILE *)m_pAIStats; + if (!pFile) { + return; + } + + name = actor->TargetName().c_str(); + itemName = "none"; + + weapon = actor->GetActiveWeapon(WEAPON_MAIN); + if (weapon) { + itemName = weapon->GetItemName(); + } + + ammoAmount = 0; + ammo = actor->FindAmmoByName("grenade"); + if (ammo) { + ammoAmount = ammo->getAmount(); + } + + WriteStatS(pFile, name); + WriteStatS(pFile, itemName); + WriteStatI(pFile, ammoAmount); + WriteStatF(pFile, actor->health); + WriteStatF(pFile, actor->mAccuracy * 100); + WriteStatF(pFile, actor->m_fHearing); + WriteStatF(pFile, actor->m_fSight); + WriteStatF(pFile, actor->m_fFov); + WriteStatF(pFile, actor->m_fMinDistance); + WriteStatF(pFile, actor->m_fMaxDistance); + WriteStatF(pFile, actor->m_fLeash); + WriteStatF(pFile, actor->m_fSoundAwareness); + WriteStatF(pFile, actor->m_fMaxNoticeTimeScale * 100); + + WriteStatI(pFile, sqrt(actor->m_fMaxShareDistSquared)); + WriteStatF(pFile, actor->m_fGrenadeAwareness); + WriteStatS(pFile, actor->model); + + fprintf(pFile, "\n"); +} + +void Level::SetForceTeamObjectiveLocation(Event *ev) +{ + m_bForceTeamObjectiveLocation = ev->GetBoolean(1); +} + +void Level::GetForceTeamObjectiveLocation(Event *ev) +{ + ev->AddInteger(g_gametype->integer >= GT_TOW || m_bForceTeamObjectiveLocation); +} + +badplace_t::badplace_t() + : m_fLifespan(FLT_MAX) + , m_iTeamSide(TEAM_ALLIES) +{} diff --git a/code/fgame/level.h b/code/fgame/level.h index 8b4128f0..5748b1e6 100644 --- a/code/fgame/level.h +++ b/code/fgame/level.h @@ -65,22 +65,26 @@ typedef struct earthquake_s { } earthquake_t; struct badplace_t { - const_str m_name; - int m_iTeamSide; - Vector m_vOrigin; - float m_fRadius; - float m_fNotBadPlaceTime; + const_str m_name; + int m_iTeamSide; + Vector m_vOrigin; + float m_fRadius; + float m_fLifespan; + +public: + badplace_t(); }; typedef struct { - str m_sName; - Vector m_vOrigin; + str m_sName; + Vector m_vOrigin; } landmark_t; extern gclient_t *spawn_client; class Camera; class SimpleArchivedEntity; +class Actor; class Level : public Listener { @@ -111,8 +115,8 @@ public: int svsTime; float svsFloatTime; int svsStartTime; - int svsEndTime; - float svsStartFloatTime; // Added in 2.0 + int svsEndTime; + float svsStartFloatTime; // Added in 2.0 // Level name variables str level_name; @@ -191,14 +195,15 @@ public: int m_numArenas; // Voting variables - float m_voteTime; - int m_voteYes; - int m_voteNo; - int m_numVoters; - str m_voteString; + int m_voteTime; + int m_nextVoteTime; + int m_voteYes; + int m_voteNo; + int m_numVoters; // Added in 2.0 - str m_voteCommand; - str m_voteName; + str m_voteString; + str m_voteName; + VoteOptions m_voteOptions; // Intermission locations Vector m_intermission_origin; @@ -220,33 +225,32 @@ public: int num_earthquakes; // Objective stuff - Vector m_vObjectiveLocation; - Vector m_vAlliedObjectiveLocation; // Added in 2.0 - Vector m_vAxisObjectiveLocation; // Added in 2.0 + Vector m_vObjectiveLocation; + Vector m_vAlliedObjectiveLocation; // Added in 2.0 + Vector m_vAxisObjectiveLocation; // Added in 2.0 + // Added in OPM + // Forces axis/allied objectives location to be used + // even if the gametype is not TOW + bool m_bForceTeamObjectiveLocation; // Current level state bool spawning; - bool m_bIgnoreClock; + bool m_bIgnoreClock; //==== // Added in 2.30 // Landmarks - float m_fLandmarkYDistMax; - float m_fLandmarkYDistMin; - float m_fLandmarkXDistMax; - float m_fLandmarkXDistMin; - landmark_t** m_pLandmarks; - int m_iMaxLandmarks; - int m_iLandmarksCount; + float m_fLandmarkYDistMax; + float m_fLandmarkYDistMin; + float m_fLandmarkXDistMin; + float m_fLandmarkXDistMax; + landmark_t **m_pLandmarks; + int m_iMaxLandmarks; + int m_iLandmarksCount; //==== - void* m_pAIStats; + void *m_pAIStats; // New Stuff - // don't put in the game class because it can be changed in another level - qboolean specialgame; - - bool m_bSpawnBot; - // Script stuff bool m_bScriptSpawn; bool m_bRejectSpawn; @@ -268,95 +272,95 @@ public: void SetMap(const char *themapname); void FindTeams(); - void SpawnEntities(char *entities, int _svsTime_); + void SpawnEntities(char *entities, int _svsTime_); //==== // Added in 2.30 - void ComputeDMWaypoints(); - void AddLandmarkOrigin(const Vector& origin); - void AddLandmarkName(const str& name, const Vector& origin); - void FreeLandmarks(); - str GetDynamicDMLocations(const Vector& origin); - str GetDMLocation(const Vector& origin); + void ComputeDMWaypoints(); + void AddLandmarkOrigin(const Vector& origin); + void AddLandmarkName(const str& name, const Vector& origin); + void FreeLandmarks(); + str GetDynamicDMLocations(const Vector& origin); + str GetDMLocation(const Vector& origin); //==== - void PreSpawnSentient(Event *ev); - void ServerSpawned(); - qboolean inhibitEntity(int spawnflags); + void PreSpawnSentient(Event *ev); + void ServerSpawned(); + qboolean inhibitEntity(int spawnflags); - void setSkill(int value); - void setTime(int _svsTime_); - void setFrametime(int frameTime); + void setSkill(int value); + void setTime(int _svsTime_); + void setFrametime(int frameTime); - void AddAutomaticCamera(Camera *cam); + void AddAutomaticCamera(Camera *cam); - void GetTime(Event *ev); - void GetTotalSecrets(Event *ev); - void GetFoundSecrets(Event *ev); + void GetTime(Event *ev); + void GetTotalSecrets(Event *ev); + void GetFoundSecrets(Event *ev); //==== // Added in 2.0 - void InitVoteOptions(); - void SendVoteOptionsFile(gentity_t* ent); - bool GetVoteOptionMain(int index, str* outOptionCommand, voteoptiontype_t* outOptionType); - bool GetVoteOptionSub(int index, int listIndex, str* outCommand); - bool GetVoteOptionMainName(int index, str* outVoteName); - bool GetVoteOptionSubName(int index, int listIndex, str* outName); - //==== - void CheckVote(); - void SetupMaplist(); // Added in 2.0 + void InitVoteOptions(); + void SendVoteOptionsFile(gentity_t *ent); + bool GetVoteOptionMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType); + bool GetVoteOptionSub(int index, int listIndex, str *outCommand); + bool GetVoteOptionMainName(int index, str *outVoteName); + bool GetVoteOptionSubName(int index, int listIndex, str *outName); + //==== + void CheckVote(); + void SetupMaplist(); // Added in 2.0 - void GetAlarm(Event *ev); - void SetAlarm(Event *ev); - void SetNoDropHealth(Event *ev); - void SetNoDropWeapons(Event *ev); // Added in 2.0 - void GetLoopProtection(Event *ev); - void SetLoopProtection(Event *ev); - void GetPapersLevel(Event *ev); - void SetPapersLevel(Event *ev); - void EventGetRoundStarted(Event *ev); - void EventGetDMRespawning(Event *ev); - void EventSetDMRespawning(Event *ev); - void EventGetDMRoundLimit(Event *ev); - void EventSetDMRoundLimit(Event *ev); - void EventGetClockSide(Event *ev); - void EventSetClockSide(Event *ev); - void EventGetBombPlantTeam(Event *ev); - void EventSetBombPlantTeam(Event *ev); - void EventGetTargetsToDestroy(Event *ev); - void EventSetTargetsToDestroy(Event *ev); - void EventGetTargetsDestroyed(Event *ev); - void EventSetTargetsDestroyed(Event *ev); - void EventGetBombsPlanted(Event *ev); - void EventSetBombsPlanted(Event *ev); - void EventGetRoundBased(Event *ev); - void EventGetObjectiveBased(Event *ev); - void EventRainDensitySet(Event *ev); - void EventRainDensityGet(Event *ev); - void EventRainSpeedSet(Event *ev); - void EventRainSpeedGet(Event *ev); - void EventRainSpeedVarySet(Event *ev); - void EventRainSpeedVaryGet(Event *ev); - void EventRainSlantSet(Event *ev); - void EventRainSlantGet(Event *ev); - void EventRainLengthSet(Event *ev); - void EventRainLengthGet(Event *ev); - void EventRainMin_DistSet(Event *ev); - void EventRainMin_DistGet(Event *ev); - void EventRainWidthSet(Event *ev); - void EventRainWidthGet(Event *ev); - void EventRainShaderSet(Event *ev); - void EventRainShaderGet(Event *ev); - void EventRainNumShadersSet(Event *ev); - void EventRainNumShadersGet(Event *ev); + void GetAlarm(Event *ev); + void SetAlarm(Event *ev); + void SetNoDropHealth(Event *ev); + void SetNoDropWeapons(Event *ev); // Added in 2.0 + void GetLoopProtection(Event *ev); + void SetLoopProtection(Event *ev); + void GetPapersLevel(Event *ev); + void SetPapersLevel(Event *ev); + void EventGetRoundStarted(Event *ev); + void EventGetDMRespawning(Event *ev); + void EventSetDMRespawning(Event *ev); + void EventGetDMRoundLimit(Event *ev); + void EventSetDMRoundLimit(Event *ev); + void EventGetClockSide(Event *ev); + void EventSetClockSide(Event *ev); + void EventGetBombPlantTeam(Event *ev); + void EventSetBombPlantTeam(Event *ev); + void EventGetTargetsToDestroy(Event *ev); + void EventSetTargetsToDestroy(Event *ev); + void EventGetTargetsDestroyed(Event *ev); + void EventSetTargetsDestroyed(Event *ev); + void EventGetBombsPlanted(Event *ev); + void EventSetBombsPlanted(Event *ev); + void EventGetRoundBased(Event *ev); + void EventGetObjectiveBased(Event *ev); + void EventRainDensitySet(Event *ev); + void EventRainDensityGet(Event *ev); + void EventRainSpeedSet(Event *ev); + void EventRainSpeedGet(Event *ev); + void EventRainSpeedVarySet(Event *ev); + void EventRainSpeedVaryGet(Event *ev); + void EventRainSlantSet(Event *ev); + void EventRainSlantGet(Event *ev); + void EventRainLengthSet(Event *ev); + void EventRainLengthGet(Event *ev); + void EventRainMin_DistSet(Event *ev); + void EventRainMin_DistGet(Event *ev); + void EventRainWidthSet(Event *ev); + void EventRainWidthGet(Event *ev); + void EventRainShaderSet(Event *ev); + void EventRainShaderGet(Event *ev); + void EventRainNumShadersSet(Event *ev); + void EventRainNumShadersGet(Event *ev); //==== // Added in 2.0 - void EventAddBadPlace(Event *ev); - void EventRemoveBadPlace(Event *ev); - void EventIgnoreClock(Event *ev); - void UpdateBadPlaces(); - badplace_t *GetNearestBadPlace(const Vector& org, float radius) const; + void EventAddBadPlace(Event *ev); + void EventRemoveBadPlace(Event *ev); + void EventIgnoreClock(Event *ev); + void UpdateBadPlaces(); + int GetNearestBadPlace(const Vector& org, float radius, int team) const; //==== - str GetRandomHeadModel(const char *model); - str GetRandomHeadSkin(const char *model); + str GetRandomHeadModel(const char *model); + str GetRandomHeadSkin(const char *model); bool RoundStarted(); bool PreSpawned(void); @@ -365,6 +369,15 @@ public: void AddEarthquake(earthquake_t *); void DoEarthquakes(void); + void OpenActorStats(); + void WriteActorStats(Actor *actor); + + //==== + // Added in OPM + void SetForceTeamObjectiveLocation(Event *ev); + void GetForceTeamObjectiveLocation(Event *ev); + //==== + void Archive(Archiver& arc) override; }; @@ -372,7 +385,7 @@ public: void G_BeginIntermission2(void); // Change the current map to the specified map with the possibility to fade the screen with fadetime. -void G_BeginIntermission(const char* map_name, INTTYPE_e transtype, bool no_fade = false); +void G_BeginIntermission(const char *map_name, INTTYPE_e transtype, bool no_fade = false); //Exit the intermission screen. void G_ExitIntermission(void); diff --git a/code/fgame/light.h b/code/fgame/light.h index 9bbcaa66..08d5ac87 100644 --- a/code/fgame/light.h +++ b/code/fgame/light.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // light.h: Classes for creating and controlling lights. // -#ifndef __LIGHT_H__ -#define __LIGHT_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -36,5 +35,3 @@ class Light : public Entity Light(); }; - -#endif /* light.h */ diff --git a/code/fgame/lodthing.cpp b/code/fgame/lodthing.cpp index cb56c2cd..b9a68ff8 100644 --- a/code/fgame/lodthing.cpp +++ b/code/fgame/lodthing.cpp @@ -129,6 +129,9 @@ void LODMaster::Spawn gi.cvar_set( "lod_tool", "1" ); ent = g_entities->entity; + if (!ent) { + return; + } if( ent->IsSubclassOfPlayer() ) { @@ -190,8 +193,7 @@ void LODMaster::PassEvent ScriptError( "No LOD Model" ); } - Event *event = new Event( ev ); - m_current->ProcessEvent( event ); + m_current->ProcessEvent(*ev); } CLASS_DECLARATION( Animate, LODSlave, "lodslave" ) diff --git a/code/fgame/misc.cpp b/code/fgame/misc.cpp index f5e6b907..14eb47ac 100644 --- a/code/fgame/misc.cpp +++ b/code/fgame/misc.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // own file to my mother's pot roast recipes. // -#include "glb_local.h" +#include "g_local.h" #include "entity.h" #include "trigger.h" #include "explosion.h" @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "weaputils.h" #include "g_spawn.h" #include "g_phys.h" +#include "../script/scriptexception.h" /*****************************************************************************/ /*QUAKED detail (0.5 0 1.0) ? @@ -60,31 +61,28 @@ Used for lighting and such ******************************************************************************/ -CLASS_DECLARATION( Entity, FuncRemove, "func_remove" ) - { - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, FuncRemove, "func_remove") { + {NULL, NULL} +}; FuncRemove::FuncRemove() - { - PostEvent( EV_Remove, EV_REMOVE ); - } +{ + PostEvent(EV_Remove, EV_REMOVE); +} /*****************************************************************************/ /*QUAKED misc_model (1 0.5 1) (0 0 0) (0 0 0) "model" arbitrary .tik file to display ******************************************************************************/ -CLASS_DECLARATION( Entity, MiscModel, "misc_model" ) - { - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, MiscModel, "misc_model") { + {NULL, NULL} +}; MiscModel::MiscModel() - { - PostEvent( EV_Remove, EV_REMOVE ); - } - +{ + PostEvent(EV_Remove, EV_REMOVE); +} /*****************************************************************************/ /*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) @@ -93,15 +91,14 @@ Used as a positional target for spotlights, etc. ******************************************************************************/ -CLASS_DECLARATION( Entity, InfoNull, "info_null" ) - { - { NULL, NULL } - }; +CLASS_DECLARATION(Listener, InfoNull, "info_null") { + {NULL, NULL} +}; InfoNull::InfoNull() - { - PostEvent( EV_Remove, EV_REMOVE ); - } +{ + PostEvent(EV_Remove, EV_REMOVE); +} /*****************************************************************************/ /*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) @@ -110,12 +107,9 @@ Used as a positional target for lightning. ******************************************************************************/ -CLASS_DECLARATION( Entity, InfoNotNull, "info_notnull" ) - { - { NULL, NULL } - }; - - +CLASS_DECLARATION(Entity, InfoNotNull, "info_notnull") { + {NULL, NULL} +}; /*****************************************************************************/ /*QUAKED func_explodingwall (0 0.25 0.5) ? RANDOMANGLES LANDSHATTER NOT_PLAYERS MONSTERS PROJECTILES INVISIBLE ACCUMALATIVE TWOSTAGE @@ -144,539 +138,459 @@ If MONSTERS is set, the trigger will respond to monsters If PROJECTILES is set, the trigger will respond to projectiles (rockets, grenades, etc.) ******************************************************************************/ -#define RANDOMANGLES ( 1 << 0 ) -#define LANDSHATTER ( 1 << 1 ) -#define INVISIBLE ( 1 << 5 ) -#define ACCUMULATIVE ( 1 << 6 ) -#define TWOSTAGE ( 1 << 7 ) +#define RANDOMANGLES (1 << 0) +#define LANDSHATTER (1 << 1) +#define INVISIBLE (1 << 5) +#define ACCUMULATIVE (1 << 6) +#define TWOSTAGE (1 << 7) Event EV_ExplodingWall_StopRotating - ( - "stoprotating", - EV_DEFAULT, - NULL, - NULL, - "Stop rotating the wall.", - EV_NORMAL - ); +( + "stoprotating", EV_DEFAULT, + NULL, + NULL, + "Stop rotating the wall.", + EV_NORMAL +); Event EV_ExplodingWall_OnGround - ( - "checkonground", - EV_DEFAULT, - NULL, - NULL, - "Check if exploding wall is on ground.", - EV_NORMAL - ); +( + "checkonground", EV_DEFAULT, + NULL, + NULL, + "Check if exploding wall is on ground.", + EV_NORMAL + +); Event EV_ExplodingWall_AngleSpeed - ( - "anglespeed", - EV_DEFAULT, - "f", - "speed", - "Set the angle speed.", - EV_NORMAL - ); +( + "anglespeed", EV_DEFAULT, + "f", + "speed", + "Set the angle speed.", + EV_NORMAL +); Event EV_ExplodingWall_LandRadius - ( - "land_radius", - EV_DEFAULT, - "f", - "radius", - "Set the land radius.", - EV_NORMAL - ); +( + "land_radius", EV_DEFAULT, + "f", + "radius", + "Set the land radius.", + EV_NORMAL +); Event EV_ExplodingWall_LandAngles - ( - "land_angles", - EV_DEFAULT, - "v", - "angles", - "Set the land angles.", - EV_NORMAL - ); +( + "land_angles", EV_DEFAULT, + "v", + "angles", + "Set the land angles.", + EV_NORMAL +); Event EV_ExplodingWall_BaseVelocity - ( - "base_velocity", - EV_DEFAULT, - "v", - "velocity", - "Set the base velocity.", - EV_NORMAL - ); -Event EV_ExplodingWall_RandomVelocity - ( - "random_velocity", - EV_DEFAULT, - "v", - "velocity", - "Set the amount of random variation of the base velocity.", - EV_NORMAL - ); +( + "base_velocity", EV_DEFAULT, + "v", + "velocity", + "Set the base velocity.", + EV_NORMAL +); +Event EV_ExplodingWall_RandomVelocity( + "random_velocity", + EV_DEFAULT, + "v", + "velocity", + "Set the amount of random variation of the base velocity.", + EV_NORMAL +); Event EV_ExplodingWall_SetDmg - ( - "dmg", - EV_DEFAULT, - "i", - "dmg", - "Set the damage from the exploding wall.", - EV_NORMAL - ); +( + "dmg", EV_DEFAULT, + "i", + "dmg", + "Set the damage from the exploding wall.", + EV_NORMAL +); Event EV_ExplodingWall_SetExplosions - ( - "explosions", - EV_DEFAULT, - "i", - "explosions", - "Set the number of explosions.", - EV_NORMAL - ); +( + "explosions", EV_DEFAULT, + "i", + "explosions", + "Set the number of explosions.", + EV_NORMAL + +); Event EV_ExplodingWall_Setup - ( - "setup", - EV_CODEONLY, - NULL, - NULL, - "Initializes the exploding wall.", - EV_NORMAL - ); +( + "setup", EV_CODEONLY, + NULL, + NULL, + "Initializes the exploding wall.", + EV_NORMAL +); -CLASS_DECLARATION( Trigger, ExplodingWall, "func_explodingwall" ) - { - { &EV_ExplodingWall_Setup, &ExplodingWall::Setup }, - { &EV_Trigger_Effect, &ExplodingWall::Explode }, - { &EV_Damage, &ExplodingWall::DamageEvent }, - { &EV_Touch, &ExplodingWall::TouchFunc }, - { &EV_ExplodingWall_StopRotating, &ExplodingWall::StopRotating }, - { &EV_ExplodingWall_OnGround, &ExplodingWall::CheckOnGround }, - { &EV_ExplodingWall_AngleSpeed, &ExplodingWall::AngleSpeed }, - { &EV_ExplodingWall_LandRadius, &ExplodingWall::LandRadius }, - { &EV_ExplodingWall_LandAngles, &ExplodingWall::LandAngles }, - { &EV_ExplodingWall_BaseVelocity, &ExplodingWall::BaseVelocity }, - { &EV_ExplodingWall_RandomVelocity, &ExplodingWall::RandomVelocity }, - { &EV_ExplodingWall_SetDmg, &ExplodingWall::SetDmg }, - { &EV_ExplodingWall_SetExplosions, &ExplodingWall::SetExplosions }, - { NULL, NULL } - }; +CLASS_DECLARATION(Trigger, ExplodingWall, "func_explodingwall") { + {&EV_ExplodingWall_Setup, &ExplodingWall::Setup }, + {&EV_Trigger_Effect, &ExplodingWall::Explode }, + {&EV_Damage, &ExplodingWall::DamageEvent }, + {&EV_Touch, &ExplodingWall::TouchFunc }, + {&EV_ExplodingWall_StopRotating, &ExplodingWall::StopRotating }, + {&EV_ExplodingWall_OnGround, &ExplodingWall::CheckOnGround }, + {&EV_ExplodingWall_AngleSpeed, &ExplodingWall::AngleSpeed }, + {&EV_ExplodingWall_LandRadius, &ExplodingWall::LandRadius }, + {&EV_ExplodingWall_LandAngles, &ExplodingWall::LandAngles }, + {&EV_ExplodingWall_BaseVelocity, &ExplodingWall::BaseVelocity }, + {&EV_ExplodingWall_RandomVelocity, &ExplodingWall::RandomVelocity}, + {&EV_ExplodingWall_SetDmg, &ExplodingWall::SetDmg }, + {&EV_ExplodingWall_SetExplosions, &ExplodingWall::SetExplosions }, + {NULL, NULL } +}; -void ExplodingWall::AngleSpeed - ( - Event *ev - ) +void ExplodingWall::AngleSpeed(Event *ev) +{ + angle_speed = ev->GetFloat(1); +} - { - angle_speed = ev->GetFloat( 1 ); - } +void ExplodingWall::LandRadius(Event *ev) +{ + land_radius = ev->GetFloat(1); +} -void ExplodingWall::LandRadius - ( - Event *ev - ) +void ExplodingWall::LandAngles(Event *ev) +{ + land_angles = ev->GetVector(1); +} - { - land_radius = ev->GetFloat( 1 ); - } +void ExplodingWall::BaseVelocity(Event *ev) +{ + base_velocity = ev->GetVector(1); +} -void ExplodingWall::LandAngles - ( - Event *ev - ) +void ExplodingWall::RandomVelocity(Event *ev) +{ + random_velocity = ev->GetVector(1); +} - { - land_angles = ev->GetVector( 1 ); - } +void ExplodingWall::SetDmg(Event *ev) +{ + dmg = ev->GetInteger(1); +} -void ExplodingWall::BaseVelocity - ( - Event *ev - ) +void ExplodingWall::SetExplosions(Event *ev) +{ + explosions = ev->GetInteger(1); +} - { - base_velocity = ev->GetVector( 1 ); - } +void ExplodingWall::Explode(Event *ev) +{ + Entity *other; + Vector pos; + Vector mins, maxs; + int i; -void ExplodingWall::RandomVelocity - ( - Event *ev - ) + if (spawnflags & INVISIBLE) { + showModel(); + setSolidType(SOLID_BSP); + takedamage = DAMAGE_YES; + } - { - random_velocity = ev->GetVector( 1 ); - } + if (takedamage == DAMAGE_NO) { + return; + } -void ExplodingWall::SetDmg - ( - Event *ev - ) + other = ev->GetEntity(1); - { - dmg = ev->GetInteger( 1 ); - } + health = 0; + takedamage = DAMAGE_NO; -void ExplodingWall::SetExplosions - ( - Event *ev - ) + // Create explosions + for (i = 0; i < explosions; i++) { + pos[0] = absmin[0] + G_Random(size[0]); + pos[1] = absmin[1] + G_Random(size[1]); + pos[2] = absmin[2] + G_Random(size[2]); - { - explosions = ev->GetInteger( 1 ); - } + CreateExplosion(pos, dmg, this, other, this); + } -void ExplodingWall::Explode - ( - Event *ev - ) + // throw itself + state = 1; + on_ground = false; + PostEvent(EV_ExplodingWall_OnGround, FRAMETIME); - { - Entity *other; - Vector pos; - Vector mins, maxs; - int i; + velocity.x = base_velocity.x + G_CRandom(random_velocity.x); + velocity.y = base_velocity.y + G_CRandom(random_velocity.y); + velocity.z = base_velocity.z + G_Random(random_velocity.z); - if ( spawnflags & INVISIBLE ) - { - showModel(); - setSolidType( SOLID_BSP ); - takedamage = DAMAGE_YES; - } + setMoveType(MOVETYPE_BOUNCE); + setSolidType(SOLID_BBOX); + if (spawnflags & RANDOMANGLES) { + avelocity[0] = G_Random(angle_speed); + avelocity[1] = G_Random(angle_speed); + avelocity[2] = G_Random(angle_speed); + } else { + Vector delta; + float most; + float time; + int t; - if ( takedamage == DAMAGE_NO ) - { - return; - } + delta = land_angles - angles; + if (delta[0] > 180) { + delta[0] -= 360; + } + if (delta[0] < -180) { + delta[0] += 360; + } + if (delta[1] > 180) { + delta[1] -= 360; + } + if (delta[1] < -180) { + delta[1] += 360; + } + if (delta[2] > 180) { + delta[2] -= 360; + } + if (delta[2] < -180) { + delta[2] += 360; + } + most = MaxValue(delta); + if (!angle_speed) { + angle_speed = 1; + } + t = 10 * most / angle_speed; + time = (float)t / 10; + delta = delta * (1.0 / time); + avelocity = delta; + PostEvent(EV_ExplodingWall_StopRotating, time); + state = 2; + } - other = ev->GetEntity( 1 ); + ActivateTargets(ev); - health = 0; - takedamage = DAMAGE_NO; + if (land_radius > 0) { + mins[0] = mins[1] = mins[2] = -land_radius; + maxs[0] = maxs[1] = maxs[2] = land_radius; + setSize(mins, maxs); + } - // Create explosions - for( i = 0; i < explosions; i++ ) - { - pos[ 0 ] = absmin[ 0 ] + G_Random( size[ 0 ] ); - pos[ 1 ] = absmin[ 1 ] + G_Random( size[ 1 ] ); - pos[ 2 ] = absmin[ 2 ] + G_Random( size[ 2 ] ); + attack_finished = 0; +} - CreateExplosion( pos, dmg, this, other, this ); - } +void ExplodingWall::DamageEvent(Event *ev) +{ + Event *event; + Entity *inflictor; + Entity *attacker; + int damage; - // throw itself - state = 1; - on_ground = false; - PostEvent( EV_ExplodingWall_OnGround, FRAMETIME ); + if (takedamage == DAMAGE_NO) { + return; + } - velocity.x = base_velocity.x + G_CRandom( random_velocity.x ); - velocity.y = base_velocity.y + G_CRandom( random_velocity.y ); - velocity.z = base_velocity.z + G_Random( random_velocity.z ); + if (on_ground) { + GroundDamage(ev); + return; + } - setMoveType( MOVETYPE_BOUNCE ); - setSolidType( SOLID_BBOX ); - if ( spawnflags & RANDOMANGLES ) - { - avelocity[ 0 ] = G_Random( angle_speed ); - avelocity[ 1 ] = G_Random( angle_speed ); - avelocity[ 2 ] = G_Random( angle_speed ); - } - else - { - Vector delta; - float most; - float time; - int t; + attacker = ev->GetEntity(1); + damage = ev->GetInteger(2); + inflictor = ev->GetEntity(3); - delta = land_angles - angles; - if ( delta[ 0 ] > 180 ) - delta[ 0 ] -= 360; - if ( delta[ 0 ] < -180 ) - delta[ 0 ] += 360; - if ( delta[ 1 ] > 180 ) - delta[ 1 ] -= 360; - if ( delta[ 1 ] < -180 ) - delta[ 1 ] += 360; - if ( delta[ 2 ] > 180 ) - delta[ 2 ] -= 360; - if ( delta[ 2 ] < -180 ) - delta[ 2 ] += 360; - most = MaxValue( delta ); - if ( !angle_speed ) - angle_speed = 1; - t = 10 * most / angle_speed; - time = (float)t / 10; - delta = delta * (1.0/time); - avelocity = delta; - PostEvent( EV_ExplodingWall_StopRotating, time ); - state = 2; - } + if (spawnflags & ACCUMULATIVE) { + health -= damage; + if (health > 0) { + return; + } + } else { + if (damage < health) { + return; + } + } - ActivateTargets( ev ); + event = new Event(EV_Activate); + event->AddEntity(attacker); + ProcessEvent(event); +} - if ( land_radius > 0 ) - { - mins[0] = mins[1] = mins[2] = -land_radius; - maxs[0] = maxs[1] = maxs[2] = land_radius; - setSize( mins, maxs ); - } +void ExplodingWall::GroundDamage(Event *ev) +{ + Entity *inflictor; + Entity *attacker; + Vector pos; + int damage; - attack_finished = 0; - } + if (takedamage == DAMAGE_NO) { + return; + } -void ExplodingWall::DamageEvent - ( - Event *ev - ) + damage = ev->GetInteger(1); + inflictor = ev->GetEntity(2); + attacker = ev->GetEntity(3); - { - Event *event; - Entity *inflictor; - Entity *attacker; - int damage; + if (spawnflags & ACCUMULATIVE) { + health -= damage; + if (health > 0) { + return; + } + } else { + if (damage < health) { + return; + } + } - if ( takedamage == DAMAGE_NO ) - { - return; - } + if (explosions) { + pos[0] = absmin[0] + G_Random(size[0]); + pos[1] = absmin[1] + G_Random(size[1]); + pos[2] = absmin[2] + G_Random(size[2]); - if ( on_ground ) - { - GroundDamage( ev ); - return; - } + CreateExplosion(pos, damage, this, attacker, this); + } + takedamage = DAMAGE_NO; + hideModel(); + BroadcastAIEvent(); + PostEvent(EV_Remove, 0); +} - attacker = ev->GetEntity( 1 ); - damage = ev->GetInteger( 2 ); - inflictor = ev->GetEntity( 3 ); +void ExplodingWall::SetupSecondStage(void) +{ + health = max_health; + takedamage = DAMAGE_YES; +} - if ( spawnflags & ACCUMULATIVE ) - { - health -= damage; - if ( health > 0 ) - return; - } - else - { - if ( damage < health ) - { - return; - } - } +void ExplodingWall::StopRotating(Event *ev) +{ + avelocity = vec_zero; + setAngles(land_angles); + if (spawnflags & TWOSTAGE) { + SetupSecondStage(); + } +} - event = new Event( EV_Activate ); - event->AddEntity( attacker ); - ProcessEvent( event ); - } +void ExplodingWall::CheckOnGround(Event *ev) +{ + if ((velocity == vec_zero) && groundentity) { + Vector delta; + float most; + float time; + int t; -void ExplodingWall::GroundDamage - ( - Event *ev - ) + delta = land_angles - angles; + if (delta.length() > 1) { + if (delta[0] > 180) { + delta[0] -= 360; + } + if (delta[0] < -180) { + delta[0] += 360; + } + if (delta[1] > 180) { + delta[1] -= 360; + } + if (delta[1] < -180) { + delta[1] += 360; + } + if (delta[2] > 180) { + delta[2] -= 360; + } + if (delta[2] < -180) { + delta[2] += 360; + } + most = MaxValue(delta); + if (angle_speed > 3) { + t = 10.0f * most / (angle_speed / 3); + } else { + t = 10.0f * most; + } + time = (float)t / 10; + delta = delta * (1.0 / time); + avelocity = delta; + PostEvent(EV_ExplodingWall_StopRotating, time); + } + state = 2; + setSize(orig_mins, orig_maxs); + on_ground = true; + } else { + PostEvent(ev, FRAMETIME); + } +} - { - Entity *inflictor; - Entity *attacker; - Vector pos; - int damage; +void ExplodingWall::TouchFunc(Event *ev) +{ + Entity *other; - if ( takedamage == DAMAGE_NO ) - { - return; - } + if ((velocity == vec_zero) || (level.time < attack_finished)) { + return; + } - damage = ev->GetInteger( 1 ); - inflictor = ev->GetEntity( 2 ); - attacker = ev->GetEntity( 3 ); + other = ev->GetEntity(1); - if ( spawnflags & ACCUMULATIVE ) - { - health -= damage; - if ( health > 0 ) - return; - } - else - { - if ( damage < health ) - { - return; - } - } + if ((spawnflags & LANDSHATTER) && (other == world)) { + Vector pos; - if ( explosions ) - { - pos[ 0 ] = absmin[ 0 ] + G_Random( size[ 0 ] ); - pos[ 1 ] = absmin[ 1 ] + G_Random( size[ 1 ] ); - pos[ 2 ] = absmin[ 2 ] + G_Random( size[ 2 ] ); + takedamage = DAMAGE_NO; - CreateExplosion( pos, damage, this, attacker, this ); - } - takedamage = DAMAGE_NO; - hideModel(); - BroadcastAIEvent(); - PostEvent( EV_Remove, 0 ); - } + if (explosions) { + pos[0] = absmin[0] + G_Random(size[0]); + pos[1] = absmin[1] + G_Random(size[1]); + pos[2] = absmin[2] + G_Random(size[2]); -void ExplodingWall::SetupSecondStage - ( - void - ) + CreateExplosion(pos, dmg, this, other, this); + } + hideModel(); + BroadcastAIEvent(); + PostEvent(EV_Remove, 0); + return; + } - { - health = max_health; - takedamage = DAMAGE_YES; - } + if (other->takedamage) { + other->Damage(this, activator, dmg, origin, vec_zero, vec_zero, 20, 0, MOD_EXPLODEWALL); + Sound("debris_generic", CHAN_WEAPON); + attack_finished = level.time + FRAMETIME; + } +} -void ExplodingWall::StopRotating - ( - Event *ev - ) +void ExplodingWall::Setup(Event *ev) +{ + if (spawnflags & INVISIBLE) { + if (Targeted()) { + takedamage = DAMAGE_YES; + } else { + takedamage = DAMAGE_NO; + } + hideModel(); + setSolidType(SOLID_NOT); + } else { + showModel(); + setSolidType(SOLID_BSP); + takedamage = DAMAGE_YES; + } - { - avelocity = vec_zero; - setAngles( land_angles ); - if ( spawnflags & TWOSTAGE ) - SetupSecondStage(); - } - -void ExplodingWall::CheckOnGround - ( - Event *ev - ) - - { - if ( ( velocity == vec_zero ) && groundentity ) - { - Vector delta; - float most; - float time; - int t; - - delta = land_angles - angles; - if ( delta.length() > 1 ) - { - if ( delta[ 0 ] > 180 ) - delta[ 0 ] -= 360; - if ( delta[ 0 ] < -180 ) - delta[ 0 ] += 360; - if ( delta[ 1 ] > 180 ) - delta[ 1 ] -= 360; - if ( delta[ 1 ] < -180 ) - delta[ 1 ] += 360; - if ( delta[ 2 ] > 180 ) - delta[ 2 ] -= 360; - if ( delta[ 2 ] < -180 ) - delta[ 2 ] += 360; - most = MaxValue( delta ); - if ( angle_speed > 3 ) - t = 10.0f * most / ( angle_speed / 3 ); - else - t = 10.0f * most; - time = (float)t / 10; - delta = delta * (1.0/time); - avelocity = delta; - PostEvent( EV_ExplodingWall_StopRotating, time ); - } - state = 2; - setSize( orig_mins, orig_maxs ); - on_ground = true; - } - else - PostEvent( ev, FRAMETIME ); - } - -void ExplodingWall::TouchFunc - ( - Event *ev - ) - - { - Entity *other; - - if ( ( velocity == vec_zero ) || ( level.time < attack_finished ) ) - { - return; - } - - other = ev->GetEntity( 1 ); - - if ( ( spawnflags & LANDSHATTER ) && ( other == world ) ) - { - Vector pos; - - takedamage = DAMAGE_NO; - - if ( explosions ) - { - pos[ 0 ] = absmin[ 0 ] + G_Random( size[ 0 ] ); - pos[ 1 ] = absmin[ 1 ] + G_Random( size[ 1 ] ); - pos[ 2 ] = absmin[ 2 ] + G_Random( size[ 2 ] ); - - CreateExplosion( pos, dmg, this, other, this ); - } - hideModel(); - BroadcastAIEvent(); - PostEvent( EV_Remove, 0 ); - return; - } - - if ( other->takedamage ) - { - other->Damage( this, activator, dmg, origin, vec_zero, vec_zero, 20, 0, MOD_EXPLODEWALL ); - Sound( "debris_generic", CHAN_WEAPON ); - attack_finished = level.time + FRAMETIME; - } - } - -void ExplodingWall::Setup - ( - Event *ev - ) - - { - if ( spawnflags & INVISIBLE ) - { - if ( Targeted() ) - takedamage = DAMAGE_YES; - else - takedamage = DAMAGE_NO; - hideModel(); - setSolidType( SOLID_NOT ); - } - else - { - showModel(); - setSolidType( SOLID_BSP ); - takedamage = DAMAGE_YES; - } - - setMoveType( MOVETYPE_PUSH ); - setOrigin(); - } + setMoveType(MOVETYPE_PUSH); + setOrigin(); +} ExplodingWall::ExplodingWall() - { - if ( LoadingSavegame ) - { - return; - } +{ + if (LoadingSavegame) { + return; + } - health = 60; - max_health = health; - on_ground = false; + health = 60; + max_health = health; + on_ground = false; - state = 0; - angle_speed = ( spawnflags & RANDOMANGLES ) ? 600 : 100; - land_radius = 16; - dmg = 10; - explosions = 1; + state = 0; + angle_speed = (spawnflags & RANDOMANGLES) ? 600 : 100; + land_radius = 16; + dmg = 10; + explosions = 1; - base_velocity = Vector( 0, 0, 280 ); - random_velocity = Vector( 140, 140, 140 ); + base_velocity = Vector(0, 0, 280); + random_velocity = Vector(140, 140, 140); - orig_mins = mins; - orig_maxs = maxs; + orig_mins = mins; + orig_maxs = maxs; - respondto = spawnflags ^ TRIGGER_PLAYERS; + respondto = spawnflags ^ TRIGGER_PLAYERS; - PostEvent( EV_ExplodingWall_Setup, EV_POSTSPAWN ); - } + PostEvent(EV_ExplodingWall_Setup, EV_POSTSPAWN); +} /*****************************************************************************/ /*QUAKED trigger_teleport (0.5 0.5 0.5) ? VISIBLE x NOT_PLAYERS NOT_MONSTERS NOT_PROJECTILES NO_EFFECTS @@ -694,323 +608,290 @@ If NO_EFFECTS is set, the special effect will not happen and the teleport will b ******************************************************************************/ -#define NO_EFFECTS ( 1 << 5 ) +#define NO_EFFECTS (1 << 5) Event EV_Teleporter_Teleport - ( - "teleport", - EV_CODEONLY, - "e", - "entity", - "Teleports the entity to destination.", - EV_NORMAL - ); - +( + "teleport", + EV_CODEONLY, + "e", + "entity", + "Teleports the entity to destination.", + EV_NORMAL +); Event EV_Teleporter_StopTeleport - ( - "stopteleport", - EV_CODEONLY, - "e", - "entity", - "Releases the entity at the end of the teleport.", - EV_NORMAL - ); +( + "stopteleport", + EV_CODEONLY, + "e", + "entity", + "Releases the entity at the end of the teleport.", + EV_NORMAL +); Event EV_Teleporter_SetThread - ( - "teleportthread", - EV_CODEONLY, - "s", - "thread_name", - "Sets the thread to run when the player is teleported.", - EV_NORMAL - ); +( + "teleportthread", + EV_CODEONLY, + "s", + "thread_name", + "Sets the thread to run when the player is teleported.", + EV_NORMAL +); -CLASS_DECLARATION( Trigger, Teleporter, "trigger_teleport" ) - { - { &EV_Trigger_Effect, &Teleporter::StartTeleport }, - { &EV_Teleporter_Teleport, &Teleporter::Teleport }, - { &EV_Teleporter_StopTeleport, &Teleporter::StopTeleport }, - { &EV_Teleporter_SetThread, &Teleporter::SetThread }, - { NULL, NULL } - }; +CLASS_DECLARATION(Trigger, Teleporter, "trigger_teleport") { + {&EV_Trigger_Effect, &Teleporter::StartTeleport}, + {&EV_Teleporter_Teleport, &Teleporter::Teleport }, + {&EV_Teleporter_StopTeleport, &Teleporter::StopTeleport }, + {&EV_Teleporter_SetThread, &Teleporter::SetThread }, + {NULL, NULL } +}; -void Teleporter::SetThread - ( - Event *ev - ) - { - teleport_label.SetThread( ev->GetValue( 1 ) ); - } +void Teleporter::SetThread(Event *ev) +{ + teleport_label.SetThread(ev->GetValue(1)); +} -void Teleporter::StartTeleport - ( - Event *ev - ) - { - Animate *fx; - Entity *other; - Event *event; - qboolean is_sentient; - Vector new_position; +void Teleporter::StartTeleport(Event *ev) +{ + Animate *fx; + Entity *other; + Event *event; + qboolean is_sentient; + Vector new_position; + if (in_use) { + return; + } - if ( in_use ) - return; + in_use = true; - in_use = true; + other = ev->GetEntity(1); - other = ev->GetEntity( 1 ); + if (!other) { + return; + } - if ( !other ) - return; + if (spawnflags & NO_EFFECTS) { + event = new Event(EV_Teleporter_Teleport); + event->AddEntity(other); + ProcessEvent(event); + return; + } - if ( spawnflags & NO_EFFECTS ) - { - event = new Event( EV_Teleporter_Teleport ); - event->AddEntity( other ); - ProcessEvent( event ); - return; - } + if (other->isSubclassOf(Sentient)) { + is_sentient = true; + } else { + is_sentient = false; + } - if ( other->isSubclassOf( Sentient ) ) - is_sentient = true; - else - is_sentient = false; + if (is_sentient) { + new_position = origin; + new_position.z += mins.z; + other->setOrigin(new_position); + other->NoLerpThisFrame(); + } - if ( is_sentient ) - { - new_position = origin; - new_position.z += mins.z; - other->setOrigin( new_position ); - other->NoLerpThisFrame(); - } + // Create the teleport special effect - // Create the teleport special effect + fx = new Animate; + fx->setOrigin(other->origin); - fx = new Animate; - fx->setOrigin( other->origin ); + fx->NewAnim("idle", EV_Remove); - fx->NewAnim( "idle", EV_Remove ); + if (is_sentient) { + fx->setModel("fx_bigteleport.tik"); + //fx->Sound( "sound/environment/electric/singles/dimming.wav" ); + } else { + fx->setModel("fx_teleport2.tik"); + } - if ( is_sentient ) - { - fx->setModel( "fx_bigteleport.tik" ); - //fx->Sound( "sound/environment/electric/singles/dimming.wav" ); - } - else - { - fx->setModel( "fx_teleport2.tik" ); - } + if (is_sentient) { + // Freeze the entity that went into the teleporter - if ( is_sentient ) - { - // Freeze the entity that went into the teleporter + other->flags |= FL_IMMOBILE; + other->takedamage = DAMAGE_NO; + } - other->flags |= FL_IMMOBILE; - other->takedamage = DAMAGE_NO; - } + // Make the entity teleport - // Make the entity teleport + event = new Event(EV_Teleporter_Teleport); + event->AddEntity(other); - event = new Event( EV_Teleporter_Teleport ); - event->AddEntity( other ); + if (is_sentient) { + PostEvent(event, 4); + } else { + PostEvent(event, 0); + } - if ( is_sentient ) - PostEvent( event, 4 ); - else - PostEvent( event, 0 ); + if (is_sentient) { + other->PostEvent(EV_CODEONLY, 2); - if ( is_sentient ) - { - other->PostEvent( EV_CODEONLY, 2 ); - - /* if ( !( spawnflags & NO_EFFECTS ) ) + /* if ( !( spawnflags & NO_EFFECTS ) ) { event = new Event( EV_Sound ); event->AddString( "snd_teleport" ); other->PostEvent( event, 2 ); } */ - } - } + } +} -void Teleporter::Teleport - ( - Event *ev - ) +void Teleporter::Teleport(Event *ev) +{ + Entity *dest; + int i; + Entity *other; + Vector mid; + Animate *fx; + Event *event; - { - Entity *dest; - int i; - Entity *other; - Vector mid; - Animate *fx; - Event *event; + other = ev->GetEntity(1); - other = ev->GetEntity( 1 ); + if (!other || (other == world)) { + return; + } - if ( !other || ( other == world ) ) - return; + dest = (Entity *)G_FindTarget(NULL, Target()); + if (!dest) { + warning("Teleport", "Couldn't find destination\n"); + return; + } - dest = ( Entity * )G_FindTarget( NULL, Target() ); - if ( !dest ) - { - warning( "Teleport", "Couldn't find destination\n" ); - return; - } + assert(dest); - assert( dest ); + // unlink to make sure it can't possibly interfere with KillBox + other->unlink(); - // unlink to make sure it can't possibly interfere with KillBox - other->unlink(); + if (other->isSubclassOf(Sentient)) { + other->origin = dest->origin + Vector(0, 0, 1); + other->velocity = vec_zero; + } else { + mid = (absmax - absmin) * 0.5; + other->origin = dest->origin + Vector(0, 0, 1); + other->origin += mid; + } - if ( other->isSubclassOf( Sentient ) ) - { - other->origin = dest->origin + Vector( 0, 0, 1 ); - other->velocity = vec_zero; - } - else - { - mid = ( absmax - absmin ) * 0.5; - other->origin = dest->origin + Vector( 0, 0, 1 ); - other->origin += mid; - } + // set angles + other->setAngles(dest->angles); - // set angles - other->setAngles( dest->angles ); + if (other->client) { + client = other->client; - if ( other->client ) - { - client = other->client; + // clear the velocity and hold them in place briefly + client->ps.pm_time = 100; + client->ps.pm_flags |= PMF_RESPAWNED; - // clear the velocity and hold them in place briefly - client->ps.pm_time = 100; - client->ps.pm_flags |= PMF_RESPAWNED; + // cut the camera on the client + ((Player *)other)->CameraCut(); - // cut the camera on the client - ( ( Player * )other )->CameraCut(); + for (i = 0; i < 3; i++) { + client->ps.delta_angles[i] = ANGLE2SHORT(dest->angles[i] - client->cmd_angles[i]); + } - for( i = 0; i < 3; i++ ) - { - client->ps.delta_angles[ i ] = ANGLE2SHORT( dest->angles[ i ] - client->cmd_angles[ i ] ); - } + VectorCopy(angles, client->ps.viewangles); + } - VectorCopy( angles, client->ps.viewangles ); - } + if (dest->isSubclassOf(TeleporterDestination)) { + float len; - if ( dest->isSubclassOf( TeleporterDestination ) ) - { - float len; + len = other->velocity.length(); + // + // give them a bit of a push + // + if (len < 400) { + len = 400; + } + other->velocity = ((TeleporterDestination *)dest)->movedir * len; + } - len = other->velocity.length(); - // - // give them a bit of a push - // - if ( len < 400 ) - len = 400; - other->velocity = ( ( TeleporterDestination * )dest )->movedir * len; - } + // kill anything at the destination + KillBox(other); - // kill anything at the destination - KillBox( other ); + other->setOrigin(other->origin); + other->origin.copyTo(other->edict->s.origin2); - other->setOrigin( other->origin ); - other->origin.copyTo( other->edict->s.origin2 ); + // Run the teleport thread if set - // Run the teleport thread if set + if (teleport_label.IsSet() && other->isSubclassOf(Player)) { + teleport_label.Execute(this); + } - if ( teleport_label.IsSet() && other->isSubclassOf( Player ) ) - { - teleport_label.Execute( this ); - } + // Skip effects if no_effects set - // Skip effects if no_effects set + if (spawnflags & NO_EFFECTS) { + Event *event = new Event(EV_Teleporter_StopTeleport); + event->AddEntity(other); + ProcessEvent(event); + return; + } - if ( spawnflags & NO_EFFECTS ) - { - Event *event = new Event( EV_Teleporter_StopTeleport ); - event->AddEntity( other ); - ProcessEvent( event ); - return; - } + // Spawn in effect - // Spawn in effect + fx = new Animate; - fx = new Animate; + fx->setOrigin(other->origin); - fx->setOrigin( other->origin ); + fx->NewAnim("idle", EV_Remove); - fx->NewAnim( "idle", EV_Remove ); + if (other->isSubclassOf(Sentient)) { + fx->setModel("fx_bigteleport.tik"); + } else { + fx->setModel("fx_teleport2.tik"); + } - if ( other->isSubclassOf( Sentient ) ) - { - fx->setModel( "fx_bigteleport.tik" ); - } - else - { - fx->setModel( "fx_teleport2.tik" ); - } + event = new Event(EV_Teleporter_StopTeleport); + event->AddEntity(other); - event = new Event( EV_Teleporter_StopTeleport ); - event->AddEntity( other ); + if (other->isSubclassOf(Sentient)) { + PostEvent(event, 1.75); + } else { + PostEvent(event, FRAMETIME); + } +} - if ( other->isSubclassOf( Sentient ) ) - PostEvent( event, 1.75 ); - else - PostEvent( event, FRAMETIME ); - } +void Teleporter::StopTeleport(Event *ev) +{ + Entity *other; -void Teleporter::StopTeleport - ( - Event *ev - ) + other = ev->GetEntity(1); - { - Entity *other; + if (other->isSubclassOf(Sentient)) { + other->flags &= ~FL_IMMOBILE; + other->takedamage = DAMAGE_AIM; + other->showModel(); + } - other = ev->GetEntity( 1 ); + //if ( !( spawnflags & NO_EFFECTS ) ) + // other->Sound( "snd_teleport" ); - if ( other->isSubclassOf( Sentient ) ) - { - other->flags &= ~FL_IMMOBILE; - other->takedamage = DAMAGE_AIM; - other->showModel(); - } - - //if ( !( spawnflags & NO_EFFECTS ) ) - // other->Sound( "snd_teleport" ); - - in_use = false; - } + in_use = false; +} Teleporter::Teleporter() { - AddWaitTill(STRING_TELEPORT); + AddWaitTill(STRING_TELEPORT); - if ( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - if ( spawnflags & 1 ) - { - PostEvent( EV_Show, EV_POSTSPAWN ); - } + if (spawnflags & 1) { + PostEvent(EV_Show, EV_POSTSPAWN); + } - //respondto = spawnflags ^ ( TRIGGER_PLAYERS | TRIGGER_MONSTERS | TRIGGER_PROJECTILES ); - respondto = spawnflags ^ ( TRIGGER_PLAYERS ); + //respondto = spawnflags ^ ( TRIGGER_PLAYERS | TRIGGER_MONSTERS | TRIGGER_PROJECTILES ); + respondto = spawnflags ^ (TRIGGER_PLAYERS); - in_use = false; + in_use = false; - // Cache all needed stuff + // Cache all needed stuff - if ( !( spawnflags & NO_EFFECTS ) ) - { - CacheResource( "models/fx_bigteleport.tik" ); - //CacheResource( "sound/environment/electric/singles/dimming.wav", this ); - CacheResource( "fx_teleport2.tik" ); - //CacheResource( "snd_teleport", this ); - } + if (!(spawnflags & NO_EFFECTS)) { + CacheResource("models/fx_bigteleport.tik"); + //CacheResource( "sound/environment/electric/singles/dimming.wav", this ); + CacheResource("fx_teleport2.tik"); + //CacheResource( "snd_teleport", this ); + } } /*****************************************************************************/ @@ -1020,28 +901,24 @@ Point trigger_teleport at these. ******************************************************************************/ -CLASS_DECLARATION( Entity, TeleporterDestination, "func_teleportdest" ) -{ - { &EV_SetAngle, &TeleporterDestination::SetMoveDir }, - { NULL, NULL } +CLASS_DECLARATION(Entity, TeleporterDestination, "func_teleportdest") { + {&EV_SetAngle, &TeleporterDestination::SetMoveDir}, + {NULL, NULL } }; TeleporterDestination::TeleporterDestination() - { - movedir = G_GetMovedir( 0 ); - } +{ + movedir = G_GetMovedir(0); +} -void TeleporterDestination::SetMoveDir - ( - Event *ev - ) - { - float angle; +void TeleporterDestination::SetMoveDir(Event *ev) +{ + float angle; - angle = ev->GetFloat( 1 ); - movedir = G_GetMovedir( angle ); - setAngles( movedir.toAngles() ); - } + angle = ev->GetFloat(1); + movedir = G_GetMovedir(angle); + setAngles(movedir.toAngles()); +} /*****************************************************************************/ /*QUAKED func_useanim (0 0.5 0) ? VISIBLE TOUCHABLE CONTINUOUS @@ -1066,584 +943,464 @@ it waits until the player has left the trigger field. ******************************************************************************/ Event EV_UseAnim_Reset - ( - "_reset", - EV_CODEONLY, - NULL, - NULL, - "Reset's the Use Anim after it has no longer been touched.", - EV_NORMAL - ); +( + "_reset", + EV_CODEONLY, + NULL, + NULL, + "Reset's the Use Anim after it has no longer been touched.", + EV_NORMAL +); Event EV_UseAnim_Thread - ( - "setthread", - EV_DEFAULT, - "s", - "label", - "Sets which thread to use when this UseAnim is triggered.", - EV_NORMAL - ); +( + "setthread", + EV_DEFAULT, + "s", + "label", + "Sets which thread to use when this UseAnim is triggered.", + EV_NORMAL +); Event EV_UseAnim_Count - ( - "count", - EV_DEFAULT, - "i", - "newCount", - "Sets how many times the UseAnim can be triggered.", - EV_NORMAL - ); +( + "count", EV_DEFAULT, + "i", + "newCount", + "Sets how many times the UseAnim can be triggered.", + EV_NORMAL +); Event EV_UseAnim_TriggerTarget - ( - "triggertarget", - EV_DEFAULT, - "s", - "targetname", - "Sets what should be triggered, when this UseAnim is triggered.", - EV_NORMAL - ); - +( + "triggertarget", + EV_DEFAULT, + "s", + "targetname", + "Sets what should be triggered, when this UseAnim is triggered.", + EV_NORMAL +); Event EV_UseAnim_SetAnim - ( - "anim", - EV_DEFAULT, - "s", - "animName", - "set the animation to use for player.", - EV_NORMAL - ); - +( + "anim", + EV_DEFAULT, + "s", + "animName", + "set the animation to use for player.", + EV_NORMAL +); Event EV_UseAnim_SetKey - ( - "key", - EV_DEFAULT, - "s", - "keyName", - "set the key needed to make this UseAnim function.", - EV_NORMAL - ); - +( + "key", + EV_DEFAULT, + "s", + "keyName", + "set the key needed to make this UseAnim function.", + EV_NORMAL +); Event EV_UseAnim_SetState - ( - "state", - EV_CHEAT, - "s", - "stateName", - "set the state to use for the player.", - EV_NORMAL - ); - -Event EV_UseAnim_SetCamera - ( - "camera", - EV_DEFAULT, - "s", - "cameraPosition", - "set the camera to use when in this animation.\n" - "topdown, behind, front, side, behind_fixed, side_left, side_right", - EV_NORMAL - ); - +( + "state", + EV_CHEAT, + "s", + "stateName", + "set the state to use for the player.", + EV_NORMAL +); +Event EV_UseAnim_SetCamera( + "camera", + EV_DEFAULT, + "s", + "cameraPosition", + "set the camera to use when in this animation.\n" + "topdown, behind, front, side, behind_fixed, side_left, side_right", + EV_NORMAL +); Event EV_UseAnim_SetNumLoops - ( - "num_loops", - EV_DEFAULT, - "i", - "loopCount", - "set the number of times to loop an animation per use.", - EV_NORMAL - ); +( + "num_loops", + EV_DEFAULT, + "i", + "loopCount", + "set the number of times to loop an animation per use.", + EV_NORMAL -Event EV_UseAnim_SetDelay - ( - "delay", - EV_DEFAULT, - "f", - "delayTime", - "how long it takes for the UseAnim to be retriggered once you leave it.", - EV_NORMAL - ); +); +Event EV_UseAnim_SetDelay( + "delay", + EV_DEFAULT, + "f", + "delayTime", + "how long it takes for the UseAnim to be retriggered once you leave it.", + EV_NORMAL +); - -CLASS_DECLARATION( Entity, UseAnim, "func_useanim" ) - { - { &EV_Use, NULL }, - { &EV_Touch, &UseAnim::Touched }, - { &EV_UseAnim_Reset, &UseAnim::Reset }, - { &EV_UseAnim_Thread, &UseAnim::SetThread }, - { &EV_UseAnim_TriggerTarget, &UseAnim::SetTriggerTarget }, - { &EV_UseAnim_Count, &UseAnim::SetCount }, - { &EV_UseAnim_SetAnim, &UseAnim::SetAnim }, - { &EV_UseAnim_SetState, &UseAnim::SetState }, - { &EV_UseAnim_SetKey, &UseAnim::SetKey }, - { &EV_UseAnim_SetNumLoops, &UseAnim::SetNumLoops }, - { &EV_UseAnim_SetCamera, &UseAnim::SetCamera }, - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, UseAnim, "func_useanim") { + {&EV_Use, NULL }, + {&EV_Touch, &UseAnim::Touched }, + {&EV_UseAnim_Reset, &UseAnim::Reset }, + {&EV_UseAnim_Thread, &UseAnim::SetThread }, + {&EV_UseAnim_TriggerTarget, &UseAnim::SetTriggerTarget}, + {&EV_UseAnim_Count, &UseAnim::SetCount }, + {&EV_UseAnim_SetAnim, &UseAnim::SetAnim }, + {&EV_UseAnim_SetState, &UseAnim::SetState }, + {&EV_UseAnim_SetKey, &UseAnim::SetKey }, + {&EV_UseAnim_SetNumLoops, &UseAnim::SetNumLoops }, + {&EV_UseAnim_SetCamera, &UseAnim::SetCamera }, + {NULL, NULL } +}; UseAnim::UseAnim() - { - AddWaitTill(STRING_TRIGGER); - if ( LoadingSavegame ) - { - return; - } +{ + AddWaitTill(STRING_TRIGGER); + if (LoadingSavegame) { + return; + } - setMoveType( MOVETYPE_NONE ); + setMoveType(MOVETYPE_NONE); - anim = "stand_use"; - num_loops = 1; - hideModel(); + anim = "stand_use"; + num_loops = 1; + hideModel(); - // - // make it not solid unless we want it touchable - // - if ( !( spawnflags & 2 ) ) - { - setSolidType( SOLID_BBOX ); - setContents( CONTENTS_BODY ); - } - else - { - setSolidType( SOLID_TRIGGER ); - edict->r.svFlags |= SVF_NOCLIENT; - } + // + // make it not solid unless we want it touchable + // + if (!(spawnflags & 2)) { + setSolidType(SOLID_BBOX); + setContents(CONTENTS_BODY); + } else { + setSolidType(SOLID_TRIGGER); + edict->r.svFlags |= SVF_NOCLIENT; + } - // by default this can activated infinitely - count = -1; - // clear out the triggertarget - triggertarget = ""; - // clear out the thread - thread.Set( "" ); - // set the default delay - delay = 3; - // initialize the last time the door was triggered - last_active_time = -delay; - // initially its not active - active = 0; - // set the default camera to be side view - camera = "behind"; - // - // only make it visible if so desired - // - if ( spawnflags & 1 ) - { - PostEvent( EV_Show, EV_POSTSPAWN ); - } - } + // by default this can activated infinitely + count = -1; + // clear out the triggertarget + triggertarget = ""; + // clear out the thread + thread.Set(""); + // set the default delay + delay = 3; + // initialize the last time the door was triggered + last_active_time = -delay; + // initially its not active + active = 0; + // set the default camera to be side view + camera = "behind"; + // + // only make it visible if so desired + // + if (spawnflags & 1) { + PostEvent(EV_Show, EV_POSTSPAWN); + } +} -void UseAnim::Touched - ( - Event *ev - ) +void UseAnim::Touched(Event *ev) +{ + Entity *other; - { - Entity *other; - - if ( active && ( !( spawnflags & 4 ) ) ) - { - CancelEventsOfType( EV_UseAnim_Reset ); - PostEvent( EV_UseAnim_Reset, 0.25f ); - return; - } + if (active && (!(spawnflags & 4))) { + CancelEventsOfType(EV_UseAnim_Reset); + PostEvent(EV_UseAnim_Reset, 0.25f); + return; + } - // don't retrigger to soon - if ( level.time < last_active_time ) - return; + // don't retrigger to soon + if (level.time < last_active_time) { + return; + } - other = ev->GetEntity( 1 ); - if ( other->isSubclassOf( Player ) ) - { - ( ( Player * ) other )->TouchedUseAnim( this ); - } - } + other = ev->GetEntity(1); + if (other->isSubclassOf(Player)) { + ((Player *)other)->TouchedUseAnim(this); + } +} -bool UseAnim::canBeUsed - ( - Entity * activator - ) - - { - Entity *dest; +bool UseAnim::canBeUsed(Entity *activator) +{ + Entity *dest; - // if this is no longer usable, return false - if ( !count ) - { - return false; - } + // if this is no longer usable, return false + if (!count) { + return false; + } - // don't retrigger to soon - if ( level.time < last_active_time ) - { - return false; - } + // don't retrigger to soon + if (level.time < last_active_time) { + return false; + } - if ( key.length() ) - { - if ( !activator->isSubclassOf( Sentient ) ) - { - return false; - } - if ( !( ( (Sentient *)activator )->HasItem( key.c_str() ) ) ) - { - qboolean setModel; - Item *item; - ClassDef *cls; - str dialog; + if (key.length()) { + if (!activator->isSubclassOf(Sentient)) { + return false; + } + if (!(((Sentient *)activator)->HasItem(key.c_str()))) { + qboolean setModel; + Item *item; + ClassDef *cls; + str dialog; - cls = FindClass( key.c_str(), &setModel ); - if ( !cls || !checkInheritance( "Item", cls->classname ) ) - { - gi.DPrintf( "No item named '%s'\n", key.c_str() ); - return true; - } - item = ( Item * )cls->newInstance(); - if ( setModel ) - { - item->setModel( key.c_str() ); + cls = FindClass(key.c_str(), &setModel); + if (!cls || !checkInheritance("Item", cls->classname)) { + gi.DPrintf("No item named '%s'\n", key.c_str()); + return true; } - item->CancelEventsOfType( EV_Item_DropToFloor ); - item->CancelEventsOfType( EV_Remove ); - item->ProcessPendingEvents(); - dialog = item->GetDialogNeeded(); - if ( dialog.length() > 0 ) - { - activator->Sound( dialog ); + item = (Item *)cls->newInstance(); + if (setModel) { + item->setModel(key.c_str()); } - else - { - gi.centerprintf ( activator->edict, "You need the %s", item->getName().c_str() ); + item->CancelEventsOfType(EV_Item_DropToFloor); + item->CancelEventsOfType(EV_Remove); + item->ProcessPendingEvents(); + dialog = item->GetDialogNeeded(); + if (dialog.length() > 0) { + activator->Sound(dialog); + } else { + gi.centerprintf(activator->edict, "You need the %s", item->getName().c_str()); } - delete item; + delete item; - // don't retrigger for 5 seconds - last_active_time = level.time + 5; - return false; - } - else - { - return qtrue; - } - } + // don't retrigger for 5 seconds + last_active_time = level.time + 5; + return false; + } else { + return qtrue; + } + } - if ( isSubclassOf( TouchAnim ) ) - { - return true; - } + if (isSubclassOf(TouchAnim)) { + return true; + } - dest = ( Entity * )G_FindTarget( NULL, Target() ); - if ( !dest || !dest->isSubclassOf( UseAnimDestination ) ) - { - warning( "UseAnim", "Couldn't find destination\n" ); - return false; - } + dest = (Entity *)G_FindTarget(NULL, Target()); + if (!dest || !dest->isSubclassOf(UseAnimDestination)) { + warning("UseAnim", "Couldn't find destination\n"); + return false; + } - return true; - } + return true; +} -bool UseAnim::GetInformation - ( - Entity *activator, - Vector *org, - Vector *angles, - str *animation, - int *loopcount, - str *state, - str *camera - ) +bool UseAnim::GetInformation( + Entity *activator, Vector *org, Vector *angles, str *animation, int *loopcount, str *state, str *camera +) +{ + Entity *dest; + UseAnimDestination *uadest; - { - Entity *dest; - UseAnimDestination *uadest; + // if this is no longer usable, return false + if (!count) { + return false; + } - // if this is no longer usable, return false - if ( !count ) - { - return false; - } + dest = (Entity *)G_FindTarget(NULL, Target()); - dest = ( Entity * )G_FindTarget( NULL, Target() ); + if (!dest || !dest->isSubclassOf(UseAnimDestination)) { + // grab the information from this entity instead + // set the destination origin + *org = origin; + // set the destination angles + *angles = this->angles; + // set the desination animation + *animation = anim; + // set the number of loops + *loopcount = num_loops; + // get the state if necessary + *state = this->state; + // set the camera + *camera = this->camera; + } else { + uadest = (UseAnimDestination *)dest; - if ( !dest || !dest->isSubclassOf( UseAnimDestination ) ) - { - // grab the information from this entity instead - // set the destination origin - *org = origin; - // set the destination angles - *angles = this->angles; - // set the desination animation - *animation = anim; - // set the number of loops - *loopcount = num_loops; - // get the state if necessary - *state = this->state; - // set the camera - *camera = this->camera; - } - else - { - uadest = ( UseAnimDestination * )dest; + // set the destination origin + *org = uadest->origin; + // set the destination angles + *angles = uadest->angles; + // set the desination animation + *animation = uadest->GetAnim(); + // set the number of loops + *loopcount = uadest->GetNumLoops(); + // get the state if necessary + *state = uadest->GetState(); + // set the camera + *camera = this->camera; + } - // set the destination origin - *org = uadest->origin; - // set the destination angles - *angles = uadest->angles; - // set the desination animation - *animation = uadest->GetAnim(); - // set the number of loops - *loopcount = uadest->GetNumLoops(); - // get the state if necessary - *state = uadest->GetState(); - // set the camera - *camera = this->camera; - } + // make this guy active + active = qtrue; - - // make this guy active - active = qtrue; - - // if this is a TouchAnim see if it is linked to another TouchAnim - if ( isSubclassOf( TouchAnim ) ) - { - dest = NULL; - do { - dest = ( Entity * )G_FindTarget( dest, Target() ); - if ( dest ) - { - if ( dest->isSubclassOf( UseAnim ) ) - { - // make our linked UseAnim's active as well - ( ( UseAnim * )dest )->active = qtrue; - } + // if this is a TouchAnim see if it is linked to another TouchAnim + if (isSubclassOf(TouchAnim)) { + dest = NULL; + do { + dest = (Entity *)G_FindTarget(dest, Target()); + if (dest) { + if (dest->isSubclassOf(UseAnim)) { + // make our linked UseAnim's active as well + ((UseAnim *)dest)->active = qtrue; + } + } else { + break; } - else - { - break; + } while (1); + } + // + // decrement the use + // + if (count > 0) { + count--; + } + + return true; +} + +void UseAnim::TriggerTargets(Entity *activator) +{ + // + // fire off our trigger target if appropriate + // + if (triggertarget.length()) { + Event *event; + Entity *ent; + + ent = NULL; + do { + ent = (Entity *)G_FindTarget(ent, triggertarget.c_str()); + if (!ent) { + break; } - } - while( 1 ); - } - // - // decrement the use - // - if ( count > 0 ) - { - count--; - } + event = new Event(EV_Activate); + event->AddEntity(activator); + ent->PostEvent(event, 0); + } while (1); + } - return true; - } + // + // fire off a thread if necessary + // + if (thread.IsSet()) { + thread.Execute(this); + } +} -void UseAnim::TriggerTargets - ( - Entity *activator - ) +void UseAnim::Reset(Event *ev) +{ + // + // find out if our triggertarget is of type door and only reset if the door is closed + // + if (triggertarget.length()) { + Entity *ent; - { - // - // fire off our trigger target if appropriate - // - if ( triggertarget.length() ) - { - Event *event; - Entity *ent; - - ent = NULL; - do - { - ent = ( Entity * )G_FindTarget( ent, triggertarget.c_str() ); - if ( !ent ) - { - break; - } - event = new Event( EV_Activate ); - event->AddEntity( activator ); - ent->PostEvent( event, 0 ); - } - while ( 1 ); - } - - // - // fire off a thread if necessary - // - if ( thread.IsSet() ) - { - thread.Execute( this ); - } - } - -void UseAnim::Reset - ( - Event *ev - ) - - { - // - // find out if our triggertarget is of type door and only reset if the door is closed - // - if ( triggertarget.length() ) - { - Entity *ent; - - ent = NULL; - do - { - ent = ( Entity * )G_FindTarget( ent, triggertarget.c_str() ); - if ( !ent ) - { - break; - } - if ( ent->isSubclassOf( Door ) ) - { - if ( !( ( Door * )ent )->isCompletelyClosed() ) - { - CancelEventsOfType( EV_UseAnim_Reset ); - PostEvent( EV_UseAnim_Reset, 0.25f ); - // - // wait for a little bit - // - return; - } + ent = NULL; + do { + ent = (Entity *)G_FindTarget(ent, triggertarget.c_str()); + if (!ent) { + break; } - } - while ( 1 ); - } - - active = qfalse; - last_active_time = level.time + delay; - - // if this is a TouchAnim see if it is linked to another TouchAnim - if ( isSubclassOf( TouchAnim ) ) - { - Entity *dest; - - dest = NULL; - do { - dest = ( Entity * )G_FindTarget( dest, Target() ); - if ( dest ) - { - if ( dest->isSubclassOf( UseAnim ) ) - { - // make our linked UseAnim's reset as well - ( ( UseAnim * )dest )->active = qfalse; - ( ( UseAnim * )dest )->last_active_time = level.time + delay; - } + if (ent->isSubclassOf(Door)) { + if (!((Door *)ent)->isCompletelyClosed()) { + CancelEventsOfType(EV_UseAnim_Reset); + PostEvent(EV_UseAnim_Reset, 0.25f); + // + // wait for a little bit + // + return; + } } - else - { - break; + } while (1); + } + + active = qfalse; + last_active_time = level.time + delay; + + // if this is a TouchAnim see if it is linked to another TouchAnim + if (isSubclassOf(TouchAnim)) { + Entity *dest; + + dest = NULL; + do { + dest = (Entity *)G_FindTarget(dest, Target()); + if (dest) { + if (dest->isSubclassOf(UseAnim)) { + // make our linked UseAnim's reset as well + ((UseAnim *)dest)->active = qfalse; + ((UseAnim *)dest)->last_active_time = level.time + delay; + } + } else { + break; } - } - while( 1 ); - } - } + } while (1); + } +} -void UseAnim::SetThread - ( - Event *ev - ) +void UseAnim::SetThread(Event *ev) +{ + thread.SetThread(ev->GetValue(1)); +} - { - thread.SetThread( ev->GetValue( 1 ) ); - } +void UseAnim::SetDelay(Event *ev) +{ + delay = ev->GetFloat(1); +} -void UseAnim::SetDelay - ( - Event *ev - ) +void UseAnim::SetTriggerTarget(Event *ev) +{ + triggertarget = ev->GetString(1); +} - { - delay = ev->GetFloat( 1 ); - } +void UseAnim::SetCount(Event *ev) +{ + count = ev->GetInteger(1); +} -void UseAnim::SetTriggerTarget - ( - Event *ev - ) +void UseAnim::SetAnim(Event *ev) +{ + anim = ev->GetString(1); +} - { - triggertarget = ev->GetString( 1 ); - } +void UseAnim::SetState(Event *ev) +{ + state = ev->GetString(1); +} -void UseAnim::SetCount - ( - Event *ev - ) +void UseAnim::SetKey(Event *ev) +{ + key = ev->GetString(1); +} - { - count = ev->GetInteger( 1 ); - } +void UseAnim::SetCamera(Event *ev) +{ + camera = ev->GetString(1); +} -void UseAnim::SetAnim - ( - Event *ev - ) - { - anim = ev->GetString( 1 ); - } +void UseAnim::SetNumLoops(Event *ev) +{ + num_loops = ev->GetInteger(1); +} -void UseAnim::SetState - ( - Event *ev - ) - { - state = ev->GetString( 1 ); - } - -void UseAnim::SetKey - ( - Event *ev - ) - { - key = ev->GetString( 1 ); - } - -void UseAnim::SetCamera - ( - Event *ev - ) - { - camera = ev->GetString( 1 ); - } - -void UseAnim::SetNumLoops - ( - Event *ev - ) - { - num_loops = ev->GetInteger( 1 ); - } - - -CLASS_DECLARATION( UseAnim, TouchAnim, "func_touchanim" ) - { - { NULL, NULL } - }; +CLASS_DECLARATION(UseAnim, TouchAnim, "func_touchanim") { + {NULL, NULL} +}; TouchAnim::TouchAnim() - { - if ( LoadingSavegame ) - { - return; - } +{ + if (LoadingSavegame) { + return; + } - spawnflags |= 2; + spawnflags |= 2; - if ( spawnflags & 8 ) - { - setSize( Vector( "-32 -32 0" ), Vector( "32 32 96" ) ); - } - else - { - setSize( Vector( "-16 -16 0" ), Vector( "16 16 96" ) ); - } + if (spawnflags & 8) { + setSize(Vector("-32 -32 0"), Vector("32 32 96")); + } else { + setSize(Vector("-16 -16 0"), Vector("16 16 96")); + } - setSolidType( SOLID_TRIGGER ); - edict->r.svFlags |= SVF_NOCLIENT; - } + setSolidType(SOLID_TRIGGER); + edict->r.svFlags |= SVF_NOCLIENT; +} /*****************************************************************************/ /* func_useanimdest (0 0.25 0.5) (0 0 0) (0 0 0) @@ -1661,271 +1418,241 @@ and placed into the specified animation ******************************************************************************/ -CLASS_DECLARATION( Entity, UseAnimDestination, "func_useanimdest" ) - { - { &EV_UseAnim_SetAnim, &UseAnimDestination::SetAnim }, - { &EV_UseAnim_SetState, &UseAnimDestination::SetState }, - { &EV_UseAnim_SetNumLoops, &UseAnimDestination::SetNumLoops }, - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, UseAnimDestination, "func_useanimdest") { + {&EV_UseAnim_SetAnim, &UseAnimDestination::SetAnim }, + {&EV_UseAnim_SetState, &UseAnimDestination::SetState }, + {&EV_UseAnim_SetNumLoops, &UseAnimDestination::SetNumLoops}, + {NULL, NULL } +}; UseAnimDestination::UseAnimDestination() - { - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - // - // default animation to use - // - anim = "stand_use"; - num_loops = 1; - setSolidType( SOLID_NOT ); - hideModel(); - } +{ + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + // + // default animation to use + // + anim = "stand_use"; + num_loops = 1; + setSolidType(SOLID_NOT); + hideModel(); +} -void UseAnimDestination::SetAnim - ( - Event *ev - ) - { - anim = ev->GetString( 1 ); - } +void UseAnimDestination::SetAnim(Event *ev) +{ + anim = ev->GetString(1); +} -void UseAnimDestination::SetState - ( - Event *ev - ) - { - state = ev->GetString( 1 ); - } +void UseAnimDestination::SetState(Event *ev) +{ + state = ev->GetString(1); +} -str UseAnimDestination::GetAnim - ( - void - ) - { - return anim; - } +str UseAnimDestination::GetAnim(void) +{ + return anim; +} -str UseAnimDestination::GetState - ( - void - ) - { - return state; - } +str UseAnimDestination::GetState(void) +{ + return state; +} -void UseAnimDestination::SetNumLoops - ( - Event *ev - ) - { - num_loops = ev->GetInteger( 1 ); - } +void UseAnimDestination::SetNumLoops(Event *ev) +{ + num_loops = ev->GetInteger(1); +} -int UseAnimDestination::GetNumLoops - ( - void - ) - { - return num_loops; - } +int UseAnimDestination::GetNumLoops(void) +{ + return num_loops; +} Event EV_UseObject_MoveThread - ( - "move_thread", - EV_DEFAULT, - "s", - "label", - "Sets which move thread to use when this UseObject has finshed looping.", - EV_NORMAL - ); - +( + "move_thread", + EV_DEFAULT, + "s", + "label", + "Sets which move thread to use when this UseObject has finshed looping.", + EV_NORMAL +); Event EV_UseObject_StopThread - ( - "stop_thread", - EV_DEFAULT, - "s", - "label", - "Sets which stop thread to use when this UseObject is finished.", - EV_NORMAL - ); +( + "stop_thread", + EV_DEFAULT, + "s", + "label", + "Sets which stop thread to use when this UseObject is finished.", + EV_NORMAL +); Event EV_UseObject_ResetThread - ( - "reset_thread", - EV_DEFAULT, - "s", - "label", - "Sets which thread to call when resetting.", - EV_NORMAL - ); +( + "reset_thread", + EV_DEFAULT, + "s", + "label", + "Sets which thread to call when resetting.", + EV_NORMAL +); Event EV_UseObject_Count - ( - "count", - EV_DEFAULT, - "i", - "newCount", - "Sets how many times the UseObject can be triggered.", - EV_NORMAL - ); +( + "count", + EV_DEFAULT, + "i", + "newCount", + "Sets how many times the UseObject can be triggered.", + EV_NORMAL +); Event EV_UseObject_Cone - ( - "cone", - EV_DEFAULT, - "f", - "newCone", - "Sets the cone in angles of where the Useobject can be used.", - EV_NORMAL - ); +( + "cone", + EV_DEFAULT, + "f", + "newCone", + "Sets the cone in angles of where the Useobject can be used.", + EV_NORMAL +); Event EV_UseObject_Offset - ( - "offset", - EV_DEFAULT, - "v", - "newOffset", - "Sets the offset to use for this UseObject.", - EV_NORMAL - ); +( + "offset", + EV_DEFAULT, + "v", + "newOffset", + "Sets the offset to use for this UseObject.", + EV_NORMAL +); Event EV_UseObject_YawOffset - ( - "yaw_offset", - EV_DEFAULT, - "f", - "newYawOffset", - "Sets the yaw offset to use for this UseObject.", - EV_NORMAL - ); +( + "yaw_offset", + EV_DEFAULT, + "f", + "newYawOffset", + "Sets the yaw offset to use for this UseObject.", + EV_NORMAL +); Event EV_UseObject_State - ( - "state", - EV_DEFAULT, - "s", - "newState", - "Sets the state to use for this UseObject.", - EV_NORMAL - ); - +( + "state", + EV_DEFAULT, + "s", + "newState", + "Sets the state to use for this UseObject.", + EV_NORMAL +); Event EV_UseObject_StateBackwards - ( - "state_backwards", - EV_DEFAULT, - "s", - "newState", - "Sets the backward state to use for this UseObject.", - EV_NORMAL - ); +( + "state_backwards", + EV_DEFAULT, + "s", + "newState", + "Sets the backward state to use for this UseObject.", + EV_NORMAL +); Event EV_UseObject_TriggerTarget - ( - "triggertarget", - EV_DEFAULT, - "s", - "targetname", - "Sets what should be triggered, when this UseObject is triggered.", - EV_NORMAL - ); - +( + "triggertarget", + EV_DEFAULT, + "s", + "targetname", + "Sets what should be triggered, when this UseObject is triggered.", + EV_NORMAL +); Event EV_UseObject_ResetTime - ( - "reset_time", - EV_DEFAULT, - "f", - "newResetTime", - "Sets the time it takes for the UseObject to reset itself.", - EV_NORMAL - ); - +( + "reset_time", + EV_DEFAULT, + "f", + "newResetTime", + "Sets the time it takes for the UseObject to reset itself.", + EV_NORMAL +); Event EV_UseObject_DamageType - ( - "damage_type", - EV_DEFAULT, - "s", - "newDamageType", - "Sets what kind of damage is needed to activate the trigger.", - EV_NORMAL - ); - +( + "damage_type", + EV_DEFAULT, + "s", + "newDamageType", + "Sets what kind of damage is needed to activate the trigger.", + EV_NORMAL +); Event EV_UseObject_Reset - ( - "_useobject_reset", - EV_DEFAULT, - NULL, - NULL, - "Resets the useobject to the start state after a certain amount of time.", - EV_NORMAL - ); - +( + "_useobject_reset", + EV_DEFAULT, + NULL, + NULL, + "Resets the useobject to the start state after a certain amount of time.", + EV_NORMAL +); Event EV_UseObject_Resetting - ( - "_useobject_resetting", - EV_DEFAULT, - NULL, - NULL, - "Intermediate function for useobject reset.", - EV_NORMAL - ); +( + "_useobject_resetting", + EV_DEFAULT, + NULL, + NULL, + "Intermediate function for useobject reset.", + EV_NORMAL +); Event EV_UseObject_DamageTriggered - ( - "_useobject_damagetriggered", - EV_DEFAULT, - "e", - "activator", - "Intermediate function for when the useobject was triggered by damage.", - EV_NORMAL - ); - +( + "_useobject_damagetriggered", + EV_DEFAULT, + "e", + "activator", + "Intermediate function for when the useobject was triggered by damage.", + EV_NORMAL +); Event EV_UseObject_Activate - ( - "activate", - EV_DEFAULT, - NULL, - NULL, - "Allow the useobject to be used.", - EV_NORMAL - ); - +( + "activate", + EV_DEFAULT, + NULL, + NULL, + "Allow the useobject to be used.", + EV_NORMAL +); Event EV_UseObject_Deactivate - ( - "deactivate", - EV_DEFAULT, - NULL, - NULL, - "Do not allow the useobject to be used.", - EV_NORMAL - ); - +( + "deactivate", + EV_DEFAULT, + NULL, + NULL, + "Do not allow the useobject to be used.", + EV_NORMAL +); Event EV_UseObject_UseMaterial - ( - "usematerial", - EV_DEFAULT, - "s", - "nameOfUseMaterial", - "the name of the material that glows when active.", - EV_NORMAL - ); +( + "usematerial", + EV_DEFAULT, + "s", + "nameOfUseMaterial", + "the name of the material that glows when active.", + EV_NORMAL +); Event EV_UseObject_SetActiveState - ( - "_setactivestate", - EV_DEFAULT, - NULL, - NULL, - "event that sets up the proper skin for the useobject.", - EV_NORMAL - ); +( + "_setactivestate", + EV_DEFAULT, + NULL, + NULL, + "event that sets up the proper skin for the useobject.", + EV_NORMAL +); - -#define MULTI_STATE ( 1 << 0 ) +#define MULTI_STATE (1 << 0) /*****************************************************************************/ /*QUAKED func_useobject (0 0.5 0) ? MULTI-STATE @@ -1970,333 +1697,247 @@ off state after a preset amount of time. When multi-state is set this must be d ******************************************************************************/ -CLASS_DECLARATION( Animate, UseObject, "func_useobject" ) - { - { &EV_Use, NULL }, - { &EV_UseObject_MoveThread, &UseObject::SetMoveThread }, - { &EV_UseObject_StopThread, &UseObject::SetStopThread }, - { &EV_UseObject_ResetThread, &UseObject::SetResetThread }, - { &EV_UseObject_TriggerTarget, &UseObject::SetTriggerTarget }, - { &EV_UseObject_Offset, &UseObject::SetOffset }, - { &EV_UseObject_YawOffset, &UseObject::SetYawOffset }, - { &EV_UseObject_Count, &UseObject::SetCount }, - { &EV_UseObject_Cone, &UseObject::SetCone }, - { &EV_UseObject_State, &UseObject::SetState }, - { &EV_UseObject_StateBackwards, &UseObject::SetBackwardsState }, - { &EV_UseObject_ResetTime, &UseObject::SetResetTime }, - { &EV_UseObject_Reset, &UseObject::Reset }, - { &EV_UseObject_DamageType, &UseObject::DamageType }, - { &EV_UseObject_Resetting, &UseObject::Resetting }, - { &EV_UseObject_DamageTriggered, &UseObject::DamageTriggered }, - { &EV_Damage, &UseObject::DamageFunc }, - { &EV_UseObject_Activate, &UseObject::ActivateEvent }, - { &EV_UseObject_Deactivate, &UseObject::DeactivateEvent }, - { &EV_UseObject_UseMaterial, &UseObject::UseMaterialEvent }, - { &EV_UseObject_SetActiveState, &UseObject::SetActiveState }, - { NULL, NULL } - }; +CLASS_DECLARATION(Animate, UseObject, "func_useobject") { + {&EV_Use, NULL }, + {&EV_UseObject_MoveThread, &UseObject::SetMoveThread }, + {&EV_UseObject_StopThread, &UseObject::SetStopThread }, + {&EV_UseObject_ResetThread, &UseObject::SetResetThread }, + {&EV_UseObject_TriggerTarget, &UseObject::SetTriggerTarget }, + {&EV_UseObject_Offset, &UseObject::SetOffset }, + {&EV_UseObject_YawOffset, &UseObject::SetYawOffset }, + {&EV_UseObject_Count, &UseObject::SetCount }, + {&EV_UseObject_Cone, &UseObject::SetCone }, + {&EV_UseObject_State, &UseObject::SetState }, + {&EV_UseObject_StateBackwards, &UseObject::SetBackwardsState}, + {&EV_UseObject_ResetTime, &UseObject::SetResetTime }, + {&EV_UseObject_Reset, &UseObject::Reset }, + {&EV_UseObject_DamageType, &UseObject::DamageType }, + {&EV_UseObject_Resetting, &UseObject::Resetting }, + {&EV_UseObject_DamageTriggered, &UseObject::DamageTriggered }, + {&EV_Damage, &UseObject::DamageFunc }, + {&EV_UseObject_Activate, &UseObject::ActivateEvent }, + {&EV_UseObject_Deactivate, &UseObject::DeactivateEvent }, + {&EV_UseObject_UseMaterial, &UseObject::UseMaterialEvent }, + {&EV_UseObject_SetActiveState, &UseObject::SetActiveState }, + {NULL, NULL } +}; UseObject::UseObject() - { - Event * e; - - AddWaitTill(STRING_RESET); - AddWaitTill(STRING_MOVE); - AddWaitTill(STRING_STOP); - - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - - setMoveType( MOVETYPE_NONE ); - setSolidType( SOLID_BBOX ); - setContents( CONTENTS_BODY ); - - // make sure the bounds get rotated with the object - flags |= FL_ROTATEDBOUNDS; - // by default this can activated infinitely - count = -1; - // clear out the triggertarget - triggertarget = ""; - // clear out the move thread - move_thread.Set( "" ); - // clear out the stop thread - stop_thread.Set( "" ); - // clear out the reset thread - reset_thread.Set( "" ); - // clear out the damage type, by default useobjects do not respond to damage - damage_type = MOD_NONE; - // turn on damage taking ability - takedamage = DAMAGE_YES; - // give it some health - health = 100; - // set the default yaw offset - yaw_offset = 0; - // set the cone - cone = cos( DEG2RAD( 90 ) ); - // set the state - state = ""; - // set the backwards state - state_backwards = ""; - // clear out the reset_time - reset_time = 0; - // clear out the object state - objectState = 0; - // the useobject is active by default - active = qtrue; - - // start off in the start animation - e = new Event( EV_SetAnim ); - e->AddString( "start" ); - PostEvent( e, 0 ); - PostEvent( EV_Show, 0 ); - // setup our skins once we are spawned - PostEvent( EV_UseObject_SetActiveState, 0 ); - - } - -void UseObject::SetActiveState - ( - Event *ev - ) - { - if ( !useMaterial.length() ) - { - return; - } - - if ( active && count ) - { - SurfaceCommand( useMaterial.c_str(), "+skin1" ); - } - else - { - SurfaceCommand( useMaterial.c_str(), "-skin1" ); - } - if ( objectState ) - { - SurfaceCommand( useMaterial.c_str(), "+skin2" ); - } - else - { - SurfaceCommand( useMaterial.c_str(), "-skin2" ); - } - } - -void UseObject::SetMoveThread - ( - Event *ev - ) - - { - move_thread.SetThread( ev->GetValue( 1 ) ); - } - -void UseObject::SetStopThread - ( - Event *ev - ) - - { - stop_thread.SetThread( ev->GetValue( 1 ) ); - } - -void UseObject::SetResetThread - ( - Event *ev - ) - - { - reset_thread.SetThread( ev->GetValue( 1 ) ); - } - -void UseObject::ActivateEvent - ( - Event *ev - ) - - { - active = qtrue; - PostEvent( EV_UseObject_SetActiveState, 0 ); - } - -void UseObject::DeactivateEvent - ( - Event *ev - ) - - { - active = qfalse; - PostEvent( EV_UseObject_SetActiveState, 0 ); - } - -void UseObject::SetTriggerTarget - ( - Event *ev - ) - - { - triggertarget = ev->GetString( 1 ); - } - -void UseObject::SetOffset - ( - Event *ev - ) - - { - offset = ev->GetVector( 1 ); - } - -void UseObject::SetYawOffset - ( - Event *ev - ) - - { - yaw_offset = ev->GetFloat( 1 ); - } - -void UseObject::SetCount - ( - Event *ev - ) - - { - count = ev->GetInteger( 1 ); - } - -void UseObject::SetCone - ( - Event *ev - ) - - { - cone = cos( DEG2RAD( ev->GetFloat( 1 ) ) ); - } - -void UseObject::SetState - ( - Event *ev - ) - - { - state = ev->GetString( 1 ); - } - -void UseObject::SetBackwardsState - ( - Event *ev - ) - - { - state_backwards = ev->GetString( 1 ); - } - -void UseObject::UseMaterialEvent - ( - Event *ev - ) - - { - useMaterial = ev->GetString( 1 ); - } - -void UseObject::SetResetTime - ( - Event *ev - ) - - { - reset_time = ev->GetFloat( 1 ); - } - -void UseObject::Reset( Event *ev ) { - NewAnim( "move_backward", EV_UseObject_Resetting ); + Event *e; + + AddWaitTill(STRING_RESET); + AddWaitTill(STRING_MOVE); + AddWaitTill(STRING_STOP); + + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + + setMoveType(MOVETYPE_NONE); + setSolidType(SOLID_BBOX); + setContents(CONTENTS_BODY); + + // make sure the bounds get rotated with the object + flags |= FL_ROTATEDBOUNDS; + // by default this can activated infinitely + count = -1; + // clear out the triggertarget + triggertarget = ""; + // clear out the move thread + move_thread.Set(""); + // clear out the stop thread + stop_thread.Set(""); + // clear out the reset thread + reset_thread.Set(""); + // clear out the damage type, by default useobjects do not respond to damage + damage_type = MOD_NONE; + // turn on damage taking ability + takedamage = DAMAGE_YES; + // give it some health + health = 100; + // set the default yaw offset + yaw_offset = 0; + // set the cone + cone = cos(DEG2RAD(90)); + // set the state + state = ""; + // set the backwards state + state_backwards = ""; + // clear out the reset_time + reset_time = 0; + // clear out the object state + objectState = 0; + // the useobject is active by default + active = qtrue; + + // start off in the start animation + e = new Event(EV_SetAnim); + e->AddString("start"); + PostEvent(e, 0); + PostEvent(EV_Show, 0); + // setup our skins once we are spawned + PostEvent(EV_UseObject_SetActiveState, 0); } -void UseObject::Resetting - ( - Event *ev - ) +void UseObject::SetActiveState(Event *ev) +{ + if (!useMaterial.length()) { + return; + } - { - SetActiveState( NULL ); - NewAnim( "start" ); + if (active && count) { + SurfaceCommand(useMaterial.c_str(), "+skin1"); + } else { + SurfaceCommand(useMaterial.c_str(), "-skin1"); + } + if (objectState) { + SurfaceCommand(useMaterial.c_str(), "+skin2"); + } else { + SurfaceCommand(useMaterial.c_str(), "-skin2"); + } +} - // reset the count - count = 1; +void UseObject::SetMoveThread(Event *ev) +{ + move_thread.SetThread(ev->GetValue(1)); +} - // - // fire off our trigger target if appropriate - // - if ( triggertarget.length() ) - { - Event *event; - Entity *ent; - - ent = NULL; - do - { - ent = ( Entity * )G_FindTarget( ent, triggertarget.c_str() ); - if ( !ent ) - { - break; - } - event = new Event( EV_Activate ); - event->AddEntity( this ); - ent->PostEvent( event, 0 ); - } - while ( 1 ); - } +void UseObject::SetStopThread(Event *ev) +{ + stop_thread.SetThread(ev->GetValue(1)); +} - // - // fire off a thread if necessary - // - if( reset_thread.IsSet() ) - { - reset_thread.Execute( this ); - } - } +void UseObject::SetResetThread(Event *ev) +{ + reset_thread.SetThread(ev->GetValue(1)); +} -bool UseObject::canBeUsed - ( - Vector org, - Vector dir - ) +void UseObject::ActivateEvent(Event *ev) +{ + active = qtrue; + PostEvent(EV_UseObject_SetActiveState, 0); +} - { - float dot; - Vector forward; - Vector diff; - Vector ang; +void UseObject::DeactivateEvent(Event *ev) +{ + active = qfalse; + PostEvent(EV_UseObject_SetActiveState, 0); +} - // see if it is active - if ( !active ) - { - return false; - } +void UseObject::SetTriggerTarget(Event *ev) +{ + triggertarget = ev->GetString(1); +} - // if this is no longer usable, return false - if ( !count ) - { - return false; - } +void UseObject::SetOffset(Event *ev) +{ + offset = ev->GetVector(1); +} - // convert our yawoffset to a vector - ang = vec_zero; - ang[ YAW ] = angles[ YAW ] + yaw_offset; - ang.AngleVectors( &forward ); - dot = forward * dir; - if ( dot < cone ) - { - return false; - } +void UseObject::SetYawOffset(Event *ev) +{ + yaw_offset = ev->GetFloat(1); +} -/* +void UseObject::SetCount(Event *ev) +{ + count = ev->GetInteger(1); +} + +void UseObject::SetCone(Event *ev) +{ + cone = cos(DEG2RAD(ev->GetFloat(1))); +} + +void UseObject::SetState(Event *ev) +{ + state = ev->GetString(1); +} + +void UseObject::SetBackwardsState(Event *ev) +{ + state_backwards = ev->GetString(1); +} + +void UseObject::UseMaterialEvent(Event *ev) +{ + useMaterial = ev->GetString(1); +} + +void UseObject::SetResetTime(Event *ev) +{ + reset_time = ev->GetFloat(1); +} + +void UseObject::Reset(Event *ev) +{ + NewAnim("move_backward", EV_UseObject_Resetting); +} + +void UseObject::Resetting(Event *ev) +{ + SetActiveState(NULL); + NewAnim("start"); + + // reset the count + count = 1; + + // + // fire off our trigger target if appropriate + // + if (triggertarget.length()) { + Event *event; + Entity *ent; + + ent = NULL; + do { + ent = (Entity *)G_FindTarget(ent, triggertarget.c_str()); + if (!ent) { + break; + } + event = new Event(EV_Activate); + event->AddEntity(this); + ent->PostEvent(event, 0); + } while (1); + } + + // + // fire off a thread if necessary + // + if (reset_thread.IsSet()) { + reset_thread.Execute(this); + } +} + +bool UseObject::canBeUsed(Vector org, Vector dir) +{ + float dot; + Vector forward; + Vector diff; + Vector ang; + + // see if it is active + if (!active) { + return false; + } + + // if this is no longer usable, return false + if (!count) { + return false; + } + + // convert our yawoffset to a vector + ang = vec_zero; + ang[YAW] = angles[YAW] + yaw_offset; + ang.AngleVectors(&forward); + dot = forward * dir; + if (dot < cone) { + return false; + } + + /* // convert our offset to a vector in worldspace forward = getLocalVector( offset ); forward.normalize(); @@ -2310,201 +1951,151 @@ bool UseObject::canBeUsed } */ - return true; - } + return true; +} -void UseObject::DamageFunc - ( - Event *ev - ) +void UseObject::DamageFunc(Event *ev) +{ + Event *e; + Entity *attacker; + int mod; - { - Event *e; - Entity *attacker; - int mod; + // if this is no longer usable, return false + if (!count) { + return; + } - // if this is no longer usable, return false - if ( !count ) - { - return; - } + // what kind of damage hit us + mod = ev->GetInteger(9); - // what kind of damage hit us - mod = ev->GetInteger( 9 ); - - // if we don't respond to any kind of damage, and our damage types do not match, return - if ( !MOD_matches( mod, damage_type ) ) - { - return; - } + // if we don't respond to any kind of damage, and our damage types do not match, return + if (!MOD_matches(mod, damage_type)) { + return; + } - // get the attacker - attacker = ev->GetEntity( 1 ); + // get the attacker + attacker = ev->GetEntity(1); - // - // decrement the use - // - if ( count > 0 ) - { - count--; - } - // setup our damage triggered event - e = new Event( EV_UseObject_DamageTriggered ); - // add our attacker - e->AddEntity( attacker ); - // start up the object with our special event - Start( e ); - } + // + // decrement the use + // + if (count > 0) { + count--; + } + // setup our damage triggered event + e = new Event(EV_UseObject_DamageTriggered); + // add our attacker + e->AddEntity(attacker); + // start up the object with our special event + Start(e); +} -void UseObject::DamageTriggered - ( - Event * ev - ) +void UseObject::DamageTriggered(Event *ev) +{ + // grab the attacker from our event + Stop(ev->GetEntity(1)); +} - { - // grab the attacker from our event - Stop( ev->GetEntity( 1 ) ); - } +void UseObject::Setup(Entity *activator, Vector *org, Vector *ang, str *newstate) +{ + if ((spawnflags & MULTI_STATE) && objectState) { + *newstate = state_backwards; + } else { + *newstate = state; + } -void UseObject::Setup - ( - Entity *activator, - Vector *org, - Vector *ang, - str *newstate - ) + // convert our offset to a vector in worldspace + MatrixTransformVector(offset, orientation, *org); + *org += origin; - { - if ( ( spawnflags & MULTI_STATE ) && objectState ) - { - *newstate = state_backwards; - } - else - { - *newstate = state; - } + *ang = angles; + ang->y += yaw_offset; - // convert our offset to a vector in worldspace - MatrixTransformVector( offset, orientation, *org ); - *org += origin; + // + // decrement the use + // + if (count > 0) { + count--; + } +} - *ang = angles; - ang->y += yaw_offset; +void UseObject::Start(Event *ev) +{ + // + // fire off the move_thread + // + if (move_thread.IsSet()) { + move_thread.Execute(this); + } - // - // decrement the use - // - if ( count > 0 ) - { - count--; - } - } + if ((spawnflags & MULTI_STATE) && objectState) { + NewAnim("move_backward", ev); + } else { + NewAnim("move", ev); + } -void UseObject::Start - ( - Event * ev - ) + SetActiveState(NULL); +} - { - // - // fire off the move_thread - // - if ( move_thread.IsSet() ) - { - move_thread.Execute( this ); - } +bool UseObject::Loop(void) +{ + if (!count) { + return qfalse; + } - if ( ( spawnflags & MULTI_STATE ) && objectState ) - { - NewAnim( "move_backward", ev ); - } - else - { - NewAnim( "move", ev ); - } + return qtrue; +} - SetActiveState( NULL ); - } +void UseObject::Stop(Entity *activator) +{ + if ((spawnflags & MULTI_STATE) && objectState) { + NewAnim("start"); + } else { + NewAnim("stop"); + } -bool UseObject::Loop - ( - void - ) + // + // fire off our trigger target if appropriate + // + if (triggertarget.length()) { + Event *event; + Entity *ent; - { - if ( !count ) - return qfalse; + ent = NULL; + do { + ent = (Entity *)G_FindTarget(ent, triggertarget.c_str()); + if (!ent) { + break; + } + event = new Event(EV_Activate); + event->AddEntity(activator); + ent->PostEvent(event, 0); + } while (1); + } - return qtrue; - } + // + // fire off a thread if necessary + // + if ((spawnflags & MULTI_STATE) && objectState) { + if (reset_thread.IsSet()) { + reset_thread.Execute(this); + } + } else { + if (stop_thread.IsSet()) { + stop_thread.Execute(this); + } + } -void UseObject::Stop - ( - Entity *activator - ) + // toggle the state + objectState ^= 1; - { - if( ( spawnflags & MULTI_STATE ) && objectState ) - { - NewAnim( "start" ); - } - else - { - NewAnim( "stop" ); - } + if (reset_time) { + count = 0; + PostEvent(EV_UseObject_Reset, reset_time); + } - // - // fire off our trigger target if appropriate - // - if ( triggertarget.length() ) - { - Event *event; - Entity *ent; - - ent = NULL; - do - { - ent = ( Entity * )G_FindTarget( ent, triggertarget.c_str() ); - if ( !ent ) - { - break; - } - event = new Event( EV_Activate ); - event->AddEntity( activator ); - ent->PostEvent( event, 0 ); - } - while ( 1 ); - } - - // - // fire off a thread if necessary - // - if ( ( spawnflags & MULTI_STATE ) && objectState ) - { - if ( reset_thread.IsSet() ) - { - reset_thread.Execute( this ); - } - } - else - { - if ( stop_thread.IsSet() ) - { - stop_thread.Execute( this ); - } - } - - // toggle the state - objectState ^= 1; - - if ( reset_time ) - { - count = 0; - PostEvent( EV_UseObject_Reset, reset_time ); - } - - SetActiveState( NULL ); - } + SetActiveState(NULL); +} /*****************************************************************************/ /*QUAKED info_waypoint (0 0.5 0) (-8 -8 -8) (8 8 8) @@ -2513,16 +2104,24 @@ Used as a positioning device for objects ******************************************************************************/ -CLASS_DECLARATION( SimpleArchivedEntity, Waypoint, "info_waypoint" ) -{ - { NULL, NULL } +CLASS_DECLARATION(SimpleArchivedEntity, Waypoint, "info_waypoint") { + {NULL, NULL} }; -CLASS_DECLARATION( SimpleArchivedEntity, TempWaypoint, NULL ) +Waypoint::Waypoint() { - { NULL, NULL } + entflags |= ECF_WAYPOINT; +} + +CLASS_DECLARATION(SimpleArchivedEntity, TempWaypoint, NULL) { + {NULL, NULL} }; +TempWaypoint::TempWaypoint() +{ + entflags |= ECF_TEMPWAYPOINT; +} + /*****************************************************************************/ /*QUAKED info_vehiclepoint (0.15 0.5 0.25) (-8 -8 -8) (8 8 8) START_STOPPING START_SKIDDING STOP_SKIDDING @@ -2531,26 +2130,28 @@ Like info_waypoints, but with spawnflags for vehicles. ******************************************************************************/ Event EV_VehiclePoint_SetSpawnFlags - ( - "spawnflags", - EV_DEFAULT, - "i", - "spawn_flags", - "Sets the spawn flags." - ); +( + "spawnflags", + EV_DEFAULT, + "i", + "spawn_flags", + "Sets the spawn flags." +); -CLASS_DECLARATION( Waypoint, VehiclePoint, NULL ) -{ - { &EV_VehiclePoint_SetSpawnFlags, &VehiclePoint::SetSpawnFlags }, - { NULL, NULL } +CLASS_DECLARATION(Waypoint, VehiclePoint, "info_vehiclepoint") { + {&EV_VehiclePoint_SetSpawnFlags, &VehiclePoint::SetSpawnFlags}, + {NULL, NULL } }; -void VehiclePoint::SetSpawnFlags - ( - Event *ev - ) +VehiclePoint::VehiclePoint() { - spawnflags = ev->GetInteger( 1 ); + entflags |= ECF_VEHICLEPOINT; + spawnflags = 0; +} + +void VehiclePoint::SetSpawnFlags(Event *ev) +{ + spawnflags = ev->GetInteger(1); } /*****************************************************************************/ @@ -2560,33 +2161,27 @@ Monkey bars ******************************************************************************/ -CLASS_DECLARATION( Entity, MonkeyBars, "func_monkeybars" ) -{ - { &EV_SetAngle, &MonkeyBars::SetAngleEvent }, - { NULL, NULL } +CLASS_DECLARATION(Entity, MonkeyBars, "func_monkeybars") { + {&EV_SetAngle, &MonkeyBars::SetAngleEvent}, + {NULL, NULL } }; MonkeyBars::MonkeyBars() - { - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - setMoveType( MOVETYPE_NONE ); - setContents( CONTENTS_SHOOTONLY | MASK_SOLID ); - PostEvent( EV_BecomeSolid, 0 ); - dir = 0; - } +{ + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + setMoveType(MOVETYPE_NONE); + setContents(CONTENTS_SHOOTONLY | MASK_SOLID); + PostEvent(EV_BecomeSolid, 0); + dir = 0; +} -void MonkeyBars::SetAngleEvent - ( - Event *ev - ) - - { - dir = ev->GetFloat( 1 ); - } +void MonkeyBars::SetAngleEvent(Event *ev) +{ + dir = ev->GetFloat(1); +} /*****************************************************************************/ /*QUAKED func_horizontalpipe (0.75 0.75 0.75) ? @@ -2595,202 +2190,165 @@ Horizontal pipe that play can crawl upside down on. ******************************************************************************/ -CLASS_DECLARATION( Entity, HorizontalPipe, "func_horizontalpipe" ) - { - { &EV_SetAngle, &HorizontalPipe::SetAngleEvent }, - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, HorizontalPipe, "func_horizontalpipe") { + {&EV_SetAngle, &HorizontalPipe::SetAngleEvent}, + {NULL, NULL } +}; HorizontalPipe::HorizontalPipe() - { - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - setMoveType( MOVETYPE_NONE ); - setContents( CONTENTS_SHOOTONLY | MASK_SOLID ); - PostEvent( EV_BecomeSolid, 0 ); - dir = 0; - } +{ + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + setMoveType(MOVETYPE_NONE); + setContents(CONTENTS_SHOOTONLY | MASK_SOLID); + PostEvent(EV_BecomeSolid, 0); + dir = 0; +} -void HorizontalPipe::SetAngleEvent - ( - Event *ev - ) - - { - dir = ev->GetFloat( 1 ); - } +void HorizontalPipe::SetAngleEvent(Event *ev) +{ + dir = ev->GetFloat(1); +} /*****************************************************************************/ // TossObject /*****************************************************************************/ Event EV_TossObject_SetBounceSound - ( - "bouncesound", - EV_DEFAULT, - "s", - "sound", - "When bouncing, what sound to play on impact", - EV_NORMAL - ); +( + "bouncesound", + EV_DEFAULT, + "s", + "sound", + "When bouncing, what sound to play on impact", + EV_NORMAL -Event EV_TossObject_SetBounceSoundChance - ( - "bouncesoundchance", - EV_DEFAULT, - "f[0,1]", - "chance", - "When bouncing, the chance that the bounce sound will be played", - EV_NORMAL - ); +); +Event EV_TossObject_SetBounceSoundChance( + "bouncesoundchance", + EV_DEFAULT, + "f[0,1]", + "chance", + "When bouncing, the chance that the bounce sound will be played", + EV_NORMAL +); -CLASS_DECLARATION( Animate, TossObject, "TossObject" ) - { - { &EV_Touch, &TossObject::Touch }, - { &EV_Stop, &TossObject::Stop }, - { &EV_TossObject_SetBounceSound, &TossObject::SetBounceSound }, - { &EV_TossObject_SetBounceSoundChance, &TossObject::SetBounceSoundChance }, - { NULL, NULL } - }; +CLASS_DECLARATION(Animate, TossObject, "TossObject") { + {&EV_Touch, &TossObject::Touch }, + {&EV_Stop, &TossObject::Stop }, + {&EV_TossObject_SetBounceSound, &TossObject::SetBounceSound }, + {&EV_TossObject_SetBounceSoundChance, &TossObject::SetBounceSoundChance}, + {NULL, NULL } +}; TossObject::TossObject() - { - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - setMoveType( MOVETYPE_GIB ); - setSolidType( SOLID_NOT ); - bouncesound = ""; - bouncesoundchance = 1.0f; - } +{ + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + setMoveType(MOVETYPE_GIB); + setSolidType(SOLID_NOT); + bouncesound = ""; + bouncesoundchance = 1.0f; +} -TossObject::TossObject( str model ) - { - setMoveType( MOVETYPE_GIB ); - setSolidType( SOLID_NOT ); - bouncesound = ""; - bouncesoundchance = 1.0f; - setModel( model ); - } +TossObject::TossObject(str model) +{ + setMoveType(MOVETYPE_GIB); + setSolidType(SOLID_NOT); + bouncesound = ""; + bouncesoundchance = 1.0f; + setModel(model); +} -void TossObject::SetBounceSound - ( - str bounce - ) +void TossObject::SetBounceSound(str bounce) +{ + bouncesound = bounce; +} - { - bouncesound = bounce; - } +void TossObject::SetBounceSound(Event *ev) +{ + bouncesound = ev->GetString(1); +} -void TossObject::SetBounceSound - ( - Event *ev - ) +void TossObject::SetBounceSoundChance(float chance) +{ + bouncesoundchance = chance; +} - { - bouncesound = ev->GetString( 1 ); - } +void TossObject::SetBounceSoundChance(Event *ev) +{ + bouncesoundchance = ev->GetFloat(1); +} -void TossObject::SetBounceSoundChance - ( - float chance - ) +void TossObject::Stop(Event *ev) +{ + setMoveType(MOVETYPE_NONE); + setSolidType(SOLID_NOT); + // cancel the previous fade out command + CancelEventsOfType(EV_FadeOut); + PostEvent(EV_FadeOut, 7 + G_Random(5)); + setAngles(Vector("0 0 0")); + NewAnim("landed"); +} - { - bouncesoundchance = chance; - } +void TossObject::Touch(Event *ev) +{ + Entity *ent; -void TossObject::SetBounceSoundChance - ( - Event *ev - ) + ent = ev->GetEntity(1); - { - bouncesoundchance = ev->GetFloat( 1 ); - } + // only touch the world + if (!ent || (ent != world)) { + return; + } + // + // every time we bounce try to go back to our nominal angles + // + setAngles(angles * 0.5f); -void TossObject::Stop - ( - Event *ev - ) + if (bouncesound.length()) { + if (G_Random(1) < bouncesoundchance) { + Sound(bouncesound); + } + } +} - { - setMoveType( MOVETYPE_NONE ); - setSolidType( SOLID_NOT ); - // cancel the previous fade out command - CancelEventsOfType( EV_FadeOut ); - PostEvent( EV_FadeOut, 7 + G_Random( 5 ) ); - setAngles( Vector( "0 0 0" ) ); - NewAnim( "landed" ); - } +void TossObject::SetVelocity(float severity) +{ + setSolidType(SOLID_BBOX); + velocity[0] = 100.0 * crandom(); + velocity[1] = 100.0 * crandom(); + velocity[2] = 200.0 + 100.0 * random(); -void TossObject::Touch - ( - Event *ev - ) + avelocity = Vector(G_Random(600), G_Random(600), G_Random(600)); - { - Entity * ent; + velocity *= severity; - ent = ev->GetEntity( 1 ); + if (velocity[0] < -400) { + velocity[0] = -400; + } else if (velocity[0] > 400) { + velocity[0] = 400; + } + if (velocity[1] < -400) { + velocity[1] = -400; + } else if (velocity[1] > 400) { + velocity[1] = 400; + } + if (velocity[2] < 200) { + velocity[2] = 200; // always some upwards + } else if (velocity[2] > 600) { + velocity[2] = 600; + } - // only touch the world - if ( !ent || ( ent != world ) ) - { - return; - } - // - // every time we bounce try to go back to our nominal angles - // - setAngles( angles * 0.5f ); + NewAnim("idle"); - if ( bouncesound.length() ) - { - if ( G_Random( 1 ) < bouncesoundchance ) - { - Sound( bouncesound ); - } - } - } - -void TossObject::SetVelocity - ( - float severity - ) - - { - setSolidType( SOLID_BBOX ); - velocity[0] = 100.0 * crandom(); - velocity[1] = 100.0 * crandom(); - velocity[2] = 200.0 + 100.0 * random(); - - avelocity = Vector( G_Random( 600 ), G_Random( 600 ), G_Random( 600 ) ); - - velocity *= severity; - - if (velocity[0] < -400) - velocity[0] = -400; - else if (velocity[0] > 400) - velocity[0] = 400; - if (velocity[1] < -400) - velocity[1] = -400; - else if (velocity[1] > 400) - velocity[1] = 400; - if (velocity[2] < 200) - velocity[2] = 200; // always some upwards - else if (velocity[2] > 600) - velocity[ 2 ] = 600; - - NewAnim( "idle" ); - - // we give it 8 seconds to fall, if not it will get faded out - PostEvent( EV_FadeOut, 8 ); - } + // we give it 8 seconds to fall, if not it will get faded out + PostEvent(EV_FadeOut, 8); +} /*****************************************************************************/ /*QUAKED func_pushobject (0.75 0.75 0.75) ? @@ -2803,174 +2361,136 @@ Pushable object ******************************************************************************/ Event EV_PushObject_Start - ( - "start", - EV_DEFAULT, - NULL, - NULL, - "Sets up the pushobject.", - EV_NORMAL - ); +( + "start", EV_DEFAULT, + NULL, + NULL, + "Sets up the pushobject.", + EV_NORMAL +); Event EV_PushObject_SetDamage - ( - "dmg", - EV_DEFAULT, - "i", - "damage", - "Set the damage.", - EV_NORMAL - ); +( + "dmg", EV_DEFAULT, + "i", + "damage", + "Set the damage.", + EV_NORMAL +); Event EV_PushObject_SetPushSound - ( - "pushsound", - EV_DEFAULT, - "s", - "sound", - "Set the pushing sound", - EV_NORMAL - ); +( + "pushsound", EV_DEFAULT, + "s", + "sound", + "Set the pushing sound", + EV_NORMAL +); -CLASS_DECLARATION( Entity, PushObject, "func_pushobject" ) - { - { &EV_PushObject_Start, &PushObject::Start }, - { &EV_Blocked, &PushObject::BlockFunc }, - { &EV_PushObject_SetDamage, &PushObject::SetDamage }, - { &EV_PushObject_SetPushSound, &PushObject::SetPushSound }, - { NULL, NULL } - }; +CLASS_DECLARATION(Entity, PushObject, "func_pushobject") { + {&EV_PushObject_Start, &PushObject::Start }, + {&EV_Blocked, &PushObject::BlockFunc }, + {&EV_PushObject_SetDamage, &PushObject::SetDamage }, + {&EV_PushObject_SetPushSound, &PushObject::SetPushSound}, + {NULL, NULL } +}; PushObject::PushObject() - { - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - dmg = 2; - attack_finished = 0; +{ + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + dmg = 2; + attack_finished = 0; - pushsound = "object_slide"; + pushsound = "object_slide"; - PostEvent( EV_PushObject_Start, EV_POSTSPAWN ); - } + PostEvent(EV_PushObject_Start, EV_POSTSPAWN); +} -void PushObject::SetPushSound - ( - Event *ev - ) +void PushObject::SetPushSound(Event *ev) +{ + pushsound = ev->GetString(1); +} - { - pushsound = ev->GetString( 1 ); - } +void PushObject::Start(Event *ev) +{ + // make sure that this touches triggers + flags |= FL_TOUCH_TRIGGERS; + edict->clipmask = MASK_SOLID; + setSolidType(SOLID_BSP); + setMoveType(MOVETYPE_PUSH); -void PushObject::Start - ( - Event *ev - ) + // fix the bounding box so that the object isn't stuck in the ground + setSize(mins + Vector(1, 1, 2), maxs - Vector(1, 1, 1)); +} - { - // make sure that this touches triggers - flags |= FL_TOUCH_TRIGGERS; - edict->clipmask = MASK_SOLID; - setSolidType( SOLID_BSP ); - setMoveType( MOVETYPE_PUSH ); +qboolean PushObject::canPush(Vector dir) +{ + trace_t trace; - // fix the bounding box so that the object isn't stuck in the ground - setSize( mins + Vector( 1, 1, 2 ), maxs - Vector( 1, 1, 1 ) ); - } + Vector end(origin.x + dir.x, origin.y + dir.y, origin.z); -qboolean PushObject::canPush - ( - Vector dir - ) + trace = G_Trace(origin, mins, maxs, end, this, MASK_DEADSOLID, false, "PushObject::Push"); + return (!trace.startsolid && (trace.fraction == 1.0f)); +} - { - trace_t trace; +qboolean PushObject::Push(Entity *pusher, Vector move) +{ + trace_t trace; - Vector end( origin.x + dir.x, origin.y + dir.y, origin.z ); + if (pushsound.length()) { + if (!edict->s.loopSound) { + LoopSound(pushsound); + PostEvent(EV_StopLoopSound, level.frametime * 5); + } + } - trace = G_Trace( origin, mins, maxs, end, this, MASK_DEADSOLID, false, "PushObject::Push" ); - return ( !trace.startsolid && ( trace.fraction == 1.0f ) ); - } + Vector end(origin.x + move.x, origin.y + move.y, origin.z); -qboolean PushObject::Push - ( - Entity *pusher, - Vector move - ) + trace = G_Trace(origin, mins, maxs, end, this, MASK_DEADSOLID, false, "PushObject::Push"); + if (!trace.startsolid && (trace.fraction > 0)) { + owner = pusher; - { - trace_t trace; + G_PushMove(this, trace.endpos - origin, vec_zero); - if ( pushsound.length() ) - { - if ( !edict->s.loopSound ) - { - LoopSound( pushsound ); - PostEvent( EV_StopLoopSound, level.frametime * 5 ); - } - } + if (edict->s.loopSound) { + PostEvent(EV_StopLoopSound, 0.f); + } - Vector end( origin.x + move.x, origin.y + move.y, origin.z ); + return qtrue; + } - trace = G_Trace( origin, mins, maxs, end, this, MASK_DEADSOLID, false, "PushObject::Push" ); - if ( !trace.startsolid && ( trace.fraction > 0 ) ) - { - owner = pusher; + return qfalse; +} - G_PushMove( this, trace.endpos - origin, vec_zero ); +Entity *PushObject::getOwner(void) +{ + return (Entity *)owner; +} - if ( edict->s.loopSound ) - PostEvent( EV_StopLoopSound, 0.f ); +void PushObject::BlockFunc(Event *ev) +{ + Entity *other; - return qtrue; - } + if ((dmg != 0) && (level.time >= attack_finished)) { + attack_finished = level.time + 0.5f; + other = ev->GetEntity(1); + if (other != owner) { + other->Damage(this, this, dmg, origin, vec_zero, vec_zero, 0, 0, MOD_CRUSH); + } + } +} - return qfalse; - } +void PushObject::SetDamage(Event *ev) +{ + dmg = ev->GetInteger(1); +} -Entity *PushObject::getOwner - ( - void - ) - - { - return ( Entity * )owner; - } - -void PushObject::BlockFunc - ( - Event *ev - ) - - { - Entity *other; - - if ( ( dmg != 0 ) && ( level.time >= attack_finished ) ) - { - attack_finished = level.time + 0.5f; - other = ev->GetEntity( 1 ); - if ( other != owner ) - { - other->Damage( this, this, dmg, origin, vec_zero, vec_zero, 0, 0, MOD_CRUSH ); - } - } - } - -void PushObject::SetDamage - ( - Event *ev - ) - - { - dmg = ev->GetInteger( 1 ); - } - -#define SPAWN_AUTO_RESET ( 1 << 0 ) -#define NO_RANDOMNESS ( 1 << 1 ) -#define REMOVE_ON_GROUND ( 1 << 2 ) +#define SPAWN_AUTO_RESET (1 << 0) +#define NO_RANDOMNESS (1 << 1) +#define REMOVE_ON_GROUND (1 << 2) /*****************************************************************************/ /*QUAKED func_fallingrock (0.75 0.75 0.75) ? AUTO_RESET NO_RANDOMNESS REMOVE_ON_GROUND @@ -2990,399 +2510,315 @@ REMOVE_ON_GROUND - remove the rocks when done ******************************************************************************/ Event EV_FallingRock_Bounce - ( - "bounce", - EV_DEFAULT, - NULL, - NULL, - "sent to entity when touched.", - EV_NORMAL - ); - +( + "bounce", + EV_DEFAULT, + NULL, + NULL, + "sent to entity when touched.", + EV_NORMAL +); Event EV_FallingRock_Rotate - ( - "rotate", - EV_DEFAULT, - NULL, - NULL, - "rotates the falling rock.", - EV_NORMAL - ); - +( + "rotate", + EV_DEFAULT, + NULL, + NULL, + "rotates the falling rock.", + EV_NORMAL +); Event EV_FallingRock_SetWait - ( - "wait", - EV_DEFAULT, - "f", - "wait", - "How long to wait before rock starts falling.", - EV_NORMAL - ); - +( + "wait", + EV_DEFAULT, + "f", + "wait", + "How long to wait before rock starts falling.", + EV_NORMAL +); Event EV_FallingRock_Start - ( - "start", - EV_DEFAULT, - NULL, - NULL, - "Starts rock falling.", - EV_NORMAL - ); - +( + "start", + EV_DEFAULT, + NULL, + NULL, + "Starts rock falling.", + EV_NORMAL +); Event EV_FallingRock_SetDmg - ( - "dmg", - EV_DEFAULT, - "i", - "dmg", - "Set the damage from the rock.", - EV_NORMAL - ); - +( + "dmg", + EV_DEFAULT, + "i", + "dmg", + "Set the damage from the rock.", + EV_NORMAL +); Event EV_FallingRock_SetSpeed - ( - "speed", - EV_DEFAULT, - "f", - "speed", - "Set the speed that the rock moves at.", - EV_NORMAL - ); - +( + "speed", + EV_DEFAULT, + "f", + "speed", + "Set the speed that the rock moves at.", + EV_NORMAL +); Event EV_FallingRock_SetBounceSound - ( - "noise", - EV_DEFAULT, - "s", - "sound", - "Set the sound to play when the rock bounces", - EV_NORMAL - ); +( + "noise", + EV_DEFAULT, + "s", + "sound", + "Set the sound to play when the rock bounces", + EV_NORMAL -CLASS_DECLARATION( Entity, FallingRock, "func_fallingrock" ) - { - { &EV_Activate, &FallingRock::Activate }, - { &EV_Touch, &FallingRock::Touch }, - { &EV_FallingRock_Bounce, &FallingRock::Bounce }, - { &EV_FallingRock_Rotate, &FallingRock::Rotate }, - { &EV_FallingRock_Start, &FallingRock::StartFalling }, - { &EV_FallingRock_SetWait, &FallingRock::SetWait }, - { &EV_FallingRock_SetSpeed, &FallingRock::SetSpeed }, - { &EV_FallingRock_SetDmg, &FallingRock::SetDmg }, - { &EV_FallingRock_SetBounceSound, &FallingRock::SetBounceSound }, - { NULL, NULL } - }; +); + +CLASS_DECLARATION(Entity, FallingRock, "func_fallingrock") { + {&EV_Activate, &FallingRock::Activate }, + {&EV_Touch, &FallingRock::Touch }, + {&EV_FallingRock_Bounce, &FallingRock::Bounce }, + {&EV_FallingRock_Rotate, &FallingRock::Rotate }, + {&EV_FallingRock_Start, &FallingRock::StartFalling }, + {&EV_FallingRock_SetWait, &FallingRock::SetWait }, + {&EV_FallingRock_SetSpeed, &FallingRock::SetSpeed }, + {&EV_FallingRock_SetDmg, &FallingRock::SetDmg }, + {&EV_FallingRock_SetBounceSound, &FallingRock::SetBounceSound}, + {NULL, NULL } +}; FallingRock::FallingRock() - { - if ( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } - active = 0; - current = NULL; - setMoveType( MOVETYPE_NONE ); - wait = 0; - dmg = 20; - speed = 200; - activator = NULL; - attack_finished = 0; - - SetBounceSound( "impact_rock" ); - } - -Entity *FallingRock::SetNextBounceDir - ( - void - ) - - { - Entity *ent; - - if ( !current->target.length() ) - { - return NULL; - } - - ent = ( Entity * )G_FindTarget( NULL, current->target.c_str() ); - if ( !ent ) - { - gi.Error( ERR_DROP, "FallingRock :: Entity with targetname of '%s' not found", current->target.c_str() ); - } - - bounce_dir = ent->origin - current->origin; - bounce_dir.normalize(); - - return ent; - } - - -void FallingRock::NextBounce - ( - void - ) - - { - float time; - float distance; - Vector delta, xydelta; - float xy_speed; - float vertical_speed; - - delta = current->origin - origin; - xydelta = delta; - xydelta.z = 0; - xy_speed = speed; - - distance = xydelta.normalize(); - - time = distance / xy_speed; - - if ( !( spawnflags & NO_RANDOMNESS ) ) - { - if ( time > 1.0f ) - { - time = 0.75f + G_Random( 1 ); - } - - if ( time < 0.4f ) - { - time = 0.4f; - } - } - - vertical_speed = ( delta.z / time ) + ( 0.5f * gravity * sv_gravity->value * time ); - if ( vertical_speed < 0 ) - { - vertical_speed = 0; - } - - velocity = xydelta * xy_speed; - velocity.z = vertical_speed; - - Vector ang( 0, vectoyaw( delta ), 0 ); - ang.AngleVectors( NULL, &rotateaxis ); - - // make sure it leaves the ground - groundentity = NULL; - } - -void FallingRock::Rotate - ( - Event *ev - ) - - { - float mat[ 3 ][ 3 ]; - float ang; - - ang = 360.0f * FRAMETIME; - RotatePointAroundVector( mat[ 0 ], rotateaxis, orientation[ 0 ], ang ); - RotatePointAroundVector( mat[ 1 ], rotateaxis, orientation[ 1 ], ang ); - RotatePointAroundVector( mat[ 2 ], rotateaxis, orientation[ 2 ], ang ); - MatrixToEulerAngles( mat, angles ); - setAngles( angles ); - - if ( velocity != vec_zero ) - { - PostEvent( EV_FallingRock_Rotate, FRAMETIME ); - } - } - -void FallingRock::SetWait - ( - Event *ev - ) - - { - wait = ev->GetFloat( 1 ); - } - -void FallingRock::SetSpeed - ( - Event *ev - ) - - { - speed = ev->GetFloat( 1 ); - } - -void FallingRock::SetDmg - ( - Event *ev - ) - - { - dmg = ev->GetInteger( 1 ); - } - -void FallingRock::SetBounceSound - ( - str sound - ) { - bouncesound = sound; - // cache the sound in - CacheResource( bouncesound.c_str() ); + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } + active = 0; + current = NULL; + setMoveType(MOVETYPE_NONE); + wait = 0; + dmg = 20; + speed = 200; + activator = NULL; + attack_finished = 0; + + SetBounceSound("impact_rock"); } -void FallingRock::SetBounceSound - ( - Event *ev - ) +Entity *FallingRock::SetNextBounceDir(void) +{ + Entity *ent; - { - SetBounceSound( ev->GetString( 1 ) ); - } + if (!current->target.length()) { + return NULL; + } -void FallingRock::Activate - ( - Event *ev - ) + ent = (Entity *)G_FindTarget(NULL, current->target.c_str()); + if (!ent) { + gi.Error(ERR_DROP, "FallingRock :: Entity with targetname of '%s' not found", current->target.c_str()); + } - { - if ( active == 1 ) - return; + bounce_dir = ent->origin - current->origin; + bounce_dir.normalize(); - if ( ( active == 2 ) && ( spawnflags & SPAWN_AUTO_RESET ) ) - { - current = NULL; - activator = NULL; - setMoveType( MOVETYPE_NONE ); - NoLerpThisFrame(); - setOrigin( start_origin ); - } + return ent; +} - activator = ev->GetEntity( 1 ); +void FallingRock::NextBounce(void) +{ + float time; + float distance; + Vector delta, xydelta; + float xy_speed; + float vertical_speed; - if ( wait ) - { - PostEvent( EV_FallingRock_Start, wait ); - } - else - { - ProcessEvent( EV_FallingRock_Start ); - } - } + delta = current->origin - origin; + xydelta = delta; + xydelta.z = 0; + xy_speed = speed; -void FallingRock::StartFalling - ( - Event *ev - ) - - { - if ( current ) - { - return; - } + distance = xydelta.normalize(); - if ( !active ) - { - start_origin = origin; - } + time = distance / xy_speed; - active = 1; - setMoveType( MOVETYPE_BOUNCE ); - setSolidType( SOLID_BBOX ); - PostEvent( EV_FallingRock_Rotate, FRAMETIME ); - edict->clipmask = MASK_SOLID|CONTENTS_BODY; + if (!(spawnflags & NO_RANDOMNESS)) { + if (time > 1.0f) { + time = 0.75f + G_Random(1); + } - last_bounce_origin = origin; - current = this; - current = SetNextBounceDir(); - if ( current ) - { - NextBounce(); - } - } + if (time < 0.4f) { + time = 0.4f; + } + } -void FallingRock::Touch - ( - Event *ev - ) + vertical_speed = (delta.z / time) + (0.5f * gravity * sv_gravity->value * time); + if (vertical_speed < 0) { + vertical_speed = 0; + } - { - Entity *other; + velocity = xydelta * xy_speed; + velocity.z = vertical_speed; - other = ev->GetEntity( 1 ); + Vector ang(0, vectoyaw(delta), 0); + ang.AngleVectors(NULL, &rotateaxis); - if ( other != world ) - { - if ( ( velocity != vec_zero ) && ( other->takedamage ) && ( level.time >= attack_finished ) ) - { - other->Damage( this, activator, dmg, origin, vec_zero, vec_zero, 20, 0, MOD_THROWNOBJECT ); - attack_finished = level.time + FRAMETIME; - } - } + // make sure it leaves the ground + groundentity = NULL; +} - if ( !current || ( other != world ) ) - { - return; - } - if ( bouncesound.length() ) - { - Vector delta( origin - last_bounce_origin ); +void FallingRock::Rotate(Event *ev) +{ + float mat[3][3]; + float ang; - if ( delta.length() > 8 ) - { - last_bounce_origin = origin; - Sound( bouncesound.c_str(), CHAN_VOICE ); - } - } + ang = 360.0f * FRAMETIME; + RotatePointAroundVector(mat[0], rotateaxis, orientation[0], ang); + RotatePointAroundVector(mat[1], rotateaxis, orientation[1], ang); + RotatePointAroundVector(mat[2], rotateaxis, orientation[2], ang); + MatrixToEulerAngles(mat, angles); + setAngles(angles); - // we have to wait to set the velocity since the physics code - // will modify it when we return. - PostEvent( EV_FallingRock_Bounce, 0 ); - } + if (velocity != vec_zero) { + PostEvent(EV_FallingRock_Rotate, FRAMETIME); + } +} -void FallingRock::Bounce - ( - Event *ev - ) +void FallingRock::SetWait(Event *ev) +{ + wait = ev->GetFloat(1); +} - { - Vector delta; +void FallingRock::SetSpeed(Event *ev) +{ + speed = ev->GetFloat(1); +} - if ( !current ) - { - return; - } +void FallingRock::SetDmg(Event *ev) +{ + dmg = ev->GetInteger(1); +} - do - { - // check if we've passed the waypoint - delta = origin - current->origin; - if ( ( delta * bounce_dir ) >= ( -2 * edict->r.radius ) ) - { - // call any threads on the current waypoint - if ( current->isSubclassOf( Trigger ) ) - { - current->ProcessEvent( EV_Trigger_StartThread ); +void FallingRock::SetBounceSound(str sound) +{ + bouncesound = sound; + // cache the sound in + CacheResource(bouncesound.c_str()); +} + +void FallingRock::SetBounceSound(Event *ev) +{ + SetBounceSound(ev->GetString(1)); +} + +void FallingRock::Activate(Event *ev) +{ + if (active == 1) { + return; + } + + if ((active == 2) && (spawnflags & SPAWN_AUTO_RESET)) { + current = NULL; + activator = NULL; + setMoveType(MOVETYPE_NONE); + NoLerpThisFrame(); + setOrigin(start_origin); + } + + activator = ev->GetEntity(1); + + if (wait) { + PostEvent(EV_FallingRock_Start, wait); + } else { + ProcessEvent(EV_FallingRock_Start); + } +} + +void FallingRock::StartFalling(Event *ev) +{ + if (current) { + return; + } + + if (!active) { + start_origin = origin; + } + + active = 1; + setMoveType(MOVETYPE_BOUNCE); + setSolidType(SOLID_BBOX); + PostEvent(EV_FallingRock_Rotate, FRAMETIME); + edict->clipmask = MASK_SOLID | CONTENTS_BODY; + + last_bounce_origin = origin; + current = this; + current = SetNextBounceDir(); + if (current) { + NextBounce(); + } +} + +void FallingRock::Touch(Event *ev) +{ + Entity *other; + + other = ev->GetEntity(1); + + if (other != world) { + if ((velocity != vec_zero) && (other->takedamage) && (level.time >= attack_finished)) { + other->Damage(this, activator, dmg, origin, vec_zero, vec_zero, 20, 0, MOD_THROWNOBJECT); + attack_finished = level.time + FRAMETIME; + } + } + + if (!current || (other != world)) { + return; + } + if (bouncesound.length()) { + Vector delta(origin - last_bounce_origin); + + if (delta.length() > 8) { + last_bounce_origin = origin; + Sound(bouncesound.c_str(), CHAN_VOICE); + } + } + + // we have to wait to set the velocity since the physics code + // will modify it when we return. + PostEvent(EV_FallingRock_Bounce, 0); +} + +void FallingRock::Bounce(Event *ev) +{ + Vector delta; + + if (!current) { + return; + } + + do { + // check if we've passed the waypoint + delta = origin - current->origin; + if ((delta * bounce_dir) >= (-2 * edict->r.radius)) { + // call any threads on the current waypoint + if (current->isSubclassOf(Trigger)) { + current->ProcessEvent(EV_Trigger_StartThread); } - current = SetNextBounceDir(); - if ( !current ) - { - velocity = vec_zero; - if ( spawnflags & SPAWN_AUTO_RESET ) - { - active = 2; - } - else if ( spawnflags & REMOVE_ON_GROUND ) - { - PostEvent( EV_Remove, 0 ); - } + current = SetNextBounceDir(); + if (!current) { + velocity = vec_zero; + if (spawnflags & SPAWN_AUTO_RESET) { + active = 2; + } else if (spawnflags & REMOVE_ON_GROUND) { + PostEvent(EV_Remove, 0); + } + break; + } + } else { + NextBounce(); break; - } - } - else - { - NextBounce(); - break; - } - } - while( 1 ); - } + } + } while (1); +} /*****************************************************************************/ /*QUAKED func_ladder (0.75 0.75 0.75) ? @@ -3393,340 +2829,329 @@ Ladder trigger volume Event EV_LadderSetup ( - "_ladder_setup", - EV_CODEONLY, - NULL, - NULL, - "Does the post spawn setup of the ladder" + "_ladder_setup", + EV_CODEONLY, + NULL, + NULL, + "Does the post spawn setup of the ladder" ); -CLASS_DECLARATION( Entity, FuncLadder, "func_ladder" ) -{ - { &EV_Use, NULL }, - { &EV_Touch, NULL }, - { &EV_SetAngle, &FuncLadder::SetLadderFacing }, - { &EV_LadderSetup, &FuncLadder::LadderSetup }, - { NULL, NULL } +CLASS_DECLARATION(Entity, FuncLadder, "func_ladder") { + {&EV_Use, NULL }, + {&EV_Touch, NULL }, + {&EV_SetAngle, &FuncLadder::SetLadderFacing}, + {&EV_LadderSetup, &FuncLadder::LadderSetup }, + {NULL, NULL } }; FuncLadder::FuncLadder() { - if( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - PostEvent( EV_LadderSetup, EV_POSTSPAWN ); + PostEvent(EV_LadderSetup, EV_POSTSPAWN); } -void FuncLadder::LadderSetup( Event *ev ) +void FuncLadder::LadderSetup(Event *ev) { - setMoveType( MOVETYPE_PUSH ); + setMoveType(MOVETYPE_PUSH); - setContents( CONTENTS_LADDER ); - setSolidType( SOLID_BSP ); + setContents(CONTENTS_LADDER); + setSolidType(SOLID_BSP); - // never send to clients - edict->r.svFlags |= SVF_NOCLIENT; + // never send to clients + edict->r.svFlags |= SVF_NOCLIENT; } -qboolean FuncLadder::CanUseLadder( Entity *pUser ) +void FuncLadder::SetLadderFacing(Event *ev) { - int iMask; - Vector vDelta; - Vector vUserFacing; - Vector start, end; - trace_t trace; + m_vFacingAngles = vec_zero; + m_vFacingAngles[1] = AngleMod(ev->GetFloat(1)); - vDelta = origin - pUser->origin; - vDelta[ 2 ] = 0; - - if( vDelta.length() > 52.0f ) { - return qfalse; - } - - AngleVectorsLeft( pUser->angles, vUserFacing, NULL, NULL ); - - iMask = pUser->client ? MASK_PLAYERSOLID : MASK_MONSTERSOLID; - - if( pUser->origin[ 2 ] + pUser->maxs[ 2 ] > absmax[ 2 ] ) - { - if( DotProduct( vUserFacing, m_vFacingDir ) <= 0.15f ) - { - vDelta = pUser->origin - origin; - vDelta[ 2 ] = 0.0f; - - if( DotProduct( m_vFacingDir, vDelta ) >= 0.0f ) - { - start = origin + m_vFacingDir * 26.0f; - start[ 2 ] = absmax[ 2 ] + 16.0f; - - end = start - Vector( 0, 0, 16 ); - - trace = G_Trace( - start, - pUser->mins, - pUser->maxs, - end, - pUser, - MASK_PLAYERSOLID, - qfalse, - "FuncLadder::CanUseLadder" - ); - - start = trace.endpos; - trace = G_Trace( - start, - pUser->mins, - pUser->maxs, - start, - pUser, - MASK_PLAYERSOLID, - qfalse, - "FuncLadder::CanUseLadder" - ); - - if( !trace.startsolid ) - { - // client can use ladder - return qtrue; - } - } - } - - return qfalse; - } - - vDelta = ( pUser->origin - origin ); - vDelta[ 2 ] = 0.0f; - - if( DotProduct( vUserFacing, m_vFacingDir ) < -0.15f || - DotProduct( vDelta, m_vFacingDir ) > 0.0f ) - { - return qfalse; - } - - start = origin - m_vFacingDir * 29.0f; - start[ 2 ] = absmin[ 2 ] + 16.0f; - - end = start; - end[ 2 ] = start[ 2 ] - 16.0f; - - trace = G_Trace( - start, - pUser->mins, - pUser->maxs, - end, - pUser, - MASK_PLAYERSOLID, - qfalse, - "FuncLadder::CanUseLadder" - ); - - if( !trace.allsolid ) - { - // client can use ladder - return qtrue; - } - - gi.DPrintf( "ladder start position is blocked by a solid object\n" ); - return qfalse; + AngleVectorsLeft(m_vFacingAngles, m_vFacingDir, NULL, NULL); } -void FuncLadder::PositionOnLadder( Entity *pUser ) +qboolean FuncLadder::CanUseLadder(Entity *pUser) { - Vector vPos; - Vector vStart; - Vector vEnd; - trace_t trace; + int iMask; + Vector vDelta; + Vector vUserFacing; + Vector start, end; + trace_t trace; - if( pUser->origin[ 2 ] + pUser->maxs[ 2 ] > absmax[ 2 ] ) - { - vEnd = origin + m_vFacingDir * 26.0f; - vEnd[ 2 ] = absmax[ 2 ] + 2.0f; - } - else if( absmin[ 2 ] + 32.0f > pUser->origin[ 2 ] ) - { - vEnd = origin - m_vFacingDir * 29.0f; - vEnd[ 2 ] = absmin[ 2 ] + 2.0f; - } - else - { - vEnd = origin - m_vFacingDir * 16.0f; - vEnd[ 2 ] = pUser->origin[ 2 ] + 8.0f; - } + vDelta = origin - pUser->origin; + vDelta[2] = 0; - vStart = vEnd; + if (vDelta.length() > 52.0f) { + return qfalse; + } - trace = G_Trace( - vStart, - pUser->mins, - pUser->maxs, - vEnd, - pUser, - MASK_PLAYERSOLID, - qtrue, - "FuncLadder::PositionOnLadder" ); + AngleVectorsLeft(pUser->angles, vUserFacing, NULL, NULL); - if( trace.allsolid ) - { - vStart = pUser->origin; - vStart[ 2 ] = pUser->origin[ 2 ] + 4.0f; + iMask = pUser->client ? MASK_PLAYERSOLID : MASK_MONSTERSOLID; - vEnd = origin - m_vFacingDir * 16.0f; - vEnd[ 2 ] = pUser->origin[ 2 ] + 4.0f; + if (pUser->origin[2] + pUser->maxs[2] > absmax[2]) { + if (DotProduct(vUserFacing, m_vFacingDir) <= 0.15f) { + vDelta = pUser->origin - origin; + vDelta[2] = 0.0f; - trace = G_Trace( - vStart, - pUser->mins, - pUser->maxs, - vEnd, - pUser, - MASK_PLAYERSOLID, - qtrue, - "FuncLadder::PositionOnLadder2" ); - } + if (DotProduct(m_vFacingDir, vDelta) >= 0.0f) { + start = origin + m_vFacingDir * 26.0f; + start[2] = absmax[2] + 16.0f; - pUser->setOrigin( trace.endpos ); - pUser->setAngles( m_vFacingAngles ); + end = start - Vector(0, 0, 16); + + trace = G_Trace( + start, pUser->mins, pUser->maxs, end, pUser, MASK_PLAYERSOLID, qfalse, "FuncLadder::CanUseLadder" + ); + + start = trace.endpos; + trace = G_Trace( + start, pUser->mins, pUser->maxs, start, pUser, MASK_PLAYERSOLID, qfalse, "FuncLadder::CanUseLadder" + ); + + if (!trace.startsolid) { + // client can use ladder + return qtrue; + } + } + } + + return qfalse; + } + + vDelta = (pUser->origin - origin); + vDelta[2] = 0.0f; + + if (DotProduct(vUserFacing, m_vFacingDir) < -0.15f || DotProduct(vDelta, m_vFacingDir) > 0.0f) { + return qfalse; + } + + start = origin - m_vFacingDir * 29.0f; + start[2] = absmin[2] + 16.0f; + + end = start; + end[2] = start[2] - 16.0f; + + trace = G_Trace(start, pUser->mins, pUser->maxs, end, pUser, MASK_PLAYERSOLID, qfalse, "FuncLadder::CanUseLadder"); + + if (!trace.allsolid) { + // client can use ladder + return qtrue; + } + + gi.DPrintf("ladder start position is blocked by a solid object\n"); + return qfalse; } -void FuncLadder::SetLadderFacing( Event *ev ) +void FuncLadder::PositionOnLadder(Entity *pUser) { - m_vFacingAngles = vec_zero; - m_vFacingAngles[ 1 ] = AngleMod( ev->GetFloat( 1 ) ); + Vector vPos; + Vector vStart; + Vector vEnd; + trace_t trace; - AngleVectorsLeft( m_vFacingAngles, m_vFacingDir, NULL, NULL ); + if (pUser->origin[2] + pUser->maxs[2] > absmax[2]) { + vEnd = origin + m_vFacingDir * 26.0f; + vEnd[2] = absmax[2] + 2.0f; + } else if (absmin[2] + 32.0f > pUser->origin[2]) { + vEnd = origin - m_vFacingDir * 29.0f; + vEnd[2] = absmin[2] + 2.0f; + } else { + vEnd = origin - m_vFacingDir * 16.0f; + vEnd[2] = pUser->origin[2] + 8.0f; + } + + vStart = vEnd; + + trace = + G_Trace(vStart, pUser->mins, pUser->maxs, vEnd, pUser, MASK_PLAYERSOLID, qtrue, "FuncLadder::PositionOnLadder"); + + if (trace.allsolid) { + vStart = pUser->origin; + vStart[2] = pUser->origin[2] + 4.0f; + + vEnd = origin - m_vFacingDir * 16.0f; + vEnd[2] = pUser->origin[2] + 4.0f; + + trace = G_Trace( + vStart, pUser->mins, pUser->maxs, vEnd, pUser, MASK_PLAYERSOLID, qtrue, "FuncLadder::PositionOnLadder2" + ); + } + + pUser->setOrigin(trace.endpos); + pUser->setAngles(m_vFacingAngles); } -void FuncLadder::AdjustPositionOnLadder( Entity *pUser ) +void FuncLadder::AdjustPositionOnLadder(Entity *pUser) { - float fHeight; - Vector vDelta; - Vector vPos; - Vector vStart; - trace_t trace; + float fHeight; + Vector vDelta; + Vector vPos; + Vector vStart; + trace_t trace; - vDelta = pUser->origin - origin; - vDelta[ 2 ] = 0; + vDelta = pUser->origin - origin; + vDelta[2] = 0; - fHeight = ( ( int )( pUser->origin[ 2 ] + 8.0f ) & ~15 ); + fHeight = ((int)(pUser->origin[2] + 8.0f) & ~15); - if( vDelta.length() > 16.0f && pUser->origin[ 2 ] == fHeight ) - { - return; - } + if (vDelta.length() == 16.0f && pUser->origin[2] == fHeight) { + return; + } - vPos = origin - m_vFacingDir * 16.0f; - vPos[ 2 ] = fHeight; + vPos = origin - m_vFacingDir * 16.0f; + vPos[2] = fHeight; - vStart = vPos + m_vFacingDir * -16.0f; + vStart = vPos + m_vFacingDir * -16.0f; - trace = G_Trace( vStart, - pUser->mins, - pUser->maxs, - vPos, - pUser, - MASK_PLAYERSOLID, - qtrue, - "FuncLadder::AdjustPositionOnLadder" ); + trace = G_Trace( + vStart, pUser->mins, pUser->maxs, vPos, pUser, MASK_PLAYERSOLID, qtrue, "FuncLadder::AdjustPositionOnLadder" + ); - if( trace.allsolid || trace.startsolid ) - { - trace = G_Trace( pUser->origin, - pUser->mins, - pUser->maxs, - vPos, - pUser, - MASK_PLAYERSOLID, - qtrue, - "FuncLadder::AdjustPositionOnLadder" ); - } + if (trace.allsolid || trace.startsolid) { + trace = G_Trace( + pUser->origin, + pUser->mins, + pUser->maxs, + vPos, + pUser, + MASK_PLAYERSOLID, + qtrue, + "FuncLadder::AdjustPositionOnLadder" + ); + } - pUser->setOrigin( trace.endpos ); + pUser->setOrigin(trace.endpos); } -void FuncLadder::EnsureOverLadder( Entity *pUser ) +void FuncLadder::EnsureOverLadder(Entity *pUser) { - float fHeight = absmax[ 2 ]; - Vector vStart; - Vector vPos; - trace_t trace; + float fHeight = absmax[2]; + Vector vStart; + Vector vPos; + trace_t trace; - if( pUser->origin[ 2 ] - fHeight >= 8.0f ) { - return; - } + if (pUser->origin[2] - fHeight >= 8.0f) { + return; + } - vPos = pUser->origin; - vPos[ 2 ] = fHeight + 16.0f; + vPos = pUser->origin; + vPos[2] = fHeight + 16.0f; - vStart = pUser->origin + m_vFacingDir * -16.0f; + vStart = pUser->origin + m_vFacingDir * -16.0f; - trace = G_Trace( vStart, - pUser->mins, - pUser->maxs, - vPos, - pUser->edict, - MASK_PLAYERSOLID, - true, - "FuncLadder::EnsureOverLadder" ); + trace = G_Trace( + vStart, pUser->mins, pUser->maxs, vPos, pUser->edict, MASK_PLAYERSOLID, true, "FuncLadder::EnsureOverLadder" + ); - if( trace.startsolid || trace.allsolid ) - { - trace = G_Trace( origin, - pUser->mins, - pUser->maxs, - vPos, - pUser->edict, - MASK_PLAYERSOLID, - true, - "FuncLadder::EnsureOverLadder" ); - } + if (trace.startsolid || trace.allsolid) { + trace = G_Trace( + origin, pUser->mins, pUser->maxs, vPos, pUser->edict, MASK_PLAYERSOLID, true, "FuncLadder::EnsureOverLadder" + ); + } - pUser->setOrigin( trace.endpos ); + pUser->setOrigin(trace.endpos); } -void FuncLadder::EnsureForwardOffLadder( Entity *pUser ) +void FuncLadder::EnsureForwardOffLadder(Entity *pUser) { - int iMask; - Vector vStart; - Vector vPos; - Vector vDelta; - trace_t trace; + int iMask; + Vector vStart; + Vector vPos; + Vector vDelta; + trace_t trace; - if( pUser->origin[ 2 ] - absmax[ 2 ] >= 8.0f ) { - return; - } + if (pUser->origin[2] - absmax[2] >= 8.0f) { + return; + } - iMask = pUser->client ? MASK_PLAYERSOLID : MASK_MONSTERSOLID; + iMask = pUser->client ? MASK_PLAYERSOLID : MASK_MONSTERSOLID; - vPos = pUser->origin; - vPos[ 2 ] = absmax[ 2 ] + 16.0f; + vPos = pUser->origin; + vPos[2] = absmax[2] + 16.0f; - vStart = vPos + m_vFacingDir * -16.0f; + vStart = vPos + m_vFacingDir * -16.0f; - trace = G_Trace( - vStart, - pUser->mins, - pUser->maxs, - vPos, - pUser, - iMask, - qtrue, - "FuncLadder::EnsureOverLadder" ); + trace = G_Trace(vStart, pUser->mins, pUser->maxs, vPos, pUser, iMask, qtrue, "FuncLadder::EnsureOverLadder"); - if( trace.allsolid || trace.startsolid ) - { - trace = G_Trace( - pUser->origin, - pUser->mins, - pUser->maxs, - vPos, - pUser, - iMask, - qtrue, - "FuncLadder::EnsureOverLadder" ); - } + if (trace.allsolid || trace.startsolid) { + trace = + G_Trace(pUser->origin, pUser->mins, pUser->maxs, vPos, pUser, iMask, qtrue, "FuncLadder::EnsureOverLadder"); + } - pUser->setOrigin( trace.endpos ); + pUser->setOrigin(trace.endpos); +} + +const Vector& FuncLadder::getFacingAngles() const +{ + return m_vFacingAngles; +} + +const Vector& FuncLadder::getFacingDir() const +{ + return m_vFacingDir; +} + +Event EV_InfoLandmark_Name +( + "landmark_name", EV_DEFAULT, + "s", + "name", + "Set the name of this landmark", + EV_NORMAL +); +Event EV_InfoLandmark_SetOrigin +( + "origin", EV_DEFAULT, + "v", + "origin", + "Set the origin of the landmark.", + EV_NORMAL +); + +CLASS_DECLARATION(Listener, InfoLandmark, "info_landmark") { + {&EV_InfoLandmark_Name, &InfoLandmark::SetLandmarkName}, + {&EV_InfoLandmark_SetOrigin, &InfoLandmark::SetOrigin }, + {NULL, NULL } +}; + +InfoLandmark::InfoLandmark() +{ + m_bNameSet = false; + m_bOriginSet = false; +} + +void InfoLandmark::SetLandmarkName(Event *ev) +{ + m_sName = ev->GetString(1); + m_bNameSet = true; + + if (m_bOriginSet) { + level.AddLandmarkName(m_sName, m_vOrigin); + PostEvent(EV_Remove, EV_REMOVE); + } +} + +void InfoLandmark::SetOrigin(Event *ev) +{ + m_vOrigin = ev->GetVector(1); + + if (m_vOrigin == Vector(99999, 99999, 99999)) { + ScriptError( + "Illegal location (%f, %f, %f) for Landmark. Please place in valid XYZ coordinates\n", + m_vOrigin[0], + m_vOrigin[1], + m_vOrigin[2] + ); + } + + level.AddLandmarkOrigin(m_vOrigin); + m_bOriginSet = true; + + if (m_bNameSet) { + level.AddLandmarkName(m_sName, m_vOrigin); + PostEvent(EV_Remove, EV_REMOVE); + } } diff --git a/code/fgame/misc.h b/code/fgame/misc.h index aa3762f7..95f4d2c2 100644 --- a/code/fgame/misc.h +++ b/code/fgame/misc.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -26,578 +26,571 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // should contain utility functions that could be used by any entity. // Right now it contains everything from entities that could be in their // own file to my mother pot roast recipes. -// +// -#ifndef __MISC_H__ -#define __MISC_H__ +#pragma once #include "g_local.h" #include "entity.h" #include "mover.h" #include "animate.h" -class InfoNull : public Entity - { - public: - CLASS_PROTOTYPE( InfoNull ); - - InfoNull(); - }; +class InfoNull : public Listener +{ +public: + CLASS_PROTOTYPE(InfoNull); + + InfoNull(); +}; class FuncRemove : public Entity - { - public: - CLASS_PROTOTYPE( FuncRemove ); - - FuncRemove(); - }; +{ +public: + CLASS_PROTOTYPE(FuncRemove); + + FuncRemove(); +}; class MiscModel : public Entity - { - public: - CLASS_PROTOTYPE( MiscModel ); - - MiscModel(); - }; +{ +public: + CLASS_PROTOTYPE(MiscModel); + + MiscModel(); +}; class InfoNotNull : public Entity - { - public: - CLASS_PROTOTYPE( InfoNotNull ); - }; +{ +public: + CLASS_PROTOTYPE(InfoNotNull); +}; class ExplodingWall : public Trigger - { - protected: - int dmg; - int explosions; - float attack_finished; - Vector land_angles; - float land_radius; - float angle_speed; - int state; - Vector base_velocity; - Vector random_velocity; - Vector orig_mins, orig_maxs; - qboolean on_ground; +{ +protected: + int dmg; + int explosions; + float attack_finished; + Vector land_angles; + float land_radius; + float angle_speed; + int state; + Vector base_velocity; + Vector random_velocity; + Vector orig_mins, orig_maxs; + qboolean on_ground; - public: - CLASS_PROTOTYPE( ExplodingWall ); +public: + CLASS_PROTOTYPE(ExplodingWall); - ExplodingWall(); - void Setup( Event *ev ); - void AngleSpeed( Event *ev ); - void LandRadius( Event *ev ); - void LandAngles( Event *ev ); - void BaseVelocity( Event *ev ); - void RandomVelocity( Event *ev ); - void SetDmg( Event *ev ); - void SetExplosions( Event *ev ); - void SetupSecondStage( void ); - void Explode( Event *ev ); - void DamageEvent( Event *ev ) override; - void GroundDamage( Event *ev ); - void TouchFunc( Event *ev ); - void StopRotating( Event *ev ); - void CheckOnGround( Event *ev ); - void Archive( Archiver &arc ) override; - }; + ExplodingWall(); + void Setup(Event *ev); + void AngleSpeed(Event *ev); + void LandRadius(Event *ev); + void LandAngles(Event *ev); + void BaseVelocity(Event *ev); + void RandomVelocity(Event *ev); + void SetDmg(Event *ev); + void SetExplosions(Event *ev); + void SetupSecondStage(void); + void Explode(Event *ev); + void DamageEvent(Event *ev) override; + void GroundDamage(Event *ev); + void TouchFunc(Event *ev); + void StopRotating(Event *ev); + void CheckOnGround(Event *ev); + void Archive(Archiver& arc) override; +}; -inline void ExplodingWall::Archive - ( - Archiver &arc - ) - { - Trigger::Archive( arc ); - - arc.ArchiveInteger( &dmg ); - arc.ArchiveInteger( &explosions ); - arc.ArchiveFloat( &attack_finished ); - arc.ArchiveVector( &land_angles ); - arc.ArchiveFloat( &land_radius ); - arc.ArchiveFloat( &angle_speed ); - arc.ArchiveInteger( &state ); - arc.ArchiveVector( &base_velocity ); - arc.ArchiveVector( &random_velocity ); - arc.ArchiveVector( &orig_mins ); - arc.ArchiveVector( &orig_maxs ); - arc.ArchiveBoolean( &on_ground ); - } +inline void ExplodingWall::Archive(Archiver& arc) +{ + Trigger::Archive(arc); + arc.ArchiveInteger(&dmg); + arc.ArchiveInteger(&explosions); + arc.ArchiveFloat(&attack_finished); + arc.ArchiveVector(&land_angles); + arc.ArchiveFloat(&land_radius); + arc.ArchiveFloat(&angle_speed); + arc.ArchiveInteger(&state); + arc.ArchiveVector(&base_velocity); + arc.ArchiveVector(&random_velocity); + arc.ArchiveVector(&orig_mins); + arc.ArchiveVector(&orig_maxs); + arc.ArchiveBoolean(&on_ground); +} class Teleporter : public Trigger - { - public: - ScriptThreadLabel teleport_label; - qboolean in_use; +{ +public: + ScriptThreadLabel teleport_label; + qboolean in_use; - CLASS_PROTOTYPE( Teleporter ); - - Teleporter(); - virtual void StartTeleport( Event *ev ); - virtual void Teleport( Event *ev ); - virtual void StopTeleport( Event *ev ); - void SetThread( Event *ev ); - void Archive( Archiver &arc ) override; - }; + CLASS_PROTOTYPE(Teleporter); -inline void Teleporter::Archive - ( - Archiver &arc - ) - { - Trigger::Archive( arc ); + Teleporter(); + virtual void StartTeleport(Event *ev); + virtual void Teleport(Event *ev); + virtual void StopTeleport(Event *ev); + void SetThread(Event *ev); + void Archive(Archiver& arc) override; +}; - arc.ArchiveBoolean( &in_use ); - } +inline void Teleporter::Archive(Archiver& arc) +{ + Trigger::Archive(arc); + + arc.ArchiveBoolean(&in_use); +} class TeleporterDestination : public Entity - { - public: - Vector movedir; +{ +public: + Vector movedir; - CLASS_PROTOTYPE( TeleporterDestination ); + CLASS_PROTOTYPE(TeleporterDestination); - TeleporterDestination(); - void SetMoveDir( Event *ev ); - void Archive( Archiver &arc ) override; - }; + TeleporterDestination(); + void SetMoveDir(Event *ev); + void Archive(Archiver& arc) override; +}; -inline void TeleporterDestination::Archive - ( - Archiver &arc - ) - { - Entity::Archive( arc ); +inline void TeleporterDestination::Archive(Archiver& arc) +{ + Entity::Archive(arc); - arc.ArchiveVector( &movedir ); - } + arc.ArchiveVector(&movedir); +} class UseAnim : public Entity - { - public: - int count; - qboolean active; - ScriptThreadLabel thread; - str triggertarget; - int num_loops; - str state; - str camera; - str anim; - str key; - float delay; - float last_active_time; +{ +public: + int count; + qboolean active; + ScriptThreadLabel thread; + str triggertarget; + int num_loops; + str state; + str camera; + str anim; + str key; + float delay; + float last_active_time; - CLASS_PROTOTYPE( UseAnim ); - - UseAnim(); - virtual void Touched( Event *ev ); - void Reset( Event *ev ); - void SetThread( Event * ev ); - void SetTriggerTarget( Event * ev ); - void SetCount( Event * ev ); - void SetAnim( Event *ev ); - void SetState( Event *ev ); - void SetKey( Event *ev ); - void SetCamera( Event *ev ); - void SetNumLoops( Event *ev ); - void SetDelay( Event *ev ); - bool canBeUsed( Entity *activator ); - bool GetInformation( Entity *activator, Vector * org, Vector * angles, str * animatoin, int * loopcount, str * state, str * camera ); - void TriggerTargets( Entity *activator ); - void Archive( Archiver &arc ) override; - }; + CLASS_PROTOTYPE(UseAnim); -inline void UseAnim::Archive - ( - Archiver &arc - ) - { - Entity::Archive( arc ); + UseAnim(); + virtual void Touched(Event *ev); + void Reset(Event *ev); + void SetThread(Event *ev); + void SetTriggerTarget(Event *ev); + void SetCount(Event *ev); + void SetAnim(Event *ev); + void SetState(Event *ev); + void SetKey(Event *ev); + void SetCamera(Event *ev); + void SetNumLoops(Event *ev); + void SetDelay(Event *ev); + bool canBeUsed(Entity *activator); + bool GetInformation( + Entity *activator, Vector *org, Vector *angles, str *animatoin, int *loopcount, str *state, str *camera + ); + void TriggerTargets(Entity *activator); + void Archive(Archiver& arc) override; +}; - arc.ArchiveInteger( &count ); - arc.ArchiveBoolean( &active ); - arc.ArchiveString( &triggertarget ); - arc.ArchiveInteger( &num_loops ); - arc.ArchiveString( &state ); - arc.ArchiveString( &camera ); - arc.ArchiveString( &anim ); - arc.ArchiveString( &key ); - arc.ArchiveFloat( &delay ); - arc.ArchiveFloat( &last_active_time ); - } +inline void UseAnim::Archive(Archiver& arc) +{ + Entity::Archive(arc); + + arc.ArchiveInteger(&count); + arc.ArchiveBoolean(&active); + arc.ArchiveString(&triggertarget); + arc.ArchiveInteger(&num_loops); + arc.ArchiveString(&state); + arc.ArchiveString(&camera); + arc.ArchiveString(&anim); + arc.ArchiveString(&key); + arc.ArchiveFloat(&delay); + arc.ArchiveFloat(&last_active_time); +} class TouchAnim : public UseAnim - { - public: - - CLASS_PROTOTYPE( TouchAnim ); - - TouchAnim(); - }; +{ +public: + CLASS_PROTOTYPE(TouchAnim); + TouchAnim(); +}; class UseAnimDestination : public Entity - { - public: - int num_loops; - str state; - str anim; +{ +public: + int num_loops; + str state; + str anim; - CLASS_PROTOTYPE( UseAnimDestination ); + CLASS_PROTOTYPE(UseAnimDestination); - UseAnimDestination(); - void SetAnim( Event *ev ); - void SetState( Event *ev ); - void SetNumLoops( Event *ev ); - int GetNumLoops( void ); - str GetAnim( void ); - str GetState( void ); - void Archive( Archiver &arc ) override; - }; + UseAnimDestination(); + void SetAnim(Event *ev); + void SetState(Event *ev); + void SetNumLoops(Event *ev); + int GetNumLoops(void); + str GetAnim(void); + str GetState(void); + void Archive(Archiver& arc) override; +}; -inline void UseAnimDestination::Archive - ( - Archiver &arc - ) - { - Entity::Archive( arc ); +inline void UseAnimDestination::Archive(Archiver& arc) +{ + Entity::Archive(arc); - arc.ArchiveInteger( &num_loops ); - arc.ArchiveString( &state ); - arc.ArchiveString( &anim ); - } + arc.ArchiveInteger(&num_loops); + arc.ArchiveString(&state); + arc.ArchiveString(&anim); +} class UseObject : public Animate - { - public: - ScriptThreadLabel move_thread; - ScriptThreadLabel stop_thread; - ScriptThreadLabel reset_thread; - str triggertarget; - Vector offset; - float yaw_offset; - int count; - float cone; - str state; - str state_backwards; - str useMaterial; - int objectState; - float reset_time; - qboolean active; +{ +public: + ScriptThreadLabel move_thread; + ScriptThreadLabel stop_thread; + ScriptThreadLabel reset_thread; + str triggertarget; + Vector offset; + float yaw_offset; + int count; + float cone; + str state; + str state_backwards; + str useMaterial; + int objectState; + float reset_time; + qboolean active; - CLASS_PROTOTYPE( UseObject ); - - UseObject(); - void SetMoveThread( Event * ev ); - void SetStopThread( Event * ev ); - void SetResetThread( Event * ev ); - void SetTriggerTarget( Event * ev ); - void SetOffset( Event * ev ); - void SetYawOffset( Event * ev ); - void SetCount( Event * ev ); - void SetCone( Event * ev ); - void SetState( Event * ev ); - void SetBackwardsState( Event * ev ); - void SetResetTime( Event * ev ); - void Reset( Event * ev ); - void Resetting( Event * ev ); - void DamageTriggered( Event * ev ); - void DamageFunc( Event * ev ); - bool canBeUsed( Vector org, Vector dir ); - void Setup( Entity *activator, Vector *org, Vector *ang, str *newstate ); - void Start( Event * ev = NULL ); - bool Loop( void ); - void SetActiveState( Event *ev ); - void Stop( Entity *activator ); - void ActivateEvent( Event *ev ); - void DeactivateEvent( Event *ev ); - void UseMaterialEvent( Event *ev ); - void Archive( Archiver &arc ) override; - }; + CLASS_PROTOTYPE(UseObject); -inline void UseObject::Archive - ( - Archiver &arc - ) - { - Animate::Archive( arc ); + UseObject(); + void SetMoveThread(Event *ev); + void SetStopThread(Event *ev); + void SetResetThread(Event *ev); + void SetTriggerTarget(Event *ev); + void SetOffset(Event *ev); + void SetYawOffset(Event *ev); + void SetCount(Event *ev); + void SetCone(Event *ev); + void SetState(Event *ev); + void SetBackwardsState(Event *ev); + void SetResetTime(Event *ev); + void Reset(Event *ev); + void Resetting(Event *ev); + void DamageTriggered(Event *ev); + void DamageFunc(Event *ev); + bool canBeUsed(Vector org, Vector dir); + void Setup(Entity *activator, Vector *org, Vector *ang, str *newstate); + void Start(Event *ev = NULL); + bool Loop(void); + void SetActiveState(Event *ev); + void Stop(Entity *activator); + void ActivateEvent(Event *ev); + void DeactivateEvent(Event *ev); + void UseMaterialEvent(Event *ev); + void Archive(Archiver& arc) override; +}; - arc.ArchiveString( &triggertarget ); - arc.ArchiveVector( &offset ); - arc.ArchiveFloat( &yaw_offset ); - arc.ArchiveInteger( &count ); - arc.ArchiveFloat( &cone ); - arc.ArchiveString( &state ); - arc.ArchiveString( &state_backwards ); - arc.ArchiveString( &useMaterial ); - arc.ArchiveInteger( &objectState ); - arc.ArchiveFloat( &reset_time ); - arc.ArchiveBoolean( &active ); - } +inline void UseObject::Archive(Archiver& arc) +{ + Animate::Archive(arc); + arc.ArchiveString(&triggertarget); + arc.ArchiveVector(&offset); + arc.ArchiveFloat(&yaw_offset); + arc.ArchiveInteger(&count); + arc.ArchiveFloat(&cone); + arc.ArchiveString(&state); + arc.ArchiveString(&state_backwards); + arc.ArchiveString(&useMaterial); + arc.ArchiveInteger(&objectState); + arc.ArchiveFloat(&reset_time); + arc.ArchiveBoolean(&active); +} class Waypoint : public SimpleArchivedEntity { public: - CLASS_PROTOTYPE( Waypoint ); + CLASS_PROTOTYPE(Waypoint); + +public: + Waypoint(); }; class TempWaypoint : public SimpleArchivedEntity { public: - CLASS_PROTOTYPE( TempWaypoint ); + CLASS_PROTOTYPE(TempWaypoint); + +public: + TempWaypoint(); }; class VehiclePoint : public Waypoint { public: - unsigned int spawnflags; + unsigned int spawnflags; - CLASS_PROTOTYPE( VehiclePoint ); + CLASS_PROTOTYPE(VehiclePoint); - void SetSpawnFlags( Event *ev ); - void Archive( Archiver& arc ) override; + VehiclePoint(); + + void SetSpawnFlags(Event *ev); + void Archive(Archiver& arc) override; }; -inline void VehiclePoint::Archive - ( - Archiver &arc - ) +inline void VehiclePoint::Archive(Archiver& arc) { - SimpleArchivedEntity::Archive( arc ); + SimpleArchivedEntity::Archive(arc); - arc.ArchiveUnsigned( &spawnflags ); + arc.ArchiveUnsigned(&spawnflags); } class MonkeyBars : public Entity - { - public: - float dir; - - CLASS_PROTOTYPE( MonkeyBars ); - - MonkeyBars(); - void SetAngleEvent( Event *ev ); - - void Archive( Archiver &arc ) override; - }; - -inline void MonkeyBars::Archive - ( - Archiver &arc - ) - - { - Entity::Archive( arc ); - - arc.ArchiveFloat( &dir ); - } - -class HorizontalPipe : public Entity - { - public: - float dir; - - CLASS_PROTOTYPE( HorizontalPipe ); - - HorizontalPipe(); - void SetAngleEvent( Event *ev ); - - void Archive( Archiver &arc ) override; - }; - -inline void HorizontalPipe::Archive - ( - Archiver &arc - ) - - { - Entity::Archive( arc ); - - arc.ArchiveFloat( &dir ); - } - -class TossObject : public Animate - { - private: - str bouncesound; - float bouncesoundchance; - void Stop( Event *ev ); - void Touch( Event *ev ); - void SetBounceSound( Event *ev ); - void SetBounceSoundChance( Event *ev ); - public: - CLASS_PROTOTYPE( TossObject ); - - TossObject(); - TossObject( str modelname ); - void SetBounceSound( str bounce ); - void SetBounceSoundChance( float chance ); - void SetVelocity( float severity ); - void Archive( Archiver &arc ) override; - }; - -inline void TossObject::Archive - ( - Archiver &arc - ) - - { - Animate::Archive( arc ); - - arc.ArchiveString( &bouncesound ); - arc.ArchiveFloat( &bouncesoundchance ); - } - - -class PushObject : public Entity - { - private: - EntityPtr owner; - float attack_finished; - int dmg; - str pushsound; - - public: - CLASS_PROTOTYPE( PushObject ); - - PushObject(); - void Start( Event *ev ); - void SetDamage( Event *ev ); - void BlockFunc( Event *ev ); - void SetPushSound( Event *ev ); - qboolean Push( Entity *pusher, Vector move ); - qboolean canPush( Vector dir ); - - Entity *getOwner( void ); - - void Archive( Archiver &arc ) override; - }; - -inline void PushObject::Archive - ( - Archiver &arc - ) - { - Entity::Archive( arc ); - - arc.ArchiveSafePointer( &owner ); - arc.ArchiveFloat( &attack_finished ); - arc.ArchiveInteger( &dmg ); - arc.ArchiveString( &pushsound ); - } - -class FallingRock : public Entity - { - private: - int active; - Vector start_origin; - Vector last_bounce_origin; - Entity *current; - Entity *activator; - Vector bounce_dir; - Vector rotateaxis; - float attack_finished; - float wait; - float speed; - int dmg; - str bouncesound; - - void Touch( Event *ev ); - void Bounce( Event *ev ); - void Rotate( Event *ev ); - void Activate( Event *ev ); - void NextBounce( void ); - void StartFalling( Event *ev ); - void SetWait( Event *ev ); - void SetSpeed( Event *ev ); - void SetDmg( Event *ev ); - Entity *SetNextBounceDir( void ); - void SetBounceSound( str sound ); - void SetBounceSound( Event *ev ); - void Archive( Archiver &arc ) override; - - public: - CLASS_PROTOTYPE( FallingRock ); - - FallingRock(); - }; - -inline void FallingRock::Archive - ( - Archiver &arc - ) - - { - Entity::Archive( arc ); - - arc.ArchiveInteger( &active ); - arc.ArchiveVector( &start_origin ); - arc.ArchiveVector( &last_bounce_origin ); - arc.ArchiveObjectPointer( ( Class ** )¤t ); - arc.ArchiveObjectPointer( ( Class ** )&activator ); - arc.ArchiveVector( &bounce_dir ); - arc.ArchiveVector( &rotateaxis ); - arc.ArchiveFloat( &attack_finished ); - arc.ArchiveFloat( &wait ); - arc.ArchiveFloat( &speed ); - arc.ArchiveInteger( &dmg ); - arc.ArchiveString( &bouncesound ); - if ( arc.Loading() ) - { - SetBounceSound( bouncesound ); - } - } - - -class SupplyWater : public Trigger - { - private: - int maxwater; - int amount; - public: - CLASS_PROTOTYPE( SupplyWater ); - - SupplyWater(); - void Activate( Event *ev ); - void MaxWater( Event *ev ); - void ChargeOff( Event *ev ); - void Archive( Archiver &arc ) override; - }; - -inline void SupplyWater::Archive - ( - Archiver &arc - ) - - { - Trigger::Archive( arc ); - - arc.ArchiveInteger( &amount ); - arc.ArchiveInteger( &maxwater ); - } - -class FuncLadder : public Entity { -private: - Vector m_vFacingAngles; - Vector m_vFacingDir; - +{ public: - CLASS_PROTOTYPE( FuncLadder ); + float dir; - FuncLadder(); + CLASS_PROTOTYPE(MonkeyBars); - void LadderSetup( Event *ev ); + MonkeyBars(); + void SetAngleEvent(Event *ev); - qboolean CanUseLadder( Entity *pUser ); - void PositionOnLadder( Entity *pUser ); - - void SetLadderFacing( Event *ev ); - void AdjustPositionOnLadder( Entity *pUser ); - - void EnsureOverLadder( Entity *pUser ); - void EnsureForwardOffLadder( Entity *pUser ); + void Archive(Archiver& arc) override; }; -#endif /* misc.h */ +inline void MonkeyBars::Archive(Archiver& arc) + +{ + Entity::Archive(arc); + + arc.ArchiveFloat(&dir); +} + +class HorizontalPipe : public Entity +{ +public: + float dir; + + CLASS_PROTOTYPE(HorizontalPipe); + + HorizontalPipe(); + void SetAngleEvent(Event *ev); + + void Archive(Archiver& arc) override; +}; + +inline void HorizontalPipe::Archive(Archiver& arc) + +{ + Entity::Archive(arc); + + arc.ArchiveFloat(&dir); +} + +class TossObject : public Animate +{ +private: + str bouncesound; + float bouncesoundchance; + void Stop(Event *ev); + void Touch(Event *ev); + void SetBounceSound(Event *ev); + void SetBounceSoundChance(Event *ev); + +public: + CLASS_PROTOTYPE(TossObject); + + TossObject(); + TossObject(str modelname); + void SetBounceSound(str bounce); + void SetBounceSoundChance(float chance); + void SetVelocity(float severity); + void Archive(Archiver& arc) override; +}; + +inline void TossObject::Archive(Archiver& arc) + +{ + Animate::Archive(arc); + + arc.ArchiveString(&bouncesound); + arc.ArchiveFloat(&bouncesoundchance); +} + +class PushObject : public Entity +{ +private: + EntityPtr owner; + float attack_finished; + int dmg; + str pushsound; + +public: + CLASS_PROTOTYPE(PushObject); + + PushObject(); + void Start(Event *ev); + void SetDamage(Event *ev); + void BlockFunc(Event *ev); + void SetPushSound(Event *ev); + qboolean Push(Entity *pusher, Vector move); + qboolean canPush(Vector dir); + + Entity *getOwner(void); + + void Archive(Archiver& arc) override; +}; + +inline void PushObject::Archive(Archiver& arc) +{ + Entity::Archive(arc); + + arc.ArchiveSafePointer(&owner); + arc.ArchiveFloat(&attack_finished); + arc.ArchiveInteger(&dmg); + arc.ArchiveString(&pushsound); +} + +class FallingRock : public Entity +{ +private: + int active; + Vector start_origin; + Vector last_bounce_origin; + Entity *current; + Entity *activator; + Vector bounce_dir; + Vector rotateaxis; + float attack_finished; + float wait; + float speed; + int dmg; + str bouncesound; + + void Touch(Event *ev); + void Bounce(Event *ev); + void Rotate(Event *ev); + void Activate(Event *ev); + void NextBounce(void); + void StartFalling(Event *ev); + void SetWait(Event *ev); + void SetSpeed(Event *ev); + void SetDmg(Event *ev); + Entity *SetNextBounceDir(void); + void SetBounceSound(str sound); + void SetBounceSound(Event *ev); + void Archive(Archiver& arc) override; + +public: + CLASS_PROTOTYPE(FallingRock); + + FallingRock(); +}; + +inline void FallingRock::Archive(Archiver& arc) + +{ + Entity::Archive(arc); + + arc.ArchiveInteger(&active); + arc.ArchiveVector(&start_origin); + arc.ArchiveVector(&last_bounce_origin); + arc.ArchiveObjectPointer((Class **)¤t); + arc.ArchiveObjectPointer((Class **)&activator); + arc.ArchiveVector(&bounce_dir); + arc.ArchiveVector(&rotateaxis); + arc.ArchiveFloat(&attack_finished); + arc.ArchiveFloat(&wait); + arc.ArchiveFloat(&speed); + arc.ArchiveInteger(&dmg); + arc.ArchiveString(&bouncesound); + if (arc.Loading()) { + SetBounceSound(bouncesound); + } +} + +class SupplyWater : public Trigger +{ +private: + int maxwater; + int amount; + +public: + CLASS_PROTOTYPE(SupplyWater); + + SupplyWater(); + void Activate(Event *ev); + void MaxWater(Event *ev); + void ChargeOff(Event *ev); + void Archive(Archiver& arc) override; +}; + +inline void SupplyWater::Archive(Archiver& arc) + +{ + Trigger::Archive(arc); + + arc.ArchiveInteger(&amount); + arc.ArchiveInteger(&maxwater); +} + +class FuncLadder : public Entity +{ +private: + Vector m_vFacingAngles; + Vector m_vFacingDir; + +public: + CLASS_PROTOTYPE(FuncLadder); + + FuncLadder(); + + void LadderSetup(Event *ev); + + qboolean CanUseLadder(Entity *pUser); + void PositionOnLadder(Entity *pUser); + + void SetLadderFacing(Event *ev); + void AdjustPositionOnLadder(Entity *pUser); + + void EnsureOverLadder(Entity *pUser); + void EnsureForwardOffLadder(Entity *pUser); + + const Vector& getFacingAngles() const; + const Vector& getFacingDir() const; + + void Archive(Archiver& arc) override; +}; + +inline void FuncLadder::Archive(Archiver& arc) +{ + Entity::Archive(arc); + + arc.ArchiveVector(&m_vFacingAngles); + arc.ArchiveVector(&m_vFacingDir); +} + +class InfoLandmark : public Listener +{ +private: + str m_sName; + Vector m_vOrigin; + bool m_bNameSet; + bool m_bOriginSet; + +public: + CLASS_PROTOTYPE(InfoLandmark); + + InfoLandmark(); + void SetLandmarkName(Event *ev); + void SetOrigin(Event *ev); +}; diff --git a/code/fgame/movegrid.cpp b/code/fgame/movegrid.cpp index f982a5f4..feb60248 100644 --- a/code/fgame/movegrid.cpp +++ b/code/fgame/movegrid.cpp @@ -24,200 +24,227 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #include "movegrid.h" +#include "debuglines.h" -// FIXME: undone class - -cMoveGrid::cMoveGrid( int x, int y, int z ) +cMoveGrid::cMoveGrid(int x, int y, int z) { - m_iXRes = x; - m_iYRes = y; - m_iZRes = z; + m_iXRes = x; + m_iYRes = y; + m_iZRes = z; - GridPoints = ( gridpoint_t * )gi.Malloc( sizeof( gridpoint_t ) * x * y * z ); + GridPoints = (gridpoint_t *)gi.Malloc(sizeof(gridpoint_t) * x * y * z); } cMoveGrid::~cMoveGrid() { - gi.Free( GridPoints ); + gi.Free(GridPoints); } -void cMoveGrid::SetOrientation - ( - float( *v )[ 3 ] - ) +void cMoveGrid::SetMoveInfo(vmove_t *vm) { - for( int i = 0; i < 3; i++ ) - { - VectorCopy( v[ i ], orientation[ i ] ); - } + v = *vm; } -void cMoveGrid::SetMoveInfo - ( - vmove_t *vm - ) +void cMoveGrid::GetMoveInfo(vmove_t *vm) { - memcpy( &v, vm, sizeof( vmove_t ) ); + *vm = v; } -void cMoveGrid::CalculateBoxPoints - ( - void - ) +gridpoint_t *cMoveGrid::GetGridPoint(int x, int y, int z) { - int x, y, z; - int rx, ry, rz; - int xdelta, ydelta, zdelta; - - Vector vBoxSize = Vector(v.maxs) - Vector(v.mins); - - rx = (int)(vBoxSize[0] / (float)m_iXRes); - ry = (int)(vBoxSize[1] / (float)m_iYRes); - rz = (int)(vBoxSize[2] / (float)m_iZRes); - - xdelta = ydelta = zdelta = 0; - - for (x = 0; x < m_iXRes; x++) - { - for (y = 0; y < m_iYRes; y++) - { - for (z = 0; z < m_iZRes; z++) - { - gridpoint_t* gridPoint = GetGridPoint(x, y, z); - - gridPoint->origin = Vector( - (float)(xdelta - rx), - (float)(ydelta - ry), - (float)rz * 0.5f - ); - } - } - } - - for (x = 0; x < m_iXRes; x++) - { - for (y = 0; y < m_iYRes; y++) - { - for (z = 0; z < m_iZRes; z++) - { - gridpoint_t* gridPoint = GetGridPoint(x, y, z); - - Vector vTmp; - MatrixTransformVector(gridPoint->origin, orientation, vTmp); - - gridPoint->origin = vTmp; - memcpy(&gridPoint->vm, &v, sizeof(gridPoint->vm)); - gridPoint->vm.vs = &gridPoint->vs; - - if (rx >= ry) - { - VectorSet( - gridPoint->vm.mins, - (float)-ry * 0.5f, - (float)-ry * 0.5f, - (float)-rz * 0.5f - ); - - VectorSet( - gridPoint->vm.maxs, - (float)ry * 0.5f, - (float)ry * 0.5f, - (float)rz * 0.5f - ); - } - else - { - VectorSet( - gridPoint->vm.mins, - (float)-rx * 0.5f, - (float)-rx * 0.5f, - (float)-rz * 0.5f - ); - - VectorSet( - gridPoint->vm.maxs, - (float)rx * 0.5f, - (float)rx * 0.5f, - (float)rz * 0.5f - ); - } - } - } - } + return &GridPoints[x * m_iZRes + y * m_iXRes + z]; } -gridpoint_t *cMoveGrid::GetGridPoint - ( - int x, - int y, - int z - ) +void cMoveGrid::SetOrientation(const vec3_t *v) { - return &GridPoints[ x * m_iZRes + y * m_iXRes + z ]; + for (int i = 0; i < 3; i++) { + VectorCopy(v[i], orientation[i]); + } } -void cMoveGrid::Move - ( - void - ) +void cMoveGrid::CalculateBoxPoints(void) { - int x; - int y; - int z; - Vector vBoxSize; - Vector old_origin; + int x, y, z; + int rx, ry, rz; + int xdelta, ydelta, zdelta; + Vector vBoxSize; - CalculateBoxPoints(); + vBoxSize = Vector(v.maxs) - Vector(v.mins); - for( x = 0; x < m_iXRes; x++ ) - { - for( y = 0; y < m_iYRes; y++ ) - { - for( z = 0; z < m_iZRes; z++ ) - { - } - } - } + rx = (int)(vBoxSize.x / (float)m_iXRes); + ry = (int)(vBoxSize.y / (float)m_iYRes); + rz = (int)(vBoxSize.z / (float)m_iZRes); - // this is not called anyways - // FIXME: stub - STUB(); + xdelta = ydelta = zdelta = 0; + + for (x = 0; x < m_iXRes; x++) { + for (y = 0; y < m_iYRes; y++) { + for (z = 0; z < m_iZRes; z++) { + gridpoint_t *gridPoint = GetGridPoint(x, y, z); + + gridPoint->origin = Vector(xdelta - rx, ydelta - ry, zdelta + rz / 2.f); + zdelta += rz; + } + zdelta = 0; + ydelta += ry; + } + ydelta = 0; + xdelta += rx; + } + + for (x = 0; x < m_iXRes; x++) { + for (y = 0; y < m_iYRes; y++) { + for (z = 0; z < m_iZRes; z++) { + Vector vTmp; + gridpoint_t *gridPoint = GetGridPoint(x, y, z); + + MatrixTransformVector(gridPoint->origin, orientation, vTmp); + + gridPoint->origin = vTmp; + gridPoint->vm = v; + gridPoint->vm.vs = &gridPoint->vs; + + if (rx >= ry) { + Vector vec; + + vec = Vector(-ry / 2.f, -ry / 2.f, -rz / 2.f); + vec.copyTo(gridPoint->vm.mins); + + vec = Vector(ry / 2.f, ry / 2.f, rz / 2.f); + vec.copyTo(gridPoint->vm.maxs); + } else { + Vector vec; + + vec = Vector(-rx / 2.f, -rx / 2.f, -rz / 2.f); + vec.copyTo(gridPoint->vm.mins); + + vec = Vector(rx / 2.f, rx / 2.f, rz / 2.f); + vec.copyTo(gridPoint->vm.maxs); + } + } + } + } } -qboolean cMoveGrid::CheckStuck - ( - void - ) +void cMoveGrid::Move(void) { - int x; - int y; - int z; - trace_t trace; + gridpoint_t *gridPoint; + int x, y, z; + Vector vBoxSize; + Vector old_origin; + float best; + float bx, by, bz; + Vector bestdelta; - for( x = 0; x < m_iXRes; x++ ) - { - for( y = 0; y < m_iYRes; y++ ) - { - for( z = 0; z < m_iZRes; z++ ) - { - gi.trace( &trace, v.vs->origin, v.mins, v.maxs, v.vs->origin, v.vs->entityNum, v.tracemask, false, false ); + old_origin = v.vs->origin; + vBoxSize = Vector(v.maxs) - Vector(v.mins); - if( trace.allsolid || trace.startsolid || trace.fraction == 0.0f ) - { - return true; - } - } - } - } + CalculateBoxPoints(); - return false; + for (x = 0; x < m_iXRes; x++) { + for (y = 0; y < m_iYRes; y++) { + for (z = 0; z < m_iZRes; z++) { + gridPoint = GetGridPoint(x, y, z); + + gridPoint->origindelta = gridPoint->origin; + gridPoint->origin += old_origin; + gridPoint->origin.copyTo(gridPoint->vm.vs->origin); + + G_DebugBBox(gridPoint->origin, gridPoint->vm.mins, gridPoint->vm.maxs, 1, 1, 0, 1); + + VmoveSingle(&gridPoint->vm); + + gridPoint->neworigin = gridPoint->vm.vs->origin; + gridPoint->changed = gridPoint->neworigin - gridPoint->origin; + gridPoint->newvel = gridPoint->vm.vs->velocity; + // set the ground entity + gridPoint->groundentity = NULL; + if (gridPoint->vm.vs->groundEntityNum != ENTITYNUM_NONE) { + gridPoint->groundentity = &g_entities[gridPoint->vm.vs->groundEntityNum]; + } + } + } + } + + best = 99999; + bx = by = bz = 0; + + for (x = 0; x < m_iXRes; x++) { + for (y = 0; y < m_iYRes; y++) { + for (z = 0; z < m_iZRes; z++) { + gridPoint = GetGridPoint(x, y, z); + float speed; + + speed = (gridPoint->changed - gridPoint->origindelta).length(); + if (speed < best) { + best = gridPoint->changed.length(); + bx = x; + by = y; + bz = z; + } + } + } + } + + gridPoint = GetGridPoint(bx, by, bz); + bestdelta = gridPoint->neworigin - gridPoint->origindelta; + bestdelta.copyTo(v.vs->origin); + gridPoint->newvel.copyTo(v.vs->velocity); } -void cMoveGrid::GetMoveInfo - ( - vmove_t *vm - ) +qboolean cMoveGrid::CheckStuck(void) { - memcpy( vm, &v, sizeof( vmove_t ) ); + int x; + int y; + int z; + trace_t trace; + + for (x = 0; x < m_iXRes; x++) { + for (y = 0; y < m_iYRes; y++) { + for (z = 0; z < m_iZRes; z++) { + gi.trace( + &trace, v.vs->origin, v.mins, v.maxs, v.vs->origin, v.vs->entityNum, v.tracemask, false, false + ); + + if (trace.allsolid || trace.startsolid || trace.fraction == 0.0f) { + return true; + } + } + } + } + + return false; } +void cMoveGrid::Archive(Archiver& arc) +{ + int i; + + arc.ArchiveInteger(&m_iXRes); + arc.ArchiveInteger(&m_iYRes); + arc.ArchiveInteger(&m_iZRes); + + arc.ArchiveFloat(&v.frametime); + arc.ArchiveFloat(&v.desired_speed); + arc.ArchiveInteger(&v.tracemask); + arc.ArchiveInteger(&v.numtouch); + + for (i = 0; i < ARRAY_LEN(v.touchents); i++) { + arc.ArchiveInteger(&v.touchents[i]); + } + arc.ArchiveVec3(v.mins); + arc.ArchiveVec3(v.maxs); + + arc.ArchiveVec3(orientation[0]); + arc.ArchiveVec3(orientation[1]); + arc.ArchiveVec3(orientation[2]); + + if (arc.Loading()) { + if (GridPoints) { + if (m_iXRes != 3 && m_iYRes != 3 && m_iZRes != 1) { + gi.Free(GridPoints); + GridPoints = (gridpoint_t *)gi.Malloc(sizeof(gridpoint_t) * m_iXRes * m_iYRes * m_iZRes); + } + } + } +} diff --git a/code/fgame/movegrid.h b/code/fgame/movegrid.h index 2b8583e9..6847d1b2 100644 --- a/code/fgame/movegrid.h +++ b/code/fgame/movegrid.h @@ -23,100 +23,71 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // movegrid.h: Move grid // -#ifndef __MOVEGRID_H__ -#define __MOVEGRID_H__ +#pragma once #include "g_local.h" #include "../qcommon/class.h" #include "../fgame/archive.h" typedef struct vehicleState_s { - float origin[ 3 ]; - float velocity[ 3 ]; - int groundEntityNum; - qboolean walking; - qboolean groundPlane; - trace_t groundTrace; - int entityNum; - float desired_dir[ 2 ]; - qboolean hit_obstacle; - float hit_origin[ 3 ]; - float obstacle_normal[ 3 ]; - qboolean useGravity; + vec3_t origin; + vec3_t velocity; + int groundEntityNum; + qboolean walking; + qboolean groundPlane; + trace_t groundTrace; + int entityNum; + vec2_t desired_dir; + qboolean hit_obstacle; + vec3_t hit_origin; + vec3_t obstacle_normal; + qboolean useGravity; } vehicleState_t; typedef struct vmove_s { - vehicleState_t *vs; - float frametime; - float desired_speed; - int tracemask; - int numtouch; - int touchents[ 32 ]; - float mins[ 3 ]; - float maxs[ 3 ]; + vehicleState_t *vs; + float frametime; + float desired_speed; + int tracemask; + int numtouch; + int touchents[32]; + vec3_t mins; + vec3_t maxs; } vmove_t; typedef struct gridpoint_s { - Vector origin; - Vector neworigin; - Vector origindelta; - Vector changed; - Vector newvel; - gentity_t *groundentity; - vmove_t vm; - vehicleState_t vs; + Vector origin; + Vector neworigin; + Vector origindelta; + Vector changed; + Vector newvel; + gentity_t *groundentity; + vmove_t vm; + vehicleState_t vs; } gridpoint_t; class cMoveGrid : public Class { public: - gridpoint_t *GridPoints; + gridpoint_t *GridPoints; private: - vmove_t v; - float orientation[ 3 ][ 3 ]; - int m_iXRes; - int m_iYRes; - int m_iZRes; + vmove_t v; + vec3_t orientation[3]; + int m_iXRes; + int m_iYRes; + int m_iZRes; public: - cMoveGrid( int x, int y, int z ); - virtual ~cMoveGrid(); + cMoveGrid(int x, int y, int z); + virtual ~cMoveGrid(); - void SetOrientation( float( *v)[ 3 ] ); - void SetMoveInfo( vmove_t *vm ); - void CalculateBoxPoints( void ); - gridpoint_t *GetGridPoint( int x, int y, int z ); - void Move( void ); - qboolean CheckStuck( void ); - void GetMoveInfo( vmove_t *vm ); - void Archive( Archiver& arc ); + void SetOrientation(const vec3_t *v); + void SetMoveInfo(vmove_t *vm); + void CalculateBoxPoints(void); + gridpoint_t *GetGridPoint(int x, int y, int z); + void Move(void); + qboolean CheckStuck(void); + void GetMoveInfo(vmove_t *vm); + void Archive(Archiver &arc); }; - -inline void cMoveGrid::Archive - ( - Archiver& arc - ) -{ - arc.ArchiveInteger( &m_iXRes ); - arc.ArchiveInteger( &m_iYRes ); - arc.ArchiveInteger( &m_iZRes ); - arc.ArchiveRaw( &v, sizeof( vmove_t ) ); - arc.ArchiveVec3( orientation[ 0 ] ); - arc.ArchiveVec3( orientation[ 1 ] ); - arc.ArchiveVec3( orientation[ 2 ] ); - - if( arc.Loading() ) - { - if( GridPoints ) - { - if( m_iXRes != 3 && m_iYRes != 3 && m_iZRes != 1 ) - { - gi.Free( GridPoints ); - GridPoints = ( gridpoint_t * )gi.Malloc( sizeof( gridpoint_t ) * m_iXRes * m_iYRes * m_iZRes ); - } - } - } -} - -#endif diff --git a/code/fgame/mover.cpp b/code/fgame/mover.cpp index 47e31d40..3b99e3df 100644 --- a/code/fgame/mover.cpp +++ b/code/fgame/mover.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -35,90 +35,81 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MOVE_ANGLES 1 #define MOVE_ORIGIN 2 -CLASS_DECLARATION( Trigger, Mover, "mover" ) - { - { &EV_MoveDone, &Mover::MoveDone }, - { NULL, NULL } - }; - +CLASS_DECLARATION(Trigger, Mover, "mover") { + {&EV_MoveDone, &Mover::MoveDone}, + {NULL, NULL } +}; Mover::Mover() - { - endevent = NULL; - } - -Mover::~Mover() - { - } - -void Mover::MoveDone - ( - Event *ev - ) { - Event * event; - Vector move; - Vector amove; + endevent = NULL; +} - // zero out the movement - if( moveflags & MOVE_ANGLES ) - { - avelocity = vec_zero; - amove = angledest - localangles; - } - else - { - amove = vec_zero; - } +Mover::~Mover() {} - if( moveflags & MOVE_ORIGIN ) - { - velocity = vec_zero; - move = finaldest - localorigin; - } - else - { - move = vec_zero; - } +void Mover::MoveDone(Event *ev) +{ + Event *event; + Vector move; + Vector amove; - if( !G_PushMove( this, move, amove ) ) - { - // Delay finish till we can move into the final position - PostEvent( EV_MoveDone, FRAMETIME ); - return; - } + // zero out the movement + avelocity = vec_zero; + if (moveflags & MOVE_ANGLES) { + amove = angledest - localangles; + } else { + amove = vec_zero; + } - // - // After moving, set origin to exact final destination - // - if( moveflags & MOVE_ORIGIN ) - { - setLocalOrigin( finaldest ); - } + velocity = vec_zero; + if (moveflags & MOVE_ORIGIN) { + move = finaldest - localorigin; + } else { + move = vec_zero; + } - if( moveflags & MOVE_ANGLES ) - { - localangles = angledest; + accel = vec_zero; + aaccel = vec_zero; - if( ( localangles.x >= 360 ) || ( localangles.x < 0 ) ) - { - localangles.x -= ( ( int )localangles.x / 360 ) * 360; - } - if( ( localangles.y >= 360 ) || ( localangles.y < 0 ) ) - { - localangles.y -= ( ( int )localangles.y / 360 ) * 360; - } - if( ( localangles.z >= 360 ) || ( localangles.z < 0 ) ) - { - localangles.z -= ( ( int )localangles.z / 360 ) * 360; - } - } + if (!G_PushMove(this, move, amove)) { + // Added in OPM + // Check to make sure the event isn't pending + // blocked events called by G_PushMove() might alter + // the mover + if (!EventPending(EV_MoveDone)) { + // Delay finish till we can move into the final position + PostEvent(EV_MoveDone, FRAMETIME); + } + return; + } - event = endevent; - endevent = NULL; + // + // After moving, set origin to exact final destination + // + if (moveflags & MOVE_ORIGIN) { + setLocalOrigin(finaldest); + } - if( event ) - ProcessEvent( event ); + if (moveflags & MOVE_ANGLES) { + localangles = angledest; + + if ((localangles.x >= 360) || (localangles.x < 0)) { + localangles.x -= ((int)localangles.x / 360) * 360; + } + if ((localangles.y >= 360) || (localangles.y < 0)) { + localangles.y -= ((int)localangles.y / 360) * 360; + } + if ((localangles.z >= 360) || (localangles.z < 0)) { + localangles.z -= ((int)localangles.z / 360) * 360; + } + } + + event = endevent; + endevent = NULL; + + if (event) { + ProcessEvent(event); + } } /* @@ -129,99 +120,87 @@ calculate self.velocity and self.nextthink to reach dest from self.origin traveling at speed =============== */ -void Mover::MoveTo( Vector tdest, Vector angdest, float tspeed, Event& event ) +void Mover::MoveTo(Vector tdest, Vector angdest, float tspeed, Event& event) { - Vector vdestdelta; - Vector angdestdelta; - float len; - float traveltime; + Vector vdestdelta; + Vector angdestdelta; + float len; + float traveltime; - assert( tspeed >= 0.0f ); + assert(tspeed >= 0.0f); - if( !tspeed ) - { - error( "MoveTo", "No speed is defined!" ); - } + if (!tspeed) { + error("MoveTo", "No speed is defined!"); + } - if( tspeed < 0.0f ) - { - error( "MoveTo", "Speed is negative!" ); - } + if (tspeed < 0.0f) { + error("MoveTo", "Speed is negative!"); + } - // Cancel previous moves - CancelEventsOfType( EV_MoveDone ); + // Cancel previous moves + CancelEventsOfType(EV_MoveDone); - moveflags = 0; + moveflags = 0; - if( endevent ) - { - delete endevent; - } + if (endevent) { + delete endevent; + } - endevent = new Event( event ); + endevent = new Event(event); - finaldest = tdest; - angledest = angdest; + finaldest = tdest; + angledest = angdest; - if( finaldest != localorigin ) - { - moveflags |= MOVE_ORIGIN; - } - if( angledest != localangles ) - { - moveflags |= MOVE_ANGLES; - } + if (finaldest != localorigin) { + moveflags |= MOVE_ORIGIN; + } + if (angledest != localangles) { + moveflags |= MOVE_ANGLES; + } - if( !moveflags ) - { - // stop the object from moving - velocity = vec_zero; - avelocity = vec_zero; + if (!moveflags) { + // stop the object from moving + velocity = vec_zero; + avelocity = vec_zero; - // post the event so we don't wait forever - PostEvent( EV_MoveDone, FRAMETIME ); - return; - } + // post the event so we don't wait forever + PostEvent(EV_MoveDone, FRAMETIME); + return; + } - // set destdelta to the vector needed to move - vdestdelta = tdest - localorigin; - angdestdelta[ 0 ] = angledist( angdest[ 0 ] - localangles[ 0 ] ); - angdestdelta[ 1 ] = angledist( angdest[ 1 ] - localangles[ 1 ] ); - angdestdelta[ 2 ] = angledist( angdest[ 2 ] - localangles[ 2 ] ); + // set destdelta to the vector needed to move + vdestdelta = tdest - localorigin; + angdestdelta[0] = angledist(angdest[0] - localangles[0]); + angdestdelta[1] = angledist(angdest[1] - localangles[1]); + angdestdelta[2] = angledist(angdest[2] - localangles[2]); - if( tdest == localorigin ) - { - // calculate length of vector based on angles - len = angdestdelta.length(); - } - else - { - // calculate length of vector based on distance - len = vdestdelta.length(); - } + if (tdest == localorigin) { + // calculate length of vector based on angles + len = angdestdelta.length(); + } else { + // calculate length of vector based on distance + len = vdestdelta.length(); + } - // divide by speed to get time to reach dest - traveltime = len / tspeed; + // divide by speed to get time to reach dest + traveltime = len / tspeed; - if( traveltime < level.frametime ) - { - traveltime = level.frametime; - vdestdelta = vec_zero; - angdestdelta = vec_zero; - } + if (traveltime < level.frametime) { + traveltime = level.frametime; + vdestdelta = vec_zero; + angdestdelta = vec_zero; + } - // scale the destdelta vector by the time spent traveling to get velocity - if( moveflags & MOVE_ORIGIN ) - { - velocity = vdestdelta * ( 1.0f / traveltime ); - } + // scale the destdelta vector by the time spent traveling to get velocity + if (moveflags & MOVE_ORIGIN) { + velocity = vdestdelta * (1.0f / traveltime); + } - if( moveflags & MOVE_ANGLES ) - { - avelocity = angdestdelta * ( 1.0f / traveltime ); - } + if (moveflags & MOVE_ANGLES) { + avelocity = angdestdelta * (1.0f / traveltime); + } - PostEvent( EV_MoveDone, traveltime ); + PostEvent(EV_MoveDone, traveltime); } /* @@ -229,55 +208,66 @@ void Mover::MoveTo( Vector tdest, Vector angdest, float tspeed, Event& event ) LinearInterpolate =============== */ -void Mover::LinearInterpolate - ( - Vector tdest, - Vector angdest, - float time, - Event &event - ) +void Mover::LinearInterpolate(Vector tdest, Vector angdest, float time, Event& event) { - Vector vdestdelta; - Vector angdestdelta; - float t; + Vector vdestdelta; + Vector angdestdelta; + float t; - if( endevent ) - { - delete endevent; - } - endevent = new Event( event ); - finaldest = tdest; - angledest = angdest; + if (endevent) { + delete endevent; + } + endevent = new Event(event); + finaldest = tdest; + angledest = angdest; - // Cancel previous moves - CancelEventsOfType( EV_MoveDone ); + // Cancel previous moves + CancelEventsOfType(EV_MoveDone); - // Quantize to FRAMETIME - if( time < FRAMETIME ) - { - time = FRAMETIME; - } + // Quantize to FRAMETIME + if (time < FRAMETIME) { + time = FRAMETIME; + } - moveflags = 0; - t = 1 / time; - // scale the destdelta vector by the time spent traveling to get velocity - if( finaldest != localorigin ) - { - vdestdelta = tdest - localorigin; - velocity = vdestdelta * t; - moveflags |= MOVE_ORIGIN; - } + moveflags = 0; + t = 1 / time; + // scale the destdelta vector by the time spent traveling to get velocity + if (finaldest != localorigin) { + vdestdelta = tdest - localorigin; + velocity = vdestdelta * t; + moveflags |= MOVE_ORIGIN; + } - if( angledest != localangles ) - { - angdestdelta = angdest - localangles; - avelocity = angdestdelta * t; - moveflags |= MOVE_ANGLES; - } + if (angledest != localangles) { + angdestdelta = angdest - localangles; + avelocity = angdestdelta * t; + moveflags |= MOVE_ANGLES; + } - if( g_bBeforeThinks ) - time -= FRAMETIME; + if (g_bBeforeThinks) { + time -= FRAMETIME; + } - PostEvent( EV_MoveDone, time ); + PostEvent(EV_MoveDone, time); } +/* +============= +Stop +=============== +*/ +void Mover::Stop() +{ + if (endevent) { + delete endevent; + endevent = NULL; + } + + CancelEventsOfType(EV_MoveDone); + + moveflags = 0; + avelocity = vec_zero; + velocity = vec_zero; + accel = vec_zero; + aaccel = vec_zero; +} diff --git a/code/fgame/mover.h b/code/fgame/mover.h index d39eed77..f128a334 100644 --- a/code/fgame/mover.h +++ b/code/fgame/mover.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,45 +24,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Base class for any object that needs to move to specific locations over a // period of time. This class is kept separate from most entities to keep // class size down for objects that don't need such behavior. -// +// -#ifndef __MOVER_H__ -#define __MOVER_H__ +#pragma once #include "g_local.h" #include "entity.h" #include "trigger.h" class Mover : public Trigger - { - private: - Vector finaldest; - Vector angledest; - Event *endevent; - int moveflags; +{ +private: + Vector finaldest; + Vector angledest; + Event *endevent; + int moveflags; - public: - CLASS_PROTOTYPE( Mover ); +public: + CLASS_PROTOTYPE(Mover); - Mover(); - virtual ~Mover(); - void MoveDone( Event *ev ); - void MoveTo( Vector tdest, Vector angdest, float tspeed, Event &event ); - void LinearInterpolate( Vector tdest, Vector angdest, float time, Event &event ); - void Archive( Archiver &arc ) override; - }; + Mover(); + virtual ~Mover(); + void MoveDone(Event *ev); + void MoveTo(Vector tdest, Vector angdest, float tspeed, Event& event); + void LinearInterpolate(Vector tdest, Vector angdest, float time, Event& event); + void Stop(); + void Archive(Archiver& arc) override; +}; -inline void Mover::Archive - ( - Archiver &arc - ) - { - Trigger::Archive( arc ); +inline void Mover::Archive(Archiver& arc) +{ + Trigger::Archive(arc); - arc.ArchiveVector( &finaldest ); - arc.ArchiveVector( &angledest ); - arc.ArchiveEventPointer( &endevent ); - arc.ArchiveInteger( &moveflags ); - } - -#endif + arc.ArchiveVector(&finaldest); + arc.ArchiveVector(&angledest); + arc.ArchiveEventPointer(&endevent); + arc.ArchiveInteger(&moveflags); +} diff --git a/code/fgame/navigate.cpp b/code/fgame/navigate.cpp index 86288c12..e8a8f24d 100644 --- a/code/fgame/navigate.cpp +++ b/code/fgame/navigate.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -31,243 +31,1222 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "player.h" #include "debuglines.h" #include "scriptexception.h" +#include "gamecmds.h" #define PATHFILE_VERSION 103 -int path_checkthisframe; -cvar_t *ai_showroutes; -cvar_t *ai_showroutes_distance; -cvar_t *ai_shownodenums; -cvar_t *ai_shownode; -cvar_t *ai_showallnode; -cvar_t *ai_showpath; -cvar_t *ai_fallheight; -cvar_t *ai_debugpath; -cvar_t *ai_pathchecktime; -cvar_t *ai_pathcheckdist; +int path_checkthisframe; +cvar_t *ai_showroutes; +cvar_t *ai_showroutes_distance; +cvar_t *ai_shownodenums; +cvar_t *ai_shownode; +cvar_t *ai_showallnode; +cvar_t *ai_showpath; +cvar_t *ai_fallheight; +cvar_t *ai_debugpath; +cvar_t *ai_pathchecktime; +cvar_t *ai_pathcheckdist; +cvar_t *ai_editmode; // Added in OPM -static float *path_start; -static float *path_end; -static PathNode *Node; -static float path_totaldir[ 2 ]; -static float path_p[ 3 ]; -static float path_startdir[ 2 ]; +static const vec_t *path_start; +static const vec_t *path_end; +static PathNode *Node; +static vec2_t path_totaldir; +static vec3_t path_p; +static vec2_t path_startdir; -static Entity *IgnoreObjects[ MAX_GENTITIES ]; -static int NumIgnoreObjects; +static Entity *IgnoreObjects[MAX_GENTITIES]; +static int NumIgnoreObjects; static qboolean pathnodesinitialized = false; -static qboolean loadingarchive = false; -static qboolean pathnodescalculated = false; -int ai_maxnode; +static qboolean loadingarchive = false; +static qboolean pathnodescalculated = false; +int ai_maxnode; -MapCell PathSearch::PathMap[ PATHMAP_GRIDSIZE ][ PATHMAP_GRIDSIZE ]; +MapCell PathSearch::PathMap[PATHMAP_GRIDSIZE][PATHMAP_GRIDSIZE]; PathNode *PathSearch::open; -int PathSearch::findFrame; -qboolean PathSearch::m_bNodesloaded; -qboolean PathSearch::m_NodeCheckFailed; -int PathSearch::m_LoadIndex; +int PathSearch::findFrame; +qboolean PathSearch::m_bNodesloaded; +qboolean PathSearch::m_NodeCheckFailed; +int PathSearch::m_LoadIndex; -PathNode *PathSearch::pathnodes[ MAX_PATHNODES ]; -int PathSearch::nodecount; -float PathSearch::total_dist; +PathNode *PathSearch::pathnodes[MAX_PATHNODES]; +int PathSearch::nodecount; +float PathSearch::total_dist; const char *PathSearch::last_error; -byte *bulkNavMemory = NULL; +byte *bulkNavMemory = NULL; byte *startBulkNavMemory = NULL; -Vector PLAYER_BASE_MIN( -15.5f, -15.5f, 0 ); -Vector PLAYER_BASE_MAX( 15.5f, 15.5f, 0 ); -Vector testpos[ 200 ]; +Vector PLAYER_BASE_MIN(-15.5f, -15.5f, 0); +Vector PLAYER_BASE_MAX(15.5f, 15.5f, 0); +Vector testpos[200]; Vector ai_startpath; Vector ai_endpath; -float NODE_MINS[ 3 ] = { -15, -15, 0 }; -float NODE_MAXS[ 3 ] = { 15, 15, 94 }; -float COLOR_PATHNODE_ERROR[ 3 ] = { 0, 0, 0 }; -float COLOR_PATHNODE_COVER[ 3 ] = { 0, 1, 0 }; -float COLOR_PATHNODE_CORNER_LEFT[ 3 ] = { 1, 1, 0 }; -float COLOR_PATHNODE_CORNER_RIGHT[ 3 ] = { 0.7f, 1, 0 }; -float COLOR_PATHNODE_SNIPER[ 3 ] = { 1, 0, 0 }; -float COLOR_PATHNODE_CRATE[ 3 ] = { 3, 0, 0 }; -float COLOR_PATHNODE_CONCEALMENT[ 3 ] = { 0, 0, 1 }; -float COLOR_PATHNODE_DUCK[ 3 ] = { 0, 1, 1 }; -float COLOR_PATHNODE_DEFAULT[ 3 ] = { 1, 0, 1 }; +float NODE_MINS[3] = {-15, -15, 0}; +float NODE_MAXS[3] = {15, 15, 94}; +float COLOR_PATHNODE_ERROR[3] = {0, 0, 0}; +float COLOR_PATHNODE_COVER[3] = {0, 1, 0}; +float COLOR_PATHNODE_CORNER_LEFT[3] = {1, 1, 0}; +float COLOR_PATHNODE_CORNER_RIGHT[3] = {0.7f, 1, 0}; +float COLOR_PATHNODE_SNIPER[3] = {1, 0, 0}; +float COLOR_PATHNODE_CRATE[3] = {3, 0, 0}; +float COLOR_PATHNODE_CONCEALMENT[3] = {0, 0, 1}; +float COLOR_PATHNODE_DUCK[3] = {0, 1, 1}; +float COLOR_PATHNODE_DEFAULT[3] = {1, 0, 1}; -int testcount = 0; +int testcount = 0; static ActorPath *test_path = NULL; struct { - float fMinRangeSquared; - float fMaxRangeSquared; - float fMinAngle; - float fMaxAngle; -} - -g_AttackParms[] = -{ - { 64 * 64, 2048 * 2048, 150.0f, 210.0f }, - { 64 * 64, 2048 * 2048, 150.0f, 210.0f }, - { 96 * 96, 2048 * 2048, 320.0f, 40.0f }, + float fMinRangeSquared; + float fMaxRangeSquared; + float fMinAngle; + float fMaxAngle; +} g_AttackParms[] = { + {Square(64), Square(2048), 150.0f, 210.0f}, + {Square(64), Square(2048), 150.0f, 210.0f}, + {Square(96), Square(2048), 320.0f, 40.0f }, + {Square(96), Square(4096), 0.0f, 0.0f }, }; PathSearch PathManager; int path_checksthisframe; -void AI_AddNode - ( - PathNode *node - ) +PathInfo *PathSearch::GeneratePath(PathInfo *path) { - int i = PathSearch::nodecount; + PathNode *ParentNode; + pathway_t *pathway; + float dist; + float dir[2]; + PathInfo *current_path; - assert( node ); + current_path = path; - if( i < MAX_PATHNODES ) - { - if( i > ai_maxnode ) - { - ai_maxnode = i; - } - PathSearch::pathnodes[ i ] = node; - node->nodenum = i; - PathSearch::nodecount++; - return; - } + dir[0] = path_end[0] - Node->m_PathPos[0]; + dir[1] = path_end[1] - Node->m_PathPos[1]; - gi.Error( ERR_DROP, "Exceeded MAX_PATHNODES!\n" ); + dist = VectorNormalize2D(dir); + + total_dist = dist + Node->g; + + VectorCopy(path_end, current_path->point); + + ParentNode = Node->Parent; + if (ParentNode) { + pathway = &ParentNode->Child[Node->pathway]; + VectorSub2D(path_end, pathway->pos2, current_path->dir); + current_path->dist = VectorNormalize2D(current_path->dir); + + if (path->dist) { + path->bAccurate = false; + current_path++; + } + + if (pathway->dist) { + VectorCopy(pathway->pos2, current_path->point); + VectorCopy2D(pathway->dir, current_path->dir); + current_path->dist = pathway->dist; + current_path->bAccurate = true; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + current_path++; + } + + for (Node = ParentNode, ParentNode = ParentNode->Parent; ParentNode != NULL; + Node = ParentNode, ParentNode = ParentNode->Parent) { + pathway = &ParentNode->Child[Node->pathway]; + if (pathway->dist) { + VectorCopy(pathway->pos2, current_path->point); + VectorCopy2D(pathway->dir, current_path->dir); + current_path->dist = pathway->dist; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + current_path->bAccurate = true; + current_path++; + } + } + + VectorCopy(pathway->pos1, current_path->point); + VectorCopy2D(path_startdir, current_path->dir); + current_path->dist = Node->g; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + } else { + VectorCopy2D(path_totaldir, current_path->dir); + path->dist = Node->h; + } + + if (current_path->dist) { + current_path->bAccurate = false; + current_path++; + + VectorCopy(path_start, current_path->point); + current_path->dist = 0; + VectorClear2D(current_path->dir); + } + + current_path->bAccurate = false; + return current_path; } -qboolean CheckMove - ( - Vector &origin, - Vector &pos, - short int *path_fallheight, - float size - ) +PathInfo *PathSearch::GeneratePathNear(PathInfo *path) { - mmove_t mm; - int i; - float air_z; - float fallheight; - float test_fallheight; - float error; - trace_t trace; - vec3_t dir; - vec3_t end; + PathInfo *current_path = path; + pathway_t *pathway; + PathNode *ParentNode; - memset( &mm, 0, sizeof( mmove_t ) ); + total_dist = Node->g; + VectorCopy(Node->m_PathPos, path->point); - VectorClear( mm.velocity ); - VectorCopy( origin, mm.origin ); - mm.desired_speed = 150.0f; - mm.entityNum = ENTITYNUM_NONE; - mm.tracemask = MASK_PATHSOLID; - mm.frametime = 0.1f; - mm.desired_dir[ 0 ] = pos[ 0 ] - origin[ 0 ]; - mm.desired_dir[ 1 ] = pos[ 1 ] - origin[ 1 ]; - VectorNormalize2D( mm.desired_dir ); + ParentNode = Node->Parent; + if (ParentNode) { + pathway = &ParentNode->Child[Node->pathway]; - mm.groundPlane = qfalse; - mm.walking = qfalse; + if (pathway->dist) { + VectorCopy(pathway->pos2, path->point); + VectorCopy2D(pathway->dir, path->dir); + path->dist = pathway->dist; - mm.mins[ 0 ] = -size; - mm.mins[ 1 ] = -size; - mm.mins[ 2 ] = 0; - mm.maxs[ 0 ] = size; - mm.maxs[ 1 ] = size; - mm.maxs[ 2 ] = 94.0f; + current_path->bAccurate = true; + current_path++; + } - testcount = 0; - fallheight = 0.0f; - air_z = mm.origin[ 2 ]; + for (Node = ParentNode, ParentNode = ParentNode->Parent; ParentNode != NULL; + Node = ParentNode, ParentNode = ParentNode->Parent) { + pathway = &ParentNode->Child[Node->pathway]; + if (pathway->dist) { + VectorCopy(pathway->pos2, current_path->point); + VectorCopy2D(pathway->dir, current_path->dir); + current_path->dist = pathway->dist; + current_path->bAccurate = true; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + current_path++; + } + } - for( i = 200; i != 1; i-- ) - { - testpos[ i - 1 ] = mm.origin; - testcount++; + VectorCopy(pathway->pos1, current_path->point); + VectorCopy2D(path_startdir, current_path->dir); + current_path->dist = Node->g; + } else { + VectorCopy2D(path_totaldir, current_path->dir); + path->dist = Node->h; + } - MmoveSingle( &mm ); + if (current_path->dist) { + current_path->bAccurate = false; + current_path++; - if( mm.groundPlane ) - { - test_fallheight = air_z - mm.origin[ 2 ]; + VectorCopy(path_start, current_path->point); + VectorClear2D(current_path->dir); + current_path->dist = 0; + } - if( test_fallheight > fallheight ) - { - if( test_fallheight > 1024.0f ) - return false; + current_path->bAccurate = false; + return current_path; +} - fallheight = test_fallheight; - } +PathInfo *PathSearch::GeneratePathAway(PathInfo *path) +{ + PathInfo *current_path = path; + pathway_t *pathway; + PathNode *ParentNode; - air_z = mm.origin[ 2 ]; - } - - dir[ 0 ] = pos[ 0 ] - mm.origin[ 0 ]; - dir[ 1 ] = pos[ 1 ] - mm.origin[ 1 ]; - - if( DotProduct2D( dir, mm.desired_dir ) <= 0.1f ) - { - error = mm.origin[ 2 ] - pos[ 2 ]; + VectorCopy(Node->m_PathPos, path->point); - gi.Printf( "error = %f\n", error ); + ParentNode = Node->Parent; + if (ParentNode) { + pathway = &ParentNode->Child[Node->pathway]; - *path_fallheight = ( short )fallheight; - if( fabs( error ) > 94.0f ) - { - if( mm.groundPlane ) - return false; + if (pathway->dist) { + VectorCopy(pathway->pos2, current_path->point); + VectorCopy2D(pathway->dir, current_path->dir); + current_path->dist = pathway->dist; - mm.desired_dir[ 0 ] = dir[ 0 ]; - mm.desired_dir[ 1 ] = dir[ 1 ]; - VectorNormalize2D( mm.desired_dir ); - } - else if( error > 0.0f && !mm.groundPlane ) - { - end[ 0 ] = mm.origin[ 0 ]; - end[ 1 ] = mm.origin[ 1 ]; - end[ 2 ] = pos[ 2 ]; + current_path->bAccurate = true; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + current_path++; + } - trace = G_Trace( mm.origin, - mm.mins, - mm.maxs, - end, - NULL, - MASK_PATHSOLID, - true, - "CheckMove" ); + for (Node = ParentNode, ParentNode = ParentNode->Parent; ParentNode != NULL; + Node = ParentNode, ParentNode = ParentNode->Parent) { + pathway = &ParentNode->Child[Node->pathway]; + if (pathway->dist) { + VectorCopy(pathway->pos2, current_path->point); + VectorCopy2D(pathway->dir, current_path->dir); + current_path->dist = pathway->dist; + current_path->bAccurate = true; + assert(current_path->dist > -1e+07 && current_path->dist < 1e+07); + current_path++; + } + } - test_fallheight = mm.origin[ 2 ] - trace.endpos[ 2 ]; + VectorCopy(pathway->pos1, current_path->point); + VectorCopy2D(pathway->pos1, current_path->point); - if( test_fallheight <= 18.0f ) - { - *path_fallheight = ( short )test_fallheight + fallheight; - return test_fallheight + fallheight <= 1024.0f; - } + current_path->dist = Node->g; - if( mm.groundPlane ) - return false; + if (Node->g) { + current_path->bAccurate = false; + current_path++; + VectorCopy(path_start, current_path->point); + VectorClear2D(current_path->dir); + current_path->dist = 0; + } + } else { + VectorClear2D(path->dir); + path->dist = 0; + } - mm.desired_dir[ 0 ] = dir[ 0 ]; - mm.desired_dir[ 1 ] = dir[ 1 ]; - VectorNormalize2D( mm.desired_dir ); - } - else - { - return true; - } - } - - if( mm.hit_obstacle ) - { - gi.DPrintf( "obstacle hit\n" ); - return false; - } - } + current_path->bAccurate = false; + return current_path; +} - return false; +int PathSearch::FindPath( + const vec3_t start, + const vec3_t end, + Entity *ent, + float maxPath, + const vec3_t vLeashHome, + float fLeashDistSquared, + int fallheight +) +{ + int i; + int g; + PathNode *NewNode; + pathway_t *pathway; + PathNode *prev; + PathNode *next; + int f; + vec2_t delta; + PathNode *to; + + if (ent) { + // Added in OPM + // Check for simple actor + if (ent->IsSubclassOfActor()) { + Node = NearestStartNode(start, static_cast(ent)); + } else { + Node = DebugNearestStartNode(start, ent); + } + } else { + Node = DebugNearestStartNode(start); + } + + if (!Node) { + last_error = "couldn't find start node"; + return 0; + } + + to = NearestEndNode(end); + if (!to) { + last_error = "couldn't find end node"; + return 0; + } + + total_dist = 1e+12f; + + if (!maxPath) { + maxPath = 1e+12f; + } + + findFrame++; + open = NULL; + + VectorSub2D(Node->origin, start, path_startdir); + Node->g = VectorNormalize2D(path_startdir); + + VectorSub2D(end, start, path_totaldir); + Node->h = VectorNormalize2D(path_totaldir); + + Node->Parent = NULL; + Node->m_Depth = 3; + Node->findCount = findFrame; + Node->inopen = true; + Node->PrevNode = NULL; + Node->NextNode = NULL; + Node->m_PathPos = start; + + open = Node; + + while (open) { + Node = open; + open->inopen = false; + open = Node->NextNode; + + if (open) { + open->PrevNode = NULL; + } + + if (Node == to) { + path_start = start; + path_end = end; + return Node->m_Depth; + } + + for (i = Node->numChildren - 1; i >= 0; i--) { + vec2_t vDist; + + pathway = &Node->Child[i]; + + NewNode = pathnodes[pathway->node]; + if (!NewNode) { + continue; + } + + if (vLeashHome) { + VectorSub2D(pathway->pos2, vLeashHome, vDist); + if (VectorLength2DSquared(vDist) > fLeashDistSquared) { + continue; + } + } + + g = (int)(pathway->dist + Node->g + 1.0f); + + if (NewNode->findCount == findFrame) { + if (NewNode->g <= g) { + continue; + } + + if (NewNode->inopen) { + NewNode->inopen = false; + next = NewNode->NextNode; + prev = NewNode->PrevNode; + + if (next) { + next->PrevNode = prev; + } + + if (prev) { + prev->NextNode = next; + } else { + open = next; + } + } + } + + VectorSub2D(end, pathway->pos2, delta); + NewNode->h = VectorLength2D(delta); + + f = (int)((float)g + NewNode->h); + + if (f >= maxPath) { + last_error = "specified path distance exceeded"; + return 0; + } + + if (pathway->fallheight <= fallheight + && (!ent || !ent->IsSubclassOfSentient() || !pathway->badPlaceTeam[static_cast(ent)->m_Team] + )) { + NewNode->m_Depth = Node->m_Depth + 1; + NewNode->Parent = Node; + NewNode->pathway = i; + NewNode->g = (float)g; + NewNode->f = (float)f; + NewNode->m_PathPos = pathway->pos2; + NewNode->findCount = findFrame; + NewNode->inopen = true; + + if (!open) { + NewNode->NextNode = NULL; + NewNode->PrevNode = NULL; + open = NewNode; + continue; + } + + if (open->f >= f) { + NewNode->NextNode = open; + NewNode->PrevNode = NULL; + + open->PrevNode = NewNode; + open = NewNode; + continue; + } + + prev = open; + for (next = open->NextNode; next; next = next->NextNode) { + if (next->f >= f) { + break; + } + prev = next; + } + + NewNode->NextNode = next; + if (next) { + next->PrevNode = NewNode; + } + prev->NextNode = NewNode; + NewNode->PrevNode = prev; + } + } + } + + last_error = "unreachable path"; + return 0; +} + +int PathSearch::FindPathNear( + const vec3_t start, + const vec3_t end, + Entity *ent, + float maxPath, + float fRadiusSquared, + const vec3_t vLeashHome, + float fLeashDistSquared, + int fallheight +) +{ + int i; + int g; + PathNode *NewNode; + pathway_t *pathway; + PathNode *prev; + PathNode *next; + int f; + vec2_t dir; + vec2_t delta; + + if (ent) { + // Added in OPM + // Check for simple actor + if (ent->IsSubclassOfActor()) { + Node = NearestStartNode(start, static_cast(ent)); + } else { + Node = DebugNearestStartNode(start, ent); + } + } else { + Node = DebugNearestStartNode(start); + } + + if (!Node) { + last_error = "no start node"; + return 0; + } + + total_dist = 1e12f; + + if (!maxPath) { + maxPath = 1e12f; + } + + findFrame++; + open = NULL; + + VectorSub2D(Node->origin, start, path_startdir); + VectorSub2D(end, start, delta); + VectorCopy2D(delta, dir); + + Node->inopen = true; + Node->g = VectorNormalize2D(path_startdir); + Node->h = VectorNormalize2D(dir); + Node->Parent = NULL; + Node->m_Depth = 3; + Node->findCount = findFrame; + Node->PrevNode = NULL; + Node->NextNode = NULL; + Node->m_PathPos = start; + + open = Node; + + while (open) { + Node = open; + open->inopen = false; + open = Node->NextNode; + + if (open) { + open->PrevNode = NULL; + } + + VectorSub2D(end, Node->m_PathPos, delta); + + if (fRadiusSquared >= VectorLength2DSquared(delta)) { + path_start = start; + path_end = end; + return Node->m_Depth; + } + + for (i = Node->numChildren - 1; i >= 0; i--) { + pathway = &Node->Child[i]; + + NewNode = pathnodes[pathway->node]; + if (!NewNode) { + continue; + } + + g = (int)(pathway->dist + Node->g + 1.0f); + + if (NewNode->findCount == findFrame) { + if (NewNode->g <= g) { + continue; + } + + if (NewNode->inopen) { + NewNode->inopen = false; + next = NewNode->NextNode; + prev = NewNode->PrevNode; + + if (next) { + next->PrevNode = prev; + } + + if (prev) { + prev->NextNode = next; + } else { + open = next; + } + } + } + + VectorSub2D(end, pathway->pos2, delta); + NewNode->h = VectorLength2D(delta); + + f = (int)((float)g + NewNode->h); + + if (f >= maxPath) { + last_error = "specified path distance exceeded"; + return 0; + } + + if (pathway->fallheight <= fallheight + && (!ent || !ent->IsSubclassOfSentient() || !pathway->badPlaceTeam[static_cast(ent)->m_Team] + )) { + NewNode->m_Depth = Node->m_Depth + 1; + NewNode->Parent = Node; + NewNode->pathway = i; + NewNode->g = (float)g; + NewNode->f = (float)f; + NewNode->m_PathPos = pathway->pos2; + NewNode->findCount = findFrame; + NewNode->inopen = true; + + if (!open) { + NewNode->NextNode = NULL; + NewNode->PrevNode = NULL; + open = NewNode; + continue; + } + + if (open->f >= f) { + NewNode->NextNode = open; + NewNode->PrevNode = NULL; + + open->PrevNode = NewNode; + open = NewNode; + continue; + } + + prev = open; + for (next = open->NextNode; next; next = next->NextNode) { + if (next->f >= f) { + break; + } + prev = next; + } + + NewNode->NextNode = next; + if (next) { + next->PrevNode = NewNode; + } + prev->NextNode = NewNode; + NewNode->PrevNode = prev; + } + } + } + + last_error = "unreachable path"; + return 0; +} + +int PathSearch::FindPathAway( + const vec3_t start, + const vec3_t avoid, + const vec3_t vPreferredDir, + Entity *ent, + float fMinSafeDist, + const vec3_t vLeashHome, + float fLeashDistSquared, + int fallheight +) +{ + int i; + int g; + PathNode *NewNode; + pathway_t *pathway; + PathNode *prev; + PathNode *next; + int f; + float fBias; + vec2_t delta; + float fMinSafeDistSquared; + + fMinSafeDistSquared = fMinSafeDist * fMinSafeDist; + + if (ent) { + // Added in OPM + // Check for simple actor + if (ent->IsSubclassOfActor()) { + Node = NearestStartNode(start, static_cast(ent)); + } else { + Node = DebugNearestStartNode(start, ent); + } + } else { + Node = DebugNearestStartNode(start); + } + + if (!Node) { + last_error = "couldn't find start node"; + return 0; + } + + findFrame++; + open = NULL; + + VectorSub2D(Node->origin, start, path_startdir); + VectorSub2D(start, avoid, delta); + + fBias = VectorLength2D(vPreferredDir); + + Node->inopen = true; + Node->g = VectorNormalize2D(path_startdir); + Node->h = fMinSafeDist - VectorNormalize2D(delta); + Node->h += fBias - DotProduct2D(vPreferredDir, delta); + Node->Parent = NULL; + Node->m_Depth = 2; + Node->findCount = findFrame; + Node->PrevNode = NULL; + Node->NextNode = NULL; + Node->m_PathPos = start; + + open = Node; + + while (open) { + Node = open; + open->inopen = false; + open = Node->NextNode; + + if (open) { + open->PrevNode = NULL; + } + + VectorSub2D(Node->m_PathPos, avoid, delta); + + if (VectorLength2DSquared(delta) >= fMinSafeDistSquared) { + path_start = start; + return Node->m_Depth; + } + + for (i = Node->numChildren - 1; i >= 0; i--) { + vec2_t vDist; + + pathway = &Node->Child[i]; + + NewNode = pathnodes[pathway->node]; + if (!NewNode) { + continue; + } + + if (vLeashHome) { + VectorSub2D(pathway->pos2, vLeashHome, vDist); + if (VectorLength2DSquared(vDist) > fLeashDistSquared) { + continue; + } + } + + g = (int)(pathway->dist + Node->g + 1.0f); + + if (NewNode->findCount == findFrame) { + if (NewNode->g <= g) { + continue; + } + + if (NewNode->inopen) { + NewNode->inopen = false; + next = NewNode->NextNode; + prev = NewNode->PrevNode; + + if (next) { + next->PrevNode = prev; + } + + if (prev) { + prev->NextNode = next; + } else { + open = next; + } + } + } + + VectorSub2D(pathway->pos2, avoid, delta); + NewNode->h = VectorNormalize2D(delta); + NewNode->h += fBias - DotProduct2D(delta, vPreferredDir); + + f = (int)((float)g + NewNode->h); + + if (pathway->fallheight <= fallheight) { + NewNode->m_Depth = Node->m_Depth + 1; + NewNode->Parent = Node; + NewNode->pathway = i; + NewNode->g = (float)g; + NewNode->f = (float)f; + NewNode->m_PathPos = pathway->pos2; + NewNode->findCount = findFrame; + NewNode->inopen = true; + + if (!open) { + NewNode->NextNode = NULL; + NewNode->PrevNode = NULL; + open = NewNode; + continue; + } + + if (open->f >= f) { + NewNode->NextNode = open; + NewNode->PrevNode = NULL; + + open->PrevNode = NewNode; + open = NewNode; + continue; + } + + prev = open; + for (next = open->NextNode; next; next = next->NextNode) { + if (next->f >= f) { + break; + } + prev = next; + } + + NewNode->NextNode = next; + if (next) { + next->PrevNode = NewNode; + } + prev->NextNode = NewNode; + NewNode->PrevNode = prev; + } + } + } + + last_error = "unreachable path"; + return 0; +} + +PathNode *PathSearch::FindCornerNodeForWall( + const vec3_t start, const vec3_t end, Entity *ent, float maxPath, const vec4_t plane +) +{ + int i, g; + PathNode *NewNode; + pathway_t *pathway; + PathNode *prev, *next; + int f; + vec2_t delta; + vec2_t dir; + + if (ent) { + // Added in OPM + // Check for simple actor + if (ent->IsSubclassOfActor()) { + Node = NearestStartNode(start, static_cast(ent)); + } else { + Node = DebugNearestStartNode(start, ent); + } + } else { + Node = DebugNearestStartNode(start); + } + + if (!Node) { + last_error = "couldn't find start node"; + return NULL; + } + + if (DotProduct(start, plane) - plane[3] < 0.0) { + last_error = "starting point is already behind the wall"; + return NULL; + } + + if (DotProduct(plane, end) - plane[3] > 0.0) { + last_error = "end point is in front of the wall"; + return NULL; + } + + total_dist = 1e12f; + + if (maxPath == 0.0) { + maxPath = 1e12f; + } + + findFrame++; + open = NULL; + + VectorSub2D(Node->origin, start, path_startdir); + Node->g = VectorNormalize2D(path_startdir); + + VectorSub2D(end, start, path_totaldir); + Node->h = VectorNormalize2D(path_totaldir); + Node->inopen = true; + Node->Parent = NULL; + Node->m_Depth = 3; + Node->findCount = findFrame; + Node->PrevNode = 0; + Node->NextNode = 0; + Node->m_PathPos = start; + + open = Node; + + while (open) { + Node = open; + open->inopen = false; + open = Node->NextNode; + + if (open) { + open->PrevNode = NULL; + } + + if (Node->Parent && DotProduct(Node->m_PathPos, plane) - plane[3] < 0) { + VectorSub2D(Node->m_PathPos, start, delta); + + if (VectorLength2DSquared(delta) >= 256) { + return Node->Parent; + } + return Node; + } + + for (i = Node->numChildren - 1; i >= 0; i--) { + pathway = &Node->Child[i]; + + NewNode = pathnodes[pathway->node]; + if (!NewNode) { + continue; + } + + g = (int)(pathway->dist + Node->g + 1.0f); + + if (NewNode->findCount == findFrame) { + if (NewNode->g <= g) { + continue; + } + + if (NewNode->inopen) { + NewNode->inopen = false; + next = NewNode->NextNode; + prev = NewNode->PrevNode; + + if (next) { + next->PrevNode = prev; + } + + if (prev) { + prev->NextNode = next; + } else { + open = next; + } + } + } + + VectorSub2D(end, pathway->pos2, dir); + NewNode->h = VectorNormalize2D(dir); + + f = (int)((float)g + NewNode->h); + + if (f >= maxPath) { + last_error = "specified path distance exceeded"; + return 0; + } + + NewNode->m_Depth = Node->m_Depth + 1; + NewNode->Parent = Node; + NewNode->pathway = i; + NewNode->g = (float)g; + NewNode->f = (float)f; + NewNode->m_PathPos = pathway->pos2; + NewNode->findCount = findFrame; + NewNode->inopen = true; + + if (!open) { + NewNode->NextNode = NULL; + NewNode->PrevNode = NULL; + open = NewNode; + continue; + } + + if (open->f >= f) { + NewNode->NextNode = open; + NewNode->PrevNode = NULL; + + open->PrevNode = NewNode; + open = NewNode; + continue; + } + + prev = open; + for (next = open->NextNode; next; next = next->NextNode) { + if (next->f >= f) { + break; + } + prev = next; + } + + NewNode->NextNode = next; + if (next) { + next->PrevNode = NewNode; + } + prev->NextNode = NewNode; + NewNode->PrevNode = prev; + } + } + + last_error = "unreachable path"; + return NULL; +} + +PathNode *PathSearch::FindCornerNodeForExactPath(Entity *pSelf, Sentient *enemy, float fMaxPath) +{ + PathNode *pPathNode[MAX_PATHNODES]; + PathNode *pParentNode; + size_t i, iDepth; + Vector vEnd; + Vector vEyeDelta; + Vector vEyePos; + + iDepth = PathSearch::FindPath(enemy->origin, pSelf->origin, pSelf, fMaxPath, 0, 0.0, 100); + if (!iDepth) { + return NULL; + } + + if (pSelf->IsSubclassOfActor()) { + vEyePos = static_cast(pSelf)->EyePosition(); + } else { + vEyePos = pSelf->origin + Vector(0, 0, pSelf->maxs.z); + } + + vEyeDelta = vEyePos - pSelf->origin; + + for (pParentNode = Node->Parent, i = 0; pParentNode; pParentNode = pParentNode->Parent, i++) { + Node = pParentNode; + pPathNode[i] = pParentNode; + } + + iDepth = i; + if (!iDepth) { + return NULL; + } + + for (i = 1; i < iDepth; i += 2) { + vEnd = vEyeDelta + pPathNode[i]->m_PathPos; + + if (!G_SightTrace( + vEyePos, vec_zero, vec_zero, vEnd, pSelf, enemy, MASK_CORNER_NODE, qfalse, "FindCornerNodeFoExactPath 1" + )) { + break; + } + } + + i--; + if (i >= iDepth) { + i = iDepth - 1; + return pPathNode[i]; + } + + if (i) { + vEnd = vEyeDelta + pPathNode[i]->m_PathPos; + + if (!G_SightTrace( + vEyePos, vec_zero, vec_zero, vEnd, pSelf, enemy, MASK_CORNER_NODE, qfalse, "FindCornerNodeFoExactPath 2" + )) { + i--; + } + } + + return pPathNode[i]; +} + +void PathSearch::ResetNodes(void) +{ + int i; + int x; + int y; + + m_bNodesloaded = false; + m_LoadIndex = -1; + + if (!startBulkNavMemory && nodecount) { + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + if (PathMap[x][y].nodes) { + gi.Free(PathMap[x][y].nodes); + } + } + } + + for (i = 0; i < nodecount; i++) { + if (pathnodes[i] && pathnodes[i]->Child) { + gi.Free(pathnodes[i]->Child); + } + } + } + + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + PathMap[x][y] = MapCell(); + } + } + + for (i = 0; i < nodecount; i++) { + if (pathnodes[i]) { + delete pathnodes[i]; + pathnodes[i] = NULL; + } + } + + nodecount = 0; + + // Free the bulk nav' memory + if (startBulkNavMemory) { + gi.Free(startBulkNavMemory); + bulkNavMemory = NULL; + startBulkNavMemory = NULL; + } +} + +void PathSearch::ClearNodes(void) +{ + int i, j; + int x; + int y; + + m_bNodesloaded = false; + m_LoadIndex = -1; + + if (!startBulkNavMemory && nodecount) { + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + if (PathMap[x][y].nodes) { + gi.Free(PathMap[x][y].nodes); + } + } + } + + for (i = 0; i < nodecount; i++) { + if (pathnodes[i] && pathnodes[i]->Child) { + gi.Free(pathnodes[i]->Child); + } + } + } + + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + PathMap[x][y] = MapCell(); + } + } + + for (i = 0; i < nodecount; i++) { + if (pathnodes[i]) { + pathnodes[i]->Child = NULL; + pathnodes[i]->virtualNumChildren = 0; + pathnodes[i]->numChildren = 0; + pathnodes[i]->findCount = 0; + } + } + + // Rebuild node list + for (i = 0; i < nodecount; i++) { + PathNode *node1 = pathnodes[i]; + if (node1) { + continue; + } + + for (j = i + 1; j < nodecount; j++) { + PathNode *node2 = pathnodes[j]; + if (node2) { + pathnodes[i] = node2; + pathnodes[j] = NULL; + node2->nodenum = i; + break; + } + } + } + + while (nodecount > 0 && !pathnodes[nodecount - 1]) { + nodecount--; + } + + // Free the bulk nav' memory + if (startBulkNavMemory) { + gi.Free(startBulkNavMemory); + bulkNavMemory = NULL; + startBulkNavMemory = NULL; + } +} + +void PathSearch::UpdatePathwaysForBadPlace(const Vector& origin, float radius, int dir, int team) +{ + float radiusSqr; + int i, j, k; + + radiusSqr = radius * radius; + + for (i = 0; i < nodecount; i++) { + PathNode *node = pathnodes[i]; + if (!node) { + continue; + } + + for (j = node->virtualNumChildren; j > 0; j--) { + pathway_t& pathway = node->Child[j - 1]; + if (PointToSegmentDistanceSquared(origin, pathway.pos1, pathway.pos2) < radiusSqr) { + for (k = 0; k < 2; k++) { + if ((1 << k) & team) { + pathway.badPlaceTeam[k] += dir; + } + } + } + } + } +} + +void AI_AddNode(PathNode *node) +{ + int i; + + assert(node); + + // + // Find a free slot + // + for (i = 0; i < PathSearch::nodecount; i++) { + if (!PathSearch::pathnodes[i]) { + PathSearch::pathnodes[i] = node; + node->nodenum = i; + return; + } + } + + if (i > ai_maxnode) { + ai_maxnode = i; + } + + if (i >= MAX_PATHNODES) { + gi.Error(ERR_DROP, "Exceeded MAX_PATHNODES!\n"); + return; + } + + PathSearch::pathnodes[i] = node; + node->nodenum = i; + + PathSearch::nodecount++; +} + +void AI_RemoveNode(PathNode *node) +{ + int num; + + num = node->nodenum; + delete node; + + PathSearch::pathnodes[num] = NULL; + if (num == PathSearch::nodecount) { + PathSearch::nodecount--; + } } /*****************************************************************************/ @@ -287,795 +1266,497 @@ JUMP marks the node as one to jump from when going to the node specified by targ ******************************************************************************/ Event EV_Path_SetNodeFlags - ( - "spawnflags", - EV_DEFAULT, - "i", - "node_flags", - "Sets the path nodes flags.", - EV_NORMAL - ); +( + "spawnflags", + EV_DEFAULT, + "i", + "node_flags", + "Sets the path nodes flags.", + EV_NORMAL +); -CLASS_DECLARATION( SimpleEntity, PathNode, "info_pathnode" ) -{ - { &EV_Path_SetNodeFlags, &PathNode::SetNodeFlags }, - { &EV_IsTouching, &PathNode::IsTouching }, - { &EV_Delete, &PathNode::Remove }, - { &EV_Remove, &PathNode::Remove }, - { NULL, NULL } +// Added in 2.0 +Event EV_Path_SetLowWallArc +( + "low_wall_arc", + EV_DEFAULT, + "f", + "arc_half_angle", + "Marks this node as good for low-wall behavior" + "and gives the arc" +); + +CLASS_DECLARATION(SimpleEntity, PathNode, "info_pathnode") { + {&EV_Path_SetNodeFlags, &PathNode::SetNodeFlags }, + {&EV_IsTouching, &PathNode::IsTouching }, + {&EV_Delete, &PathNode::Remove }, + {&EV_Remove, &PathNode::Remove }, + {&EV_Path_SetLowWallArc, &PathNode::SetLowWallArc}, + {NULL, NULL } }; -static Vector pathNodesChecksum; -static int numLoadNodes = 0; -static int numNodes = 0; +static Vector pathNodesChecksum; +static int numLoadNodes = 0; +static int numNodes = 0; -void *PathNode::operator new( size_t size ) +void *PathNode::operator new(size_t size) { - return PathManager.AllocPathNode(); + return PathManager.AllocPathNode(); } -void PathNode::operator delete( void *ptr ) +void PathNode::operator delete(void *ptr) { - return PathManager.FreePathNode( ptr ); + return PathManager.FreePathNode(ptr); } PathNode::PathNode() { - entflags |= EF_PATHNODE; - findCount = 0; - numChildren = 0; - iAvailableTime = -1; + entflags |= ECF_PATHNODE; + findCount = 0; + pLastClaimer = NULL; + numChildren = 0; + iAvailableTime = -1; - if( !loadingarchive ) - { - // our archive function will take care of this stuff - AI_AddNode( this ); - nodeflags = 0; - virtualNumChildren = 0; - iAvailableTime = -1; - Child = NULL; - } + if (!loadingarchive) { + // our archive function will take care of this stuff + AI_AddNode(this); + nodeflags = 0; + m_fLowWallArc = 0; + pLastClaimer = NULL; + iAvailableTime = -1; + virtualNumChildren = 0; + Child = NULL; + } } PathNode::~PathNode() { - entflags &= ~EF_PATHNODE; + entflags &= ~ECF_PATHNODE; } -void PathNode::Claim - ( - Entity *pClaimer - ) +void PathNode::Remove(Event *ev) { - pLastClaimer = pClaimer; - iAvailableTime = 0; + // Pathnodes mustn't be removed + ScriptError("Not allowed to delete a path node"); } -const_str PathNode::GetSpecialAttack - ( - Actor *pActor - ) +void PathNode::SetNodeFlags(Event *ev) { - int iSpecialAttack; - const_str csAnimation; - float fRangeSquared; - float vDelta[ 2 ]; - float fMinAngle; - float fMaxAngle; - - if( nodeflags & AI_CORNER_LEFT ) - { - iSpecialAttack = 0; - csAnimation = STRING_ANIM_CORNERLEFT_SCR; - } - else if( nodeflags & AI_CORNER_RIGHT ) - { - iSpecialAttack = 1; - csAnimation = STRING_ANIM_CORNERRIGHT_SCR; - } - else - { - if( nodeflags >= 0 ) - return STRING_NULL; - - iSpecialAttack = 2; - csAnimation = STRING_ANIM_OVERATTACK_SCR; - } - - if( pActor->m_Enemy ) - { - vDelta[ 0 ] = pActor->m_Enemy->origin[ 0 ] - origin[ 0 ]; - vDelta[ 1 ] = pActor->m_Enemy->origin[ 1 ] - origin[ 1 ]; - } - else - { - vDelta[ 0 ] = pActor->m_vLastEnemyPos[ 0 ] - origin[ 0 ]; - vDelta[ 1 ] = pActor->m_vLastEnemyPos[ 1 ] - origin[ 1 ]; - } - - fRangeSquared = vDelta[ 0 ] * vDelta[ 0 ] + vDelta[ 1 ] * vDelta[ 1 ]; - - if( fRangeSquared < g_AttackParms[ iSpecialAttack ].fMinRangeSquared || fRangeSquared > g_AttackParms[ iSpecialAttack ].fMaxRangeSquared ) - return STRING_NULL; - - fMinAngle = atan2( vDelta[ 0 ], vDelta[ 1 ] ) * ( 180.0f / M_PI ) - angles[ 1 ]; - - if( fMinAngle > -360.0f ) - { - if( fMinAngle >= 0.0f ) - { - if( fMinAngle >= 720.0f ) - fMaxAngle = fMinAngle - 720.0f; - else if( fMinAngle >= 360.0f ) - fMaxAngle = fMinAngle - 360.0f; - else - fMaxAngle = fMinAngle; - } - else - { - fMaxAngle = fMinAngle + 360.0f; - } - } - else - { - fMaxAngle = fMinAngle + 720.0f; - } - - if( g_AttackParms[ iSpecialAttack ].fMinAngle <= g_AttackParms[ iSpecialAttack ].fMaxAngle ) - { - if( g_AttackParms[ iSpecialAttack ].fMinAngle > fMaxAngle ) - return STRING_NULL; - } - else - { - if( g_AttackParms[ iSpecialAttack ].fMinAngle <= fMaxAngle ) - return STRING_NULL; - } - - if( fMaxAngle > g_AttackParms[ iSpecialAttack ].fMaxAngle ) - return STRING_NULL; - - return csAnimation; + nodeflags = ev->GetInteger(1); } -Entity *PathNode::GetClaimHolder - ( - void - ) const +void PathNode::SetLowWallArc(Event *ev) { - if( iAvailableTime ) - return NULL; - else - return pLastClaimer; + float value = ev->GetFloat(1); + if (value < 0 || value >= 180) { + ScriptError("low_wall_arc must be >= 0 and < 180"); + } + + m_fLowWallArc = value; + + if (!value) { + nodeflags &= ~AI_LOW_WALL_ARC; + } else { + nodeflags |= AI_LOW_WALL_ARC; + } } -bool PathNode::IsClaimedByOther - ( - Entity *pPossibleClaimer - ) const +void PathNode::ConnectTo(PathNode *node) { - if( pLastClaimer == pPossibleClaimer ) - return false; - - if( iAvailableTime ) - { - return ( level.inttime < iAvailableTime ); - } - else - { - return ( pLastClaimer != NULL ); - } + Child[virtualNumChildren].node = node->nodenum; + Child[virtualNumChildren].numBlockers = 0; + Child[virtualNumChildren].badPlaceTeam[0] = 0; + Child[virtualNumChildren].badPlaceTeam[1] = 0; + virtualNumChildren++; + numChildren++; } -qboolean PathNode::IsTouching - ( - Entity *e1 - ) +void PathNode::ConnectChild(int i) { - return e1->absmin[ 0 ] <= origin[ 0 ] + 15.5f && - e1->absmin[ 1 ] <= origin[ 1 ] + 15.5f && - e1->absmin[ 0 ] <= origin[ 2 ] + 94.0f && - origin[ 0 ] - 15.5f <= e1->absmax[ 0 ] && - origin[ 1 ] - 15.5f <= e1->absmax[ 1 ] && - origin[ 2 ] + 0.0f <= e1->absmax[ 2 ]; + int j; + pathway_t child = Child[i]; + + for (j = i - 1; j >= numChildren; j--) { + Child[j + 1] = Child[j]; + } + + Child[numChildren] = child; + numChildren++; } -void PathNode::SetNodeFlags - ( - Event *ev - ) +void PathNode::DisconnectChild(int i) { - nodeflags = ev->GetInteger( 1 ); + int j; + pathway_t child = Child[i]; + + for (j = i + 1; j < numChildren; j++) { + Child[j - 1] = Child[j]; + } + + numChildren--; + Child[numChildren] = child; } -void PathNode::IsTouching - ( - Event *ev - ) +qboolean PathNode::IsTouching(Entity *e1) { - Entity *ent = ev->GetEntity( 1 ); - - if( !ent ) - { - ScriptError( "IsTouching used with a NULL entity.\n" ); - } - - ev->AddInteger( IsTouching( ev->GetEntity( 1 ) ) ); + return e1->absmin[0] <= origin[0] + 15.5f && e1->absmin[1] <= origin[1] + 15.5f + && e1->absmin[0] <= origin[2] + 94.0f && origin[0] - 15.5f <= e1->absmax[0] + && origin[1] - 15.5f <= e1->absmax[1] && origin[2] + 0.0f <= e1->absmax[2]; } -void PathNode::Remove - ( - Event *ev - ) +void PathNode::IsTouching(Event *ev) { - // Pathnodes mustn't be removed - ScriptError( "Not allowed to delete a path node" ); + Entity *ent = ev->GetEntity(1); + + if (!ent) { + ScriptError("IsTouching used with a NULL entity.\n"); + } + + ev->AddInteger(IsTouching(ev->GetEntity(1))); } -void PathNode::setOriginEvent - ( - Vector org - ) +void PathNode::setOriginEvent(Vector org) { - if( !PathManager.m_bNodesloaded ) - { - origin = org; - centroid = org; - } + if (!PathManager.m_bNodesloaded) { + origin = org; + centroid = org; + } } -void PathNode::Archive - ( - Archiver &arc - ) +void PathNode::DrawConnections(void) { + int i; + pathway_t *path; + PathNode *node; + + for (i = 0; i < numChildren; i++) { + path = &Child[i]; + node = PathSearch::pathnodes[path->node]; + if (!node) { + continue; + } + + G_DebugLine(origin + Vector("0 0 24"), node->origin + Vector("0 0 24"), 0.7f, 0.7f, 0, 1); + } } -void PathNode::ArchiveDynamic - ( - Archiver &arc - ) +static void droptofloor(Vector& vec, PathNode *node) { - SimpleEntity::SimpleArchive( arc ); + Vector start, end; + trace_t trace; - arc.ArchiveObjectPosition( this ); - arc.ArchiveSafePointer( &pLastClaimer ); - arc.ArchiveInteger( &iAvailableTime ); - arc.ArchiveInteger( &numChildren ); + start = vec; + start[2] += 36; + end = start; + end[2] -= 2048; - if( numChildren != virtualNumChildren ) - { - for( int i = 0; i < virtualNumChildren; i++ ) - { - arc.ArchiveByte( &Child[ i ].numBlockers ); - arc.ArchiveShort( &Child[ i ].node ); - arc.ArchiveShort( &Child[ i ].fallheight ); - arc.ArchiveFloat( &Child[ i ].dist ); - arc.ArchiveVec2( Child[ i ].dir ); - arc.ArchiveVec3( Child[ i ].pos1 ); - arc.ArchiveVec3( Child[ i ].pos2 ); - } - } + trace = G_Trace(start, PLAYER_BASE_MIN, PLAYER_BASE_MAX, end, NULL, MASK_PATHSOLID, qfalse, "droptofloor"); + vec.z = trace.endpos[2]; } -void PathNode::ArchiveStatic - ( - Archiver &arc - ) +static bool IsValidPathnode(int spawnflags) { - arc.ArchiveVector( &origin ); - arc.ArchiveVector( ¢roid ); - arc.ArchiveInteger( &nodeflags ); - arc.ArchiveInteger( &virtualNumChildren ); + if ((spawnflags & AI_DUCK) + && (spawnflags & (AI_CONCEALMENT | AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE))) { + return false; + } - numChildren = virtualNumChildren; + if ((spawnflags & AI_CONCEALMENT) && (spawnflags & (AI_COVER | AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER))) { + return false; + } - if( arc.Loading() ) - { - bulkNavMemory -= virtualNumChildren * sizeof( pathway_t ) * sizeof( pathway_t * ); - Child = virtualNumChildren ? ( pathway_t * )bulkNavMemory : NULL; - } + if ((spawnflags & AI_CORNER_LEFT) + && (spawnflags & (AI_DUCK | AI_CONCEALMENT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE))) { + return false; + } - for( int i = 0; i < virtualNumChildren; i++ ) - { - arc.ArchiveShort( &Child[ i ].node ); - arc.ArchiveShort( &Child[ i ].fallheight ); - arc.ArchiveFloat( &Child[ i ].dist ); - arc.ArchiveVec2( Child[ i ].dir ); - arc.ArchiveVec3( Child[ i ].pos1 ); - arc.ArchiveVec3( Child[ i ].pos2 ); + if ((spawnflags & AI_CORNER_RIGHT) + && (spawnflags & (AI_DUCK | AI_CONCEALMENT | AI_CORNER_LEFT | AI_SNIPER | AI_CRATE))) { + return false; + } - if( arc.Loading() ) - Child[ i ].numBlockers = 0; - } + if ((spawnflags & AI_SNIPER) + && (spawnflags & (AI_DUCK | AI_COVER | AI_CONCEALMENT | AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_CRATE))) { + return false; + } + + if ((spawnflags & AI_CRATE) + && (spawnflags & (AI_DUCK | AI_CONCEALMENT | AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER))) { + return false; + } + + return true; } -void PathNode::ConnectChild - ( - int i - ) +static void GetPathnodeColor(int spawnflags, vec3_t color) { - int j; - pathway_t child = Child[ i ]; + if (!IsValidPathnode(spawnflags)) { + VectorCopy(COLOR_PATHNODE_ERROR, color); + return; + } - for( j = i - 1; j >= numChildren; j-- ) - { - Child[ j + 1 ] = Child[ j ]; - } - - Child[ numChildren ] = child; - numChildren++; + if (spawnflags & AI_CORNER_LEFT) { + VectorCopy(COLOR_PATHNODE_CORNER_LEFT, color); + } else if (spawnflags & AI_CORNER_RIGHT) { + VectorCopy(COLOR_PATHNODE_CORNER_RIGHT, color); + } else if (spawnflags & AI_DUCK) { + VectorCopy(COLOR_PATHNODE_DUCK, color); + } else if (spawnflags & AI_SNIPER) { + VectorCopy(COLOR_PATHNODE_SNIPER, color); + } else if (spawnflags & AI_CONCEALMENT) { + VectorCopy(COLOR_PATHNODE_CONCEALMENT, color); + } else if (spawnflags & AI_COVER) { + VectorCopy(COLOR_PATHNODE_COVER, color); + } else if (spawnflags & AI_CRATE) { + VectorCopy(COLOR_PATHNODE_CRATE, color); + } else { + VectorCopy(COLOR_PATHNODE_DEFAULT, color); + } } -void PathNode::DisconnectChild - ( - int i - ) +static int GetNodeTypeFromName(const char *name) { - int j; - pathway_t child = Child[ i ]; + if (!str::icmp(name, "corner_left")) { + return AI_CORNER_LEFT; + } else if (!str::icmp(name, "corner_right")) { + return AI_CORNER_RIGHT; + } else if (!str::icmp(name, "duck")) { + return AI_DUCK; + } else if (!str::icmp(name, "sniper")) { + return AI_SNIPER; + } else if (!str::icmp(name, "concealment")) { + return AI_CONCEALMENT; + } else if (!str::icmp(name, "cover")) { + return AI_COVER; + } else if (!str::icmp(name, "crate")) { + return AI_CRATE; + } else if (!str::icmp(name, "none")) { + return 0; + } - for( j = i + 1; j < numChildren; j++ ) - { - Child[ j - 1 ] = Child[ j ]; - } - - numChildren--; - Child[ numChildren ] = child; + return -1; } -void PathNode::ConnectTo - ( - PathNode *node - ) +void DrawNode(int iNodeCount) { - Child[ virtualNumChildren ].node = nodenum; - Child[ virtualNumChildren ].numBlockers = 0; - virtualNumChildren++; - numChildren++; + Vector down; + Vector up; + Vector dir; + Vector p1; + Vector p2; + Vector p3; + Vector p4; + Vector q1; + Vector q2; + Vector q3; + Vector q4; + Vector playerorigin; + Vector aStart; + Vector aEnd; + PathNode *node; + PathNode *nodelist[MAX_PATHNODES]; + Vector end; + Vector start; + Vector p; + vec3_t color; + + playerorigin = g_entities[0].client->ps.origin; + + if (iNodeCount > MAX_PATHNODES) { + iNodeCount = MAX_PATHNODES; + } + + if (ai_showallnode->integer) { + iNodeCount = PathSearch::DebugNearestNodeList2(playerorigin, nodelist, iNodeCount); + } else { + iNodeCount = PathSearch::DebugNearestNodeList(playerorigin, nodelist, iNodeCount); + } + + if (iNodeCount) { + for (int i = 0; i < iNodeCount; i++) { + node = nodelist[i]; + GetPathnodeColor(node->nodeflags, color); + + p1.x = PLAYER_BASE_MAX.x + node->origin.x; + p1.y = PLAYER_BASE_MAX.y + node->origin.y; + + p2.x = PLAYER_BASE_MAX.x + node->origin.x; + p2.y = PLAYER_BASE_MIN.y + node->origin.y; + + p3.x = PLAYER_BASE_MIN.x + node->origin.x; + p3.y = PLAYER_BASE_MIN.y + node->origin.y; + + p4.x = PLAYER_BASE_MIN.x + node->origin.x; + p4.y = PLAYER_BASE_MAX.y + node->origin.y; + + start = node->origin + Vector(0, 0, 18); + end = node->origin + Vector(0, 0, 18); + + aStart = start; + aEnd[0] = node->origin[0] + cos(M_PI / 180.0f * node->angles[1]) * 16.0f; + aEnd[1] = node->origin[1] + sin(M_PI / 180.0f * node->angles[1]) * 16.0f; + aEnd[2] = end[2]; + + G_DebugLine(aStart, aEnd, 1, 1, 1, 1); + + p1.z = node->origin.z + 36.0f; + p2.z = node->origin.z + 36.0f; + p3.z = node->origin.z + 36.0f; + p4.z = node->origin.z + 36.0f; + + G_DebugLine(p1, p2, color[0], color[1], color[2], 1); + G_DebugLine(p2, p3, color[0], color[1], color[2], 1); + G_DebugLine(p3, p4, color[0], color[1], color[2], 1); + G_DebugLine(p4, p1, color[0], color[1], color[2], 1); + + q1 = p1; + q2 = p2; + q3 = p3; + q4 = p4; + + q1.z = node->origin.z; + q2.z = node->origin.z; + q3.z = node->origin.z; + q4.z = node->origin.z; + + G_DebugLine(q1, q2, color[0], color[1], color[2], 1); + G_DebugLine(q2, q3, color[0], color[1], color[2], 1); + G_DebugLine(q3, q4, color[0], color[1], color[2], 1); + G_DebugLine(q4, q1, color[0], color[1], color[2], 1); + + G_DebugLine(p1, q1, color[0], color[1], color[2], 1); + G_DebugLine(p2, q2, color[0], color[1], color[2], 1); + G_DebugLine(p3, q3, color[0], color[1], color[2], 1); + G_DebugLine(p4, q4, color[0], color[1], color[2], 1); + } + } else { + G_DebugCircle(playerorigin + Vector(0, 0, 48), 128, 1, 0, 0, 1, true); + } } -bool PathNode::CheckPathTo - ( - PathNode *node - ) +void DrawAllConnections(void) { - - if( virtualNumChildren < NUM_PATHSPERNODE ) - { - CheckPathToDefault( node, &Child[ virtualNumChildren ] ); - return true; - } - else - { - Com_Printf( "^~^~^ %d paths per node at (%.2f %.2f %.2f) exceeded\n - use DONT_LINK on some nodes to conserve cpu and memory usage\n", NUM_PATHSPERNODE, node->origin[ 0 ], node->origin[ 1 ], node->origin[ 2 ] ); - PathSearch::m_NodeCheckFailed = true; - return false; - } -} - -void PathNode::CheckPathToDefault - ( - PathNode *node, - pathway_t *pathway - ) -{ - float dist; - float delta[ 2 ]; - Vector start; - Vector end; - - delta[ 0 ] = node->origin[ 0 ] - origin[ 0 ]; - delta[ 1 ] = node->origin[ 1 ] - origin[ 1 ]; - - dist = VectorNormalize2D( delta ); - - if( dist >= 384.0f ) - return; - - start = origin + Vector( 0, 0, 36.0f ); - end = start - Vector( 0, 0, 2048.0f ); - - trace_t trace = G_Trace( - start, - PLAYER_BASE_MIN, - PLAYER_BASE_MAX, - end, - NULL, - MASK_PATHSOLID, - qfalse, - "droptofloor" ); - - start = node->origin + Vector( 0, 0, 36.0f ); - end = start - Vector( 0, 0, 2048.0f ); - - trace_t trace2 = G_Trace( - start, - PLAYER_BASE_MIN, - PLAYER_BASE_MAX, - end, - NULL, - MASK_PATHSOLID, - qfalse, - "droptofloor" ); - - start = trace.endpos; - end = trace2.endpos; - - if( CheckMove( start, end, &pathway->fallheight, 15.5f ) ) - { - pathway->dist = dist; - pathway->dir[ 0 ] = delta[ 0 ]; - pathway->dir[ 1 ] = delta[ 1 ]; - VectorCopy( start, pathway->pos1 ); - VectorCopy( end, pathway->pos2 ); - Child[ virtualNumChildren ].node = node->nodenum; - Child[ virtualNumChildren ].numBlockers = 0; - - virtualNumChildren++; - numChildren++; - } -} - -void PathNode::MarkTemporarilyBad - ( - void - ) -{ - iAvailableTime = level.inttime + 5000; - pLastClaimer = NULL; -} - -void PathNode::Relinquish - ( - void - ) -{ - iAvailableTime = level.inttime + 4000; -} - -void PathNode::DrawConnections - ( - void - ) -{ - int i; - pathway_t *path; - PathNode *node; - - for( i = 0; i < numChildren; i++ ) - { - path = &Child[ i ]; - node = PathSearch::pathnodes[ path->node ]; - - G_DebugLine( origin + Vector( "0 0 24" ), node->origin + Vector( "0 0 24" ), 0.7f, 0.7f, 0, 1 ); - } -} - -static bool IsValidPathnode - ( - int spawnflags - ) -{ - if( ( spawnflags & AI_DUCK ) && ( spawnflags & AI_COVERFLAGS2 ) ) - return false; - - if( ( spawnflags & AI_CONCEALMENT ) && ( spawnflags & AI_SNIPERFLAGS ) ) - return false; - - if( ( spawnflags & AI_CORNER_LEFT ) && ( spawnflags & AI_COVER_LEFT_FLAGS ) ) - return false; - - if( ( spawnflags & AI_CORNER_RIGHT ) && ( spawnflags & AI_COVER_RIGHT_FLAGS ) ) - return false; - - if( ( spawnflags & AI_SNIPER ) && ( spawnflags & AI_CRATEFLAGS ) ) - return false; - - if( ( spawnflags & AI_ALL ) && ( spawnflags & AI_COVERFLAGS3 ) ) - return false; - - return true; -} - -static void GetPathnodeColor - ( - int spawnflags, - vec3_t color - ) -{ - if( IsValidPathnode( spawnflags ) ) - { - if( spawnflags & AI_CORNER_LEFT ) - { - VectorCopy( COLOR_PATHNODE_CORNER_LEFT, color ); - } - else if( spawnflags & AI_CORNER_RIGHT ) - { - VectorCopy( COLOR_PATHNODE_CORNER_RIGHT, color ); - } - else if( spawnflags & AI_DUCK ) - { - VectorCopy( COLOR_PATHNODE_DUCK, color ); - } - else if( spawnflags & AI_SNIPER ) - { - VectorCopy( COLOR_PATHNODE_SNIPER, color ); - } - else if( spawnflags & AI_CONCEALMENT ) - { - VectorCopy( COLOR_PATHNODE_CONCEALMENT, color ); - } - else if( spawnflags & AI_COVER ) - { - VectorCopy( COLOR_PATHNODE_COVER, color ); - } - else if( spawnflags & AI_CRATE ) - { - VectorCopy( COLOR_PATHNODE_CRATE, color ); - } - else - { - VectorCopy( COLOR_PATHNODE_DEFAULT, color ); - } - } - else - { - VectorCopy( COLOR_PATHNODE_ERROR, color ); - } -} - -void DrawNode - ( - int iNodeCount - ) -{ - Vector down; - Vector up; - Vector dir; - Vector p1; - Vector p2; - Vector p3; - Vector p4; - Vector q1; - Vector q2; - Vector q3; - Vector q4; - Vector playerorigin; - Vector aStart; - Vector aEnd; - PathNode *node; - PathNode *nodelist[ 4096 ]; - Vector end; - Vector start; - Vector p; - vec3_t color; - - playerorigin = g_entities[ 0 ].client->ps.origin; - - if( iNodeCount > 4096 ) - iNodeCount = 4096; - - if( ai_showallnode->integer ) - iNodeCount = PathSearch::DebugNearestNodeList2( playerorigin, nodelist, iNodeCount ); - else - iNodeCount = PathSearch::DebugNearestNodeList( playerorigin, nodelist, iNodeCount ); - - if( iNodeCount ) - { - for( int i = 0; i < iNodeCount; i++ ) - { - node = nodelist[ i ]; - GetPathnodeColor( node->nodeflags, color ); - - p1.x = PLAYER_BASE_MAX.x + node->origin.x; - p1.y = PLAYER_BASE_MAX.y + node->origin.y; - - p2.x = PLAYER_BASE_MAX.x + node->origin.x; - p2.y = PLAYER_BASE_MIN.y + node->origin.y; - - p3.x = PLAYER_BASE_MIN.x + node->origin.x; - p3.y = PLAYER_BASE_MIN.y + node->origin.y; - - p4.x = PLAYER_BASE_MIN.x + node->origin.x; - p4.y = PLAYER_BASE_MAX.y + node->origin.y; - - start = node->origin + Vector( 0, 0, 18 ); - end = node->origin + Vector( 0, 0, 18 ); - - aStart = start; - aEnd[ 0 ] = node->origin[ 0 ] + cos( M_PI / 180.0f * node->angles[ 1 ] ) * 16.0f; - aEnd[ 1 ] = node->origin[ 1 ] + sin( M_PI / 180.0f * node->angles[ 1 ] ) * 16.0f; - aEnd[ 2 ] = end[ 2 ]; - - G_DebugLine( aStart, aEnd, 1, 1, 1, 1 ); - - p1.z = node->origin.z + 36.0f; - p2.z = node->origin.z + 36.0f; - p3.z = node->origin.z + 36.0f; - p4.z = node->origin.z + 36.0f; - - G_DebugLine( p1, p2, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( p2, p3, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( p3, p4, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( p4, p1, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - - q1 = p1; - q2 = p2; - q3 = p3; - q4 = p4; - - q1.z = node->origin.z; - q2.z = node->origin.z; - q3.z = node->origin.z; - q4.z = node->origin.z; - - G_DebugLine( q1, q2, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( q2, q3, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( q3, q4, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( q4, q1, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - - G_DebugLine( p1, q1, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( p2, q2, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( p3, q3, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - G_DebugLine( p4, q4, color[ 0 ], color[ 1 ], color[ 2 ], 1 ); - } - } - else - { - G_DebugCircle( playerorigin + Vector( 0, 0, 48 ), 128, 1, 0, 0, 1, true ); - } -} - -void DrawAllConnections - ( - void - ) -{ - pathway_t *path; - pathway_t *path2; - PathNode *node; - PathNode *to; - Vector down; - Vector up; - Vector dir; - Vector p1; - Vector p2; - Vector p3; - Vector p4; - Vector playerorigin; - qboolean showroutes; - qboolean shownums; - bool reverse; - - showroutes = ( ai_showroutes->integer != 0 ); - shownums = ( ai_shownodenums->integer != 0 ); - - // Figure out where the camera is - - if( !g_entities[ 0 ].client ) - return; - - playerorigin.x = g_entities[ 0 ].client->ps.origin[ 0 ]; - playerorigin.y = g_entities[ 0 ].client->ps.origin[ 1 ]; - playerorigin.z = g_entities[ 0 ].client->ps.origin[ 2 ]; - - playerorigin[ 2 ] += g_entities[ 0 ].client->ps.viewheight; - - for( int i = 0; i < PathSearch::nodecount; i++ ) - { - node = PathSearch::pathnodes[ i ]; - - if( Vector( node->origin - playerorigin ).length() > ai_showroutes_distance->integer ) - { - continue; - } - - if( shownums ) - { - G_DrawDebugNumber( node->origin + Vector( 0, 0, 14 ), node->nodenum, 1.5, 1, 1, 0 ); - } - - for( int j = 0; j < node->numChildren; j++ ) - { - path = &node->Child[ j ]; - - if( path->fallheight > ai_fallheight->integer ) - continue; - - reverse = false; - to = PathSearch::pathnodes[ path->node ]; - - for( int k = to->numChildren - 1; k >= 0; k-- ) - { - path2 = &to->Child[ k ]; - - if( path2->fallheight < ai_fallheight->integer && PathSearch::pathnodes[ path2->node ] == node ) - { - reverse = true; - break; - } - } - - p1 = path->pos1 + Vector( 0, 0, 36 ); - p2 = path->pos2 + Vector( 0, 0, 36 ); - - if( node->nodenum < to->nodenum || !reverse ) - { - // draw connected lines in green - G_DebugLine( p1, p2, 0, 1, 0, 1 ); - - if( !reverse ) - { - dir = Vector( path->pos2 ) - Vector( path->pos1 ); - dir.z = 0; - VectorNormalize( dir ); - - p3 = dir * 8.0f + dir * 8.0f; - p4 = dir * 8.0f; - p4.z += 8.0f; - - G_DebugLine( p1 + p3 + up , p1 + p3 + up - p4, 1, 0, 0, 1 ); - - p4.z -= 16.0f; - - G_DebugLine( p1 + p3 + down, p1 + p3 + down - p4, 1, 0, 0, 1 ); - } - } - } - - if( !node->numChildren ) - { - // Put a little X where the node is to show that it had no connections - p1 = node->origin; - p1.z += 2; - - if( node->nodeflags & PATH_DONT_LINK ) - { - G_DebugCircle( p1, 12, 0, 0, 1, 1, true ); - } - else - { - p2 = Vector( 12, 12, 0 ); - G_DebugLine( p1 - p2, p1 + p2, 1, 0, 0, 1 ); - - p2.x = -12; - G_DebugLine( p1 - p2, p1 + p2, 1, 0, 0, 1 ); - } - } - } + pathway_t *path; + pathway_t *path2; + PathNode *node; + PathNode *to; + Vector down; + Vector up; + Vector dir; + Vector p1; + Vector p2; + Vector p3; + Vector p4; + Vector playerorigin; + qboolean showroutes; + qboolean shownums; + bool reverse; + + showroutes = (ai_showroutes->integer != 0); + shownums = (ai_shownodenums->integer != 0); + + // Figure out where the camera is + + if (!g_entities[0].client) { + return; + } + + playerorigin.x = g_entities[0].client->ps.origin[0]; + playerorigin.y = g_entities[0].client->ps.origin[1]; + playerorigin.z = g_entities[0].client->ps.origin[2]; + + playerorigin[2] += g_entities[0].client->ps.viewheight; + + for (int i = 0; i < PathSearch::nodecount; i++) { + node = PathSearch::pathnodes[i]; + if (!node) { + continue; + } + + if (Vector(node->origin - playerorigin).length() > ai_showroutes_distance->integer) { + continue; + } + + if (shownums) { + G_DrawDebugNumber(node->origin + Vector(0, 0, 14), node->nodenum, 1.5, 1, 1, 0); + } + + for (int j = 0; j < node->numChildren; j++) { + path = &node->Child[j]; + + if (path->fallheight > ai_fallheight->integer) { + continue; + } + + reverse = false; + + to = PathSearch::pathnodes[path->node]; + if (!to) { + continue; + } + + for (int k = to->numChildren - 1; k >= 0; k--) { + path2 = &to->Child[k]; + + if (path2->fallheight < ai_fallheight->integer && PathSearch::pathnodes[path2->node] == node) { + reverse = true; + break; + } + } + + p1 = path->pos1 + Vector(0, 0, 36); + p2 = path->pos2 + Vector(0, 0, 36); + + if (node->nodenum < to->nodenum || !reverse) { + // draw connected lines in green + G_DebugLine(p1, p2, 0, 1, 0, 1); + + if (!reverse) { + dir = Vector(path->pos2) - Vector(path->pos1); + dir.z = 0; + VectorNormalize(dir); + + p3 = dir * 8.0f + dir * 8.0f; + p4 = dir * 8.0f; + p4.z += 8.0f; + + G_DebugLine(p1 + p3 + up, p1 + p3 + up - p4, 1, 0, 0, 1); + + p4.z -= 16.0f; + + G_DebugLine(p1 + p3 + down, p1 + p3 + down - p4, 1, 0, 0, 1); + } + } + } + + if (!node->numChildren) { + // Put a little X where the node is to show that it had no connections + p1 = node->origin; + p1.z += 2; + + if (node->nodeflags & PATH_DONT_LINK) { + G_DebugCircle(p1, 12, 0, 0, 1, 1, true); + } else { + p2 = Vector(12, 12, 0); + G_DebugLine(p1 - p2, p1 + p2, 1, 0, 0, 1); + + p2.x = -12; + G_DebugLine(p1 - p2, p1 + p2, 1, 0, 0, 1); + } + } + } } MapCell::MapCell() { - numnodes = 0; - nodes = NULL; + numnodes = 0; + nodes = NULL; } -MapCell::~MapCell() +int MapCell::NumNodes(void) { - numnodes = 0; - nodes = NULL; + return numnodes; } -qboolean MapCell::AddNode - ( - PathNode *node - ) -{ - nodes[ numnodes ] = ( short )node->nodenum; - numnodes++; - - return true; -} - -int MapCell::NumNodes - ( - void - ) -{ - return numnodes; -} - /* All work and no play @@ -1122,2724 +1803,2084 @@ int MapCell::NumNodes Jim a */ -CLASS_DECLARATION( Class, PathSearch, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(Class, PathSearch, NULL) { + {NULL, NULL} }; - PathSearch::PathSearch() { - memset( pathnodes, 0, sizeof( pathnodes ) ); - open = 0; - findFrame = 0; + memset(pathnodes, 0, sizeof(pathnodes)); + open = 0; + findFrame = 0; } PathSearch::~PathSearch() { - ResetNodes(); + ResetNodes(); } -void PathSearch::AddToGrid - ( - PathNode *node, - int x, - int y - ) +void PathSearch::LoadAddToGrid(int x, int y) { - MapCell *cell; + MapCell *cell; - if( x > PATHMAP_GRIDSIZE || y > PATHMAP_GRIDSIZE ) - cell = NULL; - else - cell = &PathMap[ x ][ y ]; - - if( !cell ) - return; - - if( cell->NumNodes() >= PATHMAP_NODES ) - Com_Printf( "^~^~^ PathSearch::AddToGrid: Node overflow at ( %d, %d )\n", x, y ); - else - cell->AddNode( node ); + cell = GetNodesInCell(x, y); + if (cell) { + cell->numnodes++; + } } -int PathSearch::NodeCoordinate - ( - float coord - ) +int PathSearch::NodeCoordinate(float coord) { - float c; + float c; - //return ( ( int )coord + MAX_MAP_BOUNDS - ( PATHMAP_CELLSIZE / 2 ) ) / PATHMAP_CELLSIZE; + //return ( ( int )coord + MAX_MAP_BOUNDS - ( PATHMAP_CELLSIZE / 2 ) ) / PATHMAP_CELLSIZE; - c = coord + MAX_MAP_BOUNDS - ( PATHMAP_CELLSIZE / 2 ); + c = coord + MAX_MAP_BOUNDS - (PATHMAP_CELLSIZE / 2); - if( c < 0 ) - c = coord + MAX_MAP_BOUNDS + ( PATHMAP_CELLSIZE / 2 ) - 1; + if (c < 0) { + c = coord + MAX_MAP_BOUNDS + (PATHMAP_CELLSIZE / 2) - 1; + } - return ( int )c >> 8; + return (int)c >> 8; } -int PathSearch::GridCoordinate - ( - float coord - ) +int PathSearch::GridCoordinate(float coord) { - float c; + float c; - //return ( ( int )coord + MAX_MAP_BOUNDS ) / PATHMAP_CELLSIZE; + //return ( ( int )coord + MAX_MAP_BOUNDS ) / PATHMAP_CELLSIZE; - c = coord + MAX_MAP_BOUNDS; + c = coord + MAX_MAP_BOUNDS; - if( c < 0 ) - c = coord + MAX_MAP_BOUNDS + PATHMAP_CELLSIZE - 1; + if (c < 0) { + c = coord + MAX_MAP_BOUNDS + PATHMAP_CELLSIZE - 1; + } - return ( int )c >> 8; + return (int)c >> 8; } -void PathSearch::AddNode - ( - PathNode *node - ) +MapCell *PathSearch::GetNodesInCell(int x, int y) { - int x; - int y; + if ((x < 0) || (x >= PATHMAP_GRIDSIZE) || (y < 0) || (y >= PATHMAP_GRIDSIZE)) { + return NULL; + } - assert( node ); - - x = NodeCoordinate( node->origin[ 0 ] ); - y = NodeCoordinate( node->origin[ 1 ] ); - - AddToGrid( node, x, y ); - AddToGrid( node, x + 1, y ); - AddToGrid( node, x, y + 1 ); - AddToGrid( node, x + 1, y + 1 ); + return &PathMap[x][y]; } -void PathSearch::LoadAddToGrid - ( - int x, - int y - ) +MapCell *PathSearch::GetNodesInCell(const vec3_t pos) { - MapCell *cell; + int x; + int y; - if( x > PATHMAP_GRIDSIZE || y > PATHMAP_GRIDSIZE ) - cell = NULL; - else - cell = &PathMap[ x ][ y ]; + x = GridCoordinate(pos[0]); + y = GridCoordinate(pos[1]); - if( cell ) - cell->numnodes++; + return GetNodesInCell(x, y); } -void PathSearch::LoadAddToGrid2 - ( - PathNode *node, - int x, - int y - ) +int PathSearch::DebugNearestNodeList(const vec3_t pos, PathNode **nodelist, int iMaxNodes) { - MapCell *cell; + PathNode *node; + int i; + MapCell *cell; + int nodes[128]; + vec3_t deltas[128]; + vec3_t start; + vec3_t end; - if( x > PATHMAP_GRIDSIZE || y > PATHMAP_GRIDSIZE ) - cell = NULL; - else - cell = &PathMap[ x ][ y ]; + cell = GetNodesInCell(pos); - if( cell ) - cell->AddNode( node ); + if (!cell) { + return 0; + } + + int node_count = NearestNodeSetup(pos, cell, nodes, deltas); + int n = 0; + + for (i = 0; i < node_count && n < iMaxNodes; i++) { + node = pathnodes[cell->nodes[nodes[i]]]; + if (!node) { + continue; + } + + VectorCopy(pos, start); + VectorCopy(pos, end); + + VectorAdd(end, deltas[i], end); + + Vector vStart = start; + Vector vMins = Vector(-15, -15, 0); + Vector vMaxs = Vector(15, 15, 62); + Vector vEnd = end; + + if (G_SightTrace( + vStart, + vMins, + vMaxs, + vEnd, + (gentity_t *)NULL, + (gentity_t *)NULL, + MASK_PATHSOLID, + qtrue, + "PathSearch::DebugNearestNodeList" + )) { + nodelist[n] = node; + n++; + } + } + + if (!n && node_count) { + nodelist[0] = pathnodes[cell->nodes[nodes[0]]]; + return 1; + } else { + return n; + } + + return 0; } -MapCell *PathSearch::GetNodesInCell - ( - int x, - int y - ) +int PathSearch::DebugNearestNodeList2(const vec3_t pos, PathNode **nodelist, int iMaxNodes) { - if( ( x < 0 ) || ( x >= PATHMAP_GRIDSIZE ) || ( y < 0 ) || ( y >= PATHMAP_GRIDSIZE ) ) - { - return NULL; - } + vec3_t delta; + PathNode *node; + float dist; + int n = 0; + int i; + int j; + static float node_dist[MAX_PATHNODES]; + int node_count; - return &PathMap[ x ][ y ]; + node_count = nodecount; + + for (i = 0; i < node_count; i++) { + node = pathnodes[i]; + if (!node) { + continue; + } + + if (pos[2] > node->origin[2] + 94.0f) { + continue; + } + + if (node->origin[2] > pos[2] + 94.0f) { + continue; + } + + delta[0] = node->origin[0] - pos[0]; + delta[1] = node->origin[1] - pos[1]; + delta[2] = node->origin[2] - pos[2]; + + dist = VectorLengthSquared(delta); + + for (j = n; j > 0; j--) { + if (dist >= node_dist[j - 1]) { + break; + } + + node_dist[j] = node_dist[j - 1]; + nodelist[j] = nodelist[j - 1]; + } + + n++; + nodelist[j] = node; + node_dist[j] = dist; + } + + return n; } -MapCell *PathSearch::GetNodesInCell - ( - float *pos - ) +PathNode *PathSearch::DebugNearestStartNode(const vec3_t pos, Entity *ent) { - int x; - int y; + PathNode *node = NULL; + int i; + MapCell *cell; + int nodes[128]; + vec3_t deltas[128]; + vec3_t start; + vec3_t end; + int node_count; - x = GridCoordinate( pos[ 0 ] ); - y = GridCoordinate( pos[ 1 ] ); + cell = GetNodesInCell(pos); - return GetNodesInCell( x, y ); + if (!cell) { + return NULL; + } + + node_count = NearestNodeSetup(pos, cell, nodes, deltas); + + VectorCopy(pos, start); + start[2] += 32.0f; + + for (i = 0; i < node_count; i++) { + node = pathnodes[cell->nodes[nodes[i]]]; + if (!node) { + continue; + } + + VectorCopy(start, end); + VectorAdd(end, deltas[nodes[i]], end); + + if (G_SightTrace( + start, + Vector(-15, -15, 0), + Vector(15, 15, 62), + end, + ent, + NULL, + MASK_TARGETPATH, + qtrue, + "PathSearch::DebugNearestStartNode" + )) { + return node; + } + } + + if (node_count > 0) { + return pathnodes[cell->nodes[nodes[0]]]; + } + + return NULL; } - -PathNode *PathSearch::DebugNearestStartNode - ( - float *pos, - Entity *ent - ) +PathNode *PathSearch::NearestStartNode(const vec3_t pos, SimpleActor *ent) { - PathNode *node = NULL; - int i; - MapCell *cell; - int nodes[ 128 ]; - vec3_t deltas[ 128 ]; - vec3_t start; - vec3_t end; + PathNode *node = NULL; + int i; + MapCell *cell; + int nodes[128]; + vec3_t deltas[128]; + vec3_t start; + vec3_t end; + int node_count; - cell = GetNodesInCell( pos ); + cell = GetNodesInCell(pos); - if( !cell ) - return NULL; + if (!cell) { + return NULL; + } - int node_count = NearestNodeSetup( pos, cell, nodes, deltas ); + node_count = NearestNodeSetup(pos, cell, nodes, deltas); - if( !node_count ) - return NULL; + VectorCopy(pos, start); + start[2] += 32.0f; - VectorCopy( pos, start ); - start[ 2 ] += 32.0f; + for (i = 0; i < node_count; i++) { + node = pathnodes[cell->nodes[nodes[i]]]; + if (!node) { + continue; + } - for( i = 0; i < node_count; i++ ) - { - node = pathnodes[ cell->nodes[ nodes[ i ] ] ]; + VectorAdd(start, deltas[nodes[i]], end); - VectorCopy( start, end ); - VectorAdd( end, deltas[ nodes[ i ] ], end ); + if (G_SightTrace( + start, + Vector(-15, -15, 0), + Vector(15, 15, 62), + end, + ent, + NULL, + MASK_PATHSOLID, + qtrue, + "PathSearch::NearestStartNode 1" + )) { + ent->m_NearestNode = node; + VectorCopy(end, ent->m_vNearestNodePos); + return node; + } + } - Vector vStart = start; - Vector vMins = Vector( -15, -15, 0 ); - Vector vMaxs = Vector( 15, 15, 62 ); - Vector vEnd = end; + if (ent->m_NearestNode) { + if (G_SightTrace( + start, + Vector(-15, -15, 0), + Vector(15, 15, 62), + ent->m_vNearestNodePos, + ent, + NULL, + MASK_TARGETPATH, + qtrue, + "PathSearch::NearestStartNode 2" + )) { + return ent->m_NearestNode; + } + } - if( G_SightTrace( - vStart, - vMins, - vMaxs, - vEnd, - ent, - NULL, - MASK_TARGETPATH, - qtrue, - "PathSearch::DebugNearestStartNode" ) ) - { - return node; - } - } + if (node_count > 0) { + return pathnodes[cell->nodes[nodes[0]]]; + } - return pathnodes[ cell->nodes[ nodes[ 0 ] ] ]; + return ent->m_NearestNode; } -PathNode *PathSearch::NearestStartNode - ( - float *pos, - SimpleActor *ent - ) +PathNode *PathSearch::NearestEndNode(const vec3_t pos) { - PathNode *node = NULL; - int i; - MapCell *cell; - int nodes[128]; - vec3_t deltas[128]; - vec3_t start; - vec3_t end; + PathNode *node = NULL; + int i; + MapCell *cell; + int nodes[128]; + vec3_t deltas[128]; + vec3_t start; + vec3_t end; + int node_count; - cell = GetNodesInCell(pos); + cell = GetNodesInCell(pos); - if (!cell) - return NULL; + if (!cell) { + return NULL; + } - int node_count = NearestNodeSetup(pos, cell, nodes, deltas); - int n = 0; - int j = 0; + node_count = NearestNodeSetup(pos, cell, nodes, deltas); - VectorCopy(pos, start); - start[2] += 32.0f; + VectorCopy(pos, start); + start[2] += 32.0f; - Vector vMins = Vector(-15, -15, 0); - Vector vMaxs = Vector(15, 15, 62); + for (i = 0; i < node_count; i++) { + node = pathnodes[cell->nodes[nodes[i]]]; + if (!node) { + continue; + } - for (i = 0; i < node_count; i++) - { - node = pathnodes[cell->nodes[nodes[i]]]; + VectorAdd(start, deltas[nodes[i]], end); - VectorAdd(start, deltas[nodes[i]], end); + if (G_SightTrace( + start, + Vector(-15, -15, 0), + Vector(15, 15, 62), + end, + (Entity *)nullptr, + (Entity *)nullptr, + MASK_TARGETPATH, + qtrue, + "PathSearch::NearestEndNode" + )) { + return node; + } + } - Vector vStart = start; - Vector vEnd = end; - - if (G_SightTrace( - vStart, - vMins, - vMaxs, - vEnd, - (gentity_t *)NULL, - (gentity_t *)NULL, - 1107437825, //FIXME: macro - qtrue, - "PathSearch::NearestStartNode 1")) - { - ent->m_NearestNode = node; - ent->m_vNearestNodePos = end; - return node; - } - } - - if ((ent->m_NearestNode && - (G_SightTrace( - Vector(start), - vMins, - vMaxs, - ent->m_vNearestNodePos, - (gentity_t*)ent, - (gentity_t*)NULL, - 1073883393, //FIXME: macro - qtrue, - "PathSearch::NearestStartNode 2"))) - || node_count <= 0 - ) - { - node = ent->m_NearestNode; - } - else - { - node = pathnodes[cell->nodes[nodes[0]]]; - } - - return node; + return NULL; } -PathNode *PathSearch::NearestEndNode - ( - float *pos - ) +void PathSearch::ShowNodes(void) { - PathNode *node = NULL; - int i; - MapCell *cell; - int nodes[ 128 ]; - vec3_t deltas[ 128 ]; - vec3_t start; - vec3_t end; + if (g_entities->client) { + if (ai_shownode->integer) { + DrawNode(ai_shownode->integer); + } + if (ai_showroutes->integer || ai_shownodenums->integer) { + DrawAllConnections(); + } + } - cell = GetNodesInCell( pos ); + if (ai_showpath->integer) { + if (!test_path) { + test_path = new ActorPath; + } - if( !cell ) - return NULL; + if (ai_showpath->integer == 1) { + ai_startpath = g_entities[0].entity->origin; + } + if (ai_showpath->integer == 2) { + ai_endpath = g_entities[0].entity->origin; + } + if (ai_showpath->integer <= 2) { + test_path->SetFallHeight(ai_fallheight->integer); + test_path->FindPath(ai_startpath, ai_endpath, NULL, 0, NULL, 0); + } + if (ai_showpath->integer == 3) { + if (test_path->CurrentNode()) { + test_path->UpdatePos(g_entities[0].entity->origin); - int node_count = NearestNodeSetup( pos, cell, nodes, deltas ); - int n = 0; - int j = 0; + Vector vStart = g_entities[0].entity->origin + Vector(0, 0, 32); + Vector vEnd = g_entities[0].entity->origin + test_path->CurrentDelta() + Vector(0, 0, 32); - if( !node_count ) - return NULL; + G_DebugLine(vStart, vEnd, 1, 1, 0, 1); + } + } - VectorCopy( pos, start ); - start[ 2 ] += 32.0f; + G_DebugLine(ai_startpath, ai_endpath, 0, 0, 1, 1); - for( i = 0; i < node_count; i++ ) - { - node = pathnodes[ cell->nodes[ nodes[ i ] ] ]; + if (test_path->CurrentNode()) { + PathInfo *pos = test_path->CurrentNode(); - VectorAdd(start, deltas[nodes[i]], end); + while (pos != test_path->LastNode()) { + Vector vStart = pos->point + Vector(0, 0, 32); - Vector vStart = start; - Vector vMins = Vector( -15, -15, 0 ); - Vector vMaxs = Vector( 15, 15, 62 ); - Vector vEnd = end; + pos--; - if( G_SightTrace( - vStart, - vMins, - vMaxs, - vEnd, - ( gentity_t * )NULL, - ( gentity_t * )NULL, - MASK_TARGETPATH, - qtrue, - "PathSearch::NearestEndNode" ) ) - { - return node; - } - } + Vector vEnd = pos->point + Vector(0, 0, 32); - return pathnodes[ cell->nodes[ nodes[ 0 ] ] ]; + G_DebugLine(vStart, vEnd, 1, 0, 0, 1); + } + } + } + + navMaster.Frame(); } -int PathSearch::DebugNearestNodeList - ( - float *pos, - PathNode **nodelist, - int iMaxNodes - ) +qboolean PathSearch::ArchiveSaveNodes(void) { - PathNode *node; - int i; - MapCell *cell; - int nodes[ 128 ]; - vec3_t deltas[ 128 ]; - vec3_t start; - vec3_t end; + Archiver arc; + str maptime; + int tempInt; - cell = GetNodesInCell( pos ); + if (!arc.Create(level.m_pathfile)) { + return qfalse; + } - if( !cell ) - return 0; + tempInt = PATHFILE_VERSION; + arc.ArchiveInteger(&tempInt); - int node_count = NearestNodeSetup( pos, cell, nodes, deltas ); - int n = 0; - int j = 0; + maptime = gi.MapTime(); + arc.ArchiveString(&maptime); - for( i = 0; i < node_count && j < iMaxNodes; i++ ) - { - node = pathnodes[ cell->nodes[ nodes[ i ] ] ]; + arc.ArchiveInteger(&m_NodeCheckFailed); + ArchiveStaticSave(arc); + arc.Close(); - VectorCopy( pos, start ); - VectorCopy( pos, end ); - - VectorAdd( end, deltas[ i ], end ); - - Vector vStart = start; - Vector vMins = Vector( -15, -15, 0 ); - Vector vMaxs = Vector( 15, 15, 62 ); - Vector vEnd = end; - - if( G_SightTrace( - vStart, - vMins, - vMaxs, - vEnd, - ( gentity_t *)NULL, - ( gentity_t * )NULL, - MASK_PATHSOLID, - qtrue, - "PathSearch::DebugNearestNodeList" ) ) - { - nodelist[ n ] = node; - n++; - } - } - - if( !n && node_count ) - { - nodelist[ 0 ] = pathnodes[ cell->nodes[ nodes[ 0 ] ] ]; - return 1; - } - else - { - return n; - } - - return 0; + return true; } -int PathSearch::DebugNearestNodeList2 - ( - float *pos, - PathNode **nodelist, - int iMaxNodes - ) +void PathSearch::ArchiveLoadNodes(void) { - vec3_t delta; - PathNode *node; - float dist; - int n = 0; - int i; - int j; - static float node_dist[ MAX_PATHNODES ]; - int node_count; + Archiver arc; - node_count = nodecount; + m_LoadIndex = 0; + if (arc.Read(level.m_pathfile, false)) { + int file_version; + str maptime; - for( i = 0; i < node_count; i++ ) - { - node = pathnodes[ i ]; + // get file values + arc.ArchiveInteger(&file_version); + if (file_version != PATHFILE_VERSION) { + Com_Printf("Expecting version %d path file. Path file is version %d.\n", PATHFILE_VERSION, file_version); + arc.Close(); + return; + } - if( pos[ 2 ] > node->origin[ 2 ] + 94.0f ) - continue; + arc.ArchiveString(&maptime); + if (gi.MapTime() == maptime && gi.FS_FileNewer(level.m_mapfile.c_str(), level.m_pathfile.c_str()) <= 0) { + arc.ArchiveInteger(&m_NodeCheckFailed); - if( node->origin[ 2 ] > pos[ 2 ] + 94.0f ) - continue; + if (!g_nodecheck->integer || !m_NodeCheckFailed) { + ArchiveStaticLoad(arc); + m_bNodesloaded = arc.NoErrors(); + } else { + gi.Printf("Rebuilding pathnodes to view node errors.\n"); + } + } else { + gi.Printf("Pathnodes have changed, rebuilding.\n"); + } + } - delta[ 0 ] = node->origin[ 0 ] - pos[ 0 ]; - delta[ 1 ] = node->origin[ 1 ] - pos[ 1 ]; - delta[ 2 ] = node->origin[ 2 ] - pos[ 2 ]; - - dist = VectorLengthSquared( delta ); - - for( j = n; j > 0; j-- ) - { - if( dist >= node_dist[ j - 1 ] ) - break; - - node_dist[ j ] = node_dist[ j - 1 ]; - nodelist[ j ] = nodelist[ j - 1 ]; - } - - n++; - nodelist[ j ] = node; - node_dist[ j ] = dist; - } - - return n; + arc.Close(); } -void PathSearch::ArchiveStaticLoad - ( - Archiver& arc - ) +void PathSearch::Init(void) { - int i; - PathNode *node; - int total_nodes; - int total_children; - int x; - int y; - int size; + ai_showroutes = gi.Cvar_Get("ai_showroutes", "0", 0); + ai_showroutes_distance = gi.Cvar_Get("ai_showroutes_distance", "1000", 0); + ai_shownodenums = gi.Cvar_Get("ai_shownodenums", "0", 0); + ai_shownode = gi.Cvar_Get("ai_shownode", "0", 0); + ai_showallnode = gi.Cvar_Get("ai_showallnode", "0", 0); + ai_showpath = gi.Cvar_Get("ai_showpath", "0", 0); + ai_fallheight = gi.Cvar_Get("ai_fallheight", "96", 0); + ai_debugpath = gi.Cvar_Get("ai_debugpath", "0", 0); + ai_pathchecktime = gi.Cvar_Get("ai_pathchecktime", "1.5", CVAR_CHEAT); + ai_pathcheckdist = gi.Cvar_Get("ai_pathcheckdist", "4096", CVAR_CHEAT); - loadingarchive = true; + // + // Added in OPM + // + ai_editmode = gi.Cvar_Get("ai_editmode", "0", CVAR_LATCH); - arc.ArchiveInteger( &nodecount ); - arc.ArchiveInteger( &total_nodes ); - arc.ArchiveInteger( &total_children ); - - size = total_nodes + total_children * ( sizeof( pathway_t ) * 2 ) + nodecount * ( sizeof( PathNode ) / 2 ); - size *= sizeof(void*) / 2; - - gi.DPrintf( "%d memory allocated for navigation.\n", size ); - - if( size ) - startBulkNavMemory = ( byte * )gi.Malloc( size ); - else - startBulkNavMemory = NULL; - - bulkNavMemory = startBulkNavMemory + size; - - for( i = 0; i < nodecount; i++ ) - { - node = new PathNode; - - arc.ArchiveObjectPosition( node ); - node->ArchiveStatic( arc ); - node->nodenum = i; - - pathnodes[ i ] = node; - - if( !( node->nodeflags & PATH_DONT_LINK ) ) - { - x = NodeCoordinate( node->origin[ 0 ] ); - y = NodeCoordinate( node->origin[ 1 ] ); - - LoadAddToGrid( x, y ); - LoadAddToGrid( x + 1, y ); - LoadAddToGrid( x, y + 1 ); - LoadAddToGrid( x + 1, y + 1 ); - } - } - - for( x = 0; x < PATHMAP_GRIDSIZE; x++ ) - { - for( y = 0; y < PATHMAP_GRIDSIZE; y++ ) - { - bulkNavMemory -= PathMap[ x ][ y ].numnodes * sizeof( short ); - - PathMap[ x ][ y ].nodes = PathMap[ x ][ y ].numnodes ? ( short * )bulkNavMemory : NULL; - PathMap[ x ][ y ].numnodes = 0; - } - } - - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; - - if( !( node->nodeflags & PATH_DONT_LINK ) ) - { - x = NodeCoordinate( node->origin[ 0 ] ); - y = NodeCoordinate( node->origin[ 1 ] ); - - LoadAddToGrid2( node, x, y ); - LoadAddToGrid2( node, x + 1, y ); - LoadAddToGrid2( node, x, y + 1 ); - LoadAddToGrid2( node, x + 1, y + 1 ); - } - } - - loadingarchive = false; + navMaster.Init(); } -void PathSearch::ArchiveStaticSave - ( - Archiver& arc - ) +void *PathSearch::AllocPathNode(void) { - int i; - PathNode *node; - int total_nodes = 0; - int total_children = 0; - int x = 0; - int y = 0; + if (!bulkNavMemory) { + return gi.Malloc(sizeof(PathNode)); + } else { + bulkNavMemory -= sizeof(PathNode); + if (ai_editmode->integer) { + return gi.Malloc(sizeof(PathNode)); + } + } - for( x = 0; x < PATHMAP_GRIDSIZE; x++ ) - { - for( y = 0; y < PATHMAP_GRIDSIZE; y++ ) - { - total_nodes += PathMap[ x ][ y ].NumNodes(); - } - } + return bulkNavMemory; +} - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; - total_children += node->virtualNumChildren; - } +void PathSearch::FreePathNode(void *ptr) +{ + if (!bulkNavMemory || ai_editmode->integer) { + gi.Free(ptr); + } +} - arc.ArchiveInteger( &nodecount ); - arc.ArchiveInteger( &total_nodes ); - arc.ArchiveInteger( &total_children ); +void PathSearch::PlayerCover(Player *pPlayer) +{ + int i; + PathNode *node; + Vector delta; + Entity *pOwner; - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; - arc.ArchiveObjectPosition( node ); - node->ArchiveStatic( arc ); - } + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + + if (!node || !(node->nodeflags & AI_MOVE_MASK)) { + continue; + } + + pOwner = node->GetClaimHolder(); + + delta = node->origin - pPlayer->origin; + + // Check if we need to cover + if (VectorLengthSquared(delta) > Square(48)) { + if (pOwner == pPlayer) { + node->Relinquish(); + } + continue; + } + + if (pOwner != pPlayer) { + if (pOwner) { + pOwner->PathnodeClaimRevoked(node); + } + // Player claim the node + node->Claim(pPlayer); + } + } +} + +class nodeinfo +{ +public: + PathNode *pNode; + float fDistSquared; +}; + +int node_compare(const void *pe1, const void *pe2) +{ + nodeinfo *Pe1 = (nodeinfo *)pe1; + nodeinfo *Pe2 = (nodeinfo *)pe2; + int iConcealment; + + iConcealment = (Pe1->pNode->nodeflags & AI_CONCEALMENT_MASK) ? 1 : 0; + if (Pe2->pNode->nodeflags & AI_CONCEALMENT_MASK) { + iConcealment--; + } + + return ( + *(unsigned int*)&Pe1->fDistSquared + (iConcealment << 23) + + (((Pe1->pNode->nodeflags & AI_CONCEALMENT) - (Pe2->pNode->nodeflags & AI_CONCEALMENT)) << 21) + - *(unsigned int*)&Pe2->fDistSquared + ); +} + +int PathSearch::FindPotentialCover( + Entity *pEnt, Vector& vPos, Entity *pEnemy, PathNode **ppFoundNodes, int iMaxFind +) +{ + nodeinfo nodes[MAX_PATHNODES]; + int nNodes = 0; + int i; + Vector delta; + PathNode *node; + + Actor *pActor = static_cast(pEnt); + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + if (!node) { + continue; + } + + if (!(node->nodeflags & AI_COVER_MASK)) { + continue; + } + + if (node->IsClaimedByOther(static_cast(pEnt))) { + continue; + } + + delta = node->origin - pActor->m_vHome; + if (delta.lengthSquared() > pActor->m_fLeashSquared) { + continue; + } + + delta = node->origin - pEnemy->origin; + if (delta.lengthSquared() < pActor->m_fMinDistanceSquared + || delta.lengthSquared() > pActor->m_fMaxDistanceSquared) { + continue; + } + + delta = node->origin - pEnt->origin; + nodes[nNodes].pNode = node; + nodes[nNodes].fDistSquared = delta.lengthSquared(); + nNodes++; + } + + if (nNodes) { + qsort(nodes, nNodes, sizeof(nodeinfo), node_compare); + + if (nNodes > iMaxFind) { + nNodes = iMaxFind; + } + + for (i = 0; i < nNodes; i++) { + ppFoundNodes[nNodes - i - 1] = nodes[i].pNode; + } + } + return nNodes; +} + +PathNode *PathSearch::FindNearestSniperNode(Entity*pEnt, Vector& vPos, Entity *pEnemy) +{ + Actor *pSelf = (Actor *)pEnt; + PathNode *pNode; + Vector delta; + int nNodes = 0; + int i; + nodeinfo nodes[MAX_PATHNODES]; + + for (i = 0; i < nodecount; i++) { + pNode = pathnodes[i]; + if (!pNode) { + continue; + } + + if (!(pNode->nodeflags & AI_SNIPER)) { + continue; + } + if (pNode->IsClaimedByOther(pEnt)) { + continue; + } + + delta = pNode->origin - pSelf->m_vHome; + + if (delta.lengthSquared() > pSelf->m_fLeashSquared) { + continue; + } + + delta = pNode->origin - pEnemy->origin; + if (delta.lengthSquared() < pSelf->m_fMinDistanceSquared + || delta.lengthSquared() > pSelf->m_fMaxDistanceSquared) { + continue; + } + + delta = pNode->origin - pSelf->origin; + nodes[nNodes].fDistSquared = delta.lengthSquared(); + nodes[nNodes].pNode = pNode; + nNodes++; + } + + if (nNodes == 0) { + return NULL; + } + + qsort(nodes, nNodes, sizeof(nodeinfo), node_compare); + + if (nNodes <= 0) { + return NULL; + } + + for (i = 0; i < nNodes; i++) { + pNode = nodes[i].pNode; + if (pSelf->CanSeeFrom(pSelf->eyeposition + pNode->origin, pEnemy)) { + return pNode; + } + + pNode->MarkTemporarilyBad(); + } + + return NULL; +} + +PathNode *PathSearch::GetSpawnNode(ClassDef *cls) +{ + if (m_bNodesloaded + // Fixed in OPM + && m_LoadIndex < nodecount + ) { + return pathnodes[m_LoadIndex++]; + } else { + // Otherwise create a new node + return static_cast(cls->newInstance()); + } +} + +void PathSearch::LoadNodes(void) +{ + Init(); + + ArchiveLoadNodes(); +} + +void PathSearch::CreatePaths(void) +{ + int i; + int j; + int x; + int y; + PathNode *node; + Vector start; + Vector end; + gentity_t *ent; + int t1; + int t2; + + if (m_bNodesloaded) { + return; + } + + if (!nodecount) { + m_bNodesloaded = true; + return; + } + + m_NodeCheckFailed = false; + + gi.DPrintf( + "***********************************\n" + "***********************************\n" + "\n" + "Creating paths...\n" + "\n" + "***********************************\n" + "***********************************\n" + ); + + gi.ClearResource(); + + t1 = gi.Milliseconds(); + + for (i = 0, ent = g_entities; i < game.maxentities; i++, ent++) { + if (ent->entity && ent->entity->IsSubclassOfDoor()) { + ent->entity->unlink(); + } + } + + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + MapCell *cell = &PathMap[x][y]; + + cell->nodes = (short *)gi.Malloc(PATHMAP_CELLSIZE); + cell->numnodes = 0; + memset(cell->nodes, 0, PATHMAP_CELLSIZE); + } + } + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + if (!node) { + continue; + } + + droptofloor(node->origin, node); + node->centroid = node->origin; + + if (node->nodeflags & PATH_DONT_LINK) { + continue; + } + + for (j = i - 1; j >= 0; j--) { + PathNode *node2 = pathnodes[j]; + if (!node2) { + continue; + } + + if (node->origin == node2->origin) { + Com_Printf( + "^~^~^ Duplicate node at (%.2f %.2f %.2f) not linked\n", + node->origin[0], + node->origin[1], + node->origin[2] + ); + node->nodeflags |= PATH_DONT_LINK; + break; + } + } + + if (!(node->nodeflags & PATH_DONT_LINK)) { + node->Child = (pathway_t *)gi.Malloc(sizeof(pathway_t) * PATHMAP_NODES); + } + } + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + + if (!node || (node->nodeflags & PATH_DONT_LINK)) { + continue; + } + + AddNode(node); + } + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + + if (!node || (node->nodeflags & PATH_DONT_LINK)) { + continue; + } + + Connect(node); + } + + for (i = 0, ent = g_entities; i < game.maxentities; i++, ent++) { + if (ent->entity && ent->entity->IsSubclassOfDoor()) { + ent->entity->link(); + } + } + + gi.DPrintf("\nSaving path nodes to '%s'\n", level.m_pathfile.c_str()); + Com_Printf("Archiving\n"); + ArchiveSaveNodes(); + m_bNodesloaded = true; + Com_Printf("done.\n"); + + t2 = gi.Milliseconds(); + Com_Printf("Path connection: %5.2f seconds\n", (t2 - t1) / 1000.0f); + Com_Printf("Number of nodes: %d\n", nodecount); + gi.ClearResource(); + + if (g_nodecheck->integer && m_NodeCheckFailed) { + gi.Error(ERR_DROP, "Node check failed"); + } +} + +void PathSearch::LoadAddToGrid2(PathNode *node, int x, int y) +{ + MapCell *cell; + + cell = GetNodesInCell(x, y); + + if (cell) { + cell->AddNode(node); + } +} + +void PathSearch::ArchiveStaticLoad(Archiver& arc) +{ + int i; + PathNode *node; + int total_nodes; + int total_children; + int x; + int y; + int size; + + loadingarchive = true; + + arc.ArchiveInteger(&nodecount); + arc.ArchiveInteger(&total_nodes); + arc.ArchiveInteger(&total_children); + + size = total_nodes + total_children * (sizeof(pathway_t) * 2) + nodecount * (sizeof(PathNode) / 2); + size *= sizeof(void *) / 2; + + gi.DPrintf("%d memory allocated for navigation.\n", size); + + if (size) { + startBulkNavMemory = (byte *)gi.Malloc(size); + } else { + startBulkNavMemory = NULL; + } + + bulkNavMemory = startBulkNavMemory + size; + + for (i = 0; i < nodecount; i++) { + node = new PathNode; + + arc.ArchiveObjectPosition(node); + node->ArchiveStatic(arc); + node->nodenum = i; + + pathnodes[i] = node; + + if (!(node->nodeflags & PATH_DONT_LINK)) { + x = NodeCoordinate(node->origin[0]); + y = NodeCoordinate(node->origin[1]); + + LoadAddToGrid(x, y); + LoadAddToGrid(x + 1, y); + LoadAddToGrid(x, y + 1); + LoadAddToGrid(x + 1, y + 1); + } + } + + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + bulkNavMemory -= PathMap[x][y].numnodes * sizeof(short); + + PathMap[x][y].nodes = PathMap[x][y].numnodes ? (short *)bulkNavMemory : NULL; + PathMap[x][y].numnodes = 0; + } + } + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + + if (!(node->nodeflags & PATH_DONT_LINK)) { + x = NodeCoordinate(node->origin[0]); + y = NodeCoordinate(node->origin[1]); + + LoadAddToGrid2(node, x, y); + LoadAddToGrid2(node, x + 1, y); + LoadAddToGrid2(node, x, y + 1); + LoadAddToGrid2(node, x + 1, y + 1); + } + } + + loadingarchive = false; +} + +void PathSearch::ArchiveStaticSave(Archiver& arc) +{ + int i; + PathNode *node; + int total_nodes = 0; + int total_children = 0; + int x = 0; + int y = 0; + + for (x = 0; x < PATHMAP_GRIDSIZE; x++) { + for (y = 0; y < PATHMAP_GRIDSIZE; y++) { + total_nodes += PathMap[x][y].NumNodes(); + } + } + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + total_children += node->virtualNumChildren; + } + + arc.ArchiveInteger(&nodecount); + arc.ArchiveInteger(&total_nodes); + arc.ArchiveInteger(&total_children); + + for (i = 0; i < nodecount; i++) { + node = pathnodes[i]; + arc.ArchiveObjectPosition(node); + node->ArchiveStatic(arc); + } } bool PathSearch::ArchiveDynamic(Archiver& arc) { - PathNode* node; - int i; - int count; + PathNode *node; + int i; + int count; - if (arc.Loading()) - { - arc.ArchiveInteger(&count); - if (count != nodecount) { - Com_Printf("Path file invalid - cannot load save game\n"); - return false; - } - } - else - { - arc.ArchiveInteger(&nodecount); - } + if (arc.Saving()) { + arc.ArchiveInteger(&nodecount); + } else { + arc.ArchiveInteger(&count); + if (count != nodecount) { + Com_Printf("Path file invalid - cannot load save game\n"); + return false; + } + } - for (i = 0; i < nodecount; i++) { - node = PathSearch::pathnodes[i]; - node->ArchiveDynamic(arc); - } + for (i = 0; i < nodecount; i++) { + node = PathSearch::pathnodes[i]; + node->ArchiveDynamic(arc); + } - return true; + return true; } -void PathSearch::ArchiveLoadNodes - ( - void - ) +void PathSearch::AddToGrid(PathNode *node, int x, int y) { - Archiver arc; - qboolean success; + MapCell *cell; - success = qfalse; - if( arc.Read( level.m_pathfile, false ) ) - { - int file_version; - str maptime; + cell = GetNodesInCell(x, y); - // get file values - arc.ArchiveInteger( &file_version ); - if( file_version != PATHFILE_VERSION ) - { - Com_Printf( "Expecting version %d path file. Path file is version %d.\n", PATHFILE_VERSION, file_version ); - arc.Close(); - return; - } + if (!cell) { + return; + } - arc.ArchiveString( &maptime ); - if( gi.MapTime() == maptime && gi.FS_FileNewer( level.m_mapfile.c_str(), level.m_pathfile.c_str() ) <= 0 ) - { - arc.ArchiveInteger( &m_NodeCheckFailed ); + if (cell->NumNodes() >= PATHMAP_NODES) { + Com_Printf("^~^~^ PathSearch::AddToGrid: Node overflow at ( %d, %d )\n", x, y); + return; + } - if( !g_nodecheck->integer || !m_NodeCheckFailed ) - { - ArchiveStaticLoad( arc ); - m_bNodesloaded = arc.NoErrors(); - } - else - { - gi.Printf( "Rebuilding pathnodes to view node errors.\n" ); - } - } - else - { - gi.Printf( "Pathnodes have changed, rebuilding.\n" ); - } - } - - arc.Close(); + cell->AddNode(node); } -qboolean PathSearch::ArchiveSaveNodes - ( - void - ) +bool PathSearch::Connect(PathNode *node, int x, int y) { - Archiver arc; - str maptime; - int tempInt; + MapCell *cell; + int i; + PathNode *node2; - arc.Create( level.m_pathfile ); - tempInt = PATHFILE_VERSION; - arc.ArchiveInteger( &tempInt ); - maptime = gi.MapTime(); - arc.ArchiveString( &maptime ); - arc.ArchiveInteger( &m_NodeCheckFailed ); - ArchiveStaticSave( arc ); - arc.Close(); + cell = GetNodesInCell(x, y); - return true; + if (!cell) { + return true; + } + + for (i = 0; i < cell->numnodes; i++) { + node2 = pathnodes[cell->nodes[i]]; + if (!node2) { + continue; + } + + if (node2->findCount != findFrame) { + node2->findCount = findFrame; + + if (!node->CheckPathTo(node2)) { + return false; + } + } + } + + return true; } -void PathSearch::Connect - ( - PathNode *node - ) +bool PathNode::CheckPathTo(PathNode *node) { - int x; - int y; + if (virtualNumChildren >= NUM_PATHSPERNODE) { + Com_Printf( + "^~^~^ %d paths per node at (%.2f %.2f %.2f) exceeded\n - use DONT_LINK on some nodes to conserve cpu and " + "memory usage\n", + NUM_PATHSPERNODE, + node->origin[0], + node->origin[1], + node->origin[2] + ); + PathSearch::m_NodeCheckFailed = true; + return false; + } - findFrame++; - node->findCount = findFrame; - - x = NodeCoordinate( node->origin[ 0 ] ); - y = NodeCoordinate( node->origin[ 1 ] ); - - if( Connect( node, x - 1, y - 1 ) ) - { - if( Connect( node, x - 1, y ) ) - { - if( Connect( node, x - 1, y + 1 ) ) - { - if( Connect( node, x, y - 1 ) ) - { - if( Connect( node, x, y ) ) - { - if( Connect( node, x, y + 1 ) ) - { - if( Connect( node, x + 1, y - 1 ) ) - { - if( Connect( node, x + 1, y ) ) - { - Connect( node, x + 1, y + 1 ); - } - } - } - } - } - } - } - } + CheckPathToDefault(node, &Child[virtualNumChildren]); + return true; } -bool PathSearch::Connect - ( - PathNode *node, - int x, - int y - ) +qboolean CheckMove(Vector& origin, Vector& pos, short int *path_fallheight, float size) { - MapCell *cell; - int i; - PathNode *node2; + mmove_t mm; + int i; + float air_z; + float fallheight; + float test_fallheight; + float error; + trace_t trace; + vec3_t dir; + vec3_t end; - if( x > PATHMAP_GRIDSIZE || y > PATHMAP_GRIDSIZE ) - cell = NULL; - else - cell = &PathMap[ x ][ y ]; + memset(&mm, 0, sizeof(mmove_t)); - if( !cell ) - return true; + VectorClear(mm.velocity); + VectorCopy(origin, mm.origin); + mm.desired_speed = 150.0f; + mm.entityNum = ENTITYNUM_NONE; + mm.tracemask = MASK_PATHSOLID; + mm.frametime = 0.1f; + mm.desired_dir[0] = pos[0] - origin[0]; + mm.desired_dir[1] = pos[1] - origin[1]; + VectorNormalize2D(mm.desired_dir); - if( cell->numnodes <= 0 ) - return true; + mm.groundPlane = qfalse; + mm.walking = qfalse; - for( i = 0; i < cell->numnodes; i++ ) - { - node2 = pathnodes[ cell->nodes[ i ] ]; + mm.mins[0] = -size; + mm.mins[1] = -size; + mm.mins[2] = 0; + mm.maxs[0] = size; + mm.maxs[1] = size; + mm.maxs[2] = MAXS_Z; - if( node2->findCount != findFrame ) - { - node2->findCount = findFrame; + testcount = 0; + fallheight = 0.0f; + air_z = mm.origin[2]; - if( !node->CheckPathTo( node2 ) ) - return false; - } - } + for (i = 0; i < 200; i++) { + testpos[testcount++] = mm.origin; - return true; + MmoveSingle(&mm); + + if (mm.groundPlane) { + test_fallheight = air_z - mm.origin[2]; + + if (test_fallheight > fallheight) { + if (test_fallheight > MAXS_Z) { + Vector start; + + // + // Added in OPM + // Check to make sure that the target is reachable enough + // so that AIs don't block trying to move to the target position + + start = origin; + start.z += MAXS_Z; + + if (!G_SightTrace( + start, + vec_zero, + vec_zero, + pos, + (gentity_t *)NULL, + (gentity_t *)NULL, + MASK_PATHSOLID, + qfalse, + "CheckMove" + )) { + return false; + } + } + + if (test_fallheight > 1024.0f) { + return false; + } + + fallheight = test_fallheight; + } + + air_z = mm.origin[2]; + } + + VectorSub2D(pos, mm.origin, dir); + + if (DotProduct2D(dir, mm.desired_dir) <= 0.1f) { + error = mm.origin[2] - pos[2]; + + *path_fallheight = (short)fallheight; + if (fabs(error) <= MAXS_Z) { + if (error <= 0.0f || mm.groundPlane) { + return true; + } + + end[0] = mm.origin[0]; + end[1] = mm.origin[1]; + end[2] = pos[2]; + + trace = G_Trace(mm.origin, mm.mins, mm.maxs, end, NULL, MASK_PATHSOLID, true, "CheckMove"); + + test_fallheight = mm.origin[2] - trace.endpos[2]; + + if (test_fallheight <= 18.0f) { + *path_fallheight = (short)test_fallheight + fallheight; + return test_fallheight + fallheight <= 1024.0f; + } + } + + if (mm.groundPlane) { + return false; + } + + VectorCopy2D(dir, mm.desired_dir); + VectorNormalize2D(mm.desired_dir); + } + + if (mm.hit_obstacle) { + break; + } + } + + return false; } -void PathSearch::ShowNodes - ( - void - ) +void PathNode::CheckPathToDefault(PathNode *node, pathway_t *pathway) { - if( g_entities->client ) - { - if( ai_shownode->integer ) - { - DrawNode( ai_shownode->integer ); - } - if( ai_showroutes->integer || ai_shownodenums->integer ) - { - DrawAllConnections(); - } - } + float dist; + vec2_t delta; + Vector start; + Vector end; - if( ai_showpath->integer ) - { - if( !test_path ) - test_path = new ActorPath; + VectorSub2D(node->origin, origin, delta); + dist = VectorNormalize2D(delta); - if( ai_showpath->integer == 1 ) - { - ai_startpath = g_entities[ 0 ].entity->origin; - } - if( ai_showpath->integer == 2 ) - { - ai_endpath = g_entities[ 0 ].entity->origin; - } - if( ai_showpath->integer <= 2 ) - { - test_path->SetFallHeight( ai_fallheight->integer ); - test_path->FindPath( ai_startpath, ai_endpath, NULL, 0, NULL, 0 ); - } - if( ai_showpath->integer == 3 ) - { - if( test_path->CurrentNode() ) - { - test_path->UpdatePos( g_entities[ 0 ].entity->origin ); + if (dist >= 384.0f) { + return; + } - Vector vStart = g_entities[ 0 ].entity->origin + Vector( 0, 0, 32 ); - Vector vEnd = g_entities[ 0 ].entity->origin + test_path->CurrentDelta() + Vector( 0, 0, 32 ); + start = origin; + end = node->origin; - G_DebugLine( vStart, vEnd, 1, 1, 0, 1 ); - } - } + droptofloor(start, this); + droptofloor(end, node); - G_DebugLine( ai_startpath, ai_endpath, 0, 0, 1, 1 ); - - if( test_path->CurrentNode() ) - { - PathInfo *pos = test_path->CurrentNode(); - - while( pos != test_path->LastNode() ) - { - Vector vStart = pos->point + Vector( 0, 0, 32 ); - - pos--; - - Vector vEnd = pos->point + Vector( 0, 0, 32 ); - - G_DebugLine( vStart, vEnd, 1, 0, 0, 1 ); - } - } - } + if (CheckMove(start, end, &pathway->fallheight, 15.5f)) { + pathway->dist = dist; + VectorCopy2D(delta, pathway->dir); + start.copyTo(pathway->pos1); + end.copyTo(pathway->pos2); + ConnectTo(node); + } } -void PathSearch::LoadNodes - ( - void - ) +void MapCell::AddNode(PathNode *node) { - Init(); - - ArchiveLoadNodes(); + nodes[numnodes] = node->nodenum; + numnodes++; } -void PathSearch::CreatePaths - ( - void - ) +void PathSearch::AddNode(PathNode *node) { - int i; - int j; - int x; - int y; - PathNode *node; - Vector start; - Vector end; - gentity_t *ent; - int t1; - int t2; + int x; + int y; - if( m_bNodesloaded ) - return; + assert(node); - if( !nodecount ) - { - m_bNodesloaded = true; - return; - } + x = NodeCoordinate(node->origin[0]); + y = NodeCoordinate(node->origin[1]); - m_NodeCheckFailed = false; - - gi.DPrintf( "***********************************\n" - "***********************************\n" - "\n" - "Creating paths...\n" - "\n" - "***********************************\n" - "***********************************\n" ); - - t1 = gi.Milliseconds(); - - for( i = 0, ent = g_entities; i < game.maxentities; i++, ent++ ) - { - if( ent->entity && ent->entity->IsSubclassOfDoor() ) - gi.unlinkentity( ent ); - } - - for( x = 0; x < PATHMAP_GRIDSIZE; x++ ) - { - for( y = 0; y < PATHMAP_GRIDSIZE; y++ ) - { - MapCell *cell = &PathMap[ x ][ y ]; - - cell->nodes = ( short * )gi.Malloc( PATHMAP_CELLSIZE ); - cell->numnodes = 0; - memset( cell->nodes, 0, PATHMAP_CELLSIZE ); - } - } - - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; - - start = node->origin + Vector( 0, 0, 36.0f ); - end = node->origin - Vector( 0, 0, 2048.0f ); - - trace_t trace = G_Trace( start, - PLAYER_BASE_MIN, - PLAYER_BASE_MAX, - end, - NULL, - MASK_PATHSOLID, - qfalse, - "droptofloor" ); - - node->origin = trace.endpos; - node->centroid = trace.endpos; - - if( !( node->nodeflags & PATH_DONT_LINK ) ) - { - for( j = i - 1; j >= 0; j-- ) - { - PathNode *node2 = pathnodes[ j ]; - - if( node2->origin == node->origin ) - { - Com_Printf( "^~^~^ Duplicate node at (%.2f %.2f %.2f) not linked\n", node->origin[ 0 ], node->origin[ 1 ], node->origin[ 2 ] ); - node->nodeflags |= PATH_DONT_LINK; - break; - } - } - - if( !( node->nodeflags & PATH_DONT_LINK ) ) - node->Child = ( pathway_t * )gi.Malloc( sizeof( pathway_t ) * PATHMAP_NODES ); - } - } - - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; - - if( node->nodeflags & PATH_DONT_LINK ) - continue; - - AddNode( node ); - } - - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; - - if( node->nodeflags & PATH_DONT_LINK ) - continue; - - Connect( node ); - } - - for( i = 0, ent = g_entities; i < game.maxentities; i++, ent++ ) - { - if( ent->entity && ent->entity->IsSubclassOfDoor() ) - ent->entity->link(); - } - - gi.DPrintf( "\nSaving path nodes to '%s'\n", level.m_pathfile.c_str() ); - Com_Printf( "Archiving\n" ); - ArchiveSaveNodes(); - m_bNodesloaded = true; - Com_Printf( "done.\n" ); - - t2 = gi.Milliseconds(); - Com_Printf( "Path connection: %5.2f seconds\n", ( t2 - t1 ) / 1000.0f ); - Com_Printf( "Number of nodes: %d\n", nodecount ); - gi.ClearResource(); - - if( g_nodecheck->integer && m_NodeCheckFailed ) - { - gi.Error( ERR_DROP, "Node check failed" ); - } + AddToGrid(node, x, y); + AddToGrid(node, x + 1, y); + AddToGrid(node, x, y + 1); + AddToGrid(node, x + 1, y + 1); } -void *PathSearch::AllocPathNode - ( - void - ) +void PathSearch::Connect(PathNode *node) { - if( bulkNavMemory && !m_bNodesloaded ) - { - bulkNavMemory -= sizeof( PathNode ); - return bulkNavMemory; - } - else - { - return gi.Malloc( sizeof( PathNode ) ); - } + int x; + int y; + + findFrame++; + node->findCount = findFrame; + + x = GridCoordinate(node->origin[0]); + y = GridCoordinate(node->origin[1]); + + if (!Connect(node, x - 1, y - 1)) { + return; + } + + if (!Connect(node, x - 1, y)) { + return; + } + + if (!Connect(node, x - 1, y + 1)) { + return; + } + + if (!Connect(node, x, y - 1)) { + return; + } + + if (!Connect(node, x, y)) { + return; + } + + if (!Connect(node, x, y + 1)) { + return; + } + + if (!Connect(node, x + 1, y - 1)) { + return; + } + + if (!Connect(node, x + 1, y)) { + return; + } + + Connect(node, x + 1, y + 1); } -void PathSearch::FreePathNode - ( - void *ptr - ) +const_str PathNode::GetSpecialAttack(Actor *pActor) { - if( !bulkNavMemory || m_bNodesloaded ) - { - gi.Free( ptr ); - } + int iSpecialAttack; + const_str csAnimation; + float fRangeSquared; + vec2_t vDelta; + float fAngle; + float fMinRangeSquared; + float fMaxRangeSquared; + float fMinAngle; + float fMaxAngle; + + if (nodeflags & AI_CORNER_LEFT) { + iSpecialAttack = 0; + csAnimation = STRING_ANIM_CORNERLEFT_SCR; + fMinRangeSquared = g_AttackParms[iSpecialAttack].fMinRangeSquared; + fMaxRangeSquared = g_AttackParms[iSpecialAttack].fMaxRangeSquared; + fMinAngle = g_AttackParms[iSpecialAttack].fMinAngle; + fMaxAngle = g_AttackParms[iSpecialAttack].fMaxAngle; + } else if (nodeflags & AI_CORNER_RIGHT) { + iSpecialAttack = 1; + csAnimation = STRING_ANIM_CORNERRIGHT_SCR; + fMinRangeSquared = g_AttackParms[iSpecialAttack].fMinRangeSquared; + fMaxRangeSquared = g_AttackParms[iSpecialAttack].fMaxRangeSquared; + fMinAngle = g_AttackParms[iSpecialAttack].fMinAngle; + fMaxAngle = g_AttackParms[iSpecialAttack].fMaxAngle; + } else if (nodeflags & AI_CRATE) { + iSpecialAttack = 2; + csAnimation = STRING_ANIM_OVERATTACK_SCR; + fMinRangeSquared = g_AttackParms[iSpecialAttack].fMinRangeSquared; + fMaxRangeSquared = g_AttackParms[iSpecialAttack].fMaxRangeSquared; + fMinAngle = g_AttackParms[iSpecialAttack].fMinAngle; + fMaxAngle = g_AttackParms[iSpecialAttack].fMaxAngle; + } else if (nodeflags & AI_LOW_WALL_ARC) { + if (nodeflags & AI_DUCK) { + csAnimation = STRING_ANIM_LOWWALL_SCR; + } else { + csAnimation = STRING_ANIM_HIGHWALL_SCR; + } + + iSpecialAttack = 3; + fMinRangeSquared = g_AttackParms[iSpecialAttack].fMinRangeSquared; + fMaxRangeSquared = g_AttackParms[iSpecialAttack].fMaxRangeSquared; + fMinAngle = 360 - m_fLowWallArc; + fMaxAngle = m_fLowWallArc; + } else { + return STRING_NULL; + } + + if (pActor->m_Enemy) { + VectorSub2D(pActor->m_Enemy->centroid, origin, vDelta); + } else { + VectorSub2D(pActor->m_vLastEnemyPos, origin, vDelta); + } + + fRangeSquared = VectorLength2DSquared(vDelta); + + if (fRangeSquared < fMinRangeSquared || fRangeSquared > fMaxRangeSquared) { + return STRING_NULL; + } + + fAngle = RAD2DEG(atan2(vDelta[1], vDelta[0])) - angles[1]; + + if (fAngle <= -360) { + fAngle = fAngle + 720.0f; + } else if (fAngle < 0) { + fAngle = fAngle + 360.0f; + } else if (fAngle >= 720) { + fAngle = fAngle - 720.0f; + } else if (fAngle >= 360) { + fAngle = fAngle - 360.0f; + } else { + fAngle = fAngle; + } + + if (fMinAngle > fMaxAngle) { + if (fAngle < fMinAngle && fAngle > fMaxAngle) { + return STRING_NULL; + } + } else { + if (fAngle < fMinAngle || fAngle > fMaxAngle) { + return STRING_NULL; + } + } + + return csAnimation; } -void PathSearch::ResetNodes - ( - void - ) +void PathNode::Claim(Entity *pClaimer) { - int i; - int x; - int y; - - m_LoadIndex = -1; - m_bNodesloaded = false; - - if( !startBulkNavMemory ) - { - for( x = PATHMAP_GRIDSIZE - 1; x >= 0; x-- ) - { - for( y = PATHMAP_GRIDSIZE - 1; y >= 0; y-- ) - { - if( PathMap[ x ][ y ].nodes ) - gi.Free( PathMap[ x ][ y ].nodes ); - } - } - - for( i = 0; i < nodecount; i++ ) - { - if( pathnodes[ i ]->Child ) - gi.Free( pathnodes[ i ]->Child ); - } - } - - for( x = PATHMAP_GRIDSIZE - 1; x >= 0; x-- ) - { - for( y = PATHMAP_GRIDSIZE - 1; y >= 0; y-- ) - { - PathMap[ x ][ y ].numnodes = 0; - PathMap[ x ][ y ].nodes = NULL; - } - } - - for( i = 0; i < nodecount; i++ ) - { - delete pathnodes[ i ]; - pathnodes[ i ] = NULL; - } - - nodecount = 0; - - // Free the bulk nav' memory - if( startBulkNavMemory ) - { - gi.Free( startBulkNavMemory ); - bulkNavMemory = NULL; - startBulkNavMemory = NULL; - } + pLastClaimer = pClaimer; + iAvailableTime = 0; } -PathInfo *PathSearch::GeneratePath - ( - PathInfo *path - ) +Entity *PathNode::GetClaimHolder(void) const { - PathNode *ParentNode; - pathway_t *pathway; - float dist; - float dir[ 2 ]; - PathInfo *current_path; - - current_path = path; - - dir[ 0 ] = path_end[ 0 ] - Node->m_PathPos[ 0 ]; - dir[ 1 ] = path_end[ 1 ] - Node->m_PathPos[ 1 ]; - - dist = VectorNormalize2D( dir ); - - total_dist = dist + Node->g; - - path->point[ 0 ] = path_end[ 0 ]; - path->point[ 1 ] = path_end[ 1 ]; - path->point[ 2 ] = path_end[ 2 ]; - - ParentNode = Node->Parent; - if( ParentNode ) - { - pathway = &ParentNode->Child[ Node->pathway ]; - - path->dir[ 0 ] = path_end[ 0 ] - pathway->pos2[ 0 ]; - path->dir[ 1 ] = path_end[ 1 ] - pathway->pos2[ 1 ]; - path->dist = VectorNormalize2D( path->dir ); - - if( path->dist ) - { - path->bAccurate = false; - current_path = path + 1; - } - - if( pathway->dist ) - { - VectorCopy( pathway->pos2, current_path->point ); - current_path->dir[ 0 ] = pathway->dir[ 0 ]; - current_path->dir[ 1 ] = pathway->dir[ 1 ]; - current_path->dist = pathway->dist; - current_path->bAccurate = true; - current_path++; - } - - for( Node = ParentNode, ParentNode = ParentNode->Parent; ParentNode != NULL; Node = ParentNode, ParentNode = ParentNode->Parent ) - { - pathway = &ParentNode->Child[ Node->pathway ]; - if( pathway->dist ) - { - VectorCopy( pathway->pos2, current_path->point ); - current_path->dir[ 0 ] = pathway->dir[ 0 ]; - current_path->dir[ 1 ] = pathway->dir[ 1 ]; - current_path->dist = pathway->dist; - current_path->bAccurate = true; - current_path++; - } - } - - VectorCopy( pathway->pos1, current_path->point ); - current_path->dir[ 0 ] = path_startdir[ 0 ]; - current_path->dir[ 1 ] = path_startdir[ 1 ]; - current_path->dist = Node->g; - } - else - { - path->dir[ 0 ] = path_totaldir[ 0 ]; - path->dir[ 1 ] = path_totaldir[ 1 ]; - path->dist = Node->h; - } - - if( current_path->dist ) - { - current_path->bAccurate = false; - current_path++; - - VectorCopy( path_start, current_path->point ); - current_path->dist = 0; - VectorClear2D( current_path->dir ); - } - - current_path->bAccurate = false; - return current_path; + if (iAvailableTime) { + return NULL; + } else { + return pLastClaimer; + } } -PathInfo *PathSearch::GeneratePathNear - ( - PathInfo *path - ) +void PathNode::Relinquish(void) { - PathInfo *current_path = path; - pathway_t *pathway; - PathNode *ParentNode; - - total_dist = Node->g; - VectorCopy( Node->m_PathPos, path->point ); - - ParentNode = Node->Parent; - if( ParentNode ) - { - pathway = &ParentNode->Child[ Node->pathway ]; - - if( pathway->dist ) - { - VectorCopy( pathway->pos2, path->point ); - path->dir[ 0 ] = pathway->dir[ 0 ]; - path->dir[ 1 ] = pathway->dir[ 1 ]; - path->dist = pathway->dist; - - current_path->bAccurate = true; - current_path++; - } - - for( Node = ParentNode, ParentNode = ParentNode->Parent; ParentNode != NULL; Node = ParentNode, ParentNode = ParentNode->Parent ) - { - pathway = &ParentNode->Child[ Node->pathway ]; - if( pathway->dist ) - { - VectorCopy( pathway->pos2, current_path->point ); - current_path->dir[ 0 ] = pathway->dir[ 0 ]; - current_path->dir[ 1 ] = pathway->dir[ 1 ]; - current_path->dist = pathway->dist; - current_path->bAccurate = true; - current_path++; - } - } - - VectorCopy( pathway->pos1, current_path->point ); - current_path->dir[ 0 ] = path_startdir[ 0 ]; - current_path->dir[ 1 ] = path_startdir[ 1 ]; - - current_path->dist = Node->g; - } - else - { - path->dir[ 0 ] = path_totaldir[ 0 ]; - path->dir[ 1 ] = path_totaldir[ 1 ]; - path->dist = Node->h; - } - - if( current_path->dist ) - { - current_path->bAccurate = false; - current_path++; - - VectorCopy( path_start, current_path->point ); - current_path->dist = 0; - VectorClear2D( current_path->dir ); - } - - current_path->bAccurate = false; - return current_path; + iAvailableTime = level.inttime + 4000; } -PathInfo *PathSearch::GeneratePathAway - ( - PathInfo *path - ) +bool PathNode::IsClaimedByOther(Entity *pPossibleClaimer) const { - PathInfo *current_path = path; - pathway_t *pathway; - PathNode *ParentNode; + if (pLastClaimer == pPossibleClaimer) { + return false; + } - VectorCopy( Node->m_PathPos, path->point ); - - ParentNode = Node->Parent; - if( ParentNode ) - { - pathway = &ParentNode->Child[ Node->pathway ]; - - if( pathway->dist ) - { - VectorCopy( pathway->pos2, path->point ); - path->dir[ 0 ] = pathway->dir[ 0 ]; - path->dir[ 1 ] = pathway->dir[ 1 ]; - path->dist = pathway->dist; - - current_path->bAccurate = true; - current_path++; - } - - for( Node = ParentNode, ParentNode = ParentNode->Parent; ParentNode != NULL; Node = ParentNode, ParentNode = ParentNode->Parent ) - { - pathway = &ParentNode->Child[ Node->pathway ]; - if( pathway->dist ) - { - VectorCopy( pathway->pos2, current_path->point ); - current_path->dir[ 0 ] = pathway->dir[ 0 ]; - current_path->dir[ 1 ] = pathway->dir[ 1 ]; - current_path->dist = pathway->dist; - current_path->bAccurate = true; - current_path++; - } - } - - VectorCopy( pathway->pos1, current_path->point ); - current_path->dir[ 0 ] = path_startdir[ 0 ]; - current_path->dir[ 1 ] = path_startdir[ 1 ]; - - current_path->dist = Node->g; - - if( Node->g ) - { - current_path->bAccurate = false; - current_path++; - VectorCopy( path_start, current_path->point ); - current_path->dist = 0; - VectorClear2D( current_path->dir ); - } - } - else - { - VectorClear2D( path->dir ); - path->dist = 0; - } - - current_path->bAccurate = false; - return current_path; + if (iAvailableTime) { + return (level.inttime < iAvailableTime); + } else { + return (pLastClaimer != NULL); + } } -PathNode *PathSearch::GetSpawnNode - ( - ClassDef *cls - ) +void PathNode::MarkTemporarilyBad(void) { - if( m_bNodesloaded ) - { - return pathnodes[ m_LoadIndex++ ]; - } - else - { - // Otherwise create a new node - return ( PathNode * )cls->newInstance(); - } + iAvailableTime = level.inttime + 5000; + pLastClaimer = NULL; } -int PathSearch::FindPath - ( - float *start, - float *end, - Entity *ent, - float maxPath, - float *vLeashHome, - float fLeashDistSquared, - int fallheight - ) +void PathNode::Archive(Archiver& arc) {} + +void PathNode::ArchiveStatic(Archiver& arc) { - int i; - int g; - PathNode *NewNode; - pathway_t *pathway; - PathNode *prev; - PathNode *next; - int f; - vec2_t delta; - PathNode *to; + arc.ArchiveVector(&origin); + arc.ArchiveVector(¢roid); + arc.ArchiveInteger(&nodeflags); + arc.ArchiveInteger(&virtualNumChildren); - if( ent ) - { - if( ent->IsSubclassOfActor() ) - { - Node = NearestStartNode( start, ( SimpleActor * )ent ); - } - else - { - Node = DebugNearestStartNode( start, ent ); - } - } - else - { - Node = DebugNearestStartNode( start ); - } + numChildren = virtualNumChildren; - if( !Node ) - { - last_error = "couldn't find start node"; - return 0; - } + if (arc.Loading()) { + bulkNavMemory -= virtualNumChildren * sizeof(pathway_t) * sizeof(pathway_t *); + Child = virtualNumChildren ? (pathway_t *)bulkNavMemory : NULL; + } - to = NearestEndNode( end ); - if( !to ) - { - last_error = "couldn't find end node"; - return 0; - } + for (int i = 0; i < virtualNumChildren; i++) { + arc.ArchiveShort(&Child[i].node); + arc.ArchiveShort(&Child[i].fallheight); + arc.ArchiveFloat(&Child[i].dist); + arc.ArchiveVec2(Child[i].dir); + arc.ArchiveVec3(Child[i].pos1); + arc.ArchiveVec3(Child[i].pos2); - total_dist = 9e+11f; + if (arc.Loading()) { + Child[i].numBlockers = 0; - if( !maxPath ) - maxPath = 9e+11f; - - findFrame++; - open = NULL; - - path_startdir[ 0 ] = Node->origin[ 0 ] - start[ 0 ]; - path_startdir[ 1 ] = Node->origin[ 1 ] - start[ 1 ]; - - Node->g = VectorNormalize2D( path_startdir ); - - path_totaldir[ 0 ] = end[ 0 ] - start[ 0 ]; - path_totaldir[ 1 ] = end[ 1 ] - start[ 1 ]; - - Node->h = VectorNormalize2D( path_totaldir ); - Node->inopen = true; - Node->Parent = NULL; - Node->m_Depth = 3; - Node->m_PathPos = start; - Node->findCount = findFrame; - Node->PrevNode = NULL; - Node->NextNode = NULL; - - open = Node; - - while( 1 ) - { - Node = open; - Node->inopen = false; - - open = Node->NextNode; - if( open ) - open->PrevNode = NULL; - - if( Node == to ) - break; - - for( i = Node->numChildren - 1; i >= 0; i-- ) - { - vec2_t vDist; - - pathway = &Node->Child[ i ]; - - NewNode = pathnodes[ pathway->node ]; - - if( vLeashHome ) - { - vDist[ 0 ] = pathway->pos2[ 0 ] - vLeashHome[ 0 ]; - vDist[ 1 ] = pathway->pos2[ 1 ] - vLeashHome[ 1 ]; - } - - if( !vLeashHome || VectorLength2DSquared( vDist ) <= fLeashDistSquared ) - { - g = ( int )( pathway->dist + Node->g + 1.0f ); - - if( NewNode->findCount == findFrame ) - { - if( g >= NewNode->g ) - continue; - - if( NewNode->inopen ) - { - NewNode->inopen = false; - next = NewNode->NextNode; - prev = NewNode->PrevNode; - - if( next ) - next->PrevNode = prev; - - if( prev ) - prev->NextNode = next; - else - open = next; - } - } - - delta[ 0 ] = end[ 0 ] - pathway->pos2[ 0 ]; - delta[ 1 ] = end[ 1 ] - pathway->pos2[ 1 ]; - - NewNode->h = VectorLength2D( delta ); - - f = ( int )( ( float )g + NewNode->h ); - - if( f >= maxPath ) - { - last_error = "specified path distance exceeded"; - return 0; - } - - if( pathway->fallheight <= fallheight ) - { - NewNode->f = f; - NewNode->pathway = i; - NewNode->g = g; - NewNode->Parent = Node; - NewNode->m_Depth = Node->m_Depth + 1; - NewNode->inopen = true; - NewNode->m_PathPos = pathway->pos2; - NewNode->findCount = findFrame; - - if( !open ) - { - NewNode->NextNode = NULL; - NewNode->PrevNode = NULL; - open = NewNode; - continue; - } - - if( open->f >= f ) - { - NewNode->PrevNode = NULL; - NewNode->NextNode = open; - - open->PrevNode = NewNode; - open = NewNode; - continue; - } - - prev = open; - next = open->NextNode; - while( next && next->f < f ) - { - prev = next; - next = next->NextNode; - } - - NewNode->NextNode = next; - if( next ) - next->PrevNode = NewNode; - prev->NextNode = NewNode; - NewNode->PrevNode = prev; - } - } - } - - if( !open ) - { - last_error = "unreachable path"; - return 0; - } - } - - path_start = start; - path_end = end; - - return Node->m_Depth; + for (int j = 0; j < ARRAY_LEN(Child[i].badPlaceTeam); j++) { + Child[i].badPlaceTeam[j] = 0; + } + } + } } -int PathSearch::FindPathAway - ( - float *start, - float *avoid, - float *vPreferredDir, - Entity *ent, - float fMinSafeDist, - float *vLeashHome, - float fLeashDistSquared, - int fallheight - ) +void PathNode::ArchiveDynamic(Archiver& arc) { - int i; - int g; - PathNode *NewNode; - pathway_t *pathway; - PathNode *prev; - PathNode *next; - int f; - float fBias; - vec2_t delta; - float fMinSafeDistSquared = fMinSafeDist * fMinSafeDist; + SimpleEntity::SimpleArchive(arc); - if( ent ) - { - if( ent->IsSubclassOfActor() ) - { - Node = NearestStartNode( start, ( SimpleActor * )ent ); - } - else - { - Node = DebugNearestStartNode( start, ent ); - } - } - else - { - Node = DebugNearestStartNode( start ); - } + arc.ArchiveObjectPosition(this); + arc.ArchiveSafePointer(&pLastClaimer); + arc.ArchiveInteger(&iAvailableTime); + arc.ArchiveInteger(&numChildren); - if( !Node ) - { - last_error = "couldn't find start node"; - return 0; - } - - findFrame++; - open = NULL; - - path_startdir[ 0 ] = Node->origin[ 0 ] - start[ 0 ]; - path_startdir[ 1 ] = Node->origin[ 1 ] - start[ 1 ]; - - delta[ 0 ] = start[ 0 ] - avoid[ 0 ]; - delta[ 1 ] = start[ 1 ] - avoid[ 1 ]; - - fBias = VectorLength2D( vPreferredDir ); - - Node->inopen = true; - Node->g = VectorNormalize2D( path_startdir ); - Node->h = fMinSafeDist - VectorNormalize2D( delta ); - Node->h += fBias - DotProduct2D( vPreferredDir, delta ); - Node->Parent = NULL; - Node->m_Depth = 2; - Node->findCount = findFrame; - Node->PrevNode = NULL; - Node->NextNode = NULL; - Node->m_PathPos = start; - - open = Node; - - while( 1 ) - { - Node = open; - Node->inopen = false; - - open = Node->NextNode; - - if( open ) - open->PrevNode = NULL; - - delta[ 0 ] = Node->m_PathPos[ 0 ] - avoid[ 0 ]; - delta[ 1 ] = Node->m_PathPos[ 1 ] - avoid[ 1 ]; - - if( VectorLength2DSquared( delta ) >= fMinSafeDistSquared ) - break; - - for( i = Node->numChildren - 1; i >= 0; i-- ) - { - vec2_t vDist; - - pathway = &Node->Child[ i ]; - NewNode = pathnodes[ pathway->node ]; - - if( vLeashHome ) - { - vDist[ 0 ] = pathway->pos2[ 0 ] - vLeashHome[ 0 ]; - vDist[ 1 ] = pathway->pos2[ 1 ] - vLeashHome[ 1 ]; - } - - if( !vLeashHome || VectorLength2DSquared( vDist ) <= fLeashDistSquared ) - { - g = ( int )( pathway->dist + Node->g + 1.0f ); - - if( NewNode->findCount == findFrame ) - { - if( g >= NewNode->g ) - continue; - - if( NewNode->inopen ) - { - NewNode->inopen = false; - next = NewNode->NextNode; - prev = NewNode->PrevNode; - - if( next ) - next->PrevNode = prev; - - if( prev ) - prev->NextNode = next; - else - open = next; - } - } - - delta[ 0 ] = pathway->pos2[ 0 ] - avoid[ 0 ]; - delta[ 1 ] = pathway->pos2[ 1 ] - avoid[ 1 ]; - - NewNode->h = fMinSafeDist - VectorNormalize2D( delta ); - f = NewNode->h + fBias - DotProduct2D( vPreferredDir, delta ); - NewNode->h += f; - - if( pathway->fallheight <= fallheight ) - { - NewNode->Parent = Node; - NewNode->m_Depth = Node->m_Depth + 1; - NewNode->g = g; - NewNode->pathway = i; - NewNode->inopen = true; - NewNode->m_PathPos = pathway->pos2; - NewNode->findCount = findFrame; - NewNode->f = f; - - if( !open ) - { - NewNode->NextNode = NULL; - NewNode->PrevNode = NULL; - open = NewNode; - continue; - } - - if( open->f >= f ) - { - NewNode->PrevNode = NULL; - NewNode->NextNode = open; - - open->PrevNode = NewNode; - open = NewNode; - continue; - } - - prev = open; - next = open->NextNode; - while( next && next->f < f ) - { - prev = next; - next = next->NextNode; - } - - NewNode->NextNode = next; - if( next ) - next->PrevNode = NewNode; - prev->NextNode = NewNode; - NewNode->PrevNode = prev; - } - } - } - - if( !open ) - { - last_error = "unreachable path"; - return 0; - } - } - - path_start = start; - return Node->m_Depth; + if (numChildren != virtualNumChildren) { + for (int i = 0; i < virtualNumChildren; i++) { + arc.ArchiveByte(&Child[i].numBlockers); + arc.ArchiveShort(&Child[i].node); + arc.ArchiveShort(&Child[i].fallheight); + arc.ArchiveFloat(&Child[i].dist); + arc.ArchiveVec2(Child[i].dir); + arc.ArchiveVec3(Child[i].pos1); + arc.ArchiveVec3(Child[i].pos2); + } + } } -int PathSearch::FindPathNear - ( - float *start, - float *end, - Entity *ent, - float maxPath, - float fRadiusSquared, - float *vLeashHome, - float fLeashDistSquared, - int fallheight - ) +int PathSearch::NearestNodeSetup(const vec3_t pos, MapCell *cell, int *nodes, vec3_t *deltas) { - int i; - int g; - PathNode *NewNode; - pathway_t *pathway; - PathNode *prev; - PathNode *next; - int f; - vec2_t dir; - vec2_t delta; + vec3_t delta; + PathNode *node; + float dist; + int n = 0; + int i; + int j; + float node_dist[128]; + int node_count; - if( ent ) - { - if( ent->IsSubclassOfActor() ) - { - Node = NearestStartNode( start, ( SimpleActor * )ent ); - } - else - { - Node = DebugNearestStartNode( start, ent ); - } - } - else - { - Node = DebugNearestStartNode( start ); - } + node_count = cell->numnodes; - if( !Node ) - { - last_error = "no start node"; - return 0; - } + for (i = 0; i < node_count; i++) { + node = pathnodes[cell->nodes[i]]; + if (!node) { + continue; + } - total_dist = 9e11f; + if (pos[2] > node->origin[2] + 94.0f) { + continue; + } - if( !maxPath ) - maxPath = 9e11f; + if (pos[2] + 94.0f < node->origin[2]) { + continue; + } - findFrame++; - open = NULL; + VectorSubtract(node->origin, pos, delta); + VectorCopy(delta, deltas[i]); - path_startdir[ 0 ] = Node->origin[ 0 ] - start[ 0 ]; - path_startdir[ 1 ] = Node->origin[ 1 ] - start[ 1 ]; + dist = VectorLengthSquared(delta); - dir[ 0 ] = end[ 0 ] - start[ 0 ]; - dir[ 1 ] = end[ 1 ] - start[ 1 ]; + for (j = n; j > 0; j--) { + if (dist >= node_dist[j - 1]) { + break; + } - Node->inopen = true; - Node->g = VectorNormalize2D( path_startdir ); - Node->h = VectorNormalize2D( delta ); - Node->Parent = NULL; - Node->m_Depth = 3; - Node->findCount = findFrame; - Node->PrevNode = NULL; - Node->NextNode = NULL; - Node->m_PathPos = start; + node_dist[j] = node_dist[j - 1]; + nodes[j] = nodes[j - 1]; + } - open = Node; + n++; + nodes[j] = i; + node_dist[j] = dist; + } - while( 1 ) - { - Node = open; - Node->inopen = false; - - open = Node->NextNode; - - if( open ) - open->PrevNode = NULL; - - delta[ 0 ] = end[ 0 ] - Node->m_PathPos[ 0 ]; - delta[ 1 ] = end[ 1 ] - Node->m_PathPos[ 1 ]; - - if( fRadiusSquared >= VectorLength2DSquared( delta ) ) - break; - - for( i = Node->numChildren - 1; i >= 0; i-- ) - { - pathway = &Node->Child[ i ]; - NewNode = pathnodes[ pathway->node ]; - - g = ( int )( pathway->dist + Node->g + 1.0f ); - - if( NewNode->findCount == findFrame ) - { - if( g >= NewNode->g ) - continue; - - if( NewNode->inopen ) - { - NewNode->inopen = false; - next = NewNode->NextNode; - prev = NewNode->PrevNode; - - if( next ) - next->PrevNode = prev; - - if( prev ) - prev->NextNode = next; - else - open = next; - } - } - - delta[ 0 ] = end[ 0 ] - pathway->pos2[ 0 ]; - delta[ 1 ] = end[ 1 ] - pathway->pos2[ 1 ]; - - NewNode->h = VectorLength2D( delta ); - f = ( int )( ( float )g + NewNode->h ); - - if( f >= maxPath ) - { - last_error = "specified path distance exceeded"; - return 0; - } - - if( pathway->fallheight <= fallheight ) - { - NewNode->f = f; - NewNode->pathway = i; - NewNode->g = g; - NewNode->Parent = Node; - NewNode->m_Depth = Node->m_Depth + 1; - NewNode->inopen = true; - NewNode->m_PathPos = pathway->pos2; - NewNode->findCount = findFrame; - - if( !open ) - { - NewNode->NextNode = NULL; - NewNode->PrevNode = NULL; - open = NewNode; - continue; - } - - if( open->f >= f ) - { - NewNode->PrevNode = NULL; - NewNode->NextNode = open; - - open->PrevNode = NewNode; - open = NewNode; - continue; - } - - prev = open; - next = open->NextNode; - while( next && next->f < f ) - { - prev = next; - next = next->NextNode; - } - - NewNode->NextNode = next; - if( next ) - next->PrevNode = NewNode; - prev->NextNode = NewNode; - NewNode->PrevNode = prev; - } - } - - if( !open ) - { - last_error = "unreachable path"; - return 0; - } - } - - path_start = start; - path_end = end; - return Node->m_Depth; + return n; } -int node_compare(const void *pe1, const void *pe2) +PathNode *PathSearch::FindNearestCover(Entity *pEnt, Vector& vPos, Entity *pEnemy) { - nodeinfo *Pe1 = (nodeinfo *) pe1; - nodeinfo *Pe2 = (nodeinfo *) pe2; - int iConcealment; - - iConcealment = (Pe1->pNode->nodeflags & 0xB0) != 0; - if (Pe2->pNode->nodeflags & 0xB0) - --iConcealment; - return ((Pe1->fDistSquared) - + (iConcealment << 23) - + (((Pe1->pNode->nodeflags & 8) - (Pe2->pNode->nodeflags & 8)) << 21) - - (Pe2->fDistSquared)); - -} -PathNode *PathSearch::FindCornerNodeForWall - ( - float *start, - float *end, - SimpleActor *ent, - float maxPath, - float *plane - ) -{ - PathNode *ParentNode; - PathNode *OpenNode; - int i; - - Node = NearestStartNode(start, ent); - if (!Node) - { - last_error = "couldn't find start node"; - return NULL; - } - - if (DotProduct(start, plane) - plane[3] < 0.0) - { - last_error = "starting point is already behind the wall"; - return NULL; - } - - if (DotProduct(plane, end) - plane[3] > 0.0) - { - last_error = "end point is in front of the wall"; - return NULL; - } - - total_dist = 1.0e12f; - - if (maxPath == 0.0) - maxPath = 1.0e12f; - - findFrame++; - open = NULL; - - VectorSub2D(Node->origin, start, path_startdir); - Node->g = VectorNormalize2D(path_startdir); - - VectorSub2D(end, start, path_totaldir); - Node->h = VectorNormalize2D(path_totaldir); - - Node->inopen = true; - - Node->Parent = NULL; - - Node->m_Depth = 3; - Node->m_PathPos = start; - Node->findCount = findFrame; - Node->PrevNode = 0; - Node->NextNode = 0; - - OpenNode = Node; - open = Node; - - if (!open) - { - last_error = "unreachable path"; - return NULL; - } - - while (true) - { - Node = OpenNode; - - Node->inopen = false; - - open = Node->NextNode; - if (open) - { - open->PrevNode = NULL; - } - - ParentNode = Node->Parent; - - if (ParentNode - && DotProduct(plane, Node->m_PathPos) - plane[3] < 0.0) - { - vec2_t delta; - VectorSub2D(ParentNode->m_PathPos, start, delta); - if (VectorLength2DSquared(delta) < Square(16)) - ParentNode = Node; - return ParentNode; - } - - i = Node->numChildren; - if (i) - break; -weird_lbl: - OpenNode = open; - if (!OpenNode) - { - last_error = "unreachable path"; - return NULL; - } - } - - int f, g, h; - while (true) - { - pathway_t *pathway = &Node->Child[--i]; - PathNode *pSomeNode = PathSearch::pathnodes[pathway->node]; - g = (pathway->dist + Node->g + 1.0); - if (pSomeNode->findCount == PathSearch::findFrame) - { - if (g >= pSomeNode->g) - { - if (i == 0) - goto weird_lbl; - - continue; - } - if (pSomeNode->inopen) - { - pSomeNode->inopen = false; - - if (pSomeNode->NextNode) - pSomeNode->NextNode->PrevNode = pSomeNode->PrevNode; - if (pSomeNode->PrevNode) - pSomeNode->PrevNode->NextNode = pSomeNode->NextNode; - else - PathSearch::open = pSomeNode->NextNode; - } - } - - vec2_t vDelta2; - VectorSub2D(end, pathway->pos1, vDelta2); - pSomeNode->h = h = VectorLength2D(vDelta2); - - f = (h + g); - - if (f >= maxPath) - break; - - pSomeNode->f = f; - pSomeNode->pathway = i; - pSomeNode->g = g; - pSomeNode->Parent = Node; - pSomeNode->inopen = true; - pSomeNode->m_PathPos = pathway->pos2; - pSomeNode->findCount = PathSearch::findFrame; - pSomeNode->m_Depth = Node->m_Depth + 1; - - if (!PathSearch::open) - { - pSomeNode->NextNode = NULL; - pSomeNode->PrevNode = NULL; - PathSearch::open = pSomeNode; - if (i == 0) - goto weird_lbl; - - continue; - } - - if (PathSearch::open->f == f) - { - pSomeNode->PrevNode = NULL; - pSomeNode->NextNode = PathSearch::open; - PathSearch::open->PrevNode = pSomeNode; - PathSearch::open = pSomeNode; - if (i == 0) - goto weird_lbl; - - continue; - } - PathNode * pNextOpenNode = PathSearch::open->NextNode; - if (pNextOpenNode) - { - if (f > pNextOpenNode->f) - { - do - { - pNextOpenNode = pNextOpenNode->NextNode; - if (!pNextOpenNode) - break; - - } while (f > pNextOpenNode->f); - } - } - - pSomeNode->NextNode = pNextOpenNode; - - if (pNextOpenNode) - pNextOpenNode->PrevNode = pSomeNode; - - pNextOpenNode->NextNode = pSomeNode; - pSomeNode->PrevNode = pNextOpenNode; - - if (i == 0) - goto weird_lbl; - } - PathSearch::last_error = "specified path distance exceeded"; - return NULL; + // not found in ida + return NULL; } -PathNode *PathSearch::FindCornerNodeForExactPath - ( - SimpleActor *pSelf, - Sentient *enemy, - float fMaxPath - ) +//=============== +// Added in OPM +//=============== + +Event EV_NavMaster_CreatePaths +( + "nav_build", + EV_CHEAT, + NULL, + NULL, + "Build navigation path" +); +Event EV_NavMaster_SpawnNode +( + "nav_create", + EV_CHEAT, + "S", + "type", + "Create a new node at the player's origin" +); +Event EV_NavMaster_SetNodeFlags +( + "nav_node_set_type", + EV_CHEAT, + "sSS", + "type1 type2 ...", + "Set the selected node type. Type can be one of the following values:\n" + "- corner_left\n" + "- corner_right\n" + "- duck\n" + "- sniper\n" + "- concealment\n" + "- cover\n" + "- crate\n" + "- none\n" +); +Event EV_NavMaster_SetNodeTargetName +( + "nav_node_set_targetname", + EV_CHEAT, + "S", + "targetname", + "Set the selected node target name" +); +Event EV_NavMaster_SetNodeTarget +( + "nav_node_set_target", + EV_CHEAT, + "S", + "target", + "Set the selected node target" +); +Event EV_NavMaster_RemoveNode +( + "nav_node_remove", + EV_CHEAT, + NULL, + NULL, + "Delete the selected node" +); + +CLASS_DECLARATION(Listener, NavMaster, NULL) { + {&EV_NavMaster_CreatePaths, &NavMaster::CreatePaths }, + {&EV_NavMaster_SpawnNode, &NavMaster::CreateNode }, + {&EV_NavMaster_SetNodeFlags, &NavMaster::SetNodeFlags }, + {&EV_NavMaster_SetNodeTargetName, &NavMaster::SetNodeTargetName}, + {&EV_NavMaster_SetNodeTarget, &NavMaster::SetNodeTarget }, + {&EV_NavMaster_RemoveNode, &NavMaster::RemoveNode }, + {NULL, NULL } +}; + +NavMaster navMaster; + +NavMaster::NavMaster() {} + +void NavMaster::Init() { - PathNode *pPathNode[4096]; + G_CreateMaster("nav", this); - if (!PathSearch::FindPath(enemy->origin, pSelf->origin, pSelf, fMaxPath, 0, 0.0, 100)) - return NULL; - - size_t iDepth = 0; - for (PathNode* pParentNode = Node->Parent; pParentNode; pParentNode = pParentNode->Parent, iDepth++) - { - pPathNode[iDepth] = pParentNode; - } - - Node = pPathNode[iDepth -1]; - - - if (iDepth == 0) - { - return NULL; - } - size_t i; - for (i = 0; i < iDepth; i += 2) - { - if (!G_SightTrace( - pSelf->EyePosition(), - vec_zero, - vec_zero, - pSelf->EyePosition() - pSelf->origin + pPathNode[i]->m_PathPos, - pSelf, - enemy, - 0x2040B19, - 0, - "FindCornerNodeFoExactPath 1")) - { - break; - } - } - - size_t index = i - 1; - if (index < iDepth) - { - if (index) - { - if (!G_SightTrace( - pSelf->EyePosition(), - vec_zero, - vec_zero, - pSelf->EyePosition() - pSelf->origin + pPathNode[i]->m_PathPos, - pSelf, - enemy, - 0x2040B19, - 0, - "FindCornerNodeFoExactPath 2")) - { - index--; - } - } - } - else - { - index = iDepth - 1; - } - - return pPathNode[index]; + if (ai_editmode->integer) { + // show routes by default + gi.cvar_set("ai_showroutes", "1"); + gi.cvar_set("ai_shownode", "30"); + } } -int PathSearch::FindPotentialCover - ( - SimpleActor *pEnt, - Vector& vPos, - Entity *pEnemy, - PathNode **ppFoundNodes, - int iMaxFind - ) +void NavMaster::CreatePaths(Event *ev) { - Actor *pSelf = (Actor *)pEnt; - PathNode *pNode; - Vector delta; - int nNodes = 0; - nodeinfo nodes[MAX_PATHNODES]; - - for (int i = 0; i < nodecount; i++) - { - pNode = pathnodes[i]; - if (pNode && pNode->nodeflags & AI_SNIPER) - { - if (pNode->pLastClaimer == pSelf || (pNode->iAvailableTime && level.inttime >= pNode->iAvailableTime) || (pNode->pLastClaimer == NULL)) - { - delta = pNode->origin - pSelf->m_vHome; - if (delta.lengthSquared() <= pSelf->m_fLeashSquared) - { - delta = pNode->origin - pEnemy->origin; - if (delta.lengthSquared() >= pSelf->m_fMinDistanceSquared && delta.lengthSquared() <= pSelf->m_fMaxDistanceSquared) - { - delta = pNode->origin - pSelf->origin; - nodes[nNodes].pNode = pNode; - nodes[nNodes].fDistSquared = delta.lengthSquared(); - nNodes++; - } - } - } - } - } - - if (nNodes) - { - qsort(nodes, nNodes, sizeof(nodeinfo), node_compare); - - if (nNodes > iMaxFind) - nNodes = iMaxFind; - - if (nNodes > 0) - { - pNode = ppFoundNodes[nNodes - 1]; - - for (int i = 0; i < nNodes; i++) - { - pNode = nodes[i].pNode; - pNode--; - } - } - - } - return nNodes; + if (!ai_editmode->integer) { + return; + } + PathSearch::ClearNodes(); + PathSearch::CreatePaths(); } -void PathSearch::PlayerCover - ( - Player *pPlayer - ) +void NavMaster::CreateNode(Event *ev) { - int i; - PathNode *node; - Vector delta; - Entity *pOwner; + str type; + int spawnflags = 0; + PathNode *node; + Entity *ent; - for( i = 0; i < nodecount; i++ ) - { - node = pathnodes[ i ]; + if (ev->NumArgs() > 0) { + type = ev->GetString(1); + spawnflags = GetNodeTypeFromName(type); + if (spawnflags == -1) { + ScriptError("Unrecognized node type '%s'", type.c_str()); + } + } - if( !node || !( node->nodeflags & AI_COVERFLAGS ) ) - continue; + ent = g_entities->entity; + if (!ent) { + return; + } - pOwner = node->GetClaimHolder(); + node = new PathNode; - delta = node->origin - pPlayer->origin; - - // Check if we need to cover - if( VectorLengthSquared( delta ) > 2304.0f ) - { - if( pOwner == pPlayer ) - node->Relinquish(); - - continue; - } - - if( pOwner != pPlayer ) - { - if( pOwner ) - pOwner->PathnodeClaimRevoked( node ); - - // Player claim the node - node->Claim( pPlayer ); - } - } + node->nodeflags = spawnflags; + node->setOrigin(ent->origin); } -PathNode *PathSearch::FindNearestCover - ( - SimpleActor *pEnt, - Vector& vPos, - Entity *pEnemy - ) +void NavMaster::SetNodeFlags(Event *ev) { - // not found in ida - return NULL; + str type; + str typelist; + int spawnflags; + int i; + + CheckNodeSelected(); + + if (ev->NumArgs() < 1) { + ScriptError("A type is required"); + return; + } + + spawnflags = 0; + + for (i = 1; i <= ev->NumArgs(); i++) { + int flags; + + type = ev->GetString(i); + + flags = GetNodeTypeFromName(type); + if (flags == -1) { + ScriptError("Unrecognized node type '%s'", type.c_str()); + } + + spawnflags |= flags; + + if (i != 1) { + typelist += ", "; + } + typelist += "'" + type + "'"; + } + + selectedNode->nodeflags = spawnflags; + + gi.Printf("Node %d set type %s\n", selectedNode->nodenum, typelist.c_str()); } -PathNode *PathSearch::FindNearestSniperNode - ( - SimpleActor *pEnt, - Vector& vPos, - Entity *pEnemy - ) +void NavMaster::SetNodeTargetName(Event *ev) { - Actor *pSelf = (Actor *)pEnt; - PathNode *pNode; - Vector delta; - int nNodes = 0; - nodeinfo nodes[MAX_PATHNODES]; - - for (int i = 0; i < nodecount; i++) - { - pNode = pathnodes[i]; - if (pNode && pNode->nodeflags & AI_SNIPER) - { - if (pNode->pLastClaimer == pSelf || (pNode->iAvailableTime && level.inttime >= pNode->iAvailableTime) || (pNode->pLastClaimer == NULL)) - { - delta = pNode->origin - pSelf->m_vHome; - if (delta.lengthSquared() <= pSelf->m_fLeashSquared) - { - delta = pNode->origin - pEnemy->origin; - if (delta.lengthSquared() >= pSelf->m_fMinDistanceSquared && delta.lengthSquared() <= pSelf->m_fMaxDistanceSquared) - { - delta = pNode->origin - pSelf->origin; - nodes[nNodes].pNode = pNode; - nodes[nNodes].fDistSquared = delta.lengthSquared(); - nNodes++; - } - } - } - } - } + CheckNodeSelected(); - if (nNodes == 0) - { - return NULL; - } + selectedNode->targetname = ev->GetString(1); - qsort(nodes, nNodes, sizeof(nodeinfo), node_compare); - - if (nNodes <= 0) - return NULL; - - for (int i = 0; i < nNodes; i++) - { - pNode = nodes[i].pNode; - if (pSelf->CanSeeFrom(pSelf->EyePosition() + pNode->origin, pEnemy)) - { - return pNode; - } - - pNode->iAvailableTime = level.inttime + 5000; - pNode->pLastClaimer = NULL; - } - - return NULL; + gi.Printf("Node %d got new targetname '%s'\n", selectedNode->nodenum, selectedNode->targetname.c_str()); } -int PathSearch::NearestNodeSetup - ( - vec3_t pos, - MapCell *cell, - int *nodes, - vec3_t *deltas - ) +void NavMaster::SetNodeTarget(Event *ev) { - vec3_t delta; - PathNode *node; - float dist; - int n = 0; - int i; - int j; - float node_dist[ 128 ]; - int node_count; + CheckNodeSelected(); - node_count = cell->numnodes; + selectedNode->target = ev->GetString(1); - for( i = 0; i < node_count; i++ ) - { - node = pathnodes[ cell->nodes[ i ] ]; - - if( pos[ 2 ] > node->origin[ 2 ] + 94.0f ) - continue; - - if( node->origin[ 2 ] > pos[ 2 ] + 94.0f ) - continue; - - delta[ 0 ] = node->origin[ 0 ] - pos[ 0 ]; - delta[ 1 ] = node->origin[ 1 ] - pos[ 1 ]; - delta[ 2 ] = node->origin[ 2 ] - pos[ 2 ]; - - VectorCopy( delta, deltas[ i ] ); - - dist = VectorLengthSquared( delta ); - - for( j = n; j > 0; j-- ) - { - if( dist >= node_dist[ j - 1 ] ) - break; - - node_dist[ j ] = node_dist[ j - 1 ]; - nodes[ j ] = nodes[ j - 1 ]; - } - - n++; - nodes[ j ] = i; - node_dist[ j ] = dist; - } - - return n; + gi.Printf("Node %d got new target '%s'\n", selectedNode->nodenum, selectedNode->target.c_str()); } -void PathSearch::Init - ( - void - ) +void NavMaster::RemoveNode(Event *ev) { - ai_showroutes = gi.Cvar_Get( "ai_showroutes", "0", 0 ); - ai_showroutes_distance = gi.Cvar_Get( "ai_showroutes_distance", "1000", 0 ); - ai_shownodenums = gi.Cvar_Get( "ai_shownodenums", "0", 0 ); - ai_shownode = gi.Cvar_Get( "ai_shownode", "0", 0 ); - ai_showallnode = gi.Cvar_Get( "ai_showallnode", "0", 0 ); - ai_showpath = gi.Cvar_Get( "ai_showpath", "0", 0 ); - ai_fallheight = gi.Cvar_Get( "ai_fallheight", "96", 0 ); - ai_debugpath = gi.Cvar_Get( "ai_debugpath", "0", 0 ); - ai_pathchecktime = gi.Cvar_Get( "ai_pathchecktime", "1.5", CVAR_CHEAT ); - ai_pathcheckdist = gi.Cvar_Get( "ai_pathcheckdist", "4096", CVAR_CHEAT ); + str targetname; + int num; + + CheckNodeSelected(); + + num = selectedNode->nodenum; + targetname = selectedNode->targetname; + AI_RemoveNode(selectedNode); + + gi.Printf("Node %d removed\n", num, targetname.c_str()); +} + +void NavMaster::CheckNodeSelected() +{ + if (!selectedNode) { + ScriptError("No node selected"); + } +} + +void NavMaster::Frame() +{ + float phase; + vec3_t color; + + if (!ai_editmode->integer) { + return; + } + + phase = fmod(level.time * 2, 2.0); + if (phase > 1.0) { + phase = 2.0 - phase; + } + //phase = (sin(level.time * 5) + 1) / 2.0; + + selectedNode = DetermineCurrentNode(); + if (selectedNode) { + Vector mins, maxs; + Vector org; + vec3_t colorPhase; + + GetPathnodeColor(selectedNode->nodeflags, color); + + colorPhase[0] = 0; + colorPhase[1] = (1.0 - phase) * 0.5; + colorPhase[2] = phase; + color[1] = Q_max(color[1], colorPhase[1]) - Q_min(color[1], colorPhase[1]); + color[2] = Q_max(color[2], colorPhase[2]) - Q_min(color[2], colorPhase[2]); + + mins = Vector(-24, -24, -24); + maxs = Vector(24, 24, 24); + org = selectedNode->centroid; + org.z += 24; + + G_DebugBBox(org, mins, maxs, color[0], color[1], color[2], 1.0); + } +} + +PathNode *NavMaster::DetermineCurrentNode() const +{ + Entity *ent; + PathNode *bestnode; + float bestdist; + Vector delta; + Vector dir; + int i; + + ent = g_entities->entity; + if (!ent) { + return NULL; + } + + if (ent->IsSubclassOfSentient()) { + Sentient *sent = static_cast(ent); + const Vector viewAngles = sent->GetViewAngles(); + + Vector forward; + viewAngles.AngleVectorsLeft(&dir); + } else { + dir = ent->orientation[0]; + } + + bestdist = 1e+12f; + bestnode = NULL; + + for (i = 0; i < PathSearch::nodecount; i++) { + PathNode *node = PathSearch::pathnodes[i]; + float dist; + + if (!node) { + continue; + } + + delta = node->centroid - ent->centroid; + if (abs(delta.z) > (MAXS_Z * 2)) { + continue; + } + + if (!FovCheck(dir, delta, 45)) { + continue; + } + + dist = delta.lengthSquared(); + if (dist < bestdist) { + bestdist = dist; + bestnode = node; + } + } + + return bestnode; +} + +bool NavMaster::FovCheck(const Vector& dir, const Vector& delta, float fov) const +{ + float fovdot = cos(DEG2RAD(fov / 2.f)); + float deltadot = DotProduct(delta, dir); + + if (fovdot < 0.0f) { + if (deltadot >= 0.0f) { + return true; + } + + return VectorLengthSquared(delta) * Square(fovdot) > Square(deltadot); + } else { + if (deltadot < 0.0f) { + return false; + } + + return VectorLengthSquared(delta) * Square(fovdot) < Square(deltadot); + } } Event EV_AttractiveNode_GetPriority - ( - "priority", - EV_DEFAULT, - NULL, - NULL, - "Get the node priority", - EV_GETTER - ); - +( + "priority", + EV_DEFAULT, + NULL, + NULL, + "Get the node priority", + EV_GETTER +); Event EV_AttractiveNode_SetPriority - ( - "priority", - EV_DEFAULT, - "i", - "priority", - "Set the node priority", - EV_SETTER - ); - +( + "priority", + EV_DEFAULT, + "i", + "priority", + "Set the node priority", + EV_SETTER +); Event EV_AttractiveNode_GetDistance - ( - "max_dist", - EV_DEFAULT, - NULL, - NULL, - "Get the max distance for this node", - EV_GETTER - ); - +( + "max_dist", + EV_DEFAULT, + NULL, + NULL, + "Get the max distance for this node", + EV_GETTER +); Event EV_AttractiveNode_SetDistance - ( - "max_dist", - EV_DEFAULT, - "f", - "max_dist", - "Set the max distance for this node to be attracted, -1 for unlimited distance.", - EV_SETTER - ); - +( + "max_dist", + EV_DEFAULT, + "f", + "max_dist", + "Set the max distance for this node to be attracted, -1 for unlimited distance.", + EV_SETTER +); Event EV_AttractiveNode_GetStayTime - ( - "stay_time", - EV_DEFAULT, - NULL, - NULL, - "Get the max stay time for this node", - EV_GETTER - ); - +( + "stay_time", + EV_DEFAULT, + NULL, + NULL, + "Get the max stay time for this node", + EV_GETTER +); Event EV_AttractiveNode_SetStayTime - ( - "stay_time", - EV_DEFAULT, - "f", - "stay_time", - "Set the maximum stay time AI will stay on this node", - EV_SETTER - ); - +( + "stay_time", + EV_DEFAULT, + "f", + "stay_time", + "Set the maximum stay time AI will stay on this node", + EV_SETTER +); Event EV_AttractiveNode_GetRespawnTime - ( - "respawn_time", - EV_DEFAULT, - NULL, - NULL, - "Get the how much time will this node re-attract already attracted AIs", - EV_GETTER - ); - +( + "respawn_time", + EV_DEFAULT, + NULL, + NULL, + "Get the how much time will this node re-attract already attracted AIs", + EV_GETTER +); Event EV_AttractiveNode_SetRespawnTime - ( - "respawn_time", - EV_DEFAULT, - "f", - "respawn_time", - "Set the how much time will this node re-attract already attracted AIs. The minimum required value is 1, otherwise AI will get stuck.", - EV_SETTER - ); - +( + "respawn_time", + EV_DEFAULT, + "f", + "respawn_time", + "Set the how much time will this node re-attract already attracted AIs. The minimum required value is 1, otherwise " + "AI will get stuck.", + EV_SETTER +); Event EV_AttractiveNode_GetTeam - ( - "team", - EV_DEFAULT, - NULL, - NULL, - "Get the attractive node team. 'none' for no team.", - EV_GETTER - ); - +( + "team", + EV_DEFAULT, + NULL, + NULL, + "Get the attractive node team. 'none' for no team.", + EV_GETTER +); Event EV_AttractiveNode_SetTeam - ( - "team", - EV_DEFAULT, - "s", - "team", - "Set the attractive node team. 'none' for no team.", - EV_SETTER - ); - +( + "team", + EV_DEFAULT, + "s", + "team", + "Set the attractive node team. 'none' for no team.", + EV_SETTER +); Event EV_AttractiveNode_SetUse - ( - "setuse", - EV_DEFAULT, - "b", - "use", - "Set if AI should use or not" - ); +( + "setuse", + EV_DEFAULT, + "b", + "use", + "Set if AI should use or not" +); -CLASS_DECLARATION( SimpleArchivedEntity, AttractiveNode, NULL ) -{ - { &EV_AttractiveNode_GetPriority, &AttractiveNode::GetPriority }, - { &EV_AttractiveNode_SetPriority, &AttractiveNode::SetPriority }, - { &EV_AttractiveNode_GetDistance, &AttractiveNode::GetDistance }, - { &EV_AttractiveNode_SetDistance, &AttractiveNode::SetDistance }, - { &EV_AttractiveNode_GetStayTime, &AttractiveNode::GetStayTime }, - { &EV_AttractiveNode_SetStayTime, &AttractiveNode::SetStayTime }, - { &EV_AttractiveNode_GetRespawnTime, &AttractiveNode::GetRespawnTime }, - { &EV_AttractiveNode_SetRespawnTime, &AttractiveNode::SetRespawnTime }, - { &EV_AttractiveNode_GetTeam, &AttractiveNode::GetTeam }, - { &EV_AttractiveNode_SetTeam, &AttractiveNode::SetTeam }, - { &EV_AttractiveNode_SetUse, &AttractiveNode::SetUse }, - { NULL, NULL } +CLASS_DECLARATION(SimpleArchivedEntity, AttractiveNode, NULL) { + {&EV_AttractiveNode_GetPriority, &AttractiveNode::GetPriority }, + {&EV_AttractiveNode_SetPriority, &AttractiveNode::SetPriority }, + {&EV_AttractiveNode_GetDistance, &AttractiveNode::GetDistance }, + {&EV_AttractiveNode_SetDistance, &AttractiveNode::SetDistance }, + {&EV_AttractiveNode_GetStayTime, &AttractiveNode::GetStayTime }, + {&EV_AttractiveNode_SetStayTime, &AttractiveNode::SetStayTime }, + {&EV_AttractiveNode_GetRespawnTime, &AttractiveNode::GetRespawnTime}, + {&EV_AttractiveNode_SetRespawnTime, &AttractiveNode::SetRespawnTime}, + {&EV_AttractiveNode_GetTeam, &AttractiveNode::GetTeam }, + {&EV_AttractiveNode_SetTeam, &AttractiveNode::SetTeam }, + {&EV_AttractiveNode_SetUse, &AttractiveNode::SetUse }, + {NULL, NULL } }; -Container< AttractiveNode * > attractiveNodes; +Container attractiveNodes; AttractiveNode::AttractiveNode() { + m_iPriority = 0; // set to default 0 + m_fMaxStayTime = 0; // set to default 0, could be just a pickup + m_fMaxDistance = 1024; + m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance; + m_fRespawnTime = 15.0f; // set to default 15 seconds + m_bUse = false; + m_csTeam = STRING_EMPTY; + m_iTeam = TEAM_NONE; - m_iPriority = 0; // set to default 0 - m_fMaxStayTime = 0; // set to default 0, could be just a pickup - m_fMaxDistance = 1024; - m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance; - m_fRespawnTime = 15.0f; // set to default 15 seconds - m_bUse = false; - m_csTeam = STRING_EMPTY; - m_iTeam = TEAM_NONE; - - attractiveNodes.AddObject( this ); + attractiveNodes.AddObject(this); } AttractiveNode::~AttractiveNode() { - attractiveNodes.RemoveObject( this ); + attractiveNodes.RemoveObject(this); } -bool AttractiveNode::CheckTeam - ( - Sentient *sent - ) +bool AttractiveNode::CheckTeam(Sentient *sent) { - if( !m_iTeam ) - { - return true; - } + if (!m_iTeam) { + return true; + } - if( sent->IsSubclassOfPlayer() ) - { - Player *p = ( Player * )sent; + if (sent->IsSubclassOfPlayer()) { + Player *p = (Player *)sent; - if( ( m_iTeam == TEAM_FREEFORALL && g_gametype->integer >= GT_TEAM ) || - p->GetTeam() != m_iTeam ) - { - return false; - } - } - else - { - if( m_iTeam == TEAM_ALLIES && sent->m_Team != TEAM_AMERICAN ) - { - return false; - } - else if( m_iTeam == TEAM_AXIS && sent->m_Team != TEAM_GERMAN ) - { - return false; - } - } + if ((m_iTeam == TEAM_FREEFORALL && g_gametype->integer >= GT_TEAM) || p->GetTeam() != m_iTeam) { + return false; + } + } else { + if (m_iTeam == TEAM_ALLIES && sent->m_Team != TEAM_AMERICAN) { + return false; + } else if (m_iTeam == TEAM_AXIS && sent->m_Team != TEAM_GERMAN) { + return false; + } + } - return true; + return true; } -void AttractiveNode::setMaxDist - ( - float dist - ) +void AttractiveNode::setMaxDist(float dist) { - m_fMaxDistance = dist; + m_fMaxDistance = dist; - if( dist < 0 ) - { - m_fMaxDistanceSquared = -1; - } - else - { - m_fMaxDistanceSquared = dist * dist; - } + if (dist < 0) { + m_fMaxDistanceSquared = -1; + } else { + m_fMaxDistanceSquared = dist * dist; + } } -void AttractiveNode::GetPriority - ( - Event *ev - ) +void AttractiveNode::GetPriority(Event *ev) { - ev->AddInteger( m_iPriority ); + ev->AddInteger(m_iPriority); } -void AttractiveNode::SetPriority - ( - Event *ev - ) +void AttractiveNode::SetPriority(Event *ev) { - m_iPriority = ev->GetInteger( 1 ); + m_iPriority = ev->GetInteger(1); } -void AttractiveNode::GetDistance - ( - Event *ev - ) +void AttractiveNode::GetDistance(Event *ev) { - ev->AddFloat( m_fMaxDistance ); + ev->AddFloat(m_fMaxDistance); } -void AttractiveNode::SetDistance - ( - Event *ev - ) +void AttractiveNode::SetDistance(Event *ev) { - setMaxDist( ev->GetFloat( 1 ) ); + setMaxDist(ev->GetFloat(1)); } -void AttractiveNode::GetStayTime - ( - Event *ev - ) +void AttractiveNode::GetStayTime(Event *ev) { - ev->AddFloat( m_fMaxStayTime ); + ev->AddFloat(m_fMaxStayTime); } -void AttractiveNode::SetStayTime - ( - Event *ev - ) +void AttractiveNode::SetStayTime(Event *ev) { - m_fMaxStayTime = ev->GetFloat( 1 ); + m_fMaxStayTime = ev->GetFloat(1); } -void AttractiveNode::GetRespawnTime - ( - Event *ev - ) +void AttractiveNode::GetRespawnTime(Event *ev) { - ev->AddFloat( m_fRespawnTime ); + ev->AddFloat(m_fRespawnTime); } -void AttractiveNode::SetRespawnTime - ( - Event *ev - ) +void AttractiveNode::SetRespawnTime(Event *ev) { - m_fRespawnTime = ev->GetFloat( 1 ); - if( m_fRespawnTime < 1.0f ) - { - m_fRespawnTime = 1.0f; - } + m_fRespawnTime = ev->GetFloat(1); + if (m_fRespawnTime < 1.0f) { + m_fRespawnTime = 1.0f; + } } -void AttractiveNode::GetTeam - ( - Event *ev - ) +void AttractiveNode::GetTeam(Event *ev) { - ev->AddConstString( m_csTeam ); + ev->AddConstString(m_csTeam); } -void AttractiveNode::SetTeam - ( - Event *ev - ) +void AttractiveNode::SetTeam(Event *ev) { - if( ev->IsNilAt( 1 ) ) - { - m_csTeam = STRING_EMPTY; - m_iTeam = TEAM_NONE; - return; - } + if (ev->IsNilAt(1)) { + m_csTeam = STRING_EMPTY; + m_iTeam = TEAM_NONE; + return; + } - m_csTeam = ev->GetConstString( 1 ); + m_csTeam = ev->GetConstString(1); - switch( m_csTeam ) - { - case STRING_EMPTY: - m_iTeam = TEAM_NONE; - break; - case STRING_SPECTATOR: - m_iTeam = TEAM_SPECTATOR; - break; - case STRING_FREEFORALL: - m_iTeam = TEAM_FREEFORALL; - break; - case STRING_ALLIES: - case STRING_AMERICAN: - m_iTeam = TEAM_ALLIES; - break; - case STRING_AXIS: - case STRING_GERMAN: - m_iTeam = TEAM_AXIS; - break; - default: - m_iTeam = TEAM_NONE; - ScriptError( "Invalid team %s\n", ev->GetString( 1 ).c_str() ); - } + switch (m_csTeam) { + case STRING_EMPTY: + m_iTeam = TEAM_NONE; + break; + case STRING_SPECTATOR: + m_iTeam = TEAM_SPECTATOR; + break; + case STRING_FREEFORALL: + m_iTeam = TEAM_FREEFORALL; + break; + case STRING_ALLIES: + case STRING_AMERICAN: + m_iTeam = TEAM_ALLIES; + break; + case STRING_AXIS: + case STRING_GERMAN: + m_iTeam = TEAM_AXIS; + break; + default: + m_iTeam = TEAM_NONE; + ScriptError("Invalid team %s\n", ev->GetString(1).c_str()); + } } -void AttractiveNode::SetUse - ( - Event *ev - ) +void AttractiveNode::SetUse(Event *ev) { - m_bUse = ev->GetBoolean( 1 ); + m_bUse = ev->GetBoolean(1); } diff --git a/code/fgame/navigate.h b/code/fgame/navigate.h index e6b255b3..3404aebc 100644 --- a/code/fgame/navigate.h +++ b/code/fgame/navigate.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,8 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // is currently unfinished. // -#ifndef __NAVIGATE_H__ -#define __NAVIGATE_H__ +#pragma once #include "g_local.h" #include "class.h" @@ -37,7 +36,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "sentient.h" #include "../qcommon/qfiles.h" - extern Event EV_AI_SavePaths; extern Event EV_AI_SaveNodes; extern Event EV_AI_LoadNodes; @@ -46,326 +44,402 @@ extern Event EV_AI_RecalcPaths; extern Event EV_AI_CalcPath; extern Event EV_AI_DisconnectPath; -extern cvar_t *ai_showroutes; -extern cvar_t *ai_showroutes_distance; -extern cvar_t *ai_shownodenums; -extern cvar_t *ai_shownode; -extern cvar_t *ai_showallnode; -extern cvar_t *ai_showpath; -extern cvar_t *ai_fallheight; -extern cvar_t *ai_debugpath; -extern cvar_t *ai_pathchecktime; -extern cvar_t *ai_pathcheckdist; +extern cvar_t *ai_showroutes; +extern cvar_t *ai_showroutes_distance; +extern cvar_t *ai_shownodenums; +extern cvar_t *ai_shownode; +extern cvar_t *ai_showallnode; +extern cvar_t *ai_showpath; +extern cvar_t *ai_fallheight; +extern cvar_t *ai_debugpath; +extern cvar_t *ai_pathchecktime; +extern cvar_t *ai_pathcheckdist; -extern int ai_maxnode; +extern int ai_maxnode; #define MAX_PATHCHECKSPERFRAME 4 extern int path_checksthisframe; -#define MAX_PATH_LENGTH 128 // should be more than plenty -#define NUM_PATHSPERNODE 48 +#define MAX_PATH_LENGTH 128 // should be more than plenty +#define NUM_PATHSPERNODE 48 class Path; class PathNode; +class SimpleActor; -#define NUM_WIDTH_VALUES 16 -#define WIDTH_STEP 8 -#define MAX_WIDTH ( WIDTH_STEP * NUM_WIDTH_VALUES ) -#define MAX_HEIGHT 128 +#define NUM_WIDTH_VALUES 16 +#define WIDTH_STEP 8 +#define MAX_WIDTH (WIDTH_STEP * NUM_WIDTH_VALUES) +#define MAX_HEIGHT 128 -#define CHECK_PATH( path, width, height ) \ - ( ( ( ( width ) >= MAX_WIDTH ) || ( ( width ) < 0 ) ) ? false : \ - ( ( int )( path )->maxheight[ ( ( width ) / WIDTH_STEP ) - 1 ] < ( int )( height ) ) ) +#define CHECK_PATH(path, width, height) \ + ((((width) >= MAX_WIDTH) || ((width) < 0)) ? false \ + : ((int)(path)->maxheight[((width) / WIDTH_STEP) - 1] < (int)(height))) -class pathway_ref { +class pathway_ref +{ public: - short int from; - short int to; + short int from; + short int to; }; typedef struct { - byte numBlockers; - short int node; - short int fallheight; - float dist; - float dir[ 2 ]; - float pos1[ 3 ]; - float pos2[ 3 ]; + byte numBlockers; + byte badPlaceTeam[2]; + short int node; + short int fallheight; + float dist; + vec2_t dir; + vec3_t pos1; + vec3_t pos2; } pathway_t; -class PathInfo { +class PathInfo +{ public: - bool bAccurate; - float point[ 3 ]; - float dist; - float dir[ 2 ]; + bool bAccurate; + vec3_t point; + float dist; + vec2_t dir; public: - void Archive( Archiver& arc ); + PathInfo(); + + void Archive(Archiver& arc); }; -inline void PathInfo::Archive - ( - Archiver& arc - ) +inline PathInfo::PathInfo() + : bAccurate(false) + , point {0, 0, 0} + , dist(0) + , dir {0, 0} +{} + +inline void PathInfo::Archive(Archiver& arc) { - arc.ArchiveBool( &bAccurate ); - arc.ArchiveVec3( point ); - arc.ArchiveFloat( &dist ); - arc.ArchiveVec2( dir ); + arc.ArchiveBool(&bAccurate); + arc.ArchiveVec3(point); + arc.ArchiveFloat(&dist); + arc.ArchiveVec2(dir); } -typedef enum { NOT_IN_LIST, IN_OPEN, IN_CLOSED } pathlist_t; +typedef enum { + NOT_IN_LIST, + IN_OPEN, + IN_CLOSED +} pathlist_t; -#define PATH_DONT_LINK 1 -#define AI_DUCK 2 -#define AI_COVER 4 -#define AI_CONCEALMENT 8 -#define AI_CORNER_LEFT 16 -#define AI_CORNER_RIGHT 32 -#define AI_SNIPER 64 -#define AI_CRATE 128 +#define PATH_DONT_LINK 1 +#define AI_DUCK 2 +#define AI_COVER 4 +#define AI_CONCEALMENT 8 +#define AI_CORNER_LEFT 16 +#define AI_CORNER_RIGHT 32 +#define AI_SNIPER 64 +#define AI_CRATE 128 +// Added in 2.0 +#define AI_LOW_WALL_ARC 256 -#define AI_COVERFLAGS (AI_CRATE|AI_SNIPER|AI_CORNER_RIGHT|AI_CORNER_LEFT|AI_CONCEALMENT|AI_COVER) -#define AI_COVERFLAGS2 (AI_SNIPER|AI_CORNER_RIGHT|AI_CORNER_LEFT|AI_CONCEALMENT) -#define AI_COVERFLAGS3 (AI_SNIPER|AI_CORNER_RIGHT|AI_CORNER_LEFT|AI_CONCEALMENT|AI_DUCK|AI_CONCEALMENT) -#define AI_SNIPERFLAGS (AI_SNIPER|AI_CORNER_RIGHT|AI_CORNER_LEFT|AI_COVER) -#define AI_CRATEFLAGS (AI_CRATE|AI_CORNER_LEFT|AI_CORNER_RIGHT|AI_CONCEALMENT|AI_COVER|AI_DUCK) -#define AI_COVER_LEFT_FLAGS (AI_CRATE|AI_SNIPER|AI_CORNER_LEFT|AI_CONCEALMENT|AI_DUCK) -#define AI_COVER_RIGHT_FLAGS (AI_CRATE|AI_SNIPER|AI_CORNER_RIGHT|AI_CONCEALMENT|AI_DUCK) -#define AI_ALL (AI_DUCK|AI_COVER|AI_CONCEALMENT|AI_CORNER_LEFT|AI_CORNER_RIGHT|AI_SNIPER|AI_CRATE) +#define AI_MOVE_MASK \ + (AI_COVER | AI_CONCEALMENT | AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE | AI_LOW_WALL_ARC) +#define AI_COVER_MASK (AI_COVER | AI_CONCEALMENT | AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_CRATE | AI_LOW_WALL_ARC) +#define AI_CONCEALMENT_MASK (AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_CRATE | AI_LOW_WALL_ARC) -void DrawNode( int iNodeCount ); -void DrawAllConnections( void ); +void DrawNode(int iNodeCount); +void DrawAllConnections(void); class PathNode : public SimpleEntity - { - public: - int findCount; - pathway_t *Child; - int numChildren; - int virtualNumChildren; - float f; - float h; - float g; - class PathNode *Parent; - bool inopen; - PathNode *PrevNode; - PathNode *NextNode; - short int pathway; - vec_t *m_PathPos; - float dist; - float dir[ 2 ]; - int nodeflags; - SafePtr pLastClaimer; - int iAvailableTime; - int nodenum; - short int m_Depth; +{ +public: + int findCount; + pathway_t *Child; + int numChildren; + int virtualNumChildren; + float f; + float h; + float g; + class PathNode *Parent; + bool inopen; + PathNode *PrevNode; + PathNode *NextNode; + short int pathway; + const vec_t *m_PathPos; + float dist; + vec2_t dir; + int nodeflags; + SafePtr pLastClaimer; + int iAvailableTime; + int nodenum; + short int m_Depth; + float m_fLowWallArc; - friend class PathSearch; - friend void DrawAllConnections( void ); + friend class PathSearch; + friend void DrawAllConnections(void); - private: - void ConnectTo( PathNode *node ); - void SetNodeFlags( Event *ev ); - void Remove( Event *ev ); +private: + void ConnectTo(PathNode *node); + void SetNodeFlags(Event *ev); + void SetLowWallArc(Event *ev); // Added in 2.0 + void Remove(Event *ev); - public: - CLASS_PROTOTYPE( PathNode ); +public: + CLASS_PROTOTYPE(PathNode); - void *operator new( size_t size ); - void operator delete( void *ptr ); + PathNode(); + virtual ~PathNode(); - PathNode(); - virtual ~PathNode(); + void *operator new(size_t size); + void operator delete(void *ptr); - void Archive( Archiver& arc ) override; - void ArchiveDynamic( Archiver& arc ); - void ArchiveStatic( Archiver& arc ); + void Archive(Archiver& arc) override; + void ArchiveDynamic(Archiver& arc); + void ArchiveStatic(Archiver& arc); - bool CheckPathTo( PathNode *node ); - void CheckPathToDefault( PathNode *node, pathway_t *pathway ); - qboolean LadderTo( PathNode *node, pathway_t *pathway ); + bool CheckPathTo(PathNode *node); + void CheckPathToDefault(PathNode *node, pathway_t *pathway); + qboolean LadderTo(PathNode *node, pathway_t *pathway); - void DrawConnections( void ); - void Claim( Entity *pClaimer ); - void Relinquish( void ); - Entity *GetClaimHolder( void ) const; - bool IsClaimedByOther( Entity *pPossibleClaimer ) const; - void MarkTemporarilyBad( void ); - void ConnectChild( int i ); - void DisconnectChild( int i ); - const_str GetSpecialAttack( class Actor *pActor ); - void IsTouching( Event *ev ); - qboolean IsTouching( Entity *e1 ); - void setOriginEvent( Vector org ) override; - - }; + void DrawConnections(void); + void Claim(Entity *pClaimer); + void Relinquish(void); + Entity *GetClaimHolder(void) const; + bool IsClaimedByOther(Entity *pPossibleClaimer) const; + void MarkTemporarilyBad(void); + void ConnectChild(int i); + void DisconnectChild(int i); + const_str GetSpecialAttack(class Actor *pActor); + void IsTouching(Event *ev); + qboolean IsTouching(Entity *e1); + void setOriginEvent(Vector org) override; +}; typedef SafePtr PathNodePtr; -class nodeinfo { -public: - PathNode *pNode; - float fDistSquared; -}; +#define PATHMAP_CELLSIZE 256 +#define PATHMAP_GRIDSIZE (MAX_MAP_BOUNDS * 2 / PATHMAP_CELLSIZE) -#define PATHMAP_CELLSIZE 256 -#define PATHMAP_GRIDSIZE ( MAX_MAP_BOUNDS * 2 / PATHMAP_CELLSIZE ) +#define PATHMAP_NODES 128 // 128 - sizeof( int ) / sizeof( short ) -#define PATHMAP_NODES 128 // 128 - sizeof( int ) / sizeof( short ) - -#define MAX_PATHNODES 4096 +#define MAX_PATHNODES 4096 class MapCell : public Class { private: - int numnodes; - short *nodes; + int numnodes; + short *nodes; - friend class PathSearch; + friend class PathSearch; public: - MapCell(); - ~MapCell(); + MapCell(); + ~MapCell(); - qboolean AddNode( PathNode *node ); - int NumNodes( void ); + void AddNode(PathNode *node); + int NumNodes(void); }; class PathSearch : public Listener { - friend class PathNode; + friend class PathNode; private: - static MapCell PathMap[ PATHMAP_GRIDSIZE ][ PATHMAP_GRIDSIZE ]; - static PathNode *open; - static int findFrame; - static qboolean m_bNodesloaded; - static qboolean m_NodeCheckFailed; - static int m_LoadIndex; + static MapCell PathMap[PATHMAP_GRIDSIZE][PATHMAP_GRIDSIZE]; + static PathNode *open; + static int findFrame; + static qboolean m_bNodesloaded; + static qboolean m_NodeCheckFailed; + static int m_LoadIndex; public: - static PathNode *pathnodes[ 4096 ]; - static int nodecount; - static float total_dist; - static const char *last_error; + static PathNode *pathnodes[MAX_PATHNODES]; + static int nodecount; + static float total_dist; + static const char *last_error; private: - static void LoadAddToGrid( int x, int y ); - static void LoadAddToGrid2( PathNode *node, int x, int y ); - static void AddToGrid( PathNode *node, int x, int y ); - static bool Connect( PathNode *node, int x, int y ); - static int NodeCoordinate( float coord ); - static int GridCoordinate( float coord ); - static qboolean ArchiveSaveNodes( void ); - static void ArchiveLoadNodes( void ); - static void Init( void ); + static void LoadAddToGrid(int x, int y); + static void LoadAddToGrid2(PathNode *node, int x, int y); + static void AddToGrid(PathNode *node, int x, int y); + static bool Connect(PathNode *node, int x, int y); + static int NodeCoordinate(float coord); + static int GridCoordinate(float coord); + static qboolean ArchiveSaveNodes(void); + static void ArchiveLoadNodes(void); + static void Init(void); public: - CLASS_PROTOTYPE( PathSearch ); + CLASS_PROTOTYPE(PathSearch); - PathSearch(); - virtual ~PathSearch(); + PathSearch(); + virtual ~PathSearch(); - static void ArchiveStaticLoad( Archiver& arc ); - static void ArchiveStaticSave( Archiver& arc ); - static bool ArchiveDynamic( Archiver& arc ); - static void AddNode( PathNode *node ); - static void Connect( PathNode *node ); - static void UpdateNode( PathNode *node ); - static MapCell *GetNodesInCell( int x, int y ); - static MapCell *GetNodesInCell( float *pos ); - static class PathNode *DebugNearestStartNode( float *pos, Entity *ent = NULL ); - static class PathNode *NearestStartNode( float *pos, class SimpleActor *ent ); - static class PathNode *NearestEndNode( float *pos ); - static int DebugNearestNodeList( float *pos, PathNode **nodelist, int iMaxNodes ); - static int DebugNearestNodeList2( float *pos, PathNode **nodelist, int iMaxNodes ); - static void ShowNodes( void ); - static void LoadNodes( void ); - static void CreatePaths( void ); - static void *AllocPathNode( void ); - static void FreePathNode( void * ); - static void ResetNodes( void ); - static PathInfo *GeneratePath( PathInfo *path ); - static PathInfo *GeneratePathNear( PathInfo *path ); - static PathInfo *GeneratePathAway( PathInfo *path ); - static class PathNode *GetSpawnNode( ClassDef *cls ); - static int FindPath( float *start, float *end, Entity *ent, float maxPath, float *vLeashHome, float fLeashDistSquared, int fallheight ); - static int FindPathAway( float *start, float *avoid, float *vPreferredDir, Entity *ent, float fMinSafeDist, float *vLeashHome, float fLeashDistSquared, int fallheight ); - static int FindPathNear( float *start, float *end, Entity *ent, float maxPath, float fRadiusSquared, float *vLeashHome, float fLeashDistSquared, int fallheight ); - static class PathNode *FindCornerNodeForWall( float *start, float *end, class SimpleActor *ent, float maxPath, float *plane ); - static class PathNode *FindCornerNodeForExactPath( class SimpleActor *self, Sentient *enemy, float fMaxPath ); - static int FindPotentialCover( class SimpleActor *pEnt, Vector& vPos, Entity *pEnemy, PathNode **ppFoundNodes, int iMaxFind ); - static void PlayerCover( class Player *pPlayer ); - static class PathNode *FindNearestCover( class SimpleActor *pEnt, Vector& vPos, Entity *pEnemy ); - static class PathNode *FindNearestSniperNode( class SimpleActor *pEnt, Vector& vPos, Entity *pEnemy ); + static void ArchiveStaticLoad(Archiver& arc); + static void ArchiveStaticSave(Archiver& arc); + static bool ArchiveDynamic(Archiver& arc); + + static void AddNode(PathNode *node); + static void Connect(PathNode *node); + static void UpdateNode(PathNode *node); + + static MapCell *GetNodesInCell(int x, int y); + static MapCell *GetNodesInCell(const vec3_t pos); + + static class PathNode *DebugNearestStartNode(const vec3_t pos, Entity *ent = NULL); + static class PathNode *NearestStartNode(const vec3_t pos, SimpleActor *ent); + static class PathNode *NearestEndNode(const vec3_t pos); + static int DebugNearestNodeList(const vec3_t pos, PathNode **nodelist, int iMaxNodes); + static int DebugNearestNodeList2(const vec3_t pos, PathNode **nodelist, int iMaxNodes); + + static void ShowNodes(void); + static void LoadNodes(void); + static void CreatePaths(void); + static void *AllocPathNode(void); + static void FreePathNode(void *); + static void ResetNodes(void); + static void ClearNodes(void); // Added in OPM + + static void UpdatePathwaysForBadPlace(const Vector& origin, float radius, int dir, int team); + static PathInfo *GeneratePath(PathInfo *path); + static PathInfo *GeneratePathNear(PathInfo *path); + static PathInfo *GeneratePathAway(PathInfo *path); + + static class PathNode *GetSpawnNode(ClassDef *cls); + + static int FindPath( + const vec3_t start, + const vec3_t end, + Entity *ent, + float maxPath, + const vec3_t vLeashHome, + float fLeashDistSquared, + int fallheight + ); + static int FindPathAway( + const vec3_t start, + const vec3_t avoid, + const vec3_t vPreferredDir, + Entity *ent, + float fMinSafeDist, + const vec3_t vLeashHome, + float fLeashDistSquared, + int fallheight + ); + static int FindPathNear( + const vec3_t start, + const vec3_t end, + Entity *ent, + float maxPath, + float fRadiusSquared, + const vec3_t vLeashHome, + float fLeashDistSquared, + int fallheight + ); + + static class PathNode * + FindCornerNodeForWall(const vec3_t start, const vec3_t end, Entity *ent, float maxPath, const vec4_t plane); + static class PathNode *FindCornerNodeForExactPath(Entity *self, Sentient *enemy, float fMaxPath); + static int FindPotentialCover(Entity *pEnt, Vector& vPos, Entity *pEnemy, PathNode **ppFoundNodes, int iMaxFind); + static void PlayerCover(class Player *pPlayer); + static class PathNode *FindNearestCover(Entity *pEnt, Vector& vPos, Entity *pEnemy); + static class PathNode *FindNearestSniperNode(Entity *pEnt, Vector& vPos, Entity *pEnemy); private: - static int NearestNodeSetup( vec3_t pos, MapCell *cell, int *nodes, vec3_t *deltas ); - + static int NearestNodeSetup(const vec3_t pos, MapCell *cell, int *nodes, vec3_t *deltas); }; +inline MapCell::~MapCell() +{ + numnodes = 0; + nodes = NULL; +} + extern PathSearch PathManager; -PathNode *AI_FindNode( const char *name ); -void AI_AddNode( PathNode *node ); -void AI_RemoveNode( PathNode *node ); -void AI_ResetNodes( void ); +//=============== +// Added in OPM +//=============== + +class NavMaster : public Listener +{ +public: + CLASS_PROTOTYPE(NavMaster); + + NavMaster(); + + void Init(void); + + void CreatePaths(Event *ev); + void CreateNode(Event *ev); + void SetNodeFlags(Event *ev); + void SetNodeTargetName(Event *ev); + void SetNodeTarget(Event *ev); + void RemoveNode(Event *ev); + void Frame(); + +private: + void CheckNodeSelected(); + PathNode *DetermineCurrentNode() const; + bool FovCheck(const Vector& dir, const Vector& delta, float fov) const; + +private: + SafePtr selectedNode; +}; + +extern NavMaster navMaster; + +PathNode *AI_FindNode(const char *name); +void AI_AddNode(PathNode *node); +void AI_RemoveNode(PathNode *node); +void AI_ResetNodes(void); class AttractiveNode : public SimpleArchivedEntity { public: - int m_iPriority; - bool m_bUse; - float m_fMaxStayTime; - float m_fMaxDistance; - float m_fMaxDistanceSquared; - float m_fRespawnTime; - const_str m_csTeam; - int m_iTeam; + int m_iPriority; + bool m_bUse; + float m_fMaxStayTime; + float m_fMaxDistance; + float m_fMaxDistanceSquared; + float m_fRespawnTime; + const_str m_csTeam; + int m_iTeam; private: -// Container< SafePtr< Sentient > > m_pSentList; + // Container< SafePtr< Sentient > > m_pSentList; public: - CLASS_PROTOTYPE( AttractiveNode ); + CLASS_PROTOTYPE(AttractiveNode); - AttractiveNode(); - ~AttractiveNode(); + AttractiveNode(); + ~AttractiveNode(); - bool CheckTeam( Sentient *sent ); - void setMaxDist( float dist ); + bool CheckTeam(Sentient *sent); + void setMaxDist(float dist); - void GetPriority( Event *ev ); - void SetPriority( Event *ev ); - void GetDistance( Event *ev ); - void SetDistance( Event *ev ); - void GetStayTime( Event *ev ); - void SetStayTime( Event *ev ); - void GetRespawnTime( Event *ev ); - void SetRespawnTime( Event *ev ); - void GetTeam( Event *ev ); - void SetTeam( Event *ev ); - void SetUse( Event *ev ); + void GetPriority(Event *ev); + void SetPriority(Event *ev); + void GetDistance(Event *ev); + void SetDistance(Event *ev); + void GetStayTime(Event *ev); + void SetStayTime(Event *ev); + void GetRespawnTime(Event *ev); + void SetRespawnTime(Event *ev); + void GetTeam(Event *ev); + void SetTeam(Event *ev); + void SetUse(Event *ev); - void Archive( Archiver& arc ) override; + void Archive(Archiver& arc) override; }; -typedef SafePtr< AttractiveNode > AttractiveNodePtr; +typedef SafePtr AttractiveNodePtr; -inline void AttractiveNode::Archive - ( - Archiver& arc - ) +inline void AttractiveNode::Archive(Archiver& arc) { - arc.ArchiveInteger( &m_iPriority ); - arc.ArchiveBool( &m_bUse ); - arc.ArchiveFloat( &m_fMaxStayTime ); - arc.ArchiveFloat( &m_fMaxDistanceSquared ); + arc.ArchiveInteger(&m_iPriority); + arc.ArchiveBool(&m_bUse); + arc.ArchiveFloat(&m_fMaxStayTime); + arc.ArchiveFloat(&m_fMaxDistanceSquared); } -extern Container< AttractiveNode * > attractiveNodes; - -#endif +extern Container attractiveNodes; diff --git a/code/fgame/object.cpp b/code/fgame/object.cpp index fdf81e4a..0cd08c65 100644 --- a/code/fgame/object.cpp +++ b/code/fgame/object.cpp @@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "specialfx.h" #include "g_phys.h" #include "game.h" +#include "../script/scriptexception.h" Event EV_Object_HandleSetModel ( @@ -46,7 +47,14 @@ CLASS_DECLARATION(Animate, Object, NULL) { {NULL, NULL} }; -Event EV_InteractObject_Setup("_setup", EV_DEFAULT, NULL, NULL, "Sets up an object."); +Event EV_InteractObject_Setup +( + "_setup", + EV_DEFAULT, + NULL, + NULL, + "Sets up an object." +); Event EV_InteractObject_KilledEffect ( @@ -118,10 +126,10 @@ void InteractObject::Damaged(Event *ev) void InteractObject::Killed(Event *ev) { - Entity *ent; - Entity *attacker; - Vector dir; - const char *name; + Entity *ent; + Entity *attacker; + Vector dir; + const char *name; takedamage = DAMAGE_NO; deadflag = DEAD_NO; @@ -213,7 +221,7 @@ Event EV_ThrowObject_ThrowSound EV_NORMAL ); -CLASS_DECLARATION(Object, ThrowObject, "func_throwobject") { +CLASS_DECLARATION(Animate, ThrowObject, "func_throwobject") { {&EV_Touch, &ThrowObject::Touch }, {&EV_ThrowObject_Pickup, &ThrowObject::Pickup }, {&EV_ThrowObject_Throw, &ThrowObject::Throw }, @@ -242,7 +250,6 @@ void ThrowObject::ThrowSound(Event *ev) } void ThrowObject::Touch(Event *ev) - { Entity *other; @@ -283,7 +290,6 @@ void ThrowObject::Touch(Event *ev) } void ThrowObject::Throw(Event *ev) - { Entity *owner; Sentient *targetent; @@ -300,6 +306,7 @@ void ThrowObject::Throw(Event *ev) assert(owner); if (!owner) { + ScriptError("owner == NULL"); return; } @@ -311,6 +318,7 @@ void ThrowObject::Throw(Event *ev) targetent = (Sentient *)ev->GetEntity(3); assert(targetent); if (!targetent) { + ScriptError("targetent == NULL"); return; } @@ -328,8 +336,12 @@ void ThrowObject::Throw(Event *ev) gravity = grav; - target = targetent->origin; - target.z += targetent->viewheight; + if (targetent->IsSubclassOfSentient()) { + target = targetent->origin; + target.z += targetent->viewheight; + } else { + target = targetent->centroid; + } setMoveType(MOVETYPE_BOUNCE); setSolidType(SOLID_BBOX); @@ -359,7 +371,6 @@ void ThrowObject::Throw(Event *ev) } void ThrowObject::Pickup(Event *ev) - { Entity *ent; Event *e; @@ -385,7 +396,7 @@ void ThrowObject::Pickup(Event *ev) void ThrowObject::Archive(Archiver& arc) { - Object::Archive(arc); + Animate::Archive(arc); arc.ArchiveInteger(&owner); arc.ArchiveVector(&pickup_offset); diff --git a/code/fgame/object.h b/code/fgame/object.h index 310edf76..fe3fedfe 100644 --- a/code/fgame/object.h +++ b/code/fgame/object.h @@ -46,7 +46,7 @@ public: InteractObject(); void Damaged(Event *ev); - void Killed(Event *ev); + void Killed(Event *ev) override; void Setup(Event *ev); void EventHitEffect(Event *ev); void EventKilledEffect(Event *ev); @@ -56,7 +56,10 @@ public: extern Event EV_ThrowObject_Pickup; extern Event EV_ThrowObject_Throw; -class ThrowObject : public Object +// Fixed in 2.0 +// Before 2.0, ThrowObject was inheriting from Object. +// This caused issue when spawning the ThrowObject from script. +class ThrowObject : public Animate { private: int owner; diff --git a/code/fgame/parm.cpp b/code/fgame/parm.cpp index 9b90a719..76fd8513 100644 --- a/code/fgame/parm.cpp +++ b/code/fgame/parm.cpp @@ -30,63 +30,135 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Parm parm; -Event EV_Parm_GetOther -( - "other", - EV_DEFAULT, - NULL, - NULL, - "other", - EV_GETTER -); - -Event EV_Parm_GetOwner -( - "owner", - EV_DEFAULT, - NULL, - NULL, - "owner", - EV_GETTER -); - Event EV_Parm_GetPreviousThread ( - "previousthread", - EV_DEFAULT, - NULL, - NULL, - "previousthread", - EV_GETTER + "previousthread", + EV_DEFAULT, + NULL, + NULL, + "previousthread", + EV_GETTER +); +Event EV_Parm_GetOther +( + "other", + EV_DEFAULT, + NULL, + NULL, + "other", + EV_GETTER +); +Event EV_Parm_GetOwner +( + "owner", + EV_DEFAULT, + NULL, + NULL, + "owner", + EV_GETTER +); +Event EV_Parm_Movedone +( + "movedone", + EV_DEFAULT, + NULL, + NULL, + "movedone", + EV_GETTER +); +Event EV_Parm_Movefail +( + "movefail", + EV_DEFAULT, + NULL, + NULL, + "movefail", + EV_GETTER +); +Event EV_Parm_Motionfail +( + "motionfail", + EV_DEFAULT, + NULL, + NULL, + "motionfail", + EV_GETTER +); +Event EV_Parm_Upperfail +( + "upperfail", + EV_DEFAULT, + NULL, + NULL, + "upperfail", + EV_GETTER +); +Event EV_Parm_Sayfail +( + "sayfail", + EV_DEFAULT, + NULL, + NULL, + "sayfail", + EV_GETTER ); -void Parm::Archive( Archiver& arc ) +void Parm::Archive(Archiver& arc) { - Listener::Archive( arc ); + Listener::Archive(arc); - arc.ArchiveSafePointer( &other ); - arc.ArchiveSafePointer( &owner ); + arc.ArchiveSafePointer(&other); + arc.ArchiveSafePointer(&owner); } -void Parm::GetOther( Event *ev ) +void Parm::GetMotionFail(Event *ev) { - ev->AddListener( other ); + ev->AddInteger(motionfail); } -void Parm::GetOwner( Event *ev ) +void Parm::GetMovedone(Event *ev) { - ev->AddListener( owner ); + ev->AddInteger(movedone); } -void Parm::GetPreviousThread( Event *ev ) +void Parm::GetMovefail(Event *ev) { - ev->AddListener( Director.PreviousThread() ); + ev->AddInteger(movefail); } -CLASS_DECLARATION( Listener, Parm, NULL ) +void Parm::GetOther(Event *ev) { - { &EV_Parm_GetOther, &Parm::GetOther }, - { &EV_Parm_GetOwner, &Parm::GetOwner }, - { &EV_Parm_GetPreviousThread, &Parm::GetPreviousThread }, - { NULL, NULL } + ev->AddListener(other); +} + +void Parm::GetOwner(Event *ev) +{ + ev->AddListener(owner); +} + +void Parm::GetPreviousThread(Event *ev) +{ + ev->AddListener(Director.PreviousThread()); +} + +void Parm::GetSayFail(Event *ev) +{ + ev->AddInteger(sayfail); +} + +void Parm::GetUpperFail(Event *ev) +{ + ev->AddInteger(upperfail); +} + +CLASS_DECLARATION(Listener, Parm, NULL) { + {&EV_Parm_GetPreviousThread, &Parm::GetPreviousThread}, + {&EV_Parm_GetOther, &Parm::GetOther }, + {&EV_Parm_GetOwner, &Parm::GetOwner }, + {&EV_Parm_Movedone, &Parm::GetMovedone }, + {&EV_Parm_Movefail, &Parm::GetMovefail }, + {&EV_Parm_Motionfail, &Parm::GetMotionFail }, + {&EV_Parm_Upperfail, &Parm::GetUpperFail }, + {&EV_Parm_Sayfail, &Parm::GetSayFail }, + {NULL, NULL } }; diff --git a/code/fgame/parm.h b/code/fgame/parm.h index b942324d..aa8ae00b 100644 --- a/code/fgame/parm.h +++ b/code/fgame/parm.h @@ -22,34 +22,38 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // parm.h: Event parameters -#ifndef __PARM_H__ -#define __PARM_H__ +#pragma once #include "listener.h" -class Parm : public Listener { +class Parm : public Listener +{ public: - // General trigger variables - SafePtr< Listener > other; - SafePtr< Listener > owner; + // General trigger variables + SafePtr other; + SafePtr owner; - // Failure variables - qboolean movedone; - qboolean movefail; - qboolean motionfail; - qboolean upperfail; - qboolean sayfail; + // Failure variables + qboolean movedone; + qboolean movefail; + qboolean motionfail; + qboolean upperfail; + qboolean sayfail; public: - CLASS_PROTOTYPE( Parm ); + CLASS_PROTOTYPE(Parm); - void Archive( Archiver& arc ) override; + void GetPreviousThread(Event *ev); + void GetOther(Event *ev); + void GetOwner(Event *ev); + void GetPath(Event *ev); + void GetMovedone(Event *ev); + void GetMovefail(Event *ev); + void GetMotionFail(Event *ev); + void GetUpperFail(Event *ev); + void GetSayFail(Event *ev); - void GetOther( Event *ev ); - void GetOwner( Event *ev ); - void GetPreviousThread( Event *ev ); + void Archive(Archiver& arc) override; }; extern Parm parm; - -#endif /* __PARM_H__ */ diff --git a/code/fgame/player.cpp b/code/fgame/player.cpp index ef77689b..7b10c5bb 100644 --- a/code/fgame/player.cpp +++ b/code/fgame/player.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "entity.h" #include "consoleevent.h" #include "player.h" -#include "world.h" +#include "worldspawn.h" #include "weapon.h" #include "trigger.h" #include "scriptmaster.h" @@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "parm.h" #include "body.h" #include "playerstart.h" +#include "camera.h" #include "weapturret.h" #include "vehicleturret.h" #include "portableturret.h" @@ -57,7 +58,82 @@ const Vector power_color(0.0, 1.0, 0.0); const Vector acolor(1.0, 1.0, 1.0); const Vector bcolor(1.0, 0.0, 0.0); -qboolean TryPush(int entnum, vec3_t move_origin, vec3_t move_end); +ScriptDelegate Player::scriptDelegate_connected("player_connected", "Sent once when the player connected"); +ScriptDelegate Player::scriptDelegate_disconnecting("player_disconnecting", "The player is disconnecting"); +ScriptDelegate Player::scriptDelegate_spawned("player_spawned", "The player has spawned"); +ScriptDelegate Player::scriptDelegate_damage("player_damaged", "The player got hit"); +ScriptDelegate Player::scriptDelegate_kill("player_killed", "The player got killed"); +ScriptDelegate Player::scriptDelegate_textMessage("player_textMessage", "The player just sent a text message"); + +// +// mohaas 2.0 and above +// +const char *pInstantMsgEng[6][9] = { + {"Good job team!", + "Alright!", "We've done it!", + "Wooohoo!", "Objective achieved.", + "We've completed an objective.", "We've lost an objective!", + "The enemy has overrun our objective!", NULL}, + {"Squad, move in!", + "Squad, fall back!", "Squad, attack right flank!", + "Squad, attack left flank!", "Squad, hold this position!", + "Squad, covering fire!", "Squad, regroup!", + "Squad, split up!", NULL}, + {"Cover me!", + "I'll cover you!", "Follow me!", + "You take point.", "Taking Fire! Need some help!", + "Get ready to move in on my signal.", "Attack!", + "Open fire!", NULL}, + {"Yes sir!", + "No sir!", "Enemy Spotted.", + "Sniper!", "Grenade! Take Cover!", + "Area Clear.", "Thanks.", + "I owe you one.", NULL}, + {"Who wants more?!", + "Never send boys to do a man's job.", "This is too easy!", + "You mess with the best, you die like the rest.", "Watch that friendly fire!", + "Hey! I'm on your team!", "Come on out you cowards!", + "Where are you hiding?", NULL}, + // Added in 2.30 + {"Guard our jail!", + "Capture the enemy jail!", "I'm defending our jail!", + "I'm attacking the enemy jail!", "Rescue the Prisoners!", + "The enemy is attacking our jail!"} +}; + +// +// for mohaa version 1.11 and below +// +const char *pInstantMsgEng_ver6[5][9] = { + {"Squad, move in!", + "Squad, fall back!", "Squad, attack right flank!", + "Squad, attack left flank!", "Squad, hold this position!", + "Squad, covering fire!", "Squad, regroup!", + "", ""}, + { + "Cover me!", "I'll cover you!", + "Follow me!", "You take point.", + "You take the lead.", "Taking Fire! Need some help!", + "Charge!", "Attack!", + "Open fire!", }, + { + "Yes sir!", "No sir!", + "Enemy Spotted.", "Sniper!", + "Grenade! Take Cover!", "Area Clear.", + "Great Shot!", "Thanks.", + "I owe you one.", }, + { + "Is that all you've got?", "I think they are all out of real men!", + "Go on and run, you yellow-bellies!", "They're a bunch of cowards!", + "Come back when you've had some target practice!", "Come prepared next time!", + "Try again!", "I've seen French school girls shoot better!", + "That made a mess.", }, + {"He's going to get us killed!", + "A lot of good men are going to die because of his poor leadership", "Good riddance!", + "That guy is going to get us all killed!", "Hey buddy, get down!", + "Stay out of my foxhole, pal!", "Find your own hiding place!", + "Get out of my way!", ""} +}; Event EV_Player_DumpState ( @@ -209,7 +285,7 @@ Event EV_Player_CorrectWeaponAttachments EV_CONSOLE, NULL, NULL, - "makes sure the weapons is properly attached when interupting a reload", + "makes sure the weapons is properly attached when interrupting a reload", EV_NORMAL ); Event EV_Player_GiveCheat @@ -402,7 +478,14 @@ Event EV_Player_AnimLoop_Legs EV_NORMAL ); Event EV_Player_AnimLoop_Pain // Added in 2.0 - ("animloop_pain", EV_DEFAULT, NULL, NULL, "Called when the pain animation has finished.", EV_NORMAL); +( + "animloop_pain", + EV_DEFAULT, + NULL, + NULL, + "Called when the pain animation has finished.", + EV_NORMAL +); Event EV_Player_DoUse ( "usestuff", @@ -503,7 +586,8 @@ Event EV_Player_SafeHolster "preserves state, so it will not holster or unholster unless necessary", EV_NORMAL ); -Event EV_Player_SafeZoom( +Event EV_Player_SafeZoom +( "safezoom", EV_DEFAULT, "b", @@ -621,12 +705,14 @@ Event EV_Player_ModifyHeight EV_NORMAL ); Event EV_Player_ModifyHeightFloat // Added in 2.40 - ("modheightfloat", +( + "modheightfloat", EV_DEFAULT, "ff", "height max_z", "Specify the view height of the player and the height of his bounding box.", - EV_NORMAL); + EV_NORMAL +); Event EV_Player_SetMovePosFlags ( "moveposflags", @@ -691,30 +777,43 @@ Event EV_Player_PickWeapon EV_NORMAL ); Event EV_Player_SetInJail // Added in 2.30 - ("injail", - EV_DEFAULT, - "i", - "boolean", - "set to 1 to indicate when player is in jail," - "0 when they are free", - EV_SETTER); +( + "injail", + EV_DEFAULT, + "i", + "boolean", + "set to 1 to indicate when player is in jail," + "0 when they are free", + EV_SETTER +); Event EV_Player_GetInJail // Added in 2.30 - ("injail", - EV_DEFAULT, - NULL, - NULL, - "returns 1 if player is in jail," - "0 if out", - EV_GETTER); +( + "injail", + EV_DEFAULT, + NULL, + NULL, + "returns 1 if player is in jail," + "0 if out", + EV_GETTER +); Event EV_Player_GetNationalityPrefix // Added in 2.30 - ("nationalityprefix", - EV_DEFAULT, - NULL, - NULL, - "get the three or five letter prefix that denotes the player's nationality", - EV_GETTER); +( + "nationalityprefix", + EV_DEFAULT, + NULL, + NULL, + "get the three or five letter prefix that denotes the player's nationality", + EV_GETTER +); Event EV_Player_IsSpectator // Added in 2.30 - ("isSpectator", EV_DEFAULT, NULL, NULL, "Check to see if player is a spectator (non-zero return value)", EV_GETTER); +( + "isSpectator", + EV_DEFAULT, + NULL, + NULL, + "Check to see if player is a spectator (non-zero return value)", + EV_GETTER +); Event EV_Player_Spectator ( "spectator", @@ -788,7 +887,14 @@ Event EV_Player_Vote EV_NORMAL ); Event EV_Player_RetrieveVoteOptions // Added in 2.0 - ("gvo", EV_CONSOLE, NULL, NULL, "Retrieves the server's vote options file", EV_NORMAL); +( + "gvo", + EV_CONSOLE, + NULL, + NULL, + "Retrieves the server's vote options file", + EV_NORMAL +); Event EV_Player_PrimaryDMWeapon ( "primarydmweapon", @@ -826,9 +932,23 @@ Event EV_Player_Physics_Off EV_NORMAL ); Event EV_Player_ArmWithWeapons // Added in 2.30 - ("armwithweapons", EV_DEFAULT, NULL, NULL, "give player their primary and secondary weapons.", EV_NORMAL); +( + "armwithweapons", + EV_DEFAULT, + NULL, + NULL, + "give player their primary and secondary weapons.", + EV_NORMAL +); Event EV_Player_GetCurrentDMWeaponType // Added in 2.30 - ("getcurrentdmweapontype", EV_DEFAULT, NULL, NULL, "get the player's current DM weapon type.", EV_GETTER); +( + "getcurrentdmweapontype", + EV_DEFAULT, + NULL, + NULL, + "get the player's current DM weapon type.", + EV_GETTER +); Event EV_Player_AttachToLadder ( "attachtoladder", @@ -875,13 +995,41 @@ Event EV_Player_EnsureForwardOffLadder EV_NORMAL ); Event EV_Player_JailIsEscaping // Added in 2.30 - ("isEscaping", EV_DEFAULT, NULL, NULL, "Return non-zero if escaping or assisting escape", EV_GETTER); +( + "isEscaping", + EV_DEFAULT, + NULL, + NULL, + "Return non-zero if escaping or assisting escape", + EV_GETTER +); Event EV_Player_JailEscape // Added in 2.30 - ("jailescape", EV_DEFAULT, NULL, NULL, "Start the escape from jail animation", EV_NORMAL); +( + "jailescape", + EV_DEFAULT, + NULL, + NULL, + "Start the escape from jail animation", + EV_NORMAL +); Event EV_Player_JailAssistEscape // Added in 2.30 - ("jailassistescape", EV_DEFAULT, NULL, NULL, "Start the assist jail escape animation", EV_NORMAL); +( + "jailassistescape", + EV_DEFAULT, + NULL, + NULL, + "Start the assist jail escape animation", + EV_NORMAL +); Event EV_Player_JailEscapeStop // Added in 2.30 - ("jailescapestop", EV_DEFAULT, NULL, NULL, "Stop either the escape from jail or assist animation", EV_NORMAL); +( + "jailescapestop", + EV_DEFAULT, + NULL, + NULL, + "Stop either the escape from jail or assist animation", + EV_NORMAL +); Event EV_Player_GetIsDisguised ( "is_disguised", @@ -902,7 +1050,6 @@ Event EV_Player_GetHasDisguise "non - zero = has a disguise", EV_GETTER ); - Event EV_Player_SetHasDisguise ( "has_disguise", @@ -1034,19 +1181,22 @@ Event EV_GetFireHeld EV_GETTER ); Event EV_GetPrimaryFireHeld // Added in 2.30 - ("primaryfireheld", +( + "primaryfireheld", EV_DEFAULT, NULL, NULL, "returns 1 if this player is holding the primary fire, or 0 if not", EV_GETTER); Event EV_GetSecondaryFireHeld // Added in 2.30 - ("secondaryfireheld", +( + "secondaryfireheld", EV_DEFAULT, NULL, NULL, "returns 1 if this player is holding the secondary fire, or 0 if not", - EV_GETTER); + EV_GETTER +); Event EV_Player_GetReady ( "ready", @@ -1138,7 +1288,7 @@ Event EV_Player_SetPerferredWeapon EV_DEFAULT, "s", "weapon_name", - "Overrides your perferred weapon that is displayed in the stats screen.", + "Overrides your preferred weapon that is displayed in the stats screen.", EV_NORMAL ); Event EV_Player_SetVoiceType @@ -1152,33 +1302,46 @@ Event EV_Player_SetVoiceType ); Event EV_Player_AddKills // Added in 2.0 - ("addkills", EV_DEFAULT, "i", "kills", "Give or take kills from the player", EV_NORMAL); +( + "addkills", + EV_DEFAULT, + "i", + "kills", + "Give or take kills from the player", + EV_NORMAL +); Event EV_Player_KillAxis // Added in 2.30 - ("killaxis", - EV_CHEAT, - "f", - "radius", - "Kills all of the axis that are in the passed radius, or all of them if radius is 0.", - EV_NORMAL); +( + "killaxis", + EV_CHEAT, + "f", + "radius", + "Kills all of the axis that are in the passed radius, or all of them if radius is 0.", + EV_NORMAL +); Event EV_Player_GetTurret // Added in 2.30 - ("turret", - EV_DEFAULT, - NULL, - NULL, - "Returns the turret the player is using. NULL if player isn't using a turret.", - EV_GETTER); +( + "turret", + EV_DEFAULT, + NULL, + NULL, + "Returns the turret the player is using. NULL if player isn't using a turret.", + EV_GETTER +); Event EV_Player_GetVehicle // Added in 2.30 - ("vehicle", - EV_DEFAULT, - NULL, - NULL, - "Returns the vehicle the player is using. NULL if player isn't using a vehicle.", - EV_GETTER); +( + "vehicle", + EV_DEFAULT, + NULL, + NULL, + "Returns the vehicle the player is using. NULL if player isn't using a vehicle.", + EV_GETTER +); //////////////////////////// // -// Openmohaa additions +// Added in OPM // //////////////////////////// Event EV_Player_AddDeaths @@ -1190,7 +1353,6 @@ Event EV_Player_AddDeaths "adds deaths number to player", EV_NORMAL ); - Event EV_Player_AdminRights ( "adminrights", @@ -1200,177 +1362,6 @@ Event EV_Player_AdminRights "returns client admin rights", EV_GETTER ); - -Event EV_Player_BindWeap -( - "bindweap", - EV_DEFAULT, - "ei", - "weapon handnum", - "binds weapon to player and sets him as weapon owner", - EV_NORMAL -); - -Event EV_Player_CanSwitchTeams -( - "canswitchteams", - EV_DEFAULT, - "bB", - "allow_team_change allow_spectate", - "Specify if this player is allowed to switch teams and spectate. Doesn't override global canswitchteams.", - EV_NORMAL -); - -Event EV_Player_ClearCommand -( - "clearcommand", - EV_DEFAULT, - "S", - "command", - "Clears any or a specific client command", - EV_NORMAL -); - -Event EV_Player_Dive -( - "dive", - EV_DEFAULT, - "fF", - "height airborne_duration", - "Makes the player dive into prone position.", - EV_NORMAL -); - -Event EV_Player_Earthquake -( - "earthquake2", - EV_DEFAULT, - "ffbbVF", - "duration magnitude no_rampup no_rampdown location radius", - "Create a smooth realistic earthquake for a player. Requires sv_reborn to be set.", - EV_NORMAL -); - -Event EV_Player_FreezeControls -( - "freezecontrols", - EV_DEFAULT, - "b", - "freeze_state", - "Blocks or unblocks control input from this player.", - EV_NORMAL -); - -Event EV_Player_GetConnState -( - "getconnstate", - EV_DEFAULT, - NULL, - NULL, - "gets connection state. [DEPRECATED]", - EV_RETURN -); - -Event EV_Player_GetDamageMultiplier -( - "damage_multiplier", - EV_DEFAULT, - "Gets the current damage multiplier", - NULL, - NULL, - EV_GETTER -); - -Event EV_Player_GetKillHandler -( - "killhandler", - EV_DEFAULT, - "s", - "label", - "Gets the player's current killed event handler. Returns NIL if no custom killhandler was set.", - EV_GETTER -); - -Event EV_Player_GetKills -( - "getkills", - EV_DEFAULT, - NULL, - NULL, - "gets kills number of player", - EV_RETURN -); - -Event EV_Player_GetDeaths -( - "getdeaths", - EV_DEFAULT, - NULL, - NULL, - "gets deaths number of player", - EV_RETURN -); - -Event EV_Player_GetLegsState -( - "getlegsstate", - EV_DEFAULT, - NULL, - NULL, - "Gets the player's current legs state name", - EV_RETURN -); - -Event EV_Player_GetStateFile -( - "statefile", - EV_DEFAULT, - NULL, - NULL, - "Gets the player's current state file.", - EV_GETTER -); - -Event EV_Player_GetTorsoState -( - "gettorsostate", - EV_DEFAULT, - NULL, - NULL, - "Gets the player's current torso state name", - EV_RETURN -); - -Event EV_Player_HideEnt -( - "hideent", - EV_DEFAULT, - "e", - "entity", - "Hides the specified entity to the player.", - EV_NORMAL -); - -Event EV_Player_Inventory -( - "inventory", - EV_DEFAULT, - NULL, - NULL, - "returns player's inventory", - EV_GETTER -); - -Event EV_Player_InventorySet -( - "inventory", - EV_DEFAULT, - "e", - "array", - "Set up the player's inventory", - EV_SETTER -); - Event EV_Player_IsAdmin ( "isadmin", @@ -1380,7 +1371,123 @@ Event EV_Player_IsAdmin "checks if player is logged as admin", EV_RETURN ); - +Event EV_Player_BindWeap +( + "bindweap", + EV_DEFAULT, + "ei", + "weapon handnum", + "binds weapon to player and sets him as weapon owner", + EV_NORMAL +); +Event EV_Player_Dive +( + "dive", + EV_DEFAULT, + "fF", + "height airborne_duration", + "Makes the player dive into prone position.", + EV_NORMAL +); +Event EV_Player_FreezeControls +( + "freezecontrols", + EV_DEFAULT, + "b", + "freeze_state", + "Blocks or unblocks control input from this player.", + EV_NORMAL +); +Event EV_Player_GetConnState +( + "getconnstate", + EV_DEFAULT, + NULL, + NULL, + "gets connection state. [DEPRECATED]", + EV_RETURN +); +Event EV_Player_GetDamageMultiplier +( + "damage_multiplier", + EV_DEFAULT, + "Gets the current damage multiplier", + NULL, + NULL, + EV_GETTER +); +Event EV_Player_GetKillHandler +( + "killhandler", + EV_DEFAULT, + "s", + "label", + "Gets the player's current killed event handler. Returns NIL if no custom killhandler was set.", + EV_GETTER +); +Event EV_Player_GetKills +( + "getkills", + EV_DEFAULT, + NULL, + NULL, + "gets kills number of player", + EV_RETURN +); +Event EV_Player_GetDeaths +( + "getdeaths", + EV_DEFAULT, + NULL, + NULL, + "gets deaths number of player", + EV_RETURN +); +Event EV_Player_GetLegsState +( + "getlegsstate", + EV_DEFAULT, + NULL, + NULL, + "Gets the player's current legs state name", + EV_RETURN +); +Event EV_Player_GetStateFile +( + "statefile", + EV_DEFAULT, + NULL, + NULL, + "Gets the player's current state file.", + EV_GETTER +); +Event EV_Player_GetTorsoState +( + "gettorsostate", + EV_DEFAULT, + NULL, + NULL, + "Gets the player's current torso state name", + EV_RETURN +); +Event EV_Player_Inventory +( + "inventory", + EV_DEFAULT, + NULL, + NULL, + "returns player's inventory", + EV_GETTER +); +Event EV_Player_InventorySet +( + "inventory", + EV_DEFAULT, + "e", + "array", + "Set up the player's inventory", + EV_SETTER +); Event EV_Player_LeanLeftHeld ( "leanleftheld", @@ -1390,7 +1497,6 @@ Event EV_Player_LeanLeftHeld "Returns 1 if this player is holding lean left key, or 0 if he is not", EV_GETTER ); - Event EV_Player_LeanRightHeld ( "leanrightheld", @@ -1400,7 +1506,6 @@ Event EV_Player_LeanRightHeld "returns EV_RETURN if this player is holding lean right key, or 0 if he is not", EV_GETTER ); - Event EV_Player_MoveSpeedScale ( "moveSpeedScale", @@ -1410,7 +1515,6 @@ Event EV_Player_MoveSpeedScale "Sets the player's speed multiplier (default 1.0).", EV_SETTER ); - Event EV_Player_MoveSpeedScaleGet ( "moveSpeedScale", @@ -1420,7 +1524,6 @@ Event EV_Player_MoveSpeedScaleGet "Gets the player's speed multiplier.", EV_GETTER ); - Event EV_Player_PlayLocalSound ( "playlocalsound", @@ -1431,17 +1534,6 @@ Event EV_Player_PlayLocalSound "sounds.", EV_NORMAL ); - -Event EV_Player_Replicate -( - "replicate", - EV_DEFAULT, - "s", - "variable", - "Replicate a variable to the client (needs patch 1.12).", - EV_NORMAL -); - Event EV_Player_RunHeld ( "runheld", @@ -1452,17 +1544,15 @@ Event EV_Player_RunHeld "or 0 if he is not", EV_GETTER ); - Event EV_Player_SecFireHeld ( "secfireheld", EV_DEFAULT, NULL, NULL, - "returns EV_RETURN if this player is holding secondary fire, or 0 if he is not", + "returns 1 if this player is holding secondary fire, or 0 if he is not", EV_GETTER ); - Event EV_Player_SetAnimSpeed ( "setanimspeed", @@ -1472,7 +1562,6 @@ Event EV_Player_SetAnimSpeed "set the player's animation speed multiplier (default 1.0).", EV_NORMAL ); - Event EV_Player_SetFov ( "setfov", @@ -1482,7 +1571,6 @@ Event EV_Player_SetFov "set the player's fov (default 80).", EV_NORMAL ); - Event EV_Player_SetKillHandler ( "killhandler", @@ -1493,37 +1581,6 @@ Event EV_Player_SetKillHandler "killed event handler.", EV_SETTER ); - -Event EV_Player_SetClientFlag -( - "setclientflag", - EV_DEFAULT, - "s", - "name", - "Calls a flag to the script client.", - EV_NORMAL -); - -Event EV_Player_SetEntityShader -( - "setentshader", - EV_DEFAULT, - "es", - "entity shadername", - "Sets an entity shader for this player. An empty string will revert to the normal entity shader.", - EV_NORMAL -); - -Event EV_Player_SetLocalSoundRate -( - "setlocalsoundrate", - EV_DEFAULT, - "sfF", - "name rate time", - "Sets the local sound rate.", - EV_NORMAL -); - Event EV_Player_SetSpeed ( "setspeed", @@ -1533,7 +1590,6 @@ Event EV_Player_SetSpeed "Sets the player's speed multiplier (default 1.0). Index specify which array value will be used (maximum 4).", EV_NORMAL ); - Event EV_Player_SetStateFile ( "statefile", @@ -1543,7 +1599,6 @@ Event EV_Player_SetStateFile "Sets the player's current state file (setting NIL, NULL or an empty string will revert to the global statefile).", EV_SETTER ); - Event EV_Player_SetTeam ( "setteam", @@ -1554,17 +1609,15 @@ Event EV_Player_SetTeam "Available team names are 'none', 'spectator', 'freeforall', 'axis' and 'allies'.", EV_NORMAL ); - -Event EV_Player_SetViewModelAnimSpeed +Event EV_Player_HideEnt ( - "setvmaspeed", + "hideent", EV_DEFAULT, - "sf", - "name speed", - "Sets the player's animation speed when playing it.", + "e", + "entity", + "Hides the specified entity to the player.", EV_NORMAL ); - Event EV_Player_ShowEnt ( "showent", @@ -1574,7 +1627,6 @@ Event EV_Player_ShowEnt "Shows the specified entity to the player.", EV_NORMAL ); - Event EV_Player_StopLocalSound ( "stoplocalsound", @@ -1584,7 +1636,6 @@ Event EV_Player_StopLocalSound "Stops the specified sound.", EV_NORMAL ); - Event EV_Player_Userinfo ( "userinfo", @@ -1594,7 +1645,6 @@ Event EV_Player_Userinfo "returns userinfo string", EV_GETTER ); - Event EV_Player_ViewModelGetAnim ( "viewmodelgetanim", @@ -1604,7 +1654,6 @@ Event EV_Player_ViewModelGetAnim "Gets the player's current view model animation.", EV_RETURN ); - Event EV_Player_ViewModelAnimFinished ( "viewmodelanimfinished", @@ -1614,7 +1663,6 @@ Event EV_Player_ViewModelAnimFinished "True if the player's current view model finished its animation.", EV_RETURN ); - Event EV_Player_ViewModelAnimValid ( "viewmodelanimvalid", @@ -1625,6 +1673,61 @@ Event EV_Player_ViewModelAnimValid EV_RETURN ); +#ifdef OPM_FEATURES +Event EV_Player_Earthquake +( + "earthquake2", + EV_DEFAULT, + "ffbbVF", + "duration magnitude no_rampup no_rampdown location radius", + "Create a smooth realistic earthquake for a player. Requires sv_reborn to be set.", + EV_NORMAL +); +Event EV_Player_Replicate +( + "replicate", + EV_DEFAULT, + "s", + "variable", + "Replicate a variable to the client (needs patch 1.12).", + EV_NORMAL +); +Event EV_Player_SetClientFlag +( + "setclientflag", + EV_DEFAULT, + "s", + "name", + "Calls a flag to the script client.", + EV_NORMAL +); +Event EV_Player_SetEntityShader +( + "setentshader", + EV_DEFAULT, + "es", + "entity shadername", + "Sets an entity shader for this player. An empty string will revert to the normal entity shader.", + EV_NORMAL +); +Event EV_Player_SetLocalSoundRate +( + "setlocalsoundrate", + EV_DEFAULT, + "sfF", + "name rate time", + "Sets the local sound rate.", + EV_NORMAL +); +Event EV_Player_SetViewModelAnimSpeed +( + "setvmaspeed", + EV_DEFAULT, + "sf", + "name speed", + "Sets the player's animation speed when playing it.", + EV_NORMAL +); Event EV_Player_VisionSetBlur ( "visionsetblur", @@ -1634,7 +1737,6 @@ Event EV_Player_VisionSetBlur "Sets the player's blur level. Level is a fraction from 0-1", EV_NORMAL ); - Event EV_Player_VisionGetNaked ( "visiongetnaked", @@ -1644,7 +1746,6 @@ Event EV_Player_VisionGetNaked "Gets the player's current naked-eye vision.", EV_RETURN ); - Event EV_Player_VisionSetNaked ( "visionsetnaked", @@ -1655,6 +1756,9 @@ Event EV_Player_VisionSetNaked "an empty string, it will revert to the current global vision.", EV_NORMAL ); +#endif + +qboolean TryPush(int entnum, vec3_t move_origin, vec3_t move_end); /* ============================================================================== @@ -1806,11 +1910,7 @@ CLASS_DECLARATION(Sentient, Player, "player") { {&EV_Player_AddDeaths, &Player::AddDeaths }, {&EV_Player_AdminRights, &Player::AdminRights }, {&EV_Player_BindWeap, &Player::BindWeap }, - {&EV_Player_CanSwitchTeams, &Player::CanSwitchTeams }, - {&EV_Player_ClearCommand, &Player::ClearCommand }, {&EV_Player_Dive, &Player::Dive }, - {&EV_Player_DMMessage, &Player::EventDMMessage }, - {&EV_Player_Earthquake, &Player::EventEarthquake }, {&EV_Player_FreezeControls, &Player::FreezeControls }, {&EV_Player_SetTeam, &Player::EventSetTeam }, {&EV_Player_GetConnState, &Player::GetConnState }, @@ -1834,13 +1934,9 @@ CLASS_DECLARATION(Sentient, Player, "player") { {&EV_Player_RunHeld, &Player::RunHeld }, {&EV_Player_SecFireHeld, &Player::SecFireHeld }, {&EV_Player_SetAnimSpeed, &Player::SetAnimSpeed }, - {&EV_Player_SetClientFlag, &Player::SetClientFlag }, - {&EV_Player_SetEntityShader, &Player::SetEntityShader }, {&EV_Player_SetKillHandler, &Player::SetKillHandler }, - {&EV_Player_SetLocalSoundRate, &Player::SetLocalSoundRate }, {&EV_Player_SetSpeed, &Player::SetSpeed }, {&EV_Player_SetStateFile, &Player::SetStateFile }, - {&EV_Player_SetViewModelAnimSpeed, &Player::SetVMASpeed }, {&EV_Player_ShowEnt, &Player::ShowEntity }, {&EV_Player_Spectator, &Player::Spectator }, {&EV_Player_StopLocalSound, &Player::StopLocalSound }, @@ -1848,9 +1944,16 @@ CLASS_DECLARATION(Sentient, Player, "player") { {&EV_Player_ViewModelAnimFinished, &Player::EventGetViewModelAnimFinished}, {&EV_Player_ViewModelGetAnim, &Player::EventGetViewModelAnim }, {&EV_Player_ViewModelAnimValid, &Player::EventGetViewModelAnimValid }, +#ifdef OPM_FEATURES + {&EV_Player_Earthquake, &Player::EventEarthquake }, + {&EV_Player_SetClientFlag, &Player::SetClientFlag }, + {&EV_Player_SetEntityShader, &Player::SetEntityShader }, + {&EV_Player_SetLocalSoundRate, &Player::SetLocalSoundRate }, + {&EV_Player_SetViewModelAnimSpeed, &Player::SetVMASpeed }, {&EV_Player_VisionGetNaked, &Player::VisionGetNaked }, {&EV_Player_VisionSetBlur, &Player::VisionSetBlur }, {&EV_Player_VisionSetNaked, &Player::VisionSetNaked }, +#endif {NULL, NULL } }; @@ -1879,7 +1982,7 @@ Player::Player() // // set the entity type // - entflags |= EF_PLAYER; + entflags |= ECF_PLAYER; mCurTrailOrigin = 0; mLastTrailTime = 0; @@ -1921,6 +2024,19 @@ Player::Player() m_iInvulnerableTimeRemaining = 0; m_fLastVoteTime = 0; + // + // Added in OPM + //==== +#ifdef OPM_FEATURES + m_bShowingHint = false; +#endif + m_fpsTiki = NULL; + m_bConnected = false; + + m_iInstantMessageTime = 0; + m_iTextChatTime = 0; + //==== + if (LoadingSavegame) { return; } @@ -2062,22 +2178,16 @@ Player::Player() m_vViewPos = vec_zero; // - // Openmohaa additions - // - m_bShowingHint = false; - disable_spectate = false; - disable_team_change = false; - m_bFrozen = false; - animDoneVM = true; - m_fVMAtime = 0; - m_fpsTiki = NULL; + // Added in OPM + //==== + m_bFrozen = false; + animDoneVM = true; + m_fVMAtime = 0; + //==== for (int i = 0; i < MAX_SPEED_MULTIPLIERS; i++) { speed_multiplier[i] = 1.0f; } - - m_pKilledEvent = NULL; - m_bConnected = false; } Player::~Player() @@ -2085,8 +2195,6 @@ Player::~Player() int i, num; Conditional *cond; - gi.DPrintf("Player::~Player()\n"); - //assert(0); num = legs_conditionals.NumObjects(); for (i = num; i > 0; i--) { cond = legs_conditionals.ObjectAt(i); @@ -2101,6 +2209,19 @@ Player::~Player() legs_conditionals.FreeObjectList(); torso_conditionals.FreeObjectList(); + + // Added in 2.11 + // Make sure to clean turret stuff up + // when the player is deleted + RemoveFromVehiclesAndTurrets(); + + // Added in OPM + // Remove the player at destructor + if (g_gametype->integer != GT_SINGLE_PLAYER && dmManager.PlayerCount()) { + dmManager.RemovePlayer(this); + } + + entflags &= ~ECF_PLAYER; } static qboolean logfile_started = qfalse; @@ -2142,13 +2263,15 @@ void Player::Init(void) level.Unregister(STRING_PLAYERSPAWN); // - // Added for openmohaa + // Added in OPM // if (!m_bConnected) { m_bConnected = true; Event *ev = new Event; ev->AddEntity(this); + + scriptDelegate_connected.Trigger(this, *ev); scriptedEvents[SE_CONNECTED].Trigger(ev); } @@ -2191,7 +2314,6 @@ void Player::InitEdict(void) } void Player::InitSound(void) - { // // reset the music @@ -2218,7 +2340,7 @@ void Player::InitClient(void) client_persistant_t saved; // deathmatch wipes most client data every spawn - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { char userinfo[MAX_INFO_STRING]; char dm_primary[MAX_QPATH]; float enterTime = client->pers.enterTime; @@ -2248,7 +2370,9 @@ void Player::InitClient(void) SetStopwatch(0); +#ifdef OPM_FEATURES m_bShowingHint = false; +#endif } void Player::InitState(void) @@ -2277,7 +2401,6 @@ void Player::InitState(void) } void Player::InitHealth(void) - { static cvar_t *pMaxHealth = gi.Cvar_Get("g_maxplayerhealth", "250", 0); static cvar_t *pDMHealth = gi.Cvar_Get("g_playerdmhealth", "100", 0); @@ -2288,28 +2411,28 @@ void Player::InitHealth(void) return; } - if (g_gametype->integer != GT_SINGLE_PLAYER) { - if (pDMHealth->integer > 0) { - max_health = pDMHealth->integer; - } else { - max_health = 100.f; - } - - health = max_health; - } else if (!g_realismmode->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER && !g_realismmode->integer) { max_health = pMaxHealth->integer; - health = max_health; + } else if (g_gametype->integer != GT_SINGLE_PLAYER && pDMHealth->integer > 0) { + max_health = pDMHealth->integer; } else { // reset the health values - health = 100; - max_health = health; + max_health = 100; } + health = max_health; + // 2.0: // Make sure to clear the heal rate and the dead flag when respawning // m_fHealRate = 0; edict->s.eFlags &= ~EF_DEAD; + + // Fixed in OPM + // This avoid losing weapons when dying and then immediately respawning + CancelEventsOfType(EV_Player_DMDeathDrop); + // And this prevents the player from dying when respawning immediately after getting killed + CancelEventsOfType(EV_Player_Dead); } void Player::InitModel(void) @@ -2325,8 +2448,8 @@ void Player::InitModel(void) if (g_gametype->integer == GT_SINGLE_PLAYER) { setModel("models/player/" + str(g_playermodel->string) + ".tik"); } else if (dm_team == TEAM_AXIS) { - if (Q_stricmpn(client->pers.dm_playermodel, "german", 6) - && Q_stricmpn(client->pers.dm_playermodel, "axis", 4) + if (Q_stricmpn(client->pers.dm_playergermanmodel, "german", 6) + && Q_stricmpn(client->pers.dm_playergermanmodel, "axis", 4) // // 2.30 models // @@ -2409,15 +2532,20 @@ void Player::InitModel(void) } } + InitModelFps(); +} + +void Player::InitModelFps(void) +{ char model_name[MAX_STRING_TOKENS]; char *model_replace; - strcpy(model_name, model.c_str()); + Q_strncpyz(model_name, model.c_str(), sizeof(model_name)); size_t len = strlen(model_name); model_replace = model_name + len - 4; - strcpy(model_replace, "_fps.tik"); + Q_strncpyz(model_replace, "_fps.tik", sizeof(model_name) - (model_replace - model_name)); m_fpsTiki = gi.modeltiki(model_name); } @@ -2437,10 +2565,13 @@ void Player::InitPhysics(void) memset(&last_ucmd, 0, sizeof(last_ucmd)); client->ps.groundTrace.fraction = 1.0f; + + // Added in OPM + // Prevent the player from being stuck + flags &= ~FL_PARTIAL_IMMOBILE; } void Player::InitPowerups(void) - { // powerups poweruptimer = 0; @@ -2464,27 +2595,35 @@ void Player::InitMaxAmmo(void) GiveAmmo("heavy", 0, 5); GiveAmmo("shotgun", 0, 50); - // - // Team tactics ammunition - // - GiveAmmo("landmine", 0, 5); + if (g_target_game >= target_game_e::TG_MOHTT) { + // + // Team tactics ammunition + // + GiveAmmo("landmine", 0, 5); + } - // - // Team assault ammunition - // - GiveAmmo("smokegrenade", 0, 5); - GiveAmmo("asmokegrenade", 0, 5); - GiveAmmo("riflegrenade", 0, 3); + if (g_target_game >= target_game_e::TG_MOHTA) { + // + // Team assault ammunition + // + GiveAmmo("smokegrenade", 0, 5); + GiveAmmo("asmokegrenade", 0, 5); + GiveAmmo("riflegrenade", 0, 3); + } } void Player::InitWeapons(void) - { // Don't do anything if we're loading a server game. // This is either a loadgame or a restart if (LoadingSavegame) { return; } + + // Added in OPM + // This fixes a bug where player can charge then go to spectator or respawn. + // The grenade would immediately explode when firing + charge_start_time = 0; } void Player::InitInventory(void) {} @@ -2509,7 +2648,7 @@ void Player::ChooseSpawnPoint(void) origin.copyTo(edict->s.origin2); edict->s.renderfx |= RF_FRAMELERP; - if (g_gametype->integer && !IsSpectator()) { + if (g_gametype->integer != GT_SINGLE_PLAYER && !IsSpectator()) { KillBox(this); } @@ -2520,7 +2659,7 @@ void Player::ChooseSpawnPoint(void) VectorCopy(origin, client->ps.vEyePos); client->ps.vEyePos[2] += client->ps.viewheight; - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { for (int i = 1; i <= 4; i++) { Event *ev = new Event(EV_SetViewangles); ev->AddVector(p->angles); @@ -2537,8 +2676,12 @@ void Player::ChooseSpawnPoint(void) } void Player::EndLevel(Event *ev) - { + if (IsDead()) { + ScriptError("cannot do player.endlevel if the player is dead"); + return; + } + InitPowerups(); if (health > max_health) { health = max_health; @@ -2551,7 +2694,7 @@ void Player::EndLevel(Event *ev) void Player::Respawn(Event *ev) { - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { bool bOldVoted; if (health <= 0.0f) { @@ -2589,13 +2732,12 @@ void Player::Respawn(Event *ev) } // - // Added in openmohaa + // Added in OPM // Unregister(STRING_RESPAWN); } void Player::SetDeltaAngles(void) - { int i; @@ -2674,13 +2816,13 @@ void Player::Obituary(Entity *attacker, Entity *inflictor, int meansofdeath, int } if (bDispLocation && g_obituarylocation->integer) { - str szConv1 = s1 + str(" ") + G_LocationNumToDispString(iLocation); + str szConv2 = s2 + " in the " + G_LocationNumToDispString(iLocation); if (dedicated->integer) { - gi.Printf("%s %s\n", client->pers.netname, gi.LV_ConvertString(szConv1.c_str())); + gi.Printf("%s %s\n", client->pers.netname, gi.LV_ConvertString(szConv2.c_str())); } - G_PrintDeathMessage(szConv1, s2.c_str(), "x", client->pers.netname, this, "s"); + G_PrintDeathMessage(s1, szConv2.c_str(), "x", client->pers.netname, this, "s"); } else { if (dedicated->integer) { gi.Printf("%s %s\n", client->pers.netname, gi.LV_ConvertString(s1.c_str())); @@ -2795,20 +2937,20 @@ void Player::Obituary(Entity *attacker, Entity *inflictor, int meansofdeath, int } if (bDispLocation && g_obituarylocation->integer) { - str szConv1 = s1 + str(" ") + G_LocationNumToDispString(iLocation); + str szConv2 = s2 + " in the " + G_LocationNumToDispString(iLocation); G_PrintDeathMessage( - szConv1.c_str(), s2.c_str(), attacker->client->pers.netname, client->pers.netname, this, "p" + s1.c_str(), szConv2.c_str(), attacker->client->pers.netname, client->pers.netname, this, "p" ); if (dedicated->integer) { str szLoc1, szLoc2; - szLoc1 = gi.LV_ConvertString(szConv1.c_str()); + szLoc1 = gi.LV_ConvertString(s1.c_str()); if (s2 == 'x') { gi.Printf("%s %s %s\n", client->pers.netname, szLoc1.c_str(), attacker->client->pers.netname); } else { - szLoc2 = gi.LV_ConvertString(s2.c_str()); + szLoc2 = gi.LV_ConvertString(szConv2.c_str()); gi.Printf( "%s %s %s%s\n", client->pers.netname, @@ -2882,9 +3024,9 @@ void Player::Obituary(Entity *attacker, Entity *inflictor, int meansofdeath, int } if (bDispLocation && g_obituarylocation->integer) { - str szConv1 = s1 + str(" ") + G_LocationNumToDispString(iLocation); + str szConv2 = s2 + " in the " + G_LocationNumToDispString(iLocation); - G_PrintDeathMessage(szConv1.c_str(), s2.c_str(), "x", client->pers.netname, this, "w"); + G_PrintDeathMessage(s1.c_str(), szConv2.c_str(), "x", client->pers.netname, this, "w"); if (dedicated->integer) { gi.Printf("%s %s\n", client->pers.netname, gi.LV_ConvertString(s1.c_str())); @@ -2960,15 +3102,17 @@ void Player::Killed(Event *ev) Event *event; // + // Added in OPM // This one is openmohaa-specific // Custom killed event will do the job // - if (m_pKilledEvent) { - event = new Event(m_pKilledEvent); + if (m_killedLabel.IsSet()) { + event = new Event(0, ev->NumArgs()); for (int i = 1; i <= ev->NumArgs(); i++) { event->AddValue(ev->GetValue(i)); } - ProcessEvent(event); + m_killedLabel.Execute(this, event); + delete event; Unregister(STRING_DEATH); return; @@ -2991,14 +3135,14 @@ void Player::Killed(Event *ev) RemoveFromVehiclesAndTurrets(); - if (g_gametype->integer && attacker && attacker->IsSubclassOfPlayer()) { - ((Player *)attacker)->KilledPlayerInDeathmatch(this); + if (g_gametype->integer != GT_SINGLE_PLAYER && attacker && attacker->IsSubclassOfPlayer()) { + static_cast(attacker)->KilledPlayerInDeathmatch(this, (meansOfDeath_t)meansofdeath); } deadflag = DEAD_DYING; health = 0; - event = new Event(EV_Pain); + event = new Event(EV_Pain, 10); event->AddEntity(attacker); event->AddFloat(ev->GetFloat(2)); @@ -3013,7 +3157,7 @@ void Player::Killed(Event *ev) ProcessEvent(event); - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { if (HasItem("Binoculars")) { takeItem("Binoculars"); } @@ -3064,9 +3208,10 @@ void Player::Killed(Event *ev) } // - // Openmohaa scripted events + // Added in OPM + // Scripted events // - event = new Event; + event = new Event(0, 11); event->AddEntity(ev->GetEntity(1)); event->AddFloat(ev->GetFloat(2)); @@ -3080,6 +3225,7 @@ void Player::Killed(Event *ev) event->AddInteger(ev->GetInteger(10)); event->AddEntity(this); + scriptDelegate_kill.Trigger(this, *event); scriptedEvents[SE_KILL].Trigger(event); Unregister(STRING_DEATH); @@ -3150,49 +3296,59 @@ void Player::SetStopwatch(int iDuration, stopWatchType_t type) } } - sprintf(szCmd, "stopwatch %i %i %i", iStartTime, iDuration, type); + Com_sprintf(szCmd, sizeof(szCmd), "stopwatch %i %i %i", iStartTime, iDuration, type); } else { iStartTime = 0; if (iDuration) { iStartTime = (int)level.svsFloatTime; } - sprintf(szCmd, "stopwatch %i %i", iStartTime, iDuration); + Com_sprintf(szCmd, sizeof(szCmd), "stopwatch %i %i", iStartTime, iDuration); } gi.SendServerCommand(edict - g_entities, szCmd); } -void Player::KilledPlayerInDeathmatch(Player *killed) +void Player::KilledPlayerInDeathmatch(Player *killed, meansOfDeath_t meansofdeath) { - DM_Team* pDMTeam; + DM_Team *pDMTeam; - pDMTeam = killed->GetDM_Team(); + pDMTeam = killed->GetDM_Team(); + + if (meansofdeath == MOD_TELEFRAG) { + // + // Added in OPM + // Telefrag isn't the fault of anyone + // so don't count any kill + // + return; + } if (killed == this) { pDMTeam->AddKills(this, -1); gi.SendServerCommand( edict - g_entities, "print \"" HUD_MESSAGE_WHITE "%s\n\"", gi.LV_ConvertString("You killed yourself") ); - } else { - if (pDMTeam != GetDM_Team() || g_gametype->integer <= GT_FFA || g_gametype->integer >= GT_MAX_GAME_TYPE) { - current_team->AddKills(this, 1); - } else { - // - // A teammate was killed - // - current_team->AddKills(this, -1); - num_team_kills++; - } - - gi.SendServerCommand( - edict - g_entities, - "print \"" HUD_MESSAGE_WHITE "%s %s\n\"", - gi.LV_ConvertString("You killed"), - killed->client->pers.netname - ); + return; } + + if (pDMTeam == GetDM_Team() && g_gametype->integer >= GT_TEAM) { + // + // A teammate was killed + // + current_team->AddKills(this, -1); + num_team_kills++; + } else { + current_team->AddKills(this, 1); + } + + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_WHITE "%s %s\n\"", + gi.LV_ConvertString("You killed"), + killed->client->pers.netname + ); } void Player::Pain(Event *ev) @@ -3235,7 +3391,7 @@ void Player::Pain(Event *ev) pain_location = iLocation; // Only set the regular pain level if enough time since last pain has passed - if ((level.time > nextpaintime) && take_pain) { + if (((level.time > nextpaintime) && take_pain) || IsDead()) { pain = damage; } @@ -3254,7 +3410,7 @@ void Player::Pain(Event *ev) } } - if (g_gametype->integer && attacker && attacker->client && attacker != this) { + if (g_gametype->integer != GT_SINGLE_PLAYER && attacker && attacker->client && attacker != this) { gi.MSG_SetClient(attacker->edict - g_entities); if (IsDead()) { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_NOTIFY_KILL)); @@ -3288,23 +3444,52 @@ void Player::DoUse(Event *ev) int touch[MAX_GENTITIES]; int num; int i; + bool bWasInTurretOrVehicle; if (g_gametype->integer != GT_SINGLE_PLAYER && IsSpectator()) { + // Prevent using stuff while spectating return; } if (IsDead()) { + // Dead players mustn't use return; } - if (m_pVehicle || m_pTurret) { - RemoveFromVehiclesAndTurretsInternal(); - } else if (!(buttons & BUTTON_ATTACKLEFT) && !(buttons & BUTTON_ATTACKRIGHT)) { - // - // Allow use if the player isn't holding attack buttons - // - num = getUseableEntities(touch, MAX_GENTITIES, true); + if (edict->r.svFlags & SVF_NOCLIENT) { + // Fixed in OPM + // Clients that are not sent to other clients cannot use objects. + // Some mods make players non-solid, hide them and turn physics off + // as a way to spectate other players or for cinematics. + // This prevent players to use objects such as doors + return; + } + bWasInTurretOrVehicle = m_pVehicle || m_pTurret; + + if (bWasInTurretOrVehicle) { + RemoveFromVehiclesAndTurretsInternal(); + return; + } + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + if ((buttons & BUTTON_ATTACKLEFT) || (buttons & BUTTON_ATTACKRIGHT)) { + // + // Added in 2.0 + // Only allow use if the player isn't holding attack buttons + // + return; + } + } + + num = getUseableEntities(touch, MAX_GENTITIES, true); + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + // Fixed in 2.0 + // Since 2.0, the loop stops when the player + // uses a turret, this prevents the turret from being deleted + // after being attached to the player + // for (i = 0; i < num; i++) { hit = &g_entities[touch[i]]; @@ -3317,45 +3502,40 @@ void Player::DoUse(Event *ev) hit->entity->ProcessEvent(event); - if (m_pVehicle || m_pTurret) - { - if (m_pVehicle) - { - // - // transmit the godmode to the vehicle - // - if (flags & FL_GODMODE) { - m_pVehicle->flags |= FL_GODMODE; - } else { - m_pVehicle->flags &= ~FL_GODMODE; - } - } - - return; + if (m_pVehicle || m_pTurret) { + break; } } - } + } else { + // + // Backward compatibility + // It still allows 1.11 SP to work properly + // Such as in m1l1 when the player must man the mounted machine gun + for (i = 0; i < num; i++) { + hit = &g_entities[touch[i]]; - // FIXME: special game feature -#if 0 + if (!hit->inuse) { + continue; + } - // Now retrieve entities that doesn't require to look at - num = getUseableEntities( touch, MAX_GENTITIES, false ); + Event *event = new Event(EV_Use); + event->AddListener(this); - for( i = 0; i < num; i++ ) - { - hit = &g_entities[ touch[ i ] ]; - - if( !hit->inuse || hit->entity == NULL || hit->entity == this ) { - continue; + hit->entity->ProcessEvent(event); + } + } + + if (!bWasInTurretOrVehicle && m_pVehicle) { + // + // Added in 2.30 + // Make the vehicle also invincible if the player is invincible + // + if (flags & FL_GODMODE) { + m_pVehicle->flags |= FL_GODMODE; + } else { + m_pVehicle->flags &= ~FL_GODMODE; } - - Event *event = new Event( EV_Use ); - event->AddListener( this ); - - hit->entity->ProcessEvent( event ); } -#endif } void Player::TouchStuff(pmove_t *pm) @@ -3410,7 +3590,7 @@ void Player::GetMoveInfo(pmove_t *pm) { moveresult = pm->moveresult; - if (!deadflag || (g_gametype->integer && IsSpectator())) { + if (!deadflag || (g_gametype->integer != GT_SINGLE_PLAYER && IsSpectator())) { v_angle[0] = pm->ps->viewangles[0]; v_angle[1] = pm->ps->viewangles[1]; v_angle[2] = pm->ps->viewangles[2]; @@ -3448,11 +3628,15 @@ void Player::GetMoveInfo(pmove_t *pm) } // - // Openmohaa fix + // Fixed in OPM // Disable predictions when the groundentity is moving up/down, looks like shaky otherwise if (groundentity->entity && groundentity->entity != this && groundentity->entity->velocity[2] != 0) { pm->ps->pm_flags |= PMF_NO_PREDICTION; } + } else if (m_pGlueMaster) { + // Added in OPM + // Use the glue master for the ground entity to make the viewmodel will stay still + pm->ps->groundEntityNum = m_pGlueMaster->entnum; } velocity = Vector(pm->ps->velocity[0], pm->ps->velocity[1], pm->ps->velocity[2]); @@ -3535,20 +3719,29 @@ void Player::SetMoveInfo(pmove_t *pm, usercmd_t *ucmd) pm->alwaysAllowLean = qfalse; } - pm->leanMax = 45.f; - pm->leanAdd = 6.f; + pm->leanMax = 45.f; + pm->leanAdd = 6.f; pm->leanRecoverSpeed = 8.5f; - pm->leanSpeed = 2.f; + pm->leanSpeed = 2.f; } else { pm->alwaysAllowLean = qtrue; + if (g_gametype->integer != GT_SINGLE_PLAYER) { + pm->leanMax = 40.f; + } else { + // Don't allow lean in single-player, like in the original game + pm->leanMax = 0; + } - pm->leanMax = 40.f; - pm->leanAdd = 10.f; + pm->leanAdd = 10.f; pm->leanRecoverSpeed = 15.f; - pm->leanSpeed = 4.f; + pm->leanSpeed = 4.f; } - pm->protocol = g_protocol; + pm->protocol = g_protocol; + + // Added in OPM + // Initialize the ground entity + pm->ps->groundEntityNum = ENTITYNUM_NONE; } pmtype_t Player::GetMovePlayerMoveType(void) @@ -3622,7 +3815,6 @@ qboolean Player::AnimMove(Vector& move, Vector *endpos) } qboolean Player::TestMove(Vector& move, Vector *endpos) - { trace_t trace; Vector pos(origin + move); @@ -3675,7 +3867,6 @@ qboolean Player::TestMove(Vector& move, Vector *endpos) } float Player::TestMoveDist(Vector& move) - { Vector endpos; @@ -3761,7 +3952,6 @@ qboolean Player::CheckMove(Vector& move, Vector *endpos) } float Player::CheckMoveDist(Vector& move) - { Vector endpos; @@ -3776,7 +3966,7 @@ void Player::ClientMove(usercmd_t *ucmd) pmove_t pm; Vector move; -#if 0 +#ifdef OPM_FEATURES int touch[MAX_GENTITIES]; int num = getUseableEntities(touch, MAX_GENTITIES, true); bool bHintShown = false; @@ -3795,13 +3985,12 @@ void Player::ClientMove(usercmd_t *ucmd) m_bShowingHint = false; // FIXME: delete - if (sv_specialgame->integer) - { + if (sv_specialgame->integer) { gi.MSG_SetClient(edict - g_entities); // Send the hint string once gi.MSG_StartCGM(CGM_HINTSTRING); - gi.MSG_WriteString(""); + gi.MSG_WriteString(""); gi.MSG_EndCGM(); } } @@ -3812,8 +4001,8 @@ void Player::ClientMove(usercmd_t *ucmd) client->ps.pm_type = GetMovePlayerMoveType(); // set move flags client->ps.pm_flags &= - ~(PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_NO_GRAVITY | PMF_VIEW_PRONE - | PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START); + ~(PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_TURRET | PMF_VIEW_PRONE | PMF_VIEW_DUCK_RUN + | PMF_VIEW_JUMP_START); if (level.playerfrozen || m_bFrozen) { client->ps.pm_flags |= PMF_FROZEN; @@ -3833,23 +4022,24 @@ void Player::ClientMove(usercmd_t *ucmd) client->ps.pm_flags |= PMF_NO_MOVE; } - /* - if (maxs.z == 60.0f) { - client->ps.pm_flags |= PMF_DUCKED; - } else if (maxs.z == 54.0f) { - client->ps.pm_flags |= PMF_DUCKED | PMF_VIEW_PRONE; - } else if (maxs.z == 20.0f) { - client->ps.pm_flags |= PMF_VIEW_PRONE; - } else if (maxs.z == 53.0f) { - client->ps.pm_flags |= PMF_VIEW_DUCK_RUN; - } else if (viewheight == 52) { - client->ps.pm_flags |= PMF_VIEW_JUMP_START; - } - */ - if (maxs.z == 54.0f ||maxs.z == 60.0f) { - client->ps.pm_flags |= PMF_DUCKED; - } else if (viewheight == 52) { - client->ps.pm_flags |= PMF_VIEW_JUMP_START; + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + if (maxs.z == 54.0f || maxs.z == 60.0f) { + client->ps.pm_flags |= PMF_DUCKED; + } else if (viewheight == JUMP_START_VIEWHEIGHT) { + client->ps.pm_flags |= PMF_VIEW_JUMP_START; + } + } else { + if (maxs.z == 60.0f) { + client->ps.pm_flags |= PMF_DUCKED; + } else if (maxs.z == 54.0f) { + client->ps.pm_flags |= PMF_DUCKED | PMF_VIEW_PRONE; + } else if (maxs.z == 20.0f) { + client->ps.pm_flags |= PMF_VIEW_PRONE; + } else if (maxs.z == 53.0f) { + client->ps.pm_flags |= PMF_VIEW_DUCK_RUN; + } else if (viewheight == JUMP_START_VIEWHEIGHT) { + client->ps.pm_flags |= PMF_VIEW_JUMP_START; + } } switch (movecontrol) { @@ -3893,19 +4083,19 @@ void Player::ClientMove(usercmd_t *ucmd) // Also use the weapon movement speed // if (!IsZoomed()) { - client->ps.speed = (float)client->ps.speed * pWeap->m_fMovementSpeed; + client->ps.speed = (float)client->ps.speed * pWeap->GetMovementSpeed(); } else { - client->ps.speed = (float)client->ps.speed * pWeap->m_fZoomMovement * pWeap->m_fMovementSpeed; + client->ps.speed = (float)client->ps.speed * pWeap->GetZoomMovement(); } } } - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { client->ps.speed = (int)((float)client->ps.speed * sv_dmspeedmult->value); } //==== - // Openmohaa addition + // Added in OPM for (int i = 0; i < MAX_SPEED_MULTIPLIERS; i++) { client->ps.speed = (int)((float)client->ps.speed * speed_multiplier[i]); } @@ -4000,11 +4190,11 @@ void Player::VehicleMove(usercmd_t *ucmd) // set move flags client->ps.pm_flags &= - ~(PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_NO_GRAVITY | PMF_VIEW_PRONE - | PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START); + ~(PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_TURRET | PMF_VIEW_PRONE | PMF_VIEW_DUCK_RUN + | PMF_VIEW_JUMP_START); // disable prediction - client->ps.pm_flags |= PMF_NO_GRAVITY | PMF_NO_PREDICTION; + client->ps.pm_flags |= PMF_TURRET | PMF_NO_PREDICTION; if (level.playerfrozen || m_bFrozen) { client->ps.pm_flags |= PMF_FROZEN; @@ -4014,6 +4204,10 @@ void Player::VehicleMove(usercmd_t *ucmd) if (m_pVehicle->Drive(current_ucmd)) { client->ps.commandTime = ucmd->serverTime; + // Added in OPM + // The player can't walk while attached to a vehicle + client->ps.groundEntityNum = ENTITYNUM_NONE; + client->ps.walking = false; } else { ClientMove(ucmd); } @@ -4031,13 +4225,13 @@ void Player::TurretMove(usercmd_t *ucmd) // set move flags client->ps.pm_flags &= - ~(PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_NO_GRAVITY | PMF_VIEW_PRONE - | PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START); + ~(PMF_FROZEN | PMF_NO_PREDICTION | PMF_NO_MOVE | PMF_DUCKED | PMF_TURRET | PMF_VIEW_PRONE | PMF_VIEW_DUCK_RUN + | PMF_VIEW_JUMP_START); // disable prediction - client->ps.pm_flags |= PMF_NO_GRAVITY | PMF_NO_PREDICTION; + client->ps.pm_flags |= PMF_TURRET | PMF_NO_PREDICTION; if (getMoveType() == MOVETYPE_PORTABLE_TURRET) { - client->ps.pm_flags |= PMF_NO_GRAVITY; + client->ps.pm_flags |= PMF_TURRET; } if (level.playerfrozen || m_bFrozen) { @@ -4046,17 +4240,25 @@ void Player::TurretMove(usercmd_t *ucmd) client->ps.gravity = gravity * sv_gravity->value; - if (!m_pTurret->IsSubclassOfTurretGun() - || (m_pTurret->IsSubclassOfTurretGun() && m_pTurret->UserAim(current_ucmd))) { - ClientMove(ucmd); - } else { + if (m_pVehicle) { + // Added in 2.30 + m_pVehicle->PathDrive(current_ucmd); + } + + if (m_pTurret->IsSubclassOfTurretGun() && m_pTurret->UserAim(current_ucmd)) { client->ps.commandTime = ucmd->serverTime; + // Added in OPM + // The player can't walk while attached to a turret + client->ps.groundEntityNum = ENTITYNUM_NONE; + client->ps.walking = false; + } else { + ClientMove(ucmd); } } void Player::ClientInactivityTimer(void) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -4074,7 +4276,7 @@ void Player::ClientInactivityTimer(void) // // The player reached maximum team kills // - G_PrintToAllClients(va("%s %s", client->pers.netname, message.c_str()), qfalse); + G_PrintToAllClients(va("%s %s\n", client->pers.netname, message.c_str()), 2); if (Q_stricmp(Info_ValueForKey(client->pers.userinfo, "ip"), "localhost")) { // @@ -4103,7 +4305,7 @@ void Player::ClientInactivityTimer(void) ); } - if (current_ucmd->buttons & BUTTON_MOUSE || (!g_inactivespectate->integer && !g_inactivekick->integer) + if (current_ucmd->buttons & BUTTON_ANY || (!g_inactivespectate->integer && !g_inactivekick->integer) || current_ucmd->forwardmove || current_ucmd->rightmove || current_ucmd->upmove || (m_bTempSpectator && client->lastActiveTime >= level.inttime - 5000)) { client->lastActiveTime = level.inttime; @@ -4193,7 +4395,7 @@ void Player::UpdateEnemies(void) float fMaxCosSquared; Vector vLookDir; - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -4266,7 +4468,7 @@ void Player::ClientThink(void) TickSprint(); - if (g_gametype->integer && dm_team == TEAM_SPECTATOR && !IsSpectator()) { + if (g_gametype->integer != GT_SINGLE_PLAYER && dm_team == TEAM_SPECTATOR && !IsSpectator()) { Spectator(); } @@ -4318,7 +4520,7 @@ void Player::ClientThink(void) client->cmd_angles[1] = SHORT2ANGLE(current_ucmd->angles[1]); client->cmd_angles[2] = SHORT2ANGLE(current_ucmd->angles[2]); - if (g_gametype->integer && g_smoothClients->integer && !IsSubclassOfBot()) { + if (g_gametype->integer != GT_SINGLE_PLAYER && g_smoothClients->integer) { VectorCopy(client->ps.velocity, edict->s.pos.trDelta); edict->s.pos.trTime = client->ps.commandTime; } else { @@ -4331,6 +4533,7 @@ void Player::ClientThink(void) if (g_gametype->integer != GT_SINGLE_PLAYER) { client->ps.pm_flags |= PMF_FROZEN; client->ps.pm_flags |= PMF_INTERMISSION; + VectorClear(client->ps.velocity); if (level.time - level.intermissiontime > 5.0f && (new_buttons & (BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT))) { @@ -4352,12 +4555,13 @@ void Player::ClientThink(void) || g_medalbt3->modificationCount > 1 || g_medalbt4->modificationCount > 1 || g_medalbt5->modificationCount > 1 || g_eogmedal0->modificationCount > 1 || g_eogmedal1->modificationCount > 1 || g_eogmedal2->modificationCount > 1) { - gi.cvar_set("g_gotmedal", "0"); - } else { gi.cvar_set("g_gotmedal", "1"); + } else { + gi.cvar_set("g_gotmedal", "0"); } client->ps.pm_flags |= PMF_FROZEN; + VectorClear(client->ps.velocity); if (level.time - level.intermissiontime > 4.0f) { if (level.intermissiontype) { @@ -4529,10 +4733,16 @@ void Player::Think(void) gi.SendServerCommand(edict - g_entities, "stufftext \"pushmenu_teamselect\""); } } + // Removed in 2.0 + //else if (level.time > m_fWeapSelectTime + 10.0) { + // m_fWeapSelectTime = level.time; + // gi.centerprintf(edict, "\n\n\n%s", gi.LV_ConvertString("Press fire to join the battle!")); + //} } else if (!client->pers.dm_primary[0]) { Spectator(); if (m_fWeapSelectTime < level.time) { - gi.SendServerCommand(edict - g_entities, "stufftext \"pushmenu_weaponselect\""); + m_fWeapSelectTime = level.time + 1.0; + UserSelectWeapon(false); } } @@ -4558,7 +4768,7 @@ void Player::Think(void) } } else { if ((server_new_buttons & BUTTON_USE)) { - SetPlayerSpectateRandom(); + SetPlayerSpectate(true); } } @@ -4567,14 +4777,12 @@ void Player::Think(void) SetPlayerSpectateRandom(); } else { gentity_t *ent = g_entities + m_iPlayerSpectating - 1; - Player *player; if (!ent->inuse || !ent->entity) { + // Invalid spectate entity SetPlayerSpectateRandom(); - } - - player = static_cast(ent->entity); - if (player->deadflag >= DEAD_DEAD || player->IsSpectator() || !IsValidSpectatePlayer(player)) { + } else if (ent->entity->deadflag >= DEAD_DEAD || static_cast(ent->entity)->IsSpectator() + || !IsValidSpectatePlayer(static_cast(ent->entity))) { SetPlayerSpectateRandom(); } } @@ -4593,22 +4801,15 @@ void Player::Think(void) if (m_iPlayerSpectating) { gentity_t *ent = g_entities + m_iPlayerSpectating - 1; - Player *player; if (!ent->inuse || !ent->entity) { // Invalid spectate entity SetPlayerSpectateRandom(); - } - - player = static_cast(ent->entity); - if (player->deadflag >= DEAD_DEAD || player->IsSpectator()) { - // Dead player, spectate another player + } else if (ent->entity->deadflag >= DEAD_DEAD || static_cast(ent->entity)->IsSpectator() + || !IsValidSpectatePlayer(static_cast(ent->entity))) { SetPlayerSpectateRandom(); - } - - if (g_gametype->integer >= GT_TEAM && g_forceteamspectate->integer && GetTeam() > TEAM_FREEFORALL - && GetTeam() != player->GetTeam()) { - // Spectate another player if the target player switched teams + } else if (g_gametype->integer >= GT_TEAM && GetTeam() > TEAM_FREEFORALL + && static_cast(ent->entity)->GetTeam() != GetTeam()) { SetPlayerSpectateRandom(); } } @@ -4626,7 +4827,7 @@ void Player::Think(void) } if (!IsDead()) { - m_iClientWeaponCommand = (server_new_buttons & WEAPON_COMMAND_MASK) >> 7; + m_iClientWeaponCommand = G_GetWeaponCommand(server_new_buttons); switch (m_iClientWeaponCommand) { case 0: @@ -4707,9 +4908,8 @@ void Player::Think(void) mvTrailEyes[0] = centroid; mvTrailEyes[0][0] = EyePosition()[0]; } - - UpdateFootsteps(); } + UpdateFootsteps(); // // Added in 2.0 @@ -4727,7 +4927,7 @@ void Player::Think(void) m_fHealRate -= newrate; } } else { - newrate = 0; + newrate = m_fHealRate; m_fHealRate = 0; } @@ -4743,9 +4943,9 @@ void Player::Think(void) // Added in 2.0: talk icon // if (buttons & BUTTON_TALK) { - edict->s.eFlags |= EF_PLAYER_TALKING; + edict->s.eFlags |= EF_PLAYER_IN_MENU; } else { - edict->s.eFlags &= ~EF_PLAYER_TALKING; + edict->s.eFlags &= ~EF_PLAYER_IN_MENU; } if (m_fTalkTime > level.time) { @@ -4755,7 +4955,7 @@ void Player::Think(void) } // - // Openmohaa additions + // Added in OPM // if (!animDoneVM) { int index; @@ -4788,6 +4988,8 @@ void Player::Think(void) } server_new_buttons = 0; + + edict->r.svFlags &= ~(SVF_SINGLECLIENT | SVF_NOTSINGLECLIENT); } void Player::InitLegsStateTable(void) @@ -4819,16 +5021,32 @@ void Player::InitTorsoStateTable(void) void Player::LoadStateTable(void) { + int i; + Conditional *cond; + statemap_Legs = NULL; statemap_Torso = NULL; + // + // Free existing conditionals + // + for (i = legs_conditionals.NumObjects(); i > 0; i--) { + cond = legs_conditionals.ObjectAt(i); + delete cond; + } legs_conditionals.FreeObjectList(); + + for (i = torso_conditionals.NumObjects(); i > 0; i--) { + cond = torso_conditionals.ObjectAt(i); + delete cond; + } torso_conditionals.FreeObjectList(); statemap_Legs = - GetStatemap(str(g_statefile->string) + "_Legs.st", (Condition *)Conditions, &legs_conditionals, false); - statemap_Torso = - GetStatemap(str(g_statefile->string) + "_Torso.st", (Condition *)Conditions, &torso_conditionals, false); + GetStatemap(str(g_statefile->string) + "_Legs.st", (Condition *)m_conditions, &legs_conditionals, false); + statemap_Torso = GetStatemap( + str(g_statefile->string) + "_Torso.st", (Condition *)m_conditions, &torso_conditionals, false + ); movecontrol = MOVECONTROL_LEGS; @@ -4872,7 +5090,6 @@ void Player::ResetState(Event *ev) } void Player::StartPush(void) - { trace_t trace; Vector end(origin + yaw_forward * 64.0f); @@ -4888,7 +5105,6 @@ void Player::StartPush(void) } void Player::StartClimbLadder(void) - { trace_t trace; Vector end(origin + yaw_forward * 20.0f); @@ -4965,13 +5181,11 @@ void Player::StartUseAnim(void) } void Player::StartLoopUseAnim(void) - { useanim_numloops--; } void Player::FinishUseAnim(Event *ev) - { UseAnim *ua; @@ -4985,7 +5199,6 @@ void Player::FinishUseAnim(Event *ev) } void Player::SetupUseObject(void) - { UseObject *uo; Vector neworg; @@ -5035,7 +5248,6 @@ void Player::SetupUseObject(void) } void Player::StartUseObject(Event *ev) - { UseObject *uo; @@ -5048,7 +5260,6 @@ void Player::StartUseObject(Event *ev) } void Player::FinishUseObject(Event *ev) - { UseObject *uo; @@ -5062,7 +5273,6 @@ void Player::FinishUseObject(Event *ev) } void Player::Turn(Event *ev) - { float yaw; Vector oldang(v_angle); @@ -5086,7 +5296,6 @@ void Player::Turn(Event *ev) } void Player::TurnUpdate(Event *ev) - { float yaw; float timeleft; @@ -5115,7 +5324,6 @@ void Player::TurnUpdate(Event *ev) } void Player::TurnLegs(Event *ev) - { float yaw; @@ -5138,6 +5346,19 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) return; } + if (flags & FL_IMMOBILE) { + // Don't evaluate state when immobile + return; + } + + if (getMoveType() == MOVETYPE_PORTABLE_TURRET) { + // Added in 2.0 + // Animations are handled hardcodedly + currentState_Torso = NULL; + currentState_Legs = NULL; + return; + } + // Evaluate the current state. // When the state changes, we reevaluate the state so that if the // conditions aren't met in the new state, we don't play one frame of @@ -5159,15 +5380,31 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) laststate_Torso = currentState_Torso; - if (forceTorso) { - currentState_Torso = forceTorso; + if (currentState_Torso) { + laststate_Torso = currentState_Torso; + + if (forceTorso) { + currentState_Torso = forceTorso; + } else { + currentState_Torso = currentState_Torso->Evaluate(*this, &torso_conditionals); + } } else { - currentState_Torso = currentState_Torso->Evaluate(*this, &torso_conditionals); + // Added in 2.0 + // Switch to the default torso state if it's NULL + if (forceTorso) { + currentState_Torso = forceTorso; + } else { + currentState_Torso = statemap_Torso->FindState("STAND"); + } + + laststate_Torso = NULL; } if (currentState_Torso) { - // Process exit commands of the last state - laststate_Torso->ProcessExitCommands(this); + if (laststate_Torso) { + // Process exit commands of the last state + laststate_Torso->ProcessExitCommands(this); + } // Process entry commands of the new state currentState_Torso->ProcessEntryCommands(this); @@ -5203,6 +5440,13 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) StopPartAnimating(torso); animdone_Torso = true; } else if (torsoAnim != "") { + if (torsoAnim == partAnim[torso]) { + // Fixed in OPM + // Stop the part if it's the same animation + // so the new animation can play and make some action + // like activate the new weapon. + StopPartAnimating(torso); + } SetPartAnim(torsoAnim.c_str(), torso); } } else { @@ -5210,6 +5454,11 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) StopPartAnimating(torso); animdone_Torso = true; } else if (torsoAnim != "") { + if (torsoAnim == partAnim[torso]) { + // Fixed in OPM + // See above + StopPartAnimating(torso); + } SetPartAnim(torsoAnim.c_str(), torso); } @@ -5220,6 +5469,16 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) } else { SetPartAnim(legsAnim.c_str(), legs); } + + // Fixed in OPM + // Clear the legs state, so the torso state can reset it to STAND + // in subsequent iterations. + // As the legs animation is stopped, there would be no anim to wait on. + // + // This prevents the current legs state to be stuck + // when the move control is set to non-legs and then to legs + // in the same iteration before the legs state is being processed. + currentState_Legs = NULL; } if (movecontrol != move) { @@ -5261,26 +5520,33 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) } } - if (!laststate_Legs) { - if ((m_iMovePosFlags & MPF_POSITION_CROUCHING)) { + if (currentState_Legs) { + laststate_Legs = currentState_Legs; + + if (forceLegs) { + currentState_Legs = forceLegs; + } else { + currentState_Legs = currentState_Legs->Evaluate(*this, &legs_conditionals); + } + } else { + // Added in 2.0 + // Switch to the default legs state if it's NULL + if (forceLegs) { + currentState_Legs = forceLegs; + } else if ((m_iMovePosFlags & MPF_POSITION_CROUCHING)) { currentState_Legs = statemap_Legs->FindState("CROUCH_IDLE"); } else { currentState_Legs = statemap_Legs->FindState("STAND"); } + + laststate_Legs = NULL; } - laststate_Legs = currentState_Legs; - - if (forceLegs) { - currentState_Legs = forceLegs; - } else { - currentState_Legs = currentState_Legs->Evaluate(*this, &legs_conditionals); - } - - animdone_Legs = false; if (currentState_Legs) { - // Process exit commands of the last state - laststate_Legs->ProcessExitCommands(this); + if (laststate_Legs) { + // Process exit commands of the last state + laststate_Legs->ProcessExitCommands(this); + } // Process entry commands of the new state currentState_Legs->ProcessEntryCommands(this); @@ -5296,7 +5562,26 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) StopPartAnimating(legs); animdone_Legs = true; } else if (legsAnim != "") { - SetPartAnim(legsAnim, legs); + float oldTime; + + if (currentState_Legs == laststate_Legs) { + // + // Added in OPM + // This allows different animations in the same state + // to be continued at the same moment. + // This is used to avoid "ghost walking" where the player + // would switch weapons indefinitely to avoid footstep sounds + // + + oldTime = GetTime(m_iPartSlot[legs]); + SetPartAnim(legsAnim, legs); + + if (animtimes[m_iPartSlot[legs]] > 0) { + SetTime(m_iPartSlot[legs], fmod(oldTime, animtimes[m_iPartSlot[legs]])); + } + } else { + SetPartAnim(legsAnim, legs); + } } } else { currentState_Legs = laststate_Legs; @@ -5307,21 +5592,25 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) } if (g_showplayeranim->integer) { - if (last_leg_anim_name != AnimName(legs)) { - gi.DPrintf("Legs change from %s to %s\n", last_leg_anim_name.c_str(), AnimName(legs)); - last_leg_anim_name = AnimName(legs); + str sNewAnim; + + sNewAnim = AnimName(m_iPartSlot[legs]); + if (last_leg_anim_name != sNewAnim) { + gi.DPrintf("Legs anim change from %s to %s\n", last_leg_anim_name.c_str(), sNewAnim.c_str()); + last_leg_anim_name = sNewAnim; } - if (last_torso_anim_name != AnimName(torso)) { - gi.DPrintf("Torso change from %s to %s\n", last_torso_anim_name.c_str(), AnimName(torso)); - last_torso_anim_name = AnimName(torso); + sNewAnim = AnimName(m_iPartSlot[torso]); + if (last_torso_anim_name != sNewAnim) { + gi.DPrintf("Torso anim change from %s to %s\n", last_torso_anim_name.c_str(), sNewAnim.c_str()); + last_torso_anim_name = sNewAnim; } } if (g_showplayerstate->integer) { if (startstate_Legs != currentState_Legs) { gi.DPrintf( - "Legs change from %s to %s\n", + "Legs state change from %s to %s\n", startstate_Legs ? startstate_Legs->getName() : "NULL", currentState_Legs ? currentState_Legs->getName() : "NULL" ); @@ -5329,7 +5618,7 @@ void Player::EvaluateState(State *forceTorso, State *forceLegs) if (startstate_Torso != currentState_Torso) { gi.DPrintf( - "Torso change from %s to %s\n", + "Torso state change from %s to %s\n", startstate_Torso ? startstate_Torso->getName() : "NULL", currentState_Torso ? currentState_Torso->getName() : "NULL" ); @@ -5372,19 +5661,38 @@ void Player::SelectNextItem(Event *ev) void Player::SelectPreviousWeapon(Event *ev) { + Weapon *weapon; + Weapon *initialWeapon; + Weapon *activeWeapon; + if (deadflag) { return; } - Weapon *weapon = GetActiveWeapon(WEAPON_MAIN); - Weapon *activeWeapon = weapon; + activeWeapon = GetActiveWeapon(WEAPON_MAIN); + if (activeWeapon && activeWeapon->IsSubclassOfInventoryItem()) { + activeWeapon = NULL; + } - if (weapon) { - weapon = PreviousWeapon(weapon); + if (!activeWeapon) { + activeWeapon = newActiveWeapon.weapon; + if (activeWeapon && activeWeapon->IsSubclassOfInventoryItem()) { + activeWeapon = NULL; + } + } - if (g_gametype->integer) { - while (weapon && weapon != activeWeapon && weapon->IsSubclassOfInventoryItem()) { - weapon = PreviousWeapon(weapon); + if (activeWeapon) { + // Fixed in OPM + // Fixes the bug that cause infinite loop when the last weapon has no ammo + // and the only weapon is an inventory item + for (weapon = initialWeapon = PreviousWeapon(activeWeapon); weapon && weapon != activeWeapon;) { + if (g_gametype->integer == GT_SINGLE_PLAYER || !weapon->IsSubclassOfInventoryItem()) { + break; + } + + weapon = PreviousWeapon(weapon); + if (weapon == initialWeapon) { + break; } } } else { @@ -5394,23 +5702,46 @@ void Player::SelectPreviousWeapon(Event *ev) if (weapon && weapon != activeWeapon) { useWeapon(weapon); } + + if (deadflag) { + return; + } } void Player::SelectNextWeapon(Event *ev) { + Weapon *weapon; + Weapon *initialWeapon; + Weapon *activeWeapon; + if (deadflag) { return; } - Weapon *weapon = GetActiveWeapon(WEAPON_MAIN); - Weapon *activeWeapon = weapon; + activeWeapon = GetActiveWeapon(WEAPON_MAIN); + if (activeWeapon && activeWeapon->IsSubclassOfInventoryItem()) { + activeWeapon = NULL; + } - if (weapon) { - weapon = NextWeapon(weapon); + if (!activeWeapon) { + activeWeapon = newActiveWeapon.weapon; + if (activeWeapon && activeWeapon->IsSubclassOfInventoryItem()) { + activeWeapon = NULL; + } + } - if (g_gametype->integer) { - while (weapon && weapon != activeWeapon && weapon->IsSubclassOfInventoryItem()) { - weapon = NextWeapon(weapon); + if (activeWeapon) { + // Fixed in OPM + // Fixes the bug that cause infinite loop when the last weapon has no ammo + // and the only weapon is an inventory item + for (weapon = initialWeapon = NextWeapon(activeWeapon); weapon && weapon != activeWeapon;) { + if (g_gametype->integer == GT_SINGLE_PLAYER || !weapon->IsSubclassOfInventoryItem()) { + break; + } + + weapon = NextWeapon(weapon); + if (weapon == initialWeapon) { + break; } } } else { @@ -5427,7 +5758,7 @@ void Player::DropCurrentWeapon(Event *ev) Weapon *weapon; Vector forward; - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -5476,13 +5807,11 @@ void Player::DropCurrentWeapon(Event *ev) } void Player::GiveWeaponCheat(Event *ev) - { giveItem(ev->GetString(1)); } void Player::GiveCheat(Event *ev) - { str name; @@ -5512,7 +5841,7 @@ void Player::GiveAllCheat(Event *ev) if (gi.FS_ReadFile("global/giveall.scr", (void **)&buf, true) != -1) { buffer = buf; while (1) { - strcpy(com_token, COM_ParseExt(&buffer, qtrue)); + Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token)); if (!com_token[0]) { break; @@ -5523,7 +5852,7 @@ void Player::GiveAllCheat(Event *ev) // get the rest of the line while (1) { - strcpy(com_token, COM_ParseExt(&buffer, qfalse)); + Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token)); if (!com_token[0]) { break; } @@ -5578,7 +5907,6 @@ void Player::GiveNewWeaponsCheat(Event *ev) } void Player::GodCheat(Event *ev) - { const char *msg; @@ -5660,6 +5988,7 @@ void Player::NoclipCheat(Event *ev) // reset the state machine so that his animations are correct ResetState(NULL); + charge_start_time = 0; } else { client->ps.feetfalling = false; movecontrol = MOVECONTROL_LEGS; @@ -5672,7 +6001,6 @@ void Player::NoclipCheat(Event *ev) } void Player::GameVersion(Event *ev) - { gi.SendServerCommand(edict - g_entities, "print \"%s : %s\n\"", GAMEVERSION, __DATE__); } @@ -5690,13 +6018,18 @@ void Player::SetFov(float newFov) void Player::EventSetSelectedFov(Event *ev) { + float fOldSelectedFov; + if (ev->NumArgs() < 1) { gi.SendServerCommand(edict - g_entities, "print \"Fov = %d\n\"", (unsigned int)fov); return; } + fOldSelectedFov = selectedfov; SetSelectedFov(ev->GetFloat(1)); - SetFov(selectedfov); + if (fov == fOldSelectedFov) { + SetFov(selectedfov); + } } void Player::SetSelectedFov(float newFov) @@ -5710,7 +6043,7 @@ void Player::SetSelectedFov(float newFov) } /* - if( g_gametype->integer && !developer->integer ) + if( g_gametype->integer != GT_SINGLE_PLAYER && !developer->integer ) { if( selectedfov < 80 ) { @@ -5731,7 +6064,6 @@ CalcRoll =============== */ float Player::CalcRoll(void) - { float sign; float side; @@ -5789,8 +6121,13 @@ void Player::ProcessPmoveEvents(int event) } else { damage = 5; } - if (!DM_FLAG(DF_NO_FALLING)) { - Damage(world, world, (int)damage, origin, vec_zero, vec_zero, 0, DAMAGE_NO_ARMOR, MOD_FALLING); + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + // since 2.0, remove a percentage of the health + damage = damage * (max_health / 100.0); + } + if (g_gametype->integer == GT_SINGLE_PLAYER || !DM_FLAG(DF_NO_FALLING)) { + Damage(this, this, (int)damage, origin, vec_zero, vec_zero, 0, DAMAGE_NO_ARMOR, MOD_FALLING); } break; case EV_TERMINAL_VELOCITY: @@ -5837,7 +6174,6 @@ AddBlend ============= */ void Player::AddBlend(float r, float g, float b, float a) - { float a2; float a3; @@ -5864,7 +6200,6 @@ CalcBlend ============= */ void Player::CalcBlend(void) - { int contents; Vector vieworg; @@ -6035,151 +6370,157 @@ void Player::DamageFeedback(void) damage_blend += (damage_blood / realcount) * bcolor; } - // - // Since 2.0: Try to find and play pain animation - // - if (getMoveType() == MOVETYPE_PORTABLE_TURRET) { - // use mg42 pain animation - painAnim = "mg42_tripod_"; - } else { - Weapon *pWeap; - const char *itemName; - // try to find an animation + if (g_target_game >= target_game_e::TG_MOHTA) { + // + // Since 2.0: Try to find and play pain animation + // + if (getMoveType() == MOVETYPE_PORTABLE_TURRET) { + // use mg42 pain animation + painAnim = "mg42_tripod_"; + } else { + Weapon *pWeap; + const char *itemName; + // try to find an animation - pWeap = GetActiveWeapon(WEAPON_MAIN); - if (pWeap) { - int weapon_class; + pWeap = GetActiveWeapon(WEAPON_MAIN); + if (pWeap) { + int weapon_class; - weapon_class = pWeap->GetWeaponClass(); - if (weapon_class & WEAPON_CLASS_PISTOL) { - painAnim = "pistol_"; - } else if (weapon_class & WEAPON_CLASS_RIFLE) { - painAnim = "rifle_"; - } else if (weapon_class & WEAPON_CLASS_SMG) { - // get the animation name from the item name - itemName = pWeap->GetItemName(); + weapon_class = pWeap->GetWeaponClass(); + if (weapon_class & WEAPON_CLASS_PISTOL) { + painAnim = "pistol_"; + } else if (weapon_class & WEAPON_CLASS_RIFLE) { + painAnim = "rifle_"; + } else if (weapon_class & WEAPON_CLASS_SMG) { + // get the animation name from the item name + itemName = pWeap->GetItemName(); - if (!Q_stricmp(itemName, "MP40")) { - painAnim = "mp40_"; - } else if (!Q_stricmp(itemName, "Sten Mark II")) { - painAnim = "sten_"; + if (!Q_stricmp(itemName, "MP40")) { + painAnim = "mp40_"; + } else if (!Q_stricmp(itemName, "Sten Mark II")) { + painAnim = "sten_"; + } else { + painAnim = "smg_"; + } + } else if (weapon_class & WEAPON_CLASS_MG) { + itemName = pWeap->GetItemName(); + + if (!Q_stricmp(itemName, "StG 44")) { + painAnim = "mp44_"; + } else { + painAnim = "mg_"; + } + } else if (weapon_class & WEAPON_CLASS_GRENADE) { + itemName = pWeap->GetItemName(); + + // 2.30: use landmine animations + if (!Q_stricmp(itemName, "Minedetector")) { + painAnim = "minedetector_"; + } else if (!Q_stricmp(itemName, "Minensuchgerat")) { + painAnim = "minedetectoraxis_"; + } else if (!Q_stricmp(itemName, "LandmineAllies")) { + painAnim = "mine_"; + } else if (!Q_stricmp(itemName, "LandmineAxis")) { + painAnim = "mine_"; + } else if (!Q_stricmp(itemName, "LandmineAxis")) { + painAnim = "grenade_"; + } + } else if (weapon_class & WEAPON_CLASS_HEAVY) { + itemName = pWeap->GetItemName(); + + if (!Q_stricmp(itemName, "Shotgun")) { + painAnim = "shotgun_"; + } else { + // Defaults to bazooka + painAnim = "bazooka_"; + } } else { - painAnim = "smg_"; - } - } else if (weapon_class & WEAPON_CLASS_MG) { - itemName = pWeap->GetItemName(); + itemName = pWeap->GetItemName(); - if (!Q_stricmp(itemName, "StG 44")) { - painAnim = "mp44_"; - } else { - painAnim = "mg_"; - } - } else if (weapon_class & WEAPON_CLASS_GRENADE) { - itemName = pWeap->GetItemName(); - - // 2.30: use landmine animations - if (!Q_stricmp(itemName, "Minedetector")) { - painAnim = "minedetector_"; - } else if (!Q_stricmp(itemName, "Minensuchgerat")) { - painAnim = "minedetectoraxis_"; - } else if (!Q_stricmp(itemName, "LandmineAllies")) { - painAnim = "mine_"; - } else if (!Q_stricmp(itemName, "LandmineAxis")) { - painAnim = "mine_"; - } else if (!Q_stricmp(itemName, "LandmineAxis")) { - painAnim = "grenade_"; - } - } else if (weapon_class & WEAPON_CLASS_HEAVY) { - itemName = pWeap->GetItemName(); - - if (!Q_stricmp(itemName, "Shotgun")) { - painAnim = "shotgun_"; - } else { - // Defaults to bazooka - painAnim = "bazooka_"; + if (!Q_stricmp(itemName, "Packed MG42 Turret")) { + painAnim = "mg42_"; + } else { + // Default animation if not found + painAnim = "unarmed_"; + } } } else { - itemName = pWeap->GetItemName(); - - if (!Q_stricmp(itemName, "Packed MG42 Turret")) { - painAnim = "mg42_"; - } else { - // Default animation if not found - painAnim = "unarmed_"; - } + painAnim = "unarmed_"; } + + // use the animation based on the movement + if (m_iMovePosFlags & MPF_POSITION_CROUCHING) { + painAnim += "crouch_"; + } else { + painAnim += "stand_"; + } + } + + painAnim += "hit_"; + + if (pain_dir == PAIN_REAR || pain_location == HITLOC_TORSO_MID || HITLOC_TORSO_LOWER) { + painAnim += "back"; } else { - painAnim = "unarmed_"; + switch (pain_location) { + case HITLOC_HEAD: + case HITLOC_HELMET: + case HITLOC_NECK: + painAnim += "head"; + break; + case HITLOC_TORSO_UPPER: + case HITLOC_TORSO_MID: + painAnim += "uppertorso"; + break; + case HITLOC_TORSO_LOWER: + case HITLOC_PELVIS: + painAnim += "lowertorso"; + break; + case HITLOC_R_ARM_UPPER: + case HITLOC_R_ARM_LOWER: + case HITLOC_R_HAND: + painAnim += "rarm"; + break; + case HITLOC_L_ARM_UPPER: + case HITLOC_L_ARM_LOWER: + case HITLOC_L_HAND: + painAnim += "larm"; + break; + case HITLOC_R_LEG_UPPER: + case HITLOC_L_LEG_UPPER: + case HITLOC_R_LEG_LOWER: + case HITLOC_L_LEG_LOWER: + case HITLOC_R_FOOT: + case HITLOC_L_FOOT: + painAnim += "leg"; + break; + default: + painAnim += "uppertorso"; + break; + } } - // use the animation based on the movement - if (m_iMovePosFlags & MPF_POSITION_CROUCHING) { - painAnim += "crouch_"; + animnum = gi.Anim_NumForName(edict->tiki, painAnim.c_str()); + if (animnum == -1) { + gi.DPrintf("WARNING: Could not find player pain animation '%s'\n", painAnim.c_str()); } else { - painAnim += "stand_"; + NewAnim(animnum, EV_Player_AnimLoop_Pain, ANIMSLOT_PAIN); + RestartAnimSlot(ANIMSLOT_PAIN); + m_sPainAnim = painAnim; + m_fPainBlend = 1.f; + animdone_Pain = false; } } - painAnim += "hit_"; - - if (pain_dir == PAIN_REAR || pain_location == HITLOC_TORSO_MID || HITLOC_TORSO_LOWER) { - painAnim += "back"; - } else { - switch (pain_location) { - case HITLOC_HEAD: - case HITLOC_HELMET: - case HITLOC_NECK: - painAnim += "head"; - break; - case HITLOC_TORSO_UPPER: - case HITLOC_TORSO_MID: - painAnim += "uppertorso"; - break; - case HITLOC_TORSO_LOWER: - case HITLOC_PELVIS: - painAnim += "lowertorso"; - break; - case HITLOC_R_ARM_UPPER: - case HITLOC_R_ARM_LOWER: - case HITLOC_R_HAND: - painAnim += "rarm"; - break; - case HITLOC_L_ARM_UPPER: - case HITLOC_L_ARM_LOWER: - case HITLOC_L_HAND: - painAnim += "larm"; - break; - case HITLOC_R_LEG_UPPER: - case HITLOC_L_LEG_UPPER: - case HITLOC_R_LEG_LOWER: - case HITLOC_L_LEG_LOWER: - case HITLOC_R_FOOT: - case HITLOC_L_FOOT: - painAnim += "leg"; - break; - default: - painAnim += "uppertorso"; - break; - } - } - - animnum = gi.Anim_NumForName(edict->tiki, painAnim.c_str()); - if (animnum == -1) { - gi.DPrintf("WARNING: Could not find player pain animation '%s'\n", painAnim.c_str()); - } else { - NewAnim(animnum, EV_Player_AnimLoop_Pain, ANIMSLOT_PAIN); - RestartAnimSlot(ANIMSLOT_PAIN); - m_sPainAnim = painAnim; - m_fPainBlend = 1.f; - animdone_Pain = false; - } - // // clear totals // damage_blood = 0; - if (IsSubclassOfPlayer()) { + // + // Added in 2.0 + // Don't show damage when in god mode + // + if (flags & FL_GODMODE) { damage_count = 0; damage_blood = 0; damage_alpha = 0; @@ -6203,18 +6544,11 @@ void Player::SetPlayerView( Camera *camera, Vector position, float cameraoffset, Vector ang, Vector vel, float camerablend[4], float camerafov ) { - client->ps.viewangles[0] = ang[0]; - client->ps.viewangles[1] = ang[1]; - client->ps.viewangles[2] = ang[2]; - client->ps.viewheight = cameraoffset; + VectorCopy(ang, client->ps.viewangles); + client->ps.viewheight = cameraoffset; - client->ps.origin[0] = position[0]; - client->ps.origin[1] = position[1]; - client->ps.origin[2] = position[2]; - - client->ps.velocity[0] = vel[0]; - client->ps.velocity[1] = vel[1]; - client->ps.velocity[2] = vel[2]; + VectorCopy(position, client->ps.origin); + VectorCopy(vel, client->ps.velocity); /* client->ps.blend[ 0 ] = camerablend[ 0 ]; @@ -6227,36 +6561,50 @@ void Player::SetPlayerView( if (camera) { if (camera->IsSubclassOfCamera()) { - client->ps.camera_angles[0] = camera->angles[0]; - client->ps.camera_angles[1] = camera->angles[1]; - client->ps.camera_angles[2] = camera->angles[2]; - - client->ps.camera_origin[0] = camera->origin[0]; - client->ps.camera_origin[1] = camera->origin[1]; - client->ps.camera_origin[2] = camera->origin[2]; + VectorCopy(camera->angles, client->ps.camera_angles); + VectorCopy(camera->origin, client->ps.camera_origin); Vector vOfs = camera->GetPositionOffset(); VectorCopy(vOfs, client->ps.camera_posofs); client->ps.pm_flags |= PMF_CAMERA_VIEW; + if (camera->ShowQuakes()) { + client->ps.pm_flags |= PMF_DAMAGE_ANGLES; + } else { + client->ps.pm_flags &= ~PMF_DAMAGE_ANGLES; + } + // // clear out the flags, but preserve the CF_CAMERA_CUT_BIT // client->ps.camera_flags = client->ps.camera_flags & CF_CAMERA_CUT_BIT; - } else if (camera->IsSubclassOfPlayer()) { - Vector vPos, vAng; - Player *pPlayer = (Player *)camera; + } else { + Vector vVec; - GetSpectateFollowOrientation(pPlayer, vPos, vAng); + if (camera->IsSubclassOfPlayer()) { + Vector vPos; + Player *pPlayer = (Player *)camera; - VectorCopy(vPos, client->ps.camera_origin); - VectorCopy(vAng, client->ps.camera_angles); + GetSpectateFollowOrientation(pPlayer, vPos, vVec); - SetViewAngles(pPlayer->GetViewAngles()); - setOrigin(pPlayer->origin); + VectorCopy(vVec, client->ps.camera_angles); + VectorCopy(vPos, client->ps.camera_origin); - VectorClear(client->ps.camera_posofs); + SetViewAngles(vVec); + + vPos[2] -= viewheight; + setOrigin(vPos); + + vVec.setXYZ(0, 0, 0); + } else { + VectorCopy(ang, client->ps.camera_angles); + VectorCopy(position, client->ps.camera_angles); + + vVec.setXYZ(0, 0, 0); + } + + VectorCopy(vVec, client->ps.camera_posofs); client->ps.pm_flags |= PMF_CAMERA_VIEW; client->ps.camera_flags = client->ps.camera_flags & CF_CAMERA_CUT_BIT; } @@ -6270,7 +6618,11 @@ void Player::SetPlayerView( qboolean do_cut; int camera_type; - camera_type = currentState_Torso->getCameraType(); + if (currentState_Torso) { + camera_type = currentState_Torso->getCameraType(); + } else { + camera_type = CAMERA_BEHIND; + } if (last_camera_type != camera_type) { // // clear out the flags, but preserve the CF_CAMERA_CUT_BIT @@ -6341,6 +6693,8 @@ void Player::SetPlayerView( CameraCut(); } } + } else { + client->ps.camera_flags = client->ps.camera_flags & CF_CAMERA_CUT_BIT; } // @@ -6609,7 +6963,6 @@ void Player::SetupView(void) } Vector Player::GetAngleToTarget(Entity *ent, str tag, float yawclamp, float pitchclamp, Vector baseangles) - { assert(ent); @@ -6654,7 +7007,6 @@ Vector Player::GetAngleToTarget(Entity *ent, str tag, float yawclamp, float pitc } void Player::DebugWeaponTags(int controller_tag, Weapon *weapon, str weapon_tagname) - { int i; orientation_t bone_or, tag_weapon_or, barrel_or, final_barrel_or; @@ -6730,8 +7082,9 @@ PlayerAngles void Player::PlayerAngles(void) { if (getMoveType() == MOVETYPE_PORTABLE_TURRET) { - // Addition in 2.0 - // FIXME: Set viewangles from m_pTurret + PortableTurret *portableTurret = static_cast(m_pTurret.Pointer()); + angles[0] = portableTurret->GetGroundPitch(); + angles[1] = portableTurret->GetStartYaw(); } PmoveAdjustAngleSettings(v_angle, angles, &client->ps, &edict->s); @@ -6768,7 +7121,7 @@ void Player::FinishMove(void) DamageFeedback(); CalcBlend(); - if (g_gametype->integer && g_smoothClients->integer && !IsSubclassOfBot()) { + if (g_gametype->integer != GT_SINGLE_PLAYER && g_smoothClients->integer) { VectorCopy(client->ps.velocity, edict->s.pos.trDelta); edict->s.pos.trTime = client->ps.commandTime; } else { @@ -6799,11 +7152,8 @@ void Player::CopyStats(Player *player) VectorCopy(player->client->ps.origin, client->ps.origin); VectorCopy(player->client->ps.velocity, client->ps.velocity); - if (client->ps.iViewModelAnim != player->client->ps.iViewModelAnim) { - ViewModelAnim(player->m_sVMcurrent, qfalse, 0); - } else if (client->ps.iViewModelAnimChanged != player->client->ps.iViewModelAnimChanged) { - ViewModelAnim(player->m_sVMcurrent, qtrue, 0); - } + client->ps.iViewModelAnim = player->client->ps.iViewModelAnim; + client->ps.iViewModelAnimChanged = player->client->ps.iViewModelAnimChanged; client->ps.gravity = player->client->ps.gravity; client->ps.speed = player->client->ps.speed; @@ -6836,7 +7186,7 @@ void Player::CopyStats(Player *player) edict->r.svFlags &= ~SVF_NOCLIENT; edict->s.renderfx &= ~RF_DONTDRAW; - player->edict->r.svFlags |= SVF_PORTAL; + player->edict->r.svFlags |= SVF_NOTSINGLECLIENT; player->edict->r.singleClient = client->ps.clientNum; edict->r.svFlags |= SVF_SINGLECLIENT; @@ -6865,9 +7215,6 @@ void Player::CopyStats(Player *player) CloneEntity(dest, ent->entity); - dest->edict->r.svFlags |= SVF_SINGLECLIENT; - dest->edict->r.singleClient = client->ps.clientNum; - dest->edict->s.modelindex = ent->entity->edict->s.modelindex; dest->edict->tiki = ent->entity->edict->tiki; dest->edict->s.actionWeight = ent->entity->edict->s.actionWeight; @@ -6892,8 +7239,8 @@ void Player::UpdateStats(void) if (g_spectatefollow_firstperson->integer && IsSpectator() && m_iPlayerSpectating != 0) { // - // Openmohaa addition - // First-person spectate + // Added in OPM + // First-person spectate // gentity_t *ent = g_entities + (m_iPlayerSpectating - 1); @@ -6989,7 +7336,7 @@ void Player::UpdateStats(void) trace = G_Trace(m_vViewPos, vec_zero, vec_zero, vEnd, this, MASK_BEAM, qfalse, "infoclientcheck"); - if (trace.ent && trace.ent->entity->IsSubclassOfPlayer()) { + if (trace.ent && trace.ent->entity->IsSubclassOfPlayer() && !(trace.ent->r.svFlags & SVF_NOCLIENT)) { Player *p = static_cast(trace.ent->entity); if (IsSpectator() || p->GetTeam() == GetTeam()) { @@ -7018,14 +7365,14 @@ void Player::UpdateStats(void) } } - if (g_gametype->integer < GT_TOW) { - vObjectiveLocation = level.m_vObjectiveLocation; - } else { + if (g_gametype->integer >= GT_TOW || level.m_bForceTeamObjectiveLocation) { if (GetTeam() == TEAM_AXIS) { vObjectiveLocation = level.m_vAxisObjectiveLocation; } else if (GetTeam() == TEAM_ALLIES) { vObjectiveLocation = level.m_vAlliedObjectiveLocation; } + } else { + vObjectiveLocation = level.m_vObjectiveLocation; } if (g_protocol < protocol_e::PROTOCOL_MOHTA_MIN && vObjectiveLocation == vec_zero) { @@ -7074,7 +7421,7 @@ void Player::UpdateStats(void) healthfrac = (health / max_health * 100.0f); if (m_pVehicle && !m_pTurret) { - if (m_pVehicle->isSubclassOf(FixedTurret)) { + if (!m_pVehicle->isSubclassOf(FixedTurret)) { healthfrac = (m_pVehicle->health / m_pVehicle->max_health * 100.f); } } @@ -7190,13 +7537,6 @@ void Player::UpdateStats(void) count = inventory.NumObjects(); - if (count > MAX_WEAPONS) { - count = MAX_WEAPONS; - warning("Player::UpdateStats", "Max inventory exceeded\n"); - } - - count = inventory.NumObjects(); - int iItem = 0; for (i = 1; i <= count; i++) { @@ -7206,18 +7546,17 @@ void Player::UpdateStats(void) if (weapon->IsSubclassOfWeapon()) { if (weapon->IsSubclassOfInventoryItem()) { - if (iItem <= 3) { + if (iItem > 3) { + weapon->SetItemSlot(0); + } else { client->ps.activeItems[iItem + 2] = weapon->getIndex(); - weapon->weapon_class = (256 << iItem) & WEAPON_CLASS_ITEMINDEX; - weapon->weapon_class |= weapon->weapon_class & ~WEAPON_CLASS_ITEMINDEX; + weapon->SetItemSlot(WEAPON_CLASS_ITEM1 << iItem); if (activeweap && weapon == activeweap) { - client->ps.stats[STAT_EQUIPPED_WEAPON] = 256 << iItem; + client->ps.stats[STAT_EQUIPPED_WEAPON] = WEAPON_CLASS_ITEM1 << iItem; } iItem++; - } else { - weapon->weapon_class &= ~WEAPON_CLASS_ITEMINDEX; } } else { weapon_class = weapon->GetWeaponClass(); @@ -7328,7 +7667,7 @@ void Player::UpdateStats(void) float frac; - level.m_letterbox_time -= level.intframetime; + level.m_letterbox_time -= level.frametime; frac = level.m_letterbox_time / level.m_letterbox_time_start; @@ -7359,14 +7698,12 @@ void Player::UpdateMusic(void) } void Player::SetReverb(int type, float level) - { reverb_type = type; reverb_level = level; } void Player::SetReverb(str type, float level) - { reverb_type = EAXMode_NameToNum(type); reverb_level = level; @@ -7444,7 +7781,6 @@ void Player::EndFrame(void) } void Player::GotKill(Event *ev) - { /* Entity *victim; @@ -7467,7 +7803,6 @@ void Player::GotKill(Event *ev) } void Player::SetPowerupTimer(Event *ev) - { Event *event; @@ -7478,7 +7813,6 @@ void Player::SetPowerupTimer(Event *ev) } void Player::UpdatePowerupTimer(Event *ev) - { poweruptimer -= 1; if (poweruptimer > 0) { @@ -7516,7 +7850,6 @@ void Player::ChangeMusic(const char *current, const char *fallback, qboolean for } void Player::ChangeMusicVolume(float volume, float fade_time) - { music_volume_fade_time = fade_time; music_saved_volume = music_current_volume; @@ -7524,7 +7857,6 @@ void Player::ChangeMusicVolume(float volume, float fade_time) } void Player::RestoreMusicVolume(float fade_time) - { music_volume_fade_time = fade_time; music_current_volume = music_saved_volume; @@ -7541,18 +7873,37 @@ void Player::addOrigin(Vector org) } void Player::Jump(Event *ev) - { float maxheight; + if (m_pTurret || m_pVehicle) { + // Don't jump when inside a vehicle or turret + return; + } + + if (g_gametype->integer != GT_SINGLE_PLAYER) { + // Added in 2.0 + // Don't jump when on top of another sentient + if (groundentity && groundentity->entity && groundentity->entity->IsSubclassOfSentient()) { + return; + } + } + maxheight = ev->GetFloat(1); if (maxheight > 16) { // v^2 = 2ad velocity[2] += sqrt(2 * sv_gravity->integer * maxheight); + if (client->ps.groundEntityNum != ENTITYNUM_NONE) { + velocity += m_vPushVelocity; + } + // make sure the player leaves the ground client->ps.walking = qfalse; + + // Added in 2.0 + m_bHasJumped = true; } } @@ -7564,6 +7915,11 @@ void Player::JumpXY(Event *ev) float time; float speed; + if (m_pTurret || m_pVehicle) { + // Don't jump when inside a vehicle or turret + return; + } + forwardmove = ev->GetFloat(1); sidemove = ev->GetFloat(2); speed = ev->GetFloat(3); @@ -7574,6 +7930,10 @@ void Player::JumpXY(Event *ev) time = distance / speed; velocity[2] = sv_gravity->integer * time * 0.5f; + if (client->ps.groundEntityNum != ENTITYNUM_NONE) { + velocity += G_GetEntity(client->ps.groundEntityNum)->velocity; + } + airspeed = distance; // make sure the player leaves the ground @@ -7588,6 +7948,10 @@ void Player::SetViewAngles(Vector newViewangles) client->ps.delta_angles[2] = ANGLE2SHORT(newViewangles.z - client->cmd_angles[2]); v_angle = newViewangles; + // Fixed in OPM + // Normalize angles to the range (-180, +180) + // so interpolation is done properly client-side + v_angle.EulerNormalize(); // get the pitch and roll from our leg angles newViewangles.x = angles.x; @@ -7603,7 +7967,6 @@ void Player::SetTargetViewAngles(Vector angles) } void Player::DumpState(Event *ev) - { gi.DPrintf( "Legs: %s Torso: %s\n", currentState_Legs ? currentState_Legs->getName() : "NULL", currentState_Torso->getName() @@ -7668,17 +8031,33 @@ void Player::ExitVehicle(Event *ev) flags &= ~FL_PARTIAL_IMMOBILE; setMoveType(MOVETYPE_WALK); m_pVehicle = NULL; + + if (camera) { + SetCamera(NULL, 0.5f); + ZoomOff(); + } + + SafeHolster(false); + takedamage = DAMAGE_YES; + setSolidType(SOLID_BBOX); } void Player::EnterTurret(TurretGun *ent) { flags |= FL_PARTIAL_IMMOBILE; viewheight = DEFAULT_VIEWHEIGHT; + velocity = vec_zero; + m_pTurret = ent; - velocity = vec_zero; - - m_pTurret = ent; - setMoveType(MOVETYPE_TURRET); + if (ent->inheritsFrom(PortableTurret::classinfostatic())) { + // carryable turret + setMoveType(MOVETYPE_PORTABLE_TURRET); + StopPartAnimating(torso); + SetPartAnim("mg42tripod_aim_straight_straight"); + } else { + // standard turret + setMoveType(MOVETYPE_TURRET); + } SafeHolster(true); } @@ -7691,7 +8070,7 @@ void Player::EnterTurret(Event *ev) return; } - if (ent->IsSubclassOfTurretGun()) { + if (!ent->inheritsFrom(TurretGun::classinfostatic())) { return; } @@ -7700,12 +8079,19 @@ void Player::EnterTurret(Event *ev) void Player::ExitTurret(void) { + if (m_pTurret->inheritsFrom(PortableTurret::classinfostatic())) { + StopPartAnimating(torso); + SetPartAnim("mg42tripod_aim_straight_straight"); + } + flags &= ~FL_PARTIAL_IMMOBILE; setMoveType(MOVETYPE_WALK); - m_pTurret = NULL; SafeHolster(qfalse); + + new_buttons = 0; + server_new_buttons = 0; } void Player::ExitTurret(Event *ev) @@ -7734,7 +8120,6 @@ void Player::Holster(Event *ev) } void Player::WatchActor(Event *ev) - { if (camera || currentState_Torso->getCameraType() != CAMERA_BEHIND) { return; @@ -7744,7 +8129,6 @@ void Player::WatchActor(Event *ev) } void Player::StopWatchingActor(Event *ev) - { Actor *old_actor; @@ -7767,7 +8151,6 @@ void Player::setAngles(Vector ang) } painDirection_t Player::Pain_string_to_int(str pain) - { if (!pain.icmp(pain, "Front")) { return PAIN_FRONT; @@ -7785,6 +8168,7 @@ painDirection_t Player::Pain_string_to_int(str pain) void Player::ArchivePersistantData(Archiver& arc) { str model_name; + str name; Sentient::ArchivePersistantData(arc); @@ -7796,11 +8180,9 @@ void Player::ArchivePersistantData(Archiver& arc) // set the cvar gi.cvar_set("g_playermodel", model_name.c_str()); - model_name += ".tik"; - setModel(model_name.c_str()); + setModel("models/player/" + model_name + ".tik"); } - str name; if (arc.Saving()) { if (holsteredWeapon) { name = holsteredWeapon->getName(); @@ -7808,11 +8190,10 @@ void Player::ArchivePersistantData(Archiver& arc) name = "none"; } } + arc.ArchiveString(&name); - if (arc.Loading()) { - if (name != "none") { - holsteredWeapon = (Weapon *)FindItem(name); - } + if (arc.Loading() && name != "none") { + holsteredWeapon = (Weapon *)FindItem(name); } UpdateWeapons(); @@ -7937,8 +8318,10 @@ void Player::ModifyHeight(Event *ev) maxs.z = 94.0f; m_bHasJumped = false; } else if (!height.icmp("jumpstart")) { - //viewheight = JUMP_START_VIEWHEIGHT; - maxs.z = 94.0f; + if (g_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + viewheight = JUMP_START_VIEWHEIGHT; + } + maxs.z = 94.0f; } else if (!height.icmp("duck")) { viewheight = CROUCH_VIEWHEIGHT; maxs.z = 54.0f; @@ -7947,8 +8330,8 @@ void Player::ModifyHeight(Event *ev) maxs.z = 60.0f; } else if (!height.icmp("prone")) { // - // Prone was added in openmohaa - // + // Added in OPM + // (prone) viewheight = PRONE_VIEWHEIGHT; maxs.z = 20.0f; } else { @@ -8197,6 +8580,8 @@ nationality_t GetAlliedType(const char* name) } */ +// Commented out in OPM. See the other comment below. +/* nationality_t GetPlayerTeamType(const char *name) { if (!Q_stricmpn(name, "american", 8)) { @@ -8219,6 +8604,59 @@ nationality_t GetPlayerTeamType(const char *name) return NA_NONE; } } +*/ + +// Fixed in OPM. +// This fixes the issue where the player can equip weapons +// from the other team +nationality_t GetPlayerAxisTeamType(const char *name) +{ + if (g_target_game < target_game_e::TG_MOHTA) { + // Only american and german are supported on older versions of the game + return NA_GERMAN; + } + + if (!Q_stricmpn(name, "german", 6)) { + return NA_GERMAN; + } + + if (g_target_game < target_game_e::TG_MOHTT) { + // Italian skins are supported only in mohaab + return NA_GERMAN; + } + + if (!Q_stricmpn(name, "it", 2)) { + return NA_ITALIAN; + } else if (!Q_stricmpn(name, "sc", 2)) { + return NA_ITALIAN; + } + + // fallback to german + return NA_GERMAN; +} + +nationality_t GetPlayerAlliedTeamType(const char *name) +{ + if (g_target_game < target_game_e::TG_MOHTA) { + // Only american and german are supported on older versions of the game + return NA_AMERICAN; + } + + if (!Q_stricmpn(name, "american", 8)) { + return NA_AMERICAN; + } else if (!Q_stricmpn(name, "allied_russian", 14)) { + return NA_RUSSIAN; + } else if (!Q_stricmpn(name, "allied_british", 14)) { + return NA_BRITISH; + } else if (!Q_stricmpn(name, "allied_sas", 10)) { + return NA_BRITISH; + } else if (!Q_stricmpn(name, "allied", 6)) { + return NA_AMERICAN; + } + + // fallback to american + return NA_AMERICAN; +} void Player::InitDeathmatch(void) { @@ -8311,66 +8749,70 @@ bool Player::QueryLandminesAllowed() const { const char *mapname; + if (g_target_game < target_game_e::TG_MOHTT) { + return false; + } + if (dmflags->integer & DF_WEAPON_NO_LANDMINE) { - return qfalse; + return false; } if (dmflags->integer & DF_WEAPON_LANDMINE_ALWAYS) { - return qtrue; + return true; } mapname = level.mapname.c_str(); if (!Q_stricmpn(mapname, "obj/obj_", 8u)) { - return qfalse; + return false; } if (!Q_stricmpn(mapname, "dm/mohdm", 8u)) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Bahnhof_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "obj/MP_Ardennes_TOW")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Bazaar_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "obj/MP_Berlin_TOW")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Brest_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "obj/MP_Druckkammern_TOW")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Gewitter_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "obj/MP_Flughafen_TOW")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Holland_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Malta_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Stadt_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Unterseite_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM")) { - return qfalse; + return false; } if (!Q_stricmp(mapname, "lib/mp_ship_lib")) { - return qfalse; + return false; } - return qtrue; + return true; } void Player::EnsurePlayerHasAllowedWeapons() @@ -8392,49 +8834,49 @@ void Player::EnsurePlayerHasAllowedWeapons() return; } - strcpy(client->pers.dm_primary, "rifle"); + Q_strncpyz(client->pers.dm_primary, "rifle", sizeof(client->pers.dm_primary)); } else if (!Q_stricmp(client->pers.dm_primary, "rifle")) { if (!(dmflags->integer & DF_WEAPON_NO_RIFLE)) { return; } - strcpy(client->pers.dm_primary, "smg"); + Q_strncpyz(client->pers.dm_primary, "smg", sizeof(client->pers.dm_primary)); } else if (!Q_stricmp(client->pers.dm_primary, "smg")) { - if (!(dmflags->integer & DF_WEAPON_NO_RIFLE)) { + if (!(dmflags->integer & DF_WEAPON_NO_SMG)) { return; } - strcpy(client->pers.dm_primary, "mg"); + Q_strncpyz(client->pers.dm_primary, "mg", sizeof(client->pers.dm_primary)); } else if (!Q_stricmp(client->pers.dm_primary, "mg")) { - if (!(dmflags->integer & DF_WEAPON_NO_RIFLE)) { + if (!(dmflags->integer & DF_WEAPON_NO_MG)) { return; } - strcpy(client->pers.dm_primary, "shotgun"); + Q_strncpyz(client->pers.dm_primary, "shotgun", sizeof(client->pers.dm_primary)); } else if (!Q_stricmp(client->pers.dm_primary, "shotgun")) { - if (!(dmflags->integer & DF_WEAPON_NO_RIFLE)) { + if (!(dmflags->integer & DF_WEAPON_NO_SHOTGUN)) { return; } - strcpy(client->pers.dm_primary, "heavy"); + Q_strncpyz(client->pers.dm_primary, "heavy", sizeof(client->pers.dm_primary)); } else if (!Q_stricmp(client->pers.dm_primary, "heavy")) { - if (!(dmflags->integer & DF_WEAPON_NO_RIFLE)) { + if (!(dmflags->integer & DF_WEAPON_NO_ROCKET)) { return; } - strcpy(client->pers.dm_primary, "landmine"); + Q_strncpyz(client->pers.dm_primary, "landmine", sizeof(client->pers.dm_primary)); } else if (!Q_stricmp(client->pers.dm_primary, "landmine")) { if (QueryLandminesAllowed()) { return; } - strcpy(client->pers.dm_primary, "sniper"); + Q_strncpyz(client->pers.dm_primary, "sniper", sizeof(client->pers.dm_primary)); } } gi.cvar_set("dmflags", va("%i", dmflags->integer & ~DF_WEAPON_NO_RIFLE)); Com_Printf("No valid weapons -- re-allowing the rifle\n"); - strcpy(client->pers.dm_primary, "rifle"); + Q_strncpyz(client->pers.dm_primary, "rifle", sizeof(client->pers.dm_primary)); } void Player::EquipWeapons() @@ -8448,10 +8890,12 @@ void Player::EquipWeapons() return; } + // Fixed in OPM + // Old behavior was calling GetPlayerTeamType() regardless of the team if (GetTeam() == TEAM_AXIS) { - nationality = GetPlayerTeamType(client->pers.dm_playergermanmodel); + nationality = GetPlayerAxisTeamType(client->pers.dm_playergermanmodel); } else { - nationality = GetPlayerTeamType(client->pers.dm_playermodel); + nationality = GetPlayerAlliedTeamType(client->pers.dm_playermodel); } event = new Event(EV_Sentient_UseItem); @@ -8466,11 +8910,17 @@ void Player::EquipWeapons() if (!Q_stricmp(client->pers.dm_primary, "sniper") && !(dmflags->integer & DF_WEAPON_NO_SNIPER)) { switch (nationality) { case NA_BRITISH: - giveItem("weapons/Uk_W_L42A1.tik"); - event->AddString("Enfield L42A1"); + if (g_target_game < target_game_e::TG_MOHTT) { + giveItem("weapons/springfield.tik"); + event->AddString("Springfield '03 Sniper"); + } else { + giveItem("weapons/Uk_W_L42A1.tik"); + event->AddString("Enfield L42A1"); + } break; case NA_RUSSIAN: - if (dmflags->integer & DF_OLD_SNIPER) { + if (g_target_game < target_game_e::TG_MOHTA || dmflags->integer & DF_OLD_SNIPER) { + // Old snipers are forced older versions of the game giveItem("weapons/springfield.tik"); event->AddString("Springfield '03 Sniper"); } else { @@ -8479,7 +8929,13 @@ void Player::EquipWeapons() } break; case NA_GERMAN: - if (dmflags->integer & DF_OLD_SNIPER) { + if (g_target_game < target_game_e::TG_MOHTA + || dmflags->integer & DF_OLD_SNIPER + // Added in OPM + // This was also a feature of Daven's fixes + // Use KAR98 for panzer skins + || !Q_stricmpn(client->pers.dm_playergermanmodel, "german_panzer", 13)) { + // Old snipers are forced older versions of the game giveItem("weapons/kar98sniper.tik"); event->AddString("KAR98 - Sniper"); } else { @@ -8491,9 +8947,10 @@ void Player::EquipWeapons() giveItem("weapons/kar98sniper.tik"); event->AddString("KAR98 - Sniper"); break; + case NA_AMERICAN: default: - giveItem("weapons/kar98sniper.tik"); - event->AddString("KAR98 - Sniper"); + giveItem("weapons/springfield.tik"); + event->AddString("Springfield '03 Sniper"); break; } } else if (!Q_stricmp(client->pers.dm_primary, "smg") && !(dmflags->integer & DF_WEAPON_NO_SMG)) { @@ -8514,6 +8971,7 @@ void Player::EquipWeapons() giveItem("weapons/it_w_moschetto.tik"); event->AddString("Moschetto"); break; + case NA_AMERICAN: default: giveItem("weapons/thompsonsmg.tik"); event->AddString("Thompson"); @@ -8522,8 +8980,14 @@ void Player::EquipWeapons() } else if (!Q_stricmp(client->pers.dm_primary, "mg") && !(dmflags->integer & DF_WEAPON_NO_MG)) { switch (nationality) { case NA_BRITISH: - giveItem("weapons/Uk_W_Vickers.tik"); - event->AddString("Vickers-Berthier"); + if (g_target_game < target_game_e::TG_MOHTT) { + giveItem("weapons/bar.tik"); + event->AddString("BAR"); + break; + } else { + giveItem("weapons/Uk_W_Vickers.tik"); + event->AddString("Vickers-Berthier"); + } break; case NA_GERMAN: giveItem("weapons/mp44.tik"); @@ -8531,8 +8995,9 @@ void Player::EquipWeapons() break; case NA_ITALIAN: giveItem("weapons/It_W_Breda.tik"); - event->AddString("MP40"); + event->AddString("Breda"); break; + case NA_AMERICAN: default: giveItem("weapons/bar.tik"); event->AddString("BAR"); @@ -8546,9 +9011,15 @@ void Player::EquipWeapons() event->AddString("Panzerschreck"); break; case NA_BRITISH: - giveItem("weapons/Uk_W_Piat.tik"); - event->AddString("PIAT"); + if (g_target_game < target_game_e::TG_MOHTT) { + giveItem("weapons/bazooka.tik"); + event->AddString("Bazooka"); + } else { + giveItem("weapons/Uk_W_Piat.tik"); + event->AddString("PIAT"); + } break; + case NA_AMERICAN: default: giveItem("weapons/bazooka.tik"); event->AddString("Bazooka"); @@ -8557,12 +9028,18 @@ void Player::EquipWeapons() } else if (!Q_stricmp(client->pers.dm_primary, "shotgun") && !(dmflags->integer & DF_WEAPON_NO_SHOTGUN)) { switch (nationality) { case NA_BRITISH: - giveItem("weapons/DeLisle.tik"); - event->AddString("DeLisle"); + if (g_target_game < target_game_e::TG_MOHTT) { + giveItem("weapons/shotgun.tik"); + event->AddString("Shotgun"); + } else { + giveItem("weapons/DeLisle.tik"); + event->AddString("DeLisle"); + } break; case NA_GERMAN: - if (dmflags->integer & DF_DISALLOW_KAR98_MORTAR) { + if (g_target_game < target_game_e::TG_MOHTA || dmflags->integer & DF_DISALLOW_KAR98_MORTAR) { // Fallback to shotgun + // The shotgun is forced on older versions of the game giveItem("weapons/shotgun.tik"); event->AddString("Shotgun"); } else { @@ -8570,6 +9047,7 @@ void Player::EquipWeapons() event->AddString("Gewehrgranate"); } break; + case NA_AMERICAN: default: giveItem("weapons/shotgun.tik"); event->AddString("Shotgun"); @@ -8615,6 +9093,7 @@ void Player::EquipWeapons() GiveAmmo("pistol", 16); } break; + case NA_AMERICAN: default: giveItem("weapons/US_W_Minedetector.tik"); event->AddString("Minedetector"); @@ -8646,6 +9125,7 @@ void Player::EquipWeapons() giveItem("weapons/it_w_carcano.tik"); event->AddString("Carcano"); break; + case NA_AMERICAN: default: giveItem("weapons/m1_garand.tik"); event->AddString("M1 Garand"); @@ -8662,27 +9142,37 @@ void Player::EquipWeapons() switch (nationality) { case NA_BRITISH: giveItem("weapons/mills_grenade.tik"); - giveItem("weapons/M18_smoke_grenade.tik"); + if (g_target_game >= target_game_e::TG_MOHTA) { + giveItem("weapons/M18_smoke_grenade.tik"); + } giveItem("weapons/Webley_Revolver.tik"); break; case NA_RUSSIAN: giveItem("weapons/Russian_F1_grenade.tik"); - giveItem("weapons/RDG-1_Smoke_grenade.tik"); + if (g_target_game >= target_game_e::TG_MOHTA) { + giveItem("weapons/RDG-1_Smoke_grenade.tik"); + } giveItem("weapons/Nagant_revolver.tik"); break; case NA_GERMAN: giveItem("weapons/steilhandgranate.tik"); - giveItem("weapons/nebelhandgranate.tik"); + if (g_target_game >= target_game_e::TG_MOHTA) { + giveItem("weapons/nebelhandgranate.tik"); + } giveItem("weapons/p38.tik"); break; case NA_ITALIAN: giveItem("weapons/it_w_bomba.tik"); - giveItem("weapons/it_w_bombabreda.tik"); + if (g_target_game >= target_game_e::TG_MOHTA) { + giveItem("weapons/it_w_bombabreda.tik"); + } giveItem("weapons/it_w_beretta.tik"); break; default: giveItem("weapons/m2frag_grenade.tik"); - giveItem("weapons/M18_smoke_grenade.tik"); + if (g_target_game >= target_game_e::TG_MOHTA) { + giveItem("weapons/M18_smoke_grenade.tik"); + } giveItem("weapons/colt45.tik"); break; } @@ -8793,12 +9283,23 @@ bool Player::IsValidSpectatePlayer(Player *pPlayer) return true; } - if (GetTeam() <= TEAM_FREEFORALL || !g_forceteamspectate->integer || !GetDM_Team()->NumLivePlayers() - || pPlayer->GetTeam() == GetTeam()) { + if (GetTeam() <= TEAM_FREEFORALL) { return true; - } else { + } + + if (g_forceteamspectate->integer) { + if (!GetDM_Team()->NumLivePlayers()) { + return true; + } + + if (pPlayer->GetTeam() == GetTeam()) { + return true; + } + return false; } + + return true; } void Player::SetPlayerSpectate(bool bNext) @@ -8821,12 +9322,7 @@ void Player::SetPlayerSpectate(bool bNext) } } - if (m_iPlayerSpectating >= game.maxclients) { - m_iPlayerSpectating = 0; - } - - i = num; - while (i < game.maxclients && i >= 0) { + for (i = num; i < game.maxclients && i >= 0; i += dir) { ent = &g_entities[i]; if (!ent->inuse || !ent->entity) { continue; @@ -8840,13 +9336,6 @@ void Player::SetPlayerSpectate(bool bNext) client->ps.camera_flags |= (client->ps.camera_flags & CF_CAMERA_CUT_BIT) ^ CF_CAMERA_CUT_BIT; return; } - - if (!m_iPlayerSpectating) { - return; - } - - m_iPlayerSpectating = 0; - i += dir; } if (m_iPlayerSpectating) { @@ -8878,6 +9367,10 @@ void Player::SetPlayerSpectateRandom(void) if (!numvalid) { // There is no valid player to spectate + + // Added in OPM. + // Clear the player spectating value + m_iPlayerSpectating = 0; return; } @@ -8925,7 +9418,7 @@ void Player::GetSpectateFollowOrientation(Player *pPlayer, Vector& vPos, Vector& vCamOfs += up * g_spectatefollow_up->value; if (pPlayer->client->ps.fLeanAngle != 0.0f) { - vCamOfs += client->ps.fLeanAngle * 0.65f * right; + vCamOfs += pPlayer->client->ps.fLeanAngle * 0.65f * right; } start = pPlayer->origin; @@ -8953,7 +9446,8 @@ void Player::Spectator(Event *ev) void Player::Leave_DM_Team(Event *ev) { - // FIXME: should it stays disabled ? + // Fixed in OPM + // FIXME: should it be permanently disabled ? #if 0 if (current_team) { @@ -8971,9 +9465,13 @@ void Player::Join_DM_Team(Event *ev) teamtype_t team; str teamname; const char *join_message; - float startTime; Entity *ent; + if (ev->isSubclassOf(ConsoleEvent) && disable_team_change) { + // Added in OPM + return; + } + teamname = ev->GetString(1); if (!teamname.icmp("allies")) { @@ -8996,19 +9494,7 @@ void Player::Join_DM_Team(Event *ev) return; } - startTime = dmManager.GetMatchStartTime(); - - if (startTime >= 0.0f && (level.time - startTime) > 30.0 - && (level.time - m_fTeamSelectTime) < g_teamswitchdelay->integer) { - int seconds = g_teamswitchdelay->integer - (level.time - m_fTeamSelectTime); - - gi.SendServerCommand( - edict - g_entities, - "print \"" HUD_MESSAGE_WHITE "%s %i %s\n\"", - gi.LV_ConvertString("Can not change teams again for another"), - seconds + 1, - gi.LV_ConvertString("seconds") - ); + if (ev->isSubclassOf(ConsoleEvent) && !CheckCanSwitchTeam(team)) { return; } @@ -9184,7 +9670,7 @@ void Player::ArmorDamage(Event *ev) { int mod = ev->GetInteger(9); - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { // players that are not allowed fighting mustn't take damage if (!m_bAllowFighting && mod != MOD_TELEFRAG) { return; @@ -9194,7 +9680,7 @@ void Player::ArmorDamage(Event *ev) if (attacker && attacker->IsSubclassOfPlayer()) { if (attacker != this) { - if (g_gametype->integer > 1 && !g_teamdamage->integer) { + if (g_gametype->integer >= GT_TEAM && !g_teamdamage->integer) { // check for team damage if (attacker->GetDM_Team() == GetDM_Team() && mod != MOD_TELEFRAG) { return; @@ -9225,107 +9711,303 @@ void Player::ArmorDamage(Event *ev) event->AddInteger(ev->GetInteger(10)); event->AddEntity(this); + scriptDelegate_damage.Trigger(this, *event); scriptedEvents[SE_DAMAGE].Trigger(event); } void Player::Disconnect(void) { Event *ev = new Event; - ev->AddListener(this); + + scriptDelegate_disconnecting.Trigger(this, *ev); scriptedEvents[SE_DISCONNECTED].Trigger(ev); - if (g_gametype->integer) { - dmManager.RemovePlayer(this); - } + // if (g_gametype->integer != GT_SINGLE_PLAYER) { + // dmManager.RemovePlayer(this); + // } } void Player::CallVote(Event *ev) { str arg1; str arg2; + int numVoters; - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } if (!g_allowvote->integer) { - HUDPrint(gi.LV_ConvertString("Voting not allowed here.")); + HUDPrint(va("%s\n", gi.LV_ConvertString("Voting not allowed here."))); return; } if (level.m_voteTime != 0.0f) { - HUDPrint(gi.LV_ConvertString("A vote is already in progress.")); + HUDPrint(va("%s\n", gi.LV_ConvertString("A vote is already in progress."))); return; } if (votecount >= MAX_VOTE_COUNT) { - HUDPrint(va("%s (%d).\n", gi.LV_ConvertString("You have called the maximum number of votes"), MAX_VOTE_COUNT)); + if (m_fLastVoteTime) { + while (m_fLastVoteTime < level.time && votecount > 0) { + m_fLastVoteTime += 60; + votecount--; + } + } + + if (votecount >= MAX_VOTE_COUNT) { + HUDPrint( + va("%s %d %s.\n", + gi.LV_ConvertString("You cannot call another vote for"), + (unsigned int)(m_fLastVoteTime - level.time + 1), + gi.LV_ConvertString("seconds")) + ); + return; + } + } + + if (IsSpectator() || IsDead()) { + HUDPrint(va("%s\n", gi.LV_ConvertString("You are not allowed to call a vote as a spectator."))); return; } arg1 = ev->GetString(1); - arg2 = ev->GetString(2); - - if (strchr(arg1.c_str(), ';') || strchr(arg2.c_str(), ';')) { - HUDPrint(gi.LV_ConvertString("Invalid vote string.")); - return; + if (ev->NumArgs() > 1) { + arg2 = ev->GetString(2); } - if (Q_stricmp(arg1.c_str(), "restart") && Q_stricmp(arg1.c_str(), "nextmap") && Q_stricmp(arg1.c_str(), "map") - && Q_stricmp(arg1.c_str(), "g_gametype") && Q_stricmp(arg1.c_str(), "kick") - && Q_stricmp(arg1.c_str(), "clientkick") && Q_stricmp(arg1.c_str(), "fraglimit")) { - HUDPrint(gi.LV_ConvertString("Invalid vote string.")); - HUDPrint( - va("%s restart, nextmap, map , g_gametype , fraglimit , timelimit , kick , and " - "clientkick .", - gi.LV_ConvertString("Vote commands are:")) - ); + if (!atoi(arg1.c_str())) { + if (strchr(arg1.c_str(), ';') || strchr(arg2.c_str(), ';')) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid vote string."))); + return; + } - return; - } + if (Q_stricmp(arg1.c_str(), "restart") && Q_stricmp(arg1.c_str(), "nextmap") && Q_stricmp(arg1.c_str(), "map") + && Q_stricmp(arg1.c_str(), "g_gametype") && Q_stricmp(arg1.c_str(), "kick") + && Q_stricmp(arg1.c_str(), "clientkick") && Q_stricmp(arg1.c_str(), "fraglimit")) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid vote string."))); + HUDPrint(va( + "%s restart, nextmap, map , g_gametype , fraglimit , timelimit , kick , and " + "clientkick .\n", + gi.LV_ConvertString("Vote commands are:") + )); - if (!Q_stricmp(arg1.c_str(), "kick")) { - gentity_t *ent; - int i; + return; + } - for (i = 0; i < game.maxclients; i++) { - ent = &g_entities[i]; + if (!Q_stricmp(arg1.c_str(), "kick")) { + // + // check for a valid player + // + gentity_t *ent; + int i; - if (!ent->inuse || !ent->client || !ent->entity) { - continue; - } + for (i = 0; i < game.maxclients; i++) { + ent = &g_entities[i]; - if (!Q_stricmp(ent->client->pers.netname, arg2.c_str())) { - // Prevent the player from kicking himself out - if (ent->entity == this) { - HUDPrint(gi.LV_ConvertString("You are not allowed to kick yourself.")); - return; + if (!ent->inuse || !ent->client || !ent->entity) { + continue; } - break; + if (!Q_stricmp(ent->client->pers.netname, arg2.c_str())) { + // Prevent the player from kicking himself out + if (ent->entity == this) { + HUDPrint(va("%s\n", gi.LV_ConvertString("You are not allowed to kick yourself."))); + return; + } + + break; + } } + + if (i == game.maxclients) { + HUDPrint(va("%s %s\n", arg2.c_str(), gi.LV_ConvertString("is not a valid player name to kick."))); + return; + } + } else if (!Q_stricmp(arg1.c_str(), "map") && *sv_nextmap->string) { + level.m_voteString = va("%s %s; set next map \"%s\"", arg1.c_str(), arg2.c_str(), arg2.c_str()); + } else { + level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); } - if (i == game.maxclients) { - HUDPrint(va("%s %s", ent->client->pers.netname, gi.LV_ConvertString("is not a valid player name to kick.")) - ); + if (level.m_nextVoteTime) { + level.m_nextVoteTime = 0; + gi.SendConsoleCommand(va("%s", level.m_voteString.c_str())); + } + + if (!Q_stricmp(arg1.c_str(), "g_gametype")) { + int gametypeNum; + + // get the gametype number + gametypeNum = atoi(arg2.c_str()); + if (gametypeNum <= GT_SINGLE_PLAYER || gametypeNum >= GT_MAX_GAME_TYPE) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid gametype for a vote."))); + return; + } + + level.m_voteString = va("%s %i", arg1.c_str(), gametypeNum); + + switch (gametypeNum) { + case GT_FFA: + level.m_voteName = "Game Type Free-For-All"; + break; + case GT_TEAM: + level.m_voteName = "Game Type Match"; + break; + case GT_TEAM_ROUNDS: + level.m_voteName = "Game Type Round-Based-Match"; + break; + case GT_OBJECTIVE: + level.m_voteName = "Game Type Objective-Match"; + break; + case GT_TOW: + level.m_voteName = "Game Type Tug of War"; + break; + case GT_LIBERATION: + level.m_voteName = "Game Type Liberation"; + break; + default: + HUDPrint(va("%s %s %d\n", gi.LV_ConvertString("Game Type"), arg1.c_str(), gametypeNum)); + return; + } + } else if (!Q_stricmp(arg1.c_str(), "map")) { + if (*sv_nextmap->string) { + level.m_voteString = va("%s %s; set nextmap \"%s\"", arg1.c_str(), arg2.c_str(), sv_nextmap->string); + } else { + level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); + } + + level.m_voteName = va("Map %s", arg2.c_str()); + } else { + level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); + level.m_voteName = level.m_voteString; } - } else if (!Q_stricmp(arg1.c_str(), "map") && *sv_nextmap->string) { - level.m_voteString = va("%s %s; set next map \"%s\"", arg1.c_str(), arg2.c_str(), arg2.c_str()); } else { - level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); + int voteIndex; + int subListIndex; + str voteOptionCommand; + str voteOptionSubCommand; + str voteOptionName; + str voteOptionSubName; + voteoptiontype_t optionType; + + union { + int optionInteger; + float optionFloat; + int optionClientNum; + }; + + gentity_t *ent; + + char buffer[64]; + + voteIndex = atoi(arg1.c_str()); + if (!level.GetVoteOptionMain(voteIndex, &voteOptionCommand, &optionType)) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid vote option."))); + return; + } + + level.GetVoteOptionMainName(voteIndex, &voteOptionName); + + switch (optionType) { + case VOTE_NO_CHOICES: + level.m_voteString = voteOptionCommand; + level.m_voteName = voteOptionName; + break; + case VOTE_OPTION_LIST: + subListIndex = atoi(arg2.c_str()); + + if (!level.GetVoteOptionSub(voteIndex, subListIndex, &voteOptionSubCommand)) { + HUDPrint( + va("%s %i %s \"%s\".\n", + gi.LV_ConvertString("Invalid vote choice"), + subListIndex, + gi.LV_ConvertString("for vote option"), + voteOptionName.c_str()) + ); + return; + } + + level.m_voteString = va("%s %s", voteOptionCommand.c_str(), voteOptionSubCommand.c_str()); + // get the sub-option name + level.GetVoteOptionSubName(voteIndex, subListIndex, &voteOptionSubName); + level.m_voteName = + va("%s %s", gi.LV_ConvertString(voteOptionName.c_str()), gi.LV_ConvertString(voteOptionSubName.c_str()) + ); + break; + case VOTE_OPTION_TEXT: + if (strchr(arg2.c_str(), ';')) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid vote text entered."))); + return; + } + + level.m_voteString = va("%s %s", voteOptionCommand.c_str(), arg2.c_str()); + level.m_voteName = va("%s %s", gi.LV_ConvertString(voteOptionName.c_str()), arg2.c_str()); + break; + case VOTE_OPTION_INTEGER: + optionInteger = atoi(arg2.c_str()); + Com_sprintf(buffer, sizeof(buffer), "%d", optionInteger); + + if (Q_stricmp(buffer, arg2.c_str())) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid vote integer entered."))); + return; + } + + level.m_voteString = va("%s %i", voteOptionCommand.c_str(), optionInteger); + level.m_voteName = va("%s %i", gi.LV_ConvertString(voteOptionName.c_str()), optionInteger); + break; + case VOTE_OPTION_FLOAT: + optionFloat = atof(arg2.c_str()); + Com_sprintf(buffer, sizeof(buffer), "%f", optionFloat); + + if (Q_stricmp(buffer, arg2.c_str())) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid vote float entered."))); + return; + } + + level.m_voteString = va("%s %g", voteOptionCommand.c_str(), optionFloat); + level.m_voteName = va("%s %g", gi.LV_ConvertString(voteOptionName.c_str()), optionFloat); + break; + case VOTE_OPTION_CLIENT: + case VOTE_OPTION_CLIENT_NOT_SELF: + optionClientNum = atoi(arg2.c_str()); + if (optionClientNum < 0 || optionClientNum >= game.maxclients) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Invalid client number for a vote."))); + return; + } + + ent = &g_entities[optionClientNum]; + if (!ent->inuse || !ent->client || !ent->entity) { + HUDPrint(va("%s\n", gi.LV_ConvertString("Client selected for the vote is not connected."))); + return; + } + + level.m_voteString = va("%s %i", voteOptionCommand.c_str(), optionClientNum); + level.m_voteName = + va("%s #%i: %s", gi.LV_ConvertString(voteOptionName.c_str()), optionClientNum, ent->client->pers.netname + ); + break; + default: + level.GetVoteOptionMainName(voteIndex, &voteOptionName); + gi.Printf( + "ERROR: Vote option (\"%s\" \"%s\") with unknown vote option type\n", + voteOptionName.c_str(), + voteOptionCommand.c_str() + ); + return; + } } - dmManager.PrintAllClients( - va("%s %s: %s\n", client->pers.netname, gi.LV_ConvertString("called a vote"), level.m_voteString.c_str()) - ); + G_PrintToAllClients(va("%s %s.\n", client->pers.netname, gi.LV_ConvertString("called a vote"))); + level.m_voteTime = (level.svsFloatTime - level.svsStartFloatTime) * 1000; level.m_voteYes = 1; level.m_voteNo = 0; - level.m_voteTime = level.time; // Reset all player's vote + numVoters = 0; + for (int i = 0; i < game.maxclients; i++) { gentity_t *ent = &g_entities[i]; @@ -9334,24 +10016,40 @@ void Player::CallVote(Event *ev) } Player *p = (Player *)ent->entity; + p->voted = false; - p->voted = false; + numVoters++; } - voted = true; + level.m_numVoters = numVoters; + client->ps.voted = true; + voted = true; votecount++; - level.m_numVoters = 0; + m_fLastVoteTime = level.time + 60; + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + // + // clients below version 2.0 don't support vote cs + // + gi.setConfigstring(CS_VOTE_TIME, va("%i", level.m_voteTime)); + gi.setConfigstring(CS_VOTE_STRING, level.m_voteName.c_str()); + gi.setConfigstring(CS_VOTE_YES, va("%i", level.m_voteYes)); + gi.setConfigstring(CS_VOTE_NO, va("%i", level.m_voteNo)); + gi.setConfigstring(CS_VOTE_UNDECIDED, va("%i", level.m_numVoters - (level.m_voteYes + level.m_voteNo))); + } } void Player::Vote(Event *ev) { + str arg1; + if (level.m_voteTime == 0.0f) { HUDPrint(gi.LV_ConvertString("No vote in progress.")); return; } - if (voted) { + if (client->ps.voted) { HUDPrint(gi.LV_ConvertString("Vote already cast.")); return; } @@ -9362,15 +10060,10 @@ void Player::Vote(Event *ev) } HUDPrint(gi.LV_ConvertString("Vote cast.")); - voted = true; + client->ps.voted = true; - str arg1 = ev->GetString(1); - - if (*arg1 == 'y' || *arg1 == 'Y' || *arg1 == '1') { - level.m_voteYes++; - } else { - level.m_voteNo++; - } + arg1 = ev->GetString(1); + voted = (arg1[0] == 'y') || (arg1[0] == 'Y') || (arg1[0] == '1'); } void Player::RetrieveVoteOptions(Event *ev) @@ -9387,7 +10080,13 @@ void Player::RetrieveVoteOptions(Event *ev) void Player::EventPrimaryDMWeapon(Event *ev) { str dm_weapon = ev->GetString(1); - bool bIsBanned; + bool bIsBanned = false; + + if (!dm_weapon.length()) { + // Added in OPM. + // Prevent the player from cheating by going into spectator + return; + } if (!str::icmp(dm_weapon, "shotgun")) { bIsBanned = (dmflags->integer & DF_WEAPON_NO_SHOTGUN); @@ -9403,6 +10102,41 @@ void Player::EventPrimaryDMWeapon(Event *ev) bIsBanned = (dmflags->integer & DF_WEAPON_NO_ROCKET); } else if (!str::icmp(dm_weapon, "landmine")) { bIsBanned = (dmflags->integer & DF_WEAPON_NO_LANDMINE) || !QueryLandminesAllowed(); + } else if (!str::icmp(dm_weapon, "auto")) { + const char *primaryList[7]; + size_t numPrimaries = 0; + + // + // Added in OPM + // Choose a random allowed weapon + // + if (!(dmflags->integer & DF_WEAPON_NO_SHOTGUN)) { + primaryList[numPrimaries++] = "shotgun"; + } + if (!(dmflags->integer & DF_WEAPON_NO_RIFLE)) { + primaryList[numPrimaries++] = "rifle"; + } + if (!(dmflags->integer & DF_WEAPON_NO_SNIPER)) { + primaryList[numPrimaries++] = "sniper"; + } + if (!(dmflags->integer & DF_WEAPON_NO_SMG)) { + primaryList[numPrimaries++] = "smg"; + } + if (!(dmflags->integer & DF_WEAPON_NO_MG)) { + primaryList[numPrimaries++] = "mg"; + } + if (!(dmflags->integer & DF_WEAPON_NO_ROCKET)) { + primaryList[numPrimaries++] = "heavy"; + } + if (!(dmflags->integer & DF_WEAPON_NO_LANDMINE) && QueryLandminesAllowed()) { + primaryList[numPrimaries++] = "landmine"; + } + + if (numPrimaries) { + dm_weapon = primaryList[rand() % numPrimaries]; + } else { + bIsBanned = qtrue; + } } if (bIsBanned) { @@ -9493,6 +10227,12 @@ void Player::EventGetCurrentDMWeaponType(Event *ev) void Player::PhysicsOff(Event *ev) { + if (g_target_game > TG_MOH || g_gametype->integer != GT_SINGLE_PLAYER) { + // Added in 2.0 + // Reset the state to STAND before disabling physics + EvaluateState(statemap_Torso->FindState("STAND"), statemap_Legs->FindState("STAND")); + } + flags |= FL_IMMOBILE; } @@ -9526,9 +10266,9 @@ void Player::GetNationalityPrefix(Event *ev) nationality_t nationality; if (GetTeam() == TEAM_AXIS) { - nationality = GetPlayerTeamType(client->pers.dm_playergermanmodel); + nationality = GetPlayerAxisTeamType(client->pers.dm_playergermanmodel); } else { - nationality = GetPlayerTeamType(client->pers.dm_playermodel); + nationality = GetPlayerAlliedTeamType(client->pers.dm_playermodel); } switch (nationality) { @@ -9630,7 +10370,9 @@ void Player::Stats(Event *ev) } } - szPreferredWeapon = m_sPerferredWeaponOverride; + if (m_sPerferredWeaponOverride.length()) { + szPreferredWeapon = m_sPerferredWeaponOverride; + } if (iNumHits) { Com_sprintf( @@ -9642,7 +10384,7 @@ void Player::Stats(Event *ev) m_iObjectivesCompleted, iNumShotsFired, iNumHits, - (iNumHits / iNumShotsFired * 100.f), + ((float)iNumHits / (float)iNumShotsFired * 100.f), szPreferredWeapon.c_str(), m_iNumHitsTaken, m_iNumObjectsDestroyed, @@ -9696,39 +10438,58 @@ void Player::EventStuffText(Event *ev) Event *event = new Event(EV_Player_StuffText); event->AddValue(ev->GetValue(1)); PostEvent(event, level.frametime, 0); - } else { - gi.SendServerCommand(edict - g_entities, "stufftext \"%s\"", ev->GetString(1).c_str()); + return; } + + gi.SendServerCommand(edict - g_entities, "stufftext \"%s\"", ev->GetString(1).c_str()); + + delegate_stufftext.Execute(ev->GetString(1)); } void Player::EventSetVoiceType(Event *ev) { str sVoiceName = ev->GetString(1); - if (!sVoiceName.icmp("airborne")) { - m_voiceType = PVT_ALLIED_AIRBORNE; - } else if (!sVoiceName.icmp("manon")) { - m_voiceType = PVT_ALLIED_MANON; - } else if (!sVoiceName.icmp("SAS")) { - m_voiceType = PVT_ALLIED_SAS; - } else if (!sVoiceName.icmp("pilot")) { - m_voiceType = PVT_ALLIED_PILOT; - } else if (!sVoiceName.icmp("army")) { - m_voiceType = PVT_ALLIED_ARMY; - } else if (!sVoiceName.icmp("ranger")) { - m_voiceType = PVT_ALLIED_RANGER; - } else if (!sVoiceName.icmp("axis1")) { - m_voiceType = PVT_AXIS_AXIS1; - } else if (!sVoiceName.icmp("axis2")) { - m_voiceType = PVT_AXIS_AXIS2; - } else if (!sVoiceName.icmp("axis3")) { - m_voiceType = PVT_AXIS_AXIS3; - } else if (!sVoiceName.icmp("axis4")) { - m_voiceType = PVT_AXIS_AXIS4; - } else if (!sVoiceName.icmp("axis5")) { - m_voiceType = PVT_AXIS_AXIS5; + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + if (!sVoiceName.icmp("american")) { + m_voiceType = PVT_ALLIED_AMERICAN; + } else if (!sVoiceName.icmp("british")) { + m_voiceType = PVT_ALLIED_BRITISH; + } else if (!sVoiceName.icmp("russian")) { + m_voiceType = PVT_ALLIED_RUSSIAN; + } else if (!sVoiceName.icmp("german")) { + m_voiceType = PVT_AXIS_GERMAN; + } else if (!sVoiceName.icmp("italian")) { + m_voiceType = PVT_AXIS_ITALIAN; + } else { + m_voiceType = PVT_NONE_SET; + } } else { - m_voiceType = PVT_NONE_SET; + if (!sVoiceName.icmp("airborne")) { + m_voiceType = PVT_ALLIED_AIRBORNE; + } else if (!sVoiceName.icmp("manon")) { + m_voiceType = PVT_ALLIED_MANON; + } else if (!sVoiceName.icmp("SAS")) { + m_voiceType = PVT_ALLIED_SAS; + } else if (!sVoiceName.icmp("pilot")) { + m_voiceType = PVT_ALLIED_PILOT; + } else if (!sVoiceName.icmp("army")) { + m_voiceType = PVT_ALLIED_ARMY; + } else if (!sVoiceName.icmp("ranger")) { + m_voiceType = PVT_ALLIED_RANGER; + } else if (!sVoiceName.icmp("axis1")) { + m_voiceType = PVT_AXIS_AXIS1; + } else if (!sVoiceName.icmp("axis2")) { + m_voiceType = PVT_AXIS_AXIS2; + } else if (!sVoiceName.icmp("axis3")) { + m_voiceType = PVT_AXIS_AXIS3; + } else if (!sVoiceName.icmp("axis4")) { + m_voiceType = PVT_AXIS_AXIS4; + } else if (!sVoiceName.icmp("axis5")) { + m_voiceType = PVT_AXIS_AXIS5; + } else { + m_voiceType = PVT_NONE_SET; + } } } @@ -9740,29 +10501,84 @@ void Player::GetTeamDialogPrefix(str& outPrefix) outPrefix = "allied_"; } - switch (m_voiceType) { - case PVT_ALLIED_AMERICAN: - outPrefix += "american_"; - break; - case PVT_ALLIED_BRITISH: - outPrefix += "british_"; - break; - case PVT_ALLIED_RUSSIAN: - outPrefix += "russian_"; - break; - case PVT_AXIS_START: - outPrefix += "german_"; - break; - case PVT_AXIS_ITALIAN: - outPrefix += "italian_"; - break; - default: - if (GetTeam() == TEAM_AXIS) { - outPrefix += "german_"; - } else { + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + switch (m_voiceType) { + case PVT_ALLIED_AMERICAN: outPrefix += "american_"; + break; + case PVT_ALLIED_BRITISH: + outPrefix += "british_"; + break; + case PVT_ALLIED_RUSSIAN: + outPrefix += "russian_"; + break; + case PVT_AXIS_START: + outPrefix += "german_"; + break; + case PVT_AXIS_ITALIAN: + outPrefix += "italian_"; + break; + default: + if (GetTeam() == TEAM_AXIS) { + outPrefix += "german_"; + } else { + outPrefix += "american_"; + } + break; + } + } else { + switch (m_voiceType) { + case PVT_ALLIED_AIRBORNE: + outPrefix += "airborne_"; + break; + + case PVT_ALLIED_MANON: + outPrefix += "manon_"; + break; + + case PVT_ALLIED_SAS: + outPrefix += "sas_"; + break; + + case PVT_ALLIED_PILOT: + outPrefix += "pilot_"; + break; + + case PVT_ALLIED_ARMY: + outPrefix += "army_"; + break; + + case PVT_ALLIED_RANGER: + outPrefix += "ranger_"; + break; + + case PVT_AXIS_AXIS1: + outPrefix += "axis1_"; + break; + + case PVT_AXIS_AXIS2: + outPrefix += "axis2_"; + break; + + case PVT_AXIS_AXIS3: + outPrefix += "axis3_"; + break; + + case PVT_AXIS_AXIS4: + outPrefix += "axis4_"; + break; + + case PVT_AXIS_AXIS5: + outPrefix += "axis5_"; + break; + + default: + if (dm_team != TEAM_AXIS) { + outPrefix += "army_"; + } else { + outPrefix += "axis4_"; + } } - break; } } @@ -9792,193 +10608,296 @@ void Player::PlayInstantMessageSound(const char *name) void Player::EventDMMessage(Event *ev) { - int mode; - str stuffstrings; - str convertedstuff; - str string; - str voiceName; - str soundName; - AliasListNode_t *list = NULL; - const char *prefix = NULL; - qboolean bInstaMessage = qfalse; - qboolean met_comment = false; + int i; + //int iStringLength; + int iMode = 0; + str sToken; + char szPrintString[MAX_SAY_TEXT]; // it's MAX_STRING_CHARS in mohaa + size_t iStringLength; + const char *pTmpInstantMsg = ""; + qboolean bInstaMessage = qfalse; + AliasListNode_t *pSoundAlias = NULL; + const char *pszAliasname = NULL; + str sAliasName; + str sRandomAlias; + gentity_t *ent; - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } - mode = ev->GetInteger(1); - if (ev->NumArgs() <= 1) { return; } - string = ev->GetString(2); + if (!Q_stricmp(client->pers.netname, "console")) { + // Added in OPM + // Reserved name + gi.Printf( + "Client %d trying to send a message using a reserved name ('%s')\n", + edict - g_entities, + client->pers.netname + ); + return; + } + + sToken = ev->GetString(2); // Check for taunts - if (string.length() == 3 && *string == '*') { - char num1 = string[1]; - char num2 = string[2]; + if (sToken.length() == 3 && *sToken == '*' && sToken[1] > '0' && sToken[1] <= '9' && sToken[2] > '0' + && sToken[2] <= '9') { + unsigned int n1, n2; - if (num1 > '0' && num1 <= '9' && num2 > '0' && num2 <= '9') { - if (IsSpectator() || IsDead()) { - return; - } - - if (dm_team == TEAM_AXIS) { - voiceName = "axis_"; - } else { - voiceName = "allied_"; - } - } - - switch (m_voiceType) { - case PVT_ALLIED_AIRBORNE: - voiceName += "airborne_"; - break; - - case PVT_ALLIED_MANON: - voiceName += "manon_"; - break; - - case PVT_ALLIED_SAS: - voiceName += "sas_"; - break; - - case PVT_ALLIED_PILOT: - voiceName += "pilot_"; - break; - - case PVT_ALLIED_ARMY: - voiceName += "army_"; - break; - - case PVT_ALLIED_RANGER: - voiceName += "ranger_"; - break; - - case PVT_AXIS_AXIS1: - voiceName += "axis1_"; - break; - - case PVT_AXIS_AXIS2: - voiceName += "axis2_"; - break; - - case PVT_AXIS_AXIS3: - voiceName += "axis3_"; - break; - - case PVT_AXIS_AXIS4: - voiceName += "axis4_"; - break; - - case PVT_AXIS_AXIS5: - voiceName += "axis5_"; - break; - - default: - if (dm_team != TEAM_AXIS) { - voiceName += "army_"; - } else { - voiceName += "axis4_"; - } - } - - voiceName += va("%c%c", num1 + '0', num2 + '0'); - - FindAlias(soundName, voiceName, &list); - - if (list) { - bInstaMessage = qtrue; - } - } - - if (!bInstaMessage) { - for (int i = 2; i <= ev->NumArgs(); i++) { - string = ev->GetString(i); - - if (strstr(string, "/*")) { - met_comment = true; - } - - if (strstr(string, "*/") && met_comment) { - G_WarnPlayer(this, "Line comments ('/*' and '*/') are not allowed in messages.\n"); - return; - } - - stuffstrings += " " + string; - convertedstuff += gi.LV_ConvertString(string); - } - } else { - stuffstrings = " " + str(list->subtitle); - } - - stuffstrings += "\n"; - - // Protect again buffer overflow exploit - if (stuffstrings.length() >= MAX_STRING_CHARS) { - HUDPrint("The message you entered is too long.\n"); - return; - } - - if (convertedstuff.length() >= MAX_STRING_CHARS) { - HUDPrint("The message you entered is too long.\n"); - return; - } - - // Prevent the comment glitch - // ley: The problem seems to be an issue with COM_Parse, which skips all C comments - if (strstr(client->pers.netname, "/*")) { - met_comment = true; - } - - if (strstr(client->pers.netname, "//") || strstr(client->pers.netname, "*/")) { - HUDPrint("C comments ('//', '/*' and '*/') are not allowed in names.\n"); - return; - } - - if (IsSpectator()) { - if (mode > 0 && mode <= game.maxclients) { - const char *error = - "Message Error: Spectators are not allowed to send private messages to non-spectators.\n"; - - gi.SendServerCommand(client->ps.clientNum, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", error); + if (IsSpectator() || IsDead()) { + // spectators or death players can't talk return; } - prefix = gi.LV_ConvertString("(spectator) "); - string = prefix + str(client->pers.netname) + ":" + str(stuffstrings); - } else if (IsDead()) { - if (mode > 0 && mode <= game.maxclients) { - const char *error = - "Message Error: Dead players are not allowed to send private messages to active players.\n"; - - gi.SendServerCommand(client->ps.clientNum, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", error); + if (edict->r.svFlags & SVF_NOCLIENT) { + // Changed in OPM + // Don't send a voice chat message if the entity is not sent to client return; } - prefix = gi.LV_ConvertString("(dead) "); - string = prefix + str(client->pers.netname) + ":" + str(stuffstrings); - } else { - if (mode == -1) { - string = "(team) " + str(client->pers.netname) + ":" + str(stuffstrings); + if (!g_instamsg_allowed->integer) { + // Added in OPM + return; + } + + if (g_instamsg_minDelay->integer > 0 && level.inttime < m_iInstantMessageTime + g_instamsg_minDelay->integer) { + // Added in OPM + return; + } + + GetTeamDialogPrefix(sAliasName); + if (g_target_game >= target_game_e::TG_MOHTT && sToken[1] == '6') { + // Added in 2.30 + // Liberation messages + sAliasName += va("lib%c", (sToken[2] + '0')); } else { - string = str(client->pers.netname) + ":" + str(stuffstrings); + sAliasName += va("%c%c", (sToken[1] + '0'), (sToken[2] + '0')); + } + + sRandomAlias = GetRandomAlias(sAliasName, &pSoundAlias); + + // find a random alias + if (sRandomAlias.length() > 0) { + pszAliasname = sRandomAlias.c_str(); + } + + if (!pszAliasname) { + pszAliasname = gi.GlobalAlias_FindRandom(sAliasName, &pSoundAlias); + } + + if (!pszAliasname || !pSoundAlias) { + return; + } + + n1 = sToken[1] - '1'; + n2 = sToken[2] - '1'; + + if (g_protocol >= PROTOCOL_MOHTA_MIN) { + if (n1 >= ARRAY_LEN(pInstantMsgEng) || n2 >= ARRAY_LEN(pInstantMsgEng[0])) { + return; + } + + pTmpInstantMsg = pInstantMsgEng[n1][n2]; + } else { + if (n1 >= ARRAY_LEN(pInstantMsgEng_ver6) || n2 >= ARRAY_LEN(pInstantMsgEng_ver6[0])) { + return; + } + + // fallback to old version + pTmpInstantMsg = pInstantMsgEng_ver6[n1][n2]; + } + + bInstaMessage = qtrue; + + if (g_gametype->integer == GT_FFA) { + iMode = 0; + } else { + if (n1 == 4) { + iMode = 0; + } else { + iMode = -1; + } + } + } else { + if (!g_textmsg_allowed->integer) { + // Added in OPM + + str errorString = gi.LV_ConvertString("Message Error"); + str reasonString = gi.LV_ConvertString("Text chat is disabled on this server"); + + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_CHAT_WHITE "%s: %s.\n\"", + errorString.c_str(), + reasonString.c_str() + ); + return; + } + + if (g_textmsg_minDelay->integer > 0 && level.inttime < m_iTextChatTime + g_textmsg_minDelay->integer) { + // Added in OPM + return; } } - if (voiceName.length()) { - if (!IsDead() && (!IsSpectator() || g_spectate_allow_full_chat->integer)) { - gentity_t *ent; - int i; + if (bInstaMessage) { + if (g_voiceChatTime->value > 0) { + m_fTalkTime = g_voiceChatTime->value + level.time; + } + m_iInstantMessageTime = level.inttime; + } else { + iMode = ev->GetInteger(1); + if (g_textChatTime->value > 0) { + m_fTalkTime = g_textChatTime->value + level.time; + } + m_iTextChatTime = level.inttime; + } + + Q_strncpyz(szPrintString, "print \"" HUD_MESSAGE_CHAT_WHITE, sizeof(szPrintString)); + + if (m_bSpectator) { + if (iMode <= 0) { + Q_strcat(szPrintString, sizeof(szPrintString), gi.CL_LV_ConvertString("(spectator)")); + Q_strcat(szPrintString, sizeof(szPrintString), " "); + } else if (iMode <= game.maxclients) { + ent = &g_entities[iMode - 1]; + + if (ent->inuse && ent->entity && !static_cast(ent->entity)->IsSpectator()) { + str errorString = gi.LV_ConvertString("Message Error"); + str reasonString = + gi.LV_ConvertString("Spectators are not allowed to send private messages to non-spectators"); + + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_CHAT_WHITE "%s: %s.\n\"", + errorString.c_str(), + reasonString.c_str() + ); + return; + } + } + } else if (IsDead() || m_bTempSpectator) { + if (iMode <= 0) { + Q_strcat(szPrintString, sizeof(szPrintString), gi.CL_LV_ConvertString("(dead)")); + Q_strcat(szPrintString, sizeof(szPrintString), " "); + } else if (iMode <= game.maxclients) { + ent = &g_entities[iMode - 1]; + + if (ent->inuse && ent->entity && !static_cast(ent->entity)->IsSpectator()) { + str errorString = gi.LV_ConvertString("Message Error"); + str reasonString = + gi.LV_ConvertString("Dead players are not allowed to send private messages to active players"); + + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_CHAT_WHITE "%s: %s.\n\"", + errorString.c_str(), + reasonString.c_str() + ); + return; + } + } + } else if (iMode < 0) { + Q_strcat(szPrintString, sizeof(szPrintString), gi.CL_LV_ConvertString("(team)")); + Q_strcat(szPrintString, sizeof(szPrintString), " "); + } else if (iMode > 0) { + Q_strcat(szPrintString, sizeof(szPrintString), gi.CL_LV_ConvertString("(private)")); + Q_strcat(szPrintString, sizeof(szPrintString), " "); + } + + Q_strcat(szPrintString, sizeof(szPrintString), client->pers.netname); + + if (bInstaMessage) { + Q_strcat(szPrintString, sizeof(szPrintString), ": "); + Q_strcat(szPrintString, sizeof(szPrintString), gi.LV_ConvertString(pTmpInstantMsg)); + } else { + bool met_comment = false; + + Q_strcat(szPrintString, sizeof(szPrintString), ":"); + iStringLength = strlen(szPrintString); + + // Added in OPM. + // Checks for comments in string (as COM_Parse will parse them) + // This was fixed in 2.0 but make the fix compatible with older versions + if (g_protocol < protocol_e::PROTOCOL_MOHTA_MIN && strstr(client->pers.netname, "/*")) { + met_comment = true; + } + + for (i = 2; i <= ev->NumArgs(); i++) { + sToken = ev->GetString(i); + // Added in 2.40 + // Special battle language tokens + // So players can easily tell their position, health, etc. + sToken = TranslateBattleLanguageTokens(sToken); + + if (iStringLength + sToken.length() > (ARRAY_LEN(szPrintString) - 1)) { + break; + } + + if (met_comment && strstr(sToken, "*/")) { + // ignore messages containing comments + return; + } + + Q_strcat(szPrintString, sizeof(szPrintString), " "); + Q_strcat(szPrintString, sizeof(szPrintString), gi.LV_ConvertString(sToken)); + } + } + + Q_strcat(szPrintString, sizeof(szPrintString), "\n"); + + // ignore names containing comments + if (g_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + if (strstr(client->pers.netname, "//") + || (strstr(client->pers.netname, "/*") && strstr(client->pers.netname, "*/"))) { + return; + } + } + + // + // Added in OPM + //============= + // Print the dm message to console + sToken = ""; + + for (i = 2; i <= ev->NumArgs(); i++) { + if (i != 2) { + sToken += " "; + } + + sToken += ev->GetString(i); + } + //============= + + if (iMode == 0) { + // + // everyone + // + + // Added in OPM + if (bInstaMessage) { + gi.Printf( + "%s (%zu) says (voice) to everyone: %s\n", client->pers.netname, edict - g_entities, pTmpInstantMsg + ); + } else { + gi.Printf( + "%s (%zu) says (text) to everyone: %s\n", client->pers.netname, edict - g_entities, sToken.c_str() + ); + } + + if (!IsSpectator() || g_spectate_allow_full_chat->integer) { + for (i = 0; i < game.maxclients; i++) { + ent = &g_entities[i]; - for (i = 0, ent = g_entities; i < game.maxclients; i++, ent++) { if (!ent->inuse || !ent->entity) { continue; } - gi.SendServerCommand(i, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); + gi.SendServerCommand(i, "%s", szPrintString); if (bInstaMessage) { gi.MSG_SetClient(i); @@ -9986,53 +10905,165 @@ void Player::EventDMMessage(Event *ev) gi.MSG_WriteCoord(m_vViewPos[0]); gi.MSG_WriteCoord(m_vViewPos[1]); gi.MSG_WriteCoord(m_vViewPos[2]); - gi.MSG_WriteBits(1, 1); + gi.MSG_WriteBits(qtrue, 1); gi.MSG_WriteBits(edict - g_entities, 6); - gi.MSG_WriteString(voiceName.c_str()); + gi.MSG_WriteString(sAliasName.c_str()); gi.MSG_EndCGM(); } } + } else { + // + // send a message to spectators + // + for (i = 0; i < game.maxclients; i++) { + ent = &g_entities[i]; - return; + if (!ent->inuse || !ent->entity) { + continue; + } + + if (!static_cast(ent->entity)->IsSpectator()) { + continue; + } + + gi.SendServerCommand(i, "%s", szPrintString); + } } - } - if (mode == -1) { - int i; - gentity_t *ent; - Player *p; + if (!bInstaMessage) { + Event event; + // sent to everyone (not a team) + event.AddString(sToken); + event.AddInteger(false); + scriptDelegate_textMessage.Trigger(this, event); + } + } else if (iMode < 0) { + // // team message - for (i = 0, ent = g_entities; i < game.maxclients; i++, ent++) { - if (!ent->inuse || !ent->entity) { - continue; + // + + // Added in OPM + if (bInstaMessage) { + gi.Printf("%s (%zu) says (voice) to team: %s\n", client->pers.netname, edict - g_entities, pTmpInstantMsg); + } else { + gi.Printf("%s (%zu) says (text) to team: %s\n", client->pers.netname, edict - g_entities, sToken.c_str()); + } + + if (IsSpectator()) { + for (i = 0; i < game.maxclients; i++) { + ent = &g_entities[i]; + + if (!ent->inuse || !ent->entity) { + continue; + } + + if (!static_cast(ent->entity)->IsSpectator()) { + continue; + } + + gi.SendServerCommand(i, "%s", szPrintString); } + } else { + for (i = 0; i < game.maxclients; i++) { + bool bSameTeam; - p = (Player *)ent->entity; + ent = &g_entities[i]; - if (p->GetTeam() == GetTeam()) { - gi.SendServerCommand(i, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); + if (!ent->inuse || !ent->entity) { + continue; + } + + bSameTeam = static_cast(ent->entity)->GetTeam() == GetTeam(); + if (bSameTeam) { + gi.SendServerCommand(i, "%s", szPrintString); + } + + if (bInstaMessage) { + gi.MSG_SetClient(i); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_VOICE_CHAT)); + gi.MSG_WriteCoord(m_vViewPos[0]); + gi.MSG_WriteCoord(m_vViewPos[1]); + gi.MSG_WriteCoord(m_vViewPos[2]); + gi.MSG_WriteBits(!bSameTeam, 1); + gi.MSG_WriteBits(edict - g_entities, 6); + gi.MSG_WriteString(sAliasName.c_str()); + gi.MSG_EndCGM(); + } } } - } else if (mode > 0) { - gentity_t *ent = g_entities + mode; - if (mode > game.maxclients || !ent->inuse || !ent->entity) { + if (!bInstaMessage) { + Event event; + // sent to team + event.AddString(sToken); + event.AddInteger(true); + + scriptDelegate_textMessage.Trigger(this, event); + } + } else if (iMode <= game.maxclients) { + ent = &g_entities[iMode - 1]; + + if (!ent->inuse || !ent->entity) { + str errorString = gi.LV_ConvertString("Message Error"); + str reasonString = gi.LV_ConvertString("is not a connected client"); + gi.SendServerCommand( - client->ps.clientNum, - "print \"" HUD_MESSAGE_CHAT_WHITE "Message Error: %d is a bad client number\n\"", - mode + edict - g_entities, + "print \"" HUD_MESSAGE_CHAT_WHITE "%s: %i %s.\n\"", + errorString.c_str(), + iMode, + reasonString.c_str() ); return; } - gi.SendServerCommand(client->ps.clientNum, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); - } + // Added in OPM + if (bInstaMessage) { + gi.Printf( + "%s (%zu) says (voice) to client #%d: %s\n", + client->pers.netname, + edict - g_entities, + iMode - 1, + pTmpInstantMsg + ); + } else { + gi.Printf( + "%s (%zu) says (text) to client #%d: %s\n", + client->pers.netname, + edict - g_entities, + iMode - 1, + sToken.c_str() + ); + } - gi.SendServerCommand(mode - 1, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); + gi.SendServerCommand(iMode - 1, "%s", szPrintString); + + if (ent->entity != this) { + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_CHAT_WHITE "%s %i:\n\"", + gi.LV_ConvertString("Message to player"), + iMode + ); + gi.SendServerCommand(edict - g_entities, "%s", szPrintString); + } + } else { + str errorString = gi.LV_ConvertString("Message Error"); + str reasonString = gi.LV_ConvertString("is a bad client number"); + + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_CHAT_WHITE "%s: %i %s.\n\"", + errorString.c_str(), + iMode, + reasonString.c_str() + ); + return; + } } -const char *Player::GetBattleLanguageCondition() const +str Player::GetBattleLanguageCondition() const { int healthRatio; @@ -10049,7 +11080,7 @@ const char *Player::GetBattleLanguageCondition() const case 0: return "almost dead"; case 1: - return "severly wounded"; + return "severely wounded"; case 2: return "wounded"; case 3: @@ -10060,7 +11091,7 @@ const char *Player::GetBattleLanguageCondition() const } } -const char *Player::GetBattleLanguageDirection() const +str Player::GetBattleLanguageDirection() const { int dir = ((m_vViewAng.y - world->m_fNorth) + 22.5f + 360.f) / 45.f; switch (dir % 8) { @@ -10085,12 +11116,12 @@ const char *Player::GetBattleLanguageDirection() const } } -const char *Player::GetBattleLanguageLocation() const +str Player::GetBattleLanguageLocation() const { - return level.GetDMLocation(m_vViewPos).c_str(); + return gi.CL_LV_ConvertString(level.GetDMLocation(m_vViewPos).c_str()); } -const char *Player::GetBattleLanguageLocalFolks() +str Player::GetBattleLanguageLocalFolks() { static char buf[256]; char *p; @@ -10121,7 +11152,7 @@ const char *Player::GetBattleLanguageLocalFolks() break; } - strcpy(p, ", "); + Q_strncpyz(p, ", ", sizeof(buf) - (p - buf)); p += 2; curP = p; remaining -= 2; @@ -10132,7 +11163,7 @@ const char *Player::GetBattleLanguageLocalFolks() break; } - strcpy(p, client->pers.netname); + Q_strncpyz(p, client->pers.netname, sizeof(buf) - (p - buf)); p += length; remaining -= length; pFolk = pPlayer; @@ -10140,8 +11171,8 @@ const char *Player::GetBattleLanguageLocalFolks() } if (curP && remaining >= 2) { - strcpy(curP, "and "); - strcpy(curP + strlen(curP), pFolk->client->pers.netname); + Q_strncpyz(curP, "and ", sizeof(buf) - (curP - buf)); + Q_strncpyz(curP + strlen(curP), pFolk->client->pers.netname, sizeof(buf) - (curP + strlen(curP) - buf)); } else if (!pFolk) { return "nobody"; } @@ -10149,12 +11180,12 @@ const char *Player::GetBattleLanguageLocalFolks() return buf; } -const char *Player::GetBattleLanguageWeapon() const +str Player::GetBattleLanguageWeapon() const { return GetCurrentDMWeaponType().c_str(); } -const char *Player::GetBattleLanguageDistance() const +str Player::GetBattleLanguageDistance() const { Vector vStart, vEnd; Vector vForward; @@ -10186,7 +11217,7 @@ const char *Player::GetBattleLanguageDistance() const } } -const char *Player::GetBattleLanguageDistanceMeters(float dist) const +str Player::GetBattleLanguageDistanceMeters(float dist) const { int meters; @@ -10204,7 +11235,7 @@ const char *Player::GetBattleLanguageDistanceMeters(float dist) const return va("%d meters", meters); } -const char *Player::GetBattleLanguageDistanceFeet(float dist) const +str Player::GetBattleLanguageDistanceFeet(float dist) const { int ft; @@ -10222,7 +11253,7 @@ const char *Player::GetBattleLanguageDistanceFeet(float dist) const return va("%d feet", ft); } -const char *Player::GetBattleLanguageTarget() const +str Player::GetBattleLanguageTarget() const { Vector vStart, vEnd; Vector vForward; @@ -10264,17 +11295,17 @@ const char *Player::GetBattleLanguageTarget() const return "something"; } -const char *Player::TranslateBattleLanguageTokens(const char *string) +str Player::TranslateBattleLanguageTokens(const char *string) { - const char *token; - int type; + str token; + int type; if (!g_chat_expansions->integer) { return string; } if (!string) { - return NULL; + return str(); } if (string[0] != '$') { @@ -10325,9 +11356,13 @@ void Player::EventIPrint(Event *ev) } if (iBold) { - gi.SendServerCommand(edict - g_entities, "print \"" HUD_MESSAGE_WHITE "%s\n\"", sString.c_str()); + gi.SendServerCommand( + edict - g_entities, "print \"" HUD_MESSAGE_WHITE "%s\n\"", gi.LV_ConvertString(sString.c_str()) + ); } else { - gi.SendServerCommand(edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", sString.c_str()); + gi.SendServerCommand( + edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", gi.LV_ConvertString(sString.c_str()) + ); } } @@ -10338,7 +11373,7 @@ void Player::SetViewangles(Event *ev) void Player::GetViewangles(Event *ev) { - ev->AddVector(v_angle); + ev->AddVector(GetVAngles()); } void Player::EventGetUseHeld(Event *ev) @@ -10498,14 +11533,21 @@ void Player::RemoveFromVehiclesAndTurrets(void) RemoveFromVehiclesAndTurretsInternal(); } - m_pVehicle->Lock(); + // the vehicle might have been modified + if (m_pVehicle) { + m_pVehicle->Lock(); + } } else if (m_pTurret && m_pTurret->IsSubclassOfVehicleTurretGun()) { VehicleTurretGun *turret = (VehicleTurretGun *)m_pTurret.Pointer(); if (turret->isLocked()) { turret->UnLock(); RemoveFromVehiclesAndTurretsInternal(); - turret->Lock(); + + // the turret might have been modified + if (m_pTurret) { + turret->Lock(); + } } else { RemoveFromVehiclesAndTurretsInternal(); } @@ -10546,7 +11588,6 @@ void Player::EventSetPerferredWeapon(Event *ev) } void Player::SetMouthAngle(Event *ev) - { int tag_num; float angle_percent; @@ -10579,6 +11620,59 @@ int Player::GetMoveResult(void) return moveresult; } +qboolean Player::CheckCanSwitchTeam(teamtype_t team) +{ + float startTime; + + startTime = dmManager.GetMatchStartTime(); + + if (startTime >= 0.0f && (level.time - startTime) > 30.0 + && (level.time - m_fTeamSelectTime) < g_teamswitchdelay->integer) { + int seconds = g_teamswitchdelay->integer - (level.time - m_fTeamSelectTime); + + gi.SendServerCommand( + edict - g_entities, + "print \"" HUD_MESSAGE_WHITE "%s %i %s\n\"", + gi.LV_ConvertString("Can not change teams again for another"), + seconds + 1, + gi.LV_ConvertString("seconds") + ); + return qfalse; + } + + // Added in OPM + // Check and prevent joining the team with the highest number of players + if (g_teambalance->integer && g_gametype->integer >= GT_TEAM && !dmManager.WaitingForPlayers()) { + DM_Team *pNewTeam = dmManager.GetTeam(team); + int i; + + for (i = 0; i < 2; i++) { + DM_Team *pTeam = dmManager.GetTeam((teamtype_t)(TEAM_ALLIES + i)); + int numTeamPlayers = pTeam->m_players.NumObjects(); + + if (pTeam->m_players.IndexOfObject(this)) { + // Don't count the current player + numTeamPlayers--; + } + + if (pNewTeam->m_players.NumObjects() > numTeamPlayers) { + const char *message = gi.LV_ConvertString( + "That team has enough players. Choose the team that has the lowest number of players." + ); + + gi.SendServerCommand( + edict - g_entities, "print \"" HUD_MESSAGE_WHITE "%s\n\"", gi.LV_ConvertString(message) + ); + + gi.centerprintf(edict, message); + return qfalse; + } + } + } + + return qtrue; +} + qboolean Player::ViewModelAnim(str anim, qboolean force_restart, qboolean bFullAnim) { Unregister(STRING_VIEWMODELANIM_DONE); @@ -10593,10 +11687,10 @@ qboolean Player::ViewModelAnim(str anim, qboolean force_restart, qboolean bFullA if (!anim.length()) { anim = ""; - } + } - // Copy the item prefix and the anim name - weapon = GetActiveWeapon(WEAPON_MAIN); + // Copy the item prefix and the anim name + weapon = GetActiveWeapon(WEAPON_MAIN); if (!Q_stricmp(anim, "charge")) { viewModelAnim = VM_ANIM_CHARGE; @@ -10665,7 +11759,7 @@ qboolean Player::ViewModelAnim(str anim, qboolean force_restart, qboolean bFullA playerState->iViewModelAnim = viewModelAnim; if (m_fpsTiki && gi.Anim_NumForName(m_fpsTiki, m_sVMAcurrent) < 0) { - gi.DPrintf("WARNING: Invalid view model anim \"%s\"\n", m_sVMAcurrent.c_str()); + //gi.DPrintf("WARNING: Invalid view model anim \"%s\"\n", m_sVMAcurrent.c_str()); } animDoneVM = false; @@ -10688,6 +11782,16 @@ void Player::FindAlias(str& output, str name, AliasListNode_t **node) } } +bool Player::HasVotedYes() const +{ + return voted; +} + +bool Player::HasVotedNo() const +{ + return !voted; +} + void Player::TickSprint() { float timeHeld; @@ -10736,6 +11840,13 @@ void Player::FireWeapon(int number, firemode_t mode) return; } + if (G_GetWeaponCommand(last_ucmd.buttons)) { + // Added in OPM + // If there is a weapon command (like DROP), then just don't fire + // this prevent tricky behaviors, like silent firing + return; + } + Sentient::FireWeapon(number, mode); if (g_gametype->integer != GT_SINGLE_PLAYER) { @@ -10876,7 +11987,7 @@ bool Player::ShouldForceSpectatorOnDeath() const return dmManager.GetTeamSpawnTimeLeft() > 0; } -bool Player::HasVehicle() +bool Player::HasVehicle() const { return m_pVehicle != NULL; } @@ -10904,15 +12015,15 @@ void Player::UserSelectWeapon(bool bWait) } if (GetTeam() == TEAM_AXIS) { - nationality = GetPlayerTeamType(client->pers.dm_playergermanmodel); + nationality = GetPlayerAxisTeamType(client->pers.dm_playergermanmodel); } else { - nationality = GetPlayerTeamType(client->pers.dm_playermodel); + nationality = GetPlayerAlliedTeamType(client->pers.dm_playermodel); } if (bWait) { - strcpy(buf, "stufftext \"wait 250;pushmenu "); + Q_strncpyz(buf, "stufftext \"wait 250;pushmenu ", sizeof(buf)); } else { - strcpy(buf, "stufftext \"pushmenu "); + Q_strncpyz(buf, "stufftext \"pushmenu ", sizeof(buf)); } if (dmflags->integer & DF_WEAPON_NO_RIFLE && dmflags->integer & DF_WEAPON_NO_SNIPER @@ -10921,24 +12032,24 @@ void Player::UserSelectWeapon(bool bWait) && dmflags->integer & DF_WEAPON_NO_LANDMINE && !QueryLandminesAllowed()) { gi.cvar_set("dmflags", va("%i", dmflags->integer & ~DF_WEAPON_NO_RIFLE)); Com_Printf("No valid weapons -- re-allowing the rifle\n"); - strcpy(client->pers.dm_primary, "rifle"); + Q_strncpyz(client->pers.dm_primary, "rifle", sizeof(client->pers.dm_primary)); } switch (nationality) { case NA_BRITISH: - strcat(buf, "SelectPrimaryWeapon_british\""); + Q_strcat(buf, sizeof(buf), "SelectPrimaryWeapon_british\""); break; case NA_RUSSIAN: - strcat(buf, "SelectPrimaryWeapon_russian\""); + Q_strcat(buf, sizeof(buf), "SelectPrimaryWeapon_russian\""); break; case NA_GERMAN: - strcat(buf, "SelectPrimaryWeapon_german\""); + Q_strcat(buf, sizeof(buf), "SelectPrimaryWeapon_german\""); break; case NA_ITALIAN: - strcat(buf, "SelectPrimaryWeapon_italian\""); + Q_strcat(buf, sizeof(buf), "SelectPrimaryWeapon_italian\""); break; default: - strcat(buf, "SelectPrimaryWeapon\""); + Q_strcat(buf, sizeof(buf), "SelectPrimaryWeapon\""); break; } @@ -11027,57 +12138,166 @@ void Player::EventGetVehicle(Event *ev) bool Player::IsReady(void) const { - return m_bReady; + return m_bReady && !IsDead(); } void Player::Spawned(void) { Event *ev = new Event; - ev->AddEntity(this); + + scriptDelegate_spawned.Trigger(this, *ev); scriptedEvents[SE_SPAWN].Trigger(ev); } -// reborn stuff - -void Player::AddDeaths(Event *ev) +void Player::AddKills(int num) { - AddDeaths(ev->GetInteger(1)); + num_kills += num; +} + +void Player::AddDeaths(int num) +{ + num_deaths += num; +} + +//////////////////////////// +// +// Added in OPM +// +//////////////////////////// + +qboolean Player::canUse() +{ + int touch[MAX_GENTITIES]; + int num = getUseableEntities(touch, MAX_GENTITIES); + + return num ? true : false; +} + +qboolean Player::canUse(Entity *entity, bool requiresLookAt) +{ + gentity_t *hit; + int touch[MAX_GENTITIES]; + int num; + int i; + + num = getUseableEntities(touch, MAX_GENTITIES, requiresLookAt); + + for (i = 0; i < num; i++) { + hit = &g_entities[touch[i]]; + + if (!hit->inuse || hit->entity == NULL) { + continue; + } + + if (hit->entity == entity) { + return true; + } + } + + return false; +} + +int Player::getUseableEntities(int *touch, int maxcount, bool requiresLookAt) +{ + Vector end; + Vector start; + trace_t trace; + Vector offset; + Vector max; + Vector min; + + if ((g_gametype->integer != GT_SINGLE_PLAYER && IsSpectator()) || IsDead()) { + return 0; + } + + if (m_pTurret) { + *touch = m_pTurret->entnum; + return 1; + } + + if (m_pTurret) { + return 0; + } + + AngleVectors(client->ps.viewangles, offset, NULL, NULL); + + start = origin; + start.z += client->ps.viewheight; + + if (requiresLookAt) { + min = Vector(-4.f, -4.f, -4.f); + max = Vector(4.f, 4.f, 4.f); + + end[0] = start[0] + (offset[0] * 64.f); + end[1] = start[1] + (offset[1] * 64.f); + + if (v_angle[0] <= 0.0f) { + end[2] = start[2] + (offset[2] * 40.f); + } else { + end[2] = start[2] + (offset[2] * 88.f); + } + + trace = G_Trace(start, min, max, end, this, MASK_USE, false, "Player::getUseableEntity"); + + offset = trace.endpos; + + min = offset - Vector(16.f, 16.f, 16.f); + max = offset + Vector(16.f, 16.f, 16.f); + } else { + min = start - Vector(31.f, 31.f, 31.f); + max = start + Vector(31.f, 31.f, 31.f); + } + + return gi.AreaEntities(min, max, touch, maxcount); +} + +void Player::Postthink(void) +{ + if (bindmaster) { + SetViewAngles(GetViewAngles() + Vector(0, bindmaster->avelocity[YAW] * level.frametime, 0)); + } } void Player::AdminRights(Event *ev) { // FIXME: Admin manager ? ev->AddInteger(0); + UNIMPLEMENTED(); +} + +void Player::IsAdmin(Event *ev) +{ + // FIXME: Admin manager ? + ev->AddInteger(0); + UNIMPLEMENTED(); } void Player::BindWeap(Event *ev) { - // FIXME: TODO -} + Entity *ent = ev->GetEntity(1); + Listener *scriptOwner; -void Player::CanSwitchTeams(Event *ev) -{ - qboolean bAllow = ev->GetBoolean(1); + // + // FIXME: deprecate and use something else instead + // like implement this in the Item class directly + // this is dangerous to use especially if the weapon + // is a VehicleTurretGun, could easily mess up the camera - disable_team_change = !bAllow; - if (ev->NumArgs() > 1) { - qboolean bAllow2 = ev->GetBoolean(2); + if (ent) { + scriptOwner = ent->GetScriptOwner(); - disable_spectate = !bAllow2; + if (scriptOwner != this) { + ent->SetScriptOwner(this); + } else { + ent->SetScriptOwner(NULL); + } } } -void Player::ClearCommand(Event *ev) +void Player::AddDeaths(Event *ev) { - str command; - int clientNum = G_GetClientNumber(this); - - if (ev->NumArgs() > 0) { - command = ev->GetString(1); - } - - m_lastcommand = ""; + AddDeaths(ev->GetInteger(1)); } void Player::Dive(Event *ev) @@ -11101,39 +12321,6 @@ void Player::Dive(Event *ev) velocity[2] += height * speed / 6.80f; } -void Player::EventEarthquake(Event *ev) -{ - float duration = ev->GetFloat(1); - float magnitude = ev->GetFloat(2); - qboolean no_rampup = ev->GetBoolean(3); - qboolean no_rampdown = ev->GetBoolean(4); - - // full realistic, smooth earthquake - if (ev->NumArgs() > 4) { - Vector location = ev->GetVector(5); - float radius = 1.0f; - - if (ev->NumArgs() > 5) { - radius = ev->GetFloat(6); - } - - gi.SendServerCommand( - edict - g_entities, - "eq %f %f %d %d %f %f %f %f", - duration, - magnitude, - no_rampup, - no_rampdown, - location[0], - location[1], - location[2], - radius - ); - } else { - gi.SendServerCommand(edict - g_entities, "eq %f %f %d %d", duration, magnitude, no_rampup, no_rampdown); - } -} - void Player::EventSetTeam(Event *ev) { str team_name; @@ -11162,7 +12349,7 @@ void Player::EventSetTeam(Event *ev) SetTeam(teamType); - gi.Printf("Player::SetTeam : Player is now on team \"%s\"\n", team_name.c_str()); + gi.DPrintf("Player::SetTeam : Player is now on team \"%s\"\n", team_name.c_str()); } void Player::EventGetViewModelAnim(Event *ev) @@ -11216,7 +12403,13 @@ void Player::FreezeControls(Event *ev) void Player::GetConnState(Event *ev) { - ScriptDeprecated("Player::GetConnState"); + // Assume CS_ACTIVE + ev->AddInteger(4); + + gi.DPrintf( + "getconnstate is deprecated and will always return 4 (CS_ACTIVE).\nThe player is created only when the client " + "begins (CS_ACTIVE state).\n" + ); } void Player::GetDamageMultiplier(Event *ev) @@ -11231,8 +12424,8 @@ void Player::GetDeaths(Event *ev) void Player::GetKillHandler(Event *ev) { - if (m_pKilledEvent) { - ev->AddValue(m_pKilledEvent->GetValue(1)); + if (m_killedLabel.IsSet()) { + m_killedLabel.GetScriptValue(&ev->GetValue()); } else { ev->AddNil(); } @@ -11288,11 +12481,13 @@ void Player::GetTorsoState(Event *ev) void Player::HideEntity(Event *ev) { // FIXME: todo + UNIMPLEMENTED(); } void Player::ShowEntity(Event *ev) { // FIXME: REDO + UNIMPLEMENTED(); } void Player::Inventory(Event *ev) @@ -11371,12 +12566,6 @@ void Player::InventorySet(Event *ev) array.Clear(); } -void Player::IsAdmin(Event *ev) -{ - // FIXME: Admin manager ? - ev->AddInteger(0); -} - void Player::LeanLeftHeld(Event *ev) { Player *player = NULL; @@ -11426,19 +12615,18 @@ void Player::PlayLocalSound(Event *ev) return; } - // FIXME... - /* - gi.MSG_SetClient( client->ps.clientNum ); +#ifdef OPM_FEATURES + gi.MSG_SetClient(client->ps.clientNum); - gi.MSG_StartCGM( CGM_PLAYLOCALSOUND ); - gi.MSG_WriteString( found ); - gi.MSG_WriteBits( !!loop, 1 ); - gi.MSG_WriteFloat( time ); - gi.MSG_WriteFloat( alias->volume ); - gi.MSG_EndCGM(); + gi.MSG_StartCGM(CGM_PLAYLOCALSOUND); + gi.MSG_WriteString(found); + gi.MSG_WriteBits(!!loop, 1); + gi.MSG_WriteFloat(time); + gi.MSG_WriteFloat(alias->volume); + gi.MSG_EndCGM(); - return; - */ + return; +#endif if (loop) { edict->s.loopSound = gi.soundindex(found, alias->streamed); @@ -11487,79 +12675,18 @@ void Player::SetAnimSpeed(Event *ev) speed = 0.0f; } - //player->baseSentient.baseAnimate.baseEntity.client->customanimspeed = speed; -} - -void Player::SetClientFlag(Event *ev) -{ - str name = ev->GetString(1); - - gi.SendServerCommand(client->ps.clientNum, "cf %s", name.c_str()); -} - -void Player::SetEntityShader(Event *ev) -{ - Entity *entity = ev->GetEntity(1); - str shadername = ev->GetString(2); - qboolean fReset = false; - - if (entity == NULL) { - ScriptError("Invalid entity !"); - } - - if (!shadername.length()) { - shadername = "default"; - fReset = true; - } - - gi.SendServerCommand(edict - g_entities, "setshader %d %s %d", entity->entnum, shadername.c_str(), fReset); + UNIMPLEMENTED(); } void Player::SetKillHandler(Event *ev) { if (ev->IsNilAt(1) || (ev->IsStringAt(1) && !ev->GetString(1).icmp("none"))) { - if (m_pKilledEvent != NULL) { - delete m_pKilledEvent; - m_pKilledEvent = NULL; - } + m_killedLabel.Clear(); } else { - m_pKilledEvent = new Event(EV_Listener_ExecuteScript); - m_pKilledEvent->AddValue(ev->GetValue(1)); + m_killedLabel.SetScript(ev->GetValue(1)); } } -void Player::SetLocalSoundRate(Event *ev) -{ - str name = ev->GetString(1); - float rate = ev->GetFloat(2); - float time; - - if (ev->NumArgs() > 2) { - time = ev->GetFloat(3); - } else { - time = 0.0f; - } - - AliasListNode_t *alias = NULL; - const char *found = gi.GlobalAlias_FindRandom(name, &alias); - - if (found == NULL) { - gi.DPrintf("ERROR: Player::SetLocalSoundRate: %s needs to be aliased - Please fix.\n", name.c_str()); - return; - } - - gi.MSG_SetClient(client->ps.clientNum); - - // FIXME... - /* - gi.MSG_StartCGM( CGM_SETLOCALSOUNDRATE ); - gi.MSG_WriteString( found ); - gi.MSG_WriteFloat( rate ); - gi.MSG_WriteFloat( time ); - gi.MSG_EndCGM(); - */ -} - void Player::SetSpeed(Event *ev) { float speed; @@ -11610,35 +12737,6 @@ void Player::SetStateFile(Event *ev) } } -void Player::SetVMASpeed(Event *ev) -{ - str name = ev->GetString(1); - float speed = ev->GetFloat(2); - - if (!client || !level.specialgame) { - return; - } - - vma_t *vma = &vmalist[name]; - - if (speed < 0.0f) { - speed = 0.0f; - } - - vma->name = name; - vma->speed = speed; - - // FIXME... - /* - gi.MSG_SetClient( edict - g_entities ); - - gi.MSG_StartCGM( CGM_SETVMASPEED ); - gi.MSG_WriteString( name ); - gi.MSG_WriteFloat( speed ); - gi.MSG_EndCGM(); - */ -} - void Player::StopLocalSound(Event *ev) { str soundName = ev->GetString(1); @@ -11672,6 +12770,137 @@ void Player::Userinfo(Event *ev) ev->AddString(client->pers.userinfo); } +int Player::GetNumKills(void) const +{ + return num_kills; +} + +int Player::GetNumDeaths(void) const +{ + return num_deaths; +} + +#ifdef OPM_FEATURES + +void Player::EventEarthquake(Event *ev) +{ + float duration = ev->GetFloat(1); + float magnitude = ev->GetFloat(2); + qboolean no_rampup = ev->GetBoolean(3); + qboolean no_rampdown = ev->GetBoolean(4); + + // full realistic, smooth earthquake + if (ev->NumArgs() > 4) { + Vector location = ev->GetVector(5); + float radius = 1.0f; + + if (ev->NumArgs() > 5) { + radius = ev->GetFloat(6); + } + + gi.SendServerCommand( + edict - g_entities, + "eq %f %f %d %d %f %f %f %f", + duration, + magnitude, + no_rampup, + no_rampdown, + location[0], + location[1], + location[2], + radius + ); + } else { + gi.SendServerCommand(edict - g_entities, "eq %f %f %d %d", duration, magnitude, no_rampup, no_rampdown); + } +} + +void Player::SetClientFlag(Event *ev) +{ + str name = ev->GetString(1); + + gi.SendServerCommand(client->ps.clientNum, "cf %s", name.c_str()); +} + +void Player::SetEntityShader(Event *ev) +{ + Entity *entity = ev->GetEntity(1); + str shadername = ev->GetString(2); + qboolean fReset = false; + + if (entity == NULL) { + ScriptError("Invalid entity !"); + } + + if (!shadername.length()) { + shadername = "default"; + fReset = true; + } + + gi.SendServerCommand(edict - g_entities, "setshader %d %s %d", entity->entnum, shadername.c_str(), fReset); +} + +void Player::SetLocalSoundRate(Event *ev) +{ + str name = ev->GetString(1); + float rate = ev->GetFloat(2); + float time; + + if (ev->NumArgs() > 2) { + time = ev->GetFloat(3); + } else { + time = 0.0f; + } + + AliasListNode_t *alias = NULL; + const char *found = gi.GlobalAlias_FindRandom(name, &alias); + + if (found == NULL) { + gi.DPrintf("ERROR: Player::SetLocalSoundRate: %s needs to be aliased - Please fix.\n", name.c_str()); + return; + } + + gi.MSG_SetClient(client->ps.clientNum); + + // FIXME... + /* + gi.MSG_StartCGM( CGM_SETLOCALSOUNDRATE ); + gi.MSG_WriteString( found ); + gi.MSG_WriteFloat( rate ); + gi.MSG_WriteFloat( time ); + gi.MSG_EndCGM(); + */ +} + +void Player::SetVMASpeed(Event *ev) +{ + str name = ev->GetString(1); + float speed = ev->GetFloat(2); + + if (!client || !sv_specialgame->integer) { + return; + } + + vma_t *vma = &vmalist[name]; + + if (speed < 0.0f) { + speed = 0.0f; + } + + vma->name = name; + vma->speed = speed; + + // FIXME... + /* + gi.MSG_SetClient( edict - g_entities ); + + gi.MSG_StartCGM( CGM_SETVMASPEED ); + gi.MSG_WriteString( name ); + gi.MSG_WriteFloat( speed ); + gi.MSG_EndCGM(); + */ +} + void Player::VisionGetNaked(Event *ev) { // return the global vision @@ -11726,120 +12955,4 @@ void Player::VisionSetNaked(Event *ev) gi.SendServerCommand(edict - g_entities, "vsn %s %f %f", vision.c_str(), fade_time, phase); } - -int Player::GetNumKills(void) const -{ - return num_kills; -} - -int Player::GetNumDeaths(void) const -{ - return num_deaths; -} - -void Player::AddKills(int num) -{ - num_kills += num; - - if (g_gametype->integer >= GT_TEAM_ROUNDS) { - num_deaths += num; - } -} - -void Player::AddDeaths(int num) -{ - num_deaths += num; -} - -qboolean Player::canUse() -{ - int touch[MAX_GENTITIES]; - int num = getUseableEntities(touch, MAX_GENTITIES); - - return num ? true : false; -} - -qboolean Player::canUse(Entity *entity, bool requiresLookAt) -{ - gentity_t *hit; - int touch[MAX_GENTITIES]; - int num; - int i; - - num = getUseableEntities(touch, MAX_GENTITIES, requiresLookAt); - - for (i = 0; i < num; i++) { - hit = &g_entities[touch[i]]; - - if (!hit->inuse || hit->entity == NULL) { - continue; - } - - if (hit->entity == entity) { - return true; - } - } - - return false; -} - -int Player::getUseableEntities(int *touch, int maxcount, bool requiresLookAt) -{ - Vector end; - Vector start; - trace_t trace; - Vector offset; - Vector max; - Vector min; - - if ((g_gametype->integer && IsSpectator()) || IsDead()) { - return 0; - } - - if (m_pTurret) { - *touch = m_pTurret->entnum; - return 1; - } - - if (m_pTurret) { - return 0; - } - - AngleVectors(client->ps.viewangles, offset, NULL, NULL); - - start = origin; - start.z += client->ps.viewheight; - - if (requiresLookAt) { - min = Vector(-4.f, -4.f, -4.f); - max = Vector(4.f, 4.f, 4.f); - - end[0] = start[0] + (offset[0] * 64.f); - end[1] = start[1] + (offset[1] * 64.f); - - if (v_angle[0] <= 0.0f) { - end[2] = start[2] + (offset[2] * 40.f); - } else { - end[2] = start[2] + (offset[2] * 88.f); - } - - trace = G_Trace(start, min, max, end, this, MASK_SOLID, false, "Player::getUseableEntity"); - - offset = trace.endpos; - - min = offset - Vector(16.f, 16.f, 16.f); - max = offset + Vector(16.f, 16.f, 16.f); - } else { - min = start - Vector(31.f, 31.f, 31.f); - max = start + Vector(31.f, 31.f, 31.f); - } - - return gi.AreaEntities(min, max, touch, maxcount); -} - -void Player::Postthink(void) -{ - if (bindmaster) { - SetViewAngles(GetViewAngles() + Vector(0, bindmaster->avelocity[YAW] * level.frametime, 0)); - } -} \ No newline at end of file +#endif diff --git a/code/fgame/player.h b/code/fgame/player.h index 2168b2c3..93a7986b 100644 --- a/code/fgame/player.h +++ b/code/fgame/player.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" #include "vehicle.h" #include "dm_manager.h" +#include "scriptdelegate.h" extern Event EV_Player_EndLevel; extern Event EV_Player_GiveCheat; @@ -68,7 +69,8 @@ enum painDirection_t { }; typedef enum { - ANIMSLOT_PAIN = 4 + ANIMSLOT_PAIN = 4, + ANIMSLOT_TESTANIM = 7 } playerAnimSlot_t; typedef enum { @@ -129,7 +131,7 @@ class Player : public Sentient friend class VehicleTurretGun; private: - static Condition Conditions[]; + static Condition m_conditions[]; static movecontrolfunc_t MoveStartFuncs[]; StateMap *statemap_Legs; @@ -305,7 +307,19 @@ private: bool m_bDeathSpectator; jailstate_t m_jailstate; +#ifdef OPM_FEATURES bool m_bShowingHint; +#endif + +public: + MulticastDelegate delegate_stufftext; + + static ScriptDelegate scriptDelegate_connected; + static ScriptDelegate scriptDelegate_disconnecting; + static ScriptDelegate scriptDelegate_spawned; + static ScriptDelegate scriptDelegate_damage; + static ScriptDelegate scriptDelegate_kill; + static ScriptDelegate scriptDelegate_textMessage; public: int m_iNumObjectives; @@ -342,15 +356,15 @@ public: bool m_bWaitingForRespawn; bool m_bShouldRespawn; - // new variables + // + // Added in OPM + // str m_sVision; // current vision str m_sStateFile; // custom statefile - bool disable_spectate; - bool disable_team_change; - bool m_bFrozen; // if player is frozen + bool m_bFrozen; // if player is frozen bool animDoneVM; float speed_multiplier[MAX_SPEED_MULTIPLIERS]; - Event *m_pKilledEvent; + ScriptThreadLabel m_killedLabel; con_map vmalist; str m_sVMAcurrent; str m_sVMcurrent; @@ -359,6 +373,10 @@ public: bool m_bConnected; str m_lastcommand; +private: + int m_iInstantMessageTime; + int m_iTextChatTime; + public: qboolean CondTrue(Conditional& condition); qboolean CondChance(Conditional& condition); @@ -514,6 +532,7 @@ public: void InitWeapons(void); void InitView(void); void InitModel(void); + void InitModelFps(void); // Added in openmohaa void InitState(void); void InitHealth(void); void InitInventory(void); @@ -538,7 +557,7 @@ public: void DoUse(Event *ev); void Obituary(Entity *attacker, Entity *inflictor, int meansofdeath, int iLocation); - void Killed(Event *ev); + void Killed(Event *ev) override; void Dead(Event *ev); void Pain(Event *ev); @@ -668,7 +687,7 @@ public: void TestThread(Event *ev); Vector EyePosition(void) override; - Vector GunTarget(bool bNoCollision = false) override; + Vector GunTarget(bool bNoCollision, const vec3_t position, const vec3_t forward) override; void GotKill(Event *ev); void SetPowerupTimer(Event *ev); @@ -769,16 +788,16 @@ public: void EventDMMessage(Event *ev); //==== // Added in 2.30 - const char *GetBattleLanguageCondition() const; - const char *GetBattleLanguageDirection() const; - const char *GetBattleLanguageLocation() const; - const char *GetBattleLanguageLocalFolks(); - const char *GetBattleLanguageWeapon() const; - const char *GetBattleLanguageDistance() const; - const char *GetBattleLanguageDistanceMeters(float dist) const; - const char *GetBattleLanguageDistanceFeet(float dist) const; - const char *GetBattleLanguageTarget() const; - const char *TranslateBattleLanguageTokens(const char *string); + str GetBattleLanguageCondition() const; + str GetBattleLanguageDirection() const; + str GetBattleLanguageLocation() const; + str GetBattleLanguageLocalFolks(); + str GetBattleLanguageWeapon() const; + str GetBattleLanguageDistance() const; + str GetBattleLanguageDistanceMeters(float dist) const; + str GetBattleLanguageDistanceFeet(float dist) const; + str GetBattleLanguageTarget() const; + str TranslateBattleLanguageTokens(const char *string); //==== void EventIPrint(Event *ev); void EventGetUseHeld(Event *ev); @@ -799,7 +818,7 @@ public: void SetPlayerSpectate(bool bNext); void SetPlayerSpectateRandom(void); // Added in 2.0 bool IsValidSpectatePlayer(Player *pPlayer); - void GetSpectateFollowOrientation(Player *pPlayer, Vector &vPos, Vector &vAng); + void GetSpectateFollowOrientation(Player *pPlayer, Vector& vPos, Vector& vAng); void UpdateStatus(const char *s); void SetDM_Team(DM_Team *team); DM_Team *GetDM_Team(); @@ -842,7 +861,7 @@ public: void EventDMDeathDrop(Event *ev); void EventStopwatch(Event *ev); - void KilledPlayerInDeathmatch(Player *killed); + void KilledPlayerInDeathmatch(Player *killed, meansOfDeath_t meansofdeath); void SetStopwatch(int iDuration, stopWatchType_t type = SWT_NORMAL); void BeginTempSpectator(void); void EndSpectator(void); @@ -882,7 +901,7 @@ public: void InitInvulnerable(); void TickTeamSpawn(); bool ShouldForceSpectatorOnDeath() const; - bool HasVehicle(); + bool HasVehicle() const override; void setContentsSolid() override; void UserSelectWeapon(bool bWait); void PickWeaponEvent(Event *ev); @@ -901,20 +920,22 @@ public: void FindAlias(str& output, str name, AliasListNode_t **node); + bool HasVotedYes() const; + bool HasVotedNo() const; + //============================= - // Custom openmohaa stuff + // Added in OPM //============================= + qboolean CheckCanSwitchTeam(teamtype_t team); + qboolean ViewModelAnim(str anim, qboolean force_restart, qboolean bFullAnim); virtual void Spawned(void); void AddDeaths(Event *ev); void AdminRights(Event *ev); void BindWeap(Event *ev); - void CanSwitchTeams(Event *ev); - void ClearCommand(Event *ev); void Dive(Event *ev); - void EventEarthquake(Event *ev); void EventSetTeam(Event *ev); void EventGetViewModelAnim(Event *ev); void EventGetViewModelAnimFinished(Event *ev); @@ -929,7 +950,6 @@ public: void GetLegsState(Event *ev); void GetStateFile(Event *ev); void GetTorsoState(Event *ev); - void HideEntity(Event *ev); void Inventory(Event *ev); void InventorySet(Event *ev); void IsAdmin(Event *ev); @@ -941,19 +961,23 @@ public: void RunHeld(Event *ev); void SecFireHeld(Event *ev); void SetAnimSpeed(Event *ev); - void SetClientFlag(Event *ev); - void SetEntityShader(Event *ev); void SetKillHandler(Event *ev); - void SetLocalSoundRate(Event *ev); void SetSpeed(Event *ev); void SetStateFile(Event *ev); - void SetVMASpeed(Event *ev); + void HideEntity(Event *ev); void ShowEntity(Event *ev); void StopLocalSound(Event *ev); void Userinfo(Event *ev); +#ifdef OPM_FEATURES + void EventEarthquake(Event *ev); + void SetClientFlag(Event *ev); + void SetEntityShader(Event *ev); + void SetLocalSoundRate(Event *ev); + void SetVMASpeed(Event *ev); void VisionGetNaked(Event *ev); void VisionSetBlur(Event *ev); void VisionSetNaked(Event *ev); +#endif void Postthink() override; void GibEvent(Event *ev); @@ -974,7 +998,7 @@ inline void Player::Archive(Archiver& arc) arc.ArchiveFloat(&m_fPartBlends[0]); arc.ArchiveFloat(&m_fPartBlends[1]); arc.ArchiveFloat(&partBlendMult[0]); - arc.ArchiveFloat(&partBlendMult[0]); + arc.ArchiveFloat(&partBlendMult[1]); arc.ArchiveString(&last_torso_anim_name); arc.ArchiveString(&last_leg_anim_name); @@ -1011,6 +1035,7 @@ inline void Player::Archive(Archiver& arc) arc.ArchiveInteger(&buttons); arc.ArchiveInteger(&new_buttons); + arc.ArchiveInteger(&server_new_buttons); arc.ArchiveFloat(&respawn_time); arc.ArchiveInteger(&last_attack_button); @@ -1050,6 +1075,8 @@ inline void Player::Archive(Archiver& arc) arc.ArchiveBool(&take_pain); arc.ArchiveInteger(&nextpaintime); + arc.ArchiveFloat(&m_fHealRate); + arc.ArchiveBool(&knockdown); arc.ArchiveBool(&canfall); arc.ArchiveBool(&falling); @@ -1116,12 +1143,20 @@ inline void Player::Archive(Archiver& arc) arc.ArchiveInteger(&m_iNumLeftArmShots); arc.ArchiveInteger(&m_iNumRightArmShots); + // Added in 2.30 + //==== + ArchiveEnum(m_jailstate, jailstate_t); + arc.ArchiveString(&m_sDmPrimary); + arc.ArchiveBool(&m_bIsInJail); + //==== + arc.ArchiveFloat(&m_fLastDeltaTime); - // make sure we have the state machine loaded up - if (arc.Loading()) { - LoadStateTable(); - } + // Added in 2.0 + //==== + arc.ArchiveFloat(&m_fLastSprintTime); + arc.ArchiveBool(&m_bHasJumped); + //==== if (arc.Saving()) { if (currentState_Legs) { @@ -1138,6 +1173,13 @@ inline void Player::Archive(Archiver& arc) } arc.ArchiveString(&tempStr); } else { + statemap_Legs = GetStatemap( + str(g_statefile->string) + "_Legs.st", (Condition *)m_conditions, &legs_conditionals, false + ); + statemap_Torso = GetStatemap( + str(g_statefile->string) + "_Torso.st", (Condition *)m_conditions, &torso_conditionals, false + ); + arc.ArchiveString(&tempStr); if (tempStr != "NULL") { currentState_Legs = statemap_Legs->FindState(tempStr); @@ -1150,21 +1192,52 @@ inline void Player::Archive(Archiver& arc) } else { currentState_Torso = NULL; } + + for (int i = 1; i <= legs_conditionals.NumObjects(); i++) { + Conditional *c = legs_conditionals.ObjectAt(i); + + if (Q_stricmp(c->getName(), "PAIN") && !c->parmList.NumObjects()) { + m_pLegsPainCond = c; + break; + } + } + + for (int i = 1; i <= torso_conditionals.NumObjects(); i++) { + Conditional *c = torso_conditionals.ObjectAt(i); + + if (Q_stricmp(c->getName(), "PAIN") && !c->parmList.NumObjects()) { + m_pTorsoPainCond = c; + break; + } + } } if (arc.Loading()) { UpdateWeapons(); + SetViewAngles(v_angle); + + // Added in OPM + InitModelFps(); + } + + // + // Added in OPM + // + arc.ArchiveBool(&m_bFrozen); + arc.ArchiveBool(&animDoneVM); + arc.ArchiveFloat(&m_fVMAtime); + + for (int i = 0; i < MAX_SPEED_MULTIPLIERS; i++) { + arc.ArchiveFloat(&speed_multiplier[i]); } } inline Camera *Player::CurrentCamera(void) - { return camera; } inline void Player::CameraCut(void) - { // // toggle the camera cut bit @@ -1174,7 +1247,6 @@ inline void Player::CameraCut(void) } inline void Player::CameraCut(Camera *ent) - { if (ent == camera) { // if the camera we are currently looking through cut, than toggle the cut bits diff --git a/code/fgame/player_animation.cpp b/code/fgame/player_animation.cpp index 7b593d9a..2f46c15e 100644 --- a/code/fgame/player_animation.cpp +++ b/code/fgame/player_animation.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "player.h" #include "g_phys.h" +#include "portableturret.h" extern Event EV_Player_AnimLoop_Torso; extern Event EV_Player_AnimLoop_Legs; @@ -33,7 +34,7 @@ void Player::EndAnim_Legs(Event *ev) { animdone_Legs = true; - if ((animFlags[m_iPartSlot[legs]] & ANIM_LOOP)) { + if (IsRepeatType(m_iPartSlot[legs])) { SetAnimDoneEvent(EV_Player_AnimLoop_Legs, m_iPartSlot[legs]); } @@ -44,14 +45,14 @@ void Player::EndAnim_Torso(Event *ev) { animdone_Torso = true; - if ((animFlags[m_iPartSlot[torso]] & ANIM_LOOP)) { + if (IsRepeatType(m_iPartSlot[torso])) { SetAnimDoneEvent(EV_Player_AnimLoop_Torso, m_iPartSlot[torso]); } EvaluateState(); } -void Player::EndAnim_Pain(Event* ev) +void Player::EndAnim_Pain(Event *ev) { animdone_Pain = true; } @@ -60,13 +61,17 @@ void Player::SetPartAnim(const char *anim, bodypart_t slot) { int animnum; - if (getMoveType() == MOVETYPE_NOCLIP && slot) { - StopPartAnimating(torso); - return; + if (getMoveType() == MOVETYPE_NOCLIP) { + if (slot) { + StopPartAnimating(torso); + return; + } + + anim = "idle"; } animnum = gi.Anim_NumForName(edict->tiki, anim); - if (animnum == CurrentAnim() && partAnim[slot] == anim) { + if (animnum == CurrentAnim(m_iPartSlot[slot]) && partAnim[slot] == anim) { return; } @@ -88,21 +93,19 @@ void Player::SetPartAnim(const char *anim, bodypart_t slot) if (m_fPartBlends[slot] < 0.5f) { SetAnimDoneEvent(NULL, m_iPartSlot[slot]); - float m_fCrossTime = gi.Anim_CrossTime(edict->tiki, animnum); - - partBlendMult[slot] = m_fCrossTime; - if (m_fCrossTime <= 0.0f) { - partOldAnim[slot] = ""; - m_fPartBlends[slot] = 0.0f; - } else { + partBlendMult[slot] = gi.Anim_CrossTime(edict->tiki, animnum); + if (partBlendMult[slot] > 0.0f) { m_iPartSlot[slot] ^= 1; - partBlendMult[slot] = 1.0f / m_fCrossTime; + partBlendMult[slot] = 1.0f / partBlendMult[slot]; partOldAnim[slot] = partAnim[slot]; m_fPartBlends[slot] = 1.0f; + } else { + partOldAnim[slot] = ""; + m_fPartBlends[slot] = 0.0f; } } - if (slot) { + if (slot != legs) { animdone_Torso = false; } else { animdone_Legs = false; @@ -112,16 +115,16 @@ void Player::SetPartAnim(const char *anim, bodypart_t slot) partAnim[slot] = anim; - if (slot) { + if (slot != legs) { NewAnim(animnum, EV_Player_AnimLoop_Torso, m_iPartSlot[slot]); } else { NewAnim(animnum, EV_Player_AnimLoop_Legs, m_iPartSlot[legs]); } - SetTime(m_iPartSlot[slot]); + RestartAnimSlot(m_iPartSlot[slot]); } -static float m_fPartMult[2] = {0.2f, 0.2f}; +static float g_fPartBlendTime[2] = {0.2f, 0.2f}; void Player::StopPartAnimating(bodypart_t part) { @@ -138,11 +141,11 @@ void Player::StopPartAnimating(bodypart_t part) } partAnim[part] = ""; - partBlendMult[part] = 1.0f / m_fPartMult[part]; + partBlendMult[part] = 1.0f / g_fPartBlendTime[part]; StopAnimating(m_iPartSlot[part]); - if (part) { + if (part != legs) { animdone_Torso = false; } else { animdone_Legs = false; @@ -157,7 +160,7 @@ void Player::PausePartAnim(bodypart_t part) int Player::CurrentPartAnim(bodypart_t part) const { - if (!*partAnim[part]) { + if (partAnim[part] == "") { return -1; } @@ -166,44 +169,213 @@ int Player::CurrentPartAnim(bodypart_t part) const void Player::AdjustAnimBlends(void) { - int iPartSlot; - int iOldPartSlot; - float fWeightTotal; + int iPartSlot; + int iOldPartSlot; + float fWeightTotal; + qboolean playTurretAnim = false; + + if (movetype == MOVETYPE_PORTABLE_TURRET) { + PortableTurret *turret = static_cast(m_pTurret.Pointer()); + + if (turret->IsReloading()) { + if (partAnim[legs] != "mg42tripod_reload") { + SetPartAnim("mg42tripod_reload", legs); + StopAnimating(m_iPartSlot[torso]); + StopAnimating(m_iPartSlot[torso] ^ 1); + partAnim[torso] = ""; + } + } else if (turret->IsSettingUp()) { + if (partAnim[legs] != "mg42tripod_setup") { + SetPartAnim("mg42tripod_setup", legs); + StopAnimating(m_iPartSlot[torso]); + StopAnimating(m_iPartSlot[torso] ^ 1); + partAnim[torso] = ""; + } + } else if (turret->IsPackingUp()) { + if (partAnim[legs] != "mg42tripod_packup") { + SetPartAnim("mg42tripod_packup", legs); + StopAnimating(m_iPartSlot[torso]); + StopAnimating(m_iPartSlot[torso] ^ 1); + partAnim[torso] = ""; + } + } else { + playTurretAnim = true; + } + } + + if (playTurretAnim) { + PortableTurret *turret = static_cast(m_pTurret.Pointer()); + + if (partAnim[legs] != "mg42tripod_aim") { + StopPartAnimating(legs); + } + + if (partAnim[torso] != "mg42tripod_aim") { + StopPartAnimating(torso); + } + + partAnim[legs] = "mg42tripod_aim"; + partAnim[torso] = "mg42tripod_aim"; + + float pitch, yaw; + float legsPitchAngle, torsoPitchAngle; + float pitchAlpha, yawAlpha; + float legsYawAngle, torsoYawAngle; + float weight; + int animNum; + str vertLegsStr, vertTorsoStr; + str horzLegsStr, horzTorsoStr; + str anim; + + pitch = AngleSubtract(turret->GetGroundPitch(), turret->angles[0]); + yaw = AngleSubtract(turret->GetStartYaw(), turret->angles[1]); + + if (pitch >= 0) { + legsPitchAngle = 0.0; + torsoPitchAngle = 15.0; + vertLegsStr = "_straight"; + vertTorsoStr = "_up15"; + } else { + legsPitchAngle = -15.0; + torsoPitchAngle = 0.0; + vertLegsStr = "_down15"; + vertTorsoStr = "_straight"; + } + + pitchAlpha = (pitch - legsPitchAngle) / (torsoPitchAngle - legsPitchAngle); + pitchAlpha = Q_clamp_float(pitchAlpha, 0, 1); + + if (yaw < -20) { + legsYawAngle = -40.0; + torsoYawAngle = -20.0; + horzLegsStr = "_left40"; + horzTorsoStr = "_left20"; + } else if (yaw < 0) { + legsYawAngle = -20.0; + torsoYawAngle = 0.0; + horzLegsStr = "_left20"; + horzTorsoStr = "_straight"; + } else if (yaw <= 20) { + legsYawAngle = 0.0; + torsoYawAngle = 20.0; + horzLegsStr = "_straight"; + horzTorsoStr = "_right20"; + } else { + legsYawAngle = 20.0; + torsoYawAngle = 40.0; + horzLegsStr = "_right20"; + horzTorsoStr = "_right40"; + } + + yawAlpha = (yaw - legsYawAngle) / (torsoYawAngle - legsYawAngle); + yawAlpha = Q_clamp_float(yawAlpha, 0, 1); + + anim = "mg42tripod_aim" + horzLegsStr + vertLegsStr; + weight = (1 - pitchAlpha) * (1 - yawAlpha); + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + if (animNum == -1) { + gi.DPrintf("^~^~^ Warning: Can't find player animation '%s'.\n", anim.c_str()); + anim = "mg42tripod_aim_straight_straight"; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + } + + if (animNum == CurrentAnim(0)) { + SetWeight(0, weight); + } else { + NewAnim(animNum, 0, weight); + } + + anim = "mg42tripod_aim" + horzLegsStr + vertTorsoStr; + weight = (1.0 - yawAlpha) * pitchAlpha; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + if (animNum == -1) { + gi.DPrintf("^~^~^ Warning: Can't find player animation '%s'.\n", anim.c_str()); + anim = "mg42tripod_aim_straight_straight"; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + } + + if (animNum == CurrentAnim(1)) { + SetWeight(1, weight); + } else { + NewAnim(animNum, 1, weight); + } + + anim = "mg42tripod_aim" + horzTorsoStr + vertTorsoStr; + weight = pitchAlpha * yawAlpha; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + if (animNum == -1) { + gi.DPrintf("^~^~^ Warning: Can't find player animation '%s'.\n", anim.c_str()); + anim = "mg42tripod_aim_straight_straight"; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + } + + if (animNum == CurrentAnim(2)) { + SetWeight(2, weight); + } else { + NewAnim(animNum, 2, weight); + } + + anim = "mg42tripod_aim" + horzTorsoStr + vertTorsoStr; + weight = (1.0 - pitchAlpha) * yawAlpha; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + if (animNum == -1) { + gi.DPrintf("^~^~^ Warning: Can't find player animation '%s'.\n", anim.c_str()); + anim = "mg42tripod_aim_straight_straight"; + animNum = gi.Anim_NumForName(edict->tiki, anim.c_str()); + } + + if (animNum == CurrentAnim(3)) { + SetWeight(3, weight); + } else { + NewAnim(animNum, 3, weight); + } + } + + if (deadflag == DEAD_DEAD) { + if (m_fPainBlend) { + StopAnimating(ANIMSLOT_PAIN); + SetWeight(ANIMSLOT_PAIN, 0); + m_fPainBlend = 0; + animdone_Pain = false; + } + return; + } iPartSlot = m_iPartSlot[legs]; iOldPartSlot = m_iPartSlot[legs] ^ 1; if (m_fPartBlends[legs] <= 0.0f) { - if (partOldAnim[legs] == "") { - goto __blend_torso; + if (partOldAnim[legs] != "") { + StopAnimating(iOldPartSlot); } - StopAnimating(iOldPartSlot); + if (partAnim[legs] == "") { + SetWeight(iPartSlot, 0.0); + } else { + SetWeight(iPartSlot, 1.0); + } } else { - m_fPartBlends[legs] = m_fPartBlends[legs] - level.frametime * partBlendMult[legs]; + m_fPartBlends[legs] -= level.frametime * partBlendMult[legs]; if (m_fPartBlends[legs] >= 0.01f) { if (partOldAnim[legs] != "") { - edict->s.frameInfo[iOldPartSlot].weight = m_fPartBlends[legs]; + SetWeight(iOldPartSlot, m_fPartBlends[legs]); } if (partAnim[legs] != "") { - edict->s.frameInfo[iPartSlot].weight = 1.0f - m_fPartBlends[legs]; + SetWeight(iPartSlot, 1.0f - m_fPartBlends[legs]); } + } else { + m_fPartBlends[legs] = 0.0f; + StopAnimating(iOldPartSlot); + partOldAnim[legs] = ""; - goto __blend_torso; + if (partAnim[legs] == "") { + SetWeight(iPartSlot, 0.0); + } else { + SetWeight(iPartSlot, 1.0); + } } - - m_fPartBlends[legs] = 0.0f; - StopAnimating(iOldPartSlot); - partOldAnim[legs] = ""; } - if (partAnim[legs] != "") { - edict->s.frameInfo[iPartSlot].weight = 1.0f; - } else { - edict->s.frameInfo[iPartSlot].weight = 0.0f; - } - -__blend_torso: iPartSlot = m_iPartSlot[torso]; iOldPartSlot = m_iPartSlot[torso] ^ 1; @@ -212,27 +384,74 @@ __blend_torso: StopAnimating(iOldPartSlot); partOldAnim[torso] = ""; } + + if (partAnim[torso] == "") { + SetWeight(iPartSlot, 0.0); + edict->s.actionWeight = 0.0; + } else { + SetWeight(iPartSlot, 1.0); + edict->s.actionWeight = 1.0; + } } else { m_fPartBlends[torso] = m_fPartBlends[torso] - level.frametime * partBlendMult[torso]; if (m_fPartBlends[torso] >= 0.01f) { fWeightTotal = 0.0f; if (partOldAnim[torso] != "") { - edict->s.frameInfo[iOldPartSlot].weight = m_fPartBlends[torso]; + SetWeight(iOldPartSlot, m_fPartBlends[torso]); fWeightTotal += m_fPartBlends[torso]; } if (partAnim[torso] != "") { - edict->s.frameInfo[iPartSlot].weight = 1.0f - m_fPartBlends[torso]; - fWeightTotal += 1.0f - m_fPartBlends[torso]; + SetWeight(iPartSlot, 1.0 - m_fPartBlends[torso]); + fWeightTotal += 1.0 - m_fPartBlends[torso]; } edict->s.actionWeight = fWeightTotal; } else { m_fPartBlends[torso] = 0.0f; StopAnimating(iOldPartSlot); - partOldAnim[torso] = ""; - edict->s.frameInfo[iPartSlot].weight = partAnim[torso] != "" ? 1.0f : 0.0f; - edict->s.actionWeight = partAnim[torso] != "" ? 1.0f : 0.0f; + partOldAnim[torso] = ""; + + if (partAnim[torso] == "") { + SetWeight(iPartSlot, 0.0); + edict->s.actionWeight = 0.0; + } else { + SetWeight(iPartSlot, 1.0); + edict->s.actionWeight = 1.0; + } + } + } + + if (m_fPainBlend) { + if (m_sPainAnim == "") { + StopAnimating(ANIMSLOT_PAIN); + SetWeight(ANIMSLOT_PAIN, 0); + m_fPainBlend = 0; + animdone_Pain = false; + } else if (animdone_Pain) { + m_fPainBlend -= level.frametime * (10.0 / 3.0); + if (m_fPainBlend < 0.01f) { + StopAnimating(ANIMSLOT_PAIN); + SetWeight(ANIMSLOT_PAIN, 0); + m_fPainBlend = 0; + animdone_Pain = false; + } + } + + if (m_fPainBlend) { + int i; + float w; + + SetWeight(ANIMSLOT_PAIN, m_fPainBlend); + w = 1.0 - m_fPainBlend * 0.5; + + for (i = 0; i < ANIMSLOT_PAIN; i++) { + if (GetWeight(i)) { + SetWeight(i, GetWeight(i) * w); + } + } + + edict->s.actionWeight *= w; } } } @@ -269,7 +488,7 @@ void Player::PlayerAnimDelta(float *vDelta) // get the anim delta gi.Anim_DeltaOverTime(edict->tiki, animnum, fBackTime, fTime, vNewDelta); - VectorMA(vDelta, edict->s.frameInfo[m_iPartSlot[legs]].weight, vNewDelta, vDelta); + VectorMA(vDelta, GetWeight(m_iPartSlot[legs]), vNewDelta, vDelta); } animnum = -1; @@ -288,11 +507,34 @@ void Player::PlayerAnimDelta(float *vDelta) gi.Anim_DeltaOverTime(edict->tiki, animnum, fBackTime, fTime, vNewDelta); - VectorMA(vDelta, edict->s.frameInfo[m_iPartSlot[torso]].weight, vNewDelta, vDelta); + VectorMA(vDelta, GetWeight(m_iPartSlot[torso]), vNewDelta, vDelta); } } -void Player::EventTestAnim(Event* ev) +void Player::EventTestAnim(Event *ev) { - // FIXME: unimplemented + str name; + float weight; + int animNum; + + weight = ev->GetFloat(1); + if (weight <= 0) { + SetWeight(ANIMSLOT_TESTANIM, 0); + StopAnimating(ANIMSLOT_TESTANIM); + return; + } + + if (ev->NumArgs() > 1) { + name = ev->GetString(1); + animNum = gi.Anim_NumForName(edict->tiki, name.c_str()); + if (animNum == -1) { + gi.Printf("Couldn't find anim '%s'\n", name.c_str()); + return; + } + + NewAnim(animNum, ANIMSLOT_TESTANIM, weight); + RestartAnimSlot(ANIMSLOT_TESTANIM); + } + + SetWeight(ANIMSLOT_TESTANIM, weight); } diff --git a/code/fgame/player_combat.cpp b/code/fgame/player_combat.cpp index 5fa28e67..fecd7fda 100644 --- a/code/fgame/player_combat.cpp +++ b/code/fgame/player_combat.cpp @@ -21,81 +21,63 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // player_combat.cpp: Player combat system and combat utility functions -// +// #include "player.h" #include "weaputils.h" -static Entity *FindClosestEntityInRadius - ( - Vector origin, - Vector forward, - float fov, - float maxdist - ) +static Entity *FindClosestEntityInRadius(Vector origin, Vector forward, float fov, float maxdist) +{ + float dist, dot; + float fovdot = cos(fov * 0.5 * M_PI / 180.0); + Entity *ent; + Entity *bestent = NULL; + int bestdist = 999999; + qboolean valid_entity; - { - float dist,dot; - float fovdot = cos( fov * 0.5 * M_PI / 180.0 ); - Entity *ent; - Entity *bestent=NULL; - int bestdist = 999999; - qboolean valid_entity; + // Find closest enemy in radius + ent = findradius(NULL, origin, maxdist); - // Find closest enemy in radius - ent = findradius( NULL, origin, maxdist ); + while (ent) { + valid_entity = false; - while( ent ) - { - valid_entity = false; + if (ent->flags & FL_AUTOAIM) { + valid_entity = true; + } - if( ent->flags & FL_AUTOAIM ) - { - valid_entity = true; - } + if (valid_entity) { + // Check to see if the enemy is closest to us + Vector delta = (ent->centroid) - origin; - if ( valid_entity ) - { - // Check to see if the enemy is closest to us - Vector delta = ( ent->centroid ) - origin; + dist = delta.length(); - dist = delta.length(); + if (dist < bestdist) { + delta.normalize(); - if ( dist < bestdist ) - { - delta.normalize(); + // It's close, now check to see if it's in our FOV. + dot = DotProduct(forward, delta); - // It's close, now check to see if it's in our FOV. - dot = DotProduct( forward, delta ); - - if ( dot > fovdot ) - { - trace_t trace; - // Do a trace to see if we can get to it - trace = G_Trace( origin, - vec_zero, - vec_zero, - ent->centroid, - NULL, - MASK_OPAQUE, - false, - "FindClosestEntityInRadius" ); - - if ( ( trace.ent && trace.entityNum == ent->entnum ) || ( trace.fraction == 1 ) ) - { - // dir = delta; - bestent = ent; - bestdist = dist; - } - } + if (dot > fovdot) { + trace_t trace; + // Do a trace to see if we can get to it + trace = G_Trace( + origin, vec_zero, vec_zero, ent->centroid, NULL, MASK_OPAQUE, false, "FindClosestEntityInRadius" + ); + + if ((trace.ent && trace.entityNum == ent->entnum) || (trace.fraction == 1)) { + // dir = delta; + bestent = ent; + bestdist = dist; + } + } } - } - ent = findradius( ent, origin, maxdist ); - } - return bestent; - } + } + ent = findradius(ent, origin, maxdist); + } + return bestent; +} -Vector Player::GunTarget(bool bNoCollision) +Vector Player::GunTarget(bool bNoCollision, const vec3_t position, const vec3_t forward) { Vector vForward; Vector vOut; @@ -127,12 +109,13 @@ Vector Player::GunTarget(bool bNoCollision) AngleVectors(m_vViewAng, vForward, NULL, NULL); vDest = m_vViewPos + vForward * 1024.0f; - trace = G_Trace(m_vViewPos, vec_zero, vec_zero, vDest, this, MASK_PLAYERSOLID, qfalse, "Player::GunTarget"); + trace = G_Trace(m_vViewPos, vec_zero, vec_zero, vDest, this, MASK_GUNTARGET, qfalse, "Player::GunTarget"); - if (!m_pTurret || (Vector(trace.endpos) - m_vViewPos).lengthSquared() >= 16384.0f) { - vOut = trace.endpos; - } else { - vOut = vDest; + vOut = trace.endpos; + if (m_pTurret) { + if ((Vector(trace.endpos) - m_vViewPos).lengthSquared() < 16384) { + vOut = vDest; + } } } @@ -180,7 +163,7 @@ void Player::EventCorrectWeaponAttachments(Event *ev) iTagLeft = gi.Tag_NumForName(edict->tiki, "tag_weapon_left"); iNumChildren = numchildren; - for (int i = 0; i < iNumChildren; i++) { + for (int i = 0; i < MAX_MODEL_CHILDREN && iNumChildren; i++) { iChild = children[i]; if (iChild == ENTITYNUM_NONE) { @@ -193,18 +176,17 @@ void Player::EventCorrectWeaponAttachments(Event *ev) } if (pChild->edict->s.tag_num == iTagLeft || pChild->edict->s.tag_num == iTagRight) { - if (pChild->IsSubclassOfWeapon()) { - if (pChild->edict->s.tag_num == iTagLeft) { - iUseAngles = edict->s.attach_use_angles; - vOffset = edict->s.attach_offset; - - // reattach to the right tag - detach(); - attach(entnum, iTagRight, iUseAngles, vOffset); - } - } else { + if (!pChild->IsSubclassOfWeapon()) { // Remove entities like ammoclip pChild->PostEvent(EV_Remove, 0); + iNumChildren--; + } else if (pChild->edict->s.tag_num == iTagLeft) { + iUseAngles = pChild->edict->s.attach_use_angles; + vOffset = pChild->edict->s.attach_offset; + + // reattach to the right tag + pChild->detach(); + pChild->attach(entnum, iTagRight, iUseAngles, vOffset); } } } diff --git a/code/fgame/player_conditionals.cpp b/code/fgame/player_conditionals.cpp index b9b4cde8..ef2af238 100644 --- a/code/fgame/player_conditionals.cpp +++ b/code/fgame/player_conditionals.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -59,94 +59,86 @@ static Vector max4x4x8(4, 4, 8); qboolean Player::CondTrue(Conditional& condition) { - return true; + return true; } qboolean Player::CondChance(Conditional& condition) - { - float percent_chance; + float percent_chance; - percent_chance = atof(condition.getParm(1)); + percent_chance = atof(condition.getParm(1)); - return (G_Random() < percent_chance); + return (G_Random() < percent_chance); } qboolean Player::CondHealth(Conditional& condition) - { - return health < atoi(condition.getParm(1)); + return health < atoi(condition.getParm(1)); } qboolean Player::CondBlocked(Conditional& condition) { - int test_moveresult; + int test_moveresult; - test_moveresult = moveresult; + test_moveresult = moveresult; - if (flags & FL_IMMOBILE) { - test_moveresult = MOVERESULT_BLOCKED; - } + if (flags & FL_IMMOBILE) { + test_moveresult = MOVERESULT_BLOCKED; + } - if (condition.numParms()) { - return test_moveresult >= atoi(condition.getParm(1)); - } + if (condition.numParms()) { + return test_moveresult >= atoi(condition.getParm(1)); + } - return test_moveresult >= MOVERESULT_BLOCKED; + return test_moveresult >= MOVERESULT_BLOCKED; } qboolean Player::CondPain(Conditional& condition) - { - return (pain != 0 || knockdown != 0); + return pain != 0 && level.time > nextpaintime; } qboolean Player::CondOnGround(Conditional& condition) { - if (groundentity || client->ps.walking) { - falling = 0; - return qtrue; - } - else { - return qfalse; - } + if (groundentity || client->ps.walking) { + falling = 0; + return qtrue; + } else { + return qfalse; + } } qboolean Player::CondHasWeapon(Conditional& condition) - { - return WeaponsOut(); + return WeaponsOut(); } qboolean Player::CondNewWeapon(Conditional& condition) - { - Weapon* weapon; + Weapon *weapon; - weapon = GetNewActiveWeapon(); + weapon = GetNewActiveWeapon(); - if (weapon) { - return true; - } - else { - return false; - } + if (weapon) { + return true; + } else { + return false; + } } qboolean Player::CondImmediateSwitch(Conditional& condition) { - static cvar_t* g_immediateswitch = NULL; + static cvar_t *g_immediateswitch = NULL; - if (!g_immediateswitch) { - g_immediateswitch = gi.Cvar_Get("g_immediateswitch", "0", 0); - } + if (!g_immediateswitch) { + g_immediateswitch = gi.Cvar_Get("g_immediateswitch", "0", 0); + } - return (g_gametype->integer && g_immediateswitch->integer); + return (g_gametype->integer && g_immediateswitch->integer); } // Check to see if a weapon has been raised qboolean Player::CondUseWeapon(Conditional& condition) - { const char *weaponName; const char *parm; @@ -321,6 +313,7 @@ qboolean Player::CondWeaponClassReadyToFire(Conditional& condition) str weaponClass = "None"; weaponhand_t hand; qboolean ready; + Weapon *weapon; if (level.playerfrozen || m_bFrozen || (flags & FL_IMMOBILE)) { return false; @@ -336,7 +329,7 @@ qboolean Player::CondWeaponClassReadyToFire(Conditional& condition) return false; } - Weapon *weapon = GetActiveWeapon(hand); + weapon = GetActiveWeapon(hand); // Weapon there check if (!weapon) { @@ -348,6 +341,10 @@ qboolean Player::CondWeaponClassReadyToFire(Conditional& condition) if (!(G_WeaponClassNameToNum(weaponClass) & weapon->GetWeaponClass())) { return qfalse; } + + if (condition.numParms() > 2) { + mode = WeaponModeNameToNum(condition.getParm(3)); + } } // Ammo check @@ -357,38 +354,37 @@ qboolean Player::CondWeaponClassReadyToFire(Conditional& condition) qboolean Player::CondUsingVehicle(Conditional& condition) { - return (m_pVehicle != NULL); + return (m_pVehicle != NULL); } qboolean Player::CondVehicleType(Conditional& condition) { - str sType = condition.getParm(1); - if (m_pVehicle && m_pVehicle->IsSubclassOfVehicle()) { - return !str::cmp(sType, "vehicle"); - } - else { - return !str::cmp(sType, "none"); - } + str sType = condition.getParm(1); + if (m_pVehicle && m_pVehicle->IsSubclassOfVehicle()) { + return !str::cmp(sType, m_pVehicle->getName()); + } else { + return !str::cmp(sType, "none"); + } } qboolean Player::CondIsPassenger(Conditional& condition) { - return m_pVehicle && m_pVehicle->IsSubclassOfVehicle() && m_pVehicle->FindPassengerSlotByEntity(this); + return m_pVehicle && m_pVehicle->IsSubclassOfVehicle() && m_pVehicle->FindPassengerSlotByEntity(this); } qboolean Player::CondIsDriver(Conditional& condition) { - return m_pVehicle && m_pVehicle->IsSubclassOfVehicle() && m_pVehicle->FindDriverSlotByEntity(this); + return m_pVehicle && m_pVehicle->IsSubclassOfVehicle() && m_pVehicle->FindDriverSlotByEntity(this); } qboolean Player::CondUsingTurret(Conditional& condition) { - return (m_pTurret != NULL); + return (m_pTurret != NULL); } qboolean Player::CondIsEscaping(Conditional& condition) { - return m_jailstate == JAILSTATE_ESCAPE; + return m_jailstate == JAILSTATE_ESCAPE; } qboolean Player::CondAbleToDefuse(Conditional& condition) @@ -401,7 +397,7 @@ qboolean Player::CondAbleToDefuse(Conditional& condition) } Vector vForward, vRight, vUp; - AngleVectors(m_vViewPos, vForward, vRight, vUp); + AngleVectors(m_vViewAng, vForward, vRight, vUp); maxrange = weapon->GetMaxRange(); @@ -416,7 +412,7 @@ qboolean Player::CondCanPlaceLandmine(Conditional& condition) } Vector vPos, vForward, vRight, vUp, vBarrel; - weapon->GetMuzzlePosition(&vPos, &vForward, &vRight, &vUp, &vBarrel); + weapon->GetMuzzlePosition(vPos, vBarrel, vForward, vRight, vUp); return CanPlaceLandmine(vPos, this); } @@ -437,7 +433,90 @@ qboolean Player::CondNearLandmine(Conditional& condition) void Player::MeasureLandmineDistances() { - // FIXME: unimplemented + Weapon* weapon; + float previousMineDist; + float maxrange; + int i; + + if (m_fMineCheckTime == level.time) { + return; + } + m_fMineCheckTime = level.time; + previousMineDist = m_fMineDist; + m_fMineDist = 1000; + + weapon = GetActiveWeapon(WEAPON_MAIN); + if (!weapon) { + weapon = GetActiveWeapon(WEAPON_OFFHAND); + } + + maxrange = 40; + if (weapon) { + maxrange = weapon->GetMaxRange(); + } + + for (i = 0; i < globals.max_entities; i++) { + TriggerLandmine* landmine; + Entity* ent; + vec3_t forward; + Vector delta; + float radius; + + ent = G_GetEntity(i); + if (!ent) { + continue; + } + + if (!ent->isSubclassOf(TriggerLandmine)) { + continue; + } + + landmine = static_cast(ent); + // This could be from an allied player + if (landmine->IsImmune(this)) { + continue; + } + + AngleVectorsLeft(angles, forward, NULL, NULL); + delta = landmine->origin - origin; + radius = delta.length(); + + if (radius < maxrange) { + ent->PostEvent(EV_Show, level.frametime); + } + + if (radius > m_fMineDist) { + continue; + } + + if (radius >= 40) { + float dot; + + delta.normalize(); + + dot = DotProduct(delta, forward); + if (dot > 0 && radius / Square(dot) < m_fMineDist) { + m_fMineDist = radius / Square(dot); + } + } else if (radius < m_fMineDist) { + m_fMineDist = radius; + } + } + + m_fMineDist /= maxrange; + + if (m_fMineDist > 3) { + StopLoopSound(); + return; + } + + if (floorf(previousMineDist * 20) != floorf(m_fMineDist * 20)) { + float pitch; + + pitch = 2.f - log(m_fMineDist + 1.0); + + LoopSound("minedetector_on", -1, -1, -1, pitch); + } } qboolean Player::CondIsAssistingEscape(Conditional& condition) @@ -447,14 +526,13 @@ qboolean Player::CondIsAssistingEscape(Conditional& condition) qboolean Player::CondTurretType(Conditional& condition) { - str name = condition.getParm(1); + str name = condition.getParm(1); - if (m_pTurret) { - return m_pTurret->getName() == name; - } - else { - return name == "none"; - } + if (m_pTurret) { + return m_pTurret->getName() == name; + } else { + return name == "none"; + } } qboolean Player::CondWeaponReadyToFireNoSound(Conditional& condition) @@ -499,136 +577,127 @@ qboolean Player::CondWeaponReadyToFireNoSound(Conditional& condition) qboolean Player::CondPutAwayMain(Conditional& condition) { - Weapon* weapon = GetActiveWeapon(WEAPON_MAIN); + Weapon *weapon = GetActiveWeapon(WEAPON_MAIN); - return weapon && weapon->GetPutaway(); + return weapon && weapon->GetPutaway(); } // Check to see if any of the active weapons need to be put away qboolean Player::CondPutAwayOffHand(Conditional& condition) - { - Weapon* weapon = GetActiveWeapon(WEAPON_OFFHAND); + Weapon *weapon = GetActiveWeapon(WEAPON_OFFHAND); - return weapon && weapon->GetPutaway(); + return weapon && weapon->GetPutaway(); } // Checks to see if any weapon is active in the specified hand qboolean Player::CondAnyWeaponActive(Conditional& condition) - { - weaponhand_t hand; - Weapon* weap; + weaponhand_t hand; + Weapon *weap; - hand = WeaponHandNameToNum(condition.getParm(1)); + hand = WeaponHandNameToNum(condition.getParm(1)); - if (hand == WEAPON_ERROR) { - return false; - } + if (hand == WEAPON_ERROR) { + return false; + } - weap = GetActiveWeapon(hand); - return (weap != NULL); + weap = GetActiveWeapon(hand); + return (weap != NULL); } qboolean Player::CondAttackBlocked(Conditional& condition) - { - if (attack_blocked) { - attack_blocked = qfalse; - return true; - } - else { - return false; - } + if (attack_blocked) { + attack_blocked = qfalse; + return true; + } else { + return false; + } } qboolean Player::CondSemiAuto(Conditional& condition) { - firemode_t mode = FIRE_PRIMARY; - str handname; - weaponhand_t hand; + firemode_t mode = FIRE_PRIMARY; + str handname; + weaponhand_t hand; - handname = condition.getParm(1); + handname = condition.getParm(1); - hand = WeaponHandNameToNum(handname); + hand = WeaponHandNameToNum(handname); - if (hand != WEAPON_ERROR) { - return GetActiveWeapon(hand)->m_bSemiAuto; - } - else { - return qfalse; - } + if (hand != WEAPON_ERROR) { + return GetActiveWeapon(hand)->m_bSemiAuto; + } else { + return qfalse; + } } qboolean Player::CondMinChargeTime(Conditional& condition) { - const char* handname; - weaponhand_t hand; - Weapon* weap; + const char *handname; + weaponhand_t hand; + Weapon *weap; - handname = condition.getParm(1); - hand = WeaponHandNameToNum(handname); + handname = condition.getParm(1); + hand = WeaponHandNameToNum(handname); - if (hand != WEAPON_ERROR) { - weap = GetActiveWeapon(hand); - if (weap) { - float charge_time = weap->GetMinChargeTime(FIRE_PRIMARY); - if (charge_time) { - if (charge_start_time) { - return level.time - charge_start_time >= charge_time; - } - else { - return qfalse; - } - } - else { - return qtrue; - } - } - } + if (hand != WEAPON_ERROR) { + weap = GetActiveWeapon(hand); + // Fixed in 2.0. + // Make sure the active weapon is valid + if (weap) { + float charge_time = weap->GetMinChargeTime(FIRE_PRIMARY); + if (charge_time) { + if (charge_start_time) { + return level.time - charge_start_time >= charge_time; + } else { + return qfalse; + } + } else { + return qtrue; + } + } + } - return qfalse; + return qfalse; } qboolean Player::CondMaxChargeTime(Conditional& condition) { - const char* handname; - weaponhand_t hand; - Weapon* weap; + const char *handname; + weaponhand_t hand; + Weapon *weap; - handname = condition.getParm(1); - hand = WeaponHandNameToNum(handname); + handname = condition.getParm(1); + hand = WeaponHandNameToNum(handname); - if (hand != WEAPON_ERROR) { - weap = GetActiveWeapon(hand); - if (weap) { - float charge_time = weap->GetMaxChargeTime(FIRE_PRIMARY); - if (charge_time) { - if (charge_start_time) { - return level.time - charge_start_time >= charge_time; - } - else { - return qfalse; - } - } - else { - return qtrue; - } - } - } + if (hand != WEAPON_ERROR) { + weap = GetActiveWeapon(hand); + if (weap) { + float charge_time = weap->GetMaxChargeTime(FIRE_PRIMARY); + if (charge_time) { + if (charge_start_time) { + return level.time - charge_start_time >= charge_time; + } else { + return qfalse; + } + } else { + return qtrue; + } + } + } - return qfalse; + return qfalse; } qboolean Player::CondBlockDelay(Conditional& condition) - { float t = atof(condition.getParm(1)); return (level.time > (attack_blocked_time + t)); } qboolean Player::CondMuzzleClear(Conditional& condition) - { weaponhand_t hand; @@ -644,91 +713,87 @@ qboolean Player::CondMuzzleClear(Conditional& condition) // Checks to see if any weapon is active in the specified hand qboolean Player::CondWeaponHasAmmo(Conditional& condition) - { - weaponhand_t hand; - Weapon* weap; - firemode_t mode = FIRE_PRIMARY; + weaponhand_t hand; + Weapon *weap; + firemode_t mode = FIRE_PRIMARY; - hand = WeaponHandNameToNum(condition.getParm(1)); + hand = WeaponHandNameToNum(condition.getParm(1)); - if (condition.numParms() > 1) { - mode = WeaponModeNameToNum(condition.getParm(2)); - } + if (condition.numParms() > 1) { + mode = WeaponModeNameToNum(condition.getParm(2)); + } - if (hand == WEAPON_ERROR) { - return false; - } + if (hand == WEAPON_ERROR) { + return false; + } - weap = GetActiveWeapon(hand); + weap = GetActiveWeapon(hand); - if (!weap) { - return false; - } - else { - return (weap->HasAmmo(mode)); - } + if (!weap) { + return false; + } else { + return (weap->HasAmmo(mode)); + } } qboolean Player::CondWeaponHasAmmoInClip(Conditional& condition) { - weaponhand_t hand; - Weapon* weap; - firemode_t mode = FIRE_PRIMARY; + weaponhand_t hand; + Weapon *weap; + firemode_t mode = FIRE_PRIMARY; - hand = WeaponHandNameToNum(condition.getParm(1)); + hand = WeaponHandNameToNum(condition.getParm(1)); - if (condition.numParms() > 1) { - mode = WeaponModeNameToNum(condition.getParm(2)); - } + if (condition.numParms() > 1) { + mode = WeaponModeNameToNum(condition.getParm(2)); + } - if (hand == WEAPON_ERROR) { - return false; - } + if (hand == WEAPON_ERROR) { + return false; + } - weap = GetActiveWeapon(hand); + weap = GetActiveWeapon(hand); - if (!weap) { - return false; - } - else { - return (weap->HasAmmoInClip(mode)); - } + if (!weap) { + return false; + } else { + return (weap->HasAmmoInClip(mode)); + } } qboolean Player::CondReload(Conditional& condition) { - Weapon* weapon; - weaponhand_t hand = WEAPON_MAIN; + Weapon *weapon; + weaponhand_t hand = WEAPON_MAIN; - if (condition.numParms() > 0) { - hand = WeaponHandNameToNum(condition.getParm(1)); - if (hand == WEAPON_ERROR) { - return qfalse; - } - } + if (condition.numParms() > 0) { + hand = WeaponHandNameToNum(condition.getParm(1)); + if (hand == WEAPON_ERROR) { + return qfalse; + } + } - weapon = GetActiveWeapon(WEAPON_MAIN); + weapon = GetActiveWeapon(WEAPON_MAIN); - if (!weapon) { - return qfalse; - } + if (!weapon) { + return qfalse; + } - if (weapon->ShouldReload() && weapon->HasAmmo(FIRE_PRIMARY)) { - return qtrue; - } + if (weapon->ShouldReload() && weapon->HasAmmo(FIRE_PRIMARY)) { + return qtrue; + } - return qfalse; + return qfalse; } qboolean Player::CondWeaponsHolstered(Conditional& condition) { - if (holsteredWeapon) { - return qtrue; - } - else { - return qfalse; - } + if (holsteredWeapon) { + return qtrue; + } else { + return qfalse; + } } qboolean Player::CondWeaponIsItem(Conditional& condition) @@ -785,24 +850,36 @@ qboolean Player::CondStrafeLeft(Conditional& condition) } qboolean Player::CondStrafeRight(Conditional& condition) - { return last_ucmd.rightmove > 0; } qboolean Player::CondJump(Conditional& condition) - { + if (client->ps.pm_flags & PMF_NO_MOVE) { + return false; + } + return last_ucmd.upmove > 0; } qboolean Player::CondCrouch(Conditional& condition) { - return (last_ucmd.upmove) < 0; + // Added in 2.0 + // Don't crouch if the player is not moving + if (client->ps.pm_flags & PMF_NO_MOVE + && (g_target_game > target_game_e::TG_MOH || g_gametype->integer != GT_SINGLE_PLAYER)) { + // Added in 2.30 + // Allow ducking if specified + if (!m_pGlueMaster || !m_bGlueDuckable) { + return viewheight != DEFAULT_VIEWHEIGHT; + } + } + + return (last_ucmd.upmove) < 0; } qboolean Player::CondJumpFlip(Conditional& condition) - { return velocity.z < (sv_gravity->value * 0.5f); } @@ -819,45 +896,32 @@ qboolean Player::CondAnimDoneTorso(Conditional& condition) qboolean Player::CondAttackPrimary(Conditional& condition) { + Weapon *weapon; + if (level.playerfrozen || m_bFrozen || (flags & FL_IMMOBILE)) { return false; - } + } - if (g_gametype->integer != GT_SINGLE_PLAYER && !m_bAllowFighting) { - return false; - } - - if (last_ucmd.buttons & BUTTON_ATTACKLEFT) { - Weapon *weapon; - - last_attack_button = BUTTON_ATTACKLEFT; - - weapon = GetActiveWeapon(WEAPON_MAIN); - if (weapon) { - return true; - } - - // No ammo - return false; - } else { + if (g_gametype->integer != GT_SINGLE_PLAYER && !m_bAllowFighting) { return false; } + + if (!(last_ucmd.buttons & BUTTON_ATTACKLEFT)) { + return false; + } + + last_attack_button = BUTTON_ATTACKLEFT; + + weapon = GetActiveWeapon(WEAPON_MAIN); + if (weapon) { + return true; + } + + // No ammo + return false; } qboolean Player::CondAttackButtonPrimary(Conditional& condition) -{ - if (level.playerfrozen || m_bFrozen || (flags & FL_IMMOBILE)) { - return false; - } - - if (g_gametype->integer != GT_SINGLE_PLAYER && !m_bAllowFighting) { - return false; - } - - return (last_ucmd.buttons & BUTTON_ATTACKLEFT); -} - -qboolean Player::CondAttackSecondary(Conditional& condition) { if (level.playerfrozen || m_bFrozen || (flags & FL_IMMOBILE)) { return false; @@ -867,32 +931,45 @@ qboolean Player::CondAttackSecondary(Conditional& condition) return false; } - if (last_ucmd.buttons & BUTTON_ATTACKRIGHT) { - Weapon *weapon; + return (last_ucmd.buttons & BUTTON_ATTACKLEFT); +} - last_attack_button = BUTTON_ATTACKRIGHT; +qboolean Player::CondAttackSecondary(Conditional& condition) +{ + Weapon *weapon; - weapon = GetActiveWeapon(WEAPON_MAIN); - if (weapon) { - return true; - } - - // No ammo - return false; - } else { + if (level.playerfrozen || m_bFrozen || (flags & FL_IMMOBILE)) { return false; } + + if (g_gametype->integer != GT_SINGLE_PLAYER && !m_bAllowFighting) { + return false; + } + + if (!(last_ucmd.buttons & BUTTON_ATTACKRIGHT)) { + return false; + } + + last_attack_button = BUTTON_ATTACKRIGHT; + + weapon = GetActiveWeapon(WEAPON_MAIN); + if (weapon) { + return true; + } + + // No ammo + return false; } qboolean Player::CondAttackButtonSecondary(Conditional& condition) { if (level.playerfrozen || m_bFrozen || (flags & FL_IMMOBILE)) { return false; - } + } - if (g_gametype->integer != GT_SINGLE_PLAYER && !m_bAllowFighting) { - return false; - } + if (g_gametype->integer != GT_SINGLE_PLAYER && !m_bAllowFighting) { + return false; + } return (last_ucmd.buttons & BUTTON_ATTACKRIGHT); } @@ -941,13 +1018,11 @@ qboolean Player::CondRun(Conditional& condition) } qboolean Player::CondUse(Conditional& condition) - { return (last_ucmd.buttons & BUTTON_USE) != 0; } qboolean Player::CondCanTurn(Conditional& condition) - { float yaw; Vector oldang(v_angle); @@ -1048,7 +1123,6 @@ qboolean Player::CondHasVelocity(Conditional& condition) } qboolean Player::Cond22DegreeSlope(Conditional& condition) - { if (client->ps.walking && client->ps.groundPlane && (client->ps.groundTrace.plane.normal[2] < SLOPE_22_MAX) && (client->ps.groundTrace.plane.normal[2] >= SLOPE_22_MIN)) { @@ -1059,7 +1133,6 @@ qboolean Player::Cond22DegreeSlope(Conditional& condition) } qboolean Player::Cond45DegreeSlope(Conditional& condition) - { if (client->ps.walking && client->ps.groundPlane && (client->ps.groundTrace.plane.normal[2] < SLOPE_45_MAX) && (client->ps.groundTrace.plane.normal[2] >= SLOPE_45_MIN)) { @@ -1070,7 +1143,6 @@ qboolean Player::Cond45DegreeSlope(Conditional& condition) } qboolean Player::CondRightLegHigh(Conditional& condition) - { float groundyaw; float yawdelta; @@ -1084,7 +1156,6 @@ qboolean Player::CondRightLegHigh(Conditional& condition) } qboolean Player::CondLeftLegHigh(Conditional& condition) - { float groundyaw; float yawdelta; @@ -1098,7 +1169,6 @@ qboolean Player::CondLeftLegHigh(Conditional& condition) } qboolean Player::CondFacingUpSlope(Conditional& condition) - { float groundyaw; float yawdelta; @@ -1112,7 +1182,6 @@ qboolean Player::CondFacingUpSlope(Conditional& condition) } qboolean Player::CondFacingDownSlope(Conditional& condition) - { float groundyaw; float yawdelta; @@ -1126,20 +1195,18 @@ qboolean Player::CondFacingDownSlope(Conditional& condition) } qboolean Player::CondFalling(Conditional& condition) - { return falling; } qboolean Player::CondGroundEntity(Conditional& condition) - { return (groundentity != NULL); } qboolean Player::CondMediumImpact(Conditional& condition) { - return mediumimpact; + return mediumimpact; } qboolean Player::CondHardImpact(Conditional& condition) @@ -1149,18 +1216,16 @@ qboolean Player::CondHardImpact(Conditional& condition) qboolean Player::CondCanFall(Conditional& condition) { - return canfall; + return canfall; } qboolean Player::CondAtDoor(Conditional& condition) - { // Check if the player is at a door return (atobject && atobject->isSubclassOf(Door)); } qboolean Player::CondAtUseAnim(Conditional& condition) - { // Check if the player is at a useanim if (atobject && atobject->isSubclassOf(UseAnim)) { @@ -1171,7 +1236,6 @@ qboolean Player::CondAtUseAnim(Conditional& condition) } qboolean Player::CondTouchUseAnim(Conditional& condition) - { if (toucheduseanim) { return ((UseAnim *)(Entity *)toucheduseanim)->canBeUsed(this); @@ -1181,13 +1245,11 @@ qboolean Player::CondTouchUseAnim(Conditional& condition) } qboolean Player::CondUseAnimFinished(Conditional& condition) - { return (useanim_numloops <= 0); } qboolean Player::CondAtUseObject(Conditional& condition) - { // Check if the player is at a useanim if (atobject && atobject->isSubclassOf(UseObject)) { @@ -1198,7 +1260,6 @@ qboolean Player::CondAtUseObject(Conditional& condition) } qboolean Player::CondLoopUseObject(Conditional& condition) - { // Check if the player is at a useanim if (useitem_in_use && useitem_in_use->isSubclassOf(UseObject)) { @@ -1209,13 +1270,11 @@ qboolean Player::CondLoopUseObject(Conditional& condition) } qboolean Player::CondDead(Conditional& condition) - { return (deadflag); } qboolean Player::CondKnockDown(Conditional& condition) - { if (knockdown) { knockdown = false; @@ -1300,7 +1359,6 @@ qboolean Player::CondPainLocation(Conditional& condition) } qboolean Player::CondPainThreshold(Conditional& condition) - { float threshold = atof(condition.getParm(1)); @@ -1313,7 +1371,6 @@ qboolean Player::CondPainThreshold(Conditional& condition) } qboolean Player::CondLegsState(Conditional& condition) - { if (currentState_Legs) { str current = currentState_Legs->getName(); @@ -1328,7 +1385,6 @@ qboolean Player::CondLegsState(Conditional& condition) } qboolean Player::CondTorsoState(Conditional& condition) - { if (currentState_Torso) { str current = currentState_Torso->getName(); @@ -1343,7 +1399,6 @@ qboolean Player::CondTorsoState(Conditional& condition) } qboolean Player::CondStateName(Conditional& condition) - { str part = condition.getParm(1); str statename = condition.getParm(2); @@ -1358,7 +1413,6 @@ qboolean Player::CondStateName(Conditional& condition) } qboolean Player::CondPush(Conditional& condition) - { // Check if the player is at a pushobject if (atobject && atobject->isSubclassOf(PushObject) && (atobject_dist < (PUSH_OBJECT_DISTANCE + 15.0f))) { @@ -1372,7 +1426,6 @@ qboolean Player::CondPush(Conditional& condition) } qboolean Player::CondPull(Conditional& condition) - { // Check if the player is at a pushobject if (atobject && atobject->isSubclassOf(PushObject) && (atobject_dist < (PUSH_OBJECT_DISTANCE + 15.0f))) { @@ -1385,8 +1438,6 @@ qboolean Player::CondPull(Conditional& condition) return qfalse; } -#define LADDER_HAND_HEIGHT (MAXS_X - MINS_X) - qboolean Player::CondLadder(Conditional& condition) { trace_t trace; @@ -1421,7 +1472,7 @@ qboolean Player::CondTopOfLadder(Conditional& condition) qboolean Player::CondOnLadder(Conditional& condition) { - return m_pLadder != NULL; + return m_pLadder != NULL; } qboolean Player::CondCanClimbUpLadder(Conditional& condition) @@ -1464,7 +1515,7 @@ qboolean Player::CondCanGetOffLadderTop(Conditional& condition) angles.AngleVectorsLeft(&vForward); - vStart = origin - vForward * 12.0f; + vStart = origin - vForward * 12.0f * 1.005f; vStart[2] += maxs[2] - 8.0f; vEnd = vStart + vForward * 40.0f; @@ -1517,7 +1568,6 @@ qboolean Player::CondLookingUp(Conditional& condition) } qboolean Player::CondCanStand(Conditional& condition) - { Vector newmins(mins); Vector newmaxs(maxs); @@ -1536,15 +1586,15 @@ qboolean Player::CondCanStand(Conditional& condition) qboolean Player::CondSolidForward(Conditional& condition) { - // Trace out forward to see if there is a solid ahead - float dist = atof(condition.getParm(1)); - Vector end(centroid + yaw_forward * dist); - Vector vMins(mins.x, mins.y, -8); - Vector vMaxs(maxs.x, maxs.y, 8); + // Trace out forward to see if there is a solid ahead + float dist = atof(condition.getParm(1)); + Vector end(centroid + yaw_forward * dist); + Vector vMins(mins.x, mins.y, -8); + Vector vMaxs(maxs.x, maxs.y, 8); - trace_t trace = G_Trace(centroid, vMins, vMaxs, end, this, MASK_SOLID, true, "Player::CondSolidforward"); + trace_t trace = G_Trace(centroid, vMins, vMaxs, end, this, MASK_SOLID, true, "Player::CondSolidforward"); - return (trace.fraction < 0.7f); + return (trace.fraction < 0.7f); } qboolean Player::CondCheckHeight(Conditional& condition) @@ -1593,16 +1643,16 @@ qboolean Player::CondViewInWater(Conditional& condition) qboolean Player::CondDuckedViewInWater(Conditional& condition) { - Vector vPos = origin; - vPos[2] += 48.0f; + Vector vPos = origin; + vPos[2] += 48.0f; - return (gi.pointcontents(vPos, 0) & MASK_WATER) != 0; + return (gi.pointcontents(vPos, 0) & MASK_WATER) != 0; } qboolean Player::CondCheckMovementSpeed(Conditional& condition) { weaponhand_t hand; - Weapon* weapon; + Weapon *weapon; hand = WeaponHandNameToNum(condition.getParm(1)); if (hand == WEAPON_ERROR) { @@ -1863,7 +1913,7 @@ CLASS_DECLARATION(Class, Conditional, NULL) { {NULL, NULL} }; -Condition Player::Conditions[] = { +Condition Player::m_conditions[] = { {"default", &Player::CondTrue }, {"CHANCE", &Player::CondChance }, {"HEALTH", &Player::CondHealth }, @@ -1973,15 +2023,15 @@ Condition Player::Conditions[] = { {"ABLE_TO_DEFUSE", &Player::CondAbleToDefuse }, {"CAN_PLACE_LANDMINE", &Player::CondCanPlaceLandmine }, {"IS_USING_TURRET", &Player::CondUsingTurret }, - {"ATTACK_PRIMARY", - &Player::CondAttackPrimary }, // Checks to see if there is an active weapon as well as the button being pressed - {"ATTACK_SECONDARY", - &Player::CondAttackSecondary }, // Checks to see if there is an active weapon as well as the button being pressed + {"ATTACK_PRIMARY", &Player::CondAttackPrimary + }, // Checks to see if there is an active weapon as well as the button being pressed + {"ATTACK_SECONDARY", &Player::CondAttackSecondary + }, // Checks to see if there is an active weapon as well as the button being pressed {"ATTACK_PRIMARY_BUTTON", &Player::CondAttackButtonPrimary }, // Checks to see if the left attack button is pressed {"ATTACK_SECONDARY_BUTTON", &Player::CondAttackButtonSecondary }, {"CHECK_MOVEMENT_SPEED", &Player::CondCheckMovementSpeed }, - // Weapon conditions + // Weapon conditions {"ANIMDONE_VM", &Player::CondAnimDoneVM }, {"CLIENT_COMMAND", &Player::CondClientCommand }, {"IS_VM_ANIM", &Player::CondVMAnim }, diff --git a/code/fgame/player_util.cpp b/code/fgame/player_util.cpp index 2505b5d1..eda69045 100644 --- a/code/fgame/player_util.cpp +++ b/code/fgame/player_util.cpp @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "object.h" #include "g_spawn.h" #include "scriptexception.h" +#include extern Event EV_Entity_Start; @@ -93,8 +94,8 @@ void Player::WhatIs(Event *ev) const char *animname; animname = NULL; - if (gi.modeltiki(ent->model)) { - animname = gi.Anim_NameForNum(ent->edict->tiki, ent->edict->s.frameInfo[0].index & ANIM_MASK); + if (ent->edict->tiki) { + animname = AnimName(0); } if (!animname) { @@ -325,17 +326,18 @@ void Player::TestThread(Event *ev) void Player::SpawnEntity(Event *ev) { - Entity *ent; - str name; - ClassDef *cls; - str text; - Vector forward; - Vector up; - Vector delta; - Vector v; - int n; - int i; - Event *e; + SimpleEntity *ent; + str name; + ClassDef *cls; + str text; + Vector forward; + Vector up; + Vector delta; + Vector v; + int n; + int i; + Event *e; + bool bModelSet; if (ev->NumArgs() < 1) { ScriptError("Usage: spawn entityname [keyname] [value]..."); @@ -359,16 +361,12 @@ void Player::SpawnEntity(Event *ev) cls = &Entity::ClassInfo; } - if (!checkInheritance(&Entity::ClassInfo, cls)) { - ScriptError("%s is not a valid Entity", name.c_str()); + if (!checkInheritance(&SimpleEntity::ClassInfo, cls)) { + ScriptError("%s is not a valid SimpleEntity", name.c_str()); return; } - ent = (Entity *)cls->newInstance(); - - e = new Event(EV_Model); - e->AddString(name.c_str()); - ent->PostEvent(e, EV_PRIORITY_SPAWNARG); + ent = (SimpleEntity *)cls->newInstance(); angles.AngleVectors(&forward, NULL, &up); v = origin + (forward + up) * 40; @@ -386,21 +384,36 @@ void Player::SpawnEntity(Event *ev) e->AddVector(v); ent->PostEvent(e, EV_SPAWNARG); + bModelSet = false; + if (ev->NumArgs() > 2) { n = ev->NumArgs(); for (i = 2; i <= n; i += 2) { - e = new Event(ev->GetString(i)); + str name = ev->GetString(i); + float priority = EV_SPAWNARG; + + if (!str::icmp(name, "model")) { + bModelSet = true; + priority = EV_PRIORITY_SPAWNARG; + } + + e = new Event(name); e->AddToken(ev->GetString(i + 1)); - ent->PostEvent(e, EV_SPAWNARG); + ent->PostEvent(e, priority); } } - e = new Event(EV_SetAnim); - e->AddString("idle"); - ent->PostEvent(e, EV_SPAWNARG); + if (ent->IsSubclassOfEntity() && !bModelSet) { + e = new Event(EV_Model); + e->AddString(name.c_str()); + ent->PostEvent(e, EV_PRIORITY_SPAWNARG); + } ent->ProcessPendingEvents(); - ent->ProcessEvent(EV_Entity_Start); + + if (ent->IsSubclassOfEntity()) { + ent->ProcessEvent(EV_Entity_Start); + } } //==================== @@ -538,7 +551,7 @@ void Player::LogStats(Event *ev) // FIXME: FS gi.FS_Flush(logfile); - Event *ev1 = new Event(ev); + Event *ev1 = new Event(std::move(*ev)); PostEvent(ev1, 1); } @@ -595,20 +608,14 @@ void Player::EventJailEscape(Event* ev) void Player::EventFace(Event *ev) { - SetViewAngles(Vector(ev->GetFloat(1), ev->GetFloat(2), ev->GetFloat(3))); + if (ev->NumArgs() == 1) { + SetViewAngles(ev->GetVector(1)); + } else { + SetViewAngles(Vector(ev->GetFloat(1), ev->GetFloat(2), ev->GetFloat(3))); + } } void Player::EventCoord(Event *ev) { - const char *s = - va("location: %.2f %.2f %.2f\nangles: %.2f %.2f %.2f\n(use 'tele' or 'face' to set)\n", - origin[0], - origin[1], - origin[2], - v_angle[0], - v_angle[1], - v_angle[2]); - - HUDPrint(s); - gi.Printf(s); + gi.Printf("location: %.2f %.2f %.2f\nangles: %.2f %.2f %.2f\n(use 'tele' or 'face' to set)\n", origin[0], origin[1], origin[2], v_angle[0], v_angle[1], v_angle[2]); } diff --git a/code/fgame/playerbot.cpp b/code/fgame/playerbot.cpp index 8363a099..958e4ce4 100644 --- a/code/fgame/playerbot.cpp +++ b/code/fgame/playerbot.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -27,618 +27,250 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "consoleevent.h" #include "debuglines.h" #include "scriptexception.h" +#include "vehicleturret.h" +#include "weaputils.h" +#include "g_bot.h" // We assume that we have limited access to the server-side // and that most logic come from the playerstate_s structure cvar_t *bot_manualmove; -CLASS_DECLARATION( Player, PlayerBot, NULL ) -{ - { &EV_Killed, &PlayerBot::Killed }, - { &EV_GotKill, &PlayerBot::GotKill }, - { &EV_Player_StuffText, &PlayerBot::EventStuffText }, - { NULL, NULL } +CLASS_DECLARATION(Listener, BotController, NULL) { + {NULL, NULL} }; -PlayerBot::botfunc_t PlayerBot::botfuncs[ MAX_BOT_FUNCTIONS ]; +BotController::botfunc_t BotController::botfuncs[MAX_BOT_FUNCTIONS]; -PlayerBot::PlayerBot() +BotController::BotController() { - entflags |= EF_BOT; + if (LoadingSavegame) { + return; + } - if( LoadingSavegame ) - { - return; - } + m_botCmd.serverTime = 0; + m_botCmd.msec = 0; + m_botCmd.buttons = 0; + m_botCmd.angles[0] = ANGLE2SHORT(0); + m_botCmd.angles[1] = ANGLE2SHORT(0); + m_botCmd.angles[2] = ANGLE2SHORT(0); - m_Path.SetFallHeight( 96 ); - m_bPathing = false; - m_bTempAway = false; - m_bDeltaMove = true; + m_botCmd.forwardmove = 0; + m_botCmd.rightmove = 0; + m_botCmd.upmove = 0; - m_botCmd.serverTime = 0; - m_botCmd.msec = 0; - m_botCmd.buttons = 0; - m_botCmd.angles[ 0 ] = ANGLE2SHORT( 0 ); - m_botCmd.angles[ 1 ] = ANGLE2SHORT( 0 ); - m_botCmd.angles[ 2 ] = ANGLE2SHORT( 0 ); + m_botEyes.angles[0] = 0; + m_botEyes.angles[1] = 0; + m_botEyes.ofs[0] = 0; + m_botEyes.ofs[1] = 0; + m_botEyes.ofs[2] = DEFAULT_VIEWHEIGHT; - m_botCmd.forwardmove = 0; - m_botCmd.rightmove = 0; - m_botCmd.upmove = 0; + m_iCuriousTime = 0; + m_iAttackTime = 0; + m_iConfirmTime = 0; + m_iEnemyEyesTag = -1; - m_botEyes.angles[ 0 ] = 0; - m_botEyes.angles[ 1 ] = 0; - m_botEyes.ofs[ 0 ] = 0; - m_botEyes.ofs[ 1 ] = 0; - m_botEyes.ofs[ 2 ] = viewheight; + m_iNextTauntTime = 0; - m_vAngSpeed = vec_zero; - m_vTargetAng = vec_zero; - m_vCurrentAng = vec_zero; - m_iCheckPathTime = 0; - m_iTempAwayTime = 0; - m_fYawSpeedMult = 1.0f; - - m_iCuriousTime = 0; - m_iAttackTime = 0; - - m_StateFlags = 0; - m_RunLabel.TrySetScript("global/bot_run.scr"); + m_StateFlags = 0; + m_RunLabel.TrySetScript("global/bot_run.scr"); } -void PlayerBot::Init - ( - void - ) +BotController::~BotController() { - bot_manualmove = gi.Cvar_Get( "bot_manualmove", "0", 0 ); - - for( int i = 0; i < MAX_BOT_FUNCTIONS; i++ ) - { - botfuncs[ i ].BeginState = &PlayerBot::State_DefaultBegin; - botfuncs[ i ].EndState = &PlayerBot::State_DefaultEnd; - } - - InitState_Attack( &botfuncs[ 0 ] ); - InitState_Curious( &botfuncs[ 1 ] ); - InitState_Grenade( &botfuncs[ 2 ] ); - InitState_Idle( &botfuncs[ 3 ] ); - InitState_Weapon( &botfuncs[ 4 ] ); + if (controlledEnt) { + controlledEnt->delegate_gotKill.Remove(delegateHandle_gotKill); + controlledEnt->delegate_killed.Remove(delegateHandle_killed); + controlledEnt->delegate_stufftext.Remove(delegateHandle_stufftext); + } } -float AngleDifference( float ang1, float ang2 ) { - float diff; - - diff = ang1 - ang2; - if( ang1 > ang2 ) { - if( diff > 180.0 ) diff -= 360.0; - } - else { - if( diff < -180.0 ) diff += 360.0; - } - return diff; +BotMovement& BotController::GetMovement() +{ + return movement; } -void PlayerBot::TurnThink - ( - void - ) +void BotController::Init(void) { - float diff, factor, maxchange, anglespeed, desired_speed; - int i; + bot_manualmove = gi.Cvar_Get("bot_manualmove", "0", 0); - if( m_vTargetAng[ PITCH ] > 180 ) - m_vTargetAng[ PITCH ] -= 360; + for (int i = 0; i < MAX_BOT_FUNCTIONS; i++) { + botfuncs[i].BeginState = &BotController::State_DefaultBegin; + botfuncs[i].EndState = &BotController::State_DefaultEnd; + } - factor = 0.25f; - maxchange = 360; - - if( maxchange < 240 ) - maxchange = 240; - - maxchange *= level.frametime; - - for( i = 0; i < 2; i++ ) - { - //over reaction view model - m_vCurrentAng[ i ] = AngleMod( m_vCurrentAng[ i ] ); - m_vTargetAng[ i ] = AngleMod( m_vTargetAng[ i ] ); - diff = AngleDifference( m_vCurrentAng[ i ], m_vTargetAng[ i ] ); - desired_speed = diff * factor; - m_vAngSpeed[ i ] += ( m_vAngSpeed[ i ] - desired_speed ); - - if( m_vAngSpeed[ i ] > 180 ) - m_vAngSpeed[ i ] = maxchange; - - if( m_vAngSpeed[ i ] < -180 ) - m_vAngSpeed[ i ] = -maxchange; - - anglespeed = m_vAngSpeed[ i ]; - - if( anglespeed > maxchange ) - anglespeed = maxchange; - - if( anglespeed < -maxchange ) - anglespeed = -maxchange; - - m_vCurrentAng[ i ] += anglespeed; - m_vCurrentAng[ i ] = AngleMod( m_vCurrentAng[ i ] ); - - //demping - m_vAngSpeed[ i ] *= 0.45 * ( 1 - factor ); - } - - if( m_vCurrentAng[ PITCH ] > 180 ) - m_vCurrentAng[ PITCH ] -= 360; - - m_botEyes.angles[ 0 ] = m_vCurrentAng[ 0 ]; - m_botEyes.angles[ 1 ] = m_vCurrentAng[ 1 ]; - m_botCmd.angles[ 0 ] = ANGLE2SHORT( m_vCurrentAng[ 0 ] ) - client->ps.delta_angles[ 0 ]; - m_botCmd.angles[ 1 ] = ANGLE2SHORT( m_vCurrentAng[ 1 ] ) - client->ps.delta_angles[ 1 ]; - m_botCmd.angles[ 2 ] = ANGLE2SHORT( m_vCurrentAng[ 2 ] ) - client->ps.delta_angles[ 2 ]; + InitState_Attack(&botfuncs[0]); + InitState_Curious(&botfuncs[1]); + InitState_Grenade(&botfuncs[2]); + InitState_Idle(&botfuncs[3]); + //InitState_Weapon(&botfuncs[4]); } -void PlayerBot::CheckAttractiveNodes - ( - void - ) +void BotController::GetUsercmd(usercmd_t *ucmd) { - for( int i = m_attractList.NumObjects(); i > 0; i-- ) - { - nodeAttract_t *a = m_attractList.ObjectAt( i ); - - if( a->m_pNode == NULL || !a->m_pNode->CheckTeam( this ) || level.time > a->m_fRespawnTime ) - { - delete a; - m_attractList.RemoveObjectAt( i ); - } - } + *ucmd = m_botCmd; } -void PlayerBot::MoveThink - ( - void - ) +void BotController::GetEyeInfo(usereyes_t *eyeinfo) { - Vector vDir; - Vector vAngles; - Vector vWishDir; - - m_botCmd.forwardmove = 0; - m_botCmd.rightmove = 0; - - CheckAttractiveNodes(); - - if( !IsMoving() ) - { - return; - } - - if( m_bTempAway && level.inttime >= m_iTempAwayTime ) - { - m_bTempAway = false; - m_Path.FindPath( origin, m_vTargetPos, this, 0, NULL, 0 ); - } - - if( m_Path.CurrentNode() ) - { - m_Path.UpdatePos( origin, 8 ); - - if( m_bDeltaMove ) - m_vCurrentGoal = origin + m_Path.CurrentDelta(); - else - m_vCurrentGoal = m_Path.CurrentNode()->point; - - if( m_Path.Complete( origin ) ) - { - // Clear the path - m_Path.Clear(); - } - } - else if( !m_bTempAway ) - { - m_vCurrentGoal = origin; - } - - if( ai_debugpath->integer ) - { - G_DebugLine( centroid, m_vCurrentGoal + Vector( 0, 0, 36 ), 1, 1, 0, 1 ); - } - - // Check if we're blocked - if( level.inttime >= m_iCheckPathTime ) - { - Vector end; - - m_bDeltaMove = false; - - m_iCheckPathTime = level.inttime + 2000; - - if( m_Path.CurrentNode() && m_Path.CurrentNode() != m_Path.LastNode() ) - { - end = m_Path.NextNode()->point; - } - else - { - end = m_vCurrentGoal; - } - - if( GetMoveResult() >= MOVERESULT_BLOCKED || velocity.lengthSquared() <= 8 * 8 ) - { - gi.DPrintf( "Updating path for bot client %i\n", edict - g_entities ); - - m_bTempAway = true; - m_bDeltaMove = false; - m_iTempAwayTime = level.inttime + 750; - - // Try to backward a little - //vDir = end - origin; - //VectorNormalizeFast( vDir ); - //m_Path.FindPathAway( origin, origin + vDir * 16, vDir, this, 256, NULL, 0 ); - //m_Path.FindPathAway( origin, origin + m_vLastValidDir * 16, -m_vLastValidDir, this, 256, NULL, 0 ); - m_Path.Clear(); - m_vCurrentGoal = m_vLastValidGoal - m_vLastValidDir * 256; - return; - } - } - - if( ai_debugpath->integer ) - { - PathInfo *pos = m_Path.CurrentNode(); - - if( pos != NULL ) - { - while( pos != m_Path.LastNode() ) - { - Vector vStart = pos->point + Vector( 0, 0, 32 ); - - pos--; - - Vector vEnd = pos->point + Vector( 0, 0, 32 ); - - G_DebugLine( vStart, vEnd, 1, 0, 0, 1 ); - } - } - } - - if( ( m_vTargetPos - origin ).lengthSquared() <= 16 * 16 ) - { - ClearMove(); - } - - vDir = m_vCurrentGoal - centroid; - - // Rotate the dir - //vDir = m_Path.CurrentDelta(); - VectorNormalize( vDir ); - vAngles = vDir.toAngles() - angles; - vAngles.AngleVectorsLeft( &vWishDir ); - - m_vLastValidDir = vWishDir; - m_vLastValidGoal = m_vCurrentGoal; - - // Forward to the specified direction - float x = vWishDir.x * 255.0f; - float y = -vWishDir.y * 255.0f; - - m_botCmd.forwardmove = ( signed char )( x > 127 ? 127 : x < -127 ? -127 : x ); - m_botCmd.rightmove = ( signed char )( y > 127 ? 127 : y < -127 ? -127 : y ); - CheckJump(); - - Weapon *pWeap = GetActiveWeapon( WEAPON_MAIN ); - - if( pWeap && !pWeap->ShouldReload() ) - { - m_RunLabel.Execute(this); - } + *eyeinfo = m_botEyes; } -void PlayerBot::CheckJump - ( - void - ) +void BotController::UpdateBotStates(void) { - Vector start; - Vector end; - Vector dir; - trace_t trace; + if (bot_manualmove->integer) { + memset(&m_botCmd, 0, sizeof(usercmd_t)); + return; + } - if( !m_Path.CurrentNode() ) - return; + if (!controlledEnt->client->pers.dm_primary[0]) { + Event *event; - dir = m_Path.CurrentDelta(); - VectorNormalizeFast( dir ); + // + // Primary weapon + // + event = new Event(EV_Player_PrimaryDMWeapon); + event->AddString("auto"); - G_DebugLine( origin + Vector( 0, 0, STEPSIZE ), origin + Vector( 0, 0, STEPSIZE ) + dir * 32, 1, 0, 1, 1 ); - G_DebugLine( origin + Vector( 0, 0, 56 ), origin + Vector( 0, 0, 56 ) + dir * 32, 1, 0, 1, 1 ); + controlledEnt->ProcessEvent(event); + } - Vector vStart = origin + Vector( 0, 0, STEPSIZE ); - Vector vEnd = origin + Vector( 0, 0, STEPSIZE ) + dir * 4; + if (controlledEnt->GetTeam() == TEAM_NONE || controlledEnt->GetTeam() == TEAM_SPECTATOR) { + float time; - // Check if the bot needs to jump - trace = G_Trace( vStart, - mins, - maxs, - vEnd, - this, - MASK_PLAYERSOLID, - false, - "PlayerBot::CheckJump" ); + // Add some delay to avoid telefragging + time = controlledEnt->entnum / 20.0; - // No need to jump - if( trace.fraction >= 0.95f ) - { - m_botCmd.upmove = 0; - return; - } + if (controlledEnt->EventPending(EV_Player_AutoJoinDMTeam)) { + return; + } - start = origin + Vector( 0, 0, 56 ); - end = origin + Vector( 0, 0, 56 ) + dir * 4; + // + // Team + // + controlledEnt->PostEvent(EV_Player_AutoJoinDMTeam, time); + return; + } - // Check if the bot can jump - trace = G_Trace( - start, - mins, - maxs, - end, - this, - MASK_PLAYERSOLID, - true, - "PlayerBot::CheckJump" ); + if (controlledEnt->IsDead() || controlledEnt->IsSpectator()) { + // The bot should respawn + m_botCmd.buttons ^= BUTTON_ATTACKLEFT; + return; + } - // Make the bot climb walls - if( trace.fraction >= 0.95f ) - { - if( !m_botCmd.upmove ) - m_botCmd.upmove = 127; - else - m_botCmd.upmove = 0; - } - else - { - m_botCmd.upmove = 0; - } + m_botCmd.buttons |= BUTTON_RUN; + m_botCmd.serverTime = level.svsTime; + + m_botEyes.ofs[0] = 0; + m_botEyes.ofs[1] = 0; + m_botEyes.ofs[2] = controlledEnt->viewheight; + m_botEyes.angles[0] = 0; + m_botEyes.angles[1] = 0; + + CheckStates(); + + movement.MoveThink(m_botCmd); + rotation.TurnThink(m_botCmd, m_botEyes); + CheckUse(); + + CheckValidWeapon(); } -void PlayerBot::CheckEndPos - ( - void - ) +void BotController::CheckUse(void) { - Vector start; - Vector end; - trace_t trace; + Vector dir; + Vector start; + Vector end; + trace_t trace; - if( !m_Path.LastNode() ) - return; + controlledEnt->angles.AngleVectorsLeft(&dir); - start = m_Path.LastNode()->point; - end = m_vTargetPos; + start = controlledEnt->origin + Vector(0, 0, controlledEnt->viewheight); + end = controlledEnt->origin + Vector(0, 0, controlledEnt->viewheight) + dir * 32; - trace = G_Trace( start, - mins, - maxs, - end, - this, - MASK_TARGETPATH, - true, - "PlayerBot::CheckEndPos" ); + trace = G_Trace(start, vec_zero, vec_zero, end, controlledEnt, MASK_USABLE, false, "BotController::CheckUse"); - if( trace.fraction < 0.95f ) - m_vTargetPos = trace.endpos; + // It may be a door + if ((trace.allsolid || trace.startsolid || trace.fraction != 1.0f) && trace.ent) { + if (trace.ent->entity->IsSubclassOfDoor()) { + Door *door = static_cast(trace.ent->entity); + if (door->isOpen()) { + m_botCmd.buttons &= ~BUTTON_USE; + return; + } + } + + // + // Toggle the use button + // + m_botCmd.buttons ^= BUTTON_USE; + } else { + m_botCmd.buttons &= ~BUTTON_USE; + } } -void PlayerBot::CheckUse - ( - void - ) -{ - Vector dir; - Vector start; - Vector end; - trace_t trace; - - m_botCmd.buttons &= ~BUTTON_USE; - - angles.AngleVectorsLeft( &dir ); - - start = origin + Vector( 0, 0, viewheight ); - end = origin + Vector( 0, 0, viewheight ) + dir * 32; - - trace = G_Trace( - start, - vec_zero, - vec_zero, - end, - this, - MASK_USABLE, - false, - "PlayerBot::CheckUse" ); - - // It may be a door - if( ( trace.allsolid || trace.startsolid || trace.fraction != 1.0f ) && trace.entityNum ) - m_botCmd.buttons |= BUTTON_USE; +void BotController::CheckValidWeapon() { + Weapon* weapon = controlledEnt->GetActiveWeapon(WEAPON_MAIN); + if (!weapon) { + // If holstered, use the best weapon available + UseWeaponWithAmmo(); + } else if (!weapon->HasAmmo(FIRE_PRIMARY) && !controlledEnt->GetNewActiveWeapon()) { + // In case the current weapon has no ammo, use the best available weapon + UseWeaponWithAmmo(); + } } -void PlayerBot::GetUsercmd - ( - usercmd_t *ucmd - ) +void BotController::SendCommand(const char *text) { - *ucmd = m_botCmd; -} + char *buffer; + char *data; + size_t len; + ConsoleEvent ev; -void PlayerBot::GetEyeInfo - ( - usereyes_t *eyeinfo - ) -{ - *eyeinfo = m_botEyes; -} + len = strlen(text) + 1; -void PlayerBot::UpdateBotStates - ( - void - ) -{ - if( bot_manualmove->integer ) - { - memset( &m_botCmd, 0, sizeof( usercmd_t ) ); - return; - } + buffer = (char *)gi.Malloc(len); + data = buffer; + Q_strncpyz(data, text, len); - if( IsDead() ) - { - // The bot should respawn - m_botCmd.buttons ^= BUTTON_ATTACKLEFT; - return; - } + const char *com_token = COM_Parse(&data); - m_botCmd.buttons |= BUTTON_RUN; + if (!com_token) { + return; + } - m_botEyes.ofs[ 0 ] = 0; - m_botEyes.ofs[ 1 ] = 0; - m_botEyes.ofs[ 2 ] = viewheight; - m_botEyes.angles[ 0 ] = 0; - m_botEyes.angles[ 1 ] = 0; + controlledEnt->m_lastcommand = com_token; - SetTargetAngles( Vector( 0, 90, 0 ) ); + if (!Event::GetEvent(com_token)) { + return; + } - CheckStates(); + ev = ConsoleEvent(com_token); - MoveThink(); - TurnThink(); - CheckUse(); -} + if (!(ev.GetEventFlags(ev.eventnum) & EV_CONSOLE)) { + gi.Free(buffer); + return; + } -void PlayerBot::SendCommand - ( - const char *text - ) -{ - char *buffer; - char *data; - size_t len; - ConsoleEvent ev; + ev.SetConsoleEdict(controlledEnt->edict); - len = strlen( text ) + 1; + while (1) { + com_token = COM_Parse(&data); - buffer = ( char * )gi.Malloc( len ); - data = buffer; - Q_strncpyz( data, text, len ); + if (!com_token || !*com_token) { + break; + } - const char *com_token = COM_Parse( &data ); + ev.AddString(com_token); + } - if( !com_token ) - { - return; - } + gi.Free(buffer); - m_lastcommand = com_token; - - if( !Event::GetEvent( com_token ) ) - { - return; - } - - ev = ConsoleEvent( com_token ); - - if( !( ev.GetEventFlags( ev.eventnum ) & EV_CONSOLE ) ) - { - gi.Free( buffer ); - return; - } - - ev.SetConsoleEdict( edict ); - - while( 1 ) - { - com_token = COM_Parse( &data ); - - if( !com_token || !*com_token ) - { - break; - } - - ev.AddString( com_token ); - } - - gi.Free( buffer ); - - try - { - ProcessEvent( ev ); - } - catch( ScriptException& exc ) - { - gi.DPrintf( "*** Bot Command Exception *** %s\n", exc.string.c_str() ); - } -} - -void PlayerBot::setAngles - ( - Vector ang - ) -{ - Entity::setAngles( ang ); - SetTargetAngles( angles ); -} - -void PlayerBot::updateOrigin - ( - void - ) -{ - Entity::updateOrigin(); - - if( origin == client->ps.origin ) - { - // no change because of Pmove - return; - } - - m_pPrimaryAttract = NULL; - - if( m_Path.CurrentNode() ) - { - // recalculate paths because of a new origin - m_Path.ReFindPath( origin, this ); - } -} - -/* -==================== -SetTargetAngles - -Set the bot's angle -==================== -*/ -void PlayerBot::SetTargetAngles - ( - Vector vAngles - ) -{ - m_vTargetAng = vAngles; -} - -/* -==================== -AimAt - -Make the bot face to the specified direction -==================== -*/ -void PlayerBot::AimAt - ( - Vector vPos - ) -{ - Vector vDelta = vPos - centroid; - - VectorNormalize( vDelta ); - vectoangles( vDelta, m_vTargetAng ); + try { + controlledEnt->ProcessEvent(ev); + } catch (ScriptException& exc) { + gi.DPrintf("*** Bot Command Exception *** %s\n", exc.string.c_str()); + } } /* @@ -648,21 +280,22 @@ AimAtAimNode Make the bot face toward the current path ==================== */ -void PlayerBot::AimAtAimNode -( -void -) +void BotController::AimAtAimNode(void) { - if( m_Path.CurrentDelta() ) - { - AimAt( origin + m_Path.CurrentDelta() ); - } - else - { - AimAt( m_vCurrentGoal ); - } + Vector goal; - m_vTargetAng[ PITCH ] = 0; + if (!movement.IsMoving()) { + return; + } + + goal = movement.GetCurrentGoal(); + if (goal != controlledEnt->origin) { + rotation.AimAt(goal); + } + + Vector targetAngles = rotation.GetTargetAngles(); + targetAngles.x = 0; + rotation.SetTargetAngles(targetAngles); } /* @@ -672,295 +305,13 @@ CheckReload Make the bot reload if necessary ==================== */ -void PlayerBot::CheckReload -( -void -) +void BotController::CheckReload(void) { - Weapon *weap = GetActiveWeapon( WEAPON_MAIN ); + Weapon *weap = controlledEnt->GetActiveWeapon(WEAPON_MAIN); - if( weap && weap->CheckReload( FIRE_PRIMARY ) ) - { - SendCommand( "reload" ); - } -} - -/* -==================== -MoveTo - -Move to the specified position -==================== -*/ -void PlayerBot::MoveTo -( -Vector vPos, -float *vLeashHome, -float fLeashRadius -) -{ - m_bPathing = true; - m_vTargetPos = vPos; - m_Path.FindPath( origin, vPos, this, 0, vLeashHome, fLeashRadius * fLeashRadius ); - - if( !m_Path.CurrentNode() ) - { - m_bPathing = false; - return; - } - - CheckEndPos(); -} - -/* -==================== -MoveTo - -Move to the nearest attractive point with a minimum priority -Returns true if no attractive point was found -==================== -*/ -bool PlayerBot::MoveToBestAttractivePoint - ( - int iMinPriority - ) -{ - Container< AttractiveNode * > list; - AttractiveNode *bestNode; - float bestDistanceSquared; - int bestPriority; - - if( m_pPrimaryAttract ) - { - MoveTo( m_pPrimaryAttract->origin ); - - if( !IsMoving() ) - { - m_pPrimaryAttract = NULL; - } - else - { - if( MoveDone() ) - { - if( !m_fAttractTime ) - { - m_fAttractTime = level.time + m_pPrimaryAttract->m_fMaxStayTime; - } - if( level.time > m_fAttractTime ) - { - nodeAttract_t *a = new nodeAttract_t; - a->m_fRespawnTime = level.time + m_pPrimaryAttract->m_fRespawnTime; - a->m_pNode = m_pPrimaryAttract; - - m_pPrimaryAttract = NULL; - } - } - - return true; - } - } - - if( !attractiveNodes.NumObjects() ) - { - return false; - } - - bestNode = NULL; - bestDistanceSquared = 99999999.0f; - bestPriority = iMinPriority; - - for( int i = attractiveNodes.NumObjects(); i > 0; i-- ) - { - AttractiveNode *node = attractiveNodes.ObjectAt( i ); - float distSquared; - bool m_bRespawning = false; - - for( int j = m_attractList.NumObjects(); j > 0; j-- ) - { - AttractiveNode *node2 = m_attractList.ObjectAt( j )->m_pNode; - - if( node2 == node ) - { - m_bRespawning = true; - break; - } - } - - if( m_bRespawning ) - { - continue; - } - - if( node->m_iPriority < bestPriority ) - { - continue; - } - - if( !node->CheckTeam( this ) ) - { - continue; - } - - distSquared = VectorLengthSquared( origin - node->origin ); - - if( node->m_fMaxDistanceSquared >= 0 && distSquared > node->m_fMaxDistanceSquared ) - { - continue; - } - - if( !CanMoveTo( node->origin ) ) - { - continue; - } - - if( distSquared < bestDistanceSquared ) - { - bestDistanceSquared = distSquared; - bestNode = node; - bestPriority = node->m_iPriority; - } - } - - if( bestNode ) - { - m_pPrimaryAttract = bestNode; - m_fAttractTime = 0; - MoveTo( bestNode->origin ); - return true; - } - else - { - // No attractive point found - return false; - } -} - -/* -==================== -CanMoveTo - -Returns true if the bot has done moving -==================== -*/ -bool PlayerBot::CanMoveTo - ( - Vector vPos - ) -{ - return m_Path.DoesTheoreticPathExist( origin, vPos, NULL, 0, NULL, 0 ); -} - -/* -==================== -MoveDone - -Returns true if the bot has done moving -==================== -*/ -bool PlayerBot::MoveDone - ( - void - ) -{ - return m_Path.Complete( origin ); -} - -/* -==================== -IsMoving - -Returns true if the bot has a current path -==================== -*/ -bool PlayerBot::IsMoving - ( - void - ) -{ - return m_bPathing; -} - -/* -==================== -ClearMove - -Stop the bot from moving -==================== -*/ -void PlayerBot::ClearMove - ( - void - ) -{ - m_Path.Clear(); - m_bPathing = false; -} - -/* -==================== -MoveNear - -Move near the specified position within the radius -==================== -*/ -void PlayerBot::MoveNear - ( - Vector vNear, - float fRadius, - float *vLeashHome, - float fLeashRadius - ) -{ - m_bPathing = true; - m_Path.FindPathNear( origin, vNear, this, 0, fRadius * fRadius, vLeashHome, fLeashRadius * fLeashRadius ); - - if( !m_Path.CurrentNode() ) - { - m_bPathing = false; - return; - } - - m_vTargetPos = m_Path.LastNode()->point; -} - -/* -==================== -AvoidPath - -Avoid the specified position within the radius and start from a direction -==================== -*/ -void PlayerBot::AvoidPath - ( - Vector vAvoid, - float fAvoidRadius, - Vector vPreferredDir, - float *vLeashHome, - float fLeashRadius - ) -{ - Vector vDir; - - if( vPreferredDir == vec_zero ) - { - vDir = origin - vAvoid; - VectorNormalizeFast( vDir ); - } - else - { - vDir = vPreferredDir; - } - - m_bPathing = true; - m_Path.FindPathAway( origin, vAvoid, vDir, this, fAvoidRadius, vLeashHome, fLeashRadius * fLeashRadius ); - - if( !m_Path.CurrentNode() ) - { - m_bPathing = false; - return; - } - - m_vTargetPos = m_Path.LastNode()->point; + if (weap && weap->CheckReload(FIRE_PRIMARY)) { + SendCommand("reload"); + } } /* @@ -970,59 +321,70 @@ NoticeEvent Warn the bot of an event ==================== */ -void PlayerBot::NoticeEvent - ( - Vector vPos, - int iType, - Entity *pEnt, - float fDistanceSquared, - float fRadiusSquared - ) +void BotController::NoticeEvent(Vector vPos, int iType, Entity *pEnt, float fDistanceSquared, float fRadiusSquared) { - // Ignore teammates - if( pEnt->IsSubclassOfPlayer() ) - { - Player *p = ( Player * )pEnt; + Sentient *pSentOwner; + float fRangeFactor; - if( p->GetTeam() == GetTeam() ) - { - return; - } - } - else if( pEnt->IsSubclassOfWeapon() ) - { - Weapon *pWeap = ( Weapon * )pEnt; + fRangeFactor = 1.0 - (fDistanceSquared / fRadiusSquared); - if( pWeap->GetOwner() ) - { - Player *p = ( Player * )pWeap->GetOwner(); + if (fRangeFactor < random()) { + return; + } - if( p->IsSubclassOfPlayer() && p->GetTeam() == GetTeam() ) - { - return; - } - } - } + if (pEnt->IsSubclassOfSentient()) { + pSentOwner = static_cast(pEnt); + } else if (pEnt->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *pVTG = static_cast(pEnt); + pSentOwner = pVTG->GetSentientOwner(); + } else if (pEnt->IsSubclassOfItem()) { + Item *pItem = static_cast(pEnt); + pSentOwner = pItem->GetOwner(); + } else if (pEnt->IsSubclassOfProjectile()) { + Projectile *pProj = static_cast(pEnt); + pSentOwner = pProj->GetOwner(); + } else { + pSentOwner = NULL; + } - switch( iType ) - { - case AI_EVENT_MISC: - case AI_EVENT_MISC_LOUD: - break; - case AI_EVENT_WEAPON_FIRE: - case AI_EVENT_WEAPON_IMPACT: - case AI_EVENT_EXPLOSION: - case AI_EVENT_AMERICAN_VOICE: - case AI_EVENT_GERMAN_VOICE: - case AI_EVENT_AMERICAN_URGENT: - case AI_EVENT_GERMAN_URGENT: - case AI_EVENT_FOOTSTEP: - case AI_EVENT_GRENADE: - default: - m_iCuriousTime = level.inttime + 20000; - m_vLastCuriousPos = vPos; - break; - } + if (pSentOwner) { + if (pSentOwner == controlledEnt) { + // Ignore self + return; + } + + if ((pSentOwner->flags & FL_NOTARGET) || pSentOwner->getSolidType() == SOLID_NOT) { + return; + } + + // Ignore teammates + if (pSentOwner->IsSubclassOfPlayer()) { + Player *p = static_cast(pSentOwner); + + if (g_gametype->integer >= GT_TEAM && p->GetTeam() == controlledEnt->GetTeam()) { + return; + } + } + } + + switch (iType) { + case AI_EVENT_MISC: + case AI_EVENT_MISC_LOUD: + break; + case AI_EVENT_WEAPON_FIRE: + case AI_EVENT_WEAPON_IMPACT: + case AI_EVENT_EXPLOSION: + case AI_EVENT_AMERICAN_VOICE: + case AI_EVENT_GERMAN_VOICE: + case AI_EVENT_AMERICAN_URGENT: + case AI_EVENT_GERMAN_URGENT: + case AI_EVENT_FOOTSTEP: + case AI_EVENT_GRENADE: + default: + m_iCuriousTime = level.inttime + 20000; + m_vNewCuriousPos = vPos; + break; + } } /* @@ -1032,15 +394,14 @@ ClearEnemy Clear the bot's enemy ==================== */ -void PlayerBot::ClearEnemy - ( - void - ) +void BotController::ClearEnemy(void) { - m_iAttackTime = 0; - m_pEnemy = NULL; - m_vOldEnemyPos = vec_zero; - m_vLastEnemyPos = vec_zero; + m_iAttackTime = 0; + m_iConfirmTime = 0; + m_pEnemy = NULL; + m_iEnemyEyesTag = -1; + m_vOldEnemyPos = vec_zero; + m_vLastEnemyPos = vec_zero; } /* @@ -1057,66 +418,49 @@ ____________________ ==================== */ -void PlayerBot::CheckStates - ( - void - ) +void BotController::CheckStates(void) { - m_StateCount = 0; + m_StateCount = 0; - for( int i = 0; i < MAX_BOT_FUNCTIONS; i++ ) - { - botfunc_t *func = &botfuncs[ i ]; + for (int i = 0; i < MAX_BOT_FUNCTIONS; i++) { + botfunc_t *func = &botfuncs[i]; - if( func->CheckCondition ) - { - if( ( this->*func->CheckCondition )() ) - { - if( !( m_StateFlags & ( 1 << i ) ) ) - { - m_StateFlags |= 1 << i; + if (func->CheckCondition) { + if ((this->*func->CheckCondition)()) { + if (!(m_StateFlags & (1 << i))) { + m_StateFlags |= 1 << i; - if( func->BeginState ) - { - ( this->*func->BeginState )( ); - } - } + if (func->BeginState) { + (this->*func->BeginState)(); + } + } - if( func->ThinkState ) - { - m_StateCount++; - ( this->*func->ThinkState )( ); - } - } - else - { - if( ( m_StateFlags & ( 1 << i ) ) ) - { - m_StateFlags &= ~( 1 << i ); + if (func->ThinkState) { + m_StateCount++; + (this->*func->ThinkState)(); + } + } else { + if ((m_StateFlags & (1 << i))) { + m_StateFlags &= ~(1 << i); - if( func->EndState ) - { - ( this->*func->EndState )( ); - } - } - } - } - else - { - if( func->ThinkState ) - { - m_StateCount++; - ( this->*func->ThinkState )( ); - } - } - } + if (func->EndState) { + (this->*func->EndState)(); + } + } + } + } else { + if (func->ThinkState) { + m_StateCount++; + (this->*func->ThinkState)(); + } + } + } - assert( m_StateCount ); - if( !m_StateCount ) - { - gi.DPrintf( "*** WARNING *** %s was stuck with no states !!!", client->pers.netname ); - State_Reset(); - } + assert(m_StateCount); + if (!m_StateCount) { + gi.DPrintf("*** WARNING *** %s was stuck with no states !!!", controlledEnt->client->pers.netname); + State_Reset(); + } } /* @@ -1126,34 +470,23 @@ Default state ==================== */ -void PlayerBot::State_DefaultBegin - ( - void - ) +void BotController::State_DefaultBegin(void) { - ClearMove(); + movement.ClearMove(); } -void PlayerBot::State_DefaultEnd - ( - void - ) -{ +void BotController::State_DefaultEnd(void) {} -} - -void PlayerBot::State_Reset - ( - void - ) +void BotController::State_Reset(void) { - m_iCuriousTime = 0; - m_iAttackTime = 0; - m_vLastCuriousPos = vec_zero; - m_vOldEnemyPos = vec_zero; - m_vLastEnemyPos = vec_zero; - m_vLastDeathPos = vec_zero; - m_pEnemy = NULL; + m_iCuriousTime = 0; + m_iAttackTime = 0; + m_vLastCuriousPos = vec_zero; + m_vOldEnemyPos = vec_zero; + m_vLastEnemyPos = vec_zero; + m_vLastDeathPos = vec_zero; + m_pEnemy = NULL; + m_iEnemyEyesTag = -1; } /* @@ -1163,53 +496,45 @@ Idle state Make the bot move to random directions ==================== */ -void PlayerBot::InitState_Idle - ( - botfunc_t *func - ) +void BotController::InitState_Idle(botfunc_t *func) { - func->CheckCondition = &PlayerBot::CheckCondition_Idle; - func->ThinkState = &PlayerBot::State_Idle; + func->CheckCondition = &BotController::CheckCondition_Idle; + func->ThinkState = &BotController::State_Idle; } -bool PlayerBot::CheckCondition_Idle - ( - void - ) +bool BotController::CheckCondition_Idle(void) { - if( m_iCuriousTime ) - return false; + if (m_iCuriousTime) { + return false; + } - if( m_iAttackTime ) - return false; + if (m_iAttackTime) { + return false; + } - return true; + return true; } -void PlayerBot::State_Idle - ( - void - ) +void BotController::State_Idle(void) { - AimAtAimNode(); - CheckReload(); + AimAtAimNode(); + CheckReload(); - if( !MoveToBestAttractivePoint() && !IsMoving() ) - { - if( m_vLastDeathPos != vec_zero ) - { - MoveTo( m_vLastDeathPos ); + if (!movement.MoveToBestAttractivePoint() && !movement.IsMoving()) { + if (m_vLastDeathPos != vec_zero) { + movement.MoveTo(m_vLastDeathPos); - if( MoveDone() ) - { - m_vLastDeathPos = vec_zero; - } - } - else - { - AvoidPath( origin - Vector( orientation[ 0 ] ) * 128.0f, 1024 ); - } - } + if (movement.MoveDone()) { + m_vLastDeathPos = vec_zero; + } + } else { + Vector randomDir(G_CRandom(16), G_CRandom(16), G_CRandom(16)); + Vector preferredDir = Vector(controlledEnt->orientation[0]) * (rand() % 5 ? 1024 : -1024); + float radius = 512 + G_Random(2048); + + movement.AvoidPath(controlledEnt->origin + randomDir, radius, preferredDir); + } + } } /* @@ -1219,57 +544,43 @@ Curious state Forward to the last event position ==================== */ -void PlayerBot::InitState_Curious - ( - botfunc_t *func - ) +void BotController::InitState_Curious(botfunc_t *func) { - func->CheckCondition = &PlayerBot::CheckCondition_Curious; - func->ThinkState = &PlayerBot::State_Curious; + func->CheckCondition = &BotController::CheckCondition_Curious; + func->ThinkState = &BotController::State_Curious; } -bool PlayerBot::CheckCondition_Curious - ( - void - ) +bool BotController::CheckCondition_Curious(void) { - if( m_iAttackTime ) - { - m_iCuriousTime = 0; - return false; - } + if (m_iAttackTime) { + m_iCuriousTime = 0; + return false; + } - if( level.inttime > m_iCuriousTime ) - { - if( m_iCuriousTime ) - { - ClearMove(); - m_iCuriousTime = 0; - } + if (level.inttime > m_iCuriousTime) { + if (m_iCuriousTime) { + movement.ClearMove(); + m_iCuriousTime = 0; + } - return false; - } + return false; + } - return true; + return true; } -void PlayerBot::State_Curious - ( - void - ) +void BotController::State_Curious(void) { - //AimAt( m_vLastCuriousPos ); - AimAtAimNode(); + AimAtAimNode(); - if( !MoveToBestAttractivePoint( 3 ) && !IsMoving() ) - { - MoveTo( m_vLastCuriousPos ); - } + if (!movement.MoveToBestAttractivePoint(3) && (!movement.IsMoving() || m_vLastCuriousPos != m_vNewCuriousPos)) { + movement.MoveTo(m_vNewCuriousPos); + m_vLastCuriousPos = m_vNewCuriousPos; + } - if( MoveDone() ) - { - m_iCuriousTime = 0; - } + if (movement.MoveDone()) { + m_iCuriousTime = 0; + } } /* @@ -1279,217 +590,304 @@ Attack state Attack the enemy ==================== */ -void PlayerBot::InitState_Attack - ( - botfunc_t *func - ) +void BotController::InitState_Attack(botfunc_t *func) { - func->CheckCondition = &PlayerBot::CheckCondition_Attack; - func->EndState = &PlayerBot::State_EndAttack; - func->ThinkState = &PlayerBot::State_Attack; + func->CheckCondition = &BotController::CheckCondition_Attack; + func->EndState = &BotController::State_EndAttack; + func->ThinkState = &BotController::State_Attack; } static Vector bot_origin; -static int sentients_compare( const void *elem1, const void *elem2 ) +static int sentients_compare(const void *elem1, const void *elem2) { - Entity *e1, *e2; - float delta[ 3 ]; - float d1, d2; + Entity *e1, *e2; + float delta[3]; + float d1, d2; - e1 = *( Entity ** )elem1; - e2 = *( Entity ** )elem2; + e1 = *(Entity **)elem1; + e2 = *(Entity **)elem2; - VectorSubtract( bot_origin, e1->origin, delta ); - d1 = VectorLengthSquared( delta ); + VectorSubtract(bot_origin, e1->origin, delta); + d1 = VectorLengthSquared(delta); - VectorSubtract( bot_origin, e2->origin, delta ); - d2 = VectorLengthSquared( delta ); + VectorSubtract(bot_origin, e2->origin, delta); + d2 = VectorLengthSquared(delta); - if( d2 <= d1 ) - { - return d1 > d2; - } - else - { - return -1; - } + if (d2 <= d1) { + return d1 > d2; + } else { + return -1; + } } -bool PlayerBot::CheckCondition_Attack - ( - void - ) +bool BotController::IsValidEnemy(Sentient *sent) const { - Container< Sentient * > sents = SentientList; + if (sent == controlledEnt) { + return false; + } - bot_origin = origin; - sents.Sort( sentients_compare ); + if (sent->hidden() || (sent->flags & FL_NOTARGET)) { + // Ignore hidden / non-target enemies + return false; + } - for( int i = 1; i <= sents.NumObjects(); i++ ) - { - Sentient *sent = sents.ObjectAt( i ); - Player *player = ( Player * )sent; + if (sent->IsDead()) { + // Ignore dead enemies + return false; + } - if( sent == this ) - continue; + if (sent->getSolidType() == SOLID_NOT) { + // Ignore non-solid, like spectators + return false; + } - if( sent->hidden() ) - continue; + if (sent->IsSubclassOfPlayer()) { + Player *player = static_cast(sent); - if( sent->IsDead() ) - continue; + if (g_gametype->integer >= GT_TEAM && player->GetTeam() == controlledEnt->GetTeam()) { + return false; + } + } else { + if (sent->m_Team == controlledEnt->m_Team) { + return false; + } + } - if( sent->IsSubclassOfPlayer() ) - { - if( g_gametype->integer >= GT_TEAM && player->GetTeam() == GetTeam() ) - continue; - } - else - { - if( sent->m_Team == m_Team ) - continue; - } - - if( CanSee( sent, 80, world->m_fAIVisionDistance, false ) ) - { - m_pEnemy = sent; - m_iAttackTime = level.inttime + 10000; - return true; - } - } - - if( level.inttime > m_iAttackTime ) - { - if( m_iAttackTime ) - { - ClearMove(); - m_iAttackTime = 0; - } - - return false; - } - - return true; + return true; } -void PlayerBot::State_EndAttack - ( - void - ) +bool BotController::CheckCondition_Attack(void) { - m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ); + Container sents = SentientList; + float maxDistance = 0; + + bot_origin = controlledEnt->origin; + sents.Sort(sentients_compare); + + for (int i = 1; i <= sents.NumObjects(); i++) { + Sentient *sent = sents.ObjectAt(i); + + if (!IsValidEnemy(sent)) { + continue; + } + + maxDistance = Q_min(world->m_fAIVisionDistance, world->farplane_distance * 0.828); + + if (controlledEnt->CanSee(sent, 80, maxDistance, false)) { + if (m_pEnemy != sent) { + m_iEnemyEyesTag = -1; + } + + if (!m_pEnemy) { + // Slight reaction time + m_iConfirmTime = level.inttime + (200 + G_Random(200)); + m_iAttackTime = 0; + } + + m_pEnemy = sent; + m_vLastEnemyPos = m_pEnemy->origin; + if (level.inttime < m_iConfirmTime) { + return false; + } + } + + if (m_pEnemy && level.inttime >= m_iConfirmTime) { + m_iAttackTime = level.inttime + 1000; + return true; + } + } + + if (level.inttime > m_iAttackTime) { + if (m_iAttackTime) { + movement.ClearMove(); + m_iAttackTime = 0; + } + + return false; + } + + return true; } -void PlayerBot::State_Attack - ( - void - ) +void BotController::State_EndAttack(void) { - Player *p = ( Player * )m_pEnemy.Pointer(); - bool bMelee = false; - float fMinDistance = 128; - float fMinDistanceSquared = fMinDistance * fMinDistance; + m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT); + controlledEnt->ZoomOff(); +} - if( !m_pEnemy || m_pEnemy->IsDead() || ( !p->IsSubclassOfPlayer() && m_pEnemy->m_Team == m_Team ) || ( g_gametype->integer >= GT_TEAM && p->GetTeam() == GetTeam() ) ) - { - m_iAttackTime = 0; - return; - } +void BotController::State_Attack(void) +{ + bool bMelee = false; + bool bCanSee = false; + float fMinDistance = 128; + float fMinDistanceSquared = fMinDistance * fMinDistance; + float fEnemyDistanceSquared; + Weapon *pWeap = controlledEnt->GetActiveWeapon(WEAPON_MAIN); + bool bNoMove = false; - float fDistanceSquared = ( m_pEnemy->origin - origin ).lengthSquared(); + if (!m_pEnemy || !IsValidEnemy(m_pEnemy)) { + // Ignore dead enemies + m_iAttackTime = 0; + return; + } + float fDistanceSquared = (m_pEnemy->origin - controlledEnt->origin).lengthSquared(); - if( CanSee( m_pEnemy, 20, world->m_fAIVisionDistance, false ) ) - { - Weapon *pWeap = GetActiveWeapon( WEAPON_MAIN ); + m_vOldEnemyPos = m_vLastEnemyPos; - if( !pWeap ) - { - return; - } + bCanSee = + controlledEnt->CanSee(m_pEnemy, 20, Q_min(world->m_fAIVisionDistance, world->farplane_distance * 0.828), false); + if (bCanSee) { + if (!pWeap) { + return; + } - float fPrimaryBulletRange = pWeap->GetBulletRange( FIRE_PRIMARY ) / 1.25f; - float fPrimaryBulletRangeSquared = fPrimaryBulletRange * fPrimaryBulletRange; - float fSecondaryBulletRange = pWeap->GetBulletRange( FIRE_SECONDARY ); - float fSecondaryBulletRangeSquared = fSecondaryBulletRange * fSecondaryBulletRange; + float fPrimaryBulletRange = pWeap->GetBulletRange(FIRE_PRIMARY) / 1.25f; + float fPrimaryBulletRangeSquared = fPrimaryBulletRange * fPrimaryBulletRange; + float fSecondaryBulletRange = pWeap->GetBulletRange(FIRE_SECONDARY); + float fSecondaryBulletRangeSquared = fSecondaryBulletRange * fSecondaryBulletRange; + float fSpreadFactor = pWeap->GetSpreadFactor(FIRE_PRIMARY); - fMinDistance = fPrimaryBulletRange; + // + // check the fire movement speed if the weapon has a max fire movement + // + if (pWeap->GetMaxFireMovement() < 1 && pWeap->HasAmmoInClip(FIRE_PRIMARY)) { + float length; - if( fMinDistance > 256 ) - { - fMinDistance = 256; - } + length = controlledEnt->velocity.length(); + if ((length / sv_runspeed->value) > (pWeap->GetMaxFireMovementMult())) { + bNoMove = true; + movement.ClearMove(); + } + } - fMinDistanceSquared = fMinDistance * fMinDistance; + fMinDistance = fPrimaryBulletRange; - if( client->ps.stats[ STAT_AMMO ] > 0 || client->ps.stats[ STAT_CLIPAMMO ] > 0 ) - { - if( fDistanceSquared <= fPrimaryBulletRangeSquared ) - { - if( pWeap->IsSemiAuto() ) - { - m_botCmd.buttons ^= BUTTON_ATTACKLEFT; - } - else - { - m_botCmd.buttons |= BUTTON_ATTACKLEFT; - } - } - else - { - m_botCmd.buttons &= ~BUTTON_ATTACKLEFT; - } - } - else if( pWeap->GetFireType( FIRE_SECONDARY ) == FT_MELEE ) - { - bMelee = true; + if (fMinDistance > 256) { + fMinDistance = 256; + } - if( fDistanceSquared <= fSecondaryBulletRangeSquared ) - { - m_botCmd.buttons ^= BUTTON_ATTACKRIGHT; - } - else - { - m_botCmd.buttons &= ~BUTTON_ATTACKRIGHT; - } - } - else - { - m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ); - } - } - else - { - m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ); - fMinDistanceSquared = 0; - } + fMinDistanceSquared = fMinDistance * fMinDistance; - AimAt( m_vLastEnemyPos ); + if (controlledEnt->client->ps.stats[STAT_AMMO] > 0 || controlledEnt->client->ps.stats[STAT_CLIPAMMO] > 0) { + if (fDistanceSquared <= fPrimaryBulletRangeSquared) { + if (pWeap->IsSemiAuto()) { + if (controlledEnt->client->ps.iViewModelAnim == VM_ANIM_IDLE + || controlledEnt->client->ps.iViewModelAnim >= VM_ANIM_IDLE_0 + && controlledEnt->client->ps.iViewModelAnim <= VM_ANIM_IDLE_2) { + if (fSpreadFactor < 0.25) { + m_botCmd.buttons ^= BUTTON_ATTACKLEFT; + if (pWeap->GetZoom()) { + if (!controlledEnt->IsZoomed()) { + m_botCmd.buttons |= BUTTON_ATTACKRIGHT; + } else { + m_botCmd.buttons &= ~BUTTON_ATTACKRIGHT; + } + } + } else { + bNoMove = true; + movement.ClearMove(); + } + } else { + m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT); + controlledEnt->ZoomOff(); + } + } else { + m_botCmd.buttons |= BUTTON_ATTACKLEFT; + } + } else { + m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT); + controlledEnt->ZoomOff(); + } + } else { + m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT); + controlledEnt->ZoomOff(); + } - m_vOldEnemyPos = m_vLastEnemyPos; - m_vLastEnemyPos = m_pEnemy->centroid; + if (pWeap->GetFireType(FIRE_SECONDARY) == FT_MELEE) { + if (controlledEnt->client->ps.stats[STAT_AMMO] <= 0 && controlledEnt->client->ps.stats[STAT_CLIPAMMO] <= 0) { + bMelee = true; + } else if (fDistanceSquared <= fSecondaryBulletRangeSquared) { + bMelee = true; + } + } - if( ( !MoveToBestAttractivePoint( 5 ) && !IsMoving() ) || ( m_vOldEnemyPos != m_vLastEnemyPos && !MoveDone() ) ) - { - if( !bMelee ) - { - if( ( origin - m_vLastEnemyPos ).lengthSquared() < fMinDistanceSquared ) - { - Vector vDir = origin - m_vLastEnemyPos; - VectorNormalizeFast( vDir ); + if (bMelee) { + m_botCmd.buttons &= ~BUTTON_ATTACKLEFT; - AvoidPath( m_vLastEnemyPos, fMinDistance, vDir ); - } - else - { - MoveNear( m_vLastEnemyPos, fMinDistance ); - } - } - else - { - MoveTo( m_vLastEnemyPos ); - } - } + if (fDistanceSquared <= fSecondaryBulletRangeSquared) { + m_botCmd.buttons ^= BUTTON_ATTACKRIGHT; + } else { + m_botCmd.buttons &= ~BUTTON_ATTACKRIGHT; + } + } + + m_iAttackTime = level.inttime + 1000; + m_iAttackStopAimTime = level.inttime + 3000; + m_vLastEnemyPos = m_pEnemy->centroid; + } else { + m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT); + fMinDistanceSquared = 0; + } + + if (bCanSee || level.inttime < m_iAttackStopAimTime) { + Vector vRandomOffset; + Vector vTarget; + orientation_t eyes_or; + + if (m_iEnemyEyesTag == -1) { + // Cache the tag + m_iEnemyEyesTag = gi.Tag_NumForName(m_pEnemy->edict->tiki, "eyes bone"); + } + + if (m_iEnemyEyesTag != -1) { + // Use the enemy's eyes bone + m_pEnemy->GetTag(m_iEnemyEyesTag, &eyes_or); + + vRandomOffset = Vector(G_CRandom(8), G_CRandom(8), -G_Random(32)); + vTarget = eyes_or.origin + vRandomOffset; + rotation.AimAt(eyes_or.origin + vRandomOffset); + } else { + vRandomOffset = Vector(G_CRandom(8), G_CRandom(8), 16 + G_Random(m_pEnemy->viewheight - 16)); + vTarget = m_pEnemy->origin + vRandomOffset; + } + + rotation.AimAt(vTarget); + } else { + AimAtAimNode(); + } + + if (bNoMove) { + return; + } + + fEnemyDistanceSquared = (controlledEnt->origin - m_vLastEnemyPos).lengthSquared(); + + if ((!movement.MoveToBestAttractivePoint(5) && !movement.IsMoving()) + || (m_vOldEnemyPos != m_vLastEnemyPos && !movement.MoveDone()) || fEnemyDistanceSquared < fMinDistanceSquared) { + if (!bMelee || !bCanSee) { + if (fEnemyDistanceSquared < fMinDistanceSquared) { + Vector vDir = controlledEnt->origin - m_vLastEnemyPos; + VectorNormalizeFast(vDir); + + movement.AvoidPath(m_vLastEnemyPos, fMinDistance, Vector(controlledEnt->orientation[1]) * 512); + } else { + movement.MoveTo(m_vLastEnemyPos); + } + + if (!bCanSee && movement.MoveDone()) { + // Lost track of the enemy + ClearEnemy(); + return; + } + } else { + movement.MoveTo(m_vLastEnemyPos); + } + } + + if (movement.IsMoving()) { + m_iAttackTime = level.inttime + 1000; + } } /* @@ -1499,30 +897,21 @@ Grenade state Avoid any grenades ==================== */ -void PlayerBot::InitState_Grenade - ( - botfunc_t *func - ) +void BotController::InitState_Grenade(botfunc_t *func) { - func->CheckCondition = &PlayerBot::CheckCondition_Grenade; - func->ThinkState = &PlayerBot::State_Grenade; + func->CheckCondition = &BotController::CheckCondition_Grenade; + func->ThinkState = &BotController::State_Grenade; } -bool PlayerBot::CheckCondition_Grenade - ( - void - ) +bool BotController::CheckCondition_Grenade(void) { - // FIXME: TODO - return false; + // FIXME: TODO + return false; } -void PlayerBot::State_Grenade - ( - void - ) +void BotController::State_Grenade(void) { - // FIXME: TODO + // FIXME: TODO } /* @@ -1532,87 +921,311 @@ Weapon state Change weapon when necessary ==================== */ -void PlayerBot::InitState_Weapon - ( - botfunc_t *func - ) +void BotController::InitState_Weapon(botfunc_t *func) { - func->CheckCondition = &PlayerBot::CheckCondition_Weapon; - func->BeginState = &PlayerBot::State_BeginWeapon; + func->CheckCondition = &BotController::CheckCondition_Weapon; + func->BeginState = &BotController::State_BeginWeapon; } -bool PlayerBot::CheckCondition_Weapon - ( - void - ) +bool BotController::CheckCondition_Weapon(void) { - return GetActiveWeapon( WEAPON_MAIN ) != BestWeapon( NULL, false, WEAPON_CLASS_THROWABLE ); + return controlledEnt->GetActiveWeapon(WEAPON_MAIN) + != controlledEnt->BestWeapon(NULL, false, WEAPON_CLASS_THROWABLE); } -void PlayerBot::State_BeginWeapon - ( - void - ) +void BotController::State_BeginWeapon(void) { - Weapon *weap = BestWeapon( NULL, false, WEAPON_CLASS_THROWABLE ); + Weapon *weap = controlledEnt->BestWeapon(NULL, false, WEAPON_CLASS_THROWABLE); - if( weap == NULL ) - { - SendCommand( "safeholster 1" ); - return; - } + if (weap == NULL) { + SendCommand("safeholster 1"); + return; + } - SendCommand( va( "use \"%s\"", weap->model.c_str() ) ); + SendCommand(va("use \"%s\"", weap->model.c_str())); } -void PlayerBot::Spawned - ( - void - ) -{ - ClearEnemy(); - m_iCuriousTime = 0; +Weapon* BotController::FindWeaponWithAmmo() { + + Weapon *next; + int n; + int j; + int bestrank; + Weapon *bestweapon; + const Container& inventory = controlledEnt->getInventory(); - Player::Spawned(); + n = inventory.NumObjects(); + + // Search until we find the best weapon with ammo + bestweapon = NULL; + bestrank = -999999; + + for (j = 1; j <= n; j++) { + next = (Weapon *)G_GetEntity(inventory.ObjectAt(j)); + + assert(next); + if (!next->IsSubclassOfWeapon() || next->IsSubclassOfInventoryItem()) { + continue; + } + + if (next->GetWeaponClass() & WEAPON_CLASS_THROWABLE) { + continue; + } + + if (next->GetRank() < bestrank) { + continue; + } + + if (!next->HasAmmo(FIRE_PRIMARY)) { + continue; + } + + bestweapon = (Weapon*)next; + bestrank = bestweapon->GetRank(); + } + + return bestweapon; } -void PlayerBot::Killed - ( - Event *ev - ) -{ - Player::Killed( ev ); +Weapon* BotController::FindMeleeWeapon() { + + Weapon *next; + int n; + int j; + int bestrank; + Weapon *bestweapon; + const Container& inventory = controlledEnt->getInventory(); - // send the respawn buttons - if( !( m_botCmd.buttons & BUTTON_ATTACKLEFT ) ) - m_botCmd.buttons |= BUTTON_ATTACKLEFT; - else - m_botCmd.buttons &= ~BUTTON_ATTACKLEFT; + n = inventory.NumObjects(); - m_botEyes.ofs[ 0 ] = 0; - m_botEyes.ofs[ 1 ] = 0; - m_botEyes.ofs[ 2 ] = 0; - m_botEyes.angles[ 0 ] = 0; - m_botEyes.angles[ 1 ] = 0; + // Search until we find the best weapon with ammo + bestweapon = NULL; + bestrank = -999999; - m_vLastDeathPos = origin; + for (j = 1; j <= n; j++) { + next = (Weapon *)G_GetEntity(inventory.ObjectAt(j)); + + assert(next); + if (!next->IsSubclassOfWeapon() || next->IsSubclassOfInventoryItem()) { + continue; + } + + if (next->GetRank() < bestrank) { + continue; + } + + if (next->GetFireType(FIRE_SECONDARY) != FT_MELEE) { + continue; + } + + bestweapon = (Weapon*)next; + bestrank = bestweapon->GetRank(); + } + + return bestweapon; } -void PlayerBot::GotKill - ( - Event *ev - ) -{ - Player::GotKill( ev ); +void BotController::UseWeaponWithAmmo() { + Weapon* bestWeapon = FindWeaponWithAmmo(); + if (!bestWeapon) { + // + // If there is no weapon with ammo, fallback to a weapon that can melee + // + bestWeapon = FindMeleeWeapon(); + } - ClearEnemy(); - m_iCuriousTime = 0; + if (!bestWeapon || bestWeapon == controlledEnt->GetActiveWeapon(WEAPON_MAIN)) { + return; + } + + controlledEnt->useWeapon(bestWeapon, WEAPON_MAIN); } -void PlayerBot::EventStuffText - ( - Event *ev - ) +void BotController::Spawned(void) { - SendCommand( ev->GetString( 1 ) ); + ClearEnemy(); + m_iCuriousTime = 0; + m_botCmd.buttons = 0; +} + +void BotController::Think() +{ + usercmd_t ucmd; + usereyes_t eyeinfo; + + UpdateBotStates(); + GetUsercmd(&ucmd); + GetEyeInfo(&eyeinfo); + + G_ClientThink(controlledEnt->edict, &ucmd, &eyeinfo); +} + +void BotController::Killed(const Event& ev) +{ + Entity *attacker; + + // send the respawn buttons + if (!(m_botCmd.buttons & BUTTON_ATTACKLEFT)) { + m_botCmd.buttons |= BUTTON_ATTACKLEFT; + } else { + m_botCmd.buttons &= ~BUTTON_ATTACKLEFT; + } + + m_botEyes.ofs[0] = 0; + m_botEyes.ofs[1] = 0; + m_botEyes.ofs[2] = 0; + m_botEyes.angles[0] = 0; + m_botEyes.angles[1] = 0; + + attacker = ev.GetEntity(1); + + if (attacker && rand() % 5 == 0) { + // 1/5 chance to go back to the attacker position + m_vLastDeathPos = attacker->origin; + } else { + m_vLastDeathPos = vec_zero; + } + + // Choose a new random primary weapon + Event event(EV_Player_PrimaryDMWeapon); + event.AddString("auto"); + + controlledEnt->ProcessEvent(event); + + // + // This is useful to change nationality in Spearhead and Breakthrough + // this allows the AI to use more weapons + // + Info_SetValueForKey(controlledEnt->client->pers.userinfo, "dm_playermodel", G_GetRandomAlliedPlayerModel()); + Info_SetValueForKey(controlledEnt->client->pers.userinfo, "dm_playergermanmodel", G_GetRandomGermanPlayerModel()); + + G_ClientUserinfoChanged(controlledEnt->edict, controlledEnt->client->pers.userinfo); +} + +void BotController::GotKill(const Event& ev) +{ + ClearEnemy(); + m_iCuriousTime = 0; + + if (level.inttime >= m_iNextTauntTime && (rand() % 5) == 0) { + // + // Randomly play a taunt + // + Event event("dmmessage"); + + event.AddInteger(0); + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + event.AddString("*5" + str(1 + (rand() % 8))); + } else { + event.AddString("*4" + str(1 + (rand() % 9))); + } + + controlledEnt->ProcessEvent(event); + + m_iNextTauntTime = level.inttime + 5000; + } +} + +void BotController::EventStuffText(const str& text) +{ + SendCommand(text); +} + +void BotController::setControlledEntity(Player *player) +{ + controlledEnt = player; + movement.SetControlledEntity(player); + rotation.SetControlledEntity(player); + + delegateHandle_gotKill = player->delegate_gotKill.Add(std::bind(&BotController::GotKill, this, std::placeholders::_1)); + delegateHandle_killed = player->delegate_killed.Add(std::bind(&BotController::Killed, this, std::placeholders::_1)); + delegateHandle_stufftext = player->delegate_stufftext.Add(std::bind(&BotController::EventStuffText, this, std::placeholders::_1)); +} + +Player *BotController::getControlledEntity() const +{ + return controlledEnt; +} + +BotController *BotControllerManager::createController(Player *player) +{ + BotController *controller = new BotController(); + controller->setControlledEntity(player); + + controllers.AddObject(controller); + + return controller; +} + +void BotControllerManager::removeController(BotController *controller) +{ + controllers.RemoveObject(controller); + delete controller; +} + +BotController *BotControllerManager::findController(Entity *ent) +{ + int i; + + for (i = 1; i <= controllers.NumObjects(); i++) { + BotController *controller = controllers.ObjectAt(i); + if (controller->getControlledEntity() == ent) { + return controller; + } + } + + return nullptr; +} + +const Container& BotControllerManager::getControllers() const +{ + return controllers; +} + +BotControllerManager::~BotControllerManager() +{ + Cleanup(); +} + +void BotControllerManager::Init() +{ + BotController::Init(); +} + +void BotControllerManager::Cleanup() +{ + int i; + + BotController::Init(); + + for (i = 1; i <= controllers.NumObjects(); i++) { + BotController *controller = controllers.ObjectAt(i); + delete controller; + } + + controllers.FreeObjectList(); +} + +void BotControllerManager::ThinkControllers() +{ + int i; + + // Delete controllers that don't have associated player entity + // This cannot happen unless some mods remove them + for (i = controllers.NumObjects(); i > 0; i--) { + BotController* controller = controllers.ObjectAt(i); + if (!controller->getControlledEntity()) { + gi.DPrintf("Bot %d has no associated player entity. This shouldn't happen unless the entity has been removed by a script. The controller will be removed, please fix.\n", i); + + // Remove the controller, it will be recreated later to match `sv_numbots` + delete controller; + controllers.RemoveObjectAt(i); + } + } + + for (i = 1; i <= controllers.NumObjects(); i++) { + BotController *controller = controllers.ObjectAt(i); + controller->Think(); + } } diff --git a/code/fgame/playerbot.h b/code/fgame/playerbot.h index 7664c3ab..6d67fab3 100644 --- a/code/fgame/playerbot.h +++ b/code/fgame/playerbot.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -21,156 +21,270 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // playerbot.h: Multiplayer bot system. -#ifndef __PLAYERBOT_H__ -#define __PLAYERBOT_H__ +#pragma once #include "player.h" #include "navigate.h" #include "actorpath.h" -#define MAX_BOT_FUNCTIONS 5 +#define MAX_BOT_FUNCTIONS 5 typedef struct nodeAttract_s { - float m_fRespawnTime; - AttractiveNodePtr m_pNode; + float m_fRespawnTime; + AttractiveNodePtr m_pNode; } nodeAttract_t; -class PlayerBot : public Player +class BotController; + +class BotMovement { - struct botfunc_t { - bool ( PlayerBot::*CheckCondition )( void ); - void ( PlayerBot::*BeginState )( void ); - void ( PlayerBot::*EndState )( void ); - void ( PlayerBot::*ThinkState )( void ); - }; - -private: - static botfunc_t botfuncs[]; - - // Paths - ActorPath m_Path; - Vector m_vTargetPos; - Vector m_vCurrentGoal; - Vector m_vLastValidDir; - Vector m_vLastValidGoal; - bool m_bPathing; - bool m_bTempAway; - bool m_bAimPath; - bool m_bDeltaMove; - int m_iTempAwayTime; - int m_iCheckPathTime; - AttractiveNodePtr m_pPrimaryAttract; - float m_fAttractTime; - Container< nodeAttract_t * > m_attractList; - - // States - int m_iCuriousTime; - int m_iAttackTime; - Vector m_vLastCuriousPos; - Vector m_vOldEnemyPos; - Vector m_vLastEnemyPos; - Vector m_vLastDeathPos; - SafePtr< Sentient > m_pEnemy; - - // Input - usercmd_t m_botCmd; - usereyes_t m_botEyes; - - // Direction - Vector m_vTargetAng; - Vector m_vCurrentAng; - Vector m_vAngSpeed; - float m_fYawSpeedMult; - - // States - int m_StateCount; - unsigned int m_StateFlags; - ScriptThreadLabel m_RunLabel; - -private: - void CheckAttractiveNodes( void ); - void MoveThink( void ); - void TurnThink( void ); - void CheckEndPos( void ); - void CheckJump( void ); - void CheckUse( void ); - - void State_DefaultBegin( void ); - void State_DefaultEnd( void ); - void State_Reset( void ); - - static void InitState_Idle( botfunc_t *func ); - bool CheckCondition_Idle( void ); - void State_BeginIdle( void ); - void State_EndIdle( void ); - void State_Idle( void ); - - static void InitState_Curious( botfunc_t *func ); - bool CheckCondition_Curious( void ); - void State_BeginCurious( void ); - void State_EndCurious( void ); - void State_Curious( void ); - - static void InitState_Attack( botfunc_t *func ); - bool CheckCondition_Attack( void ); - void State_BeginAttack( void ); - void State_EndAttack( void ); - void State_Attack( void ); - - static void InitState_Grenade( botfunc_t *func ); - bool CheckCondition_Grenade( void ); - void State_BeginGrenade( void ); - void State_EndGrenade( void ); - void State_Grenade( void ); - - static void InitState_Weapon( botfunc_t *func ); - bool CheckCondition_Weapon( void ); - void State_BeginWeapon( void ); - void State_EndWeapon( void ); - void State_Weapon( void ); - - void CheckStates( void ); - public: - CLASS_PROTOTYPE( PlayerBot ); + BotMovement(); - PlayerBot(); + void SetControlledEntity(Player *newEntity); - static void Init( void ); + void MoveThink(usercmd_t& botcmd); - void GetEyeInfo( usereyes_t *eyeinfo ); - void GetUsercmd( usercmd_t *ucmd ); - void SetTargetAngles( Vector vAngles ); + void AvoidPath( + Vector vPos, + float fAvoidRadius, + Vector vPreferredDir = vec_zero, + float *vLeashHome = NULL, + float fLeashRadius = 0.0f + ); + void MoveNear(Vector vNear, float fRadius, float *vLeashHome = NULL, float fLeashRadius = 0.0f); + void MoveTo(Vector vPos, float *vLeashHome = NULL, float fLeashRadius = 0.0f); + bool MoveToBestAttractivePoint(int iMinPriority = 0); - void UpdateBotStates( void ); - void CheckReload( void ); + bool CanMoveTo(Vector vPos); + bool MoveDone(); + bool IsMoving(void); + void ClearMove(void); - void AimAt( Vector vPos ); - void AimAtAimNode( void ); + Vector GetCurrentGoal() const; - void AvoidPath( Vector vPos, float fAvoidRadius, Vector vPreferredDir = vec_zero, float *vLeashHome = NULL, float fLeashRadius = 0.0f ); - void MoveNear( Vector vNear, float fRadius, float *vLeashHome = NULL, float fLeashRadius = 0.0f ); - void MoveTo( Vector vPos, float *vLeashHome = NULL, float fLeashRadius = 0.0f ); - bool MoveToBestAttractivePoint( int iMinPriority = 0 ); +private: + void CheckAttractiveNodes(); + void CheckEndPos(Entity *entity); + void CheckJump(usercmd_t& botcmd); + void NewMove(); - bool CanMoveTo( Vector vPos ); - bool MoveDone( void ); - bool IsMoving( void ); - void ClearMove( void ); +private: + SafePtr controlledEntity; + AttractiveNodePtr m_pPrimaryAttract; + Container m_attractList; + ActorPath m_Path; - void NoticeEvent( Vector vPos, int iType, Entity *pEnt, float fDistanceSquared, float fRadiusSquared ); - void ClearEnemy( void ); - - void SendCommand( const char *text ); - - void setAngles( Vector angles ) override; - void updateOrigin( void ) override; - - void Spawned( void ) override; - - void Killed( Event *ev ); - void GotKill( Event *ev ); - void EventStuffText( Event *ev ); + Vector m_vCurrentOrigin; + Vector m_vTargetPos; + Vector m_vCurrentGoal; + Vector m_vLastValidDir; + Vector m_vLastValidGoal; + Vector m_vLastCheckPos[2]; + float m_fAttractTime; + int m_iTempAwayTime; + int m_iNumBlocks; + int m_iCheckPathTime; + bool m_bPathing; + bool m_bTempAway; }; -#endif /* playerbot.h */ +class BotRotation +{ +public: + BotRotation(); + + void SetControlledEntity(Player *newEntity); + + void TurnThink(usercmd_t& botcmd, usereyes_t& eyeinfo); + const Vector& GetTargetAngles() const; + void SetTargetAngles(Vector vAngles); + void AimAt(Vector vPos); + +private: + SafePtr controlledEntity; + + Vector m_vTargetAng; + Vector m_vCurrentAng; + Vector m_vAngSpeed; + float m_fYawSpeedMult; +}; + +class BotState +{ +public: + virtual bool CheckCondition() const = 0; + virtual void Begin() = 0; + virtual void End() = 0; + virtual void Think() = 0; +}; + +class BotController : public Listener +{ +public: + struct botfunc_t { + bool (BotController::*CheckCondition)(void); + void (BotController::*BeginState)(void); + void (BotController::*EndState)(void); + void (BotController::*ThinkState)(void); + }; + +private: + static botfunc_t botfuncs[]; + + BotMovement movement; + BotRotation rotation; + + // States + int m_iCuriousTime; + int m_iAttackTime; + int m_iConfirmTime; + int m_iAttackStopAimTime; + Vector m_vLastCuriousPos; + Vector m_vNewCuriousPos; + Vector m_vOldEnemyPos; + Vector m_vLastEnemyPos; + Vector m_vLastDeathPos; + SafePtr m_pEnemy; + int m_iEnemyEyesTag; + + // Input + usercmd_t m_botCmd; + usereyes_t m_botEyes; + + // States + int m_StateCount; + unsigned int m_StateFlags; + ScriptThreadLabel m_RunLabel; + + // Taunts + int m_iNextTauntTime; + +private: + DelegateHandle delegateHandle_gotKill; + DelegateHandle delegateHandle_killed; + DelegateHandle delegateHandle_stufftext; + +private: + Weapon* FindWeaponWithAmmo(void); + Weapon* FindMeleeWeapon(void); + void UseWeaponWithAmmo(void); + + void CheckUse(void); + void CheckValidWeapon(void); + + void State_DefaultBegin(void); + void State_DefaultEnd(void); + void State_Reset(void); + + static void InitState_Idle(botfunc_t *func); + bool CheckCondition_Idle(void); + void State_BeginIdle(void); + void State_EndIdle(void); + void State_Idle(void); + + static void InitState_Curious(botfunc_t *func); + bool CheckCondition_Curious(void); + void State_BeginCurious(void); + void State_EndCurious(void); + void State_Curious(void); + + static void InitState_Attack(botfunc_t *func); + bool CheckCondition_Attack(void); + void State_BeginAttack(void); + void State_EndAttack(void); + void State_Attack(void); + bool IsValidEnemy(Sentient *sent) const; + + static void InitState_Grenade(botfunc_t *func); + bool CheckCondition_Grenade(void); + void State_BeginGrenade(void); + void State_EndGrenade(void); + void State_Grenade(void); + + static void InitState_Weapon(botfunc_t *func); + bool CheckCondition_Weapon(void); + void State_BeginWeapon(void); + void State_EndWeapon(void); + void State_Weapon(void); + + void CheckStates(void); + +public: + CLASS_PROTOTYPE(BotController); + + BotController(); + ~BotController(); + + static void Init(void); + + void GetEyeInfo(usereyes_t *eyeinfo); + void GetUsercmd(usercmd_t *ucmd); + + void UpdateBotStates(void); + void CheckReload(void); + + void AimAtAimNode(void); + + void NoticeEvent(Vector vPos, int iType, Entity *pEnt, float fDistanceSquared, float fRadiusSquared); + void ClearEnemy(void); + + void SendCommand(const char *text); + + void Think(); + + void Spawned(void); + + void Killed(const Event& ev); + void GotKill(const Event& ev); + void EventStuffText(const str& text); + + BotMovement& GetMovement(); + +public: + void setControlledEntity(Player *player); + Player *getControlledEntity() const; + +private: + SafePtr controlledEnt; +}; + +class BotControllerManager : public Listener +{ +public: + CLASS_PROTOTYPE(BotControllerManager); + +public: + ~BotControllerManager(); + + BotController *createController(Player *player); + void removeController(BotController *controller); + BotController *findController(Entity *ent); + const Container& getControllers() const; + + void Init(); + void Cleanup(); + void ThinkControllers(); + +private: + Container controllers; +}; + +class BotManager : public Listener +{ +public: + CLASS_PROTOTYPE(BotManager); + +public: + BotControllerManager& getControllerManager(); + + void Init(); + void Cleanup(); + void Frame(); + void BroadcastEvent(Entity *originator, Vector origin, int iType, float radius); + +private: + BotControllerManager botControllerManager; +}; + +extern BotManager botManager; diff --git a/code/fgame/playerbot_master.cpp b/code/fgame/playerbot_master.cpp new file mode 100644 index 00000000..d4cdcd4e --- /dev/null +++ b/code/fgame/playerbot_master.cpp @@ -0,0 +1,114 @@ +#include "playerbot.h" +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// playerbot_master.cpp: Multiplayer bot system. + +#include "g_local.h" +#include "actor.h" +#include "playerbot.h" +#include "consoleevent.h" +#include "debuglines.h" +#include "scriptexception.h" +#include "vehicleturret.h" +#include "weaputils.h" + +BotManager botManager; + +CLASS_DECLARATION(Listener, BotControllerManager, NULL) { + {NULL, NULL} +}; + +CLASS_DECLARATION(Listener, BotManager, NULL) { + {NULL, NULL} +}; + +void BotManager::Init() +{ + botControllerManager.Init(); +} + +void BotManager::Cleanup() +{ + botControllerManager.Cleanup(); +} + +void BotManager::Frame() +{ + botControllerManager.ThinkControllers(); +} + +void BotManager::BroadcastEvent(Entity *originator, Vector origin, int iType, float radius) +{ + Sentient *ent; + Actor *act; + Vector delta; + str name; + float r2; + float dist2; + int i; + int iNumSentients; + int iAreaNum; + BotController *controller; + + if (radius <= 0.0f) { + radius = G_AIEventRadius(iType); + } + + assert(originator); + + r2 = Square(radius); + + const Container& controllers = getControllerManager().getControllers(); + for (i = 1; i <= controllers.NumObjects(); i++) { + controller = controllers.ObjectAt(i); + ent = controller->getControlledEntity(); + if (!ent || ent == originator || ent->deadflag) { + continue; + } + + delta = origin - ent->centroid; + + // dot product returns length squared + dist2 = Square(delta); + + if (originator) { + iAreaNum = originator->edict->r.areanum; + } else { + iAreaNum = gi.AreaForPoint(origin); + } + + if (dist2 > r2) { + continue; + } + + if (iAreaNum != ent->edict->r.areanum && !gi.AreasConnected(iAreaNum, ent->edict->r.areanum)) { + continue; + } + + controller->NoticeEvent(origin, iType, originator, dist2, r2); + } +} + +BotControllerManager& BotManager::getControllerManager() +{ + return botControllerManager; +} diff --git a/code/fgame/playerbot_movement.cpp b/code/fgame/playerbot_movement.cpp new file mode 100644 index 00000000..03e402f0 --- /dev/null +++ b/code/fgame/playerbot_movement.cpp @@ -0,0 +1,635 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// playerbot_movement.cpp: Manages bot movements + +#include "playerbot.h" +#include "debuglines.h" + +BotMovement::BotMovement() +{ + controlledEntity = NULL; + + m_Path.SetFallHeight(400); + m_bPathing = false; + m_bTempAway = false; + m_fAttractTime = 0; + + m_iCheckPathTime = 0; + m_iTempAwayTime = 0; + m_iNumBlocks = 0; +} + +void BotMovement::SetControlledEntity(Player *newEntity) +{ + controlledEntity = newEntity; +} + +void BotMovement::MoveThink(usercmd_t& botcmd) +{ + Vector vDir; + Vector vAngles; + Vector vWishDir; + + botcmd.forwardmove = 0; + botcmd.rightmove = 0; + + CheckAttractiveNodes(); + + if (!IsMoving()) { + return; + } + + if (level.inttime >= m_Path.Time() + 1000 && m_vCurrentOrigin != controlledEntity->origin) { + m_vCurrentOrigin = controlledEntity->origin; + + if (m_Path.CurrentNode()) { + // recalculate paths because of a new origin + m_Path.ReFindPath(controlledEntity->origin, controlledEntity); + } + } + + if (m_bTempAway && level.inttime >= m_iTempAwayTime) { + m_bTempAway = false; + m_Path.FindPath(controlledEntity->origin, m_vTargetPos, controlledEntity, 0, NULL, 0); + } + + if (!m_bTempAway) { + if (m_Path.CurrentNode()) { + m_Path.UpdatePos(controlledEntity->origin, 8); + + m_vCurrentGoal = controlledEntity->origin; + VectorAdd2D(m_vCurrentGoal, m_Path.CurrentDelta(), m_vCurrentGoal); + + if (MoveDone()) { + // Clear the path + m_Path.Clear(); + } + } + } + + if (ai_debugpath->integer) { + G_DebugLine(controlledEntity->centroid, m_vCurrentGoal + Vector(0, 0, 36), 1, 1, 0, 1); + } + + // Check if we're blocked + if (level.inttime >= m_iCheckPathTime) { + m_iCheckPathTime = level.inttime + 1000; + + if (m_iNumBlocks >= 5) { + // Give up + ClearMove(); + } + + m_bTempAway = false; + + if (controlledEntity->groundentity || controlledEntity->client->ps.walking) { + if (controlledEntity->GetMoveResult() >= MOVERESULT_BLOCKED + || controlledEntity->velocity.lengthSquared() <= Square(8)) { + m_bTempAway = true; + } else if ((controlledEntity->origin - m_vLastCheckPos[0]).lengthSquared() <= Square(32) + && (controlledEntity->origin - m_vLastCheckPos[1]).lengthSquared() <= Square(32)) { + m_bTempAway = true; + } + } else { + // falling + if (controlledEntity->GetMoveResult() >= MOVERESULT_BLOCKED) { + // stuck while falling + m_bTempAway = true; + } + } + + if (m_bTempAway) { + Vector nextPos; + Vector dir; + + m_bTempAway = true; + m_iTempAwayTime = level.inttime + 750; + m_iNumBlocks++; + + // Try to backward a little + if (m_Path.CurrentNode()) { + nextPos = m_Path.CurrentNode()->point; + } else { + nextPos = m_vTargetPos; + } + + m_Path.Clear(); + m_Path.ForceShortLookahead(); + + if (rand() % 10 != 0) { + dir = nextPos - controlledEntity->origin; + dir.z = 0; + dir.normalize(); + + if (dir.x < -0.5 || dir.x > 0.5) { + dir.x *= 4; + dir.y /= 4; + } else if (dir.y < -0.5 || dir.y > 0.5) { + dir.x /= 4; + dir.y *= 4; + } else { + dir.x = G_CRandom(2); + dir.y = G_CRandom(2); + } + + m_vCurrentGoal = nextPos + dir * 128; + } else { + m_vCurrentGoal = controlledEntity->origin + Vector(G_CRandom(512), G_CRandom(512), G_CRandom(512)); + } + + } else { + m_iNumBlocks = 0; + + if (!m_Path.CurrentNode()) { + m_vTargetPos = controlledEntity->origin + Vector(G_CRandom(512), G_CRandom(512), G_CRandom(512)); + m_vCurrentGoal = m_vTargetPos; + } + } + + m_vLastCheckPos[1] = m_vLastCheckPos[0]; + m_vLastCheckPos[0] = controlledEntity->origin; + } + + if (ai_debugpath->integer) { + PathInfo *pos = m_Path.CurrentNode(); + + if (pos != NULL) { + while (pos != m_Path.LastNode()) { + Vector vStart = pos->point + Vector(0, 0, 32); + + pos--; + + Vector vEnd = pos->point + Vector(0, 0, 32); + + G_DebugLine(vStart, vEnd, 1, 0, 0, 1); + } + } + } + + if (m_Path.CurrentNode()) { + if ((m_vTargetPos - controlledEntity->origin).lengthSquared() <= Square(16)) { + ClearMove(); + } + } else { + if ((m_vTargetPos - controlledEntity->origin).lengthXYSquared() <= Square(16)) { + ClearMove(); + } + } + + // Rotate the dir + if (m_Path.CurrentNode()) { + vDir[0] = m_Path.CurrentDelta()[0]; + vDir[1] = m_Path.CurrentDelta()[1]; + } else { + vDir = m_vCurrentGoal - controlledEntity->origin; + } + vDir[2] = 0; + + VectorNormalize2D(vDir); + vAngles = vDir.toAngles() - controlledEntity->angles; + vAngles.AngleVectorsLeft(&vWishDir); + + m_vLastValidDir = vDir; + m_vLastValidGoal = m_vCurrentGoal; + + // Forward to the specified direction + float x = vWishDir.x * 127; + float y = -vWishDir.y * 127; + + botcmd.forwardmove = (signed char)Q_clamp(x, -127, 127); + botcmd.rightmove = (signed char)Q_clamp(y, -127, 127); + + CheckJump(botcmd); +} + +void BotMovement::CheckAttractiveNodes() +{ + for (int i = m_attractList.NumObjects(); i > 0; i--) { + nodeAttract_t *a = m_attractList.ObjectAt(i); + + if (a->m_pNode == NULL || !a->m_pNode->CheckTeam(controlledEntity) || level.time > a->m_fRespawnTime) { + delete a; + m_attractList.RemoveObjectAt(i); + } + } +} + +void BotMovement::CheckEndPos(Entity *entity) +{ + Vector start; + Vector end; + trace_t trace; + + if (!m_Path.LastNode()) { + return; + } + + start = m_Path.LastNode()->point; + end = m_vTargetPos; + + trace = + G_Trace(start, entity->mins, entity->maxs, end, entity, MASK_TARGETPATH, true, "BotController::CheckEndPos"); + + if (trace.fraction < 0.95f) { + m_vTargetPos = trace.endpos; + } +} + +void BotMovement::CheckJump(usercmd_t& botcmd) +{ + Vector start; + Vector end; + Vector dir; + trace_t trace; + + if (controlledEntity->GetLadder()) { + if (!botcmd.upmove) { + botcmd.upmove = 127; + } else { + botcmd.upmove = 0; + } + return; + } + + dir = m_vLastValidDir; + + start = controlledEntity->origin + Vector(0, 0, STEPSIZE); + end = + controlledEntity->origin + Vector(0, 0, STEPSIZE) + dir * (controlledEntity->maxs.y - controlledEntity->mins.y); + + if (ai_debugpath->integer) { + G_DebugLine(start, end, 1, 0, 1, 1); + } + + // Check if the bot needs to jump + trace = G_Trace( + start, + controlledEntity->mins, + controlledEntity->maxs, + end, + controlledEntity, + MASK_PLAYERSOLID, + false, + "BotController::CheckJump" + ); + + // No need to jump + if (trace.fraction > 0.5f) { + botcmd.upmove = 0; + return; + } + + start = controlledEntity->origin; + end = controlledEntity->origin + Vector(0, 0, STEPSIZE * 3); + + if (ai_debugpath->integer) { + G_DebugLine(start, end, 1, 0, 1, 1); + } + + // Check if the bot can jump up + trace = G_Trace( + start, + controlledEntity->mins, + controlledEntity->maxs, + end, + controlledEntity, + MASK_PLAYERSOLID, + true, + "BotController::CheckJump" + ); + + start = trace.endpos; + end = trace.endpos + dir * (controlledEntity->maxs.y - controlledEntity->mins.y); + + if (ai_debugpath->integer) { + G_DebugLine(start, end, 1, 0, 1, 1); + } + + Vector bounds[2]; + bounds[0] = Vector(controlledEntity->mins[0], controlledEntity->mins[1], 0); + bounds[1] = Vector( + controlledEntity->maxs[0], + controlledEntity->maxs[1], + (controlledEntity->maxs[0] + controlledEntity->maxs[1]) * 0.5 + ); + + // Check if the bot can jump at the location + trace = G_Trace( + start, bounds[0], bounds[1], end, controlledEntity, MASK_PLAYERSOLID, false, "BotController::CheckJump" + ); + + if (trace.fraction < 1) { + botcmd.upmove = 0; + return; + } + + // Make the bot climb walls + if (!botcmd.upmove) { + botcmd.upmove = 127; + } else { + botcmd.upmove = 0; + } +} + +/* +==================== +AvoidPath + +Avoid the specified position within the radius and start from a direction +==================== +*/ +void BotMovement::AvoidPath( + Vector vAvoid, float fAvoidRadius, Vector vPreferredDir, float *vLeashHome, float fLeashRadius +) +{ + Vector vDir; + + if (vPreferredDir == vec_zero) { + vDir = controlledEntity->origin - vAvoid; + VectorNormalizeFast(vDir); + } else { + vDir = vPreferredDir; + } + + m_Path.FindPathAway( + controlledEntity->origin, vAvoid, vDir, controlledEntity, fAvoidRadius, vLeashHome, fLeashRadius * fLeashRadius + ); + NewMove(); + + if (!m_Path.CurrentNode()) { + // Random movements + m_vTargetPos = controlledEntity->origin + Vector(G_Random(256) - 128, G_Random(256) - 128, G_Random(256) - 128); + m_vCurrentGoal = m_vTargetPos; + return; + } + + m_vTargetPos = m_Path.LastNode()->point; +} + +/* +==================== +MoveNear + +Move near the specified position within the radius +==================== +*/ +void BotMovement::MoveNear(Vector vNear, float fRadius, float *vLeashHome, float fLeashRadius) +{ + m_Path.FindPathNear( + controlledEntity->origin, vNear, controlledEntity, 0, fRadius * fRadius, vLeashHome, fLeashRadius * fLeashRadius + ); + NewMove(); + + if (!m_Path.CurrentNode()) { + m_bPathing = false; + return; + } + + m_vTargetPos = m_Path.LastNode()->point; +} + +/* +==================== +MoveTo + +Move to the specified position +==================== +*/ +void BotMovement::MoveTo(Vector vPos, float *vLeashHome, float fLeashRadius) +{ + m_vTargetPos = vPos; + m_Path.FindPath( + controlledEntity->origin, m_vTargetPos, controlledEntity, 0, vLeashHome, fLeashRadius * fLeashRadius + ); + + NewMove(); + + if (!m_Path.CurrentNode()) { + m_bPathing = false; + return; + } + + CheckEndPos(controlledEntity); +} + +/* +==================== +MoveToBestAttractivePoint + +Move to the nearest attractive point with a minimum priority +Returns true if no attractive point was found +==================== +*/ +bool BotMovement::MoveToBestAttractivePoint(int iMinPriority) +{ + Container list; + AttractiveNode *bestNode; + float bestDistanceSquared; + int bestPriority; + + if (m_pPrimaryAttract) { + MoveTo(m_pPrimaryAttract->origin); + + if (!IsMoving()) { + m_pPrimaryAttract = NULL; + } else { + if (MoveDone()) { + if (!m_fAttractTime) { + m_fAttractTime = level.time + m_pPrimaryAttract->m_fMaxStayTime; + } + if (level.time > m_fAttractTime) { + nodeAttract_t *a = new nodeAttract_t; + a->m_fRespawnTime = level.time + m_pPrimaryAttract->m_fRespawnTime; + a->m_pNode = m_pPrimaryAttract; + + m_pPrimaryAttract = NULL; + } + } + + return true; + } + } + + if (!attractiveNodes.NumObjects()) { + return false; + } + + bestNode = NULL; + bestDistanceSquared = 99999999.0f; + bestPriority = iMinPriority; + + for (int i = attractiveNodes.NumObjects(); i > 0; i--) { + AttractiveNode *node = attractiveNodes.ObjectAt(i); + float distSquared; + bool m_bRespawning = false; + + for (int j = m_attractList.NumObjects(); j > 0; j--) { + AttractiveNode *node2 = m_attractList.ObjectAt(j)->m_pNode; + + if (node2 == node) { + m_bRespawning = true; + break; + } + } + + if (m_bRespawning) { + continue; + } + + if (node->m_iPriority < bestPriority) { + continue; + } + + if (!node->CheckTeam(controlledEntity)) { + continue; + } + + distSquared = VectorLengthSquared(controlledEntity->origin - node->origin); + + if (node->m_fMaxDistanceSquared >= 0 && distSquared > node->m_fMaxDistanceSquared) { + continue; + } + + if (!CanMoveTo(node->origin)) { + continue; + } + + if (distSquared < bestDistanceSquared) { + bestDistanceSquared = distSquared; + bestNode = node; + bestPriority = node->m_iPriority; + } + } + + if (bestNode) { + m_pPrimaryAttract = bestNode; + m_fAttractTime = 0; + MoveTo(bestNode->origin); + return true; + } else { + // No attractive point found + return false; + } +} + +/* +==================== +NewMove + +Called when there is a new move +==================== +*/ +void BotMovement::NewMove() +{ + m_bPathing = true; + m_vLastCheckPos[0] = controlledEntity->origin; + m_vLastCheckPos[1] = controlledEntity->origin; +} + +/* +==================== +CanMoveTo + +Returns true if the bot has done moving +==================== +*/ +bool BotMovement::CanMoveTo(Vector vPos) +{ + return m_Path.DoesTheoreticPathExist(controlledEntity->origin, vPos, NULL, 0, NULL, 0); +} + +/* +==================== +MoveDone + +Returns true if the bot has done moving +==================== +*/ +bool BotMovement::MoveDone() +{ + PathInfo *next; + + if (!m_bPathing) { + return true; + } + + if (m_bTempAway) { + return false; + } + + if (!m_Path.CurrentNode()) { + return true; + } + + Vector delta = Vector(m_Path.CurrentPathGoal()) - controlledEntity->origin; + if (delta.lengthXYSquared() < Square(16) && delta.z < controlledEntity->maxs.z) { + return true; + } + + return false; +} + +/* +==================== +IsMoving + +Returns true if the bot has a current path +==================== +*/ +bool BotMovement::IsMoving(void) +{ + return m_bPathing; +} + +/* +==================== +ClearMove + +Stop the bot from moving +==================== +*/ +void BotMovement::ClearMove(void) +{ + m_Path.Clear(); + m_bPathing = false; + m_iNumBlocks = 0; +} + +/* +==================== +GetCurrentGoal + +Return the current goal, usually the nearest node the player should look at +==================== +*/ +Vector BotMovement::GetCurrentGoal() const +{ + if (!m_Path.CurrentNode()) { + return m_vCurrentGoal; + } + + if (!m_Path.Complete(controlledEntity->origin)) { + return controlledEntity->origin + Vector(m_Path.CurrentDelta()[0], m_Path.CurrentDelta()[1], 0); + } + + return controlledEntity->origin; +} diff --git a/code/fgame/playerbot_rotation.cpp b/code/fgame/playerbot_rotation.cpp new file mode 100644 index 00000000..0228be21 --- /dev/null +++ b/code/fgame/playerbot_rotation.cpp @@ -0,0 +1,139 @@ +/* +=========================================================================== +Copyright (C) 2024 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// playerbot_rotation.cpp: Manages bot rotation + +#include "playerbot.h" + +BotRotation::BotRotation() +{ + m_vAngSpeed = vec_zero; + m_vTargetAng = vec_zero; + m_vCurrentAng = vec_zero; + m_fYawSpeedMult = 1.0f; +} + +void BotRotation::SetControlledEntity(Player *newEntity) +{ + controlledEntity = newEntity; +} + +float AngleDifference(float ang1, float ang2) +{ + float diff; + + diff = ang1 - ang2; + if (ang1 > ang2) { + if (diff > 180.0) { + diff -= 360.0; + } + } else { + if (diff < -180.0) { + diff += 360.0; + } + } + return diff; +} + +void BotRotation::TurnThink(usercmd_t& botcmd, usereyes_t& eyeinfo) +{ + float diff, factor, maxchange, anglespeed, desired_speed; + int i; + + if (m_vTargetAng[PITCH] > 180) { + m_vTargetAng[PITCH] -= 360; + } + + factor = 0.5f; + maxchange = 360; + + if (maxchange < 240) { + maxchange = 240; + } + + maxchange *= level.frametime; + + for (i = 0; i < 2; i++) { + //over reaction view model + m_vCurrentAng[i] = AngleMod(m_vCurrentAng[i]); + m_vTargetAng[i] = AngleMod(m_vTargetAng[i]); + diff = AngleDifference(m_vCurrentAng[i], m_vTargetAng[i]); + desired_speed = diff * factor; + + m_vAngSpeed[i] = Q_clamp_float(m_vAngSpeed[i] + (m_vAngSpeed[i] - desired_speed), -180, 180); + anglespeed = Q_clamp_float(m_vAngSpeed[i], -maxchange, maxchange); + + m_vCurrentAng[i] += anglespeed; + m_vCurrentAng[i] = AngleMod(m_vCurrentAng[i]); + + //damping + m_vAngSpeed[i] *= 0.2 * (1 - factor); + } + + if (m_vCurrentAng[PITCH] > 180) { + m_vCurrentAng[PITCH] -= 360; + } + + eyeinfo.angles[0] = m_vCurrentAng[0]; + eyeinfo.angles[1] = m_vCurrentAng[1]; + botcmd.angles[0] = ANGLE2SHORT(m_vCurrentAng[0]) - controlledEntity->client->ps.delta_angles[0]; + botcmd.angles[1] = ANGLE2SHORT(m_vCurrentAng[1]) - controlledEntity->client->ps.delta_angles[1]; + botcmd.angles[2] = ANGLE2SHORT(m_vCurrentAng[2]) - controlledEntity->client->ps.delta_angles[2]; +} + +/* +==================== +GetTargetAngles + +Return the target angle +==================== +*/ +const Vector& BotRotation::GetTargetAngles() const +{ + return m_vTargetAng; +} + +/* +==================== +SetTargetAngles + +Set the bot's angle +==================== +*/ +void BotRotation::SetTargetAngles(Vector vAngles) +{ + m_vTargetAng = vAngles; +} + +/* +==================== +AimAt + +Make the bot face to the specified direction +==================== +*/ +void BotRotation::AimAt(Vector vPos) +{ + Vector vDelta = vPos - controlledEntity->EyePosition(); + + VectorNormalize(vDelta); + vectoangles(vDelta, m_vTargetAng); +} diff --git a/code/renderergl2/new/tr_world.c b/code/fgame/playerbot_strategy.cpp similarity index 84% rename from code/renderergl2/new/tr_world.c rename to code/fgame/playerbot_strategy.cpp index 2f55db4f..db8e8b83 100644 --- a/code/renderergl2/new/tr_world.c +++ b/code/fgame/playerbot_strategy.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,9 +20,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#include "../tr_local.h" +#include "g_local.h" +#include "playerbot_strategy.h" -void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs) -{ - // FIXME: unimplemented -} \ No newline at end of file +CLASS_DECLARATION(SimpleEntity, NavigationPoint, NULL) { + {NULL, NULL} +}; diff --git a/code/renderergl2/new/tr_bsp.c b/code/fgame/playerbot_strategy.h similarity index 76% rename from code/renderergl2/new/tr_bsp.c rename to code/fgame/playerbot_strategy.h index dacb52d7..8352e1f9 100644 --- a/code/renderergl2/new/tr_bsp.c +++ b/code/fgame/playerbot_strategy.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -19,16 +19,19 @@ along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +// playerbot_strategy.h: Bot strategy & navigation points -#include "../tr_local.h" +#pragma once -int RE_MapVersion(void) +#include "simpleentity.h" + +// +// Abstract class for navigation points +// +class NavigationPoint : public SimpleEntity { - // FIXME: unimplemented - return 0; -} +public: + CLASS_PROTOTYPE(NavigationPoint); -void RE_PrintBSPFileSizes(void) -{ - // FIXME: unimplemented -} + // TODO +}; diff --git a/code/fgame/playerstart.h b/code/fgame/playerstart.h index 37beee68..e856a2df 100644 --- a/code/fgame/playerstart.h +++ b/code/fgame/playerstart.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // PlayerStart.h: Player start location entity declarations // -#ifndef __PLAYERSTART_H__ -#define __PLAYERSTART_H__ +#pragma once #include "g_local.h" #include "simpleentity.h" @@ -89,5 +88,3 @@ class PlayerIntermission : public Camera CLASS_PROTOTYPE( PlayerIntermission ); PlayerIntermission(); }; - -#endif /* PlayerStart.h */ diff --git a/code/fgame/portableturret.cpp b/code/fgame/portableturret.cpp index e57f33ff..718d0bd0 100644 --- a/code/fgame/portableturret.cpp +++ b/code/fgame/portableturret.cpp @@ -22,6 +22,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "portableturret.h" #include "g_spawn.h" +#include "g_phys.h" +#include "player.h" Event EV_CarryableTurret_Drop ( @@ -61,23 +63,72 @@ Event EV_CarryableTurret_EnablePickup ); CLASS_DECLARATION(InventoryItem, CarryableTurret, NULL) { - {&EV_Touch, NULL }, - {&EV_Item_Pickup, &CarryableTurret::EventPickup }, - {&EV_CarryableTurret_Drop, &CarryableTurret::DropTurret }, - {&EV_CarryableTurret_TurretTik, &CarryableTurret::EventTurretTik }, - {&EV_CarryableTurret_Place, &CarryableTurret::EventPlaceTurret}, - {&EV_CarryableTurret_EnablePickup, &CarryableTurret::EventPickup }, - {NULL, NULL } + {&EV_Touch, NULL }, + {&EV_Item_Pickup, &CarryableTurret::EventPickup }, + {&EV_CarryableTurret_Drop, &CarryableTurret::DropTurret }, + {&EV_CarryableTurret_TurretTik, &CarryableTurret::EventTurretTik }, + {&EV_CarryableTurret_Place, &CarryableTurret::EventPlaceTurret }, + {&EV_CarryableTurret_EnablePickup, &CarryableTurret::EventEnablePickup}, + {NULL, NULL } }; CarryableTurret::CarryableTurret() { - // FIXME: unimplemented + if (LoadingSavegame) { + return; + } + + if (spawnflags & 1) { + Event *ev = new Event(EV_CarryableTurret_Place); + ev->AddInteger(1); + + PostEvent(ev, EV_POSTSPAWN); + } + + isPickable = true; } void CarryableTurret::EventPickup(Event *ev) { - // FIXME: unimplemented + Entity *ent; + Sentient *sent; + Item *item; + Weapon *activeWeap; + + if (!isPickable) { + return; + } + + ent = ev->GetEntity(1); + if (!Pickupable(ent)) { + // can't be picked up by the entity + return; + } + + sent = static_cast(ent); + if (sent->HasItem(item_name)) { + // already in possession of the carryable turret + return; + } + + item = ItemPickup(sent); + if (!item) { + // couldn't pick it up + return; + } + + if (!item->GetOwner()) { + // invalid owner?! + return; + } + + activeWeap = item->GetOwner()->GetActiveWeapon(WEAPON_MAIN); + if (activeWeap && activeWeap != item) { + activeWeap->DetachFromOwner(); + } + + // make the sentient use the carryable turret + item->GetOwner()->ChangeWeapon(static_cast(item), WEAPON_MAIN); } qboolean CarryableTurret::Removable(void) @@ -87,17 +138,37 @@ qboolean CarryableTurret::Removable(void) void CarryableTurret::DetachFromOwner(void) { - // FIXME: unimplemented + Weapon::DetachFromOwner(); + + PostEvent(EV_CarryableTurret_Drop, 0); } void CarryableTurret::AttachToHolster(weaponhand_t hand) { - // FIXME: unimplemented + Weapon::AttachToHolster(hand); + + PostEvent(EV_CarryableTurret_Drop, 0); } void CarryableTurret::DropTurret(Event *ev) { - // FIXME: unimplemented + Weapon *activeWeap; + Sentient *currentOwner; + + if (!owner) { + return; + } + + currentOwner = owner; + activeWeap = currentOwner->GetActiveWeapon(WEAPON_MAIN); + Drop(); + isPickable = false; + + PostEvent(EV_CarryableTurret_EnablePickup, 1.5f); + + if (activeWeap == this) { + currentOwner->edict->s.eFlags |= EF_UNARMED; + } } qboolean CarryableTurret::Drop(void) @@ -113,17 +184,293 @@ qboolean CarryableTurret::Drop(void) void CarryableTurret::EventTurretTik(Event *ev) { - // FIXME: unimplemented + turretModel = ev->GetString(1); } void CarryableTurret::EventPlaceTurret(Event *ev) { - // FIXME: unimplemented + Event *newev; + Player *ownerP; + Entity *placer; + Vector turretAngles, targetPos; + Vector forward, right, up; + Vector endpos, endpos2; + Vector start, end; + Vector mins, maxs; + trace_t trace; + float groundAngle; + bool autoPlace = false; + + if (ev->NumArgs() && ev->GetInteger(1)) { + autoPlace = true; + + AngleVectors(angles, forward, NULL, NULL); + mins = Vector(-32, -32, 0); + maxs = Vector(32, 32, 32); + start = origin; + end = origin - forward * 55; + + trace = + G_Trace(start, mins, maxs, end, this, MASK_CARRYABLETURRET, qtrue, "CarryableTurret::EventPlaceTurret1"); + + if (trace.startsolid || trace.fraction < 1 || trace.ent) { + gi.DPrintf( + "~*~*~ Not enough room to auto place portable turret at (%i %i %i)\n", + (int)origin[0], + (int)origin[1], + (int)origin[2] + ); + angles = Vector(-90, 0, 0); + setAngles(angles); + return; + } + + mins = Vector(-16, -16, 0); + maxs = Vector(16, 16, 8); + start = origin - forward * 55; + end = start; + end[2] -= 128; + + trace = + G_Trace(start, mins, maxs, end, this, MASK_CARRYABLETURRET, qtrue, "CarryableTurret::EventPlaceTurret1"); + + mins = Vector(-16, -16, 0); + maxs = Vector(16, 16, 95); + start = trace.endpos; + + trace = + G_Trace(start, mins, maxs, end, this, MASK_CARRYABLETURRET, qtrue, "CarryableTurret::EventPlaceTurret1"); + + if (trace.startsolid || trace.fraction < 1) { + gi.DPrintf( + "~*~*~ Not enough room to auto place portable turret at (%i %i %i)\n", + (int)origin[0], + (int)origin[1], + (int)origin[2] + ); + angles = Vector(-90, 0, 0); + setAngles(angles); + return; + } + + setOrigin(start); + angles[0] = 0; + angles[2] = 0; + setAngles(angles); + placer = this; + } else { + if (!owner) { + return; + } + + placer = owner; + + if (!placer->groundentity) { + return; + } + + if (placer->IsSubclassOfPlayer()) { + ownerP = static_cast(placer); + if (ownerP->client->ps.pm_flags & (PMF_NO_GRAVITY | PMF_VIEW_JUMP_START | PMF_VIEW_DUCK_RUN)) { + if (level.time > next_noammo_time) { + Sound(m_NoAmmoSound); + } + + next_noammo_time = FireDelay(FIRE_PRIMARY) + level.time + level.frametime; + ownerP->HUDPrint(va("%s\n", gi.LV_ConvertString("You cannot place a turret right now."))); + return; + } else if (ownerP->client->ps.pm_flags & PMF_DUCKED) { + mins = Vector(-16, -16, 0); + maxs = Vector(16, 16, 95); + start = placer->origin; + + trace = G_Trace( + start, mins, maxs, end, owner, MASK_PLAYERSOLID, qtrue, "CarryableTurret::EventPlaceTurret1" + ); + + if (trace.startsolid || trace.fraction < 1) { + if (level.time > next_noammo_time) { + Sound(m_NoAmmoSound); + } + + next_noammo_time = FireDelay(FIRE_PRIMARY) + level.time + level.frametime; + ownerP->HUDPrint(va("%s\n", gi.LV_ConvertString("Not enough room to place the turret."))); + return; + } + } + } + } + + turretAngles[0] = 0; + turretAngles[1] = placer->angles[1]; + turretAngles[2] = 0; + AngleVectors(turretAngles, forward, right, NULL); + + targetPos = placer->origin + forward * 55 + Vector(0, 0, 65.43f); + mins = Vector(-32, -32, -16); + maxs = Vector(32, 32, 8); + + trace = G_Trace( + targetPos, mins, maxs, targetPos, placer, MASK_CARRYABLETURRET, qtrue, "CarryableTurret::EventPlaceTurret1" + ); + if (trace.startsolid || trace.fraction < 1 || trace.ent) { + if (level.time > next_noammo_time) { + Sound(m_NoAmmoSound); + } + + next_noammo_time = FireDelay(FIRE_PRIMARY) + level.time + level.frametime; + if (autoPlace) { + gi.DPrintf("Not enough room to place the turret.\n"); + } else if (placer->IsSubclassOfPlayer()) { + ownerP->HUDPrint(va("%s\n", gi.LV_ConvertString("Not enough room to place the turret."))); + } + return; + } + + mins = Vector(-4, -4, 0); + maxs = Vector(4, 4, 4); + start = placer->origin + Vector(0, 0, 16) + right * 12; + end = start + Vector(0, 0, -128); + + trace = G_Trace( + start, mins, maxs, end, placer, CONTENTS_FENCE | CONTENTS_SOLID, qtrue, "CarryableTurret::EventPlaceTurret2" + ); + endpos = trace.endpos; + + start = placer->origin + Vector(0, 0, 16) - right * 12; + end = start + Vector(0, 0, -128); + + trace = G_Trace( + start, mins, maxs, end, placer, CONTENTS_FENCE | CONTENTS_SOLID, qtrue, "CarryableTurret::EventPlaceTurret2" + ); + endpos2 = trace.endpos; + + groundAngle = RAD2DEG(atan2(endpos[2] - endpos2[2], 12)); + if (fabs(groundAngle) > 40) { + if (level.time > next_noammo_time) { + Sound(m_NoAmmoSound); + } + + next_noammo_time = FireDelay(FIRE_PRIMARY) + level.time + level.frametime; + if (autoPlace) { + gi.DPrintf( + "Ground is too uneven to place the turret. (Too much ground roll to the side. Ground is at %g, limit " + "is %g)\n", + fabs(groundAngle), + 40.f + ); + } else if (placer->IsSubclassOfPlayer()) { + ownerP = static_cast(placer); + ownerP->HUDPrint(va("%s", gi.LV_ConvertString("Ground is too uneven to place the turret."))); + } + return; + } + mins = Vector(-2, -2, 0); + maxs = Vector(2, 2, 4); + start = targetPos + forward * 13; + end = start + Vector(0, 0, -129.43f); + + trace = G_Trace( + start, mins, maxs, end, placer, CONTENTS_FENCE | CONTENTS_SOLID, qtrue, "CarryableTurret::EventPlaceTurret2" + ); + + groundAngle = RAD2DEG(atan2(placer->origin[2] - trace.endpos[2], 55)); + if (fabs(groundAngle) > 30) { + if (level.time > next_noammo_time) { + Sound(m_NoAmmoSound); + } + + next_noammo_time = FireDelay(FIRE_PRIMARY) + level.time + level.frametime; + if (autoPlace) { + gi.DPrintf( + "Ground is too uneven to place the turret. (Too much ground pitch. Ground is at %g, limit is %g)\n", + fabs(groundAngle), + 30.f + ); + } else if (placer->IsSubclassOfPlayer()) { + Player *ownerP = static_cast(placer); + + ownerP->HUDPrint(va("%s", gi.LV_ConvertString("Ground is too uneven to place the turret."))); + } + return; + } + + turretAngles[0] = groundAngle; + AngleVectors(turretAngles, forward, NULL, up); + + targetPos = placer->origin + forward * 55 + up * 65.43f; + if (!turretModel.length()) { + gi.DPrintf("WARNING: Carryable turret item '%s' doesn't have a turrettik specified\n", model.c_str()); + return; + } + + ClassDef *c; + PortableTurret *ent; + SpawnArgs spawnArgs; + + spawnArgs.setArg("model", turretModel); + c = spawnArgs.getClassDef(); + if (!c || !checkInheritance(Entity::classinfostatic(), c)) { + gi.DPrintf( + "WARNING: Carryable turret item '%s' can't find turrettik '%s'\n", model.c_str(), turretModel.c_str() + ); + return; + } + + if (c != PortableTurret::classinfostatic()) { + gi.DPrintf( + "WARNING: Carryable turret item '%s' set to invalid turrettik '%s'\n", model.c_str(), turretModel.c_str() + ); + return; + } + + ent = static_cast(c->newInstance()); + ent->setModel(turretModel); + ent->setOrigin(placer->origin + forward * 32 + up * 65.43f); + ent->setAngles(turretAngles); + ent->ProcessInitCommands(); + ent->SetGroundPitch(turretAngles[0]); + ent->SetOwnerPosition(placer->origin); + ent->CancelEventsOfType(EV_Item_DropToFloor); + + if (autoPlace) { + newev = new Event(EV_Item_DropToFloor, 1); + newev->AddInteger(1); + ent->ProcessEvent(newev); + + ent->setOrigin(vec_zero); + PostEvent(EV_Remove, level.frametime); + } else { + ent->ProcessEvent(EV_Item_DropToFloor); + + DetachGun(); + RemoveFromOwner(); + setOrigin(vec_zero); + PostEvent(EV_Remove, level.frametime); + placer->velocity = vec_zero; + + newev = new Event(EV_Use, 1); + newev->AddEntity(placer); + ent->ProcessEvent(newev); + } } void CarryableTurret::EventEnablePickup(Event *ev) { - // FIXME: unimplemented + isPickable = true; +} + +bool CarryableTurret::IsCarryableTurret() const +{ + return true; +} + +void CarryableTurret::Archive(Archiver& arc) +{ + Weapon::Archive(arc); + + arc.ArchiveString(&turretModel); + arc.ArchiveBoolean(&isPickable); } CLASS_DECLARATION(TurretGun, PortableTurret, NULL) { @@ -134,60 +481,533 @@ CLASS_DECLARATION(TurretGun, PortableTurret, NULL) { PortableTurret::PortableTurret() { - // FIXME: unimplemented + groundPitch = 0.0; + nextUsableTime = 0.0; + packingUp = 0; + mustDetach = 0; + ammo_in_clip[0] = 0; + ammo_clip_size[0] = 0; + endReloadTime = 0.0; +} + +PortableTurret::~PortableTurret() +{ + if (baseEntity) { + baseEntity->ProcessEvent(EV_Remove); + baseEntity = NULL; + } + + TurretGun::RemoveUserCamera(); } void PortableTurret::SetGroundPitch(float pitch) { - // FIXME: unimplemented + groundPitch = pitch; } void PortableTurret::SetOwnerPosition(const Vector& pos) { - // FIXME: unimplemented + ownerPosition = pos + Vector(0, 0, 16); } void PortableTurret::PortablePlaceTurret(Event *ev) { - // FIXME: unimplemented + Vector turretAngles; + Vector forward, up; + bool attachPlayer = false; + char baseModel[1024]; + + PlaceTurret(ev); + if (ev->NumArgs() && ev->GetInteger(1)) { + attachPlayer = true; + } + + m_fPitchUpCap += groundPitch; + m_fPitchDownCap += groundPitch; + m_fMaxIdlePitch += groundPitch; + + m_pUserCamera = new Camera(); + currentModel = model; + + COM_StripExtension(model.c_str(), baseModel, sizeof(baseModel)); + strcat(baseModel, "_setup.tik"); + setupModel = CanonicalTikiName(baseModel); + + turretAngles[0] = groundPitch; + turretAngles[1] = m_fStartYaw; + turretAngles[2] = 0; + AngleVectors(turretAngles, forward, NULL, up); + + cameraOrigin = origin + (forward * m_vViewOffset[0]) + (up * m_vViewOffset[2]); + + if (attachPlayer) { + nextUsableTime = 0; + packingUp = false; + mustDetach = false; + + m_pUserCamera->setOrigin(origin); + m_pUserCamera->setAngles(angles); + + m_pUserCamera->SetPositionOffset(m_vViewOffset); + MakeBaseEntity(); + + endReloadTime = 0; + owner = NULL; + edict->r.ownerNum = ENTITYNUM_NONE; + + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + m_iFiring = 0; + + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + + ForceIdle(); + } else { + nextUsableTime = level.time + 2; + packingUp = false; + + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + + model = setupModel; + if (setModel()) { + ForceIdle(); + P_DeleteViewModel(); + mustDetach = true; + + m_pUserCamera->setOrigin(cameraOrigin); + m_pUserCamera->setAngles(turretAngles); + m_pUserCamera->SetPositionOffset(vec_zero); + } else { + Com_Printf("^~^~^PortableTurret::PortablePlaceTurret: Bad model name '%s'\n", setupModel.c_str()); + } + } } void PortableTurret::MakeBaseEntity() { - // FIXME: unimplemented + char baseModel[1024]; + Vector turretAngles; + + if (!baseEntity) { + COM_StripExtension(model, baseModel, sizeof(baseModel)); + strcat(baseModel, "_base.tik"); + baseEntity = new Entity(); + } + + baseEntity->takedamage = DAMAGE_NO; + baseEntity->setModel(baseModel); + baseEntity->setMoveType(MOVETYPE_NONE); + baseEntity->setSolidType(SOLID_NOT); + + baseEntity->setSize(Vector(4, 4, 4), Vector(-4, -4, -50)); + baseEntity->setOrigin(origin); + + turretAngles[0] = groundPitch; + turretAngles[1] = angles[1]; + turretAngles[2] = 0; + baseEntity->setAngles(turretAngles); } void PortableTurret::EventSetClipSize(Event *ev) { - // FIXME: unimplemented + ammo_clip_size[FIRE_PRIMARY] = ev->GetFloat(1); + ammo_in_clip[FIRE_PRIMARY] = ammo_clip_size[FIRE_PRIMARY]; } void PortableTurret::AbortTurretSetup() { - // FIXME: unimplemented + Sentient *currentOwner; + bool isPackingUp = packingUp; + + currentOwner = owner; + nextUsableTime = 0; + packingUp = false; + P_TurretEndUsed(); + + m_iFiring = 0; + + if (isPackingUp) { + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + + model = currentModel; + if (setModel()) { + ForceIdle(); + MakeBaseEntity(); + } else { + Com_Printf("^~^~^PortableTurret::P_ThinkActive: Bad model name '%s'\n", currentModel.c_str()); + } + } else { + Item *item; + + item = currentOwner->giveItem("weapons/mg42carryable.tik"); + if (item) { + item->Drop(); + } else { + gi.DPrintf("couldn't spawn carryable turret for player\n"); + } + + RemoveUserCamera(); + hideModel(); + setOrigin(vec_zero); + + PostEvent(EV_Remove, level.frametime); + + if (baseEntity) { + baseEntity->hideModel(); + baseEntity->setOrigin(vec_zero); + baseEntity->PostEvent(EV_Remove, level.frametime); + baseEntity = NULL; + } + } } void PortableTurret::P_UserAim(usercmd_t *cmd) { - // FIXME: unimplemented + bool doDetach = false; + + if (cmd->buttons & BUTTON_ATTACKRIGHT) { + if (!mustDetach) { + doDetach = true; + } + + mustDetach = true; + } else { + mustDetach = false; + } + + if (nextUsableTime > level.time) { + angles[0] = groundPitch; + angles[1] = m_fStartYaw; + + setAngles(angles); + + TurretGun::P_UserAim(cmd); + m_iFiring = 0; + flags |= FL_THINK; + } else if (doDetach) { + nextUsableTime = level.time + 2; + packingUp = true; + + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + + model = setupModel; + + if (setModel()) { + SetWeaponAnim("packup"); + + P_DeleteViewModel(); + + if (baseEntity) { + baseEntity->ProcessEvent(EV_Remove); + baseEntity = NULL; + } + } else { + Com_Printf("^~^~^PortableTurret::PortablePlaceTurret: Bad model name '%s'\n", model.c_str()); + } + } else { + TurretGun::P_UserAim(cmd); + } } void PortableTurret::P_TurretEndUsed() { - // FIXME: unimplemented + if (nextUsableTime > level.time) { + AbortTurretSetup(); + return; + } + + endReloadTime = 0; + TurretGun::P_TurretEndUsed(); + + RemoveUserCamera(); + ForceIdle(); } void PortableTurret::P_TurretBeginUsed(Player *pEnt) { - // FIXME: unimplemented + Event *ev; + Weapon *activeWeap; + + TurretGun::P_TurretBeginUsed(pEnt); + + activeWeap = pEnt->GetActiveWeapon(WEAPON_MAIN); + if (activeWeap && activeWeap->GetPutaway()) { + ev = new Event("deactivateweapon", 1); + ev->AddString("righthand"); + pEnt->PostEvent(ev, 0); + } + + ev = new Event("modheight", 1); + ev->AddString("stand"); + pEnt->ProcessEvent(ev); + + ev = new Event("moveposflags", 1); + ev->AddString("standing"); + pEnt->ProcessEvent(ev); } void PortableTurret::P_ThinkActive() { - // FIXME: unimplemented + Event *ev; + Weapon *activeWeap; + Entity *ent; + Player *ownerP = static_cast(owner.Pointer()); + + if (!ownerP->IsZoomed()) { + ownerP->ToggleZoom(80); + } + + owner->setOrigin(ownerPosition); + + if (nextUsableTime != 0) { + if (nextUsableTime > level.time) { + float yawCap; + + // cap the pitch + if (m_vUserViewAng[0] < m_fPitchUpCap) { + m_vUserViewAng[0] = m_fPitchUpCap; + } else if (m_vUserViewAng[0] > m_fPitchDownCap) { + m_vUserViewAng[0] = m_fPitchDownCap; + } + + yawCap = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + if (yawCap > m_fMaxYawOffset) { + yawCap = m_fMaxYawOffset; + } else if (yawCap < -m_fMaxYawOffset) { + yawCap = -m_fMaxYawOffset; + } + + m_vUserViewAng[1] = m_fStartYaw + yawCap; + // set the view angles + owner->SetViewAngles(m_vUserViewAng); + m_pUserCamera->setAngles(m_vUserViewAng); + + return; + } + + nextUsableTime = 0; + + if (packingUp) { + SpawnArgs spawnArgs; + ClassDef *c; + + ownerP->SetHolsteredByCode(false); + P_TurretEndUsed(); + + m_iFiring = 0; + + spawnArgs.setArg("model", "weapons/mg42carryable.tik"); + c = spawnArgs.getClassDef(); + if (c && checkInheritance(Entity::classinfostatic(), c)) { + ent = static_cast(c->newInstance()); + if (ent) { + activeWeap = ownerP->GetActiveWeapon(WEAPON_MAIN); + if (activeWeap) { + activeWeap->DetachFromOwner(); + } + + ent->setModel("weapons/mg42carryable.tik"); + ent->setOrigin(vec_zero); + ent->ProcessInitCommands(); + + ev = new Event(EV_Item_Pickup, 1); + ev->AddEntity(ownerP); + ent->ProcessEvent(ev); + ent->PostEvent(EV_Remove, 0); + } else { + gi.DPrintf("couldn't spawn carryable turret for player\n"); + } + + // remove the carryable turret entity and the base + hideModel(); + setOrigin(vec_zero); + PostEvent(EV_Remove, level.frametime); + + if (baseEntity) { + baseEntity->hideModel(); + baseEntity->setOrigin(vec_zero); + baseEntity->PostEvent(EV_Remove, level.frametime); + baseEntity = NULL; + } + } else { + gi.DPrintf("WARNING: couldn't spawn tiki '%s'\n", "weapons/mg42carryable.tik"); + } + + return; + } + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + StopWeaponAnim(); + + model = currentModel; + if (setModel()) { + ForceIdle(); + MakeBaseEntity(); + P_CreateViewModel(); + ForceIdle(); + } else { + Com_Printf("^~^~^PortableTurret::P_ThinkActive: Bad model name '%s'\n", currentModel.c_str()); + return; + } + } + + if (endReloadTime != 0) { + float yawCap; + Vector jittering; + + m_iFiring = 0; + if (endReloadTime < level.time) { + ammo_in_clip[FIRE_PRIMARY] = ammo_clip_size[FIRE_PRIMARY]; + endReloadTime = 0; + } + + // cap the pitch + if (m_vUserViewAng[0] < m_fPitchUpCap) { + m_vUserViewAng[0] = m_fPitchUpCap; + } else if (m_vUserViewAng[0] > m_fPitchDownCap) { + m_vUserViewAng[0] = m_fPitchDownCap; + } + + yawCap = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + if (yawCap > m_fMaxYawOffset) { + yawCap = m_fMaxYawOffset; + } else if (yawCap < -m_fMaxYawOffset) { + yawCap = -m_fMaxYawOffset; + } + + m_vUserViewAng[1] = m_fStartYaw + yawCap; + // set the view angles + owner->SetViewAngles(m_vUserViewAng); + m_pUserCamera->setAngles(m_vUserViewAng); + } else { + if (ammo_clip_size[FIRE_PRIMARY] && ammo_in_clip[FIRE_PRIMARY] > 0) { + float yawCap; + Vector delta; + Vector targetAngles; + Vector jittering; + + // cap the pitch + if (m_vUserViewAng[0] < m_fPitchUpCap) { + m_vUserViewAng[0] = m_fPitchUpCap; + } else if (m_vUserViewAng[0] > m_fPitchDownCap) { + m_vUserViewAng[0] = m_fPitchDownCap; + } + + yawCap = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + if (yawCap > m_fMaxYawOffset) { + yawCap = m_fMaxYawOffset; + } else if (yawCap < -m_fMaxYawOffset) { + yawCap = -m_fMaxYawOffset; + } + + m_vUserViewAng[1] = m_fStartYaw + yawCap; + // set the view angles + owner->SetViewAngles(m_vUserViewAng); + + delta = owner->GunTarget() - origin; + targetAngles = delta.toAngles(); + P_SetTargetAngles(targetAngles); + if (m_iFiring) { + m_iFiring = 4; + + if (ReadyToFire(FIRE_PRIMARY)) { + Fire(FIRE_PRIMARY); + m_fCurrViewJitter = m_fViewJitter; + if (ammo_clip_size[FIRE_PRIMARY]) { + // decrease the ammo count + ammo_in_clip[FIRE_PRIMARY]--; + } + } + } + + // apply some jitter + jittering = m_vUserViewAng; + P_ApplyFiringViewJitter(jittering); + m_pUserCamera->setOrigin(origin); + m_pUserCamera->setAngles(jittering); + m_pUserCamera->SetPositionOffset(m_vViewOffset); + ownerP->client->ps.camera_flags |= CF_CAMERA_ANGLES_TURRETMODE; + } else { + m_iFiring = 0; + endReloadTime = level.time + 1.5; + + angles[0] = GetGroundPitch(); + angles[1] = GetStartYaw(); + setAngles(angles); + + SetWeaponAnim("reload"); + } + } } void PortableTurret::P_TurretUsed(Player *player) { - // FIXME: unimplemented + if (player != owner) { + for (Player *p = static_cast(findradius(NULL, centroid, 50)); p; + p = static_cast(findradius(p, centroid, 50))) { + if (!p->IsSubclassOfPlayer()) { + continue; + } + + if (p != player && !p->IsSpectator() && !p->IsDead()) { + return; + } + } + } + + TurretGun::P_TurretUsed(player); +} + +float PortableTurret::GetGroundPitch() const +{ + return groundPitch; +} + +float PortableTurret::GetStartYaw() const +{ + return m_fStartYaw; +} + +bool PortableTurret::IsReloading() const +{ + return endReloadTime > level.time; +} + +bool PortableTurret::IsSettingUp() const +{ + return nextUsableTime > level.time && !packingUp; +} + +bool PortableTurret::IsPackingUp() const +{ + return nextUsableTime > level.time && packingUp; +} + +void PortableTurret::Archive(Archiver& arc) +{ + TurretGun::Archive(arc); + + arc.ArchiveSafePointer(&baseEntity); + arc.ArchiveFloat(&groundPitch); + arc.ArchiveVector(&ownerPosition); + arc.ArchiveFloat(&nextUsableTime); + arc.ArchiveBoolean(&packingUp); + arc.ArchiveBoolean(&mustDetach); + arc.ArchiveString(¤tModel); + arc.ArchiveString(&setupModel); + arc.ArchiveVector(&cameraOrigin); + arc.ArchiveFloat(&endReloadTime); } diff --git a/code/fgame/portableturret.h b/code/fgame/portableturret.h index ee91f60b..d24131cf 100644 --- a/code/fgame/portableturret.h +++ b/code/fgame/portableturret.h @@ -27,6 +27,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class CarryableTurret : public InventoryItem { +private: + str turretModel; + qboolean isPickable; + public: CLASS_PROTOTYPE(CarryableTurret); @@ -35,22 +39,39 @@ public: void EventPickup(Event *ev); qboolean Removable(void) override; - void DetachFromOwner(void); - void AttachToHolster(weaponhand_t hand); + void DetachFromOwner(void) override; + void AttachToHolster(weaponhand_t hand) override; void DropTurret(Event *ev); qboolean Drop(void) override; void EventTurretTik(Event *ev); void EventPlaceTurret(Event *ev); void EventEnablePickup(Event *ev); + + bool IsCarryableTurret() const override; + + void Archive(Archiver& arc) override; }; class PortableTurret : public TurretGun { +private: + EntityPtr baseEntity; + float groundPitch; + Vector ownerPosition; + float nextUsableTime; + qboolean packingUp; + qboolean mustDetach; + str currentModel; + str setupModel; + Vector cameraOrigin; + float endReloadTime; + public: CLASS_PROTOTYPE(PortableTurret); public: PortableTurret(); + ~PortableTurret(); void SetGroundPitch(float pitch); void SetOwnerPosition(const Vector& pos); @@ -64,4 +85,12 @@ public: void P_TurretBeginUsed(Player *pEnt) override; void P_ThinkActive() override; void P_TurretUsed(Player *player) override; + + float GetGroundPitch() const; + float GetStartYaw() const; + bool IsReloading() const; + bool IsSettingUp() const; + bool IsPackingUp() const; + + void Archive(Archiver& arc) override; }; diff --git a/code/fgame/portal.h b/code/fgame/portal.h index 1679378c..a7200819 100644 --- a/code/fgame/portal.h +++ b/code/fgame/portal.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // portal.h: // -#ifndef __PORTAL_H__ -#define __PORTAL_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -45,6 +44,3 @@ class PortalCamera : public Entity PortalCamera(); void Roll( Event *ev ); }; - -#endif // __PORTAL_H__ - diff --git a/code/fgame/scriptdelegate.cpp b/code/fgame/scriptdelegate.cpp new file mode 100644 index 00000000..636aa88c --- /dev/null +++ b/code/fgame/scriptdelegate.cpp @@ -0,0 +1,190 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "scriptdelegate.h" +#include "../script/scriptexception.h" + +ScriptDelegate *ScriptDelegate::root = NULL; + +ScriptRegisteredDelegate_Script::ScriptRegisteredDelegate_Script(const ScriptThreadLabel& inLabel) + : label(inLabel) +{} + +void ScriptRegisteredDelegate_Script::Execute(Listener *object, const Event& ev) +{ + Event newev = ev; + + label.Execute(object, newev); +} + +bool ScriptRegisteredDelegate_Script::operator==(const ScriptRegisteredDelegate_Script& registeredDelegate) const +{ + return label == registeredDelegate.label; +} + +ScriptRegisteredDelegate_CodeMember::ScriptRegisteredDelegate_CodeMember( + Class *inObject, DelegateClassResponse inResponse +) + : object(inObject) + , response(inResponse) +{} + +void ScriptRegisteredDelegate_CodeMember::Execute(Listener *object, const Event& ev) +{ + if (!object) { + return; + } + + (object->*response)(object, ev); +} + +bool ScriptRegisteredDelegate_CodeMember::operator==(const ScriptRegisteredDelegate_CodeMember& registeredDelegate +) const +{ + return object == registeredDelegate.object && response == registeredDelegate.response; +} + +ScriptRegisteredDelegate_Code::ScriptRegisteredDelegate_Code(DelegateResponse inResponse) + : response(inResponse) +{} + +void ScriptRegisteredDelegate_Code::Execute(Listener *object, const Event& ev) +{ + (*response)(object, ev); +} + +bool ScriptRegisteredDelegate_Code::operator==(const ScriptRegisteredDelegate_Code& registeredDelegate) const +{ + return response == registeredDelegate.response; +} + +ScriptDelegate::ScriptDelegate(const char *inName, const char *inDescription) + : name(inName) + , description(inDescription) +{ + LL_SafeAddFirst(root, this, next, prev); +} + +ScriptDelegate::~ScriptDelegate() +{ + LL_SafeRemoveRoot(root, this, next, prev); +} + +const ScriptDelegate *ScriptDelegate::GetRoot() +{ + return root; +} + +const ScriptDelegate *ScriptDelegate::GetNext() const +{ + return next; +} + +void ScriptDelegate::Register(const ScriptThreadLabel& label) +{ + if (!label.IsSet()) { + ScriptError("Invalid label specified for the script delegate"); + } + + list_script.AddUniqueObject(label); +} + +void ScriptDelegate::Unregister(const ScriptThreadLabel& label) +{ + list_script.RemoveObject(label); +} + +void ScriptDelegate::Register(ScriptRegisteredDelegate_Code::DelegateResponse response) +{ + list_code.AddUniqueObject(ScriptRegisteredDelegate_Code(response)); +} + +void ScriptDelegate::Unregister(ScriptRegisteredDelegate_Code::DelegateResponse response) +{ + list_code.RemoveObject(response); +} + +void ScriptDelegate::Register(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response) +{ + list_codeMember.AddUniqueObject(ScriptRegisteredDelegate_CodeMember(object, response)); +} + +void ScriptDelegate::Unregister(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response) +{ + list_codeMember.RemoveObject(ScriptRegisteredDelegate_CodeMember(object, response)); +} + +void ScriptDelegate::Trigger(const Event& ev) const +{ + Trigger(NULL, ev); +} + +void ScriptDelegate::Trigger(Listener *object, const Event& ev) const +{ + size_t i; + + { + const Container tmpList = list_script; + for (i = 1; i <= tmpList.NumObjects(); i++) { + tmpList.ObjectAt(i).Execute(object, ev); + } + } + + { + const Container tmpList = list_code; + for (i = 1; i <= tmpList.NumObjects(); i++) { + tmpList.ObjectAt(i).Execute(object, ev); + } + } + + { + const Container tmpList = list_codeMember; + for (i = 1; i <= tmpList.NumObjects(); i++) { + tmpList.ObjectAt(i).Execute(object, ev); + } + } +} + +ScriptDelegate *ScriptDelegate::GetScriptDelegate(const char *name) +{ + for (ScriptDelegate *delegate = root; delegate; delegate = delegate->next) { + if (!Q_stricmp(delegate->name, name)) { + return delegate; + } + } + + return NULL; +} + +void ScriptDelegate::Reset() +{ + list_script.FreeObjectList(); + list_code.FreeObjectList(); + list_codeMember.FreeObjectList(); +} + +void ScriptDelegate::ResetAllDelegates() +{ + for (ScriptDelegate *delegate = root; delegate; delegate = delegate->next) { + delegate->Reset(); + } +} diff --git a/code/fgame/scriptdelegate.h b/code/fgame/scriptdelegate.h new file mode 100644 index 00000000..0ff04923 --- /dev/null +++ b/code/fgame/scriptdelegate.h @@ -0,0 +1,196 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// scriptdelegate -- manages function delegate + +#include "../qcommon/listener.h" +#include "../qcommon/delegate.h" +#include "gamescript.h" + +class ScriptRegisteredDelegate +{ +public: + void Execute(Listener *object, const Event& ev); +}; + +/** + * Registered delegate, for scripts. + * It contains a ScriptThreadLabel with the game script and the label to execute. + */ +class ScriptRegisteredDelegate_Script : public ScriptRegisteredDelegate +{ +public: + ScriptRegisteredDelegate_Script(const ScriptThreadLabel& inLabel); + + void Execute(Listener *object, const Event& ev); + + bool operator==(const ScriptRegisteredDelegate_Script& registeredDelegate) const; + +private: + ScriptThreadLabel label; +}; + +/** + * Registered delegate, for code use. + * It contains the function to execute. + */ +class ScriptRegisteredDelegate_Code : public ScriptRegisteredDelegate +{ +public: + using DelegateResponse = void (*)(Listener *object, const Event& ev); + +public: + ScriptRegisteredDelegate_Code(DelegateResponse inResponse); + + void Execute(Listener *object, const Event& ev); + + bool operator==(const ScriptRegisteredDelegate_Code& registeredDelegate) const; + +private: + DelegateResponse response; +}; + +/** + * Registered delegate, for code use. + * It contains the object along the member function to execute. + * The function will not be executed if the object is NULL. + */ +class ScriptRegisteredDelegate_CodeMember : public ScriptRegisteredDelegate +{ +public: + using DelegateClassResponse = void (Class::*)(Listener *object, const Event& ev); + +public: + ScriptRegisteredDelegate_CodeMember(Class *inObject, DelegateClassResponse inResponse); + + void Execute(Listener *object, const Event& ev); + + bool operator==(const ScriptRegisteredDelegate_CodeMember& registeredDelegate) const; + +private: + SafePtr object; + DelegateClassResponse response; +}; + +/** + * A script delegate provides a way for code to subscribe for events. + * Scripts and code can register for a delegate and have their function executed + * when the delegate gets triggered. + */ +class ScriptDelegate +{ +public: + ScriptDelegate(const char *name, const char *description); + ~ScriptDelegate(); + + static const ScriptDelegate *GetRoot(); + const ScriptDelegate *GetNext() const; + + /** + * Register a script label. + * + * @param label The label to be executed + */ + void Register(const ScriptThreadLabel& label); + + /** + * Unregistered the label. + * + * @param label The label to unregister + */ + void Unregister(const ScriptThreadLabel& label); + + /** + * Register a function. + * + * @param response The function to be executed + */ + void Register(ScriptRegisteredDelegate_Code::DelegateResponse response); + + /** + * Unregistered the function. + * + * @param response the function to unregister + */ + void Unregister(ScriptRegisteredDelegate_Code::DelegateResponse response); + + /** + * Register with an object and a member function. + * + * @param object The object to notify + * @param response The member function of the object to be executed + */ + void Register(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response); + + /** + * Unregistered the member function. + * + * @param object The object where the member function is + * @param response The member function to unregister + */ + void Unregister(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response); + + /** + * Executes all registered delegates with the specified event. + * + * @param ev Parameter list + */ + void Trigger(const Event& ev = Event()) const; + + /** + * Executes all registered delegates with the specified event. + * + * @param ev Parameter list + */ + void Trigger(Listener *object, const Event& ev = Event()) const; + + /** + * Reset the delegate, unregister callbacks. + */ + void Reset(); + + /** + * Search and return the specified script delegate by name. + * + * @param name The name to search for + */ + static ScriptDelegate *GetScriptDelegate(const char *name); + static void ResetAllDelegates(); + + // non-movable and non-copyable + ScriptDelegate(ScriptDelegate&& other) = delete; + ScriptDelegate& operator=(ScriptDelegate&& other) = delete; + ScriptDelegate(const ScriptDelegate& other) = delete; + ScriptDelegate& operator=(const ScriptDelegate& other) = delete; + +private: + // Linked-list + ScriptDelegate *next; + ScriptDelegate *prev; + static ScriptDelegate *root; + const char *name; + const char *description; + + Container list_script; + Container list_code; + Container list_codeMember; +}; diff --git a/code/fgame/scriptmaster.cpp b/code/fgame/scriptmaster.cpp index 1544fd3b..6900dc42 100644 --- a/code/fgame/scriptmaster.cpp +++ b/code/fgame/scriptmaster.cpp @@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "game.h" #include "g_spawn.h" #include "object.h" -#include "world.h" +#include "worldspawn.h" #include "scriptcompiler.h" #include "scriptexception.h" @@ -82,7 +82,8 @@ CLASS_DECLARATION(Class, ScriptEvent, NULL) { // // world stuff // -Event EV_SetTiki( +Event EV_SetTiki +( "settiki", EV_DEFAULT, NULL, @@ -229,13 +230,14 @@ const char *ScriptMaster::ConstStrings[] = { "anim/shoot.scr", "anim/mg42_shoot.scr", "anim/mg42_idle.scr", - "anim_mg42_reload.scr", + "anim/mg42_reload.scr", "drive", "global/weapon.scr", "global/moveto.scr", "global/anim.scr", "global/anim_scripted.scr", "global/anim_noclip.scr", + "global/anim_attached.scr", "global/walkto.scr", "global/runto.scr", "aimat", @@ -252,7 +254,7 @@ const char *ScriptMaster::ConstStrings[] = { "anim/idle.scr", "anim/surprise.scr", "anim/standshock.scr", - "anim/standidentify", + "anim/standidentify.scr", "anim/standflinch.scr", "anim/dog_idle.scr", "anim/dog_attack.scr", @@ -260,6 +262,7 @@ const char *ScriptMaster::ConstStrings[] = { "anim/dog_chase.scr", "cannon", "grenade", + "badplace", "heavy", "item", "items", @@ -305,6 +308,7 @@ const char *ScriptMaster::ConstStrings[] = { "anim/killed.scr", "anim/attack.scr", "anim/sniper.scr", + "anim/suppress.scr", "knees", "crawl", "floor", @@ -335,13 +339,14 @@ const char *ScriptMaster::ConstStrings[] = { "anim/cornerleft.scr", "anim/cornerright.scr", "anim/overattack.scr", + "anim/lowwall.scr", + "anim/highwall.scr", "anim/continue_last_anim.scr", "flagged", "anim/fullbody.scr", - "internal", "salute", "sentry", - "officier", + "officer", "rover", "none", "machinegunner", @@ -394,12 +399,12 @@ const char *ScriptMaster::ConstStrings[] = { "anim/no_anim_killed.scr", "mg42", "mp40", + // Added in 2.0 "auto", "both", + // Added in 2.30 "runandshoot", - // - // Openmohaa additions - // + // Added in OPM "respawn", "viewmodelanim_done" }; @@ -435,24 +440,27 @@ static int bLoadForMap(char *psMapsBuffer, const char *name) return false; } -void ScriptMaster::RegisterAliasInternal(Event *ev, bool bCache) +void ScriptMaster::RegisterAliasAndCache(Event *ev) { - int i; - char parameters[MAX_STRING_CHARS]; - char *psMapsBuffer; - int subtitle; - bool bAlwaysLoaded = false; + int i; + char parameters[MAX_STRING_CHARS]; + char *psMapsBuffer; + bool bAlwaysLoaded = false; + + if (ev->NumArgs() < 2) { + return; + } // Get the parameters for this alias command parameters[0] = 0; - subtitle = 0; psMapsBuffer = NULL; for (i = 3; i <= ev->NumArgs(); i++) { str s; - // MOHAA doesn't check that + // Added in OPM + // MOHAA doesn't check that if (ev->IsListenerAt(i)) { Listener *l = ev->GetListener(i); @@ -465,44 +473,97 @@ void ScriptMaster::RegisterAliasInternal(Event *ev, bool bCache) s = ev->GetString(i); } - if (subtitle) { + if (!s.icmp("maps")) { + i++; + psMapsBuffer = (char *)ev->GetToken(i).c_str(); + continue; + } + + if (!s.icmp("always")) { + bAlwaysLoaded = true; + continue; + } + + strcat(parameters, s); + strcat(parameters, " "); + } + + if (bAlwaysLoaded) { + gi.GlobalAlias_Add(ev->GetString(1), ev->GetString(2), parameters); + } + + if (bLoadForMap(psMapsBuffer, ev->GetString(1))) { + if (!bAlwaysLoaded) { + gi.GlobalAlias_Add(ev->GetString(1), ev->GetString(2), parameters); + } + + CacheResource(ev->GetString(2)); + } +} + +void ScriptMaster::RegisterAlias(Event *ev) +{ + int i; + char parameters[MAX_STRING_CHARS]; + char *psMapsBuffer; + qboolean subtitle; + bool bAlwaysLoaded = false; + + if (ev->NumArgs() < 2) { + return; + } + + // Get the parameters for this alias command + + parameters[0] = 0; + subtitle = 0; + psMapsBuffer = NULL; + + for (i = 3; i <= ev->NumArgs(); i++) { + str s; + + // Added in OPM + // MOHAA doesn't check that + if (ev->IsListenerAt(i)) { + Listener *l = ev->GetListener(i); + + if (l && l == Director.CurrentThread()) { + s = "local"; + } else { + s = ev->GetString(i); + } + } else { + s = ev->GetString(i); + } + + if (!s.icmp("maps")) { + i++; + psMapsBuffer = (char *)ev->GetToken(i).c_str(); + continue; + } + + if (!s.icmp("always")) { + bAlwaysLoaded = true; + } else if (subtitle) { strcat(parameters, "\""); strcat(parameters, s); strcat(parameters, "\" "); subtitle = 0; - } else if (!s.icmp("maps")) { - i++; - psMapsBuffer = (char *)ev->GetToken(i).c_str(); - } else if (!s.icmp("always")) { - bAlwaysLoaded = true; } else { subtitle = s.icmp("subtitle") == 0; strcat(parameters, s); - strcat(parameters, " "); } + + strcat(parameters, " "); } if (bAlwaysLoaded || bLoadForMap(psMapsBuffer, ev->GetString(1))) { gi.GlobalAlias_Add(ev->GetString(1), ev->GetString(2), parameters); - - if (bCache) { - CacheResource(ev->GetString(2)); - } } } -void ScriptMaster::RegisterAliasAndCache(Event *ev) -{ - RegisterAliasInternal(ev, true); -} - -void ScriptMaster::RegisterAlias(Event *ev) -{ - RegisterAliasInternal(ev); -} - void ScriptMaster::Cache(Event *ev) { #ifdef GAME_DLL @@ -520,11 +581,21 @@ void ScriptMaster::InitConstStrings(void) const_str name; unsigned int eventnum; con_map_enum en; + int i; - for (int i = 0; i < sizeof(ConstStrings) / sizeof(ConstStrings[0]); i++) { + static_assert(ARRAY_LEN(ConstStrings) == (STRING_LENGTH_ - 1), "Constant strings don't match. Make sure the 'const_str' enum match with the 'ConstStrings' string array"); + + for (i = 0; i < ARRAY_LEN(ConstStrings); i++) { AddString(ConstStrings[i]); } + if (!Listener::EventSystemStarted) { + // Added in OPM + // This usually means the game module is getting destroyed + // most often, the event command list has been destroyed earlier + return; + } + Event::normalCommandList.clear(); Event::returnCommandList.clear(); Event::getterCommandList.clear(); @@ -536,7 +607,10 @@ void ScriptMaster::InitConstStrings(void) eventDef = en.CurrentValue(); eventnum = (*en.CurrentKey())->eventnum; str command = eventDef->command.c_str(); - command.tolower(); + + if (eventDef->type == EV_NORMAL || eventDef->type == EV_RETURN) { + command.tolower(); + } name = AddString(command); @@ -660,6 +734,10 @@ ScriptThread *ScriptMaster::CreateScriptThread(ScriptClass *scriptClass, str lab } } +ScriptMaster::ScriptMaster() +{ +} + void ScriptMaster::Reset(qboolean samemap) { ScriptClass_allocator.FreeAll(); @@ -688,45 +766,72 @@ void ScriptMaster::Reset(qboolean samemap) StringDict.clear(); InitConstStrings(); } + + ScriptDelegate::ResetAllDelegates(); } void ScriptMaster::ExecuteRunning(void) { int i; int startTime; + int startMs; + str fileName; + str sourcePosString; if (stackCount) { return; } - if (timerList.IsDirty()) { - cmdTime = 0; - cmdCount = 0; - startTime = level.svsTime; + if (!timerList.IsDirty()) { + return; + } + cmdTime = 0; + cmdCount = 0; + startTime = level.svsTime; + + try { while ((m_CurrentThread = (ScriptThread *)timerList.GetNextElement(i))) { + if (g_timescripts->integer) { + fileName = m_CurrentThread->FileName(); + sourcePosString = m_CurrentThread->m_ScriptVM->GetSourcePos(); + startMs = gi.Milliseconds(); + } + level.setTime(level.svsStartTime + i); m_CurrentThread->m_ScriptVM->m_ThreadState = THREAD_RUNNING; m_CurrentThread->m_ScriptVM->Execute(); - } - level.setTime(startTime); - level.m_LoopProtection = true; + if (g_timescripts->integer) { + str string; + + string = "Execute Running: "; + string += str(gi.Milliseconds() - startMs / 1000.f); + string += " file: "; + string += fileName; + string += " codepos: "; + string += sourcePosString; + + gi.DebugPrintf("%s\n", string.c_str()); + } + } + } catch (const ScriptException& e) { + gi.Error(ERR_DROP, "%s", e.string.c_str()); } - startTime = gi.Milliseconds(); + level.setTime(startTime); + level.m_LoopProtection = true; } void ScriptMaster::SetTime(int time) { timerList.SetTime(time); - timerList.SetDirty(); } -void ScriptMaster::AddTiming(ScriptThread *thread, float time) +void ScriptMaster::AddTiming(ScriptThread *thread, int time) { - timerList.AddElement(thread, level.inttime + (int)(time * 1000.0f + 0.5f)); + timerList.AddElement(thread, time); } void ScriptMaster::RemoveTiming(ScriptThread *thread) @@ -736,7 +841,7 @@ void ScriptMaster::RemoveTiming(ScriptThread *thread) ScriptClass *ScriptMaster::CurrentScriptClass(void) { - return CurrentThread()->GetScriptClass(); + return CurrentScriptThread()->GetScriptClass(); } void ScriptMaster::CloseGameScript(void) @@ -767,16 +872,16 @@ GameScript *ScriptMaster::GetGameScriptInternal(str& filename) gi.Error(ERR_DROP, "Script filename '%s' exceeds maximum length of %d\n", filename.c_str(), MAX_QPATH); } + Q_strncpyz(filepath, filename.c_str(), sizeof(filepath)); + gi.FS_CanonicalFilename(filepath); + filename = filepath; + scr = m_GameScripts[StringDict.findKeyIndex(filename)]; if (scr != NULL) { return scr; } - strcpy(filepath, filename.c_str()); - gi.FS_CanonicalFilename(filepath); - filename = filepath; - scr = new GameScript(filename); m_GameScripts[StringDict.addKeyIndex(filename)] = scr; @@ -895,44 +1000,59 @@ void ScriptMaster::ArchiveString(Archiver& arc, const_str& s) void ScriptMaster::Archive(Archiver& arc) { - ScriptClass *scr; - ScriptVM *m_current; - ScriptThread *m_thread; - int numClasses; - int numThreads; - int i, j; + int count; + int i, j; + ScriptClass *c; + int num; + ScriptVM *scriptVM; + ScriptVM *prevScriptVM; if (arc.Saving()) { - numClasses = (int)ScriptClass_allocator.Count(); - arc.ArchiveInteger(&numClasses); + count = (int)ScriptClass_allocator.Count(); + arc.ArchiveInteger(&count); MEM_BlockAlloc_enum en = ScriptClass_allocator; - for (scr = en.NextElement(); scr != NULL; scr = en.NextElement()) { - scr->ArchiveInternal(arc); + for (c = en.NextElement(); c != NULL; c = en.NextElement()) { + c->ArchiveInternal(arc); - numThreads = 0; - for (m_current = scr->m_Threads; m_current != NULL; m_current = m_current->next) { - numThreads++; + num = 0; + for (scriptVM = c->m_Threads; scriptVM != NULL; scriptVM = scriptVM->next) { + num++; } - arc.ArchiveInteger(&numThreads); + arc.ArchiveInteger(&num); - for (m_current = scr->m_Threads; m_current != NULL; m_current = m_current->next) { - m_current->m_Thread->ArchiveInternal(arc); + for (scriptVM = c->m_Threads; scriptVM != NULL; scriptVM = scriptVM->next) { + scriptVM->m_Thread->ArchiveInternal(arc); } } } else { - arc.ArchiveInteger(&numClasses); + arc.ArchiveInteger(&count); - for (i = 0; i < numClasses; i++) { - scr = new ScriptClass(); - scr->ArchiveInternal(arc); + for (i = 0; i < count; i++) { + c = new ScriptClass(); + c->ArchiveInternal(arc); - arc.ArchiveInteger(&numThreads); + arc.ArchiveInteger(&num); - for (j = 0; j < numThreads; j++) { - m_thread = new ScriptThread(scr, NULL); - m_thread->ArchiveInternal(arc); + c->m_Threads = NULL; + prevScriptVM = NULL; + + for (j = 0; j < num; j++) { + scriptVM = new ScriptVM; + scriptVM->m_Thread = new ScriptThread; + scriptVM->m_Thread->m_ScriptVM = scriptVM; + scriptVM->m_ScriptClass = c; + scriptVM->next = NULL; + + if (prevScriptVM) { + prevScriptVM->next = scriptVM; + } else { + c->m_Threads = scriptVM; + } + + prevScriptVM = scriptVM; + scriptVM->m_Thread->ArchiveInternal(arc); } } } @@ -985,7 +1105,6 @@ ScriptThread *ScriptMaster::CurrentThread(void) ScriptThread *ScriptMaster::CurrentScriptThread(void) { - assert(m_CurrentThread); if (!m_CurrentThread) { ScriptError("current thread is NULL"); } @@ -1027,7 +1146,8 @@ void ScriptMaster::Pause() void ScriptMaster::Unpause() { - if (iPaused-- == 1) { + iPaused--; + if (iPaused == 0) { ExecuteRunning(); } } @@ -1059,30 +1179,30 @@ void ScriptMaster::PrintStatus(void) ScriptVM *vm; for (vm = scriptClass->m_Threads; vm != NULL; vm = vm->next) { - sprintf(szBuffer, "%.7d", iThreadNum); + Com_sprintf(szBuffer, sizeof(szBuffer), "%.7d", iThreadNum); status += szBuffer + str(" "); switch (vm->ThreadState()) { case THREAD_RUNNING: - sprintf(szBuffer, "%8s", "running"); + Com_sprintf(szBuffer, sizeof(szBuffer), "%8s", "running"); iThreadRunning++; break; case THREAD_WAITING: - sprintf(szBuffer, "%8s", "waiting"); + Com_sprintf(szBuffer, sizeof(szBuffer), "%8s", "waiting"); iThreadWaiting++; break; case THREAD_SUSPENDED: - sprintf(szBuffer, "%8s", "suspended"); + Com_sprintf(szBuffer, sizeof(szBuffer), "%8s", "suspended"); iThreadSuspended++; break; } status += szBuffer; - sprintf(szBuffer, "%15s", vm->Label().c_str()); + Com_sprintf(szBuffer, sizeof(szBuffer), "%15s", vm->Label().c_str()); status += szBuffer + str(" "); - sprintf(szBuffer, "%15s", vm->Filename().c_str()); + Com_sprintf(szBuffer, sizeof(szBuffer), "%15s", vm->Filename().c_str()); status += szBuffer; status += "\n"; @@ -1148,12 +1268,12 @@ void ScriptMaster::PrintThread(int iThreadNum) if (!vm->m_Thread->m_WaitForList) { status += "(none)\n"; } else { - con_set_enum en = *vm->m_Thread->m_WaitForList; + con_set_enum en = *vm->m_Thread->m_WaitForList; con_set::Entry *entry; - int i = 0; + int i = 0; for (entry = en.NextElement(); entry != NULL; entry = en.NextElement()) { - str& name = Director.GetString(entry->key); + str& name = Director.GetString(entry->GetKey()); if (i > 0) { status += ", "; diff --git a/code/fgame/scriptmaster.h b/code/fgame/scriptmaster.h index 414f7fde..28faef7f 100644 --- a/code/fgame/scriptmaster.h +++ b/code/fgame/scriptmaster.h @@ -82,11 +82,11 @@ protected: void Cache(Event *ev); void RegisterAliasAndCache(Event *ev); void RegisterAlias(Event *ev); - void RegisterAliasInternal(Event *ev, bool bCache = false); public: CLASS_PROTOTYPE(ScriptMaster); + ScriptMaster(); virtual ~ScriptMaster(); // @@ -116,7 +116,7 @@ public: void SetTime(int time); - void AddTiming(ScriptThread *thread, float time); + void AddTiming(ScriptThread *thread, int time); void RemoveTiming(ScriptThread *thread); const_str AddString(const char *s); const_str AddString(str& s); diff --git a/code/fgame/scriptslave.cpp b/code/fgame/scriptslave.cpp index 6a4f7f31..b357820f 100644 --- a/code/fgame/scriptslave.cpp +++ b/code/fgame/scriptslave.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -43,6 +43,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "explosion.h" #include "game.h" #include "debuglines.h" +#include "weaputils.h" +#include "parm.h" /*****************************************************************************/ /*QUAKED script_object (0 0.5 1) ? NOT_SOLID @@ -50,2052 +52,1907 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ Event EV_ScriptSlave_DoMove - ( - "move", - EV_DEFAULT, - NULL, - NULL, - "Move the script slave.", - EV_NORMAL - ); +( + "move", + EV_DEFAULT, + NULL, + NULL, + "Move the script slave.", + EV_NORMAL +); Event EV_ScriptSlave_WaitMove - ( - "waitmove", - EV_DEFAULT, - NULL, - NULL, - "Move the script slave and wait until finished.", - EV_NORMAL - ); +( + "waitmove", + EV_DEFAULT, + NULL, + NULL, + "Move the script slave and wait until finished.", + EV_NORMAL +); +Event EV_ScriptSlave_Stop +( + "stop", + EV_DEFAULT, + NULL, + NULL, + "Stop the script slave." +); +Event EV_ScriptSlave_ThreadMove +( + "threadmove", + EV_DEFAULT, + "s", + "label", + "Move the script slave and create thread which waits until finished." +); Event EV_ScriptSlave_Angles - ( - "angles", - EV_DEFAULT, - "v", - "angles", - "Sets the angles.", - EV_NORMAL - ); +( + "angles", + EV_DEFAULT, + "v", + "angles", + "Sets the angles.", + EV_NORMAL +); Event EV_ScriptSlave_Trigger - ( - "trigger", - EV_DEFAULT, - "e", - "ent", - "Trigger entities target.", - EV_NORMAL - ); +( + "trigger", + EV_DEFAULT, + "e", + "ent", + "Trigger entities target.", + EV_NORMAL +); Event EV_ScriptSlave_Next - ( - "next", - EV_DEFAULT, - NULL, - NULL, - "Goto the next waypoint.", - EV_NORMAL - ); +( + "next", + EV_DEFAULT, + NULL, + NULL, + "Goto the next waypoint.", + EV_NORMAL +); Event EV_ScriptSlave_JumpTo - ( - "jumpto", - EV_DEFAULT, - "s", - "vector_or_entity", - "Jump to specified vector or entity.", - EV_NORMAL - ); +( + "jumpto", + EV_DEFAULT, + "s", + "vector_or_entity", + "Jump to specified vector or entity.", + EV_NORMAL +); Event EV_ScriptSlave_MoveTo - ( - "moveto", - EV_DEFAULT, - "s", - "vector_or_entity", - "Move to the specified vector or entity.", - EV_NORMAL - ); +( + "moveto", + EV_DEFAULT, + "s", + "vector_or_entity", + "Move to the specified vector or entity.", + EV_NORMAL +); Event EV_ScriptSlave_Speed - ( - "speed", - EV_DEFAULT, - "f", - "speed", - "Sets the speed.", - EV_NORMAL - ); +( + "speed", + EV_DEFAULT, + "f", + "speed", + "Sets the speed.", + EV_NORMAL +); Event EV_ScriptSlave_Time - ( - "time", - EV_DEFAULT, - "f", - "travel_time", - "Sets the travel time.", - EV_NORMAL - ); +( + "time", + EV_DEFAULT, + "f", + "travel_time", + "Sets the travel time.", + EV_NORMAL +); Event EV_ScriptSlave_MoveUp - ( - "moveUp", - EV_DEFAULT, - "f", - "dist", - "Move the position up.", - EV_NORMAL - ); +( + "moveUp", + EV_DEFAULT, + "f", + "dist", + "Move the position up.", + EV_NORMAL +); Event EV_ScriptSlave_MoveDown - ( - "moveDown", - EV_DEFAULT, - "f", - "dist", - "Move the position down.", - EV_NORMAL - ); +( + "moveDown", + EV_DEFAULT, + "f", + "dist", + "Move the position down.", + EV_NORMAL +); Event EV_ScriptSlave_MoveNorth - ( - "moveNorth", - EV_DEFAULT, - "f", - "dist", - "Move the position north.", - EV_NORMAL - ); +( + "moveNorth", + EV_DEFAULT, + "f", + "dist", + "Move the position north.", + EV_NORMAL +); Event EV_ScriptSlave_MoveSouth - ( - "moveSouth", - EV_DEFAULT, - "f", - "dist", - "Move the position south.", - EV_NORMAL - ); +( + "moveSouth", + EV_DEFAULT, + "f", + "dist", + "Move the position south.", + EV_NORMAL +); Event EV_ScriptSlave_MoveEast - ( - "moveEast", - EV_DEFAULT, - "f", - "dist", - "Move the position east.", - EV_NORMAL - ); +( + "moveEast", + EV_DEFAULT, + "f", + "dist", + "Move the position east.", + EV_NORMAL +); Event EV_ScriptSlave_MoveWest - ( - "moveWest", - EV_DEFAULT, - "f", - "dist", - "Move the position west.", - EV_NORMAL - ); +( + "moveWest", + EV_DEFAULT, + "f", + "dist", + "Move the position west.", + EV_NORMAL +); Event EV_ScriptSlave_MoveForward - ( - "moveForward", - EV_DEFAULT, - "f", - "dist", - "Move the position forward.", - EV_NORMAL - ); +( + "moveForward", + EV_DEFAULT, + "f", + "dist", + "Move the position forward.", + EV_NORMAL +); Event EV_ScriptSlave_MoveBackward - ( - "moveBackward", - EV_DEFAULT, - "f", - "dist", - "Move the position backward.", - EV_NORMAL - ); +( + "moveBackward", + EV_DEFAULT, + "f", + "dist", + "Move the position backward.", + EV_NORMAL +); Event EV_ScriptSlave_MoveLeft - ( - "moveLeft", - EV_DEFAULT, - "f", - "dist", - "Move the position left.", - EV_NORMAL - ); +( + "moveLeft", + EV_DEFAULT, + "f", + "dist", + "Move the position left.", + EV_NORMAL +); Event EV_ScriptSlave_MoveRight - ( - "moveRight", - EV_DEFAULT, - "f", - "dist", - "Move the position right.", - EV_NORMAL - ); +( + "moveRight", + EV_DEFAULT, + "f", + "dist", + "Move the position right.", + EV_NORMAL +); +Event EV_ScriptSlave_MoveOffset +( + "moveOffset", + EV_DEFAULT, + "v", + "dist", + "Move the position by the offset vector.", + EV_NORMAL +); Event EV_ScriptSlave_RotateXDownTo - ( - "rotateXdownto", - EV_DEFAULT, - "f", - "angle", - "Rotate the x down to angle.", - EV_NORMAL - ); +( + "rotateXdownto", + EV_DEFAULT, + "f", + "angle", + "Rotate the x down to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateYDownTo - ( - "rotateYdownto", - EV_DEFAULT, - "f", - "angle", - "Rotate the y down to angle.", - EV_NORMAL - ); +( + "rotateYdownto", + EV_DEFAULT, + "f", + "angle", + "Rotate the y down to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateZDownTo - ( - "rotateZdownto", - EV_DEFAULT, - "f", - "angle", - "Rotate the z down to angle.", - EV_NORMAL - ); +( + "rotateZdownto", + EV_DEFAULT, + "f", + "angle", + "Rotate the z down to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateAxisDownTo - ( - "rotateaxisdownto", - EV_DEFAULT, - "if", - "axis angle", - "Rotate the specified axis down to angle.", - EV_NORMAL - ); +( + "rotateaxisdownto", + EV_DEFAULT, + "if", + "axis angle", + "Rotate the specified axis down to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateXUpTo - ( - "rotateXupto", - EV_DEFAULT, - "f", - "angle", - "Rotate the x up to angle.", - EV_NORMAL - ); +( + "rotateXupto", + EV_DEFAULT, + "f", + "angle", + "Rotate the x up to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateYUpTo - ( - "rotateYupto", - EV_DEFAULT, - "f", - "angle", - "Rotate the y up to angle.", - EV_NORMAL - ); +( + "rotateYupto", + EV_DEFAULT, + "f", + "angle", + "Rotate the y up to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateZUpTo - ( - "rotateZupto", - EV_DEFAULT, - "f", - "angle", - "Rotate the z up to angle.", - EV_NORMAL - ); +( + "rotateZupto", + EV_DEFAULT, + "f", + "angle", + "Rotate the z up to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateAxisUpTo - ( - "rotateaxisupto", - EV_DEFAULT, - "if", - "axis angle", - "Rotate the specified axis up to angle.", - EV_NORMAL - ); +( + "rotateaxisupto", + EV_DEFAULT, + "if", + "axis angle", + "Rotate the specified axis up to angle.", + EV_NORMAL +); Event EV_ScriptSlave_RotateXDown - ( - "rotateXdown", - EV_DEFAULT, - "f", - "angle", - "Rotate the x down by the specified amount.", - EV_NORMAL - ); +( + "rotateXdown", + EV_DEFAULT, + "f", + "angle", + "Rotate the x down by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateYDown - ( - "rotateYdown", - EV_DEFAULT, - "f", - "angle", - "Rotate the y down by the specified amount.", - EV_NORMAL - ); +( + "rotateYdown", + EV_DEFAULT, + "f", + "angle", + "Rotate the y down by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateZDown - ( - "rotateZdown", - EV_DEFAULT, - "f", - "angle", - "Rotate the z down by the specified amount.", - EV_NORMAL - ); +( + "rotateZdown", + EV_DEFAULT, + "f", + "angle", + "Rotate the z down by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateAxisDown - ( - "rotateaxisdown", - EV_DEFAULT, - "if", - "axis angle", - "Rotate the specified axis down by the specified amount.", - EV_NORMAL - ); +( + "rotateaxisdown", + EV_DEFAULT, + "if", + "axis angle", + "Rotate the specified axis down by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateXUp - ( - "rotateXup", - EV_DEFAULT, - "f", - "angle", - "Rotate the x up by the specified amount.", - EV_NORMAL - ); +( + "rotateXup", + EV_DEFAULT, + "f", + "angle", + "Rotate the x up by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateYUp - ( - "rotateYup", - EV_DEFAULT, - "f", - "angle", - "Rotate the y up by the specified amount.", - EV_NORMAL - ); +( + "rotateYup", + EV_DEFAULT, + "f", + "angle", + "Rotate the y up by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateZUp - ( - "rotateZup", - EV_DEFAULT, - "f", - "angle", - "Rotate the z up by the specified amount.", - EV_NORMAL - ); +( + "rotateZup", + EV_DEFAULT, + "f", + "angle", + "Rotate the z up by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateAxisUp - ( - "rotateaxisup", - EV_DEFAULT, - "if", - "axis angle", - "Rotate the specified axis up by the specified amount.", - EV_NORMAL - ); +( + "rotateaxisup", + EV_DEFAULT, + "if", + "axis angle", + "Rotate the specified axis up by the specified amount.", + EV_NORMAL +); Event EV_ScriptSlave_RotateX - ( - "rotateX", - EV_DEFAULT, - "f", - "avelocity", - "Rotate about the x axis at the specified angular velocity.", - EV_NORMAL - ); +( + "rotateX", + EV_DEFAULT, + "f", + "avelocity", + "Rotate about the x axis at the specified angular velocity.", + EV_NORMAL +); Event EV_ScriptSlave_RotateY - ( - "rotateY", - EV_DEFAULT, - "f", - "avelocity", - "Rotate about the y axis at the specified angular velocity.", - EV_NORMAL - ); +( + "rotateY", + EV_DEFAULT, + "f", + "avelocity", + "Rotate about the y axis at the specified angular velocity.", + EV_NORMAL +); Event EV_ScriptSlave_RotateZ - ( - "rotateZ", - EV_DEFAULT, - "f", - "avelocity", - "Rotate about the z axis at the specified angular velocity.", - EV_NORMAL - ); +( + "rotateZ", + EV_DEFAULT, + "f", + "avelocity", + "Rotate about the z axis at the specified angular velocity.", + EV_NORMAL +); Event EV_ScriptSlave_RotateAxis - ( - "rotateaxis", - EV_DEFAULT, - "if", - "axis avelocity", - "Rotate about the specified axis at the specified angular velocity.", - EV_NORMAL - ); +( + "rotateaxis", + EV_DEFAULT, + "if", + "axis avelocity", + "Rotate about the specified axis at the specified angular velocity.", + EV_NORMAL +); Event EV_ScriptSlave_RotateDownTo - ( - "rotatedownto", - EV_DEFAULT, - "v", - "direction", - "Rotate down to the specified direction.", - EV_NORMAL - ); +( + "rotatedownto", + EV_DEFAULT, + "v", + "direction", + "Rotate down to the specified direction.", + EV_NORMAL +); Event EV_ScriptSlave_RotateUpTo - ( - "rotateupto", - EV_DEFAULT, - "v", - "direction", - "Rotate up to the specified direction.", - EV_NORMAL - ); +( + "rotateupto", + EV_DEFAULT, + "v", + "direction", + "Rotate up to the specified direction.", + EV_NORMAL +); Event EV_ScriptSlave_RotateTo - ( - "rotateto", - EV_DEFAULT, - "v", - "direction", - "Rotate to the specified direction.", - EV_NORMAL - ); +( + "rotateto", + EV_DEFAULT, + "v", + "direction", + "Rotate to the specified direction.", + EV_NORMAL +); Event EV_ScriptSlave_SetDamage - ( - "setdamage", - EV_DEFAULT, - "i", - "damage", - "Set the damage.", - EV_NORMAL - ); +( + "setdamage", + EV_DEFAULT, + "i", + "damage", + "Set the damage.", + EV_NORMAL +); Event EV_ScriptSlave_SetMeansOfDeath - ( - "setmeansofdeath", - EV_DEFAULT, - "s", - "means_of_death", - "Set the damage means of death.", - EV_NORMAL - ); +( + "setmeansofdeath", + EV_DEFAULT, + "s", + "means_of_death", + "Set the damage means of death.", + EV_NORMAL +); Event EV_ScriptSlave_SetDamageSpawn - ( - "dmg", - EV_DEFAULT, - "i", - "damage", - "Set the damage.", - EV_NORMAL - ); +( + "dmg", + EV_DEFAULT, + "i", + "damage", + "Set the damage.", + EV_NORMAL +); Event EV_ScriptSlave_FollowPath - ( - "followpath", - EV_DEFAULT, - "eSSSSSS", - "path arg1 arg2 arg3 arg4 arg5 arg6", - "Makes the script slave follow the specified path. The allowable arguments are ignoreangles,\n" - "normalangles, loop, and a number specifying the start time.", - EV_NORMAL - ); +( + "followpath", + EV_DEFAULT, + "eSSSSSS", + "path arg1 arg2 arg3 arg4 arg5 arg6", + "Makes the script slave follow the specified path. The allowable arguments are ignoreangles,\n" + "ignorevelocity, normalangles, loop, and a number specifying the start time.", + EV_NORMAL +); +Event EV_ScriptSlave_FollowPath_RelativeYaw +( + "path_relativeyaw", + EV_DEFAULT, + "f", + "relativeYaw", + "Makes the script slave follow the specified path with a yaw offset,", + EV_NORMAL +); Event EV_ScriptSlave_EndPath - ( - "endpath", - EV_DEFAULT, - NULL, - NULL, - "Stop following the path", - EV_NORMAL - ); +( + "endpath", + EV_DEFAULT, + NULL, + NULL, + "Stop following the path", + EV_NORMAL +); Event EV_ScriptSlave_MoveDone - ( - "scriptslave_movedone", - EV_DEFAULT, - NULL, - NULL, - "Called when the script slave is doen moving", - EV_NORMAL - ); +( + "scriptslave_movedone", + EV_DEFAULT, + NULL, + NULL, + "Called when the script slave is doen moving", + EV_NORMAL +); Event EV_ScriptSlave_FollowingPath - ( - "scriptslave_followingpath", - EV_DEFAULT, - NULL, - NULL, - "Called every frame to actually follow the path", - EV_NORMAL - ); +( + "scriptslave_followingpath", + EV_DEFAULT, + NULL, + NULL, + "Called every frame to actually follow the path", + EV_NORMAL +); Event EV_ScriptSlave_Explode - ( - "explode", - EV_DEFAULT, - "f", - "damage", - "Creates an explosion at the script slave's position", - EV_NORMAL - ); +( + "explode", + EV_DEFAULT, + "f", + "damage", + "Creates an explosion at the script slave's position", + EV_NORMAL +); Event EV_ScriptSlave_NotShootable - ( - "notshootable", - EV_DEFAULT, - NULL, - NULL, - "Makes the script slave not shootable", - EV_NORMAL - ); +( + "notshootable", + EV_DEFAULT, + NULL, + NULL, + "Makes the script slave not shootable", + EV_NORMAL +); Event EV_ScriptSlave_OpenAreaPortal - ( - "openportal", - EV_DEFAULT, - NULL, - NULL, - "Open the area portal enclosed in this object", - EV_NORMAL - ); +( + "openportal", + EV_DEFAULT, + NULL, + NULL, + "Open the area portal enclosed in this object", + EV_NORMAL +); Event EV_ScriptSlave_CloseAreaPortal - ( - "closeportal", - EV_DEFAULT, - NULL, - NULL, - "Close the area portal enclosed in this object", - EV_NORMAL - ); +( + "closeportal", + EV_DEFAULT, + NULL, + NULL, + "Close the area portal enclosed in this object", + EV_NORMAL +); Event EV_ScriptSlave_PhysicsOn - ( - "physics_on", - EV_DEFAULT, - "I", - "no_collide_entity", - "Turn physics on this script object on\n" - "If no_collide_entity is set to 1 then the script slave will not collide with other entities", - EV_NORMAL - ); +( + "physics_on", + EV_DEFAULT, + "I", + "no_collide_entity", + "Turn physics on this script object on\n" + "If no_collide_entity is set to 1 then the script slave will not collide with other entities", + EV_NORMAL +); Event EV_ScriptSlave_PhysicsOff - ( - "physics_off", - EV_DEFAULT, - NULL, - NULL, - "Turn physics off this script object on", - EV_NORMAL - ); +( + "physics_off", + EV_DEFAULT, + NULL, + NULL, + "Turn physics off this script object on", + EV_NORMAL +); Event EV_ScriptSlave_PhysicsVelocity - ( - "physics_velocity", - EV_DEFAULT, - "v", - "impulseVector", - "Add a physical impulse to an object when it is being physically simulated", - EV_NORMAL - ); +( + "physics_velocity", + EV_DEFAULT, + "v", + "impulseVector", + "Add a physical impulse to an object when it is being physically simulated", + EV_NORMAL +); Event EV_ScriptSlave_FlyPath - ( - "flypath", - EV_DEFAULT, - "efff", - "array speed acceleration look_ahead", - "Makes the script slave fly the specified path with speed and acceleration until reached_distance close to position", - EV_NORMAL - ); +( + "flypath", + EV_DEFAULT, + "efff", + "array speed acceleration look_ahead", + "Makes the script slave fly the specified path with speed and acceleration until reached_distance close to " + "position", + EV_NORMAL +); Event EV_ScriptSlave_ModifyFlyPath - ( - "modifyflypath", - EV_DEFAULT, - "efff", - "array speed acceleration look_ahead", - "Makes the script slave fly the specified path with speed and acceleration until reached_distance close to position", - EV_NORMAL - ); +( + "modifyflypath", + EV_DEFAULT, + "efff", + "array speed acceleration look_ahead", + "Makes the script slave fly the specified path with speed and acceleration until reached_distance close to " + "position", + EV_NORMAL +); -CLASS_DECLARATION( Mover, ScriptSlave, "script_object" ) -{ - { &EV_Bind, &ScriptSlave::BindEvent }, - { &EV_Unbind, &ScriptSlave::EventUnbind }, - { &EV_ScriptSlave_DoMove, &ScriptSlave::DoMove }, - { &EV_ScriptSlave_WaitMove, &ScriptSlave::WaitMove }, - { &EV_ScriptSlave_Angles, &ScriptSlave::SetAnglesEvent }, - { &EV_SetAngle, &ScriptSlave::SetAngleEvent }, - { &EV_Model, &ScriptSlave::SetModelEvent }, - { &EV_ScriptSlave_Trigger, &ScriptSlave::TriggerEvent }, - { &EV_ScriptSlave_Next, &ScriptSlave::GotoNextWaypoint }, - { &EV_ScriptSlave_JumpTo, &ScriptSlave::JumpTo }, - { &EV_ScriptSlave_MoveTo, &ScriptSlave::MoveToEvent }, - { &EV_ScriptSlave_Speed, &ScriptSlave::SetSpeed }, - { &EV_ScriptSlave_Time, &ScriptSlave::SetTime }, - { &EV_ScriptSlave_MoveUp, &ScriptSlave::MoveUp }, - { &EV_ScriptSlave_MoveDown, &ScriptSlave::MoveDown }, - { &EV_ScriptSlave_MoveNorth, &ScriptSlave::MoveNorth }, - { &EV_ScriptSlave_MoveSouth, &ScriptSlave::MoveSouth }, - { &EV_ScriptSlave_MoveEast, &ScriptSlave::MoveEast }, - { &EV_ScriptSlave_MoveWest, &ScriptSlave::MoveWest }, - { &EV_ScriptSlave_MoveForward, &ScriptSlave::MoveForward }, - { &EV_ScriptSlave_MoveBackward, &ScriptSlave::MoveBackward }, - { &EV_ScriptSlave_MoveLeft, &ScriptSlave::MoveLeft }, - { &EV_ScriptSlave_MoveRight, &ScriptSlave::MoveRight }, - { &EV_ScriptSlave_RotateXDownTo, &ScriptSlave::RotateXdownto }, - { &EV_ScriptSlave_RotateYDownTo, &ScriptSlave::RotateYdownto }, - { &EV_ScriptSlave_RotateZDownTo, &ScriptSlave::RotateZdownto }, - { &EV_ScriptSlave_RotateXUpTo, &ScriptSlave::RotateXupto }, - { &EV_ScriptSlave_RotateYUpTo, &ScriptSlave::RotateYupto }, - { &EV_ScriptSlave_RotateZUpTo, &ScriptSlave::RotateZupto }, - { &EV_ScriptSlave_RotateXDown, &ScriptSlave::RotateXdown }, - { &EV_ScriptSlave_RotateYDown, &ScriptSlave::RotateYdown }, - { &EV_ScriptSlave_RotateZDown, &ScriptSlave::RotateZdown }, - { &EV_ScriptSlave_RotateXUp, &ScriptSlave::RotateXup }, - { &EV_ScriptSlave_RotateYUp, &ScriptSlave::RotateYup }, - { &EV_ScriptSlave_RotateZUp, &ScriptSlave::RotateZup }, - { &EV_ScriptSlave_RotateX, &ScriptSlave::RotateX }, - { &EV_ScriptSlave_RotateY, &ScriptSlave::RotateY }, - { &EV_ScriptSlave_RotateZ, &ScriptSlave::RotateZ }, - { &EV_ScriptSlave_RotateAxisDownTo, &ScriptSlave::RotateAxisdownto }, - { &EV_ScriptSlave_RotateAxisUpTo, &ScriptSlave::RotateAxisupto }, - { &EV_ScriptSlave_RotateAxisDown, &ScriptSlave::RotateAxisdown }, - { &EV_ScriptSlave_RotateAxisUp, &ScriptSlave::RotateAxisup }, - { &EV_ScriptSlave_RotateAxis, &ScriptSlave::RotateZ }, - { &EV_ScriptSlave_SetDamage, &ScriptSlave::SetDamage }, - { &EV_ScriptSlave_SetMeansOfDeath, &ScriptSlave::SetMeansOfDeath }, - { &EV_ScriptSlave_SetDamageSpawn, &ScriptSlave::SetDamage }, - { &EV_ScriptSlave_FollowPath, &ScriptSlave::FollowPath }, - { &EV_ScriptSlave_EndPath, &ScriptSlave::EndPath }, - { &EV_ScriptSlave_FollowingPath, &ScriptSlave::FollowingPath }, - { &EV_ScriptSlave_MoveDone, &ScriptSlave::MoveEnd }, - { &EV_Damage, &ScriptSlave::DamageFunc }, - { &EV_ScriptSlave_RotateDownTo, &ScriptSlave::Rotatedownto }, - { &EV_ScriptSlave_RotateUpTo, &ScriptSlave::Rotateupto }, - { &EV_ScriptSlave_RotateTo, &ScriptSlave::Rotateto }, - { &EV_ScriptSlave_Explode, &ScriptSlave::Explode }, - { &EV_ScriptSlave_NotShootable, &ScriptSlave::NotShootable }, - { &EV_ScriptSlave_OpenAreaPortal, &ScriptSlave::OpenPortal }, - { &EV_ScriptSlave_CloseAreaPortal, &ScriptSlave::ClosePortal }, - { &EV_ScriptSlave_PhysicsOn, &ScriptSlave::PhysicsOn }, - { &EV_ScriptSlave_PhysicsOff, &ScriptSlave::PhysicsOff }, - { &EV_ScriptSlave_PhysicsVelocity, &ScriptSlave::PhysicsVelocity }, - { &EV_ScriptSlave_FlyPath, &ScriptSlave::EventFlyPath }, - { &EV_ScriptSlave_ModifyFlyPath, &ScriptSlave::EventModifyFlyPath }, +Event EV_ScriptSlave_NormalAngles +( + "normalangles", + EV_DEFAULT, + "b", + "bUseNormalAngles", + "Sets the object to use normal angles when travelling on a spline path", + EV_NORMAL +); - { NULL, NULL } +CLASS_DECLARATION(Mover, ScriptSlave, "script_object") { + {&EV_Bind, &ScriptSlave::BindEvent }, + {&EV_Unbind, &ScriptSlave::EventUnbind }, + {&EV_ScriptSlave_DoMove, &ScriptSlave::DoMove }, + {&EV_ScriptSlave_WaitMove, &ScriptSlave::WaitMove }, + {&EV_ScriptSlave_Stop, &ScriptSlave::Stop }, + {&EV_ScriptSlave_ThreadMove, &ScriptSlave::ThreadMove }, + {&EV_ScriptSlave_Angles, &ScriptSlave::SetAnglesEvent }, + {&EV_SetAngle, &ScriptSlave::SetAngleEvent }, + {&EV_Model, &ScriptSlave::SetModelEvent }, + {&EV_ScriptSlave_Trigger, &ScriptSlave::TriggerEvent }, + {&EV_ScriptSlave_Next, &ScriptSlave::GotoNextWaypoint }, + {&EV_ScriptSlave_JumpTo, &ScriptSlave::JumpTo }, + {&EV_ScriptSlave_MoveTo, &ScriptSlave::MoveToEvent }, + {&EV_ScriptSlave_Speed, &ScriptSlave::SetSpeed }, + {&EV_ScriptSlave_Time, &ScriptSlave::SetTime }, + {&EV_ScriptSlave_MoveUp, &ScriptSlave::MoveUp }, + {&EV_ScriptSlave_MoveDown, &ScriptSlave::MoveDown }, + {&EV_ScriptSlave_MoveNorth, &ScriptSlave::MoveNorth }, + {&EV_ScriptSlave_MoveSouth, &ScriptSlave::MoveSouth }, + {&EV_ScriptSlave_MoveEast, &ScriptSlave::MoveEast }, + {&EV_ScriptSlave_MoveWest, &ScriptSlave::MoveWest }, + {&EV_ScriptSlave_MoveForward, &ScriptSlave::MoveForward }, + {&EV_ScriptSlave_MoveBackward, &ScriptSlave::MoveBackward }, + {&EV_ScriptSlave_MoveLeft, &ScriptSlave::MoveLeft }, + {&EV_ScriptSlave_MoveRight, &ScriptSlave::MoveRight }, + {&EV_ScriptSlave_MoveOffset, &ScriptSlave::MoveOffset }, + {&EV_ScriptSlave_RotateXDownTo, &ScriptSlave::RotateXdownto }, + {&EV_ScriptSlave_RotateYDownTo, &ScriptSlave::RotateYdownto }, + {&EV_ScriptSlave_RotateZDownTo, &ScriptSlave::RotateZdownto }, + {&EV_ScriptSlave_RotateXUpTo, &ScriptSlave::RotateXupto }, + {&EV_ScriptSlave_RotateYUpTo, &ScriptSlave::RotateYupto }, + {&EV_ScriptSlave_RotateZUpTo, &ScriptSlave::RotateZupto }, + {&EV_ScriptSlave_RotateXDown, &ScriptSlave::RotateXdown }, + {&EV_ScriptSlave_RotateYDown, &ScriptSlave::RotateYdown }, + {&EV_ScriptSlave_RotateZDown, &ScriptSlave::RotateZdown }, + {&EV_ScriptSlave_RotateXUp, &ScriptSlave::RotateXup }, + {&EV_ScriptSlave_RotateYUp, &ScriptSlave::RotateYup }, + {&EV_ScriptSlave_RotateZUp, &ScriptSlave::RotateZup }, + {&EV_ScriptSlave_RotateX, &ScriptSlave::RotateX }, + {&EV_ScriptSlave_RotateY, &ScriptSlave::RotateY }, + {&EV_ScriptSlave_RotateZ, &ScriptSlave::RotateZ }, + {&EV_ScriptSlave_RotateAxisDownTo, &ScriptSlave::RotateAxisdownto }, + {&EV_ScriptSlave_RotateAxisUpTo, &ScriptSlave::RotateAxisupto }, + {&EV_ScriptSlave_RotateAxisDown, &ScriptSlave::RotateAxisdown }, + {&EV_ScriptSlave_RotateAxisUp, &ScriptSlave::RotateAxisup }, + {&EV_ScriptSlave_RotateAxis, &ScriptSlave::RotateZ }, + {&EV_ScriptSlave_SetDamage, &ScriptSlave::SetDamage }, + {&EV_ScriptSlave_SetMeansOfDeath, &ScriptSlave::SetMeansOfDeath }, + {&EV_ScriptSlave_SetDamageSpawn, &ScriptSlave::SetDamage }, + {&EV_ScriptSlave_FollowPath, &ScriptSlave::FollowPath }, + {&EV_ScriptSlave_FollowPath_RelativeYaw, &ScriptSlave::FollowPathRelativeYaw}, + {&EV_ScriptSlave_EndPath, &ScriptSlave::EndPath }, + {&EV_ScriptSlave_FollowingPath, &ScriptSlave::FollowingPath }, + {&EV_Touch, &ScriptSlave::TouchFunc }, + {&EV_Blocked, &ScriptSlave::BlockFunc }, + {&EV_Activate, &ScriptSlave::TriggerFunc }, + {&EV_Use, &ScriptSlave::UseFunc }, + {&EV_ScriptSlave_MoveDone, &ScriptSlave::MoveEnd }, + {&EV_Damage, &ScriptSlave::DamageFunc }, + {&EV_ScriptSlave_RotateDownTo, &ScriptSlave::Rotatedownto }, + {&EV_ScriptSlave_RotateUpTo, &ScriptSlave::Rotateupto }, + {&EV_ScriptSlave_RotateTo, &ScriptSlave::Rotateto }, + {&EV_ScriptSlave_Explode, &ScriptSlave::Explode }, + {&EV_ScriptSlave_NotShootable, &ScriptSlave::NotShootable }, + {&EV_ScriptSlave_OpenAreaPortal, &ScriptSlave::OpenPortal }, + {&EV_ScriptSlave_CloseAreaPortal, &ScriptSlave::ClosePortal }, + {&EV_ScriptSlave_PhysicsOn, &ScriptSlave::PhysicsOn }, + {&EV_ScriptSlave_PhysicsOff, &ScriptSlave::PhysicsOff }, + {&EV_ScriptSlave_PhysicsVelocity, &ScriptSlave::PhysicsVelocity }, + {&EV_ScriptSlave_FlyPath, &ScriptSlave::EventFlyPath }, + {&EV_ScriptSlave_ModifyFlyPath, &ScriptSlave::EventModifyFlyPath }, + {&EV_ScriptSlave_NormalAngles, &ScriptSlave::EventNormalAngles }, + {NULL, NULL } }; cvar_t *g_showflypath; ScriptSlave::ScriptSlave() { - g_showflypath = gi.Cvar_Get( "g_showflypath", "0", 0 ); + g_showflypath = gi.Cvar_Get("g_showflypath", "0", 0); - AddWaitTill(STRING_TOUCH); - AddWaitTill(STRING_BLOCK); - AddWaitTill(STRING_TRIGGER); - AddWaitTill(STRING_USE); - AddWaitTill(STRING_DAMAGE); + AddWaitTill(STRING_TOUCH); + AddWaitTill(STRING_BLOCK); + AddWaitTill(STRING_TRIGGER); + AddWaitTill(STRING_USE); + AddWaitTill(STRING_DAMAGE); - if( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } - // this is a normal entity - edict->s.eType = ET_GENERAL; + // this is a normal entity + edict->s.eType = ET_GENERAL; - speed = 100; - takedamage = DAMAGE_YES; - waypoint = NULL; - NewAngles = localangles; - NewPos = localorigin; - traveltime = 0; - commandswaiting = false; + splineTime = 0; - dmg = 2; - dmg_means_of_death = MOD_CRUSH; + ignoreangles = false; + ignorevelocity = false; + moving = false; - setMoveType( MOVETYPE_PUSH ); + speed = 100; + takedamage = DAMAGE_YES; + waypoint = NULL; + traveltime = 0; + commandswaiting = false; - if( spawnflags & 2 ) - edict->s.renderfx = RF_ALWAYSDRAW; + splinePath = NULL; + splineangles = false; + m_fFollowRelativeYaw = 0; - splinePath = NULL; - m_pCurPath = NULL; - m_iCurNode = 0; - m_fLookAhead = 0; - m_fCurSpeed = 0; - m_fIdealSpeed = 0; - m_fIdealAccel = 0; - m_fIdealDistance = 100; - splineangles = false; - attack_finished = 0; + attack_finished = 0; + dmg = 2; + dmg_means_of_death = MOD_CRUSH; - setSolidType( SOLID_NOT ); + setMoveType(MOVETYPE_PUSH); - if( spawnflags & 1 ) - { - PostEvent( EV_BecomeNonSolid, EV_POSTSPAWN ); - } + if (spawnflags & 2) { + edict->s.renderfx = RF_ALWAYSDRAW; + } - edict->s.eFlags |= EF_LINKANGLES; + setSolidType(SOLID_NOT); + + m_pCurPath = NULL; + m_iCurNode = 0; + m_fCurSpeed = 0; + m_fLookAhead = 0; + m_fIdealSpeed = 0; + m_fIdealAccel = 0; + m_fIdealDistance = 100; + + if (spawnflags & 1) { + PostEvent(EV_BecomeNonSolid, EV_POSTSPAWN); + } + + edict->s.eFlags |= EF_LINKANGLES; } ScriptSlave::~ScriptSlave() - { - if ( splinePath ) - { - delete splinePath; - splinePath = NULL; - } - } - -void ScriptSlave::CheckNewOrders - ( - void - ) { - // make sure position and angles are current - if( !commandswaiting ) - { - commandswaiting = true; - NewAngles = localangles; - NewPos = localorigin; - } + if (splinePath) { + delete splinePath; + splinePath = NULL; + } } -void ScriptSlave::NewMove - ( - void - ) +void ScriptSlave::CheckNewOrders(void) { - float dist; - - CheckNewOrders(); - - commandswaiting = false; - - if( RegisterSize( 0 ) ) - { - Event ev = Event( EV_DelayThrow ); - ev.AddConstString( STRING_FAIL ); - BroadcastEvent( 0, ev ); - } - - if( m_pCurPath ) - { - PostEvent( EV_ScriptSlave_FollowingPath, 0 ); - } - else if( splinePath ) - { - moving = true; - PostEvent( EV_ScriptSlave_FollowingPath, 0 ); - } - else - { - float t = traveltime; - if( t == 0 ) - { - dist = Vector( NewPos - localorigin ).length(); - t = dist / speed; - } - moving = true; - LinearInterpolate( NewPos, NewAngles, t, EV_ScriptSlave_MoveDone ); - } + // make sure position and angles are current + if (!commandswaiting) { + commandswaiting = true; + NewAngles = localangles; + NewPos = localorigin; + } } -void ScriptSlave::BindEvent - ( - Event *ev - ) - - { - Entity *ent; - - ent = ev->GetEntity( 1 ); - if ( ent ) - { - bind( ent ); - } - - // make sure position and angles are current - NewAngles = localangles; - NewPos = localorigin; - } - -void ScriptSlave::EventUnbind - ( - Event *ev - ) - - { - unbind(); - - // make sure position and angles are current - NewAngles = localangles; - NewPos = localorigin; - } - -void ScriptSlave::DoMove - ( - Event *ev - ) +void ScriptSlave::NewMove(void) { - NewMove(); + float dist; + + CheckNewOrders(); + + commandswaiting = false; + + if (RegisterSize(0)) { + Event ev = Event(EV_DelayThrow); + ev.AddConstString(STRING_FAIL); + BroadcastEvent(0, ev); + } + + if (m_pCurPath || splinePath) { + PostEvent(EV_ScriptSlave_FollowingPath, 0); + } else { + float t = traveltime; + if (t == 0) { + dist = Vector(NewPos - localorigin).length(); + t = dist / speed; + } + LinearInterpolate(NewPos, NewAngles, t, EV_ScriptSlave_MoveDone); + } } -void ScriptSlave::WaitMove( Event *ev ) +void ScriptSlave::BindEvent(Event *ev) { - NewMove(); - Register( 0, Director.CurrentThread() ); + Entity *ent; + + ent = ev->GetEntity(1); + if (ent) { + bind(ent); + } + + // make sure position and angles are current + NewAngles = localangles; + NewPos = localorigin; } -void ScriptSlave::MoveEnd( Event *ev ) +void ScriptSlave::EventUnbind(Event *ev) { - Unregister( 0 ); + unbind(); + + // make sure position and angles are current + NewAngles = localangles; + NewPos = localorigin; } -void ScriptSlave::SetAnglesEvent - ( - Event *ev - ) - - { - commandswaiting = true; - SetAngles(ev); - NewAngles = localangles; - } - -void ScriptSlave::SetAngleEvent - ( - Event *ev - ) - - { - float angle; - - angle = ev->GetFloat( 1 ); - if ( angle == -1 ) - { - ForwardDir = Vector( 0, 0, 90 ); - } - else if ( angle == -2 ) - { - ForwardDir = Vector( 0, 0, -90 ); - } - else - { - ForwardDir = Vector( 0, angle, 0 ); - } - } - -void ScriptSlave::SetModelEvent - ( - Event *ev - ) +void ScriptSlave::DoMove(Event *ev) { - const char *m; - - m = ev->GetString( 1 ); - - edict->r.svFlags &= ~SVF_NOCLIENT; - - if( !m || strstr( m, ".tik" ) ) - { - setSolidType( SOLID_BBOX ); - setModel( m ); - } - else if( strstr( m, ".spr" ) ) - { - setModel( m ); - setSolidType( SOLID_NOT ); - } - else - { - setModel( m ); - } - - if( !edict->s.modelindex ) - { - hideModel(); - setSolidType( SOLID_NOT ); - } + NewMove(); } -void ScriptSlave::TriggerEvent - ( - Event *ev - ) - - { - Entity *ent; - Event *e; - - ent = ev->GetEntity( 1 ); - if ( ent ) - { - target = ent->TargetName(); - - e = new Event( EV_Trigger_ActivateTargets ); - //fixme - //get "other" - e->AddEntity( world ); - ProcessEvent( e ); - } - } - -void ScriptSlave::GotoNextWaypoint - ( - Event *ev - ) - - { - commandswaiting = true; - - if ( !waypoint ) - { - ScriptError( "%s is currently not at a waypoint", TargetName().c_str() ); - return; - } - - waypoint = ( Waypoint * )G_FindTarget( NULL, waypoint->Target() ); - if ( !waypoint ) - { - ScriptError( "%s could not find waypoint %s", TargetName().c_str(), waypoint->Target().c_str() ); - return; - } - else - { - NewPos = waypoint->origin; - } - } - -void ScriptSlave::JumpTo - ( - Event *ev - ) +void ScriptSlave::WaitMove(Event *ev) { - Entity *part; - - // - // see if it is a vector - // - if( ev->IsVectorAt( 1 ) ) - { - NewPos = ev->GetVector( 1 ); - if( bindmaster ) - { - localorigin = bindmaster->getLocalVector( NewPos - bindmaster->origin ); - } - else - { - localorigin = NewPos; - } - - for( part = this; part; part = part->teamchain ) - { - part->setOrigin(); - part->origin.copyTo( part->edict->s.origin2 ); - part->edict->s.renderfx |= RF_FRAMELERP; - } - } - else - { - waypoint = ev->GetWaypoint( 1 ); - if( waypoint ) - { - NewPos = waypoint->origin; - if( bindmaster ) - { - localorigin = bindmaster->getLocalVector( NewPos - bindmaster->origin ); - } - else - { - localorigin = NewPos; - } - - for( part = this; part; part = part->teamchain ) - { - part->setOrigin(); - part->origin.copyTo( part->edict->s.origin2 ); - part->edict->s.renderfx |= RF_FRAMELERP; - } - } - } + NewMove(); + Register(0, Director.CurrentScriptThread()); } -void ScriptSlave::MoveToEvent - ( - Event *ev - ) +void ScriptSlave::Stop(Event *ev) +{ + commandswaiting = false; + if (RegisterSize(0)) { + Event newev(EV_DelayThrow); + newev.AddConstString(STRING_FAIL); + BroadcastEvent(0, newev); + } - { - commandswaiting = true; + Mover::Stop(); +} - // - // see if it is a vector - // - if ( ev->IsVectorAt( 1 ) ) - { - NewPos = ev->GetVector( 1 ); - } - else - { - waypoint = ( Waypoint * )ev->GetEntity( 1 ); - if ( waypoint ) - { - NewPos = waypoint->origin; - } - } - } +void ScriptSlave::ThreadMove(Event *ev) +{ + NewMove(); + Register(0, CreateThreadInternal(ev->GetValue(1))); +} -void ScriptSlave::SetSpeed - ( - Event *ev - ) +void ScriptSlave::MoveEnd(Event *ev) +{ + Unregister(0); +} - { - speed = ev->GetFloat( 1 ); - traveltime = 0; - } +void ScriptSlave::SetAnglesEvent(Event *ev) +{ + CheckNewOrders(); + SetAngles(ev); + NewAngles = localangles; +} -void ScriptSlave::SetTime - ( - Event *ev - ) +void ScriptSlave::SetAngleEvent(Event *ev) +{ + float angle; - { - traveltime = ev->GetFloat( 1 ); - } + angle = ev->GetFloat(1); + if (angle == -1) { + ForwardDir = Vector(0, 0, 90); + } else if (angle == -2) { + ForwardDir = Vector(0, 0, -90); + } else { + ForwardDir = Vector(0, angle, 0); + } +} + +void ScriptSlave::SetModelEvent(Event *ev) +{ + str m; + + m = ev->GetString(1); + + edict->r.svFlags &= ~SVF_NOCLIENT; + + if (!m || strstr(m, ".tik")) { + setSolidType(SOLID_BBOX); + setModel(m); + if (!edict->s.modelindex) { + hideModel(); + setSolidType(SOLID_NOT); + } + } else if (strstr(m, ".spr")) { + setModel(m); + if (!edict->s.modelindex) { + hideModel(); + } + setSolidType(SOLID_NOT); + } else { + setModel(m); + if (edict->s.modelindex) { + setSolidType(SOLID_BSP); + } else { + hideModel(); + setSolidType(SOLID_NOT); + } + } + + if (!edict->s.modelindex) { + hideModel(); + setSolidType(SOLID_NOT); + } +} + +void ScriptSlave::TriggerEvent(Event *ev) +{ + Entity *ent; + Event *e; + + ent = ev->GetEntity(1); + if (ent) { + target = ent->TargetName(); + + e = new Event(EV_Trigger_ActivateTargets); + //fixme + //get "other" + e->AddEntity(world); + ProcessEvent(e); + } +} + +void ScriptSlave::GotoNextWaypoint(Event *ev) +{ + CheckNewOrders(); + + if (!waypoint) { + ScriptError("%s is currently not at a waypoint", TargetName().c_str()); + return; + } + + waypoint = (Waypoint *)G_FindTarget(NULL, waypoint->Target()); + if (!waypoint) { + ScriptError("%s could not find waypoint %s", TargetName().c_str(), waypoint->Target().c_str()); + return; + } else { + NewPos = waypoint->origin; + } +} + +void ScriptSlave::JumpTo(Event *ev) +{ + Entity *part; + + // + // see if it is a vector + // + if (ev->IsVectorAt(1)) { + NewPos = ev->GetVector(1); + if (bindmaster) { + localorigin = bindmaster->getLocalVector(NewPos - bindmaster->origin); + } else { + localorigin = NewPos; + } + + for (part = this; part; part = part->teamchain) { + part->setOrigin(); + part->origin.copyTo(part->edict->s.origin2); + part->edict->s.renderfx |= RF_FRAMELERP; + } + } else { + waypoint = ev->GetWaypoint(1); + if (waypoint) { + NewPos = waypoint->origin; + if (bindmaster) { + localorigin = bindmaster->getLocalVector(NewPos - bindmaster->origin); + } else { + localorigin = NewPos; + } + + for (part = this; part; part = part->teamchain) { + part->setOrigin(); + part->origin.copyTo(part->edict->s.origin2); + part->edict->s.renderfx |= RF_FRAMELERP; + } + } + } +} + +void ScriptSlave::MoveToEvent(Event *ev) +{ + CheckNewOrders(); + + // + // see if it is a vector + // + if (ev->IsVectorAt(1)) { + NewPos = ev->GetVector(1); + } else { + SimpleEntity* ent; + + ent = ev->GetSimpleEntity(1); + if (ent) { + // + // see if it is a waypoint + // + if (ent->IsSubclassOfWaypoint()) { + waypoint = static_cast(ent); + } + // use the entity's origin + NewPos = ent->origin; + } + } +} + +void ScriptSlave::SetSpeed(Event *ev) +{ + speed = ev->GetFloat(1); + traveltime = 0; +} + +void ScriptSlave::SetTime(Event *ev) +{ + traveltime = ev->GetFloat(1); +} // Relative move commands -void ScriptSlave::MoveUp - ( - Event *ev - ) +void ScriptSlave::MoveUp(Event *ev) { - CheckNewOrders(); - NewPos[ 2 ] += ev->GetFloat( 1 ); + CheckNewOrders(); + NewPos[2] += ev->GetFloat(1); } -void ScriptSlave::MoveDown - ( - Event *ev - ) +void ScriptSlave::MoveDown(Event *ev) { - CheckNewOrders(); - NewPos[ 2 ] -= ev->GetFloat( 1 ); + CheckNewOrders(); + NewPos[2] -= ev->GetFloat(1); } -void ScriptSlave::MoveNorth - ( - Event *ev - ) +void ScriptSlave::MoveNorth(Event *ev) { - CheckNewOrders(); - NewPos[ 1 ] += ev->GetFloat( 1 ); + CheckNewOrders(); + NewPos[1] += ev->GetFloat(1); } -void ScriptSlave::MoveSouth - ( - Event *ev - ) +void ScriptSlave::MoveSouth(Event *ev) { - CheckNewOrders(); - NewPos[ 1 ] -= ev->GetFloat( 1 ); + CheckNewOrders(); + NewPos[1] -= ev->GetFloat(1); } -void ScriptSlave::MoveEast - ( - Event *ev - ) +void ScriptSlave::MoveEast(Event *ev) { - CheckNewOrders(); - NewPos[ 0 ] += ev->GetFloat( 1 ); + CheckNewOrders(); + NewPos[0] += ev->GetFloat(1); } -void ScriptSlave::MoveWest - ( - Event *ev - ) +void ScriptSlave::MoveWest(Event *ev) { - CheckNewOrders(); - NewPos[ 0 ] -= ev->GetFloat( 1 ); + CheckNewOrders(); + NewPos[0] -= ev->GetFloat(1); } -void ScriptSlave::MoveForward - ( - Event *ev - ) +void ScriptSlave::MoveForward(Event *ev) { - Vector v; - Vector t; + Vector v; + Vector t; - CheckNewOrders(); + CheckNewOrders(); - t = NewAngles + ForwardDir; - t.AngleVectorsLeft( &v, NULL, NULL ); + t = NewAngles + ForwardDir; + t.AngleVectorsLeft(&v, NULL, NULL); - NewPos += v * ev->GetFloat( 1 ); + NewPos += v * ev->GetFloat(1); } -void ScriptSlave::MoveBackward - ( - Event *ev - ) +void ScriptSlave::MoveBackward(Event *ev) { - Vector v; - Vector t; + Vector v; + Vector t; - CheckNewOrders(); + CheckNewOrders(); - t = NewAngles + ForwardDir; - t.AngleVectorsLeft( &v, NULL, NULL ); + t = NewAngles + ForwardDir; + t.AngleVectorsLeft(&v, NULL, NULL); - NewPos -= v * ev->GetFloat( 1 ); + NewPos -= v * ev->GetFloat(1); } -void ScriptSlave::MoveLeft - ( - Event *ev - ) +void ScriptSlave::MoveLeft(Event *ev) { - Vector v; - Vector t; + Vector v; + Vector t; - CheckNewOrders(); + CheckNewOrders(); - t = NewAngles + ForwardDir; - t.AngleVectorsLeft( NULL, &v, NULL ); + t = NewAngles + ForwardDir; + t.AngleVectorsLeft(NULL, &v, NULL); - NewPos += v * ev->GetFloat( 1 ); + NewPos += v * ev->GetFloat(1); } -void ScriptSlave::MoveRight - ( - Event *ev - ) +void ScriptSlave::MoveRight(Event *ev) { - Vector t; - Vector v; + Vector t; + Vector v; - CheckNewOrders(); + CheckNewOrders(); - t = NewAngles + ForwardDir; - t.AngleVectorsLeft( NULL, &v, NULL ); + t = NewAngles + ForwardDir; + t.AngleVectorsLeft(NULL, &v, NULL); - NewPos -= v * ev->GetFloat( 1 ); + NewPos -= v * ev->GetFloat(1); +} + +void ScriptSlave::MoveOffset(Event *ev) +{ + CheckNewOrders(); + NewPos += ev->GetVector(1); } // exact rotate commands -void ScriptSlave::RotateXdownto - ( - Event *ev - ) +void ScriptSlave::RotateXdownto(Event *ev) { - CheckNewOrders(); + CheckNewOrders(); - NewAngles[ 0 ] = ev->GetFloat( 1 ); - if ( NewAngles[ 0 ] > localangles[ 0 ] ) - { - NewAngles[ 0 ] -= 360; - } + NewAngles[0] = ev->GetFloat(1); + if (NewAngles[0] > localangles[0]) { + NewAngles[0] -= 360; + } } -void ScriptSlave::RotateYdownto - ( - Event *ev - ) +void ScriptSlave::RotateYdownto(Event *ev) { - CheckNewOrders(); + CheckNewOrders(); - NewAngles[ 1 ] = ev->GetFloat( 1 ); - if ( NewAngles[ 1 ] > localangles[ 1 ] ) - { - NewAngles[ 1 ] -= 360; - } + NewAngles[1] = ev->GetFloat(1); + if (NewAngles[1] > localangles[1]) { + NewAngles[1] -= 360; + } } -void ScriptSlave::RotateZdownto - ( - Event *ev - ) +void ScriptSlave::RotateZdownto(Event *ev) { - CheckNewOrders(); + CheckNewOrders(); - NewAngles[ 2 ] = ev->GetFloat( 1 ); - if ( NewAngles[ 2 ] > localangles[ 2 ] ) - { - NewAngles[ 2 ] -= 360; - } + NewAngles[2] = ev->GetFloat(1); + if (NewAngles[2] > localangles[2]) { + NewAngles[2] -= 360; + } } -void ScriptSlave::RotateAxisdownto - ( - Event *ev - ) +void ScriptSlave::RotateAxisdownto(Event *ev) { - int axis; - CheckNewOrders(); + int axis; + CheckNewOrders(); - axis = ev->GetInteger( 1 ); - NewAngles[ axis ] = ev->GetFloat( 2 ); - if ( NewAngles[ axis ] > localangles[ axis ] ) - { - NewAngles[ axis ] -= 360; - } + axis = ev->GetInteger(1); + NewAngles[axis] = ev->GetFloat(2); + if (NewAngles[axis] > localangles[axis]) { + NewAngles[axis] -= 360; + } } -void ScriptSlave::RotateXupto - ( - Event *ev - ) +void ScriptSlave::RotateXupto(Event *ev) { - CheckNewOrders(); + CheckNewOrders(); - NewAngles[ 0 ] = ev->GetFloat( 1 ); - if ( NewAngles[ 0 ] < localangles[ 0 ] ) - { - NewAngles[ 0 ] += 360; - } + NewAngles[0] = ev->GetFloat(1); + if (NewAngles[0] < localangles[0]) { + NewAngles[0] += 360; + } } -void ScriptSlave::RotateYupto - ( - Event *ev - ) +void ScriptSlave::RotateYupto(Event *ev) { - CheckNewOrders(); + CheckNewOrders(); - NewAngles[ 1 ] = ev->GetFloat( 1 ); - if ( NewAngles[ 1 ] < localangles[ 1 ] ) - { - NewAngles[ 1 ] += 360; - } + NewAngles[1] = ev->GetFloat(1); + if (NewAngles[1] < localangles[1]) { + NewAngles[1] += 360; + } } -void ScriptSlave::RotateZupto - ( - Event *ev - ) +void ScriptSlave::RotateZupto(Event *ev) { - CheckNewOrders(); + CheckNewOrders(); - NewAngles[ 2 ] = ev->GetFloat( 1 ); - if ( NewAngles[ 2 ] < localangles[ 2 ] ) - { - NewAngles[ 2 ] += 360; - } + NewAngles[2] = ev->GetFloat(1); + if (NewAngles[2] < localangles[2]) { + NewAngles[2] += 360; + } } -void ScriptSlave::RotateAxisupto - ( - Event *ev - ) +void ScriptSlave::RotateAxisupto(Event *ev) { - int axis; - CheckNewOrders(); + int axis; + CheckNewOrders(); - axis = ev->GetInteger( 1 ); - NewAngles[ axis ] = ev->GetFloat( 2 ); - if ( NewAngles[ axis ] < localangles[ axis ] ) - { - NewAngles[ axis ] += 360; - } + axis = ev->GetInteger(1); + NewAngles[axis] = ev->GetFloat(2); + if (NewAngles[axis] < localangles[axis]) { + NewAngles[axis] += 360; + } } // full vector rotation -void ScriptSlave::Rotatedownto - ( - Event *ev - ) +void ScriptSlave::Rotatedownto(Event *ev) { - Vector ang; + Vector ang; - CheckNewOrders(); + CheckNewOrders(); - ang = ev->GetVector( 1 ); + ang = ev->GetVector(1); - NewAngles[ 0 ] = ang[ 0 ]; - if ( NewAngles[ 0 ] > localangles[ 0 ] ) - { - NewAngles[ 0 ] -= 360; - } - NewAngles[ 1 ] = ang[ 1 ]; - if ( NewAngles[ 1 ] > localangles[ 1 ] ) - { - NewAngles[ 1 ] -= 360; - } - NewAngles[ 2 ] = ang[ 2 ]; - if ( NewAngles[ 2 ] > localangles[ 2 ] ) - { - NewAngles[ 2 ] -= 360; - } + NewAngles[0] = ang[0]; + if (NewAngles[0] > localangles[0]) { + NewAngles[0] -= 360; + } + NewAngles[1] = ang[1]; + if (NewAngles[1] > localangles[1]) { + NewAngles[1] -= 360; + } + NewAngles[2] = ang[2]; + if (NewAngles[2] > localangles[2]) { + NewAngles[2] -= 360; + } } -void ScriptSlave::Rotateupto - ( - Event *ev - ) +void ScriptSlave::Rotateupto(Event *ev) { - Vector ang; + Vector ang; - CheckNewOrders(); + CheckNewOrders(); - ang = ev->GetVector( 1 ); + ang = ev->GetVector(1); - NewAngles[ 0 ] = ang[ 0 ]; - if ( NewAngles[ 0 ] < localangles[ 0 ] ) - { - NewAngles[ 0 ] += 360; - } - NewAngles[ 1 ] = ang[ 1 ]; - if ( NewAngles[ 1 ] < localangles[ 1 ] ) - { - NewAngles[ 1 ] += 360; - } - NewAngles[ 2 ] = ang[ 2 ]; - if ( NewAngles[ 2 ] < localangles[ 2 ] ) - { - NewAngles[ 2 ] += 360; - } + NewAngles[0] = ang[0]; + if (NewAngles[0] < localangles[0]) { + NewAngles[0] += 360; + } + NewAngles[1] = ang[1]; + if (NewAngles[1] < localangles[1]) { + NewAngles[1] += 360; + } + NewAngles[2] = ang[2]; + if (NewAngles[2] < localangles[2]) { + NewAngles[2] += 360; + } } -void ScriptSlave::Rotateto - ( - Event *ev - ) +void ScriptSlave::Rotateto(Event *ev) { - Vector ang; + Vector ang; - CheckNewOrders(); + CheckNewOrders(); - ang = ev->GetVector( 1 ); + ang = ev->GetVector(1); - NewAngles = ang; + NewAngles = ang; } // Relative rotate commands -void ScriptSlave::RotateXdown - ( - Event *ev - ) +void ScriptSlave::RotateXdown(Event *ev) { - CheckNewOrders(); - NewAngles[ 0 ] = localangles[ 0 ] - ev->GetFloat( 1 ); + CheckNewOrders(); + NewAngles[0] = localangles[0] - ev->GetFloat(1); } -void ScriptSlave::RotateYdown - ( - Event *ev - ) +void ScriptSlave::RotateYdown(Event *ev) { - CheckNewOrders(); - NewAngles[ 1 ] = localangles[ 1 ] - ev->GetFloat( 1 ); + CheckNewOrders(); + NewAngles[1] = localangles[1] - ev->GetFloat(1); } -void ScriptSlave::RotateZdown - ( - Event *ev - ) +void ScriptSlave::RotateZdown(Event *ev) { - CheckNewOrders(); - NewAngles[ 2 ] = localangles[ 2 ] - ev->GetFloat( 1 ); + CheckNewOrders(); + NewAngles[2] = localangles[2] - ev->GetFloat(1); } -void ScriptSlave::RotateAxisdown - ( - Event *ev - ) +void ScriptSlave::RotateAxisdown(Event *ev) { - int axis; - CheckNewOrders(); + int axis; + CheckNewOrders(); - axis = ev->GetInteger( 1 ); - NewAngles[ axis ] = localangles[ axis ] - ev->GetFloat( 2 ); + axis = ev->GetInteger(1); + NewAngles[axis] = localangles[axis] - ev->GetFloat(2); } -void ScriptSlave::RotateXup - ( - Event *ev - ) +void ScriptSlave::RotateXup(Event *ev) { - CheckNewOrders(); - NewAngles[ 0 ] = localangles[ 0 ] + ev->GetFloat( 1 ); + CheckNewOrders(); + NewAngles[0] = localangles[0] + ev->GetFloat(1); } -void ScriptSlave::RotateYup - ( - Event *ev - ) +void ScriptSlave::RotateYup(Event *ev) { - CheckNewOrders(); - NewAngles[ 1 ] = localangles[ 1 ] + ev->GetFloat( 1 ); + CheckNewOrders(); + NewAngles[1] = localangles[1] + ev->GetFloat(1); } -void ScriptSlave::RotateZup - ( - Event *ev - ) +void ScriptSlave::RotateZup(Event *ev) { - CheckNewOrders(); - NewAngles[ 2 ] = localangles[ 2 ] + ev->GetFloat( 1 ); + CheckNewOrders(); + NewAngles[2] = localangles[2] + ev->GetFloat(1); } -void ScriptSlave::RotateAxisup - ( - Event *ev - ) +void ScriptSlave::RotateAxisup(Event *ev) { - int axis; - CheckNewOrders(); + int axis; + CheckNewOrders(); - axis = ev->GetInteger( 1 ); - NewAngles[ axis ] = localangles[ axis ] + ev->GetFloat( 2 ); + axis = ev->GetInteger(1); + NewAngles[axis] = localangles[axis] + ev->GetFloat(2); } -void ScriptSlave::RotateX - ( - Event *ev - ) - - { - avelocity[ 0 ] = ev->GetFloat( 1 ); - } - -void ScriptSlave::RotateY - ( - Event *ev - ) - - { - avelocity[ 1 ] = ev->GetFloat( 1 ); - } - -void ScriptSlave::RotateZ - ( - Event *ev - ) - - { - avelocity[ 2 ] = ev->GetFloat( 1 ); - } - -void ScriptSlave::RotateAxis - ( - Event *ev - ) - - { - int axis; - - axis = ev->GetInteger( 1 ); - avelocity[ axis ] = ev->GetFloat( 2 ); - } - -void ScriptSlave::DamageFunc - ( - Event *ev - ) +void ScriptSlave::RotateX(Event *ev) { - Unregister( STRING_DAMAGE ); + avelocity[0] = ev->GetFloat(1); } -void ScriptSlave::SetDamage - ( - Event *ev - ) - - { - dmg = ev->GetInteger( 1 ); - } - -void ScriptSlave::SetMeansOfDeath - ( - Event *ev - ) - - { - dmg_means_of_death = MOD_string_to_int( ev->GetString( 1 ) ); - } - -void ScriptSlave::CreatePath - ( - SplinePath *path, - splinetype_t type - ) - - { - SplinePath *node; - - if ( !splinePath ) - { - splinePath = new BSpline; - } - - splinePath->Clear(); - splinePath->SetType( type ); - - node = path; - while( node != NULL ) - { - splinePath->AppendControlPoint( node->origin, node->angles, node->speed ); - node = node->GetNext(); - - if ( node == path ) - { - break; - } - } - } - -void ScriptSlave::FollowPath - ( - Event *ev - ) +void ScriptSlave::RotateY(Event *ev) { - int i, argnum; - Entity * ent; - const char * token; - SplinePath *path; - qboolean clamp; - float starttime; - - - ent = ev->GetEntity( 1 ); - argnum = 2; - starttime = -2; - clamp = true; - ignoreangles = false; - splineangles = true; - for( i = argnum; i <= ev->NumArgs(); i++ ) - { - token = ev->GetString( i ); - if( !Q_stricmp( token, "ignoreangles" ) ) - { - ignoreangles = true; - } - else if( !Q_stricmp( token, "normalangles" ) ) - { - splineangles = false; - } - else if( !Q_stricmp( token, "loop" ) ) - { - clamp = false; - } - else if( IsNumeric( token ) ) - { - starttime = atof( token ); - } - else - { - ScriptError( "Unknown followpath command %s.", token ); - } - } - if( ent && ent->IsSubclassOfSplinePath() ) - { - commandswaiting = true; - path = ( SplinePath * )ent; - if( clamp ) - CreatePath( path, SPLINE_CLAMP ); - else - CreatePath( path, SPLINE_LOOP ); - splineTime = starttime; - CancelEventsOfType( EV_ScriptSlave_FollowingPath ); - if( !ignoreangles ) - { - avelocity = vec_zero; - } - velocity = vec_zero; - } + avelocity[1] = ev->GetFloat(1); } -void ScriptSlave::EndPath - ( - Event *ev - ) - { - if ( !splinePath ) - return; - - delete splinePath; - splinePath = NULL; - velocity = vec_zero; - if ( !ignoreangles ) - { - avelocity = vec_zero; - } - } - -void ScriptSlave::FollowingPath - ( - Event *ev - ) +void ScriptSlave::RotateZ(Event *ev) { - Vector pos; - Vector orient; - float speed_multiplier; - - if( m_pCurPath && m_pCurPath->m_iPoints ) - { - Vector vAngles; - Vector vDeltaAngles; - Vector vDelta; - float *vTmp; - Vector vPrev; - Vector vCur; - Vector vTotal; - float fCoef; - Vector vWishPosition; - Vector vWishAngles; - Vector vNextWishAngles; - Vector primal_angles; - Vector n_angles; - - if( g_showflypath && g_showflypath->integer ) - { - for( int i = 0; i < m_pCurPath->m_iPoints; i++ ) - { - vTmp = m_pCurPath->GetByNode( i, NULL ); - G_DebugBBox( ( vTmp + 1 ), Vector( -32, -32, -32 ), Vector( 32, 32, 32 ), 0.0f, 1.0f, 1.0f, 1.0f ); - - for( int ii = 0; ii <= 8; ii++ ) - { - G_DebugLine( ( m_pCurPath->GetByNode( ( ii / 10.0f + ( i + 1 ) ), NULL ) + 1 ), ( m_pCurPath->GetByNode( m_fLookAhead + ( ii / 10.0f + ( i + 1 ) ), NULL ) + 1 ), 0.0f, 1.0f, 1.0f, 1.0f ); - } - } - } - - if( m_iCurNode <= 0 ) - { - vTmp = m_pCurPath->GetByNode( m_iCurNode, NULL ); - vWishPosition = ( vTmp + 1 ); - vDelta = vWishPosition - origin; - - if( vDelta.length() <= 32.0f ) - { - m_iCurNode++; - - if( m_iCurNode >= m_pCurPath->m_iPoints ) - { - velocity = vec_zero; - avelocity = vec_zero; - - delete m_pCurPath; - m_pCurPath = NULL; - m_iCurNode = 0; - moving = false; - ProcessEvent( EV_ScriptSlave_MoveDone ); - return; - } - } - } - else - { - vTmp = m_pCurPath->GetByNode( m_iCurNode - 1, NULL ); - vPrev = ( vTmp + 1 ); - vTmp = m_pCurPath->GetByNode( m_iCurNode, NULL ); - vCur = ( vTmp + 1 ); - - m_vIdealDir = vCur - vPrev; - VectorNormalize( m_vIdealDir ); - angles.AngleVectorsLeft( &vWishAngles ); - - fCoef = ProjectLineOnPlane( vWishAngles, DotProduct( origin, vWishAngles ), vPrev, vCur, NULL ); - - vTmp = m_pCurPath->GetByNode( ( m_iCurNode - ( 1.0f - fCoef ) ), NULL ); - vTmp = m_pCurPath->Get( vTmp[ 0 ] + m_fLookAhead, NULL ); - vWishPosition = ( vTmp + 1 ); - - if( fCoef > 1.0f ) - { - m_iCurNode++; - - if( m_iCurNode >= m_pCurPath->m_iPoints ) - { - velocity = vec_zero; - avelocity = vec_zero; - - delete m_pCurPath; - m_pCurPath = NULL; - m_iCurNode = 0; - moving = false; - ProcessEvent( EV_ScriptSlave_MoveDone ); - return; - } - } - } - - vWishAngles = vWishPosition - origin; - - if( vWishAngles.length() > 0.0f ) - { - VectorNormalize( vWishAngles ); - VectorToAngles( vWishAngles, vNextWishAngles ); - } - else - { - AngleVectorsLeft( angles, vWishAngles, NULL, NULL ); - vNextWishAngles = angles; - } - - vAngles = angles; - - for( int i = 0; i < 3; i++ ) - { - n_angles[ i ] = vNextWishAngles[ i ] - angles[ i ]; - - if( n_angles[ i ] <= 180.0f ) - { - if( n_angles[ i ] < -180.0f ) - { - n_angles[ i ] += 360.0f; - } - } - else - { - n_angles[ i ] -= 360.0f; - } - - float change = level.frametime * 360.0f; - float error = 0.33f * n_angles[ i ]; - - if( -change > error ) - { - error = -change; - } - else if( error <= change ) - { - change = error; - } - - primal_angles[ i ] = change + angles[ i ]; - } - - setAngles( primal_angles ); - - vDeltaAngles = ( angles - vAngles ) * level.frametime; - - if( vDeltaAngles[ 0 ] > 180.0f || vDeltaAngles[ 0 ] <= -180.0f ) - { - vDeltaAngles[ 0 ] = 0.0f; - } - - if( vDeltaAngles[ 1 ] > 180.0f || vDeltaAngles[ 1 ] <= -180.0f ) - { - vDeltaAngles[ 1 ] = 0.0f; - } - - if( vDeltaAngles[ 2 ] > 180.0f || vDeltaAngles[ 2 ] <= -180.0f ) - { - vDeltaAngles[ 2 ] = 0.0f; - } - - if( vDeltaAngles[ 0 ] > -1.0f || vDeltaAngles[ 0 ] < 1.0f ) - { - vDeltaAngles[ 0 ] = 0.0f; - } - - if( vDeltaAngles[ 1 ] > -1.0f || vDeltaAngles[ 1 ] < 1.0f ) - { - vDeltaAngles[ 1 ] = 0.0f; - } - - if( vDeltaAngles[ 2 ] > -1.0f || vDeltaAngles[ 2 ] < 1.0f ) - { - vDeltaAngles[ 2 ] = 0.0f; - } - - avelocity = vDeltaAngles; - velocity = vWishAngles * m_fCurSpeed; - - if( m_fCurSpeed < m_fIdealSpeed ) - { - m_fCurSpeed += m_fIdealAccel * level.frametime; - - if( m_fCurSpeed > m_fIdealSpeed ) - { - m_fCurSpeed = m_fIdealSpeed; - } - } - else if( m_fCurSpeed > m_fIdealSpeed ) - { - m_fCurSpeed -= m_fIdealAccel * level.frametime; - - if( m_fCurSpeed < m_fIdealSpeed ) - { - m_fCurSpeed = m_fIdealSpeed; - } - } - } - else - { - if( !splinePath ) - { - return; - } - - if( ( splinePath->GetType() == SPLINE_CLAMP ) && ( splineTime > ( splinePath->EndPoint() - 2 ) ) ) - { - delete splinePath; - splinePath = NULL; - velocity = vec_zero; - if( !ignoreangles ) - { - avelocity = vec_zero; - } - moving = false; - ProcessEvent( EV_ScriptSlave_MoveDone ); - return; - } - - speed_multiplier = splinePath->Eval( splineTime, pos, orient ); - - splineTime += level.frametime * speed_multiplier; - - velocity = ( pos - origin ) * ( 1 / level.frametime ); - if( !ignoreangles ) - { - if( splineangles ) - { - avelocity = ( orient - angles ) * ( 1 / level.frametime ); - } - else - { - float len; - - len = velocity.length(); - if( len > 0.05 ) - { - Vector ang; - Vector dir; - float aroll; - - aroll = avelocity[ ROLL ]; - dir = velocity * ( 1 / len ); - ang = dir.toAngles(); - avelocity = ( ang - angles ) * ( 1 / level.frametime ); - avelocity[ ROLL ] = aroll; - } - else - avelocity = vec_zero; - } - } - } - - PostEvent( EV_ScriptSlave_FollowingPath, level.frametime ); + avelocity[2] = ev->GetFloat(1); } -void ScriptSlave::Explode - ( - Event *ev - ) - - { - float damage; - - if ( ev->NumArgs() ) - { - damage = ev->GetFloat( 1 ); - } - else - { - damage = 120.0f; - } - - CreateExplosion( origin, damage, this, this, this ); - } - -void ScriptSlave::NotShootable - ( - Event *ev - ) - { - setContents( 0 ); - } - -void ScriptSlave::OpenPortal - ( - Event *ev - ) - { - gi.AdjustAreaPortalState( this->edict, true ); - } - -void ScriptSlave::ClosePortal - ( - Event *ev - ) - { - gi.AdjustAreaPortalState( this->edict, false ); - } - -void ScriptSlave::PhysicsOn - ( - Event *ev - ) +void ScriptSlave::RotateAxis(Event *ev) { - commandswaiting = false; - setMoveType(MOVETYPE_BOUNCE); - setSolidType(SOLID_BBOX); - velocity = Vector(0, 0, 1); - edict->clipmask = MASK_SOLID | CONTENTS_BODY; - if (ev->NumArgs() == 1 && ev->GetInteger(1)) - { - edict->clipmask &= ~MASK_SCRIPT_SLAVE; - } + int axis; + + axis = ev->GetInteger(1); + avelocity[axis] = ev->GetFloat(2); } -void ScriptSlave::PhysicsOff - ( - Event *ev - ) - { - Event * event; - - commandswaiting = false; - setMoveType( MOVETYPE_PUSH ); - edict->clipmask = 0; - // become solid again - event = new Event( EV_Model ); - event->AddString( model ); - PostEvent( event, 0 ); - } - -void ScriptSlave::PhysicsVelocity - ( - Event *ev - ) - { - velocity += ev->GetVector( 1 ); - } - - -void ScriptSlave::EventFlyPath - ( - Event *ev - ) +void ScriptSlave::TouchFunc(Event* ev) { - SimpleEntity *path; - - m_fIdealDistance = 100.0f; - m_fLookAhead = 256.0f; - m_fIdealAccel = 35.0f; - m_fIdealSpeed = 250.0f; - - if( ev->NumArgs() != 1 && ev->NumArgs() != 2 && ev->NumArgs() != 3 && ev->NumArgs() != 4 ) - ScriptError( "wrong number of arguments" ); - - if( ev->NumArgs() > 1 ) - m_fIdealSpeed = ev->GetFloat( 2 ); - - if( ev->NumArgs() > 2 ) - m_fIdealAccel = ev->GetFloat( 3 ); - - if( ev->NumArgs() > 3 ) - m_fLookAhead = ev->GetFloat( 4 ); - - path = ev->GetSimpleEntity( 1 ); - - if( !path ) - ScriptError( "ScriptSlave Given FlyPath Command with NULL path." ); - - if( m_pCurPath ) - delete m_pCurPath; - - m_pCurPath = new cSpline < 4, 512 > ; - - SetupPath( m_pCurPath, path ); - m_iCurNode = 0; - CancelEventsOfType( EV_ScriptSlave_FollowingPath ); + parm.other = ev->GetEntity(1); + parm.owner = parm.other; + Unregister(STRING_TOUCH); } -void ScriptSlave::EventModifyFlyPath - ( - Event *ev - ) +void ScriptSlave::BlockFunc(Event* ev) { - m_fIdealDistance = 100.0f; + Entity* other; - if( ev->NumArgs() != 1 && ev->NumArgs() != 2 && ev->NumArgs() != 3 ) - ScriptError( "wrong number of arguments" ); + other = ev->GetEntity(1); + if (level.time >= attack_finished) { + attack_finished = level.time + 0.5; + if (dmg) { + other->Damage(this, this, dmg, origin, vec_zero, vec_zero, 0, 0, dmg_means_of_death); + } + } - if( ev->NumArgs() > 0 ) - m_fIdealSpeed = ev->GetFloat( 1 ); - - if( ev->NumArgs() > 1 ) - m_fIdealAccel = ev->GetFloat( 2 ); - - if( ev->NumArgs() > 2 ) - m_fLookAhead = ev->GetFloat( 3 ); + parm.other = ev->GetEntity(1); + parm.owner = parm.other; + Unregister(STRING_BLOCK); } -void ScriptSlave::SetupPath - ( - cSpline< 4, 512 > *pPath, - SimpleEntity *se - ) +void ScriptSlave::TriggerFunc(Event* ev) { - str name; - //int iObjNum; - Vector vLastOrigin; - SimpleEntity *ent; - int i; - static cSpline< 4, 512 > *pTmpPath = NULL; - - if( !pTmpPath ) - { - pTmpPath = new cSpline < 4, 512 >; - } - - if( !pPath ) - { - return; - } - - pPath->Reset(); - pTmpPath->Reset(); - - vLastOrigin = se->origin; - - name = se->Target(); - - if( name.c_str() ) - { - Vector vDelta; - vec4_t origin; - float fCurLength; - - i = 0; - fCurLength = 0; - ent = se; - while( ent ) - { - if( vLastOrigin.length() == 0.0f && i > 1 ) - { - Com_Printf( "^~^~^Warning: ScriptSlave Flying with a Path that contains 2 equal points\n" ); - } - else - { - origin[ 0 ] = fCurLength; - origin[ 1 ] = ent->origin[ 0 ]; - origin[ 2 ] = ent->origin[ 1 ]; - origin[ 3 ] = ent->origin[ 2 ]; - pTmpPath->Add( origin, 0 ); - vLastOrigin = ent->origin; - fCurLength++; - } - - if( ent == se && i > 1 ) - break; - - i++; - ent = ent->Next(); - } - - if( pTmpPath->m_iPoints > 2 ) - { - float *vTmp; - - pPath->Reset(); - vTmp = pTmpPath->GetByNode( 0.0f, 0 ); - - vLastOrigin[ 0 ] = vTmp[ 1 ]; - vLastOrigin[ 1 ] = vTmp[ 2 ]; - vLastOrigin[ 2 ] = vTmp[ 3 ]; - - fCurLength = 0; - - for( i = 0; i < pTmpPath->m_iPoints; i++ ) - { - vTmp = pTmpPath->GetByNode( i, 0 ); - - vDelta = ( vTmp + 1 ) - vLastOrigin; - - fCurLength += vDelta.length(); - origin[ 0 ] = fCurLength; - origin[ 1 ] = vTmp[ 1 ]; - origin[ 2 ] = vTmp[ 2 ]; - origin[ 3 ] = vTmp[ 3 ]; - - pPath->Add( origin, 0 ); - vLastOrigin = ( vTmp + 1 ); - } - } - } + parm.other = ev->GetEntity(1); + parm.owner = parm.other; + Unregister(STRING_TRIGGER); } +void ScriptSlave::UseFunc(Event* ev) +{ + parm.other = ev->GetEntity(1); + parm.owner = parm.other; + Unregister(STRING_USE); +} + +void ScriptSlave::DamageFunc(Event *ev) +{ + Unregister(STRING_DAMAGE); +} + +void ScriptSlave::SetDamage(Event *ev) +{ + dmg = ev->GetInteger(1); +} + +void ScriptSlave::SetMeansOfDeath(Event *ev) +{ + dmg_means_of_death = MOD_string_to_int(ev->GetString(1)); +} + +void ScriptSlave::CreatePath(SplinePath *path, splinetype_t type) +{ + SplinePath *node; + + if (!splinePath) { + splinePath = new BSpline; + } + + splinePath->Clear(); + splinePath->SetType(type); + + node = path; + while (node != NULL) { + splinePath->AppendControlPoint(node->origin, node->angles, node->speed); + node = node->GetNext(); + + if (node == path) { + break; + } + } +} + +void ScriptSlave::FollowPath(Event *ev) +{ + int i, argnum; + SimpleEntity *ent; + str token; + SplinePath *path; + qboolean clamp; + float starttime; + + ent = ev->GetSimpleEntity(1); + argnum = 2; + starttime = -2; + clamp = true; + ignoreangles = false; + ignorevelocity = false; + splineangles = true; + for (i = argnum; i <= ev->NumArgs(); i++) { + token = ev->GetString(i); + if (!Q_stricmp(token, "ignoreangles")) { + ignoreangles = true; + } else if (!Q_stricmp(token, "ignorevelocity")) { + ignorevelocity = true; + } else if (!Q_stricmp(token, "normalangles")) { + splineangles = false; + } else if (!Q_stricmp(token, "loop")) { + clamp = false; + } else if (IsNumeric(token)) { + starttime = atof(token); + // Fixed in OPM + // HACKHACK + // + // There is a bug in mohaa where the token's raw pointer is directly used + // but then the token can be freed before comparison, which cause + // starttime to be always 0. + // OPM is correct here but for compatibility purpose the bug have to be reproduced. + // Otherwise, for example the final bomber plane in t3l2 will not fly. + if (!ev->IsStringAt(i)) { + starttime = 0; + } + } else { + ScriptError("Unknown followpath command %s.", token.c_str()); + } + } + + if (ent && ent->IsSubclassOfSplinePath()) { + path = (SplinePath *)ent; + if (clamp) { + CreatePath(path, SPLINE_CLAMP); + } else { + CreatePath(path, SPLINE_LOOP); + } + splineTime = starttime; + CancelEventsOfType(EV_ScriptSlave_FollowingPath); + if (!ignoreangles) { + avelocity = vec_zero; + } + if (!ignorevelocity) { + velocity = vec_zero; + } + } +} + +void ScriptSlave::FollowPathRelativeYaw(Event *ev) +{ + m_fFollowRelativeYaw = ev->GetFloat(1); +} + +void ScriptSlave::EndPath(Event *ev) +{ + if (!splinePath) { + return; + } + + delete splinePath; + splinePath = NULL; + if (!ignorevelocity) { + velocity = vec_zero; + } + if (!ignoreangles) { + avelocity = vec_zero; + } +} + +void ScriptSlave::FollowingPath(Event *ev) +{ + Vector pos; + Vector orient; + float speed_multiplier; + + if (m_pCurPath && m_pCurPath->m_iPoints) { + Vector vAngles; + Vector vDeltaAngles; + Vector vDelta; + float *vTmp; + Vector vPrev; + Vector vCur; + Vector vTotal; + float fCoef; + Vector vWishPosition; + Vector vWishAngles; + Vector vNextWishAngles; + Vector primal_angles; + Vector n_angles; + + if (g_showflypath && g_showflypath->integer) { + for (int i = 0; i < m_pCurPath->m_iPoints; i++) { + vTmp = m_pCurPath->GetByNode(i, NULL); + VectorCopy((vTmp + 1), vCur); + + G_DebugBBox(vCur, Vector(-32, -32, -32), Vector(32, 32, 32), 0, 1, 1, 1); + + for (int ii = 0; ii <= 8; ii++) { + vTmp = m_pCurPath->GetByNode(i + ii / 10.0, NULL); + VectorCopy((vTmp + 1), vPrev); + vTmp = m_pCurPath->GetByNode(i + ii / 10.0 + m_fLookAhead, NULL); + VectorCopy((vTmp + 1), vCur); + + G_DebugLine(vPrev, vCur, 0, 1, 0, 1); + } + } + } + + if (m_iCurNode > 0) { + // Get previous node + vTmp = m_pCurPath->GetByNode(m_iCurNode - 1, NULL); + vPrev = (vTmp + 1); + // Get current node + vTmp = m_pCurPath->GetByNode(m_iCurNode, NULL); + vCur = (vTmp + 1); + + vDelta = vCur - vPrev; + m_vIdealDir = vDelta; + VectorNormalize(m_vIdealDir); + angles.AngleVectorsLeft(&vWishAngles); + + fCoef = ProjectLineOnPlane(vWishAngles, DotProduct(origin, vWishAngles), vPrev, vCur, NULL); + + vTmp = m_pCurPath->GetByNode(m_iCurNode - (1.0 - fCoef), NULL); + vTmp = m_pCurPath->Get(vTmp[0] + m_fLookAhead, NULL); + vWishPosition = (vTmp + 1); + + if (fCoef > 1.0f) { + m_iCurNode++; + + if (m_iCurNode >= m_pCurPath->m_iPoints) { + velocity = vec_zero; + avelocity = vec_zero; + + delete m_pCurPath; + m_pCurPath = NULL; + m_iCurNode = 0; + moving = false; + + ProcessEvent(EV_ScriptSlave_MoveDone); + return; + } + } + } else { + vTmp = m_pCurPath->GetByNode(m_iCurNode, NULL); + vWishPosition = (vTmp + 1); + vDelta = vWishPosition - origin; + + if (vDelta.length() <= 32.0f) { + m_iCurNode++; + + if (m_iCurNode >= m_pCurPath->m_iPoints) { + velocity = vec_zero; + avelocity = vec_zero; + + delete m_pCurPath; + m_pCurPath = NULL; + m_iCurNode = 0; + moving = false; + ProcessEvent(EV_ScriptSlave_MoveDone); + return; + } + } + } + + vDelta = vWishPosition - origin; + + if (vDelta.length() > 0.0f) { + vDelta.normalize(); + VectorToAngles(vDelta, vNextWishAngles); + + // + // Added in 2.0 + // Relative yaw + vNextWishAngles[1] += m_fFollowRelativeYaw; + if (m_fFollowRelativeYaw == 180) { + vNextWishAngles[0] *= -1; + } + } else { + vNextWishAngles = angles; + AngleVectorsLeft(angles, vDelta, NULL, NULL); + } + + vAngles = angles; + + for (int i = 0; i < 3; i++) { + float change, error; + + n_angles[i] = vNextWishAngles[i] - angles[i]; + + if (n_angles[i] > 180) { + n_angles[i] -= 360; + } else if (n_angles[i] < -180) { + n_angles[i] += 360; + } + + change = level.frametime * 360.0f; + error = 0.33f * n_angles[i]; + + if (error < -change) { + error = -change; + } else if (error > change) { + error = change; + } + + primal_angles[i] = angles[i] + error; + } + + setAngles(primal_angles); + + vDeltaAngles = (angles - vAngles) * level.frametime; + + if (vDeltaAngles[0] > 180.0f || vDeltaAngles[0] <= -180.0f) { + vDeltaAngles[0] = 0.0f; + } + + if (vDeltaAngles[1] > 180.0f || vDeltaAngles[1] <= -180.0f) { + vDeltaAngles[1] = 0.0f; + } + + if (vDeltaAngles[2] > 180.0f || vDeltaAngles[2] <= -180.0f) { + vDeltaAngles[2] = 0.0f; + } + + if (vDeltaAngles[0] > -1.0f || vDeltaAngles[0] < 1.0f) { + vDeltaAngles[0] = 0.0f; + } + + if (vDeltaAngles[1] > -1.0f || vDeltaAngles[1] < 1.0f) { + vDeltaAngles[1] = 0.0f; + } + + if (vDeltaAngles[2] > -1.0f || vDeltaAngles[2] < 1.0f) { + vDeltaAngles[2] = 0.0f; + } + + avelocity = vDeltaAngles; + velocity = vDelta * m_fCurSpeed; + + if (m_fIdealSpeed > m_fCurSpeed) { + m_fCurSpeed += m_fIdealAccel * level.frametime; + + if (m_fCurSpeed > m_fIdealSpeed) { + m_fCurSpeed = m_fIdealSpeed; + } + } else if (m_fIdealSpeed < m_fCurSpeed) { + m_fCurSpeed -= m_fIdealAccel * level.frametime; + + if (m_fCurSpeed < m_fIdealSpeed) { + m_fCurSpeed = m_fIdealSpeed; + } + } + } else { + if (!splinePath) { + return; + } + + if ((splinePath->GetType() == SPLINE_CLAMP) && (splineTime > (splinePath->EndPoint() - 2))) { + delete splinePath; + splinePath = NULL; + if (!ignorevelocity) { + velocity = vec_zero; + } + if (!ignoreangles) { + avelocity = vec_zero; + } + moving = false; + ProcessEvent(EV_ScriptSlave_MoveDone); + return; + } + + speed_multiplier = splinePath->Eval(splineTime, pos, orient); + + splineTime += level.frametime * speed_multiplier; + + velocity = (pos - origin) * (1 / level.frametime); + if (!ignoreangles) { + if (splineangles) { + avelocity = (orient - angles) * (1 / level.frametime); + } else { + float len; + + len = velocity.length(); + if (len > 0.05) { + Vector ang; + Vector dir; + float aroll; + + aroll = avelocity[ROLL]; + dir = velocity * (1 / len); + ang = dir.toAngles(); + avelocity = (ang - angles) * (1 / level.frametime); + avelocity[ROLL] = aroll; + } else { + avelocity = vec_zero; + } + } + } + } + + PostEvent(EV_ScriptSlave_FollowingPath, level.frametime); +} + +void ScriptSlave::Explode(Event *ev) +{ + float damage; + + if (ev->NumArgs()) { + damage = ev->GetFloat(1); + } else { + damage = 120.0f; + } + + CreateExplosion(origin, damage, this, this, this); +} + +void ScriptSlave::NotShootable(Event *ev) +{ + setContents(0); +} + +void ScriptSlave::OpenPortal(Event *ev) +{ + gi.AdjustAreaPortalState(this->edict, true); +} + +void ScriptSlave::ClosePortal(Event *ev) +{ + gi.AdjustAreaPortalState(this->edict, false); +} + +void ScriptSlave::PhysicsOn(Event *ev) +{ + commandswaiting = false; + setMoveType(MOVETYPE_BOUNCE); + setSolidType(SOLID_BBOX); + velocity = Vector(0, 0, 1); + edict->clipmask = MASK_SOLID | CONTENTS_BODY; + if (ev->NumArgs() == 1 && ev->GetInteger(1)) { + edict->clipmask &= ~MASK_SCRIPT_SLAVE; + } +} + +void ScriptSlave::PhysicsOff(Event *ev) +{ + Event *event; + + commandswaiting = false; + setMoveType(MOVETYPE_PUSH); + edict->clipmask = 0; + // become solid again + event = new Event(EV_Model); + event->AddString(model); + PostEvent(event, 0); +} + +void ScriptSlave::PhysicsVelocity(Event *ev) +{ + velocity += ev->GetVector(1); +} + +void ScriptSlave::EventFlyPath(Event *ev) +{ + SimpleEntity *path; + + m_fIdealDistance = 100.0f; + m_fLookAhead = 256.0f; + m_fIdealAccel = 35.0f; + m_fIdealSpeed = 250.0f; + + if (ev->NumArgs() != 1 && ev->NumArgs() != 2 && ev->NumArgs() != 3 && ev->NumArgs() != 4) { + ScriptError("wrong number of arguments"); + } + + if (ev->NumArgs() > 1) { + m_fIdealSpeed = ev->GetFloat(2); + } + + if (ev->NumArgs() > 2) { + m_fIdealAccel = ev->GetFloat(3); + } + + if (ev->NumArgs() > 3) { + m_fLookAhead = ev->GetFloat(4); + } + + path = ev->GetSimpleEntity(1); + + if (!path) { + ScriptError("ScriptSlave Given FlyPath Command with NULL path."); + } + + if (m_pCurPath) { + delete m_pCurPath; + } + + m_pCurPath = new cSpline<4, 512>; + + SetupPath(m_pCurPath, path); + m_iCurNode = 0; + CancelEventsOfType(EV_ScriptSlave_FollowingPath); +} + +void ScriptSlave::EventModifyFlyPath(Event *ev) +{ + m_fIdealDistance = 100.0f; + + if (ev->NumArgs() != 1 && ev->NumArgs() != 2 && ev->NumArgs() != 3) { + ScriptError("wrong number of arguments"); + } + + if (ev->NumArgs() > 0) { + m_fIdealSpeed = ev->GetFloat(1); + } + + if (ev->NumArgs() > 1) { + m_fIdealAccel = ev->GetFloat(2); + } + + if (ev->NumArgs() > 2) { + m_fLookAhead = ev->GetFloat(3); + } +} + +void ScriptSlave::EventNormalAngles(Event *ev) +{ + splineangles = !ev->GetBoolean(1); + ignoreangles = false; +} + +void ScriptSlave::SetupPath(cSpline<4, 512> *pPath, SimpleEntity *se) +{ + str name; + int iObjNum = 0; + Vector vLastOrigin; + SimpleEntity *ent; + int i = 1; + static cSpline<4, 512> *pTmpPath = new cSpline<4, 512>; + + if (!pPath) { + return; + } + + pPath->Reset(); + pTmpPath->Reset(); + + vLastOrigin = se->origin; + + name = se->Target(); + + if (name.length()) { + for(ent = se; ent; ent = ent->Next()) { + Vector vDelta; + vec4_t vTmp; + + vDelta = vLastOrigin - ent->origin; + + if (vDelta.length() == 0 && i > 1) { + Com_Printf("^~^~^Warning: ScriptSlave Flying with a Path that contains 2 equal points\n"); + } else { + vTmp[0] = iObjNum++; + vTmp[1] = ent->origin[0]; + vTmp[2] = ent->origin[1]; + vTmp[3] = ent->origin[2]; + pTmpPath->Add(vTmp, 0); + vLastOrigin = ent->origin; + } + + if (ent == se && i > 1) { + break; + } + + i++; + } + } + + if (pTmpPath->m_iPoints > 2) { + float* vTmp; + float fCurLength = 0; + vec3_t vLastOrigin; + vec3_t origin; + vec3_t vDelta; + + pPath->Reset(); + + vTmp = pTmpPath->GetByNode(0, NULL); + VectorCopy((vTmp + 1), vLastOrigin); + VectorCopy((vTmp + 1), origin); + + for (i = 0; i < pTmpPath->m_iPoints; i++) { + vec4_t vTmp2; + + vTmp = pTmpPath->GetByNode(i, NULL); + + VectorCopy((vTmp + 1), vLastOrigin); + VectorSubtract(vLastOrigin, origin, vDelta); + + fCurLength += VectorLength(vDelta); + vTmp2[0] = fCurLength; + vTmp2[1] = vLastOrigin[0]; + vTmp2[2] = vLastOrigin[1]; + vTmp2[3] = vLastOrigin[2]; + + pPath->Add(vTmp2, 0); + VectorCopy(vLastOrigin, origin); + } + } +} /*****************************************************************************/ /*QUAKED script_model (0 0.5 1) (0 0 0) (0 0 0) NOT_SOLID @@ -2103,153 +1960,195 @@ void ScriptSlave::SetupPath ******************************************************************************/ Event EV_ScriptModel_SetAnim - ( - "anim", - EV_DEFAULT, - "s", - "anim_name", - "Sets the script model's animation", - EV_NORMAL - ); -Event EV_ScriptModel_AnimOnce - ( - "animonce", - EV_DEFAULT, - "s", - "anim_name", - "Sets the script model's animation but only plays it once", - EV_NORMAL - ); +( + "anim", + EV_DEFAULT, + "s", + "anim_name", + "Sets the script model's animation", + EV_NORMAL +); +Event EV_ScriptModel_AnimDone +( + "animdone", + EV_ZERO, + NULL, + NULL, + "Script model animation has finished.", + EV_NORMAL +); +Event EV_ScriptModel_MoveAnim +( + "moveanim", + EV_DEFAULT, + "s", + "animName", + "Makes the script model play an animation and move with the deltas contained in the animation", + EV_NORMAL +); +Event EV_ScriptModel_MovingAnim +( + "moving_from_anim", + EV_DEFAULT, + NULL, + NULL, + "The script model is moving based on an animation", + EV_NORMAL +); -CLASS_DECLARATION( ScriptSlave, ScriptModel, "script_model" ) - { - { &EV_Gib, &ScriptModel::GibEvent }, - { &EV_SetAngle, &ScriptModel::SetAngleEvent }, - { &EV_ScriptModel_SetAnim, &ScriptModel::SetAnimEvent }, - { &EV_ScriptModel_AnimOnce, &ScriptModel::AnimOnceEvent }, - { &EV_Model, &ScriptModel::SetModelEvent }, - { NULL, NULL }, - }; +CLASS_DECLARATION(ScriptSlave, ScriptModel, "script_model") { + {&EV_SetAngle, &ScriptModel::SetAngleEvent }, + {&EV_ScriptModel_SetAnim, &ScriptModel::SetAnimEvent }, + {&EV_Model, &ScriptModel::SetModelEvent }, + {&EV_ScriptModel_AnimDone, &ScriptModel::AnimDoneEvent }, + {&EV_ScriptModel_MoveAnim, &ScriptModel::MoveAnimEvent }, + {&EV_ScriptModel_MovingAnim, &ScriptModel::MovingFromAnimEvent}, + {NULL, NULL }, +}; ScriptModel::ScriptModel() { - // this is a tiki model - edict->s.eType = ET_MODELANIM; + // this is a tiki model + edict->s.eType = ET_MODELANIM; + + AddWaitTill(STRING_ANIMDONE); } -void ScriptModel::SetModelEvent - ( - Event *ev - ) +void ScriptModel::SetModelEvent(Event *ev) +{ + ScriptSlave::SetModelEvent(ev); - { - ScriptSlave::SetModelEvent( ev ); + if (edict->tiki && !mins.length() && !maxs.length()) { + gi.TIKI_CalculateBounds(edict->tiki, edict->s.scale, mins, maxs); + } +} - if( ( gi.modeltiki( model ) ) && !mins.length() && !maxs.length() ) - { - gi.CalculateBounds( edict->tiki, edict->s.scale, mins, maxs ); - } - } +void ScriptModel::SetAnimEvent(Event *ev) +{ + str animname; -void ScriptModel::SetAnimEvent - ( - Event *ev - ) + animname = ev->GetString(1); + if (animname.length() && edict->tiki) { + int animnum; - { - const char * animname; + animnum = gi.Anim_NumForName(edict->tiki, animname); + if (animnum >= 0) { + NewAnim(animnum, EV_ScriptModel_AnimDone); + RestartAnimSlot(0); + } + } +} - animname = ev->GetString( 1 ); - if( animname && strlen( animname ) && gi.modeltiki( model ) ) - { - int animnum; +void ScriptModel::AnimDoneEvent(Event *ev) +{ + CancelEventsOfType(EV_ScriptModel_MovingAnim); + Unregister(STRING_ANIMDONE); +} - animnum = gi.Anim_NumForName( edict->tiki, animname ); - if ( animnum >= 0 ) - { - NewAnim( animnum ); - } - } - } +void ScriptModel::MoveAnimEvent(Event *ev) +{ + str animName; + int animNum; -void ScriptModel::AnimOnceEvent - ( - Event *ev - ) + animName = ev->GetString(1); - { - const char * animname; + if (!animName.length()) { + return; + } - animname = ev->GetString( 1 ); - if( animname && strlen( animname ) && gi.modeltiki( model ) ) - { - NewAnim( animname ); - } - } + animNum = gi.Anim_NumForName(edict->tiki, animName.c_str()); + if (animNum < 0) { + ScriptError("ScriptModel could not find animation %s.", animName.c_str()); + } -void ScriptModel::SetAngleEvent - ( - Event *ev - ) + NewAnim(animNum, EV_ScriptModel_AnimDone); + RestartAnimSlot(0); + PostEvent(EV_ScriptModel_MovingAnim, 0); +} - { - float angle; +void ScriptModel::MovingFromAnimEvent(Event *ev) +{ + Vector newOrigin; + Vector newAngles; - angle = ev->GetFloat( 1 ); - if ( angle == -1 ) - { - ForwardDir = Vector( 0, 0, 90 ); - localangles = Vector( -90, 0, 0 ); - } - else if ( angle == -2 ) - { - ForwardDir = Vector( 0, 0, -90 ); - localangles = Vector( 90, 0, 0 ); - } - else - { - ForwardDir = Vector( 0, angle, 0 ); - localangles = Vector( 0, angle, 0 ); - } + // calculate velocity + newOrigin = origin + frame_delta; + velocity = (newOrigin - origin) / level.frametime; - setAngles( localangles ); - } + // calculate angular velocity + newAngles = angles + Vector(0, angular_delta, 0); + avelocity = (newAngles - angles) / level.frametime; -void ScriptModel::GibEvent - ( - Event *ev - ) + PostEvent(EV_ScriptModel_MovingAnim, level.frametime); +} - { - int num,power; - float scale; +void ScriptModel::SetAngleEvent(Event *ev) +{ + float angle; - setSolidType( SOLID_NOT ); - hideModel(); + angle = ev->GetFloat(1); + if (angle == -1) { + ForwardDir = Vector(0, 0, 90); + localangles = Vector(-90, 0, 0); + } else if (angle == -2) { + ForwardDir = Vector(0, 0, -90); + localangles = Vector(90, 0, 0); + } else { + ForwardDir = Vector(0, angle, 0); + localangles = Vector(0, angle, 0); + } - if ( !com_blood->integer ) - { - PostEvent( EV_Remove, 0 ); - return; - } + setAngles(localangles); +} - num = ev->GetInteger( 1 ); - power = ev->GetInteger( 2 ); - scale = ev->GetFloat( 3 ); +void ScriptModel::GibEvent(Event *ev) +{ + int num, power; + float scale; - power = -power; + setSolidType(SOLID_NOT); + hideModel(); - if ( ev->NumArgs() > 3 ) - { - CreateGibs( this, power, scale, num, ev->GetString( 4 ) ); - } - else - { - CreateGibs( this, power, scale, num ); - } + if (!com_blood->integer) { + PostEvent(EV_Remove, 0); + return; + } - PostEvent( EV_Remove, 0 ); - } + num = ev->GetInteger(1); + power = ev->GetInteger(2); + scale = ev->GetFloat(3); + + power = -power; + + if (ev->NumArgs() > 3) { + CreateGibs(this, power, scale, num, ev->GetString(4)); + } else { + CreateGibs(this, power, scale, num); + } + + PostEvent(EV_Remove, 0); +} + +/*****************************************************************************/ +/*QUAKED script_model_realdamage (0 0.5 1) (0 0 0) (0 0 0) NOT_SOLID ALWAYS_DRAW + +******************************************************************************/ +/*****************************************************************************/ + +CLASS_DECLARATION(ScriptModel, ScriptModelRealDamage, "script_model_realdamage") { + {&EV_Damage, &ScriptModelRealDamage::EventDamage}, + {NULL, NULL } +}; + +ScriptModelRealDamage::ScriptModelRealDamage() +{ + RemoveWaitTill(STRING_DAMAGE); +} + +void ScriptModelRealDamage::EventDamage(Event *ev) +{ + Entity::DamageEvent(ev); +} /*****************************************************************************/ /*QUAKED script_origin (1.0 0 0) (-8 -8 -8) (8 8 8) @@ -2258,17 +2157,80 @@ Used as an alternate origin for objects. Bind the object to the script_origin in order to simulate changing that object's origin. ******************************************************************************/ -CLASS_DECLARATION( ScriptSlave, ScriptOrigin, "script_origin" ) - { - { &EV_Model, &ScriptOrigin::SetModelEvent }, - { NULL, NULL } - }; +// Added in 2.30 +Event EV_ScriptOrigin_SetAngle +( + "angle", + EV_DEFAULT, + "f", + "newAngle", + "set the angles of the entity using just one value.\n" + "Sets the yaw of the entity or an up and down\n" + "direction if newAngle is [0-359] or -1 or -2" +); + +// Added in 2.30 +Event EV_ScriptOrigin_GetAngle +( + "angle", + EV_DEFAULT, + NULL, + NULL, + "get the angles of the entity using just one value.\n" + "Gets the yaw of the entity or an up and down\n" + "direction if newAngle is [0-359] or -1 or -2", + EV_GETTER +); + +CLASS_DECLARATION(ScriptSlave, ScriptOrigin, "script_origin") { + {&EV_Model, &ScriptOrigin::SetModelEvent}, + + // + // Added in 2.30 + // + {&EV_ScriptOrigin_SetAngle, &ScriptOrigin::SetAngleEvent}, + {&EV_ScriptOrigin_GetAngle, &ScriptOrigin::GetAngleEvent}, + {NULL, NULL } +}; ScriptOrigin::ScriptOrigin() - { - setContents( 0 ); - setSolidType( SOLID_NOT ); - } +{ + setContents(0); + setSolidType(SOLID_NOT); +} + +void ScriptOrigin::SetAngleEvent(Event* ev) +{ + float angle; + + if (g_target_game < target_game_e::TG_MOHTT) { + // Restore the old behavior on previous versions (below 2.30). + // For example, higgins rangers in m3l1a would not face forward + return ScriptSlave::SetAngleEvent(ev); + } + + angle = ev->GetFloat(1); + if (angle == -1) { + ForwardDir = Vector(0, 0, 90); + localangles = Vector(-90, 0, 0); + } else if (angle == -2) { + ForwardDir = Vector(0, 0, -90); + localangles = Vector(90, 0, 0); + } else { + ForwardDir = Vector(0, angle, 0); + localangles = Vector(0, angle, 0); + } + + setAngles(localangles); +} + +void ScriptOrigin::GetAngleEvent(Event* ev) +{ + Vector forward; + + angles.AngleVectorsLeft(&forward); + ev->AddFloat(G_GetAngle(forward)); +} /*****************************************************************************/ /*QUAKED script_skyorigin (1.0 0 0) ? @@ -2276,14 +2238,199 @@ ScriptOrigin::ScriptOrigin() Used to specify the origin of a portal sky ******************************************************************************/ -CLASS_DECLARATION( ScriptSlave, ScriptSkyOrigin, "script_skyorigin" ) - { - { NULL, NULL } - }; +CLASS_DECLARATION(ScriptSlave, ScriptSkyOrigin, "script_skyorigin") { + {NULL, NULL} +}; ScriptSkyOrigin::ScriptSkyOrigin() - { - edict->s.renderfx |= RF_SKYORIGIN; - setContents( 0 ); - setSolidType( SOLID_NOT ); - } +{ + edict->s.renderfx |= RF_SKYORIGIN; + edict->r.svFlags &= ~SVF_NOCLIENT; + setContents(0); + setSolidType(SOLID_NOT); +} + +Event EV_ScriptSimpleStrafingGunfire_On +( + "on", + EV_DEFAULT, + NULL, + NULL, + "Turn the gunfire on.", + EV_NORMAL +); +Event EV_ScriptSimpleStrafingGunfire_Off +( + "off", + EV_DEFAULT, + NULL, + NULL, + "Turn the gunfire off.", + EV_NORMAL +); +Event EV_ScriptSimpleStrafingGunfire_Fire +( + "fire", + EV_DEFAULT, + NULL, + NULL, + "Fire.", + EV_NORMAL +); +Event EV_ScriptSimpleStrafingGunfire_TracerFreq +( + "tracerfreq", + EV_DEFAULT, + "f", + NULL, + "Set the frequency of the tracers", + EV_NORMAL +); +Event EV_ScriptSimpleStrafingGunfire_ProjectileModel +( + "projectile", + EV_DEFAULT, + "s", + NULL, + "Set the projectile model", + EV_NORMAL +); + +CLASS_DECLARATION(ScriptSlave, ScriptSimpleStrafingGunfire, "script_simplestrafinggunfire") { + {&EV_ScriptSimpleStrafingGunfire_On, &ScriptSimpleStrafingGunfire::GunOn }, + {&EV_ScriptSimpleStrafingGunfire_Off, &ScriptSimpleStrafingGunfire::GunOff }, + {&EV_ScriptSimpleStrafingGunfire_Fire, &ScriptSimpleStrafingGunfire::GunFire }, + {&EV_Weapon_FireDelay, &ScriptSimpleStrafingGunfire::SetFireDelay }, + {&EV_Weapon_SetBulletRange, &ScriptSimpleStrafingGunfire::SetRange }, + {&EV_Weapon_SetBulletSpread, &ScriptSimpleStrafingGunfire::SetSpread }, + {&EV_Weapon_SetBulletDamage, &ScriptSimpleStrafingGunfire::SetDamage }, + {&EV_Weapon_SetBulletKnockback, &ScriptSimpleStrafingGunfire::SetKnockback }, + {&EV_Weapon_SetBulletThroughWood, &ScriptSimpleStrafingGunfire::SetThroughWood }, + {&EV_Weapon_SetBulletThroughMetal, &ScriptSimpleStrafingGunfire::SetThroughMetal }, + {&EV_Weapon_SetBulletCount, &ScriptSimpleStrafingGunfire::SetBulletCount }, + {&EV_ScriptSimpleStrafingGunfire_TracerFreq, &ScriptSimpleStrafingGunfire::SetTracerFreq }, + {&EV_ScriptSimpleStrafingGunfire_ProjectileModel, &ScriptSimpleStrafingGunfire::SetProjectileModel}, + {NULL, NULL } +}; + +ScriptSimpleStrafingGunfire::ScriptSimpleStrafingGunfire() +{ + isOn = false; + fireDelay = 0.05f; + range = 4000; + spread = Vector(100, 100, 0); + damage = 100; + knockback = 0; + throughWood = 0; + throughMetal = 0; + bulletCount = 1; + tracerCount = 0; + tracerFrequency = 0; + projectileModel = "models/projectiles/stukaround.tik"; +} + +void ScriptSimpleStrafingGunfire::GunOn(Event *ev) +{ + isOn = true; + + CancelEventsOfType(&EV_ScriptSimpleStrafingGunfire_Fire); + PostEvent(EV_ScriptSimpleStrafingGunfire_Fire, 0.05f); +} + +void ScriptSimpleStrafingGunfire::GunOff(Event *ev) +{ + isOn = false; + + CancelEventsOfType(&EV_ScriptSimpleStrafingGunfire_Fire); +} + +void ScriptSimpleStrafingGunfire::GunFire(Event *ev) +{ + Vector dir, right, up; + Vector horzAngles; + + AngleVectors(angles, NULL, NULL, up); + dir = -1 * up; + + VectorToAngles(dir, horzAngles); + AngleVectors(horzAngles, NULL, right, up); + + dir = dir * range + right * grandom() * spread.x; + dir += up * grandom() * spread.y; + dir.normalize(); + + ProjectileAttack(origin, dir, this, projectileModel, 1, 0, NULL); + // continue firing + PostEvent(EV_ScriptSimpleStrafingGunfire_Fire, fireDelay); +} + +void ScriptSimpleStrafingGunfire::Archive(Archiver& arc) +{ + ScriptSlave::Archive(arc); + + arc.ArchiveBoolean(&isOn); + arc.ArchiveFloat(&fireDelay); + arc.ArchiveFloat(&range); + arc.ArchiveVector(&spread); + arc.ArchiveFloat(&damage); + arc.ArchiveFloat(&knockback); + arc.ArchiveFloat(&throughWood); + arc.ArchiveFloat(&throughMetal); + arc.ArchiveInteger(&bulletCount); + arc.ArchiveInteger(&tracerCount); + arc.ArchiveInteger(&tracerFrequency); + arc.ArchiveString(&projectileModel); +} + +Event EV_ScriptAimedStrafingGunfire_AimTarget +( + "aimtarget", + EV_DEFAULT, + "e", + NULL, + "Set the aim target.", + EV_NORMAL +); + +CLASS_DECLARATION(ScriptSimpleStrafingGunfire, ScriptAimedStrafingGunfire, "script_aimedstrafinggunfire") { + {&EV_ScriptAimedStrafingGunfire_AimTarget, &ScriptAimedStrafingGunfire::SetAimTarget}, + {&EV_ScriptSimpleStrafingGunfire_Fire, &ScriptAimedStrafingGunfire::GunFire }, + {NULL, NULL } +}; + +ScriptAimedStrafingGunfire::ScriptAimedStrafingGunfire() +{ + aimTarget = NULL; +} + +void ScriptAimedStrafingGunfire::GunFire(Event *ev) +{ + if (!aimTarget) { + ScriptSimpleStrafingGunfire::GunFire(ev); + return; + } + + Vector dir, right, up; + Vector horzAngles; + + dir = aimTarget->origin - origin; + dir.normalize(); + + VectorToAngles(dir, horzAngles); + AngleVectors(horzAngles, NULL, right, up); + + dir = dir * range + right * grandom() * spread.x; + dir += up * grandom() * spread.y; + dir.normalize(); + + ProjectileAttack(origin, dir, this, projectileModel, 1, 0, NULL); + // continue firing + PostEvent(EV_ScriptSimpleStrafingGunfire_Fire, fireDelay); +} + +void ScriptAimedStrafingGunfire::Archive(Archiver& arc) +{ + ScriptSimpleStrafingGunfire::Archive(arc); + + arc.ArchiveObjectPointer((Class **)&aimTarget); +} diff --git a/code/fgame/scriptslave.h b/code/fgame/scriptslave.h index be35d25a..b3bbae74 100644 --- a/code/fgame/scriptslave.h +++ b/code/fgame/scriptslave.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -27,10 +27,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // perform several different relative and specific rotations and translations // and can cause other parts of the script to be executed when touched, damaged, // touched, or used. -// +// -#ifndef __SCRIPTSLAVE_H__ -#define __SCRIPTSLAVE_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -44,236 +43,373 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class ScriptSlave : public Mover { - protected: - float attack_finished; +protected: + float attack_finished; - int dmg; - int dmg_means_of_death; + int dmg; + int dmg_means_of_death; - public: - qboolean commandswaiting; +public: + qboolean commandswaiting; - Vector TotalRotation; - Vector NewAngles; - Vector NewPos; - Vector ForwardDir; - float speed; + Vector TotalRotation; + Vector NewAngles; + Vector NewPos; + Vector ForwardDir; + float speed; - Waypoint *waypoint; - float traveltime; - BSpline *splinePath; - float splineTime; + Waypoint *waypoint; + float traveltime; + BSpline *splinePath; + float splineTime; - cSpline<4, 512> *m_pCurPath; - int m_iCurNode; + cSpline<4, 512> *m_pCurPath; + int m_iCurNode; - float m_fCurSpeed; - float m_fIdealSpeed; - Vector m_vIdealPosition; - Vector m_vIdealDir; - float m_fIdealAccel; - float m_fIdealDistance; - float m_fLookAhead; + float m_fCurSpeed; + float m_fIdealSpeed; + Vector m_vIdealPosition; + Vector m_vIdealDir; + float m_fIdealAccel; + float m_fIdealDistance; + float m_fLookAhead; - qboolean splineangles; - qboolean ignoreangles; - qboolean ignorevelocity; - qboolean moving; // is the script object currently moving? + qboolean splineangles; + qboolean ignoreangles; + qboolean ignorevelocity; + float m_fFollowRelativeYaw; + qboolean moving; // is the script object currently moving? - protected: - void CheckNewOrders( void ); - void NewMove( void ); +protected: + void CheckNewOrders(void); + void NewMove(void); + CLASS_PROTOTYPE(ScriptSlave); - CLASS_PROTOTYPE( ScriptSlave ); + ScriptSlave(); + ~ScriptSlave(); - ScriptSlave(); - ~ScriptSlave(); + void BindEvent(Event *ev); + void EventUnbind(Event *ev); + void DoMove(Event *ev); + void WaitMove(Event *ev); + void Stop(Event *ev); + void ThreadMove(Event *ev); + void MoveEnd(Event *ev); + void SetAnglesEvent(Event *ev); + void SetAngleEvent(Event *ev); + void SetModelEvent(Event *ev); + void TriggerEvent(Event *ev) override; + void GotoNextWaypoint(Event *ev); + void JumpTo(Event *ev); + void MoveToEvent(Event *ev); + void SetSpeed(Event *ev); + void SetTime(Event *ev); + void MoveUp(Event *ev); + void MoveDown(Event *ev); + void MoveNorth(Event *ev); + void MoveSouth(Event *ev); + void MoveEast(Event *ev); + void MoveWest(Event *ev); + void MoveForward(Event *ev); + void MoveBackward(Event *ev); + void MoveLeft(Event *ev); + void MoveRight(Event *ev); + void MoveOffset(Event *ev); + void RotateXdownto(Event *ev); + void RotateYdownto(Event *ev); + void RotateZdownto(Event *ev); + void RotateAxisdownto(Event *ev); + void RotateXupto(Event *ev); + void RotateYupto(Event *ev); + void RotateZupto(Event *ev); + void RotateAxisupto(Event *ev); + void Rotateupto(Event *ev); + void Rotatedownto(Event *ev); + void Rotateto(Event *ev); + void RotateXdown(Event *ev); + void RotateYdown(Event *ev); + void RotateZdown(Event *ev); + void RotateAxisdown(Event *ev); + void RotateXup(Event *ev); + void RotateYup(Event *ev); + void RotateZup(Event *ev); + void RotateAxisup(Event *ev); + void RotateX(Event *ev); + void RotateY(Event *ev); + void RotateZ(Event *ev); + void RotateAxis(Event *ev); + void TouchFunc(Event *ev); + void BlockFunc(Event *ev); + void TriggerFunc(Event *ev); + void UseFunc(Event *ev); + void DamageFunc(Event *ev); + void SetDamage(Event *ev); + void SetMeansOfDeath(Event *ev); + void FollowPath(Event *ev); + void FollowPathRelativeYaw(Event *ev); // Added in 2.0 + void EndPath(Event *ev); + void FollowingPath(Event *ev); + void CreatePath(SplinePath *path, splinetype_t type); + void Explode(Event *ev); + void NotShootable(Event *ev); + void OpenPortal(Event *ev); + void ClosePortal(Event *ev); + void PhysicsOn(Event *ev); + void PhysicsOff(Event *ev); + void PhysicsVelocity(Event *ev); + void EventFlyPath(Event *ev); + void EventModifyFlyPath(Event *ev); + void EventNormalAngles(Event *ev); // Added in 2.0 + void SetupPath(cSpline<4, 512> *pPath, SimpleEntity *se); - void BindEvent( Event *ev ); - void EventUnbind( Event *ev ); - void DoMove( Event *ev ); - void WaitMove( Event *ev ); - void MoveEnd( Event *ev ); - void SetAnglesEvent( Event *ev ); - void SetAngleEvent( Event *ev ); - void SetModelEvent( Event *ev ); - void TriggerEvent( Event *ev ) override; - void GotoNextWaypoint( Event *ev ); - void JumpTo( Event *ev ); - void MoveToEvent( Event *ev ); - void SetSpeed( Event *ev ); - void SetTime( Event *ev ); - void MoveUp( Event *ev ); - void MoveDown( Event *ev ); - void MoveNorth( Event *ev ); - void MoveSouth( Event *ev ); - void MoveEast( Event *ev ); - void MoveWest( Event *ev ); - void MoveForward( Event *ev ); - void MoveBackward( Event *ev ); - void MoveLeft( Event *ev ); - void MoveRight( Event *ev ); - void RotateXdownto( Event *ev ); - void RotateYdownto( Event *ev ); - void RotateZdownto( Event *ev ); - void RotateAxisdownto( Event *ev ); - void RotateXupto( Event *ev ); - void RotateYupto( Event *ev ); - void RotateZupto( Event *ev ); - void RotateAxisupto( Event *ev ); - void Rotateupto( Event *ev ); - void Rotatedownto( Event *ev ); - void Rotateto( Event *ev ); - void RotateXdown( Event *ev ); - void RotateYdown( Event *ev ); - void RotateZdown( Event *ev ); - void RotateAxisdown( Event *ev ); - void RotateXup( Event *ev ); - void RotateYup( Event *ev ); - void RotateZup( Event *ev ); - void RotateAxisup( Event *ev ); - void RotateX( Event *ev ); - void RotateY( Event *ev ); - void RotateZ( Event *ev ); - void RotateAxis( Event *ev ); - void SetDamage( Event *ev ); - void SetMeansOfDeath( Event *ev ); - void FollowPath( Event *ev ); - void EndPath( Event *ev ); - void FollowingPath( Event *ev ); - void CreatePath( SplinePath *path, splinetype_t type ); - void Explode( Event *ev ); - void NotShootable( Event *ev ); - void OpenPortal( Event *ev ); - void ClosePortal( Event *ev ); - void PhysicsOn( Event *ev ); - void PhysicsOff( Event *ev ); - void PhysicsVelocity( Event *ev ); - void DamageFunc( Event *ev ); - void EventFlyPath( Event *ev ); - void EventModifyFlyPath( Event *ev ); - void SetupPath( cSpline< 4, 512 > *pPath, SimpleEntity *se ); + void Archive(Archiver& arc) override; +}; - void Archive( Archiver &arc ) override; - }; - -inline void ScriptSlave::Archive - ( - Archiver &arc - ) +inline void ScriptSlave::Archive(Archiver& arc) { - int tempInt; + int tempInt; - Mover::Archive( arc ); + Mover::Archive(arc); - arc.ArchiveFloat( &attack_finished ); - arc.ArchiveInteger( &dmg ); - arc.ArchiveInteger( &dmg_means_of_death ); + arc.ArchiveFloat(&attack_finished); + arc.ArchiveInteger(&dmg); + arc.ArchiveInteger(&dmg_means_of_death); - arc.ArchiveBoolean( &commandswaiting ); - arc.ArchiveVector( &TotalRotation ); - arc.ArchiveVector( &NewAngles ); - arc.ArchiveVector( &NewPos ); - arc.ArchiveVector( &ForwardDir ); - arc.ArchiveFloat( &speed ); - arc.ArchiveObjectPointer( ( Class ** )&waypoint ); - arc.ArchiveFloat( &traveltime ); + arc.ArchiveBoolean(&commandswaiting); + arc.ArchiveVector(&TotalRotation); + arc.ArchiveVector(&NewAngles); + arc.ArchiveVector(&NewPos); + arc.ArchiveVector(&ForwardDir); + arc.ArchiveFloat(&speed); + arc.ArchiveObjectPointer((Class **)&waypoint); + arc.ArchiveFloat(&traveltime); - if( arc.Saving() ) - { - // if it exists, archive it, otherwise place a special NULL ptr tag - if( splinePath ) - { - tempInt = ARCHIVE_POINTER_VALID; - } - else - { - tempInt = ARCHIVE_POINTER_NULL; - } - arc.ArchiveInteger( &tempInt ); - if( tempInt == ARCHIVE_POINTER_VALID ) - { - splinePath->Archive( arc ); - } - } - else - { - arc.ArchiveInteger( &tempInt ); - if( tempInt == ARCHIVE_POINTER_VALID ) - { - splinePath = new BSpline; - splinePath->Archive( arc ); - } - else - { - splinePath = NULL; - } - } - arc.ArchiveFloat( &splineTime ); - arc.ArchiveBoolean( &splineangles ); - arc.ArchiveBoolean( &ignoreangles ); - arc.ArchiveBoolean( &moving ); + if (arc.Saving()) { + // if it exists, archive it, otherwise place a special NULL ptr tag + if (splinePath) { + tempInt = ARCHIVE_POINTER_VALID; + } else { + tempInt = ARCHIVE_POINTER_NULL; + } + arc.ArchiveInteger(&tempInt); + if (tempInt == ARCHIVE_POINTER_VALID) { + splinePath->Archive(arc); + } + } else { + arc.ArchiveInteger(&tempInt); + if (tempInt == ARCHIVE_POINTER_VALID) { + splinePath = new BSpline; + splinePath->Archive(arc); + } else { + splinePath = NULL; + } + } + arc.ArchiveFloat(&splineTime); + arc.ArchiveBoolean(&splineangles); + arc.ArchiveBoolean(&ignoreangles); + arc.ArchiveBoolean(&ignorevelocity); + arc.ArchiveBoolean(&moving); - if( arc.Saving() ) - { - // if it exists, archive it, otherwise place a special NULL ptr tag - if( m_pCurPath ) - { - tempInt = ARCHIVE_POINTER_VALID; - } - else - { - tempInt = ARCHIVE_POINTER_NULL; - } - arc.ArchiveInteger( &tempInt ); - if( tempInt == ARCHIVE_POINTER_VALID ) - { - m_pCurPath->Archive( arc ); - } - } - else - { - arc.ArchiveInteger( &tempInt ); - if( tempInt == ARCHIVE_POINTER_VALID ) - { - m_pCurPath = new cSpline< 4, 512 >; - m_pCurPath->Archive( arc ); - } - else - { - m_pCurPath = NULL; - } - } + if (arc.Saving()) { + // if it exists, archive it, otherwise place a special NULL ptr tag + if (m_pCurPath) { + tempInt = ARCHIVE_POINTER_VALID; + } else { + tempInt = ARCHIVE_POINTER_NULL; + } + arc.ArchiveInteger(&tempInt); + if (tempInt == ARCHIVE_POINTER_VALID) { + m_pCurPath->Archive(arc); + } + } else { + arc.ArchiveInteger(&tempInt); + if (tempInt == ARCHIVE_POINTER_VALID) { + m_pCurPath = new cSpline<4, 512>; + m_pCurPath->Archive(arc); + } else { + m_pCurPath = NULL; + } + } + + arc.ArchiveInteger(&m_iCurNode); + arc.ArchiveFloat(&m_fCurSpeed); + arc.ArchiveFloat(&m_fIdealSpeed); + arc.ArchiveVector(&m_vIdealPosition); + arc.ArchiveVector(&m_vIdealDir); + arc.ArchiveFloat(&m_fIdealAccel); + arc.ArchiveFloat(&m_fIdealDistance); + arc.ArchiveFloat(&m_fLookAhead); + arc.ArchiveFloat(&m_fFollowRelativeYaw); } class ScriptModel : public ScriptSlave - { - private: - void GibEvent(Event *ev); +{ +private: + void GibEvent(Event *ev); - public: - CLASS_PROTOTYPE( ScriptModel ); +public: + CLASS_PROTOTYPE(ScriptModel); - ScriptModel(); - void SetAngleEvent( Event *ev ); - void SetModelEvent( Event *ev ); - void SetAnimEvent( Event *ev ); - void AnimOnceEvent( Event *ev ); - }; + ScriptModel(); + void SetAngleEvent(Event *ev); + void SetModelEvent(Event *ev); + void SetAnimEvent(Event *ev); + void AnimDoneEvent(Event *ev); + void MoveAnimEvent(Event *ev); + void MovingFromAnimEvent(Event *ev); + + void Archive(Archiver& arc) override; +}; + +inline void ScriptModel::Archive(Archiver& arc) +{ + ScriptSlave::Archive(arc); +} + +class ScriptModelRealDamage : public ScriptModel +{ +public: + CLASS_PROTOTYPE(ScriptModelRealDamage); + + ScriptModelRealDamage(); + void EventDamage(Event *ev); + + void Archive(Archiver& arc) override; +}; + +inline void ScriptModelRealDamage::Archive(Archiver& arc) +{ + ScriptModel::Archive(arc); +} class ScriptOrigin : public ScriptSlave - { - public: - CLASS_PROTOTYPE( ScriptOrigin ); - ScriptOrigin(); - }; +{ +public: + CLASS_PROTOTYPE(ScriptOrigin); + ScriptOrigin(); + + void SetAngleEvent(Event *ev); // Added in 2.30 + void GetAngleEvent(Event *ev); // Added in 2.30 +}; class ScriptSkyOrigin : public ScriptSlave - { - public: - CLASS_PROTOTYPE( ScriptSkyOrigin ); - ScriptSkyOrigin(); - }; +{ +public: + CLASS_PROTOTYPE(ScriptSkyOrigin); + ScriptSkyOrigin(); +}; -#endif /* scriptslave.h */ +class ScriptSimpleStrafingGunfire : public ScriptSlave +{ +protected: + qboolean isOn; + float fireDelay; + float range; + Vector spread; + float damage; + float knockback; + float throughWood; + float throughMetal; + int bulletCount; + int tracerCount; + int tracerFrequency; + str projectileModel; + +public: + CLASS_PROTOTYPE(ScriptSimpleStrafingGunfire); + + ScriptSimpleStrafingGunfire(); + + void Archive(Archiver& arc) override; + +protected: + void GunFire(Event *ev); + +private: + void GunOn(Event *ev); + void GunOff(Event *ev); + void SetFireDelay(Event *ev); + void SetRange(Event *ev); + void SetSpread(Event *ev); + void SetDamage(Event *ev); + void SetKnockback(Event *ev); + void SetThroughWood(Event *ev); + void SetThroughMetal(Event *ev); + void SetBulletCount(Event *ev); + void SetTracerFreq(Event *ev); + void SetProjectileModel(Event *ev); +}; + +inline void ScriptSimpleStrafingGunfire::SetFireDelay(Event *ev) +{ + fireDelay = ev->GetFloat(1); +} + +inline void ScriptSimpleStrafingGunfire::SetRange(Event *ev) +{ + range = ev->GetFloat(1); +} + +inline void ScriptSimpleStrafingGunfire::SetSpread(Event *ev) +{ + spread.x = ev->GetFloat(1); + spread.y = ev->GetFloat(2); +} + +inline void ScriptSimpleStrafingGunfire::SetDamage(Event *ev) +{ + damage = ev->GetFloat(1); +} + +inline void ScriptSimpleStrafingGunfire::SetKnockback(Event *ev) +{ + knockback = ev->GetFloat(1); +} + +inline void ScriptSimpleStrafingGunfire::SetThroughWood(Event *ev) +{ + throughWood = ev->GetFloat(1); +} + +inline void ScriptSimpleStrafingGunfire::SetThroughMetal(Event *ev) +{ + throughMetal = ev->GetFloat(1); +} + +inline void ScriptSimpleStrafingGunfire::SetBulletCount(Event *ev) +{ + bulletCount = ev->GetInteger(1); +} + +inline void ScriptSimpleStrafingGunfire::SetTracerFreq(Event *ev) +{ + tracerFrequency = ev->GetInteger(1); + tracerCount = 0; +} + +inline void ScriptSimpleStrafingGunfire::SetProjectileModel(Event *ev) +{ + projectileModel = ev->GetString(1); +} + +class ScriptAimedStrafingGunfire : public ScriptSimpleStrafingGunfire +{ +private: + Entity *aimTarget; + +public: + CLASS_PROTOTYPE(ScriptAimedStrafingGunfire); + + ScriptAimedStrafingGunfire(); + + void Archive(Archiver& arc) override; + + void GunFire(Event *ev); + void SetAimTarget(Event *ev); +}; + +inline void ScriptAimedStrafingGunfire::SetAimTarget(Event *ev) +{ + aimTarget = ev->GetEntity(1); +} diff --git a/code/fgame/scriptthread.cpp b/code/fgame/scriptthread.cpp index 2743ee35..f5a91873 100644 --- a/code/fgame/scriptthread.cpp +++ b/code/fgame/scriptthread.cpp @@ -430,7 +430,8 @@ Event EV_ScriptThread_KillEnt ); Event EV_ScriptThread_IsAlive ( - "IsAlive", EV_DEFAULT, + "IsAlive", + EV_DEFAULT, "e", "ent", "Returns true if the specified entity exists and has health > 0.", @@ -707,7 +708,8 @@ Event EV_ScriptThread_Vector_Normalize ); Event EV_ScriptThread_Vector_Add ( - "vector_add", EV_DEFAULT, + "vector_add", + EV_DEFAULT, "vv", "vector1 vector2", "Returns vector1 + vector2.", @@ -724,7 +726,8 @@ Event EV_ScriptThread_Vector_Subtract ); Event EV_ScriptThread_Vector_Scale ( - "vector_scale", EV_DEFAULT, + "vector_scale", + EV_DEFAULT, "vf", "vector1 scale_factor", "Returns vector1 * scale_factor.", @@ -732,7 +735,8 @@ Event EV_ScriptThread_Vector_Scale ); Event EV_ScriptThread_Vector_DotProduct ( - "vector_dot", EV_DEFAULT, + "vector_dot", + EV_DEFAULT, "vv", "vector1 vector2", "Returns vector1 * vector2.", @@ -841,7 +845,7 @@ Event EV_ScriptThread_PlayMovie // Added in 2.0 ( "PlayMovie", EV_DEFAULT, - "sI", + "s", "name", "Play a Movie..." ); @@ -953,7 +957,7 @@ Event EV_ScriptThread_HudDraw_VirtualSize EV_DEFAULT, "ii", "index virtual", - "Sets if the huddraw element for given player should use virutal screen resolution for positioning and size", + "Sets if the huddraw element for given player should use virtual screen resolution for positioning and size", EV_NORMAL ); Event EV_ScriptThread_HudDraw_Color @@ -1039,10 +1043,9 @@ Event EV_ScriptThread_BspTransition ( "bsptransition", EV_DEFAULT, - "s", - "next_map", - "Transitions to the next BSP. Keeps player data," - "and game data." + "sB", + "next_map skipFade", // Added in 2.30: skipFade + "Transitions to the next BSP. Keeps player data, and game data." ); Event EV_ScriptThread_LevelTransition ( @@ -1173,7 +1176,7 @@ Event EV_ScriptThread_RegisterCommand ); // -// Openmohaa additions +// Added in OPM // Event EV_ScriptThread_CancelWaiting ( @@ -1365,7 +1368,7 @@ Event EV_ScriptThread_iHudDrawVirtualSize EV_DEFAULT, "eii", "player index virtual", - "Sets if the huddraw element for given player should use virutal screen resolution for positioning and size", + "Sets if the huddraw element for given player should use virtual screen resolution for positioning and size", EV_NORMAL ); Event EV_ScriptThread_IsArray @@ -1432,6 +1435,15 @@ Event EV_ScriptThread_FileRead EV_NORMAL ); Event EV_ScriptThread_FileClose +( + "fclose", + EV_DEFAULT, + "i", + "filehandle", + "Closes file of given file handle", + EV_NORMAL +); +Event EV_ScriptThread_FileClose2 ( "fclose", EV_DEFAULT, @@ -1664,6 +1676,24 @@ Event EV_ScriptThread_UnregisterEv "Unregisters script callback handler for specified event", EV_RETURN ); +Event EV_ScriptThread_Event_Subscribe +( + "event_subscribe", + EV_DEFAULT, + "ss", + "eventname script", + "Subscribe to the specified event. The specified script will be executed when the event gets triggered.", + EV_NORMAL +); +Event EV_ScriptThread_Event_Unsubscribe +( + "event_unsubscribe", + EV_DEFAULT, + "ss", + "eventname script", + "Unsubscribe the script from the specified event.", + EV_NORMAL +); Event EV_ScriptThread_Conprintf ( "conprintf", @@ -1969,6 +1999,15 @@ Event EV_ScriptThread_Md5String "generates MD5 hash of given text", EV_RETURN ); +Event EV_ScriptThread_GetEntity +( + "getentity", + EV_CHEAT, + "i", + "ent_num", + "Gets the specified entity", + EV_RETURN +); Event EV_ScriptThread_SetTimer ( "settimer", @@ -2015,6 +2054,15 @@ Event EV_ScriptThread_VisionSetNaked "empty string, it will be set to the current map's name.", EV_NORMAL ); +Event EV_ScriptThread_IsBot +( + "isBot", + EV_DEFAULT, + "e", + "entity", + "Returns 1 if the client is a bot, 0 otherwise. Will return 0 if the entity is not a client.", + EV_RETURN +); CLASS_DECLARATION(Listener, ScriptThread, NULL) { {&EV_ScriptThread_GetCvar, &ScriptThread::Getcvar }, @@ -2109,7 +2157,7 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) { {&EV_ScriptThread_MissionFailed, &ScriptThread::MissionFailed }, {&EV_ScriptThread_IsAlive, &ScriptThread::EventIsAlive }, {&EV_ScriptThread_Popmenu, &ScriptThread::EventPopmenu }, - {&EV_ScriptThread_Showmenu, &ScriptThread::EventPopmenu }, + {&EV_ScriptThread_Showmenu, &ScriptThread::EventShowmenu }, {&EV_ScriptThread_Hidemenu, &ScriptThread::EventHidemenu }, {&EV_ScriptThread_PlayMovie, &ScriptThread::EventPlayMovie }, {&EV_ScriptThread_Pushmenu, &ScriptThread::EventPushmenu }, @@ -2168,9 +2216,12 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) { {&EV_ScriptThread_GetTanH, &ScriptThread::EventTanH }, {&EV_ScriptThread_strncpy, &ScriptThread::StringBytesCopy }, {&EV_ScriptThread_Md5String, &ScriptThread::Md5String }, + {&EV_ScriptThread_GetEntity, &ScriptThread::GetEntByEntnum }, {&EV_ScriptThread_TypeOf, &ScriptThread::TypeOfVariable }, {&EV_ScriptThread_RegisterEv, &ScriptThread::RegisterEvent }, {&EV_ScriptThread_UnregisterEv, &ScriptThread::UnregisterEvent }, + {&EV_ScriptThread_Event_Subscribe, &ScriptThread::SubscribeEvent }, + {&EV_ScriptThread_Event_Unsubscribe, &ScriptThread::UnsubscribeEvent }, {&EV_ScriptThread_CancelWaiting, &ScriptThread::CancelWaiting }, {&EV_ScriptThread_GetTime, &ScriptThread::GetTime }, {&EV_ScriptThread_GetTimeZone, &ScriptThread::GetTimeZone }, @@ -2188,6 +2239,7 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) { {&EV_ScriptThread_Earthquake2, &ScriptThread::Earthquake }, {&EV_ScriptThread_FadeSound, &ScriptThread::FadeSound }, {&EV_ScriptThread_FileClose, &ScriptThread::FileClose }, + {&EV_ScriptThread_FileClose2, &ScriptThread::FileClose }, {&EV_ScriptThread_FileCopy, &ScriptThread::FileCopy }, {&EV_ScriptThread_FileEof, &ScriptThread::FileEof }, {&EV_ScriptThread_FileError, &ScriptThread::FileError }, @@ -2240,6 +2292,7 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) { {&EV_ScriptThread_TraceDetails, &ScriptThread::TraceDetails }, {&EV_ScriptThread_VisionGetNaked, &ScriptThread::VisionGetNaked }, {&EV_ScriptThread_VisionSetNaked, &ScriptThread::VisionSetNaked }, + {&EV_ScriptThread_IsBot, &ScriptThread::IsPlayerBot }, {NULL, NULL } }; @@ -2265,17 +2318,28 @@ ScriptThread::ScriptThread(ScriptClass *scriptClass, unsigned char *pCodePos) m_ScriptVM = new ScriptVM(scriptClass, pCodePos, this); m_ScriptVM->m_ThreadState = THREAD_RUNNING; + + if (g_scripttrace->integer && CanScriptTracePrint()) { + gi.DPrintf2("+++Constructor THREAD: %p %p\n", this, scriptClass); + } } ScriptThread::~ScriptThread() { - ScriptVM *vm = m_ScriptVM; - assert(vm); - if (!vm) { - // should never happen - throw ScriptException("Attempting to delete a dead thread."); + ScriptVM *vm; + + if (g_scripttrace->integer && CanScriptTracePrint()) { + gi.DPrintf2("---Destructor THREAD: %p\n", this); } + assert(m_ScriptVM); + if (!m_ScriptVM) { + // should never happen + //throw ScriptException("Attempting to delete a dead thread."); + gi.Error(ERR_DROP, "Attempting to delete a dead thread."); + } + + vm = m_ScriptVM; m_ScriptVM = NULL; if (vm->ThreadState() == THREAD_WAITING) { vm->m_ThreadState = THREAD_RUNNING; @@ -2290,7 +2354,7 @@ ScriptThread::~ScriptThread() ScriptClass *ScriptThread::GetScriptClass(void) { - return m_ScriptVM->m_ScriptClass; + return m_ScriptVM->GetScriptClass(); } str ScriptThread::FileName(void) @@ -2301,8 +2365,7 @@ str ScriptThread::FileName(void) void ScriptThread::StartedWaitFor(void) { Stop(); - - m_ScriptVM->m_ThreadState = THREAD_SUSPENDED; + StartWaiting(); m_ScriptVM->Suspend(); } @@ -2326,17 +2389,13 @@ void ScriptThread::StoppedWaitFor(const_str name, bool bDeleting) if (m_ScriptVM->m_ThreadState == THREAD_SUSPENDED) { if (name != 0) { - if (m_ScriptVM->state == STATE_EXECUTION) { + if (m_ScriptVM->IsSuspended()) { Execute(); } else { m_ScriptVM->Resume(); } } else { - m_ScriptVM->m_ThreadState = THREAD_RUNNING; - CancelWaitingAll(); - m_ScriptVM->m_ThreadState = THREAD_WAITING; - - Director.AddTiming(this, 0.0f); + StartTiming(); } } } @@ -2358,10 +2417,13 @@ void ScriptThread::ScriptExecute(ScriptVariable *data, int dataSize, ScriptVaria void ScriptThread::ScriptExecuteInternal(ScriptVariable *data, int dataSize) { - SafePtr currentThread = Director.m_CurrentThread; - SafePtr previousThread = Director.m_PreviousThread; + SafePtr currentThread; + SafePtr previousThread; - Director.m_PreviousThread = currentThread; + currentThread = Director.CurrentThread(); + previousThread = this; + + Director.m_PreviousThread = Director.CurrentThread(); Director.m_CurrentThread = this; Stop(); @@ -2409,29 +2471,42 @@ void ScriptThread::Execute(ScriptVariable *data, int dataSize) ScriptExecuteInternal(data, dataSize); } +void ScriptThread::Execute() +{ + if (Director.iPaused > 0) { + StartTiming(); + } else { + ScriptExecuteInternal(NULL, 0); + } +} + ScriptThread *ScriptThread::CreateThreadInternal(const ScriptVariable& label) { - return m_ScriptVM->GetScriptClass()->CreateThreadInternal(label); + return GetScriptClass()->CreateThreadInternal(label); } ScriptThread *ScriptThread::CreateScriptInternal(const ScriptVariable& label) { - return m_ScriptVM->GetScriptClass()->CreateScriptInternal(label); + return GetScriptClass()->CreateScriptInternal(label); } void ScriptThread::StartTiming(void) -{ - StartTiming(0); -} - -void ScriptThread::StartTiming(float time) { Stop(); m_ScriptVM->m_ThreadState = THREAD_WAITING; - if (time < 0) { - time = 0; + Director.AddTiming(this, level.inttime); +} + +void ScriptThread::StartTiming(int time) +{ + Stop(); + + m_ScriptVM->m_ThreadState = THREAD_WAITING; + + if (time < level.inttime) { + time = level.inttime; } Director.AddTiming(this, time); @@ -2453,9 +2528,9 @@ void ScriptThread::Stop(void) } } -void ScriptThread::Wait(float time) +void ScriptThread::Wait(int time) { - StartTiming(time); + StartTiming(level.inttime + time); m_ScriptVM->Suspend(); } @@ -2468,10 +2543,10 @@ void ScriptThread::Pause() void ScriptThread::Getcvar(Event *ev) { str varName = ev->GetString(1); - str s = gi.Cvar_Get(varName.c_str(), "", 0)->string; + str s = gi.Cvar_Get(varName.c_str(), "", 0)->string; if (strstr(s.c_str(), ".")) { - for (int i = s.length() - 1; i >= 0; i--) { + for (size_t i = s.length() - 1; i >= 0; i--) { if (s[i] == '0') { s[i] = 0; } else { @@ -2617,7 +2692,7 @@ void ScriptThread::EventGoto(Event *ev) { m_ScriptVM->EventGoto(ev); - if (m_ScriptVM->State() == STATE_EXECUTION) { + if (m_ScriptVM->IsSuspended()) { ScriptExecuteInternal(); } else { Stop(); @@ -2632,11 +2707,10 @@ void ScriptThread::EventThrow(Event *ev) } if (m_ScriptVM->EventThrow(ev)) { - if (m_ScriptVM->State() == STATE_EXECUTION) { + if (m_ScriptVM->IsSuspended()) { ScriptExecuteInternal(); } else { Stop(); - m_ScriptVM->Resume(); } } else { @@ -2645,7 +2719,7 @@ void ScriptThread::EventThrow(Event *ev) Stop(); - if (!BroadcastEvent("", *ev)) { + if (!BroadcastEvent(0, *ev)) { m_ScriptVM->GetScriptClass()->EventThrow(ev); } @@ -2663,11 +2737,10 @@ void ScriptThread::EventDelayThrow(Event *ev) } if (m_ScriptVM->EventThrow(ev)) { - if (m_ScriptVM->State() == STATE_EXECUTION) { - Wait(0); + if (m_ScriptVM->IsSuspended()) { + StartTiming(); } else { Stop(); - m_ScriptVM->Resume(); } } else { @@ -2688,12 +2761,17 @@ void ScriptThread::EventDelayThrow(Event *ev) void ScriptThread::EventWait(Event *ev) { - Wait(ev->GetFloat(1)); + float timeSeconds; + + // Fixed in OPM + // Clamp to make sure to not overflow when converting to integer + timeSeconds = Q_clamp_float(ev->GetFloat(1), 0, 2000000); + Wait((int)roundf(timeSeconds * 1000)); } void ScriptThread::EventWaitFrame(Event *ev) { - Wait(level.frametime); + Wait((int)roundf(level.frametime * 1000)); } void ScriptThread::EventResume(Event *ev) @@ -2769,7 +2847,7 @@ void ScriptThread::IPrintln(Event *ev) sString += ev->GetString(i); } - G_PrintToAllClients(gi.LV_ConvertString(sString), false); + gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", gi.LV_ConvertString(sString.c_str())); } void ScriptThread::IPrintlnBold(Event *ev) @@ -2782,7 +2860,7 @@ void ScriptThread::IPrintlnBold(Event *ev) sString += ev->GetString(i); } - G_PrintToAllClients(gi.LV_ConvertString(sString), true); + gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\n\"", gi.LV_ConvertString(sString.c_str())); } void ScriptThread::IPrintln_NoLoc(Event *ev) @@ -2795,7 +2873,7 @@ void ScriptThread::IPrintln_NoLoc(Event *ev) sString += ev->GetString(i); } - G_PrintToAllClients(sString, false); + gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", sString.c_str()); } void ScriptThread::IPrintlnBold_NoLoc(Event *ev) @@ -2808,7 +2886,7 @@ void ScriptThread::IPrintlnBold_NoLoc(Event *ev) sString += ev->GetString(i); } - G_PrintToAllClients(sString, true); + gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\n\"", sString.c_str()); } void ScriptThread::MPrint(Event *ev) @@ -2887,7 +2965,8 @@ void ScriptThread::TriggerEvent(Event *ev) void ScriptThread::RegisterAliasAndCache(Event *ev) { //assert(!"ScriptThread::RegisterAliasAndCache needs to be implemented like ClientGameCommandManager::AliasCache"); - gi.DPrintf("ScriptThread::RegisterAliasAndCache needs to be implemented like ClientGameCommandManager::AliasCache\n"); + gi.DPrintf("ScriptThread::RegisterAliasAndCache needs to be implemented like ClientGameCommandManager::AliasCache\n" + ); } void ScriptThread::CacheResourceEvent(Event *ev) @@ -3003,6 +3082,16 @@ Listener *ScriptThread::SpawnInternal(Event *ev) throw ScriptException("Usage: spawn entityname [keyname] [value]..."); } + // Fixed in OPM + // The original game uses a raw char* pointer to get the classname rather than storing it in an str. + // This causes an issue when the argument is none (NIL), stringValue() will allocate and return a new str() with "NIL". + // As the returned str() is not stored anywhere, it gets destroyed immediately, meaning that the char* pointer gets empty. + // This has the effect of using empty class ID, which is "Explosion" in original game. + // + // For example, t2l2 has an incorrect "mg42_spawner_gunner" of class PathNode, but PathNode has no model variable. + // global/spawner.scr::spawner_activate: + // - In OG, it will successfully spawn an instance of "Explosion" due to the NIL argument behavior stated above. + // - In OPM, it will not spawn anything and will cause script errors, it's the expected behavior by design classname = ev->GetString(1); if (getClassForID(classname) || getClass(classname)) { @@ -3418,17 +3507,17 @@ void ScriptThread::RemoveClass(Event *ev) void ScriptThread::CameraCommand(Event *ev) { - Event *e; - const char *cmd; - int i; - int n; + Event *e; + str cmd; + int i; + int n; if (!ev->NumArgs()) { throw ScriptException("Usage: cam [command] [arg 1]...[arg n]"); } cmd = ev->GetString(1); - if (Event::FindEventNum(cmd)) { + if (Event::Exists(cmd)) { e = new ConsoleEvent(cmd); n = ev->NumArgs(); @@ -3438,13 +3527,21 @@ void ScriptThread::CameraCommand(Event *ev) CameraMan.ProcessEvent(e); } else { - throw ScriptException("Unknown camera command '%s'.\n", cmd); + throw ScriptException("Unknown camera command '%s'.\n", cmd.c_str()); } } void ScriptThread::MissionFailed(Event *ev) { - G_MissionFailed(); + bool bNoFade; + + if (level.intermissiontime) { + return; + } + + bNoFade = ev->NumArgs() && ev->GetInteger(1); + + G_BeginIntermission(level.current_map, TRANS_MISSION_FAILED, bNoFade); } void ScriptThread::Archive(Archiver& arc) {} @@ -3504,31 +3601,46 @@ void ScriptThread::Vector_CrossProduct(Event *ev) void ScriptThread::Vector_ToAngles(Event *ev) { - ev->AddVector(ev->GetVector(1).toAngles()); + Vector v1; + Vector v3; + + v1 = ev->GetVector(1); + vectoangles(v1, v3); + + ev->AddVector(v3); } void ScriptThread::Angles_ToForward(Event *ev) { - Vector fwd; + Vector v1; + Vector v3; - ev->GetVector(1).AngleVectors(&fwd); - ev->AddVector(fwd); + v1 = ev->GetVector(1); + + AngleVectors(v1, v3, NULL, NULL); + ev->AddVector(v3); } void ScriptThread::Angles_ToLeft(Event *ev) { - Vector left; + Vector v1; + Vector v3; - ev->GetVector(1).AngleVectors(NULL, &left); - ev->AddVector(left); + v1 = ev->GetVector(1); + + AngleVectors(v1, NULL, v3, NULL); + ev->AddVector(v3); } void ScriptThread::Angles_ToUp(Event *ev) { - Vector up; + Vector v1; + Vector v3; - ev->GetVector(1).AngleVectors(NULL, NULL, &up); - ev->AddVector(up); + v1 = ev->GetVector(1); + + AngleVectors(v1, NULL, NULL, v3); + ev->AddVector(v3); } void ScriptThread::Angles_PointAt(Event *ev) @@ -3557,13 +3669,20 @@ void ScriptThread::Angles_PointAt(Event *ev) void ScriptThread::EventIsAlive(Event *ev) { - Entity *ent = ev->GetEntity(1); + Entity *ent; - if (ent) { - ev->AddInteger(!ent->IsDead()); - } else { - ev->AddInteger(0); + if (!ev->IsEntityAt(1)) { + ev->AddInteger(false); + return; } + + ent = ev->GetEntity(1); + if (!ent) { + ev->AddInteger(false); + return; + } + + ev->AddInteger(ent->health > 0); } void ScriptThread::EventPopmenu(Event *ev) @@ -3679,13 +3798,6 @@ void ScriptThread::EventHideMouse(Event *ev) { gentity_t *ent; int i; - str name; - - if (game.maxclients <= 0) { - return; - } - - name = ev->GetString(1); for (i = 0, ent = g_entities; i < game.maxclients; i++, ent++) { if (!ent->inuse || !ent->client) { @@ -3720,7 +3832,7 @@ void ScriptThread::EventTrace(Event *ev) mins = ev->GetVector(4); case 3: if (ev->GetInteger(3)) { - content_mask = MASK_SOLID; + content_mask &= ~MASK_SCRIPT_SLAVE; } case 2: end = ev->GetVector(2); @@ -3739,7 +3851,7 @@ void ScriptThread::EventTrace(Event *ev) void ScriptThread::EventSightTrace(Event *ev) { - int content_mask = MASK_LINE; + int content_mask = MASK_SOLID; Vector start; Vector mins; Vector maxs; @@ -3755,7 +3867,7 @@ void ScriptThread::EventSightTrace(Event *ev) mins = ev->GetVector(4); case 3: if (ev->GetInteger(3)) { - content_mask = MASK_SOLID; + content_mask &= ~MASK_IGNORE_ENTS; } case 2: end = ev->GetVector(2); @@ -3842,7 +3954,7 @@ void ScriptThread::EventHudDrawAlign(Event *ev) } else if (h_align == "right") { h_alignement = 2; } else { - throw ScriptException("Wrong alignement h_align string for huddraw_align!\n"); + throw ScriptException("Wrong alignment h_align string for huddraw_align!\n"); } if (v_align == "top") { @@ -3852,7 +3964,7 @@ void ScriptThread::EventHudDrawAlign(Event *ev) } else if (v_align == "bottom") { v_alignement = 2; } else { - throw ScriptException("Wrong alignement v_align string for huddraw_align!\n"); + throw ScriptException("Wrong alignment v_align string for huddraw_align!\n"); } HudDrawAlign(index, h_alignement, v_alignement); @@ -3996,7 +4108,7 @@ void ScriptThread::EventDebugInt3(Event *ev) void ScriptThread::EventTimeout(Event *ev) { - Director.maxTime = ev->GetFloat(1) * 1000.0f + 0.5f; + Director.maxTime = roundf(ev->GetFloat(1) * 1000.0f); } void ScriptThread::EventLandmineDamage(Event *ev) @@ -4041,10 +4153,16 @@ void ScriptThread::EventRadiusDamage(Event *ev) void ScriptThread::EventBspTransition(Event *ev) { - str map = ev->GetString(1); + str map = ev->GetString(1); + bool skipFade = false; + + if (ev->NumArgs() >= 2) { + // Added in 2.30 + skipFade = ev->GetBoolean(2); + } if (level.intermissiontime == 0.0f) { - G_BeginIntermission(map, TRANS_BSP); + G_BeginIntermission(map, TRANS_BSP, skipFade); } } @@ -4091,7 +4209,7 @@ void ScriptThread::EventTeamWin(Event *ev) const_str team; int teamnum; - if (g_gametype->integer != GT_OBJECTIVE) { + if (g_gametype->integer < GT_OBJECTIVE) { throw ScriptException("'teamwin' only valid for objective-based DM games"); } @@ -4100,8 +4218,10 @@ void ScriptThread::EventTeamWin(Event *ev) teamnum = TEAM_ALLIES; } else if (team == STRING_AXIS) { teamnum = TEAM_AXIS; + } else if (team == STRING_DISGUISE_NONE) { + teamnum = TEAM_NONE; } else { - throw ScriptException("'teamwin' must be called with 'axis' or 'allies' as its argument"); + throw ScriptException("'teamwin' must be called with 'axis', 'allies' or 'none' as its argument"); } dmManager.TeamWin(teamnum); @@ -4111,7 +4231,7 @@ void ScriptThread::EventEarthquake(Event *ev) { earthquake_t e; - e.duration = (int)(ev->GetFloat(1) * 1000.0f + 0.5f); + e.duration = (int)roundf(ev->GetFloat(1) * 1000.0f); if (e.duration <= 0) { return; } @@ -4142,12 +4262,16 @@ void ScriptThread::EventAIsCloserThanBToC(Event *ev) void ScriptThread::EventPointsWithinDist(Event *ev) { Vector delta; - float dist = ev->GetFloat(3); + Vector v1, v2; + float fDistance; - delta = ev->GetVector(1) - ev->GetVector(2); + v1 = ev->GetVector(1); + v2 = ev->GetVector(2); + fDistance = ev->GetFloat(3); + delta = v1 - v2; // check squared distance - ev->AddInteger(((delta * delta) < (dist * dist))); + ev->AddInteger(delta.lengthSquared() < Square(fDistance)); } bool ScriptThread::CanScriptTracePrint(void) @@ -4246,27 +4370,20 @@ void ScriptThread::SetCurrentObjective(int iObjective, int iTeam) gi.setConfigstring(CS_CURRENT_OBJECTIVE, va("%i", iObjective)); if (iObjective == -1) { - level.m_vObjectiveLocation = vec_zero; + level.m_vObjectiveLocation = vec_zero; level.m_vAlliedObjectiveLocation = vec_zero; - level.m_vAxisObjectiveLocation = vec_zero; + level.m_vAxisObjectiveLocation = vec_zero; } else { const char *s = gi.getConfigstring(CS_OBJECTIVES + iObjective); const char *loc = Info_ValueForKey(s, "loc"); - Vector v; + Vector v; - sscanf( - loc, - "%f %f %f", - &v[0], - &v[1], - &v[2] - ); + sscanf(loc, "%f %f %f", &v[0], &v[1], &v[2]); // // Since 2.0, allow objective location per team // - switch (iTeam) - { + switch (iTeam) { case TEAM_NONE: default: level.m_vObjectiveLocation = v; @@ -4285,7 +4402,7 @@ void ScriptThread::EventAddObjective(Event *ev) { int index; int status; - str text = ""; + str text; Vector location; index = ev->GetInteger(1) - 1; @@ -4347,14 +4464,13 @@ void ScriptThread::EventSetScoreboardToggle(Event *ev) void ScriptThread::EventSetCurrentObjective(Event *ev) { int iObjective = ev->GetInteger(1); - int iTeam = 0; + int iTeam = 0; if (iObjective > MAX_OBJECTIVES) { ScriptError("Index Out Of Range"); } - if (ev->NumArgs() >= 2) - { + if (ev->NumArgs() >= 2) { const_str teamStr = ev->GetConstString(2); if (teamStr == STRING_ALLIES) { iTeam = TEAM_ALLIES; @@ -4594,7 +4710,7 @@ void ScriptThread::RestoreSound(Event *ev) time = delaytime * 1000.0f; - gi.SendServerCommand(player != NULL ? player->edict - g_entities : NULL, "restoresound %0.2f %f", time, max_vol); + gi.SendServerCommand(player != NULL ? player->edict - g_entities : 0, "restoresound %0.2f %f", time, max_vol); } void ScriptThread::EventHudDraw3d(Event *ev) @@ -4688,7 +4804,7 @@ void ScriptThread::GetPlayerIP(Event *ev) ip = ent->client->pers.ip; - sprintf(ip_buff, "%s:%i", ip, ent->client->pers.port); + Com_sprintf(ip_buff, sizeof(ip_buff), "%s:%i", ip, ent->client->pers.port); ev->AddString(ip_buff); } @@ -4994,7 +5110,7 @@ void ScriptThread::EventIHudDrawAlign(Event *ev) } else if (h_align == "right") { h_alignement = 2; } else { - throw ScriptException("Wrong alignement h_align string for ihuddraw_align!\n"); + throw ScriptException("Wrong alignment h_align string for ihuddraw_align!\n"); } if (v_align == "top") { @@ -5004,7 +5120,7 @@ void ScriptThread::EventIHudDrawAlign(Event *ev) } else if (v_align == "bottom") { v_alignement = 2; } else { - throw ScriptException("Wrong alignement v_align string for ihuddraw_align!\n"); + throw ScriptException("Wrong alignment v_align string for ihuddraw_align!\n"); } iHudDrawAlign(player->edict - g_entities, index, h_alignement, v_alignement); @@ -5255,13 +5371,13 @@ void ScriptThread::TeamSetScore(Event *ev) if (bAdd) { team->m_iKills += score; - if (g_gametype->integer < 3) { + if (g_gametype->integer < GT_TEAM_ROUNDS) { team->m_teamwins += score; } } else { team->m_iKills = score; - if (g_gametype->integer < 3) { + if (g_gametype->integer < GT_TEAM_ROUNDS) { team->m_teamwins = score; } } @@ -5305,15 +5421,15 @@ void ScriptThread::FileOpen(Event *ev) f = fopen(filename, accesstype); - if (f == NULL) { - ev->AddInteger(0); - return; - } else { - ev->AddInteger((int)(size_t)f); - sprintf(buf, "%i", scriptfiles->integer + 1); - gi.cvar_set("sv_scriptfiles", buf); + if (!f) { + ev->AddNil(); return; } + + ev->AddListener(new OSFile(f)); + + Com_sprintf(buf, sizeof(buf), "%i", scriptfiles->integer + 1); + gi.cvar_set("sv_scriptfiles", buf); } void ScriptThread::FileWrite(Event *ev) {} @@ -5322,11 +5438,10 @@ void ScriptThread::FileRead(Event *ev) {} void ScriptThread::FileClose(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; - char buf[16] = {0}; + OSFile *osFile = NULL; + int numArgs = 0; + FILE *f = NULL; + char buf[16] = {0}; numArgs = ev->NumArgs(); @@ -5334,57 +5449,30 @@ void ScriptThread::FileClose(Event *ev) throw ScriptException("Wrong arguments count for fclose!\n"); } - id = ev->GetInteger(1); - - /*if( (int)scriptFiles[0].f != id && (int)scriptFiles[1].f != id ) - { - gi.Printf("Wrong file handle for fclose!\n"); - return; + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); } - if( (int)scriptFiles[0].f == id ) - { - scriptFiles[0].inUse = 0; - fclose( scriptFiles[0].f ); - return; - } - else if( (int)scriptFiles[1].f == id ) - { - scriptFiles[1].inUse = 0; - fclose( scriptFiles[1].f ); - return; - } - else - { - gi.Printf("Unknown error while closing file - fclose!\n"); - return; - }*/ - - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); if (f == NULL) { throw ScriptException("File handle is NULL for fclose!\n"); } - ret = fclose(f); + // delete the file object + delete osFile; - if (ret == 0) { - ev->AddInteger(0); - sprintf(buf, "%i", scriptfiles->integer - 1); - gi.cvar_set("sv_scriptfiles", buf); - return; - } else { - ev->AddInteger(ret); - return; - } + Com_sprintf(buf, sizeof(buf), "%i", scriptfiles->integer - 1); + gi.cvar_set("sv_scriptfiles", buf); } void ScriptThread::FileEof(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; + OSFile *osFile = NULL; + int numArgs = 0; + int ret = 0; + FILE *f = NULL; numArgs = ev->NumArgs(); @@ -5392,9 +5480,12 @@ void ScriptThread::FileEof(Event *ev) throw ScriptException("Wrong arguments count for feof!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); ret = feof(f); @@ -5403,7 +5494,7 @@ void ScriptThread::FileEof(Event *ev) void ScriptThread::FileSeek(Event *ev) { - int id = 0; + OSFile *osFile = NULL; int numArgs = 0; int pos = 0; long int offset = 0; @@ -5416,9 +5507,12 @@ void ScriptThread::FileSeek(Event *ev) throw ScriptException("Wrong arguments count for fseek!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); offset = ev->GetInteger(2); @@ -5439,7 +5533,7 @@ void ScriptThread::FileSeek(Event *ev) void ScriptThread::FileTell(Event *ev) { - int id = 0; + OSFile *osFile = NULL; int numArgs = 0; long int ret = 0; FILE *f = NULL; @@ -5450,9 +5544,12 @@ void ScriptThread::FileTell(Event *ev) throw ScriptException("Wrong arguments count for ftell!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); ret = ftell(f); @@ -5461,7 +5558,7 @@ void ScriptThread::FileTell(Event *ev) void ScriptThread::FileRewind(Event *ev) { - int id = 0; + OSFile *osFile = NULL; int numArgs = 0; long int ret = 0; FILE *f = NULL; @@ -5472,20 +5569,23 @@ void ScriptThread::FileRewind(Event *ev) throw ScriptException("Wrong arguments count for frewind!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); rewind(f); } void ScriptThread::FilePutc(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; - int c = 0; + OSFile *osFile = NULL; + int numArgs = 0; + int ret = 0; + FILE *f = NULL; + int c = 0; numArgs = ev->NumArgs(); @@ -5493,9 +5593,12 @@ void ScriptThread::FilePutc(Event *ev) throw ScriptException("Wrong arguments count for fputc!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); c = ev->GetInteger(2); @@ -5506,11 +5609,11 @@ void ScriptThread::FilePutc(Event *ev) void ScriptThread::FilePuts(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; - str c; + OSFile *osFile = NULL; + int numArgs = 0; + int ret = 0; + FILE *f = NULL; + str c; numArgs = ev->NumArgs(); @@ -5518,9 +5621,12 @@ void ScriptThread::FilePuts(Event *ev) throw ScriptException("Wrong arguments count for fputs!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); c = ev->GetString(2); //gi.Printf("Putting line into a file\n"); @@ -5531,10 +5637,10 @@ void ScriptThread::FilePuts(Event *ev) void ScriptThread::FileGetc(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; + OSFile *osFile = NULL; + int numArgs = 0; + int ret = 0; + FILE *f = NULL; numArgs = ev->NumArgs(); @@ -5542,9 +5648,12 @@ void ScriptThread::FileGetc(Event *ev) throw ScriptException("Wrong arguments count for fgetc!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); ret = fgetc(f); @@ -5553,12 +5662,12 @@ void ScriptThread::FileGetc(Event *ev) void ScriptThread::FileGets(Event *ev) { - int id = 0; - int numArgs = 0; - int maxCount = 0; - FILE *f = NULL; - char *c = NULL; - char *buff = NULL; + OSFile *osFile = NULL; + int numArgs = 0; + int maxCount = 0; + FILE *f = NULL; + char *c = NULL; + char *buff = NULL; numArgs = ev->NumArgs(); @@ -5566,9 +5675,12 @@ void ScriptThread::FileGets(Event *ev) throw ScriptException("Wrong arguments count for fgets!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); maxCount = ev->GetInteger(2); @@ -5601,10 +5713,10 @@ void ScriptThread::FileGets(Event *ev) void ScriptThread::FileError(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; + OSFile *osFile = NULL; + int numArgs = 0; + int ret = 0; + FILE *f = NULL; numArgs = ev->NumArgs(); @@ -5612,9 +5724,12 @@ void ScriptThread::FileError(Event *ev) throw ScriptException("Wrong arguments count for ferror!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); ret = ferror(f); @@ -5623,10 +5738,10 @@ void ScriptThread::FileError(Event *ev) void ScriptThread::FileFlush(Event *ev) { - int id = 0; - int numArgs = 0; - int ret = 0; - FILE *f = NULL; + OSFile *osFile = NULL; + int numArgs = 0; + int ret = 0; + FILE *f = NULL; numArgs = ev->NumArgs(); @@ -5634,9 +5749,12 @@ void ScriptThread::FileFlush(Event *ev) throw ScriptException("Wrong arguments count for fflush!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); ret = fflush(f); @@ -5645,7 +5763,6 @@ void ScriptThread::FileFlush(Event *ev) void ScriptThread::FileExists(Event *ev) { - int id = 0; int numArgs = 0; FILE *f = 0; str filename; @@ -5658,7 +5775,7 @@ void ScriptThread::FileExists(Event *ev) filename = ev->GetString(1); - if (filename == NULL) { + if (!filename.length()) { throw ScriptException("Empty file name passed to fexists!\n"); } @@ -5673,13 +5790,13 @@ void ScriptThread::FileExists(Event *ev) void ScriptThread::FileReadAll(Event *ev) { - int id = 0; - int numArgs = 0; - FILE *f = NULL; - char *ret = NULL; - long currentPos = 0; - size_t size = 0; - size_t sizeRead = 0; + OSFile *osFile = NULL; + int numArgs = 0; + FILE *f = NULL; + char *ret = NULL; + long currentPos = 0; + size_t size = 0; + size_t sizeRead = 0; numArgs = ev->NumArgs(); @@ -5687,9 +5804,12 @@ void ScriptThread::FileReadAll(Event *ev) throw ScriptException("Wrong arguments count for freadall!\n"); } - id = ev->GetInteger(1); + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } - f = (FILE *)id; + f = (FILE *)osFile->getOSFile(); currentPos = ftell(f); fseek(f, 0, SEEK_END); @@ -5713,11 +5833,11 @@ void ScriptThread::FileReadAll(Event *ev) void ScriptThread::FileSaveAll(Event *ev) { - int id = 0; - int numArgs = 0; - FILE *f = NULL; - size_t sizeWrite = 0; - str text; + OSFile *osFile = NULL; + int numArgs = 0; + FILE *f = NULL; + size_t sizeWrite = 0; + str text; numArgs = ev->NumArgs(); @@ -5725,12 +5845,16 @@ void ScriptThread::FileSaveAll(Event *ev) throw ScriptException("Wrong arguments count for fsaveall!\n"); } - id = ev->GetInteger(1); - f = (FILE *)id; + osFile = (OSFile *)ev->GetListener(1); + if (!osFile || !osFile->isSubclassOf(OSFile)) { + throw ScriptException("Not a file!\n"); + } + + f = (FILE *)osFile->getOSFile(); text = ev->GetString(2); - if (text == NULL) { + if (text.length()) { ev->AddInteger(-1); throw ScriptException("Text to be written is NULL - fsaveall!\n"); } @@ -5742,7 +5866,6 @@ void ScriptThread::FileSaveAll(Event *ev) void ScriptThread::FileRemove(Event *ev) { - int id = 0; int numArgs = 0; int ret = 0; str filename; @@ -5755,7 +5878,7 @@ void ScriptThread::FileRemove(Event *ev) filename = ev->GetString(1); - if (filename == NULL) { + if (!filename.length()) { throw ScriptException("Empty file name passed to fremove!\n"); } @@ -5766,7 +5889,6 @@ void ScriptThread::FileRemove(Event *ev) void ScriptThread::FileRename(Event *ev) { - int id = 0; int numArgs = 0; int ret = 0; str oldfilename, newfilename; @@ -5866,7 +5988,7 @@ void ScriptThread::FileReadPak(Event *ev) filename = ev->GetString(1); - if (filename == NULL) { + if (!filename.length()) { throw ScriptException("Filename is NULL - freadpak!\n"); } @@ -5941,7 +6063,7 @@ void ScriptThread::FileNewDirectory(Event *ev) path = ev->GetString(1); - if (path == NULL) { + if (!path.length()) { throw ScriptException("Path is NULL - fnewdir!\n"); } @@ -5969,7 +6091,7 @@ void ScriptThread::FileRemoveDirectory(Event *ev) path = ev->GetString(1); - if (path == NULL) { + if (!path.length()) { throw ScriptException("Path is NULL - fremovedir!\n"); } @@ -6214,7 +6336,7 @@ void ScriptThread::FlagInit(Event *ev) flag = new Flag; flag->bSignaled = false; - strcpy(flag->flagName, name); + Q_strncpyz(flag->flagName, name, sizeof(flag->flagName)); } void ScriptThread::FlagSet(Event *ev) @@ -6565,7 +6687,7 @@ void ScriptThread::EventFmod(Event *ev) ev->AddFloat((float)res); } -int checkMD5(const char *filepath, char *md5Hash) +int checkMD5(const char *filepath, char *md5Hash, size_t destSize) { md5_state_t state; md5_byte_t digest[16]; @@ -6614,7 +6736,7 @@ int checkMD5(const char *filepath, char *md5Hash) md5_finish(&state, digest); for (di = 0; di < 16; ++di) { - sprintf(md5Hash + di * 2, "%02x", digest[di]); + Com_sprintf(md5Hash + di * 2, destSize - di * 2, "%02x", digest[di]); } gi.Free(buff); @@ -6622,7 +6744,7 @@ int checkMD5(const char *filepath, char *md5Hash) return 0; } -int checkMD5String(const char *string, char *md5Hash) +int checkMD5String(const char *string, char *md5Hash, size_t destSize) { md5_state_t state; md5_byte_t digest[16]; @@ -6647,7 +6769,7 @@ int checkMD5String(const char *string, char *md5Hash) md5_finish(&state, digest); for (di = 0; di < 16; ++di) { - sprintf(md5Hash + di * 2, "%02x", digest[di]); + Com_sprintf(md5Hash + di * 2, destSize - di * 2, "%02x", digest[di]); } gi.Free(buff); @@ -6667,7 +6789,7 @@ void ScriptThread::Md5File(Event *ev) filename = ev->GetString(1); - ret = checkMD5(filename, hash); + ret = checkMD5(filename, hash, sizeof(hash)); if (ret != 0) { ev->AddInteger(-1); throw ScriptException("Error while generating MD5 checksum for file - md5file!\n"); @@ -6704,7 +6826,7 @@ void ScriptThread::Md5String(Event *ev) text = ev->GetString(1); - ret = checkMD5String(text, hash); + ret = checkMD5String(text, hash, sizeof(hash)); if (ret != 0) { ev->AddInteger(-1); throw ScriptException("Error while generating MD5 checksum for strin!\n"); @@ -6763,6 +6885,8 @@ void ScriptThread::RegisterEvent(Event *ev) char eventname_full[64]; scriptedEvType_t evType; + ScriptDeprecatedAltMethod("event_subscribe"); + eventname = ev->GetString(1); evType = EventNameToType(eventname, eventname_full); @@ -6794,6 +6918,8 @@ void ScriptThread::UnregisterEvent(Event *ev) int numArgs = 0; scriptedEvType_t evType; + ScriptDeprecatedAltMethod("event_unsubscribe"); + eventname = ev->GetString(1); evType = EventNameToType(eventname, NULL); @@ -6827,6 +6953,42 @@ void ScriptThread::UnregisterEvent(Event *ev) ev->AddInteger(0); } +void ScriptThread::SubscribeEvent(Event *ev) +{ + str eventName; + ScriptDelegate *delegate; + ScriptThreadLabel label; + + eventName = ev->GetString(1); + + delegate = ScriptDelegate::GetScriptDelegate(eventName); + if (!delegate) { + throw ScriptException("Invalid event '%s'", eventName.c_str()); + } + + label.SetThread(ev->GetValue(2)); + + delegate->Register(label); +} + +void ScriptThread::UnsubscribeEvent(Event *ev) +{ + str eventName; + ScriptDelegate *delegate; + ScriptThreadLabel label; + + eventName = ev->GetString(1); + + delegate = ScriptDelegate::GetScriptDelegate(eventName); + if (!delegate) { + throw ScriptException("Invalid event '%s'", eventName.c_str()); + } + + label.SetThread(ev->GetValue(2)); + + delegate->Unregister(label); +} + void ScriptThread::TypeOfVariable(Event *ev) { int numArgs = 0; @@ -6899,7 +7061,7 @@ void ScriptThread::GetTime(Event *ev) timediff = timearray[0] - gmttime; - sprintf(buff, "%02i:%02i:%02i", (int)timearray[0], (int)timearray[1], (int)timearray[2]); + Com_sprintf(buff, sizeof(buff), "%02i:%02i:%02i", (int)timearray[0], (int)timearray[1], (int)timearray[2]); ev->AddString(buff); } @@ -6993,4 +7155,47 @@ void ScriptThread::TraceDetails(Event *ev) array.setArrayAtRef(entityIndex, entityValue); ev->AddValue(array); -} \ No newline at end of file +} + +void ScriptThread::IsPlayerBot(Event *ev) +{ + Entity *e = ev->GetEntity(1); + + if (!e || !e->client) { + // Invalid entity or not a client + ev->AddInteger(0); + return; + } + + if (!(e->edict->r.svFlags & SVF_BOT)) { + ev->AddInteger(0); + return; + } + + // has SVF_BOT server flag + ev->AddInteger(1); +} + +CLASS_DECLARATION(Listener, OSFile, NULL) { + {NULL, NULL} +}; + +OSFile::OSFile() + : file(NULL) +{} + +OSFile::OSFile(void *inFile) + : file(inFile) +{} + +OSFile::~OSFile() +{ + if (file) { + fclose((FILE *)file); + } +} + +void *OSFile::getOSFile() const +{ + return file; +} diff --git a/code/fgame/scriptthread.h b/code/fgame/scriptthread.h index e35ab541..89536853 100644 --- a/code/fgame/scriptthread.h +++ b/code/fgame/scriptthread.h @@ -131,14 +131,14 @@ protected: void GetRandomFloat(Event *ev); void GetRandomInt(Event *ev); - void GetAbs(Event* ev); + void GetAbs(Event *ev); ////////// // Added in 2.30 - void EventCos(Event* ev); - void EventSin(Event* ev); - void EventTan(Event* ev); - void EventATan(Event* ev); - void EventSqrt(Event* ev); + void EventCos(Event *ev); + void EventSin(Event *ev); + void EventTan(Event *ev); + void EventATan(Event *ev); + void EventSqrt(Event *ev); ////////// void GetSelf(Event *ev); void Vector_Length(Event *ev); @@ -192,16 +192,17 @@ public: ScriptThread(ScriptClass *scriptClass, unsigned char *pCodePos); virtual ~ScriptThread(); - void Execute(Event &ev); - void Execute(Event *ev = NULL); + void Execute(Event& ev); + void Execute(Event *ev); + void Execute(); void Execute(ScriptVariable *data, int dataSize); - void Wait(float time); + void Wait(int time); void Pause(void); - void ScriptExecute(ScriptVariable *data, int dataSize, ScriptVariable &returnValue); + void ScriptExecute(ScriptVariable *data, int dataSize, ScriptVariable& returnValue); void ScriptExecuteInternal(ScriptVariable *data = NULL, int dataSize = 0); void EventThrow(Event *ev); void StartWaiting(); - void StartTiming(float time); + void StartTiming(int time); void StartTiming(void); void Stop(void); virtual void StartedWaitFor(void) override; @@ -224,22 +225,22 @@ public: // static void AddObjective(int index, int status, str text, Vector location); static void SetCurrentObjective(int iObjective, int iTeam); - void SendObjective(); - void SendObjectives(); - void ClearObjectives(); - void EventAddObjective(Event *ev); - void EventSetScoreboardToggle(Event *ev); // Added in 2.30 - void EventSetCurrentObjective(Event *ev); - void EventClearObjectives(Event *ev); - void SetObjectiveLocation(Vector vLocation); - void SetObjectiveLocation(Event *ev); - void ClearObjectiveLocation(void); - void ClearObjectiveLocation(Event *ev); + void SendObjective(); + void SendObjectives(); + void ClearObjectives(); + void EventAddObjective(Event *ev); + void EventSetScoreboardToggle(Event *ev); // Added in 2.30 + void EventSetCurrentObjective(Event *ev); + void EventClearObjectives(Event *ev); + void SetObjectiveLocation(Vector vLocation); + void SetObjectiveLocation(Event *ev); + void ClearObjectiveLocation(void); + void ClearObjectiveLocation(Event *ev); void EventDrawHud(Event *ev); virtual void Archive(Archiver& arc) override; - void ArchiveInternal(Archiver &arc); + void ArchiveInternal(Archiver& arc); // // Openmohaa addition @@ -344,4 +345,23 @@ public: void UnregisterEvent(Event *ev); void VisionGetNaked(Event *ev); void VisionSetNaked(Event *ev); -}; \ No newline at end of file + void IsPlayerBot(Event *ev); + + void SubscribeEvent(Event *ev); + void UnsubscribeEvent(Event *ev); +}; + +class OSFile : public Listener +{ + CLASS_PROTOTYPE(OSFile); + +public: + OSFile(); + OSFile(void *inFile); + ~OSFile(); + + void *getOSFile() const; + +private: + void *file; +}; diff --git a/code/fgame/scripttimer.cpp b/code/fgame/scripttimer.cpp index 243e9c0b..95acbdb2 100644 --- a/code/fgame/scripttimer.cpp +++ b/code/fgame/scripttimer.cpp @@ -175,12 +175,10 @@ void ScriptTimer::Disable() void ScriptTimer::Enable() { - bEnabled = true; + bEnabled = true; - CancelEventsOfType( &EV_ScriptTimer_Think ); - - Event *ev = new Event( &EV_ScriptTimer_Think ); - ProcessEvent( ev ); + CancelEventsOfType(EV_ScriptTimer_Think); + ProcessEvent(EV_ScriptTimer_Think); } qboolean ScriptTimer::Done() diff --git a/code/fgame/scripttimer.h b/code/fgame/scripttimer.h index 96fff34a..9fcfd46d 100644 --- a/code/fgame/scripttimer.h +++ b/code/fgame/scripttimer.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ScriptTimer.cpp: Scripted Timer & Fader // -#ifndef __SCRIPTTIMER_H__ -#define __SCRIPTTIMER_H__ +#pragma once #include "listener.h" @@ -81,5 +80,3 @@ public: bool isEnabled(); void setType( timertype_e type ); }; - -#endif /* __SCRIPTTIMER_H__ */ diff --git a/code/fgame/sentient.cpp b/code/fgame/sentient.cpp index 967f1de0..1551a715 100644 --- a/code/fgame/sentient.cpp +++ b/code/fgame/sentient.cpp @@ -41,6 +41,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "g_spawn.h" #include "object.h" #include "../qcommon/tiki.h" +#include "weapturret.h" Event EV_Sentient_ReloadWeapon ( @@ -145,8 +146,8 @@ Event EV_Sentient_GiveAmmo ( "ammo", EV_DEFAULT, - "si", - "type amount", + "siI", + "type amount max_amount", "Gives the sentient some ammo.", EV_NORMAL ); @@ -192,7 +193,7 @@ Event EV_Sentient_UseItem EV_CONSOLE, "si", "name weapon_hand", - "Use the specified weapon or item in the hand choosen (optional).", + "Use the specified weapon or item in the hand chosen (optional).", EV_NORMAL ); Event EV_Sentient_SetBloodModel @@ -390,7 +391,7 @@ Event EV_Sentient_UseWeaponClass EV_CONSOLE, "sI", "name weapon_hand", - "Use the weapon of the specified class in the hand choosen (optional).", + "Use the weapon of the specified class in the hand chosen (optional).", EV_NORMAL ); Event EV_Sentient_German @@ -530,7 +531,7 @@ Event EV_Sentient_ForceDropWeapon2 ); Event EV_Sentient_ForceDropHealth ( - "forcedropweapon", + "forcedrophealth", EV_DEFAULT, NULL, NULL, @@ -539,7 +540,7 @@ Event EV_Sentient_ForceDropHealth ); Event EV_Sentient_ForceDropHealth2 ( - "forcedropweapon", + "forcedrophealth", EV_DEFAULT, NULL, NULL, @@ -564,6 +565,10 @@ Event EV_Sentient_GetForceDropWeapon "Get if the sentient is forced to drop health no matter what level.nodrophealth is.", EV_GETTER ); + +// +// Added in OPM +// Event EV_Sentient_GetNewActiveWeap ( "getnewactiveweap", @@ -573,6 +578,24 @@ Event EV_Sentient_GetNewActiveWeap "gets new active weapon", EV_RETURN ); +Event EV_Sentient_GetNewActiveWeapon +( + "newActiveWeapon", + EV_DEFAULT, + NULL, + NULL, + "gets new active weapon", + EV_GETTER +); +Event EV_Sentient_GetNewActiveWeaponHand +( + "newActiveWeaponHand", + EV_DEFAULT, + NULL, + NULL, + "gets the hand of the new active weapon", + EV_GETTER +); Event EV_Sentient_GetActiveWeap ( "getactiveweap", @@ -582,6 +605,14 @@ Event EV_Sentient_GetActiveWeap "gets currently active weapon in a given hand", EV_RETURN ); +Event EV_Sentient_Client_Landing +( + "_client_landing", + EV_DEFAULT, + "FI", + "fVolume iEquipment", + "Play a landing sound that is appropriate to the surface we are landing on\n" +); CLASS_DECLARATION(Animate, Sentient, NULL) { {&EV_Sentient_ReloadWeapon, &Sentient::ReloadWeapon }, @@ -643,9 +674,12 @@ CLASS_DECLARATION(Animate, Sentient, NULL) { {&EV_Sentient_ForceDropWeapon2, &Sentient::EventForceDropWeapon }, {&EV_Sentient_GetForceDropWeapon, &Sentient::EventGetForceDropWeapon }, - {&EV_Sentient_GetActiveWeap, &Sentient::GetActiveWeap }, - {&EV_Sentient_GetNewActiveWeap, &Sentient::GetNewActiveWeapon }, - {NULL, NULL } + {&EV_Sentient_GetActiveWeap, &Sentient::GetActiveWeap }, + {&EV_Sentient_GetNewActiveWeap, &Sentient::GetNewActiveWeaponOld }, + {&EV_Sentient_GetNewActiveWeapon, &Sentient::GetNewActiveWeapon }, + {&EV_Sentient_GetNewActiveWeaponHand, &Sentient::GetNewActiveWeaponHand }, + {&EV_Sentient_Client_Landing, &Sentient::EventClientLanding }, + {NULL, NULL } }; Container SentientList; @@ -676,10 +710,11 @@ void Sentient::EventGiveDynItem(Event *ev) } Sentient::Sentient() - : m_bIsAnimal(false) + : mAccuracy(0.2f) + , m_bIsAnimal(false) { SentientList.AddObject((Sentient *)this); - entflags |= EF_SENTIENT; + entflags |= ECF_SENTIENT; m_bOvercookDied = false; @@ -761,6 +796,7 @@ Sentient::Sentient() m_iThreatBias = 0; m_bFootOnGround_Right = true; m_bFootOnGround_Left = true; + iNextLandTime = 0; m_bDontDropWeapons = false; if (g_realismmode->integer) { @@ -809,7 +845,7 @@ Sentient::~Sentient() SentientList.RemoveObject((Sentient *)this); FreeInventory(); - entflags &= ~EF_SENTIENT; + entflags &= ~ECF_SENTIENT; } void Sentient::Link() @@ -1016,7 +1052,7 @@ void Sentient::FreeInventory(void) num = inventory.NumObjects(); for (i = num; i > 0; i--) { item = (Item *)G_GetEntity(inventory.ObjectAt(i)); - delete item; + item->Delete(); } inventory.ClearObjectList(); @@ -1105,30 +1141,19 @@ qboolean Sentient::HasSecondaryWeapon(void) void Sentient::EventGiveTargetname(Event *ev) { - int i; - ConSimple *tlist; - str name; - const char *ptr; - qboolean found; + int i; + str name; + qboolean found; + ScriptVariable var; + SimpleEntity *ent; - name = ev->GetString(1); + var = ev->GetValue(1); + var.CastConstArrayValue(); - ptr = name.c_str(); - - // skip over the $ - ptr++; - - found = qfalse; - - str sName = ptr; - tlist = world->GetTargetList(sName); - for (i = 1; i <= tlist->NumObjects(); i++) { - Entity *ent; - - ent = (Entity *)tlist->ObjectAt(i).Pointer(); - assert(ent); - - if (ent->isSubclassOf(Item)) { + for (i = var.arraysize(); i > 0; i--) { + const ScriptVariable *variable = var[i]; + ent = variable->simpleEntityValue(); + if (ent && ent->IsSubclassOfItem()) { Item *item; item = (Item *)ent; @@ -1197,13 +1222,13 @@ Item *Sentient::giveItem(str itemname, int amount) AddItem(item); - if (item->isSubclassOf(Weapon)) { + if (item->IsSubclassOfWeapon()) { // Post an event to give the ammo to the sentient Event *ev1; ev1 = new Event(EV_Weapon_GiveStartingAmmo); ev1->AddEntity(this); - item->PostEvent(ev1, 0); + item->PostEvent(ev1, level.frametime); } return item; @@ -1269,8 +1294,8 @@ void Sentient::EventTake(Event *ev) void Sentient::EventGiveItem(Event *ev) { - const char *type; - float amount; + str type; + float amount; type = ev->GetString(1); if (ev->NumArgs() > 1) { @@ -1338,24 +1363,22 @@ void Sentient::ArmorDamage(Event *ev) { Entity *inflictor; Sentient *attacker; - float damage; - Vector momentum; - Vector position; - Vector normal; - Vector direction; - Event *event; - int dflags; - int meansofdeath; - int knockback; - int location; + float damage; + Vector momentum; + Vector position; + Vector normal; + Vector direction; + Event event; + int dflags; + int meansofdeath; + int knockback; + int location; - /* - qboolean blocked; + //qboolean blocked; float damage_red; float damage_green; float damage_time; - qboolean set_means_of_death; -*/ + //qboolean set_means_of_death; static bool tmp = false; static cvar_t *AIDamageMult = NULL; @@ -1380,7 +1403,7 @@ void Sentient::ArmorDamage(Event *ev) meansofdeath = ev->GetInteger(9); location = CheckHitLocation(ev->GetInteger(10)); - if (location == -2) { + if (location == HITLOC_MISS) { return; } @@ -1388,12 +1411,10 @@ void Sentient::ArmorDamage(Event *ev) return; } - if ((client && !g_gametype->integer) || (location < 0 || location > 18)) { - if (attacker && attacker->IsSubclassOfActor()) { - damage *= AIDamageMult->value; - } - } else { + if ((!isClient() || g_gametype->integer != GT_SINGLE_PLAYER) && (location > HITLOC_GENERAL && location < NUMBODYLOCATIONS)) { damage *= m_fDamageMultipliers[location]; + } else if (isClient() && attacker && attacker->IsSubclassOfActor() && g_gametype->integer == GT_SINGLE_PLAYER) { + damage *= AIDamageMult->value; } // See if sentient is immune to this type of damage @@ -1455,34 +1476,6 @@ void Sentient::ArmorDamage(Event *ev) } */ - /* -if( meansofdeath == MOD_SLIME ) -{ - damage_green = damage / 50; - if( damage_green > 1.0f ) - damage_green = 1.0f; - if( ( damage_green < 0.2 ) && ( damage_green > 0 ) ) - damage_green = 0.2f; - damage_red = 0; -} -else -{ - damage_red = damage / 50; - if( damage_red > 1.0f ) - damage_red = 1.0f; - if( ( damage_red < 0.2 ) && ( damage_red > 0 ) ) - damage_red = 0.2f; - damage_green = 0; -} - -damage_time = damage / 50; - -if( damage_time > 2 ) - damage_time = 2; - -SetOffsetColor( damage_red, damage_green, 0, damage_time ); -*/ - // Do the kick if (!(dflags & DAMAGE_NO_KNOCKBACK)) { if ((knockback) && (movetype != MOVETYPE_NONE) && (movetype != MOVETYPE_STATIONARY) @@ -1490,14 +1483,14 @@ SetOffsetColor( damage_red, damage_green, 0, damage_time ); float m; Event *immunity_event; - if (mass < 50) { - m = 50; + if (mass < 20) { + m = 20; } else { m = mass; } direction.normalize(); - if (isClient() && (attacker == this) && g_gametype->integer) { + if (isClient() && (attacker == this) && deathmatch->integer) { momentum = direction * (1700.0f * (float)knockback / m); // the rocket jump hack... } else { momentum = direction * (500.0f * (float)knockback / m); @@ -1526,8 +1519,8 @@ SetOffsetColor( damage_red, damage_green, 0, damage_time ); } if (!(flags & FL_GODMODE) - && ((g_gametype->integer) || !(attacker) || (attacker) == this || !(attacker->IsSubclassOfPlayer()) - || !(attacker->IsTeamMate(this)))) { + && ((g_gametype->integer != GT_SINGLE_PLAYER) || !(attacker) || (attacker) == this || !(attacker->IsSubclassOfSentient()) + || (attacker->m_Team != m_Team))) { health -= damage; } @@ -1557,44 +1550,88 @@ SetOffsetColor( damage_red, damage_green, 0, damage_time ); } } - if (health > 0) { - // Send pain event - event = new Event(EV_Pain); - event->AddEntity(attacker); - event->AddFloat(damage); - event->AddEntity(inflictor); - event->AddVector(position); - event->AddVector(direction); - event->AddVector(normal); - event->AddInteger(knockback); - event->AddInteger(dflags); - event->AddInteger(meansofdeath); - event->AddInteger(location); - - ProcessEvent(event); + if (meansofdeath == MOD_SLIME) + { + damage_green = damage / 50; + if (damage_green > 1.0f) + damage_green = 1.0f; + if ((damage_green < 0.2) && (damage_green > 0)) + damage_green = 0.2f; + damage_red = 0; } + else + { + damage_red = damage / 50; + if (damage_red > 1.0f) + damage_red = 1.0f; + if ((damage_red < 0.2) && (damage_red > 0)) + damage_red = 0.2f; + damage_green = 0; + } + + damage_time = damage / 50; + + if (damage_time > 2) + damage_time = 2; + + //SetOffsetColor(damage_red, damage_green, 0, damage_time); if (health < 0.1) { // Make sure health is now 0 health = 0; - event = new Event(EV_Killed); - event->AddEntity(attacker); - event->AddFloat(damage); - event->AddEntity(inflictor); - event->AddVector(position); - event->AddVector(direction); - event->AddVector(normal); - event->AddInteger(knockback); - event->AddInteger(dflags); - event->AddInteger(meansofdeath); - event->AddInteger(location); + if (attacker) { + const EntityPtr attackerPtr = attacker; + + // Added in OPM + event = Event(EV_GotKill); + event.AddEntity(this); + event.AddInteger(damage); + event.AddEntity(inflictor); + event.AddInteger(meansofdeath); + event.AddInteger(0); + + attackerPtr->ProcessEvent(event); + if (attackerPtr) { + attackerPtr->delegate_gotKill.Execute(event); + } + } + + event = Event(EV_Killed, 10); + event.AddEntity(attacker); + event.AddFloat(damage); + event.AddEntity(inflictor); + event.AddVector(position); + event.AddVector(direction); + event.AddVector(normal); + event.AddInteger(knockback); + event.AddInteger(dflags); + event.AddInteger(meansofdeath); + event.AddInteger(location); + + ProcessEvent(event); + delegate_killed.Execute(event); + } + + if (health > 0) { + // Send pain event + event = Event(EV_Pain, 10); + event.AddEntity(attacker); + event.AddFloat(damage); + event.AddEntity(inflictor); + event.AddVector(position); + event.AddVector(direction); + event.AddVector(normal); + event.AddInteger(knockback); + event.AddInteger(dflags); + event.AddInteger(meansofdeath); + event.AddInteger(location); ProcessEvent(event); } - return; + delegate_damage.Execute(*ev); } qboolean Sentient::CanBlock(int meansofdeath, qboolean full_block) @@ -1947,17 +1984,49 @@ void Sentient::DropInventoryItems(void) int i; Item *item; + if (m_bForceDropHealth) { + giveItem("ITEMS/item_25_healthbox.tik", 25); + } else if (skill->integer != 2 && !level.mbNoDropHealth) { + static cvar_t *ai_health_kar = gi.Cvar_Get("ai_health_kar", "6", CVAR_CHEAT); + static cvar_t *ai_health_mp40 = gi.Cvar_Get("ai_health_mp40points", "2", CVAR_CHEAT); + + Weapon *weapon = GetActiveWeapon(WEAPON_MAIN); + if (weapon) { + if (!Q_stricmp("rifle", Director.GetString(weapon->GetWeaponGroup()))) { + level.mHealthPopCount++; + } else { + level.mHealthPopCount += ai_health_mp40->integer; + } + + if (level.mHealthPopCount >= ai_health_kar->integer) { + giveItem("ITEMS/item_25_healthbox.tik", 25); + level.mHealthPopCount -= ai_health_kar->integer; + } + } + } + // Drop any inventory items num = inventory.NumObjects(); for (i = num; i >= 1; i--) { item = (Item *)G_GetEntity(inventory.ObjectAt(i)); - if (item->isSubclassOf(InventoryItem)) { - if (m_bDontDropWeapons && item->IsSubclassOfWeapon()) { - item->Delete(); - } else { - item->Drop(); - } + // Added in 2.30 + // Force drop the item when specified + if (m_bForceDropWeapon && item->IsSubclassOfWeapon()) { + item->Drop(); + continue; } + + if (!m_bDontDropWeapons && !level.mbNoDropWeapons) { + item->Drop(); + continue; + } + + if (!item->IsSubclassOfWeapon()) { + item->Drop(); + continue; + } + + item->Delete(); } } @@ -2113,6 +2182,11 @@ void Sentient::Archive(Archiver& arc) Holster(true); } } + + // + // Added in OPM + // + arc.ArchiveInteger(&iNextLandTime); } static bool IsItemName(const char *name) @@ -2132,11 +2206,27 @@ static bool IsItemName(const char *name) void Sentient::ArchivePersistantData(Archiver& arc) { - int i; - int num; + int i; + int num; + str name; + int amount; + Item *item; + Entity *ent; // archive the inventory if (arc.Saving()) { + // remove all special items before persistence + for (i = inventory.NumObjects(); i > 0; i--) { + int index; + + index = inventory.ObjectAt(i); + ent = G_GetEntity(index); + name = ent->model; + + if (IsItemName(name)) { + ent->Delete(); + } + } // count up the total number num = inventory.NumObjects(); } else { @@ -2146,10 +2236,6 @@ void Sentient::ArchivePersistantData(Archiver& arc) arc.ArchiveInteger(&num); // archive each item for (i = 1; i <= num; i++) { - str name; - int amount; - Item *item; - if (arc.Saving()) { Entity *ent; @@ -2162,11 +2248,26 @@ void Sentient::ArchivePersistantData(Archiver& arc) error("ArchivePersistantData", "Non Item in inventory\n"); } } + arc.ArchiveString(&name); arc.ArchiveInteger(&amount); + if (arc.Loading()) { item = giveItem(name, amount); + } + + if (item && item->IsSubclassOfWeapon()) { + Weapon *pWeap = static_cast(item); + item->CancelEventsOfType(EV_Weapon_GiveStartingAmmo); + if (arc.Saving()) { + amount = pWeap->ClipAmmo(FIRE_PRIMARY); + } + arc.ArchiveInteger(&amount); + + if (arc.Loading()) { + pWeap->SetAmmoAmount(amount, FIRE_PRIMARY); + } } } @@ -2192,16 +2293,17 @@ void Sentient::ArchivePersistantData(Archiver& arc) amount = ptr->getAmount(); maxamount = ptr->getMaxAmount(); } + arc.ArchiveString(&name); arc.ArchiveInteger(&amount); arc.ArchiveInteger(&maxamount); + if (arc.Loading()) { GiveAmmo(name, amount, maxamount); } } for (i = 0; i < MAX_ACTIVE_WEAPONS; i++) { - str name; if (arc.Saving()) { if (activeWeaponList[i]) { name = activeWeaponList[i]->getName(); @@ -2209,18 +2311,25 @@ void Sentient::ArchivePersistantData(Archiver& arc) name = "none"; } } + arc.ArchiveString(&name); - if (arc.Loading()) { - if (name != "none") { - Weapon *weapon; - weapon = (Weapon *)FindItem(name); - if (weapon) { - ChangeWeapon(weapon, (weaponhand_t)i); - } + + if (arc.Loading() && name != "none") { + Weapon *weapon; + + weapon = (Weapon *)FindItem(name); + if (weapon) { + ChangeWeapon(weapon, (weaponhand_t)i); } } } + if (GetActiveWeapon(WEAPON_MAIN)) { + edict->s.eFlags &= ~EF_UNARMED; + } else { + edict->s.eFlags |= EF_UNARMED; + } + arc.ArchiveFloat(&health); arc.ArchiveFloat(&max_health); } @@ -2495,6 +2604,11 @@ void Sentient::EventGerman(Event *ev) if (bRejoinSquads) { JoinNearbySquads(1024.0f); } + + // Added in 2.0 + // Tell clients about sentient team + edict->s.eFlags &= ~EF_ALLIES; + edict->s.eFlags |= EF_AXIS; } void Sentient::EventAmerican(Event *ev) @@ -2512,7 +2626,6 @@ void Sentient::EventAmerican(Event *ev) DisbandSquadMate(this); } - Unlink(); m_Team = TEAM_AMERICAN; Link(); @@ -2526,6 +2639,11 @@ void Sentient::EventAmerican(Event *ev) pActor->m_csMood = STRING_NERVOUS; pActor->m_csIdleMood = STRING_NERVOUS; } + + // Added in 2.0 + // Tell clients about sentient team + edict->s.eFlags &= ~EF_AXIS; + edict->s.eFlags |= EF_ALLIES; } void Sentient::EventGetTeam(Event *ev) @@ -2701,7 +2819,10 @@ void Sentient::RemovedItem(Item *item) {} void Sentient::AssertValidSquad() { - for (Sentient *pSquadMate = this; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) {} + for (Sentient *pSquadMate = this; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) { + assert(pSquadMate->m_pNextSquadMate); + assert(pSquadMate->m_pPrevSquadMate); + } } bool Sentient::IsTeamMate(Sentient *pOther) @@ -2748,6 +2869,8 @@ void Sentient::DisbandSquadMate(Sentient *pExFriendly) Sentient *pPrev; Sentient *pNext; + AssertValidSquad(); + pPrev = pExFriendly->m_pPrevSquadMate; pNext = pExFriendly->m_pNextSquadMate; @@ -2756,6 +2879,9 @@ void Sentient::DisbandSquadMate(Sentient *pExFriendly) pExFriendly->m_pPrevSquadMate = pExFriendly; pExFriendly->m_pNextSquadMate = pExFriendly; + + AssertValidSquad(); + pNext->AssertValidSquad(); } bool Sentient::IsSquadMate(Sentient *pFriendly) @@ -2774,6 +2900,11 @@ bool Sentient::IsSquadMate(Sentient *pFriendly) } } +bool Sentient::IsDisabled() const +{ + return false; +} + VehicleTank *Sentient::GetVehicleTank(void) { if (m_pVehicle && m_pVehicle->IsSubclassOfVehicleTank()) { @@ -2797,7 +2928,8 @@ void Sentient::UpdateFootsteps(void) } } - if ((iAnimFlags & (TAF_AUTOSTEPS | TAF_AUTOSTEPS_RUNNING)) != (TAF_AUTOSTEPS | TAF_AUTOSTEPS_RUNNING)) { + if (!(iAnimFlags & TAF_AUTOSTEPS_RUNNING) || !(iAnimFlags & TAF_AUTOSTEPS)) { + // if walking, or if the animation doesn't step m_bFootOnGround_Right = true; m_bFootOnGround_Left = true; return; @@ -2814,10 +2946,14 @@ void Sentient::UpdateFootsteps(void) iTagNum = gi.Tag_NumForName(edict->tiki, "Bip01 R Foot"); if (iTagNum >= 0) { if (G_TIKI_IsOnGround(edict, iTagNum, 13.461539f)) { - BroadcastAIEvent(10, G_AIEventRadius(10)); + BroadcastAIEvent(AI_EVENT_FOOTSTEP, G_AIEventRadius(AI_EVENT_FOOTSTEP)); + // simulate footstep sounds + Footstep("Bip01 L Foot", (iAnimFlags & TAF_AUTOSTEPS_RUNNING), (iAnimFlags & TAF_AUTOSTEPS_EQUIPMENT)); + m_bFootOnGround_Right = true; } + } else { + m_bFootOnGround_Right = true; } - m_bFootOnGround_Right = true; } if (m_bFootOnGround_Left) { @@ -2828,13 +2964,17 @@ void Sentient::UpdateFootsteps(void) m_bFootOnGround_Left = true; } } else { - iTagNum = gi.Tag_NumForName(edict->tiki, "Bip01 R Foot"); + iTagNum = gi.Tag_NumForName(edict->tiki, "Bip01 L Foot"); if (iTagNum >= 0) { if (G_TIKI_IsOnGround(edict, iTagNum, 13.461539f)) { - BroadcastAIEvent(10, G_AIEventRadius(10)); + BroadcastAIEvent(AI_EVENT_FOOTSTEP, G_AIEventRadius(AI_EVENT_FOOTSTEP)); + // simulate footstep sounds + Footstep("Bip01 R Foot", (iAnimFlags & TAF_AUTOSTEPS_RUNNING), (iAnimFlags & TAF_AUTOSTEPS_EQUIPMENT)); + m_bFootOnGround_Left = true; } + } else { + m_bFootOnGround_Left = true; } - m_bFootOnGround_Left = true; } } @@ -2905,3 +3045,308 @@ void Sentient::SetMinViewVariation(const Vector& vVariation) m_vViewVariation.y = Q_min(m_vViewVariation.y, vVariation.y); m_vViewVariation.z = Q_min(m_vViewVariation.z, vVariation.z); } + +void Sentient::SetHolsteredByCode(bool holstered) +{ + weapons_holstered_by_code = holstered; +} + +Vehicle *Sentient::GetVehicle() const +{ + return m_pVehicle; +} + +void Sentient::SetVehicle(Vehicle *pVehicle) +{ + m_pVehicle = NULL; +} + +TurretGun *Sentient::GetTurret() const +{ + return m_pTurret; +} + +void Sentient::SetTurret(TurretGun *pTurret) +{ + m_pTurret = pTurret; +} + +Entity* Sentient::GetLadder() const { + return m_pLadder; +} + +#define GROUND_DISTANCE 8 +#define WATER_NO_SPLASH_HEIGHT 16 + +void Sentient::EventClientLanding(Event *ev) +{ + float fVolume = ev->NumArgs() >= 1 ? ev->GetFloat(1) : 1; + int iEquipment = ev->NumArgs() >= 2 ? ev->GetInteger(2) : 1; + + LandingSound(fVolume, iEquipment); +} + +void Sentient::FootstepMain(trace_t *trace, int iRunning, int iEquipment) +{ + int contents; + int surftype; + float fVolume; + vec3_t vPos; + vec3_t midlegs; + str sSoundName; + + VectorCopy(trace->endpos, vPos); + sSoundName = "snd_step_"; + + contents = gi.pointcontents(trace->endpos, -1); + if (contents & MASK_WATER) { + // take our ground position and trace upwards + VectorCopy(trace->endpos, midlegs); + midlegs[2] += WATER_NO_SPLASH_HEIGHT; + contents = gi.pointcontents(midlegs, -1); + if (contents & MASK_WATER) { + sSoundName += "wade"; + } else { + sSoundName += "puddle"; + } + } else { + surftype = trace->surfaceFlags & MASK_SURF_TYPE; + switch (surftype) { + case SURF_FOLIAGE: + sSoundName += "foliage"; + break; + case SURF_SNOW: + sSoundName += "snow"; + break; + case SURF_CARPET: + sSoundName += "carpet"; + break; + case SURF_SAND: + sSoundName += "sand"; + break; + case SURF_PUDDLE: + sSoundName += "puddle"; + break; + case SURF_GLASS: + sSoundName += "glass"; + break; + case SURF_GRAVEL: + sSoundName += "gravel"; + break; + case SURF_MUD: + sSoundName += "mud"; + break; + case SURF_DIRT: + sSoundName += "dirt"; + break; + case SURF_GRILL: + sSoundName += "grill"; + break; + case SURF_GRASS: + sSoundName += "grass"; + break; + case SURF_ROCK: + sSoundName += "stone"; + break; + case SURF_PAPER: + sSoundName += "paper"; + break; + case SURF_WOOD: + sSoundName += "wood"; + break; + case SURF_METAL: + sSoundName += "metal"; + break; + default: + sSoundName += "stone"; + break; + } + } + + if (iRunning) { + if (iRunning == -1) { + fVolume = 0.5; + } else { + fVolume = 1.0; + } + } else { + fVolume = 0.25; + } + + if (!iRunning && g_gametype->integer == GT_SINGLE_PLAYER) { + return; + } + + PlayNonPvsSound(sSoundName, fVolume); + + if (iEquipment && random() < 0.3) { + // also play equipment sound + PlayNonPvsSound("snd_step_equipment", fVolume); + } +} + +void Sentient::Footstep(const char *szTagName, int iRunning, int iEquipment) +{ + int i; + int iTagNum; + vec3_t vStart, vEnd; + vec3_t midlegs; + vec3_t vMins, vMaxs; + str sSoundName; + trace_t trace; + orientation_t oTag; + + // send a trace down from the player to the ground + VectorCopy(this->origin, vStart); + vStart[2] += GROUND_DISTANCE; + + if (szTagName) { + iTagNum = gi.Tag_NumForName(this->edict->tiki, szTagName); + if (iTagNum != -1) { + oTag = G_TIKI_Orientation(this->edict, iTagNum); + + for (i = 0; i < 2; i++) { + VectorMA(vStart, oTag.origin[i], this->orientation[i], vStart); + } + } + } + + if (iRunning == -1) { + AngleVectors(this->angles, midlegs, NULL, NULL); + VectorMA(vStart, -16, midlegs, vStart); + VectorMA(vStart, 64, midlegs, vEnd); + + VectorSet(vMins, -2, -2, -8); + VectorSet(vMaxs, 2, 2, 8); + } else { + VectorSet(vMins, -4, -4, 0); + VectorSet(vMaxs, 4, 4, 2); + + // add 16 units above feets + vStart[2] += 16.0; + VectorCopy(vStart, vEnd); + vEnd[2] -= 64.0; + } + + if (IsSubclassOfPlayer()) { + trace = G_Trace(vStart, vMins, vMaxs, vEnd, edict, MASK_PLAYERSOLID, qtrue, "Player Footsteps"); + } else { + trace = G_Trace(vStart, vMins, vMaxs, vEnd, edict, MASK_MONSTERSOLID, qfalse, "Monster Footsteps"); + } + + if (trace.fraction == 1.0f) { + return; + } + + FootstepMain(&trace, iRunning, iEquipment); +} + +void Sentient::LandingSound(float volume, int iEquipment) +{ + int contents; + int surftype; + vec3_t vStart, vEnd; + vec3_t midlegs; + str sSoundName; + trace_t trace; + static vec3_t g_vFootstepMins = {-4, -4, 0}; + static vec3_t g_vFootstepMaxs = {4, 4, 2}; + + if (this->iNextLandTime > level.inttime) { + this->iNextLandTime = level.inttime + 200; + return; + } + + this->iNextLandTime = level.time + 200; + VectorCopy(this->origin, vStart); + vStart[2] += GROUND_DISTANCE; + + VectorCopy(vStart, vEnd); + vEnd[2] -= 64.0; + + if (IsSubclassOfPlayer()) { + trace = + G_Trace(vStart, g_vFootstepMins, g_vFootstepMaxs, vEnd, edict, MASK_PLAYERSOLID, qtrue, "Player Footsteps"); + } else { + trace = G_Trace( + vStart, g_vFootstepMins, g_vFootstepMaxs, vEnd, edict, MASK_MONSTERSOLID, qfalse, "Monster Footsteps" + ); + } + + if (trace.fraction == 1.0) { + return; + } + + sSoundName += "snd_landing_"; + + contents = gi.pointcontents(trace.endpos, -1); + if (contents & MASK_WATER) { + // take our ground position and trace upwards + VectorCopy(trace.endpos, midlegs); + midlegs[2] += WATER_NO_SPLASH_HEIGHT; + contents = gi.pointcontents(midlegs, -1); + if (contents & MASK_WATER) { + sSoundName += "wade"; + } else { + sSoundName += "puddle"; + } + } else { + surftype = trace.surfaceFlags & MASK_SURF_TYPE; + switch (surftype) { + case SURF_FOLIAGE: + sSoundName += "foliage"; + break; + case SURF_SNOW: + sSoundName += "snow"; + break; + case SURF_CARPET: + sSoundName += "carpet"; + break; + case SURF_SAND: + sSoundName += "sand"; + break; + case SURF_PUDDLE: + sSoundName += "puddle"; + break; + case SURF_GLASS: + sSoundName += "glass"; + break; + case SURF_GRAVEL: + sSoundName += "gravel"; + break; + case SURF_MUD: + sSoundName += "mud"; + break; + case SURF_DIRT: + sSoundName += "dirt"; + break; + case SURF_GRILL: + sSoundName += "grill"; + break; + case SURF_GRASS: + sSoundName += "grass"; + break; + case SURF_ROCK: + sSoundName += "stone"; + break; + case SURF_PAPER: + sSoundName += "paper"; + break; + case SURF_WOOD: + sSoundName += "wood"; + break; + case SURF_METAL: + sSoundName += "metal"; + break; + default: + sSoundName += "stone"; + break; + } + } + + PlayNonPvsSound(sSoundName, volume); + + if (iEquipment && random() < 0.5) { + PlayNonPvsSound("snd_step_equipment", volume); + } +} diff --git a/code/fgame/sentient.h b/code/fgame/sentient.h index 0f515cd1..c148db26 100644 --- a/code/fgame/sentient.h +++ b/code/fgame/sentient.h @@ -110,7 +110,7 @@ protected: bool weapons_holstered_by_code; ActiveWeapon lastActiveWeapon; float m_fDamageMultipliers[MAX_DAMAGE_MULTIPLIERS]; - class SafePtr m_pVehicle; + SafePtr m_pVehicle; SafePtr m_pTurret; SafePtr m_pLadder; str m_sHelmetSurface1; @@ -216,8 +216,13 @@ public: float next_bleed_time; bool m_bForceDropHealth; bool m_bForceDropWeapon; - bool m_bFootOnGround_Right; - bool m_bFootOnGround_Left; + + bool m_bFootOnGround_Right; + bool m_bFootOnGround_Left; + // + // Added in OPM + // + int iNextLandTime; CLASS_PROTOTYPE(Sentient); @@ -230,9 +235,11 @@ public: virtual Vector GetViewAngles(void); void AddViewVariation(const Vector &vVariation); void SetMinViewVariation(const Vector &vVariation); + void SetHolsteredByCode(bool holstered); bool CanSee(Entity *ent, float fov, float vision_distance, bool bNoEnts) override; + bool CanSee(const Vector& org, float fov, float vision_distance, bool bNoEnts) override; virtual Vector GunPosition(void); - virtual Vector GunTarget(bool bNoCollision = false); + virtual Vector GunTarget(bool bNoCollision = false, const vec3_t position = NULL, const vec3_t forward = NULL); void ReloadWeapon(Event *ev); void FireWeapon(Event *ev); void StopFireWeapon(Event *ev); @@ -314,6 +321,7 @@ public: Weapon *GetNewActiveWeapon(void); weaponhand_t GetNewActiveWeaponHand(void); void ClearNewActiveWeapon(void); + void SetNewActiveWeapon(Weapon* weapon, weaponhand_t hand); void Holster(qboolean putaway); void SafeHolster(qboolean putaway); void ActivateNewWeapon(void); @@ -334,11 +342,31 @@ public: void DisbandSquadMate(Sentient *pExFriendly); bool IsSquadMate(Sentient *pFriendly); + virtual bool IsDisabled() const; // Added in 2.30 + + Vehicle* GetVehicle() const; + void SetVehicle(Vehicle* pVehicle); + + TurretGun* GetTurret() const; + void SetTurret(TurretGun* pTurret); + + Entity* GetLadder() const; // Added in OPM + // // Custom openmohaa stuff // void GetActiveWeap(Event *ev); + void GetNewActiveWeaponOld(Event *ev); void GetNewActiveWeapon(Event *ev); + void GetNewActiveWeaponHand(Event *ev); + void EventClientLanding(Event *ev); + + void FootstepMain(trace_t *trace, int iRunning, int iEquipment); + void Footstep(const char *szTagName, int iRunning, int iEquipment); + void LandingSound(float volume, int iEquipment); + + const Container& getInventory() const; + const Container& getAmmoInventory() const; }; typedef SafePtr SentientPtr; diff --git a/code/fgame/sentient_combat.cpp b/code/fgame/sentient_combat.cpp index 38395dbe..e095d49d 100644 --- a/code/fgame/sentient_combat.cpp +++ b/code/fgame/sentient_combat.cpp @@ -33,7 +33,7 @@ ActiveWeapon::ActiveWeapon() void ActiveWeapon::Archive(Archiver& arc) { - arc.ArchiveObjectPointer((Class **)&weapon); + arc.ArchiveSafePointer(&weapon); ArchiveEnum(hand, weaponhand_t); } @@ -54,14 +54,19 @@ Weapon *Sentient::GetNewActiveWeapon(void) void Sentient::ClearNewActiveWeapon(void) { - newActiveWeapon.weapon.Clear(); - newActiveWeapon.hand = WEAPON_ERROR; + SetNewActiveWeapon(NULL, WEAPON_ERROR); +} + +void Sentient::SetNewActiveWeapon(Weapon* weapon, weaponhand_t hand) +{ + newActiveWeapon.weapon = weapon; + newActiveWeapon.hand = hand; } void Sentient::EventGiveAmmo(Event *ev) { - int amount, maxamount = -1; - const char *type; + int amount, maxamount = -1; + str type; type = ev->GetString(1); amount = ev->GetInteger(2); @@ -74,7 +79,6 @@ void Sentient::EventGiveAmmo(Event *ev) } int Sentient::AmmoIndex(str type) - { Ammo *ammo; @@ -146,7 +150,6 @@ void Sentient::GiveAmmo(str type, int amount, int maxamount) } int Sentient::UseAmmo(str type, int amount) - { int count, i; @@ -154,7 +157,7 @@ int Sentient::UseAmmo(str type, int amount) for (i = 1; i <= count; i++) { Ammo *ammo = ammo_inventory.ObjectAt(i); - if (type == ammo->getName()) { + if (!str::icmp(type, ammo->getName())) { int ammo_amount = ammo->getAmount(); // Less ammo than what we specified to use @@ -180,7 +183,9 @@ void Sentient::AmmoAmountInClipChanged(str type, int amount_in_clip) for (i = 1; i <= count; i++) { Ammo *ammo = ammo_inventory.ObjectAt(i); - if (type == ammo->getName()) { + // Fixed in OPM + // Original uses strcmp + if (!str::icmp(type, ammo->getName())) { AmmoAmountChanged(ammo, amount_in_clip); } } @@ -213,34 +218,70 @@ void Sentient::WeaponKnockedFromHands(void) bool Sentient::CanSee(Entity *ent, float fov, float vision_distance, bool bNoEnts) { - float delta[2]; + vec2_t delta; + int mask; - delta[0] = ent->centroid[0] - centroid[0]; - delta[1] = ent->centroid[1] - centroid[1]; + VectorSub2D(ent->centroid, centroid, delta); - if ((vision_distance <= 0.0f) || VectorLength2DSquared(delta) <= (vision_distance * vision_distance)) { - if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum) - && ((fov <= 0.0f || fov >= 360.0f) || (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0)))))) { - // - // Parent checking for subclass is absolute non-sense... - // - if (ent->IsSubclassOfPlayer()) { - Player *p = (Player *)ent; - - Vector vStart = EyePosition(); - Vector vEnd = p->EyePosition(); - - return G_SightTrace(vStart, vec_zero, vec_zero, vEnd, this, ent, MASK_CANSEE, 0, "Sentient::CanSee 1"); - } else { - Vector vStart = EyePosition(); - Vector vEnd = ent->centroid; - - return G_SightTrace(vStart, vec_zero, vec_zero, vEnd, this, ent, MASK_CANSEE, 0, "Sentient::CanSee 2"); - } - } + if (vision_distance > 0 && Square(vision_distance) < VectorLength2DSquared(delta)) { + return false; } - return false; + if (!AreasConnected(ent)) { + return false; + } + + if (fov > 0 && fov < 360 && !FovCheck(delta, cos(DEG2RAD(fov / 2.f)))) { + return false; + } + + if (bNoEnts) { + mask = MASK_CANSEE_NOENTS; + } else { + mask = MASK_CANSEE; + } + + if (ent->IsSubclassOfSentient()) { + return G_SightTrace( + EyePosition(), + vec_zero, + vec_zero, + static_cast(ent)->EyePosition(), + this, + ent, + mask, + qfalse, + "Sentient::CanSee 1" + ); + } else { + return G_SightTrace( + EyePosition(), vec_zero, vec_zero, ent->centroid, this, ent, mask, qfalse, "Sentient::CanSee 2" + ); + } +} + +bool Sentient::CanSee(const Vector& org, float fov, float vision_distance, bool bNoEnts) +{ + vec2_t delta; + int mask; + + VectorSub2D(org, centroid, delta); + + if (vision_distance > 0 && Square(vision_distance) < VectorLength2DSquared(delta)) { + return false; + } + + if (fov > 0 && fov < 360 && !FovCheck(delta, cos(DEG2RAD(fov / 2.f)))) { + return false; + } + + if (bNoEnts) { + mask = MASK_CANSEE_NOENTS; + } else { + mask = MASK_CANSEE; + } + + return G_SightTrace(EyePosition(), vec_zero, vec_zero, org, this, NULL, mask, qfalse, "Sentient::CanSee"); } Vector Sentient::GunPosition(void) @@ -248,7 +289,7 @@ Vector Sentient::GunPosition(void) Vector vPos; if (activeWeaponList[WEAPON_MAIN]) { - activeWeaponList[WEAPON_MAIN]->GetMuzzlePosition(&vPos); + activeWeaponList[WEAPON_MAIN]->GetMuzzlePosition(vPos); } else { vPos = origin; } @@ -256,7 +297,7 @@ Vector Sentient::GunPosition(void) return vPos; } -Vector Sentient::GunTarget(bool bNoCollision) +Vector Sentient::GunTarget(bool bNoCollision, const vec3_t position, const vec3_t forward) { Vector vPos; @@ -299,7 +340,7 @@ void Sentient::ChargeWeapon(weaponhand_t hand, firemode_t mode) return; } - if (hand > MAX_ACTIVE_WEAPONS) { + if (hand >= MAX_ACTIVE_WEAPONS) { warning( "Sentient::ChargeWeapon", "Weapon hand number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n", @@ -410,7 +451,7 @@ void Sentient::FireWeapon(int number, firemode_t mode) { Weapon *activeWeapon = activeWeaponList[number]; - if (activeWeapon) { + if (activeWeapon && activeWeapon->ReadyToFire(mode)) { if (mode == FIRE_SECONDARY && activeWeapon->GetZoom() && !activeWeapon->GetAutoZoom() && IsSubclassOfPlayer()) { Player *p = (Player *)this; p->ToggleZoom(activeWeapon->GetZoom()); @@ -470,7 +511,7 @@ void Sentient::StopFireWeapon(Event *ev) number = WeaponHandNameToNum(side); } - if ((number > MAX_ACTIVE_WEAPONS) || (number < 0)) { + if ((number >= MAX_ACTIVE_WEAPONS) || (number < 0)) { warning( "Sentient::StopFireWeapon", "Weapon number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n", @@ -497,7 +538,7 @@ void Sentient::ReleaseFireWeapon(int number, firemode_t mode) charge_start_time = 0; - if ((number > MAX_ACTIVE_WEAPONS) || (number < 0)) { + if ((number >= MAX_ACTIVE_WEAPONS) || (number < 0)) { warning( "Sentient::FireWeapon", "Weapon number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n", @@ -599,7 +640,7 @@ void Sentient::AttachAllActiveWeapons(void) } } - if (this->isSubclassOf(Player)) { + if (this->IsSubclassOfPlayer()) { Player *player = (Player *)this; player->UpdateWeapons(); } @@ -640,7 +681,7 @@ int Sentient::NumWeapons(void) void Sentient::ChangeWeapon(Weapon *weapon, weaponhand_t hand) { - if ((hand > MAX_ACTIVE_WEAPONS) || (hand < 0)) { + if ((hand >= MAX_ACTIVE_WEAPONS) || (hand < 0)) { warning( "Sentient::ChangeWeapon", "Weapon hand number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n", @@ -667,27 +708,33 @@ void Sentient::DeactivateWeapon(weaponhand_t hand) return; } + if (!(activeWeaponList[hand]->GetWeaponClass() & WEAPON_CLASS_ANY_ITEM)) { + // Set the last active weapon only if the weapon is not an item + lastActiveWeapon.weapon = activeWeaponList[hand]; + lastActiveWeapon.hand = hand; + } + activeWeaponList[hand]->AttachToHolster(hand); activeWeaponList[hand]->SetPutAway(false); - activeWeaponList[hand]->NewAnim("putaway"); + activeWeaponList[hand]->SetWeaponAnim("putaway"); // Check the player's inventory and detach any weapons that are already attached to that spot - for (i = 1; i <= inventory.NumObjects(); i++) { - Item *item = (Item *)G_GetEntity(inventory.ObjectAt(i)); + if (activeWeaponList[hand]->GetCurrentAttachToTag().length() > 0) { + for (i = 1; i <= inventory.NumObjects(); i++) { + Item *item = (Item *)G_GetEntity(inventory.ObjectAt(i)); - if (item->IsSubclassOfWeapon()) { - Weapon *weap = (Weapon *)item; + if (item->IsSubclassOfWeapon()) { + Weapon *weap = (Weapon *)item; - if ((weap != activeWeaponList[hand]) - && (!str::cmp(weap->GetCurrentAttachToTag(), activeWeaponList[hand]->GetCurrentAttachToTag()))) { - weap->DetachFromOwner(); + if ((weap != activeWeaponList[hand]) + && (!str::icmp(weap->GetCurrentAttachToTag(), activeWeaponList[hand]->GetCurrentAttachToTag()))) { + weap->DetachFromOwner(); + } } } } - lastActiveWeapon.weapon = activeWeaponList[hand]; - lastActiveWeapon.hand = hand; - activeWeaponList[hand] = NULL; + activeWeaponList[hand] = NULL; } void Sentient::DeactivateWeapon(Weapon *weapon) @@ -696,6 +743,12 @@ void Sentient::DeactivateWeapon(Weapon *weapon) for (i = 0; i < MAX_ACTIVE_WEAPONS; i++) { if (activeWeaponList[i] == weapon) { + if (activeWeaponList[i] && !(activeWeaponList[i]->GetWeaponClass() & WEAPON_CLASS_ANY_ITEM)) { + // Set the last active weapon only if the weapon is not an item + lastActiveWeapon.weapon = activeWeaponList[i]; + lastActiveWeapon.hand = (weaponhand_t)i; + } + activeWeaponList[i]->DetachFromOwner(); activeWeaponList[i]->SetPutAway(false); activeWeaponList[i] = NULL; @@ -723,6 +776,7 @@ void Sentient::EventDeactivateWeapon(Event *ev) void Sentient::ActivateWeapon(Weapon *weapon, weaponhand_t hand) { + str holsterTag; int i; if (hand == WEAPON_ERROR) { @@ -731,22 +785,31 @@ void Sentient::ActivateWeapon(Weapon *weapon, weaponhand_t hand) } activeWeaponList[hand] = weapon; - str holsterTag = weapon->GetHolsterTag(); - // Check the player's inventory and detach any weapons that are currently attached to that tag. - for (i = 1; i <= inventory.NumObjects(); i++) { - Item *item = (Item *)G_GetEntity(inventory.ObjectAt(i)); + if (hand == WEAPON_MAIN) { + holsterTag = weapon->GetHolsterTag(); + } - if (item->isSubclassOf(Weapon)) { - Weapon *weap = (Weapon *)item; + if (holsterTag.length() > 0) { + // Check the player's inventory and detach any weapons that are currently attached to that tag. + for (i = 1; i <= inventory.NumObjects(); i++) { + Item *item = (Item *)G_GetEntity(inventory.ObjectAt(i)); - if ((!str::cmp(holsterTag, weap->GetCurrentAttachToTag()))) { - weap->DetachFromOwner(); + if (item->IsSubclassOfWeapon()) { + Weapon *weap = (Weapon *)item; + + if ((!str::cmp(holsterTag, weap->GetCurrentAttachToTag()))) { + weap->DetachFromOwner(); + } } } } weapon->AttachToOwner(hand); - weapon->NewAnim("raise"); + weapon->SetWeaponAnim("raise"); + + if (weapon == holsteredWeapon) { + holsteredWeapon = NULL; + } } void Sentient::ActivateLastActiveWeapon(void) @@ -805,15 +868,32 @@ Weapon *Sentient::BestWeapon(Weapon *ignore, qboolean bGetItem, int iIgnoreClass next = (Weapon *)G_GetEntity(inventory.ObjectAt(j)); assert(next); - - if ((next != ignore) - && ((next->IsSubclassOfWeapon() && !(next->GetWeaponClass() & iIgnoreClass)) - || (next->IsSubclassOfItem() && bGetItem)) - && (next->GetRank() > bestrank) - && (next->HasAmmo(FIRE_PRIMARY) || next->GetFireType(FIRE_SECONDARY) == FT_MELEE)) { - bestweapon = (Weapon *)next; - bestrank = bestweapon->GetRank(); + if (next == ignore) { + continue; } + + if (!next->IsSubclassOfWeapon() && (!bGetItem || !next->IsSubclassOfInventoryItem())) { + continue; + } + + if (!bGetItem && next->IsSubclassOfInventoryItem()) { + continue; + } + + if (next->GetWeaponClass() & iIgnoreClass) { + continue; + } + + if (next->GetRank() < bestrank) { + continue; + } + + if (!next->HasAmmo(FIRE_PRIMARY) && !next->GetUseNoAmmo()) { + continue; + } + + bestweapon = (Weapon*)next; + bestrank = bestweapon->GetRank(); } return bestweapon; @@ -837,14 +917,32 @@ Weapon *Sentient::WorstWeapon(Weapon *ignore, qboolean bGetItem, int iIgnoreClas assert(next); - if ((next != ignore) - && ((next->IsSubclassOfWeapon() && !(next->GetWeaponClass() & iIgnoreClass)) - || (next->IsSubclassOfWeapon() && bGetItem)) - && (next->GetRank() < iWorstRank) - && (next->HasAmmo(FIRE_PRIMARY) || next->GetFireType(FIRE_SECONDARY) == FT_MELEE)) { - worstweapon = (Weapon *)next; - iWorstRank = worstweapon->GetRank(); + if (next == ignore) { + continue; } + + if (!next->IsSubclassOfWeapon()) { + continue; + } + + if (!bGetItem && next->IsSubclassOfInventoryItem()) { + continue; + } + + if (next->GetWeaponClass() & iIgnoreClass) { + continue; + } + + if (next->GetRank() >= iWorstRank) { + continue; + } + + if (!next->HasAmmo(FIRE_PRIMARY) && !next->GetUseNoAmmo()) { + continue; + } + + worstweapon = (Weapon*)next; + iWorstRank = worstweapon->GetRank(); } return worstweapon; @@ -879,7 +977,7 @@ Weapon *Sentient::NextWeapon(Weapon *weapon) assert(item); - if (item->isSubclassOf(Weapon)) { + if (item->IsSubclassOfWeapon()) { choice = (Weapon *)item; if ((!choice->HasAmmo(FIRE_PRIMARY) && !choice->GetUseNoAmmo()) || !choice->AutoChange()) { continue; @@ -934,7 +1032,7 @@ Weapon *Sentient::PreviousWeapon(Weapon *weapon) assert(item); - if (item->isSubclassOf(Weapon)) { + if (item->IsSubclassOfWeapon()) { choice = (Weapon *)item; if ((!choice->HasAmmo(FIRE_PRIMARY) && !choice->GetUseNoAmmo()) || !choice->AutoChange()) { continue; @@ -963,7 +1061,7 @@ Weapon *Sentient::PreviousWeapon(Weapon *weapon) Weapon *Sentient::GetActiveWeapon(weaponhand_t hand) const { - if ((hand > MAX_ACTIVE_WEAPONS) || (hand < 0)) { + if ((hand >= MAX_ACTIVE_WEAPONS) || (hand < 0)) { warning( "Sentient::GetActiveWeapon", "Weapon hand number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n", @@ -977,7 +1075,6 @@ Weapon *Sentient::GetActiveWeapon(weaponhand_t hand) const } qboolean Sentient::IsActiveWeapon(Weapon *weapon) - { int i; @@ -1005,6 +1102,9 @@ void Sentient::useWeapon(const char *weaponname, weaponhand_t hand) // Find the item in the sentient's inventory weapon = (Weapon *)FindItem(weaponname); + if (!weapon) { + weapon = (Weapon *)FindItemByExternalName(weaponname); + } // If it exists, then make the change to the slot number specified if (weapon) { @@ -1022,8 +1122,7 @@ void Sentient::useWeapon(Weapon *weapon, weaponhand_t hand) } if (newActiveWeapon.weapon) { - newActiveWeapon.weapon = weapon; - newActiveWeapon.hand = hand; + SetNewActiveWeapon(weapon, hand); return; } @@ -1035,20 +1134,21 @@ void Sentient::useWeapon(Weapon *weapon, weaponhand_t hand) activeWeaponList[WEAPON_OFFHAND]->PutAway(); } - if (activeWeaponList[WEAPON_MAIN] && activeWeaponList[WEAPON_MAIN] != weapon) { + if (activeWeaponList[WEAPON_MAIN] == weapon) { + return; + } + + if (activeWeaponList[WEAPON_MAIN]) { activeWeaponList[WEAPON_MAIN]->PutAway(); } - newActiveWeapon.weapon = weapon; - newActiveWeapon.hand = hand; - - //ChangeWeapon( weapon, hand ); + SetNewActiveWeapon(weapon, hand); } void Sentient::EventUseWeaponClass(Event *ev) { - const char *name; - int weapon_class; + str name; + int weapon_class; if (deadflag) { return; @@ -1138,8 +1238,8 @@ void Sentient::PutawayWeapon(Event *ev) weapon = GetActiveWeapon(hand); - if (weapon->isSubclassOf(Weapon)) { - weapon->NewAnim("putaway"); + if (weapon->IsSubclassOfWeapon()) { + weapon->SetWeaponAnim("putaway"); } } @@ -1188,18 +1288,30 @@ Ammo *Sentient::FindAmmoByName(str name) for (i = 1; i <= count; i++) { Ammo *ammo = ammo_inventory.ObjectAt(i); - if (name == ammo->getName()) { + if (!str::icmp(name, ammo->getName())) { return ammo; } } return NULL; } -void Sentient::GetNewActiveWeapon(Event *ev) +void Sentient::GetNewActiveWeaponOld(Event *ev) +{ + ScriptDeprecatedAltVariable("newActiveWeapon"); + + ev->AddEntity(GetNewActiveWeapon()); +} + +void Sentient::GetNewActiveWeapon(Event* ev) { ev->AddEntity(GetNewActiveWeapon()); } +void Sentient::GetNewActiveWeaponHand(Event* ev) +{ + ev->AddInteger(GetNewActiveWeaponHand()); +} + void Sentient::GetActiveWeap(Event *ev) { weaponhand_t weaponhand; @@ -1216,3 +1328,11 @@ void Sentient::GetActiveWeap(Event *ev) ev->AddEntity(weapon); } + +const Container& Sentient::getInventory() const { + return inventory; +} + +const Container& Sentient::getAmmoInventory() const { + return ammo_inventory; +} diff --git a/code/fgame/simpleactor.cpp b/code/fgame/simpleactor.cpp index 3d1ce293..d4d407db 100644 --- a/code/fgame/simpleactor.cpp +++ b/code/fgame/simpleactor.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,1883 +25,1318 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actor.h" #include "bg_local.h" #include "scriptexception.h" +#include "scriptthread.h" +#include "../script/scriptclass.h" +#include "weapturret.h" #include -CLASS_DECLARATION( Sentient, SimpleActor, NULL ) -{ - { NULL, NULL } +Event EV_NoAnimLerp +( + "noanimlerp", + EV_DEFAULT, + NULL, + NULL, + "Do not LERP to the next animation", + EV_NORMAL +); + +CLASS_DECLARATION(Sentient, SimpleActor, NULL) { + {&EV_NoAnimLerp, &SimpleActor::EventNoAnimLerp}, + {NULL, NULL } }; -#define OVERLOADED_ERROR() assert( !"overloaded version should always get called" ) +#define OVERLOADED_ERROR() assert(!"overloaded version should always get called") SimpleActor::SimpleActor() { - if( LoadingSavegame ) - return; + m_ChangeMotionAnimIndex = -1; + m_ChangeActionAnimIndex = -1; + m_ChangeSayAnimIndex = -1; - m_AnimMotionHigh = true; - m_DesiredGunDir = vec_zero; - m_eEmotionMode = EMOTION_NEUTRAL; - m_eNextAnimMode = -1; - m_fPathGoalTime = 0.0f; - m_csPathGoalEndAnimScript = STRING_EMPTY; + if (LoadingSavegame) { + return; + } - m_AnimActionHigh = true; - m_AnimDialogHigh = true; - m_fAimLimit_up = 60.0f; - m_fAimLimit_down = -60.0f; + m_AnimMotionHigh = true; + m_AnimActionHigh = true; + m_AnimDialogHigh = true; - m_csNextAnimString = STRING_NULL; - m_bNextForceStart = false; - m_fCrossblendTime = 0.5f; - m_csCurrentPosition = STRING_STAND; - m_bStartPathGoalEndAnim = false; + m_fAimLimit_up = 60.0f; + m_fAimLimit_down = -60.0f; - for( int i = 0; i < MAX_FRAMEINFOS; i++ ) - { - m_weightType[ i ] = 0.0f; - } + VectorClear(m_DesiredGunDir); + VectorClear(m_DesiredLookAngles); + VectorClear(m_Dest); + VectorClear(m_NoClipDest); - m_bMotionAnimSet = false; - m_ChangeActionAnimIndex = -1; - m_ChangeActionAnimIndex = -1; - m_ChangeSayAnimIndex = -1; - m_iMotionSlot = -1; - m_iActionSlot = -1; - m_bActionAnimSet = false; - m_bSayAnimSet = false; - m_iVoiceTime = 0; - m_bAimAnimSet = false; - m_iSaySlot = -1; - m_bLevelMotionAnim = false; - m_bLevelActionAnim = false; - m_bLevelSayAnim = 0; - m_bNextLevelSayAnim = 0; - m_DesiredYaw = 0.0f; - m_YawAchieved = true; - m_bPathErrorTime = -10000000.0f; + for (int i = 0; i < MAX_FRAMEINFOS; i++) { + m_weightBase[i] = 0.0f; + m_weightCrossBlend[i] = 0.0f; + } - m_PainHandler.TrySetScript( STRING_ANIM_PAIN_SCR ); - m_DeathHandler.TrySetScript( STRING_ANIM_KILLED_SCR ); - m_AttackHandler.TrySetScript( STRING_ANIM_ATTACK_SCR ); - m_SniperHandler.TrySetScript( STRING_ANIM_SNIPER_SCR ); + m_eEmotionMode = EMOTION_NEUTRAL; + m_eNextAnimMode = -1; + m_csPathGoalEndAnimScript = STRING_EMPTY; + m_bNextForceStart = false; + m_fCrossblendTime = 0.5f; + m_csCurrentPosition = STRING_STAND; + m_fPathGoalTime = 0.0f; + m_bStartPathGoalEndAnim = false; + m_csNextAnimString = STRING_NULL; - m_bHasDesiredLookDest = false; - m_bUpdateAnimDoneFlags = false; + for (int i = 0; i < MAX_FRAMEINFOS; i++) { + m_weightType[i] = ANIM_WEIGHT_NONE; + } - m_NearestNode = NULL; - m_fCrouchWeight = 0.0f; + m_ChangeActionAnimIndex = -1; + m_ChangeActionAnimIndex = -1; + m_ChangeSayAnimIndex = -1; - m_csMood = STRING_BORED; - m_csIdleMood = STRING_BORED; + m_bMotionAnimSet = false; + m_bActionAnimSet = false; + m_bSayAnimSet = false; + m_iVoiceTime = 0; + m_bAimAnimSet = false; - m_groundPlane = qfalse; - m_walking = qfalse; - m_groundPlaneNormal = vec_zero; - m_maxspeed = 1000000.0f; + m_iMotionSlot = -1; + m_iActionSlot = -1; + m_iSaySlot = -1; + m_bLevelMotionAnim = false; + m_bLevelActionAnim = false; + m_bLevelSayAnim = false; + m_bNextLevelSayAnim = false; + m_DesiredYaw = 0.0f; + m_YawAchieved = true; + m_bPathErrorTime = -10000000; + + m_PainHandler.TrySetScript(STRING_ANIM_PAIN_SCR); + m_DeathHandler.TrySetScript(STRING_ANIM_KILLED_SCR); + m_AttackHandler.TrySetScript(STRING_ANIM_ATTACK_SCR); + m_SniperHandler.TrySetScript(STRING_ANIM_SNIPER_SCR); + + m_bHasDesiredLookDest = false; + m_bUpdateAnimDoneFlags = false; + + m_NearestNode = NULL; + m_fCrouchWeight = 0.0f; + + m_csMood = STRING_BORED; + m_csIdleMood = STRING_BORED; + + m_groundPlane = qfalse; + m_walking = qfalse; + VectorClear(m_groundPlaneNormal); + m_maxspeed = 1000000.0f; } -void SimpleActor::Archive - ( - Archiver& arc - ) +SimpleActor::~SimpleActor() { - Sentient::Archive( arc ); - - arc.ArchiveInteger( &m_eAnimMode ); - m_Anim.Archive( arc ); - - arc.ArchiveBool( &m_bHasDesiredLookDest ); - arc.ArchiveBool( &m_bHasDesiredLookAngles ); - arc.ArchiveVector( &m_vDesiredLookDest ); - arc.ArchiveVec3( m_DesiredLookAngles ); - arc.ArchiveVec3( m_DesiredGunDir ); - - m_Path.Archive( arc ); - arc.ArchiveVec3( m_Dest ); - arc.ArchiveVec3( m_NoClipDest ); - - arc.ArchiveFloat( &path_failed_time ); - arc.ArchiveFloat( &m_fPathGoalTime ); - arc.ArchiveBool( &m_bStartPathGoalEndAnim ); - Director.ArchiveString( arc, m_csPathGoalEndAnimScript ); - - arc.ArchiveInteger( &m_eNextAnimMode ); - Director.ArchiveString( arc, m_csNextAnimString ); - m_NextAnimLabel.Archive( arc ); - arc.ArchiveBool( &m_bNextForceStart ); - - arc.ArchiveBoolean( &m_walking ); - arc.ArchiveBoolean( &m_groundPlane ); - arc.ArchiveVec3( m_groundPlaneNormal ); - - arc.ArchiveVector( &watch_offset ); - arc.ArchiveBool( &m_bThink ); - arc.ArchiveInteger( &m_PainTime ); - - arc.ArchiveBool( &m_bAimAnimSet ); - arc.ArchiveBool( &m_bActionAnimSet ); - - Director.ArchiveString( arc, m_csMood ); - Director.ArchiveString( arc, m_csIdleMood ); - - ArchiveEnum(m_eEmotionMode, eEmotionMode); - - arc.ArchiveFloat( &m_fAimLimit_up ); - arc.ArchiveFloat( &m_fAimLimit_down ); - - for( int i = MAX_FRAMEINFOS - 1; i >= 0; i-- ) - { - arc.ArchiveUnsigned( &m_weightType[ i ] ); - } - - for( int i = MAX_FRAMEINFOS - 1; i >= 0; i-- ) - { - arc.ArchiveFloat( &m_weightBase[ i ] ); - } - - for( int i = MAX_FRAMEINFOS - 1; i >= 0; i-- ) - { - arc.ArchiveFloat( &m_weightCrossBlend[ i ] ); - } - - arc.ArchiveBool( &m_AnimMotionHigh ); - arc.ArchiveBool( &m_AnimActionHigh ); - arc.ArchiveBool( &m_AnimDialogHigh ); - - arc.ArchiveVec2( obstacle_vel ); - - Director.ArchiveString( arc, m_csCurrentPosition ); - - arc.ArchiveBool( &m_bMotionAnimSet ); - arc.ArchiveBool( &m_bDoAI ); - - arc.ArchiveFloat( &m_fCrossblendTime ); - - arc.ArchiveSafePointer( &m_pAnimThread ); - - arc.ArchiveBool( &m_YawAchieved ); - arc.ArchiveFloat( &m_DesiredYaw ); - - arc.ArchiveInteger( &m_iVoiceTime ); - arc.ArchiveBool( &m_bSayAnimSet ); - - arc.ArchiveInteger( &hit_obstacle_time ); - - Director.ArchiveString( arc, m_csAnimName ); - - arc.ArchiveInteger( &m_bPathErrorTime ); - arc.ArchiveInteger( &m_iMotionSlot ); - arc.ArchiveInteger( &m_iActionSlot ); - arc.ArchiveInteger( &m_iSaySlot ); - - arc.ArchiveBool( &m_bLevelMotionAnim ); - arc.ArchiveBool( &m_bLevelActionAnim ); - arc.ArchiveByte( &m_bLevelSayAnim ); - arc.ArchiveByte( &m_bNextLevelSayAnim ); - - Director.ArchiveString( arc, m_csSayAnim ); - Director.ArchiveString( arc, m_csUpperAnim ); - - m_PainHandler.Archive( arc ); - m_DeathHandler.Archive( arc ); - m_AttackHandler.Archive( arc ); - m_SniperHandler.Archive( arc ); - - arc.ArchiveObjectPointer( ( Class ** )&m_NearestNode ); - arc.ArchiveVector( &m_vNearestNodePos ); - - arc.ArchiveFloat( &m_fCrouchWeight ); - arc.ArchiveFloat( &m_maxspeed ); + if (m_pAnimThread) { + delete m_pAnimThread->GetScriptClass(); + } } -void SimpleActor::SetMoveInfo - ( - mmove_t * - ) +void SimpleActor::SetMoveInfo(mmove_t *) { - OVERLOADED_ERROR(); + OVERLOADED_ERROR(); } -void SimpleActor::GetMoveInfo -( -mmove_t * +void SimpleActor::GetMoveInfo(mmove_t *) +{ + OVERLOADED_ERROR(); +} + +bool SimpleActor::CanSeeFrom(vec3_t pos, Entity *ent) +{ + return false; +} + +bool SimpleActor::CanTarget(void) +{ + OVERLOADED_ERROR(); + return false; +} + +bool SimpleActor::IsImmortal(void) +{ + OVERLOADED_ERROR(); + return false; +} + +bool SimpleActor::DoesTheoreticPathExist(Vector vDestPos, float fMaxPath) +{ + return m_Path.DoesTheoreticPathExist(origin, vDestPos, this, fMaxPath, NULL, 0); +} + +void SimpleActor::SetPath( + Vector vDestPos, const char *description, int iMaxDirtyTime, float *vLeashHome, float fLeashDistSquared ) { - OVERLOADED_ERROR(); -} - -void SimpleActor::StopAnimating - ( - int slot - ) -{ - int index = 0; - - m_weightType[ slot ] = 0; - DoExitCommands( slot ); - - if( edict->s.frameInfo[ slot ].index || gi.TIKI_NumAnims( edict->tiki ) <= 1 ) - { - edict->s.frameInfo[ slot ].index = 0; - } - else - { - edict->s.frameInfo[ slot ].index = 1; - } - - animFlags[ slot ] = ANIM_LOOP | ANIM_NODELTA | ANIM_NOEXIT | ANIM_PAUSED; - edict->s.frameInfo[ slot ].weight = 0; - animtimes[ slot ] = 0; - animFlags[ slot ] = ( animFlags[ slot ] | ANIM_NODELTA ) & ~ANIM_FINISHED; -} - -void SimpleActor::AnimFinished - ( - int slot - ) -{ - assert( !DumpCallTrace("") ); -} - -bool SimpleActor::CanTarget - ( - void - ) -{ - OVERLOADED_ERROR(); - return false; -} - -bool SimpleActor::IsImmortal - ( - void - ) -{ - OVERLOADED_ERROR(); - return false; -} - -bool SimpleActor::DoesTheoreticPathExist - ( - Vector vDestPos, - float fMaxPath - ) -{ - return m_Path.DoesTheoreticPathExist( origin, vDestPos, this, fMaxPath, NULL, 0 ); -} - -void SimpleActor::SetPath - ( - Vector vDestPos, - const char *description, - int iMaxDirtyTime, - float *vLeashHome, - float fLeashDistSquared - ) -{ - if (!PathExists() - || ( ( level.inttime >= m_Path.Time() + iMaxDirtyTime - || m_Path.Complete(origin) ) - && PathGoal() != vDestPos) - ) - { - m_Path.FindPath(origin, - vDestPos, - this, - 0.0, - vLeashHome, - fLeashDistSquared); - - if (!PathExists()) - { - if (g_patherror->integer) - { - if (description) - { - int thinkState = ((Actor*)this)->m_ThinkState; - if (g_patherror->integer == 1 || (g_patherror->integer == 2 && (thinkState == THINKSTATE_IDLE || thinkState == THINKSTATE_CURIOUS))) - { - if (m_bPathErrorTime + 5000 < level.inttime) - { - m_bPathErrorTime = level.inttime; - Com_Printf( - "^~^~^ Path not found in '%s' for (entnum %d, radnum %d, targetname '%s') from (%f %f %f) to (%f %f %f)\n", - description, - entnum, - radnum, - targetname.c_str(), - origin.x, - origin.y, - origin.z, - vDestPos.x, - vDestPos.y, - vDestPos.z - ); - Com_Printf("Reason: %s\n", PathSearch::last_error); - } - } - } - } - } - } -} - -void SimpleActor::SetPath - ( - SimpleEntity *pDestNode, - const char *description, - int iMaxDirtyTime - ) -{ - if (pDestNode) - { - SetPath( - pDestNode->origin, - description, - iMaxDirtyTime, - NULL, - 0.0); - } - else - { - if (m_bPathErrorTime + 5000 < level.inttime) - { - m_bPathErrorTime = level.inttime; - Com_Printf( - "^~^~^ No destination node specified for '%s' at (%f %f %f)\n", - targetname.c_str(), - origin.x, - origin.y, - origin.z); - } - ClearPath(); - } -} - -void SimpleActor::SetPathWithinDistance - ( - Vector vDestPos, - char *description, - float fMaxPath, - int iMaxDirtyTime - ) -{ - SetPath(vDestPos, description, iMaxDirtyTime, NULL, 0); -} - -void SimpleActor::FindPathAway - ( - vec_t *vAwayFrom, - vec_t *vDirPreferred, - float fMinSafeDist - ) -{ - m_Path.FindPathAway(origin, vAwayFrom, vDirPreferred, this, fMinSafeDist, NULL, 0); - - ShortenPathToAvoidSquadMates(); -} - -void SimpleActor::ClearPath - ( - void - ) -{ - m_Path.Clear(); -} - -bool SimpleActor::PathComplete - ( - void - ) const -{ - if( level.time >= m_fPathGoalTime ) - { - if( m_Path.Complete( origin ) ) - return true; - } - - return false; -} - -bool SimpleActor::PathExists - ( - void - ) const -{ - return m_Path.CurrentNode() != NULL; -} - -bool SimpleActor::PathIsValid - ( - void - ) const -{ - //Called by SetPath... - return true; -} - -bool SimpleActor::PathAvoidsSquadMates - ( - void - ) const -{ - Entity* player; - float fDelta; - float fDistSoFar; - float fDistCap; - float vDelta2[2]; - float vMins[3]; - float vMaxs[3]; - float vPos[3]; - //Sentient *pOther; - Sentient *pBuddy[256]; - int iNumBuddies; - int i; - //float fRatio; - - if (ai_pathchecktime->value <= 0.0) - return true; - player = G_GetEntity(0); - if (!player) - { - return true; - } - - //player = G_GetEntity(0); - //player = G_GetEntity(0); - VectorSub2D(player->origin, origin, vDelta2); - if (VectorLength2D(vDelta2) > Square(ai_pathcheckdist->value)) - { - return true; - } - - fDistCap = (ai_pathchecktime->value * 250.0); - fDistSoFar = 0; - - VectorCopy(vMins, CurrentPathNode()->point); - VectorCopy(vMaxs, CurrentPathNode()->point); - PathInfo *pNode = CurrentPathNode() - 1; - - while (1) - { - if (pNode < LastPathNode()) - break; - - if (fDistSoFar <= fDistCap) - break; - - fDelta = fDistCap + 0.001 - fDistSoFar; - - if (pNode->dist < fDelta) - { - VectorCopy(pNode->point, vPos); - } - else - { - VectorSubtract(pNode[1].point, pNode[0].point, vPos); - VectorMA(pNode[1].point, fDelta / pNode->dist, vPos, vPos); - } - - if (vPos[0] > vMaxs[0]) - { - vMaxs[0] = vPos[0]; - } - else - { - if (vPos[0] < vMins[0] ) - { - vMins[0] = vPos[0]; - } - } - - if (vPos[1] > vMaxs[1]) - { - vMaxs[1] = vPos[1]; - } - else - { - if (vPos[1] < vMins[1]) - { - vMins[1] = vPos[1]; - } - } - - if (vPos[2] > vMaxs[2]) - { - vMaxs[2] = vPos[2]; - } - else - { - if (vPos[2] < vMins[2]) - { - vMins[2] = vPos[2]; - } - } - - fDistSoFar += fDelta; - pNode--; - } - - vMins[0] -= 30; - vMins[1] -= 30; - vMins[2] -= 94; - - vMaxs[0] += 30; - vMaxs[1] += 30; - vMaxs[2] += 94; - - iNumBuddies = 0; - if ((Sentient *)m_pNextSquadMate != this) - { - do - { - if (m_pNextSquadMate->origin[0] > vMins[0] && m_pNextSquadMate->origin[0] < vMaxs[0] - && m_pNextSquadMate->origin[1] > vMins[1] && m_pNextSquadMate->origin[1] < vMaxs[1] - && m_pNextSquadMate->origin[2] > vMins[2] && m_pNextSquadMate->origin[2] < vMaxs[2] - ) - { - VectorSub2D(m_pNextSquadMate->origin, origin, vDelta2); - if (vDelta2[0] <= -32 || vDelta2[0] >= 32 || vDelta2[1] <= -32 || vDelta2[1] >= 32) - { - if (DotProduct2D(vDelta2, m_pNextSquadMate->velocity) <= 0) - { - pBuddy[iNumBuddies++] = m_pNextSquadMate; - } - } - } - } while ((Sentient *)m_pNextSquadMate != this && iNumBuddies <= 255); - } - - if (iNumBuddies == 0) - { - return true; - } - float fDist; - while (1) - { - i = 0; - - if (iNumBuddies > 0) - break; -weird_lbl: - pNode++; - - VectorCopy2D(pNode->point, vPos); - fDist = pNode->dist; - - if (pNode >= CurrentPathNode()) - return true; - } - float fDot; - while (1) - { - VectorSub2D(pBuddy[i]->origin, vPos, vDelta2); - if (VectorLength2D(vDelta2) <= 900) - { - return false; - } - fDot = DotProduct2D(vDelta2, pNode->dir); - if (fDot < 0.0 && -fDist <= fDot) - { - if (Square(CrossProduct2D(vDelta2, pNode->dir)) <= 900) - { - return false; - } - } - if (++i >= iNumBuddies) - { - goto weird_lbl; - } - } -} - -void SimpleActor::ShortenPathToAvoidSquadMates - ( - void - ) -{ - if (PathExists() && !PathComplete()) - { - Vector vBuddyPos; - Vector vDelta; - Vector vGoal; - do - { - vGoal = PathGoal(); - Actor *pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); - if (pSquadMate == this) - { - break; - } - - while (true) - { - vGoal = PathGoal(); - vBuddyPos = pSquadMate->origin; - if (pSquadMate->IsSubclassOfActor() && pSquadMate->PathExists()) - { - vBuddyPos = pSquadMate->PathGoal(); - } - vDelta.x = vGoal[0] - vBuddyPos.x; - if (vDelta.x >= -15.0 && vDelta.x <= 15.0) - { - vDelta.y = vGoal[1] - vBuddyPos.y; - vDelta.z = vGoal[2] - vBuddyPos.z; - - if (vDelta.y >= -15.0 && vDelta.y <= 15.0 && vDelta.z >= 0.0 && vDelta.z <= 94.0) - break; - } - pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer(); - if (pSquadMate == this) - { - return; - } - } - m_Path.Shorten(45.0); - - } while (PathExists()); - } -} - -PathInfo *SimpleActor::CurrentPathNode - ( - void - ) const -{ - return m_Path.CurrentNode(); -} - -PathInfo *SimpleActor::LastPathNode - ( - void - ) const -{ - return m_Path.LastNode(); -} - -float SimpleActor::PathDist - ( - void - ) const -{ - return m_Path.TotalDist(); -} - -bool SimpleActor::PathHasCompleteLookahead - ( - void - ) const -{ - return m_Path.HasCompleteLookahead(); -} - -Vector SimpleActor::PathGoal - ( - void - ) const -{ - return LastPathNode()->point; -} + if (PathExists()) { + if (level.inttime < iMaxDirtyTime + m_Path.Time() && !m_Path.Complete(origin)) { + // Too soon + return; + } + + if (PathGoal() == vDestPos && PathIsValid()) { + // Still a valid path + return; + } + } + + m_Path.FindPath(origin, vDestPos, this, 0.0, vLeashHome, fLeashDistSquared); + + if (!PathExists()) { + if (!g_patherror->integer || !description) { + return; + } + + if (g_patherror->integer != 1 && g_patherror->integer != 2) { + return; + } + + if (g_patherror->integer == 2) { + int thinkState = static_cast(this)->m_ThinkState; + if (thinkState != THINKSTATE_IDLE && thinkState != THINKSTATE_CURIOUS) { + return; + } + } + + if (m_bPathErrorTime + 5000 >= level.inttime) { + return; + } + + m_bPathErrorTime = level.inttime; + + Com_Printf( + "^~^~^ Path not found in '%s' for (entnum %d, radnum %d, targetname '%s') from (%f %f " + "%f) to (%f %f %f)\n", + description, + entnum, + radnum, + targetname.c_str(), + origin.x, + origin.y, + origin.z, + vDestPos.x, + vDestPos.y, + vDestPos.z + ); + Com_Printf("Reason: %s\n", PathSearch::last_error); + } +} -float *SimpleActor::PathDelta - ( - void - ) const +void SimpleActor::SetPath(SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime) { - return m_Path.CurrentDelta(); + if (pDestNode) { + SetPath(pDestNode->origin, description, iMaxDirtyTime, NULL, 0.0); + return; + } + + if (m_bPathErrorTime + 5000 < level.inttime) { + m_bPathErrorTime = level.inttime; + Com_Printf( + "^~^~^ No destination node specified for '%s' at (%f %f %f)\n", + targetname.c_str(), + origin.x, + origin.y, + origin.z + ); + } + + ClearPath(); } -bool SimpleActor::PathGoalSlowdownStarted - ( - void - ) const -{ - return m_fPathGoalTime >= level.time; -} - -void SimpleActor::SetDest - ( - vec3_t dest - ) -{ - VectorCopy(dest, m_Dest); -} - -void SimpleActor::StopTurning - ( - void - ) -{ - m_YawAchieved = true; -} - -void SimpleActor::SetDesiredYaw - ( - float yaw - ) -{ - m_YawAchieved = false; - m_DesiredYaw = yaw; -} - -void SimpleActor::SetDesiredYawDir - ( - vec3_t vec - ) -{ - m_YawAchieved = false; - m_DesiredYaw = vectoyaw(vec); -} - -void SimpleActor::SetDesiredYawDest - ( - vec3_t vec - ) -{ - float facedir[2]; - VectorSub2D(vec, origin, facedir); - if (facedir[0] == 0 || facedir[1] == 0) - { - m_YawAchieved = false; - m_DesiredYaw = vectoyaw(vec); - } -} - -void SimpleActor::UpdateEmotion - ( - void - ) -{ - int anim; - if (IsDead()) - { - Anim_Emotion(EMOTION_DEAD); - } - - anim = GetEmotionAnim(); - - if (anim == -1) - { - Com_Printf( - "Failed to set emotion for (entnum %d, radnum %d, targetname '%s'\n", - entnum, - radnum, - targetname.c_str()); - } - else - { - m_bSayAnimSet = true; - StartSayAnimSlot(anim); - } -} - -int SimpleActor::GetEmotionAnim - ( - void - ) -{ - const char *emotionanim = NULL; - int anim; - - if (m_eEmotionMode) - { - switch (m_eEmotionMode) - { - case EMOTION_NEUTRAL: - case EMOTION_AIMING: - emotionanim = "facial_idle_neutral"; - break; - case EMOTION_WORRY: - emotionanim = "facial_idle_worry"; - break; - case EMOTION_PANIC: - emotionanim = "facial_idle_panic"; - break; - case EMOTION_FEAR: - emotionanim = "facial_idle_fear"; - break; - case EMOTION_DISGUST: - emotionanim = "facial_idle_disgust"; - break; - case EMOTION_ANGER: - emotionanim = "facial_idle_anger"; - break; - case EMOTION_DETERMINED: - case EMOTION_CURIOUS: - emotionanim = "facial_idle_determined"; - break; - case EMOTION_DEAD: - emotionanim = "facial_idle_dead"; - break; - default: - - char assertStr[16317] = { 0 }; - strcpy(assertStr, "\"Unknown value for m_EmotionMode in SimpleActor::GetEmotionAnim\"\n\tMessage: "); - Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); - assert(!assertStr); - return -1; - break; - } - } - else - { - if (m_csMood == STRING_NERVOUS) - { - emotionanim = "facial_idle_determined"; - } - else if (m_csMood <= STRING_NERVOUS) - { - if (m_csMood != STRING_BORED) - { - assert(!"Unknown value for m_csMood"); - return -1; - } - else - { - emotionanim = "facial_idle_neutral"; - } - - } - else if (m_csMood == STRING_CURIOUS) - { - emotionanim = "facial_idle_determined"; - } - else if (m_csMood != STRING_ALERT) - { - assert(!"Unknown value for m_csMood"); - return -1; - } - else - { - - } - } - - if (emotionanim == NULL) - { - emotionanim = "facial_idle_anger"; - //assert(!"Unexpected behaviour in SimpleActor::GetEmotionAnim"); - } - - anim = gi.Anim_NumForName(edict->tiki, emotionanim); - if (anim == -1) - Com_Printf( - "^~^~^ SimpleActor::GetEmotionAnim: unknown animation '%s' in '%s'\n", - emotionanim, - edict->tiki->a->name); - return anim; -} - -int SimpleActor::GetMotionSlot - ( - int slot - ) -{ - if( m_AnimMotionHigh ) - return slot + 3; - else - return slot; -} - -int SimpleActor::GetActionSlot - ( - int slot - ) -{ - if( m_AnimActionHigh ) - return slot + 9; - else - return slot + 6; -} - -int SimpleActor::GetSaySlot - ( - void - ) -{ - return m_AnimDialogHigh ? 13 : 12; -} - -void SimpleActor::StartCrossBlendAnimSlot - ( - int slot - ) -{ - if (m_weightType[slot] == 1) - { - m_weightType[slot] = 4; - } - else - { - if (m_weightType[slot] < 1) - return; - if (m_weightType[slot] == 6) - m_weightType[slot] = 5; - else - m_weightType[slot] = 3; - } - m_weightCrossBlend[slot] = 1.0; - m_weightBase[slot] = edict->s.frameInfo[slot].weight; +void SimpleActor::SetPathWithinDistance(Vector vDestPos, char *description, float fMaxPath, int iMaxDirtyTime) +{ + if (PathExists()) { + if (level.inttime < iMaxDirtyTime + m_Path.Time()) { + // Too soon + return; + } + + if (!m_Path.Complete(origin)) { + // The current path has not complete yet + return; + } + + if (PathGoal() == vDestPos && PathIsValid()) { + // Still a valid path + return; + } + } + + m_Path.FindPath(origin, vDestPos, this, fMaxPath, 0, 0); + + if (!PathExists()) { + if (g_patherror->integer && description + && (g_patherror->integer + || g_patherror->integer == 2 + && (static_cast(this)->m_ThinkState == THINKSTATE_IDLE + || static_cast(this)->m_ThinkState == THINKSTATE_CURIOUS) + && m_bPathErrorTime + 5000 < level.inttime)) { + m_bPathErrorTime = level.inttime; + + Com_Printf( + "^~^~^ Path not found in '%s' for '%s' from (%f %f %f) to (%f %f %f)\n", + description, + targetname.c_str(), + origin.x, + origin.y, + origin.z, + vDestPos.x, + vDestPos.y, + vDestPos.z + ); + Com_Printf("Reason: %s\n", PathSearch::last_error); + } + } +} + +void SimpleActor::FindPathAway(vec3_t vAwayFrom, vec2_t vDirPreferred, float fMinSafeDist) +{ + m_Path.FindPathAway(origin, vAwayFrom, vDirPreferred, this, fMinSafeDist, NULL, 0); + + ShortenPathToAvoidSquadMates(); +} + +void SimpleActor::ClearPath(void) +{ + m_Path.Clear(); +} + +bool SimpleActor::PathComplete(void) const +{ + if (level.time < m_fPathGoalTime) { + return false; + } + + return m_Path.Complete(origin); +} + +bool SimpleActor::PathExists(void) const +{ + return m_Path.CurrentNode() != NULL; +} + +bool SimpleActor::PathIsValid(void) const +{ + //Called by SetPath... + return true; +} + +bool SimpleActor::PathAvoidsSquadMates(void) const +{ + Entity *player; + float fDelta; + float fDistSoFar; + float fDistCap; + vec2_t vDelta2; + vec3_t vMins, vMaxs; + vec3_t vPos; + PathInfo *pNode; + Sentient *pOther; + Sentient *pBuddy[256]; + int iNumBuddies; + int i; + float fRatio; + + if (ai_pathchecktime->value <= 0.0) { + return true; + } + + player = static_cast(G_GetEntity(0)); + if (!player) { + return true; + } + + VectorSub2D(player->origin, origin, vDelta2); + if (VectorLength2D(vDelta2) > Square(ai_pathcheckdist->value)) { + return true; + } + + pNode = CurrentPathNode(); + VectorCopy(pNode->point, vMins); + VectorCopy(pNode->point, vMaxs); + + fDistCap = (ai_pathchecktime->value * 250.0); + fDistSoFar = 0; + + for (pNode = CurrentPathNode() - 1; pNode >= LastPathNode(); pNode--) { + if (fDistSoFar >= fDistCap) { + break; + } + + fDelta = fDistCap + 0.001 - fDistSoFar; + + if (fDelta > pNode->dist) { + VectorCopy(pNode->point, vPos); + } else { + VectorSubtract(pNode[1].point, pNode[0].point, vPos); + VectorMA(pNode[1].point, fDelta / pNode->dist, vPos, vPos); + } + + fDistSoFar += fDelta; + + for (i = 0; i < 3; i++) { + if (vMaxs[i] < vPos[i]) { + vMaxs[i] = vPos[i]; + } else if (vMins[i] > vPos[i]) { + vMins[i] = vPos[i]; + } + } + } + + vMins[0] -= 30; + vMins[1] -= 30; + vMins[2] -= 94; + + vMaxs[0] += 30; + vMaxs[1] += 30; + vMaxs[2] += 94; + + iNumBuddies = 0; + for (pOther = m_pNextSquadMate; pOther != this && iNumBuddies < ARRAY_LEN(pBuddy); + pOther = pOther->m_pNextSquadMate) { + if (vMins[0] >= pOther->origin[0] || pOther->origin[0] >= vMaxs[0]) { + continue; + } + if (vMins[1] >= pOther->origin[1] || pOther->origin[1] >= vMaxs[1]) { + continue; + } + if (vMins[2] >= pOther->origin[2] || pOther->origin[2] >= vMaxs[2]) { + continue; + } + + VectorSub2D(pOther->origin, origin, vDelta2); + if (vDelta2[0] <= -32 || vDelta2[0] >= 32 || vDelta2[1] <= -32 || vDelta2[1] >= 32) { + if (DotProduct2D(vDelta2, pOther->velocity) <= 0) { + pBuddy[iNumBuddies++] = pOther; + } + } + } + + if (!iNumBuddies) { + // No buddy, can safely avoid + return true; + } + + do { + for (i = 0; i < iNumBuddies; i++) { + VectorSub2D(pOther->origin, vPos, vDelta2); + + if (VectorLength2DSquared(vDelta2) <= 900) { + return false; + } + + fRatio = DotProduct2D(vDelta2, pNode->dir); + if (fRatio < 0 && fRatio >= -fDelta) { + vec2_t vInvDelta2 = {vDelta2[1], vDelta2[0]}; + + if (Square(DotProduct2D(vInvDelta2, pNode->dir)) <= 900) { + return false; + } + } + } + + pNode++; + + VectorCopy2D(pNode->point, vPos); + fDelta = pNode->dist; + } while (pNode < CurrentPathNode()); + + return true; } -void SimpleActor::StartMotionAnimSlot - ( - int slot, - int anim, - float weight - ) +void SimpleActor::ShortenPathToAvoidSquadMates(void) { - int iSlot = GetMotionSlot(slot); + if (!PathExists() || PathComplete()) { + return; + } - m_weightCrossBlend[iSlot] = 0.0; - m_weightType[iSlot] = 1; - m_weightBase[iSlot] = weight; + Vector vGoal; + Sentient *pBuddy; - NewAnim(anim, iSlot, 1.0); - animFlags[iSlot] |= ANIM_NOACTION; +retry: + vGoal = PathGoal(); - SetTime(iSlot, 0.0); + for (pBuddy = m_pNextSquadMate; pBuddy != this; pBuddy = pBuddy->m_pNextSquadMate) { + Vector vBuddyPos; + Vector vDelta; - UpdateNormalAnimSlot(iSlot); + vBuddyPos = pBuddy->origin; + if (pBuddy->IsSubclassOfActor()) { + Actor *pBuddyActor = static_cast(pBuddy); + if (pBuddyActor->PathExists()) { + vBuddyPos = pBuddyActor->PathGoal(); + } + } + + vDelta = vGoal - vBuddyPos; + + if (vDelta.x >= -15 && vDelta.x <= 15 && vDelta.y >= -15 && vDelta.y <= 15 && vDelta.z >= 0 && vDelta.z <= 94) { + m_Path.Shorten(45.0); + + if (!PathExists()) { + return; + } + + goto retry; + } + } } -void SimpleActor::StartAimMotionAnimSlot - ( - int slot, - int anim - ) +Vector SimpleActor::PathGoal(void) const { - int iSlot = GetMotionSlot(slot); + return m_Path.CurrentPathGoal(); +} - m_weightCrossBlend[iSlot] = 0.0; - m_weightType[iSlot] = 1; +bool SimpleActor::PathGoalSlowdownStarted(void) const +{ + return m_fPathGoalTime >= level.time; +} - NewAnim(anim, iSlot, 1.0); - animFlags[iSlot] |= ANIM_NOACTION; +const float *SimpleActor::PathDelta(void) const +{ + return m_Path.CurrentDelta(); +} - SetTime(iSlot, 0.0); +PathInfo *SimpleActor::CurrentPathNode(void) const +{ + return m_Path.CurrentNode(); +} - UpdateNormalAnimSlot(iSlot); +PathInfo *SimpleActor::LastPathNode(void) const +{ + return m_Path.LastNode(); } -void SimpleActor::StartActionAnimSlot - ( - int anim - ) +float SimpleActor::PathDist(void) const { - int iSlot = GetActionSlot(0); + return m_Path.TotalDist(); +} - m_weightCrossBlend[iSlot] = 0.0; - m_weightType[iSlot] = 2; - m_weightBase[iSlot] = 1.0; +bool SimpleActor::PathHasCompleteLookahead(void) const +{ + return m_Path.HasCompleteLookahead(); +} - NewAnim(anim, iSlot, 1.0); +void SimpleActor::UpdateEmotion(void) +{ + int anim; - SetTime(iSlot, 0.0); + if (deadflag != DEAD_NO) { + m_eEmotionMode = EMOTION_DEAD; + } - UpdateNormalAnimSlot(iSlot); + anim = GetEmotionAnim(); + + if (anim == -1) { + Com_Printf( + "Failed to set emotion for (entnum %d, radnum %d, targetname '%s'\n", entnum, radnum, TargetName().c_str() + ); + return; + } + + m_bSayAnimSet = true; + StartSayAnimSlot(anim); +} + +int SimpleActor::GetMotionSlot(int slot) +{ + if (m_AnimMotionHigh) { + return slot + 3; + } else { + return slot; + } } -void SimpleActor::StartSayAnimSlot - ( - int anim - ) +void SimpleActor::ChangeMotionAnim(void) { - int iSlot = GetSaySlot(); + int slot; + int lastMotionSlot; + int firstMotionSlot; + + m_bMotionAnimSet = false; + m_iMotionSlot = -1; + m_bLevelMotionAnim = false; + + if (m_ChangeMotionAnimIndex != level.frame_skel_index) { + m_ChangeMotionAnimIndex = level.frame_skel_index; + + firstMotionSlot = GetMotionSlot(0); + lastMotionSlot = firstMotionSlot + 3; + + MPrintf("Swapping motion channels....\n"); + for (slot = firstMotionSlot; slot < lastMotionSlot; slot++) { + StartCrossBlendAnimSlot(slot); + + // Added in 2.0 + // Don't lerp animations + if (edict->s.eFlags & EF_NO_LERP) { + m_weightCrossBlend[slot] = 0; + m_weightBase[slot] = 0; + // Next animation should lerp + edict->s.eFlags &= ~EF_NO_LERP; + } + } + + m_AnimMotionHigh = !m_AnimMotionHigh; + } - m_weightCrossBlend[iSlot] = 0.0; - m_weightType[iSlot] = 6; - m_weightBase[iSlot] = 1.0; + firstMotionSlot = GetMotionSlot(0); + lastMotionSlot = firstMotionSlot + 3; - NewAnim(anim, iSlot, 1.0); - animFlags[iSlot] |= ANIM_NOACTION; + for (slot = firstMotionSlot; slot < lastMotionSlot; slot++) { + StopAnimating(slot); + } +} - SetTime(iSlot, 0.0); - UpdateSayAnimSlot(iSlot); +int SimpleActor::GetActionSlot(int slot) +{ + if (m_AnimActionHigh) { + return slot + 9; + } else { + return slot + 6; + } } -void SimpleActor::StartAimAnimSlot - ( - int slot, - int anim - ) +void SimpleActor::ChangeActionAnim(void) { - int iSlot = GetActionSlot(slot); + int slot; + int firstActionSlot; + int lastActionSlot; + + m_bAimAnimSet = false; + m_bActionAnimSet = false; + m_iActionSlot = -1; + m_bLevelActionAnim = false; + + if (m_ChangeActionAnimIndex != level.frame_skel_index) { + m_ChangeActionAnimIndex = level.frame_skel_index; + + firstActionSlot = GetActionSlot(0); + lastActionSlot = firstActionSlot + 3; + + MPrintf("Swapping action channels....\n"); - m_weightCrossBlend[iSlot] = 0.0; - m_weightType[iSlot] = 7; + for (slot = firstActionSlot; slot < lastActionSlot; slot++) { + animFlags[slot] |= ANIM_NOACTION; + StartCrossBlendAnimSlot(slot); + } - NewAnim(anim, iSlot, 1.0); + m_AnimActionHigh = !m_AnimActionHigh; // toggle + } - SetTime(iSlot, 0.0); + firstActionSlot = GetActionSlot(0); + lastActionSlot = firstActionSlot + 3; - UpdateNormalAnimSlot(iSlot); + for (slot = firstActionSlot; slot < lastActionSlot; slot++) { + StopAnimating(slot); + } } -void SimpleActor::SetBlendedWeight - ( - int slot - ) +int SimpleActor::GetSaySlot(void) { - m_bUpdateAnimDoneFlags |= 1 << slot; - if (m_weightCrossBlend[slot] < 1.0) - { - edict->s.frameInfo[slot].weight = (3.0 - m_weightCrossBlend[slot] - m_weightCrossBlend[slot]) - * Square(m_weightCrossBlend[slot]) - * m_weightBase[slot]; - } - else - { - m_weightCrossBlend[slot] = 1.0; - edict->s.frameInfo[slot].weight = m_weightBase[slot]; - } + return m_AnimDialogHigh ? 13 : 12; } -void SimpleActor::EventSetAnimLength - ( - Event *ev - ) +void SimpleActor::ChangeSayAnim(void) { - int slot; - float length; - - if (ev->NumArgs() != 1) - { - ScriptError("bad number of arguments"); - } + m_bSayAnimSet = false; + m_iVoiceTime = level.inttime; + m_iSaySlot = -1; + m_bLevelSayAnim = false; - length = ev->GetFloat(1); + if (m_ChangeSayAnimIndex != level.frame_skel_index) { + m_ChangeSayAnimIndex = level.frame_skel_index; - if (length <= 0) - { - ScriptError("Positive lengths only allowed"); - } + MPrintf("Swapping dialog channel....\n"); - if (m_bMotionAnimSet) - { - ScriptError("Must set anim before length"); - } + StartCrossBlendAnimSlot(GetSaySlot()); - slot = GetMotionSlot(0); + m_AnimDialogHigh = !m_AnimDialogHigh; // toggle + } - if (animFlags[slot] & ANIM_LOOP) - { - gi.Anim_Frametime(edict->tiki, edict->s.frameInfo[slot].index); + StopAnimating(GetSaySlot()); +} - animFlags[slot] = (animFlags[slot] | ANIM_NODELTA) & ~ANIM_FINISHED; +void SimpleActor::StopAnimating(int slot) +{ + int index = 0; - animtimes[slot] = Square(gi.Anim_NumFrames(edict->tiki, edict->s.frameInfo[slot].index) - 1); + m_weightType[slot] = ANIM_WEIGHT_NONE; + DoExitCommands(slot); - SetOnceType(slot); - } + if (edict->s.frameInfo[slot].index || gi.TIKI_NumAnims(edict->tiki) <= 1) { + edict->s.frameInfo[slot].index = 0; + } else { + edict->s.frameInfo[slot].index = 1; + } - SetSyncTime(0); + animFlags[slot] = ANIM_LOOP | ANIM_NODELTA | ANIM_NOEXIT | ANIM_PAUSED; + SetWeight(slot, 0); - if (length > animtimes[slot]) - { - ScriptError("cannot lengthen animation which has length %f", animtimes[slot]); - } - - animtimes[slot] = length; - animFlags[slot] = (animFlags[slot] | ANIM_NODELTA) & ~ANIM_FINISHED; + animtimes[slot] = 0; + SlotChanged(slot); } -void SimpleActor::UpdateNormalAnimSlot - ( - int slot - ) +void SimpleActor::EventSetAnimLength(Event *ev) { - m_weightCrossBlend[slot] += m_fCrossblendTime == 0.0 ? 1.0 : level.frametime / m_fCrossblendTime; + int slot; + float length; + + if (ev->NumArgs() != 1) { + ScriptError("bad number of arguments"); + } + + length = ev->GetFloat(1); + + if (length <= 0) { + ScriptError("Positive lengths only allowed"); + } - SetBlendedWeight(slot); + if (!m_bMotionAnimSet) { + ScriptError("Must set anim before length"); + } + + slot = GetMotionSlot(0); + + if (IsRepeatType(slot) && edict->tiki) { + int numframes; + + numframes = gi.Anim_NumFrames(edict->tiki, edict->s.frameInfo[slot].index); + animtimes[slot] = gi.Anim_Frametime(edict->tiki, edict->s.frameInfo[slot].index) * numframes; + + SlotChanged(slot); + SetOnceType(slot); + } + + SetSyncTime(0); + + if (length > animtimes[slot]) { + ScriptError("cannot lengthen animation which has length %f", animtimes[slot]); + } + + animtimes[slot] = length; + SlotChanged(slot); } -void SimpleActor::UpdateCrossBlendAnimSlot - ( - int slot - ) -{ - m_weightCrossBlend[slot] -= m_fCrossblendTime == 0.0 ? 1.0 : level.frametime / m_fCrossblendTime; +void SimpleActor::EventSetCrossblendTime(Event *ev) +{ + m_fCrossblendTime = ev->GetFloat(1); +} - if (m_weightCrossBlend[slot] > 0.0) - { - SetBlendedWeight(slot); - } - else - { - m_weightType[slot] = 8; - edict->s.frameInfo[slot].weight = 0.0; - } -} - -void SimpleActor::UpdateCrossBlendDialogAnimSlot - ( - int slot - ) -{ - m_weightCrossBlend[slot] -= m_iSaySlot < 0 ? level.frametime + level.frametime : level.frametime / 0.1; - - if (m_weightCrossBlend[slot] > 0.0) - { - SetBlendedWeight(slot); - } - else - { - m_weightType[slot] = 8; - edict->s.frameInfo[slot].weight = 0.0; - } -} - -void SimpleActor::UpdateSayAnimSlot - ( - int slot - ) -{ - m_weightCrossBlend[slot] += m_iSaySlot < 0 ? level.frametime + level.frametime : level.frametime / 0.1; - - SetBlendedWeight(slot); -} - -void SimpleActor::UpdateLastFrameSlot - ( - int slot - ) -{ - StopAnimating(slot); +void SimpleActor::EventGetCrossblendTime(Event *ev) +{ + ev->AddFloat(m_fCrossblendTime); } -void SimpleActor::UpdateAnimSlot - ( - int slot - ) -{ - int weightType = m_weightType[slot]; - switch (weightType) - { - case 0: - break; - case 1: - case 2: - case 7: - UpdateNormalAnimSlot(slot); - break; - case 3: - case 4: - UpdateCrossBlendAnimSlot(slot); - break; - case 5: - UpdateCrossBlendDialogAnimSlot(slot); - break; - case 6: - UpdateSayAnimSlot(slot); - break; - case 8: - UpdateLastFrameSlot(slot); - break; - default: - assert(weightType && !"impleActor::UpdateAnimSlot: Bad weight type."); - break; - } -} - -void SimpleActor::StopAllAnimating - ( - void - ) -{ - SetSyncTime(0); - - for (int slot = 0; slot < MAX_FRAMEINFOS; slot++) - { - StopAnimating(slot); - } -} - -void SimpleActor::ChangeMotionAnim - ( - void - ) -{ - //int lastMotionSlot; - //int firstMotionSlot; - int iSlot; - int i; - - m_bMotionAnimSet = false; - m_iMotionSlot = -1; - m_bLevelMotionAnim = false; - - if (m_ChangeMotionAnimIndex != level.frame_skel_index) - { - m_ChangeMotionAnimIndex = level.frame_skel_index; - - MPrintf("Swapping motion channels....\n"); - for (iSlot = GetMotionSlot(0), i = 0; i < 3; i++, iSlot++) - { - StartCrossBlendAnimSlot(iSlot); - } - m_AnimDialogHigh = !m_AnimDialogHigh; - - } - - for (iSlot = GetMotionSlot(0), i = 0; i < 3; i++, iSlot++) - { - StopAnimating(iSlot); - } -} - -void SimpleActor::ChangeActionAnim - ( - void - ) -{ - int iSlot; - int i; - - m_bAimAnimSet = false; - m_bActionAnimSet = false; - m_iActionSlot = -1; - m_bLevelActionAnim = false; - - - if (m_ChangeActionAnimIndex != level.frame_skel_index) - { - m_ChangeActionAnimIndex = level.frame_skel_index; - - MPrintf("Swapping action channels....\n"); - - iSlot = GetActionSlot(0); - for (i = iSlot; i < iSlot + 3; i++) - { - animFlags[i] |= ANIM_NOACTION; - StartCrossBlendAnimSlot(i); - } - m_AnimDialogHigh = !m_AnimDialogHigh; // toggle - } - - iSlot = GetActionSlot(0); - for (i = iSlot; i < iSlot + 3; i++) - { - StopAnimating(iSlot); - } -} - -void SimpleActor::ChangeSayAnim - ( - void - ) -{ - int iSlot; - - m_bSayAnimSet = false; - m_bLevelSayAnim = 0; - m_iVoiceTime = level.inttime; - m_iSaySlot = -1; +void SimpleActor::StartCrossBlendAnimSlot(int slot) +{ + if (m_weightType[slot] == ANIM_WEIGHT_NONE) { + return; + } - if (m_ChangeSayAnimIndex != level.frame_skel_index) - { - m_ChangeSayAnimIndex = level.frame_skel_index; - - MPrintf("Swapping dialog channel....\n"); - - iSlot = GetSaySlot(); - StartCrossBlendAnimSlot(iSlot); + switch (m_weightType[slot]) { + case ANIM_WEIGHT_MOTION: + m_weightType[slot] = ANIM_WEIGHT_CROSSBLEND_2; + break; + case ANIM_WEIGHT_SAY: + m_weightType[slot] = ANIM_WEIGHT_CROSSBLEND_DIALOG; + break; + default: + m_weightType[slot] = ANIM_WEIGHT_CROSSBLEND_1; + break; + } - m_AnimDialogHigh = !m_AnimDialogHigh; // toggle - } + m_weightCrossBlend[slot] = 1.0; + m_weightBase[slot] = GetWeight(slot); +} + +void SimpleActor::StartMotionAnimSlot(int slot, int anim, float weight) +{ + slot = GetMotionSlot(slot); - iSlot = GetSaySlot(); - StopAnimating(iSlot); -} - -void SimpleActor::UpdateAim - ( - void - ) -{ - float dir; - - int aimForwardSlot; - int aimUpSlot; - int aimDownSlot; - - if (m_bAimAnimSet) - { - dir = AngleNormalize180(-m_DesiredGunDir[0]); - - aimForwardSlot = GetActionSlot(0); - aimUpSlot = aimForwardSlot + 1; - aimDownSlot = aimForwardSlot + 2; - - - float factor; - if (dir < 0) - { - if (dir < m_fAimLimit_down) - dir = m_fAimLimit_down; - - factor = dir / m_fAimLimit_down; - - m_weightBase[aimForwardSlot] = 0; - m_weightBase[aimUpSlot] = 1 - factor; - m_weightBase[aimDownSlot] = factor; - } - else - { - if (dir > m_fAimLimit_up) - dir = m_fAimLimit_up; - - factor = dir / m_fAimLimit_up; - - m_weightBase[aimForwardSlot] = factor; - m_weightBase[aimUpSlot] = 1 - factor; - m_weightBase[aimDownSlot] = 0; - - } - SetControllerAngles(TORSO_TAG, vec_origin); - } -} - -void SimpleActor::UpdateAimMotion - ( - void - ) -{ - int slot = GetMotionSlot(0); - - if (m_fCrouchWeight < 0.0) - { - m_weightBase[slot] = 0.0; - m_weightBase[slot + 1] = m_fCrouchWeight + 1.0; - m_weightBase[slot + 2] = -m_fCrouchWeight; - } - else - { - m_weightBase[slot] = m_fCrouchWeight; - m_weightBase[slot + 1] = 1.0 - m_fCrouchWeight; - m_weightBase[slot + 2] = 0.0; - } -} - -void SimpleActor::EventAIOn - ( - Event *ev - ) -{ - m_bDoAI = true; -} - -void SimpleActor::EventAIOff - ( - Event *ev - ) -{ - m_bDoAI = false; -} - -void SimpleActor::EventGetWeaponGroup - ( - Event *ev - ) -{ - const_str csWeaponGroup; - Weapon *weapon = GetActiveWeapon(WEAPON_MAIN); - if (!weapon) - { - csWeaponGroup = STRING_UNARMED; - } - else - { - csWeaponGroup = weapon->GetWeaponGroup(); - if (csWeaponGroup == STRING_EMPTY) - { - csWeaponGroup = STRING_UNARMED; - } - } - ev->AddConstString(csWeaponGroup); -} - -void SimpleActor::EventGetWeaponType - ( - Event *ev - ) -{ - Weapon *weapon; - const_str csWeaponType; - - if (!m_pTurret) - { - weapon = GetActiveWeapon(WEAPON_MAIN); - } - - if (!weapon) - { - csWeaponType = STRING_RIFLE; - } - else - { - int iWeaponClass = weapon->GetWeaponClass(); - - switch (iWeaponClass) - { - case WEAPON_CLASS_PISTOL: - csWeaponType = STRING_PISTOL; - break; - case WEAPON_CLASS_RIFLE: - csWeaponType = STRING_RIFLE; - break; - case WEAPON_CLASS_SMG: - csWeaponType = STRING_SMG; - break; - case WEAPON_CLASS_MG: - csWeaponType = STRING_MG; - break; - case WEAPON_CLASS_GRENADE: - csWeaponType = STRING_GRENADE; - break; - case WEAPON_CLASS_HEAVY: - csWeaponType = STRING_HEAVY; - break; - case WEAPON_CLASS_CANNON: - csWeaponType = STRING_CANNON; - break; - case WEAPON_CLASS_ITEM: - csWeaponType = STRING_ITEM; - break; - case WEAPON_CLASS_ITEM2: - csWeaponType = STRING_ITEM2; - break; - case WEAPON_CLASS_ITEM3: - csWeaponType = STRING_ITEM3; - break; - case WEAPON_CLASS_ITEM4: - csWeaponType = STRING_ITEM4; - break; - default: - csWeaponType = STRING_EMPTY; - break; - } - - } - - ev->AddConstString(csWeaponType); -} - -void SimpleActor::EventGetPainHandler - ( - Event *ev - ) -{ - ScriptVariable var; - - m_PainHandler.GetScriptValue(&var); - - ev->AddValue(var); -} - -void SimpleActor::EventSetPainHandler - ( - Event *ev - ) -{ - if (ev->IsFromScript()) - { - ScriptVariable var = ev->GetValue(1); - - m_PainHandler.SetScript(var); - } - else - { - str varString = ev->GetString(1); - m_PainHandler.SetScript(varString); - } -} - -void SimpleActor::EventGetDeathHandler - ( - Event *ev - ) -{ - ScriptVariable var; - - m_DeathHandler.GetScriptValue(&var); - - ev->AddValue(var); -} - -void SimpleActor::EventSetDeathHandler - ( - Event *ev - ) -{ - if (ev->IsFromScript()) - { - ScriptVariable var = ev->GetValue(1); - - m_DeathHandler.SetScript(var); - } - else - { - str varString = ev->GetString(1); - m_DeathHandler.SetScript(varString); - } -} - -void SimpleActor::EventGetAttackHandler - ( - Event *ev - ) -{ - ScriptVariable var; - - m_AttackHandler.GetScriptValue(&var); - - ev->AddValue(var); -} - -void SimpleActor::EventSetAttackHandler - ( - Event *ev - ) -{ - if (ev->IsFromScript()) - { - ScriptVariable var = ev->GetValue(1); - - m_AttackHandler.SetScript(var); - } - else - { - str varString = ev->GetString(1); - m_AttackHandler.SetScript(varString); - } -} + m_weightType[slot] = ANIM_WEIGHT_MOTION; + m_weightCrossBlend[slot] = 0.0; + m_weightBase[slot] = weight; + NewAnim(anim, slot, 1.0); + + animFlags[slot] |= ANIM_NOACTION; + RestartAnimSlot(slot); + UpdateNormalAnimSlot(slot); +} -void SimpleActor::EventGetSniperHandler - ( - Event *ev - ) +void SimpleActor::StartAimMotionAnimSlot(int slot, int anim) { - ScriptVariable var; + slot = GetMotionSlot(slot); - m_SniperHandler.GetScriptValue(&var); + m_weightType[slot] = ANIM_WEIGHT_MOTION; + m_weightCrossBlend[slot] = 0.0; + NewAnim(anim, slot, 1.0); - ev->AddValue(var); -} - -void SimpleActor::EventSetSniperHandler - ( - Event *ev - ) + animFlags[slot] |= ANIM_NOACTION; + RestartAnimSlot(slot); + UpdateNormalAnimSlot(slot); +} + +void SimpleActor::StartActionAnimSlot(int anim) { - if (ev->IsFromScript()) - { - ScriptVariable var = ev->GetValue(1); + int slot = GetActionSlot(0); + + m_weightType[slot] = ANIM_WEIGHT_ACTION; + m_weightCrossBlend[slot] = 0.0; + m_weightBase[slot] = 1.0; + NewAnim(anim, slot, 1.0); - m_SniperHandler.SetScript(var); - } - else - { - str varString = ev->GetString(1); - m_SniperHandler.SetScript(varString); - } + RestartAnimSlot(slot); + UpdateNormalAnimSlot(slot); } -void SimpleActor::EventSetCrossblendTime - ( - Event *ev - ) +void SimpleActor::StartSayAnimSlot(int anim) { - m_fCrossblendTime = ev->GetFloat(1); + int slot = GetSaySlot(); + + m_weightType[slot] = ANIM_WEIGHT_SAY; + m_weightCrossBlend[slot] = 0.0; + m_weightBase[slot] = 1.0; + NewAnim(anim, slot, 1.0); + + animFlags[slot] |= ANIM_NOACTION; + RestartAnimSlot(slot); + UpdateNormalAnimSlot(slot); } -void SimpleActor::EventGetCrossblendTime - ( - Event *ev - ) +void SimpleActor::StartAimAnimSlot(int slot, int anim) { - ev->AddFloat(m_fCrossblendTime); + slot = GetActionSlot(slot); + + m_weightType[slot] = ANIM_WEIGHT_AIM; + m_weightCrossBlend[slot] = 0.0; + NewAnim(anim, slot, 1.0); + + RestartAnimSlot(slot); + UpdateNormalAnimSlot(slot); +} + +void SimpleActor::SetBlendedWeight(int slot) +{ + m_bUpdateAnimDoneFlags |= 1 << slot; + + if (m_weightCrossBlend[slot] < 1.0) { + float w; + + w = (3.0 - m_weightCrossBlend[slot] - m_weightCrossBlend[slot]) * Square(m_weightCrossBlend[slot]); + SetWeight(slot, m_weightBase[slot] * w); + } else { + m_weightCrossBlend[slot] = 1.0; + SetWeight(slot, m_weightBase[slot]); + } +} + +void SimpleActor::UpdateNormalAnimSlot(int slot) +{ + if (m_fCrossblendTime) { + m_weightCrossBlend[slot] += level.frametime / m_fCrossblendTime; + } else { + m_weightCrossBlend[slot] += 1.f; + } + SetBlendedWeight(slot); +} + +void SimpleActor::UpdateCrossBlendAnimSlot(int slot) +{ + if (m_fCrossblendTime) { + m_weightCrossBlend[slot] -= level.frametime / m_fCrossblendTime; + } else { + m_weightCrossBlend[slot] -= 1.f; + } + + if (m_weightCrossBlend[slot] > 0) { + SetBlendedWeight(slot); + } else { + m_weightType[slot] = ANIM_WEIGHT_LASTFRAME; + SetWeight(slot, 0); + } +} + +void SimpleActor::UpdateCrossBlendDialogAnimSlot(int slot) +{ + if (m_iSaySlot >= 0) { + m_weightCrossBlend[slot] -= level.frametime / 0.1f; + } else { + m_weightCrossBlend[slot] -= level.frametime / 0.5f; + } + + if (m_weightCrossBlend[slot] > 0.0) { + SetBlendedWeight(slot); + } else { + m_weightType[slot] = ANIM_WEIGHT_LASTFRAME; + SetWeight(slot, 0); + } +} + +void SimpleActor::UpdateSayAnimSlot(int slot) +{ + if (m_iSaySlot >= 0) { + m_weightCrossBlend[slot] += level.frametime / 0.1f; + } else { + m_weightCrossBlend[slot] += level.frametime / 0.5f; + } + + SetBlendedWeight(slot); +} + +void SimpleActor::UpdateLastFrameSlot(int slot) +{ + StopAnimating(slot); +} + +void SimpleActor::UpdateAnimSlot(int slot) +{ + switch (m_weightType[slot]) { + case ANIM_WEIGHT_NONE: + break; + case ANIM_WEIGHT_MOTION: + case ANIM_WEIGHT_ACTION: + case ANIM_WEIGHT_AIM: + UpdateNormalAnimSlot(slot); + break; + case ANIM_WEIGHT_CROSSBLEND_1: + case ANIM_WEIGHT_CROSSBLEND_2: + UpdateCrossBlendAnimSlot(slot); + break; + case ANIM_WEIGHT_CROSSBLEND_DIALOG: + UpdateCrossBlendDialogAnimSlot(slot); + break; + case ANIM_WEIGHT_SAY: + UpdateSayAnimSlot(slot); + break; + case ANIM_WEIGHT_LASTFRAME: + UpdateLastFrameSlot(slot); + break; + default: + assert(!"SimpleActor::UpdateAnimSlot: Bad weight type."); + break; + } +} + +void SimpleActor::StopAllAnimating(void) +{ + SetSyncTime(0); + + for (int slot = 0; slot < MAX_FRAMEINFOS; slot++) { + StopAnimating(slot); + } +} + +void SimpleActor::UpdateAim(void) +{ + int aimUpSlot; + int aimForwardSlot; + int aimDownSlot; + float dir; + + if (m_bAimAnimSet) { + aimForwardSlot = GetActionSlot(0); + aimUpSlot = aimForwardSlot + 1; + aimDownSlot = aimForwardSlot + 2; + dir = -m_DesiredGunDir[0]; + + if (dir > 180) { + dir -= 360; + } else if (dir < -180) { + dir += 360; + } + + if (dir < 0) { + if (dir < m_fAimLimit_down) { + dir = m_fAimLimit_down; + } + + m_weightBase[aimForwardSlot] = 0; + m_weightBase[aimUpSlot] = 1 - dir / m_fAimLimit_down; + m_weightBase[aimDownSlot] = dir / m_fAimLimit_down; + } else { + if (dir > m_fAimLimit_up) { + dir = m_fAimLimit_up; + } + + m_weightBase[aimForwardSlot] = dir / m_fAimLimit_up; + m_weightBase[aimUpSlot] = 1 - dir / m_fAimLimit_up; + m_weightBase[aimDownSlot] = 0; + } + + SetControllerAngles(TORSO_TAG, vec_origin); + } +} + +void SimpleActor::UpdateAimMotion(void) +{ + if (m_fCrouchWeight < 0.0) { + m_weightBase[GetMotionSlot(0)] = 0.0; + m_weightBase[GetMotionSlot(1)] = m_fCrouchWeight + 1.0; + m_weightBase[GetMotionSlot(2)] = -m_fCrouchWeight; + } else { + m_weightBase[GetMotionSlot(0)] = m_fCrouchWeight; + m_weightBase[GetMotionSlot(1)] = 1.0 - m_fCrouchWeight; + m_weightBase[GetMotionSlot(2)] = 0.0; + } +} + +void SimpleActor::EventGetPosition(Event *ev) +{ + ev->AddConstString(m_csCurrentPosition); +} + +void SimpleActor::EventSetPosition(Event *ev) +{ + m_csCurrentPosition = ev->GetConstString(1); +} + +void SimpleActor::EventSetEmotion(Event *ev) +{ + switch (ev->GetConstString(1)) { + case STRING_EMOTION_NONE: + Anim_Emotion(EMOTION_NONE); + break; + case STRING_EMOTION_NEUTRAL: + Anim_Emotion(EMOTION_NEUTRAL); + break; + case STRING_EMOTION_WORRY: + Anim_Emotion(EMOTION_WORRY); + break; + case STRING_EMOTION_PANIC: + Anim_Emotion(EMOTION_PANIC); + break; + case STRING_EMOTION_FEAR: + Anim_Emotion(EMOTION_FEAR); + break; + case STRING_EMOTION_DISGUST: + Anim_Emotion(EMOTION_DISGUST); + break; + case STRING_EMOTION_ANGER: + Anim_Emotion(EMOTION_ANGER); + break; + case STRING_EMOTION_AIMING: + Anim_Emotion(EMOTION_AIMING); + break; + case STRING_EMOTION_DETERMINED: + Anim_Emotion(EMOTION_DETERMINED); + break; + case STRING_EMOTION_DEAD: + Anim_Emotion(EMOTION_DEAD); + break; + case STRING_EMOTION_CURIOUS: + Anim_Emotion(EMOTION_CURIOUS); + break; + default: + assert(!"Unknown emotion mode specified in script."); + break; + } +} + +int SimpleActor::GetEmotionAnim(void) +{ + const char *emotionanim = NULL; + int anim; + + if (m_eEmotionMode) { + switch (m_eEmotionMode) { + case EMOTION_NEUTRAL: + emotionanim = "facial_idle_neutral"; + break; + case EMOTION_WORRY: + emotionanim = "facial_idle_worry"; + break; + case EMOTION_PANIC: + emotionanim = "facial_idle_panic"; + break; + case EMOTION_FEAR: + emotionanim = "facial_idle_fear"; + break; + case EMOTION_DISGUST: + emotionanim = "facial_idle_disgust"; + break; + case EMOTION_ANGER: + emotionanim = "facial_idle_anger"; + break; + case EMOTION_AIMING: + emotionanim = "facial_idle_neutral"; + break; + case EMOTION_DETERMINED: + emotionanim = "facial_idle_determined"; + break; + case EMOTION_DEAD: + emotionanim = "facial_idle_dead"; + break; + case EMOTION_CURIOUS: + emotionanim = "facial_idle_determined"; + break; + default: + + char assertStr[16317] = {0}; + Q_strncpyz(assertStr, "\"Unknown value for m_EmotionMode in SimpleActor::GetEmotionAnim\"\n\tMessage: ", sizeof(assertStr)); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); + assert(!assertStr); + return -1; + break; + } + } else { + switch (m_csMood) { + case STRING_NERVOUS: + emotionanim = "facial_idle_determined"; + break; + case STRING_CURIOUS: + emotionanim = "facial_idle_determined"; + break; + case STRING_ALERT: + emotionanim = "facial_idle_anger"; + break; + case STRING_BORED: + emotionanim = "facial_idle_neutral"; + break; + default: + + char assertStr[16317] = {0}; + Q_strncpyz(assertStr, "\"Unknown value for m_csMood in SimpleActor::GetEmotionAnim\"\n\tMessage: ", sizeof(assertStr)); + Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("")); + assert(!assertStr); + return -1; + break; + } + } + + assert(emotionanim); + + anim = gi.Anim_NumForName(edict->tiki, emotionanim); + if (anim == -1) { + Com_Printf( + "^~^~^ SimpleActor::GetEmotionAnim: unknown animation '%s' in '%s'\n", emotionanim, edict->tiki->a->name + ); + } + return anim; +} + +void SimpleActor::EventSetAnimFinal(Event *ev) +{ + ScriptError("animfinal is obsolete"); +} + +void SimpleActor::EventGetWeaponType(Event *ev) +{ + Weapon *weapon; + const_str csWeaponType; + + if (m_pTurret) { + weapon = m_pTurret; + } else { + weapon = GetActiveWeapon(WEAPON_MAIN); + } + + if (weapon) { + switch (weapon->GetWeaponClass()) { + case WEAPON_CLASS_PISTOL: + csWeaponType = STRING_PISTOL; + break; + case WEAPON_CLASS_RIFLE: + csWeaponType = STRING_RIFLE; + break; + case WEAPON_CLASS_SMG: + csWeaponType = STRING_SMG; + break; + case WEAPON_CLASS_MG: + csWeaponType = STRING_MG; + break; + case WEAPON_CLASS_GRENADE: + csWeaponType = STRING_GRENADE; + break; + case WEAPON_CLASS_HEAVY: + csWeaponType = STRING_HEAVY; + break; + case WEAPON_CLASS_CANNON: + csWeaponType = STRING_CANNON; + break; + case WEAPON_CLASS_ITEM: + csWeaponType = STRING_ITEM; + break; + case WEAPON_CLASS_ITEM2: + csWeaponType = STRING_ITEM2; + break; + case WEAPON_CLASS_ITEM3: + csWeaponType = STRING_ITEM3; + break; + case WEAPON_CLASS_ITEM4: + csWeaponType = STRING_ITEM4; + break; + default: + csWeaponType = STRING_EMPTY; + break; + } + } else { + csWeaponType = STRING_RIFLE; + } + + ev->AddConstString(csWeaponType); +} + +void SimpleActor::EventGetWeaponGroup(Event *ev) +{ + const_str csWeaponGroup; + Weapon *weapon = GetActiveWeapon(WEAPON_MAIN); + + if (weapon) { + csWeaponGroup = weapon->GetWeaponGroup(); + if (csWeaponGroup == STRING_EMPTY) { + csWeaponGroup = STRING_UNARMED; + } + } else { + csWeaponGroup = STRING_UNARMED; + } + + ev->AddConstString(csWeaponGroup); +} + +void SimpleActor::EventAIOn(Event *ev) +{ + m_bDoAI = true; +} + +void SimpleActor::EventAIOff(Event *ev) +{ + m_bDoAI = false; +} + +void SimpleActor::AnimFinished(int slot) +{ + assert(!DumpCallTrace("\"never should be called\"\n\tMessage: ")); } -void SimpleActor::EventSetEmotion - ( - Event *ev - ) +void SimpleActor::EventGetPainHandler(Event *ev) { - switch (ev->GetConstString(1)) - { - case STRING_EMOTION_NONE: - Anim_Emotion(EMOTION_NONE); - break; - case STRING_EMOTION_NEUTRAL: - Anim_Emotion(EMOTION_NEUTRAL); - break; - case STRING_EMOTION_WORRY: - Anim_Emotion(EMOTION_WORRY); - break; - case STRING_EMOTION_PANIC: - Anim_Emotion(EMOTION_PANIC); - break; - case STRING_EMOTION_FEAR: - Anim_Emotion(EMOTION_FEAR); - break; - case STRING_EMOTION_DISGUST: - Anim_Emotion(EMOTION_DISGUST); - break; - case STRING_EMOTION_ANGER: - Anim_Emotion(EMOTION_ANGER); - break; - case STRING_EMOTION_AIMING: - Anim_Emotion(EMOTION_AIMING); - break; - case STRING_EMOTION_DETERMINED: - Anim_Emotion(EMOTION_DETERMINED); - break; - case STRING_EMOTION_DEAD: - Anim_Emotion(EMOTION_DEAD); - break; - case STRING_EMOTION_CURIOUS: - Anim_Emotion(EMOTION_CURIOUS); - break; - default: - assert(!"Unknown emotion mode specified in script."); - break; - } -} - -void SimpleActor::EventGetPosition - ( - Event *ev - ) + ScriptVariable var; + + m_PainHandler.GetScriptValue(&var); + ev->AddValue(var); +} + +void SimpleActor::EventSetPainHandler(Event *ev) +{ + if (ev->IsFromScript()) { + m_PainHandler.SetScript(ev->GetValue(1)); + } else { + m_PainHandler.SetScript(ev->GetString(1)); + } +} + +void SimpleActor::EventGetDeathHandler(Event *ev) +{ + ScriptVariable var; + + m_DeathHandler.GetScriptValue(&var); + ev->AddValue(var); +} + +void SimpleActor::EventSetDeathHandler(Event *ev) +{ + if (ev->IsFromScript()) { + m_DeathHandler.SetScript(ev->GetValue(1)); + } else { + m_DeathHandler.SetScript(ev->GetString(1)); + } +} + +void SimpleActor::EventGetAttackHandler(Event *ev) { - ev->AddConstString(m_csCurrentPosition); + ScriptVariable var; + + m_AttackHandler.GetScriptValue(&var); + ev->AddValue(var); } - -void SimpleActor::EventSetPosition - ( - Event *ev - ) -{ - m_csCurrentPosition = ev->GetConstString(1); -} - -void SimpleActor::EventGetAnimMode - ( - Event *ev - ) -{ - // not found in ida -} - -void SimpleActor::EventSetAnimMode - ( - Event *ev - ) -{ - // not found in ida -} - -void SimpleActor::EventSetAnimFinal - ( - Event *ev - ) -{ - ScriptError("animfinal is obsolete"); -} - -void SimpleActor::DesiredAnimation - ( - int eAnimMode, - const_str csAnimString - ) -{ - //fixme: this is an inline function. - m_eNextAnimMode = eAnimMode; - m_csNextAnimString = csAnimString; - m_bNextForceStart = false; -} - -void SimpleActor::StartAnimation - ( - int eAnimMode, - const_str csAnimString - ) -{ - //fixme: this is an inline function. - m_eNextAnimMode = eAnimMode; - m_csNextAnimString = csAnimString; - m_bNextForceStart = true; -} - -void SimpleActor::DesiredAnimation - ( - int eAnimMode, - ScriptThreadLabel AnimLabel - ) -{ - //fixme: this is an inline function. - m_eNextAnimMode = eAnimMode; - m_csNextAnimString = STRING_NULL; - m_NextAnimLabel = AnimLabel; - m_bNextForceStart = false; -} - -void SimpleActor::StartAnimation - ( - int eAnimMode, - ScriptThreadLabel AnimLabel - ) -{ - //fixme: this is an inline function. - m_eNextAnimMode = eAnimMode; - m_csNextAnimString = STRING_NULL; - m_NextAnimLabel = AnimLabel; - m_bNextForceStart = true; -} - -void SimpleActor::ContinueAnimationAllowNoPath - ( - void - ) -{ - if (m_eNextAnimMode < 0) - { - m_bNextForceStart = false; - m_csNextAnimString = STRING_NULL; - m_eNextAnimMode = m_eAnimMode; - m_NextAnimLabel = m_Anim; - } -} - -void SimpleActor::ContinueAnimation - ( - void - ) -{ - int eAnimMode = m_eNextAnimMode; - if (eAnimMode < 0) - { - m_bNextForceStart = false; - m_csNextAnimString = STRING_NULL; - m_eNextAnimMode = m_eAnimMode; - m_NextAnimLabel = m_Anim; - eAnimMode = m_eAnimMode; - } - - if (eAnimMode <= 3 && !PathExists()) - { - //assert(!DumpCallTrace("ContinueAnimation() called on a pathed animation, but no path exists")); - Anim_Stand(); - } -} - -void SimpleActor::SetPathGoalEndAnim - ( - const_str csEndAnim - ) -{ - //fixme: this is an inline function - m_csPathGoalEndAnimScript = csEndAnim; -} - -bool SimpleActor::UpdateSelectedAnimation - ( - void - ) -{ - if (m_csNextAnimString == STRING_NULL) - { - if (m_bNextForceStart) - { - m_Anim = m_NextAnimLabel; - m_eAnimMode = m_eNextAnimMode; - if (m_eNextAnimMode != 3) - SetPathGoalEndAnim(STRING_EMPTY); - m_bStartPathGoalEndAnim = false; - m_eNextAnimMode = -1; - return true; - } - - if (m_pAnimThread) - { - if (m_eAnimMode == m_eNextAnimMode) - { - if (m_Anim == m_NextAnimLabel) - { - m_bStartPathGoalEndAnim = false; - m_eNextAnimMode = -1; - return false; - } - } - } - m_Anim = m_NextAnimLabel; - m_eAnimMode = m_eNextAnimMode; - if (m_eNextAnimMode != 3) - SetPathGoalEndAnim(STRING_EMPTY); - m_bStartPathGoalEndAnim = false; - m_eNextAnimMode = -1; - return true; - } - - if (m_bNextForceStart) - { - - Com_Printf("UpdateSelectedAnimation\n"); - m_Anim.TrySetScript(m_csNextAnimString); - m_eAnimMode = m_eNextAnimMode; - if (m_eNextAnimMode != 3) - SetPathGoalEndAnim(STRING_EMPTY); - m_bStartPathGoalEndAnim = false; - m_eNextAnimMode = -1; - return true; - } - - if (!m_pAnimThread || m_eAnimMode != m_eNextAnimMode) - { - m_Anim.TrySetScript(m_csNextAnimString); - m_eAnimMode = m_eNextAnimMode; - if (m_eNextAnimMode != 3) - SetPathGoalEndAnim(STRING_EMPTY); - m_bStartPathGoalEndAnim = false; - m_eNextAnimMode = -1; - return true; - } - - if (m_fPathGoalTime <= level.time) - { - if (!m_Anim.IsFile(m_csNextAnimString)) - { - m_Anim.TrySetScript(m_csNextAnimString); - m_eAnimMode = m_eNextAnimMode; - if (m_eNextAnimMode != 3) - SetPathGoalEndAnim(STRING_EMPTY); - m_bStartPathGoalEndAnim = false; - m_eNextAnimMode = -1; - return true; - } - } - - m_eNextAnimMode = -1; - if (m_bStartPathGoalEndAnim) - { - m_bStartPathGoalEndAnim = false; - - if (!m_Anim.IsFile(m_csPathGoalEndAnimScript)) - { - m_Anim.TrySetScript(m_csPathGoalEndAnimScript); - return true; - } - } - return false; -} - -const char *SimpleActor::DumpCallTrace - ( - const char *pszFmt, - ... - ) const -{ - OVERLOADED_ERROR(); - return "overloaded version should always get called"; + +void SimpleActor::EventSetAttackHandler(Event *ev) +{ + if (ev->IsFromScript()) { + m_AttackHandler.SetScript(ev->GetValue(1)); + } else { + m_AttackHandler.SetScript(ev->GetString(1)); + } } + +void SimpleActor::EventGetSniperHandler(Event *ev) +{ + ScriptVariable var; + + m_SniperHandler.GetScriptValue(&var); + ev->AddValue(var); +} + +void SimpleActor::EventSetSniperHandler(Event *ev) +{ + if (ev->IsFromScript()) { + m_SniperHandler.SetScript(ev->GetValue(1)); + } else { + m_SniperHandler.SetScript(ev->GetString(1)); + } +} + +bool SimpleActor::UpdateSelectedAnimation(void) +{ + if (m_csNextAnimString != STRING_NULL) { + if (!m_bNextForceStart && m_pAnimThread && m_eAnimMode == m_eNextAnimMode + && (m_fPathGoalTime > level.time || m_Anim.IsFile(m_csNextAnimString))) { + // Clear the next animation + m_eNextAnimMode = -1; + + if (!m_bStartPathGoalEndAnim) { + return false; + } + m_bStartPathGoalEndAnim = false; + + if (m_Anim.IsFile(m_csPathGoalEndAnimScript)) { + return false; + } + + m_Anim.TrySetScript(m_csPathGoalEndAnimScript); + return true; + } + + m_Anim.TrySetScript(m_csNextAnimString); + } else { + if (!m_bNextForceStart && m_pAnimThread && m_eAnimMode == m_eNextAnimMode && m_Anim == m_NextAnimLabel) { + m_bStartPathGoalEndAnim = false; + m_eNextAnimMode = -1; + return false; + } + + m_Anim = m_NextAnimLabel; + } + + m_eAnimMode = m_eNextAnimMode; + + if (m_eAnimMode != ANIM_MODE_PATH_GOAL) { + m_csPathGoalEndAnimScript = STRING_EMPTY; + } + + m_bStartPathGoalEndAnim = false; + m_eNextAnimMode = -1; + + return true; +} + +void SimpleActor::EventNoAnimLerp(Event *ev) +{ + edict->s.eFlags |= EF_NO_LERP; + NoLerpThisFrame(); +} + +const char *SimpleActor::DumpCallTrace(const char *pszFmt, ...) const +{ + OVERLOADED_ERROR(); + return "overloaded version should always get called"; +} + +void SimpleActor::EventGetAnimMode(Event *ev) {} + +void SimpleActor::EventSetAnimMode(Event *ev) {} diff --git a/code/fgame/simpleactor.h b/code/fgame/simpleactor.h index aa1e6464..4aea2112 100644 --- a/code/fgame/simpleactor.h +++ b/code/fgame/simpleactor.h @@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // simpleactor.h: Base class for character AI. -#ifndef __SIMPLEACTOR_H__ -#define __SIMPLEACTOR_H__ +#pragma once #include "weapon.h" #include "sentient.h" @@ -35,18 +34,44 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "actorpath.h" enum eEmotionMode { - EMOTION_NONE, - EMOTION_NEUTRAL, - EMOTION_WORRY, - EMOTION_PANIC, - EMOTION_FEAR, - EMOTION_DISGUST, - EMOTION_ANGER, - EMOTION_AIMING, - EMOTION_DETERMINED, - EMOTION_DEAD, - EMOTION_CURIOUS + EMOTION_NONE, + EMOTION_NEUTRAL, + EMOTION_WORRY, + EMOTION_PANIC, + EMOTION_FEAR, + EMOTION_DISGUST, + EMOTION_ANGER, + EMOTION_AIMING, + EMOTION_DETERMINED, + EMOTION_DEAD, + EMOTION_CURIOUS }; + +enum eAnimMode { + ANIM_MODE_NONE, + ANIM_MODE_NORMAL, + ANIM_MODE_PATH, + ANIM_MODE_PATH_GOAL, + ANIM_MODE_DEST, + ANIM_MODE_SCRIPTED, + ANIM_MODE_NOCLIP, + ANIM_MODE_FALLING_PATH, + ANIM_MODE_FROZEN, + ANIM_MODE_ATTACHED, +}; + +enum eAnimWeightType { + ANIM_WEIGHT_NONE, + ANIM_WEIGHT_MOTION, + ANIM_WEIGHT_ACTION, + ANIM_WEIGHT_CROSSBLEND_1, + ANIM_WEIGHT_CROSSBLEND_2, + ANIM_WEIGHT_CROSSBLEND_DIALOG, + ANIM_WEIGHT_SAY, + ANIM_WEIGHT_AIM, + ANIM_WEIGHT_LASTFRAME, +}; + class SimpleActor; typedef SafePtr SimpleActorPtr; @@ -54,204 +79,402 @@ typedef SafePtr SimpleActorPtr; class SimpleActor : public Sentient { public: - int m_eAnimMode; - ScriptThreadLabel m_Anim; - SafePtr m_pAnimThread; - int m_eNextAnimMode; - const_str m_csNextAnimString; - ScriptThreadLabel m_NextAnimLabel; - bool m_bNextForceStart; - float m_fCrouchWeight; - bool m_YawAchieved; - float m_DesiredYaw; - bool m_bHasDesiredLookDest; - bool m_bHasDesiredLookAngles; - Vector m_vDesiredLookDest; - Vector m_DesiredLookAngles; - Vector m_DesiredGunDir; - ActorPath m_Path; - float m_Dest[ 3 ]; - float m_NoClipDest[ 3 ]; - float path_failed_time; - float m_fPathGoalTime; - bool m_bStartPathGoalEndAnim; - const_str m_csPathGoalEndAnimScript; - qboolean m_walking; - qboolean m_groundPlane; - Vector m_groundPlaneNormal; - Vector watch_offset; - bool m_bThink; - int m_PainTime; - eEmotionMode m_eEmotionMode; - float m_fAimLimit_up; - float m_fAimLimit_down; - int m_ChangeMotionAnimIndex; - int m_ChangeActionAnimIndex; - int m_ChangeSayAnimIndex; + int m_eAnimMode; + ScriptThreadLabel m_Anim; + SafePtr m_pAnimThread; + int m_eNextAnimMode; + const_str m_csNextAnimString; + ScriptThreadLabel m_NextAnimLabel; + bool m_bNextForceStart; + float m_fCrouchWeight; + bool m_YawAchieved; + float m_DesiredYaw; + bool m_bHasDesiredLookDest; + bool m_bHasDesiredLookAngles; + Vector m_vDesiredLookDest; + Vector m_DesiredLookAngles; + Vector m_DesiredGunDir; + ActorPath m_Path; + float m_Dest[3]; + float m_NoClipDest[3]; + float path_failed_time; + float m_fPathGoalTime; + bool m_bStartPathGoalEndAnim; + const_str m_csPathGoalEndAnimScript; + qboolean m_walking; + qboolean m_groundPlane; + vec3_t m_groundPlaneNormal; + Vector watch_offset; + bool m_bThink; + int m_PainTime; + eEmotionMode m_eEmotionMode; + float m_fAimLimit_up; + float m_fAimLimit_down; + int m_ChangeMotionAnimIndex; + int m_ChangeActionAnimIndex; + int m_ChangeSayAnimIndex; protected: - unsigned int m_weightType[ MAX_FRAMEINFOS ]; - float m_weightBase[ MAX_FRAMEINFOS ]; - float m_weightCrossBlend[ MAX_FRAMEINFOS ]; - bool m_AnimMotionHigh; - bool m_AnimActionHigh; - bool m_AnimDialogHigh; + unsigned int m_weightType[MAX_FRAMEINFOS]; + float m_weightBase[MAX_FRAMEINFOS]; + float m_weightCrossBlend[MAX_FRAMEINFOS]; + bool m_AnimMotionHigh; + bool m_AnimActionHigh; + bool m_AnimDialogHigh; public: - int hit_obstacle_time; - float obstacle_vel[ 2 ]; - const_str m_csAnimName; - const_str m_csSayAnim; - const_str m_csUpperAnim; - const_str m_csCurrentPosition; - int m_bPathErrorTime; - class PathNode *m_NearestNode; - Vector m_vNearestNodePos; - short int m_bUpdateAnimDoneFlags; - float m_maxspeed; - const_str m_csMood; - const_str m_csIdleMood; - int m_iMotionSlot; - int m_iActionSlot; - int m_iSaySlot; - bool m_bLevelMotionAnim; - bool m_bLevelActionAnim; - byte m_bLevelSayAnim; - byte m_bNextLevelSayAnim; - bool m_bMotionAnimSet; - bool m_bActionAnimSet; - bool m_bSayAnimSet; - bool m_bAimAnimSet; - int m_iVoiceTime; - bool m_bDoAI; - ScriptThreadLabel m_PainHandler; - ScriptThreadLabel m_DeathHandler; - ScriptThreadLabel m_AttackHandler; - ScriptThreadLabel m_SniperHandler; - float m_fCrossblendTime; + int hit_obstacle_time; + float obstacle_vel[2]; + const_str m_csAnimName; + const_str m_csSayAnim; + const_str m_csUpperAnim; + const_str m_csCurrentPosition; + int m_bPathErrorTime; + class PathNode *m_NearestNode; + Vector m_vNearestNodePos; + short m_bUpdateAnimDoneFlags; + float m_maxspeed; + const_str m_csMood; + const_str m_csIdleMood; + int m_iMotionSlot; + int m_iActionSlot; + int m_iSaySlot; + bool m_bLevelMotionAnim; + bool m_bLevelActionAnim; + byte m_bLevelSayAnim; + byte m_bNextLevelSayAnim; + bool m_bMotionAnimSet; + bool m_bActionAnimSet; + bool m_bSayAnimSet; + bool m_bAimAnimSet; + int m_iVoiceTime; + bool m_bDoAI; + ScriptThreadLabel m_PainHandler; + ScriptThreadLabel m_DeathHandler; + ScriptThreadLabel m_AttackHandler; + ScriptThreadLabel m_SniperHandler; + float m_fCrossblendTime; public: - CLASS_PROTOTYPE( SimpleActor ); + CLASS_PROTOTYPE(SimpleActor); - SimpleActor(); + SimpleActor(); + ~SimpleActor(); - void Archive( Archiver & arc ) override; - virtual void SetMoveInfo(mmove_t* mm); - virtual void GetMoveInfo(mmove_t* mm); - bool CanSeeFrom(vec3_t pos, Entity* ent); - virtual bool CanTarget(void); - virtual bool IsImmortal(void); - bool DoesTheoreticPathExist( Vector vDestPos, float fMaxPath ); - void SetPath( Vector vDestPos, const char *description, int iMaxDirtyTime, float *vLeashHome, float fLeashDistSquared ); - void SetPath( SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime ); - void SetPathWithinDistance( Vector vDestPos, char *description, float fMaxPath, int iMaxDirtyTime ); - void FindPathAway( vec_t *vAwayFrom, vec_t *vDirPreferred, float fMinSafeDist ); - void ClearPath( void ); - bool PathComplete( void ) const; - bool PathExists( void ) const; - bool PathIsValid( void ) const; - bool PathAvoidsSquadMates( void ) const; - void ShortenPathToAvoidSquadMates( void ); - PathInfo *CurrentPathNode( void ) const; - PathInfo *LastPathNode( void ) const; - float PathDist( void ) const; - bool PathHasCompleteLookahead( void ) const; - Vector PathGoal( void ) const; - float *PathDelta( void ) const; - bool PathGoalSlowdownStarted( void ) const; - void SetDest( vec3_t dest ); - void StopTurning( void ); - void SetDesiredYaw( float yaw ); - void SetDesiredYawDir( vec3_t vec ); - void SetDesiredYawDest( vec3_t vec ); - void UpdateEmotion( void ); - int GetEmotionAnim( void ); - int GetMotionSlot( int slot ); - int GetActionSlot( int slot ); - int GetSaySlot( void ); - void StartCrossBlendAnimSlot( int slot ); - void StartMotionAnimSlot( int slot, int anim, float weight ); - void StartAimMotionAnimSlot( int slot, int anim ); - void StartActionAnimSlot( int anim ); - void StartSayAnimSlot( int anim ); - void StartAimAnimSlot( int slot, int anim ); - void SetBlendedWeight( int slot ); - void EventSetAnimLength( Event *ev ); - void UpdateNormalAnimSlot( int slot ); - void UpdateCrossBlendAnimSlot( int slot ); - void UpdateCrossBlendDialogAnimSlot( int slot ); - void UpdateSayAnimSlot( int slot ); - void UpdateLastFrameSlot( int slot ); - void UpdateAnimSlot( int slot ); - void StopAllAnimating( void ); - void ChangeMotionAnim( void ); - void ChangeActionAnim( void ); - void ChangeSayAnim( void ); - void StopAnimating( int slot ); - void AnimFinished( int slot ) override; - void UpdateAim( void ); - void UpdateAimMotion( void ); - void EventAIOn( Event *ev ); - void EventAIOff( Event *ev ); - void EventGetWeaponGroup( Event *ev ); - void EventGetWeaponType( Event *ev ); - void EventGetPainHandler( Event *ev ); - void EventSetPainHandler( Event *ev ); - void EventGetDeathHandler( Event *ev ); - void EventSetDeathHandler( Event *ev ); - void EventGetAttackHandler( Event *ev ); - void EventSetAttackHandler( Event *ev ); - void EventGetSniperHandler( Event *ev ); - void EventSetSniperHandler( Event *ev ); - void EventSetCrossblendTime( Event *ev ); - void EventGetCrossblendTime( Event *ev ); - void EventSetEmotion( Event *ev ); - void EventGetPosition( Event *ev ); - void EventSetPosition( Event *ev ); - void EventGetAnimMode( Event *ev ); - void EventSetAnimMode( Event *ev ); - void EventSetAnimFinal( Event *ev ); - const_str GetRunAnim( void ); - const_str GetWalkAnim( void ); - void DesiredAnimation( int eAnimMode, const_str csAnimString ); - void StartAnimation( int eAnimMode, const_str csAnimString ); - void DesiredAnimation( int eAnimMode, ScriptThreadLabel AnimLabel ); - void StartAnimation( int eAnimMode, ScriptThreadLabel AnimLabel ); - void ContinueAnimationAllowNoPath( void ); - void ContinueAnimation( void ); - void SetPathGoalEndAnim( const_str csEndAnim ); - bool UpdateSelectedAnimation( void ); - void Anim_Attack( void ); - void Anim_Sniper( void ); - void Anim_Aim( void ); - void Anim_Shoot( void ); - void Anim_Idle( void ); - void Anim_Crouch( void ); - void Anim_Prone( void ); - void Anim_Stand( void ); - void Anim_Cower( void ); - void Anim_Killed( void ); - void Anim_StartPain( void ); - void Anim_Pain( void ); - void Anim_CrouchRunTo( int eAnimMode ); - void Anim_CrouchWalkTo( int eAnimMode ); - void Anim_StandRunTo( int eAnimMode ); - void Anim_StandWalkTo( int eAnimMode ); - void Anim_RunTo( int eAnimMode ); - void Anim_WalkTo( int eAnimMode ); - void Anim_RunAwayFiring( int eAnimMode ); - void Anim_RunToShooting( int eAnimMode ); - void Anim_RunToAlarm( int eAnimMode ); - void Anim_RunToCasual( int eAnimMode ); - void Anim_RunToCover( int eAnimMode ); - void Anim_RunToDanger( int eAnimMode ); - void Anim_RunToDive( int eAnimMode ); - void Anim_RunToFlee( int eAnimMode ); - void Anim_RunToInOpen( int eAnimMode ); - void Anim_Emotion( eEmotionMode eEmotMode ); - void Anim_Say( const_str csSayAnimScript, int iMinTimeSinceLastSay, bool bCanInterrupt ); - void Anim_FullBody( const_str csFullBodyAnim, int eAnimMode ); - virtual const char *DumpCallTrace( const char *pszFmt, ... ) const; + void Archive(Archiver &arc) override; + virtual void SetMoveInfo(mmove_t *mm); + virtual void GetMoveInfo(mmove_t *mm); + bool CanSeeFrom(vec3_t pos, Entity *ent); + virtual bool CanTarget(void); + virtual bool IsImmortal(void); + bool DoesTheoreticPathExist(Vector vDestPos, float fMaxPath); + void + SetPath(Vector vDestPos, const char *description, int iMaxDirtyTime, float *vLeashHome, float fLeashDistSquared); + void SetPath(SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime); + void SetPathWithinDistance(Vector vDestPos, char *description, float fMaxPath, int iMaxDirtyTime); + void FindPathAway(vec3_t vAwayFrom, vec2_t vDirPreferred, float fMinSafeDist); + void ClearPath(void); + bool PathComplete(void) const; + bool PathExists(void) const; + bool PathIsValid(void) const; + bool PathAvoidsSquadMates(void) const; + void ShortenPathToAvoidSquadMates(void); + PathInfo *CurrentPathNode(void) const; + PathInfo *LastPathNode(void) const; + float PathDist(void) const; + bool PathHasCompleteLookahead(void) const; + Vector PathGoal(void) const; + const float *PathDelta(void) const; + bool PathGoalSlowdownStarted(void) const; + void SetDest(vec3_t dest); + void StopTurning(void); + void SetDesiredYaw(float yaw); + void SetDesiredYawDir(const vec2_t vec); + void SetDesiredYawDest(const vec3_t vec); + void UpdateEmotion(void); + int GetEmotionAnim(void); + int GetMotionSlot(int slot); + int GetActionSlot(int slot); + int GetSaySlot(void); + void StartCrossBlendAnimSlot(int slot); + void StartMotionAnimSlot(int slot, int anim, float weight); + void StartAimMotionAnimSlot(int slot, int anim); + void StartActionAnimSlot(int anim); + void StartSayAnimSlot(int anim); + void StartAimAnimSlot(int slot, int anim); + void SetBlendedWeight(int slot); + void EventSetAnimLength(Event *ev); + void UpdateNormalAnimSlot(int slot); + void UpdateCrossBlendAnimSlot(int slot); + void UpdateCrossBlendDialogAnimSlot(int slot); + void UpdateSayAnimSlot(int slot); + void UpdateLastFrameSlot(int slot); + void UpdateAnimSlot(int slot); + void StopAllAnimating(void); + void ChangeMotionAnim(void); + void ChangeActionAnim(void); + void ChangeSayAnim(void); + void StopAnimating(int slot); + void AnimFinished(int slot) override; + void UpdateAim(void); + void UpdateAimMotion(void); + void EventAIOn(Event *ev); + void EventAIOff(Event *ev); + void EventGetWeaponGroup(Event *ev); + void EventGetWeaponType(Event *ev); + void EventGetPainHandler(Event *ev); + void EventSetPainHandler(Event *ev); + void EventGetDeathHandler(Event *ev); + void EventSetDeathHandler(Event *ev); + void EventGetAttackHandler(Event *ev); + void EventSetAttackHandler(Event *ev); + void EventGetSniperHandler(Event *ev); + void EventSetSniperHandler(Event *ev); + void EventSetCrossblendTime(Event *ev); + void EventGetCrossblendTime(Event *ev); + void EventSetEmotion(Event *ev); + void EventGetPosition(Event *ev); + void EventSetPosition(Event *ev); + void EventGetAnimMode(Event *ev); + void EventSetAnimMode(Event *ev); + void EventSetAnimFinal(Event *ev); + void EventNoAnimLerp(Event *ev); // Added in 2.0 + const_str GetRunAnim(void); + const_str GetWalkAnim(void); + void DesiredAnimation(int eAnimMode, const_str csAnimString); + void StartAnimation(int eAnimMode, const_str csAnimString); + void DesiredAnimation(int eAnimMode, ScriptThreadLabel AnimLabel); + void StartAnimation(int eAnimMode, ScriptThreadLabel AnimLabel); + void ContinueAnimationAllowNoPath(void); + void ContinueAnimation(void); + void SetPathGoalEndAnim(const_str csEndAnim); + bool UpdateSelectedAnimation(void); + void Anim_Attack(void); + void Anim_Suppress(void); // Added in 2.0 + void Anim_Sniper(void); + void Anim_Aim(void); + void Anim_Shoot(void); + void Anim_Idle(void); + void Anim_Crouch(void); + void Anim_Prone(void); + void Anim_Stand(void); + void Anim_Cower(void); + void Anim_Killed(void); + void Anim_StartPain(void); + void Anim_Pain(void); + void Anim_CrouchRunTo(int eAnimMode); + void Anim_CrouchWalkTo(int eAnimMode); + void Anim_StandRunTo(int eAnimMode); + void Anim_StandWalkTo(int eAnimMode); + void Anim_RunTo(int eAnimMode); + void Anim_WalkTo(int eAnimMode); + void Anim_RunAwayFiring(int eAnimMode); + void Anim_RunToShooting(int eAnimMode); + void Anim_RunToAlarm(int eAnimMode); + void Anim_RunToCasual(int eAnimMode); + void Anim_RunToCover(int eAnimMode); + void Anim_RunToDanger(int eAnimMode); + void Anim_RunToDive(int eAnimMode); + void Anim_RunToFlee(int eAnimMode); + void Anim_RunToInOpen(int eAnimMode); + void Anim_Emotion(eEmotionMode eEmotMode); + void Anim_Say(const_str csSayAnimScript, int iMinTimeSinceLastSay, bool bCanInterrupt); + void Anim_FullBody(const_str csFullBodyAnim, int eAnimMode); + virtual const char *DumpCallTrace(const char *pszFmt, ...) const; }; -#endif /* simpleactor.h */ \ No newline at end of file +inline void SimpleActor::StartAnimation(int eAnimMode, const_str csAnimString) +{ + m_eNextAnimMode = eAnimMode; + m_csNextAnimString = csAnimString; + m_bNextForceStart = true; +} + +inline void SimpleActor::DesiredAnimation(int eAnimMode, const_str csAnimString) +{ + m_eNextAnimMode = eAnimMode; + m_csNextAnimString = csAnimString; + m_bNextForceStart = false; +} + +inline void SimpleActor::StartAnimation(int eAnimMode, ScriptThreadLabel AnimLabel) +{ + m_eNextAnimMode = eAnimMode; + m_csNextAnimString = STRING_NULL; + m_NextAnimLabel = AnimLabel; + m_bNextForceStart = true; +} + +inline void SimpleActor::DesiredAnimation(int eAnimMode, ScriptThreadLabel AnimLabel) +{ + m_eNextAnimMode = eAnimMode; + m_csNextAnimString = STRING_NULL; + m_NextAnimLabel = AnimLabel; + m_bNextForceStart = false; +} + +inline void SimpleActor::ContinueAnimationAllowNoPath(void) +{ + if (m_eNextAnimMode < ANIM_MODE_NONE) { + m_eNextAnimMode = m_eAnimMode; + m_csNextAnimString = STRING_NULL; + m_NextAnimLabel = m_Anim; + m_bNextForceStart = false; + } +} + +inline void SimpleActor::ContinueAnimation(void) +{ + ContinueAnimationAllowNoPath(); + + if ((m_eNextAnimMode == ANIM_MODE_PATH || m_eNextAnimMode == ANIM_MODE_PATH_GOAL) && !PathExists()) { + assert(!"ContinueAnimation() called on a pathed animation, but no path exists"); + Anim_Stand(); + } +} + +inline void SimpleActor::SetPathGoalEndAnim(const_str csEndAnim) +{ + m_csPathGoalEndAnimScript = csEndAnim; +} + +inline void SimpleActor::Archive(Archiver& arc) +{ + int i; + + Sentient::Archive(arc); + + arc.ArchiveInteger(&m_eAnimMode); + m_Anim.Archive(arc); + + arc.ArchiveBool(&m_bHasDesiredLookDest); + arc.ArchiveBool(&m_bHasDesiredLookAngles); + arc.ArchiveVector(&m_vDesiredLookDest); + arc.ArchiveVec3(m_DesiredLookAngles); + arc.ArchiveVec3(m_DesiredGunDir); + + m_Path.Archive(arc); + arc.ArchiveVec3(m_Dest); + arc.ArchiveVec3(m_NoClipDest); + + arc.ArchiveFloat(&path_failed_time); + arc.ArchiveFloat(&m_fPathGoalTime); + arc.ArchiveBool(&m_bStartPathGoalEndAnim); + Director.ArchiveString(arc, m_csPathGoalEndAnimScript); + + arc.ArchiveInteger(&m_eNextAnimMode); + Director.ArchiveString(arc, m_csNextAnimString); + m_NextAnimLabel.Archive(arc); + arc.ArchiveBool(&m_bNextForceStart); + + arc.ArchiveBoolean(&m_walking); + arc.ArchiveBoolean(&m_groundPlane); + arc.ArchiveVec3(m_groundPlaneNormal); + + arc.ArchiveVector(&watch_offset); + arc.ArchiveBool(&m_bThink); + arc.ArchiveInteger(&m_PainTime); + + arc.ArchiveBool(&m_bAimAnimSet); + arc.ArchiveBool(&m_bActionAnimSet); + + Director.ArchiveString(arc, m_csMood); + Director.ArchiveString(arc, m_csIdleMood); + + ArchiveEnum(m_eEmotionMode, eEmotionMode); + + arc.ArchiveFloat(&m_fAimLimit_up); + arc.ArchiveFloat(&m_fAimLimit_down); + + for (i = 0; i < MAX_FRAMEINFOS; i++) { + arc.ArchiveUnsigned(&m_weightType[i]); + } + + for (i = 0; i < MAX_FRAMEINFOS; i++) { + arc.ArchiveFloat(&m_weightBase[i]); + } + + for (i = 0; i < MAX_FRAMEINFOS; i++) { + arc.ArchiveFloat(&m_weightCrossBlend[i]); + } + + arc.ArchiveBool(&m_AnimMotionHigh); + arc.ArchiveBool(&m_AnimActionHigh); + arc.ArchiveBool(&m_AnimDialogHigh); + + arc.ArchiveVec2(obstacle_vel); + + Director.ArchiveString(arc, m_csCurrentPosition); + + arc.ArchiveBool(&m_bMotionAnimSet); + arc.ArchiveBool(&m_bDoAI); + + arc.ArchiveFloat(&m_fCrossblendTime); + + arc.ArchiveSafePointer(&m_pAnimThread); + + arc.ArchiveBool(&m_YawAchieved); + arc.ArchiveFloat(&m_DesiredYaw); + + arc.ArchiveInteger(&m_iVoiceTime); + arc.ArchiveBool(&m_bSayAnimSet); + + arc.ArchiveInteger(&hit_obstacle_time); + + Director.ArchiveString(arc, m_csAnimName); + + arc.ArchiveInteger(&m_bPathErrorTime); + arc.ArchiveInteger(&m_iMotionSlot); + arc.ArchiveInteger(&m_iActionSlot); + arc.ArchiveInteger(&m_iSaySlot); + + arc.ArchiveBool(&m_bLevelMotionAnim); + arc.ArchiveBool(&m_bLevelActionAnim); + arc.ArchiveByte(&m_bLevelSayAnim); + arc.ArchiveByte(&m_bNextLevelSayAnim); + + Director.ArchiveString(arc, m_csSayAnim); + Director.ArchiveString(arc, m_csUpperAnim); + + m_PainHandler.Archive(arc); + m_DeathHandler.Archive(arc); + m_AttackHandler.Archive(arc); + m_SniperHandler.Archive(arc); + + arc.ArchiveObjectPointer((Class **)&m_NearestNode); + arc.ArchiveVector(&m_vNearestNodePos); + + arc.ArchiveFloat(&m_fCrouchWeight); + arc.ArchiveFloat(&m_maxspeed); +} + +inline void SimpleActor::StopTurning(void) +{ + m_YawAchieved = true; +} + +inline void SimpleActor::SetDesiredYaw(float yaw) +{ + m_YawAchieved = false; + m_DesiredYaw = yaw; +} + +inline void SimpleActor::SetDesiredYawDir(const vec2_t vec) +{ + SetDesiredYaw(vectoyaw(vec)); +} + +inline void SimpleActor::SetDesiredYawDest(const vec3_t vec) +{ + vec2_t facedir; + VectorSub2D(vec, origin, facedir); + + if (facedir[0] || facedir[1]) { + SetDesiredYawDir(facedir); + } +} + +inline void SimpleActor::SetDest(vec3_t dest) +{ + VectorCopy(dest, m_Dest); +} diff --git a/code/fgame/simpleentity.cpp b/code/fgame/simpleentity.cpp index 854a8024..6b582500 100644 --- a/code/fgame/simpleentity.cpp +++ b/code/fgame/simpleentity.cpp @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "glb_local.h" #include "simpleentity.h" -#include "world.h" +#include "worldspawn.h" #include "level.h" #include "../script/scriptexception.h" @@ -253,112 +253,107 @@ SimpleEntity::~SimpleEntity() int SimpleEntity::IsSubclassOfEntity(void) const { - return (entflags & EF_ENTITY); + return (entflags & ECF_ENTITY); } int SimpleEntity::IsSubclassOfAnimate(void) const { - return (entflags & EF_ANIMATE); + return (entflags & ECF_ANIMATE); } int SimpleEntity::IsSubclassOfSentient(void) const { - return (entflags & EF_SENTIENT); + return (entflags & ECF_SENTIENT); } int SimpleEntity::IsSubclassOfPlayer(void) const { - return (entflags & EF_PLAYER); + return (entflags & ECF_PLAYER); } int SimpleEntity::IsSubclassOfActor(void) const { - return (entflags & EF_ACTOR); + return (entflags & ECF_ACTOR); } int SimpleEntity::IsSubclassOfItem(void) const { - return (entflags & EF_ITEM); + return (entflags & ECF_ITEM); } int SimpleEntity::IsSubclassOfInventoryItem(void) const { - return (entflags & EF_INVENTORYITEM); + return (entflags & ECF_INVENTORYITEM); } int SimpleEntity::IsSubclassOfWeapon(void) const { - return (entflags & EF_WEAPON); + return (entflags & ECF_WEAPON); } int SimpleEntity::IsSubclassOfProjectile(void) const { - return (entflags & EF_PROJECTILE); + return (entflags & ECF_PROJECTILE); } int SimpleEntity::IsSubclassOfDoor(void) const { - return (entflags & EF_DOOR); + return (entflags & ECF_DOOR); } int SimpleEntity::IsSubclassOfCamera(void) const { - return (entflags & EF_CAMERA); + return (entflags & ECF_CAMERA); } int SimpleEntity::IsSubclassOfVehicle(void) const { - return (entflags & EF_VEHICLE); + return (entflags & ECF_VEHICLE); } int SimpleEntity::IsSubclassOfVehicleTank(void) const { - return (entflags & EF_VEHICLETANK); + return (entflags & ECF_VEHICLETANK); } int SimpleEntity::IsSubclassOfVehicleTurretGun(void) const { - return (entflags & EF_VEHICLETURRET); + return (entflags & ECF_VEHICLETURRET); } int SimpleEntity::IsSubclassOfTurretGun(void) const { - return (entflags & EF_TURRET); + return (entflags & ECF_TURRET); } int SimpleEntity::IsSubclassOfPathNode(void) const { - return (entflags & EF_PATHNODE); + return (entflags & ECF_PATHNODE); } int SimpleEntity::IsSubclassOfWaypoint(void) const { - return (entflags & EF_WAYPOINT); + return (entflags & ECF_WAYPOINT); } int SimpleEntity::IsSubclassOfTempWaypoint(void) const { - return (entflags & EF_TEMPWAYPOINT); + return (entflags & ECF_TEMPWAYPOINT); } int SimpleEntity::IsSubclassOfVehiclePoint(void) const { - return (entflags & EF_VEHICLEPOINT); + return (entflags & ECF_VEHICLEPOINT); } int SimpleEntity::IsSubclassOfSplinePath(void) const { - return (entflags & EF_SPLINEPATH); + return (entflags & ECF_SPLINEPATH); } int SimpleEntity::IsSubclassOfCrateObject(void) const { - return (entflags & EF_CRATEOBJECT); -} - -int SimpleEntity::IsSubclassOfBot(void) const -{ - return (entflags & EF_BOT); + return (entflags & ECF_CRATEOBJECT); } void SimpleEntity::SetTargetName(str targetname) @@ -411,7 +406,7 @@ void SimpleEntity::GetCentroid(Event *ev) ev->AddVector(centroid); } -str& SimpleEntity::Target() +const str& SimpleEntity::Target() { return target; } @@ -491,7 +486,10 @@ void SimpleEntity::SetAngleEvent(Event *ev) void SimpleEntity::GetAngleEvent(Event *ev) { - ev->AddFloat(angles[1]); + Vector forward; + + angles.AngleVectorsLeft(&forward); + ev->AddFloat(G_GetAngle(forward)); } void SimpleEntity::setAngles(Vector angles) @@ -533,12 +531,18 @@ void SimpleEntity::GetUpVector(Event *ev) SimpleEntity *SimpleEntity::Next(void) { - SimpleEntity *ent = world->GetTarget(target, true); + Listener* ent; + + if (!target.length()) { + return NULL; + } + + ent = world->GetTarget(target, true); if (!ent || !ent->isSubclassOf(SimpleEntity)) { return NULL; } else { - return ent; + return static_cast(ent); } } diff --git a/code/fgame/simpleentity.h b/code/fgame/simpleentity.h index 235a4b6c..d9f2aa18 100644 --- a/code/fgame/simpleentity.h +++ b/code/fgame/simpleentity.h @@ -64,7 +64,7 @@ public: virtual void setOrigin(Vector origin); virtual void setOriginEvent(Vector origin); virtual void setAngles(Vector angles); - str & Target(); + const str & Target(); qboolean Targeted(void); str & TargetName(); virtual void SetTargetName(str targetname); @@ -91,7 +91,6 @@ public: int IsSubclassOfVehiclePoint(void) const; int IsSubclassOfSplinePath(void) const; int IsSubclassOfCrateObject(void) const; - int IsSubclassOfBot(void) const; void GetOrigin(Event *ev); void SetOrigin(Event *ev); diff --git a/code/fgame/smokegrenade.cpp b/code/fgame/smokegrenade.cpp index 05543a6f..0ec353c8 100644 --- a/code/fgame/smokegrenade.cpp +++ b/code/fgame/smokegrenade.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "smokegrenade.h" #include "smokesprite.h" #include "level.h" +#include "sentient.h" Event EV_SmokeGrenade_SetSpawnRate ( @@ -32,7 +33,6 @@ Event EV_SmokeGrenade_SetSpawnRate "rate", "sets how many smoke volumes are spawned per second" ); - Event EV_SmokeGrenade_SetBouncefactor ( "bouncefactor", @@ -41,7 +41,6 @@ Event EV_SmokeGrenade_SetBouncefactor "factor", "sets how far smoke volumes bounce when they collide with something" ); - Event EV_SmokeGrenade_SetLife ( "life", @@ -50,7 +49,6 @@ Event EV_SmokeGrenade_SetLife "life", "sets how long the smoke emitter lives" ); - Event EV_SmokeGrenade_SetSpawnLife ( "spawnlife", @@ -59,7 +57,6 @@ Event EV_SmokeGrenade_SetSpawnLife "life", "sets how long each smoke volume lives" ); - Event EV_SmokeGrenade_SetScalerate ( "scalerate", @@ -68,7 +65,6 @@ Event EV_SmokeGrenade_SetScalerate "rate", "sets how fast the smoke volume grows" ); - Event EV_SmokeGrenade_SetVelocity ( "velocity", @@ -77,16 +73,14 @@ Event EV_SmokeGrenade_SetVelocity "vel_x vel_y vel_z", "sets how fast the smoke volume moves away, with x forward and z up" ); - Event EV_SmokeGrenade_SetSpin ( - "spawnrate", + "spin", EV_DEFAULT, "f", "avel", "sets the number of rotations per second for this entity around its z axis" ); - Event EV_SmokeGrenade_SetOffset ( "offset", @@ -95,7 +89,6 @@ Event EV_SmokeGrenade_SetOffset "offset_x offset_y offset_z", "sets offset of the smoke volume from the entity" ); - Event EV_SmokeGrenade_SetScale ( "scale", @@ -104,7 +97,6 @@ Event EV_SmokeGrenade_SetScale "scale", "sets initial scale of each smoke volume" ); - Event EV_SmokeGrenade_SetFadein ( "fadein", @@ -113,7 +105,6 @@ Event EV_SmokeGrenade_SetFadein "time", "sets fadein time from 0 alpha to 1 alpha, in seconds" ); - Event EV_SmokeGrenade_SetFadedelay ( "fadedelay", @@ -122,7 +113,6 @@ Event EV_SmokeGrenade_SetFadedelay "time", "sets how long the entity waits until fading out from 1 alpha to 0 alpha, in seconds" ); - Event EV_SmokeGrenade_SetMaxAlpha ( "maxalpha", @@ -132,106 +122,107 @@ Event EV_SmokeGrenade_SetMaxAlpha "sets maximum opacity of an individual smoke particle, in 0-1 range" ); -CLASS_DECLARATION(EffectEntity, SmokeGrenade, "smokegrenade") -{ - { &EV_SmokeGrenade_SetSpawnRate, &SmokeGrenade::EventSetSpawnrate }, - { &EV_SmokeGrenade_SetBouncefactor, &SmokeGrenade::EventSetBouncefactor }, - { &EV_SmokeGrenade_SetLife, &SmokeGrenade::EventSetLife }, - { &EV_SmokeGrenade_SetSpawnLife, &SmokeGrenade::EventSetSpawnLife }, - { &EV_SmokeGrenade_SetScalerate, &SmokeGrenade::EventSetScalerate }, - { &EV_SmokeGrenade_SetVelocity, &SmokeGrenade::EventSetVelocity }, - { &EV_SmokeGrenade_SetSpin, &SmokeGrenade::EventSetSpin }, - { &EV_SmokeGrenade_SetOffset, &SmokeGrenade::EventSetOffset }, - { &EV_SmokeGrenade_SetScale, &SmokeGrenade::EventSetScale }, - { &EV_SmokeGrenade_SetFadein, &SmokeGrenade::EventSetFadein }, - { &EV_SmokeGrenade_SetFadedelay, &SmokeGrenade::EventSetFadedelay }, - { &EV_SmokeGrenade_SetMaxAlpha, &SmokeGrenade::EventSetMaxAlpha }, - { NULL, NULL } +CLASS_DECLARATION(EffectEntity, SmokeGrenade, "smokegrenade") { + {&EV_SmokeGrenade_SetSpawnRate, &SmokeGrenade::EventSetSpawnrate }, + {&EV_SmokeGrenade_SetBouncefactor, &SmokeGrenade::EventSetBouncefactor}, + {&EV_SmokeGrenade_SetLife, &SmokeGrenade::EventSetLife }, + {&EV_SmokeGrenade_SetSpawnLife, &SmokeGrenade::EventSetSpawnLife }, + {&EV_SmokeGrenade_SetScalerate, &SmokeGrenade::EventSetScalerate }, + {&EV_SmokeGrenade_SetVelocity, &SmokeGrenade::EventSetVelocity }, + {&EV_SmokeGrenade_SetSpin, &SmokeGrenade::EventSetSpin }, + {&EV_SmokeGrenade_SetOffset, &SmokeGrenade::EventSetOffset }, + {&EV_SmokeGrenade_SetScale, &SmokeGrenade::EventSetScale }, + {&EV_SmokeGrenade_SetFadein, &SmokeGrenade::EventSetFadein }, + {&EV_SmokeGrenade_SetFadedelay, &SmokeGrenade::EventSetFadedelay }, + {&EV_SmokeGrenade_SetMaxAlpha, &SmokeGrenade::EventSetMaxAlpha }, + {NULL, NULL } }; -void SmokeGrenade::EventSetSpawnrate(Event* ev) +void SmokeGrenade::EventSetSpawnrate(Event *ev) { float rate = ev->GetFloat(1); - if (rate < 0.001f) rate = 0.001f; + if (rate < 0.001f) { + rate = 0.001f; + } spawnRate = 1000.0f / rate; } -void SmokeGrenade::EventSetBouncefactor(Event* ev) +void SmokeGrenade::EventSetBouncefactor(Event *ev) { bounceFactor = ev->GetFloat(1); } -void SmokeGrenade::EventSetLife(Event* ev) +void SmokeGrenade::EventSetLife(Event *ev) { nextRemoveTime = level.time + ev->GetFloat(1); } -void SmokeGrenade::EventSetSpawnLife(Event* ev) +void SmokeGrenade::EventSetSpawnLife(Event *ev) { spawnLife = ev->GetFloat(1); } -void SmokeGrenade::EventSetScalerate(Event* ev) +void SmokeGrenade::EventSetScalerate(Event *ev) { scaleRate = ev->GetFloat(1); } -void SmokeGrenade::EventSetVelocity(Event* ev) +void SmokeGrenade::EventSetVelocity(Event *ev) { velocity[0] = ev->GetFloat(1); velocity[1] = ev->GetFloat(2); velocity[2] = ev->GetFloat(3); } -void SmokeGrenade::EventSetSpin(Event* ev) +void SmokeGrenade::EventSetSpin(Event *ev) { spinRate = ev->GetFloat(1); } -void SmokeGrenade::EventSetOffset(Event* ev) +void SmokeGrenade::EventSetOffset(Event *ev) { offset[0] = ev->GetFloat(1); offset[1] = ev->GetFloat(2); offset[2] = ev->GetFloat(3); } -void SmokeGrenade::EventSetScale(Event* ev) +void SmokeGrenade::EventSetScale(Event *ev) { scale = ev->GetFloat(1) * 0.5; } -void SmokeGrenade::EventSetFadein(Event* ev) +void SmokeGrenade::EventSetFadein(Event *ev) { fadeIn = ev->GetFloat(1); } -void SmokeGrenade::EventSetFadedelay(Event* ev) +void SmokeGrenade::EventSetFadedelay(Event *ev) { fadeDelay = ev->GetFloat(1); } -void SmokeGrenade::EventSetMaxAlpha(Event* ev) +void SmokeGrenade::EventSetMaxAlpha(Event *ev) { maxAlpha = ev->GetFloat(1); } SmokeGrenade::SmokeGrenade() { - flags |= FL_THINK; - nextRemoveTime = level.time + 1.0; - spawnRate = 1000; - bounceFactor = 0.0; - spawnLife = 1.0; - scaleRate = 1.0; - velocity = vec_zero; - offset = vec_zero; - spinRate = 0.0; - scale = 1.0; - fadeIn = 0.0; - fadeDelay = spawnLife; - maxAlpha = 1.0; - lastSpawnTime = level.inttime + 150; + flags |= FL_THINK; + nextRemoveTime = level.time + 1.0; + spawnRate = 1000; + bounceFactor = 0.0; + spawnLife = 1.0; + scaleRate = 1.0; + velocity = vec_zero; + offset = vec_zero; + spinRate = 0.0; + scale = 1.0; + fadeIn = 0.0; + fadeDelay = spawnLife; + maxAlpha = 1.0; + lastSpawnTime = level.inttime + 150; } void SmokeGrenade::Think() @@ -243,32 +234,57 @@ void SmokeGrenade::Think() if (level.inttime >= lastSpawnTime + spawnRate) { SmokeSprite sp; - float degrees; + float degrees; lastSpawnTime += spawnRate; - sp.origin = origin; + sp.origin = origin; sp.spawnTime = level.time; - sp.scale = scale; + sp.scale = scale; degrees = angles.y + (((level.inttime / 1000.0 - 176.0) * spinRate) * -0.36); - - RotatePointAroundAxis( - sp.velocity, - 2, - velocity, - degrees - ); - sp.spawnLife = spawnLife; + RotatePointAroundAxis(sp.velocity, 2, velocity, degrees); + + sp.spawnLife = spawnLife; sp.bounceFactor = bounceFactor; - sp.scaleStart = scale; - sp.scaleRate = scaleRate; - sp.fadeIn = fadeIn; - sp.fadeDelay = fadeDelay; - sp.maxAlpha = maxAlpha; - sp.owner = owner; + sp.scaleStart = scale; + sp.scaleRate = scaleRate; + sp.fadeIn = fadeIn; + sp.fadeDelay = fadeDelay; + sp.maxAlpha = maxAlpha; + sp.owner = owner; G_AddSmokeSprite(&sp); } } + +void SmokeGrenade::Archive(Archiver& arc) +{ + EffectEntity::Archive(arc); + + arc.ArchiveFloat(&nextRemoveTime); + arc.ArchiveInteger(&spawnRate); + arc.ArchiveFloat(&bounceFactor); + arc.ArchiveFloat(&spawnLife); + arc.ArchiveFloat(&scaleRate); + arc.ArchiveVector(&velocity); + arc.ArchiveFloat(&spinRate); + arc.ArchiveVector(&offset); + arc.ArchiveFloat(&scale); + arc.ArchiveFloat(&fadeIn); + arc.ArchiveFloat(&fadeDelay); + arc.ArchiveFloat(&maxAlpha); + arc.ArchiveInteger(&lastSpawnTime); + arc.ArchiveSafePointer(&owner); +} + +void SmokeGrenade::setOwner(Sentient *other) +{ + owner = other; +} + +Sentient *SmokeGrenade::getOwner() const +{ + return owner; +} diff --git a/code/fgame/smokegrenade.h b/code/fgame/smokegrenade.h index e5d0456a..15b6f710 100644 --- a/code/fgame/smokegrenade.h +++ b/code/fgame/smokegrenade.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,40 +24,48 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "effectentity.h" -class SmokeGrenade : public EffectEntity { +class Sentient; + +class SmokeGrenade : public EffectEntity +{ CLASS_PROTOTYPE(SmokeGrenade); public: SmokeGrenade(); - void EventSetSpawnrate(Event* ev); - void EventSetBouncefactor(Event* ev); - void EventSetLife(Event* ev); - void EventSetSpawnLife(Event* ev); - void EventSetScalerate(Event* ev); - void EventSetVelocity(Event* ev); - void EventSetSpin(Event* ev); - void EventSetOffset(Event* ev); - void EventSetScale(Event* ev); - void EventSetFadein(Event* ev); - void EventSetFadedelay(Event* ev); - void EventSetMaxAlpha(Event* ev); + void EventSetSpawnrate(Event *ev); + void EventSetBouncefactor(Event *ev); + void EventSetLife(Event *ev); + void EventSetSpawnLife(Event *ev); + void EventSetScalerate(Event *ev); + void EventSetVelocity(Event *ev); + void EventSetSpin(Event *ev); + void EventSetOffset(Event *ev); + void EventSetScale(Event *ev); + void EventSetFadein(Event *ev); + void EventSetFadedelay(Event *ev); + void EventSetMaxAlpha(Event *ev); void Think() override; + void Archive(Archiver& arc) override; + + void setOwner(Sentient *other); + Sentient *getOwner() const; + private: - float nextRemoveTime; - int spawnRate; - float bounceFactor; - float spawnLife; - float scaleRate; - Vector velocity; - float spinRate; - Vector offset; - float scale; - float fadeIn; - float fadeDelay; - float maxAlpha; - int lastSpawnTime; - SafePtr owner; + float nextRemoveTime; + int spawnRate; + float bounceFactor; + float spawnLife; + float scaleRate; + Vector velocity; + float spinRate; + Vector offset; + float scale; + float fadeIn; + float fadeDelay; + float maxAlpha; + int lastSpawnTime; + SafePtr owner; }; diff --git a/code/fgame/smokesprite.cpp b/code/fgame/smokesprite.cpp index 84b916ff..f848a8cb 100644 --- a/code/fgame/smokesprite.cpp +++ b/code/fgame/smokesprite.cpp @@ -112,21 +112,64 @@ void G_AddSmokeSprite(const SmokeSprite* sprite) g_Sprites.AddObject(*sprite); } -float G_ObfuscationForSmokeSprites(float, const Vector& end, const Vector& start) { - // FIXME: unimplemented - return 0; +float G_ObfuscationForSmokeSprites(float visibilityAlpha, const Vector& start, const Vector& end) { + Vector vDelta = end - start; + float fLength = vDelta.length(); + Vector vDir = vDelta * (1.0 / fLength); + float fObfuscation = visibilityAlpha; + int i; + + for (i = 1; i <= g_Sprites.NumObjects(); i++) { + const SmokeSprite& sprite = g_Sprites.ObjectAt(i); + Vector vSpriteDelta = sprite.origin - start; + float fDot = vSpriteDelta * vDir; + float fTimeAlive; + + if (fDot < -sprite.scale || fDot > fLength + sprite.scale) { + continue; + } + + if (fDot <= 0) { + if (Square(sprite.scale) <= vSpriteDelta.lengthSquared()) { + continue; + } + } else if (fDot >= fLength) { + Vector vSpriteEndDelta = sprite.origin - end; + + if (Square(sprite.scale) <= vSpriteEndDelta.lengthSquared()) { + continue; + } + } else { + Vector vSpriteEndDelta = vSpriteDelta - (vDir * fDot); + + if (Square(sprite.scale) <= vSpriteEndDelta.lengthSquared()) { + continue; + } + } + + fTimeAlive = level.time - sprite.spawnTime; + if (fTimeAlive < sprite.fadeIn) { + fObfuscation += sprite.maxAlpha * fTimeAlive / sprite.fadeIn; + } else if (sprite.spawnTime + sprite.fadeDelay >= level.svsTime) { + fObfuscation += sprite.maxAlpha; + } else if (sprite.spawnLife - fTimeAlive > 0) { + fObfuscation = (sprite.spawnLife - fTimeAlive) * sprite.maxAlpha / (sprite.spawnLife - sprite.fadeDelay); + } + + if(fObfuscation >= 1.0) { + // Completely obfuscated + return 1.0; + } + } + + return fObfuscation; } SmokeSprite* G_GetRandomSmokeSprite() { - int randVal; - int numObjects; - if (g_Sprites.NumObjects()) { + if (!g_Sprites.NumObjects()) { return NULL; } - numObjects = g_Sprites.NumObjects(); - randVal = rand(); - - return &g_Sprites.ObjectAt(randVal - randVal / numObjects * numObjects + 1); + return &g_Sprites.ObjectAt((rand() % g_Sprites.NumObjects()) + 1); } diff --git a/code/fgame/smokesprite.h b/code/fgame/smokesprite.h index fc835685..37be9d4e 100644 --- a/code/fgame/smokesprite.h +++ b/code/fgame/smokesprite.h @@ -45,6 +45,6 @@ public: void G_ResetSmokeSprites(); void G_ArchiveSmokeSprites(Archiver& arc); void G_UpdateSmokeSprites(); -float G_ObfuscationForSmokeSprites(float, const Vector& end, const Vector& start); +float G_ObfuscationForSmokeSprites(float visibilityAlpha, const Vector& start, const Vector& end); SmokeSprite* G_GetRandomSmokeSprite(); void G_AddSmokeSprite(const SmokeSprite* sprite); diff --git a/code/fgame/soundman.h b/code/fgame/soundman.h index 3ac6e758..2f0943ad 100644 --- a/code/fgame/soundman.h +++ b/code/fgame/soundman.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // soundman.h: Sound Manager // -#ifndef __SOUND_MANAGER_H__ -#define __SOUND_MANAGER_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -110,5 +109,3 @@ inline void SoundManager::Archive } extern SoundManager SoundMan; - -#endif /* camera.h */ diff --git a/code/fgame/specialfx.h b/code/fgame/specialfx.h index 2e52e41a..fc2138a0 100644 --- a/code/fgame/specialfx.h +++ b/code/fgame/specialfx.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // specialfx.h: special effects // -#ifndef __SPECIAL_FX_H__ -#define __SPECIAL_FX_H__ +#pragma once #include "g_local.h" #include "scriptslave.h" @@ -174,5 +173,3 @@ inline void SinkObject::Archive arc.ArchiveBoolean( &active ); arc.ArchiveVector( &startpos ); } - -#endif /* specialfx.h */ diff --git a/code/fgame/spline.h b/code/fgame/spline.h index 77f11968..a32dc460 100644 --- a/code/fgame/spline.h +++ b/code/fgame/spline.h @@ -23,320 +23,258 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // spline.h: Spline paths. // -#ifndef __SPLINE_H__ -#define __SPLINE_H__ +#pragma once #include "g_local.h" #include -template< unsigned int cGrids, unsigned int cPoints > +template class cSpline : public Class { public: - int m_iPoints; - float m_vPoints[ cPoints ][ cGrids ]; - int m_iPointFlags[ cPoints ]; + int m_iPoints; + float m_vPoints[cPoints][cGrids]; + int m_iPointFlags[cPoints]; - void Reset( void ); - int Add( float *fAdd, int flags ); - void Modify( int, float *, int ); - void UniformAdd( float *pos ); - void Remove( class cSpline *, int ); - void RemoveRange( int, int ); - int Right( float x ); - float *Get( float x, int *flags ); - float *GetByNode( float x, int *flags ); - int Append( cSpline *pNew ); + cSpline(); - void Archive( Archiver& arc ); + void Reset(void); + int Add(float *fAdd, int flags); + void Modify(int, float *, int); + void UniformAdd(float *pos); + void Remove(class cSpline *, int); + void RemoveRange(int, int); + int Right(float x); + float *Get(float x, int *flags); + float *GetByNode(float x, int *flags); + int Append(cSpline *pNew); + + void Archive(Archiver& arc); }; -template< unsigned int cGrids, unsigned int cPoints > -void cSpline< cGrids, cPoints >::Archive - ( - Archiver& arc - ) +template +cSpline::cSpline() { - arc.ArchiveInteger( &m_iPoints ); - - for( int i = 0; i < cPoints; i++ ) - { - for( int j = 0; i < cGrids; i++ ) - { - arc.ArchiveFloat( &m_vPoints[ i ][ j ] ); - } - - arc.ArchiveInteger( &m_iPointFlags[ i ] ); - } + m_iPoints = 0; } -template< unsigned int cGrids, unsigned int cPoints > -void cSpline< cGrids, cPoints >::Reset - ( - void - ) +template +void cSpline::Archive(Archiver& arc) { - m_iPoints = 0; + arc.ArchiveInteger(&m_iPoints); + + for (int i = 0; i < cPoints; i++) { + for (int j = 0; j < cGrids; j++) { + arc.ArchiveFloat(&m_vPoints[i][j]); + } + + arc.ArchiveInteger(&m_iPointFlags[i]); + } } -template< unsigned int cGrids, unsigned int cPoints > -int cSpline< cGrids, cPoints >::Add - ( - float *fAdd, - int flags - ) +template +void cSpline::Reset(void) { - int i; - int ii; - int insertIndex; - - if( m_iPoints + 1 > 512 ) { - return -1; - } - - insertIndex = Right( *fAdd ); - - for( i = m_iPoints; i > insertIndex; i-- ) - { - for( ii = 0; ii < cGrids; ii++ ) - { - m_vPoints[ i ][ ii ] = m_vPoints[ i - 1 ][ ii ]; - } - - m_iPointFlags[ i ] = m_iPointFlags[ i - 1 ]; - } - - for( i = 0; i < cGrids; i++ ) - { - m_vPoints[ insertIndex ][ i ] = fAdd[ i ]; - } - - m_iPointFlags[ insertIndex ] = flags; - m_iPoints++; - - return insertIndex; + m_iPoints = 0; } -template< unsigned int cGrids, unsigned int cPoints > -void cSpline< cGrids, cPoints >::UniformAdd - ( - float *pos - ) +template +int cSpline::Add(float *fAdd, int flags) { - int i; - int ii; + int i; + int ii; + int insertIndex; - for( i = m_iPoints; i > 0; i-- ) - { - for( ii = 0; ii <= cGrids; ii++ ) - { - m_vPoints[ i ][ ii ] += pos[ ii ]; - } - } + if (m_iPoints + 1 > cPoints) { + return -1; + } + + insertIndex = Right(*fAdd); + + for (i = m_iPoints; i > insertIndex; i--) { + for (ii = 0; ii < cGrids; ii++) { + m_vPoints[i][ii] = m_vPoints[i - 1][ii]; + } + + m_iPointFlags[i] = m_iPointFlags[i - 1]; + } + + for (i = 0; i < cGrids; i++) { + m_vPoints[insertIndex][i] = fAdd[i]; + } + + m_iPointFlags[insertIndex] = flags; + m_iPoints++; + + return insertIndex; } -template< unsigned int cGrids, unsigned int cPoints > -int cSpline< cGrids, cPoints >::Right - ( - float x - ) +template +void cSpline::UniformAdd(float *pos) { - int i; + int i; + int ii; - for( i = 0; i < m_iPoints; i++ ) - { - if( m_vPoints[ i ][ 0 ] > x ) { - break; - } - } - - return i; + for (i = 0; i < m_iPoints; i++) { + for (ii = 0; ii < cGrids; ii++) { + m_vPoints[i][ii] += pos[ii]; + } + } } -template< unsigned int cGrids, unsigned int cPoints > -float *cSpline< cGrids, cPoints >::Get - ( - float x, - int *flags - ) +template +int cSpline::Right(float x) { - if( !m_iPoints ) - { - return NULL; - } + int i; - int rp; - int i; - static float r[ cGrids ]; - double delta[ cGrids ]; + for (i = 0; i < m_iPoints; i++) { + if (m_vPoints[i][0] > x) { + break; + } + } - rp = Right( x ); - - if( rp ) - { - if( rp == m_iPoints ) - { - if( flags ) - { - *flags = m_iPointFlags[ rp - 1 ]; - } - - for( i = 0; i < cGrids; i++ ) - { - r[ i ] = m_vPoints[ rp - 1 ][ i ]; - } - } - else - { - if( flags ) - { - *flags = m_iPointFlags[ rp - 1 ]; - } - - for( i = 0; i < cGrids; i++ ) - { - delta[ i ] = m_vPoints[ rp ][ i ] - m_vPoints[ rp - 1 ][ i ]; - } - - for( i = 0; i < cGrids; i++ ) - { - r[ i ] = ( x - m_vPoints[ rp - 1 ][ 0 ] ) / delta[ 0 ] * delta[ i ] + m_vPoints[ rp - 1 ][ i ]; - } - } - } - else - { - if( flags ) - { - *flags = m_iPointFlags[ 0 ]; - } - - for( i = 0; i < 4; i++ ) - { - r[ i ] = m_vPoints[ 0 ][ i ]; - } - } - - return r; + return i; } -template< unsigned int cGrids, unsigned int cPoints > -float *cSpline< cGrids, cPoints >::GetByNode - ( - float x, - int *flags - ) +template +float *cSpline::Get(float x, int *flags) { - if( !m_iPoints ) - { - return NULL; - } + if (!m_iPoints) { + return NULL; + } - int rp; - int i; - static float r[ cGrids ]; - double delta[ cGrids ]; + int rp; + int i; + static float r[cGrids]; + double delta[cGrids]; - rp = ( int )( floor( x ) + 1.0f ); + rp = Right(x); - if( rp <= 0 ) - { - if( flags ) - { - *flags = m_iPointFlags[ 0 ]; - } + if (rp) { + if (rp == m_iPoints) { + if (flags) { + *flags = m_iPointFlags[rp - 1]; + } - for( i = 0; i < cGrids; i++ ) - { - r[ i ] = m_vPoints[ 0 ][ i ]; - } - } - else if( rp < m_iPoints ) - { - if( flags ) - { - *flags = m_iPointFlags[ rp - 1 ]; - } + for (i = 0; i < cGrids; i++) { + r[i] = m_vPoints[rp - 1][i]; + } + } else { + if (flags) { + *flags = m_iPointFlags[rp - 1]; + } - for( i = 0; i < cGrids; i++ ) - { - delta[ i ] = m_vPoints[ rp ][ i ] - m_vPoints[ rp - 1 ][ i ]; - } + for (i = 0; i < cGrids; i++) { + delta[i] = m_vPoints[rp][i] - m_vPoints[rp - 1][i]; + } - for( i = 0; i < cGrids; i++ ) - { - r[ i ] = ( x - ( rp - 1 ) ) * delta[ i ] + m_vPoints[ rp - 1 ][ i ]; - } - } - else - { - if( flags ) - { - *flags = m_iPointFlags[ rp - 1 ]; - } + for (i = 0; i < cGrids; i++) { + r[i] = (x - m_vPoints[rp - 1][0]) / delta[0] * delta[i] + m_vPoints[rp - 1][i]; + } + } + } else { + if (flags) { + *flags = m_iPointFlags[0]; + } - for( i = 0; i < cGrids; i++ ) - { - r[ i ] = m_vPoints[ rp - 1 ][ i ]; - } - } + for (i = 0; i < cGrids; i++) { + r[i] = m_vPoints[0][i]; + } + } - return r; + return r; } -template< unsigned int cGrids, unsigned int cPoints > -int cSpline< cGrids, cPoints >::Append - ( - cSpline< cGrids, cPoints > *pNew - ) +template +float *cSpline::GetByNode(float x, int *flags) { - float *i_fTmp; - float o_fTmp[ 4 ]; - float fIndexAdd; - int i; - int ii; - int iFlags; + if (!m_iPoints) { + return NULL; + } - if( !pNew || pNew->m_iPoints == 0 ) - { - return -1; - } + int rp; + int i; + static float r[cGrids]; + double delta[cGrids]; - if( m_iPoints ) - { - fIndexAdd = *GetByNode( m_iPoints, NULL ); + rp = (int)(floor(x) + 1.0); - for( i = 0; i < pNew->m_iPoints; i++ ) - { - i_fTmp = pNew->GetByNode( i, &iFlags ); + if (rp <= 0) { + if (flags) { + *flags = m_iPointFlags[0]; + } - for( ii = 0; ii < cGrids; ii++ ) - { - o_fTmp[ ii ] = i_fTmp[ ii ]; - } + for (i = 0; i < cGrids; i++) { + r[i] = m_vPoints[0][i]; + } + } else if (rp < m_iPoints) { + if (flags) { + *flags = m_iPointFlags[rp - 1]; + } - o_fTmp[ 0 ] += fIndexAdd; - Add( o_fTmp, iFlags ); - } + for (i = 0; i < cGrids; i++) { + delta[i] = m_vPoints[rp][i] - m_vPoints[rp - 1][i]; + } - return m_iPoints; - } - else - { - for( i = 0; i < pNew->m_iPoints; i++ ) - { - i_fTmp = pNew->GetByNode( i, &iFlags ); + for (i = 0; i < cGrids; i++) { + r[i] = (x - (rp - 1)) * delta[i] + m_vPoints[rp - 1][i]; + } + } else { + if (flags) { + *flags = m_iPointFlags[m_iPoints - 1]; + } - for( ii = 0; ii < cGrids; ii++ ) - { - o_fTmp[ ii ] = i_fTmp[ ii ]; - } + for (i = 0; i < cGrids; i++) { + r[i] = m_vPoints[m_iPoints - 1][i]; + } + } - Add( o_fTmp, iFlags ); - } - - return 0; - } + return r; } -#endif // __SPLINE_H__ +template +int cSpline::Append(cSpline *pNew) +{ + float *i_fTmp; + float o_fTmp[4]; + float fIndexAdd; + int i; + int ii; + int iFlags = 0; + + if (!pNew || pNew->m_iPoints == 0) { + return -1; + } + + if (m_iPoints) { + int points; + + points = m_iPoints; + fIndexAdd = *GetByNode(m_iPoints, NULL); + + for (i = 0; i < pNew->m_iPoints; i++) { + i_fTmp = pNew->GetByNode(i, &iFlags); + + for (ii = 0; ii < cGrids; ii++) { + o_fTmp[ii] = i_fTmp[ii]; + } + + o_fTmp[0] += fIndexAdd; + Add(o_fTmp, iFlags); + } + + return points; + } else { + for (i = 0; i < pNew->m_iPoints; i++) { + i_fTmp = pNew->GetByNode(i, &iFlags); + + for (ii = 0; ii < cGrids; ii++) { + o_fTmp[ii] = i_fTmp[ii]; + } + + Add(o_fTmp, iFlags); + } + + return 0; + } +} diff --git a/code/fgame/stack.h b/code/fgame/stack.h index 86d4807b..e67df81e 100644 --- a/code/fgame/stack.h +++ b/code/fgame/stack.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // stack.h: Generic Stack object. // -#ifndef __STACK_H__ -#define __STACK_H__ +#pragma once #include "g_local.h" #include "class.h" @@ -142,5 +141,3 @@ inline Type Stack::Pop return ret; } - -#endif /* stack.h */ diff --git a/code/fgame/trigger.cpp b/code/fgame/trigger.cpp index 21de2093..0cc77ade 100644 --- a/code/fgame/trigger.cpp +++ b/code/fgame/trigger.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -41,7 +41,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "trigger.h" #include "scriptmaster.h" #include "parm.h" -#include "world.h" +#include "worldspawn.h" #include "barrels.h" Event EV_Trigger_ActivateTargets @@ -77,7 +77,7 @@ Event EV_Trigger_SetCount EV_DEFAULT, "i", "count", - "Set the amount of times this trigger can be triggered", + "Set the number of times this trigger can be triggered", EV_NORMAL ); Event EV_Trigger_SetMessage @@ -110,7 +110,7 @@ Event EV_Trigger_SetSound Event EV_Trigger_SetThread ( "setthread", - EV_DEFAULT, + EV_DEFAULT, "s", "thread", "Set the thread to execute when this trigger is activated", @@ -190,6 +190,15 @@ Event EV_Trigger_SetTriggerCone "Sets the cone in which directed triggers will trigger.", EV_NORMAL ); +Event EV_Trigger_GetActivator +( + "activator", + EV_DEFAULT, + NULL, + NULL, + "Get's entity who last activated this trigger.", + EV_GETTER +); #define MULTI_ACTIVATE 1 #define INVISIBLE 2 @@ -251,6 +260,7 @@ CLASS_DECLARATION(Animate, Trigger, "trigger_multiple") { {&EV_Trigger_SetMultiFaceted, &Trigger::SetMultiFaceted }, {&EV_Trigger_SetEdgeTriggered, &Trigger::SetEdgeTriggered }, {&EV_Trigger_SetTriggerCone, &Trigger::SetTriggerCone }, + {&EV_Trigger_GetActivator, &Trigger::EventGetActivator}, {NULL, NULL } }; @@ -312,7 +322,6 @@ Trigger::Trigger() Trigger::~Trigger() {} void Trigger::SetTriggerDir(float angle) - { triggerDirYaw = angle; triggerDir = G_GetMovedir(angle); @@ -320,13 +329,11 @@ void Trigger::SetTriggerDir(float angle) } Vector Trigger::GetTriggerDir(void) - { return triggerDir; } void Trigger::SetTriggerCone(Event *ev) - { triggerCone = cos(DEG2RAD(ev->GetFloat(1))); } @@ -337,7 +344,6 @@ qboolean Trigger::UsingTriggerDir(void) } void Trigger::SetTriggerDir(Event *ev) - { SetTriggerDir(ev->GetFloat(1)); } @@ -346,7 +352,7 @@ void Trigger::SetModelEvent(Event *ev) { Animate::SetModelEvent(ev); if (spawnflags & TRIGGER_DAMAGE) { - setContents(CONTENTS_TRIGGER); + setContents(CONTENTS_CLAYPIDGEON); } else { setContents(0); } @@ -358,31 +364,36 @@ void Trigger::StartThread(Event *ev) { SafePtr This = this; - parm.other = ev->GetEntity(1); + parm.other = NULL; - if (ev->NumArgs() > 1) { - parm.owner = ev->GetEntity(2); + if (ev->NumArgs() > 0) { + parm.other = ev->GetEntity(1); } + parm.other = ev->NumArgs() > 0 ? ev->GetEntity(1) : NULL; + parm.owner = ev->NumArgs() > 1 ? ev->GetEntity(2) : NULL; + Unregister(STRING_TRIGGER); if (This) { - m_Thread.Execute(this); + //m_Thread.Execute(this); + // Changed in 2.30 + // First parameter of the thread label is parm.other + // Second parameter of the thread label is parm.owner + m_Thread.Execute(This, parm.other, parm.owner); } } qboolean Trigger::respondTo(Entity *other) - { return ( ((respondto & TRIGGER_PLAYERS) && other->isClient()) - || ((respondto & TRIGGER_MONSTERS) && other->isSubclassOf(Actor)) - || ((respondto & TRIGGER_PROJECTILES) && other->isSubclassOf(Projectile)) + || ((respondto & TRIGGER_MONSTERS) && other->IsSubclassOfActor()) + || ((respondto & TRIGGER_PROJECTILES) && other->IsSubclassOfProjectile()) ); } Entity *Trigger::getActivator(Entity *other) - { return other; } @@ -399,6 +410,11 @@ void Trigger::TriggerStuff(Event *ev) return; } + if (isSubclassOf(TriggerUse) && *ev != EV_Use) { + Com_Printf("^~^~^ Attempting to trigger TriggerUse with non-use trigger\n"); + return; + } + // Don't bother with testing anything if we can't trigger yet if ((level.time < trigger_time) || (trigger_time == -1)) { // if we are edgeTriggered, we reset our time until we leave the trigger @@ -408,19 +424,32 @@ void Trigger::TriggerStuff(Event *ev) return; } + /* health = max_health; if (health && (*ev != EV_Killed) && (*ev != EV_Activate)) { // if health is set, we only respond to killed and activate messages return; } + */ other = ev->GetEntity(1); assert(other != this); + if (other == this) { + ScriptError("trigger '%s' triggered by self", TargetName().c_str()); + } + + // Fixed in OPM + // Safety check + if (other == NULL) { + ScriptError("trigger '%s' triggered by NULL entity", TargetName().c_str()); + } + // Always respond to activate messages from the world since they're probably from // the "trigger" command - if (!respondTo(other) && !((other == world) && (*ev == EV_Activate)) && (!other || !other->isSubclassOf(Camera))) { + if (!respondTo(other) && (other != world || *ev != EV_Activate) + && (!other || (!other->isSubclassOf(Camera) && !other->isSubclassOf(BarrelObject)))) { return; } @@ -428,7 +457,7 @@ void Trigger::TriggerStuff(Event *ev) // if we setup an angle for this trigger, only trigger if other is within ~60 degrees of the triggers origin // only test for this case if we were touched, activating or killed should never go through this code // - if (useTriggerDir && (*ev == EV_Touch)) { + if (useTriggerDir && (*ev == EV_Touch || (*ev == EV_Use && isSubclassOf(TriggerSidedUse)))) { Vector norm; float dot; @@ -476,7 +505,9 @@ void Trigger::TriggerStuff(Event *ev) whatToTrigger = 0; } - trigger_time = level.time + wait; + if (takedamage == DAMAGE_NO) { + trigger_time = level.time + wait; + } if (!whatToTrigger) { event = new Event(EV_Trigger_Effect); @@ -493,10 +524,14 @@ void Trigger::TriggerStuff(Event *ev) PostEvent(event, delay); // don't trigger the thread if we were triggered by the world touching us - if ((activator != world) || (ev->eventnum != EV_Touch.eventnum)) { + if ((activator != world) || (*ev != EV_Touch)) { event = new Event(EV_Trigger_StartThread); if (activator) { event->AddEntity(activator); + if (activator->IsSubclassOfProjectile()) { + Projectile* proj = static_cast(activator); + event->AddEntity(G_GetEntity(proj->owner)); + } } PostEvent(event, delay); } @@ -535,7 +570,6 @@ void Trigger::TriggerStuff(Event *ev) //============================== // void Trigger::ActivateTargets(Event *ev) - { Entity *other; Entity *ent; @@ -612,13 +646,11 @@ void Trigger::ActivateTargets(Event *ev) } void Trigger::EventSetWait(Event *ev) - { wait = ev->GetFloat(1); } void Trigger::EventSetDelay(Event *ev) - { delay = ev->GetFloat(1); } @@ -631,20 +663,18 @@ void Trigger::EventSetThread(Event *ev) m_Thread.Set(ev->GetString(1)); } } -void Trigger::EventSetCount(Event *ev) +void Trigger::EventSetCount(Event *ev) { count = ev->GetInteger(1); } void Trigger::EventSetMessage(Event *ev) - { SetMessage(ev->GetString(1)); } void Trigger::SetMessage(const char *text) - { if (text) { message = Director.AddString(text); @@ -654,19 +684,16 @@ void Trigger::SetMessage(const char *text) } str& Trigger::Message(void) - { return Director.GetString(message); } void Trigger::EventSetNoise(Event *ev) - { SetNoise(ev->GetString(1)); } void Trigger::SetNoise(const char *text) - { if (text) { noise = Director.AddString(text); @@ -678,7 +705,6 @@ void Trigger::SetNoise(const char *text) } str& Trigger::Noise(void) - { return Director.GetString(noise); } @@ -723,6 +749,57 @@ void Trigger::SetNotTriggerable(Event *ev) triggerable = qfalse; } +void Trigger::DamageEvent(Event *ev) +{ + Entity *attacker; + int damage; + Vector dir; + Vector momentum; + + if (!takedamage) { + return; + } + + if (Immune(ev->GetInteger(9))) { + // trigger is immune + return; + } + + attacker = ev->GetEntity(1); + if (!attacker) { + ScriptError("attacker is NULL"); + } + + if (max_health) { + if (health <= 0) { + return; + } + + damage = ev->GetInteger(2); + health -= damage; + } + + if (health <= 0) { + Event *event; + + if (max_health) { + deadflag = DEAD_DEAD; + } + + event = new Event(EV_Activate, 1); + event->AddEntity(attacker); + ProcessEvent(event); + } + + // notify scripts about the damage + Unregister(STRING_DAMAGE); +} + +void Trigger::EventGetActivator(Event *ev) +{ + ev->AddEntity(activator); +} + void Trigger::Archive(Archiver& arc) { Animate::Archive(arc); @@ -737,6 +814,7 @@ void Trigger::Archive(Archiver& arc) SetNoise(Director.GetString(noise).c_str()); } Director.ArchiveString(arc, message); + m_Thread.Archive(arc); arc.ArchiveSafePointer(&activator); arc.ArchiveInteger(&respondto); arc.ArchiveBoolean(&useTriggerDir); @@ -759,7 +837,7 @@ CLASS_DECLARATION(Trigger, TriggerVehicle, "trigger_vehicle") { qboolean TriggerVehicle::respondTo(Entity *other) { - if ((other->IsSubclassOfVehicle()) || isSubclassOf(VehicleCollisionEntity)) { + if ((other->IsSubclassOfVehicle()) || other->isSubclassOf(VehicleCollisionEntity)) { return qtrue; } else { return qfalse; @@ -793,6 +871,7 @@ If DAMAGE is set, the trigger will only respond to bullets set "message" to text string ******************************************************************************/ + CLASS_DECLARATION(Trigger, TriggerAll, "trigger_multipleall") { {&EV_Touch, &TriggerAll::TriggerStuff}, {&EV_Activate, &TriggerAll::TriggerStuff}, @@ -821,6 +900,12 @@ void TriggerAll::TriggerStuff(Event *ev) ScriptError("trigger '%s' triggered by self", TargetName().c_str()); } + // Fixed in OPM + // Safety check + if (other == NULL) { + ScriptError("trigger '%s' triggered by NULL entity", TargetName().c_str()); + } + // Always respond to activate messages from the world since they're probably from // the "trigger" command if (!respondTo(other) && !((other == world) && (*ev == EV_Activate)) @@ -907,10 +992,14 @@ void TriggerAll::TriggerStuff(Event *ev) PostEvent(event, delay); // don't trigger the thread if we were triggered by the world touching us - if ((activator != world) || (ev->eventnum != EV_Touch.eventnum)) { + if ((activator != world) || (*ev != EV_Touch)) { event = new Event(EV_Trigger_StartThread); if (activator) { event->AddEntity(activator); + if (activator->IsSubclassOfProjectile()) { + Projectile* proj = static_cast(activator); + event->AddEntity(G_GetEntity(proj->owner)); + } } PostEvent(event, delay); } @@ -987,7 +1076,6 @@ TouchField::TouchField() } void TouchField::Setup(Entity *ownerentity, Event& touchevent, Vector min, Vector max, int respondto) - { assert(ownerentity); if (!ownerentity) { @@ -1010,13 +1098,12 @@ void TouchField::Setup(Entity *ownerentity, Event& touchevent, Vector min, Vecto } void TouchField::SendEvent(Event *ev) - { Event *event; // Check if our owner is still around if (owner) { - event = new Event(ontouch); + event = new Event(*ontouch); event->AddEntity(ev->GetEntity(1)); owner->PostEvent(event, delay); } else { @@ -1119,7 +1206,8 @@ set "message" to text string ******************************************************************************/ -Event EV_TriggerSave_SaveName( +Event EV_TriggerSave_SaveName +( "savename", EV_DEFAULT, "s", @@ -1127,6 +1215,16 @@ Event EV_TriggerSave_SaveName( "Sets the name which is appended to the world.message for this specific autosave" ); +TriggerSave::TriggerSave() +{ + if (LoadingSavegame) { + return; + } + + m_sSaveName = ""; + SetTargetName("autosave"); +} + void TriggerSave::SaveGame(Event *ev) { gi.setConfigstring(CS_SAVENAME, m_sSaveName); @@ -1135,13 +1233,13 @@ void TriggerSave::SaveGame(Event *ev) void TriggerSave::EventSaveName(Event *ev) { - m_sSaveName = ev->GetConstString(1); + m_sSaveName = ev->GetString(1); } void TriggerSave::Archive(Archiver& arc) { - Trigger::Archive(arc); - arc.ArchiveString(&m_sSaveName); + Trigger::Archive(arc); + arc.ArchiveString(&m_sSaveName); } CLASS_DECLARATION(Trigger, TriggerSave, "trigger_save") { @@ -1211,7 +1309,6 @@ TriggerSecret::TriggerSecret() } void TriggerSecret::FoundSecret(Event *ev) - { // // anything that causes the trigger to fire increments the number @@ -1219,7 +1316,7 @@ void TriggerSecret::FoundSecret(Event *ev) // secret from the script, the player still gets credit for finding // it. This is to prevent a secret from becoming undiscoverable. // - level.found_secrets++; + level.found_secrets++; } /*****************************************************************************/ @@ -1297,7 +1394,6 @@ void TriggerPush::SetPushDir(Event *ev) } void TriggerPush::SetPushSpeed(Event *ev) - { speed = ev->GetFloat(1); } @@ -1308,7 +1404,7 @@ TriggerPush::TriggerPush() // Archive function will setup all necessary data return; } - speed = 1000; + speed = 1000; } /*****************************************************************************/ @@ -1351,7 +1447,7 @@ TriggerPushAny::TriggerPushAny() // Archive function will setup all necessary data return; } - speed = 1000; + speed = 1000; } void TriggerPushAny::Push(Event *ev) @@ -1432,7 +1528,6 @@ CLASS_DECLARATION(Trigger, TriggerPlaySound, "play_sound_triggered") { }; void TriggerPlaySound::ToggleSound(Event *ev) - { if (!state) { // noise should already be initialized @@ -1458,7 +1553,6 @@ void TriggerPlaySound::ToggleSound(Event *ev) } void TriggerPlaySound::StartSound(void) - { // turn the current one off state = 1; @@ -1470,31 +1564,26 @@ void TriggerPlaySound::StartSound(void) } void TriggerPlaySound::SetVolume(float vol) - { volume = vol; } void TriggerPlaySound::SetVolume(Event *ev) - { volume = ev->GetFloat(1); } void TriggerPlaySound::SetMinDist(float dist) - { min_dist = dist; } void TriggerPlaySound::SetMinDist(Event *ev) - { min_dist = ev->GetFloat(1); } void TriggerPlaySound::SetChannel(Event *ev) - { channel = ev->GetInteger(1); } @@ -1628,7 +1717,6 @@ CLASS_DECLARATION(TriggerSpeaker, RandomSpeaker, "sound_randomspeaker") { }; void RandomSpeaker::TriggerSound(Event *ev) - { ScheduleSound(); if (G_Random(1) <= chance) { @@ -1637,44 +1725,37 @@ void RandomSpeaker::TriggerSound(Event *ev) } void RandomSpeaker::ScheduleSound(void) - { CancelEventsOfType(EV_Trigger_Effect); PostEvent(EV_Trigger_Effect, mindelay + G_Random(maxdelay - mindelay)); } void RandomSpeaker::SetMinDelay(Event *ev) - { mindelay = ev->GetFloat(1); } void RandomSpeaker::SetMaxDelay(Event *ev) - { maxdelay = ev->GetFloat(1); } void RandomSpeaker::SetChance(Event *ev) - { chance = ev->GetFloat(1); } void RandomSpeaker::SetMinDelay(float newMinDelay) - { mindelay = newMinDelay; } void RandomSpeaker::SetMaxDelay(float newMaxDelay) - { maxdelay = newMaxDelay; } void RandomSpeaker::SetChance(float newChance) - { chance = newChance; } @@ -1752,7 +1833,6 @@ TriggerChangeLevel::TriggerChangeLevel() } void TriggerChangeLevel::SetMap(Event *ev) - { map = ev->GetConstString(1); } @@ -1796,7 +1876,7 @@ void TriggerChangeLevel::ChangeLevel(Event *ev) // m_Thread.Execute(); - if (g_gametype->integer) { + if (g_gametype->integer != GT_SINGLE_PLAYER) { G_BeginIntermission2(); return; } @@ -1855,9 +1935,28 @@ CLASS_DECLARATION(Trigger, TriggerUse, "trigger_use") { {NULL, NULL } }; -TriggerUse::TriggerUse() -{ -} +TriggerUse::TriggerUse() {} + +/*****************************************************************************/ +/*QUAKED trigger_sideduse (1 0 0) ? x x NOT_PLAYERS MONSTERS + +Activates targets when 'used' by an entity. It is usable only within specific degrees. +"setthread" name of thread to trigger. This can be in a different script file as well\ +by using the '::' notation. + +"triggerable" turn trigger on +"nottriggerable" turn trigger off + +If NOT_PLAYERS is set, the trigger does not respond to players +If MONSTERS is set, the trigger will respond to monsters + +******************************************************************************/ + +CLASS_DECLARATION(TriggerUse, TriggerSidedUse, "trigger_sideduse") { + {NULL, NULL} +}; + +TriggerSidedUse::TriggerSidedUse() {} /*****************************************************************************/ /*QUAKED trigger_useonce (1 0 0) ? x x NOT_PLAYERS MONSTERS @@ -2005,12 +2104,12 @@ TriggerDamageTargets::TriggerDamageTargets() return; } - damage = 0; + damage = 0; if (spawnflags & 1) { health = 60; max_health = health; - deadflag = DEAD_NO; + deadflag = DEAD_NO; takedamage = DAMAGE_YES; setSolidType(SOLID_BBOX); } else { @@ -2020,13 +2119,11 @@ TriggerDamageTargets::TriggerDamageTargets() } void TriggerDamageTargets::SetDamage(Event *ev) - { damage = ev->GetInteger(1); } void TriggerDamageTargets::PassDamage(Event *ev) - { Entity *attacker; int dmg; @@ -2062,7 +2159,6 @@ void TriggerDamageTargets::PassDamage(Event *ev) // void TriggerDamageTargets::DamageTargets(Event *ev) - { Entity *other; Entity *ent; @@ -2212,17 +2308,15 @@ CLASS_DECLARATION(Trigger, TriggerExit, "trigger_exit") { TriggerExit::TriggerExit() { - wait = 1; + wait = 1; } void TriggerExit::TurnExitSignOff(Event *ev) - { level.near_exit = false; } void TriggerExit::DisplayExitSign(Event *ev) - { level.near_exit = qtrue; @@ -2262,7 +2356,8 @@ Event EV_TriggerBox_SetMins EV_DEFAULT, "v", "mins", - "Sets the minimum bounds of the trigger box.", EV_NORMAL + "Sets the minimum bounds of the trigger box.", + EV_NORMAL ); Event EV_TriggerBox_SetMaxs ( @@ -2417,7 +2512,7 @@ TriggerMusic::TriggerMusic() SetOneShot(false); - noise = STRING_EMPTY; + noise = STRING_EMPTY; current = STRING_NORMAL; fallback = STRING_NORMAL; @@ -2499,13 +2594,13 @@ void TriggerMusic::SetOneShot(Event *ev) void TriggerMusic::Archive(Archiver& arc) { - Trigger::Archive(arc); + Trigger::Archive(arc); - arc.ArchiveBoolean(&oneshot); - Director.ArchiveString(arc, current); - Director.ArchiveString(arc, fallback); - Director.ArchiveString(arc, altcurrent); - Director.ArchiveString(arc, altfallback); + arc.ArchiveBoolean(&oneshot); + Director.ArchiveString(arc, current); + Director.ArchiveString(arc, fallback); + Director.ArchiveString(arc, altcurrent); + Director.ArchiveString(arc, altfallback); } /*****************************************************************************/ @@ -2625,7 +2720,7 @@ TriggerReverb::TriggerReverb() SetOneShot(false); - noise = STRING_EMPTY; + noise = STRING_EMPTY; reverbtype = 0; altreverbtype = 0; @@ -2738,7 +2833,6 @@ void TriggerByPushObject::setTriggerName(Event *event) } qboolean TriggerByPushObject::respondTo(Entity *other) - { if (other->isSubclassOf(PushObject)) { if (triggername != STRING_EMPTY) { @@ -2752,7 +2846,6 @@ qboolean TriggerByPushObject::respondTo(Entity *other) } Entity *TriggerByPushObject::getActivator(Entity *other) - { Entity *owner; @@ -2769,11 +2862,19 @@ Entity *TriggerByPushObject::getActivator(Entity *other) void TriggerByPushObject::Archive(Archiver& arc) { - TriggerOnce::Archive(arc); + TriggerOnce::Archive(arc); - Director.ArchiveString(arc, triggername); + Director.ArchiveString(arc, triggername); } +/*****************************************************************************/ +/*QUAKED trigger_givepowerup (1 0 0) ? x x NOT_PLAYERS MONSTERS x x x DAMAGE +Special trigger that can be triggered to give special items to sentients. + +"cnt" how many times it can be triggered (default 1, use -1 for infinite) +"powerupname" the name of the powerup to give to sentients +******************************************************************************/ + Event EV_TriggerGivePowerup_OneShot ( "oneshot", @@ -2793,10 +2894,10 @@ Event EV_TriggerGivePowerup_PowerupName ); CLASS_DECLARATION(Trigger, TriggerGivePowerup, "trigger_givepowerup") { - {&EV_TriggerGivePowerup_OneShot, &TriggerGivePowerup::SetOneShot }, - {&EV_TriggerGivePowerup_PowerupName, &TriggerGivePowerup::SetPowerupName}, - {&EV_Trigger_Effect, &TriggerGivePowerup::GivePowerup }, - {NULL, NULL } + {&EV_TriggerGivePowerup_OneShot, &TriggerGivePowerup::SetOneShot }, + {&EV_TriggerGivePowerup_PowerupName, &TriggerGivePowerup::SetPowerupName}, + {&EV_Trigger_Effect, &TriggerGivePowerup::GivePowerup }, + {NULL, NULL } }; TriggerGivePowerup::TriggerGivePowerup() @@ -2824,37 +2925,37 @@ TriggerGivePowerup::TriggerGivePowerup() trigger_time = (float)0; - oneshot = false; + oneshot = false; count = -1; noise = STRING_EMPTY; powerup_name = STRING_EMPTY; } -void TriggerGivePowerup::SetOneShot(Event* ev) +void TriggerGivePowerup::SetOneShot(Event *ev) { trigger_time = 0.f; oneshot = true; count = 1; } -void TriggerGivePowerup::SetPowerupName(Event* ev) +void TriggerGivePowerup::SetPowerupName(Event *ev) { powerup_name = ev->GetConstString(1); } -void TriggerGivePowerup::GivePowerup(Event* ev) +void TriggerGivePowerup::GivePowerup(Event *ev) { - Entity* other = ev->GetEntity(1); - Sentient* sen; - str powerup_name_str; + Entity *other = ev->GetEntity(1); + Sentient *sen; + str powerup_name_str; if (!other->IsSubclassOfSentient()) { // ignore non-sentient entities return; } - sen = static_cast(other); + sen = static_cast(other); powerup_name_str = Director.GetString(powerup_name); if (sen->FindItem(powerup_name_str)) { // sentient already has that item, so ignore @@ -2874,10 +2975,10 @@ void TriggerGivePowerup::GivePowerup(Event* ev) void TriggerGivePowerup::Archive(Archiver& arc) { - Trigger::Archive(arc); + Trigger::Archive(arc); - arc.ArchiveBoolean(&oneshot); - Director.ArchiveString(arc, powerup_name); + arc.ArchiveBoolean(&oneshot); + Director.ArchiveString(arc, powerup_name); } /***************************************************************************** @@ -2931,6 +3032,27 @@ void TriggerClickItem::SetClickItemModelEvent(Event *ev) link(); } +//=============== +// +// Added in 2.0 +// +//=============== + +/*****************************************************************************/ +/*QUAKED trigger_nodamage (1 0 0) ? x x NOT_PLAYERS MONSTERS + +Activates targets when 'used' by an entity. It cannot take damage. +"setthread" name of thread to trigger. This can be in a different script file as well\ +by using the '::' notation. + +"triggerable" turn trigger on +"nottriggerable" turn trigger off + +If NOT_PLAYERS is set, the trigger does not respond to players +If MONSTERS is set, the trigger will respond to monsters + +******************************************************************************/ + CLASS_DECLARATION(TriggerUse, TriggerNoDamage, "trigger_nodamage") { {&EV_Touch, &TriggerNoDamage::TakeNoDamage}, {&EV_Trigger_Effect, &TriggerNoDamage::TakeNoDamage}, @@ -2951,10 +3073,59 @@ void TriggerNoDamage::TakeNoDamage(Event *ev) ent->PostEvent(newev, level.frametime * 3); } +//=============== +// +// Added in 2.30 +// +//=============== + +/*****************************************************************************/ +/*QUAKED trigger_entity (1 0 0) ? + +Variable sized repeatable trigger that respond to entities. Must be targeted at one or more entities. + +If "health" is set, the trigger must be killed to activate each time. +If "delay" is set, the trigger waits some time after activating before firing. + +"setthread" name of thread to trigger. This can be in a different script file as well\ +by using the '::' notation. + +if "angle" is set, the trigger will only fire when someone is facing the +direction of the angle. +"cone" the cone in which a directed trigger can be triggered (default 60 degrees) + +"wait" : Seconds between triggerings. (.2 default) +"cnt" how many times it can be triggered (infinite default) + +"triggerable" turn trigger on +"nottriggerable" turn trigger off + +set "message" to text string + +******************************************************************************/ + CLASS_DECLARATION(Trigger, TriggerEntity, "trigger_entity") { {NULL, NULL} }; +qboolean TriggerEntity::respondTo(Entity* other) +{ + return other != NULL && other->IsSubclassOfEntity() != false; +} + +/*****************************************************************************/ +/*QUAKED trigger_landmine (1 0 0) ? + +Variable sized repeatable trigger for landmine. Must be handled by scripts. + +"setthread" name of thread to trigger. This can be in a different script file as well\ +by using the '::' notation. + +"triggerable" turn trigger on +"nottriggerable" turn trigger off + +******************************************************************************/ + Event EV_Trigger_IsAbandoned ( "isabandoned", @@ -3031,9 +3202,9 @@ void TriggerLandmine::EventIsAbandoned(Event *ev) weapontype = p->GetCurrentDMWeaponType(); if (!str::icmp(weapontype, "landmine")) { - ev->AddInteger(1); - } else { ev->AddInteger(0); + } else { + ev->AddInteger(1); } } diff --git a/code/fgame/trigger.h b/code/fgame/trigger.h index 469fea92..1a4e56e9 100644 --- a/code/fgame/trigger.h +++ b/code/fgame/trigger.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // trigger.h: Environment based triggers. // -#ifndef __TRIGGER_H__ -#define __TRIGGER_H__ +#pragma once #include "glb_local.h" #include "animate.h" @@ -56,8 +55,8 @@ protected: float trigger_time; qboolean triggerActivated; int count; - const_str noise; - const_str message; + const_str noise; + const_str message; ScriptThreadLabel m_Thread; EntityPtr activator; int respondto; @@ -116,6 +115,8 @@ public: void StartThread(Event *ev); void TriggerStuff(Event *ev); void ActivateTargets(Event *ev); + void DamageEvent(Event *ev) override; + void EventGetActivator(Event *ev); // Added in 2.30 void Archive(Archiver& arc) override; }; @@ -171,7 +172,7 @@ public: TouchField(); virtual void Setup(Entity *ownerentity, Event& ontouch, Vector min, Vector max, int respondto); void SendEvent(Event *ev); - void Archive(Archiver &arc) override; + void Archive(Archiver& arc) override; }; inline void TouchField::Archive(Archiver& arc) @@ -191,7 +192,7 @@ public: TriggerOnce(); }; -class TriggerSave : public Trigger +class TriggerSave : public TriggerOnce { private: str m_sSaveName; @@ -199,6 +200,8 @@ private: public: CLASS_PROTOTYPE(TriggerSave); + TriggerSave(); + void SaveGame(Event *ev); void EventSaveName(Event *ev); void Archive(Archiver& arc) override; @@ -377,7 +380,7 @@ public: void ChangeLevel(Event *ev); const char *Map(void); const char *SpawnSpot(void); - void Archive(Archiver &arc) override; + void Archive(Archiver& arc) override; }; class TriggerExit : public Trigger @@ -398,6 +401,17 @@ public: TriggerUse(); }; +// +// Added in 2.30 +// Can only be triggered if within specific degrees +class TriggerSidedUse : public TriggerUse +{ +public: + CLASS_PROTOTYPE(TriggerSidedUse); + + TriggerSidedUse(); +}; + class TriggerUseOnce : public TriggerUse { public: @@ -590,6 +604,10 @@ inline void TriggerClickItem::Archive(Archiver& arc) Trigger::Archive(arc); } +// +// Added in 2.0 +// + class TriggerNoDamage : public TriggerUse { public: @@ -599,10 +617,17 @@ public: void TakeNoDamage(Event *ev); }; +// +// Added in 2.30 +// + class TriggerEntity : public Trigger { public: CLASS_PROTOTYPE(TriggerEntity); + +public: + qboolean respondTo(Entity *other) override; }; class TriggerLandmine : public TriggerEntity @@ -631,5 +656,3 @@ inline void TriggerLandmine::Archive(Archiver& arc) arc.ArchiveInteger(&team); } - -#endif /* trigger.h */ diff --git a/code/fgame/umap.h b/code/fgame/umap.h index e3cdfdae..2a44a341 100644 --- a/code/fgame/umap.h +++ b/code/fgame/umap.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -24,8 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // stored data. // -#ifndef __UMAP_H__ -#define __UMAP_H__ +#pragma once #include "str.h" #include @@ -335,5 +334,3 @@ inline unsigned UMap::getNumEntries { return m_numentries; } - -#endif /* !__UMAP_H__ */ diff --git a/code/fgame/vehicle.cpp b/code/fgame/vehicle.cpp index a97359f8..6f8ca73b 100644 --- a/code/fgame/vehicle.cpp +++ b/code/fgame/vehicle.cpp @@ -37,784 +37,918 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "debuglines.h" Event EV_Vehicle_Start - ( - "start", - EV_DEFAULT, - NULL, - NULL, - "Initialize the vehicle." - ); - +( + "start", + EV_DEFAULT, + NULL, + NULL, + "Initialize the vehicle.", + EV_NORMAL +); Event EV_Vehicle_Enter - ( - "enter", - EV_DEFAULT, - "eS", - "vehicle driver_anim", - "Called when someone gets into a vehicle." - ); - +( + "enter", + EV_DEFAULT, + "eS", + "vehicle driver_anim", + "Called when someone gets into a vehicle.", + EV_NORMAL +); Event EV_Vehicle_Exit - ( - "exit", - EV_DEFAULT, - "e", - "entity", - "Called when driver gets out of the vehicle." - ); - +( + "exit", + EV_DEFAULT, + "e", + "vehicle", + "Called when driver gets out of the vehicle.", + EV_NORMAL +); Event EV_Vehicle_Drivable - ( - "drivable", - EV_DEFAULT, - NULL, - NULL, - "Make the vehicle drivable" - ); - +( + "drivable", + EV_DEFAULT, + NULL, + NULL, + "Make the vehicle drivable", + EV_NORMAL +); Event EV_Vehicle_UnDrivable - ( - "undrivable", - EV_DEFAULT, - NULL, - NULL, - "Make the vehicle undrivable" - ); - +( + "undrivable", + EV_DEFAULT, + NULL, + NULL, + "Make the vehicle undrivable", + EV_NORMAL +); +Event EV_Vehicle_PathDrivable +( + "pathDrivable", + EV_DEFAULT, + "b", + "pathDrivable", + "Make the vehicle drivable along a path", + EV_NORMAL +); Event EV_Vehicle_Jumpable - ( - "canjump", - EV_DEFAULT, - "b", - "jumpable", - "Sets whether or not the vehicle can jump" - ); - +( + "canjump", + EV_DEFAULT, + "b", + "jumpable", + "Sets whether or not the vehicle can jump", + EV_NORMAL +); Event EV_Vehicle_Lock - ( - "lock", - EV_DEFAULT, - NULL, - NULL, - "Sets the vehicle to be locked" - ); - +( + "lock", + EV_DEFAULT, + NULL, + NULL, + "Sets the vehicle to be locked", + EV_NORMAL +); Event EV_Vehicle_UnLock - ( - "unlock", - EV_DEFAULT, - NULL, - NULL, - "Sets the vehicle to be unlocked" - ); - +( + "unlock", + EV_DEFAULT, + NULL, + NULL, + "Sets the vehicle to be unlocked", + EV_NORMAL +); Event EV_Vehicle_SeatAnglesOffset - ( - "seatangles", - EV_DEFAULT, - "v", - "angles", - "Set the angles offset of the seat" - ); - +( + "seatanglesoffset", + EV_DEFAULT, + "v", + "angles", + "Set the angles offset of the seat", + EV_NORMAL +); Event EV_Vehicle_SeatOffset - ( - "seatoffset", - EV_DEFAULT, - "v", - "offset", - "Set the offset of the seat" - ); - - +( + "seatoffset", + EV_DEFAULT, + "v", + "offset", + "Set the offset of the seat", + EV_NORMAL +); Event EV_Vehicle_SetWeapon - ( - "setweapon", - EV_DEFAULT, - "s", - "weaponname", - "Set the weapon for the vehicle" - ); - +( + "setweapon", + EV_DEFAULT, + "s", + "weaponname", + "Set the weapon for the vehicle", + EV_NORMAL +); +Event EV_Vehicle_SetName +( + "name", + EV_DEFAULT, + "s", + "vehicleName", + "Set the name for the vehicle", + EV_NORMAL +); Event EV_Vehicle_ShowWeapon - ( - "showweapon", - EV_DEFAULT, - NULL, - NULL, - "Set the weapon to be show in the view" - ); - +( + "showweapon", + EV_DEFAULT, + NULL, + NULL, + "Set the weapon to be show in the view", + EV_NORMAL +); Event EV_Vehicle_SetSpeed - ( - "vehiclespeed", - EV_DEFAULT, - "f", - "speed", - "Set the speed of the vehicle" - ); - +( + "vehiclespeed", + EV_DEFAULT, + "f", + "speed", + "Set the speed of the vehicle", + EV_NORMAL +); Event EV_Vehicle_SetTurnRate - ( - "turnrate", - EV_DEFAULT, - "f", - "rate", - "Set the turning rate of the vehicle" - ); - +( + "turnrate", + EV_DEFAULT, + "f", + "rate", + "Set the turning rate of the vehicle", + EV_NORMAL +); Event EV_Vehicle_SteerInPlace - ( - "steerinplace", - EV_DEFAULT, - NULL, - NULL, - "Set the vehicle to turn in place" - ); - +( + "steerinplace", + EV_DEFAULT, + NULL, + NULL, + "Set the vehicle to turn in place", + EV_NORMAL +); Event EV_Vehicle_Destroyed - ( - "vehicledestroyed", - EV_DEFAULT, - NULL, - NULL, - "Driver is dead" - ); - +( + "vehicledestroyed", + EV_DEFAULT, + NULL, + NULL, + "Driver is dead", + EV_NORMAL +); Event EV_Vehicle_Mass - ( - "vehiclemass", - EV_DEFAULT, - "f", - "weight", - "Sets the mass of the vehicle (backmass = frontmass = mass/2)" - ); - +( + "vehiclemass", + EV_DEFAULT, + "f", + "weight", + "Sets the mass of the vehicle (backmass = frontmass = mass/2)", + EV_NORMAL +); Event EV_Vehicle_Front_Mass - ( - "front_mass", - EV_DEFAULT, - "f", - "weight", - "Sets the mass of the front of the vehicle" - ); - +( + "front_mass", + EV_DEFAULT, + "f", + "weight", + "Sets the mass of the front of the vehicle", + EV_NORMAL +); Event EV_Vehicle_Back_Mass - ( - "back_mass", - EV_DEFAULT, - "f", - "weight", - "Sets the mass of the back of the vehicle" - ); - +( + "back_mass", + EV_DEFAULT, + "f", + "weight", + "Sets the mass of the back of the vehicle", + EV_NORMAL +); Event EV_Vehicle_Tread - ( - "vehicletread", - EV_DEFAULT, - "f", - "size", - "Sets the size of the wheels" - ); - +( + "vehicletread", + EV_DEFAULT, + "f", + "size", + "Sets the size of the wheels", + EV_NORMAL +); Event EV_Vehicle_Radius - ( - "vehicleradius", - EV_DEFAULT, - "f", - "size", - "Sets the radius of the wheels" - ); - +( + "vehicleradius", + EV_DEFAULT, + "f", + "size", + "Sets the radius of the wheels", + EV_NORMAL +); Event EV_Vehicle_RollingResistance - ( - "vehiclerollingresistance", - EV_DEFAULT, - "f", - "size", - "Sets the radius of the wheels" - ); - +( + "vehiclerollingresistance", + EV_DEFAULT, + "f", + "size", + "Sets the radius of the wheels", + EV_NORMAL +); Event EV_Vehicle_Drag - ( - "vehicledrag", - EV_DEFAULT, - "f", - "size", - "Sets the Drag Factor" - ); - +( + "vehicledrag", + EV_DEFAULT, + "f", + "size", + "Sets the Drag Factor", + EV_NORMAL +); Event EV_Vehicle_Drive - ( - "drive", - EV_DEFAULT, - "vffffV", - "position speed acceleration reach_distance look_ahead alternate_position", - "Makes the vehicle drive to position with speed and acceleration until reached_distance close to position" - ); - +( + "drive", + EV_DEFAULT, + "vffffV", + "position speed acceleration reach_distance look_ahead alternate_position", + "Makes the vehicle drive to position with speed and acceleration until reached_distance close to position", + EV_NORMAL +); Event EV_Vehicle_DriveNoWait - ( - "driveNo", - EV_DEFAULT, - "vfff", - "position speed acceleration reach_distance", - "Makes the vehicle drive to position with speed and acceleration until reached_distance close to position, thread doesn't wait" - ); - +( + "driveNoWait", + EV_DEFAULT, + "vfff", + "position speed acceleration reach_distance", + "Makes the vehicle drive to position with speed and acceleration until reached_distance close to position, thread " + "doesn't wait", + EV_NORMAL +); Event EV_Vehicle_Stop - ( - "stop", - EV_DEFAULT, - NULL, - NULL, - "Make the Vehicle Stop Moving... FULL BREAKS!" - ); - +( + "stop", + EV_DEFAULT, + NULL, + NULL, + "Make the Vehicle Stop Moving... FULL BREAKS!", + EV_NORMAL +); Event EV_Vehicle_FullStop - ( - "fullstop", - EV_DEFAULT, - NULL, - NULL, - "Make the Vehicle Stop Moving... Completely!" - ); - +( + "fullstop", + EV_DEFAULT, + NULL, + NULL, + "Make the Vehicle Stop Moving... Completely!", + EV_NORMAL +); Event EV_Vehicle_Init - ( - "vehicleinit", - EV_DEFAULT, - NULL, - NULL, - "Initialized the Vehicle as the specified file" - ); - +( + "vehicleinit", + EV_DEFAULT, + NULL, + NULL, + "Initialized the Vehicle as the specified file", + EV_NORMAL +); Event EV_Vehicle_BouncyCoef - ( - "vehiclebouncy", - EV_DEFAULT, - "f", - "bouncycoef", - "Sets the Bouncy Coefficient for the shocks." - ); - +( + "vehiclebouncy", + EV_DEFAULT, + "f", + "bouncycoef", + "Sets the Bouncy Coefficient for the shocks.", + EV_NORMAL +); Event EV_Vehicle_SpringyCoef - ( - "vehiclespringy", - EV_DEFAULT, - "f", - "springycoef", - "Sets the Springy Coefficient for the shocks." - ); - +( + "vehiclespringy", + EV_DEFAULT, + "f", + "springycoef", + "Sets the Springy Coefficient for the shocks.", + EV_NORMAL +); Event EV_Vehicle_Yaw - ( - "vehicleYaw", - EV_DEFAULT, - "fff", - "min max coef", - "Sets the Yaw min and max and the acceleration coefficient for the shocks." - ); - +( + "vehicleYaw", + EV_DEFAULT, + "fff", + "min max coef", + "Sets the Yaw min and max and the acceleration coefficient for the shocks.", + EV_NORMAL +); Event EV_Vehicle_Roll - ( - "vehicleRoll", - EV_DEFAULT, - "fff", - "min max coef", - "Sets the Roll min and max and the acceleration coefficient for the shocks." - ); - +( + "vehicleRoll", + EV_DEFAULT, + "fff", + "min max coef", + "Sets the Roll min and max and the acceleration coefficient for the shocks.", + EV_NORMAL +); Event EV_Vehicle_Z - ( - "vehicleZ", - EV_DEFAULT, - "fff", - "min max coef", - "Sets the Z min and max and the acceleration coefficient for the shocks." - ); - +( + "vehicleZ", + EV_DEFAULT, + "fff", + "min max coef", + "Sets the Z min and max and the acceleration coefficient for the shocks.", + EV_NORMAL +); +Event EV_Vehicle_QuerySpeed +( + "QuerySpeed", + EV_DEFAULT, + "f", + "speed", + "Returns the current speed of the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryFreePassengerSlot - ( - "QueryFreePassengerSlot", - EV_DEFAULT, - NULL, - NULL, - "Returns a number that represents the first free passenger slot on the vehicle.", - EV_RETURN ); - +( + "QueryFreePassengerSlot", + EV_DEFAULT, + NULL, + NULL, + "Returns a number that represents the first free passenger slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryPassengerSlotPosition - ( - "QueryPassengerSlotPosition", - EV_DEFAULT, - "i", - "slot", - "Returns the position of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryPassengerSlotPosition", + EV_DEFAULT, + "i", + "slot", + "Returns the position of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryPassengerSlotStatus - ( - "QueryPassengerSlotStatus", - EV_DEFAULT, - "i", - "slot", - "Returns the status of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryPassengerSlotStatus", + EV_DEFAULT, + "i", + "slot", + "Returns the status of the specified slot on the vehicle.", + EV_RETURN +); +Event EV_Vehicle_BounceForwardsVelocity +( + "BounceForwardsVelocity", + EV_DEFAULT, + NULL, + NULL, + "For vehicles on rails that are moving forwards, reverse our velocity.", + EV_NORMAL +); +Event EV_Vehicle_BounceBackwardsVelocity +( + "BounceBackwardsVelocity", + EV_DEFAULT, + "i", + "bStayFullSpeed", + "For vehicles on rails that are moving backwards, reverse our velocity. (Optionally pass bStayFullSpeed to keep " + "vehic" + "le at full speed after the bounce)", + EV_NORMAL +); +Event EV_Vehicle_StopForwardsVelocity +( + "StopForwardsVelocity", + EV_DEFAULT, + NULL, + NULL, + "Stops any forward motion for vehicles on rails.", + EV_NORMAL +); +Event EV_Vehicle_StopBackwardsVelocity +( + "StopBackwardsVelocity", + EV_DEFAULT, + NULL, + NULL, + "Stops any backwards motion for vehicles on rails.", + EV_NORMAL +); Event EV_Vehicle_AttachPassengerSlot - ( - "AttachPassengerSlot", - EV_DEFAULT, - "ie", - "slot entity", - "Attaches an entity to the specified slot." - ); - +( + "AttachPassengerSlot", + EV_DEFAULT, + "ie", + "slot entity", + "Attaches an entity to the specified slot.", + EV_NORMAL +); Event EV_Vehicle_QueryPassengerSlotEntity - ( - "QueryPassengerSlotEntity", - EV_DEFAULT, - "i", - "slot", - "Returns an entity at the specified slot.", - EV_RETURN ); - +( + "QueryPassengerSlotEntity", + EV_DEFAULT, + "i", + "slot", + "Returns an entity at the specified slot.", + EV_RETURN +); Event EV_Vehicle_DetachPassengerSlot - ( - "DetachPassengerSlot", - EV_DEFAULT, - "iV", - "slot exit_", - "Detaches an entity to the specified slot." - ); - +( + "DetachPassengerSlot", + EV_DEFAULT, + "iV", + "slot exit_position", + "Detaches an entity to the specified slot.", + EV_NORMAL +); Event EV_Vehicle_QueryFreeDriverSlot - ( - "QueryFreeDriverSlot", - EV_DEFAULT, - NULL, - NULL, - "Returns a number that represents the first free driver slot on the vehicle.", - EV_RETURN ); - +( + "QueryFreeDriverSlot", + EV_DEFAULT, + NULL, + NULL, + "Returns a number that represents the first free driver slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryDriverSlotPosition - ( - "QueryDriverSlotPosition", - EV_DEFAULT, - "i", - "slot", - "Returns the position of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryDriverSlotPosition", + EV_DEFAULT, + "i", + "slot", + "Returns the position of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryDriverSlotStatus - ( - "QueryDriverSlotStatus", - EV_DEFAULT, - "i", - "slot", - "Returns the status of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryDriverSlotStatus", + EV_DEFAULT, + "i", + "slot", + "Returns the status of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_AttachDriverSlot - ( - "AttachDriverSlot", - EV_DEFAULT, - "ie", - "slot entity", - "Attaches an entity to the specified slot." - ); - +( + "AttachDriverSlot", + EV_DEFAULT, + "ie", + "slot entity", + "Attaches an entity to the specified slot.", + EV_NORMAL +); Event EV_Vehicle_QueryDriverSlotEntity - ( - "QueryDriverSlotEntity", - EV_DEFAULT, - "i", - "slot", - "Returns an entity at the specified slot.", - EV_RETURN ); - +( + "QueryDriverSlotEntity", + EV_DEFAULT, + "i", + "slot", + "Returns an entity at the specified slot.", + EV_RETURN +); Event EV_Vehicle_DetachDriverSlot - ( - "DetachDriverSlot", - EV_DEFAULT, - "iV", - "slot exit_", - "Detaches an entity to the specified slot." - ); - +( + "DetachDriverSlot", + EV_DEFAULT, + "iV", + "slot exit_position", + "Detaches an entity to the specified slot.", + EV_NORMAL +); Event EV_Vehicle_QueryFreeTurretSlot - ( - "QueryFreeTurretSlot", - EV_DEFAULT, - NULL, - NULL, - "Returns a number that represents the first free turret slot on the vehicle.", - EV_RETURN ); - +( + "QueryFreeTurretSlot", + EV_DEFAULT, + NULL, + NULL, + "Returns a number that represents the first free turret slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryTurretSlotPosition - ( - "QueryTurretSlotPosition", - EV_DEFAULT, - "i", - "slot", - "Returns the position of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryTurretSlotPosition", + EV_DEFAULT, + "i", + "slot", + "Returns the position of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryTurretSlotStatus - ( - "QueryTurretSlotStatus", - EV_DEFAULT, - "i", - "slot", - "Returns the status of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryTurretSlotStatus", + EV_DEFAULT, + "i", + "slot", + "Returns the status of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_AttachTurretSlot - ( - "AttachTurretSlot", - EV_DEFAULT, - "ie", - "slot entity", - "Attaches an entity to the specified slot." - ); - +( + "AttachTurretSlot", + EV_DEFAULT, + "ie", + "slot entity", + "Attaches an entity to the specified slot.", + EV_NORMAL +); Event EV_Vehicle_QueryTurretSlotEntity - ( - "QueryTurretSlotEntity", - EV_DEFAULT, - "i", - "slot", - "Returns an entity at the specified slot.", - EV_RETURN ); - +( + "QueryTurretSlotEntity", + EV_DEFAULT, + "i", + "slot", + "Returns an entity at the specified slot.", + EV_RETURN +); Event EV_Vehicle_DetachTurretSlot - ( - "DetachTurretSlot", - EV_DEFAULT, - "iV", - "slot exit_", - "Detaches an entity to the specified slot." - ); - +( + "DetachTurretSlot", + EV_DEFAULT, + "iV", + "slot exit_position", + "Detaches an entity to the specified slot.", + EV_NORMAL +); Event EV_Vehicle_WheelCorners - ( - "VehicleWheelCorners", - EV_DEFAULT, - "vv", - "size offset", - "Sets the wheel trace corners." - ); - +( + "VehicleWheelCorners", + EV_DEFAULT, + "vv", + "size offset", + "Sets the wheel trace corners.", + EV_NORMAL +); Event EV_Vehicle_QueryDriverSlotAngles - ( - "QueryDriverSlotAngles", - EV_DEFAULT, - "i", - "slot", - "Returns the angles of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryDriverSlotAngles", + EV_DEFAULT, + "i", + "slot", + "Returns the angles of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryPassengerSlotAngles - ( - "QueryDriverSlotAngles", - EV_DEFAULT, - "i", - "slot", - "Returns the angles of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryDriverSlotAngles", + EV_DEFAULT, + "i", + "slot", + "Returns the angles of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_QueryTurretSlotAngles - ( - "QueryDriverSlotAngles", - EV_DEFAULT, - "i", - "slot", - "Returns the angles of the specified slot on the vehicle.", - EV_RETURN ); - +( + "QueryDriverSlotAngles", + EV_DEFAULT, + "i", + "slot", + "Returns the angles of the specified slot on the vehicle.", + EV_RETURN +); Event EV_Vehicle_AnimationSet - ( - "AnimationSet", - EV_DEFAULT, - "s", - "animset", - "Sets the Animation Set to use." - ); - +( + "AnimationSet", + EV_DEFAULT, + "s", + "animset", + "Sets the Animation Set to use.", + EV_NORMAL +); Event EV_Vehicle_SoundSet - ( - "SoundSet", - EV_DEFAULT, - "s", - "soundset", - "Sets the Sound Set to use." - ); - +( + "SoundSet", + EV_DEFAULT, + "s", + "soundset", + "Sets the Sound Set to use.", + EV_NORMAL +); Event EV_Vehicle_SpawnTurret - ( - "spawnturret", - EV_DEFAULT, - "is", - "slot tikifile", - "Spawns a turret with the specified model and connects it to the specified slot" - ); - +( + "spawnturret", + EV_DEFAULT, + "is", + "slot tikifile", + "Spawns a turret with the specified model and connects it to the specified slot", + EV_NORMAL +); Event EV_Vehicle_ModifyDrive - ( - "modifydrive", - EV_DEFAULT, - "fff", - "desired_speed acceleration look_ahead", - "Modifys the parameters of the current drive." - ); - +( + "modifydrive", + EV_DEFAULT, + "fff", + "desired_speed acceleration look_ahead", + "Modifys the parameters of the current drive.", + EV_NORMAL +); Event EV_Vehicle_NextDrive - ( - "nextdrive", - EV_DEFAULT, - "e", - "next_path", - "appends the specified path to the current path" - ); - +( + "nextdrive", + EV_DEFAULT, + "e", + "next_path", + "appends the specified path to the current path", + EV_NORMAL +); Event EV_Vehicle_StopAtEnd - ( - "stopatend", - EV_DEFAULT, - NULL, - NULL, - "Makes the vehicle slow down to a complete stop at the end of the path." - ); - +( + "stopatend", + EV_DEFAULT, + NULL, + NULL, + "Makes the vehicle slow down to a complete stop at the end of the path.", + EV_NORMAL +); Event EV_Vehicle_LockMovement - ( - "lockmovement", - EV_DEFAULT, - NULL, - NULL, - "The Vehicle cannot move." - ); - +( + "lockmovement", + EV_DEFAULT, + NULL, + NULL, + "The Vehicle cannot move.", + EV_NORMAL +); Event EV_Vehicle_UnlockMovement - ( - "unlockmovement", - EV_DEFAULT, - NULL, - NULL, - "The Vehicle can move again." - ); - +( + "unlockmovement", + EV_DEFAULT, + NULL, + NULL, + "The Vehicle can move again.", + EV_NORMAL +); Event EV_Vehicle_RemoveOnDeath - ( - "removeondeath", - EV_DEFAULT, - "i", - "removeondeath", - "If set to a non-zero value, vehicles will not be removed when they die" - ); - +( + "removeondeath", + EV_DEFAULT, + "i", + "removeondeath", + "If set to a non-zero value, vehicles will not be removed when they die", + EV_NORMAL +); Event EV_Vehicle_SetExplosionModel - ( - "explosionmodel", - EV_DEFAULT, - "s", - "model", - "Sets the TIKI to call when the vehicle dies." - ); - +( + "explosionmodel", + EV_DEFAULT, + "s", + "model", + "Sets the TIKI to call when the vehicle dies.", + EV_NORMAL +); Event EV_Vehicle_SetCollisionEntity - ( - "setcollisionentity", - EV_DEFAULT, - "e", - "entity", - "Sets the Collision Entity." - ); - +( + "setcollisionentity", + EV_DEFAULT, + "e", + "entity", + "Sets the Collision Entity.", + EV_NORMAL +); Event EV_Vehicle_CollisionEntitySetter - ( - "collisionent", - EV_DEFAULT, - "e", - "entity", - "Gets the Collision Entity", - EV_SETTER ); - +( + "collisionent", + EV_DEFAULT, + "e", + "entity", + "Gets the Collision Entity", + EV_SETTER +); Event EV_Vehicle_CollisionEntityGetter - ( - "collisionent", - EV_DEFAULT, - NULL, - NULL, - "Gets the Collision Entity", - EV_GETTER ); - +( + "collisionent", + EV_DEFAULT, + NULL, + NULL, + "Gets the Collision Entity", + EV_GETTER +); Event EV_Vehicle_SetSoundParameters - ( - "setsoundparameters", - EV_DEFAULT, - "ffff", - "min_speed min_pitch max_speed max_pitch", - "Sets the Sound parameters for this vehicle" - ); - +( + "setsoundparameters", + EV_DEFAULT, + "ffff", + "min_speed min_pitch max_speed max_pitch", + "Sets the Sound parameters for this vehicle", + EV_NORMAL +); Event EV_Vehicle_SetVolumeParameters - ( - "setvolumeparameters", - EV_DEFAULT, - "ffff", - "min_speed min_volume max_speed max_volume", - "Sets the Volume parameters for this vehicle" - ); - +( + "setvolumeparameters", + EV_DEFAULT, + "ffff", + "min_speed min_volume max_speed max_volume", + "Sets the Volume parameters for this vehicle", + EV_NORMAL +); Event EV_Vehicle_Skidding - ( - "skidding", - EV_DEFAULT, - "i", - "on_off", - "Makes the vehicle skid around corners." - ); - +( + "skidding", + EV_DEFAULT, + "i", + "on_off", + "Makes the vehicle skid around corners.", + EV_NORMAL +); Event EV_Vehicle_ContinueSkidding - ( - "_continue", - EV_DEFAULT, - NULL, - NULL, - "Continues the skidding animation of a vehicle." - ); - +( + "_continueskidding", + EV_DEFAULT, + NULL, + NULL, + "Continues the skidding animation of a vehicle.", + EV_NORMAL +); Event EV_Vehicle_VehicleAnim - ( - "vehicleanim", - EV_DEFAULT, - "sF", - "anim_name weight", - "Sets an animation to use in the LD Animation slot. \nWeight defaults to 1.0" - ); - +( + "vehicleanim", + EV_DEFAULT, + "sF", + "anim_name weight", + "Sets an animation to use in the LD Animation slot. \nWeight defaults to 1.0", + EV_NORMAL +); Event EV_Vehicle_VehicleAnimDone - ( - "_vehicleanimdone", - EV_DEFAULT, - NULL, - NULL, - "For Internal Use Only" - ); +( + "_vehicleanimdone", + EV_DEFAULT, + NULL, + NULL, + "For Internal Use Only", + EV_NORMAL +); +Event EV_Vehicle_VehicleMoveAnim +( + "moveanim", + EV_DEFAULT, + "s", + "anim_name", + "move the vehicle with an animation", + EV_NORMAL +); +Event EV_Vehicle_VehicleMoveAnimDone +( + "_moveanimdone", + EV_DEFAULT, + NULL, + NULL, + "For Internal Use Only", + EV_NORMAL +); +Event EV_Vehicle_DamageSounds +( + "damagesounds", + EV_DEFAULT, + "i", + "on_off", + "Makes the vehicle play damaged sounds.", + EV_NORMAL +); +Event EV_Vehicle_RunSounds +( + "runsounds", + EV_DEFAULT, + "i", + "on_off", + "Makes the vehicle play running sounds.", + EV_NORMAL +); +Event EV_Vehicle_ProjectileVulnerable +( + "projectilevulnerable", + EV_DEFAULT, + "I", + "number_of_hits", + "Make vehicle vulnerable to being one-shot by projectiles. If number_of_hits is given, it will take this many " + "shots.", + EV_NORMAL +); +Event EV_Vehicle_CanUse +( + "canuse", + EV_DEFAULT, + "e", + "entity", + "Returns 1 if passed entity can 'use' this vehicle.", + EV_RETURN +); cvar_t *g_showvehiclemovedebug; cvar_t *g_showvehicleentrypoints; cvar_t *g_showvehicleslotpoints; +cvar_t *g_showvehicletags; cvar_t *g_showvehiclepath; -CLASS_DECLARATION( Animate, VehicleBase, NULL ) -{ - { NULL, NULL } +CLASS_DECLARATION(Animate, VehicleBase, NULL) { + {NULL, NULL} }; VehicleBase::VehicleBase() { - offset = "0 0 0"; + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } - if( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } + takedamage = DAMAGE_NO; + showModel(); - takedamage = DAMAGE_NO; - edict->s.renderfx &= ~RF_DONTDRAW; - edict->r.svFlags &= ~SVF_NOCLIENT; + // + // rotate the mins and maxs for the model + // + setSize(mins, maxs); - // - // rotate the mins and maxs for the model - // - setSize( mins, maxs ); + vlink = NULL; + offset = vec_zero; - vlink = NULL; - offset = vec_zero; - - PostEvent( EV_BecomeNonSolid, EV_POSTSPAWN ); + PostEvent(EV_BecomeNonSolid, EV_POSTSPAWN); } -CLASS_DECLARATION( VehicleBase, Vehicle, "script_vehicle" ) -{ - { &EV_Blocked, &Vehicle::VehicleBlocked }, - { &EV_Touch, &Vehicle::VehicleTouched }, - { &EV_Use, &Vehicle::DriverUse }, - { &EV_Vehicle_Start, &Vehicle::VehicleStart }, - { &EV_Vehicle_Drivable, &Vehicle::Drivable }, - { &EV_Vehicle_UnDrivable, &Vehicle::UnDrivable }, - { &EV_Vehicle_Jumpable, &Vehicle::Jumpable }, - { &EV_Vehicle_SeatAnglesOffset, &Vehicle::SeatAnglesOffset }, - { &EV_Vehicle_SeatOffset, &Vehicle::SeatOffset }, - { &EV_Vehicle_Lock, &Vehicle::Lock }, - { &EV_Vehicle_UnLock, &Vehicle::UnLock }, - { &EV_Vehicle_SetWeapon, &Vehicle::SetWeapon }, - { &EV_Vehicle_SetSpeed, &Vehicle::SetSpeed }, - { &EV_Vehicle_SetTurnRate, &Vehicle::SetTurnRate }, - { &EV_Vehicle_SteerInPlace, &Vehicle::SteerInPlace }, - { &EV_Vehicle_ShowWeapon, &Vehicle::ShowWeaponEvent }, - { &EV_Damage, &Vehicle::EventDamage }, - { &EV_Vehicle_Destroyed, &Vehicle::VehicleDestroyed }, - { &EV_Vehicle_Mass, &Vehicle::SetMass }, - { &EV_Vehicle_Front_Mass, &Vehicle::SetFrontMass }, - { &EV_Vehicle_Back_Mass, &Vehicle::SetBackMass }, - { &EV_Vehicle_Tread, &Vehicle::SetTread }, - { &EV_Vehicle_RollingResistance, &Vehicle::SetRollingResistance }, - { &EV_Vehicle_Drag, &Vehicle::SetDrag }, - { &EV_Vehicle_Drive, &Vehicle::EventDrive }, - { &EV_Vehicle_DriveNoWait, &Vehicle::EventDriveNoWait }, - { &EV_Vehicle_Stop, &Vehicle::EventStop }, - { &EV_Vehicle_FullStop, &Vehicle::EventFullStop }, - { &EV_Vehicle_BouncyCoef, &Vehicle::BouncyCoef }, - { &EV_Vehicle_SpringyCoef, &Vehicle::SpringyCoef }, - { &EV_Vehicle_Yaw, &Vehicle::GetYaw }, - { &EV_Vehicle_Roll, &Vehicle::RollMinMax }, - { &EV_Vehicle_Z, &Vehicle::ZMinMax }, - { &EV_Vehicle_QueryFreePassengerSlot, &Vehicle::QueryFreePassengerSlot }, - { &EV_Vehicle_QueryFreeDriverSlot, &Vehicle::QueryFreeDriverSlot }, - { &EV_Vehicle_QueryFreeTurretSlot, &Vehicle::QueryFreeTurretSlot }, - { &EV_Vehicle_QueryPassengerSlotPosition, &Vehicle::QueryPassengerSlotPosition }, - { &EV_Vehicle_QueryDriverSlotPosition, &Vehicle::QueryDriverSlotPosition }, - { &EV_Vehicle_QueryTurretSlotPosition, &Vehicle::QueryTurretSlotPosition }, - { &EV_Vehicle_QueryPassengerSlotStatus, &Vehicle::QueryPassengerSlotStatus }, - { &EV_Vehicle_QueryDriverSlotStatus, &Vehicle::QueryDriverSlotStatus }, - { &EV_Vehicle_QueryTurretSlotStatus, &Vehicle::QueryTurretSlotStatus }, - { &EV_Vehicle_QueryPassengerSlotEntity, &Vehicle::QueryPassengerSlotEntity }, - { &EV_Vehicle_QueryDriverSlotEntity, &Vehicle::QueryDriverSlotEntity }, - { &EV_Vehicle_QueryTurretSlotEntity, &Vehicle::QueryTurretSlotEntity }, - { &EV_Vehicle_QueryDriverSlotAngles, &Vehicle::QueryDriverSlotAngles }, - { &EV_Vehicle_QueryPassengerSlotAngles, &Vehicle::QueryPassengerSlotAngles }, - { &EV_Vehicle_QueryTurretSlotAngles, &Vehicle::QueryTurretSlotAngles }, - { &EV_Vehicle_AttachPassengerSlot, &Vehicle::AttachPassengerSlot }, - { &EV_Vehicle_AttachDriverSlot, &Vehicle::AttachDriverSlot }, - { &EV_Vehicle_AttachTurretSlot, &Vehicle::AttachTurretSlot }, - { &EV_Vehicle_DetachPassengerSlot, &Vehicle::DetachPassengerSlot }, - { &EV_Vehicle_DetachDriverSlot, &Vehicle::DetachDriverSlot }, - { &EV_Vehicle_DetachTurretSlot, &Vehicle::DetachTurretSlot }, - { &EV_Vehicle_WheelCorners, &Vehicle::SetWheelCorners }, - { &EV_Vehicle_AnimationSet, &Vehicle::SetAnimationSet }, - { &EV_Vehicle_SoundSet, &Vehicle::SetSoundSet }, - { &EV_Vehicle_ModifyDrive, &Vehicle::EventModifyDrive }, - { &EV_Model, &Vehicle::EventModel }, - { &EV_Vehicle_NextDrive, &Vehicle::EventNextDrive }, - { &EV_Vehicle_LockMovement, &Vehicle::EventLockMovement }, - { &EV_Vehicle_UnlockMovement, &Vehicle::EventUnlockMovement }, - { &EV_Vehicle_RemoveOnDeath, &Vehicle::EventRemoveOnDeath }, - { &EV_Vehicle_SetExplosionModel, &Vehicle::EventSetExplosionModel }, - { &EV_Vehicle_SetCollisionEntity, &Vehicle::EventSetCollisionModel }, - { &EV_Vehicle_SetSoundParameters, &Vehicle::EventSetSoundParameters }, - { &EV_Vehicle_SetVolumeParameters, &Vehicle::EventSetVolumeParameters }, - { &EV_Vehicle_StopAtEnd, &Vehicle::EventStopAtEnd }, - { &EV_Vehicle_Skidding, &Vehicle::EventSkidding }, - { &EV_Vehicle_ContinueSkidding, &Vehicle::EventContinueSkidding }, - { &EV_Vehicle_CollisionEntitySetter, &Vehicle::EventSetCollisionModel }, - { &EV_Vehicle_CollisionEntityGetter, &Vehicle::EventGetCollisionModel }, - { &EV_Vehicle_VehicleAnim, &Vehicle::EventVehicleAnim }, - { &EV_Vehicle_VehicleAnimDone, &Vehicle::EventVehicleAnimDone }, - { NULL, NULL } +CLASS_DECLARATION(VehicleBase, Vehicle, "script_vehicle") { + {&EV_Blocked, &Vehicle::VehicleBlocked }, + {&EV_Touch, &Vehicle::VehicleTouched }, + {&EV_Use, &Vehicle::DriverUse }, + {&EV_Vehicle_Start, &Vehicle::VehicleStart }, + {&EV_Vehicle_Drivable, &Vehicle::Drivable }, + {&EV_Vehicle_PathDrivable, &Vehicle::PathDrivable }, + {&EV_Vehicle_ProjectileVulnerable, &Vehicle::SetProjectileVulnerable }, + {&EV_Vehicle_UnDrivable, &Vehicle::UnDrivable }, + {&EV_Vehicle_Jumpable, &Vehicle::Jumpable }, + {&EV_Vehicle_SeatAnglesOffset, &Vehicle::SeatAnglesOffset }, + {&EV_Vehicle_SeatOffset, &Vehicle::SeatOffset }, + {&EV_Vehicle_Lock, &Vehicle::Lock }, + {&EV_Vehicle_UnLock, &Vehicle::UnLock }, + {&EV_Vehicle_SetWeapon, &Vehicle::SetWeapon }, + {&EV_Vehicle_SetName, &Vehicle::SetName }, + {&EV_Vehicle_SetSpeed, &Vehicle::SetSpeed }, + {&EV_Vehicle_SetTurnRate, &Vehicle::SetTurnRate }, + {&EV_Vehicle_SteerInPlace, &Vehicle::SteerInPlace }, + {&EV_Vehicle_ShowWeapon, &Vehicle::ShowWeaponEvent }, + {&EV_Damage, &Vehicle::EventDamage }, + {&EV_Vehicle_Destroyed, &Vehicle::VehicleDestroyed }, + {&EV_Vehicle_Mass, &Vehicle::SetMass }, + {&EV_Vehicle_Front_Mass, &Vehicle::SetFrontMass }, + {&EV_Vehicle_Back_Mass, &Vehicle::SetBackMass }, + {&EV_Vehicle_Tread, &Vehicle::SetTread }, + {&EV_Vehicle_Radius, &Vehicle::SetTireRadius }, + {&EV_Vehicle_RollingResistance, &Vehicle::SetRollingResistance }, + {&EV_Vehicle_Drag, &Vehicle::SetDrag }, + {&EV_Vehicle_Drive, &Vehicle::EventDrive }, + {&EV_Vehicle_DriveNoWait, &Vehicle::EventDriveNoWait }, + {&EV_Vehicle_Stop, &Vehicle::EventStop }, + {&EV_Vehicle_FullStop, &Vehicle::EventFullStop }, + {&EV_Vehicle_Init, &Vehicle::ModelInit }, + {&EV_Vehicle_BouncyCoef, &Vehicle::BouncyCoef }, + {&EV_Vehicle_SpringyCoef, &Vehicle::SpringyCoef }, + {&EV_Vehicle_Yaw, &Vehicle::GetYaw }, + {&EV_Vehicle_Roll, &Vehicle::RollMinMax }, + {&EV_Vehicle_Z, &Vehicle::ZMinMax }, + {&EV_Vehicle_QuerySpeed, &Vehicle::QuerySpeed }, + {&EV_Vehicle_QueryFreePassengerSlot, &Vehicle::QueryFreePassengerSlot }, + {&EV_Vehicle_QueryFreeDriverSlot, &Vehicle::QueryFreeDriverSlot }, + {&EV_Vehicle_QueryFreeTurretSlot, &Vehicle::QueryFreeTurretSlot }, + {&EV_Vehicle_QueryPassengerSlotPosition, &Vehicle::QueryPassengerSlotPosition}, + {&EV_Vehicle_QueryDriverSlotPosition, &Vehicle::QueryDriverSlotPosition }, + {&EV_Vehicle_QueryTurretSlotPosition, &Vehicle::QueryTurretSlotPosition }, + {&EV_Vehicle_QueryPassengerSlotStatus, &Vehicle::QueryPassengerSlotStatus }, + {&EV_Vehicle_QueryDriverSlotStatus, &Vehicle::QueryDriverSlotStatus }, + {&EV_Vehicle_QueryTurretSlotStatus, &Vehicle::QueryTurretSlotStatus }, + {&EV_Vehicle_QueryPassengerSlotEntity, &Vehicle::QueryPassengerSlotEntity }, + {&EV_Vehicle_QueryDriverSlotEntity, &Vehicle::QueryDriverSlotEntity }, + {&EV_Vehicle_QueryTurretSlotEntity, &Vehicle::QueryTurretSlotEntity }, + {&EV_Vehicle_QueryDriverSlotAngles, &Vehicle::QueryDriverSlotAngles }, + {&EV_Vehicle_QueryPassengerSlotAngles, &Vehicle::QueryPassengerSlotAngles }, + {&EV_Vehicle_BounceForwardsVelocity, &Vehicle::BounceForwardsVelocity }, + {&EV_Vehicle_BounceBackwardsVelocity, &Vehicle::BounceBackwardsVelocity }, + {&EV_Vehicle_StopBackwardsVelocity, &Vehicle::StopBackwardsVelocity }, + {&EV_Vehicle_StopBackwardsVelocity, &Vehicle::StopBackwardsVelocity }, + {&EV_Vehicle_QueryTurretSlotAngles, &Vehicle::QueryTurretSlotAngles }, + {&EV_Vehicle_AttachPassengerSlot, &Vehicle::AttachPassengerSlot }, + {&EV_Vehicle_AttachDriverSlot, &Vehicle::AttachDriverSlot }, + {&EV_Vehicle_AttachTurretSlot, &Vehicle::AttachTurretSlot }, + {&EV_Vehicle_DetachPassengerSlot, &Vehicle::DetachPassengerSlot }, + {&EV_Vehicle_DetachDriverSlot, &Vehicle::DetachDriverSlot }, + {&EV_Vehicle_DetachTurretSlot, &Vehicle::DetachTurretSlot }, + {&EV_Vehicle_WheelCorners, &Vehicle::SetWheelCorners }, + {&EV_Vehicle_AnimationSet, &Vehicle::SetAnimationSet }, + {&EV_Vehicle_SoundSet, &Vehicle::SetSoundSet }, + {&EV_Vehicle_SpawnTurret, &Vehicle::SpawnTurret }, + {&EV_Vehicle_ModifyDrive, &Vehicle::EventModifyDrive }, + {&EV_Model, &Vehicle::EventModel }, + {&EV_Vehicle_NextDrive, &Vehicle::EventNextDrive }, + {&EV_Vehicle_LockMovement, &Vehicle::EventLockMovement }, + {&EV_Vehicle_UnlockMovement, &Vehicle::EventUnlockMovement }, + {&EV_Vehicle_RemoveOnDeath, &Vehicle::EventRemoveOnDeath }, + {&EV_Vehicle_SetExplosionModel, &Vehicle::EventSetExplosionModel }, + {&EV_Vehicle_SetCollisionEntity, &Vehicle::EventSetCollisionModel }, + {&EV_Vehicle_SetSoundParameters, &Vehicle::EventSetSoundParameters }, + {&EV_Vehicle_SetVolumeParameters, &Vehicle::EventSetVolumeParameters }, + {&EV_Vehicle_StopAtEnd, &Vehicle::EventStopAtEnd }, + {&EV_Vehicle_Skidding, &Vehicle::EventSkidding }, + {&EV_Vehicle_ContinueSkidding, &Vehicle::EventContinueSkidding }, + {&EV_Vehicle_CollisionEntitySetter, &Vehicle::EventSetCollisionModel }, + {&EV_Vehicle_CollisionEntityGetter, &Vehicle::EventGetCollisionModel }, + {&EV_Vehicle_VehicleAnim, &Vehicle::EventVehicleAnim }, + {&EV_Vehicle_VehicleAnimDone, &Vehicle::EventVehicleAnimDone }, + {&EV_Vehicle_VehicleMoveAnim, &Vehicle::EventVehicleMoveAnim }, + {&EV_Vehicle_VehicleMoveAnimDone, &Vehicle::EventVehicleMoveAnimDone }, + {&EV_Vehicle_DamageSounds, &Vehicle::EventDamageSounds }, + {&EV_Vehicle_RunSounds, &Vehicle::EventRunSounds }, + {&EV_Remove, &Vehicle::Remove }, + {&EV_Turret_SetMaxUseAngle, &Vehicle::EventSetMaxUseAngle }, + {&EV_Vehicle_CanUse, &Vehicle::EventCanUse }, + {NULL, NULL } }; /* @@ -824,137 +958,235 @@ Vehicle::Vehicle */ Vehicle::Vehicle() { - entflags |= EF_VEHICLE; + int i; - g_showvehiclemovedebug = gi.Cvar_Get( "g_showvehiclemovedebug", "0", 0 ); - g_showvehicleentrypoints = gi.Cvar_Get( "g_showvehicleentrypoints", "0", 0 ); - g_showvehicleslotpoints = gi.Cvar_Get( "g_showvehicleslotpoints", "0", 0 ); - g_showvehiclepath = gi.Cvar_Get( "g_showvehiclepath", "0", 0 ); + entflags |= ECF_VEHICLE; - if( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } + AddWaitTill(STRING_DRIVE); + AddWaitTill(STRING_VEHICLEANIMDONE); + AddWaitTill(STRING_ANIMDONE); - edict->s.eType = ET_VEHICLE; + g_showvehiclemovedebug = gi.Cvar_Get("g_showvehiclemovedebug", "0", 0); + g_showvehicleentrypoints = gi.Cvar_Get("g_showvehicleentrypoints", "0", 0); + g_showvehicleslotpoints = gi.Cvar_Get("g_showvehicleslotpoints", "0", 0); + g_showvehicletags = gi.Cvar_Get("g_showvehicletags", "0", 0); + g_showvehiclepath = gi.Cvar_Get("g_showvehiclepath", "0", 0); - takedamage = DAMAGE_YES; - seatangles = vec_zero; - driveroffset = Vector( 0, 0, 50 ); - seatoffset = vec_zero; - currentspeed = 0; - turnangle = 0; - turnimpulse = 0; - moveimpulse = 0; - jumpimpulse = 0; - conesize = 75; - hasweapon = false; - locked = true; - steerinplace = false; - drivable = false; - jumpable = false; - showweapon = false; - hasweapon = false; - flags |= FL_TOUCH_TRIGGERS | FL_POSTTHINK | FL_THINK | FL_DIE_EXPLODE; - // touch triggers by default - gravity = 1; - mass = size.length() * 10; + for (i = 0; i < NUM_VEHICLE_TIRES; i++) { + VectorClear(m_vTireEnd[i]); + } + m_bTireHit[0] = false; + VectorClear(m_vNormalSum); + m_iNumNormals = 0; - health = 1000; - speed = 1200; - maxturnrate = 60.0f; + if (LoadingSavegame) { + // Archive function will setup all necessary data + return; + } - m_vAngles = angles; - prev_acceleration = vec_zero; - real_acceleration = vec_zero; - prev_origin = origin; - real_velocity = vec_zero; - prev_velocity = velocity; - m_vPrevNormal = vec_zero; - prev_moveimpulse = 0; - m_iFrameCtr = 0; - m_bFrontSlipping = qfalse; - m_bBackSlipping = qfalse; - m_vAngularVelocity = vec_zero; - m_vAngularAcceleration = vec_zero; - m_sMoveGrid = new cMoveGrid( 3, 3, 1 ); - m_bAutoPilot = qfalse; - m_fIdealSpeed = 0; - m_fIdealAccel = 0; - m_fIdealDistance = 100; - m_vOriginOffset = vec_zero; - m_vOriginOffset2 = vec_zero; - m_vAnglesOffset = vec_zero; - m_fBouncyCoef = 0.2f; - m_fSpringyCoef = 0.8f; - m_fYawMin = -10.0f; - m_fYawMax = 10.0f; - m_fYawCoef = 0.1f; - m_fRollMin = -10.0f; - m_fRollMax = 10.0f; - m_fRollCoef = 0.1f; - m_fZMin = -10.0f; - m_fZMax = 10.0f; - m_fZCoef = 0.1f; - v_angle = vec_zero; - m_pCurPath = NULL; - m_bThinkCalled = qfalse; - m_iCurNode = 0; - m_pAlternatePath = NULL; - m_pNextPath = NULL; - m_iNextPathStartNode = 0; - vs.hit_obstacle = qfalse; - m_iAlternateNode = 0; - m_fLookAhead = 0; - m_fShaderOffset = 0; - vs.groundTrace.fraction = 1.0f; - edict->clipmask = MASK_VEHICLE; - m_fLeftForce = 0; - m_fRightForce = 0; - m_fForwardForce = 0; - m_fBackForce = 0; - m_fUpForce = 0; - m_fDownForce = 0; - edict->s.eFlags |= EF_LINKANGLES; - m_bMovementLocked = qfalse; - m_bRemoveOnDeath = qfalse; - m_sExplosionModel = "fx/fx_explosion.tik"; - m_pCollisionEntity = NULL; - m_fSoundMinPitch = 0.95f; - m_fSoundMinSpeed = 0; - m_fSoundMaxPitch = 1.0f; - m_fSoundMaxSpeed = 200.0f; - m_fVolumeMinPitch = 1.0f; - m_fVolumeMinSpeed = 0; - m_fVolumeMaxPitch = 1.5f; - m_fVolumeMaxSpeed = 200.0f; - m_eSoundState = ST_OFF; - m_fNextSoundState = level.time; - m_pVehicleSoundEntities[ 0 ] = NULL; - m_pVehicleSoundEntities[ 1 ] = NULL; - m_pVehicleSoundEntities[ 2 ] = NULL; - m_pVehicleSoundEntities[ 3 ] = NULL; - m_bStopEnabled = qfalse; - m_bEnableSkidding = qfalse; - m_vSkidOrigin = vec_zero; - m_fSkidLeftForce = 0; - m_fSkidRightForce = 0; - m_sAnimationSet = ""; - m_sSoundSet = ""; - m_iLastTiresUpdate = -1; - m_vTireEnd[ 0 ] = origin; - m_bTireHit[ 0 ] = false; - m_vTireEnd[ 1 ] = origin; - m_bTireHit[ 1 ] = false; - m_vTireEnd[ 2 ] = origin; - m_bTireHit[ 2 ] = false; - m_vTireEnd[ 3 ] = origin; - m_bTireHit[ 3 ] = false; + edict->s.eType = ET_VEHICLE; - ResetSlots(); + moveresult = 0; + isBlocked = false; + m_iGear = 1; + m_iRPM = 0; + maxtracedist = 0; + airspeed = 0; + for (i = 0; i < 6; i++) { + m_fGearRatio[i] = 0; + } - PostEvent( EV_Vehicle_Start, EV_POSTSPAWN ); + m_fMass = 0; + m_fFrontMass = 0; + m_fBackMass = 0; + + m_fWheelBase = 0.0; + m_fWheelFrontLoad = 0.0; + m_fWheelFrontInnerLoad = 0.0; + m_fWheelFrontOutterLoad = 0.0; + m_fWheelFrontDist = 0.0; + m_fWheelFrontSuspension = 0.0; + m_fWheelBackLoad = 0.0; + m_fWheelBackInnerLoad = 0.0; + m_fWheelBackOutterLoad = 0.0; + m_fWheelBackDist = 0.0; + m_fWheelBackSuspension = 0.0; + + m_fCGHeight = 0.0; + m_fBankAngle = 0.0; + m_fTread = 0.0; + m_fTrackWidth = 0.0; + m_fTireFriction = 0.0; + m_fDrag = 0.0; + m_fTireRadius = 0.0; + m_fFrontBrakes = 0.0; + m_fBackBrakes = 0.0; + + m_fRollingResistance = 0.0; + m_fTireRotationalSpeed = 0.0; + m_fFrontBrakingForce = 0.0; + m_fBackBrakingForce = 0.0; + m_fBrakingPerformance = 0.0; + + m_fLastTurn = 0.0; + m_fTangForce = 0.0; + m_fInertia = 0.0; + m_fDifferentialRatio = 0.0; + m_fGearEfficiency = 0.0; + m_fMaxTraction = 0.0; + m_fTractionForce = 0.0; + m_fAccelerator = 0.0; + m_fTorque = 0.0; + m_fStopStartDistance = 0.0; + m_fStopStartSpeed = 0.0; + m_fStopEndDistance = 0.0; + m_bWheelSpinning = 0; + m_bIsSkidding = 0; + m_bIsBraking = 0; + m_bAutomatic = 0; + m_iNumNormals = 0; + + memset(&vs, 0, sizeof(vs)); + takedamage = DAMAGE_YES; + seatangles = vec_zero; + driveroffset = Vector(0, 0, 50); + seatoffset = vec_zero; + currentspeed = 0; + turnangle = 0; + turnimpulse = 0; + moveimpulse = 0; + jumpimpulse = 0; + conesize = 75; + hasweapon = false; + locked = true; + steerinplace = false; + drivable = false; + pathDrivable = false; + jumpable = false; + showweapon = false; + m_iProjectileHitsRemaining = 0; + + flags |= FL_TOUCH_TRIGGERS | FL_POSTTHINK | FL_THINK | FL_DIE_EXPLODE; + // touch triggers by default + gravity = 1; + mass = size.length() * 10; + + health = 1000; + speed = 1200; + maxturnrate = 60.0f; + m_vAngles = angles; + + prev_acceleration = vec_zero; + real_acceleration = vec_zero; + prev_origin = origin; + real_velocity = vec_zero; + prev_velocity = velocity; + + m_vPrevNormal = vec_zero; + prev_moveimpulse = 0; + + m_iFrameCtr = 0; + m_bFrontSlipping = qfalse; + m_bBackSlipping = qfalse; + + m_vAngularVelocity = vec_zero; + m_vAngularAcceleration = vec_zero; + + m_sMoveGrid = new cMoveGrid(3, 3, 1); + + m_bAutoPilot = qfalse; + m_fIdealSpeed = 0; + m_fMaxSpeed = 0; + m_fIdealAccel = 0; + m_fIdealDistance = 100; + m_bBounceBackwards = false; + + m_vOriginOffset = vec_zero; + m_vOriginOffset2 = vec_zero; + m_vAnglesOffset = vec_zero; + + m_fBouncyCoef = 0.2f; + m_fSpringyCoef = 0.8f; + m_fYawMin = -10.0f; + m_fYawMax = 10.0f; + m_fYawCoef = 0.1f; + m_fRollMin = -10.0f; + m_fRollMax = 10.0f; + m_fRollCoef = 0.1f; + m_fZMin = -10.0f; + m_fZMax = 10.0f; + m_fZCoef = 0.1f; + + m_vAngularVelocity = vec_zero; + m_vAngularAcceleration = vec_zero; + v_angle = vec_zero; + m_bThinkCalled = qfalse; + m_pCurPath = NULL; + m_iCurNode = 0; + m_pAlternatePath = NULL; + m_iAlternateNode = 0; + m_pNextPath = NULL; + m_iNextPathStartNode = -1; + + m_fLookAhead = 0; + m_fShaderOffset = 0; + vs.hit_obstacle = false; + vs.groundTrace.fraction = 1.0f; + edict->clipmask = MASK_VEHICLE; + + m_fLeftForce = 0; + m_fRightForce = 0; + m_fForwardForce = 0; + m_fBackForce = 0; + m_fUpForce = 0; + m_fDownForce = 0; + + edict->s.eFlags |= EF_LINKANGLES; + + m_bMovementLocked = qfalse; + m_bRemoveOnDeath = qtrue; + m_sExplosionModel = "fx/fx_explosion.tik"; + m_pCollisionEntity = NULL; + + m_fSoundMinPitch = 0.95f; + m_fSoundMinSpeed = 0; + m_fSoundMaxPitch = 1.0f; + m_fSoundMaxSpeed = 200.0f; + m_fVolumeMinPitch = 1.0f; + m_fVolumeMinSpeed = 0; + m_fVolumeMaxPitch = 1.5f; + m_fVolumeMaxSpeed = 200.0f; + + m_eSoundState = ST_OFF; + m_fNextSoundState = level.time; + m_pVehicleSoundEntities[0] = NULL; + m_pVehicleSoundEntities[1] = NULL; + m_pVehicleSoundEntities[2] = NULL; + m_pVehicleSoundEntities[3] = NULL; + + m_bStopEnabled = qfalse; + m_bEnableSkidding = qfalse; + m_fSkidAngle = 0; + m_vSkidOrigin = vec_zero; + m_fSkidLeftForce = 0; + m_fSkidRightForce = 0; + + m_sAnimationSet = ""; + m_sSoundSet = ""; + + m_iLastTiresUpdate = -1; + for (i = 0; i < NUM_VEHICLE_TIRES; i++) { + m_vTireEnd[i] = origin; + m_bTireHit[i] = false; + } + + m_bAnimMove = false; + m_fMaxUseAngle = 0; + m_bBounceStayFullSpeed = false; + + ResetSlots(); + + PostEvent(EV_Vehicle_Start, EV_POSTSPAWN); } /* @@ -964,2760 +1196,13 @@ Vehicle::~Vehicle */ Vehicle::~Vehicle() { - for( int i = 0; i < MAX_SOUND_ENTITIES; i++ ) - { - if( m_pVehicleSoundEntities[ i ] ) - m_pVehicleSoundEntities[ i ]->PostEvent( EV_Remove, EV_LINKDOORS ); - } + RemoveVehicleSoundEntities(); - if( m_pCollisionEntity ) - m_pCollisionEntity->ProcessEvent( EV_Remove ); + if (m_pCollisionEntity) { + m_pCollisionEntity->ProcessEvent(EV_Remove); + } - entflags &= ~EF_VEHICLE; -} - -/* -==================== -Vehicle::VehicleStart -==================== -*/ -void Vehicle::VehicleStart - ( - Event *ev - ) -{ - Entity *ent; - VehicleBase *last; - Vector drivemins, drivemaxs; - float max; - orientation_t orient; - - // become solid - setSolidType( SOLID_BBOX ); - edict->r.contents = CONTENTS_BBOX; - - last = this; - - setLocalOrigin( localorigin + Vector( 0.0f, 0.0f, 30.0f ) ); - angles = m_vAngles; - - for( ent = G_NextEntity( NULL ); ent != NULL; ent = G_NextEntity( ent ) ) - { - if( ( ent != this ) && ( ent->isSubclassOf( VehicleBase ) ) ) - { - if( ( ent->absmax.x >= absmin.x ) && ( ent->absmax.y >= absmin.y ) && ( ent->absmax.z >= absmin.z ) && - ( ent->absmin.x <= absmax.x ) && ( ent->absmin.y <= absmax.y ) && ( ent->absmin.z <= absmax.z ) ) - { - last->vlink = ( VehicleBase * )ent; - last = ( VehicleBase * )ent; - last->offset = last->origin - origin; - last->offset = getLocalVector( last->offset ); - last->edict->s.scale *= edict->s.scale; - } - } - } - - last->vlink = NULL; - - OpenSlotsByModel(); - - // - // get the seat offset - // - if( GetRawTag( "seat", &orient ) ) - { - driveroffset = Vector( orient.origin ); - } - driveroffset += seatoffset * edict->s.scale; - - SetDriverAngles( angles + seatangles ); - - max_health = health; - - // - // calculate drive mins and maxs - // - max = 0; - if( fabs( mins[ 0 ] ) > max ) - max = fabs( mins[ 0 ] ); - if( fabs( maxs[ 0 ] ) > max ) - max = fabs( maxs[ 0 ] ); - if( fabs( mins[ 1 ] ) > max ) - max = fabs( mins[ 1 ] ); - if( fabs( maxs[ 1 ] ) > max ) - max = fabs( maxs[ 1 ] ); - drivemins = Vector( -max, -max, mins[ 2 ] ) * edict->s.scale; - drivemaxs = Vector( max, max, maxs[ 2 ] ) * edict->s.scale; - - last_origin = origin; - link(); -} - -/* -==================== -Vehicle::Drivable -==================== -*/ -void Vehicle::Drivable - ( - Event *ev - ) -{ - setMoveType( MOVETYPE_VEHICLE ); - drivable = true; -} - -/* -==================== -Vehicle::UnDrivable -==================== -*/ -void Vehicle::UnDrivable - ( - Event *ev - ) -{ - setMoveType( MOVETYPE_PUSH ); - drivable = false; -} - -/* -==================== -Vehicle::Jumpable -==================== -*/ -void Vehicle::Jumpable - ( - Event *ev - ) -{ - jumpable = true; -} - -/* -==================== -Vehicle::Lock -==================== -*/ -void Vehicle::Lock - ( - Event *ev - ) -{ - Lock(); -} - -/* -==================== -Vehicle::UnLock -==================== -*/ -void Vehicle::UnLock - ( - Event *ev - ) -{ - UnLock(); -} - -/* -==================== -Vehicle::SteerInPlace -==================== -*/ -void Vehicle::SteerInPlace - ( - Event *ev - ) -{ - steerinplace = true; -} - -/* -==================== -Vehicle::SeatAnglesOffset -==================== -*/ -void Vehicle::SeatAnglesOffset - ( - Event *ev - ) -{ - seatangles = ev->GetVector( 1 ); -} - -/* -==================== -Vehicle::SeatOffset -==================== -*/ -void Vehicle::SeatOffset - ( - Event *ev - ) -{ - seatoffset = ev->GetVector( 1 ); -} - -/* -==================== -Vehicle::SetWeapon -==================== -*/ -void Vehicle::SetWeapon - ( - Event *ev - ) -{ - showweapon = true; - hasweapon = true; - weaponName = ev->GetString( 1 ); -} - -/* -==================== -Vehicle::ShowWeaponEvent -==================== -*/ -void Vehicle::ShowWeaponEvent - ( - Event *ev - ) -{ - showweapon = true; -} - -/* -==================== -Vehicle::HasWeapon -==================== -*/ -qboolean Vehicle::HasWeapon - ( - void - ) -{ - return hasweapon; -} - -/* -==================== -Vehicle::ShowWeapon -==================== -*/ -qboolean Vehicle::ShowWeapon - ( - void - ) -{ - return showweapon; -} - -/* -==================== -Vehicle::SetDriverAngles -==================== -*/ -void Vehicle::SetDriverAngles - ( - Vector angles - ) -{ - int i; - - if( !driver.ent ) - return; - - for( i = 0; i < 3; i++ ) - { - driver.ent->client->ps.delta_angles[ i ] = ANGLE2SHORT( angles[ i ] - driver.ent->client->cmd_angles[ i ] ); - } -} - -/* -==================== -Vehicle::CheckWater -==================== -*/ -void Vehicle::CheckWater - ( - void - ) -{ - Vector point; - int cont; - int sample1; - int sample2; - VehicleBase *v; - - unlink(); - v = this; - while( v->vlink ) - { - v = v->vlink; - v->unlink(); - } - - if( driver.ent ) - { - driver.ent->unlink(); - } - - // - // get waterlevel - // - waterlevel = 0; - watertype = 0; - - sample2 = maxs[ 2 ] - mins[ 2 ]; - sample1 = sample2 / 2; - - point = origin; - point[ 2 ] += mins[ 2 ]; - cont = gi.pointcontents( point, 0 ); - - if( cont & MASK_WATER ) - { - watertype = cont; - waterlevel = 1; - point[ 2 ] = origin[ 2 ] + mins[ 2 ] + sample1; - cont = gi.pointcontents( point, 0 ); - if( cont & MASK_WATER ) - { - waterlevel = 2; - point[ 2 ] = origin[ 2 ] + mins[ 2 ] + sample2; - cont = gi.pointcontents( point, 0 ); - if( cont & MASK_WATER ) - { - waterlevel = 3; - } - } - } - - link(); - v = this; - while( v->vlink ) - { - v = v->vlink; - v->link(); - } - - if( driver.ent ) - { - driver.ent->link(); - driver.ent->waterlevel = waterlevel; - driver.ent->watertype = watertype; - } -} - -/* -==================== -Vehicle::WorldEffects -==================== -*/ -void Vehicle::WorldEffects - ( - void - ) -{ - // - // Check for earthquakes - // - if( groundentity && ( level.earthquake_magnitude > 0.0f ) ) - { - velocity += Vector - ( - level.earthquake_magnitude * EARTHQUAKE_STRENGTH * G_CRandom(), - level.earthquake_magnitude * EARTHQUAKE_STRENGTH * G_CRandom(), - level.earthquake_magnitude * 1.5f * G_Random() - ); - } - - // - // check for lava - // - if( watertype & CONTENTS_LAVA ) - { - Damage( world, world, 20 * waterlevel, origin, vec_zero, vec_zero, 0, DAMAGE_NO_ARMOR, MOD_LAVA ); - } -} - -/* -==================== -Vehicle::DriverUse -==================== -*/ -void Vehicle::DriverUse - ( - Event *ev - ) -{ - int slot; - Vector pos; - Vector dist; - float min_length = 1e30f; - int min_slot = 0; - int min_type = -1; - Entity *ent; - Vector vExitAngles; - bool bHasExitAngles; - Vector vExitPosition; - - ent = ev->GetEntity( 1 ); - - if( locked ) - { - return; - } - - if( ev->NumArgs() == 2 ) - { - if( ev->IsVectorAt( 2 ) ) - { - vExitPosition = ev->GetVector( 2 ); - } - else if( ev->IsEntityAt( 2 ) ) - { - Entity *pEnt = ev->GetEntity( 2 ); - - bHasExitAngles = true; - vExitAngles = pEnt->angles; - vExitPosition = pEnt->origin; - } - else if( ev->IsSimpleEntityAt( 2 ) ) - { - SimpleEntity *pEnt = ev->GetSimpleEntity( 2 ); - - bHasExitAngles = true; - vExitAngles = pEnt->angles; - vExitPosition = pEnt->origin; - } - } - - slot = FindDriverSlotByEntity( ent ); - - if( slot >= 0 ) - { - DetachDriverSlot( slot, vec_zero, NULL ); - - if( ent->IsSubclassOfVehicleTank() && Turrets[ 0 ].ent->IsSubclassOfVehicleTurretGun() ) - { - VehicleTurretGun *pTurret = ( VehicleTurretGun * )Turrets[ 0 ].ent.Pointer(); - - pTurret->m_bUseRemoteControl = false; - pTurret->m_pRemoteOwner = NULL; - } - - return; - } - - slot = FindPassengerSlotByEntity( ent ); - - if( slot >= 0 ) - { - DetachPassengerSlot( slot, vec_zero, NULL ); - return; - } - - if( ent->IsSubclassOfWeapon() ) - { - slot = FindTurretSlotByEntity( ent ); - - if( slot >= 0 ) - { - DetachTurretSlot( slot, vec_zero, NULL ); - } - } - else if( ent->IsSubclassOfPlayer() ) - { - Player *player = ( Player * )ent; - - if( player->m_pTurret ) - { - slot = FindTurretSlotByEntity( player->m_pTurret ); - - if( slot >= 0 ) - { - if( bHasExitAngles ) - { - AttachTurretSlot( slot, player->m_pTurret, vExitPosition, &vExitAngles ); - } - else - { - AttachTurretSlot( slot, player->m_pTurret, vExitPosition, NULL ); - } - - player->m_pVehicle = NULL; - return; - } - } - } - - // Check for passengers slots - for( slot = 0; slot < MAX_PASSENGERS; slot++ ) - { - if( !( Passengers[ 0 ].flags & SLOT_FREE ) ) - { - continue; - } - - QueryPassengerSlotPosition( slot, ( float * )&pos ); - - dist = pos - ent->origin; - - if( dist.length() < min_length ) - { - min_length = dist.length(); - min_type = 0; - min_slot = slot; - } - } - - // Check for turrets slots - if( ent->IsSubclassOfWeapon() ) - { - for( slot = 0; slot < MAX_TURRETS; slot++ ) - { - if( !( Turrets[ 0 ].flags & SLOT_FREE ) ) - { - continue; - } - - QueryTurretSlotPosition( slot, ( float * )&pos ); - - dist = pos - ent->origin; - - if( dist.length() < min_length ) - { - min_length = dist.length(); - min_type = 1; - min_slot = slot; - } - } - } - else - { - for( slot = 0; slot < MAX_TURRETS; slot++ ) - { - if( !( Turrets[ 0 ].flags & SLOT_BUSY ) ) - { - continue; - } - - QueryTurretSlotPosition( slot, ( float * )&pos ); - - dist = pos - ent->origin; - - if( dist.length() < min_length ) - { - min_length = dist.length(); - min_type = 1; - min_slot = slot; - } - } - } - - slot = 0; - - // Check for driver(s) slot(s) - if( driver.flags & SLOT_FREE ) - { - QueryDriverSlotPosition( slot, ( float * )&pos ); - - dist = pos - ent->origin; - - if( dist.length() < min_length ) - { - min_length = dist.length(); - min_type = 2; - min_slot = slot; - } - } - - switch( min_type ) - { - case 0: - AttachPassengerSlot( min_slot, ent, vec_zero ); - break; - case 1: - AttachTurretSlot( min_slot, ent, vec_zero, NULL ); - break; - case 2: - AttachDriverSlot( min_slot, ent, vec_zero ); - break; - } -} - -/* -==================== -Vehicle::Drive -==================== -*/ -qboolean Vehicle::Drive - ( - usercmd_t *ucmd - ) -{ - Vector i, j, k; - - i = velocity; - VectorNormalize( i ); - - if( !driver.ent || !driver.ent->isClient() ) - { - return false; - } - - if( !drivable ) - { - driver.ent->client->ps.pm_flags |= PMF_FROZEN; - ucmd->forwardmove = 0; - ucmd->rightmove = 0; - ucmd->upmove = 0; - return false; - } - - driver.ent->client->ps.pm_flags |= PMF_NO_PREDICTION; - - moveimpulse = ( ( float )ucmd->forwardmove ) * ( VectorLength( i ) + 1.0 ); - m_bIsBraking = ucmd->forwardmove >> 31; - m_fAccelerator += ( ( float )ucmd->forwardmove ) * 0.005; - if( m_fAccelerator < 0.0 ) - m_fAccelerator = 0.0; - else if( m_fAccelerator > 1.0 ) - m_fAccelerator = 1.0; - - turnimpulse = ( ( float )-ucmd->rightmove ); - jumpimpulse = ( ( float )ucmd->upmove * gravity ) / 350; - if( ( jumpimpulse < 0 ) || ( !jumpable ) ) - jumpimpulse = 0; - - turnimpulse += 8 * angledist( SHORT2ANGLE( ucmd->angles[ 1 ] ) - driver.ent->client->cmd_angles[ 1 ] ); - - return true; -} - -/* -==================== -Vehicle::Think -==================== -*/ -void Vehicle::Think - ( - void - ) -{ - flags |= FL_POSTTHINK; -} - -/* -==================== -Vehicle::Postthink -==================== -*/ -void Vehicle::Postthink - ( - void - ) -{ - float turn; - Vector i; - Vector j; - Vector k; - Vector temp; - Vector roll; - Vector acceleration; - Vector atmp; - Vector atmp2; - Vector aup; - VehicleBase *v; - VehicleBase *last; - float drivespeed; - Vector primal_angles = angles; - Vector primal_origin = origin; - Vector vTmp; - Vector vAddedAngles; - Vector n_angles; - orientation_t orient; - - if( !g_vehicle->integer ) - { - return; - } - - if( m_pCollisionEntity ) - { - setSolidType( SOLID_NOT ); - m_pCollisionEntity->Solid(); - } - - prev_velocity = velocity; - - FactorOutAnglesOffset(); - FactorOutOriginOffset(); - - if( m_vOldMins != vec_zero && m_vOldMaxs != vec_zero ) - { - mins = m_vOldMins; - maxs = m_vOldMaxs; - } - else - { - if( mins != vec_zero || maxs != vec_zero ) - { - m_vOldMins = mins; - m_vOldMaxs = maxs; - } - } - - SetSlotsNonSolid(); - MoveVehicle(); - SetSlotsSolid(); - - m_bThinkCalled = true; - - if( !m_bAutoPilot ) - { - if( !driver.ent || !driver.ent->IsSubclassOfPlayer() ) - { - acceleration = velocity; - acceleration.z = 0; - - if( acceleration.length() < 0.1f ) - { - velocity = vec_zero; - } - } - - moveimpulse *= 0.825f; - turnimpulse *= 0.825f; - } - else - { - AutoPilot(); - } - - currentspeed = moveimpulse; - turnangle = turnangle * 0.25f + turnimpulse; - if( turnangle > maxturnrate ) - { - turnangle = maxturnrate; - } - else if( turnangle < -maxturnrate ) - { - turnangle = -maxturnrate; - } - - if( level.inttime <= 1200 ) - { - prev_origin = origin; - } - else - { - real_velocity = origin - prev_origin; - prev_origin = origin; - prev_acceleration = real_acceleration; - real_acceleration = prev_velocity - real_velocity; - prev_velocity = real_velocity; - - n_angles = real_acceleration - prev_acceleration; - } - - UpdateSkidAngle(); - UpdateBones(); - UpdateShaderOffset(); - UpdateTires(); - UpdateNormals(); - - angles.AngleVectorsLeft( &i, &j, &k ); - - turn = level.frametime * turnangle; - - velocity[ 0 ] *= 0.925f; - velocity[ 1 ] *= 0.925f; - - velocity = Vector( orientation[ 0 ] ) * currentspeed; - - drivespeed = velocity * Vector( orientation[ 0 ] ); - - if( drivespeed > speed ) - { - drivespeed = speed; - } - - velocity = Vector( orientation[ 0 ] ) * drivespeed; - velocity.z = drivespeed * jumpimpulse; - avelocity *= 0.05f; - - if( steerinplace && drivespeed < 350.0f ) - { - drivespeed = 350.0f; - } - - avelocity[ 1 ] += turn * drivespeed; - angles += avelocity * level.frametime; - - UpdateSound(); - - CalculateAnglesOffset( n_angles ); - CalculateOriginOffset(); - - last_origin = origin; - - vAddedAngles = angles - primal_angles; - - if( vAddedAngles[ 0 ] * level.frametime > -1.0f || vAddedAngles[ 0 ] * level.frametime < 1.0f ) - { - vAddedAngles[ 0 ] = 0.0f; - } - - if( vAddedAngles[ 1 ] * level.frametime > -1.0f || vAddedAngles[ 1 ] * level.frametime < 1.0f ) - { - vAddedAngles[ 1 ] = 0.0f; - } - - if( vAddedAngles[ 2 ] * level.frametime > -1.0f || vAddedAngles[ 2 ] * level.frametime < 1.0f ) - { - vAddedAngles[ 2 ] = 0.0f; - } - - avelocity = vAddedAngles; - - FactorInOriginOffset(); - FactorInAnglesOffset( &vAddedAngles ); - - CalculateAnimationData( vAddedAngles, m_vOriginOffset + m_vOriginOffset2 ); - - if( m_pCollisionEntity ) - { - n_angles = angles - m_pCollisionEntity->angles; - - n_angles[ 0 ] = angledist( n_angles[ 0 ] ); - n_angles[ 1 ] = angledist( n_angles[ 1 ] ); - n_angles[ 2 ] = angledist( n_angles[ 2 ] ); - - G_PushMove( m_pCollisionEntity, origin - primal_origin, n_angles ); - G_TouchTriggers( m_pCollisionEntity ); - - m_pCollisionEntity->setOrigin( origin ); - m_pCollisionEntity->setAngles( angles ); - } - - SetupVehicleSoundEntities(); - UpdateDriverSlot( 0 ); - - for( int slot = 0; slot < MAX_PASSENGERS; slot++ ) - { - UpdatePassengerSlot( slot ); - } - - for( int slot = 0; slot < MAX_TURRETS; slot++ ) - { - UpdateTurretSlot( slot ); - } - - atmp = angles - primal_angles; - - if( g_showvehicleentrypoints->integer ) - { - for( int slot = 0; slot < MAX_PASSENGERS; slot++ ) - { - if( Passengers[ slot ].enter_boneindex >= 0 ) - { - QueryPassengerSlotPosition( slot, ( float * )&temp ); - - G_DebugCircle( temp, 10.0f, 1.0f, 0.0f, 0.0f, 1.0f, true ); - } - } - - for( int slot = 0; slot < MAX_TURRETS; slot++ ) - { - if( Turrets[ slot ].enter_boneindex >= 0 ) - { - QueryTurretSlotPosition( slot, ( float * )&temp ); - - G_DebugCircle( temp, 10.0f, 0.0f, 1.0f, 0.0f, 1.0f, true ); - } - } - - if( driver.enter_boneindex >= 0 ) - { - QueryTurretSlotPosition( 0, ( float * )&temp ); - - G_DebugCircle( temp, 10.0f, 0.0f, 0.0f, 1.0f, 1.0f, true ); - } - } - - if( g_showvehicleslotpoints->integer ) - { - for( int slot = 0; slot < MAX_PASSENGERS; slot++ ) - { - if( Passengers[ slot ].boneindex < 0 ) - { - continue; - } - - GetTagPositionAndOrientation( Passengers[ slot ].boneindex, &orient ); - G_DebugCircle( orient.origin, 10.0, 1.0f, 0.5f, 0.5f, 1.0f, true ); - } - - for( int slot = 0; slot < MAX_TURRETS; slot++ ) - { - if( Turrets[ slot ].boneindex < 0 ) - { - continue; - } - - GetTagPositionAndOrientation( Turrets[ slot ].boneindex, &orient ); - G_DebugCircle( orient.origin, 10.0, 0.5f, 1.0f, 1.0f, 1.0f, true ); - } - - if( driver.boneindex >= 0 ) - { - GetTagPositionAndOrientation( driver.boneindex, &orient ); - G_DebugCircle( orient.origin, 10.0, 0.5f, 0.5f, 1.0f, 1.0f, true ); - } - } - - last = this; - while( last->vlink ) - { - v = last->vlink; - v->setOrigin( origin + ( i * v->offset.x ) + ( j * v->offset.y ) + ( k * v->offset.z ) ); - v->avelocity = avelocity; - v->velocity = velocity; - v->angles[ ROLL ] = angles[ ROLL ]; - v->angles[ YAW ] = angles[ YAW ]; - v->angles[ PITCH ] = ( float )( ( int )( v->angles[ PITCH ] + ( drivespeed / 4 ) ) % 360 ); - - v->setAngles( v->angles ); - - last = v; - } - - CheckWater(); - WorldEffects(); - - if( m_pCollisionEntity ) - { - setSolidType( SOLID_NOT ); - m_pCollisionEntity->Solid(); - } - else - { - setSolidType( SOLID_BBOX ); - edict->r.contents = CONTENTS_UNKNOWN2; - } -} - -/* -==================== -Vehicle::VehicleTouched -==================== -*/ -void Vehicle::VehicleTouched - ( - Event *ev - ) - - { - Entity *other; - float speed; - Vector delta; - Vector dir; - - other = ev->GetEntity( 1 ); - if ( other == driver.ent ) - { - return; - } - - if ( other == world ) - { - return; - } - - if ( drivable && !driver.ent ) - { - return; - } - - delta = origin - last_origin; - speed = delta.length(); - if ( speed > 2 ) - { - Sound( "vehicle_crash", qtrue ); - dir = delta * ( 1 / speed ); - other->Damage( this, lastdriver.ent, speed * 8, origin, dir, vec_zero, speed*15, 0, MOD_VEHICLE ); - } - - } - -/* -==================== -Vehicle::VehicleBlocked -==================== -*/ -void Vehicle::VehicleBlocked - ( - Event *ev - ) - - { - return; -/* - Entity *other; - float speed; - float damage; - Vector delta; - Vector newvel; - Vector dir; - - if ( !velocity[0] && !velocity[1] ) - return; - - other = ev->GetEntity( 1 ); - if ( other == driver.ent ) - { - return; - } - if ( other->isSubclassOf( VehicleBase ) ) - { - delta = other->origin - origin; - delta.normalize(); - - newvel = vec_zero - ( velocity) + ( other->velocity * 0.25 ); - if ( newvel * delta < 0 ) - { - velocity = newvel; - delta = velocity - other->velocity; - damage = delta.length()/4; - } - else - { - return; - } - } - else if ( ( velocity.length() < 350 ) ) - { - other->velocity += velocity*1.25f; - other->velocity[ 2 ] += 100; - damage = velocity.length()/4; - } - else - { - damage = other->health + 1000; - } - - // Gib 'em outright - speed = fabs( velocity.length() ); - dir = velocity * ( 1 / speed ); - other->Damage( this, lastdriver.ent, damage, origin, dir, vec_zero, speed, 0, MOD_VEHICLE, -1, -1, 1.0f ); -*/ - } - -/* -==================== -Vehicle::Driver -==================== -*/ -Entity *Vehicle::Driver - ( - void - ) - - { - return driver.ent; - } - -/* -==================== -Vehicle::IsDrivable -==================== -*/ -qboolean Vehicle::IsDrivable - ( - void - ) - - { - return drivable; - } - -/* -==================== -Vehicle::EventSetSpeed -==================== -*/ -void Vehicle::SetSpeed - ( - Event *ev - ) - { - speed = ev->GetFloat( 1 ); - } - -/* -==================== -Vehicle::EventSetTurnRate -==================== -*/ -void Vehicle::SetTurnRate - ( - Event *ev - ) - { - maxturnrate = ev->GetFloat( 1 ); - } - -/* -==================== -Vehicle::VehicleDestroyed -==================== -*/ -void Vehicle::VehicleDestroyed - ( - Event *ev - ) - -{ -} - -void Vehicle::DetachRemoteOwner() -{ - // FIXME: unimplemented -} - -/* -==================== -Vehicle::SetMoveInfo -==================== -*/ -void Vehicle::SetMoveInfo - ( - vmove_t *vm - ) -{ - memset( vm, 0, sizeof( vmove_t ) ); - - VectorCopy( origin, vs.origin ); - vs.useGravity = 0; - vs.entityNum = entnum; - - vm->vs = &vs; - vm->frametime = level.frametime; - vm->tracemask = edict->clipmask; - VectorCopy( mins, vm->mins ); - VectorCopy( maxs, vm->maxs ); - - vs.entityNum = edict->s.number; - vs.desired_dir[ 0 ] = velocity[ 0 ]; - vs.desired_dir[ 1 ] = velocity[ 1 ]; - - vm->desired_speed = VectorNormalize2D( this->vs.desired_dir ); -} - -/* -==================== -Vehicle::GetMoveInfo -==================== -*/ -void Vehicle::GetMoveInfo - ( - vmove_t *vm - ) -{ - Vector newOrigin = vm->vs->origin; - - if( bindmaster ) - { - newOrigin = vm->vs->origin - origin; - } - - setLocalOrigin( newOrigin ); - - groundentity = NULL; - if( vm->vs->groundEntityNum != ENTITYNUM_NONE ) - { - groundentity = &g_entities[ vm->vs->groundEntityNum ]; - } -} - -/* -==================== -Vehicle::SetCEMoveInfo -==================== -*/ -void Vehicle::SetCEMoveInfo - ( - vmove_t *vm - ) -{ - SetMoveInfo( vm ); - - vm->mins[ 0 ] = m_pCollisionEntity->mins[ 0 ] - 24.0f; - vm->mins[ 1 ] = m_pCollisionEntity->mins[ 1 ] - 24.0f; - vm->mins[ 2 ] = m_pCollisionEntity->mins[ 2 ]; - vm->maxs[ 0 ] = m_pCollisionEntity->maxs[ 0 ] + 24.0f; - vm->maxs[ 1 ] = m_pCollisionEntity->maxs[ 1 ] + 24.0f; - vm->maxs[ 2 ] = m_pCollisionEntity->maxs[ 2 ]; -} - -/* -==================== -Vehicle::GetCEMoveInfo -==================== -*/ -void Vehicle::GetCEMoveInfo - ( - vmove_t *vm - ) -{ - GetMoveInfo( vm ); -} - -/* -==================== -Vehicle::SetViewAngles -==================== -*/ -void Vehicle::SetViewAngles - ( - Vector newViewangles - ) -{ - client->ps.delta_angles[ 0 ] = ANGLE2SHORT( newViewangles.x ); - client->ps.delta_angles[ 1 ] = ANGLE2SHORT( newViewangles.y ); - client->ps.delta_angles[ 2 ] = ANGLE2SHORT( newViewangles.z ); - - AnglesToAxis( newViewangles, orientation ); - - yaw_forward = orientation[ 0 ]; - yaw_left = orientation[ 1 ]; -} - -/* -==================== -Vehicle::EventSetMass -==================== -*/ -void Vehicle::SetMass - ( - Event *ev - ) - -{ - m_fMass = ev->GetFloat( 1 ); - m_fFrontMass = m_fMass * 0.5; - m_fBackMass = m_fMass * 0.5; -} - -void Vehicle::SetFrontMass - ( - Event *ev - ) - -{ - m_fFrontMass = ev->GetFloat( 1 ); - m_fMass = m_fFrontMass + m_fBackMass; -} - -/* -==================== -Vehicle::EventSetBackMass -==================== -*/ -void Vehicle::SetBackMass - ( - Event *ev - ) - -{ - m_fBackMass = ev->GetFloat( 1 ); - m_fMass = m_fFrontMass + m_fBackMass; -} - -/* -==================== -Vehicle::EventSetTread -==================== -*/ -void Vehicle::SetTread - ( - Event *ev - ) - -{ - m_fTread = ev->GetFloat( 1 ); -} - -/* -==================== -Vehicle::EventSetTireRadius -==================== -*/ -void Vehicle::SetTireRadius - ( - Event *ev - ) - -{ - m_fTireRadius = ev->GetFloat( 1 ); -} - -/* -==================== -Vehicle::EventSetRollingResistance -==================== -*/ -void Vehicle::SetRollingResistance - ( - Event *ev - ) - -{ - m_fRollingResistance = ev->GetFloat( 1 ); -} - -/* -==================== -Vehicle::EventSetDrag -==================== -*/ -void Vehicle::SetDrag - ( - Event *ev - ) - -{ - m_fDrag = ev->GetFloat( 1 ); -} - -/* -==================== -Vehicle::TorqueLookup -==================== -*/ -float Vehicle::TorqueLookup - ( - int rpm - ) -{ - if( rpm > 4999 ) - { - if( rpm > 5999 ) - { - return 0.0; - } - else - { - return ( float )( 190 * ( 6000 - rpm ) ) * 0.001; - } - } - else - { - return 190.0; - } -} - -/* -==================== -Vehicle::UpdateVariables -==================== -*/ -void Vehicle::UpdateVariables - ( - Vector *acceleration, - Vector *vpn, - Vector *vup, - Vector *vright, - Vector *t_vpn, - Vector *t_vup, - Vector *t_vright - ) -{ - -} - -/* -==================== -Vehicle::EventModelInit -==================== -*/ -void Vehicle::ModelInit - ( - Event *ev - ) - -{ - SetControllerTag( 0, gi.Tag_NumForName( edict->tiki, "tire_rotate_front_left" ) ); - SetControllerTag( 1, gi.Tag_NumForName( edict->tiki, "tire_rotate_front_right" ) ); - SetControllerTag( 2, gi.Tag_NumForName( edict->tiki, "steeringwheel_center" ) ); -} - -/* -==================== -Vehicle::EventBouncyCoef -==================== -*/ -void Vehicle::BouncyCoef - ( - Event *ev - ) - -{ - m_fBouncyCoef = ev->GetFloat( 1 ); -} - -/* -==================== -Vehicle::EventSpringyCoef -==================== -*/ -void Vehicle::SpringyCoef - ( - Event *ev - ) - -{ - m_fSpringyCoef = ev->GetFloat( 1 ); -} - -/* -==================== -Vehicle::EventYawMinMax -==================== -*/ -void Vehicle::YawMinMax - ( - Event *ev - ) - -{ - if( ev->NumArgs() != 3 ) - { - ScriptError( "No Parameter for YawMinMax" ); - } - - m_fYawMin = ev->GetFloat( 1 ); - m_fYawMax = ev->GetFloat( 2 ); - m_fYawCoef = ev->GetFloat( 3 ); - - if( m_fYawMin > m_fYawMax ) - { - ScriptError( "Mismatched mins and maxs for YawMinMax" ); - } -} - -/* -==================== -Vehicle::EventRollMinMax -==================== -*/ -void Vehicle::RollMinMax - ( - Event *ev - ) - -{ - if( ev->NumArgs() != 3 ) - { - ScriptError( "No Parameter for RollMinMax" ); - } - - m_fRollMin = ev->GetFloat( 1 ); - m_fRollMax = ev->GetFloat( 2 ); - m_fRollCoef = ev->GetFloat( 3 ); - - if( m_fRollMin > m_fRollMax ) - { - ScriptError( "Mismatched mins and maxs for RollMinMax" ); - } -} - -/* -==================== -Vehicle::EventZMinMax -==================== -*/ -void Vehicle::ZMinMax - ( - Event *ev - ) - -{ - if( ev->NumArgs() != 3 ) - { - ScriptError( "No Parameter for ZMinMax" ); - } - - m_fZMin = ev->GetFloat( 1 ); - m_fZMax = ev->GetFloat( 2 ); - m_fZCoef = ev->GetFloat( 3 ); - - if( m_fZMin > m_fZMax ) - { - ScriptError( "Mismatched mins and maxs for ZMinMax" ); - } -} - -/* -==================== -Vehicle::EventSetAnimationSet -==================== -*/ -void Vehicle::SetAnimationSet - ( - Event *ev - ) - -{ - m_sAnimationSet = ev->GetString( 1 ); -} - -/* -==================== -Vehicle::EventSetSoundSet -==================== -*/ -void Vehicle::SetSoundSet - ( - Event *ev - ) - -{ - m_sSoundSet = ev->GetString( 1 ); -} - -/* -==================== -Vehicle::EventSpawnTurret -==================== -*/ -void Vehicle::SpawnTurret - ( - Event *ev - ) - -{ - VehicleTurretGun *pTurret; - int slot; - - pTurret = new VehicleTurretGun; - pTurret->SetBaseOrientation( orientation, NULL ); - pTurret->setModel( ev->GetString( 2 ) ); - - slot = ev->GetInteger( 1 ); - AttachTurretSlot( slot, pTurret, vec_zero, NULL ); - - pTurret->SetVehicleOwner( this ); - Event *event = new Event( EV_TakeDamage ); - pTurret->PostEvent( event, EV_POSTSPAWN ); - UpdateTurretSlot( slot ); - - pTurret->ProcessPendingEvents(); -} - -/* -==================== -Vehicle::EventLockMovement -==================== -*/ -void Vehicle::EventLockMovement - ( - Event *ev - ) - -{ - m_bMovementLocked = true; -} - -/* -==================== -Vehicle::EventUnlockMovement -==================== -*/ -void Vehicle::EventUnlockMovement - ( - Event *ev - ) - -{ - m_bMovementLocked = false; -} - -/* -==================== -Vehicle::EventQueryFreePassengerSlot -==================== -*/ -void Vehicle::QueryFreePassengerSlot - ( - Event *ev - ) - -{ - ev->AddInteger( QueryFreePassengerSlot() ); -} - -/* -==================== -Vehicle::EventQueryFreeDriverSlot -==================== -*/ -void Vehicle::QueryFreeDriverSlot - ( - Event *ev - ) - -{ - ev->AddInteger( QueryFreeDriverSlot() ); -} - -/* -==================== -Vehicle::EventQueryFreeTurretSlot -==================== -*/ -void Vehicle::QueryFreeTurretSlot - ( - Event *ev - ) - -{ - ev->AddInteger( QueryFreeTurretSlot() ); -} - -/* -==================== -Vehicle::EventQueryPassengerSlotPosition -==================== -*/ -void Vehicle::QueryPassengerSlotPosition - ( - Event *ev - ) - -{ - Vector vPos; - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_PASSENGERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - QueryPassengerSlotPosition( iSlot, vPos ); - ev->AddVector( vPos ); -} - -/* -==================== -Vehicle::EventQueryDriverSlotPosition -==================== -*/ -void Vehicle::QueryDriverSlotPosition - ( - Event *ev - ) - -{ - Vector vPos; - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_DRIVERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - QueryDriverSlotPosition( iSlot, vPos ); - ev->AddVector( vPos ); -} - -/* -==================== -Vehicle::EventQueryTurretSlotPosition -==================== -*/ -void Vehicle::QueryTurretSlotPosition - ( - Event *ev - ) - -{ - Vector vPos; - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_TURRETS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - QueryTurretSlotPosition( iSlot, vPos ); - ev->AddVector( vPos ); -} - -/* -==================== -Vehicle::EventQueryPassengerSlotAngles -==================== -*/ -void Vehicle::QueryPassengerSlotAngles - ( - Event *ev - ) - -{ - Vector vAngles; - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_PASSENGERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - QueryPassengerSlotAngles( iSlot, vAngles ); - ev->AddVector( vAngles ); -} - -/* -==================== -Vehicle::EventQueryDriverSlotAngles -==================== -*/ -void Vehicle::QueryDriverSlotAngles - ( - Event *ev - ) - -{ - Vector vAngles; - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_DRIVERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - QueryDriverSlotAngles( iSlot, vAngles ); - ev->AddVector( vAngles ); -} - -/* -==================== -Vehicle::EventQueryTurretSlotAngles -==================== -*/ -void Vehicle::QueryTurretSlotAngles - ( - Event *ev - ) - -{ - Vector vAngles; - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_TURRETS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - QueryTurretSlotAngles( iSlot, vAngles ); - ev->AddVector( vAngles ); -} - -/* -==================== -Vehicle::EventQueryPassengerSlotStatus -==================== -*/ -void Vehicle::QueryPassengerSlotStatus - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_PASSENGERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - ev->AddInteger( QueryPassengerSlotStatus( iSlot ) ); -} - -/* -==================== -Vehicle::EventQueryDriverSlotStatus -==================== -*/ -void Vehicle::QueryDriverSlotStatus - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_DRIVERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - ev->AddInteger( QueryDriverSlotStatus( iSlot ) ); -} - -/* -==================== -Vehicle::EventQueryTurretSlotStatus -==================== -*/ -void Vehicle::QueryTurretSlotStatus - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_TURRETS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - ev->AddInteger( QueryTurretSlotStatus( iSlot ) ); -} - -/* -==================== -Vehicle::EventQueryPassengerSlotEntity -==================== -*/ -void Vehicle::QueryPassengerSlotEntity - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_PASSENGERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - ev->AddEntity( QueryPassengerSlotEntity( iSlot ) ); -} - -/* -==================== -Vehicle::EventQueryDriverSlotEntity -==================== -*/ -void Vehicle::QueryDriverSlotEntity - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_DRIVERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - ev->AddEntity( QueryDriverSlotEntity( iSlot ) ); -} - -/* -==================== -Vehicle::EventQueryTurretSlotEntity -==================== -*/ -void Vehicle::QueryTurretSlotEntity - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_TURRETS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - ev->AddEntity( QueryTurretSlotEntity( iSlot ) ); -} - -/* -==================== -Vehicle::EventAttachPassengerSlot -==================== -*/ -void Vehicle::AttachPassengerSlot - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_PASSENGERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - AttachPassengerSlot( iSlot, ev->GetEntity( 2 ), vec_zero ); - UpdatePassengerSlot( iSlot ); -} - -/* -==================== -Vehicle::EventAttachDriverSlot -==================== -*/ -void Vehicle::AttachDriverSlot - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_DRIVERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - AttachDriverSlot( 0, ev->GetEntity( 2 ), vec_zero ); - UpdateDriverSlot( 0 ); -} - -/* -==================== -Vehicle::EventAttachTurretSlot -==================== -*/ -void Vehicle::AttachTurretSlot - ( - Event *ev - ) - -{ - int iSlot; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_TURRETS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - AttachTurretSlot( iSlot, ev->GetEntity( 2 ), vec_zero, NULL ); - UpdateTurretSlot( iSlot ); -} - -/* -==================== -Vehicle::EventDetachPassengerSlot -==================== -*/ -void Vehicle::DetachPassengerSlot - ( - Event *ev - ) - -{ - int iSlot; - Vector vExitPosition; - Vector vExitAngles; - bool bHasExitAngles = false; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_PASSENGERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - if( ev->NumArgs() == 2 ) - { - if( ev->IsVectorAt( 2 ) ) - { - vExitPosition = ev->GetVector( 2 ); - } - else if( ev->IsEntityAt( 2 ) ) - { - vExitPosition = ev->GetEntity( 2 )->origin; - bHasExitAngles = true; - } - else if( ev->IsSimpleEntityAt( 2 ) ) - { - vExitPosition = ev->GetSimpleEntity( 2 )->origin; - } - - DetachPassengerSlot( iSlot, vExitPosition, bHasExitAngles ? &vExitAngles : NULL ); - } - else - { - DetachPassengerSlot( iSlot, vec_zero, NULL ); - } -} - -/* -==================== -Vehicle::EventDetachDriverSlot -==================== -*/ -void Vehicle::DetachDriverSlot - ( - Event *ev - ) - -{ - int iSlot; - Vector vExitPosition; - Vector vExitAngles; - bool bHasExitAngles = false; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_DRIVERS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - if( ev->NumArgs() == 2 ) - { - if( ev->IsVectorAt( 2 ) ) - { - vExitPosition = ev->GetVector( 2 ); - } - else if( ev->IsEntityAt( 2 ) ) - { - vExitPosition = ev->GetEntity( 2 )->origin; - bHasExitAngles = true; - } - else if( ev->IsSimpleEntityAt( 2 ) ) - { - vExitPosition = ev->GetSimpleEntity( 2 )->origin; - } - - DetachDriverSlot( iSlot, vExitPosition, bHasExitAngles ? &vExitAngles : NULL ); - } - else - { - DetachDriverSlot( iSlot, vec_zero, NULL ); - } -} - -/* -==================== -Vehicle::EventDetachTurretSlot -==================== -*/ -void Vehicle::DetachTurretSlot - ( - Event *ev - ) - -{ - int iSlot; - Vector vExitPosition; - Vector vExitAngles; - bool bHasExitAngles = false; - - iSlot = ev->GetInteger( 1 ); - if( iSlot >= MAX_TURRETS ) - { - ScriptError( "Slot Specified is greater than maximum allowed for that parameter\n" ); - } - - if( ev->NumArgs() == 2 ) - { - if( ev->IsVectorAt( 2 ) ) - { - vExitPosition = ev->GetVector( 2 ); - } - else if( ev->IsEntityAt( 2 ) ) - { - vExitPosition = ev->GetEntity( 2 )->origin; - bHasExitAngles = true; - } - else if( ev->IsSimpleEntityAt( 2 ) ) - { - vExitPosition = ev->GetSimpleEntity( 2 )->origin; - } - - DetachTurretSlot( iSlot, vExitPosition, bHasExitAngles ? &vExitAngles : NULL ); - } - else - { - DetachTurretSlot( iSlot, vec_zero, NULL ); - } -} - -/* -==================== -Vehicle::SetWheelCorners -==================== -*/ -void Vehicle::SetWheelCorners - ( - Event *ev - ) - -{ - Vector size; - - size = ev->GetVector( 1 ); - m_vOriginCornerOffset = ev->GetVector( 2 ); - - maxtracedist = size[ 2 ]; - - Corners[ 0 ][ 0 ] = -( size[ 0 ] * 0.5 ); - Corners[ 0 ][ 1 ] = ( size[ 1 ] * 0.5 ); - Corners[ 0 ][ 2 ] = size[ 2 ]; - - Corners[ 1 ][ 0 ] = ( size[ 0 ] * 0.5 ); - Corners[ 1 ][ 1 ] = ( size[ 1 ] * 0.5 ); - Corners[ 1 ][ 2 ] = size[ 2 ]; - - Corners[ 2 ][ 0 ] = -( size[ 0 ] * 0.5 ); - Corners[ 2 ][ 1 ] = -( size[ 1 ] * 0.5 ); - Corners[ 2 ][ 2 ] = size[ 2 ]; - - Corners[ 3 ][ 0 ] = ( size[ 0 ] * 0.5 ); - Corners[ 3 ][ 1 ] = -( size[ 1 ] * 0.5 ); - Corners[ 3 ][ 2 ] = size[ 2 ]; - - SetupVehicleSoundEntities(); -} - -/* -==================== -Vehicle::EventDriveInternal -==================== -*/ -void Vehicle::EventDriveInternal - ( - Event *ev, - bool wait - ) -{ - SimpleEntity *path; - SimpleEntity *alternate_path = NULL; - - m_fIdealDistance = 100.0f; - m_fLookAhead = 256.0f; - m_fIdealAccel = 35.0f; - m_fIdealSpeed = 250.0f; - - switch( ev->NumArgs() ) - { - case 6: - alternate_path = ev->GetSimpleEntity( 6 ); - case 5: - m_fLookAhead = ev->GetFloat( 5 ); - case 4: - m_fIdealDistance = ev->GetFloat( 4 ); - case 3: - m_fIdealAccel = ev->GetFloat( 3 ); - case 2: - m_fIdealSpeed = ev->GetFloat( 2 ); - break; - case 1: - break; - default: - ScriptError( "wrong number of arguments" ); - } - - path = ev->GetSimpleEntity( 1 ); - - if( path ) - { - ScriptError( "Vehicle Given Drive Command with NULL path." ); - } - - if( !m_pCurPath ) - { - m_pCurPath = new cSpline < 4, 512 > ; - } - - if( !m_pAlternatePath ) - { - m_pAlternatePath = new cSpline < 4, 512 > ; - } - - SetupPath( m_pCurPath, path ); - - // Setup the alternate path - if( alternate_path ) - { - SetupPath( m_pAlternatePath, alternate_path ); - } - - m_bAutoPilot = true; - m_iCurNode = 0; - m_iAlternateNode = 0; - - Sound( m_sSoundSet + "snd_start" ); -} - -/* -==================== -Vehicle::EventDrive -==================== -*/ -void Vehicle::EventDrive - ( - Event *ev - ) - -{ - EventDriveInternal( ev, true ); -} - -/* -==================== -Vehicle::EventDriveNoWait -==================== -*/ -void Vehicle::EventDriveNoWait - ( - Event *ev - ) - -{ - EventDriveInternal( ev, false ); -} - -/* -==================== -Vehicle::EventStop -==================== -*/ -void Vehicle::EventStop - ( - Event *ev - ) - -{ - m_bStopEnabled = false; - m_bAutoPilot = false; - m_bIsSkidding = false; - moveimpulse = 0; - turnimpulse = 0; - m_iCurNode = 0; - Unregister( STRING_DRIVE ); -} - -/* -==================== -Vehicle::EventFullStop -==================== -*/ -void Vehicle::EventFullStop - ( - Event *ev - ) - -{ - m_bStopEnabled = 0; - m_bIsSkidding = 0; - m_bAutoPilot = 0; - moveimpulse = 0; - turnimpulse = 0; - velocity = vec_zero; - m_iCurNode = 0; - Unregister( STRING_DRIVE ); -} - -/* -==================== -Vehicle::EventModifyDrive -==================== -*/ -void Vehicle::EventModifyDrive - ( - Event *ev - ) - -{ - if( !level.Spawned() ) - { - ScriptError( "ModifyDrive used improperly... (used before the level is spawned)" ); - } - - if( !m_bAutoPilot || !this->m_pCurPath ) - { - ScriptError( "ModifyDrive used when not driving!" ); - } - - if( ev->NumArgs() < 1 || ev->NumArgs() > 3 ) - { - ScriptError( "wrong number of arguments" ); - } - - m_fIdealSpeed = ev->GetFloat( 1 ); - - if( ev->NumArgs() >= 2 ) - { - m_fIdealAccel = ev->GetFloat( 2 ); - } - - if( ev->NumArgs() >= 3 ) - { - m_fLookAhead = ev->GetFloat( 3 ); - } -} - -/* -==================== -Vehicle::EventNextDrive -==================== -*/ -void Vehicle::EventNextDrive - ( - Event *ev - ) - -{ - SimpleEntity *path; - float *i_fTmp; - float o_fTmp[ 4 ]; - Vector org1; - Vector org2; - - path = ev->GetSimpleEntity( 1 ); - - if( !m_bAutoPilot ) - { - ScriptError( "Cannot Set Next Path because Not Currently Driving a Path." ); - } - - if( !m_pCurPath || m_pCurPath->m_iPoints == 0 ) - { - ScriptError( "Cannot Set Next Path because Current Path is Empty." ); - } - - if( !m_pNextPath ) - { - m_pNextPath = new cSpline < 4, 512 > ; - } - - SetupPath( m_pNextPath, path ); - - i_fTmp = m_pCurPath->GetByNode( m_pCurPath->m_iPoints, NULL ); - org1 = ( i_fTmp + 1 ); - i_fTmp = m_pNextPath->GetByNode( 0.0f, NULL ); - org2 = ( i_fTmp + 1 ); - - o_fTmp[ 0 ] = ( org2 - org1 ).length(); - VectorClear( o_fTmp + 1 ); - - m_pNextPath->UniformAdd( o_fTmp ); - m_iNextPathStartNode = m_pCurPath->Append( m_pNextPath ); -} - -/* -==================== -Vehicle::EventModel -==================== -*/ -void Vehicle::EventModel - ( - Event *ev - ) - -{ - SetModelEvent( ev ); -} - -/* -==================== -Vehicle::EventRemoveOnDeath -==================== -*/ -void Vehicle::EventRemoveOnDeath - ( - Event *ev - ) - -{ - m_bRemoveOnDeath = ev->GetBoolean( 1 ); -} - -/* -==================== -Vehicle::EventSetExplosionModel -==================== -*/ -void Vehicle::EventSetExplosionModel - ( - Event *ev - ) - -{ - m_sExplosionModel = ev->GetString( 1 ); -} - -/* -==================== -Vehicle::EventSetCollisionModel -==================== -*/ -void Vehicle::EventSetCollisionModel - ( - Event *ev - ) - -{ - Entity *pColEnt = ev->GetEntity( 1 ); - - if( !pColEnt ) - { - ScriptError( "Trying to set a collision model with a NULL entity." ); - } - - if( m_pCollisionEntity ) - { - m_pCollisionEntity->PostEvent( EV_Remove, EV_VEHICLE ); - } - - m_pCollisionEntity = new VehicleCollisionEntity( this ); - m_pCollisionEntity->setModel( pColEnt->model ); - - if( !m_pCollisionEntity->model.length() || *m_pCollisionEntity->model != '*' ) - { - // Re-post the event with the correct time - m_pCollisionEntity->CancelEventsOfType( EV_Remove ); - m_pCollisionEntity->PostEvent( EV_Remove, EV_VEHICLE ); - m_pCollisionEntity = NULL; - - ScriptError( "Model for Entity not of a valid type. Must be B-Model." ); - } - - m_pCollisionEntity->setOrigin( origin ); - m_pCollisionEntity->setAngles( angles ); -} - -/* -==================== -Vehicle::EventGetCollisionModel -==================== -*/ -void Vehicle::EventGetCollisionModel - ( - Event *ev - ) - -{ - ev->AddEntity( m_pCollisionEntity ); -} - -/* -==================== -Vehicle::EventSetSoundParameters -==================== -*/ -void Vehicle::EventSetSoundParameters - ( - Event *ev - ) - -{ - m_fSoundMinSpeed = ev->GetFloat( 1 ); - m_fSoundMinPitch = ev->GetFloat( 2 ); - m_fSoundMaxSpeed = ev->GetFloat( 3 ); - m_fSoundMaxPitch = ev->GetFloat( 4 ); -} - -/* -==================== -Vehicle::EventSetVolumeParameters -==================== -*/ -void Vehicle::EventSetVolumeParameters - ( - Event *ev - ) - -{ - m_fVolumeMinSpeed = ev->GetFloat( 1 ); - m_fVolumeMinPitch = ev->GetFloat( 2 ); - m_fVolumeMaxSpeed = ev->GetFloat( 3 ); - m_fVolumeMaxPitch = ev->GetFloat( 4 ); -} - -/* -==================== -Vehicle::EventDamage -==================== -*/ -void Vehicle::EventDamage - ( - Event *ev - ) - -{ - Vector vDirection; - float fForce; - int i; - - if( !IsDamagedBy( ev->GetEntity( 3 ) ) ) - { - return; - } - - Event *event = new Event( EV_Damage ); - - vDirection = ev->GetVector( 5 ); - fForce = ev->GetFloat( 7 ); - VectorNormalizeFast( vDirection ); - - m_fForwardForce += DotProduct( orientation[ 1 ], vDirection ) * fForce; - m_fLeftForce += DotProduct( orientation[ 0 ], vDirection ) * fForce; - - for( i = 1; i <= ev->NumArgs(); i++ ) - { - if( i == 7 ) - { - event->AddFloat( 0 ); - } - else - { - event->AddValue( ev->GetValue( i ) ); - } - } - - if( driver.ent ) - { - if( driver.ent->IsSubclassOfPlayer() ) - { - Player *player = ( Player * )driver.ent.Pointer(); - Vector dir = ev->GetVector( 5 ); - - if( player->camera ) - { - player->damage_yaw = AngleSubtract( player->camera->angles[ 1 ], dir.toYaw() ) + 180.5f; - } - else - { - player->damage_yaw = AngleSubtract( player->GetVAngles()[ 1 ], dir.toYaw() ) + 180.5f; - } - } - } - - DamageEvent( event ); - delete event; -} - -/* -==================== -Vehicle::EventStopAtEnd -==================== -*/ -void Vehicle::EventStopAtEnd - ( - Event *ev - ) - -{ - if( !m_pCurPath ) - { - ScriptError( "Tried to Stop at end of path on a vehicle who is not driving a path!" ); - } - - m_fStopStartDistance = GetPathPosition( m_pCurPath, m_iCurNode ); - m_fStopStartSpeed = moveimpulse; - m_fStopEndDistance = *m_pCurPath->GetByNode( m_pCurPath->m_vPoints[ 0 ][ 0 ], NULL ); - m_bStopEnabled = 1; -} - -/* -==================== -Vehicle::EventSkidding -==================== -*/ -void Vehicle::EventSkidding - ( - Event *ev - ) - -{ - if( ev->NumArgs() == 1 ) - { - m_bEnableSkidding = ev->GetInteger( 1 ); - } - else - { - m_bEnableSkidding = true; - } - - ProcessEvent( EV_Vehicle_ContinueSkidding ); -} - -/* -==================== -Vehicle::EventContinueSkidding -==================== -*/ -void Vehicle::EventContinueSkidding - ( - Event *ev - ) - -{ - if( m_bEnableSkidding ) - { - if( HasAnim( "skidding" ) ) - { - NewAnim( "skidding", EV_Vehicle_ContinueSkidding, 7, 0.000001f ); - return; - } - else - { - assert( !"Vehicle without skidding animation." ); - } - } - else - { - if( HasAnim( "idle" ) ) - { - NewAnim( "idle", 0, 7, 0.000001f ); - return; - } - else - { - assert( !"Vehicle without idle animation." ); - } - } -} - -/* -==================== -Vehicle::EventVehicleAnim -==================== -*/ -void Vehicle::EventVehicleAnim - ( - Event *ev - ) - -{ - float weight; - - if( ev->NumArgs() > 1 ) - { - weight = ev->GetFloat( 2 ); - } - else - { - weight = 1.0f; - } - - NewAnim( ev->GetString( 1 ), EV_Vehicle_VehicleAnimDone, 8, weight ); -} - -/* -==================== -Vehicle::EventVehicleAnimDone -==================== -*/ -void Vehicle::EventVehicleAnimDone - ( - Event *ev - ) - -{ - Unregister( STRING_VEHICLEANIMDONE ); -} - -/* -==================== -Vehicle::TouchStuff -==================== -*/ -void Vehicle::TouchStuff - ( - vmove_t *vm - ) -{ - int i, j; - gentity_t *other; - Event *event; - - if (driver.ent) - G_TouchTriggers(driver.ent); - - for (int i = 0; i < MAX_PASSENGERS; i++) - { - if (Passengers[i].ent) - { - G_TouchTriggers(Passengers[i].ent); - } - } - - for (int i = 0; i < MAX_TURRETS; i++) - { - if (Turrets[i].ent) - { - G_TouchTriggers(Turrets[i].ent); - } - } - - if (getMoveType() != MOVETYPE_NOCLIP) - { - G_TouchTriggers(this); - } - - for (i = 0; i < vm->numtouch; i++) - { - other = &g_entities[vm->touchents[i]]; - - for (j = 0; j < i; j++) - { - gentity_t *ge = &g_entities[j]; - - if (ge == other) - break; - } - - if (j != i) - { - // duplicated - continue; - } - - // Don't bother touching the world - if ((!other->entity) || (other->entity == world)) - { - continue; - } - - event = new Event(EV_Touch); - event->AddEntity(this); - other->entity->ProcessEvent(event); - - event = new Event(EV_Touch); - event->AddEntity(other->entity); - ProcessEvent(event); - } + entflags &= ~ECF_VEHICLE; } /* @@ -3725,36 +1210,30 @@ void Vehicle::TouchStuff Vehicle::ResetSlots ==================== */ -void Vehicle::ResetSlots - ( - void - ) - +void Vehicle::ResetSlots(void) { - driver.ent = NULL; - driver.boneindex = -1; - driver.enter_boneindex = -1; - driver.flags = SLOT_UNUSED; - lastdriver.ent = NULL; - lastdriver.boneindex = -1; - lastdriver.enter_boneindex = -1; - lastdriver.flags = SLOT_UNUSED; + driver.ent = NULL; + driver.boneindex = -1; + driver.enter_boneindex = -1; + driver.flags = 0; + lastdriver.ent = NULL; + lastdriver.boneindex = -1; + lastdriver.enter_boneindex = -1; + lastdriver.flags = SLOT_UNUSED; - for( int i = 0; i < MAX_PASSENGERS; i++ ) - { - Passengers[ i ].ent = NULL; - Passengers[ i ].boneindex = -1; - Passengers[ i ].enter_boneindex = -1; - Passengers[ i ].flags = SLOT_UNUSED; - } + for (int i = 0; i < MAX_PASSENGERS; i++) { + Passengers[i].ent = NULL; + Passengers[i].boneindex = -1; + Passengers[i].enter_boneindex = -1; + Passengers[i].flags = SLOT_UNUSED; + } - for( int i = 0; i < MAX_TURRETS; i++ ) - { - Turrets[ i ].ent = NULL; - Turrets[ i ].boneindex = -1; - Turrets[ i ].enter_boneindex = -1; - Turrets[ i ].flags = SLOT_UNUSED; - } + for (int i = 0; i < MAX_TURRETS; i++) { + Turrets[i].ent = NULL; + Turrets[i].boneindex = -1; + Turrets[i].enter_boneindex = -1; + Turrets[i].flags = SLOT_UNUSED; + } } /* @@ -3762,1807 +1241,179 @@ void Vehicle::ResetSlots Vehicle::OpenSlotsByModel ==================== */ -void Vehicle::OpenSlotsByModel - ( - void - ) - +void Vehicle::OpenSlotsByModel(void) { - str bonename; - int bonenum; - int boneindex; + str bonename; + int bonenum; + int boneindex; - driver.boneindex = gi.Tag_NumForName( edict->tiki, "driver" ); - driver.enter_boneindex = gi.Tag_NumForName( edict->tiki, "driver_enter" ); + driver.boneindex = gi.Tag_NumForName(edict->tiki, "driver"); + driver.enter_boneindex = gi.Tag_NumForName(edict->tiki, "driver_enter"); - if( driver.flags & SLOT_UNUSED ) - { - driver.ent = NULL; - driver.flags = SLOT_FREE; - } + if (driver.flags & SLOT_UNUSED) { + driver.ent = NULL; + driver.flags = SLOT_FREE; + } - numPassengers = 0; + numPassengers = 0; - for( bonenum = 0; bonenum < MAX_PASSENGERS; bonenum++ ) - { - str bonenumstr = bonenum; - bonename = "passenger" + bonenumstr; - boneindex = gi.Tag_NumForName( edict->tiki, bonename.c_str() ); + for (bonenum = 0; bonenum < MAX_PASSENGERS; bonenum++) { + str bonenumstr = bonenum; + bonename = "passenger" + bonenumstr; + boneindex = gi.Tag_NumForName(edict->tiki, bonename.c_str()); - if( boneindex >= 0 ) - { - numPassengers++; + if (boneindex >= 0) { + numPassengers++; - Passengers[ bonenum ].boneindex = boneindex; - Passengers[ bonenum ].enter_boneindex = gi.Tag_NumForName( edict->tiki, "passenger_enter" + bonenumstr); + Passengers[bonenum].boneindex = boneindex; + Passengers[bonenum].enter_boneindex = gi.Tag_NumForName(edict->tiki, "passenger_enter" + bonenumstr); - if( Passengers[ bonenum ].flags & SLOT_UNUSED ) - { - Passengers[ bonenum ].ent = NULL; - Passengers[ bonenum ].flags = SLOT_FREE; - } - } - } + if (Passengers[bonenum].flags & SLOT_UNUSED) { + Passengers[bonenum].ent = NULL; + Passengers[bonenum].flags = SLOT_FREE; + } + } + } - numTurrets = 0; + numTurrets = 0; - for( bonenum = 0; bonenum < MAX_TURRETS; bonenum++ ) - { - str bonenumstr = bonenum; - bonename = "turret" + bonenumstr; - boneindex = gi.Tag_NumForName( edict->tiki, bonename.c_str() ); + for (bonenum = 0; bonenum < MAX_TURRETS; bonenum++) { + str bonenumstr = bonenum; + bonename = "turret" + bonenumstr; + boneindex = gi.Tag_NumForName(edict->tiki, bonename.c_str()); - if( boneindex >= 0 ) - { - numTurrets++; + if (boneindex >= 0) { + numTurrets++; - Turrets[ bonenum ].boneindex = boneindex; - Turrets[ bonenum ].enter_boneindex = gi.Tag_NumForName( edict->tiki, "turret_enter" + bonenumstr); + Turrets[bonenum].boneindex = boneindex; + Turrets[bonenum].enter_boneindex = gi.Tag_NumForName(edict->tiki, "turret_enter" + bonenumstr); - if( Turrets[ bonenum ].flags & SLOT_UNUSED ) - { - Turrets[ bonenum ].ent = NULL; - Turrets[ bonenum ].flags = SLOT_FREE; - } - } - } + if (Turrets[bonenum].flags & SLOT_UNUSED) { + Turrets[bonenum].ent = NULL; + Turrets[bonenum].flags = SLOT_FREE; + } + } + } } /* ==================== -Vehicle::MoveVehicle +Vehicle::EventModelInit ==================== */ -void Vehicle::MoveVehicle - ( - void - ) - +void Vehicle::ModelInit(Event *ev) { - trace_t tr; - Vector vecStart; - Vector vecStart2; - Vector vecEnd; - Vector vecDelta; - Vector vecAng; - int i; - gridpoint_t *gp; - vmove_t vm; - float flMoveFrac = 1.0f; - float fSpeed; - bool bDoGravity = true; - bool bHitPerson = false; - Entity *pSkippedEntities[ MAX_SKIPPED_ENTITIES ]; - int iContentsEntities[ MAX_SKIPPED_ENTITIES ]; - solid_t solidEntities[ MAX_SKIPPED_ENTITIES ]; - int iNumSkippedEntities = 0; - Event* event = nullptr; - - if( m_bMovementLocked ) - { - return; - } - - setAngles(); - if( m_pCollisionEntity ) - { - SetCEMoveInfo( &vm ); - } - else - { - SetMoveInfo( &vm ); - } - m_sMoveGrid->SetMoveInfo( &vm ); - m_sMoveGrid->SetOrientation( orientation ); - m_sMoveGrid->CalculateBoxPoints(); - CheckGround(); - - VmoveSingle( &vm ); - - setOrigin( vm.vs->origin ); - - if( velocity.length() > 0.5f ) - { - fSpeed = DotProduct( velocity, orientation[ 0 ] ); - vecDelta = velocity * level.frametime; - - for( i = 0; i < 3; i++ ) - { - if( fSpeed > 0.0f ) - { - gp = m_sMoveGrid->GetGridPoint( 0, i, 0 ); - vecStart = gp->origin + origin; - } - else - { - gp = m_sMoveGrid->GetGridPoint( 2, i, 0 ); - vecStart = gp->origin + origin; - } - - if( real_velocity.length() > 0.5f ) - { - vecStart2 = vecDelta + vecStart; - - for( ;; ) - { - tr = G_Trace( vecStart2, Vector( vm.mins ) - Vector( -32, -32, -32 ), Vector( vm.maxs ) + Vector( 32, 32, 32 ), vecStart2, this, 0x6001382, false, "Vehicle::MoveVehicle" ); - - if( !tr.ent || !tr.ent->entity || tr.ent->entity == world ) - { - break; - } - - tr.ent->entity->CheckGround(); - - if (!tr.ent->entity->groundentity || (tr.ent->entity->groundentity == edict && - (!m_pCollisionEntity || tr.ent->entity != m_pCollisionEntity))) - { - Event *event = new Event( EV_Touch ); - event->AddEntity( this ); - tr.ent->entity->ProcessEvent( event ); - - event = new Event( EV_Touch ); - event->AddEntity( tr.ent->entity ); - ProcessEvent( event ); - - if( tr.ent->entity->IsSubclassOfSentient() ) - bHitPerson = true; - - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Hit(MV0): %s : %s\n", tr.ent->entity->getClassname(), tr.ent->entity->targetname.c_str() ); - } - - break; - } - - pSkippedEntities[ iNumSkippedEntities ] = tr.ent->entity; - iContentsEntities[ iNumSkippedEntities ] = tr.ent->r.contents; - solidEntities[ iNumSkippedEntities ] = tr.ent->solid; - iNumSkippedEntities++; - - if( iNumSkippedEntities >= MAX_SKIPPED_ENTITIES ) - { - gi.Error( ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n" ); - return; - } - - tr.ent->entity->setSolidType( SOLID_NOT ); - - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Skipped(MV0): %s : %s\n", tr.ent->entity->getClassname(), tr.ent->entity->targetname.c_str() ); - } - } - } - - if( g_showvehiclemovedebug->integer ) - { - G_DebugBBox( vecStart, vm.mins, vm.maxs, 1.0f, 0.0f, 0.0f, 1.0f ); - G_DebugBBox( vecStart + Vector( 0, 0, 64.0f ), vm.mins, vm.maxs, 1.0f, 0.0f, 0.0f, 1.0f ); - } - - vecEnd = vecStart + vecDelta; - - for( ;; ) - { - tr = G_Trace( vecStart, Vector( vm.mins ), Vector( vm.maxs ), vecEnd, this, edict->clipmask, false, "Vehicle::MoveVehicle" ); - - if( tr.fraction == 1.0f && !tr.allsolid && !tr.startsolid ) - { - break; - } - - if( !tr.ent || !tr.ent->entity || tr.ent->entity == world ) - { - if( g_showvehiclemovedebug->integer ) - { - if( flMoveFrac > tr.fraction ) - { - flMoveFrac = tr.fraction - 0.1f; - } - - G_DebugBBox( tr.endpos, vm.mins, vm.maxs, 0.0f, 1.0f, 0.0f, 1.0f ); - } - - vecStart = tr.endpos; - vecEnd = tr.endpos; - - for( ;; ) - { - tr = G_Trace( vecStart, Vector( vm.mins ), Vector( vm.maxs ), vecEnd, this, edict->clipmask, false, "Vehicle::MoveVehicle" ); - - if( tr.fraction != 1.0f || tr.plane.normal[ 2 ] < 0.7f || tr.allsolid ) - { - flMoveFrac = 0.0f; - } - - if( !tr.ent || !tr.ent->entity || tr.ent->entity == world ) - { - goto _label1; - break; - } - - tr.ent->entity->CheckGround(); - - if( !tr.ent->entity->groundentity ) - { - break; - } - - if( tr.ent != edict ) - { - if( !m_pCollisionEntity ) - { - break; - } - - if( tr.ent->entity != m_pCollisionEntity ) - { - break; - } - } - - pSkippedEntities[ iNumSkippedEntities ] = tr.ent->entity; - iContentsEntities[ iNumSkippedEntities ] = tr.ent->r.contents; - solidEntities[ iNumSkippedEntities ] = tr.ent->solid; - iNumSkippedEntities++; - - if( iNumSkippedEntities >= MAX_SKIPPED_ENTITIES ) - { - gi.Error( ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n" ); - return; - } - - tr.ent->entity->setSolidType( SOLID_NOT ); - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Skipped(MV2): %s : %s\n", tr.ent->entity->getClassname(), tr.ent->entity->targetname.c_str() ); - } - } - - event = new Event( EV_Touch ); - event->AddEntity( this ); - tr.ent->entity->ProcessEvent( event ); - - event = new Event( EV_Touch ); - event->AddEntity( tr.ent->entity ); - ProcessEvent( event ); - - if( tr.ent->entity->IsSubclassOfPlayer() ) - { - bHitPerson = true; - } - -_label1: - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Hit(MV2): %s : %s\n", tr.ent->entity->getClassname(), tr.ent->entity->targetname.c_str() ); - G_DebugBBox( vecStart, gp->vm.mins, gp->vm.maxs, 0.0f, 0.0f, 1.0f, 1.0f ); - } - - if( ( !tr.ent || !tr.ent->entity->IsSubclassOfProjectile() ) && driver.ent && driver.ent->IsSubclassOfPlayer() ) - { - if( fSpeed > 0.0f ) - { - if( i ) - { - if( i == 2 && turnimpulse >= 0.0f ) - { - turnimpulse -= 800.0f * level.frametime; - } - - continue; - } - - if( turnimpulse > 0.0f ) - { - continue; - } - - turnimpulse += 800 * level.frametime; - continue; - } - - if( i == 0 ) - { - if( turnimpulse < 0.0f ) - continue; - - turnimpulse -= 800 * level.frametime; - continue; - } - - if( i == 2 && turnimpulse <= 0.0f ) - { - turnimpulse += 800 * level.frametime; - continue; - } - } - - if( flMoveFrac < 0.1f ) - { - bDoGravity = false; - } - - break; - } - - tr.ent->entity->CheckGround(); - - if (!tr.ent->entity->groundentity || (tr.ent->entity->groundentity == edict && - (!m_pCollisionEntity || tr.ent->entity != m_pCollisionEntity))) - { - Event *event = new Event( EV_Touch ); - event->AddEntity( this ); - tr.ent->entity->ProcessEvent( event ); - - event = new Event( EV_Touch ); - event->AddEntity( tr.ent->entity ); - ProcessEvent( event ); - - if( tr.ent->entity->IsSubclassOfSentient() ) - bHitPerson = true; - - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Hit(MV): %s : %s\n", tr.ent->entity->getClassname(), tr.ent->entity->targetname.c_str() ); - } - - break; - } - - pSkippedEntities[ iNumSkippedEntities ] = tr.ent->entity; - iContentsEntities[ iNumSkippedEntities ] = tr.ent->r.contents; - solidEntities[ iNumSkippedEntities ] = tr.ent->solid; - iNumSkippedEntities++; - - if( iNumSkippedEntities >= MAX_SKIPPED_ENTITIES ) - { - gi.Error( ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n" ); - return; - } - - tr.ent->entity->setSolidType( SOLID_NOT ); - - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Skipped(MV): %s : %s\n", tr.ent->entity->getClassname(), tr.ent->entity->targetname.c_str() ); - } - } - } - } + SetControllerTag(0, gi.Tag_NumForName(edict->tiki, "Tire_rotate_front_left")); + SetControllerTag(1, gi.Tag_NumForName(edict->tiki, "Tire_rotate_front_right")); + SetControllerTag(2, gi.Tag_NumForName(edict->tiki, "steeringwheel_center")); } /* ==================== -Vehicle::AssertMove +Vehicle::VehicleStart ==================== */ -bool Vehicle::AssertMove - ( - Vector vNewOrigin, - Vector vOldOrigin - ) +void Vehicle::VehicleStart(Event *ev) { - Entity *check; - gentity_t *edict; - int touch[ MAX_GENTITIES ]; - int i; - int num; + Entity *ent; + VehicleBase *last; + orientation_t orient; - if( m_pCollisionEntity ) - { - num = gi.AreaEntities( m_pCollisionEntity->mins, m_pCollisionEntity->maxs, touch, MAX_GENTITIES ); - } - else - { - num = gi.AreaEntities( mins, maxs, touch, MAX_GENTITIES ); - } + // become solid + setSolidType(SOLID_BBOX); + edict->r.contents = CONTENTS_BBOX; - if( num <= 0 ) - { - return true; - } + last = this; - for( i = 0; i < num; i++ ) - { - edict = &g_entities[ touch[ i ] ]; - check = edict->entity; + setLocalOrigin(localorigin + Vector(0.0f, 0.0f, 30.0f)); + angles.x = m_vAngles.x; + angles.z = m_vAngles.z; - if( check->edict->s.number != edict->s.number && edict->solid && check->movetype != MOVETYPE_STOP ) - { - if( check->movetype != MOVETYPE_NONE - && check->movetype != MOVETYPE_NOCLIP - && edict->r.contents != CONTENTS_PLAYERCLIP - && IsTouching( check ) - && G_TestEntityPosition( check, check->origin ) ) - { - return false; - } - } - } + for (ent = G_NextEntity(NULL); ent != NULL; ent = G_NextEntity(ent)) { + if ((ent != this) && (ent->isSubclassOf(VehicleBase))) { + if ((ent->absmax.x >= absmin.x) && (ent->absmax.y >= absmin.y) && (ent->absmax.z >= absmin.z) + && (ent->absmin.x <= absmax.x) && (ent->absmin.y <= absmax.y) && (ent->absmin.z <= absmax.z)) { + last->vlink = (VehicleBase *)ent; + last = (VehicleBase *)ent; + last->offset = last->origin - origin; + last->offset = getLocalVector(last->offset); + last->edict->s.scale *= edict->s.scale; + } + } + } - return true; + last->vlink = NULL; + + OpenSlotsByModel(); + + // + // get the seat offset + // + if (GetRawTag("seat", &orient)) { + driveroffset = Vector(orient.origin); + } + driveroffset += seatoffset * edict->s.scale; + + SetDriverAngles(angles + seatangles); + + max_health = health; + + // + // since 2.0: set targetname for all busy turrets + // + for (int i = 0; i < numTurrets; i++) { + if (Turrets[i].flags & SLOT_BUSY) { + Turrets[i].ent->SetTargetName(TargetName() + "_turret" + str(i)); + } + } + + last_origin = origin; + link(); } /* ==================== -Vehicle::AssertRotation +Vehicle::SetWheelCorners ==================== */ -bool Vehicle::AssertRotation - ( - Vector vNewAngles, - Vector vOldAngles - ) +void Vehicle::SetWheelCorners(Event *ev) { - Vector i; - Vector j; - Vector k; - Vector i2; - Vector j2; - Vector k2; - Vector vAngleDiff; - float mAngleDiff[ 3 ][ 3 ]; + Vector size; + Vector offset; - AngleVectorsLeft( vOldAngles, i, j, k ); - AngleVectorsLeft( vNewAngles, i2, j2, k2 ); - AnglesSubtract( vOldAngles, vNewAngles, vAngleDiff ); - AngleVectorsLeft( vAngleDiff, mAngleDiff[ 0 ], mAngleDiff[ 1 ], mAngleDiff[ 2 ] ); + size = ev->GetVector(1); + offset = ev->GetVector(2); - // FIXME: not sure what it is supposed to do. Should we put an assert there ? + m_vOriginCornerOffset = offset; + maxtracedist = size[2]; - return true; + Corners[0][0] = -(size[0] / 2); + Corners[0][1] = (size[1] / 2); + Corners[0][2] = size[2]; + + Corners[1][0] = (size[0] / 2); + Corners[1][1] = (size[1] / 2); + Corners[1][2] = size[2]; + + Corners[2][0] = -(size[0] / 2); + Corners[2][1] = -(size[1] / 2); + Corners[2][2] = size[2]; + + Corners[3][0] = (size[0] / 2); + Corners[3][1] = -(size[1] / 2); + Corners[3][2] = size[2]; + + SetupVehicleSoundEntities(); } /* ==================== -Vehicle::NoMove +Vehicle::QuerySpeed ==================== */ -void Vehicle::NoMove - ( - void - ) - +float Vehicle::QuerySpeed(void) { - vmove_t vm; - - SetMoveInfo( &vm ); - VectorClear2D( vs.desired_dir ); - VmoveSingle( &vm ); - GetMoveInfo( &vm ); -} - -/* -==================== -Vehicle::SlidePush -==================== -*/ -void Vehicle::SlidePush - ( - Vector vPush - ) -{ - vmove_t vm; - int i; - int j; - Entity *pSkippedEntities[ MAX_SKIPPED_ENTITIES ]; - int iContentsEntities[ MAX_SKIPPED_ENTITIES ]; - solid_t solidEntities[ MAX_SKIPPED_ENTITIES ]; - int iNumSkippedEntities = 0; - int iNumSkipped = 0; - gentity_t *other; - Vector newOrigin; - - do - { - SetMoveInfo( &vm ); - - VectorCopy( vPush, vs.velocity ); - vs.desired_dir[ 0 ] = vPush[ 0 ]; - vs.desired_dir[ 1 ] = vPush[ 1 ]; - VectorNormalize2D( vs.desired_dir ); - - if( g_showvehiclemovedebug->integer ) - { - G_DebugBBox( origin, vm.mins, vm.maxs, 1.0f, 0.0f, 0.0f, 1.0f ); - G_DebugBBox( origin, vm.mins, vm.maxs, 0.0f, 1.0f, 0.0f, 1.0f ); - } - - VmoveSingle( &vm ); - - iNumSkippedEntities = 0; - - for( i = 0; i < vm.numtouch; i++ ) - { - other = &g_entities[ vm.touchents[ i ] ]; - - for( j = 0; j < i; j++ ) - { - if( &g_entities[ j ] == other ) - { - break; - } - } - - if( j == i && other->entity ) - { - other->entity->CheckGround(); - - if( other->entity->groundentity && ( other->entity->groundentity == edict || other->entity == m_pCollisionEntity ) ) - { - // save the entity - pSkippedEntities[ iNumSkipped ] = other->entity; - iContentsEntities[ iNumSkipped ] = other->r.contents; - solidEntities[ iNumSkipped ] = other->solid; - iNumSkipped++; - - if( iNumSkipped >= MAX_SKIPPED_ENTITIES ) - { - gi.Error( ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n" ); - return; - } - - other->entity->setSolidType( SOLID_NOT ); - iNumSkippedEntities++; - } - - if( g_showvehiclemovedebug->integer ) - { - Com_Printf( "Vehicle Hit(SP): %s : %s\n", other->entity->getClassname(), other->entity->targetname.c_str() ); - } - } - } - } while( iNumSkippedEntities != 0 ); - - if( bindmaster ) - { - newOrigin = vm.vs->origin - bindmaster->origin; - } - else - { - newOrigin = vm.vs->origin; - } - - setLocalOrigin( newOrigin ); - - if( g_showvehiclemovedebug->integer ) - { - G_DebugBBox( origin, vm.mins, vm.maxs, 0, 0, 1.0f, 1.0f ); - } - - TouchStuff( &vm ); - - for( i = 0; i < iNumSkipped; i++ ) - { - pSkippedEntities[ i ]->setSolidType( solidEntities[ i ] ); - pSkippedEntities[ i ]->edict->r.contents = iContentsEntities[ i ]; - } -} - -/* -==================== -Vehicle::SetupPath -==================== -*/ -void Vehicle::SetupPath - ( - cSpline<4, 512> *pPath, - SimpleEntity *se - ) -{ - Vector vLastOrigin; - SimpleEntity *ent; - float fCurLength = 0.0f; - int i = 1; - - if( !pPath ) - { - return; - } - - pPath->Reset(); - - if( !se->target.length() || !*se->target ) - { - return; - } - - vLastOrigin = se->origin; - - for( ent = se; ent != NULL; ent = ent->Next(), i++ ) - { - Vector vDelta = vLastOrigin - ent->origin; - float vTmp[ 4 ]; - - if( vDelta.length() == 0.0f && i > 1 ) - { - Com_Printf( "^~^~^Warning: Vehicle Driving with a Path that contains 2 equal points\n" ); - } - else - { - vLastOrigin = ent->origin; - fCurLength += vDelta.length(); - - vTmp[ 0 ] = fCurLength; - VectorCopy( vTmp + 1, ent->origin ); - - if( ent->IsSubclassOfVehiclePoint() ) - { - pPath->Add( vTmp, ( ( VehiclePoint * )ent )->spawnflags ); - } - else - { - pPath->Add( vTmp, 0 ); - } - } - - if( ent == se && i > 1 ) - { - break; - } - } -} - -/* -==================== -Vehicle::UpdateSound -==================== -*/ -void Vehicle::UpdateSound - ( - void - ) - -{ - float pitch; - float volume; - - if( level.time < m_fNextSoundState ) - { - return; - } - - // Calculate the pitch based on the vehicle's speed - pitch = ( velocity.length() - m_fSoundMinSpeed ) / ( m_fSoundMaxSpeed - m_fSoundMinSpeed ); - - if( pitch > 1.0f ) - { - pitch = 1.0f; - } - else if( pitch < 0.0f ) - { - pitch = 0.0f; - } - - pitch = m_fSoundMinPitch + ( m_fSoundMaxPitch - m_fSoundMinPitch ) * pitch; - - volume = ( velocity.length() - m_fVolumeMinSpeed ) / ( m_fVolumeMaxSpeed - m_fVolumeMinSpeed ); - - if( volume > 1.0f ) - { - volume = 1.0f; - } - else if( volume < 0.0f ) - { - volume = 0.0f; - } - - volume = this->m_fVolumeMinPitch + ( this->m_fVolumeMaxPitch - this->m_fVolumeMinPitch ) * volume; - - switch( m_eSoundState ) - { - case ST_OFF: - StopLoopSound(); - TurnOffVehicleSoundEntities(); - m_fNextSoundState = level.time; - - if( driver.ent || m_bAutoPilot ) - { - m_eSoundState = ST_OFF_TRANS_IDLE; - } - break; - - case ST_OFF_TRANS_IDLE: - m_fNextSoundState = level.time; - m_eSoundState = ST_IDLE; - Sound( m_sSoundSet + "snd_on" ); - LoopSound( m_sSoundSet + "snd_idle" ); - break; - - case ST_IDLE_TRANS_OFF: - m_fNextSoundState = level.time; - m_eSoundState = ST_OFF; - Sound( m_sSoundSet + "snd_off" ); - StopLoopSound(); - break; - - case ST_IDLE: - m_fNextSoundState = level.time; - - if( driver.ent || m_bAutoPilot ) - { - if( fabs( DotProduct( orientation[ 0 ], velocity ) ) > 10.0f ) - { - m_eSoundState = ST_IDLE_TRANS_RUN; - } - } - else - { - m_eSoundState = ST_IDLE_TRANS_OFF; - } - - LoopSound( m_sSoundSet + "snd_idle" ); - - TurnOffVehicleSoundEntities(); - break; - - case ST_IDLE_TRANS_RUN: - m_fNextSoundState = level.time; - m_eSoundState = ST_RUN; - - Sound( m_sSoundSet + "snd_revup" ); - LoopSound( m_sSoundSet + "snd_run", -1.0f, -1.0f, -1.0f, pitch ); - break; - - case ST_RUN: - m_fNextSoundState = level.time; - - if( fabs( DotProduct( orientation[ 0 ], velocity ) ) < 10.0f ) - { - m_eSoundState = ST_RUN_TRANS_IDLE; - } - - TurnOnVehicleSoundEntities(); - LoopSound( m_sSoundSet + "snd_run", volume, -1.0f, -1.0f, pitch ); - break; - - case ST_RUN_TRANS_IDLE: - m_fNextSoundState = level.time; - m_eSoundState = ST_IDLE; - - Sound( m_sSoundSet + "snd_revdown" ); - LoopSound( m_sSoundSet + "snd_idle" ); - break; - - default: - m_fNextSoundState = level.time; - m_eSoundState = ST_OFF; - break; - } -} - -/* -==================== -Vehicle::SetupVehicleSoundEntities -==================== -*/ -void Vehicle::SetupVehicleSoundEntities - ( - void - ) - -{ - int i; - Vector a; - Vector b; - Vector c; - Vector start; - - angles.AngleVectorsLeft( &a, &b, &c ); - - // place the sound entities in the vehicle wheels - for( i = 0; i < MAX_SOUND_ENTITIES; i++ ) - { - if( !m_pVehicleSoundEntities[ i ] ) - { - m_pVehicleSoundEntities[ i ] = new VehicleSoundEntity( this ); - } - - start = origin + a * Corners[ i ][ 0 ] + b * Corners[ i ][ 1 ] + c * Corners[ i ][ 2 ]; - m_pVehicleSoundEntities[ i ]->setOrigin( start ); - } -} - -/* -==================== -Vehicle::RemoveVehicleSoundEntities -==================== -*/ -void Vehicle::RemoveVehicleSoundEntities - ( - void - ) - -{ - for( int i = 0; i < MAX_SOUND_ENTITIES; i++ ) - { - if( !m_pVehicleSoundEntities[ i ] ) - { - continue; - } - - m_pVehicleSoundEntities[ i ]->PostEvent( EV_Remove, EV_VEHICLE ); - } -} - -/* -==================== -Vehicle::TurnOnVehicleSoundEntities -==================== -*/ -void Vehicle::TurnOnVehicleSoundEntities - ( - void - ) - -{ - for( int i = 0; i < MAX_SOUND_ENTITIES; i++ ) - { - if( !m_pVehicleSoundEntities[ i ] ) - { - m_pVehicleSoundEntities[ i ] = new VehicleSoundEntity( this ); - } - - m_pVehicleSoundEntities[ i ]->Start(); - } -} - -/* -==================== -Vehicle::TurnOffVehicleSoundEntities -==================== -*/ -void Vehicle::TurnOffVehicleSoundEntities - ( - void - ) - -{ - for( int i = 0; i < MAX_SOUND_ENTITIES; i++ ) - { - if( !m_pVehicleSoundEntities[ i ] ) - { - m_pVehicleSoundEntities[ i ] = new VehicleSoundEntity( this ); - } - - m_pVehicleSoundEntities[ i ]->Stop(); - } -} - -/* -==================== -Vehicle::UpdateTires -==================== -*/ -void Vehicle::UpdateTires - ( - void - ) - -{ - int index; - trace_t trace; - Vector a; - Vector b; - Vector c; - Vector vTmp; - Vector t_mins; - Vector t_maxs; - Vector start; - Vector end; - Vector boxoffset; - Entity *pSkippedEntities[ MAX_SKIPPED_ENTITIES ]; - int iContentsEntities[ MAX_SKIPPED_ENTITIES ]; - solid_t solidEntities[ MAX_SKIPPED_ENTITIES ]; - int iNumSkippedEntities; - int iNumSkipped = 0; - - t_mins = mins * 0.25f; - t_maxs = maxs * 0.25f; - - if( real_velocity.length() <= 0.5f && m_iLastTiresUpdate != -1 ) - { - if( m_iLastTiresUpdate + 1000 > level.inttime ) - return; - } - - m_iLastTiresUpdate = level.inttime; - - vTmp[ 1 ] = angles[ 1 ] + m_fSkidAngle; - AngleVectors( vTmp, a, b, c ); - - // Temporary make slots non-solid for G_Trace - SetSlotsNonSolid(); - - do - { - iNumSkippedEntities = 0; - - for( index = 0; index < MAX_CORNERS; index++ ) - { - boxoffset = Corners[ index ]; - start = origin + a * boxoffset[ 0 ] + b * boxoffset[ 1 ] + c * boxoffset[ 2 ]; - end = start; - end[ 2 ] -= 400.0f; - - trace = G_Trace( start, t_mins, t_maxs, end, this, MASK_VEHICLE, false, "Vehicle::PostThink Corners" ); - - if( g_showvehiclemovedebug->integer ) - { - G_DebugBBox( origin, start, end, 1.0f, 1.0f, 1.0f, 1.0f ); - G_DebugBBox( origin, start, trace.endpos, 1.0f, 0.0f, 0.0f, 1.0f ); - } - - if( trace.ent && trace.ent->entity && trace.ent->entity->isSubclassOf( VehicleCollisionEntity ) ) - { - // save the entity - pSkippedEntities[ iNumSkipped ] = trace.ent->entity; - iContentsEntities[ iNumSkipped ] = trace.ent->r.contents; - solidEntities[ iNumSkipped ] = trace.ent->solid; - iNumSkipped++; - - if( iNumSkipped >= MAX_SKIPPED_ENTITIES ) - { - gi.Error( ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n" ); - return; - } - - trace.ent->entity->setSolidType( SOLID_NOT ); - iNumSkippedEntities++; - } - - if( trace.fraction == 1.0 ) - { - m_bTireHit[ index ] = false; - } - else - { - m_vTireEnd[ index ] = trace.endpos; - m_bTireHit[ index ] = true; - } - } - } while( iNumSkippedEntities != 0 ); - - for( index = 0; index < iNumSkipped; index++ ) - { - pSkippedEntities[ index ]->setSolidType( solidEntities[ index ] ); - pSkippedEntities[ index ]->edict->r.contents = iContentsEntities[ index ]; - } - - // Turn slots back into a solid state - SetSlotsSolid(); -} - -/* -==================== -Vehicle::UpdateNormals -==================== -*/ -void Vehicle::UpdateNormals - ( - void - ) - -{ - Vector vDist1; - Vector vDist2; - Vector vCross; - Vector temp; - Vector pitch; - Vector i; - Vector j; - - if (real_velocity.length() <= 0.5) - { - if (m_iLastTiresUpdate != -1 && m_iLastTiresUpdate + 1000 > level.inttime) - return; - } - - AngleVectorsLeft(angles, NULL, pitch, NULL); - - m_vNormalSum = vec_zero; - - pitch = -pitch; - - m_iNumNormals = 0; - - if (m_bTireHit[0] && m_bTireHit[1] && m_bTireHit[2]) - { - vDist1 = m_vTireEnd[1] - m_vTireEnd[0]; - vDist2 = m_vTireEnd[1] - m_vTireEnd[2]; - - vCross.CrossProduct(vDist1, vDist2); - VectorNormalize(vCross); - - m_vNormalSum += vCross; - - m_iNumNormals++; - } - - if (m_bTireHit[1] && m_bTireHit[2] && m_bTireHit[3]) - { - vDist1 = m_vTireEnd[2] - m_vTireEnd[1]; - vDist2 = m_vTireEnd[2] - m_vTireEnd[3]; - - vCross.CrossProduct(vDist1, vDist2); - VectorNormalize(vCross); - - m_vNormalSum += vCross; - - m_iNumNormals++; - } - - if (m_bTireHit[2] && m_bTireHit[3] && m_bTireHit[0]) - { - vDist1 = m_vTireEnd[3] - m_vTireEnd[0]; - vDist2 = m_vTireEnd[3] - m_vTireEnd[2]; - - vCross.CrossProduct(vDist1, vDist2); - VectorNormalize(vCross); - - m_vNormalSum += vCross; - - m_iNumNormals++; - } - - if (m_bTireHit[3] && m_bTireHit[0] && m_bTireHit[1]) - { - vDist1 = m_vTireEnd[0] - m_vTireEnd[3]; - vDist2 = m_vTireEnd[0] - m_vTireEnd[1]; - - vCross.CrossProduct(vDist1, vDist2); - VectorNormalize(vCross); - - m_vNormalSum += vCross; - - m_iNumNormals++; - } - - if (m_iNumNormals > 1) - { - temp = m_vNormalSum / m_iNumNormals; - - i.CrossProduct(temp, pitch); - - angles[0] = i.toPitch(); - - j.CrossProduct(temp, i); - - angles[2] = j.toPitch(); - } -} - -/* -==================== -Vehicle::UpdateBones -==================== -*/ -void Vehicle::UpdateBones - ( - void - ) - -{ - float fNewTurnAngle = AngleNormalize180( turnangle - m_fSkidAngle ); - - if( fabs( fNewTurnAngle ) > maxturnrate ) - { - fNewTurnAngle = maxturnrate; - } - - SetControllerAngles( 0, Vector( 0, fNewTurnAngle, 0 ) ); - SetControllerAngles( 1, Vector( 0, fNewTurnAngle, 0 ) ); -} - -/* -==================== -Vehicle::UpdateShaderOffset -==================== -*/ -void Vehicle::UpdateShaderOffset - ( - void - ) - -{ - m_fShaderOffset -= orientation[ 0 ] * real_velocity * 0.25 * level.frametime; - edict->s.shader_time = m_fShaderOffset; -} - -/* -==================== -Vehicle::UpdateTurretSlot -==================== -*/ -void Vehicle::UpdateTurretSlot - ( - int iSlot - ) -{ - orientation_t orient; - - if( !( Turrets[ iSlot ].flags & SLOT_BUSY ) || !Turrets[ iSlot ].ent ) - { - return; - } - - if( Turrets[ iSlot ].boneindex != -1 ) - { - GetTag( Turrets[ iSlot ].boneindex, &orient ); - if( Turrets[ iSlot ].ent->IsSubclassOfActor() ) - { - Turrets[ iSlot ].ent->setOriginEvent( orient.origin ); - } - else - { - Turrets[ iSlot ].ent->setOrigin( orient.origin ); - } - } - else - { - Vector forward = orientation[ 0 ]; - Vector left = orientation[ 1 ]; - Vector up = orientation[ 2 ]; - - if( Turrets[ iSlot ].ent->IsSubclassOfActor() ) - { - Turrets[ iSlot ].ent->setOriginEvent( origin ); - } - else - { - Turrets[ iSlot ].ent->setOrigin( origin ); - } - } - - Turrets[ iSlot ].ent->avelocity = avelocity; - Turrets[ iSlot ].ent->velocity = velocity; - - if( !Turrets[ iSlot ].ent->IsSubclassOfActor() || ( ( Actor * )Turrets[ iSlot ].ent.Pointer() )->m_Enemy ) - { - Turrets[ iSlot ].ent->setAngles( angles ); - } -} - -/* -==================== -Vehicle::UpdatePassengerSlot -==================== -*/ -void Vehicle::UpdatePassengerSlot - ( - int iSlot - ) -{ - orientation_t orient; - - if( !( Passengers[ iSlot ].flags & SLOT_BUSY ) || !Passengers[ iSlot ].ent ) - { - return; - } - - if( Passengers[ iSlot ].boneindex != -1 ) - { - GetTag( Passengers[ iSlot ].boneindex, &orient ); - if( Passengers[ iSlot ].ent->IsSubclassOfActor() ) - { - Passengers[ iSlot ].ent->setOriginEvent( orient.origin ); - } - else - { - Passengers[ iSlot ].ent->setOrigin( orient.origin ); - } - } - else - { - if( Passengers[ iSlot ].ent->IsSubclassOfActor() ) - { - Passengers[ iSlot ].ent->setOriginEvent( origin ); - } - else - { - Passengers[ iSlot ].ent->setOrigin( origin ); - } - } - - Passengers[ iSlot ].ent->avelocity = avelocity; - Passengers[ iSlot ].ent->velocity = velocity; - - if( !Passengers[ iSlot ].ent->IsSubclassOfActor() || ( ( Actor * )Passengers[ iSlot ].ent.Pointer() )->m_Enemy ) - { - Passengers[ iSlot ].ent->setAngles( angles ); - } -} - -/* -==================== -Vehicle::UpdateDriverSlot -==================== -*/ -void Vehicle::UpdateDriverSlot - ( - int iSlot - ) -{ - orientation_t orient; - - if( !( driver.flags & SLOT_BUSY ) || !driver.ent ) - { - return; - } - - if( driver.boneindex != -1 ) - { - GetTag( driver.boneindex, &orient ); - if( driver.ent->IsSubclassOfActor() ) - { - driver.ent->setOriginEvent( orient.origin ); - } - else - { - driver.ent->setOrigin( orient.origin ); - } - } - else - { - Vector forward = orientation[ 0 ]; - Vector left = orientation[ 1 ]; - Vector up = orientation[ 2 ]; - - if( driver.ent->IsSubclassOfActor() ) - { - driver.ent->setOriginEvent( origin + forward * driveroffset[ 0 ] + left * driveroffset[ 1 ] + up * driveroffset[ 2 ] ); - } - else - { - driver.ent->setOrigin( origin + forward * driveroffset[ 0 ] + left * driveroffset[ 1 ] + up * driveroffset[ 2 ] ); - } - } - - if( drivable ) - { - driver.ent->avelocity = avelocity; - driver.ent->velocity = velocity; - driver.ent->setAngles( angles ); - } -} - -/* -==================== -Vehicle::UpdateSkidAngle -==================== -*/ -void Vehicle::UpdateSkidAngle - ( - void - ) -{ - if( m_bEnableSkidding ) - { - if( g_showvehiclemovedebug && g_showvehiclemovedebug->integer ) - { - Com_Printf( "Skidding!\n" ); - } - - m_fSkidLeftForce += velocity.length() / 150.0f * turnangle; - m_fSkidRightForce += -m_fSkidAngle * 0.2; - m_fSkidRightForce *= 0.3f; - m_fSkidAngle = m_fSkidAngle + ( m_fSkidLeftForce + m_fSkidRightForce ) * 22.0f * level.frametime; - m_vSkidOrigin[ 0 ] = -fabs( m_fSkidAngle ); - } - else - { - m_fSkidAngle = 0; - } -} - -/* -==================== -Vehicle::GetPathPosition -==================== -*/ -float Vehicle::GetPathPosition - ( - cSpline<4, 512> *pPath, - int iNode - ) -{ - float *vTmp; - float vPrev[ 3 ]; - float vCur[ 3 ]; - float vTotal[ 3 ]; - Vector vDelta; - float fTotal; - float fCoef; - - vTmp = pPath->GetByNode( iNode, NULL ); - VectorCopy( vCur, vTmp + 1 ); - - if( g_showvehiclemovedebug->integer ) - { - G_DebugString( Vector( vTmp[ 1 ], vTmp[ 2 ], vTmp[ 3 ] ), 3.0f, 1.0f, 1.0f, 1.0f, "%f", vTmp[ 0 ] ); - } - - vTmp = pPath->GetByNode( iNode - 1, NULL ); - VectorCopy( vPrev, vTmp + 1 ); - - if( g_showvehiclemovedebug->integer ) - { - G_DebugString( Vector( vTmp[ 1 ], vTmp[ 2 ], vTmp[ 3 ] ), 3.0f, 1.0f, 1.0f, 1.0f, "%f", vTmp[ 0 ] ); - } - - VectorCopy( Vector( vCur ) - Vector( vPrev ), vTotal ); - m_vIdealDir = vTotal; - fTotal = m_vIdealDir.length(); - VectorNormalize( m_vIdealDir ); - angles.AngleVectorsLeft( &vDelta, NULL, NULL ); - - fCoef = ProjectLineOnPlane( vDelta, DotProduct( vDelta, origin ), vPrev, vCur, NULL ); - - if( g_showvehiclemovedebug->integer ) - { - G_DebugBBox( vPrev, Vector( -32.0f, -32.0f, -32.0f ), Vector( 32.0f, 32.0f, 32.0f ), 0, 1.0f, 1.0f, 1.0f ); - G_DebugBBox( vCur, Vector( -32.0f, -32.0f, -32.0f ), Vector( 32.0f, 32.0f, 32.0f ), 1.0f, 1.0f, 0, 1.0f ); - G_DebugArrow( vCur, m_vIdealDir * -1.0f, ( 1.0 - fCoef ) * fTotal, 0, 1.0f, 0, 1.0f ); - G_DebugArrow( vPrev, m_vIdealDir, fCoef * fTotal, 0, 0, 1.0f, 1.0f ); - } - - return *pPath->GetByNode( iNode - ( 1.0 - fCoef ), NULL ); -} - -/* -==================== -Vehicle::FactorInSkidOrigin -==================== -*/ -void Vehicle::FactorInSkidOrigin - ( - void - ) - -{ - Vector vNewOrigin; - - vNewOrigin[ 0 ] = orientation[ 0 ][ 0 ] * m_vSkidOrigin[ 0 ] + orientation[ 1 ][ 0 ] * m_vSkidOrigin[ 1 ] + orientation[ 2 ][ 0 ] * m_vSkidOrigin[ 2 ]; - vNewOrigin[ 1 ] = orientation[ 0 ][ 1 ] * m_vSkidOrigin[ 0 ] + orientation[ 1 ][ 1 ] * m_vSkidOrigin[ 1 ] + orientation[ 2 ][ 1 ] * m_vSkidOrigin[ 2 ]; - vNewOrigin[ 2 ] = orientation[ 0 ][ 2 ] * m_vSkidOrigin[ 0 ] + orientation[ 1 ][ 2 ] * m_vSkidOrigin[ 1 ] + orientation[ 2 ][ 2 ] * m_vSkidOrigin[ 2 ]; - - m_vOriginOffset2 += vNewOrigin; -} - -/* -==================== -Vehicle::FactorInOriginOffset -==================== -*/ -void Vehicle::FactorInOriginOffset - ( - void - ) - -{ - origin += m_vOriginOffset; - setOrigin( origin ); -} - -/* -==================== -Vehicle::CalculateOriginOffset -==================== -*/ -void Vehicle::CalculateOriginOffset - ( - void - ) - -{ - int index; - Vector vTireAvg; - Vector vMissHit; - Vector temp; - int iNum = 0; - Vector acceleration; - - m_vOriginOffset += m_vOriginOffset2; - m_vOriginOffset2 = vec_zero; - - for( index = 0; index < MAX_CORNERS; index++ ) - { - if( m_bTireHit[ index ] ) - { - iNum++; - temp = m_vTireEnd[ index ]; - vTireAvg += origin - temp; - } - else - { - temp = Corners[ index ]; - vMissHit = temp; - } - } - - if( iNum == 3 ) - { - temp = m_vNormalSum * ( 1.0f / m_iNumNormals ); - ProjectPointOnPlane( acceleration, vMissHit, temp ); - vTireAvg += acceleration; - } - else if( iNum == 4 ) - { - vTireAvg *= 0.25f; - MatrixTransformVector( m_vOriginCornerOffset, orientation, acceleration ); - vTireAvg -= acceleration; - m_vOriginOffset2 += vTireAvg; - } - - m_vOriginOffset2[ 0 ] += orientation[ 0 ][ 0 ] * m_vSkidOrigin[ 0 ] + orientation[ 1 ][ 0 ] * m_vSkidOrigin[ 1 ] + orientation[ 2 ][ 0 ] * m_vSkidOrigin[ 2 ]; - m_vOriginOffset2[ 1 ] += orientation[ 0 ][ 1 ] * m_vSkidOrigin[ 0 ] + orientation[ 1 ][ 1 ] * m_vSkidOrigin[ 1 ] + orientation[ 2 ][ 1 ] * m_vSkidOrigin[ 2 ]; - m_vOriginOffset2[ 2 ] += orientation[ 0 ][ 2 ] * m_vSkidOrigin[ 0 ] + orientation[ 1 ][ 2 ] * m_vSkidOrigin[ 1 ] + orientation[ 2 ][ 2 ] * m_vSkidOrigin[ 2 ]; - - Vector vTmp = real_acceleration - prev_acceleration; - - m_fDownForce = vTmp[ 2 ] * m_fZCoef; - - if( m_fDownForce > m_fZMax ) - { - m_fDownForce = m_fZMax; - } - else if( m_fDownForce < m_fZMin ) - { - m_fDownForce = m_fZMin; - } - - m_fUpForce = ( -m_vOriginOffset[ 2 ] * m_fBouncyCoef + m_fUpForce ) * m_fSpringyCoef; - m_vOriginOffset2[ 2 ] += ( m_fDownForce + m_fUpForce ) * 12.0 * level.frametime; - - if( m_vOriginOffset2[ 2 ] > m_fZMax ) - { - m_vOriginOffset2[ 2 ] = m_fZMax; - } - else if( m_vOriginOffset2[ 2 ] < m_fZMin ) - { - m_vOriginOffset2[ 2 ] = m_fZMin; - } - - m_vOriginOffset -= m_vOriginOffset2; -} - -/* -==================== -Vehicle::FactorOutOriginOffset -==================== -*/ -void Vehicle::FactorOutOriginOffset - ( - void - ) - -{ - origin -= m_vOriginOffset; - setOrigin( origin ); -} - -/* -==================== -Vehicle::FactorInAnglesOffset -==================== -*/ -void Vehicle::FactorInAnglesOffset - ( - Vector *vAddedAngles - ) -{ - ( *vAddedAngles ) += m_vAnglesOffset; - ( *vAddedAngles )[ 1 ] += m_fSkidAngle; -} - -/* -==================== -Vehicle::CalculateAnglesOffset -==================== -*/ -void Vehicle::CalculateAnglesOffset - ( - Vector acceleration - ) -{ - if( level.time <= 1200 ) - { - return; - } - - m_fForwardForce += DotProduct( orientation[ 0 ], acceleration ) * m_fYawCoef; - m_fBackForce = ( -m_vAnglesOffset[ 0 ] * m_fBouncyCoef + m_fBackForce ) * m_fSpringyCoef; - - m_vAnglesOffset[ 0 ] += m_fForwardForce + m_fBackForce * 12.0 * level.frametime; - - if( m_vAnglesOffset[ 0 ] > m_fYawMax ) - { - m_vAnglesOffset[ 0 ] = m_fYawMax; - } - else if( m_vAnglesOffset[ 0 ] < m_fYawMin ) - { - m_vAnglesOffset[ 0 ] = m_fYawMin; - } - - m_fForwardForce = 0; - m_fLeftForce += DotProduct( orientation[ 1 ], acceleration ) * m_fRollCoef; - m_fRightForce = ( -m_vAnglesOffset[ 2 ] * m_fBouncyCoef + m_fRightForce ) * m_fSpringyCoef; - - m_vAnglesOffset[ 2 ] += 12.0 * ( m_fLeftForce + m_fRightForce ) *level.frametime; - - if( m_vAnglesOffset[ 2 ] > m_fRollMax ) - { - m_vAnglesOffset[ 2 ] = m_fRollMax; - } - else if( m_vAnglesOffset[ 2 ] < m_fRollMin ) - { - m_vAnglesOffset[ 2 ] = m_fRollMin; - } - - m_fLeftForce = 0; -} - -/* -==================== -Vehicle::FactorOutAnglesOffset -==================== -*/ -void Vehicle::FactorOutAnglesOffset - ( - void - ) - -{ - -} - -/* -==================== -Vehicle::GetTagPositionAndOrientation -==================== -*/ -qboolean Vehicle::GetTagPositionAndOrientation - ( - str tagname, - orientation_t *new_or - ) -{ - int tagnum = gi.Tag_NumForName( edict->tiki, tagname.c_str() ); - - if( tagnum < 0 ) - { - warning( "Vehicle::GetTagPositionAndOrientation", "Could not find tag \"%s\"", tagname.c_str() ); - return false; - } - else - { - return GetTagPositionAndOrientation( tagnum, new_or ); - } -} - -/* -==================== -Vehicle::GetTagPositionAndOrientation -==================== -*/ -qboolean Vehicle::GetTagPositionAndOrientation - ( - int tagnum, - orientation_t *new_or - ) -{ - int i; - orientation_t tag_or; - float axis[ 3 ][ 3 ]; - - GetRawTag( tagnum, &tag_or ); - - AnglesToAxis( angles, axis ); - - VectorCopy( origin, new_or->origin ); - - for( i = 0; i < 3; i++ ) - { - VectorMA( new_or->origin, tag_or.origin[ i ], tag_or.axis[ i ], new_or->origin ); - } - - MatrixMultiply( tag_or.axis, axis, new_or->axis ); - return true; -} - -/* -==================== -Vehicle::CalculateAnimationData -==================== -*/ -void Vehicle::CalculateAnimationData - ( - Vector vAngles, - Vector vOrigin - ) -{ - float fLeft = fEpsilon(); - float fRight = fEpsilon(); - float fForward = 0; - float fBack = fEpsilon(); - float fLow = fEpsilon(); - - if( vAngles[ 1 ] < 0.0 ) - { - fBack = vAngles[ 1 ] / m_fYawMin; - } - else if( vAngles[ 1 ] > 0.0 ) - { - fForward = vAngles[ 1 ] / m_fYawMax; - } - - if( vAngles[ 2 ] > 0.0 ) - { - fRight = vAngles[ 2 ] / m_fRollMin; - } - else if( vAngles[ 2 ] < 0.0 ) - { - fLeft = vAngles[ 2 ] / m_fRollMax; - } - - if( vOrigin[ 2 ] < 0.0 ) - { - fBack = vOrigin[ 2 ] / m_fZMin; - } - else if( vOrigin[ 2 ] > 0.0 ) - { - fForward = vOrigin[ 2 ] / m_fZMax; - } - - NewAnim( "idle", 0 ); - NewAnim( "lean_left", 0, 3, fLeft ); - NewAnim( "lean_right", 0, 4, fRight ); - NewAnim( "lean_forward", 0, 1, fForward ); - NewAnim( "lean_back", 0, 2, fBack ); - NewAnim( "high", 0, 6, fEpsilon() ); - NewAnim( "low", 0, 5, fEpsilon() ); -} - -/* -==================== -Vehicle::IsDamagedBy - -Returns whether or not the vehicle is damaged by the specified entity. -==================== -*/ -bool Vehicle::IsDamagedBy - ( - Entity *ent - ) -{ - int i = FindDriverSlotByEntity( ent ); - - if( i == -1 ) - { - i = FindPassengerSlotByEntity( ent ); - - if( i == -1 ) - { - i = FindTurretSlotByEntity( ent ); - - if( i == -1 ) - { - for( i = 0; i < MAX_TURRETS; i++ ) - { - TurretGun *pTurret = ( TurretGun * )Turrets[ i ].ent.Pointer(); - - if( !pTurret ) - { - continue; - } - - if( pTurret->IsSubclassOfTurretGun() && pTurret->GetOwner() == ent ) - { - return false; - } - } - - return true; - } - } - } - - return false; -} - -/* -==================== -Vehicle::AutoPilot -==================== -*/ -void Vehicle::AutoPilot - ( - void - ) -{ - float *vTmp; - - if (!m_pCurPath || m_pCurPath->m_iPoints == 0) - { - m_bAutoPilot = false; - return; - } - - if (g_showvehiclepath && g_showvehiclepath->integer) - { - int iFlags = 0; - float fZ; - Vector vTmp1; - Vector vTmp2; - for (int i = 0; i < m_pCurPath->m_iPoints; i++) - { - vTmp = m_pCurPath->GetByNode(i, &iFlags); - vTmp1 = vTmp + 1; - fZ = 0; - //FIXME: macros - if (iFlags & 1) - { - fZ = 1; - G_DebugString(vTmp1 + Vector(0, 0, 32), sin(level.time) + 3, 1, 1, 0, "START_STOPPING"); - } - if (iFlags & 2) - { - G_DebugString(vTmp1 + Vector(0, 0, (fZ + 1) * 32), sin(level.time) + 3, 0, 1, 0, "START_SKIDDING"); - fZ++; - } - if (iFlags & 4) - { - G_DebugString(vTmp1 + Vector(0, 0, (fZ + 1) * 32), sin(level.time) + 3, 0, 0, 1, "STOP_SKIDDING"); - } - Vector vMaxs = Vector(sin(level.time), sin(level.time), sin(level.time)) * 16; - Vector vMins = vMaxs * -1; - vMaxs = Vector(sin(level.time), sin(level.time), sin(level.time)) * 16; - G_DebugBBox(vTmp1, vMins, vMaxs, 0, 0, 1, 1); - - - vTmp = m_pCurPath->GetByNode(i + 1, NULL); - vTmp2 = vTmp + 1; - - G_DebugLine(vTmp1, vTmp2, 0, 1, 0, 1); - } - } - // FIXME: stub -} - -/* -==================== -Vehicle::GetSoundSet -==================== -*/ -str Vehicle::GetSoundSet - ( - void - ) -{ - return m_sSoundSet; + return currentspeed; } /* @@ -5570,20 +1421,15 @@ str Vehicle::GetSoundSet Vehicle::QueryFreePassengerSlot ==================== */ -int Vehicle::QueryFreePassengerSlot - ( - void - ) +int Vehicle::QueryFreePassengerSlot(void) { - for( int i = 0; i < numPassengers; i++ ) - { - if( Passengers[ i ].flags & SLOT_FREE ) - { - return i; - } - } + for (int i = 0; i < numPassengers; i++) { + if (Passengers[i].flags & SLOT_FREE) { + return i; + } + } - return -1; + return -1; } /* @@ -5591,12 +1437,9 @@ int Vehicle::QueryFreePassengerSlot Vehicle::QueryFreeDriverSlot ==================== */ -int Vehicle::QueryFreeDriverSlot - ( - void - ) +int Vehicle::QueryFreeDriverSlot(void) { - return ( driver.flags & SLOT_FREE ) ? 0 : -1; + return (driver.flags & SLOT_FREE) ? 0 : -1; } /* @@ -5604,20 +1447,15 @@ int Vehicle::QueryFreeDriverSlot Vehicle::QueryFreeTurretSlot ==================== */ -int Vehicle::QueryFreeTurretSlot - ( - void - ) +int Vehicle::QueryFreeTurretSlot(void) { - for( int i = 0; i < numTurrets; i++ ) - { - if( Turrets[ i ].flags & SLOT_FREE ) - { - return i; - } - } + for (int i = 0; i < numTurrets; i++) { + if (Turrets[i].flags & SLOT_FREE) { + return i; + } + } - return -1; + return -1; } /* @@ -5625,23 +1463,16 @@ int Vehicle::QueryFreeTurretSlot Vehicle::QueryPassengerSlotPosition ==================== */ -void Vehicle::QueryPassengerSlotPosition - ( - int slot, - float *pos - ) +void Vehicle::QueryPassengerSlotPosition(int slot, float *pos) { - orientation_t orient; + orientation_t orient; - if( Passengers[ slot ].enter_boneindex >= 0 ) - { - GetTagPositionAndOrientation( Passengers[ slot ].enter_boneindex, &orient ); - VectorCopy( orient.origin, pos ); - } - else - { - VectorCopy( origin, pos ); - } + if (Passengers[slot].enter_boneindex >= 0) { + GetTagPositionAndOrientation(Passengers[slot].enter_boneindex, &orient); + VectorCopy(orient.origin, pos); + } else { + VectorCopy(origin, pos); + } } /* @@ -5649,23 +1480,16 @@ void Vehicle::QueryPassengerSlotPosition Vehicle::QueryDriverSlotPosition ==================== */ -void Vehicle::QueryDriverSlotPosition - ( - int slot, - float *pos - ) +void Vehicle::QueryDriverSlotPosition(int slot, float *pos) { - orientation_t orient; + orientation_t orient; - if( driver.enter_boneindex >= 0 ) - { - GetTagPositionAndOrientation( driver.enter_boneindex, &orient ); - VectorCopy( orient.origin, pos ); - } - else - { - VectorCopy( origin, pos ); - } + if (driver.enter_boneindex >= 0) { + GetTagPositionAndOrientation(driver.enter_boneindex, &orient); + VectorCopy(orient.origin, pos); + } else { + VectorCopy(origin, pos); + } } /* @@ -5673,23 +1497,19 @@ void Vehicle::QueryDriverSlotPosition Vehicle::QueryTurretSlotPosition ==================== */ -void Vehicle::QueryTurretSlotPosition - ( - int slot, - float *pos - ) +void Vehicle::QueryTurretSlotPosition(int slot, float *pos) { - orientation_t orient; + orientation_t orient; - if( Turrets[ slot ].enter_boneindex >= 0 ) - { - GetTagPositionAndOrientation( Turrets[ slot ].enter_boneindex, &orient ); - VectorCopy( orient.origin, pos ); - } - else - { - VectorCopy( origin, pos ); - } + if (Turrets[slot].enter_boneindex >= 0) { + GetTagPositionAndOrientation(Turrets[slot].enter_boneindex, &orient); + VectorCopy(orient.origin, pos); + } else if (Turrets[slot].boneindex >= 0) { + GetTagPositionAndOrientation(Turrets[slot].boneindex, &orient); + VectorCopy(orient.origin, pos); + } else { + VectorCopy(origin, pos); + } } /* @@ -5697,16 +1517,12 @@ void Vehicle::QueryTurretSlotPosition Vehicle::QueryPassengerSlotAngles ==================== */ -void Vehicle::QueryPassengerSlotAngles - ( - int slot, - float *ang - ) +void Vehicle::QueryPassengerSlotAngles(int slot, float *ang) { - orientation_t orient; + orientation_t orient; - GetTagPositionAndOrientation( Passengers[ slot ].enter_boneindex, &orient ); - MatrixToEulerAngles( orient.axis, ang ); + GetTagPositionAndOrientation(Passengers[slot].enter_boneindex, &orient); + MatrixToEulerAngles(orient.axis, ang); } /* @@ -5714,16 +1530,12 @@ void Vehicle::QueryPassengerSlotAngles Vehicle::QueryDriverSlotAngles ==================== */ -void Vehicle::QueryDriverSlotAngles - ( - int slot, - float *ang - ) +void Vehicle::QueryDriverSlotAngles(int slot, float *ang) { - orientation_t orient; + orientation_t orient; - GetTagPositionAndOrientation( driver.enter_boneindex, &orient ); - MatrixToEulerAngles( orient.axis, ang ); + GetTagPositionAndOrientation(driver.enter_boneindex, &orient); + MatrixToEulerAngles(orient.axis, ang); } /* @@ -5731,16 +1543,12 @@ void Vehicle::QueryDriverSlotAngles Vehicle::QueryTurretSlotAngles ==================== */ -void Vehicle::QueryTurretSlotAngles - ( - int slot, - float *ang - ) +void Vehicle::QueryTurretSlotAngles(int slot, float *ang) { - orientation_t orient; + orientation_t orient; - GetTagPositionAndOrientation( Turrets[ slot ].enter_boneindex, &orient ); - MatrixToEulerAngles( orient.axis, ang ); + GetTagPositionAndOrientation(Turrets[slot].enter_boneindex, &orient); + MatrixToEulerAngles(orient.axis, ang); } /* @@ -5748,12 +1556,9 @@ void Vehicle::QueryTurretSlotAngles Vehicle::QueryPassengerSlotStatus ==================== */ -int Vehicle::QueryPassengerSlotStatus - ( - int slot - ) +int Vehicle::QueryPassengerSlotStatus(int slot) { - return Passengers[ slot ].flags; + return Passengers[slot].flags; } /* @@ -5761,12 +1566,9 @@ int Vehicle::QueryPassengerSlotStatus Vehicle::QueryDriverSlotStatus ==================== */ -int Vehicle::QueryDriverSlotStatus - ( - int slot - ) +int Vehicle::QueryDriverSlotStatus(int slot) { - return driver.flags; + return driver.flags; } /* @@ -5774,12 +1576,417 @@ int Vehicle::QueryDriverSlotStatus Vehicle::QueryTurretSlotStatus ==================== */ -int Vehicle::QueryTurretSlotStatus - ( - int slot - ) +int Vehicle::QueryTurretSlotStatus(int slot) { - return Turrets[ slot ].flags; + return Turrets[slot].flags; +} + +/* +==================== +Vehicle::QuerySpeed +==================== +*/ +void Vehicle::QuerySpeed(Event *ev) +{ + ev->AddFloat(QuerySpeed()); +} + +/* +==================== +Vehicle::EventQueryFreePassengerSlot +==================== +*/ +void Vehicle::QueryFreePassengerSlot(Event *ev) +{ + ev->AddInteger(QueryFreePassengerSlot()); +} + +/* +==================== +Vehicle::EventQueryFreeDriverSlot +==================== +*/ +void Vehicle::QueryFreeDriverSlot(Event *ev) +{ + ev->AddInteger(QueryFreeDriverSlot()); +} + +/* +==================== +Vehicle::EventQueryFreeTurretSlot +==================== +*/ +void Vehicle::QueryFreeTurretSlot(Event *ev) +{ + ev->AddInteger(QueryFreeTurretSlot()); +} + +/* +==================== +Vehicle::EventQueryPassengerSlotPosition +==================== +*/ +void Vehicle::QueryPassengerSlotPosition(Event *ev) +{ + Vector vPos; + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_PASSENGERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + QueryPassengerSlotPosition(iSlot, vPos); + ev->AddVector(vPos); +} + +/* +==================== +Vehicle::EventQueryDriverSlotPosition +==================== +*/ +void Vehicle::QueryDriverSlotPosition(Event *ev) +{ + Vector vPos; + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_DRIVERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + QueryDriverSlotPosition(iSlot, vPos); + ev->AddVector(vPos); +} + +/* +==================== +Vehicle::EventQueryTurretSlotPosition +==================== +*/ +void Vehicle::QueryTurretSlotPosition(Event *ev) +{ + Vector vPos; + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_TURRETS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + QueryTurretSlotPosition(iSlot, vPos); + ev->AddVector(vPos); +} + +/* +==================== +Vehicle::EventQueryPassengerSlotAngles +==================== +*/ +void Vehicle::QueryPassengerSlotAngles(Event *ev) +{ + Vector vAngles; + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_PASSENGERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + QueryPassengerSlotAngles(iSlot, vAngles); + ev->AddVector(vAngles); +} + +/* +==================== +Vehicle::EventQueryDriverSlotAngles +==================== +*/ +void Vehicle::QueryDriverSlotAngles(Event *ev) +{ + Vector vAngles; + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_DRIVERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + QueryDriverSlotAngles(iSlot, vAngles); + ev->AddVector(vAngles); +} + +/* +==================== +Vehicle::EventQueryTurretSlotAngles +==================== +*/ +void Vehicle::QueryTurretSlotAngles(Event *ev) +{ + Vector vAngles; + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_TURRETS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + QueryTurretSlotAngles(iSlot, vAngles); + ev->AddVector(vAngles); +} + +/* +==================== +Vehicle::EventQueryPassengerSlotStatus +==================== +*/ +void Vehicle::QueryPassengerSlotStatus(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_PASSENGERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + ev->AddInteger(QueryPassengerSlotStatus(iSlot)); +} + +/* +==================== +Vehicle::EventQueryDriverSlotStatus +==================== +*/ +void Vehicle::QueryDriverSlotStatus(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_DRIVERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + ev->AddInteger(QueryDriverSlotStatus(iSlot)); +} + +/* +==================== +Vehicle::EventQueryTurretSlotStatus +==================== +*/ +void Vehicle::QueryTurretSlotStatus(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_TURRETS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + ev->AddInteger(QueryTurretSlotStatus(iSlot)); +} + +/* +==================== +Vehicle::EventQueryPassengerSlotEntity +==================== +*/ +void Vehicle::QueryPassengerSlotEntity(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_PASSENGERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + ev->AddEntity(QueryPassengerSlotEntity(iSlot)); +} + +/* +==================== +Vehicle::EventQueryDriverSlotEntity +==================== +*/ +void Vehicle::QueryDriverSlotEntity(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_DRIVERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + ev->AddEntity(QueryDriverSlotEntity(iSlot)); +} + +/* +==================== +Vehicle::EventQueryTurretSlotEntity +==================== +*/ +void Vehicle::QueryTurretSlotEntity(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_TURRETS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + ev->AddEntity(QueryTurretSlotEntity(iSlot)); +} + +/* +==================== +Vehicle::EventAttachPassengerSlot +==================== +*/ +void Vehicle::AttachPassengerSlot(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_PASSENGERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + AttachPassengerSlot(iSlot, ev->GetEntity(2), vec_zero); + UpdatePassengerSlot(iSlot); +} + +/* +==================== +Vehicle::EventAttachDriverSlot +==================== +*/ +void Vehicle::AttachDriverSlot(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_DRIVERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + AttachDriverSlot(0, ev->GetEntity(2), vec_zero); + UpdateDriverSlot(0); +} + +/* +==================== +Vehicle::EventAttachTurretSlot +==================== +*/ +void Vehicle::AttachTurretSlot(Event *ev) +{ + int iSlot; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_TURRETS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + AttachTurretSlot(iSlot, ev->GetEntity(2), vec_zero, NULL); + UpdateTurretSlot(iSlot); +} + +/* +==================== +Vehicle::EventDetachPassengerSlot +==================== +*/ +void Vehicle::DetachPassengerSlot(Event *ev) +{ + int iSlot; + Vector vExitPosition; + Vector vExitAngles; + bool bHasExitAngles = false; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_PASSENGERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + if (ev->NumArgs() == 2) { + if (ev->IsVectorAt(2)) { + vExitPosition = ev->GetVector(2); + } else if (ev->IsEntityAt(2)) { + vExitPosition = ev->GetEntity(2)->origin; + bHasExitAngles = true; + } else if (ev->IsSimpleEntityAt(2)) { + vExitPosition = ev->GetSimpleEntity(2)->origin; + } + + DetachPassengerSlot(iSlot, vExitPosition, bHasExitAngles ? &vExitAngles : NULL); + } else { + DetachPassengerSlot(iSlot, vec_zero, NULL); + } +} + +/* +==================== +Vehicle::EventDetachDriverSlot +==================== +*/ +void Vehicle::DetachDriverSlot(Event *ev) +{ + int iSlot; + Vector vExitPosition; + Vector vExitAngles; + bool bHasExitAngles = false; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_DRIVERS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + if (ev->NumArgs() == 2) { + if (ev->IsVectorAt(2)) { + vExitPosition = ev->GetVector(2); + } else if (ev->IsEntityAt(2)) { + vExitPosition = ev->GetEntity(2)->origin; + bHasExitAngles = true; + } else if (ev->IsSimpleEntityAt(2)) { + vExitPosition = ev->GetSimpleEntity(2)->origin; + } + + DetachDriverSlot(iSlot, vExitPosition, bHasExitAngles ? &vExitAngles : NULL); + } else { + DetachDriverSlot(iSlot, vec_zero, NULL); + } +} + +/* +==================== +Vehicle::EventDetachTurretSlot +==================== +*/ +void Vehicle::DetachTurretSlot(Event *ev) +{ + int iSlot; + Vector vExitPosition; + Vector vExitAngles; + bool bHasExitAngles = false; + + iSlot = ev->GetInteger(1); + if (iSlot >= MAX_TURRETS) { + ScriptError("Slot Specified is greater than maximum allowed for that parameter\n"); + } + + if (ev->NumArgs() == 2) { + if (ev->IsVectorAt(2)) { + vExitPosition = ev->GetVector(2); + } else if (ev->IsEntityAt(2)) { + vExitAngles = ev->GetEntity(2)->angles; + bHasExitAngles = true; + vExitPosition = ev->GetEntity(2)->origin; + } else if (ev->IsSimpleEntityAt(2)) { + vExitPosition = ev->GetSimpleEntity(2)->origin; + } + } + + DetachTurretSlot(iSlot, vExitPosition, bHasExitAngles ? &vExitAngles : NULL); } /* @@ -5787,12 +1994,9 @@ int Vehicle::QueryTurretSlotStatus Vehicle::QueryPassengerSlotEntity ==================== */ -Entity *Vehicle::QueryPassengerSlotEntity - ( - int slot - ) +Entity *Vehicle::QueryPassengerSlotEntity(int slot) { - return Passengers[ slot ].ent; + return Passengers[slot].ent; } /* @@ -5800,12 +2004,9 @@ Entity *Vehicle::QueryPassengerSlotEntity Vehicle::QueryDriverSlotEntity ==================== */ -Entity *Vehicle::QueryDriverSlotEntity - ( - int slot - ) +Entity *Vehicle::QueryDriverSlotEntity(int slot) { - return driver.ent; + return driver.ent; } /* @@ -5813,12 +2014,103 @@ Entity *Vehicle::QueryDriverSlotEntity Vehicle::QueryTurretSlotEntity ==================== */ -Entity *Vehicle::QueryTurretSlotEntity - ( - int slot - ) +Entity *Vehicle::QueryTurretSlotEntity(int slot) { - return Turrets[ slot ].ent; + return Turrets[slot].ent; +} + +/* +==================== +Vehicle::FindExitPosition +==================== +*/ +bool Vehicle::FindExitPosition(Entity *pEnt, const Vector& vOrigin, const Vector *vAngles) +{ + Event *ev; + Vector yawAngles; + Vector forward; + Vector offset; + float radius; + int i, j; + trace_t trace; + + if (!pEnt) { + return false; + } + + if ((g_target_game < target_game_e::TG_MOHTA || !pEnt->IsSubclassOfPlayer()) && vOrigin != vec_zero) { + if (vAngles) { + pEnt->setAngles(*vAngles); + } + + pEnt->setOrigin(vOrigin); + pEnt->velocity = vec_zero; + + ev = new Event(EV_Vehicle_Exit); + ev->AddEntity(this); + pEnt->ProcessEvent(ev); + + return true; + } + + radius = (pEnt->size.length() + size.length()) * 0.5; + + for (i = 0; i < 128; i += 32) { + for (j = 0; j < 360; j += 30) { + yawAngles = vec_zero; + yawAngles[1] = j + angles[1] + 180; + yawAngles.AngleVectorsLeft(&forward); + + offset = origin + forward * radius; + offset[2] += i; + + trace = G_Trace( + offset, + pEnt->mins, + pEnt->maxs, + offset, + NULL, + pEnt->edict->clipmask, + pEnt->IsSubclassOfPlayer() ? qtrue : qfalse, + " Vehicle::FindExitPosition" + ); + + if (!trace.startsolid && !trace.allsolid) { + Vector end; + + offset = trace.endpos; + end = offset; + end[2] -= 128; + + trace = G_Trace( + offset, + pEnt->mins, + pEnt->maxs, + end, + NULL, + pEnt->edict->clipmask, + pEnt->IsSubclassOfPlayer() ? qtrue : qfalse, + " Vehicle::FindExitPosition" + ); + + if (!trace.startsolid && !trace.allsolid && trace.fraction < 1) { + pEnt->setOrigin(trace.endpos); + pEnt->velocity = vec_zero; + + if (vAngles) { + pEnt->setAngles(*vAngles); + } + + ev = new Event(EV_Vehicle_Exit); + ev->AddEntity(this); + pEnt->ProcessEvent(ev); + return true; + } + } + } + } + + return false; } /* @@ -5826,43 +2118,34 @@ Entity *Vehicle::QueryTurretSlotEntity Vehicle::AttachPassengerSlot ==================== */ -void Vehicle::AttachPassengerSlot - ( - int slot, - Entity *ent, - Vector vExitPosition - ) +void Vehicle::AttachPassengerSlot(int slot, Entity *ent, Vector vExitPosition) { - Entity *passenger; - str sName; + Entity *passenger; + str sName; - if( !ent ) - { - return; - } + if (!ent) { + return; + } - passenger = Passengers[ slot ].ent; - if( !passenger ) - { - Passengers[ slot ].ent = ent; - Passengers[ slot ].flags = SLOT_BUSY; + passenger = Passengers[slot].ent; + if (!passenger) { + Passengers[slot].ent = ent; + Passengers[slot].flags = SLOT_BUSY; - sName = m_sSoundSet + "snd_doorclose"; - Sound( sName ); + sName = m_sSoundSet + "snd_doorclose"; + Sound(sName); - Event *event = new Event( EV_Vehicle_Enter ); - event->AddEntity( this ); - driver.ent->ProcessEvent( event ); + Event *event = new Event(EV_Vehicle_Enter); + event->AddEntity(this); + Passengers[slot].ent->ProcessEvent(event); - offset = ent->origin - origin; + offset = ent->origin - origin; - flags |= FL_POSTTHINK; - SetDriverAngles( seatangles + angles ); - } - else if( !isLocked() && ent == passenger ) - { - DetachPassengerSlot( slot, vec_zero, NULL ); - } + flags |= FL_POSTTHINK; + SetDriverAngles(seatangles + angles); + } else if (!isLocked() && ent == passenger) { + DetachPassengerSlot(slot, vec_zero, NULL); + } } /* @@ -5870,47 +2153,39 @@ void Vehicle::AttachPassengerSlot Vehicle::AttachDriverSlot ==================== */ -void Vehicle::AttachDriverSlot - ( - int slot, - Entity *ent, - Vector vExitPosition - ) +void Vehicle::AttachDriverSlot(int slot, Entity *ent, Vector vExitPosition) { - Entity *d; - str sName; + Entity *d; + str sName; - if( !ent || !ent->IsSubclassOfSentient() ) - { - return; - } + if (!ent || !ent->IsSubclassOfSentient()) { + return; + } - d = Driver(); - if( !d ) - { - driver.ent = ent; - driver.flags = SLOT_BUSY; - lastdriver.ent = driver.ent; + d = Driver(); + if (!d) { + driver.ent = ent; + driver.flags = SLOT_BUSY; + lastdriver.ent = driver.ent; - sName = m_sSoundSet + "snd_doorclose"; - Sound( sName ); + sName = m_sSoundSet + "snd_doorclose"; + Sound(sName); - sName = m_sSoundSet + "snd_start"; - Sound( sName ); + sName = m_sSoundSet + "snd_start"; + Sound(sName); - Event *event = new Event( EV_Vehicle_Enter ); - event->AddEntity( this ); - driver.ent->ProcessEvent( event ); + Event *event = new Event(EV_Vehicle_Enter); + event->AddEntity(this); + driver.ent->ProcessEvent(event); - offset = ent->origin - origin; + offset = ent->origin - origin; - flags |= FL_POSTTHINK; - SetDriverAngles( seatangles + angles ); - } - else if( !isLocked() && ent == d ) - { - DetachDriverSlot( slot, vec_zero, NULL ); - } + flags |= FL_POSTTHINK; + SetDriverAngles(seatangles + angles); + DriverAdded(); + } else if (ent == d && !isLocked()) { + DetachDriverSlot(slot, vec_zero, NULL); + } } /* @@ -5920,198 +2195,85 @@ Vehicle::AttachTurretSlot Attach a turret or a sentient that will use the turret to the vehicle. ==================== */ -void Vehicle::AttachTurretSlot - ( - int slot, - Entity *ent, - Vector vExitPosition, - Vector *vExitAngles - ) +void Vehicle::AttachTurretSlot(int slot, Entity *ent, Vector vExitPosition, Vector *vExitAngles) { - TurretGun *pTurret; - VehicleTurretGun *pVehicleTurret; - str sName; + TurretGun *pTurret; + VehicleTurretGun *pVehicleTurret; + str sName; - if( !ent ) - { - return; - } + if (!ent) { + return; + } - pTurret = ( TurretGun * )Turrets[ slot ].ent.Pointer(); - if( pTurret && ent->IsSubclassOfWeapon() ) - { - if( !isLocked() ) - DetachTurretSlot( slot, vec_zero, NULL ); - } - else - { - if( ent->IsSubclassOfWeapon() ) - { - Turrets[ slot ].ent = ent; - Turrets[ slot ].flags = SLOT_BUSY; + pTurret = (TurretGun *)Turrets[slot].ent.Pointer(); + if (pTurret && ent->IsSubclassOfWeapon()) { + if (ent == pTurret && !isLocked()) { + DetachTurretSlot(slot, vec_zero, NULL); + } + } else if (ent->IsSubclassOfWeapon()) { + Turrets[slot].ent = ent; + Turrets[slot].flags = SLOT_BUSY; - pTurret = ( TurretGun * )ent; + pTurret = (TurretGun *)ent; - ent->takedamage = DAMAGE_NO; - ent->setSolidType( SOLID_NOT ); + ent->takedamage = DAMAGE_NO; + ent->setSolidType(SOLID_NOT); - Event *event = new Event( EV_Vehicle_Enter ); - event->AddEntity( this ); - Turrets[ slot ].ent->ProcessEvent( event ); + Event *event = new Event(EV_Vehicle_Enter); + event->AddEntity(this); + Turrets[slot].ent->ProcessEvent(event); - offset = ent->origin - origin; + offset = ent->origin - origin; - flags |= FL_POSTTHINK; - Turrets[ slot ].ent->setAngles( angles ); + flags |= FL_POSTTHINK; + Turrets[slot].ent->setAngles(angles); - if( pTurret->IsSubclassOfTurretGun() ) - { - pTurret->m_bUsable = false; - pTurret->m_bRestable = false; - } - } - else if( pTurret ) - { - Entity *pTurretOwner = NULL; - Entity *pRemoteTurretOwner = NULL; + if (pTurret->IsSubclassOfTurretGun()) { + pTurret->m_bUsable = false; + pTurret->m_bRestable = false; + } + } else if (pTurret) { + Entity *pTurretOwner = NULL; + Entity *pRemoteTurretOwner = NULL; - if( pTurret->IsSubclassOfTurretGun() ) - { - pTurretOwner = pTurret->GetOwner(); - } + if (pTurret->IsSubclassOfTurretGun()) { + pTurretOwner = pTurret->GetOwner(); + } - if( pTurret->IsSubclassOfVehicleTurretGun() ) - { - pVehicleTurret = ( VehicleTurretGun * )pTurret; - pRemoteTurretOwner = pVehicleTurret->GetRemoteOwner(); - } + if (pTurret->IsSubclassOfVehicleTurretGun()) { + pVehicleTurret = (VehicleTurretGun *)pTurret; + pRemoteTurretOwner = pVehicleTurret->GetRawRemoteOwner(); + } - if( pTurret->IsSubclassOfTurretGun() ) - { - if( pTurret->IsSubclassOfVehicleTurretGun() && pVehicleTurret->isLocked() ) - { - ScriptError( "Turret is locked, cannot attach to turret slot." ); - } + if (pTurret->IsSubclassOfTurretGun()) { + if (pTurret->IsSubclassOfVehicleTurretGun() && pVehicleTurret->isLocked()) { + ScriptError("Turret is locked, cannot attach to turret slot."); + } - pTurret->m_bUsable = true; - } + pTurret->m_bUsable = true; + } - Event *event = new Event( EV_Use ); - event->AddEntity( ent ); - pTurret->ProcessEvent( event ); + Event *event = new Event(EV_Use); + event->AddEntity(ent); + pTurret->ProcessEvent(event); - if( ent->IsSubclassOfPlayer() ) - { - Player *pPlayer = ( Player * )ent; - pPlayer->m_pVehicle = this; - } + if (ent->IsSubclassOfPlayer()) { + Player *pPlayer = (Player *)ent; + pPlayer->m_pVehicle = this; + } - if( pTurret->IsSubclassOfTurretGun() ) - { - pTurret->m_bUsable = false; - } + if (pTurret->IsSubclassOfTurretGun()) { + pTurret->m_bUsable = false; + } - if( pTurretOwner == ent || pRemoteTurretOwner == ent ) - { - if( pRemoteTurretOwner ) - { - pVehicleTurret->SetRemoteOwner( NULL ); - } + if (pTurretOwner == ent || pRemoteTurretOwner == ent) { + if (pRemoteTurretOwner) { + pVehicleTurret->SetRemoteOwner(NULL); + } - if( vExitPosition != vec_zero ) - { - Vector pos; - trace_t trace; - - pos = vExitPosition; - - trace = G_Trace( - pos, - ent->mins, - ent->maxs, - pos, - NULL, - edict->clipmask, - false, - "Vehicle::AttachTurretSlot" ); - - if( !trace.allsolid && !trace.startsolid ) - { - trace = G_Trace( - pos, - ent->mins, - ent->maxs, - pos - Vector( 0, 0, 128 ), - NULL, - edict->clipmask, - false, - "Vehicle::AttachTurretSlot" ); - - if( trace.fraction < 1.0f ) - { - if( vExitAngles ) - { - ent->setAngles( *vExitAngles ); - } - - ent->setOrigin( trace.endpos ); - velocity = vec_zero; - - Event *event = new Event( EV_Vehicle_Exit ); - event->AddEntity( this ); - ent->ProcessEvent( event ); - } - } - } - else - { - int height; - int ang; - Vector angles; - Vector forward; - Vector pos; - float ofs; - trace_t trace; - - if( locked ) - return; - - // - // place the turret on the ground - // - ofs = size.length() * 0.5f; - for( height = 0; height < 100; height += 16 ) - { - for( ang = 0; ang < 360; ang += 30 ) - { - angles[ 1 ] = ent->angles[ 1 ] + ang + 90; - angles.AngleVectors( &forward, NULL, NULL ); - pos = origin + ( forward * ofs ); - pos[ 2 ] += height; - trace = G_Trace( pos, ent->mins, ent->maxs, pos, NULL, MASK_PLAYERSOLID, false, "Vehicle::AttachTurretSlot" ); - if( !trace.startsolid && !trace.allsolid ) - { - Vector end; - - end = pos; - end[ 2 ] -= 128; - trace = G_Trace( pos, ent->mins, ent->maxs, end, NULL, MASK_PLAYERSOLID, false, "Vehicle::AttachTurretSlot" ); - if( trace.fraction < 1.0f ) - { - ent->setOrigin( vExitPosition ); - ent->velocity = vec_zero; - - Event *ev = new Event( EV_Vehicle_Exit ); - ev->AddEntity( this ); - ent->ProcessEvent( ev ); - } - } - } - } - } - } - } - } + FindExitPosition(ent, vExitPosition, vExitAngles); + } + } } /* @@ -6119,85 +2281,22 @@ void Vehicle::AttachTurretSlot Vehicle::DetachPassengerSlot ==================== */ -void Vehicle::DetachPassengerSlot - ( - int slot, - Vector vExitPosition, - Vector *vExitAngles - ) +void Vehicle::DetachPassengerSlot(int slot, Vector vExitPosition, Vector *vExitAngles) { - Entity *passenger = Passengers[ slot ].ent; + Entity *passenger = Passengers[slot].ent; - if( !passenger ) - { - return; - } + if (!passenger) { + return; + } - if( vExitPosition == vec_zero ) - { - int height; - int ang; - Vector angles; - Vector forward; - Vector pos; - float ofs; - trace_t trace; + if (!FindExitPosition(passenger, vExitPosition, vExitAngles)) { + // cannot exit + return; + } - if( locked ) - return; - - // - // place the passenger on the ground - // - ofs = size.length() * 0.5f; - for( height = 0; height < 100; height += 16 ) - { - for( ang = 0; ang < 360; ang += 30 ) - { - angles[ 1 ] = passenger->angles[ 1 ] + ang + 90; - angles.AngleVectors( &forward, NULL, NULL ); - pos = origin + ( forward * ofs ); - pos[ 2 ] += height; - trace = G_Trace( pos, passenger->mins, passenger->maxs, pos, NULL, MASK_PLAYERSOLID, false, "Vehicle::DetachPassengerSlot" ); - if( !trace.startsolid && !trace.allsolid ) - { - Vector end; - - end = pos; - end[ 2 ] -= 128; - trace = G_Trace( pos, passenger->mins, passenger->maxs, end, NULL, MASK_PLAYERSOLID, false, "Vehicle::DetachPassengerSlot" ); - if( trace.fraction < 1.0f ) - { - passenger->setOrigin( pos ); - passenger->velocity = vec_zero; - - Event *ev = new Event( EV_Vehicle_Exit ); - ev->AddEntity( this ); - passenger->ProcessEvent( ev ); - - Sound( m_sSoundSet + "snd_dooropen" ); - } - } - } - } - } - else - { - if( vExitAngles ) - { - passenger->setAngles( *vExitAngles ); - } - - passenger->setOrigin( vExitPosition ); - passenger->velocity = vec_zero; - - Event *ev = new Event( EV_Vehicle_Exit ); - ev->AddEntity( this ); - passenger->ProcessEvent( ev ); - } - - Passengers[ slot ].ent = NULL; - Passengers[ slot ].flags = SLOT_FREE; + Sound(m_sSoundSet + "snd_dooropen"); + Passengers[slot].ent = NULL; + Passengers[slot].flags = SLOT_FREE; } /* @@ -6205,103 +2304,32 @@ void Vehicle::DetachPassengerSlot Vehicle::DetachDriverSlot ==================== */ -void Vehicle::DetachDriverSlot - ( - int slot, - Vector vExitPosition, - Vector *vExitAngles - ) +void Vehicle::DetachDriverSlot(int slot, Vector vExitPosition, Vector *vExitAngles) { - Entity *other = driver.ent; + Entity *other = driver.ent; - if( !other ) - { - return; - } + if (!other) { + return; + } - if( vExitPosition == vec_zero ) - { - int height; - int ang; - Vector angles; - Vector forward; - Vector pos; - float ofs; - trace_t trace; + if (!FindExitPosition(other, vExitPosition, vExitAngles)) { + // cannot exit + return; + } - if( other != driver.ent ) - { - return; - } + turnimpulse = 0; + moveimpulse = 0; + jumpimpulse = 0; - if( locked ) - return; + if (drivable) { + StopLoopSound(); + Sound("snd_dooropen", CHAN_BODY); + Sound("snd_stop", CHAN_VOICE); + driver.ent->setSolidType(SOLID_BBOX); + } - // - // place the driver.ent on the ground - // - ofs = size.length() * 0.5f; - for( height = 0; height < 100; height += 16 ) - { - for( ang = 0; ang < 360; ang += 30 ) - { - angles[ 1 ] = driver.ent->angles[ 1 ] + ang + 90; - angles.AngleVectors( &forward, NULL, NULL ); - pos = origin + ( forward * ofs ); - pos[ 2 ] += height; - trace = G_Trace( pos, driver.ent->mins, driver.ent->maxs, pos, NULL, MASK_PLAYERSOLID, false, "Vehicle::DetachDriverSlot" ); - if( !trace.startsolid && !trace.allsolid ) - { - Vector end; - - end = pos; - end[ 2 ] -= 128; - trace = G_Trace( pos, driver.ent->mins, driver.ent->maxs, end, NULL, MASK_PLAYERSOLID, false, "Vehicle::DetachDriverSlot" ); - if( trace.fraction < 1.0f ) - { - driver.ent->setOrigin( pos ); - - turnimpulse = 0; - moveimpulse = 0; - jumpimpulse = 0; - - Event *event = new Event( EV_Vehicle_Exit ); - event->AddEntity( this ); - driver.ent->ProcessEvent( event ); - if( hasweapon ) - { - Player *player = ( Player * )driver.ent.Pointer(); - player->takeItem( weaponName.c_str() ); - } - if( drivable ) - { - StopLoopSound(); - Sound( "snd_dooropen", CHAN_BODY ); - Sound( "snd_stop", CHAN_VOICE ); - driver.ent->setSolidType( SOLID_BBOX ); - } - } - } - } - } - } - else - { - if( vExitAngles ) - { - other->setAngles( *vExitAngles ); - } - - other->setOrigin( vExitPosition ); - other->velocity = vec_zero; - - Event *ev = new Event( EV_Vehicle_Exit ); - ev->AddEntity( this ); - other->ProcessEvent( ev ); - } - - driver.ent = NULL; - driver.flags = SLOT_FREE; + driver.ent = NULL; + driver.flags = SLOT_FREE; } /* @@ -6311,96 +2339,34 @@ Vehicle::DetachTurretSlot Detach a turret or a sentient. ==================== */ -void Vehicle::DetachTurretSlot - ( - int slot, - Vector vExitPosition, - Vector *vExitAngles - ) +void Vehicle::DetachTurretSlot(int slot, Vector vExitPosition, Vector *vExitAngles) { - Entity *passenger = Turrets[ slot ].ent; + Entity *passenger = Turrets[slot].ent; - if( !passenger ) - { - return; - } + if (!passenger) { + return; + } - if( vExitPosition == vec_zero ) - { - int height; - int ang; - Vector angles; - Vector forward; - Vector pos; - float ofs; - trace_t trace; + if (!FindExitPosition(passenger, vExitPosition, vExitAngles)) { + // cannot exit + return; + } - if( locked ) - return; + turnimpulse = 0; + moveimpulse = 0; + jumpimpulse = 0; + passenger->setSolidType(SOLID_BBOX); - // - // place the turret on the ground - // - ofs = size.length() * 0.5f; - for( height = 0; height < 100; height += 16 ) - { - for( ang = 0; ang < 360; ang += 30 ) - { - angles[ 1 ] = passenger->angles[ 1 ] + ang + 90; - angles.AngleVectors( &forward, NULL, NULL ); - pos = origin + ( forward * ofs ); - pos[ 2 ] += height; - trace = G_Trace( pos, passenger->mins, passenger->maxs, pos, NULL, MASK_PLAYERSOLID, false, "Vehicle::DetachTurretSlot" ); - if( !trace.startsolid && !trace.allsolid ) - { - Vector end; + Sound(m_sSoundSet + "snd_dooropen"); - end = pos; - end[ 2 ] -= 128; - trace = G_Trace( pos, passenger->mins, passenger->maxs, end, NULL, MASK_PLAYERSOLID, false, "Vehicle::DetachTurretSlot" ); - if( trace.fraction < 1.0f ) - { - passenger->setOrigin( pos ); - passenger->velocity = vec_zero; + if (passenger->IsSubclassOfTurretGun()) { + TurretGun *pTurret = static_cast(passenger); + pTurret->m_bUsable = true; + pTurret->m_bRestable = true; + } - turnimpulse = 0; - moveimpulse = 0; - jumpimpulse = 0; - - Event *ev = new Event( EV_Vehicle_Exit ); - ev->AddEntity( this ); - passenger->ProcessEvent( ev ); - - Sound( m_sSoundSet + "snd_dooropen" ); - - TurretGun *pTurret = ( TurretGun * )passenger; - if( pTurret->IsSubclassOfTurretGun() ) - { - pTurret->m_bUsable = true; - pTurret->m_bRestable = true; - } - } - } - } - } - } - else - { - if( vExitAngles ) - { - passenger->setAngles( *vExitAngles ); - } - - passenger->setOrigin( vExitPosition ); - passenger->velocity = vec_zero; - - Event *ev = new Event( EV_Vehicle_Exit ); - ev->AddEntity( this ); - passenger->ProcessEvent( ev ); - } - - Turrets[ slot ].ent = NULL; - Turrets[ slot ].flags = SLOT_FREE; + Turrets[slot].ent = NULL; + Turrets[slot].flags = SLOT_FREE; } /* @@ -6408,20 +2374,15 @@ void Vehicle::DetachTurretSlot Vehicle::FindPassengerSlotByEntity ==================== */ -int Vehicle::FindPassengerSlotByEntity - ( - Entity *ent - ) +int Vehicle::FindPassengerSlotByEntity(Entity *ent) { - for( int i = 0; i < MAX_PASSENGERS; i++ ) - { - if( Passengers[ i ].ent == ent ) - { - return i; - } - } + for (int i = 0; i < MAX_PASSENGERS; i++) { + if (Passengers[i].ent == ent) { + return i; + } + } - return -1; + return -1; } /* @@ -6429,12 +2390,9 @@ int Vehicle::FindPassengerSlotByEntity Vehicle::FindDriverSlotByEntity ==================== */ -int Vehicle::FindDriverSlotByEntity - ( - Entity *ent - ) +int Vehicle::FindDriverSlotByEntity(Entity *ent) { - return driver.ent == ent ? 0 : -1; + return driver.ent == ent ? 0 : -1; } /* @@ -6442,106 +2400,57 @@ int Vehicle::FindDriverSlotByEntity Vehicle::FindTurretSlotByEntity ==================== */ -int Vehicle::FindTurretSlotByEntity - ( - Entity *ent - ) +int Vehicle::FindTurretSlotByEntity(Entity *ent) { - for( int i = 0; i < MAX_TURRETS; i++ ) - { - if( Turrets[ i ].ent == ent ) - { - return i; - } - } + for (int i = 0; i < MAX_TURRETS; i++) { + if (Turrets[i].ent == ent) { + return i; + } + } - return -1; + return -1; } /* ==================== -Vehicle::SetSlotsNonSolid +Vehicle::Drivable ==================== */ -void Vehicle::SetSlotsNonSolid - ( - void - ) +void Vehicle::Drivable(Event *ev) { - for( int i = 0; i < MAX_PASSENGERS; i++ ) - { - Passengers[ i ].NotSolid(); - } - - for( int i = 0; i < MAX_TURRETS; i++ ) - { - Turrets[ i ].NotSolid(); - } - - driver.NotSolid(); - - if( m_pCollisionEntity ) - { - m_pCollisionEntity->NotSolid(); - } + setMoveType(MOVETYPE_VEHICLE); + drivable = true; } /* ==================== -Vehicle::SetSlotsSolid +Vehicle::PathDrivable ==================== */ -void Vehicle::SetSlotsSolid - ( - void - ) +void Vehicle::PathDrivable(Event *ev) { - for( int i = 0; i < MAX_PASSENGERS; i++ ) - { - Passengers[ i ].Solid(); - } - - for( int i = 0; i < MAX_TURRETS; i++ ) - { - Turrets[ i ].Solid(); - } - - driver.Solid(); - - if( m_pCollisionEntity ) - { - m_pCollisionEntity->Solid(); - } + pathDrivable = ev->GetBoolean(1); } /* ==================== -Vehicle::KickSuspension +Vehicle::UnDrivable ==================== */ -void Vehicle::KickSuspension - ( - Vector vDirection, - float fForce - ) +void Vehicle::UnDrivable(Event *ev) { - VectorNormalizeFast( vDirection ); - - m_fForwardForce += DotProduct( vDirection, orientation[ 1 ] ) * fForce; - m_fLeftForce += DotProduct( vDirection, orientation[ 0 ] ) * fForce; + setMoveType(MOVETYPE_PUSH); + drivable = false; } /* ==================== -Vehicle::isLocked +Vehicle::Jumpable ==================== */ -qboolean Vehicle::isLocked - ( - void - ) +void Vehicle::Jumpable(Event *ev) { - return locked; + jumpable = true; } /* @@ -6549,12 +2458,9 @@ qboolean Vehicle::isLocked Vehicle::Lock ==================== */ -void Vehicle::Lock - ( - void - ) +void Vehicle::Lock(Event *ev) { - locked = true; + Lock(); } /* @@ -6562,12 +2468,4417 @@ void Vehicle::Lock Vehicle::UnLock ==================== */ -void Vehicle::UnLock - ( - void - ) +void Vehicle::UnLock(Event *ev) { - locked = false; + UnLock(); +} + +/* +==================== +Vehicle::SteerInPlace +==================== +*/ +void Vehicle::SteerInPlace(Event *ev) +{ + steerinplace = true; +} + +/* +==================== +Vehicle::SeatAnglesOffset +==================== +*/ +void Vehicle::SeatAnglesOffset(Event *ev) +{ + seatangles = ev->GetVector(1); +} + +/* +==================== +Vehicle::SeatOffset +==================== +*/ +void Vehicle::SeatOffset(Event *ev) +{ + seatoffset = ev->GetVector(1); +} + +/* +==================== +Vehicle::SetWeapon +==================== +*/ +void Vehicle::SetWeapon(Event *ev) +{ + showweapon = true; + hasweapon = true; + weaponName = ev->GetString(1); +} + +/* +==================== +Vehicle::SetName +==================== +*/ +void Vehicle::SetName(Event *ev) +{ + vehicleName = ev->GetString(1); +} + +/* +==================== +Vehicle::ShowWeaponEvent +==================== +*/ +void Vehicle::ShowWeaponEvent(Event *ev) +{ + showweapon = true; +} + +/* +==================== +Vehicle::HasWeapon +==================== +*/ +qboolean Vehicle::HasWeapon(void) +{ + return hasweapon; +} + +/* +==================== +Vehicle::ShowWeapon +==================== +*/ +qboolean Vehicle::ShowWeapon(void) +{ + return showweapon; +} + +/* +==================== +Vehicle::SetDriverAngles +==================== +*/ +void Vehicle::SetDriverAngles(Vector angles) +{ + int i; + + if (!driver.ent || !driver.ent->client) { + return; + } + + for (i = 0; i < 3; i++) { + driver.ent->client->ps.delta_angles[i] = ANGLE2SHORT(angles[i] - driver.ent->client->cmd_angles[i]); + } +} + +/* +==================== +Vehicle::Driver +==================== +*/ +Entity *Vehicle::Driver(void) +{ + return driver.ent; +} + +/* +==================== +Vehicle::IsDrivable +==================== +*/ +qboolean Vehicle::IsDrivable(void) +{ + return drivable; +} + +/* +==================== +Vehicle::BounceForwardsVelocity +==================== +*/ +void Vehicle::BounceForwardsVelocity(Event *ev) +{ + if (m_bBounceBackwards) { + m_bBounceStayFullSpeed = false; + m_bBounceBackwards = false; + currentspeed = -currentspeed; + moveimpulse = -moveimpulse; + } +} + +/* +==================== +Vehicle::BounceBackwardsVelocity +==================== +*/ +void Vehicle::BounceBackwardsVelocity(Event *ev) +{ + if (!m_bBounceBackwards) { + m_bBounceBackwards = true; + currentspeed = -currentspeed; + moveimpulse = -moveimpulse; + if (ev->NumArgs() > 0) { + m_bBounceStayFullSpeed = ev->GetBoolean(1); + } + } +} + +/* +==================== +Vehicle::StopForwardsVelocity +==================== +*/ +void Vehicle::StopForwardsVelocity(Event *ev) +{ + if (!m_bBounceBackwards) { + moveimpulse = 0; + } +} + +/* +==================== +Vehicle::StopBackwardsVelocity +==================== +*/ +void Vehicle::StopBackwardsVelocity(Event *ev) +{ + if (m_bBounceBackwards) { + moveimpulse = 0; + } +} + +/* +==================== +Vehicle::EventSetSpeed +==================== +*/ +void Vehicle::SetSpeed(Event *ev) +{ + speed = ev->GetFloat(1); +} + +/* +==================== +Vehicle::EventSetTurnRate +==================== +*/ +void Vehicle::SetTurnRate(Event *ev) +{ + maxturnrate = ev->GetFloat(1); +} + +/* +==================== +Vehicle::SetMass +==================== +*/ +void Vehicle::SetMass(Event *ev) +{ + m_fMass = ev->GetFloat(1); + m_fFrontMass = m_fMass * 0.5; + m_fBackMass = m_fMass * 0.5; +} + +/* +==================== +Vehicle::SetFrontMass +==================== +*/ +void Vehicle::SetFrontMass(Event *ev) +{ + m_fFrontMass = ev->GetFloat(1); + m_fMass = m_fFrontMass + m_fBackMass; +} + +/* +==================== +Vehicle::SetBackMass +==================== +*/ +void Vehicle::SetBackMass(Event *ev) +{ + m_fBackMass = ev->GetFloat(1); + m_fMass = m_fFrontMass + m_fBackMass; +} + +/* +==================== +Vehicle::SetTread +==================== +*/ +void Vehicle::SetTread(Event *ev) +{ + m_fTread = ev->GetFloat(1); +} + +/* +==================== +Vehicle::SetTireRadius +==================== +*/ +void Vehicle::SetTireRadius(Event *ev) +{ + m_fTireRadius = ev->GetFloat(1); +} + +/* +==================== +Vehicle::SetRollingResistance +==================== +*/ +void Vehicle::SetRollingResistance(Event *ev) +{ + m_fRollingResistance = ev->GetFloat(1); +} + +/* +==================== +Vehicle::SetDrag +==================== +*/ +void Vehicle::SetDrag(Event *ev) +{ + m_fDrag = ev->GetFloat(1); +} + +/* +==================== +Vehicle::BouncyCoef +==================== +*/ +void Vehicle::BouncyCoef(Event *ev) +{ + m_fBouncyCoef = ev->GetFloat(1); +} + +/* +==================== +Vehicle::SpringyCoef +==================== +*/ +void Vehicle::SpringyCoef(Event *ev) +{ + m_fSpringyCoef = ev->GetFloat(1); +} + +/* +==================== +Vehicle::YawMinMax +==================== +*/ +void Vehicle::YawMinMax(Event *ev) +{ + if (ev->NumArgs() != 3) { + ScriptError("No Parameter for YawMinMax"); + } + + m_fYawMin = ev->GetFloat(1); + m_fYawMax = ev->GetFloat(2); + m_fYawCoef = ev->GetFloat(3); + + if (m_fYawMin > m_fYawMax) { + ScriptError("Mismatched mins and maxs for YawMinMax"); + } +} + +/* +==================== +Vehicle::RollMinMax +==================== +*/ +void Vehicle::RollMinMax(Event *ev) +{ + if (ev->NumArgs() != 3) { + ScriptError("No Parameter for RollMinMax"); + } + + m_fRollMin = ev->GetFloat(1); + m_fRollMax = ev->GetFloat(2); + m_fRollCoef = ev->GetFloat(3); + + if (m_fRollMin > m_fRollMax) { + ScriptError("Mismatched mins and maxs for RollMinMax"); + } +} + +/* +==================== +Vehicle::ZMinMax +==================== +*/ +void Vehicle::ZMinMax(Event *ev) +{ + if (ev->NumArgs() != 3) { + ScriptError("No Parameter for ZMinMax"); + } + + m_fZMin = ev->GetFloat(1); + m_fZMax = ev->GetFloat(2); + m_fZCoef = ev->GetFloat(3); + + if (m_fZMin > m_fZMax) { + ScriptError("Mismatched mins and maxs for ZMinMax"); + } +} + +/* +==================== +Vehicle::SetAnimationSet +==================== +*/ +void Vehicle::SetAnimationSet(Event *ev) +{ + m_sAnimationSet = ev->GetString(1); +} + +/* +==================== +Vehicle::SetSoundSet +==================== +*/ +void Vehicle::SetSoundSet(Event *ev) +{ + m_sSoundSet = ev->GetString(1); +} + +/* +==================== +Vehicle::GetTagPositionAndOrientation +==================== +*/ +qboolean Vehicle::GetTagPositionAndOrientation(int tagnum, orientation_t *new_or) +{ + int i; + orientation_t tag_or; + float axis[3][3]; + + GetRawTag(tagnum, &tag_or); + + AnglesToAxis(angles, axis); + + VectorCopy(origin, new_or->origin); + + for (i = 0; i < 3; i++) { + VectorMA(new_or->origin, tag_or.origin[i], tag_or.axis[i], new_or->origin); + } + + MatrixMultiply(tag_or.axis, axis, new_or->axis); + return true; +} + +/* +==================== +Vehicle::GetTagPositionAndOrientation +==================== +*/ +qboolean Vehicle::GetTagPositionAndOrientation(str tagname, orientation_t *new_or) +{ + int tagnum = gi.Tag_NumForName(edict->tiki, tagname.c_str()); + + if (tagnum < 0) { + warning("Vehicle::GetTagPositionAndOrientation", "Could not find tag \"%s\"", tagname.c_str()); + return false; + } else { + return GetTagPositionAndOrientation(tagnum, new_or); + } +} + +/* +==================== +Vehicle::CheckWater +==================== +*/ +void Vehicle::CheckWater(void) +{ + Vector point; + int cont; + int sample1; + int sample2; + VehicleBase *v; + + unlink(); + v = this; + while (v->vlink) { + v = v->vlink; + v->unlink(); + } + + if (driver.ent) { + driver.ent->unlink(); + } + + // + // get waterlevel + // + waterlevel = 0; + watertype = 0; + + sample2 = maxs[2] - mins[2]; + sample1 = sample2 / 2; + + point = origin; + point[2] += mins[2]; + cont = gi.pointcontents(point, 0); + + if (cont & MASK_WATER) { + watertype = cont; + waterlevel = 1; + point[2] = origin[2] + mins[2] + sample1; + cont = gi.pointcontents(point, 0); + if (cont & MASK_WATER) { + waterlevel = 2; + point[2] = origin[2] + mins[2] + sample2; + cont = gi.pointcontents(point, 0); + if (cont & MASK_WATER) { + waterlevel = 3; + } + } + } + + link(); + v = this; + while (v->vlink) { + v = v->vlink; + v->link(); + } + + if (driver.ent) { + driver.ent->link(); + driver.ent->waterlevel = waterlevel; + driver.ent->watertype = watertype; + } +} + +/* +==================== +Vehicle::Drive +==================== +*/ +qboolean Vehicle::Drive(usercmd_t *ucmd) +{ + Vector i, j, k; + + i = velocity; + VectorNormalize(i); + + if (!driver.ent || !driver.ent->isClient()) { + return false; + } + + if (!drivable) { + driver.ent->client->ps.pm_flags |= PMF_FROZEN; + ucmd->forwardmove = 0; + ucmd->rightmove = 0; + ucmd->upmove = 0; + return false; + } + + driver.ent->client->ps.pm_flags |= PMF_NO_PREDICTION; + + moveimpulse = ((float)ucmd->forwardmove) * (VectorLength(i) + 1.0); + m_bIsBraking = ucmd->forwardmove < 0; + m_fAccelerator += ((float)ucmd->forwardmove) * 0.005; + if (m_fAccelerator < 0.0) { + m_fAccelerator = 0.0; + } else if (m_fAccelerator > 1.0) { + m_fAccelerator = 1.0; + } + + turnimpulse = ((float)-ucmd->rightmove); + jumpimpulse = ((float)ucmd->upmove * gravity) / 350; + if ((jumpimpulse < 0) || (!jumpable)) { + jumpimpulse = 0; + } + + turnimpulse += angledist(SHORT2ANGLE(ucmd->angles[1]) - driver.ent->client->cmd_angles[1]) * 8; + + return true; +} + +/* +==================== +Vehicle::PathDrive +==================== +*/ +qboolean Vehicle::PathDrive(usercmd_t *ucmd) +{ + if (!pathDrivable) { + return false; + } + + if (m_bAutoPilot) { + if (ucmd->forwardmove > 0) { + // + // forward speed + // + if (m_bBounceBackwards) { + m_fIdealSpeed = 0; + if (!currentspeed) { + m_bBounceBackwards = false; + } + } else { + m_fIdealSpeed = m_fMaxSpeed; + } + } else if (ucmd->forwardmove < 0) { + // + // backward speed + // + if (m_bBounceBackwards) { + m_fIdealSpeed = -m_fMaxSpeed; + } else { + m_fIdealSpeed = 0; + if (!currentspeed) { + m_bBounceBackwards = true; + } + } + } else { + // + // stopped + // + m_fIdealSpeed = 0; + } + } + + return true; +} + +/* +==================== +Vehicle::AutoPilot +==================== +*/ +void Vehicle::AutoPilot(void) +{ + Vector vAngles; + Vector vDeltaAngles, vDelta, vDeltaSave; + float *vTmp; + vec3_t vPrev, vCur, vTotal; + float fTotal, fCoef; + Vector vWishPosition, vAlternateWishPosition; + float fDistToCurPos, fCurPathPosition; + + if (!m_pCurPath || m_pCurPath->m_iPoints == 0) { + m_bAutoPilot = false; + return; + } + + if (g_showvehiclepath && g_showvehiclepath->integer) { + int iFlags; + float fBS; + Vector vTmp1; + Vector vTmp2; + Vector vBS; + + iFlags = 0; + fBS = sin(level.time) * 16; + vBS = Vector(1, 1, 1) * fBS; + + for (int i = 0; i < m_pCurPath->m_iPoints; i++) { + float fZ = 0; + Vector vColor(0, 1, 1); + + vTmp = m_pCurPath->GetByNode(i, &iFlags); + vTmp1 = vTmp + 1; + fZ = 0; + + if (iFlags & 1) { + vColor = Vector(1, 1, 1); + fZ += 1; + G_DebugString(vTmp1 + Vector(0, 0, fZ * 32), sin(level.time) + 3, 1, 1, 0, "START_STOPPING"); + } + if (iFlags & 2) { + vColor = Vector(0, 1, 1); + fZ += 1; + G_DebugString(vTmp1 + Vector(0, 0, fZ * 32), sin(level.time) + 3, 0, 1, 0, "START_SKIDDING"); + } + if (iFlags & 4) { + fZ += 1; + G_DebugString(vTmp1 + Vector(0, 0, fZ * 32), sin(level.time) + 3, 0, 0, 1, "STOP_SKIDDING"); + } + + if (i == m_iCurNode) { + G_DebugBBox(vTmp1, vBS * -1, vBS, 1, 0, 0, 1); + } else { + G_DebugBBox(vTmp1, vBS * -1, vBS, vColor[0], vColor[1], vColor[2], 1); + } + + vTmp = m_pCurPath->GetByNode(i + 1, NULL); + vTmp2 = vTmp + 1; + + G_DebugLine(vTmp1, vTmp2, 0, 1, 0, 1); + } + } + + do { + if (m_iCurNode > 0) { + int iFlags; + + vTmp = m_pCurPath->GetByNode(m_iCurNode, NULL); + VectorCopy(vTmp + 1, vCur); + + if (g_showvehiclemovedebug->integer) { + G_DebugString(vCur, 3, 1, 1, 1, "%f", vTmp[0]); + } + + vTmp = m_pCurPath->GetByNode(m_iCurNode - 1, NULL); + VectorCopy(vTmp + 1, vPrev); + + if (g_showvehiclemovedebug->integer) { + G_DebugString(vPrev, 3, 1, 1, 1, "%f", vTmp[0]); + } + + VectorSubtract(vCur, vPrev, vTotal); + fTotal = VectorLength(vTotal); + m_vIdealDir = vTotal; + + VectorNormalize(m_vIdealDir); + angles.AngleVectorsLeft(&vDelta, NULL, NULL); + fCoef = ProjectLineOnPlane(vDelta, DotProduct(origin, vDelta), vPrev, vCur, NULL); + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(vPrev, Vector(-32, -32, -32), Vector(32, 32, 32), 0, 1, 1, 1); + G_DebugBBox(vCur, Vector(-32, -32, -32), Vector(32, 32, 32), 1, 1, 0, 1); + G_DebugArrow(vCur, m_vIdealDir * -1, (1 - fCoef) * fTotal, 0, 1, 0, 1); + G_DebugArrow(vPrev, m_vIdealDir * 1, fCoef * fTotal, 0, 0, 1, 1); + } + + vTmp = m_pCurPath->GetByNode(m_iCurNode - (1.0 - fCoef), NULL); + fCurPathPosition = vTmp[0]; + // Added in 2.30 + // Check if vehicle bounces backwards + if (m_bBounceBackwards) { + vTmp = m_pCurPath->Get(fCurPathPosition - m_fLookAhead, NULL); + } else { + vTmp = m_pCurPath->Get(fCurPathPosition + m_fLookAhead, NULL); + } + vWishPosition = vTmp + 1; + fDistToCurPos = Vector(origin[0] - vWishPosition[0], origin[1] - vWishPosition[1], 0).length(); + + // Added in 2.30 + // Check if vehicle bounces backwards + if (fCoef > 1 && !m_bBounceBackwards) { + m_iCurNode++; + if (m_iCurNode >= m_pCurPath->m_iPoints) { + break; + } + + m_pCurPath->GetByNode(m_iCurNode, &iFlags); + if (iFlags & 1) { + ProcessEvent(EV_Vehicle_StopAtEnd); + } + + if (iFlags & 2) { + Event *event = new Event(EV_Vehicle_Skidding); + event->AddInteger(1); + ProcessEvent(event); + } + + if (iFlags & 4) { + Event *event = new Event(EV_Vehicle_Skidding); + event->AddInteger(0); + ProcessEvent(event); + } + } else if (fCoef < 0 && m_bBounceBackwards) { + m_iCurNode--; + if (m_iCurNode < 1) { + m_iCurNode = 1; + m_bBounceBackwards = false; + currentspeed = -currentspeed; + moveimpulse = -moveimpulse; + } + } + + cont: + if (m_pAlternatePath && m_pAlternatePath->m_iPoints) { + if (m_iAlternateNode > 1) { + vTmp = m_pAlternatePath->GetByNode(m_iAlternateNode, NULL); + VectorCopy(vTmp + 1, vCur); + + vTmp = m_pAlternatePath->GetByNode(m_iAlternateNode - 1, NULL); + VectorCopy(vTmp + 1, vPrev); + + VectorSubtract(vCur, vPrev, vTotal); + fTotal = VectorLength(vTotal); + m_vIdealDir = vTotal; + + VectorNormalize(m_vIdealDir); + angles.AngleVectorsLeft(&vDelta, NULL, NULL); + fCoef = ProjectLineOnPlane(vDelta, DotProduct(origin, vDelta), vPrev, vCur, NULL); + + vTmp = m_pCurPath->GetByNode(m_iAlternateNode - (1.0 - fCoef), NULL); + // 2.30: bounce backward + if (m_bBounceBackwards) { + vTmp = m_pCurPath->Get(vTmp[0] - m_fLookAhead, NULL); + } else { + vTmp = m_pCurPath->Get(vTmp[0] + m_fLookAhead, NULL); + } + vAlternateWishPosition = vTmp + 1; + + if (fCoef > 1) { + m_iAlternateNode++; + } else if (fCoef < 0) { + // 2.30: backward + m_iAlternateNode--; + } + } else { + vTmp = m_pAlternatePath->GetByNode(m_iAlternateNode, NULL); + vAlternateWishPosition = vTmp + 1; + m_vIdealDir = origin - vWishPosition; + m_vIdealDir[2] = 0; + m_vIdealDir.normalize(); + + vDelta = vAlternateWishPosition - origin; + vDelta[2] = 0; + + if (vDelta.length() <= m_fIdealDistance) { + m_iAlternateNode++; + } + } + } + + vDelta = vWishPosition - origin; + + if (g_showvehiclemovedebug->integer) { + G_DebugLine(vWishPosition, origin, 1, 0, 0, 1); + } + + vDeltaSave = vDelta; + vDelta.normalize(); + + if (m_pAlternatePath && m_pAlternatePath->m_iPoints) { + trace_t trace; + + trace = G_Trace( + origin, vec_zero, vec_zero, vWishPosition, this, edict->clipmask, qfalse, "Vehicle::AutoPilot" + ); + if ((trace.fraction < 1 || trace.startsolid || trace.allsolid) && trace.ent + && trace.entityNum != ENTITYNUM_WORLD) { + vDelta = vAlternateWishPosition - origin; + vDeltaSave = vDelta; + vDelta.normalize(); + } + } + + vDelta[2] = 0; + vDeltaSave[2] = 0; + + if (fDistToCurPos > 1) { + // Added 2.30: checks if it doesn't bounce backwards + if (moveimpulse >= 0 && !m_bBounceBackwards) { + vectoangles(vDelta, vDeltaAngles); + turnimpulse = angledist(vDeltaAngles.y - angles.y); + } else { + Vector vVec = vDelta * -1; + + vectoangles(vVec, vDeltaAngles); + if (IsSubclassOfVehicleTank()) { + turnimpulse = angledist(vDeltaAngles.y - angles.y); + } else { + turnimpulse = -angledist(vDeltaAngles.y - angles.y); + } + } + } + + if (m_bStopEnabled) { + moveimpulse = (fCurPathPosition - m_fStopStartDistance) / (m_fStopEndDistance - m_fStopStartDistance); + moveimpulse *= moveimpulse; + moveimpulse *= moveimpulse; + moveimpulse *= moveimpulse; + moveimpulse *= moveimpulse; + moveimpulse = 1 - moveimpulse; + moveimpulse *= m_fStopStartSpeed; + + if (fabs(moveimpulse) < 2) { + if (m_fIdealSpeed >= 0) { + moveimpulse = 2; + } else { + moveimpulse = -2; + } + } + // 2.30: check if it stays full speed when bouncing + } else if (m_bBounceStayFullSpeed) { + if (m_fIdealSpeed > fabs(moveimpulse)) { + moveimpulse -= m_fIdealAccel * level.frametime; + if (fabs(moveimpulse) > m_fIdealSpeed) { + moveimpulse = -m_fIdealSpeed; + } + } + } else if (moveimpulse < m_fIdealSpeed) { + moveimpulse += m_fIdealAccel * level.frametime; + if (moveimpulse > m_fIdealSpeed) { + moveimpulse = m_fIdealSpeed; + } + } else if (moveimpulse > m_fIdealSpeed) { + moveimpulse -= m_fIdealAccel * level.frametime; + if (moveimpulse < m_fIdealSpeed) { + moveimpulse = m_fIdealSpeed; + } + } + + if (m_iNextPathStartNode >= 0 && m_pNextPath && m_pNextPath->m_iPoints + && m_iCurNode > m_iNextPathStartNode + 2) { + cVehicleSpline *spline; + + spline = m_pCurPath; + m_pCurPath = m_pNextPath; + m_pNextPath = spline; + + m_iCurNode = 2; + m_pNextPath->Reset(); + m_iNextPathStartNode = -1; + + // notify scripts that the drive has finished + Unregister(STRING_DRIVE); + + m_bStopEnabled = false; + m_bEnableSkidding = false; + } + return; + } + + vTmp = m_pCurPath->GetByNode(m_iCurNode, NULL); + vWishPosition = vTmp + 1; + m_vIdealDir = origin - vWishPosition; + m_vIdealDir[2] = 0; + m_vIdealDir.normalize(); + + vDelta = vWishPosition - origin; + vDelta[2] = 0; + + fDistToCurPos = 2; + if (vDelta.length() > m_fIdealDistance) { + goto cont; + } + + fDistToCurPos = 0; + + m_iCurNode++; + } while (m_iCurNode < m_pCurPath->m_iPoints); + + if (m_bStopEnabled) { + moveimpulse = 0; + } + + m_bAutoPilot = false; + m_bStopEnabled = false; + m_bEnableSkidding = false; + + StopLoopSound(); + // play the stop sound + Sound(m_sSoundSet + "snd_stop", CHAN_VOICE); + + delete m_pCurPath; + m_pCurPath = NULL; + m_iCurNode = 0; + turnimpulse = 0; + + // + // notify scripts that driving has stopped + // + Unregister(STRING_DRIVE); +} + +/* +==================== +Vehicle::EventDriveInternal +==================== +*/ +void Vehicle::EventDriveInternal(Event *ev, bool wait) +{ + SimpleEntity *path; + SimpleEntity *alternate_path = NULL; + + m_fIdealDistance = 100; + m_fLookAhead = 256; + m_fIdealAccel = 35; + m_fIdealSpeed = 250; + m_fMaxSpeed = 250; // Added in 2.30 + + switch (ev->NumArgs()) { + case 6: + alternate_path = ev->GetSimpleEntity(6); + case 5: + m_fLookAhead = ev->GetFloat(5); + case 4: + m_fIdealDistance = ev->GetFloat(4); + case 3: + m_fIdealAccel = ev->GetFloat(3); + case 2: + m_fIdealSpeed = ev->GetFloat(2); + m_fMaxSpeed = m_fIdealSpeed; // Added in 2.30 + case 1: + path = ev->GetSimpleEntity(1); + if (!path) { + ScriptError("Vehicle Given Drive Command with NULL path."); + return; + } + break; + default: + ScriptError("wrong number of arguments"); + } + + if (!m_pCurPath) { + m_pCurPath = new cVehicleSpline; + } + + if (!m_pAlternatePath) { + m_pAlternatePath = new cVehicleSpline; + } + + SetupPath(m_pCurPath, path); + + // Setup the alternate path + if (alternate_path) { + SetupPath(m_pAlternatePath, alternate_path); + } + + m_bAutoPilot = true; + m_iCurNode = 0; + m_iAlternateNode = 0; + + Sound(m_sSoundSet + "snd_start"); +} + +/* +==================== +Vehicle::SetupPath +==================== +*/ +void Vehicle::SetupPath(cVehicleSpline *pPath, SimpleEntity *se) +{ + Vector vLastOrigin; + SimpleEntity *ent; + float fCurLength = 0.0f; + int i = 1; + + if (!pPath) { + return; + } + + pPath->Reset(); + + if (!se->Target().length() || !se->Target()[0]) { + return; + } + + vLastOrigin = se->origin; + + for (ent = se; ent; ent = ent->Next(), i++) { + Vector vDelta = vLastOrigin - ent->origin; + float vTmp[4]; + + if (vDelta.length() == 0 && i > 1) { + Com_Printf("^~^~^Warning: Vehicle Driving with a Path that contains 2 equal points\n"); + } else { + fCurLength += vDelta.length(); + + vTmp[0] = fCurLength; + VectorCopy(ent->origin, vTmp + 1); + + if (ent->IsSubclassOfVehiclePoint()) { + pPath->Add(vTmp, static_cast(ent)->spawnflags); + } else { + pPath->Add(vTmp, 0); + } + + vLastOrigin = ent->origin; + } + + if (ent == se && i > 1) { + break; + } + } +} + +/* +==================== +Vehicle::EventDrive +==================== +*/ +void Vehicle::EventDrive(Event *ev) +{ + EventDriveInternal(ev, true); +} + +/* +==================== +Vehicle::EventDriveNoWait +==================== +*/ +void Vehicle::EventDriveNoWait(Event *ev) +{ + EventDriveInternal(ev, false); +} + +/* +==================== +Vehicle::EventStop +==================== +*/ +void Vehicle::EventStop(Event *ev) +{ + m_bStopEnabled = false; + m_bAutoPilot = false; + m_bIsSkidding = false; + moveimpulse = 0; + turnimpulse = 0; + m_iCurNode = 0; + Unregister(STRING_DRIVE); +} + +/* +==================== +Vehicle::EventFullStop +==================== +*/ +void Vehicle::EventFullStop(Event *ev) +{ + m_bAutoPilot = false; + m_bStopEnabled = false; + m_bIsSkidding = false; + moveimpulse = 0; + turnimpulse = 0; + velocity = vec_zero; + m_iCurNode = 0; + Unregister(STRING_DRIVE); +} + +/* +==================== +Vehicle::VehicleDestroyed +==================== +*/ +void Vehicle::VehicleDestroyed(Event *ev) +{ + Entity *ent; + Entity *targetEnt; + Event *event; + const char *name; + VehicleBase *v; + Vector vDelta; + + takedamage = DAMAGE_NO; + setSolidType(SOLID_NOT); + hideModel(); + + ent = ev->GetEntity(1); + if (driver.ent) { + EntityPtr driverPtr; + + velocity = vec_zero; + driverPtr = driver.ent; + + event = new Event(EV_Use); + event->AddEntity(driverPtr); + ProcessEvent(event); + + vDelta = driverPtr->origin - origin; + vDelta[2] += 64; + vDelta.normalize(); + + // kill the driver + driverPtr->Damage(this, this, driverPtr->health * 2, origin, vDelta, vec_zero, 50, 0, MOD_VEHICLE); + } + + if (flags & FL_DIE_EXPLODE) { + setSolidType(SOLID_NOT); + hideModel(); + CreateExplosion(origin, edict->s.scale * 150, this, this, this, m_sExplosionModel); + } + + if (flags & FL_DIE_GIBS) { + setSolidType(SOLID_NOT); + hideModel(); + CreateGibs(this, -150, edict->s.scale, 3, NULL); + } + + // + // remove all links + // + for (v = this; v->vlink; v = vlink) { + v->vlink->PostEvent(EV_Remove, EV_VEHICLE); + } + + // + // remove all kill targets + // + name = KillTarget(); + if (name && strcmp(name, "")) { + for (targetEnt = G_FindTarget(NULL, name); targetEnt; targetEnt = G_FindTarget(targetEnt, name)) { + targetEnt->PostEvent(EV_Remove, EV_VEHICLE); + } + } + + // + // activate targets + // + name = Target(); + if (name && strcmp(name, "")) { + for (targetEnt = G_FindTarget(NULL, name); targetEnt; targetEnt = G_FindTarget(targetEnt, name)) { + event = new Event(EV_Activate); + event->AddEntity(ent); + targetEnt->ProcessEvent(event); + } + } + + PostEvent(EV_Remove, EV_VEHICLE); +} + +/* +==================== +Vehicle::DetachRemoteOwner +==================== +*/ +void Vehicle::DetachRemoteOwner() +{ + VehicleTurretGun *vtg = static_cast(Turrets[0].ent.Pointer()); + vtg->EndRemoteControl(); +} + +static float GetAngleBetweenVectors2D(const Vector& a, const Vector& b) +{ + float value; + float angle; + + value = atan2f(a.x, a.y); + angle = RAD2DEG(value - atan2f(b.x, b.y)); + if (fabs(angle) <= 180) { + return angle; + } else if (angle < 0) { + return angle + 360; + } else { + return angle - 360; + } +} + +/* +==================== +Vehicle::DriverUse +==================== +*/ +void Vehicle::DriverUse(Event *ev) +{ + int slot; + Vector pos; + Vector dist; + float min_length = 1e30f; + int min_slot = 0; + int min_type = -1; + Entity *ent; + Vector vExitAngles; + bool bHasExitAngles; + Vector vExitPosition; + bool bHasExitPosition; + + ent = ev->GetEntity(1); + + bHasExitAngles = false; + bHasExitPosition = false; + + if (locked) { + return; + } + + // Added in 2.30 + // Check use angle + if (!driver.ent && m_fMaxUseAngle && ent && Turrets[0].ent) { + Vector vForward; + Vector vDir; + + AngleVectors(Turrets[0].ent->angles, vForward, NULL, NULL); + + vDir = Turrets[0].ent->origin - ent->origin; + VectorNormalize(vDir); + + if (fabs(GetAngleBetweenVectors2D(vForward, vDir)) > m_fMaxUseAngle) { + // Not usable + return; + } + } + + if (ev->NumArgs() == 2) { + if (ev->IsVectorAt(2)) { + vExitPosition = ev->GetVector(2); + bHasExitPosition = true; + } else if (ev->IsEntityAt(2)) { + Entity *pEnt = ev->GetEntity(2); + + bHasExitAngles = true; + vExitAngles = pEnt->angles; + vExitPosition = pEnt->origin; + bHasExitPosition = true; + } else if (ev->IsSimpleEntityAt(2)) { + SimpleEntity *pEnt = ev->GetSimpleEntity(2); + + bHasExitAngles = true; + vExitAngles = pEnt->angles; + vExitPosition = pEnt->origin; + bHasExitPosition = true; + } + } + + slot = FindDriverSlotByEntity(ent); + + if (slot >= 0) { + DetachDriverSlot(slot, vec_zero, NULL); + + if (IsSubclassOfVehicleTank()) { + // Added check to see if the turret is valid in OPM + if (Turrets[0].ent && Turrets[0].ent->IsSubclassOfVehicleTurretGun()) { + DetachRemoteOwner(); + } + } + + return; + } + + slot = FindPassengerSlotByEntity(ent); + + if (slot >= 0) { + DetachPassengerSlot(slot, vec_zero, NULL); + return; + } + + if (ent->IsSubclassOfWeapon()) { + slot = FindTurretSlotByEntity(ent); + + if (slot >= 0) { + DetachTurretSlot(slot, vec_zero, NULL); + } + } else if (ent->IsSubclassOfSentient()) { + Sentient *sent = static_cast(ent); + TurretGun *sentTurret = sent->GetTurret(); + + if (sentTurret) { + slot = FindTurretSlotByEntity(sent->GetTurret()); + + if (slot >= 0) { + if (!bHasExitPosition) { + AttachTurretSlot(slot, sent, vec_zero, NULL); + } else if (!bHasExitAngles) { + AttachTurretSlot(slot, sent, vExitPosition, NULL); + } else { + AttachTurretSlot(slot, sent, vExitPosition, &vExitAngles); + } + + sent->SetVehicle(NULL); + return; + } + } + } + + // Check for passengers slots + for (slot = 0; slot < MAX_PASSENGERS; slot++) { + if (!(Passengers[slot].flags & SLOT_FREE)) { + continue; + } + + QueryPassengerSlotPosition(slot, (float *)&pos); + + dist = pos - ent->origin; + + if (dist.length() < min_length) { + min_length = dist.length(); + min_type = 0; + min_slot = slot; + } + } + + // Check for turrets slots + if (ent->IsSubclassOfWeapon()) { + for (slot = 0; slot < MAX_TURRETS; slot++) { + if (!(Turrets[slot].flags & SLOT_FREE)) { + continue; + } + + QueryTurretSlotPosition(slot, (float *)&pos); + + dist = pos - ent->origin; + + if (dist.length() < min_length) { + min_length = dist.length(); + min_type = 1; + min_slot = slot; + } + } + } else { + for (slot = 0; slot < MAX_TURRETS; slot++) { + if (!(Turrets[slot].flags & SLOT_BUSY)) { + continue; + } + + QueryTurretSlotPosition(slot, (float *)&pos); + + dist = pos - ent->origin; + + if (dist.length() < min_length) { + min_length = dist.length(); + min_type = 1; + min_slot = slot; + } + } + } + + slot = 0; + + // Check for driver(s) slot(s) + if (driver.flags & SLOT_FREE) { + float length; + + QueryDriverSlotPosition(slot, (float *)&pos); + + dist = pos - ent->origin; + + length = dist.length(); + if (ent->IsSubclassOfPlayer()) { + length /= 2.0; + } + + if (length < min_length) { + min_length = dist.length(); + min_type = 2; + min_slot = slot; + } + } + + if (g_gametype->integer == GT_SINGLE_PLAYER || min_type == 2) { + switch (min_type) { + case 0: + AttachPassengerSlot(min_slot, ent, vec_zero); + break; + case 1: + AttachTurretSlot(min_slot, ent, vec_zero, NULL); + break; + case 2: + AttachDriverSlot(min_slot, ent, vec_zero); + break; + } + } +} + +/* +==================== +Vehicle::SetMoveInfo +==================== +*/ +void Vehicle::SetMoveInfo(vmove_t *vm) +{ + memset(vm, 0, sizeof(vmove_t)); + + origin.copyTo(vs.origin); + vs.useGravity = false; + vs.entityNum = entnum; + + vm->vs = &vs; + vm->frametime = level.frametime; + vm->tracemask = edict->clipmask; + mins.copyTo(vm->mins); + maxs.copyTo(vm->maxs); + + vs.entityNum = edict->s.number; + vs.desired_dir[0] = velocity[0]; + vs.desired_dir[1] = velocity[1]; + + vm->desired_speed = VectorNormalize2D(vs.desired_dir); +} + +/* +==================== +Vehicle::GetMoveInfo +==================== +*/ +void Vehicle::GetMoveInfo(vmove_t *vm) +{ + Vector newOrigin = vm->vs->origin; + + if (bindmaster) { + newOrigin = vm->vs->origin - origin; + } + + setLocalOrigin(newOrigin); + + groundentity = NULL; + if (vm->vs->groundEntityNum != ENTITYNUM_NONE) { + groundentity = &g_entities[vm->vs->groundEntityNum]; + } +} + +/* +==================== +Vehicle::SetCEMoveInfo +==================== +*/ +void Vehicle::SetCEMoveInfo(vmove_t *vm) +{ + Vector mins, maxs; + + SetMoveInfo(vm); + + mins = m_pCollisionEntity->mins; + maxs = m_pCollisionEntity->maxs; + mins -= Vector(24, 24, 0); + maxs += Vector(24, 24, 0); + + mins.copyTo(vm->mins); + maxs.copyTo(vm->maxs); +} + +/* +==================== +Vehicle::GetCEMoveInfo +==================== +*/ +void Vehicle::GetCEMoveInfo(vmove_t *vm) +{ + GetMoveInfo(vm); +} + +/* +==================== +Vehicle::SetViewAngles +==================== +*/ +void Vehicle::SetViewAngles(Vector newViewangles) +{ + client->ps.delta_angles[0] = floor(ANGLE2SHORT(newViewangles.x)); + client->ps.delta_angles[1] = floor(ANGLE2SHORT(newViewangles.y)); + client->ps.delta_angles[2] = floor(ANGLE2SHORT(newViewangles.z)); + + v_angle = newViewangles; + AnglesToAxis(v_angle, orientation); + + yaw_forward = orientation[0]; + yaw_left = orientation[1]; +} + +/* +==================== +Vehicle::SetSlotsNonSolid +==================== +*/ +void Vehicle::SetSlotsNonSolid(void) +{ + for (int i = 0; i < MAX_PASSENGERS; i++) { + Passengers[i].NotSolid(); + } + + for (int i = 0; i < MAX_TURRETS; i++) { + Turrets[i].NotSolid(); + } + + driver.NotSolid(); + + if (m_pCollisionEntity) { + m_pCollisionEntity->NotSolid(); + } +} + +/* +==================== +Vehicle::SetSlotsSolid +==================== +*/ +void Vehicle::SetSlotsSolid(void) +{ + for (int i = 0; i < MAX_PASSENGERS; i++) { + Passengers[i].Solid(); + } + + for (int i = 0; i < MAX_TURRETS; i++) { + Turrets[i].Solid(); + } + + driver.Solid(); + + if (m_pCollisionEntity) { + m_pCollisionEntity->Solid(); + } +} + +/* +==================== +Vehicle::AssertMove +==================== +*/ +bool Vehicle::AssertMove(Vector vNewOrigin, Vector vOldOrigin) +{ + Entity *check; + gentity_t *edict; + int touch[MAX_GENTITIES]; + int i; + int num; + + if (m_pCollisionEntity) { + num = gi.AreaEntities(m_pCollisionEntity->mins, m_pCollisionEntity->maxs, touch, MAX_GENTITIES); + } else { + num = gi.AreaEntities(mins, maxs, touch, MAX_GENTITIES); + } + + if (num <= 0) { + return true; + } + + for (i = 0; i < num; i++) { + edict = &g_entities[touch[i]]; + check = edict->entity; + + if (check->edict->s.number != edict->s.number && edict->solid && check->movetype != MOVETYPE_STOP) { + if (check->movetype != MOVETYPE_NONE && check->movetype != MOVETYPE_NOCLIP + && edict->r.contents != CONTENTS_PLAYERCLIP && IsTouching(check) + && G_TestEntityPosition(check, check->origin)) { + return false; + } + } + } + + return true; +} + +/* +==================== +Vehicle::AssertRotation +==================== +*/ +bool Vehicle::AssertRotation(Vector vNewAngles, Vector vOldAngles) +{ + Vector i; + Vector j; + Vector k; + Vector i2; + Vector j2; + Vector k2; + Vector vAngleDiff; + float mAngleDiff[3][3]; + + AngleVectorsLeft(vOldAngles, i, j, k); + AngleVectorsLeft(vNewAngles, i2, j2, k2); + AnglesSubtract(vOldAngles, vNewAngles, vAngleDiff); + AngleVectorsLeft(vAngleDiff, mAngleDiff[0], mAngleDiff[1], mAngleDiff[2]); + + // FIXME: shrug + + return true; +} + +/* +==================== +Vehicle::NoMove +==================== +*/ +void Vehicle::NoMove(void) +{ + vmove_t vm; + + SetMoveInfo(&vm); + VectorClear2D(vs.desired_dir); + VmoveSingle(&vm); + GetMoveInfo(&vm); +} + +/* +==================== +Vehicle::SlidePush +==================== +*/ +void Vehicle::SlidePush(Vector vPush) +{ + vmove_t vm; + int i; + int j; + Entity *pSkippedEntities[MAX_SKIPPED_ENTITIES]; + int iContentsEntities[MAX_SKIPPED_ENTITIES]; + solid_t solidEntities[MAX_SKIPPED_ENTITIES]; + int iNumSkippedEntities = 0; + int iNumSkipped = 0; + gentity_t *other; + Vector newOrigin; + + do { + SetMoveInfo(&vm); + + vPush.copyTo(vm.vs->velocity); + vm.frametime = 1; + + vs.desired_dir[0] = vPush[0]; + vs.desired_dir[1] = vPush[1]; + vm.desired_speed = VectorNormalize2D(vs.desired_dir); + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(origin, vm.mins, vm.maxs, 1, 0, 0, 1); + G_DebugBBox(origin, vm.mins, vm.maxs, 0, 1, 0, 1); + } + + VmoveSingle(&vm); + + iNumSkippedEntities = 0; + + for (i = 0; i < vm.numtouch; i++) { + other = &g_entities[vm.touchents[i]]; + + for (j = 0; j < i; j++) { + if (&g_entities[j] == other) { + break; + } + } + + if (j == i && other->entity) { + other->entity->CheckGround(); + + if (other->entity->groundentity && (other->entity->groundentity == edict + || m_pCollisionEntity && other->entity->groundentity->entity == m_pCollisionEntity)) { + // save the entity + pSkippedEntities[iNumSkipped] = other->entity; + iContentsEntities[iNumSkipped] = other->r.contents; + solidEntities[iNumSkipped] = other->solid; + iNumSkipped++; + + if (iNumSkipped >= MAX_SKIPPED_ENTITIES) { + gi.Error(ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n"); + return; + } + + other->entity->setSolidType(SOLID_NOT); + iNumSkippedEntities++; + } + + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Hit(SP): %s : %s\n", other->entity->getClassname(), other->entity->targetname.c_str() + ); + } + } + } + } while (iNumSkippedEntities != 0); + + newOrigin = vm.vs->origin; + if (bindmaster) { + newOrigin -= bindmaster->origin; + } + + setLocalOrigin(newOrigin); + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(origin, vm.mins, vm.maxs, 0, 0, 1, 1); + } + + TouchStuff(&vm); + + for (i = 0; i < iNumSkipped; i++) { + pSkippedEntities[i]->setSolidType(solidEntities[i]); + pSkippedEntities[i]->setContents(iContentsEntities[i]); + } +} + +/* +==================== +Vehicle::AnimMoveVehicle +==================== +*/ +void Vehicle::AnimMoveVehicle(void) +{ + Vector vPosition; + Vector vAngles; + Entity *ent; + + // + // velocity + // + vPosition = origin + frame_delta; + velocity = (vPosition - origin) * (1.0 / level.frametime); + + setOrigin(vPosition); + + // + // angular velocity + // + vAngles = angles; + vAngles[1] += angular_delta; + avelocity = (vAngles - angles) * (1.0 / level.frametime); + + setAngles(vAngles); + + for (ent = teamchain; ent; ent = ent->teamchain) { + ent->setLocalOrigin(ent->localorigin); + ent->setAngles(ent->localangles); + } +} + +/* +==================== +Vehicle::MoveVehicle +==================== +*/ +void Vehicle::MoveVehicle(void) +{ + trace_t tr; + Vector vecStart; + Vector vecStart2; + Vector vecEnd; + Vector vecDelta; + Vector vecAng; + int i; + gridpoint_t *gp; + vmove_t vm; + float flMoveFrac = 1; + float fSpeed; + bool bDoPush = true; + bool bDoGravity = false; + bool bHitPerson = false; + Entity *pSkippedEntities[MAX_SKIPPED_ENTITIES]; + int iContentsEntities[MAX_SKIPPED_ENTITIES]; + solid_t solidEntities[MAX_SKIPPED_ENTITIES]; + int iNumSkippedEntities = 0; + Event *event = nullptr; + Entity *chain; + Entity *driverEnt = NULL; + solid_t solidDriver = SOLID_NOT; + int contentsDriver = 0; + + if (m_bMovementLocked) { + return; + } + + setAngles(); + if (m_pCollisionEntity) { + SetCEMoveInfo(&vm); + } else { + SetMoveInfo(&vm); + } + m_sMoveGrid->SetMoveInfo(&vm); + m_sMoveGrid->SetOrientation(orientation); + m_sMoveGrid->CalculateBoxPoints(); + CheckGround(); + + if (velocity.length() > 0.5f) { + Vector vVel; + + if (driver.ent && driver.ent->edict->solid != SOLID_NOT) { + // + // Added in OPM + // Make the driver nonsolid while moving. + // Scripts usually set the player to nonsolid. + // However some scripts still rely on the old 1.11 behavior + // where the player is set to nonsolid when driving some type of vehicles + solidDriver = driver.ent->edict->solid; + contentsDriver = driver.ent->getContents(); + + driver.ent->setSolidType(SOLID_NOT); + } + + fSpeed = orientation[0] * velocity; + vecDelta = velocity * level.frametime; + + vVel = velocity * level.frametime * 8; + vecDelta[2] = 0; + + for (i = 0; i < 3 && bDoPush; i++) { + bool bContinue = false; + + if (fSpeed > 0.0f) { + gp = m_sMoveGrid->GetGridPoint(2, i, 0); + } else { + gp = m_sMoveGrid->GetGridPoint(0, i, 0); + } + vecStart = origin + gp->origin; + + if (real_velocity.length() > 0.5f) { + vecEnd = vecStart + vVel; + + for (;;) { + tr = G_Trace( + vecEnd, + Vector(gp->vm.mins) - Vector(-32, -32, -32), + Vector(gp->vm.maxs) + Vector(32, 32, 32), + vecEnd, + this, + MASK_MOVEVEHICLE, + false, + "Vehicle::MoveVehicle" + ); + + if (!tr.ent || !tr.ent->entity || tr.ent->entity == world) { + break; + } + + tr.ent->entity->CheckGround(); + + if (!tr.ent->entity->groundentity + || (tr.ent->entity->groundentity != edict + && (!m_pCollisionEntity || tr.ent->entity->groundentity->entity != m_pCollisionEntity))) { + Event *event = new Event(EV_Touch); + event->AddEntity(this); + tr.ent->entity->ProcessEvent(event); + + event = new Event(EV_Touch); + event->AddEntity(tr.ent->entity); + ProcessEvent(event); + + if (tr.ent->entity->IsSubclassOfSentient()) { + bHitPerson = true; + } + + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Hit(MV0): %s : %s\n", + tr.ent->entity->getClassname(), + tr.ent->entity->targetname.c_str() + ); + } + + // Added in OPM + // Skip the entity if the sentient is dead. + // This is a workaround against sentients getting in path of vehicles + // and thus blocking them temporarily while dying. + // For example in e1l1, the first tank would get stuck, because sometimes + // there are too many actors moving in the path of the vehicle + if (!bHitPerson || !tr.ent->entity->IsDead()) { + break; + } + } + + pSkippedEntities[iNumSkippedEntities] = tr.ent->entity; + iContentsEntities[iNumSkippedEntities] = tr.ent->r.contents; + solidEntities[iNumSkippedEntities] = tr.ent->solid; + iNumSkippedEntities++; + + if (iNumSkippedEntities >= MAX_SKIPPED_ENTITIES) { + gi.Error(ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n"); + return; + } + + tr.ent->entity->setSolidType(SOLID_NOT); + + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Skipped(MV0): %s : %s\n", + tr.ent->entity->getClassname(), + tr.ent->entity->targetname.c_str() + ); + } + } + } + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(vecStart, gp->vm.mins, gp->vm.maxs, 1, 0, 0, 1); + } + + vecStart.z += 64; + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(vecStart, gp->vm.mins, gp->vm.maxs, 1, 0, 0, 1); + } + + vecEnd = vecStart + vecDelta; + + for (;;) { + tr = G_Trace( + vecStart, + Vector(gp->vm.mins), + Vector(gp->vm.maxs), + vecEnd, + this, + edict->clipmask, + false, + "Vehicle::MoveVehicle" + ); + + if (tr.fraction == 1.0f && !tr.allsolid && !tr.startsolid) { + bContinue = true; + break; + } + + if (!tr.ent || !tr.ent->entity || tr.ent->entity == world) { + break; + } + + tr.ent->entity->CheckGround(); + + if (!tr.ent->entity->groundentity + || (tr.ent->entity->groundentity != edict + && (!m_pCollisionEntity || tr.ent->entity->groundentity->entity != m_pCollisionEntity))) { + Event *event = new Event(EV_Touch); + event->AddEntity(this); + tr.ent->entity->ProcessEvent(event); + + event = new Event(EV_Touch); + event->AddEntity(tr.ent->entity); + ProcessEvent(event); + + if (tr.ent->entity->IsSubclassOfSentient()) { + bHitPerson = true; + } + + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Hit(MV): %s : %s\n", + tr.ent->entity->getClassname(), + tr.ent->entity->TargetName().c_str() + ); + } + + // Added in OPM + // (see the comment above) + if (!bHitPerson || !tr.ent->entity->IsDead()) { + break; + } + } + + pSkippedEntities[iNumSkippedEntities] = tr.ent->entity; + iContentsEntities[iNumSkippedEntities] = tr.ent->r.contents; + solidEntities[iNumSkippedEntities] = tr.ent->solid; + iNumSkippedEntities++; + + if (iNumSkippedEntities >= MAX_SKIPPED_ENTITIES) { + gi.Error(ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n"); + return; + } + + tr.ent->entity->setSolidType(SOLID_NOT); + + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Skipped(MV): %s : %s\n", + tr.ent->entity->getClassname(), + tr.ent->entity->TargetName().c_str() + ); + } + } + + if (bContinue) { + continue; + } + + if (flMoveFrac > tr.fraction) { + flMoveFrac = tr.fraction - 0.1f; + } + + vecStart = tr.endpos; + vecEnd = vecStart; + vecEnd.z -= 64; + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(tr.endpos, gp->vm.mins, gp->vm.maxs, 0, 1, 0, 1); + } + + for (;;) { + tr = G_Trace( + vecStart, + Vector(gp->vm.mins), + Vector(gp->vm.maxs), + vecEnd, + this, + edict->clipmask, + false, + "Vehicle::MoveVehicle" + ); + + if ((tr.fraction != 1.0f && tr.plane.normal[2] < 0.7f) || tr.allsolid) { + flMoveFrac = 0.0f; + } + + if (!tr.ent || !tr.ent->entity || tr.ent->entity == world) { + break; + } + + tr.ent->entity->CheckGround(); + + if (!tr.ent->entity->groundentity + || (tr.ent->entity->groundentity != edict + && (!m_pCollisionEntity || tr.ent->entity->groundentity->entity != m_pCollisionEntity))) { + Event *event = new Event(EV_Touch); + event->AddEntity(this); + tr.ent->entity->ProcessEvent(event); + + event = new Event(EV_Touch); + event->AddEntity(tr.ent->entity); + ProcessEvent(event); + + if (tr.ent->entity->IsSubclassOfSentient()) { + bHitPerson = true; + } + + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Hit(MV2): %s : %s\n", + tr.ent->entity->getClassname(), + tr.ent->entity->TargetName().c_str() + ); + } + + // Added in OPM + // (see the comment above) + if (!bHitPerson || !tr.ent->entity->IsDead()) { + break; + } + } + + pSkippedEntities[iNumSkippedEntities] = tr.ent->entity; + iContentsEntities[iNumSkippedEntities] = tr.ent->r.contents; + solidEntities[iNumSkippedEntities] = tr.ent->solid; + iNumSkippedEntities++; + + if (iNumSkippedEntities >= MAX_SKIPPED_ENTITIES) { + gi.Error(ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n"); + return; + } + + tr.ent->entity->setSolidType(SOLID_NOT); + if (g_showvehiclemovedebug->integer) { + Com_Printf( + "Vehicle Skipped(MV2): %s : %s\n", + tr.ent->entity->getClassname(), + tr.ent->entity->targetname.c_str() + ); + } + } + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(tr.endpos, gp->vm.mins, gp->vm.maxs, 0, 0, 1, 1); + } + + if ((!tr.ent || !tr.ent->entity->IsSubclassOfProjectile()) && driver.ent + && driver.ent->IsSubclassOfPlayer()) { + if (fSpeed > 0) { + if (i) { + if (i == 2 && turnimpulse >= 0.0f) { + turnimpulse -= level.frametime * 800; + } + } else if (turnimpulse <= 0) { + turnimpulse += level.frametime * 800; + } + } else { + if (i) { + if (i == 2 && turnimpulse <= 0.0f) { + turnimpulse += level.frametime * 800; + } + } else if (turnimpulse >= 0) { + turnimpulse -= level.frametime * 800; + } + } + } + + if (flMoveFrac < 0.1f) { + bDoPush = false; + } + } + + if (bDoPush) { + SlidePush(Vector(0, 0, 64)); + SlidePush(vecDelta * flMoveFrac); + SlidePush(Vector(0, 0, -128)); + + bDoGravity = true; + if (!bHitPerson) { + velocity *= flMoveFrac; + } + } else if (!bHitPerson) { + velocity *= 0.5; + } + + if (solidDriver != SOLID_NOT) { + driver.ent->setSolidType(solidDriver); + driver.ent->setContents(contentsDriver); + } + } + + if (bDoGravity) { + velocity[2] -= sv_gravity->value * level.frametime; + + tr = G_Trace( + origin, + mins, + maxs, + origin + Vector(0, 0, velocity[2] * level.frametime), + this, + edict->clipmask, + qtrue, + "Vehicle::MoveVehicle" + ); + + if (tr.fraction < 1) { + velocity[2] = 0; + } + + setOrigin(tr.endpos); + } + + for (i = 0; i < iNumSkippedEntities; i++) { + pSkippedEntities[i]->setSolidType(solidEntities[i]); + pSkippedEntities[i]->setContents(iContentsEntities[i]); + } + + for (chain = teamchain; chain; chain = chain->teamchain) { + chain->setLocalOrigin(chain->localorigin); + chain->setAngles(chain->localangles); + } +} + +/* +==================== +Vehicle::Think +==================== +*/ +void Vehicle::Think(void) +{ + flags |= FL_POSTTHINK; +} + +/* +==================== +Vehicle::Postthink +==================== +*/ +void Vehicle::Postthink(void) +{ + float turn; + Vector i; + Vector j; + Vector k; + Vector temp; + Vector roll; + Vector acceleration; + Vector atmp; + Vector atmp2; + Vector aup; + VehicleBase *v; + VehicleBase *last; + float drivespeed; + float dot; + Vector primal_angles = angles; + Vector primal_origin = origin; + Vector vTmp; + Vector vAddedAngles; + Vector n_angles; + orientation_t orient; + + if (!g_vehicle->integer || (edict->s.renderfx & RF_DONTDRAW)) { + return; + } + + if (m_pCollisionEntity) { + setSolidType(SOLID_NOT); + m_pCollisionEntity->Solid(); + } + + prev_velocity = velocity; + + if (m_vOldMins != vec_zero && m_vOldMaxs != vec_zero) { + mins = m_vOldMins; + maxs = m_vOldMaxs; + } else if (mins != vec_zero || maxs != vec_zero) { + m_vOldMins = mins; + m_vOldMaxs = maxs; + } + + SetSlotsNonSolid(); + if (m_bAnimMove) { // 2.0: use vehicle's animation to move + AnimMoveVehicle(); + } else { + if (!m_bMovementLocked) { + FactorOutAnglesOffset(); + FactorOutOriginOffset(); + } + MoveVehicle(); + } + + SetSlotsSolid(); + + m_bThinkCalled = true; + + if (m_bAnimMove) { + moveimpulse = velocity.length() * level.frametime; + turnimpulse = avelocity[1] * level.frametime; + } else if (m_bAutoPilot) { + AutoPilot(); + } else { + if (!driver.ent || !driver.ent->IsSubclassOfPlayer()) { + acceleration = velocity; + + if (acceleration.length() < 0.1f) { + velocity = vec_zero; + } + } + + moveimpulse *= 0.825f; + turnimpulse *= 0.825f; + } + + currentspeed = moveimpulse; + turnangle = turnangle * 0.25f + turnimpulse; + turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate); + + if (level.inttime <= 1200) { + prev_origin = origin; + } else { + real_velocity = origin - prev_origin; + prev_origin = origin; + prev_acceleration = real_acceleration; + real_acceleration = real_velocity - prev_velocity; + prev_velocity = real_velocity; + acceleration = real_acceleration - prev_acceleration; + } + + UpdateSkidAngle(); + UpdateBones(); + UpdateShaderOffset(); + UpdateTires(); + UpdateNormals(); + + angles.AngleVectorsLeft(&i, &j, &k); + + turn = level.frametime * turnangle; + + velocity[0] *= 0.925f; + velocity[1] *= 0.925f; + + velocity = Vector(orientation[0]) * currentspeed; + temp = orientation[0]; + temp.z = 0; + + drivespeed = velocity * temp; + drivespeed = Q_clamp_float(drivespeed, -speed, speed); + n_angles = temp * drivespeed; + + velocity = n_angles; + velocity.z = drivespeed * jumpimpulse; + avelocity *= 0.05f; + + if (steerinplace && drivespeed < 350) { + drivespeed = 350; + } + + avelocity.y += turn * drivespeed; + angles += avelocity * level.frametime; + + dot = acceleration * orientation[0]; + + UpdateSound(); + + i = orientation[0]; + j = orientation[1]; + k = orientation[2]; + + CalculateAnglesOffset(acceleration); + CalculateOriginOffset(); + + last_origin = origin; + vTmp = (angles - primal_angles) * level.frametime; + + if (vTmp.x > 180 || vTmp.x < -180) { + vTmp.x = 0; + } + if (vTmp.y > 180 || vTmp.y < -180) { + vTmp.y = 0; + } + if (vTmp.z > 180 || vTmp.z < -180) { + vTmp.z = 0; + } + + if (vTmp.x > -1 || vTmp.x < 1) { + vTmp.x = 0; + } + if (vTmp.y > -1 || vTmp.y < 1) { + vTmp.y = 0; + } + if (vTmp.z > -1 || vTmp.z < 1) { + vTmp.z = 0; + } + + avelocity = vAddedAngles; + + if (!m_bAnimMove && !m_bMovementLocked) { + FactorInOriginOffset(); + FactorInAnglesOffset(&vAddedAngles); + } + + n_angles = m_vOriginOffset + m_vOriginOffset2; + CalculateAnimationData(vAddedAngles, m_vOriginOffset + m_vOriginOffset2); + + if (m_pCollisionEntity) { + Vector vaDelta; + + SetSlotsNonSolid(); + + vaDelta[0] = angledist(angles[0] - m_pCollisionEntity->angles[0]); + vaDelta[1] = angledist(angles[1] - m_pCollisionEntity->angles[1]); + vaDelta[2] = angledist(angles[2] - m_pCollisionEntity->angles[2]); + + m_pCollisionEntity->Solid(); + + G_PushMove(m_pCollisionEntity, origin - primal_origin, vaDelta); + G_TouchTriggers(m_pCollisionEntity); + + SetSlotsSolid(); + + m_pCollisionEntity->setOrigin(origin); + m_pCollisionEntity->setAngles(angles); + } + + SetupVehicleSoundEntities(); + UpdateDriverSlot(0); + + for (int slot = 0; slot < MAX_PASSENGERS; slot++) { + UpdatePassengerSlot(slot); + } + + atmp = angles - primal_angles; + + for (int slot = 0; slot < MAX_TURRETS; slot++) { + UpdateTurretSlot(slot); + } + + if (g_showvehicleentrypoints->integer) { + for (int slot = 0; slot < MAX_PASSENGERS; slot++) { + if (Passengers[slot].enter_boneindex >= 0) { + QueryPassengerSlotPosition(slot, (float *)&temp); + + G_DebugCircle(temp, 10, 1, 0, 0, 1, true); + } + } + + for (int slot = 0; slot < MAX_TURRETS; slot++) { + if (Turrets[slot].enter_boneindex >= 0) { + QueryTurretSlotPosition(slot, (float *)&temp); + + G_DebugCircle(temp, 10, 0, 1, 0, 1, true); + } + } + + if (driver.enter_boneindex >= 0) { + QueryDriverSlotPosition(0, (float *)&temp); + + G_DebugCircle(temp, 10, 0, 0, 1, 1, true); + } + } + + if (g_showvehicleslotpoints->integer) { + for (int slot = 0; slot < MAX_PASSENGERS; slot++) { + if (Passengers[slot].boneindex >= 0) { + GetTagPositionAndOrientation(Passengers[slot].boneindex, &orient); + G_DebugCircle(orient.origin, 10.0, 1.0f, 0.5f, 0.5f, 1.0f, true); + + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[0]) * 32, 1, 0, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[1]) * 32, 0, 1, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[2]) * 32, 0, 0, 1, 1); + } + } + + for (int slot = 0; slot < MAX_TURRETS; slot++) { + if (Turrets[slot].boneindex >= 0) { + GetTagPositionAndOrientation(Turrets[slot].boneindex, &orient); + G_DebugCircle(orient.origin, 10.0, 0.5f, 1.0f, 1.0f, 1.0f, true); + + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[0]) * 32, 1, 0, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[1]) * 32, 0, 1, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[2]) * 32, 0, 0, 1, 1); + } + } + + if (driver.boneindex >= 0) { + GetTagPositionAndOrientation(driver.boneindex, &orient); + G_DebugCircle(orient.origin, 10.0, 0.5f, 0.5f, 1.0f, 1.0f, true); + + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[0]) * 32, 1, 0, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[1]) * 32, 0, 1, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[2]) * 32, 0, 0, 1, 1); + } + } + + if (g_showvehicletags->integer) { + int numtags; + int tagnum; + + numtags = gi.TIKI_NumTags(edict->tiki); + for (tagnum = 0; tagnum < numtags; tagnum++) { + const char *name = gi.Tag_NameForNum(edict->tiki, tagnum); + if (!strncmp(name, "tag", 3)) { + GetTagPositionAndOrientation(tagnum, &orient); + G_DebugCircle(orient.origin, 10.0, 1, 1, 1, 1, true); + + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[0]) * 32, 1, 0, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[1]) * 32, 0, 1, 0, 1); + G_DebugLine(orient.origin, orient.origin + Vector(orient.axis[2]) * 32, 0, 0, 1, 1); + } + } + } + + for (last = this; last->vlink; last = v) { + v = last->vlink; + + v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z); + v->avelocity = avelocity; + v->velocity = velocity; + + v->angles[ROLL] = angles[ROLL]; + v->angles[YAW] = angles[YAW]; + v->angles[PITCH] = (float)((int)(v->angles[PITCH] + drivespeed / 4.f) % 360); + v->setAngles(v->angles); + } + + CheckWater(); + WorldEffects(); + + if (m_pCollisionEntity) { + setSolidType(SOLID_NOT); + m_pCollisionEntity->Solid(); + } else { + setSolidType(SOLID_BBOX); + setContents(CONTENTS_UNKNOWN2); + } +} + +/* +==================== +Vehicle::VehicleTouched +==================== +*/ +void Vehicle::VehicleTouched(Event *ev) +{ + Entity *other; + float dot; + float speed; + Vector delta; + Vector dir; + Event *event; + + other = ev->GetEntity(1); + if (other == driver.ent) { + return; + } + + if (other == world) { + return; + } + + delta = other->origin - last_origin; + delta.normalize(); + + dot = velocity * orientation[0]; + if (dot > 0) { + if (delta * orientation[0] < 0) { + return; + } + } else { + if (delta * orientation[0] > 0) { + return; + } + } + + if (!other->IsSubclassOfVehicleTurretGun()) { + speed = velocity.length(); + if (speed > 10) { + Sound(m_sSoundSet + "vehicle_crash"); + dir = delta * (1 / speed); + + event = new Event(EV_Damage); + if (lastdriver.ent && lastdriver.ent->IsSubclassOfPlayer()) { + event->AddEntity(lastdriver.ent); + } else { + event->AddEntity(world); + } + + event->AddFloat(speed); + event->AddEntity(this); + event->AddVector(origin); + event->AddVector(dir); + event->AddVector(vec_zero); + event->AddFloat(speed); + event->AddInteger(0); + event->AddInteger(MOD_VEHICLE); + event->AddInteger(-1); + other->PostEvent(event, 0); + } + } +} + +void Vehicle::SetProjectileVulnerable(Event *ev) +{ + if (ev->NumArgs() > 1) { + ScriptError("Too many arguments"); + } + + if (ev->NumArgs() > 0) { + m_iProjectileHitsRemaining = ev->GetInteger(1); + if (m_iProjectileHitsRemaining < 0) { + ScriptError("Negative arguments illegal"); + } + } else { + m_iProjectileHitsRemaining = 0; + } +} + +void Vehicle::DoProjectileVulnerability(Entity *pProjectile, Entity *pOwner, meansOfDeath_t meansOfDeath) +{ + Event *event; + Vector delta; + + if (m_iProjectileHitsRemaining > 1) { + m_iProjectileHitsRemaining--; + return; + } + + event = new Event(EV_Damage); + delta = origin - pProjectile->origin; + + event->AddEntity(pProjectile); + event->AddFloat(health * 2); + event->AddEntity(pOwner); + event->AddVector(origin); + event->AddVector(delta); + event->AddVector(vec_zero); + event->AddFloat(0); + event->AddInteger(0); + event->AddInteger(meansOfDeath); + event->AddInteger(-1); + PostEvent(event, 0); +} + +/* +==================== +Vehicle::VehicleBlocked +==================== +*/ +void Vehicle::VehicleBlocked(Event *ev) +{ + return; + /* + Entity* other; + float speed; + float damage; + Vector delta; + Vector newvel; + Vector dir; + + if (!velocity[0] && !velocity[1]) + return; + + other = ev->GetEntity(1); + if (other == driver.ent) + { + return; + } + if (other->isSubclassOf(VehicleBase)) + { + delta = other->origin - origin; + delta.normalize(); + + newvel = vec_zero - (velocity)+(other->velocity * 0.25); + if (newvel * delta < 0) + { + velocity = newvel; + delta = velocity - other->velocity; + damage = delta.length() / 4; + } + else + { + return; + } + } + else if ((velocity.length() < 350)) + { + other->velocity += velocity * 1.25f; + other->velocity[2] += 100; + damage = velocity.length() / 4; + } + else + { + damage = other->health + 1000; + } + + // Gib 'em outright + speed = fabs(velocity.length()); + dir = velocity * (1 / speed); + other->Damage(this, lastdriver.ent, damage, origin, dir, vec_zero, speed, 0, MOD_VEHICLE, -1, -1, 1.0f); +*/ +} + +/* +==================== +Vehicle::WorldEffects +==================== +*/ +void Vehicle::WorldEffects(void) +{ + /* + // + // Check for earthquakes + // + if (groundentity && (level.earthquake_magnitude > 0.0f)) { + velocity += Vector( + level.earthquake_magnitude * EARTHQUAKE_STRENGTH * G_CRandom(), + level.earthquake_magnitude * EARTHQUAKE_STRENGTH * G_CRandom(), + level.earthquake_magnitude * 1.5f * G_Random() + ); + } + + // + // check for lava + // + if (watertype & CONTENTS_LAVA) { + Damage(world, world, 20 * waterlevel, origin, vec_zero, vec_zero, 0, DAMAGE_NO_ARMOR, MOD_LAVA); + } +*/ +} + +/* +==================== +Vehicle::UpdateVariables +==================== +*/ +void Vehicle::UpdateVariables( + Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright +) +{} + +/* +==================== +Vehicle::TorqueLookup +==================== +*/ +float Vehicle::TorqueLookup(int rpm) +{ + if (rpm < 5000) { + return 190; + } else if (rpm < 6000) { + return (float)(190 * (6000 - rpm)) / 1000.f; + } else { + return 0; + } +} + +/* +==================== +Vehicle::SpawnTurret +==================== +*/ +void Vehicle::SpawnTurret(Event *ev) +{ + VehicleTurretGun *pTurret; + int slot; + + pTurret = new VehicleTurretGun(); + pTurret->SetBaseOrientation(orientation, NULL); + pTurret->setModel(ev->GetString(2)); + + slot = ev->GetInteger(1); + AttachTurretSlot(slot, pTurret, vec_zero, NULL); + + pTurret->SetVehicleOwner(this); + pTurret->PostEvent(EV_TakeDamage, EV_POSTSPAWN); + UpdateTurretSlot(slot); + + pTurret->ProcessPendingEvents(); +} + +/* +==================== +Vehicle::EventModifyDrive +==================== +*/ +void Vehicle::EventModifyDrive(Event *ev) +{ + if (!level.Spawned()) { + ScriptError("ModifyDrive used improperly... (used before the level is spawned)"); + } + + if (!m_bAutoPilot || !this->m_pCurPath) { + ScriptError("ModifyDrive used when not driving!"); + } + + if (ev->NumArgs() < 1 || ev->NumArgs() > 3) { + ScriptError("wrong number of arguments"); + } + + switch (ev->NumArgs()) { + case 3: + m_fLookAhead = ev->GetFloat(3); + case 2: + m_fIdealAccel = ev->GetFloat(2); + case 1: + m_fIdealSpeed = ev->GetFloat(1); + m_fMaxSpeed = m_fIdealSpeed; + break; + } +} + +/* +==================== +Vehicle::EventModel +==================== +*/ +void Vehicle::EventModel(Event *ev) +{ + SetModelEvent(ev); +} + +/* +==================== +Vehicle::TouchStuff +==================== +*/ +void Vehicle::TouchStuff(vmove_t *vm) +{ + int i, j; + gentity_t *other; + Event *event; + + if (driver.ent) { + G_TouchTriggers(driver.ent); + } + + for (int i = 0; i < MAX_PASSENGERS; i++) { + if (Passengers[i].ent) { + G_TouchTriggers(Passengers[i].ent); + } + } + + for (int i = 0; i < MAX_TURRETS; i++) { + if (Turrets[i].ent) { + G_TouchTriggers(Turrets[i].ent); + } + } + + if (getMoveType() != MOVETYPE_NOCLIP) { + G_TouchTriggers(this); + } + + for (i = 0; i < vm->numtouch; i++) { + other = &g_entities[vm->touchents[i]]; + + for (j = 0; j < i; j++) { + gentity_t *ge = &g_entities[j]; + + if (ge == other) { + break; + } + } + + if (j != i) { + // duplicated + continue; + } + + // Don't bother touching the world + if ((!other->entity) || (other->entity == world)) { + continue; + } + + event = new Event(EV_Touch); + event->AddEntity(this); + other->entity->ProcessEvent(event); + + event = new Event(EV_Touch); + event->AddEntity(other->entity); + ProcessEvent(event); + } +} + +/* +==================== +Vehicle::EventNextDrive +==================== +*/ +void Vehicle::EventNextDrive(Event *ev) +{ + SimpleEntity *path; + float *i_fTmp; + float o_fTmp[4]; + Vector org1; + Vector org2; + + path = ev->GetSimpleEntity(1); + + if (!m_bAutoPilot) { + ScriptError("Cannot Set Next Path because Not Currently Driving a Path."); + } + + if (!m_pCurPath || m_pCurPath->m_iPoints == 0) { + ScriptError("Cannot Set Next Path because Current Path is Empty."); + } + + if (!m_pNextPath) { + m_pNextPath = new cVehicleSpline; + } + + SetupPath(m_pNextPath, path); + + i_fTmp = m_pCurPath->GetByNode(m_pCurPath->m_iPoints, NULL); + org1 = (i_fTmp + 1); + i_fTmp = m_pNextPath->GetByNode(0.0f, NULL); + org2 = (i_fTmp + 1); + + o_fTmp[0] = (org2 - org1).length(); + VectorClear(o_fTmp + 1); + + m_pNextPath->UniformAdd(o_fTmp); + m_iNextPathStartNode = m_pCurPath->Append(m_pNextPath); +} + +/* +==================== +Vehicle::EventLockMovement +==================== +*/ +void Vehicle::EventLockMovement(Event *ev) +{ + m_bMovementLocked = true; +} + +/* +==================== +Vehicle::EventUnlockMovement +==================== +*/ +void Vehicle::EventUnlockMovement(Event *ev) +{ + m_bMovementLocked = false; +} + +/* +==================== +Vehicle::EventRemoveOnDeath +==================== +*/ +void Vehicle::EventRemoveOnDeath(Event *ev) +{ + m_bRemoveOnDeath = ev->GetBoolean(1); +} + +/* +==================== +Vehicle::EventSetExplosionModel +==================== +*/ +void Vehicle::EventSetExplosionModel(Event *ev) +{ + m_sExplosionModel = ev->GetString(1); +} + +/* +==================== +Vehicle::EventSetCollisionModel +==================== +*/ +void Vehicle::EventSetCollisionModel(Event *ev) +{ + Entity *pColEnt = ev->GetEntity(1); + + if (!pColEnt) { + ScriptError("Trying to set a collision model with a NULL entity."); + } + + if (m_pCollisionEntity) { + m_pCollisionEntity->PostEvent(EV_Remove, EV_VEHICLE); + } + + m_pCollisionEntity = new VehicleCollisionEntity(this); + m_pCollisionEntity->setModel(pColEnt->model); + + if (!m_pCollisionEntity->model.length() || *m_pCollisionEntity->model != '*') { + // Re-post the event with the correct time + m_pCollisionEntity->CancelEventsOfType(EV_Remove); + m_pCollisionEntity->PostEvent(EV_Remove, EV_VEHICLE); + m_pCollisionEntity = NULL; + + ScriptError("Model for Entity not of a valid type. Must be B-Model."); + } + + m_pCollisionEntity->setOrigin(origin); + m_pCollisionEntity->setAngles(angles); +} + +/* +==================== +Vehicle::EventGetCollisionModel +==================== +*/ +void Vehicle::EventGetCollisionModel(Event *ev) +{ + ev->AddEntity(m_pCollisionEntity); +} + +/* +==================== +Vehicle::EventSetSoundParameters +==================== +*/ +void Vehicle::EventSetSoundParameters(Event *ev) +{ + m_fSoundMinSpeed = ev->GetFloat(1); + m_fSoundMinPitch = ev->GetFloat(2); + m_fSoundMaxSpeed = ev->GetFloat(3); + m_fSoundMaxPitch = ev->GetFloat(4); +} + +/* +==================== +Vehicle::EventSetVolumeParameters +==================== +*/ +void Vehicle::EventSetVolumeParameters(Event *ev) +{ + m_fVolumeMinSpeed = ev->GetFloat(1); + m_fVolumeMinPitch = ev->GetFloat(2); + m_fVolumeMaxSpeed = ev->GetFloat(3); + m_fVolumeMaxPitch = ev->GetFloat(4); +} + +/* +==================== +Vehicle::UpdateSound +==================== +*/ +void Vehicle::UpdateSound(void) +{ + float pitch; + float volume; + + if (level.time < m_fNextSoundState) { + return; + } + + // Calculate the pitch based on the vehicle's speed + pitch = (velocity.length() - m_fSoundMinSpeed) / (m_fSoundMaxSpeed - m_fSoundMinSpeed); + + if (pitch > 1.0f) { + pitch = 1.0f; + } else if (pitch < 0.0f) { + pitch = 0.0f; + } + + pitch = m_fSoundMinPitch + (m_fSoundMaxPitch - m_fSoundMinPitch) * pitch; + + volume = (velocity.length() - m_fVolumeMinSpeed) / (m_fVolumeMaxSpeed - m_fVolumeMinSpeed); + + if (volume > 1.0f) { + volume = 1.0f; + } else if (volume < 0.0f) { + volume = 0.0f; + } + + volume = this->m_fVolumeMinPitch + (this->m_fVolumeMaxPitch - this->m_fVolumeMinPitch) * volume; + + switch (m_eSoundState) { + case ST_OFF: + StopLoopSound(); + TurnOffVehicleSoundEntities(); + m_fNextSoundState = level.time; + + if (driver.ent || m_bAutoPilot) { + m_eSoundState = ST_OFF_TRANS_IDLE; + } + break; + + case ST_OFF_TRANS_IDLE: + m_fNextSoundState = level.time; + m_eSoundState = ST_IDLE; + Sound(m_sSoundSet + "snd_on"); + LoopSound(m_sSoundSet + "snd_idle"); + break; + + case ST_IDLE_TRANS_OFF: + m_fNextSoundState = level.time; + m_eSoundState = ST_OFF; + Sound(m_sSoundSet + "snd_off"); + StopLoopSound(); + break; + + case ST_IDLE: + m_fNextSoundState = level.time; + + if (driver.ent || m_bAutoPilot) { + if (fabs(DotProduct(orientation[0], velocity)) > 10.0f) { + m_eSoundState = ST_IDLE_TRANS_RUN; + } + } else { + m_eSoundState = ST_IDLE_TRANS_OFF; + } + + LoopSound(m_sSoundSet + "snd_idle"); + + TurnOffVehicleSoundEntities(); + break; + + case ST_IDLE_TRANS_RUN: + m_fNextSoundState = level.time; + m_eSoundState = ST_RUN; + + Sound(m_sSoundSet + "snd_revup"); + LoopSound(m_sSoundSet + "snd_run", -1.0f, -1.0f, -1.0f, pitch); + break; + + case ST_RUN: + m_fNextSoundState = level.time; + + if (fabs(DotProduct(orientation[0], velocity)) < 10.0f) { + m_eSoundState = ST_RUN_TRANS_IDLE; + } + + TurnOnVehicleSoundEntities(); + LoopSound(m_sSoundSet + "snd_run", volume, -1.0f, -1.0f, pitch); + break; + + case ST_RUN_TRANS_IDLE: + m_fNextSoundState = level.time; + m_eSoundState = ST_IDLE; + + Sound(m_sSoundSet + "snd_revdown"); + LoopSound(m_sSoundSet + "snd_idle"); + break; + + default: + m_fNextSoundState = level.time; + m_eSoundState = ST_OFF; + break; + } +} + +/* +==================== +Vehicle::SetupVehicleSoundEntities +==================== +*/ +void Vehicle::SetupVehicleSoundEntities(void) +{ + int i; + Vector a; + Vector b; + Vector c; + Vector start; + + angles.AngleVectorsLeft(&a, &b, &c); + + // place the sound entities in the vehicle wheels + for (i = 0; i < MAX_CORNERS; i++) { + if (!m_pVehicleSoundEntities[i]) { + m_pVehicleSoundEntities[i] = new VehicleSoundEntity(this); + } + + start = origin + a * Corners[i][0] + b * Corners[i][1] + c * Corners[i][2]; + m_pVehicleSoundEntities[i]->setOrigin(start); + } +} + +/* +==================== +Vehicle::TurnOnVehicleSoundEntities +==================== +*/ +void Vehicle::TurnOnVehicleSoundEntities(void) +{ + for (int i = 0; i < MAX_CORNERS; i++) { + if (!m_pVehicleSoundEntities[i]) { + m_pVehicleSoundEntities[i] = new VehicleSoundEntity(this); + } + + m_pVehicleSoundEntities[i]->Start(); + } +} + +/* +==================== +Vehicle::TurnOffVehicleSoundEntities +==================== +*/ +void Vehicle::TurnOffVehicleSoundEntities(void) +{ + for (int i = 0; i < MAX_CORNERS; i++) { + if (!m_pVehicleSoundEntities[i]) { + m_pVehicleSoundEntities[i] = new VehicleSoundEntity(this); + } + + m_pVehicleSoundEntities[i]->Stop(); + } +} + +/* +==================== +Vehicle::RemoveVehicleSoundEntities +==================== +*/ +void Vehicle::RemoveVehicleSoundEntities(void) +{ + for (int i = 0; i < MAX_CORNERS; i++) { + if (!m_pVehicleSoundEntities[i]) { + continue; + } + + m_pVehicleSoundEntities[i]->PostEvent(EV_Remove, EV_VEHICLE); + } +} + +/* +==================== +Vehicle::KickSuspension +==================== +*/ +void Vehicle::KickSuspension(Vector vDirection, float fForce) +{ + VectorNormalizeFast(vDirection); + + m_fForwardForce += vDirection * orientation[1] * fForce; + m_fLeftForce += vDirection * orientation[0] * fForce; +} + +/* +==================== +Vehicle::EventDamage +==================== +*/ +void Vehicle::EventDamage(Event *ev) +{ + Entity *pEnt; + Vector vDirection; + float fForce; + int i; + + if (!IsDamagedBy(ev->GetEntity(3))) { + return; + } + + pEnt = ev->GetEntity(1); + if (pEnt && pEnt == driver.ent) { + return; + } + + Event *event = new Event(EV_Damage, ev->NumArgs()); + + vDirection = ev->GetVector(5); + fForce = ev->GetFloat(7); + KickSuspension(vDirection, fForce); + + for (i = 1; i <= ev->NumArgs(); i++) { + if (i == 7) { + event->AddFloat(0); + } else { + event->AddValue(ev->GetValue(i)); + } + } + + if (driver.ent && driver.ent->IsSubclassOfPlayer()) { + Player *player = static_cast(driver.ent.Pointer()); + Vector dir = ev->GetVector(1); + float dir_yaw; + float camera_yaw; + + if (player->camera) { + dir_yaw = dir.toYaw(); + camera_yaw = player->camera->angles[1]; + } else { + dir_yaw = dir.toYaw(); + camera_yaw = player->GetVAngles()[1]; + } + + player->damage_yaw = AngleSubtract(camera_yaw, dir_yaw) + 180.5; + } + + DamageEvent(event); + delete event; +} + +/* +==================== +Vehicle::FactorInOriginOffset +==================== +*/ +void Vehicle::FactorInOriginOffset(void) +{ + origin += m_vOriginOffset; + setOrigin(origin); +} + +/* +==================== +Vehicle::FactorOutOriginOffset +==================== +*/ +void Vehicle::FactorOutOriginOffset(void) +{ + origin -= m_vOriginOffset; + setOrigin(origin); +} + +/* +==================== +Vehicle::CalculateOriginOffset +==================== +*/ +void Vehicle::CalculateOriginOffset(void) +{ + int index; + Vector vTireAvg; + Vector vMissHit; + Vector temp; + int iNum = 0; + Vector acceleration; + Vector oldoffset; + + oldoffset = m_vOriginOffset; + m_vOriginOffset += m_vOriginOffset2; + m_vOriginOffset2 = vec_zero; + + for (index = 0; index < MAX_CORNERS; index++) { + if (m_bTireHit[index]) { + temp = m_vTireEnd[index]; + vTireAvg += origin - temp; + iNum++; + } else { + temp = Corners[index]; + vMissHit = temp; + } + } + + if (iNum == 3) { + temp = m_vNormalSum * (1.0f / m_iNumNormals); + ProjectPointOnPlane(acceleration, vMissHit, temp); + vTireAvg += acceleration; + } else if (iNum == 4) { + vTireAvg *= 0.25f; + MatrixTransformVector(m_vOriginCornerOffset, orientation, acceleration); + vTireAvg -= acceleration; + m_vOriginOffset2 += vTireAvg; + } + + m_vOriginOffset2 += vec_zero; + FactorInSkidOrigin(); + + Vector vTmp = real_acceleration - prev_acceleration; + + m_fDownForce = vTmp[2] * m_fZCoef; + m_fDownForce = Q_clamp_float(m_fDownForce, m_fZMin, m_fZMax); + + m_fUpForce = -m_vOriginOffset[2] * m_fBouncyCoef + m_fUpForce; + m_fUpForce *= m_fSpringyCoef; + m_vOriginOffset[2] += (m_fDownForce + m_fUpForce) * level.frametime * 12; + + if (m_vOriginOffset[2] < m_fZMin) { + m_vOriginOffset[2] = m_fZMin; + } + + m_vOriginOffset -= m_vOriginOffset2; + + if (!isfinite(m_vOriginOffset[0]) || !isfinite(m_vOriginOffset[1]) || !isfinite(m_vOriginOffset[2])) { + m_vOriginOffset = oldoffset; + } +} + +/* +==================== +Vehicle::UpdateTires +==================== +*/ +void Vehicle::UpdateTires(void) +{ + int index; + trace_t trace; + Vector a; + Vector b; + Vector c; + Vector vTmp; + Vector t_mins; + Vector t_maxs; + Vector start; + Vector end; + Vector boxoffset; + Entity *pSkippedEntities[MAX_SKIPPED_ENTITIES]; + int iContentsEntities[MAX_SKIPPED_ENTITIES]; + solid_t solidEntities[MAX_SKIPPED_ENTITIES]; + int iNumSkippedEntities; + int iNumSkipped = 0; + + t_mins = mins * 0.25f; + t_maxs = maxs * 0.25f; + + if (real_velocity.length() <= 0.5f && m_iLastTiresUpdate != -1 && m_iLastTiresUpdate + 1000 > level.inttime) { + return; + } + + m_iLastTiresUpdate = level.inttime; + + vTmp.y = angles.y + m_fSkidAngle; + AngleVectors(vTmp, a, b, c); + + // Temporary make slots non-solid for G_Trace + SetSlotsNonSolid(); + + do { + iNumSkippedEntities = 0; + + for (index = 0; index < MAX_CORNERS; index++) { + boxoffset = Corners[index]; + start = origin + a * boxoffset[0] + b * boxoffset[1] + c * boxoffset[2]; + end = start + Vector(0, 0, -400); + + trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_VEHICLE_TIRES, false, "Vehicle::PostThink Corners"); + + if (g_showvehiclemovedebug->integer) { + G_DebugLine(start, end, 1, 1, 1, 1); + G_DebugLine(start, trace.endpos, 1, 0, 0, 1); + } + + if (trace.ent && trace.ent->entity && trace.ent->entity->isSubclassOf(VehicleCollisionEntity)) { + // save the entity + pSkippedEntities[iNumSkipped] = trace.ent->entity; + iContentsEntities[iNumSkipped] = trace.ent->r.contents; + solidEntities[iNumSkipped] = trace.ent->solid; + iNumSkipped++; + + if (iNumSkipped >= MAX_SKIPPED_ENTITIES) { + gi.Error(ERR_DROP, "MAX_SKIPPED_ENTITIES hit in VehicleMove.\n"); + return; + } + + trace.ent->entity->setSolidType(SOLID_NOT); + iNumSkippedEntities++; + } + + if (trace.fraction == 1.0) { + m_bTireHit[index] = false; + } else { + m_vTireEnd[index] = trace.endpos; + m_bTireHit[index] = true; + } + } + } while (iNumSkippedEntities != 0); + + for (index = 0; index < iNumSkipped; index++) { + pSkippedEntities[index]->setSolidType(solidEntities[index]); + pSkippedEntities[index]->setContents(iContentsEntities[index]); + } + + // Turn slots back into a solid state + SetSlotsSolid(); +} + +/* +==================== +Vehicle::UpdateNormals +==================== +*/ +void Vehicle::UpdateNormals(void) +{ + Vector vDist1; + Vector vDist2; + Vector vCross; + Vector temp; + Vector pitch; + Vector i; + Vector j; + + if (real_velocity.length() <= 0.5 && m_iLastTiresUpdate != -1 && m_iLastTiresUpdate + 1000 > level.inttime) { + return; + } + + angles.AngleVectorsLeft(&i, &j, NULL); + + j = vec_zero - j; + m_vNormalSum = vec_zero; + m_iNumNormals = 0; + + if (m_bTireHit[0] && m_bTireHit[1] && m_bTireHit[2]) { + vDist1 = m_vTireEnd[1] - m_vTireEnd[0]; + vDist2 = m_vTireEnd[1] - m_vTireEnd[2]; + + CrossProduct(vDist1, vDist2, vCross); + vCross.normalize(); + m_vNormalSum += vCross; + + m_iNumNormals++; + } + + if (m_bTireHit[1] && m_bTireHit[2] && m_bTireHit[3]) { + vDist1 = m_vTireEnd[2] - m_vTireEnd[1]; + vDist2 = m_vTireEnd[2] - m_vTireEnd[3]; + + CrossProduct(vDist1, vDist2, vCross); + vCross.normalize(); + m_vNormalSum += vCross; + + m_iNumNormals++; + } + + if (m_bTireHit[2] && m_bTireHit[3] && m_bTireHit[0]) { + vDist1 = m_vTireEnd[3] - m_vTireEnd[0]; + vDist2 = m_vTireEnd[3] - m_vTireEnd[2]; + + CrossProduct(vDist1, vDist2, vCross); + vCross.normalize(); + m_vNormalSum += vCross; + + m_iNumNormals++; + } + + if (m_bTireHit[3] && m_bTireHit[0] && m_bTireHit[1]) { + vDist1 = m_vTireEnd[0] - m_vTireEnd[3]; + vDist2 = m_vTireEnd[0] - m_vTireEnd[1]; + + CrossProduct(vDist1, vDist2, vCross); + vCross.normalize(); + m_vNormalSum += vCross; + + m_iNumNormals++; + } + + if (m_iNumNormals > 1) { + float x, z; + + temp = m_vNormalSum / m_iNumNormals; + i = temp.CrossProduct(temp, j); + + pitch = i; + x = pitch.toPitch(); + + temp = m_vNormalSum / m_iNumNormals; + pitch = temp.CrossProduct(temp, i); + z = pitch.toPitch(); + + angles[0] = x; + angles[2] = z; + } +} + +/* +==================== +Vehicle::UpdateBones +==================== +*/ +void Vehicle::UpdateBones(void) +{ + float fNewTurnAngle = AngleNormalize180(turnangle - m_fSkidAngle); + fNewTurnAngle = Q_clamp_float(fNewTurnAngle, -maxturnrate, maxturnrate); + + SetControllerAngles(0, Vector(0, fNewTurnAngle, 0)); + SetControllerAngles(1, Vector(0, fNewTurnAngle, 0)); +} + +/* +==================== +Vehicle::UpdateShaderOffset +==================== +*/ +void Vehicle::UpdateShaderOffset(void) +{ + m_fShaderOffset -= real_velocity * orientation[0] / 4 * level.frametime; + edict->s.shader_time = m_fShaderOffset; +} + +/* +==================== +Vehicle::UpdateDriverSlot +==================== +*/ +void Vehicle::UpdateDriverSlot(int iSlot) +{ + orientation_t orient; + + if (!(driver.flags & SLOT_BUSY) || !driver.ent) { + return; + } + + if (driver.boneindex != -1) { + GetTag(driver.boneindex, &orient); + if (driver.ent->IsSubclassOfActor()) { + driver.ent->setOriginEvent(orient.origin); + } else { + driver.ent->setOrigin(orient.origin); + } + + if (drivable) { + driver.ent->avelocity = avelocity; + driver.ent->velocity = velocity; + driver.ent->setAngles(angles); + } + } else { + Vector forward = orientation[0]; + Vector left = orientation[1]; + Vector up = orientation[2]; + + if (driver.ent->IsSubclassOfActor()) { + driver.ent->setOriginEvent( + origin + forward * driveroffset[0] + left * driveroffset[1] + up * driveroffset[2] + ); + } else { + driver.ent->setOrigin(origin + forward * driveroffset[0] + left * driveroffset[1] + up * driveroffset[2]); + } + + if (drivable) { + driver.ent->avelocity = avelocity; + driver.ent->velocity = velocity; + driver.ent->setAngles(angles); + } + } +} + +/* +==================== +Vehicle::UpdatePassengerSlot +==================== +*/ +void Vehicle::UpdatePassengerSlot(int iSlot) +{ + orientation_t orient; + + if (!(Passengers[iSlot].flags & SLOT_BUSY) || !Passengers[iSlot].ent) { + return; + } + + if (Passengers[iSlot].boneindex != -1) { + GetTag(Passengers[iSlot].boneindex, &orient); + if (Passengers[iSlot].ent->IsSubclassOfActor()) { + Passengers[iSlot].ent->setOriginEvent(orient.origin); + } else { + Passengers[iSlot].ent->setOrigin(orient.origin); + } + + Passengers[iSlot].ent->avelocity = avelocity; + Passengers[iSlot].ent->velocity = velocity; + + if (!Passengers[iSlot].ent->IsSubclassOfActor() || !((Actor *)Passengers[iSlot].ent.Pointer())->m_Enemy) { + Vector newAngles; + + MatrixToEulerAngles(orient.axis, newAngles); + Passengers[iSlot].ent->setAngles(newAngles); + } + } else { + if (Passengers[iSlot].ent->IsSubclassOfActor()) { + Passengers[iSlot].ent->setOriginEvent(origin); + } else { + Passengers[iSlot].ent->setOrigin(origin); + } + + Passengers[iSlot].ent->avelocity = avelocity; + Passengers[iSlot].ent->velocity = velocity; + + if (!Passengers[iSlot].ent->IsSubclassOfActor() || ((Actor *)Passengers[iSlot].ent.Pointer())->m_Enemy) { + Passengers[iSlot].ent->setAngles(angles); + } + } +} + +/* +==================== +Vehicle::UpdateTurretSlot +==================== +*/ +void Vehicle::UpdateTurretSlot(int iSlot) +{ + orientation_t orient; + + if (!(Turrets[iSlot].flags & SLOT_BUSY) || !Turrets[iSlot].ent) { + return; + } + + if (Turrets[iSlot].boneindex != -1) { + GetTag(Turrets[iSlot].boneindex, &orient); + if (Turrets[iSlot].ent->IsSubclassOfActor()) { + Turrets[iSlot].ent->setOriginEvent(orient.origin); + } else { + Turrets[iSlot].ent->setOrigin(orient.origin); + } + + Turrets[iSlot].ent->avelocity = avelocity; + Turrets[iSlot].ent->velocity = velocity; + + if (Turrets[iSlot].ent->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *vtg = static_cast(Turrets[iSlot].ent.Pointer()); + vtg->SetBaseOrientation(orient.axis, NULL); + } + } else { + Vector forward = orientation[0]; + Vector left = orientation[1]; + Vector up = orientation[2]; + + if (Turrets[iSlot].ent->IsSubclassOfActor()) { + Turrets[iSlot].ent->setOriginEvent(origin); + } else { + Turrets[iSlot].ent->setOrigin(origin); + } + + Turrets[iSlot].ent->avelocity = avelocity; + Turrets[iSlot].ent->velocity = velocity; + + if (Turrets[iSlot].ent->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *vtg = static_cast(Turrets[iSlot].ent.Pointer()); + vtg->SetBaseOrientation(this->orientation, NULL); + } + } +} + +/* +==================== +Vehicle::EventStopAtEnd +==================== +*/ +void Vehicle::EventStopAtEnd(Event *ev) +{ + if (!m_pCurPath) { + ScriptError("Tried to Stop at end of path on a vehicle who is not driving a path!"); + } + + m_fStopStartDistance = GetPathPosition(m_pCurPath, m_iCurNode); + m_fStopStartSpeed = moveimpulse; + m_fStopEndDistance = *m_pCurPath->GetByNode(m_pCurPath->m_iPoints, NULL); + m_bStopEnabled = true; +} + +/* +==================== +Vehicle::GetPathPosition +==================== +*/ +float Vehicle::GetPathPosition(cVehicleSpline *pPath, int iNode) +{ + float *vTmp; + vec3_t vPrev; + vec3_t vCur; + vec3_t vTotal; + Vector vDelta; + float fTotal; + float fCoef; + + vTmp = pPath->GetByNode(iNode, NULL); + VectorCopy(vTmp + 1, vCur); + + if (g_showvehiclemovedebug->integer) { + G_DebugString(vCur, 3.0f, 1.0f, 1.0f, 1.0f, "%f", vTmp[0]); + } + + vTmp = pPath->GetByNode(iNode - 1, NULL); + VectorCopy(vTmp + 1, vPrev); + + if (g_showvehiclemovedebug->integer) { + G_DebugString(vPrev, 3.0f, 1.0f, 1.0f, 1.0f, "%f", vTmp[0]); + } + + VectorSubtract(vCur, vPrev, vTotal); + fTotal = VectorLength(vTotal); + m_vIdealDir = vTotal; + VectorNormalize(m_vIdealDir); + angles.AngleVectorsLeft(&vDelta, NULL, NULL); + + fCoef = ProjectLineOnPlane(vDelta, DotProduct(vDelta, origin), vPrev, vCur, NULL); + + if (g_showvehiclemovedebug->integer) { + G_DebugBBox(vPrev, Vector(-32, -32, -32), Vector(32, 32, 32), 0, 1, 1, 1); + G_DebugBBox(vCur, Vector(-32, -32, -32), Vector(32, 32, 32), 1, 1, 0, 1); + G_DebugArrow(vCur, m_vIdealDir * -1.0, (1.0 - fCoef) * fTotal, 0, 1, 0, 1); + G_DebugArrow(vPrev, m_vIdealDir, fCoef * fTotal, 0, 0, 1, 1); + } + + return *pPath->GetByNode(iNode - (1.0 - fCoef), NULL); +} + +/* +==================== +Vehicle::EventSkidding +==================== +*/ +void Vehicle::EventSkidding(Event *ev) +{ + if (ev->NumArgs() == 1) { + m_bEnableSkidding = ev->GetInteger(1); + } else { + m_bEnableSkidding = true; + } + + ProcessEvent(EV_Vehicle_ContinueSkidding); +} + +/* +==================== +Vehicle::UpdateSkidAngle +==================== +*/ +void Vehicle::UpdateSkidAngle(void) +{ + if (m_bEnableSkidding) { + if (g_showvehiclemovedebug && g_showvehiclemovedebug->integer) { + Com_Printf("Skidding!\n"); + } + + m_fSkidLeftForce += velocity.length() / 150.0f * turnangle; + m_fSkidRightForce += -m_fSkidAngle * 0.2; + m_fSkidRightForce *= 0.3f; + m_fSkidAngle = m_fSkidAngle + (m_fSkidLeftForce + m_fSkidRightForce) * 22.0f * level.frametime; + m_vSkidOrigin[0] = -fabs(m_fSkidAngle); + } else { + m_fSkidAngle = 0; + } +} + +/* +==================== +Vehicle::FactorInSkidOrigin +==================== +*/ +void Vehicle::FactorInSkidOrigin(void) +{ + Vector vNewOrigin; + + vNewOrigin[0] = orientation[0][0] * m_vSkidOrigin[0] + orientation[1][0] * m_vSkidOrigin[1] + + orientation[2][0] * m_vSkidOrigin[2]; + vNewOrigin[1] = orientation[0][1] * m_vSkidOrigin[0] + orientation[1][1] * m_vSkidOrigin[1] + + orientation[2][1] * m_vSkidOrigin[2]; + vNewOrigin[2] = orientation[0][2] * m_vSkidOrigin[0] + orientation[1][2] * m_vSkidOrigin[1] + + orientation[2][2] * m_vSkidOrigin[2]; + + m_vOriginOffset2 += vNewOrigin; +} + +/* +==================== +Vehicle::EventContinueSkidding +==================== +*/ +void Vehicle::EventContinueSkidding(Event *ev) +{ + if (m_bEnableSkidding) { + if (HasAnim("skidding")) { + NewAnim("skidding", EV_Vehicle_ContinueSkidding, 7, 0.000001f); + } else { + assert(!"Vehicle without skidding animation."); + } + } else { + if (HasAnim("idle")) { + NewAnim("idle", 0, 7, 0.000001f); + } else { + assert(!"Vehicle without idle animation."); + } + } +} + +/* +==================== +Vehicle::FactorInAnglesOffset +==================== +*/ +void Vehicle::FactorInAnglesOffset(Vector *vAddedAngles) +{ + (*vAddedAngles) = m_vAnglesOffset; + vAddedAngles->y += m_fSkidAngle; +} + +/* +==================== +Vehicle::FactorOutAnglesOffset +==================== +*/ +void Vehicle::FactorOutAnglesOffset(void) {} + +/* +==================== +Vehicle::CalculateAnglesOffset +==================== +*/ +void Vehicle::CalculateAnglesOffset(Vector acceleration) +{ + if (level.inttime <= 1200) { + // leave some time before allowing to shake + // so all tanks spawn peacefully in the level + return; + } + + m_fForwardForce += DotProduct(orientation[0], acceleration) * m_fYawCoef; + m_fBackForce = -m_vAnglesOffset[0] * m_fBouncyCoef + m_fBackForce; + m_fBackForce *= m_fSpringyCoef; + + m_vAnglesOffset[0] += m_fForwardForce + m_fBackForce * 12.0 * level.frametime; + m_vAnglesOffset[0] = Q_clamp_float(m_vAnglesOffset[0], m_fYawMin, m_fYawMax); + + m_fForwardForce = 0; + m_fLeftForce += acceleration * orientation[1] * m_fRollCoef; + m_fRightForce = -m_vAnglesOffset[2] * m_fBouncyCoef + m_fRightForce; + m_fRightForce *= m_fSpringyCoef; + + m_vAnglesOffset[2] += 12.0 * (m_fLeftForce + m_fRightForce) * level.frametime; + m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fRollMin, m_fRollMax); + + m_fLeftForce = 0; +} + +/* +==================== +Vehicle::CalculateAnimationData +==================== +*/ +void Vehicle::CalculateAnimationData(Vector vAngles, Vector vOrigin) +{ + float fLeft = fEpsilon(); + float fRight = fEpsilon(); + float fForward = fEpsilon(); + float fBack = fEpsilon(); + float fLow = fEpsilon(); + float fHigh = fEpsilon(); + + if (vAngles[0] < 0.0) { + fBack = vAngles[0] / m_fYawMin; + } else if (vAngles[0] > 0.0) { + fForward = vAngles[0] / m_fYawMax; + } + + if (vAngles[2] < 0.0) { + fRight = vAngles[2] / m_fRollMin; + } else if (vAngles[2] > 0.0) { + fLeft = vAngles[2] / m_fRollMax; + } + + if (vOrigin[2] < 0.0) { + fBack = vOrigin[2] / m_fZMin; + } else if (vOrigin[2] > 0.0) { + fForward = vOrigin[2] / m_fZMax; + } + + if (!m_bAnimMove) { + NewAnim("idle", NULL, 0, 1.0); + NewAnim("lean_left", NULL, 3, fLeft); + NewAnim("lean_right", NULL, 4, fRight); + NewAnim("lean_forward", NULL, 1, fForward); + NewAnim("lean_back", NULL, 2, fBack); + NewAnim("high", NULL, 6, fLow); + NewAnim("low", NULL, 5, fHigh); + } +} + +/* +==================== +Vehicle::EventVehicleAnim +==================== +*/ +void Vehicle::EventVehicleAnim(Event *ev) +{ + float weight; + + if (ev->NumArgs() > 1) { + weight = ev->GetFloat(2); + } else { + weight = 1.0f; + } + + NewAnim(ev->GetString(1), EV_Vehicle_VehicleAnimDone, 8, weight); +} + +/* +==================== +Vehicle::EventVehicleAnimDone +==================== +*/ +void Vehicle::EventVehicleAnimDone(Event *ev) +{ + Unregister(STRING_VEHICLEANIMDONE); +} + +void Vehicle::EventVehicleMoveAnim(Event *ev) +{ + str anim_name; + + anim_name = ev->GetString(1); + if (!HasAnim(anim_name)) { + return; + } + + m_bAnimMove = true; + + StopAnimating(0); + StopAnimating(3); + StopAnimating(4); + StopAnimating(1); + StopAnimating(2); + StopAnimating(6); + StopAnimating(5); + StopAnimating(8); + + NewAnim(anim_name, EV_Vehicle_VehicleMoveAnimDone); +} + +void Vehicle::EventVehicleMoveAnimDone(Event *ev) +{ + Unregister(STRING_ANIMDONE); + moveimpulse = 0; + turnimpulse = 0; + m_bAnimMove = false; +} + +void Vehicle::EventDamageSounds(Event *ev) +{ + if (ev->NumArgs() == 1) { + m_bDamageSounds = ev->GetInteger(1); + } else { + m_bDamageSounds = true; + } +} + +void Vehicle::EventRunSounds(Event *ev) +{ + if (ev->NumArgs() == 1) { + m_bRunSounds = ev->GetInteger(1); + } else { + m_bRunSounds = true; + } +} + +void Vehicle::Remove(Event *ev) +{ + int i; + + for (i = 0; i < MAX_TURRETS; i++) { + Entity *pTurret = Turrets[i].ent; + if (!pTurret) { + continue; + } + + pTurret->PostEvent(EV_Remove, 0); + Turrets[i].ent = NULL; + } + + Entity::Remove(ev); +} + +/* +==================== +Vehicle::IsDamagedBy + +Returns whether or not the vehicle is damaged by the specified entity. +==================== +*/ +bool Vehicle::IsDamagedBy(Entity *ent) +{ + int i; + + if (FindDriverSlotByEntity(ent) != -1) { + return false; + } + + if (FindPassengerSlotByEntity(ent) != -1) { + return false; + } + + if (FindTurretSlotByEntity(ent) != -1) { + return false; + } + + for (i = 0; i < MAX_TURRETS; i++) { + TurretGun *pTurret; + + if (!Turrets[i].ent) { + continue; + } + + pTurret = static_cast(Turrets[i].ent.Pointer()); + if (pTurret->IsSubclassOfTurretGun() && pTurret->owner == ent) { + return false; + } + } + + return true; +} + +/* +==================== +Vehicle::DriverAdded +==================== +*/ +void Vehicle::DriverAdded() {} + +void Vehicle::EventSetMaxUseAngle(Event *ev) +{ + m_fMaxUseAngle = ev->GetFloat(1); +} + +void Vehicle::EventCanUse(Event *ev) +{ + Entity *entity = ev->GetEntity(1); + + if (driver.ent || !m_fMaxUseAngle || !Turrets[0].ent) { + ev->AddInteger(1); + return; + } + + if (!entity) { + ev->AddInteger(0); + return; + } + + Vector vForward; + Vector vDir; + + AngleVectors(Turrets[0].ent->angles, vForward, NULL, NULL); + + vDir = Turrets[0].ent->origin - entity->origin; + VectorNormalize(vDir); + + if (fabs(GetAngleBetweenVectors2D(vForward, vDir)) > m_fMaxUseAngle) { + ev->AddInteger(false); + } else { + ev->AddInteger(true); + } +} + +int Vehicle::GetProjectileHitsRemaining() const { + return m_iProjectileHitsRemaining; +} + +/* +==================== +Vehicle::Archive +==================== +*/ +void Vehicle::Archive(Archiver& arc) +{ + VehicleBase::Archive(arc); + + arc.ArchiveFloat(&maxturnrate); + arc.ArchiveFloat(¤tspeed); + arc.ArchiveFloat(&turnangle); + arc.ArchiveFloat(&turnimpulse); + arc.ArchiveFloat(&moveimpulse); + arc.ArchiveFloat(&jumpimpulse); + arc.ArchiveFloat(&speed); + arc.ArchiveFloat(&conesize); + arc.ArchiveFloat(&maxtracedist); + arc.ArchiveString(&weaponName); + arc.ArchiveString(&vehicleName); + arc.ArchiveVector(&last_origin); + arc.ArchiveVector(&seatangles); + arc.ArchiveVector(&seatoffset); + arc.ArchiveVector(&driveroffset); + + arc.ArchiveVector(&Corners[0]); + arc.ArchiveVector(&Corners[1]); + arc.ArchiveVector(&Corners[2]); + arc.ArchiveVector(&Corners[3]); + + arc.ArchiveBoolean(&drivable); + arc.ArchiveBoolean(&pathDrivable); // Added in 2.30 + arc.ArchiveBoolean(&locked); + arc.ArchiveBoolean(&hasweapon); + arc.ArchiveBoolean(&showweapon); + arc.ArchiveBoolean(&steerinplace); + arc.ArchiveBoolean(&jumpable); + + arc.ArchiveBoolean(&m_bMovementLocked); + arc.ArchiveBoolean(&m_bAnimMove); // Added in 2.0 + arc.ArchiveBoolean(&m_bDamageSounds); // Added in 2.0 + arc.ArchiveBoolean(&m_bRunSounds); // Added in 2.0 + arc.ArchiveInteger(&m_iProjectileHitsRemaining); // Added in 2.30 + + driver.Archive(arc); + lastdriver.Archive(arc); + + for (int i = 0; i < MAX_PASSENGERS; i++) { + Passengers[i].Archive(arc); + } + + for (int i = 0; i < MAX_TURRETS; i++) { + Turrets[i].Archive(arc); + } + + arc.ArchiveInteger(&numPassengers); + arc.ArchiveInteger(&numTurrets); + arc.ArchiveInteger(&moveresult); + arc.ArchiveInteger(&isBlocked); + arc.ArchiveInteger(&m_iFrameCtr); + arc.ArchiveInteger(&m_iGear); + arc.ArchiveInteger(&m_iRPM); + arc.ArchiveInteger(&m_iNextPathStartNode); + + if (!arc.Saving()) { + m_iLastTiresUpdate = -1; + + int tempInt; + arc.ArchiveInteger(&tempInt); + + if (tempInt) { + m_pAlternatePath = new cVehicleSpline; + } else { + m_pAlternatePath = NULL; + } + } else { + int tempInt = m_pAlternatePath != NULL; + arc.ArchiveInteger(&tempInt); + } + + if (m_pAlternatePath) { + m_pAlternatePath->Archive(arc); + } + + arc.ArchiveInteger(&m_iAlternateNode); + + if (!arc.Saving()) { + int tempInt; + arc.ArchiveInteger(&tempInt); + + if (tempInt) { + m_pCurPath = new cVehicleSpline; + } else { + m_pCurPath = NULL; + } + } else { + int tempInt = m_pCurPath != NULL; + arc.ArchiveInteger(&tempInt); + } + + if (m_pCurPath) { + m_pCurPath->Archive(arc); + } + + arc.ArchiveInteger(&m_iCurNode); + + if (!arc.Saving()) { + int tempInt; + arc.ArchiveInteger(&tempInt); + + if (tempInt) { + m_pNextPath = new cVehicleSpline; + } else { + m_pNextPath = NULL; + } + } else { + int tempInt = m_pNextPath != NULL; + arc.ArchiveInteger(&tempInt); + } + + if (m_pNextPath) { + m_pNextPath->Archive(arc); + } + + arc.ArchiveFloat(&maxturnrate); + arc.ArchiveFloat(¤tspeed); + arc.ArchiveFloat(&turnangle); + arc.ArchiveFloat(&turnimpulse); + arc.ArchiveFloat(&moveimpulse); + arc.ArchiveFloat(&prev_moveimpulse); + arc.ArchiveFloat(&jumpimpulse); + arc.ArchiveFloat(&speed); + arc.ArchiveFloat(&conesize); + arc.ArchiveFloat(&maxtracedist); + arc.ArchiveFloat(&airspeed); + arc.ArchiveFloat(&m_fGearRatio[0]); + arc.ArchiveFloat(&m_fGearRatio[1]); + arc.ArchiveFloat(&m_fGearRatio[2]); + arc.ArchiveFloat(&m_fGearRatio[3]); + arc.ArchiveFloat(&m_fGearRatio[4]); + arc.ArchiveFloat(&m_fGearRatio[5]); + arc.ArchiveFloat(&m_fMass); + arc.ArchiveFloat(&m_fFrontMass); + arc.ArchiveFloat(&m_fBackMass); + arc.ArchiveFloat(&m_fWheelBase); + arc.ArchiveFloat(&m_fWheelFrontLoad); + arc.ArchiveFloat(&m_fWheelFrontInnerLoad); + arc.ArchiveFloat(&m_fWheelFrontOutterLoad); + arc.ArchiveFloat(&m_fWheelFrontDist); + arc.ArchiveFloat(&m_fWheelFrontSuspension); + arc.ArchiveFloat(&m_fWheelBackLoad); + arc.ArchiveFloat(&m_fWheelBackInnerLoad); + arc.ArchiveFloat(&m_fWheelBackOutterLoad); + arc.ArchiveFloat(&m_fWheelBackDist); + arc.ArchiveFloat(&m_fWheelBackSuspension); + arc.ArchiveFloat(&m_fCGHeight); + arc.ArchiveFloat(&m_fBankAngle); + arc.ArchiveFloat(&m_fTread); + arc.ArchiveFloat(&m_fTrackWidth); + arc.ArchiveFloat(&m_fTireFriction); + arc.ArchiveFloat(&m_fDrag); + arc.ArchiveFloat(&m_fTireRadius); + arc.ArchiveFloat(&m_fFrontBrakes); + arc.ArchiveFloat(&m_fBackBrakes); + arc.ArchiveFloat(&m_fRollingResistance); + arc.ArchiveFloat(&m_fTireRotationalSpeed); + arc.ArchiveFloat(&m_fFrontBrakingForce); + arc.ArchiveFloat(&m_fBackBrakingForce); + arc.ArchiveFloat(&m_fBrakingPerformance); + arc.ArchiveFloat(&m_fLastTurn); + arc.ArchiveFloat(&m_fTangForce); + arc.ArchiveFloat(&m_fInertia); + arc.ArchiveFloat(&m_fDifferentialRatio); + arc.ArchiveFloat(&m_fGearEfficiency); + arc.ArchiveFloat(&m_fMaxTraction); + arc.ArchiveFloat(&m_fTractionForce); + arc.ArchiveFloat(&m_fAccelerator); + arc.ArchiveFloat(&m_fTorque); + arc.ArchiveFloat(&m_fDownForce); + arc.ArchiveFloat(&m_fUpForce); + arc.ArchiveFloat(&m_fLeftForce); + arc.ArchiveFloat(&m_fRightForce); + arc.ArchiveFloat(&m_fForwardForce); + arc.ArchiveFloat(&m_fBackForce); + arc.ArchiveFloat(&m_fBouncyCoef); + arc.ArchiveFloat(&m_fSpringyCoef); + arc.ArchiveFloat(&m_fYawMin); + arc.ArchiveFloat(&m_fYawMax); + arc.ArchiveFloat(&m_fRollMin); + arc.ArchiveFloat(&m_fRollMax); + arc.ArchiveFloat(&m_fZMin); + arc.ArchiveFloat(&m_fZMax); + arc.ArchiveFloat(&m_fYawCoef); + arc.ArchiveFloat(&m_fRollCoef); + arc.ArchiveFloat(&m_fZCoef); + arc.ArchiveFloat(&m_fShaderOffset); + arc.ArchiveFloat(&m_fSoundMinSpeed); + arc.ArchiveFloat(&m_fSoundMinPitch); + arc.ArchiveFloat(&m_fSoundMaxSpeed); + arc.ArchiveFloat(&m_fSoundMaxPitch); + arc.ArchiveFloat(&m_fVolumeMinSpeed); + arc.ArchiveFloat(&m_fVolumeMinPitch); + arc.ArchiveFloat(&m_fVolumeMaxSpeed); + arc.ArchiveFloat(&m_fVolumeMaxPitch); + arc.ArchiveFloat(&m_fStopStartDistance); + arc.ArchiveFloat(&m_fStopStartSpeed); + arc.ArchiveFloat(&m_fStopEndDistance); + arc.ArchiveFloat(&m_fSkidAngle); + arc.ArchiveFloat(&m_fSkidLeftForce); + arc.ArchiveFloat(&m_fSkidRightForce); + arc.ArchiveString(&weaponName); + arc.ArchiveString(&m_sAnimationSet); + arc.ArchiveString(&m_sSoundSet); + arc.ArchiveString(&m_sExplosionModel); + arc.ArchiveVector(&last_origin); + arc.ArchiveVector(&seatangles); + arc.ArchiveVector(&driveroffset); + arc.ArchiveVector(&Corners[0]); + arc.ArchiveVector(&Corners[1]); + arc.ArchiveVector(&Corners[2]); + arc.ArchiveVector(&Corners[3]); + arc.ArchiveVector(&v_angle); + arc.ArchiveVector(&yaw_forward); + arc.ArchiveVector(&yaw_left); + arc.ArchiveVector(&ground_normal); + arc.ArchiveVector(&base_angles); + arc.ArchiveVector(&prev_velocity); + arc.ArchiveVector(&real_velocity); + arc.ArchiveVector(&prev_origin); + arc.ArchiveVector(&real_acceleration); + arc.ArchiveVector(&prev_acceleration); + arc.ArchiveVector(&m_vOldMins); + arc.ArchiveVector(&m_vOldMaxs); + arc.ArchiveVector(&m_vCG); + arc.ArchiveVector(&m_vAngularAcceleration); + arc.ArchiveVector(&m_vAngularVelocity); + arc.ArchiveVector(&m_vAngles); + arc.ArchiveVector(&m_vFrontNormal); + arc.ArchiveVector(&m_vBackNormal); + arc.ArchiveVector(&m_vFrontAngles); + arc.ArchiveVector(&m_vBackAngles); + arc.ArchiveVector(&m_vBaseNormal); + arc.ArchiveVector(&m_vBaseAngles); + arc.ArchiveVector(&m_vPrevNormal); + arc.ArchiveVector(&m_vResistance); + arc.ArchiveVector(&m_vWheelForce); + arc.ArchiveVector(&m_vTangForce); + arc.ArchiveVector(&m_vForce); + arc.ArchiveVector(&m_vAcceleration); + arc.ArchiveVector(&m_vOriginOffset); + arc.ArchiveVector(&m_vOriginOffset2); + arc.ArchiveVector(&m_vOriginCornerOffset); + arc.ArchiveVector(&m_vAnglesOffset); + arc.ArchiveVector(&m_vSaveAngles); + arc.ArchiveVector(&m_vSkidOrigin); + arc.ArchiveBoolean(&drivable); + arc.ArchiveBoolean(&locked); + arc.ArchiveBoolean(&hasweapon); + arc.ArchiveBoolean(&showweapon); + arc.ArchiveBoolean(&steerinplace); + arc.ArchiveBoolean(&jumpable); + arc.ArchiveBoolean(&m_bWheelSpinning); + arc.ArchiveBoolean(&m_bIsSkidding); + arc.ArchiveBoolean(&m_bIsBraking); + arc.ArchiveBoolean(&m_bBackSlipping); + arc.ArchiveBoolean(&m_bFrontSlipping); + arc.ArchiveBoolean(&m_bAutomatic); + arc.ArchiveBoolean(&m_bThinkCalled); + arc.ArchiveBoolean(&m_bRemoveOnDeath); + arc.ArchiveBoolean(&m_bStopEnabled); + arc.ArchiveBoolean(&m_bEnableSkidding); + + arc.ArchiveVec3(vs.origin); + arc.ArchiveVec3(vs.velocity); + arc.ArchiveInteger(&vs.groundEntityNum); + arc.ArchiveBoolean(&vs.walking); + arc.ArchiveBoolean(&vs.groundPlane); + G_ArchiveTrace(arc, &vs.groundTrace); + arc.ArchiveInteger(&vs.entityNum); + arc.ArchiveVec2(vs.desired_dir); + arc.ArchiveBoolean(&vs.hit_obstacle); + arc.ArchiveVec3(vs.hit_origin); + arc.ArchiveVec3(vs.obstacle_normal); + arc.ArchiveBoolean(&vs.useGravity); + + if (!arc.Saving()) { + m_sMoveGrid = new cMoveGrid(3, 3, 1); + } + + m_sMoveGrid->Archive(arc); + + arc.ArchiveFloat(&m_fIdealSpeed); + arc.ArchiveFloat(&m_fMaxSpeed); // Added in 2.30 + arc.ArchiveBool(&m_bBounceBackwards); // Added in 2.30 + arc.ArchiveVector(&m_vIdealPosition); + arc.ArchiveVector(&m_vIdealDir); + arc.ArchiveFloat(&m_fIdealAccel); + arc.ArchiveFloat(&m_fIdealDistance); + arc.ArchiveFloat(&m_fLookAhead); + arc.ArchiveBool(&m_bAutoPilot); + arc.ArchiveSafePointer(&m_pCollisionEntity); + ArchiveEnum(m_eSoundState, SOUND_STATE); + arc.ArchiveFloat(&m_fNextSoundState); + arc.ArchiveSafePointer(&m_pVehicleSoundEntities[0]); + arc.ArchiveSafePointer(&m_pVehicleSoundEntities[1]); + arc.ArchiveSafePointer(&m_pVehicleSoundEntities[2]); + arc.ArchiveSafePointer(&m_pVehicleSoundEntities[3]); + + // Added in 2.30 + arc.ArchiveFloat(&m_fMaxUseAngle); + arc.ArchiveBool(&m_bBounceStayFullSpeed); +} + +/* +==================== +Vehicle::GetSoundSet +==================== +*/ +str Vehicle::GetSoundSet(void) +{ + return m_sSoundSet; +} + +/* +==================== +Vehicle::getName +==================== +*/ +const str& Vehicle::getName() const +{ + return vehicleName; +} + +/* +==================== +Vehicle::isLocked +==================== +*/ +qboolean Vehicle::isLocked(void) +{ + return locked; +} + +/* +==================== +Vehicle::Lock +==================== +*/ +void Vehicle::Lock(void) +{ + locked = true; +} + +/* +==================== +Vehicle::UnLock +==================== +*/ +void Vehicle::UnLock(void) +{ + locked = false; } /* @@ -6575,19 +6886,15 @@ void Vehicle::UnLock Vehicle::GetCollisionEntity ==================== */ -VehicleCollisionEntity *Vehicle::GetCollisionEntity - ( - void - ) +VehicleCollisionEntity *Vehicle::GetCollisionEntity(void) { - return m_pCollisionEntity; + return m_pCollisionEntity; } -CLASS_DECLARATION( Vehicle, DrivableVehicle, "script_drivablevehicle" ) -{ - { &EV_Damage, &Entity::DamageEvent }, - { &EV_Killed, &DrivableVehicle::Killed }, - { NULL, NULL } +CLASS_DECLARATION(Vehicle, DrivableVehicle, "script_drivablevehicle") { + {&EV_Damage, &Entity::DamageEvent }, + {&EV_Killed, &DrivableVehicle::Killed}, + {NULL, NULL } }; /* @@ -6597,15 +6904,11 @@ DrivableVehicle::DrivableVehicle */ DrivableVehicle::DrivableVehicle() { - if( LoadingSavegame ) - { - // Archive function will setup all necessary data - return; - } + AddWaitTill(STRING_DEATH); - drivable = true; - flags |= FL_POSTTHINK | FL_THINK; - setMoveType( MOVETYPE_VEHICLE ); + drivable = true; + setMoveType(MOVETYPE_VEHICLE); + flags |= FL_POSTTHINK | FL_THINK; } /* @@ -6613,105 +6916,118 @@ DrivableVehicle::DrivableVehicle() DrivableVehicle::Killed ==================== */ -void DrivableVehicle::Killed - ( - Event *ev - ) +void DrivableVehicle::Killed(Event *ev) { - Entity * ent; - Entity * attacker; - Vector dir; - Event * event; - const char * name; - VehicleBase *last; + Entity *ent; + Entity *attacker; + Vector dir; + Event *event; + const char *name; + VehicleBase *last; + int i; - takedamage = DAMAGE_NO; - setSolidType( SOLID_NOT ); - hideModel(); + deadflag = DEAD_DEAD; + if (!m_bRemoveOnDeath) { + Unregister(STRING_DEATH); + return; + } - attacker = ev->GetEntity( 1 ); + takedamage = DAMAGE_NO; + setSolidType(SOLID_NOT); + hideModel(); - // - // kill the driver.ent - // - if( driver.ent ) - { - Vector dir; - SentientPtr sent; - Event * event; + attacker = ev->GetEntity(1); - velocity = vec_zero; - sent = ( Sentient * )driver.ent.Pointer(); - event = new Event( EV_Use ); - event->AddEntity( sent ); - ProcessEvent( event ); - dir = sent->origin - origin; - dir[ 2 ] += 64; - dir.normalize(); - sent->Damage( this, this, sent->health * 2, origin, dir, vec_zero, 50, 0, MOD_VEHICLE ); - } + // + // kill the driver.ent + // + if (driver.ent) { + Vector dir; + SentientPtr sent; + Event *event; - if( flags & FL_DIE_EXPLODE ) - { - CreateExplosion( origin, 150 * edict->s.scale, this, this, this ); - } + velocity = vec_zero; + sent = static_cast(driver.ent.Pointer()); + event = new Event(EV_Use); + event->AddEntity(sent); + ProcessEvent(event); + dir = sent->origin - origin; + dir[2] += 64; + dir.normalize(); + sent->Damage(this, this, sent->health * 2, origin, dir, vec_zero, 50, 0, MOD_VEHICLE); + } - if( flags & FL_DIE_GIBS ) - { - setSolidType( SOLID_NOT ); - hideModel(); + // + // kill all passengers + // + for (i = 0; i < MAX_PASSENGERS; i++) { + if (Passengers[i].ent) { + Vector dir; + SentientPtr sent; + Event *event; - CreateGibs( this, -150, edict->s.scale, 3 ); - } - // - // kill all my wheels - // - last = this; - while( last->vlink ) - { - last->vlink->PostEvent( EV_Remove, 0 ); - last = last->vlink; - } + velocity = vec_zero; + sent = static_cast(Passengers[i].ent.Pointer()); + event = new Event(EV_Use); + event->AddEntity(sent); + ProcessEvent(event); + dir = sent->origin - origin; + dir[2] += 64; + dir.normalize(); + sent->Damage(this, this, sent->health * 2, origin, dir, vec_zero, 50, 0, MOD_VEHICLE); + } + } + // + // remove all turrets + // + for (i = 0; i < MAX_TURRETS; i++) { + if (Turrets[i].ent) { + Turrets[i].ent->PostEvent(EV_Remove, EV_VEHICLE); + } + } - // - // kill the killtargets - // - name = KillTarget(); - if( name && strcmp( name, "" ) ) - { - ent = NULL; - do - { - ent = ( Entity * )G_FindTarget( ent, name ); - if( !ent ) - { - break; - } - ent->PostEvent( EV_Remove, 0 ); - } while( 1 ); - } + if (flags & FL_DIE_EXPLODE) { + CreateExplosion(origin, 150 * edict->s.scale, this, this, this); + } - // - // fire targets - // - name = Target(); - if( name && strcmp( name, "" ) ) - { - ent = NULL; - do - { - ent = ( Entity * )G_FindTarget( ent, name ); - if( !ent ) - { - break; - } + if (flags & FL_DIE_GIBS) { + setSolidType(SOLID_NOT); + hideModel(); - event = new Event( EV_Activate ); - event->AddEntity( attacker ); - ent->ProcessEvent( event ); - } while( 1 ); - } + CreateGibs(this, -150, edict->s.scale, 3); + } + // + // kill all my wheels + // + last = this; + while (last->vlink) { + last->vlink->PostEvent(EV_Remove, EV_VEHICLE); + last = last->vlink; + } - PostEvent( EV_Remove, 0 ); + // + // kill the killtargets + // + name = KillTarget(); + if (name && strcmp(name, "")) { + for (ent = G_FindTarget(NULL, name); ent; ent = G_FindTarget(ent, name)) { + ent->PostEvent(EV_Remove, EV_VEHICLE); + } + } + + // + // fire targets + // + name = Target(); + if (name && strcmp(name, "")) { + for (ent = G_FindTarget(NULL, name); ent; ent = G_FindTarget(ent, name)) { + event = new Event(EV_Activate); + event->AddEntity(attacker); + ent->ProcessEvent(event); + } + } + + PostEvent(EV_Remove, EV_VEHICLE); + Unregister(STRING_DEATH); } diff --git a/code/fgame/vehicle.h b/code/fgame/vehicle.h index 140ef507..b8709df2 100644 --- a/code/fgame/vehicle.h +++ b/code/fgame/vehicle.h @@ -21,10 +21,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // vehicle.h: Script controlled vehicles. -// +// -#ifndef __VEHICLE_H__ -#define __VEHICLE_H__ +#pragma once #include "g_local.h" #include "entity.h" @@ -53,821 +52,557 @@ extern Event EV_Vehicle_SetTurnRate; extern cvar_t *g_showvehiclemovedebug; extern cvar_t *g_showvehicleentrypoints; extern cvar_t *g_showvehicleslotpoints; +extern cvar_t *g_showvehicletags; extern cvar_t *g_showvehiclepath; -class wheel_s { - Vector vOrigin; - Vector vAcceleration; - Vector vVelocity; - Vector vLongForce; - Vector vLatForce; - Vector vForce; - Vector vOrientation; - Vector vResistance; - float fYawOffset; - float fSlipAngle; - float fGripCoef; - float fLoad; - float fLongForce; - float fLatForce; - float fForce; - float fTraction; - float fLongTorque; - float fLatTorque; - float fTorque; - float fLongDist; - float fLatDist; - qboolean bSkidding; - qboolean bSpinning; - int iPowered; -}; +#define NUM_VEHICLE_TIRES 4 + +using cVehicleSpline = cSpline<4, 512>; + +typedef struct wheel_s { + Vector vOrigin; + Vector vAcceleration; + Vector vVelocity; + Vector vLongForce; + Vector vLatForce; + Vector vForce; + Vector vOrientation; + Vector vResistance; + float fYawOffset; + float fSlipAngle; + float fGripCoef; + float fLoad; + float fLongForce; + float fLatForce; + float fForce; + float fTraction; + float fLongTorque; + float fLatTorque; + float fTorque; + float fLongDist; + float fLatDist; + qboolean bSkidding; + qboolean bSpinning; + int iPowered; +} wheel_t; class VehicleBase : public Animate { public: - VehicleBase *vlink; - Vector offset; + VehicleBase *vlink; + Vector offset; - CLASS_PROTOTYPE( VehicleBase ); + CLASS_PROTOTYPE(VehicleBase); - VehicleBase( void ); - void Archive( Archiver &arc ) override; + VehicleBase(void); + void Archive(Archiver& arc) override; }; -inline void VehicleBase::Archive - ( - Archiver &arc - ) +inline void VehicleBase::Archive(Archiver& arc) { - Animate::Archive( arc ); + Animate::Archive(arc); - arc.ArchiveObjectPointer( ( Class ** )&vlink ); - arc.ArchiveVector( &offset ); + arc.ArchiveObjectPointer((Class **)&vlink); + arc.ArchiveVector(&offset); } -typedef enum -{ - ST_OFF, - ST_OFF_TRANS_IDLE, - ST_IDLE_TRANS_OFF, - ST_IDLE, - ST_IDLE_TRANS_RUN, - ST_RUN, - ST_RUN_TRANS_IDLE, - ST_IDLE_TRANS_TURN, - ST_TURN, - ST_TURN_TRANS_IDLE +typedef enum { + ST_OFF, + ST_OFF_TRANS_IDLE, + ST_IDLE_TRANS_OFF, + ST_IDLE, + ST_IDLE_TRANS_RUN, + ST_RUN, + ST_RUN_TRANS_IDLE, + ST_IDLE_TRANS_TURN, + ST_TURN, + ST_TURN_TRANS_IDLE } SOUND_STATE; -#define MAX_DRIVERS 1 -#define MAX_PASSENGERS 32 -#define MAX_TURRETS 8 -#define MAX_SOUND_ENTITIES 4 -#define MAX_CORNERS 4 +#define MAX_DRIVERS 1 +#define MAX_PASSENGERS 32 +#define MAX_TURRETS 8 +#define MAX_CORNERS 4 -#define MAX_SKIPPED_ENTITIES 64 +#define MAX_SKIPPED_ENTITIES 64 class Vehicle : public VehicleBase { - friend class VehicleSoundEntity; - friend class VehicleTurretGun; + friend class VehicleSoundEntity; + friend class VehicleTurretGun; protected: - cVehicleSlot driver; - cVehicleSlot lastdriver; - cVehicleSlot Passengers[ MAX_PASSENGERS ]; - cTurretSlot Turrets[ MAX_TURRETS ]; - int numPassengers; - int numTurrets; - int moveresult; - int isBlocked; - int m_iFrameCtr; - int m_iGear; - int m_iRPM; - int m_iLastTiresUpdate; - class cSpline<4, 512> *m_pAlternatePath; - int m_iAlternateNode; - class cSpline<4, 512> *m_pCurPath; - int m_iCurNode; - class cSpline<4, 512> *m_pNextPath; - int m_iNextPathStartNode; - float maxturnrate; - float currentspeed; - float turnangle; - float turnimpulse; - float moveimpulse; - float prev_moveimpulse; - float jumpimpulse; - float speed; - float conesize; - float maxtracedist; - float airspeed; - float m_fGearRatio[ 6 ]; - float m_fMass; - float m_fFrontMass; - float m_fBackMass; - float m_fWheelBase; - float m_fWheelFrontLoad; - float m_fWheelFrontInnerLoad; - float m_fWheelFrontOutterLoad; - float m_fWheelFrontDist; - float m_fWheelFrontSuspension; - float m_fWheelBackLoad; - float m_fWheelBackInnerLoad; - float m_fWheelBackOutterLoad; - float m_fWheelBackDist; - float m_fWheelBackSuspension; - float m_fCGHeight; - float m_fBankAngle; - float m_fTread; - float m_fTrackWidth; - float m_fTireFriction; - float m_fDrag; - float m_fTireRadius; - float m_fFrontBrakes; - float m_fBackBrakes; - float m_fRollingResistance; - float m_fTireRotationalSpeed; - float m_fFrontBrakingForce; - float m_fBackBrakingForce; - float m_fBrakingPerformance; - float m_fLastTurn; - float m_fTangForce; - float m_fInertia; - float m_fDifferentialRatio; - float m_fGearEfficiency; - float m_fMaxTraction; - float m_fTractionForce; - float m_fAccelerator; - float m_fTorque; - float m_fDownForce; - float m_fUpForce; - float m_fLeftForce; - float m_fRightForce; - float m_fForwardForce; - float m_fBackForce; - float m_fBouncyCoef; - float m_fSpringyCoef; - float m_fYawMin; - float m_fYawMax; - float m_fRollMin; - float m_fRollMax; - float m_fZMin; - float m_fZMax; - float m_fYawCoef; - float m_fRollCoef; - float m_fZCoef; - float m_fShaderOffset; - float m_fSoundMinSpeed; - float m_fSoundMinPitch; - float m_fSoundMaxSpeed; - float m_fSoundMaxPitch; - float m_fVolumeMinSpeed; - float m_fVolumeMinPitch; - float m_fVolumeMaxSpeed; - float m_fVolumeMaxPitch; - float m_fStopStartDistance; - float m_fStopStartSpeed; - float m_fStopEndDistance; - float m_fSkidAngle; - float m_fSkidLeftForce; - float m_fSkidRightForce; - str weaponName; - str m_sAnimationSet; - str m_sSoundSet; - str m_sExplosionModel; - Vector last_origin; - Vector seatangles; - Vector seatoffset; - Vector driveroffset; - Vector Corners[ MAX_CORNERS ]; - Vector v_angle; - Vector yaw_forward; - Vector yaw_left; - Vector ground_normal; - Vector base_angles; - Vector prev_velocity; - Vector real_velocity; - Vector prev_origin; - Vector real_acceleration; - Vector prev_acceleration; - Vector m_vOldMins; - Vector m_vOldMaxs; - Vector m_vCG; - Vector m_vAngularAcceleration; - Vector m_vAngularVelocity; - Vector m_vAngles; - Vector m_vFrontNormal; - Vector m_vBackNormal; - Vector m_vFrontAngles; - Vector m_vBackAngles; - Vector m_vBaseNormal; - Vector m_vBaseAngles; - Vector m_vPrevNormal; - Vector m_vResistance; - Vector m_vWheelForce; - Vector m_vTangForce; - Vector m_vForce; - Vector m_vAcceleration; - Vector m_vOriginOffset; - Vector m_vOriginOffset2; - Vector m_vOriginCornerOffset; - Vector m_vAnglesOffset; - Vector m_vSaveAngles; - Vector m_vSkidOrigin; - qboolean drivable; - qboolean locked; - qboolean hasweapon; - qboolean showweapon; - qboolean steerinplace; - qboolean jumpable; - qboolean m_bWheelSpinning; - qboolean m_bIsSkidding; - qboolean m_bIsBraking; - qboolean m_bBackSlipping; - qboolean m_bFrontSlipping; - qboolean m_bAutomatic; - qboolean m_bThinkCalled; - qboolean m_bMovementLocked; - qboolean m_bRemoveOnDeath; - qboolean m_bStopEnabled; - qboolean m_bEnableSkidding; - vmove_s *vm; - vehicleState_t vs; - cMoveGrid *m_sMoveGrid; - float m_fIdealSpeed; - Vector m_vIdealPosition; - Vector m_vIdealDir; - float m_fIdealAccel; - float m_fIdealDistance; - float m_fLookAhead; - bool m_bAutoPilot; - SafePtr m_pCollisionEntity; - SOUND_STATE m_eSoundState; - float m_fNextSoundState; - SafePtr m_pVehicleSoundEntities[ MAX_SOUND_ENTITIES ]; - Vector m_vTireEnd[ 4 ]; - bool m_bTireHit[ 4 ]; - Vector m_vNormalSum; - int m_iNumNormals; + cVehicleSlot driver; + cVehicleSlot lastdriver; + cVehicleSlot Passengers[MAX_PASSENGERS]; + cTurretSlot Turrets[MAX_TURRETS]; + int numPassengers; + int numTurrets; + int moveresult; + int isBlocked; + int m_iFrameCtr; + int m_iGear; + int m_iRPM; + int m_iLastTiresUpdate; + cVehicleSpline *m_pAlternatePath; + int m_iAlternateNode; + cVehicleSpline *m_pCurPath; + int m_iCurNode; + cVehicleSpline *m_pNextPath; + int m_iNextPathStartNode; + float maxturnrate; + float currentspeed; + float turnangle; + float turnimpulse; + float moveimpulse; + float prev_moveimpulse; + float jumpimpulse; + float speed; + float conesize; + float maxtracedist; + float airspeed; + float m_fGearRatio[6]; + float m_fMass; + float m_fFrontMass; + float m_fBackMass; + float m_fWheelBase; + float m_fWheelFrontLoad; + float m_fWheelFrontInnerLoad; + float m_fWheelFrontOutterLoad; + float m_fWheelFrontDist; + float m_fWheelFrontSuspension; + float m_fWheelBackLoad; + float m_fWheelBackInnerLoad; + float m_fWheelBackOutterLoad; + float m_fWheelBackDist; + float m_fWheelBackSuspension; + float m_fCGHeight; + float m_fBankAngle; + float m_fTread; + float m_fTrackWidth; + float m_fTireFriction; + float m_fDrag; + float m_fTireRadius; + float m_fFrontBrakes; + float m_fBackBrakes; + float m_fRollingResistance; + float m_fTireRotationalSpeed; + float m_fFrontBrakingForce; + float m_fBackBrakingForce; + float m_fBrakingPerformance; + float m_fLastTurn; + float m_fTangForce; + float m_fInertia; + float m_fDifferentialRatio; + float m_fGearEfficiency; + float m_fMaxTraction; + float m_fTractionForce; + float m_fAccelerator; + float m_fTorque; + float m_fDownForce; + float m_fUpForce; + float m_fLeftForce; + float m_fRightForce; + float m_fForwardForce; + float m_fBackForce; + float m_fBouncyCoef; + float m_fSpringyCoef; + float m_fYawMin; + float m_fYawMax; + float m_fRollMin; + float m_fRollMax; + float m_fZMin; + float m_fZMax; + float m_fYawCoef; + float m_fRollCoef; + float m_fZCoef; + float m_fShaderOffset; + float m_fSoundMinSpeed; + float m_fSoundMinPitch; + float m_fSoundMaxSpeed; + float m_fSoundMaxPitch; + float m_fVolumeMinSpeed; + float m_fVolumeMinPitch; + float m_fVolumeMaxSpeed; + float m_fVolumeMaxPitch; + float m_fStopStartDistance; + float m_fStopStartSpeed; + float m_fStopEndDistance; + float m_fSkidAngle; + float m_fSkidLeftForce; + float m_fSkidRightForce; + str vehicleName; + str weaponName; + str m_sAnimationSet; + str m_sSoundSet; + str m_sExplosionModel; + Vector last_origin; + Vector seatangles; + Vector seatoffset; + Vector driveroffset; + Vector Corners[MAX_CORNERS]; + Vector v_angle; + Vector yaw_forward; + Vector yaw_left; + Vector ground_normal; + Vector base_angles; + Vector prev_velocity; + Vector real_velocity; + Vector prev_origin; + Vector real_acceleration; + Vector prev_acceleration; + Vector m_vOldMins; + Vector m_vOldMaxs; + Vector m_vCG; + Vector m_vAngularAcceleration; + Vector m_vAngularVelocity; + Vector m_vAngles; + Vector m_vFrontNormal; + Vector m_vBackNormal; + Vector m_vFrontAngles; + Vector m_vBackAngles; + Vector m_vBaseNormal; + Vector m_vBaseAngles; + Vector m_vPrevNormal; + Vector m_vResistance; + Vector m_vWheelForce; + Vector m_vTangForce; + Vector m_vForce; + Vector m_vAcceleration; + Vector m_vOriginOffset; + Vector m_vOriginOffset2; + Vector m_vOriginCornerOffset; + Vector m_vAnglesOffset; + Vector m_vSaveAngles; + Vector m_vSkidOrigin; + qboolean drivable; + qboolean pathDrivable; + qboolean locked; + qboolean hasweapon; + qboolean showweapon; + qboolean steerinplace; + qboolean jumpable; + qboolean m_bWheelSpinning; + qboolean m_bIsSkidding; + qboolean m_bIsBraking; + qboolean m_bBackSlipping; + qboolean m_bFrontSlipping; + qboolean m_bAutomatic; + qboolean m_bThinkCalled; + qboolean m_bMovementLocked; + qboolean m_bRemoveOnDeath; + qboolean m_bStopEnabled; + qboolean m_bEnableSkidding; + qboolean m_bAnimMove; + qboolean m_bDamageSounds; + qboolean m_bRunSounds; + int m_iProjectileHitsRemaining; + vehicleState_t vs; + cMoveGrid *m_sMoveGrid; + float m_fIdealSpeed; + float m_fMaxSpeed; + bool m_bBounceBackwards; + Vector m_vIdealPosition; + Vector m_vIdealDir; + float m_fIdealAccel; + float m_fIdealDistance; + float m_fLookAhead; + bool m_bAutoPilot; + SafePtr m_pCollisionEntity; + SOUND_STATE m_eSoundState; + float m_fNextSoundState; + SafePtr m_pVehicleSoundEntities[MAX_CORNERS]; + Vector m_vTireEnd[NUM_VEHICLE_TIRES]; + bool m_bTireHit[NUM_VEHICLE_TIRES]; + Vector m_vNormalSum; + int m_iNumNormals; + float m_fMaxUseAngle; + bool m_bBounceStayFullSpeed; protected: - virtual void WorldEffects( void ); - virtual void CheckWater( void ); - virtual void DriverUse( Event *ev ); - virtual void VehicleStart( Event *ev ); - virtual void VehicleTouched( Event *ev ); - virtual void VehicleBlocked( Event *ev ); - void Think( void ) override; - void Postthink( void ) override; - virtual void Drivable( Event *ev ); - virtual void UnDrivable( Event *ev ); - virtual void Jumpable( Event *ev ); - virtual void SeatAnglesOffset( Event *ev ); - virtual void SeatOffset( Event *ev ); - virtual void SetDriverAngles( Vector angles ); - virtual void Lock( Event *ev ); - virtual void UnLock( Event *ev ); - virtual void SetWeapon( Event *ev ); - virtual void ShowWeaponEvent( Event *ev ); - virtual void SetSpeed( Event *ev ); - virtual void SetTurnRate( Event *ev ); - virtual void SteerInPlace( Event *ev ); - virtual void VehicleDestroyed( Event *ev ); - virtual void SetMoveInfo( vmove_t *vm ); - virtual void GetMoveInfo( vmove_t *vm ); - virtual void SetCEMoveInfo( vmove_t *vm ); - virtual void GetCEMoveInfo( vmove_t *vm ); - virtual void SetViewAngles( Vector newViewangles ); - virtual void SetMass( Event *ev ); - virtual void SetFrontMass( Event *ev ); - virtual void SetBackMass( Event *ev ); - virtual void SetTread( Event *ev ); - virtual void SetTireRadius( Event *ev ); - virtual void SetRollingResistance( Event *ev ); - virtual void SetDrag( Event *ev ); - virtual float TorqueLookup( int rpm ); - virtual void UpdateVariables( Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright ); - virtual void ModelInit( Event *ev ); - virtual void BouncyCoef( Event *ev ); - virtual void SpringyCoef( Event *ev ); - virtual void YawMinMax( Event *ev ); - virtual void RollMinMax( Event *ev ); - virtual void ZMinMax( Event *ev ); - virtual void SetAnimationSet( Event *ev ); - virtual void SetSoundSet( Event *ev ); - virtual void SpawnTurret( Event *ev ); - void EventLockMovement( Event *ev ); - void EventUnlockMovement( Event *ev ); - virtual void QueryFreePassengerSlot(Event* ev); - virtual void QueryFreeDriverSlot(Event* ev); - virtual void QueryFreeTurretSlot(Event* ev); - virtual void QueryPassengerSlotPosition(Event* ev); - virtual void QueryDriverSlotPosition(Event* ev); - virtual void QueryTurretSlotPosition(Event* ev); - virtual void QueryPassengerSlotAngles(Event* ev); - virtual void QueryDriverSlotAngles(Event* ev); - virtual void QueryTurretSlotAngles(Event* ev); - virtual void QueryPassengerSlotStatus(Event* ev); - virtual void QueryDriverSlotStatus(Event* ev); - virtual void QueryTurretSlotStatus(Event* ev); - virtual void QueryPassengerSlotEntity(Event* ev); - virtual void QueryDriverSlotEntity(Event* ev); - virtual void QueryTurretSlotEntity(Event* ev); - virtual void AttachPassengerSlot(Event* ev); - virtual void AttachDriverSlot(Event* ev); - virtual void AttachTurretSlot(Event* ev); - virtual void DetachPassengerSlot(Event* ev); - virtual void DetachDriverSlot(Event* ev); - virtual void DetachTurretSlot(Event* ev); - virtual void DetachRemoteOwner(); - virtual void SetWheelCorners(Event* ev); - virtual void EventDriveInternal(Event* ev, bool wait); - virtual void EventDrive(Event* ev); - virtual void EventDriveNoWait(Event* ev); - virtual void EventStop(Event* ev); - virtual void EventFullStop(Event* ev); - virtual void EventModifyDrive(Event* ev); - virtual void EventNextDrive(Event* ev); - void EventModel( Event *ev ); - void EventRemoveOnDeath( Event *ev ); - void EventSetExplosionModel( Event *ev ); - void EventSetCollisionModel( Event *ev ); - void EventGetCollisionModel( Event *ev ); - void EventSetSoundParameters( Event *ev ); - void EventSetVolumeParameters( Event *ev ); - void EventDamage( Event *ev ); - void EventStopAtEnd( Event *ev ); - void EventSkidding( Event *ev ); - void EventContinueSkidding( Event *ev ); - void EventVehicleAnim( Event *ev ); - void EventVehicleAnimDone( Event *ev ); - void TouchStuff( vmove_t *vm ); - virtual void ResetSlots( void ); - virtual void OpenSlotsByModel( void ); - virtual void MoveVehicle( void ); - virtual bool AssertMove( Vector vNewOrigin, Vector vOldOrigin ); - virtual bool AssertRotation( Vector vNewAngles, Vector vOldAngles ); - virtual void NoMove( void ); - virtual void SlidePush( Vector vPush ); - void SetupPath( cSpline<4, 512> *pPath, SimpleEntity *se ); - virtual void UpdateSound( void ); - void SetupVehicleSoundEntities( void ); - void RemoveVehicleSoundEntities( void ); - void TurnOnVehicleSoundEntities( void ); - void TurnOffVehicleSoundEntities( void ); - void UpdateTires( void ); - void UpdateNormals( void ); - void UpdateBones( void ); - void UpdateShaderOffset( void ); - void UpdateTurretSlot( int iSlot ); - void UpdatePassengerSlot( int iSlot ); - void UpdateDriverSlot( int iSlot ); - float GetPathPosition( cSpline<4, 512> *pPath, int iNode ); - void UpdateSkidAngle( void ); - void FactorInSkidOrigin( void ); - virtual void FactorInOriginOffset( void ); - virtual void CalculateOriginOffset( void ); - virtual void FactorOutOriginOffset( void ); - virtual void FactorInAnglesOffset( Vector *vAddedAngles ); - virtual void CalculateAnglesOffset( Vector acceleration ); - virtual void FactorOutAnglesOffset( void ); - qboolean GetTagPositionAndOrientation( str tagname, orientation_t *new_or ); - qboolean GetTagPositionAndOrientation( int tagnum, orientation_t *new_or ); - void CalculateAnimationData( Vector vAngles, Vector vOrigin ); - bool IsDamagedBy( Entity *ent ); + virtual void WorldEffects(void); + virtual void CheckWater(void); + virtual void DriverUse(Event *ev); + virtual void VehicleStart(Event *ev); + virtual void VehicleTouched(Event *ev); + virtual void VehicleBlocked(Event *ev); + void Think(void) override; + void Postthink(void) override; + virtual void Drivable(Event *ev); + virtual void PathDrivable(Event *ev); // Added in 2.30 + virtual void UnDrivable(Event *ev); + virtual void Jumpable(Event *ev); + virtual void SeatAnglesOffset(Event *ev); + virtual void SeatOffset(Event *ev); + virtual void SetDriverAngles(Vector angles); + virtual void Lock(Event *ev); + virtual void UnLock(Event *ev); + virtual void SetWeapon(Event *ev); + virtual void SetName(Event *ev); // added in 2.0 + virtual void ShowWeaponEvent(Event *ev); + // added in 2.30 + //==== + virtual void BounceForwardsVelocity(Event *ev); + virtual void BounceBackwardsVelocity(Event *ev); + virtual void StopForwardsVelocity(Event *ev); + virtual void StopBackwardsVelocity(Event *ev); + //==== + virtual void SetSpeed(Event *ev); + virtual void SetTurnRate(Event *ev); + virtual void SteerInPlace(Event *ev); + virtual void VehicleDestroyed(Event *ev); + virtual void SetMoveInfo(vmove_t *vm); + virtual void GetMoveInfo(vmove_t *vm); + virtual void SetCEMoveInfo(vmove_t *vm); + virtual void GetCEMoveInfo(vmove_t *vm); + virtual void SetViewAngles(Vector newViewangles); + virtual void SetMass(Event *ev); + virtual void SetFrontMass(Event *ev); + virtual void SetBackMass(Event *ev); + virtual void SetTread(Event *ev); + virtual void SetTireRadius(Event *ev); + virtual void SetRollingResistance(Event *ev); + virtual void SetDrag(Event *ev); + virtual float TorqueLookup(int rpm); + virtual void UpdateVariables( + Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright + ); + virtual void ModelInit(Event *ev); + virtual void BouncyCoef(Event *ev); + virtual void SpringyCoef(Event *ev); + virtual void YawMinMax(Event *ev); + virtual void RollMinMax(Event *ev); + virtual void ZMinMax(Event *ev); + virtual void SetAnimationSet(Event *ev); + virtual void SetSoundSet(Event *ev); + virtual void SpawnTurret(Event *ev); + void EventLockMovement(Event *ev); + void EventUnlockMovement(Event *ev); + virtual void QuerySpeed(Event *ev); + virtual void QueryFreePassengerSlot(Event *ev); + virtual void QueryFreeDriverSlot(Event *ev); + virtual void QueryFreeTurretSlot(Event *ev); + virtual void QueryPassengerSlotPosition(Event *ev); + virtual void QueryDriverSlotPosition(Event *ev); + virtual void QueryTurretSlotPosition(Event *ev); + virtual void QueryPassengerSlotAngles(Event *ev); + virtual void QueryDriverSlotAngles(Event *ev); + virtual void QueryTurretSlotAngles(Event *ev); + virtual void QueryPassengerSlotStatus(Event *ev); + virtual void QueryDriverSlotStatus(Event *ev); + virtual void QueryTurretSlotStatus(Event *ev); + virtual void QueryPassengerSlotEntity(Event *ev); + virtual void QueryDriverSlotEntity(Event *ev); + virtual void QueryTurretSlotEntity(Event *ev); + virtual void AttachPassengerSlot(Event *ev); + virtual void AttachDriverSlot(Event *ev); + virtual void AttachTurretSlot(Event *ev); + virtual void DetachPassengerSlot(Event *ev); + virtual void DetachDriverSlot(Event *ev); + virtual void DetachTurretSlot(Event *ev); + virtual void DetachRemoteOwner(); // added in 2.0 + virtual void SetWheelCorners(Event *ev); + virtual void EventDriveInternal(Event *ev, bool wait); + virtual void EventDrive(Event *ev); + virtual void EventDriveNoWait(Event *ev); + virtual void EventStop(Event *ev); + virtual void EventFullStop(Event *ev); + virtual void EventModifyDrive(Event *ev); + virtual void EventNextDrive(Event *ev); + void EventModel(Event *ev); + void EventRemoveOnDeath(Event *ev); + void EventSetExplosionModel(Event *ev); + void EventSetCollisionModel(Event *ev); + void EventGetCollisionModel(Event *ev); + void EventSetSoundParameters(Event *ev); + void EventSetVolumeParameters(Event *ev); + void EventDamage(Event *ev); + void EventStopAtEnd(Event *ev); + void EventSkidding(Event *ev); + void EventContinueSkidding(Event *ev); + void EventVehicleAnim(Event *ev); + void EventVehicleAnimDone(Event *ev); + // added in 2.0 + //==== + void EventVehicleMoveAnim(Event *ev); + void EventVehicleMoveAnimDone(Event *ev); + void EventDamageSounds(Event *ev); + void EventRunSounds(Event *ev); + void Remove(Event *ev); + //==== + void TouchStuff(vmove_t *vm); + virtual void ResetSlots(void); + virtual void OpenSlotsByModel(void); + virtual void MoveVehicle(void); + virtual void AnimMoveVehicle(void); + virtual bool AssertMove(Vector vNewOrigin, Vector vOldOrigin); + virtual bool AssertRotation(Vector vNewAngles, Vector vOldAngles); + virtual void NoMove(void); + virtual void SlidePush(Vector vPush); + void SetupPath(cVehicleSpline *pPath, SimpleEntity *se); + virtual void UpdateSound(void); + void SetupVehicleSoundEntities(void); + void RemoveVehicleSoundEntities(void); + void TurnOnVehicleSoundEntities(void); + void TurnOffVehicleSoundEntities(void); + void UpdateTires(void); + void UpdateNormals(void); + void UpdateBones(void); + void UpdateShaderOffset(void); + virtual void UpdateTurretSlot(int iSlot); + void UpdatePassengerSlot(int iSlot); + void UpdateDriverSlot(int iSlot); + float GetPathPosition(cVehicleSpline *pPath, int iNode); + void UpdateSkidAngle(void); + void FactorInSkidOrigin(void); + virtual void FactorInOriginOffset(void); + virtual void CalculateOriginOffset(void); + virtual void FactorOutOriginOffset(void); + virtual void FactorInAnglesOffset(Vector *vAddedAngles); + virtual void CalculateAnglesOffset(Vector acceleration); + virtual void FactorOutAnglesOffset(void); + qboolean GetTagPositionAndOrientation(str tagname, orientation_t *new_or); + qboolean GetTagPositionAndOrientation(int tagnum, orientation_t *new_or); + void CalculateAnimationData(Vector vAngles, Vector vOrigin); + bool IsDamagedBy(Entity *ent); - public: - CLASS_PROTOTYPE( Vehicle ); +public: + CLASS_PROTOTYPE(Vehicle); - Vehicle(); - virtual ~Vehicle(); + Vehicle(); + virtual ~Vehicle(); - virtual qboolean Drive( usercmd_t *ucmd ); - void AutoPilot( void ); - virtual qboolean HasWeapon( void ); - virtual qboolean ShowWeapon( void ); - Entity *Driver( void ); - virtual qboolean IsDrivable( void ); - void Archive( Archiver& arc ) override; - str GetSoundSet( void ); - virtual int QueryFreePassengerSlot( void ); - virtual int QueryFreeDriverSlot( void ); - virtual int QueryFreeTurretSlot( void ); - virtual void QueryPassengerSlotPosition( int slot, float *pos ); - virtual void QueryDriverSlotPosition( int slot, float *pos ); - virtual void QueryTurretSlotPosition( int slot, float *pos ); - virtual void QueryPassengerSlotAngles( int slot, float *ang ); - virtual void QueryDriverSlotAngles( int slot, float *ang ); - virtual void QueryTurretSlotAngles( int slot, float *ang ); - virtual int QueryPassengerSlotStatus( int slot ); - virtual int QueryDriverSlotStatus( int slot ); - virtual int QueryTurretSlotStatus( int slot ); - virtual Entity *QueryPassengerSlotEntity( int slot ); - virtual Entity *QueryDriverSlotEntity( int slot ); - virtual Entity *QueryTurretSlotEntity( int slot ); - virtual void AttachPassengerSlot( int slot, Entity *ent, Vector vExitPosition ); - virtual void AttachDriverSlot( int slot, Entity *ent, Vector vExitPosition ); - virtual void AttachTurretSlot( int slot, Entity *ent, Vector vExitPosition, Vector *vExitAngles ); - virtual void DetachPassengerSlot( int slot, Vector vExitPosition, Vector *vExitAngles ); - virtual void DetachDriverSlot( int slot, Vector vExitPosition, Vector *vExitAngles ); - virtual void DetachTurretSlot( int slot, Vector vExitPosition, Vector *vExitAngles ); - virtual int FindPassengerSlotByEntity( Entity *ent ); - virtual int FindDriverSlotByEntity( Entity *ent ); - virtual int FindTurretSlotByEntity( Entity *ent ); - virtual void SetSlotsNonSolid( void ); - virtual void SetSlotsSolid( void ); - void KickSuspension( Vector vDirection, float fForce ); - qboolean isLocked( void ); - void Lock( void ); - void UnLock( void ); - VehicleCollisionEntity *GetCollisionEntity( void ); + virtual void DriverAdded(); // added in 2.0 + virtual qboolean Drive(usercmd_t *ucmd); + virtual qboolean PathDrive(usercmd_t *ucmd); + void AutoPilot(void); + virtual qboolean HasWeapon(void); + virtual qboolean ShowWeapon(void); + Entity *Driver(void); + virtual qboolean IsDrivable(void); + void Archive(Archiver& arc) override; + str GetSoundSet(void); + virtual float QuerySpeed(void); + virtual int QueryFreePassengerSlot(void); + virtual int QueryFreeDriverSlot(void); + virtual int QueryFreeTurretSlot(void); + virtual void QueryPassengerSlotPosition(int slot, float *pos); + virtual void QueryDriverSlotPosition(int slot, float *pos); + virtual void QueryTurretSlotPosition(int slot, float *pos); + virtual void QueryPassengerSlotAngles(int slot, float *ang); + virtual void QueryDriverSlotAngles(int slot, float *ang); + virtual void QueryTurretSlotAngles(int slot, float *ang); + virtual int QueryPassengerSlotStatus(int slot); + virtual int QueryDriverSlotStatus(int slot); + virtual int QueryTurretSlotStatus(int slot); + virtual Entity *QueryPassengerSlotEntity(int slot); + virtual Entity *QueryDriverSlotEntity(int slot); + virtual Entity *QueryTurretSlotEntity(int slot); + bool FindExitPosition(Entity *pEnt, const Vector& vOrigin, const Vector *vAngles); // added in 2.0 + virtual void AttachPassengerSlot(int slot, Entity *ent, Vector vExitPosition); + virtual void AttachDriverSlot(int slot, Entity *ent, Vector vExitPosition); + virtual void AttachTurretSlot(int slot, Entity *ent, Vector vExitPosition, Vector *vExitAngles); + virtual void DetachPassengerSlot(int slot, Vector vExitPosition, Vector *vExitAngles); + virtual void DetachDriverSlot(int slot, Vector vExitPosition, Vector *vExitAngles); + virtual void DetachTurretSlot(int slot, Vector vExitPosition, Vector *vExitAngles); + virtual int FindPassengerSlotByEntity(Entity *ent); + virtual int FindDriverSlotByEntity(Entity *ent); + virtual int FindTurretSlotByEntity(Entity *ent); + virtual void SetSlotsNonSolid(void); + virtual void SetSlotsSolid(void); + void KickSuspension(Vector vDirection, float fForce); + qboolean isLocked(void); + void Lock(void); + void UnLock(void); + const str& getName() const; // added in 2.0 + VehicleCollisionEntity *GetCollisionEntity(void); + // Added in 2.30 + //==== + void EventSetMaxUseAngle(Event *ev); + void EventCanUse(Event *ev); + int GetProjectileHitsRemaining() const; + void SetProjectileVulnerable(Event* ev); + void DoProjectileVulnerability(Entity* pProjectile, Entity* pOwner, meansOfDeath_t meansOfDeath); + //==== }; -inline void Vehicle::Archive - ( - Archiver &arc - ) -{ - VehicleBase::Archive( arc ); - - arc.ArchiveFloat( &maxturnrate ); - arc.ArchiveFloat( ¤tspeed ); - arc.ArchiveFloat( &turnangle ); - arc.ArchiveFloat( &turnimpulse ); - arc.ArchiveFloat( &moveimpulse ); - arc.ArchiveFloat( &jumpimpulse ); - arc.ArchiveFloat( &speed ); - arc.ArchiveFloat( &conesize ); - arc.ArchiveFloat( &maxtracedist ); - arc.ArchiveString( &weaponName ); - arc.ArchiveVector( &last_origin ); - arc.ArchiveVector( &seatangles ); - arc.ArchiveVector( &seatoffset ); - arc.ArchiveVector( &driveroffset ); - - arc.ArchiveVector( &Corners[ 0 ] ); - arc.ArchiveVector( &Corners[ 1 ] ); - arc.ArchiveVector( &Corners[ 2 ] ); - arc.ArchiveVector( &Corners[ 3 ] ); - - arc.ArchiveBoolean( &drivable ); - arc.ArchiveBoolean( &locked ); - arc.ArchiveBoolean( &hasweapon ); - arc.ArchiveBoolean( &showweapon ); - arc.ArchiveBoolean( &steerinplace ); - arc.ArchiveBoolean( &jumpable ); - - arc.ArchiveBoolean( &m_bMovementLocked ); - driver.Archive( arc ); - lastdriver.Archive( arc ); - - for( int i = MAX_PASSENGERS - 1; i >= 0; i-- ) - { - Passengers[ i ].Archive( arc ); - } - - for( int i = MAX_TURRETS - 1; i >= 0; i-- ) - { - Turrets[ i ].Archive( arc ); - } - - arc.ArchiveInteger( &numPassengers ); - arc.ArchiveInteger( &numTurrets ); - arc.ArchiveInteger( &moveresult ); - arc.ArchiveInteger( &isBlocked ); - arc.ArchiveInteger( &m_iFrameCtr ); - arc.ArchiveInteger( &m_iGear ); - arc.ArchiveInteger( &m_iRPM ); - arc.ArchiveInteger( &m_iNextPathStartNode ); - - if( !arc.Saving() ) - { - m_iLastTiresUpdate = -1; - - int tempInt; - arc.ArchiveInteger( &tempInt ); - - if( tempInt ) - { - m_pAlternatePath = new cSpline < 4, 512 > ; - } - else - { - m_pAlternatePath = NULL; - } - } - else - { - int tempInt = m_pAlternatePath != NULL; - arc.ArchiveInteger( &tempInt ); - } - - if( m_pAlternatePath ) - { - m_pAlternatePath->Archive( arc ); - } - - arc.ArchiveInteger( &m_iAlternateNode ); - - if( !arc.Saving() ) - { - int tempInt; - arc.ArchiveInteger( &tempInt ); - - if( tempInt ) - { - m_pCurPath = new cSpline < 4, 512 > ; - } - else - { - m_pCurPath = NULL; - } - } - else - { - int tempInt = m_pCurPath != NULL; - arc.ArchiveInteger( &tempInt ); - } - - if( m_pCurPath ) - { - m_pCurPath->Archive( arc ); - } - - arc.ArchiveInteger( &m_iCurNode ); - - if( !arc.Saving() ) - { - int tempInt; - arc.ArchiveInteger( &tempInt ); - - if( tempInt ) - { - m_pNextPath = new cSpline < 4, 512 > ; - } - else - { - m_pNextPath = NULL; - } - } - else - { - int tempInt = m_pNextPath != NULL; - arc.ArchiveInteger( &tempInt ); - } - - if( m_pNextPath ) - { - m_pNextPath->Archive( arc ); - } - - arc.ArchiveFloat( &maxturnrate ); - arc.ArchiveFloat( ¤tspeed ); - arc.ArchiveFloat( &turnangle ); - arc.ArchiveFloat( &turnimpulse ); - arc.ArchiveFloat( &moveimpulse ); - arc.ArchiveFloat( &prev_moveimpulse ); - arc.ArchiveFloat( &jumpimpulse ); - arc.ArchiveFloat( &speed ); - arc.ArchiveFloat( &conesize ); - arc.ArchiveFloat( &maxtracedist ); - arc.ArchiveFloat( &airspeed ); - arc.ArchiveFloat( &m_fGearRatio[ 0 ] ); - arc.ArchiveFloat( &m_fGearRatio[ 1 ] ); - arc.ArchiveFloat( &m_fGearRatio[ 2 ] ); - arc.ArchiveFloat( &m_fGearRatio[ 3 ] ); - arc.ArchiveFloat( &m_fGearRatio[ 4 ] ); - arc.ArchiveFloat( &m_fGearRatio[ 5 ] ); - arc.ArchiveFloat( &m_fMass ); - arc.ArchiveFloat( &m_fFrontMass ); - arc.ArchiveFloat( &m_fBackMass ); - arc.ArchiveFloat( &m_fWheelBase ); - arc.ArchiveFloat( &m_fWheelFrontLoad ); - arc.ArchiveFloat( &m_fWheelFrontInnerLoad ); - arc.ArchiveFloat( &m_fWheelFrontOutterLoad ); - arc.ArchiveFloat( &m_fWheelFrontDist ); - arc.ArchiveFloat( &m_fWheelFrontSuspension ); - arc.ArchiveFloat( &m_fWheelBackLoad ); - arc.ArchiveFloat( &m_fWheelBackInnerLoad ); - arc.ArchiveFloat( &m_fWheelBackOutterLoad ); - arc.ArchiveFloat( &m_fWheelBackDist ); - arc.ArchiveFloat( &m_fWheelBackSuspension ); - arc.ArchiveFloat( &m_fCGHeight ); - arc.ArchiveFloat( &m_fBankAngle ); - arc.ArchiveFloat( &m_fTread ); - arc.ArchiveFloat( &m_fTrackWidth ); - arc.ArchiveFloat( &m_fTireFriction ); - arc.ArchiveFloat( &m_fDrag ); - arc.ArchiveFloat( &m_fTireRadius ); - arc.ArchiveFloat( &m_fFrontBrakes ); - arc.ArchiveFloat( &m_fBackBrakes ); - arc.ArchiveFloat( &m_fRollingResistance ); - arc.ArchiveFloat( &m_fTireRotationalSpeed ); - arc.ArchiveFloat( &m_fFrontBrakingForce ); - arc.ArchiveFloat( &m_fBackBrakingForce ); - arc.ArchiveFloat( &m_fBrakingPerformance ); - arc.ArchiveFloat( &m_fLastTurn ); - arc.ArchiveFloat( &m_fTangForce ); - arc.ArchiveFloat( &m_fInertia ); - arc.ArchiveFloat( &m_fDifferentialRatio ); - arc.ArchiveFloat( &m_fGearEfficiency ); - arc.ArchiveFloat( &m_fMaxTraction ); - arc.ArchiveFloat( &m_fTractionForce ); - arc.ArchiveFloat( &m_fAccelerator ); - arc.ArchiveFloat( &m_fTorque ); - arc.ArchiveFloat( &m_fDownForce ); - arc.ArchiveFloat( &m_fUpForce ); - arc.ArchiveFloat( &m_fLeftForce ); - arc.ArchiveFloat( &m_fRightForce ); - arc.ArchiveFloat( &m_fForwardForce ); - arc.ArchiveFloat( &m_fBackForce ); - arc.ArchiveFloat( &m_fBouncyCoef ); - arc.ArchiveFloat( &m_fSpringyCoef ); - arc.ArchiveFloat( &m_fYawMin ); - arc.ArchiveFloat( &m_fYawMax ); - arc.ArchiveFloat( &m_fRollMin ); - arc.ArchiveFloat( &m_fRollMax ); - arc.ArchiveFloat( &m_fZMin ); - arc.ArchiveFloat( &m_fZMax ); - arc.ArchiveFloat( &m_fYawCoef ); - arc.ArchiveFloat( &m_fRollCoef ); - arc.ArchiveFloat( &m_fZCoef ); - arc.ArchiveFloat( &m_fShaderOffset ); - arc.ArchiveFloat( &m_fSoundMinSpeed ); - arc.ArchiveFloat( &m_fSoundMinPitch ); - arc.ArchiveFloat( &m_fSoundMaxSpeed ); - arc.ArchiveFloat( &m_fSoundMaxPitch ); - arc.ArchiveFloat( &m_fVolumeMinSpeed ); - arc.ArchiveFloat( &m_fVolumeMinPitch ); - arc.ArchiveFloat( &m_fVolumeMaxSpeed ); - arc.ArchiveFloat( &m_fVolumeMaxPitch ); - arc.ArchiveFloat( &m_fStopStartDistance ); - arc.ArchiveFloat( &m_fStopStartSpeed ); - arc.ArchiveFloat( &m_fStopEndDistance ); - arc.ArchiveFloat( &m_fSkidAngle ); - arc.ArchiveFloat( &m_fSkidLeftForce ); - arc.ArchiveFloat( &m_fSkidRightForce ); - arc.ArchiveString( &weaponName ); - arc.ArchiveString( &m_sAnimationSet ); - arc.ArchiveString( &m_sSoundSet ); - arc.ArchiveString( &m_sExplosionModel ); - arc.ArchiveVector( &last_origin ); - arc.ArchiveVector( &seatangles ); - arc.ArchiveVector( &driveroffset ); - arc.ArchiveVector( &Corners[ 0 ] ); - arc.ArchiveVector( &Corners[ 1 ] ); - arc.ArchiveVector( &Corners[ 2 ] ); - arc.ArchiveVector( &Corners[ 3 ] ); - arc.ArchiveVector( &v_angle ); - arc.ArchiveVector( &yaw_forward ); - arc.ArchiveVector( &yaw_left ); - arc.ArchiveVector( &ground_normal ); - arc.ArchiveVector( &base_angles ); - arc.ArchiveVector( &prev_velocity ); - arc.ArchiveVector( &real_velocity ); - arc.ArchiveVector( &prev_origin ); - arc.ArchiveVector( &real_acceleration ); - arc.ArchiveVector( &prev_acceleration ); - arc.ArchiveVector( &m_vOldMins ); - arc.ArchiveVector( &m_vOldMaxs ); - arc.ArchiveVector( &m_vCG ); - arc.ArchiveVector( &m_vAngularAcceleration ); - arc.ArchiveVector( &m_vAngularVelocity ); - arc.ArchiveVector( &m_vAngles ); - arc.ArchiveVector( &m_vFrontNormal ); - arc.ArchiveVector( &m_vBackNormal ); - arc.ArchiveVector( &m_vFrontAngles ); - arc.ArchiveVector( &m_vBackAngles ); - arc.ArchiveVector( &m_vBaseNormal ); - arc.ArchiveVector( &m_vBaseAngles ); - arc.ArchiveVector( &m_vPrevNormal ); - arc.ArchiveVector( &m_vResistance ); - arc.ArchiveVector( &m_vWheelForce ); - arc.ArchiveVector( &m_vTangForce ); - arc.ArchiveVector( &m_vForce ); - arc.ArchiveVector( &m_vAcceleration ); - arc.ArchiveVector( &m_vOriginOffset ); - arc.ArchiveVector( &m_vOriginOffset2 ); - arc.ArchiveVector( &m_vOriginCornerOffset ); - arc.ArchiveVector( &m_vAnglesOffset ); - arc.ArchiveVector( &m_vSaveAngles ); - arc.ArchiveVector( &m_vSkidOrigin ); - arc.ArchiveBoolean( &drivable ); - arc.ArchiveBoolean( &locked ); - arc.ArchiveBoolean( &hasweapon ); - arc.ArchiveBoolean( &showweapon ); - arc.ArchiveBoolean( &steerinplace ); - arc.ArchiveBoolean( &jumpable ); - arc.ArchiveBoolean( &m_bWheelSpinning ); - arc.ArchiveBoolean( &m_bIsSkidding ); - arc.ArchiveBoolean( &m_bIsBraking ); - arc.ArchiveBoolean( &m_bBackSlipping ); - arc.ArchiveBoolean( &m_bFrontSlipping ); - arc.ArchiveBoolean( &m_bAutomatic ); - arc.ArchiveBoolean( &m_bThinkCalled ); - arc.ArchiveBoolean( &m_bRemoveOnDeath ); - arc.ArchiveBoolean( &m_bStopEnabled ); - arc.ArchiveBoolean( &m_bEnableSkidding ); - arc.ArchiveRaw( &vs, sizeof( vehicleState_t ) ); - - if( !arc.Saving() ) - { - m_sMoveGrid = new cMoveGrid( 3, 3, 1 ); - } - - m_sMoveGrid->Archive( arc ); - - arc.ArchiveFloat( &m_fIdealSpeed ); - arc.ArchiveVector( &m_vIdealPosition ); - arc.ArchiveVector( &m_vIdealDir ); - arc.ArchiveFloat( &m_fIdealAccel ); - arc.ArchiveFloat( &m_fIdealDistance ); - arc.ArchiveFloat( &m_fLookAhead ); - arc.ArchiveBool( &m_bAutoPilot ); - arc.ArchiveSafePointer( &m_pCollisionEntity ); - ArchiveEnum( m_eSoundState, SOUND_STATE ); - arc.ArchiveFloat( &m_fNextSoundState ); - arc.ArchiveSafePointer( &m_pVehicleSoundEntities[ 0 ] ); - arc.ArchiveSafePointer( &m_pVehicleSoundEntities[ 1 ] ); - arc.ArchiveSafePointer( &m_pVehicleSoundEntities[ 2 ] ); - arc.ArchiveSafePointer( &m_pVehicleSoundEntities[ 3 ] ); -} - class DrivableVehicle : public Vehicle { public: + CLASS_PROTOTYPE(DrivableVehicle); - CLASS_PROTOTYPE(DrivableVehicle); + DrivableVehicle(void); - DrivableVehicle(void); - - virtual void Killed(Event* ev); + virtual void Killed(Event *ev) override; }; class VehicleWheelsX4 : public DrivableVehicle { private: - wheel_s m_sWheels[4]; + wheel_t m_sWheels[4]; public: - CLASS_PROTOTYPE(VehicleWheelsX4); + CLASS_PROTOTYPE(VehicleWheelsX4); - VehicleWheelsX4(); + VehicleWheelsX4(); - virtual void UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright) override; - virtual float TorqueLookup(int rpm) override; - virtual void Think() override; - virtual void Postthink() override; - virtual void Killed(Event* ev) override; + virtual void UpdateVariables( + Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright + ) override; + virtual float TorqueLookup(int rpm) override; + virtual void Think() override; + virtual void Postthink() override; + virtual void Killed(Event *ev) override; }; class VehicleWheelsX2 : public DrivableVehicle { private: - wheel_s m_sWheels[2]; + wheel_t m_sWheels[2]; public: - CLASS_PROTOTYPE(VehicleWheelsX2); + CLASS_PROTOTYPE(VehicleWheelsX2); - VehicleWheelsX2(); + VehicleWheelsX2(); - virtual void UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright) override; - virtual float TorqueLookup(int rpm) override; - virtual void Think() override; - virtual void Postthink() override; - virtual void Killed(Event* ev) override; + virtual void UpdateVariables( + Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright + ) override; + virtual float TorqueLookup(int rpm) override; + virtual void Think() override; + virtual void Postthink() override; + virtual void Killed(Event *ev) override; }; class VehicleTank : public DrivableVehicle { public: - CLASS_PROTOTYPE(VehicleTank); + CLASS_PROTOTYPE(VehicleTank); - VehicleTank(); - ~VehicleTank(); + VehicleTank(); + ~VehicleTank(); - virtual qboolean Drive(usercmd_t *ucmd) override; - void EventDamage(Event *ev); - virtual void Think() override; - virtual void Postthink() override; - virtual void CalculateOriginOffset() override; - void UpdateSound() override; - void AttachDriverSlot(Event* ev) override; + virtual void DriverAdded() override; + virtual qboolean Drive(usercmd_t *ucmd) override; + void EventDamage(Event *ev); + virtual void Think() override; + virtual void Postthink() override; + virtual void CalculateOriginOffset() override; + void UpdateSound() override; + //void AttachDriverSlot(Event* ev) override; + void AttachDriverSlot(int slot, Entity *ent, Vector vExitPosition) override; }; class VehicleHalfTrack : public DrivableVehicle { public: - CLASS_PROTOTYPE(VehicleHalfTrack); + CLASS_PROTOTYPE(VehicleHalfTrack); - VehicleHalfTrack(); + VehicleHalfTrack(); - virtual void Think() override; - virtual void Postthink() override; - virtual void Killed(Event* ev) override; + virtual void Think() override; + virtual void Postthink() override; + virtual void Killed(Event *ev) override; }; typedef SafePtr VehiclePtr; - -#endif diff --git a/code/fgame/vehicletanktandem.cpp b/code/fgame/vehicletanktandem.cpp index d6d535f5..92e42f5a 100644 --- a/code/fgame/vehicletanktandem.cpp +++ b/code/fgame/vehicletanktandem.cpp @@ -21,6 +21,45 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "vehicletanktandem.h" +#include "vehicleturret.h" -// FIXME: unimplemented +CLASS_DECLARATION(VehicleTank, VehicleTankTandem, "VehicleTankTandem") { + {NULL, NULL} +}; +VehicleTankTandem::VehicleTankTandem() +{ +} + +VehicleTankTandem::~VehicleTankTandem() +{ +} + +void VehicleTankTandem::SpawnTurret(Event *ev) +{ + VehicleTurretGunTandem* pTurret = new VehicleTurretGunTandem(); + int slot; + + pTurret->SetBaseOrientation(orientation, NULL); + pTurret->setModel(ev->GetString(2)); + + slot = ev->GetInteger(1); + AttachTurretSlot(slot, pTurret, vec_zero, NULL); + pTurret->SetVehicleOwner(this); + + pTurret->PostEvent(EV_TakeDamage, EV_POSTSPAWN); + + UpdateTurretSlot(slot); + + pTurret->ProcessPendingEvents(); +} + +void VehicleTankTandem::UpdateTurretSlot(int iSlot) +{ + VehicleTank::UpdateTurretSlot(iSlot); + + if (Turrets[iSlot].ent && Turrets[iSlot].ent->isSubclassOf(VehicleTurretGunTandem)) { + VehicleTurretGunTandem* pTurret = static_cast(Turrets[iSlot].ent.Pointer()); + pTurret->UpdateLinkedTurret(); + } +} diff --git a/code/fgame/vehicletanktandem.h b/code/fgame/vehicletanktandem.h index 64b139d4..543cc8a4 100644 --- a/code/fgame/vehicletanktandem.h +++ b/code/fgame/vehicletanktandem.h @@ -21,3 +21,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once + +#include "vehicle.h" + +class VehicleTankTandem : public VehicleTank +{ +private: + CLASS_PROTOTYPE(VehicleTankTandem); + +public: + VehicleTankTandem(); + ~VehicleTankTandem(); + + void SpawnTurret(Event *ev) override; + void UpdateTurretSlot(int iSlot) override; +}; diff --git a/code/fgame/vehicleturret.cpp b/code/fgame/vehicleturret.cpp index 3905831d..6bd57faa 100644 --- a/code/fgame/vehicleturret.cpp +++ b/code/fgame/vehicleturret.cpp @@ -30,34 +30,156 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "gibs.h" #include "scriptexception.h" -Event EV_VehicleTurretGun_SetBaseEntity( - "setbaseentity", EV_DEFAULT, "e", "base_entity", "Sets the base entity to take its orientation from." -); +static const Vector g_vUserMins(-16, -16, 0); +static const Vector g_vUserMaxs(16, 16, 96); -Event EV_VehicleTurretGun_RemoveOnDeath( +static constexpr float MAX_TANDEM_YAW_OFFSET = 0; +static constexpr float MAX_VT_PITCHCAP_OFFSET = 0; +static constexpr float MAX_VT_YAW_OFFSET = 0; + +Event EV_VehicleTurretGun_SetBaseEntity +( + "setbaseentity", + EV_DEFAULT, + "e", + "base_entity", + "Sets the base entity to take its orientation from.", + EV_NORMAL +); +Event EV_VehicleTurretGun_RemoveOnDeath +( "removeondeath", EV_DEFAULT, "i", "removeondeath", - "If set to a non-zero value, vehicles will not be removed when they die" + "If set to a non-zero value, vehicles will not be removed when they die", + EV_NORMAL ); - -Event EV_VehicleTurretGun_SetCollisionEntity( - "setcollisionentity", EV_DEFAULT, "e", "entity", "Sets the Collision Entity." +Event EV_VehicleTurretGun_SetCollisionEntity +( + "setcollisionentity", + EV_DEFAULT, + "e", + "entity", + "Sets the Collision Entity.", + EV_NORMAL ); - -Event EV_VehicleTurretGun_Lock("lock", EV_DEFAULT, NULL, NULL, "The Turret can not be used."); - -Event EV_VehicleTurretGun_Unlock("unlock", EV_DEFAULT, NULL, NULL, "The Turret Can be used."); - -Event EV_VehicleTurretGun_SoundSet("SoundSet", EV_DEFAULT, "s", "soundset", "Sets the Sound Set to use."); - -Event EV_VehicleTurretGun_CollisionEntitySetter( - "collisionent", EV_DEFAULT, "s", "entity", "Sets the Collision Entity", EV_SETTER +Event EV_VehicleTurretGun_Lock +( + "lock", + EV_DEFAULT, + NULL, + NULL, + "The turret cannot be used.", + EV_NORMAL ); - -Event EV_VehicleTurretGun_CollisionEntityGetter( - "collisionent", EV_DEFAULT, NULL, NULL, "Gets the Collision Entity", EV_GETTER +Event EV_VehicleTurretGun_Unlock +( + "unlock", + EV_DEFAULT, + NULL, + NULL, + "The turret can be used.", + EV_NORMAL +); +Event EV_VehicleTurretGun_SoundSet +( + "SoundSet", + EV_DEFAULT, + "s", + "soundset", + "Sets the Sound Set to use.", + EV_NORMAL +); +Event EV_VehicleTurretGun_CollisionEntitySetter +( + "collisionent", + EV_DEFAULT, + "e", + "entity", + "Sets the Collision Entity", + EV_SETTER +); +Event EV_VehicleTurretGun_CollisionEntityGetter +( + "collisionent", + EV_DEFAULT, + NULL, + NULL, + "Gets the Collision Entity", + EV_GETTER +); +Event EV_VehicleTurretGun_WarmupDelay +( + "warmupdelay", + EV_DEFAULT, + "f", + "value", + "Set the warmup delay before use after mounting the weapon.", + EV_NORMAL +); +Event EV_VehicleTurretGun_FireWarmupDelay +( + "firewarmupdelay", + EV_DEFAULT, + "f", + "value", + "Set the warmup delay before use after mounting the weapon.", + EV_NORMAL +); +Event EV_VehicleTurretGun_ReloadShots +( + "reloadshots", + EV_DEFAULT, + "i", + "value", + "Set the number of shots fired before forcing a reload", + EV_NORMAL +); +Event EV_VehicleTurretGun_ReloadDelay +( + "reloaddelay", + EV_DEFAULT, + "f", + "value", + "Set a delay that implies a reload. Will also play a sound", + EV_NORMAL +); +Event EV_VehicleTurretGun_AimOffset +( + "aimoffset", + EV_DEFAULT, + "v", + "value", + "Adjust aiming angles by offset.", + EV_NORMAL +); +Event EV_VehicleTurretGun_AimTolerance +( + "aimtolerance", + EV_DEFAULT, + "v", + "caps", + "Sets a tolerance for the angles.", + EV_NORMAL +); +Event EV_VehicleTurretGun_SetTargetEntity +( + "settargetentity", + EV_DEFAULT, + "e", + "ent", + "Set the entity to point the turret at visually.", + EV_NORMAL +); +Event EV_VehicleTurretGun_PlayReloadSound +( + "playreloadsound", + EV_DEFAULT, + NULL, + NULL, + "Play the turret reload sound.", + EV_NORMAL ); CLASS_DECLARATION(TurretGun, VehicleTurretGun, NULL) { @@ -70,20 +192,27 @@ CLASS_DECLARATION(TurretGun, VehicleTurretGun, NULL) { {&EV_VehicleTurretGun_SetCollisionEntity, &VehicleTurretGun::EventSetCollisionModel}, {&EV_Damage, &VehicleTurretGun::EventDamage }, {&EV_Killed, &VehicleTurretGun::EventKilled }, - {&EV_Turret_TurnSpeed, &VehicleTurretGun::EventTurnSpeed }, {&EV_VehicleTurretGun_Lock, &VehicleTurretGun::EventLock }, {&EV_VehicleTurretGun_Unlock, &VehicleTurretGun::EventUnlock }, {&EV_VehicleTurretGun_SoundSet, &VehicleTurretGun::SetSoundSet }, {&EV_VehicleTurretGun_CollisionEntitySetter, &VehicleTurretGun::EventSetCollisionModel}, {&EV_VehicleTurretGun_CollisionEntityGetter, &VehicleTurretGun::EventGetCollisionModel}, + {&EV_VehicleTurretGun_WarmupDelay, &VehicleTurretGun::SetWarmupDelay }, + {&EV_VehicleTurretGun_FireWarmupDelay, &VehicleTurretGun::SetFireWarmupDelay }, + {&EV_VehicleTurretGun_ReloadShots, &VehicleTurretGun::SetReloadShots }, + {&EV_VehicleTurretGun_ReloadDelay, &VehicleTurretGun::SetReloadDelay }, + {&EV_VehicleTurretGun_AimOffset, &VehicleTurretGun::SetAimOffset }, + {&EV_VehicleTurretGun_AimTolerance, &VehicleTurretGun::SetAimTolerance }, + {&EV_VehicleTurretGun_SetTargetEntity, &VehicleTurretGun::SetTargetEntity }, + {&EV_VehicleTurretGun_PlayReloadSound, &VehicleTurretGun::PlayReloadSound }, {NULL, NULL } }; -// FIXME - VehicleTurretGun::VehicleTurretGun() { - entflags |= EF_VEHICLETURRET; + entflags |= ECF_VEHICLETURRET; + + AddWaitTill(STRING_DEATH); if (LoadingSavegame) { return; @@ -91,38 +220,76 @@ VehicleTurretGun::VehicleTurretGun() edict->s.eType = ET_MODELANIM; setRespawn(false); - respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS; - edict->clipmask = MASK_VEHICLETURRET; - m_iIdleHitCount = 0; + + respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS; + edict->clipmask = MASK_VEHICLETURRET; + m_bUsable = true; m_bPlayerUsable = true; m_bRestable = false; m_fIdlePitchSpeed = 0; - takedamage = DAMAGE_NO; - health = 100.0f; - max_health = 100.0f; + m_iIdleHitCount = 0; + + takedamage = DAMAGE_NO; + health = 100.0f; + max_health = 100.0f; + setSize(Vector(-16, -16, 0), Vector(16, 16, 32)); - m_fTurnSpeed = 1001.0f; - m_fPitchUpCap = -45.0f; - m_fPitchDownCap = 45.0f; - m_fMaxYawOffset = 180.0f; - m_fUserDistance = 64.0f; - m_vIdleCheckOffset = Vector(-56, 0, 0); - m_bBOIsSet = false; - m_iFiring = 0; - m_fFireToggleTime = 0; - m_pBaseEntity = NULL; - m_vLastBaseAngles = vec_zero; - m_vBaseAngles = vec_zero; - m_vBarrelPos = origin; - m_vLastBarrelPos = origin; + + m_fPitchUpCap = -45; + m_fPitchDownCap = 45; + m_fMaxYawOffset = 180; + m_fTurnSpeed = 160; + m_fAIPitchSpeed = 48; + m_fUserDistance = 64.0f; + m_vIdleCheckOffset.setXYZ(-56, 0, 0); + + m_fMinBurstTime = 0; + m_fMaxBurstTime = 0; + m_fMinBurstDelay = 0; + m_fMaxBurstDelay = 0; + + AxisClear(m_mBaseOrientation); + m_fFireToggleTime = 0; + m_iFiring = 0; + m_bBOIsSet = false; + + m_pBaseEntity = NULL; + m_vLastBaseAngles = vec_zero; + m_vBaseAngles = vec_zero; + + m_vBarrelPos = origin; + m_vLastBarrelPos = origin; + m_bUseRemoteControl = false; m_pVehicleOwner = NULL; - m_bRemoveOnDeath = true; - m_eSoundState = ST_OFF; - m_bLocked = true; - m_fNextSoundState = level.time; - m_sSoundSet = ""; + + m_bRemoveOnDeath = true; + m_eSoundState = STT_OFF; + m_fNextSoundState = level.time; + + m_fWarmupDelay = 0; + m_fFireWarmupDelay = 0; + m_fTargetReloadTime = 0; + m_fWarmupTimeRemaining = 0; + m_fReloadDelay = 0; + m_fReloadTimeRemaining = 0; + + m_iReloadShots = 1; + m_iAmmo = 1; + + ammo_in_clip[FIRE_PRIMARY] = m_iAmmo; + ammo_clip_size[FIRE_PRIMARY] = m_iReloadShots; + + m_vAimOffset[0] = 0; + m_vAimOffset[1] = 0; + m_vAimOffset[2] = 0; + m_vAimTolerance[0] = 20; + m_vAimTolerance[1] = 20; + + m_bLocked = true; + m_bLockedAim = false; + m_sSoundSet = ""; } VehicleTurretGun::~VehicleTurretGun() @@ -133,15 +300,226 @@ VehicleTurretGun::~VehicleTurretGun() m_pCollisionEntity->PostEvent(EV_Remove, 0); } - entflags &= ~EF_VEHICLETURRET; + entflags &= ~ECF_VEHICLETURRET; } void VehicleTurretGun::Think(void) { - // FIXME: stub + Sentient *sentOwner; + float yawOffset, pitchOffset; + + if (m_pCollisionEntity) { + m_pCollisionEntity->NotSolid(); + } + + sentOwner = GetSentientOwner(); + + if (g_gametype->integer == GT_SINGLE_PLAYER && m_pRemoteOwner && m_pRemoteOwner->isSubclassOf(Player)) { + // always render the turret + edict->s.renderfx |= RF_DEPTHHACK; + } else { + edict->s.renderfx &= ~RF_DEPTHHACK; + } + + UpdateTimers(yawOffset, pitchOffset); + + if (owner) { + UpdateAndMoveOwner(); + UpdateCaps(yawOffset, pitchOffset); + } else if (m_bUseRemoteControl) { + UpdateRemoteControl(); + UpdateCaps(yawOffset, pitchOffset); + } else if (aim_target) { + UpdateAimTarget(); + UpdateCaps(yawOffset, pitchOffset); + } else if (m_bRestable) { + IdleToRestPosition(); + } + + UpdateOrientation(false); + UpdateSound(); + UpdateFireControl(); + + if (sentOwner) { + G_TouchTriggers(sentOwner); + UpdateOwner(sentOwner); + } + + UpdateCollisionEntity(); } -void VehicleTurretGun::SetBaseOrientation(float (*borientation)[3], float *bangles) +void VehicleTurretGun::P_UserAim(usercmd_t *ucmd) +{ + Vehicle *pVehicle; + int slot; + int newSlot; + + TurretGun::P_UserAim(ucmd); + + if (ucmd->buttons & BUTTON_ATTACKRIGHT) { + m_bLockedAim = false; + return; + } + + if (m_bLockedAim) { + return; + } + + if (m_iFiring) { + m_bLockedAim = false; + return; + } + + if (!m_pVehicleOwner) { + // Added in OPM + return; + } + + if (!m_pVehicleOwner->IsSubclassOfVehicle()) { + return; + } + + pVehicle = static_cast(m_pVehicleOwner.Pointer()); + slot = pVehicle->FindTurretSlotByEntity(this); + newSlot = slot + 1; + if (newSlot == pVehicle->numTurrets) { + newSlot = 0; + } + + if (newSlot != slot) { + Entity *slotEnt; + + slotEnt = pVehicle->QueryTurretSlotEntity(newSlot); + // slotEnt check: + // Added in OPM + if (slotEnt && slotEnt->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *existing; + Vector newAng; + bool wasThisLocked, wasExistingLocked; + + existing = static_cast(slotEnt); + + wasThisLocked = m_bLocked; + wasExistingLocked = existing->m_bLocked; + m_bLocked = false; + existing->m_bLocked = false; + + newAng = existing->m_vUserViewAng; + m_vUserLastCmdAng = vec_zero; + + pVehicle->AttachTurretSlot(newSlot, owner, vec_zero, NULL); + existing->m_vUserViewAng = newAng; + + owner = NULL; + edict->r.ownerNum = ENTITYNUM_NONE; + + if (wasThisLocked) { + m_bLocked = true; + } + if (wasExistingLocked) { + existing->m_bLocked = true; + } + + existing->m_bLockedAim = true; + m_bLockedAim = false; + } + } +} + +void VehicleTurretGun::TurretBeginUsed(Sentient *pEnt) +{ + if (m_pVehicleOwner) { + Vehicle *pVehicle = (Vehicle *)m_pVehicleOwner.Pointer(); + int slot = pVehicle->FindTurretSlotByEntity(this); + + pVehicle->UpdateTurretSlot(slot); + m_vBaseAngles = m_pVehicleOwner->angles; + } + + owner = pEnt; + edict->r.ownerNum = pEnt->entnum; + m_bHadOwner = true; + + Sound(sPickupSound); + + owner->SetViewAngles(m_vBaseAngles); + + m_vUserViewAng = m_vBaseAngles; + m_vUserViewAng[0] = AngleNormalize180(m_vUserViewAng[0]); + m_vUserLastCmdAng.setXYZ(0, 0, 0); + + setAngles(m_vBaseAngles); + + if (owner->IsSubclassOfPlayer()) { + Player *player = (Player *)owner.Pointer(); + + player->EnterTurret(this); + + if (!m_pUserCamera) { + m_pUserCamera = new Camera; + } + + player->SetCamera(m_pUserCamera, 0.5); + m_pUserCamera->setAngles(m_vBaseAngles); + } + + UpdateOwner(owner); + flags &= ~FL_THINK; + current_attachToTag = ""; + ForceIdle(); + P_CreateViewModel(); +} + +void VehicleTurretGun::TurretEndUsed(void) +{ + if (owner->IsSubclassOfPlayer()) { + Player *player = (Player *)owner.Pointer(); + + RemoveUserCamera(); + player->ExitTurret(); + P_DeleteViewModel(); + } + + owner = NULL; + edict->r.ownerNum = ENTITYNUM_NONE; + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + m_iFiring = 0; + m_vTargetAngles = m_vLocalAngles; +} + +void VehicleTurretGun::TurretUsed(Sentient *pEnt) +{ + if (!owner) { + TurretBeginUsed(pEnt); + return; + } + + if (owner == pEnt) { + TurretEndUsed(); + } +} + +void VehicleTurretGun::TurretUsed(Event *ev) +{ + Sentient *pEnt = (Sentient *)ev->GetEntity(1); + + if (!pEnt || !pEnt->IsSubclassOfSentient()) { + return; + } + + if (!m_bUsable || m_bLocked) { + return; + } + + if (pEnt->IsSubclassOfPlayer() && !m_bPlayerUsable) { + return; + } + + TurretUsed(pEnt); +} + +void VehicleTurretGun::SetBaseOrientation(const vec3_t borientation[3], const vec3_t bangles) { m_bBOIsSet = true; @@ -172,206 +550,140 @@ void VehicleTurretGun::SetBaseEntity(Entity *e) flags |= FL_THINK; } -void VehicleTurretGun::SetVehicleOwner(Entity *e) -{ - m_pVehicleOwner = e; -} - -void VehicleTurretGun::SetRemoteOwner(Sentient *e) -{ - m_bUseRemoteControl = true; - m_pRemoteOwner = e; -} - -void VehicleTurretGun::RemoteControl(usercmd_t *ucmd, Sentient *owner) {} - -void VehicleTurretGun::CollisionCorrect(trace_t *pTr) {} - -void VehicleTurretGun::UpdateOrientation(bool bCollisionCheck) {} - -void VehicleTurretGun::UpdateSound(void) -{ - if (level.time < m_fNextSoundState) { - return; - } - - float fDiff = AngleSubtract(m_vTargetAngles[1], m_vLocalAngles[1]); - - switch (m_eSoundState) { - case ST_OFF: - StopLoopSound(); - m_fNextSoundState = level.time; - if (fabs(fDiff) > 0.5f) { - m_eSoundState = ST_OFF_TRANS_IDLE; - } - break; - - case ST_OFF_TRANS_IDLE: - m_eSoundState = ST_IDLE_TRANS_OFF; - m_fNextSoundState = level.time; - LoopSound(m_sSoundSet + "snd_move"); - break; - - case ST_IDLE_TRANS_OFF: - m_fNextSoundState = level.time; - if (fabs(fDiff) < 0.5f) { - m_eSoundState = ST_IDLE; - } - - LoopSound(m_sSoundSet + "snd_move"); - break; - - case ST_IDLE: - m_eSoundState = ST_OFF; - m_fNextSoundState = level.time; - LoopSound(m_sSoundSet + "snd_move"); - break; - - default: - // FIXME: default sound? - break; - } -} - -void VehicleTurretGun::UpdateOwner(Sentient *pOwner) -{ - // FIXME: stub - STUB(); -} - void VehicleTurretGun::SetBaseEntity(Event *ev) { SetBaseEntity(ev->GetEntity(1)); + + flags |= FL_THINK; } -void VehicleTurretGun::PlaceTurret(Event *ev) +void VehicleTurretGun::RemoteControl(usercmd_t *ucmd, Sentient *owner) { - setSolidType(SOLID_BBOX); - edict->r.contents = CONTENTS_UNKNOWN2; - setMoveType(MOVETYPE_NONE); - showModel(); - groundentity = NULL; - m_fStartYaw = angles[1]; - flags |= FL_THINK; - m_vLastBaseAngles = angles; - m_vBaseAngles = angles; + Vector vNewCmdAng; - if (m_vBaseAngles.length() != 0.0f) { - AnglesToAxis(m_vBaseAngles, m_mBaseOrientation); - m_bBOIsSet = true; + if (!ucmd || !owner) { + return; + } + + vNewCmdAng = Vector(SHORT2ANGLE(ucmd->angles[0]), SHORT2ANGLE(ucmd->angles[1]), SHORT2ANGLE(ucmd->angles[2])); + + if (vNewCmdAng[0] || vNewCmdAng[1] || vNewCmdAng[2]) { + m_vUserViewAng[0] += AngleSubtract(vNewCmdAng[0], m_vUserLastCmdAng[0]); + m_vUserViewAng[1] += AngleSubtract(vNewCmdAng[1], m_vUserLastCmdAng[1]); + m_vUserViewAng[2] += AngleSubtract(vNewCmdAng[2], m_vUserLastCmdAng[2]); + } + + m_vUserLastCmdAng = vNewCmdAng; + + if (!m_bUseRemoteControl) { + m_bUseRemoteControl = true; + m_pRemoteOwner = owner; + m_vUserViewAng = m_vLocalAngles; + + GetRemoteOwner()->SetViewAngles(m_vUserViewAng + m_vBaseAngles); + } + + if (ucmd->buttons & (BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT)) { + if (!m_iFiring) { + m_iFiring = 1; + } + } else { + m_iFiring = 0; + m_fTargetReloadTime = 0; + flags |= FL_THINK; + } +} + +void VehicleTurretGun::UpdateOrientation(bool bCollisionCheck) +{ + Entity *ent; + Vector localAngles; + vec3_t mat[3]; + + if (m_pBaseEntity) { + ent = m_pBaseEntity; + } else if (edict->s.parent) { + ent = G_GetEntity(edict->s.parent); + } else { + ent = NULL; } m_iPitchBone = gi.Tag_NumForName(edict->tiki, "pitch"); - SetControllerTag(0, m_iPitchBone); - m_iBarrelTag = gi.Tag_NumForName(edict->tiki, "tag_barrel"); + m_iBarrelTag = gi.Tag_NumForName(edict->tiki, GetTagBarrel()); m_iEyeBone = gi.Tag_NumForName(edict->tiki, "eyebone"); - if (m_pRemoteOwner || owner) { - if (m_pRemoteOwner) { - UpdateOwner(m_pRemoteOwner); - } else { - UpdateOwner(owner); - } - } -} + if (m_iBarrelTag >= 0) { + orientation_t barrel_or; -void VehicleTurretGun::TurretBeginUsed(Sentient *pEnt) -{ - if (m_pVehicleOwner) { - Vehicle *pVehicle = (Vehicle *)m_pVehicleOwner.Pointer(); - int slot = pVehicle->FindTurretSlotByEntity(this); - - pVehicle->UpdateTurretSlot(slot); - m_vBaseAngles = m_pVehicleOwner->angles; + GetTagPositionAndOrientation(m_iBarrelTag, &barrel_or); + m_vLastBarrelPos = m_vBarrelPos; + m_vBarrelPos = barrel_or.origin; } - owner = pEnt; + if (bCollisionCheck && m_iBarrelTag >= 0) { + trace_t trace; + // check if the new barrel position is ok + trace = G_Trace( + m_vLastBarrelPos, + Vector(8, 8, 8), + Vector(-8, -8, -8), + m_vBarrelPos, + this, + edict->clipmask, + qfalse, + "VehicleTurretGun::Think.BarrelCheck" + ); - edict->r.ownerNum = pEnt->entnum; - m_bHadOwner = true; - - Sound(sPickupSound); - - owner->SetViewAngles(m_vBaseAngles); - - m_vUserViewAng = m_vBaseAngles; - m_vUserViewAng[0] = AngleNormalize180(m_vUserViewAng[0]); - m_vUserLastCmdAng = vec_zero; - - setAngles(m_vBaseAngles); - - if (owner->IsSubclassOfPlayer()) { - Player *player = (Player *)owner.Pointer(); - - player->EnterTurret(this); - - if (!m_pUserCamera) { - m_pUserCamera = new Camera; + if (trace.fraction == 1 || trace.startsolid || trace.allsolid) { + CollisionCorrect(&trace); } - - player->SetCamera(m_pUserCamera, 0.0f); - m_pUserCamera->setAngles(m_vBaseAngles); } - UpdateOwner(owner); - flags &= ~FL_THINK; - current_attachToTag = ""; - ForceIdle(); - CreateViewModel(); -} + localAngles = m_vLocalAngles; -void VehicleTurretGun::TurretEndUsed(void) -{ - if (owner->IsSubclassOfPlayer()) { - Player *player = (Player *)owner.Pointer(); - - if (m_pUserCamera) { - player->SetCamera(NULL, 0); - player->ZoomOff(); - m_pUserCamera->PostEvent(EV_Remove, 0); - m_pUserCamera = NULL; - } - - player->ExitTurret(); - DeleteViewModel(); + if (m_iPitchBone >= 0) { + vec3_t controllerAngles = {localAngles[0], 0, 0}; + SetControllerAngles(0, controllerAngles); + localAngles[0] = 0; } - owner = NULL; - edict->r.ownerNum = ENTITYNUM_NONE; - m_fIdlePitchSpeed = 0; - m_iIdleHitCount = 0; - m_iFiring = 0; -} + AnglesToAxis(localAngles, mat); -void VehicleTurretGun::TurretUsed(Sentient *pEnt) -{ - if (owner) { - if (owner == pEnt) { - TurretEndUsed(); - m_iFiring = 0; - } + if (m_bBOIsSet) { + vec3_t BOmat[3]; + + MatrixMultiply(mat, m_mBaseOrientation, BOmat); + MatrixToEulerAngles(BOmat, angles); + setAngles(angles); } else { - TurretBeginUsed(pEnt); + setAngles(localAngles); } } -void VehicleTurretGun::TurretUsed(Event *ev) +void VehicleTurretGun::CollisionCorrect(trace_t *pTr) { - Sentient *pEnt = (Sentient *)ev->GetEntity(1); + float planedot; - if (!pEnt || !pEnt->IsSubclassOfSentient()) { + if (pTr->plane.normal == vec_zero) { return; } - if (!m_bUsable || m_bLocked) { - return; + if (pTr->plane.normal[2]) { + if (pTr->plane.normal[2] > 0) { + m_vLocalAngles[0] -= m_fAIPitchSpeed * level.frametime; + } else { + m_vLocalAngles[0] += m_fAIPitchSpeed * level.frametime; + } } - if (pEnt->IsSubclassOfPlayer() && !m_bPlayerUsable) { - return; + planedot = DotProduct(pTr->plane.normal, orientation[1]); + if (fabs(planedot) > 0.25f) { + if (planedot > 0) { + m_vLocalAngles[1] += m_fTurnSpeed * level.frametime; + } else { + m_vLocalAngles[1] -= m_fTurnSpeed * level.frametime; + } } - - TurretUsed(pEnt); } void VehicleTurretGun::EventKilled(Event *ev) @@ -421,38 +733,114 @@ void VehicleTurretGun::EventKilled(Event *ev) void VehicleTurretGun::EventDamage(Event *ev) { - Event *event = new Event(ev); + if (g_gametype->integer == GT_TOW && !dmManager.RoundActive()) { + return; + } if (owner) { - owner->ProcessEvent(event); + owner->ProcessEvent(*ev); return; } if (m_pVehicleOwner) { - m_pVehicleOwner->ProcessEvent(event); + m_pVehicleOwner->ProcessEvent(*ev); return; } if (!m_bUseRemoteControl) { - DamageEvent(event); + meansOfDeath_t mod = static_cast(ev->GetInteger(9)); + switch (mod) { + case MOD_BULLET: + case MOD_BASH: + case MOD_FAST_BULLET: + case MOD_VEHICLE: + case MOD_SHOTGUN: + return; + default: + break; + } + + Entity::DamageEvent(ev); return; } - if (m_pRemoteOwner && m_pRemoteOwner->IsSubclassOfPlayer()) { - Player *player = (Player *)m_pRemoteOwner.Pointer(); + if (m_pRemoteOwner && m_pRemoteOwner->IsSubclassOfSentient()) { + Sentient *sent = static_cast(m_pRemoteOwner.Pointer()); - if (player->m_pVehicle) { - player->m_pVehicle->ProcessEvent(event); + if (sent->GetVehicle()) { + sent->GetVehicle()->ProcessEvent(*ev); return; } } } +void VehicleTurretGun::SetVehicleOwner(Entity *e) +{ + m_pVehicleOwner = e; +} + void VehicleTurretGun::EventRemoveOnDeath(Event *ev) { m_bRemoveOnDeath = ev->GetBoolean(1); } +void VehicleTurretGun::UpdateSound(void) +{ + float fPitchDiff, fYawDiff, fDiff; + + if (level.time < m_fNextSoundState) { + return; + } + + fYawDiff = fabs(AngleSubtract(m_vTargetAngles[1], m_vLocalAngles[1])); + fPitchDiff = fabs(AngleSubtract(m_vTargetAngles[0], m_vLocalAngles[0])); + if (fYawDiff > fPitchDiff) { + fDiff = fYawDiff; + } else { + fDiff = fPitchDiff; + } + + if (!owner && !m_bUseRemoteControl && !aim_target && !m_bRestable) { + fDiff = 0; + } + + switch (m_eSoundState) { + case STT_OFF: + StopLoopSound(); + m_fNextSoundState = level.time; + if (fabs(fDiff) > 0.5f) { + m_eSoundState = STT_OFF_TRANS_MOVING; + } + break; + + case STT_OFF_TRANS_MOVING: + m_fNextSoundState = level.time; + m_eSoundState = STT_MOVING; + Sound(m_sSoundSet + "snd_move_start"); + break; + + case STT_MOVING: + m_fNextSoundState = level.time; + if (fDiff < 0.5) { + m_eSoundState = STT_MOVING_TRANS_OFF; + } + LoopSound(m_sSoundSet + "snd_move"); + break; + + case STT_MOVING_TRANS_OFF: + m_fNextSoundState = level.time; + m_eSoundState = STT_OFF; + StopLoopSound(); + Sound(m_sSoundSet + "snd_move_stop"); + break; + + default: + m_fNextSoundState = level.time; + m_eSoundState = STT_OFF; + break; + } +} + void VehicleTurretGun::EventSetCollisionModel(Event *ev) { Entity *pColEnt = ev->GetEntity(1); @@ -462,33 +850,27 @@ void VehicleTurretGun::EventSetCollisionModel(Event *ev) } if (m_pCollisionEntity) { - m_pCollisionEntity->PostEvent(EV_Remove, EV_VEHICLE); + m_pCollisionEntity->PostEvent(EV_Remove, 0); } m_pCollisionEntity = new VehicleCollisionEntity(this); - m_pCollisionEntity->setModel(pColEnt->model); + if (m_pCollisionEntity) { + m_pCollisionEntity->setModel(pColEnt->model); + m_pCollisionEntity->setOrigin(origin); + m_pCollisionEntity->setAngles(angles); - if (!m_pCollisionEntity->model.length() || *m_pCollisionEntity->model != '*') { - // Re-post the event with the correct time - m_pCollisionEntity->CancelEventsOfType(EV_Remove); - m_pCollisionEntity->PostEvent(EV_Remove, EV_VEHICLE); - m_pCollisionEntity = NULL; + if (m_pCollisionEntity->model.length() && *m_pCollisionEntity->model == '*') { + UpdateCollisionEntity(); + m_pCollisionEntity->DisconnectPaths(); + } else { + // Re-post the event with the correct time + m_pCollisionEntity->CancelEventsOfType(EV_Remove); + m_pCollisionEntity->PostEvent(EV_Remove, EV_VEHICLE); + m_pCollisionEntity = NULL; - ScriptError("Model for Entity not of a valid type. Must be B-Model."); + ScriptError("Model for Entity not of a valid type. Must be B-Model."); + } } - - m_pCollisionEntity->setOrigin(origin); - m_pCollisionEntity->setAngles(angles); -} - -void VehicleTurretGun::EventGetCollisionModel(Event *ev) -{ - ev->AddEntity(m_pCollisionEntity); -} - -void VehicleTurretGun::EventTurnSpeed(Event *ev) -{ - TurnSpeed(ev->GetFloat(1)); } void VehicleTurretGun::EventLock(Event *ev) @@ -506,10 +888,840 @@ void VehicleTurretGun::SetSoundSet(Event *ev) m_sSoundSet = ev->GetString(1); } -bool VehicleTurretGun::TurretHasBeenMounted() +void VehicleTurretGun::UpdateOwner(Sentient *pOwner) { - // FIXME: unimplemented - return false; + Vector jitter; + Vector position; + Vector forward, left, up; + orientation_t bone_or; + + if (m_iEyeBone >= 0) { + GetRawTag(m_iEyeBone, &bone_or); + angles.AngleVectorsLeft(&forward, &left, &up); + + position = origin + bone_or.origin[0] * forward + bone_or.origin[1] * left + bone_or.origin[2] * up; + } else { + (m_vBaseAngles + m_vLocalAngles).AngleVectorsLeft(&forward, &left, &up); + + position = origin + forward * -16 + up * 5; + + if (m_iPitchBone >= 0) { + GetRawTag(m_iPitchBone, &bone_or); + angles.AngleVectorsLeft(&forward, &left, &up); + + position += bone_or.origin[0] * forward + bone_or.origin[1] * left + bone_or.origin[2] * up; + } else { + angles.AngleVectorsLeft(&forward, NULL, &up); + position += up * 40; + } + } + + jitter = m_vUserViewAng + m_vBaseAngles; + P_ApplyFiringViewJitter(jitter); + + if (!m_pUserCamera && pOwner->IsSubclassOfPlayer()) { + Player *player = static_cast(pOwner); + + m_pUserCamera = new Camera(); + player->SetCamera(m_pUserCamera, 0.5); + } + + if (owner) { + jitter[1] = m_vUserViewAng[1]; + } + + m_pUserCamera->setOrigin(position); + m_pUserCamera->setAngles(jitter); + + if (GetTag("tag_seat", &bone_or)) { + vec3_t ang; + + pOwner->setOrigin(bone_or.origin); + MatrixToEulerAngles(bone_or.axis, ang); + pOwner->setAngles(ang); + } else { + // no seat + pOwner->setOrigin(origin); + } + + if (pOwner->IsSubclassOfPlayer()) { + Player *player = static_cast(pOwner); + + if (!player->IsZoomed()) { + player->ToggleZoom(80); + } + + player->client->ps.camera_flags |= CF_CAMERA_ANGLES_TURRETMODE; + } +} + +void VehicleTurretGun::TurretHasBeenMounted() +{ + m_fLastFireTime = (level.time + m_fWarmupDelay) - fire_delay[FIRE_PRIMARY]; + if (m_fWarmupDelay > 0.25) { + Sound(m_sSoundSet + "snd_warmup"); + } + + m_fWarmupTimeRemaining = m_fWarmupDelay; +} + +void VehicleTurretGun::PlaceTurret(Event *ev) +{ + setSolidType(SOLID_BBOX); + setContents(CONTENTS_UNKNOWN2); + setMoveType(MOVETYPE_NONE); + showModel(); + groundentity = NULL; + m_fStartYaw = angles[1]; + flags |= FL_THINK; + m_vLastBaseAngles = angles; + m_vBaseAngles = angles; + + if (m_vBaseAngles.length() != 0.0f) { + AnglesToAxis(m_vBaseAngles, m_mBaseOrientation); + m_bBOIsSet = true; + } + + m_iPitchBone = gi.Tag_NumForName(edict->tiki, "pitch"); + SetControllerTag(0, m_iPitchBone); + m_iBarrelTag = gi.Tag_NumForName(edict->tiki, GetTagBarrel()); + m_iEyeBone = gi.Tag_NumForName(edict->tiki, "eyebone"); + + if (m_pRemoteOwner) { + UpdateOwner(m_pRemoteOwner); + } else if (owner) { + UpdateOwner(owner); + } +} + +void VehicleTurretGun::EventTurnSpeed(Event *ev) +{ + AI_TurnSpeed(ev->GetFloat(1)); +} + +bool VehicleTurretGun::UseRemoteControl(void) +{ + return m_bUseRemoteControl; +} + +qboolean VehicleTurretGun::ReadyToFire(firemode_t mode, qboolean playsound) +{ + if (!use_no_ammo) { + return Weapon::ReadyToFire(mode, playsound); + } + + if (m_fReloadDelay <= 0) { + return Weapon::ReadyToFire(mode, playsound); + } + + if (m_fReloadTimeRemaining <= 0) { + return Weapon::ReadyToFire(mode, playsound); + } + + return qfalse; +} + +void VehicleTurretGun::AdjustReloadStatus() +{ + if (!use_no_ammo) { + return; + } + + if (m_fReloadDelay <= 0) { + return; + } + + m_iAmmo--; + ammo_in_clip[FIRE_PRIMARY] = m_iAmmo; + if (!m_iAmmo) { + m_iAmmo = m_iReloadShots; + m_fReloadTimeRemaining = m_fReloadDelay; + + if (g_target_game <= target_game_e::TG_MOHTA) { + // + // Below 2.30 (Spearhead), the sound is played immediately. + // 2.30 has it wrong with the Nebelwerfer. + // + ProcessEvent(EV_VehicleTurretGun_PlayReloadSound); + return; + } + + // + // Changed in 2.30 + // Play the reload sound once finished reloading + PostEvent(EV_VehicleTurretGun_PlayReloadSound, m_fReloadDelay * 0.5); + } +} + +void VehicleTurretGun::GetMuzzlePosition(vec3_t position, vec3_t vBarrelPos, vec3_t forward, vec3_t right, vec3_t up) +{ + Vector delta; + Vector aim_angles; + Sentient *viewer; + orientation_t barrel_or; + vec3_t weap_axis[3]; + float mat[3][3]; + int i; + + viewer = owner; + if (!owner) { + viewer = GetRemoteOwner(); + } + + if (!viewer) { + if (forward || right || up) { + if (!m_bUseRemoteControl && aim_target) { + Vector dir; + Vector vAng; + Vector vFwd; + + AngleVectors(angles, vFwd, right, up); + delta = aim_target->origin; + + if (aim_target->HasVehicle()) { + delta.z -= 60; + } + + dir = delta - origin; + VectorNormalize(dir); + dir.x = vFwd.x; + dir.y = vFwd.y; + VectorNormalize(dir); + VectorToAngles(dir, vAng); + AngleVectors(vAng, forward, right, up); + } else { + AngleVectors(angles, forward, right, up); + } + } + + VectorCopy(origin, position); + + if (GetRawTag(GetTagBarrel(), &barrel_or)) { + AnglesToAxis(angles, weap_axis); + + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_axis[i], position); + } + } + + if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } + } else if (viewer->IsSubclassOfPlayer()) { + VectorCopy(origin, position); + + if (GetRawTag(GetTagBarrel(), &barrel_or)) { + AnglesToAxis(angles, weap_axis); + + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_axis[i], position); + } + } + + if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } + + delta = viewer->GunTarget(false, position) - position; + aim_angles = delta.toAngles(); + + if (IsSubclassOfVehicleTurretGun()) { + vec3_t ang; + + MatrixMultiply(barrel_or.axis, weap_axis, mat); + vectoangles(mat[0], ang); + + for (i = 0; i < 2; i++) { + float diff; + + diff = abs(AngleSubtract(aim_angles[i], ang[i])); + if (diff > m_vAimTolerance[i]) { + aim_angles[i] = m_vAimOffset[i] + ang[i]; + } + } + } + + if (forward || right || up) { + AngleVectors(aim_angles, forward, right, up); + } + } else { + TurretGun::GetMuzzlePosition(position, vBarrelPos, forward, right, up); + } +} + +void VehicleTurretGun::ApplyFireKickback(const Vector& org, float kickback) +{ + Vehicle *pVehicle; + + if (!m_pVehicleOwner || !m_pVehicleOwner->IsSubclassOfVehicle()) { + return; + } + + if (g_target_game <= target_game_e::TG_MOH) { + // Don't apply fire kickback in older version + // this could cause issues as models weren't made for this feature + return; + } + + // Added in 2.0 + + pVehicle = static_cast(m_pVehicleOwner.Pointer()); + pVehicle->m_fForwardForce += org.x * kickback; + pVehicle->m_fLeftForce += org.y * kickback; +} + +void VehicleTurretGun::SetRemoteOwner(Sentient *e) +{ + m_bUseRemoteControl = true; + m_pRemoteOwner = e; + flags |= FL_THINK; +} + +void VehicleTurretGun::EventGetCollisionModel(Event *ev) +{ + ev->AddEntity(m_pCollisionEntity); +} + +float VehicleTurretGun::FireDelay(firemode_t mode) +{ + return fire_delay[mode]; +} + +void VehicleTurretGun::SetWarmupDelay(Event *ev) +{ + m_fWarmupDelay = ev->GetFloat(1); +} + +void VehicleTurretGun::SetFireWarmupDelay(Event *ev) +{ + m_fFireWarmupDelay = ev->GetFloat(1); +} + +void VehicleTurretGun::SetReloadDelay(Event *ev) +{ + m_fReloadDelay = ev->GetFloat(1); +} + +void VehicleTurretGun::SetReloadShots(Event *ev) +{ + m_iReloadShots = ev->GetInteger(1); + m_iAmmo = m_iReloadShots; + ammo_in_clip[FIRE_PRIMARY] = m_iAmmo; + ammo_clip_size[FIRE_PRIMARY] = m_iAmmo; +} + +void VehicleTurretGun::SetAimOffset(Event *ev) +{ + m_vAimOffset = ev->GetVector(1); +} + +void VehicleTurretGun::SetAimTolerance(Event *ev) +{ + m_vAimTolerance = ev->GetVector(1); +} + +void VehicleTurretGun::SetTargetEntity(Event *ev) +{ + SetTargetEntity(ev->GetEntity(1)); +} + +void VehicleTurretGun::PlayReloadSound(Event *ev) +{ + Sound(m_sSoundSet + "snd_reload", CHAN_AUTO); +} + +void VehicleTurretGun::SetTargetEntity(Entity *ent) +{ + Vector delta; + int i; + + if (!ent) { + return; + } + + if (owner || m_pRemoteOwner) { + return; + } + + delta = ent->origin - origin; + delta.normalize(); + + vectoangles(delta, m_vLocalAngles); + m_vLocalAngles -= m_vBaseAngles; + + for (i = 0; i < 2; i++) { + if (m_vLocalAngles[i] > 180) { + m_vLocalAngles[i] -= 360; + } + + if (m_vLocalAngles[i] < -180) { + m_vLocalAngles[i] += 360; + } + } + + m_vLocalAngles[0] = Q_clamp_float(m_vLocalAngles[0], m_fPitchUpCap, m_fPitchDownCap); + m_vLocalAngles[1] = Q_clamp_float(m_vLocalAngles[1], -(m_fStartYaw + m_fMaxYawOffset), m_fStartYaw + m_fMaxYawOffset); + + UpdateOrientation(false); +} + +void VehicleTurretGun::UpdateAndMoveOwner() +{ + Vector delta; + Vector dir; + Vector targetAngles; + Entity *parentEnt; + float fDiff; + + parentEnt = GetParent(); + + m_vUserViewAng[0] = Q_clamp_float(m_vUserViewAng[0], m_fPitchUpCap - MAX_VT_PITCHCAP_OFFSET, m_fPitchDownCap + MAX_VT_PITCHCAP_OFFSET); + + fDiff = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + fDiff = Q_clamp_float(fDiff, -(m_fMaxYawOffset + MAX_VT_YAW_OFFSET), m_fMaxYawOffset + MAX_VT_YAW_OFFSET); + m_vUserViewAng[1] = m_fStartYaw + fDiff; + + owner->SetViewAngles(m_vUserViewAng + m_vBaseAngles); + delta = owner->GunTarget(true) - origin; + + if (m_bBOIsSet) { + dir[0] = m_mBaseOrientation[0] * delta; + dir[1] = m_mBaseOrientation[1] * delta; + dir[2] = m_mBaseOrientation[2] * delta; + } else if (parentEnt) { + vec3_t mat[3]; + + AnglesToAxis(parentEnt->angles, mat); + dir[0] = mat[0] * delta; + dir[1] = mat[1] * delta; + dir[2] = mat[2] * delta; + } else { + dir = delta; + } + + VectorNormalize(dir); + vectoangles(dir, m_vTargetAngles); +} + +void VehicleTurretGun::UpdateTimers(float& yawTimer, float& pitchTimer) +{ + if (m_fReloadTimeRemaining > 0) { + m_fReloadTimeRemaining -= level.frametime; + if (m_fReloadTimeRemaining <= 0) { + ammo_in_clip[FIRE_PRIMARY] = m_iAmmo; + } + } + + if (m_fWarmupTimeRemaining > 0) { + m_fWarmupTimeRemaining -= level.frametime; + yawTimer = level.frametime * (m_fTurnSpeed * ((m_fWarmupDelay - m_fWarmupTimeRemaining) / m_fWarmupDelay)); + pitchTimer = level.frametime * (m_fAIPitchSpeed * ((m_fWarmupDelay - m_fWarmupTimeRemaining) / m_fWarmupDelay)); + } else { + yawTimer = m_fTurnSpeed * level.frametime; + pitchTimer = m_fAIPitchSpeed * level.frametime; + } +} + +void VehicleTurretGun::UpdateCaps(float maxYawOffset, float maxPitchOffset) +{ + float fDiff; + + if (m_vTargetAngles[0] > 180) { + m_vTargetAngles[0] -= 360; + } else if (m_vTargetAngles[0] < -180) { + m_vTargetAngles[0] += 360; + } + + m_vTargetAngles[0] = Q_clamp_float(m_vTargetAngles[0], m_fPitchUpCap, m_fPitchDownCap); + + if (m_fAIPitchSpeed > 1000) { + m_vLocalAngles[0] = m_vTargetAngles[0]; + } else { + fDiff = AngleSubtract(m_vTargetAngles[0], m_vLocalAngles[0]); + if (fabs(fDiff) >= maxPitchOffset) { + if (fDiff > 0) { + m_vLocalAngles[0] += maxPitchOffset; + } else { + m_vLocalAngles[0] -= maxPitchOffset; + } + } else { + m_vLocalAngles[0] = m_vTargetAngles[0]; + } + } + + fDiff = AngleSubtract(m_vTargetAngles[1], m_fStartYaw); + fDiff = Q_clamp_float(fDiff, -m_fMaxYawOffset, m_fMaxYawOffset); + + if (m_fTurnSpeed > 1000) { + m_vLocalAngles[1] = m_vTargetAngles[1]; + } else { + m_vTargetAngles[1] = m_fStartYaw + fDiff; + + fDiff = AngleSubtract(m_vTargetAngles[1], m_vLocalAngles[1]); + if (fabs(fDiff) < 2) { + Unregister(STRING_ONTARGET); + } + + if (fabs(fDiff) >= maxYawOffset) { + if (fDiff > 0) { + m_vLocalAngles[1] += maxYawOffset; + } else { + m_vLocalAngles[1] -= maxYawOffset; + } + } else { + m_vLocalAngles[1] = m_vTargetAngles[1]; + } + } +} + +void VehicleTurretGun::IdleToRestPosition() +{ + Vector vDir, vNewAngles, vEnd; + trace_t trace; + + if (angles[0] > 180) { + angles[0] -= 360; + } + + if (angles[0] < -80) { + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + return; + } + + if (m_iIdleHitCount > 1) { + return; + } + + m_fIdlePitchSpeed -= level.frametime * 300; + + vNewAngles = Vector(angles[0] + level.frametime * m_fIdlePitchSpeed, angles[1], angles[2]); + vNewAngles.AngleVectorsLeft(&vDir); + vEnd = origin + vDir * m_vIdleCheckOffset[0]; + + trace = G_Trace(origin, vec_zero, vec_zero, vEnd, this, edict->clipmask, false, "TurretGun::Think idle"); + + if (trace.fraction == 1) { + setAngles(vNewAngles); + m_iIdleHitCount = 0; + return; + } + + int iTry; + for (iTry = 3; iTry > 0; iTry--) { + vNewAngles[0] = angles[0] + level.frametime * m_fIdlePitchSpeed * iTry * 0.25f; + if (vNewAngles[0] < m_fMaxIdlePitch) { + continue; + } + + vNewAngles.AngleVectorsLeft(&vDir); + vEnd = origin + vDir * m_vIdleCheckOffset[0]; + + trace = G_Trace(origin, vec_zero, vec_zero, vEnd, this, edict->clipmask, false, "TurretGun::Think idle"); + + if (trace.fraction == 1) { + setAngles(vNewAngles); + + m_iIdleHitCount = 0; + m_fIdlePitchSpeed *= 0.25f * iTry; + break; + } + } + + if (!iTry) { + m_fIdlePitchSpeed = 0; + + Entity *ent = G_GetEntity(trace.entityNum); + + if (ent && ent == world) { + m_iIdleHitCount++; + } else { + m_iIdleHitCount = 0; + } + } +} + +void VehicleTurretGun::UpdateFireControl() +{ + if (!m_iFiring) { + return; + } + + if (m_iFiring == 1) { + if (m_fFireWarmupDelay > 0) { + Sound(m_sSoundSet + "snd_fire_warmup"); + m_fTargetReloadTime = level.time + m_fFireWarmupDelay; + m_iFiring = 2; + } else { + m_iFiring = 3; + } + } else if (m_iFiring == 2) { + if (level.time >= m_fTargetReloadTime) { + m_iFiring = 3; + } + } + + if (m_iFiring <= 2) { + return; + } + + if (!m_fMaxBurstDelay) { + m_iFiring = 4; + + if (ReadyToFire(FIRE_PRIMARY, false)) { + Fire(FIRE_PRIMARY); + assert(!m_pVehicleOwner || (m_pVehicleOwner && m_pVehicleOwner->IsSubclassOfVehicle())); + + m_fCurrViewJitter = m_fViewJitter; + AdjustReloadStatus(); + + if (m_pVehicleOwner && m_pVehicleOwner->IsSubclassOfVehicleTank()) { + VehicleTank *tank = static_cast(m_pVehicleOwner.Pointer()); + tank->KickSuspension(Vector(orientation[1]) * -1, 6); + } + } + } else if (m_iFiring == 4) { + if (ReadyToFire(FIRE_PRIMARY, false)) { + Fire(FIRE_PRIMARY); + assert(!m_pVehicleOwner || (m_pVehicleOwner && m_pVehicleOwner->IsSubclassOfVehicle())); + + m_fCurrViewJitter = m_fViewJitter; + AdjustReloadStatus(); + + if (m_pVehicleOwner && m_pVehicleOwner->IsSubclassOfVehicleTank()) { + VehicleTank *tank = static_cast(m_pVehicleOwner.Pointer()); + tank->KickSuspension(Vector(orientation[1]) * -1, 6); + } + + if (level.time > m_fFireToggleTime) { + m_iFiring = 1; + m_fFireToggleTime = level.time + m_fMinBurstDelay + (m_fMaxBurstDelay - m_fMinBurstDelay) * random(); + } + } + } else if (level.time > m_fFireToggleTime) { + m_iFiring = 4; + m_fFireToggleTime = level.time + m_fMinBurstDelay + (m_fMaxBurstDelay - m_fMinBurstDelay) * random(); + } +} + +void VehicleTurretGun::UpdateCollisionEntity() +{ + Sentient *sentOwner; + Vector amove; + Vector newAngles; + solid_t oldsolid; + + if (!m_pCollisionEntity) { + return; + } + + setSolidType(SOLID_NOT); + + sentOwner = GetSentientOwner(); + if (sentOwner) { + oldsolid = sentOwner->edict->solid; + sentOwner->setSolidType(SOLID_NOT); + } + + m_pCollisionEntity->Solid(); + if (m_iPitchBone < 0) { + newAngles = angles; + } else if (m_bBOIsSet) { + vec3_t axis[3]; + vec3_t mat[3]; + + AnglesToAxis(m_vLocalAngles, axis); + MatrixMultiply(axis, m_mBaseOrientation, mat); + MatrixToEulerAngles(mat, newAngles); + } else { + newAngles = m_vLocalAngles; + } + + amove[0] = angledist(newAngles[0] - m_pCollisionEntity->angles[0]); + amove[1] = angledist(newAngles[1] - m_pCollisionEntity->angles[1]); + amove[2] = angledist(newAngles[2] - m_pCollisionEntity->angles[2]); + + G_PushMove(m_pCollisionEntity, origin - m_pCollisionEntity->origin, amove); + + m_pCollisionEntity->setOrigin(origin); + m_pCollisionEntity->setAngles(newAngles); + m_pCollisionEntity->velocity = velocity; + m_pCollisionEntity->avelocity = avelocity; + + if (sentOwner) { + sentOwner->setSolidType(static_cast(oldsolid)); + } +} + +void VehicleTurretGun::RestrictPitch() +{ + m_vUserViewAng[0] = Q_clamp_float(m_vUserViewAng[0], m_fPitchUpCap - MAX_VT_PITCHCAP_OFFSET, m_fPitchDownCap + MAX_VT_PITCHCAP_OFFSET); +} + +void VehicleTurretGun::RestrictYaw() +{ + float fDiff; + + fDiff = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + fDiff = Q_clamp_float(fDiff, -(m_fMaxYawOffset + MAX_VT_YAW_OFFSET), m_fMaxYawOffset + MAX_VT_YAW_OFFSET); + + m_vUserViewAng[1] = m_fStartYaw + fDiff; +} + +void VehicleTurretGun::UpdateRemoteControl() +{ + Sentient *sentOwner; + Vector position; + Vector forward, left, up; + Vector start, end; + Vector delta; + Vector transformed; + trace_t trace; + + RestrictPitch(); + RestrictYaw(); + + sentOwner = GetSentientOwner(); + if (!sentOwner) { + return; + } + + sentOwner->SetViewAngles(m_vUserViewAng + m_vBaseAngles); + + if (m_iEyeBone < 0) { + (m_vUserViewAng + m_vBaseAngles).AngleVectors(&forward); + end = m_pRemoteOwner->origin + forward * 16384; + + trace = + G_Trace(m_pRemoteOwner->origin, vec_zero, vec_zero, end, this, MASK_TRANSPARENT, qfalse, "VehicleTurret"); + + position = trace.endpos; + } else { + orientation_t eye_or; + + GetRawTag(m_iEyeBone, &eye_or); + angles.AngleVectorsLeft(&forward, &left, &up); + + start = origin + forward * eye_or.origin[0] + left * eye_or.origin[1] + up * eye_or.origin[2]; + (m_vUserViewAng + m_vBaseAngles).AngleVectorsLeft(&forward); + + end = start + forward * 8192; + + trace = G_Trace(start, vec_zero, vec_zero, end, this, MASK_TRANSPARENT, qfalse, "VehicleTurret"); + + position = trace.endpos; + } + + delta = position - origin; + + if (m_bBOIsSet) { + transformed[0] = m_mBaseOrientation[0] * delta; + transformed[1] = m_mBaseOrientation[1] * delta; + transformed[2] = m_mBaseOrientation[2] * delta; + } else if (GetParent()) { + vec3_t mat[3]; + + AnglesToAxis(GetParent()->angles, mat); + transformed[0] = mat[0] * delta; + transformed[1] = mat[1] * delta; + transformed[2] = mat[2] * delta; + } else { + transformed = delta; + } + + VectorNormalize(transformed); + vectoangles(transformed, m_vTargetAngles); +} + +void VehicleTurretGun::UpdateAimTarget() +{ + Vector delta; + Vector transformed; + + delta = aim_target->centroid - centroid; + if (m_bBOIsSet) { + transformed[0] = m_mBaseOrientation[0] * delta; + transformed[1] = m_mBaseOrientation[1] * delta; + transformed[2] = m_mBaseOrientation[2] * delta; + } else if (GetParent()) { + vec3_t mat[3]; + + AnglesToAxis(GetParent()->angles, mat); + transformed[0] = mat[0] * delta; + transformed[1] = mat[1] * delta; + transformed[2] = mat[2] * delta; + } else { + transformed = delta; + } + + VectorNormalize(transformed); + vectoangles(transformed, m_vTargetAngles); +} + +Entity *VehicleTurretGun::GetParent() const +{ + if (m_pBaseEntity) { + return m_pBaseEntity; + } + + if (edict->s.parent) { + return G_GetEntity(edict->s.parent); + } + + return NULL; +} + +SentientPtr VehicleTurretGun::GetRemoteOwner(void) +{ + return m_pRemoteOwner; +} + +SentientPtr VehicleTurretGun::GetSentientOwner() +{ + if (IsRemoteControlled()) { + return GetRemoteOwner(); + } else { + return owner; + } +} + +void VehicleTurretGun::EndRemoteControl() +{ + m_bUseRemoteControl = false; + m_pRemoteOwner = NULL; + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + m_iFiring = 0; + m_vTargetAngles = m_vLocalAngles; + + // Added in OPM + // Clear the camera shake/jitter + m_fCurrViewJitter = 0; + + // + // Added in OPM. + // The camera must be removed after ending the remote control. + RemoveUserCamera(); +} + +float VehicleTurretGun::GetWarmupFraction() const +{ + float frac; + + if (!m_fTargetReloadTime) { + return 0; + } + + frac = (m_fTargetReloadTime - level.time) / m_fFireWarmupDelay; + // Clamp between [0,1] + frac = Q_clamp_float(frac, 0, 1); + + return 1.0 - frac; +} + +bool VehicleTurretGun::IsRemoteControlled() +{ + return m_bUseRemoteControl; } bool VehicleTurretGun::isLocked(void) @@ -527,60 +1739,473 @@ void VehicleTurretGun::UnLock(void) m_bLocked = false; } -bool VehicleTurretGun::UseRemoteControl(void) -{ - return m_bUseRemoteControl; -} - -void VehicleTurretGun::RestrictPitch() -{ - // FIXME: unimplemented -} - -void VehicleTurretGun::RestrictYaw() -{ - // FIXME: unimplemented -} - -void VehicleTurretGun::UpdateRemoteControl() -{ - // FIXME: unimplemented -} - -void VehicleTurretGun::UpdateAimTarget() -{ - // FIXME: unimplemented -} - -Entity *VehicleTurretGun::GetParent() const -{ - // FIXME: unimplemented - return NULL; -} - -SentientPtr VehicleTurretGun::GetRemoteOwner(void) -{ - return m_pRemoteOwner; -} - -SentientPtr VehicleTurretGun::GetSentientOwner() -{ - // FIXME: unimplemented - return m_pRemoteOwner; -} - -void VehicleTurretGun::EndRemoteControl() -{ - // FIXME: unimplemented -} - -float VehicleTurretGun::GetWarmupFraction() const -{ - // FIXME: unimplemented - return 0; -} - void VehicleTurretGun::Archive(Archiver& arc) { - // FIXME: unimplemented -} \ No newline at end of file + TurretGun::Archive(arc); + + arc.ArchiveVector(&m_vTargetAngles); + arc.ArchiveVector(&m_vLocalAngles); + arc.ArchiveVec3(m_mBaseOrientation[0]); + arc.ArchiveVec3(m_mBaseOrientation[1]); + arc.ArchiveVec3(m_mBaseOrientation[2]); + arc.ArchiveInteger(&m_iPitchBone); + arc.ArchiveVector(&m_vBaseAngles); + arc.ArchiveVector(&m_vLastBaseAngles); + arc.ArchiveSafePointer(&m_pBaseEntity); + arc.ArchiveBool(&m_bBOIsSet); + arc.ArchiveBool(&m_bUseRemoteControl); + arc.ArchiveSafePointer(&m_pRemoteOwner); + arc.ArchiveInteger(&m_iBarrelTag); + arc.ArchiveInteger(&m_iEyeBone); + arc.ArchiveVector(&m_vBarrelPos); + arc.ArchiveVector(&m_vLastBarrelPos); + arc.ArchiveFloat(&m_fWarmupTimeRemaining); + arc.ArchiveFloat(&m_fWarmupDelay); + arc.ArchiveFloat(&m_fFireWarmupDelay); + arc.ArchiveFloat(&m_fTargetReloadTime); + arc.ArchiveInteger(&m_iReloadShots); + arc.ArchiveInteger(&m_iAmmo); + arc.ArchiveFloat(&m_fReloadDelay); + arc.ArchiveFloat(&m_fReloadTimeRemaining); + arc.ArchiveVector(&m_vAimOffset); + arc.ArchiveVector(&m_vAimTolerance); + arc.ArchiveSafePointer(&m_pVehicleOwner); + arc.ArchiveBool(&m_bRemoveOnDeath); + ArchiveEnum(m_eSoundState, SOUND_STATE_TURRET); + arc.ArchiveFloat(&m_fNextSoundState); + arc.ArchiveBool(&m_bLocked); + arc.ArchiveString(&m_sSoundSet); + arc.ArchiveSafePointer(&m_pCollisionEntity); +} + +EntityPtr VehicleTurretGun::GetVehicle() const +{ + return m_pVehicleOwner; +} + +SentientPtr VehicleTurretGun::GetRawRemoteOwner() const +{ + return m_pRemoteOwner; +} + +Event EV_VTGP_LinkTurret +( + "linkturret", + EV_DEFAULT, + "s", + "name", + "Sets the next turret in the link.", + EV_NORMAL +); + +// Added in 2.30 +Event EV_VTGP_SetSwitchThread +( + "setswitchthread", + EV_DEFAULT, + "s", + "thread", + "Set the thread to execute when turret is switched", + EV_NORMAL +); + +CLASS_DECLARATION(VehicleTurretGun, VehicleTurretGunTandem, "VehicleTurretGunTandem") { + {&EV_VTGP_LinkTurret, &VehicleTurretGunTandem::EventLinkTurret }, + + // Added in 2.30 + {&EV_VTGP_SetSwitchThread, &VehicleTurretGunTandem::EventSetSwitchThread}, + {NULL, NULL } +}; + +VehicleTurretGunTandem::VehicleTurretGunTandem() +{ + m_Slot.ent = NULL; + m_Slot.flags = SLOT_FREE; + m_Slot.boneindex = -1; + m_Slot.enter_boneindex = -1; + + m_PrimaryTurret = NULL; + m_HeadTurret = this; + m_ActiveTurret = NULL; + + m_fSwitchTimeRemaining = 0; + // 1 second switch delay + m_fSwitchDelay = 1; +} + +VehicleTurretGunTandem::~VehicleTurretGunTandem() +{ + // + // Added in 2.30 + // Also remove linked turrets + // + if (m_Slot.ent) { + m_Slot.ent->PostEvent(EV_Remove, 0); + } +} + +void VehicleTurretGunTandem::EventLinkTurret(Event *ev) +{ + VehicleTurretGunTandem *linkedTurret; + + linkedTurret = new VehicleTurretGunTandem(); + linkedTurret->SetBaseOrientation(orientation, NULL); + linkedTurret->setModel(ev->GetString(1)); + + AttachLinkedTurret(linkedTurret); + UpdateLinkedTurret(); +} + +void VehicleTurretGunTandem::AttachLinkedTurret(Entity *ent) +{ + if (!ent) { + return; + } + + OpenSlotsByModel(); + m_Slot.ent = ent; + m_Slot.flags = SLOT_BUSY; + ent->takedamage = DAMAGE_NO; + ent->PostEvent(EV_BecomeNonSolid, level.frametime); + + // process every end of frame + flags |= FL_POSTTHINK; + + m_Slot.ent->setAngles(angles); + + if (m_PrimaryTurret) { + VehicleTurretGunTandem *pTurret = static_cast(m_Slot.ent.Pointer()); + pTurret->SetPrimaryTurret(m_PrimaryTurret); + } else { + VehicleTurretGunTandem *pTurret = static_cast(m_Slot.ent.Pointer()); + pTurret->SetPrimaryTurret(this); + } +} + +void VehicleTurretGunTandem::UpdateLinkedTurret() +{ + VehicleTurretGun *pTurret; + orientation_t tag_or; + + if (!(m_Slot.flags & SLOT_BUSY) || !m_Slot.ent) { + return; + } + if (m_Slot.boneindex == -1) { + m_Slot.ent->setOrigin(origin); + m_Slot.ent->avelocity = avelocity; + m_Slot.ent->velocity = velocity; + + pTurret = static_cast(m_Slot.ent.Pointer()); + pTurret->SetBaseOrientation(orientation, NULL); + } else { + GetTag(m_Slot.boneindex, &tag_or); + + m_Slot.ent->setOrigin(tag_or.origin); + m_Slot.ent->avelocity = avelocity; + m_Slot.ent->velocity = velocity; + + pTurret = static_cast(m_Slot.ent.Pointer()); + pTurret->SetBaseOrientation(tag_or.axis, NULL); + } +} + +void VehicleTurretGunTandem::OpenSlotsByModel() +{ + int tagnum; + + tagnum = gi.Tag_NumForName(edict->tiki, "turret0"); + if (tagnum >= 0) { + m_Slot.boneindex = tagnum; + m_Slot.ent = NULL; + m_Slot.flags = SLOT_FREE; + } +} + +void VehicleTurretGunTandem::Think() +{ + if (m_PrimaryTurret) { + ThinkSecondary(); + } else { + ThinkPrimary(); + } +} + +bool VehicleTurretGunTandem::IsRemoteControlled() +{ + if (m_PrimaryTurret) { + return m_PrimaryTurret->m_bUseRemoteControl; + } else { + return m_bUseRemoteControl; + } +} + +SentientPtr VehicleTurretGunTandem::GetRemoteOwner() +{ + if (m_PrimaryTurret) { + return m_PrimaryTurret->m_pRemoteOwner; + } else { + return m_pRemoteOwner; + } +} + +void VehicleTurretGunTandem::EndRemoteControl() +{ + // + // Added in OPM. + // This cleanups remove control stuff from the main turret and linked turrets. + VehicleTurretGun::EndRemoteControl(); + + if (m_HeadTurret && m_HeadTurret != this) { + return m_HeadTurret->EndRemoteControl(); + } +} + +void VehicleTurretGunTandem::ThinkSecondary() +{ + float yawOffset, pitchOffset; + Sentient *sentOwner; + + if (g_gametype->integer == GT_SINGLE_PLAYER && m_PrimaryTurret->edict->s.renderfx & RF_DEPTHHACK) { + edict->s.renderfx |= RF_DEPTHHACK; + } + + if (m_pCollisionEntity) { + m_pCollisionEntity->NotSolid(); + } + + UpdateTimers(yawOffset, pitchOffset); + + if (IsRemoteControlled() && IsActiveTurret()) { + UpdateRemoteControl(); + UpdateCaps(yawOffset, pitchOffset); + } else if (m_bRestable) { + IdleToRestPosition(); + } + + UpdateOrientation(false); + UpdateSound(); + UpdateFireControl(); + + sentOwner = GetSentientOwner(); + if (IsActiveTurret() && sentOwner) { + G_TouchTriggers(sentOwner); + UpdateOwner(sentOwner); + } + + UpdateCollisionEntity(); +} + +void VehicleTurretGunTandem::ThinkPrimary() +{ + float yawOffset, pitchOffset; + Sentient *sentOwner; + + if (m_fSwitchTimeRemaining > 0) { + m_fSwitchTimeRemaining -= level.frametime; + } + + if (m_ActiveTurret && m_ActiveTurret != m_HeadTurret) { + m_fSwitchTimeRemaining = m_fSwitchDelay; + m_HeadTurret->m_pUserCamera->PostEvent(EV_Remove, 0); + m_HeadTurret->m_pUserCamera = NULL; + + // switch to the active turret + m_HeadTurret = m_ActiveTurret; + m_ActiveTurret = NULL; + + // clear angles + m_vUserLastCmdAng = vec_zero; + m_HeadTurret->m_vUserLastCmdAng = vec_zero; + m_vTargetAngles = m_vLocalAngles; + } + + if (m_pCollisionEntity) { + m_pCollisionEntity->NotSolid(); + } + + if (g_gametype->integer == GT_SINGLE_PLAYER && m_pRemoteOwner && m_pRemoteOwner->isSubclassOf(Player)) { + // always render the turret + edict->s.renderfx |= RF_DEPTHHACK; + } else { + edict->s.renderfx &= ~RF_DEPTHHACK; + } + + UpdateTimers(yawOffset, pitchOffset); + + if (IsRemoteControlled()) { + UpdateRemoteControl(); + UpdateCaps(yawOffset, pitchOffset); + } else if (m_bRestable) { + IdleToRestPosition(); + } + + UpdateOrientation(false); + UpdateSound(); + UpdateFireControl(); + + sentOwner = GetSentientOwner(); + if (IsActiveTurret() && sentOwner) { + G_TouchTriggers(sentOwner); + UpdateOwner(sentOwner); + } + + UpdateCollisionEntity(); +} + +void VehicleTurretGunTandem::SetPrimaryTurret(VehicleTurretGunTandem *pTurret) +{ + m_PrimaryTurret = pTurret; + if (m_PrimaryTurret) { + m_HeadTurret = NULL; + } +} + +void VehicleTurretGunTandem::RemoteControl(usercmd_t *ucmd, Sentient *owner) +{ + Vector vNewCmdAng; + + if (!ucmd || !owner) { + return; + } + + if (m_HeadTurret && m_HeadTurret != this) { + m_HeadTurret->RemoteControlSecondary(ucmd, owner); + return; + } + + vNewCmdAng = Vector(SHORT2ANGLE(ucmd->angles[0]), SHORT2ANGLE(ucmd->angles[1]), SHORT2ANGLE(ucmd->angles[2])); + + if (m_vUserLastCmdAng[0] || m_vUserLastCmdAng[1] || m_vUserLastCmdAng[2]) { + m_vUserViewAng[0] += AngleSubtract(vNewCmdAng[0], m_vUserLastCmdAng[0]); + m_vUserViewAng[1] += AngleSubtract(vNewCmdAng[1], m_vUserLastCmdAng[1]); + m_vUserViewAng[2] += AngleSubtract(vNewCmdAng[2], m_vUserLastCmdAng[2]); + } + + m_vUserLastCmdAng = vNewCmdAng; + + RemoteControlFire(ucmd, owner); +} + +void VehicleTurretGunTandem::RemoteControlSecondary(usercmd_t *ucmd, Sentient *owner) +{ + Vector vNewCmdAng; + + if (!ucmd || !owner) { + return; + } + + vNewCmdAng = Vector(SHORT2ANGLE(ucmd->angles[0]), SHORT2ANGLE(ucmd->angles[1]), SHORT2ANGLE(ucmd->angles[2])); + + if (m_vUserLastCmdAng[0] || m_vUserLastCmdAng[1] || m_vUserLastCmdAng[2]) { + m_vUserViewAng[0] += AngleSubtract(vNewCmdAng[0], m_vUserLastCmdAng[0]); + m_vUserViewAng[1] += AngleSubtract(vNewCmdAng[1], m_vUserLastCmdAng[1]); + m_vUserViewAng[2] += AngleSubtract(vNewCmdAng[2], m_vUserLastCmdAng[2]); + } + + m_vUserLastCmdAng = vNewCmdAng; + + RemoteControlFire(ucmd, owner); +} + +void VehicleTurretGunTandem::RemoteControlFire(usercmd_t *ucmd, Sentient *owner) +{ + if (ucmd->buttons & BUTTON_ATTACKLEFT) { + if (!m_iFiring) { + m_iFiring = 1; + } + } else { + if (ucmd->buttons & BUTTON_ATTACKRIGHT) { + SwitchToLinkedTurret(); + } + m_iFiring = 0; + } + + flags |= FL_THINK; +} + +void VehicleTurretGunTandem::EventSetSwitchThread(Event *ev) +{ + if (ev->IsFromScript()) { + m_SwitchLabel.SetThread(ev->GetValue(1)); + } else { + m_SwitchLabel.Set(ev->GetString(1)); + } +} + +void VehicleTurretGunTandem::SwitchToLinkedTurret() +{ + VehicleTurretGunTandem *pTurret; + + if (GetPrimaryTurret()->m_fSwitchTimeRemaining > 0) { + return; + } + + if (m_Slot.ent) { + pTurret = static_cast(m_Slot.ent.Pointer()); + // Added in 2.30 + m_SwitchLabel.Execute(this, pTurret, NULL); + } else { + pTurret = m_PrimaryTurret; + // Added in 2.30 + if (m_PrimaryTurret) { + // Fixed in OPM + // Check for primary turret before setting the switch label + m_PrimaryTurret->m_SwitchLabel.Execute(this, pTurret, NULL); + } + } + + SetActiveTurret(pTurret); +} + +void VehicleTurretGunTandem::SetActiveTurret(VehicleTurretGunTandem *pTurret) +{ + if (m_PrimaryTurret) { + if (!m_PrimaryTurret->m_ActiveTurret) { + m_PrimaryTurret->m_ActiveTurret = pTurret; + } + } else if (!m_ActiveTurret) { + m_ActiveTurret = pTurret; + } +} + +void VehicleTurretGunTandem::RestrictYaw() +{ + float delta; + + delta = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + delta = Q_clamp_float(delta, -(m_fMaxYawOffset + MAX_VT_YAW_OFFSET), m_fMaxYawOffset + MAX_VT_YAW_OFFSET); + + m_vUserViewAng[1] = m_fStartYaw + delta; +} + +void VehicleTurretGunTandem::Archive(Archiver& arc) +{ + VehicleTurretGun::Archive(arc); + + m_Slot.Archive(arc); + arc.ArchiveSafePointer(&m_PrimaryTurret); + arc.ArchiveSafePointer(&m_HeadTurret); + arc.ArchiveSafePointer(&m_ActiveTurret); + arc.ArchiveFloat(&m_fSwitchTimeRemaining); + arc.ArchiveFloat(&m_fSwitchDelay); + // Added in 2.30 + m_SwitchLabel.Archive(arc); +} + +VehicleTurretGunTandem *VehicleTurretGunTandem::GetPrimaryTurret() +{ + if (m_PrimaryTurret) { + return m_PrimaryTurret; + } else { + return this; + } +} + +bool VehicleTurretGunTandem::IsActiveTurret() const +{ + if (!m_PrimaryTurret) { + return m_HeadTurret == this; + } + + return m_PrimaryTurret->m_HeadTurret == this; +} diff --git a/code/fgame/vehicleturret.h b/code/fgame/vehicleturret.h index 2382bd41..97244137 100644 --- a/code/fgame/vehicleturret.h +++ b/code/fgame/vehicleturret.h @@ -23,12 +23,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // vehicleturret.h: Vehicle Turret. // -#ifndef __VEHICLETURRET_H__ -#define __VEHICLETURRET_H__ +#pragma once #include "weapturret.h" #include "vehicle.h" +typedef enum { + STT_OFF, + STT_OFF_TRANS_MOVING, + STT_MOVING, + STT_MOVING_TRANS_OFF +} SOUND_STATE_TURRET; + class VehicleTurretGun : public TurretGun { friend class Vehicle; @@ -43,28 +49,46 @@ protected: int m_iPitchBone; bool m_bBOIsSet; bool m_bUseRemoteControl; - SentientPtr m_pRemoteOwner; int m_iBarrelTag; int m_iEyeBone; SafePtr m_pVehicleOwner; bool m_bRemoveOnDeath; SafePtr m_pCollisionEntity; bool m_bLocked; - SOUND_STATE m_eSoundState; + bool m_bLockedAim; + SOUND_STATE_TURRET m_eSoundState; float m_fNextSoundState; str m_sSoundSet; + // added in 2.0 + //=== + float m_fWarmupDelay; + float m_fWarmupTimeRemaining; + float m_fFireWarmupDelay; + float m_fTargetReloadTime; + int m_iReloadShots; + int m_iAmmo; + float m_fReloadDelay; + float m_fReloadTimeRemaining; + Vector m_vAimTolerance; + SentientPtr m_pRemoteOwner; + //=== + public: CLASS_PROTOTYPE(VehicleTurretGun); Vector m_vBarrelPos; Vector m_vLastBarrelPos; + // added in 2.0 + Vector m_vAimOffset; VehicleTurretGun(); virtual ~VehicleTurretGun(); - void Think(void) override; - void SetBaseOrientation(float (*borientation)[3], float *bangles); + void Think(void) override; + void P_UserAim(usercmd_t *ucmd) override; + + void SetBaseOrientation(const vec3_t borientation[3], const vec3_t bangles); void SetBaseEntity(Entity *e); void SetVehicleOwner(Entity *e); void SetRemoteOwner(Sentient *e); @@ -99,20 +123,89 @@ public: virtual bool IsRemoteControlled(); virtual void RestrictPitch(); virtual void RestrictYaw(); - virtual bool TurretHasBeenMounted(); + virtual void TurretHasBeenMounted(); void UpdateRemoteControl(); void UpdateAimTarget(); Entity *GetParent() const; float GetWarmupFraction() const; + qboolean ReadyToFire(firemode_t mode, qboolean playsound) override; + void AdjustReloadStatus(); + void GetMuzzlePosition(vec3_t position, vec3_t vBarrelPos, vec3_t forward, vec3_t right, vec3_t up) override; + void ApplyFireKickback(const Vector &org, float kickback) override; + float FireDelay(firemode_t mode) override; + + // Added in 2.0 + //==== + void SetWarmupDelay(Event *ev); + void SetFireWarmupDelay(Event *ev); + void SetReloadDelay(Event *ev); + void SetReloadShots(Event *ev); + void SetAimOffset(Event *ev); + void SetAimTolerance(Event *ev); + void SetTargetEntity(Event *ev); + //==== + void PlayReloadSound(Event *ev); // Added in 2.30 + void SetTargetEntity(Entity *ent); + void UpdateAndMoveOwner(); + void UpdateTimers(float &yawTimer, float &pitchTimer); + void UpdateCaps(float maxYawOffset, float maxPitchOffset); + void IdleToRestPosition(); + void UpdateFireControl(); + void UpdateCollisionEntity(); + EntityPtr GetVehicle() const; + SentientPtr GetRawRemoteOwner() const; + void Archive(Archiver& arc) override; }; -inline bool VehicleTurretGun::IsRemoteControlled() +// +// Added in 2.0 +// +class VehicleTurretGunTandem : public VehicleTurretGun { - // FIXME: unimplemented - return false; -} +private: + cTurretSlot m_Slot; + SafePtr m_PrimaryTurret; + SafePtr m_HeadTurret; + SafePtr m_ActiveTurret; + float m_fSwitchTimeRemaining; + float m_fSwitchDelay; + ScriptThreadLabel m_SwitchLabel; -#endif // __VEHICLETURRET_H__ +public: + CLASS_PROTOTYPE(VehicleTurretGunTandem); + +public: + VehicleTurretGunTandem(); + ~VehicleTurretGunTandem(); + + virtual void EventLinkTurret(Event *ev); + virtual void EventSetSwitchThread(Event *ev); // Added in 2.30 + virtual void AttachLinkedTurret(Entity *ent); + virtual void UpdateLinkedTurret(); + virtual void OpenSlotsByModel(); + + void Think() override; + bool IsRemoteControlled() override; + SentientPtr GetRemoteOwner() override; + void EndRemoteControl() override; // Added in OPM + + virtual void SetPrimaryTurret(VehicleTurretGunTandem *pTurret); + virtual void SetActiveTurret(VehicleTurretGunTandem *pTurret); + VehicleTurretGunTandem *GetPrimaryTurret(); + bool IsActiveTurret() const; + + void RemoteControl(usercmd_t *ucmd, Sentient *owner) override; + virtual void RemoteControlSecondary(usercmd_t *ucmd, Sentient *owner); + virtual void RemoteControlFire(usercmd_t *ucmd, Sentient *owner); + + virtual void SwitchToLinkedTurret(); + virtual void ThinkPrimary(); + virtual void ThinkSecondary(); + + void RestrictYaw() override; + + void Archive(Archiver& arc) override; +}; diff --git a/code/fgame/viewthing.cpp b/code/fgame/viewthing.cpp index 260ad8b2..75f5ab99 100644 --- a/code/fgame/viewthing.cpp +++ b/code/fgame/viewthing.cpp @@ -418,7 +418,7 @@ void ViewMaster::Spawn { Viewthing *viewthing; - const char *mdl; + str mdl; Vector forward; Vector up; Vector delta; @@ -467,7 +467,7 @@ void ViewMaster::Spawn if( !gi.modeltiki( viewthing->model ) ) { - ScriptError( "model %s not found, viewmodel not spawned.", mdl ); + ScriptError( "model %s not found, viewmodel not spawned.", mdl.c_str() ); delete viewthing; current_viewthing = NULL; return; @@ -480,7 +480,7 @@ void ViewMaster::SetModelEvent ) { - const char *mdl; + str mdl; char str[ 128 ]; Event *event; Viewthing *viewthing; @@ -537,8 +537,7 @@ void ViewMaster::PassEvent viewthing = ( Viewthing * )( ( Entity * )current_viewthing ); if ( viewthing ) { - event = new Event( ev ); - viewthing->ProcessEvent( event ); + viewthing->ProcessEvent( *ev ); } } diff --git a/code/fgame/viewthing.h b/code/fgame/viewthing.h index 29763439..fc466257 100644 --- a/code/fgame/viewthing.h +++ b/code/fgame/viewthing.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // viewthing.h: Actor code for the viewthing. // -#ifndef __VIEWTHING_H__ -#define __VIEWTHING_H__ +#pragma once #include "animate.h" @@ -113,5 +112,3 @@ inline void Viewthing::Archive arc.ArchiveVector( &baseorigin ); arc.ArchiveRaw( origSurfaces, sizeof( origSurfaces ) ); } - -#endif /* viewthing.h */ diff --git a/code/fgame/weapon.cpp b/code/fgame/weapon.cpp index bc549a05..2d7de504 100644 --- a/code/fgame/weapon.cpp +++ b/code/fgame/weapon.cpp @@ -142,7 +142,8 @@ Event EV_Weapon_FillClip ); Event EV_Weapon_EmptyClip ( - "clip_empty", EV_DEFAULT, + "clip_empty", + EV_DEFAULT, NULL, NULL, "Empties the weapon's clip of ammo," @@ -194,7 +195,14 @@ Event EV_Weapon_DMSetFireDelay "Set the minimum time between shots from the weapon", EV_NORMAL ); -Event EV_Weapon_NotDroppable("notdroppable", EV_DEFAULT, NULL, NULL, "Makes a weapon not droppable"); +Event EV_Weapon_NotDroppable +( + "notdroppable", + EV_DEFAULT, + NULL, + NULL, + "Makes a weapon not droppable" +); Event EV_Weapon_SetAimAnim ( "setaimanim", @@ -204,8 +212,14 @@ Event EV_Weapon_SetAimAnim "Set the aim animation and frame for when a weapon fires", EV_NORMAL ); -Event - EV_Weapon_SetRank("rank", EV_DEFAULT, "ii", "iOrder iRank", "Set the order value and power ranking for the weapon"); +Event EV_Weapon_SetRank +( + "rank", + EV_DEFAULT, + "ii", + "iOrder iRank", + "Set the order value and power ranking for the weapon" +); Event EV_Weapon_SetFireType ( "firetype", @@ -215,7 +229,8 @@ Event EV_Weapon_SetFireType "Set the firing type of the weapon (projectile or bullet)", EV_NORMAL ); -Event EV_Weapon_SetAIRange( +Event EV_Weapon_SetAIRange +( "airange", EV_DEFAULT, "s", @@ -349,7 +364,8 @@ Event EV_Weapon_SetDMBulletRange "Set the range of the bullets", EV_NORMAL ); -Event EV_Weapon_SetBulletSpread( +Event EV_Weapon_SetBulletSpread +( "bulletspread", EV_DEFAULT, "ffFF", @@ -357,7 +373,8 @@ Event EV_Weapon_SetBulletSpread( "Set the min & optional max spread of the bullet in the x and y axis", EV_NORMAL ); -Event EV_Weapon_SetDMBulletSpread( +Event EV_Weapon_SetDMBulletSpread +( "dmbulletspread", EV_DEFAULT, "ffFF", @@ -653,7 +670,8 @@ Event EV_Weapon_SetMeansOfDeath "Set the meansOfDeath of the weapon.", EV_NORMAL ); -Event EV_Weapon_SetWorldHitSpawn( +Event EV_Weapon_SetWorldHitSpawn +( "worldhitspawn", EV_DEFAULT, "s", @@ -869,6 +887,30 @@ Event EV_OverCooked_Warning EV_NORMAL ); +// +// Added in OPM +// + +Event EV_Weapon_DoneAnimating +( + "doneanimating", + EV_DEFAULT, + NULL, + NULL, + "Signals the end of animation", + EV_NORMAL +); + +Event EV_Weapon_GetPutaway +( + "putaway", + EV_DEFAULT, + NULL, + NULL, + "Returns whether or not the given weapon is being put away", + EV_GETTER +); + CLASS_DECLARATION(Item, Weapon, NULL) { {&EV_SetAnim, &Weapon::SetWeaponAnimEvent }, {&EV_Item_Pickup, &Weapon::PickupWeapon }, @@ -886,7 +928,7 @@ CLASS_DECLARATION(Item, Weapon, NULL) { {&EV_Weapon_AddToClip, &Weapon::AddToAmmoClip }, {&EV_Weapon_SetMaxRange, &Weapon::SetMaxRangeEvent }, {&EV_Weapon_SetMinRange, &Weapon::SetMinRangeEvent }, - {&EV_Weapon_FireDelay, &Weapon::SetFireDelay }, + {&EV_Weapon_FireDelay, &Weapon::SetFireDelay }, {&EV_Weapon_NotDroppable, &Weapon::NotDroppableEvent }, {&EV_Weapon_SetAimAnim, &Weapon::SetAimAnim }, {&EV_Weapon_Shoot, &Weapon::Shoot }, @@ -965,6 +1007,11 @@ CLASS_DECLARATION(Item, Weapon, NULL) { {&EV_OverCooked_Warning, &Weapon::OnOverCookedWarning }, {&EV_Weapon_SetCurrentFireAnim, &Weapon::SetCurrentFireAnim }, {&EV_Weapon_SetSecondaryAmmoInHud, &Weapon::SetSecondaryAmmoInHud }, + // + // Added in OPM + // + {&EV_Weapon_DoneAnimating, &Weapon::DoneAnimating }, + {&EV_Weapon_GetPutaway, &Weapon::EventGetPutaway }, {NULL, NULL } }; @@ -973,7 +1020,7 @@ CLASS_DECLARATION(Item, Weapon, NULL) { //====================== Weapon::Weapon() { - entflags |= EF_WEAPON; + entflags |= ECF_WEAPON; mAIRange = RANGE_SHORT; @@ -1062,7 +1109,7 @@ Weapon::Weapon() INITIALIZE_WEAPONMODE_VAR(loopfire, qfalse); INITIALIZE_WEAPONMODE_VAR(tracercount, 0); INITIALIZE_WEAPONMODE_VAR(tracerfrequency, 0); - INITIALIZE_WEAPONMODE_VAR(tracerspeed, 0); + INITIALIZE_WEAPONMODE_VAR(tracerspeed, 1); for (int i = 0; i < MAX_FIREMODES; i++) { INITIALIZE_WEAPONMODE_VAR(viewkickmin[i], 0); @@ -1132,6 +1179,7 @@ Weapon::Weapon() INITIALIZE_WEAPONMODE_VAR(meansofdeath, MOD_NONE); // Set the stats + m_iNumShotsFired = 0; m_iNumHits = 0; m_iNumGroinShots = 0; m_iNumHeadShots = 0; @@ -1175,7 +1223,6 @@ Weapon::Weapon() //Weapon::Weapon //====================== Weapon::Weapon(const char *file) - { // The tik file holds all the information available for a weapon Weapon(); @@ -1187,7 +1234,12 @@ Weapon::Weapon(const char *file) Weapon::~Weapon() { DetachGun(); - entflags &= ~EF_WEAPON; + + if (owner) { + RemoveFromOwner(); + } + + entflags &= ~ECF_WEAPON; } //====================== @@ -1197,15 +1249,9 @@ void Weapon::Delete(void) { if (g_iInThinks) { DetachGun(); - - if (owner) { - RemoveFromOwner(); - } - - PostEvent(EV_Remove, 0); - } else { - delete this; } + + Item::Delete(); } //====================== @@ -1277,7 +1323,7 @@ void Weapon::SetUseNoAmmo(Event *ev) //====================== void Weapon::SetStartAmmo(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -1290,7 +1336,7 @@ void Weapon::SetStartAmmo(Event *ev) //====================== void Weapon::SetDMStartAmmo(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -1302,7 +1348,6 @@ void Weapon::SetDMStartAmmo(Event *ev) //Weapon::SetMaxChargeTime //====================== void Weapon::SetMaxChargeTime(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); max_charge_time[firemodeindex] = ev->GetFloat(1); @@ -1340,7 +1385,7 @@ float Weapon::GetMaxChargeTime(firemode_t mode) //====================== void Weapon::SetAmmoRequired(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -1353,7 +1398,7 @@ void Weapon::SetAmmoRequired(Event *ev) //====================== void Weapon::SetDMAmmoRequired(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -1376,7 +1421,6 @@ str Weapon::GetAmmoType(firemode_t mode) //Weapon::SetAmmoType //====================== void Weapon::SetAmmoType(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); @@ -1592,19 +1636,15 @@ out: //====================== //Weapon::GetMuzzlePosition //====================== -void Weapon::GetMuzzlePosition(Vector *position, Vector *forward, Vector *right, Vector *up, Vector *vBarrelPos) +void Weapon::GetMuzzlePosition(vec3_t position, vec3_t vBarrelPos, vec3_t forward, vec3_t right, vec3_t up) { orientation_t weap_or, barrel_or, orient; - //orientation_t view_or; - Vector pos, f, r, u, aim_dir; - Vector vAng; - vec3_t mat[3] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, tagnum; - Player *owner; - //qboolean bViewShot; + Vector delta; + Vector aim_angles; + int tagnum; + int i; owner = (Player *)this->owner.Pointer(); - assert(owner); // We should always have an owner if (!owner) { @@ -1614,36 +1654,9 @@ void Weapon::GetMuzzlePosition(Vector *position, Vector *forward, Vector *right, } } - // If this is a crosshair or torsoaim weapon, then the dir is specified by the player's torso angles - if (crosshair) { - Player *player; - - // Use the player's torso angles to determine direction, but use the actual barrel to determine position - - player = (Player *)owner; - AngleVectors(player->GetViewAngles(), f, r, u); - - if (forward) { - *forward = f; - } - if (right) { - *right = r; - } - if (up) { - *up = u; - } - } - - if (current_attachToTag.length()) { + if (owner) { tagnum = gi.Tag_NumForName(owner->edict->tiki, current_attachToTag.c_str()); - if (tagnum < 0) { - warning("Weapon::GetMuzzlePosition", "Could not find tag \"%s\"", current_attachToTag.c_str()); - pos = owner->origin; - AnglesToAxis(owner->angles, mat); - goto out; - } - // Get the orientation based on the frame and anim stored off in the owner. // This is to prevent weird timing with getting orientations on different frames of firing // animations and the orientations will not be consistent. @@ -1651,159 +1664,75 @@ void Weapon::GetMuzzlePosition(Vector *position, Vector *forward, Vector *right, orient = G_TIKI_Orientation(owner->edict, tagnum); - for (i = 0; i < 3; i++) { - VectorMA(weap_or.origin, orient.origin[i], owner->orientation[i], weap_or.origin); - } - - MatrixMultiply(orient.axis, owner->orientation, weap_or.axis); - } else { - VectorCopy(origin, weap_or.origin); - AnglesToAxis(angles, weap_or.axis); - } - - if (!IsSubclassOfTurretGun()) { - if ((weapon_class & WEAPON_CLASS_THROWABLE)) { - AngleVectors(owner->GetViewAngles(), mat[0], mat[1], mat[2]); - } - - pos = owner->EyePosition(); - VectorCopy(pos, weap_or.origin); - } else { - // using the weapon's current origin - VectorCopy(origin, weap_or.origin); - AnglesToAxis(angles, weap_or.axis); - } - - // For debugging - G_DrawCoordSystem(weap_or.origin, weap_or.axis[0], weap_or.axis[1], weap_or.axis[2], 50); - pos = weap_or.origin; - - // Get the tag_barrel orientation from the weapon - if (!vBarrelPos || !this->GetRawTag(GetTagBarrel(), &barrel_or)) { - //warning( "Weapon::GetMuzzlePosition", "Could not find tag_barrel\n" ); - if (owner->IsSubclassOfPlayer()) { - Player *player = (Player *)owner; - AnglesToAxis(player->GetViewAngles(), weap_or.axis); + Player *player; + + // Use the player's torso angles to determine direction, but use the actual barrel to determine position + + player = static_cast(owner.Pointer()); + + if (forward || right || up) { + AngleVectors(player->m_vViewAng, forward, right, up); + } + + VectorCopy(player->m_vViewPos, position); + + if (this->GetRawTag(GetTagBarrel(), &barrel_or) && vBarrelPos) { + VectorCopy(owner->origin, vBarrelPos); + for (i = 0; i < 3; i++) { + VectorMA(vBarrelPos, orient.origin[i], owner->orientation[i], vBarrelPos); + } + + MatrixMultiply(orient.axis, owner->orientation, weap_or.axis); + for (i = 0; i < 3; i++) { + VectorMA(vBarrelPos, barrel_or.origin[i], weap_or.axis[i], vBarrelPos); + } + } else if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } } else { - AnglesToAxis(owner->angles, weap_or.axis); - } + VectorCopy(owner->origin, position); - AxisCopy(weap_or.axis, mat); + for (i = 0; i < 3; i++) { + VectorMA(position, orient.origin[i], owner->orientation[i], position); + } - if (vBarrelPos) { - *vBarrelPos = weap_or.origin; - } + MatrixMultiply(orient.axis, owner->orientation, weap_or.axis); - goto out; - } + if (this->GetRawTag(GetTagBarrel(), &barrel_or)) { + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_or.axis[i], position); + } + } - if (owner->IsSubclassOfPlayer() && !IsSubclassOfTurretGun()) { - if (vBarrelPos) { - *vBarrelPos = origin; + if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } + + delta = owner->GunTarget(false, position, weap_or.axis[0]) - position; + aim_angles = delta.toAngles(); + + if (forward || right || up) { + AngleVectors(aim_angles, forward, right, up); + } } } else { - // Translate the barrel's orientation through the weapon's orientation - VectorCopy(weap_or.origin, pos); - - for (i = 0; i < 3; i++) { - VectorMA(pos, barrel_or.origin[i], weap_or.axis[i], pos); + if (forward || right || up) { + AngleVectors(angles, forward, right, up); } - MatrixMultiply(barrel_or.axis, weap_or.axis, mat); + VectorCopy(origin, position); + + if (this->GetRawTag(GetTagBarrel(), &barrel_or)) { + AnglesToAxis(angles, weap_or.axis); + + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_or.axis[i], position); + } + } if (vBarrelPos) { - *vBarrelPos = pos; - } - } - -#if 0 - gi.DPrintf( "own_angles: %0.2f %0.2f %0.2f\n", owner->angles[0], owner->angles[1], owner->angles[2] ); - gi.DPrintf( "own_orient: %0.2f %0.2f %0.2f\n", owner->orientation[0][0], owner->orientation[0][1], owner->orientation[0][2] ); - gi.DPrintf( "bone forward: %0.2f %0.2f %0.2f\n", orient.axis[0][0], orient.axis[0][1], orient.axis[0][2] ); - gi.DPrintf( "barrel forward: %0.2f %0.2f %0.2f\n", barrel_or.axis[0][0], barrel_or.axis[0][1], barrel_or.axis[0][2] ); - gi.DPrintf( "weapon forward: %0.2f %0.2f %0.2f\n", weap_or.axis[0][0], weap_or.axis[0][1], weap_or.axis[0][2] ); - gi.DPrintf( "mat forward: %0.2f %0.2f %0.2f\n \n", mat[0][0], mat[0][1], mat[0][2] ); -#endif - - // Ok - we now have a position, forward, right, and up -out: - - // For debugging - G_DrawCoordSystem(pos, mat[0], mat[1], mat[2], 30); - - if (position) { - *position = pos; - } - - if (!forward && !right && !up) { - return; - } - - if (!IsSubclassOfTurretGun() && owner && owner->IsSubclassOfPlayer()) { - // ... - // fixme? - } - - if (pos != vec_zero) { - // ffs, wondering how they fucking done it in mohaaa... - //aim_dir = barrel_or.origin - pos; - //aim_dir.normalize(); - - AngleVectors(owner->GetViewAngles(), aim_dir, NULL, NULL); - - if (!IsSubclassOfVehicleTurretGun()) { - goto out2; - } - - Vector ang; - - vectoangles(mat[0], ang); - - // this is a part of the most annoying function to reverse ever - // fixme - } - - // If there is a target, then use the dir based on that - if (aim_target) { - aim_dir = aim_target->centroid - pos; - aim_dir.normalize(); - - if (!IsSubclassOfTurretGun()) { - out2: - AngleVectors(aim_dir.toAngles(), mat[0], mat[1], mat[2]); - - if (forward) { - *forward = mat[0]; - } - if (right) { - *right = mat[1]; - } - if (up) { - *up = mat[2]; - } - - return; - } - - Vector ang; - - vectoangles(mat[0], ang); - - // again a very annoying part to reverse - // fixme - } - - // If this weapon doesn't have a crosshair specified, then use the mat from the barrel for the directions - if (!crosshair) { - if (forward) { - *forward = mat[0]; - } - if (right) { - *right = mat[1]; - } - if (up) { - *up = mat[2]; + VectorCopy(position, vBarrelPos); } } } @@ -1812,7 +1741,6 @@ out: //Weapon::SetAmmoClipSize //====================== void Weapon::SetAmmoClipSize(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); ammo_clip_size[firemodeindex] = ev->GetInteger(1); @@ -1822,7 +1750,6 @@ void Weapon::SetAmmoClipSize(Event *ev) //Weapon::SetAmmoInClip //====================== void Weapon::SetAmmoInClip(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); ammo_in_clip[firemodeindex] = ev->GetInteger(1); @@ -1873,7 +1800,7 @@ void Weapon::Shoot(Event *ev) } } - if (owner->IsSubclassOfSentient() && owner->m_bOvercookDied) { + if (owner && owner->IsSubclassOfSentient() && owner->m_bOvercookDied) { owner->m_bOvercookDied = false; return; } @@ -1896,8 +1823,8 @@ void Weapon::Shoot(Event *ev) return; } - GetMuzzlePosition(&pos, &forward, &right, &up, &vBarrel); - ApplyFireKickback(right, 1000.0); + GetMuzzlePosition(pos, vBarrel, forward, right, up); + ApplyFireKickback(forward, 1000.0); if (firetype[mode] != FT_LANDMINE || CanPlaceLandmine(pos, owner)) { if (m_fFireSpreadMultAmount[mode] != 0.0f) { @@ -1928,13 +1855,13 @@ void Weapon::Shoot(Event *ev) switch (firetype[mode]) { case FT_PROJECTILE: - ProjectileAttack(pos, forward, owner, projectileModel[mode], charge_fraction); + ProjectileAttack(pos, forward, owner, projectileModel[mode], charge_fraction, 0, this); break; case FT_LANDMINE: PlaceLandmine(pos, owner, projectileModel[mode], this); break; case FT_DEFUSE: - DefuseObject(right, owner, bulletrange[mode]); + DefuseObject(forward, owner, bulletrange[mode]); break; case FT_BULLET: { @@ -1947,11 +1874,7 @@ void Weapon::Shoot(Event *ev) if (owner->client) { Player *player = (Player *)owner.Pointer(); - fSpreadFactor = player->velocity.length() / sv_runspeed->integer; - - if (fSpreadFactor > 1.0f) { - fSpreadFactor = 1.0f; - } + fSpreadFactor = GetSpreadFactor(mode); vSpread = bulletspreadmax[mode] * fSpreadFactor; fSpreadFactor = 1.0f - fSpreadFactor; @@ -1968,7 +1891,9 @@ void Weapon::Shoot(Event *ev) vSpread = (bulletspreadmax[mode] + bulletspread[mode]) * 0.5f; } - if (!g_gametype->integer && owner && owner->IsSubclassOfPlayer()) { + // Don't display tracers if the owner is a player for non-turret weapons + // It would have some artifacts for the first person model, as the tracer is created from the world model + if ((g_target_game == TG_MOH || g_gametype->integer == GT_SINGLE_PLAYER) && owner && owner->IsSubclassOfPlayer()) { if (IsSubclassOfTurretGun()) { tracerFrequency = 3; } else { @@ -2111,13 +2036,22 @@ void Weapon::Shoot(Event *ev) } } break; + default: + // none or unsupported + break; } - if (!quiet[firemodeindex]) { - if (next_noise_time <= level.time) { - BroadcastAIEvent(AI_EVENT_WEAPON_FIRE); - next_noise_time = level.time + 1; + if (!quiet[mode] && next_noise_time <= level.time) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { + BroadcastAIEvent(AI_EVENT_WEAPON_FIRE, 1500); + } else { + // + // Added in OPM + // Weapon firing sounds can be heard 8000 units away + // (from ubersound.scr) + BroadcastAIEvent(AI_EVENT_WEAPON_FIRE, 8000); } + next_noise_time = level.time + 1; } if (owner && owner->client) { @@ -2169,7 +2103,6 @@ void Weapon::ApplyFireKickback(const Vector& org, float kickback) {} //Weapon::SetAimAnim //====================== void Weapon::SetAimAnim(Event *ev) - { str anim; @@ -2182,7 +2115,6 @@ void Weapon::SetAimAnim(Event *ev) //Weapon::SetOwner //====================== void Weapon::SetOwner(Sentient *ent) - { assert(ent); if (!ent) { @@ -2224,7 +2156,7 @@ int Weapon::AmmoAvailable(firemode_t mode) qboolean Weapon::UnlimitedAmmo(firemode_t mode) { if (!owner) { - return false; + return true; } if (!owner->isClient() || DM_FLAG(DF_INFINITE_AMMO)) { @@ -2446,23 +2378,27 @@ qboolean Weapon::Drop(void) int ammo; if (ammo_clip_size[FIRE_PRIMARY]) { - startammo[FIRE_PRIMARY] = g_dropclips->integer * ammo_in_clip[FIRE_PRIMARY]; + // Fixed in OPM + // Always drop at least 1 because of grenades + startammo[FIRE_PRIMARY] = g_dropclips->integer * Q_max(ammo_in_clip[FIRE_PRIMARY], 1); } else { startammo[FIRE_PRIMARY] = g_dropclips->integer; } - ammo = AmmoAvailable(FIRE_PRIMARY); + // Fixed in OPM + // Use the max between the available ammo and the ammo in clip + ammo = Q_max(AmmoAvailable(FIRE_PRIMARY), ammo_in_clip[FIRE_PRIMARY]); if (startammo[FIRE_PRIMARY] > ammo) { startammo[FIRE_PRIMARY] = ammo; } if (ammo_clip_size[FIRE_SECONDARY]) { - startammo[FIRE_SECONDARY] = g_dropclips->integer * ammo_in_clip[FIRE_SECONDARY]; + startammo[FIRE_SECONDARY] = g_dropclips->integer * Q_max(ammo_in_clip[FIRE_SECONDARY], 1); } else { startammo[FIRE_SECONDARY] = g_dropclips->integer; } - ammo = AmmoAvailable(FIRE_SECONDARY); + ammo = Q_max(AmmoAvailable(FIRE_SECONDARY), ammo_in_clip[FIRE_SECONDARY]); if (startammo[FIRE_SECONDARY] > ammo) { startammo[FIRE_SECONDARY] = ammo; } @@ -2505,7 +2441,10 @@ qboolean Weapon::Drop(void) // Remove this from the owner's item list RemoveFromOwner(); - PostEvent(EV_Remove, g_droppeditemlife->value); + if (g_droppeditemlife->value > 0) { + PostEvent(EV_Remove, g_droppeditemlife->value); + } + PostEvent(EV_Weapon_FallingAngleAdjust, level.frametime); return true; } @@ -2515,10 +2454,8 @@ qboolean Weapon::Drop(void) //====================== void Weapon::Charge(firemode_t mode) { - if (mode == FIRE_PRIMARY) - { - if (m_fCookTime > 0) - { + if (mode == FIRE_PRIMARY) { + if (m_fCookTime > 0) { m_eCookModeIndex = mode; // // Post cook event @@ -2527,19 +2464,16 @@ void Weapon::Charge(firemode_t mode) PostEvent(EV_OverCooked_Warning, m_fCookTime - 1); } SetWeaponAnim("charge"); - } - else if (mode == FIRE_SECONDARY) - { - if (m_fCookTime > 0) - { - m_eCookModeIndex = mode; - // - // Post cook event - // - PostEvent(EV_OverCooked, m_fCookTime); - PostEvent(EV_OverCooked_Warning, m_fCookTime - 1); - } - SetWeaponAnim("secondarycharge"); + } else if (mode == FIRE_SECONDARY) { + if (m_fCookTime > 0) { + m_eCookModeIndex = mode; + // + // Post cook event + // + PostEvent(EV_OverCooked, m_fCookTime); + PostEvent(EV_OverCooked_Warning, m_fCookTime - 1); + } + SetWeaponAnim("secondarycharge"); } } @@ -2610,8 +2544,8 @@ void Weapon::OnOverCooked(Event *ev) void Weapon::ReleaseFire(firemode_t mode, float charge_time) { // Make sure to stop the wepaon from cooking - CancelEventsOfType(EV_OverCooked); - CancelEventsOfType(EV_OverCooked_Warning); + CancelEventsOfType(EV_OverCooked); + CancelEventsOfType(EV_OverCooked_Warning); // Calculate and store off the charge fraction to use when the weapon actually shoots @@ -2845,7 +2779,7 @@ void Weapon::AttachToHand(Event *ev) //====================== void Weapon::SetCantPartialReload(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -2857,7 +2791,7 @@ void Weapon::SetCantPartialReload(Event *ev) //====================== void Weapon::SetDMCantPartialReload(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -2890,10 +2824,7 @@ void Weapon::GiveStartingAmmoToOwner(Event *ev) int mode; int i; - assert(owner); - if (!owner) { - warning("Weapon::GiveStartingAmmoToOwner", "Owner not found\n"); return; } @@ -3005,83 +2936,108 @@ void Weapon::PickupWeapon(Event *ev) "print \"" HUD_MESSAGE_YELLOW "%s\n\"", gi.LV_ConvertString(va("Picked Up %s", item_name.c_str())) ); - - if (!(spawnflags & DROPPED_PLAYER_ITEM) && !(spawnflags & DROPPED_ITEM)) { - ItemPickup(other); - return; - } - - if (Pickupable(other)) { - setMoveType(MOVETYPE_NONE); - setSolidType(SOLID_NOT); - - hideModel(); - - velocity = vec_zero; - avelocity = vec_zero; - - CancelEventsOfType(EV_Remove); - CancelEventsOfType(EV_Weapon_FallingAngleAdjust); - - DetachFromOwner(); - current_attachToTag = ""; - lastValid = qfalse; - edict->s.tag_num = -1; - edict->s.attach_use_angles = qfalse; - VectorClear(edict->s.attach_offset); - - setOrigin(vec_zero); - setAngles(vec_zero); - SetOwner(sen); - - sen->AddItem(this); - sen->ReceivedItem(this); - - Sound(sPickupSound); - } } + + if (!(spawnflags & DROPPED_PLAYER_ITEM) && !(spawnflags & DROPPED_ITEM)) { + ItemPickup(other); + return; + } + + if (!Pickupable(other)) { + return; + } + + setMoveType(MOVETYPE_NONE); + setSolidType(SOLID_NOT); + + hideModel(); + + velocity = vec_zero; + avelocity = vec_zero; + + CancelEventsOfType(EV_Remove); + CancelEventsOfType(EV_Weapon_FallingAngleAdjust); + + DetachFromOwner(); + current_attachToTag = ""; + lastValid = qfalse; + edict->s.tag_num = -1; + edict->s.attach_use_angles = qfalse; + VectorClear(edict->s.attach_offset); + + setOrigin(vec_zero); + setAngles(vec_zero); + SetOwner(sen); + + sen->AddItem(this); + sen->ReceivedItem(this); + + iGiveAmmo = startammo[FIRE_PRIMARY]; + + Sound(sPickupSound); } else { - str sAmmoName = ammo_type[FIRE_PRIMARY]; + bool bSameAmmo[MAX_FIREMODES] = { false }; - if (sen->AmmoCount(sAmmoName) != sen->MaxAmmoCount(sAmmoName)) { - setSolidType(SOLID_NOT); - hideModel(); - - CancelEventsOfType(EV_Item_DropToFloor); - CancelEventsOfType(EV_Item_Respawn); - CancelEventsOfType(EV_FadeOut); - CancelEventsOfType(EV_Remove); - CancelEventsOfType(EV_Weapon_FallingAngleAdjust); - - if (Respawnable()) { - PostEvent(EV_Item_Respawn, 0); - } else { - PostEvent(EV_Remove, 0); + if (sen->AmmoCount(ammo_type[FIRE_PRIMARY]) == sen->MaxAmmoCount(ammo_type[FIRE_PRIMARY])) { + bSameAmmo[FIRE_PRIMARY] = true; + if (ammo_type[0] == ammo_type[1]) { + bSameAmmo[FIRE_SECONDARY] = true; } - - Sound(m_sAmmoPickupSound); } + + if (!bSameAmmo[FIRE_SECONDARY]) { + if (sen->AmmoCount(ammo_type[FIRE_SECONDARY]) == sen->MaxAmmoCount(ammo_type[FIRE_SECONDARY])) { + bSameAmmo[FIRE_SECONDARY] = true; + } + } + + if (bSameAmmo[FIRE_PRIMARY] && bSameAmmo[FIRE_SECONDARY]) { + return; + } + + if (bSameAmmo[FIRE_PRIMARY]) { + startammo[FIRE_PRIMARY] = 0; + } + + if (bSameAmmo[FIRE_SECONDARY]) { + startammo[FIRE_SECONDARY] = 0; + } + + iGiveAmmo = ammo_in_clip[FIRE_PRIMARY] + startammo[FIRE_PRIMARY]; + + if (!iGiveAmmo && !startammo[FIRE_SECONDARY]) { + // Fixed in OPM + // Don't let the sentient pick the ammo up if it already has the weapon in inventory + // and the player would get no ammo. + // This can only be picked up as a new weapon. + return; + } + + setSolidType(SOLID_NOT); + hideModel(); + + CancelEventsOfType(EV_Item_DropToFloor); + CancelEventsOfType(EV_Item_Respawn); + CancelEventsOfType(EV_FadeOut); + CancelEventsOfType(EV_Remove); + CancelEventsOfType(EV_Weapon_FallingAngleAdjust); + + if (Respawnable()) { + PostEvent(EV_Item_Respawn, 0); + } else { + PostEvent(EV_Remove, 0); + } + + Sound(m_sAmmoPickupSound); } if (startammo[FIRE_PRIMARY] && ammo_type[FIRE_PRIMARY].length() && other->isClient()) { str sMessage; const str& sAmmoType = ammo_type[FIRE_PRIMARY]; - iGiveAmmo = startammo[FIRE_PRIMARY]; - sen->GiveAmmo(sAmmoType, iGiveAmmo); - if (!g_gametype->integer && other->IsSubclassOfPlayer()) { - if (!sAmmoType.icmp("agrenade")) { - if (iGiveAmmo == 1) { - sMessage = gi.LV_ConvertString("Got 1 Grenade"); - } else { - sMessage = gi.LV_ConvertString(va("Got %i Grenades", iGiveAmmo)); - } - } - } - - if (!sAmmoType.icmp("grenade")) { + if (!sAmmoType.icmp("grenade") || !sAmmoType.icmp("agrenade")) { if (iGiveAmmo == 1) { sMessage = gi.LV_ConvertString("Got 1 Grenade"); } else { @@ -3094,26 +3050,16 @@ void Weapon::PickupWeapon(Event *ev) gi.SendServerCommand(other->edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", sMessage.c_str()); } - if (ammo_type[FIRE_SECONDARY] != ammo_type[FIRE_PRIMARY]) { + if (ammo_type[FIRE_SECONDARY] != ammo_type[FIRE_PRIMARY] && str::icmp(ammo_type[FIRE_SECONDARY], "none")) { if (startammo[FIRE_SECONDARY] && ammo_type[FIRE_SECONDARY].length() && other->isClient()) { str sMessage; - const str& sAmmoType = ammo_type[FIRE_PRIMARY]; + const str& sAmmoType = ammo_type[FIRE_SECONDARY]; iGiveAmmo = startammo[FIRE_SECONDARY]; sen->GiveAmmo(sAmmoType, iGiveAmmo); - if (!g_gametype->integer && other->IsSubclassOfPlayer()) { - if (!sAmmoType.icmp("agrenade")) { - if (iGiveAmmo == 1) { - sMessage = gi.LV_ConvertString("Got 1 Grenade"); - } else { - sMessage = gi.LV_ConvertString(va("Got %i Grenades", iGiveAmmo)); - } - } - } - - if (!sAmmoType.icmp("grenade")) { + if (!sAmmoType.icmp("grenade") || !sAmmoType.icmp("agrenade")) { if (iGiveAmmo == 1) { sMessage = gi.LV_ConvertString("Got 1 Grenade"); } else { @@ -3145,6 +3091,12 @@ void Weapon::ForceIdle(void) // Force the weapon to the idle animation weaponstate = WEAPON_READY; + + // Fixed in OPM + // Stop the weapon from charging/cooking + CancelEventsOfType(EV_OverCooked); + CancelEventsOfType(EV_OverCooked_Warning); + charge_fraction = 0; } //====================== @@ -3184,7 +3136,8 @@ void Weapon::SetWeaponIdleAnimEvent(Event *ev) //====================== void Weapon::SetWeaponAnimEvent(Event *ev) { - SetWeaponAnim(ev->GetString(1)); + //SetWeaponAnim(ev->GetString(1)); + SetWeaponAnim(ev->GetString(1), EV_Weapon_DoneAnimating); } //====================== @@ -3208,7 +3161,7 @@ qboolean Weapon::SetWeaponAnim(const char *anim, Event *ev) int idleanim = gi.Anim_NumForName(edict->tiki, "idle"); edict->s.frameInfo[m_iAnimSlot].index = idleanim; - m_iAnimSlot = (m_iAnimSlot + 1) & 3; + m_iAnimSlot = (m_iAnimSlot + 1) % MAX_WEAPON_ANIM_SLOTS; edict->s.frameInfo[m_iAnimSlot].index = idleanim; if (ev) { @@ -3246,7 +3199,7 @@ void Weapon::StopWeaponAnim(void) animnum = gi.Anim_NumForName(edict->tiki, "idle"); StartAnimSlot(m_iAnimSlot, animnum, 1.f); - m_iAnimSlot = (m_iAnimSlot + 1) & 3; + m_iAnimSlot = (m_iAnimSlot + 1) % MAX_WEAPON_ANIM_SLOTS; } //====================== @@ -3267,7 +3220,6 @@ void Weapon::DoneRaising(Event *ev) //Weapon::ClientFireDone //====================== void Weapon::ClientFireDone(void) - { // This is called when the client's firing animation is done } @@ -3301,21 +3253,21 @@ void Weapon::FillAmmoClip(Event *ev) if (UnlimitedAmmo(FIRE_PRIMARY)) { // reload directly - ammo_in_clip[FIRE_PRIMARY] = ammo_clip_size[0]; + ammo_in_clip[FIRE_PRIMARY] = ammo_clip_size[0]; } else { // Calc the amount the clip should get - amount = ammo_clip_size[FIRE_PRIMARY] - ammo_in_clip[FIRE_PRIMARY]; + amount = ammo_clip_size[FIRE_PRIMARY] - ammo_in_clip[FIRE_PRIMARY]; - // use up the ammo from the player - amount_used = owner->UseAmmo(ammo_type[FIRE_PRIMARY], amount); + // use up the ammo from the player + amount_used = owner->UseAmmo(ammo_type[FIRE_PRIMARY], amount); - // Stick it in the clip - ammo_in_clip[FIRE_PRIMARY] = amount_used + ammo_in_clip[FIRE_PRIMARY]; - } + // Stick it in the clip + ammo_in_clip[FIRE_PRIMARY] = amount_used + ammo_in_clip[FIRE_PRIMARY]; + } - owner->AmmoAmountInClipChanged(ammo_type[FIRE_PRIMARY], ammo_in_clip[FIRE_PRIMARY]); + owner->AmmoAmountInClipChanged(ammo_type[FIRE_PRIMARY], ammo_in_clip[FIRE_PRIMARY]); - SetShouldReload(qfalse); + SetShouldReload(qfalse); } //====================== @@ -3349,14 +3301,14 @@ void Weapon::AddToAmmoClip(Event *ev) if (!ammo_clip_size[FIRE_PRIMARY] || !owner) { return; - } + } - // Calc the amount the clip should get - amount = ev->GetInteger(1); + // Calc the amount the clip should get + amount = ev->GetInteger(1); - if (amount > ammo_clip_size[FIRE_PRIMARY] - ammo_in_clip[FIRE_PRIMARY]) { - amount = ammo_clip_size[FIRE_PRIMARY] - ammo_in_clip[FIRE_PRIMARY]; - } + if (amount > ammo_clip_size[FIRE_PRIMARY] - ammo_in_clip[FIRE_PRIMARY]) { + amount = ammo_clip_size[FIRE_PRIMARY] - ammo_in_clip[FIRE_PRIMARY]; + } if (UnlimitedAmmo(FIRE_PRIMARY)) { // Stick it in the clip @@ -3367,11 +3319,11 @@ void Weapon::AddToAmmoClip(Event *ev) // Stick it in the clip ammo_in_clip[FIRE_PRIMARY] = amount_used + ammo_in_clip[FIRE_PRIMARY]; - } + } - owner->AmmoAmountInClipChanged(ammo_type[FIRE_PRIMARY], ammo_in_clip[FIRE_PRIMARY]); + owner->AmmoAmountInClipChanged(ammo_type[FIRE_PRIMARY], ammo_in_clip[FIRE_PRIMARY]); - SetShouldReload(qfalse); + SetShouldReload(qfalse); } //====================== @@ -3423,6 +3375,10 @@ void Weapon::DoneReloading(Event *ev) { SetShouldReload(qfalse); weaponstate = WEAPON_READY; + + // Added in OPM + // Set to idle when done reloading + SetWeaponIdleAnim(); } //====================== @@ -3495,7 +3451,6 @@ void Weapon::IdleInit(Event *ev) //Weapon::GetMaxRange //====================== float Weapon::GetMaxRange(void) - { return maxrange; } @@ -3504,7 +3459,6 @@ float Weapon::GetMaxRange(void) //Weapon::GetMinRange //====================== float Weapon::GetMinRange(void) - { return minrange; } @@ -3513,7 +3467,6 @@ float Weapon::GetMinRange(void) //Weapon::SetMaxRangeEvent //====================== void Weapon::SetMaxRangeEvent(Event *ev) - { maxrange = ev->GetFloat(1); } @@ -3522,7 +3475,6 @@ void Weapon::SetMaxRangeEvent(Event *ev) //Weapon::SetMinRangeEvent //====================== void Weapon::SetMinRangeEvent(Event *ev) - { minrange = ev->GetFloat(1); } @@ -3531,7 +3483,6 @@ void Weapon::SetMinRangeEvent(Event *ev) //Weapon::NotDroppableEvent //====================== void Weapon::NotDroppableEvent(Event *ev) - { notdroppable = true; } @@ -3540,7 +3491,6 @@ void Weapon::NotDroppableEvent(Event *ev) //Weapon::SetMaxRange //====================== void Weapon::SetMaxRange(float val) - { maxrange = val; } @@ -3549,7 +3499,6 @@ void Weapon::SetMaxRange(float val) //Weapon::SetMinRange //====================== void Weapon::SetMinRange(float val) - { minrange = val; } @@ -3559,8 +3508,6 @@ void Weapon::SetMinRange(float val) //====================== void Weapon::WeaponSound(Event *ev) { - Event *e; - // Broadcasting a sound can be time consuming. Only do it once in a while on really fast guns. if (nextweaponsoundtime > level.time) { if (owner) { @@ -3572,8 +3519,7 @@ void Weapon::WeaponSound(Event *ev) } if (owner) { - e = new Event(ev); - owner->ProcessEvent(e); + owner->ProcessEvent(*ev); } else { Item::BroadcastAIEvent(AI_EVENT_WEAPON_FIRE); } @@ -3586,7 +3532,6 @@ void Weapon::WeaponSound(Event *ev) //Weapon::Removable //====================== qboolean Weapon::Removable(void) - { if (((int)(dmflags->integer) & DF_WEAPONS_STAY) && !(spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) { return false; @@ -3599,7 +3544,6 @@ qboolean Weapon::Removable(void) //Weapon::Pickupable //====================== qboolean Weapon::Pickupable(Entity *other) - { Sentient *sen; @@ -3611,9 +3555,6 @@ qboolean Weapon::Pickupable(Entity *other) sen = (Sentient *)other; - //FIXME - // This should be in player - // If we have the weapon and weapons stay, then don't pick it up if (((int)(dmflags->integer) & DF_WEAPONS_STAY) && !(spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) { Weapon *weapon; @@ -3632,7 +3573,6 @@ qboolean Weapon::Pickupable(Entity *other) //Weapon::AutoChange //====================== qboolean Weapon::AutoChange(void) - { return true; } @@ -3658,7 +3598,7 @@ int Weapon::ClipAmmo(firemode_t mode) //====================== void Weapon::SetFireDelay(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3670,7 +3610,7 @@ void Weapon::SetFireDelay(Event *ev) //====================== void Weapon::SetDMFireDelay(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3737,7 +3677,6 @@ void Weapon::SetFireType(Event *ev) //Weapon::GetFireType //====================== firetype_t Weapon::GetFireType(firemode_t mode) - { return firetype[mode]; } @@ -3752,7 +3691,7 @@ firemode_t Weapon::GetFireMode() //====================== void Weapon::SetProjectile(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3766,7 +3705,7 @@ void Weapon::SetProjectile(Event *ev) //====================== void Weapon::SetDMProjectile(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3779,7 +3718,6 @@ void Weapon::SetDMProjectile(Event *ev) //Weapon::SetBulletDamage //====================== void Weapon::SetBulletDamage(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); bulletdamage[firemodeindex] = ev->GetFloat(1); @@ -3789,7 +3727,6 @@ void Weapon::SetBulletDamage(Event *ev) //Weapon::SetBulletLarge //====================== void Weapon::SetBulletLarge(Event *ev) - { bulletlarge[firemodeindex] = ev->GetInteger(1); } @@ -3798,7 +3735,6 @@ void Weapon::SetBulletLarge(Event *ev) //Weapon::SetBulletLarge //====================== void Weapon::SetTracerSpeed(Event *ev) - { tracerspeed[firemodeindex] = ev->GetFloat(1); } @@ -3808,7 +3744,7 @@ void Weapon::SetTracerSpeed(Event *ev) //====================== void Weapon::SetDMBulletDamage(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3820,7 +3756,6 @@ void Weapon::SetDMBulletDamage(Event *ev) //Weapon::SetBulletKnockback //====================== void Weapon::SetBulletKnockback(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); bulletknockback[firemodeindex] = ev->GetFloat(1); @@ -3831,7 +3766,7 @@ void Weapon::SetBulletKnockback(Event *ev) //====================== void Weapon::SetDMBulletKnockback(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3860,7 +3795,7 @@ void Weapon::SetBulletThroughMetal(Event *ev) //====================== void Weapon::SetBulletRange(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3873,7 +3808,7 @@ void Weapon::SetBulletRange(Event *ev) //====================== void Weapon::SetDMBulletRange(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3894,7 +3829,7 @@ void Weapon::SetRange(Event *ev) //====================== void Weapon::SetBulletCount(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3907,7 +3842,7 @@ void Weapon::SetBulletCount(Event *ev) //====================== void Weapon::SetDMBulletCount(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3920,7 +3855,7 @@ void Weapon::SetDMBulletCount(Event *ev) //====================== void Weapon::SetBulletSpread(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3939,7 +3874,7 @@ void Weapon::SetBulletSpread(Event *ev) //====================== void Weapon::SetDMBulletSpread(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3958,7 +3893,7 @@ void Weapon::SetDMBulletSpread(Event *ev) //====================== void Weapon::SetZoomSpreadMult(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3970,7 +3905,7 @@ void Weapon::SetZoomSpreadMult(Event *ev) //====================== void Weapon::SetDMZoomSpreadMult(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -3983,7 +3918,7 @@ void Weapon::SetDMZoomSpreadMult(Event *ev) //====================== void Weapon::SetFireSpreadMult(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -3999,7 +3934,7 @@ void Weapon::SetFireSpreadMult(Event *ev) //====================== void Weapon::SetDMFireSpreadMult(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -4042,7 +3977,6 @@ void Weapon::Secondary(Event *ev) //Weapon::AutoAim //==================== void Weapon::AutoAim(Event *ev) - { autoaim = true; } @@ -4060,7 +3994,7 @@ void Weapon::Crosshair(Event *ev) //==================== void Weapon::DMCrosshair(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -4111,7 +4045,6 @@ void Weapon::SetHolsterAngles(Event *ev) //Weapon::SetHolsterScale //==================== void Weapon::SetHolsterScale(Event *ev) - { holsterScale = ev->GetFloat(1); } @@ -4128,7 +4061,6 @@ void Weapon::SetQuiet(Event *ev) //Weapon::SetLoopFire //==================== void Weapon::SetLoopFire(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); loopfire[firemodeindex] = true; @@ -4138,7 +4070,6 @@ void Weapon::SetLoopFire(Event *ev) //Weapon::SetMeansOfDeath //====================== void Weapon::SetMeansOfDeath(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); meansofdeath[firemodeindex] = (meansOfDeath_t)MOD_string_to_int(ev->GetString(1)); @@ -4163,7 +4094,6 @@ meansOfDeath_t Weapon::GetMeansOfDeath(firemode_t mode) //Weapon::SetAimTarget //====================== void Weapon::SetAimTarget(Entity *ent) - { aim_target = ent; } @@ -4177,7 +4107,6 @@ void Weapon::WorldHitSpawn(firemode_t mode, Vector origin, Vector angles, float //Weapon::SetWorldHitSpawn //====================== void Weapon::SetWorldHitSpawn(Event *ev) - { assert((firemodeindex >= 0) && (firemodeindex < MAX_FIREMODES)); worldhitspawn[firemodeindex] = ev->GetString(1); @@ -4294,6 +4223,11 @@ void Weapon::FallingAngleAdjust(Event *ev) //====================== qboolean Weapon::GetUseCrosshair() const { + if (g_protocol < protocol_e::PROTOCOL_MOHTA_MIN) { + // Always show the crosshair in 1.11 and below + return qtrue; + } + if (m_fMaxFireMovement >= 1.f) { return crosshair; } @@ -4365,7 +4299,7 @@ void Weapon::SetViewKick(Event *ev) //====================== void Weapon::SetMovementSpeed(Event *ev) { - if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer) { + if (g_protocol <= protocol_e::PROTOCOL_MOH && g_gametype->integer != GT_SINGLE_PLAYER) { return; } @@ -4377,7 +4311,7 @@ void Weapon::SetMovementSpeed(Event *ev) //====================== void Weapon::SetDMMovementSpeed(Event *ev) { - if (!g_gametype->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER) { return; } @@ -4485,7 +4419,6 @@ void Weapon::SetRank(int order, int rank) //Weapon::GetRank //====================== int Weapon::GetRank(void) - { return rank; } @@ -4494,7 +4427,6 @@ int Weapon::GetRank(void) //Weapon::GetOrder //====================== int Weapon::GetOrder(void) - { return order; } @@ -4520,7 +4452,8 @@ const_str Weapon::GetWeaponGroup(void) const //====================== void Weapon::SetItemSlot(int slot) { - // FIXME: unimplemented + weapon_class &= ~WEAPON_CLASS_ITEM_SLOT_BITS; + weapon_class |= slot & WEAPON_CLASS_ITEM_SLOT_BITS; } //====================== @@ -4616,7 +4549,7 @@ float Weapon::GetMovementSpeed() const //====================== //Weapon::IsCarryableTurret //====================== -bool Weapon::IsCarryableTurret() +bool Weapon::IsCarryableTurret() const { return false; } @@ -4662,6 +4595,36 @@ float Weapon::GetBulletRange(firemode_t mode) return bulletrange[mode]; } +//====================== +//Weapon::GetSpreadFactor +//====================== +float Weapon::GetSpreadFactor(firemode_t mode) +{ + float fSpreadFactor; + + if (owner && owner->client) { + Player* player = (Player*)owner.Pointer(); + + fSpreadFactor = player->velocity.length() / sv_runspeed->integer; + + if (fSpreadFactor > 1.0f) { + fSpreadFactor = 1.0f; + } + } else { + fSpreadFactor = 0.5f; + } + + return fSpreadFactor; +} + +//====================== +//Weapon::GetChargeFraction +//====================== +float Weapon::GetChargeFraction(void) const +{ + return charge_fraction; +} + //====================== //Weapon::GetScriptOwner //====================== @@ -4669,3 +4632,42 @@ Listener *Weapon::GetScriptOwner(void) { return owner; } + +//====================== +//Weapon::DoneAnimating +//====================== +void Weapon::DoneAnimating(Event* ev) { + // Added in OPM + // Set to idle when done reloading + SetWeaponIdleAnim(); +} + +//====================== +//Weapon::GetMaxFireMovementMult +//====================== +void Weapon::EventGetPutaway(Event* ev) { + // Added in OPM + // Set to idle when done reloading + ev->AddInteger(GetPutaway()); +} + +//====================== +//Weapon::GetMaxFireMovementMult +//====================== +float Weapon::GetMaxFireMovementMult() const { + return m_fMaxFireMovement * m_fMovementSpeed; +} + +//====================== +//Weapon::GetMaxFireMovementMult +//====================== +float Weapon::GetZoomMovement() const { + return m_fZoomMovement * m_fMovementSpeed; +} + +//====================== +//Weapon::GetMaxFireMovement +//====================== +float Weapon::GetMaxFireMovement() const { + return m_fMaxFireMovement; +} diff --git a/code/fgame/weapon.h b/code/fgame/weapon.h index c48b171d..18e9bf8f 100644 --- a/code/fgame/weapon.h +++ b/code/fgame/weapon.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,8 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // class will be usable by any Sentient (players and monsters) as a weapon. // -#ifndef __WEAPON_H__ -#define __WEAPON_H__ +#pragma once #include "g_local.h" #include "item.h" @@ -92,6 +91,8 @@ typedef enum { } \ } +static const unsigned int MAX_WEAPON_ANIM_SLOTS = 4; + class Player; class Weapon : public Item @@ -147,28 +148,28 @@ protected: // in its primary(index 0) and alternate(index 1) mode float fire_delay[MAX_FIREMODES]; - str ammo_type[MAX_FIREMODES]; // The type of ammo used - int ammorequired[MAX_FIREMODES]; // The amount of ammo required to fire this weapon - int startammo[MAX_FIREMODES]; // The starting amount of ammo when the weapon is picked up - str projectileModel[MAX_FIREMODES]; // The model of the projectile fired - float bulletdamage[MAX_FIREMODES]; // The amount of damate a single bullet causes - float bulletcount[MAX_FIREMODES]; // The number of bullets the weapon fires - int bulletlarge[MAX_FIREMODES]; // The number of bullets the weapon fires - float bulletrange[MAX_FIREMODES]; // The range of the bullet - float bulletknockback[MAX_FIREMODES]; // The amount of knockback a bullet causes - float bulletthroughwood[MAX_FIREMODES]; // The amount of knockback a bullet causes - float bulletthroughmetal[MAX_FIREMODES]; // The amount of knockback a bullet causes - float projectilespeed[MAX_FIREMODES]; // The speed of the projectile fired - Vector bulletspread[MAX_FIREMODES]; // The amount of spread bullets can have - Vector bulletspreadmax[MAX_FIREMODES]; // The max amount of spread bullets can have - firetype_t firetype[MAX_FIREMODES]; // The type of fire (projectile or bullet) - int ammo_clip_size[MAX_FIREMODES]; // The amount of rounds the clip can hold - int ammo_in_clip[MAX_FIREMODES]; // The current amount of ammo in the clip - float max_charge_time[MAX_FIREMODES]; // The max amount of time the weapon may be charged. - float min_charge_time[MAX_FIREMODES]; // The min amount of time the weapon may be charged. - meansOfDeath_t meansofdeath[MAX_FIREMODES]; // The means of death for this mode - qboolean loopfire[MAX_FIREMODES]; // The weapon loopfires and will not idle when shooting - str worldhitspawn[MAX_FIREMODES]; // The models to spawn when the weapon strikes the world + str ammo_type[MAX_FIREMODES]; // The type of ammo used + int ammorequired[MAX_FIREMODES]; // The amount of ammo required to fire this weapon + int startammo[MAX_FIREMODES]; // The starting amount of ammo when the weapon is picked up + str projectileModel[MAX_FIREMODES]; // The model of the projectile fired + float bulletdamage[MAX_FIREMODES]; // The amount of damate a single bullet causes + float bulletcount[MAX_FIREMODES]; // The number of bullets the weapon fires + int bulletlarge[MAX_FIREMODES]; // The number of bullets the weapon fires + float bulletrange[MAX_FIREMODES]; // The range of the bullet + float bulletknockback[MAX_FIREMODES]; // The amount of knockback a bullet causes + float bulletthroughwood[MAX_FIREMODES]; // The amount of knockback a bullet causes + float bulletthroughmetal[MAX_FIREMODES]; // The amount of knockback a bullet causes + float projectilespeed[MAX_FIREMODES]; // The speed of the projectile fired + Vector bulletspread[MAX_FIREMODES]; // The amount of spread bullets can have + Vector bulletspreadmax[MAX_FIREMODES]; // The max amount of spread bullets can have + firetype_t firetype[MAX_FIREMODES]; // The type of fire (projectile or bullet) + int ammo_clip_size[MAX_FIREMODES]; // The amount of rounds the clip can hold + int ammo_in_clip[MAX_FIREMODES]; // The current amount of ammo in the clip + float max_charge_time[MAX_FIREMODES]; // The max amount of time the weapon may be charged. + float min_charge_time[MAX_FIREMODES]; // The min amount of time the weapon may be charged. + meansOfDeath_t meansofdeath[MAX_FIREMODES]; // The means of death for this mode + qboolean loopfire[MAX_FIREMODES]; // The weapon loopfires and will not idle when shooting + str worldhitspawn[MAX_FIREMODES]; // The models to spawn when the weapon strikes the world int tracerfrequency[MAX_FIREMODES]; int tracercount[MAX_FIREMODES]; float tracerspeed[MAX_FIREMODES]; @@ -234,27 +235,27 @@ public: SafePtr aim_target; protected: - friend class Player; - friend class PlayerBot; - friend class Sentient; + friend class Player; + friend class PlayerBot; + friend class Sentient; void SetMaxRangeEvent(Event *ev); void SetMinRangeEvent(Event *ev); void SetSecondaryAmmo(const char *type, int amount, int startamount); void DetachGun(void); - void AttachGun(weaponhand_t hand, qboolean holstering = qfalse); - qboolean IsSecondaryWeapon(void); + void AttachGun(weaponhand_t hand, qboolean holstering = qfalse); + qboolean IsSecondaryWeapon(void); void PickupWeapon(Event *ev); void DoneRaising(Event *ev); void DoneFiring(Event *ev); void Idle(Event *ev); - void IdleInit(Event* ev); - void FillAmmoClip(Event* ev); - void EmptyAmmoClip(Event* ev); - void AddToAmmoClip(Event* ev); + void IdleInit(Event *ev); + void FillAmmoClip(Event *ev); + void EmptyAmmoClip(Event *ev); + void AddToAmmoClip(Event *ev); void DoneReloading(Event *ev); - void ApplyFireKickback(const Vector& org, float kickback); + virtual void ApplyFireKickback(const Vector& org, float kickback); void SetAimAnim(Event *ev); virtual void Shoot(Event *ev); void Secondary(Event *ev); @@ -270,7 +271,7 @@ protected: void SetDMBulletRange(Event *ev); void SetBulletKnockback(Event *ev); void SetDMBulletKnockback(Event *ev); - void SetBulletThroughWood(Event *ev); // Added in 2.0 + void SetBulletThroughWood(Event *ev); // Added in 2.0 void SetBulletThroughMetal(Event *ev); // Added in 2.0 void SetBulletCount(Event *ev); void SetDMBulletCount(Event *ev); @@ -282,11 +283,11 @@ protected: void SetDMFireSpreadMult(Event *ev); void SetTracerFrequency(Event *ev); void SetAutoPutaway(Event *ev); - void SetRange(Event* ev); - void SetWeaponType(Event* ev); - void SetWeaponGroup(Event* ev); - void SetUseNoAmmo(Event* ev); - void MainAttachToTag(Event* ev); + void SetRange(Event *ev); + void SetWeaponType(Event *ev); + void SetWeaponGroup(Event *ev); + void SetUseNoAmmo(Event *ev); + void MainAttachToTag(Event *ev); void OffHandAttachToTag(Event *ev); void HolsterAttachToTag(Event *ev); void SetHolsterOffset(Event *ev); @@ -297,17 +298,17 @@ protected: void SetMovementSpeed(Event *ev); void SetDMMovementSpeed(Event *ev); void SetMaxFireMovement(Event *ev); // Added in 2.0 - void SetZoomMovement(Event *ev); // Added in 2.0 + void SetZoomMovement(Event *ev); // Added in 2.0 void EventAmmoPickupSound(Event *ev); void EventNoAmmoSound(Event *ev); void EventMaxMovementSound(Event *ev); // Added in 2.0 //==== // Added in 2.0 - void SetNumFireAnims(Event *ev); - void SetWeaponSubtype(Event *ev); - void SetCookTime(Event *ev); - void SetCurrentFireAnim(Event *ev); - void SetSecondaryAmmoInHud(Event* ev); + void SetNumFireAnims(Event *ev); + void SetWeaponSubtype(Event *ev); + void SetCookTime(Event *ev); + void SetCurrentFireAnim(Event *ev); + void SetSecondaryAmmoInHud(Event *ev); //==== void ShowInfo(float fDot, float fDist) override; @@ -315,18 +316,18 @@ public: CLASS_PROTOTYPE(Weapon); Weapon(); - Weapon(const char* file); + Weapon(const char *file); ~Weapon(); - void Delete(void) override; - int GetRank(void); - int GetOrder(void); + void Delete(void) override; + int GetRank(void); + int GetOrder(void); int GetWeaponClass(void) const; const_str GetWeaponGroup(void) const; - void SetItemSlot(int slot); + void SetItemSlot(int slot); void SetRank(int order, int rank); void SetRankEvent(Event *ev); float GetMaxRange(void); @@ -360,8 +361,8 @@ public: void SetAmmoClipSize(Event *ev); void SetAmmoInClip(Event *ev); void SetShareClip(Event *ev); - void SetTagBarrel(const char* tagBarrel); // Added in 2.0 - str GetTagBarrel() const; // Added in 2.0 + void SetTagBarrel(const char *tagBarrel); // Added in 2.0 + str GetTagBarrel() const; // Added in 2.0 void SetModels(const char *world, const char *view); void SetOwner(Sentient *ent) override; void SetMaxChargeTime(Event *ev); @@ -374,88 +375,96 @@ public: qboolean HasAmmoInClip(firemode_t mode); int GetClipSize(firemode_t mode); - qboolean CheckReload(firemode_t mode); + qboolean CheckReload(firemode_t mode); qboolean ShouldReload(void); - void SetShouldReload(qboolean should_reload); - void StartReloading(void); + void SetShouldReload(qboolean should_reload); + void StartReloading(void); - qboolean ReadyToFire(firemode_t mode, qboolean playsound = qtrue); - qboolean MuzzleClear(void); + virtual qboolean ReadyToFire(firemode_t mode, qboolean playsound = qtrue); + qboolean MuzzleClear(void); - void PutAway(void); - qboolean Drop(void) override; - void Fire(firemode_t mode); - void Charge(firemode_t mode); - void OnOverCookedWarning(Event *ev); // Added in 2.0 - void OnOverCooked(Event *ev); // Added in 2.0 - void ReleaseFire(firemode_t mode, float chargetime); - const char* GetFireAnim() const; // Added in 2.0 - void ClientFireDone(void); - qboolean Removable(void) override; - qboolean Pickupable(Entity *other) override; - void DetachFromOwner(void); - void AttachToOwner(weaponhand_t hand); - void WeaponSound(Event *ev); - void GetMuzzlePosition( - Vector *position, Vector *forward = NULL, Vector *right = NULL, Vector *up = NULL, Vector *vBarrelPos = NULL - ); - qboolean AutoChange(void); - int ClipAmmo(firemode_t mode); - qboolean IsDroppable(void); - float FireDelay(firemode_t mode); - void SetFireDelay(Event *ev); - void SetDMFireDelay(Event* ev); + void PutAway(void); + qboolean Drop(void) override; + void Fire(firemode_t mode); + void Charge(firemode_t mode); + void OnOverCookedWarning(Event *ev); // Added in 2.0 + void OnOverCooked(Event *ev); // Added in 2.0 + void ReleaseFire(firemode_t mode, float chargetime); + const char *GetFireAnim() const; // Added in 2.0 + void ClientFireDone(void); + qboolean Removable(void) override; + qboolean Pickupable(Entity *other) override; + virtual void DetachFromOwner(void); + void AttachToOwner(weaponhand_t hand); + void WeaponSound(Event *ev); + virtual void GetMuzzlePosition( + vec3_t position, vec3_t vBarrelPos = NULL, vec3_t forward = NULL, vec3_t right = NULL, vec3_t up = NULL + ); + qboolean AutoChange(void); + int ClipAmmo(firemode_t mode); + qboolean IsDroppable(void); + virtual float FireDelay(firemode_t mode); + virtual void SetFireDelay(Event *ev); + void SetDMFireDelay(Event *ev); - weaponstate_t GetState(void); - void ForceState(weaponstate_t state); + weaponstate_t GetState(void); + void ForceState(weaponstate_t state); - void NotDroppableEvent(Event *ev); - void GiveStartingAmmoToOwner(Event *ev); - void AutoAim(Event *ev); - void Crosshair(Event *ev); - void DMCrosshair(Event *ev); - void SetZoom(Event *ev); - void SetSemiAuto(Event *ev); - void AttachToHand(Event *ev); - void SetCantPartialReload(Event *ev); - void SetDMCantPartialReload(Event *ev); - void AddAdditionalStartAmmo(Event *ev); // Added in 2.0 - void AddStartItem(Event *ev); // Added in 2.0 - void SetQuiet(Event *ev); - void SetLoopFire(Event *ev); + void NotDroppableEvent(Event *ev); + void GiveStartingAmmoToOwner(Event *ev); + void AutoAim(Event *ev); + void Crosshair(Event *ev); + void DMCrosshair(Event *ev); + void SetZoom(Event *ev); + void SetSemiAuto(Event *ev); + void AttachToHand(Event *ev); + void SetCantPartialReload(Event *ev); + void SetDMCantPartialReload(Event *ev); + void AddAdditionalStartAmmo(Event *ev); // Added in 2.0 + void AddStartItem(Event *ev); // Added in 2.0 + void SetQuiet(Event *ev); + void SetLoopFire(Event *ev); virtual void SpecialFireProjectile( Vector pos, Vector forward, Vector right, Vector up, Entity *owner, str projectileModel, float charge_fraction ); - void AttachToHolster(weaponhand_t hand); - str GetCurrentAttachToTag(void); - void SetCurrentAttachToTag(str s); - str GetHolsterTag(void); - qboolean GetUseNoAmmo(void); + virtual void AttachToHolster(weaponhand_t hand); + str GetCurrentAttachToTag(void); + void SetCurrentAttachToTag(str s); + str GetHolsterTag(void); + qboolean GetUseNoAmmo(void); int GetZoom(void); qboolean GetAutoZoom(void); void SetMeansOfDeath(Event *ev); meansOfDeath_t GetMeansOfDeath(firemode_t mode); - void SetAimTarget(Entity*); + void SetAimTarget(Entity *); void SetIdleState(int state); // Added in 2.0 void WorldHitSpawn(firemode_t mode, Vector org, Vector angles, float life); void MakeNoise(Event *ev); void FallingAngleAdjust(Event *ev); float GetMovementSpeed() const; - qboolean GetUseCrosshair() const; + qboolean GetUseCrosshair() const; - virtual bool IsCarryableTurret(); // Added in 2.0 + virtual bool IsCarryableTurret() const; // Added in 2.0 - void Archive(Archiver &arc) override; + void Archive(Archiver& arc) override; // - // Added in openmohaa - // - Listener* GetScriptOwner(void) override; - float GetBulletRange(firemode_t firemode); - firemode_t GetFireMode(void); - qboolean IsSemiAuto(void); + // Added in OPM + // + Listener *GetScriptOwner(void) override; + float GetBulletRange(firemode_t firemode); + float GetSpreadFactor(firemode_t firemode); + float GetChargeFraction(void) const; + firemode_t GetFireMode(void); + qboolean IsSemiAuto(void); + void DoneAnimating(Event *ev); + void EventGetPutaway(Event *ev); + + float GetMaxFireMovementMult() const; + float GetZoomMovement() const; + float GetMaxFireMovement() const; }; inline void Weapon::Archive(Archiver& arc) @@ -529,8 +538,8 @@ inline void Weapon::Archive(Archiver& arc) arc.ArchiveFloat(&bulletknockback[0]); arc.ArchiveFloat(&bulletknockback[1]); arc.ArchiveFloat(&bulletthroughwood[0]); - arc.ArchiveFloat(&bulletthroughwood[0]); - arc.ArchiveFloat(&bulletthroughmetal[1]); + arc.ArchiveFloat(&bulletthroughwood[1]); + arc.ArchiveFloat(&bulletthroughmetal[0]); arc.ArchiveFloat(&bulletthroughmetal[1]); arc.ArchiveFloat(&projectilespeed[0]); arc.ArchiveFloat(&projectilespeed[1]); @@ -590,6 +599,7 @@ inline void Weapon::Archive(Archiver& arc) ArchiveEnum(firemodeindex, firemode_t); + arc.ArchiveInteger(&weapon_class); Director.ArchiveString(arc, m_csWeaponGroup); arc.ArchiveFloat(&m_fMovementSpeed); arc.ArchiveFloat(&m_fMaxFireMovement); @@ -619,5 +629,3 @@ inline void Weapon::Archive(Archiver& arc) } typedef SafePtr WeaponPtr; - -#endif /* weapon.h */ diff --git a/code/fgame/weapturret.cpp b/code/fgame/weapturret.cpp index 274e7757..9857ac24 100644 --- a/code/fgame/weapturret.cpp +++ b/code/fgame/weapturret.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -25,1432 +25,2213 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110EV_DEFAULT301 U #include "g_phys.h" #include "weapturret.h" +#include "vehicleturret.h" #include "player.h" +#include "../script/scriptexception.h" + +static cvar_t *pTurretCameras = NULL; Event EV_Turret_IdleCheckOffset ( - "idleCheckOffset", - EV_DEFAULT, - "v", - "offset", - "Sets the to trace to for collision checking when idling" + "idleCheckOffset", + EV_DEFAULT, + "v", + "offset", + "Sets the offset to trace to for collision checking when idling", + EV_NORMAL ); - -Event EV_Turret_ViewOffset +Event EV_Turret_P_ViewOffset ( - "viewOffset", - EV_DEFAULT, - "v", - "offset", - "Sets the view to use for the turret" + "viewOffset", + EV_DEFAULT, + "v", + "offset", + "Sets the view offset to use for the turret", + EV_NORMAL ); - -Event EV_Turret_SetPlayerUsable +Event EV_Turret_MaxIdlePitch ( - "setPlayerUsable", - EV_DEFAULT, - "i", - "state", - "Sets wether the turret can be used by players. 0 means no, 1 means yes." + "maxIdlePitch", + EV_DEFAULT, + "f", + "offset", + "Sets the offset to trace to for collision checking when idling", + EV_NORMAL ); - -Event EV_Turret_SetAimTarget +Event EV_Turret_MaxIdleYaw ( - "setAimTarget", - EV_DEFAULT, - "S", - "target", - "Makes the turret aim at an entity" + "maxIdleYaw", + EV_DEFAULT, + "f", + "offset", + "Sets the offset to trace to for collision checking when idling", + EV_NORMAL ); - -Event EV_Turret_SetAimOffset +Event EV_Turret_P_SetPlayerUsable ( - "setAimOffset", - EV_DEFAULT, - "v", - "offset", - "Makes the turret aim with specified offset" + "setPlayerUsable", + EV_DEFAULT, + "i", + "state", + "Sets whether the turret can be used by players. 0 means no, 1 means yes.", + EV_NORMAL ); - -Event EV_Turret_ClearAimTarget +Event EV_Turret_AI_SetAimTarget ( - "clearAimTarget", - EV_DEFAULT, - "S", - "target", - "Makes the turret aim at an entity" + "setAimTarget", + EV_DEFAULT, + "S", + "target", + "Makes the turret aim at an entity", + EV_NORMAL ); - -Event EV_Turret_StartFiring +Event EV_Turret_AI_SetAimOffset ( - "startFiring", - EV_DEFAULT, - 0, - 0, - "Makes the turret start shooting" + "setAimOffset", + EV_DEFAULT, + "v", + "offset", + "Makes the turret aim with specified offset", + EV_NORMAL ); - -Event EV_Turret_StopFiring +Event EV_Turret_AI_ClearAimTarget ( - "stopFiring", - EV_DEFAULT, - 0, - 0, - "Makes the turret stop shooting" + "clearAimTarget", + EV_DEFAULT, + "S", + "target", + "Makes the turret aim at an entity", + EV_NORMAL ); - -Event EV_Turret_TurnSpeed +Event EV_Turret_AI_StartFiring ( - "turnSpeed", - EV_DEFAULT, - "f", - "speed", - "Sets the turret's turn speed" + "startFiring", + EV_DEFAULT, + NULL, + NULL, + "Makes the turret start shooting", + EV_NORMAL +); +Event EV_Turret_AI_StopFiring +( + "stopFiring", + EV_DEFAULT, + NULL, + NULL, + "Makes the turret stop shooting", + EV_NORMAL +); +Event EV_Turret_AI_TurnSpeed +( + "turnSpeed", + EV_DEFAULT, + "f", + "speed", + "Sets the turret's turn speed", + EV_NORMAL +); +Event EV_Turret_AI_PitchSpeed +( + "pitchSpeed", + EV_DEFAULT, + "f", + "speed", + "Sets the turret's pitch speed", + EV_NORMAL ); - Event EV_Turret_PitchCaps ( - "pitchCaps", - EV_DEFAULT, - "v", - "caps", - "Sets the pitch caps for the turret. First number is upward cap, second is downward cap, and the third just makes it nice little vector" + "pitchCaps", + EV_DEFAULT, + "v", + "caps", + "Sets the pitch caps for the turret. First number is upward cap, second is downward cap, and the third just makes " + "it " + "nice little vector", + EV_NORMAL ); - Event EV_Turret_MaxYawOffset ( - "maxYawOffset", - EV_DEFAULT, - "f", - "maxoffset", - "Sets the max yaw from the turrets central facing direction" + "maxYawOffset", + EV_DEFAULT, + "f", + "maxoffset", + "Sets the max yaw offset from the turrets central facing direction", + EV_NORMAL ); - Event EV_Turret_YawCenter ( - "yawCenter", - EV_DEFAULT, - "f", - "yaw", - "Sets the yaw for the center of the turret's turning arc" + "yawCenter", + EV_DEFAULT, + "f", + "yaw", + "Sets the yaw for the center of the turret's turning arc", + EV_NORMAL ); - -Event EV_Turret_UserDistance +Event EV_Turret_P_UserDistance ( - "userdistance", - EV_DEFAULT, - "f", - "min_dist", - "Sets the distance the user should be placed at while using this turret" + "userdistance", + EV_DEFAULT, + "f", + "dist", + "Sets the distance the user should be placed at while using this turret", + EV_NORMAL ); - -Event EV_Turret_ViewJitter +Event EV_Turret_P_ViewJitter ( - "viewjitter", - EV_DEFAULT, - "f", - "amount", - "Sets the amount that the owner's view should be jittered when fired" + "viewjitter", + EV_DEFAULT, + "f", + "amount", + "Sets the amount that the owner's view should be jittered when fired", + EV_NORMAL ); - -Event EV_Turret_BurstFireSettings +Event EV_Turret_EventDoJitter ( - "burstFireSettings", - EV_DEFAULT, - "ffff", - "mintime maxtime mindelay maxdelay", - "Sets the settings for burst mode firing" + "dojitter", + EV_DEFAULT, + "F", + "jitterAmount", + "Apply the jitter without firing", + EV_NORMAL +); +Event EV_Turret_AI_BurstFireSettings +( + "burstFireSettings", + EV_DEFAULT, + "ffff", + "mintime maxtime mindelay maxdelay", + "Sets the settings for burst mode firing", + EV_NORMAL ); - Event EV_Turret_Enter ( - "turretenter", - EV_DEFAULT, - "eS", - "turret driver_anim", - "Called when someone gets into a turret." + "turretenter", + EV_DEFAULT, + "eS", + "turret driver_anim", + "Called when someone gets into a turret.", + EV_NORMAL ); - Event EV_Turret_Exit ( - "turretexit", - EV_DEFAULT, - "e", - "turret", - "Called when driver gets out of the turret." + "turretexit", + EV_DEFAULT, + "e", + "turret", + "Called when driver gets out of the turret.", + EV_NORMAL ); - -Event EV_Turret_SetThread +Event EV_Turret_P_SetThread ( - "setthread", - EV_DEFAULT, - "s", - "value", - "Sets the name of the thread called when a player uses the turret" + "setthread", + EV_DEFAULT, + "s", + "value", + "Sets the name of the thread called when a player uses the turret", + EV_NORMAL +); +Event EV_Turret_AI_SetTargetType +( + "targettype", + EV_DEFAULT, + "s", + "value", + "Sets the target type to be none, any, or player", + EV_NORMAL +); +Event EV_Turret_AI_SetTargetType2 +( + "targettype", + EV_DEFAULT, + "s", + "value", + "Sets the target type to be none any, or player", + EV_SETTER +); +Event EV_Turret_AI_GetTargetType +( + "targettype", + EV_DEFAULT, + NULL, + NULL, + "Gets the target type", + EV_GETTER +); +Event EV_Turret_AI_ConvergeTime +( + "convergeTime", + EV_DEFAULT, + "f", + "time", + "Sets the convergence time", + EV_NORMAL +); +Event EV_Turret_AI_SuppressTime +( + "suppressTime", + EV_DEFAULT, + "f", + "time", + "Sets the suppression time", + EV_NORMAL +); +Event EV_Turret_AI_SuppressWaitTime +( + "suppressWaitTime", + EV_DEFAULT, + "f", + "time", + "Sets the suppression wait nonfiring time before turret returns to default position", + EV_NORMAL +); +Event EV_Turret_AI_SuppressWidth +( + "suppressWidth", + EV_DEFAULT, + "f", + "radius", + "Sets the horizontal radius of suppression fire", + EV_NORMAL +); +Event EV_Turret_AI_SuppressHeight +( + "suppressHeight", + EV_DEFAULT, + "f", + "radius", + "Sets the vertical radius of suppression fire", + EV_NORMAL +); +Event EV_Turret_SetUsable +( + "setusable", + EV_DEFAULT, + "i", + "state", + "Sets whether the turret can be used as a weapon. 0 means no, 1 means yes.", + EV_NORMAL +); +Event EV_Turret_AI_SetBulletSpread +( + "aibulletspread", + EV_DEFAULT, + "ff", + "bulletSpreadX bulletSpreadY", + "Set the spread of the bullets in the x and y axis", + EV_NORMAL +); +Event EV_Turret_SetMaxUseAngle +( + "maxuseangle", + EV_DEFAULT, + "f", + "maxuseangle", + "Set max use angle to allow player to mount the turret.", + EV_NORMAL +); +Event EV_Turret_SetStartYaw +( + "startyaw", + EV_DEFAULT, + "f", + "startyaw", + "Sets the yaw to be used as the center of our allowed turn arc.", + EV_NORMAL +); +Event EV_Turret_P_SetViewAngles +( + "psetviewangles", + EV_DEFAULT, + "v", + "offset", + "Sets the view angles.", + EV_NORMAL ); -CLASS_DECLARATION( Weapon, TurretGun, NULL ) -{ - { &EV_Trigger_Effect, NULL }, - { &EV_Item_DropToFloor, &TurretGun::PlaceTurret }, - { &EV_Item_Pickup, NULL }, - { &EV_Weapon_Shoot, &TurretGun::Shoot }, - { &EV_Use, &TurretGun::TurretUsed }, - { &EV_Turret_SetPlayerUsable, &TurretGun::SetPlayerUsable }, - { &EV_Turret_IdleCheckOffset, &TurretGun::SetIdleCheckOffset }, - { &EV_Turret_ViewOffset, &TurretGun::SetViewOffset }, - { &EV_Turret_SetAimTarget, &TurretGun::EventSetAimTarget }, - { &EV_Turret_SetAimOffset, &TurretGun::EventSetAimOffset }, - { &EV_Turret_ClearAimTarget, &TurretGun::EventClearAimTarget }, - { &EV_Turret_StartFiring, &TurretGun::EventStartFiring }, - { &EV_Turret_StopFiring, &TurretGun::EventStopFiring }, - { &EV_Turret_TurnSpeed, &TurretGun::EventTurnSpeed }, - { &EV_Turret_PitchCaps, &TurretGun::EventPitchCaps }, - { &EV_Turret_MaxYawOffset, &TurretGun::EventMaxYawOffset }, - { &EV_Turret_YawCenter, &TurretGun::EventYawCenter }, - { &EV_Turret_UserDistance, &TurretGun::EventUserDistance }, - { &EV_Turret_ViewJitter, &TurretGun::EventViewJitter }, - { &EV_Turret_BurstFireSettings, &TurretGun::EventBurstFireSettings }, - { &EV_Turret_SetThread, &TurretGun::EventSetThread }, - { &EV_SetViewangles, &TurretGun::SetViewangles }, - { &EV_GetViewangles, &TurretGun::GetViewangles }, - { NULL, NULL } +CLASS_DECLARATION(Weapon, TurretGun, NULL) { + {&EV_Trigger_Effect, NULL }, + {&EV_Item_DropToFloor, &TurretGun::PlaceTurret }, + {&EV_Item_Pickup, NULL }, + {&EV_Weapon_Shoot, &TurretGun::Shoot }, + {&EV_Use, &TurretGun::TurretUsed }, + {&EV_Turret_P_SetPlayerUsable, &TurretGun::P_SetPlayerUsable }, + {&EV_Turret_SetUsable, &TurretGun::EventSetUsable }, + {&EV_Turret_IdleCheckOffset, &TurretGun::SetIdleCheckOffset }, + {&EV_Turret_P_ViewOffset, &TurretGun::P_SetViewOffset }, + {&EV_Turret_MaxIdlePitch, &TurretGun::EventMaxIdlePitch }, + {&EV_Turret_MaxIdleYaw, &TurretGun::EventMaxIdleYaw }, + {&EV_Turret_AI_SetAimTarget, &TurretGun::AI_EventSetAimTarget }, + {&EV_Turret_AI_SetAimOffset, &TurretGun::AI_EventSetAimOffset }, + {&EV_Turret_AI_ClearAimTarget, &TurretGun::AI_EventClearAimTarget }, + {&EV_Turret_AI_StartFiring, &TurretGun::AI_EventStartFiring }, + {&EV_Turret_AI_StopFiring, &TurretGun::AI_EventStopFiring }, + {&EV_Turret_AI_TurnSpeed, &TurretGun::AI_EventTurnSpeed }, + {&EV_Turret_AI_PitchSpeed, &TurretGun::AI_EventPitchSpeed }, + {&EV_Turret_PitchCaps, &TurretGun::EventPitchCaps }, + {&EV_Turret_MaxYawOffset, &TurretGun::EventMaxYawOffset }, + {&EV_Turret_YawCenter, &TurretGun::EventYawCenter }, + {&EV_Turret_P_UserDistance, &TurretGun::P_EventUserDistance }, + {&EV_Turret_P_ViewJitter, &TurretGun::P_EventViewJitter }, + {&EV_Turret_EventDoJitter, &TurretGun::P_EventDoJitter }, + {&EV_Turret_AI_BurstFireSettings, &TurretGun::AI_EventBurstFireSettings }, + {&EV_Turret_P_SetThread, &TurretGun::EventSetThread }, + {&EV_Turret_SetMaxUseAngle, &TurretGun::P_SetMaxUseAngle }, + {&EV_Turret_SetStartYaw, &TurretGun::P_SetStartYaw }, + {&EV_Turret_P_SetViewAngles, &TurretGun::P_SetViewAnglesForTurret }, + {&EV_SetViewangles, &TurretGun::P_SetViewangles }, + {&EV_GetViewangles, &TurretGun::P_GetViewangles }, + {&EV_Turret_AI_SetTargetType, &TurretGun::AI_EventSetTargetType }, + {&EV_Turret_AI_SetTargetType2, &TurretGun::AI_EventSetTargetType }, + {&EV_Turret_AI_GetTargetType, &TurretGun::AI_EventGetTargetType }, + {&EV_Turret_AI_ConvergeTime, &TurretGun::AI_EventSetConvergeTime }, + {&EV_Turret_AI_SuppressTime, &TurretGun::AI_EventSetSuppressTime }, + {&EV_Turret_AI_SuppressWaitTime, &TurretGun::AI_EventSetSuppressWaitTime}, + {&EV_Turret_AI_SuppressWidth, &TurretGun::AI_EventSetSuppressWidth }, + {&EV_Turret_AI_SuppressHeight, &TurretGun::AI_EventSetSuppressHeight }, + {&EV_Turret_AI_SetBulletSpread, &TurretGun::AI_EventSetBulletSpread }, + {NULL, NULL } }; TurretGun::TurretGun() { - entflags |= EF_TURRET; + entflags |= ECF_TURRET; - AddWaitTill(STRING_ONTARGET); + AddWaitTill(STRING_ONTARGET); - if( LoadingSavegame ) - { - return; - } + if (LoadingSavegame) { + return; + } - // turrets must not respawn - // it can't be picked up - setRespawn( qfalse ); + // turrets must not respawn + // it can't be picked up + setRespawn(qfalse); - // allow monsters to use the turret - respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS; + // allow monsters to use the turret + respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS; - // set the clipmask - edict->clipmask = MASK_AUTOCALCLIFE; + // set the clipmask + edict->clipmask = MASK_AUTOCALCLIFE; - m_iIdleHitCount = 0; + // make the turret already usable + m_bUsable = true; + m_bPlayerUsable = true; + m_bRestable = true; - // set the fakebullets - m_bFakeBullets = ( spawnflags & FAKEBULLETS ); + // set the fakebullets + m_bFakeBullets = (spawnflags & FAKEBULLETS); - // make the turret already usable - m_bUsable = true; - m_bPlayerUsable = true; - m_bRestable = true; + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + m_fMaxIdlePitch = -80; + m_fMaxIdleYaw = 180; - m_fIdlePitchSpeed = 0; + // set the size + setSize(Vector(-16, -16, -8), Vector(16, 16, 32)); - // set the size - setSize( Vector( -16, -16, -8 ), Vector( 16, 16, 32 ) ); + // setup the turret angles cap + m_fTurnSpeed = 180; + m_fAIPitchSpeed = 180; + m_fPitchUpCap = -45; + m_fPitchDownCap = 45; + m_fMaxYawOffset = 180; + m_fUserDistance = 64; - // setup the turret angles cap - m_fTurnSpeed = 180.0f; - m_fPitchUpCap = -45.0f; - m_fPitchDownCap = 45.0f; - m_fMaxYawOffset = 180.0f; - m_fUserDistance = 64.0f; + // set the idle angles + m_vIdleCheckOffset = Vector(-56, 0, 0); - // set the idle angles - m_vIdleCheckOffset = Vector( -56, 0, 0 ); + // set the burst time + m_fMinBurstTime = 0; + m_fMaxBurstTime = 0; + // set the burst delay + m_fMinBurstDelay = 0; + m_fMaxBurstDelay = 0; - // set the burst time - m_fMinBurstTime = 0; - m_fMaxBurstTime = 0; + m_fFireToggleTime = level.time; + m_iFiring = 0; + m_iTargetType = 0; - // set the burst delay - m_fMinBurstDelay = 0; - m_fMaxBurstDelay = 0; + // set the camera + m_pUserCamera = NULL; - m_iFiring = 0; - m_fFireToggleTime = level.time; + // setup the view jitter + m_fViewJitter = 0; + m_fCurrViewJitter = 0; + // turret doesn't have an owner when spawning + m_bHadOwner = false; + m_pViewModel = NULL; - // set the camera - m_pUserCamera = NULL; + m_iAIState = 0; + m_fAIConvergeTime = g_turret_convergetime->value; + if (m_fAIConvergeTime < 0) { + m_fAIConvergeTime = 0; + } - // setup the view jitter - m_fViewJitter = 0; - m_fCurrViewJitter = 0; + m_iAISuppressTime = g_turret_suppresstime->value * 1000; + if (m_iAISuppressTime < 0) { + m_iAISuppressTime = 0; + } - // turret doesn't have an owner when spawning - m_bHadOwner = 0; + m_iAISuppressWaitTime = g_turret_suppresswaittime->value * 1000; + if (m_iAISuppressWaitTime < 0) { + m_iAISuppressWaitTime = 0; + } - m_pViewModel = NULL; + m_iAILastTrackTime = 0; + m_iAIStartSuppressTime = 0; + VectorClear(m_vDesiredTargetAngles); + m_fAIDesiredTargetSpeed = 0; + VectorClear(m_vAIDesiredTargetPosition); + VectorClear(m_vAITargetPosition); + VectorClear(m_vAICurrentTargetPosition); + VectorClear(m_vAITargetSpeed); + m_iAINextSuppressTime = 0; + m_fAISuppressWidth = 256; + m_fAISuppressHeight = 64; + VectorClear(m_vMuzzlePosition); + fire_delay[FIRE_PRIMARY] = 0.05f; + m_fMaxUseAngle = 80; } TurretGun::~TurretGun() { - Unregister( STRING_ONTARGET ); + Unregister(STRING_ONTARGET); - entflags &= ~EF_TURRET; + // + // Added in OPM: + // Remove the user camera if any. + // + if (m_pUserCamera) { + RemoveUserCamera(); + } + + // + // Added in OPM: + // Remove the view model. + // + if (m_pViewModel) { + m_pViewModel->Delete(); + m_pViewModel = NULL; + } + + // + // Added in OPM: + // Detach the owner from the turret. + // + if (owner && owner->IsSubclassOfPlayer()) { + Player *player = static_cast(owner.Pointer()); + player->ExitTurret(); + } + + entflags &= ~ECF_TURRET; } -void TurretGun::Archive - ( - Archiver& arc - ) +void TurretGun::PlaceTurret(Event *ev) { - Weapon::Archive( arc ); + // Don't make the turret solid + setSolidType(SOLID_NOT); - arc.ArchiveBool( &m_bFakeBullets ); - arc.ArchiveBool( &m_bPlayerUsable ); + // The turret shouldn't move + setMoveType(MOVETYPE_NONE); - arc.ArchiveFloat( &m_fIdlePitchSpeed ); - arc.ArchiveInteger( &m_iIdleHitCount ); - arc.ArchiveVector( &m_vIdleCheckOffset ); - arc.ArchiveVector( &m_vViewOffset ); + showModel(); - arc.ArchiveFloat( &m_fTurnSpeed ); - arc.ArchiveFloat( &m_fPitchUpCap ); - arc.ArchiveFloat( &m_fPitchDownCap ); - arc.ArchiveFloat( &m_fStartYaw ); - arc.ArchiveFloat( &m_fMaxYawOffset ); - arc.ArchiveFloat( &m_fUserDistance ); + m_fStartYaw = angles[1]; + groundentity = NULL; - arc.ArchiveFloat( &m_fMinBurstTime ); - arc.ArchiveFloat( &m_fMaxBurstTime ); - arc.ArchiveFloat( &m_fMinBurstDelay ); - arc.ArchiveFloat( &m_fMaxBurstDelay ); + if (m_bFakeBullets) { + firetype[FIRE_PRIMARY] = FT_FAKEBULLET; + } - arc.ArchiveFloat( &m_fFireToggleTime ); - arc.ArchiveInteger( &m_iFiring ); - arc.ArchiveVector( &m_vUserViewAng ); - arc.ArchiveSafePointer( &m_pUserCamera ); - - arc.ArchiveFloat( &m_fViewJitter ); - arc.ArchiveFloat( &m_fCurrViewJitter ); - - arc.ArchiveVector( &m_Aim_offset ); - arc.ArchiveSafePointer( &m_pViewModel ); - arc.ArchiveBool( &m_bUsable ); - - m_UseThread.Archive( arc ); - - arc.ArchiveBool( &m_bHadOwner ); - arc.ArchiveBool( &m_bRestable ); - - if( arc.Loading() ) - { - m_vUserLastCmdAng = vec_zero; - } + flags |= FL_THINK; } -void TurretGun::SetTargetAngles - ( - Vector& vTargAngles - ) +void TurretGun::ThinkIdle(void) { - float fDiff; - float fTurnAmount; + Vector vDir, vNewAngles, vEnd; + trace_t trace; - if( vTargAngles[ 0 ] > 180.0f ) - { - vTargAngles[ 0 ] -= 360.0f; - } - else if( vTargAngles[ 0 ] < -180.0f ) - { - vTargAngles[ 0 ] += 360.0f; - } + if (!m_bRestable) { + return; + } - if( vTargAngles[ 0 ] < m_fPitchUpCap ) - { - vTargAngles[ 0 ] = m_fPitchUpCap; - } + if (angles[0] > 180) { + angles[0] -= 360; + } - if( vTargAngles[ 0 ] > m_fPitchDownCap ) - { - vTargAngles[ 0 ] = m_fPitchDownCap; - } + if (angles[0] <= m_fMaxIdlePitch) { + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + angles[0] = m_fMaxIdlePitch; + setAngles(angles); + return; + } - if( owner && owner->IsSubclassOfPlayer() ) - { - fTurnAmount = 180.0f; - } - else - { - fTurnAmount = level.frametime * m_fTurnSpeed; - } + if (m_iIdleHitCount >= 2) { + return; + } - fDiff = AngleSubtract( m_fPitchDownCap, angles[ 0 ] ); - if( fTurnAmount <= fabs( fDiff ) ) - { - if( fDiff <= 0.0f ) - { - angles[ 0 ] = angles[ 0 ] - fTurnAmount; - } - else - { - angles[ 0 ] = fTurnAmount + angles[ 0 ]; - } - } - else - { - angles[ 0 ] = vTargAngles[ 0 ]; - } + m_fIdlePitchSpeed -= level.frametime * 300.0f; - fDiff = AngleSubtract( vTargAngles[ 1 ], m_fStartYaw ); - if( fDiff <= m_fMaxYawOffset ) - { - vTargAngles[ 1 ] = fDiff + m_fStartYaw; + vNewAngles = Vector( + Q_max(angles[0] + level.frametime * m_fIdlePitchSpeed, m_fMaxIdlePitch), + angles[1], + angles[2] + ); - if( -( m_fMaxYawOffset ) > fDiff ) - { - vTargAngles[ 1 ] = m_fStartYaw - m_fMaxYawOffset; - } - } - else - { - vTargAngles[ 1 ] = m_fMaxYawOffset + m_fStartYaw; - } + vNewAngles.AngleVectorsLeft(&vDir); + vEnd = origin + vDir * m_vIdleCheckOffset[0]; - fDiff = AngleSubtract( vTargAngles[ 1 ], angles[ 1 ] ); + trace = G_Trace(origin, vec_zero, vec_zero, vEnd, this, edict->clipmask, false, "TurretGun::Think"); - if( fTurnAmount <= fabs( fDiff ) ) - { - if( fDiff <= 0.0f ) - { - angles[ 1 ] = angles[ 1 ] - fTurnAmount; - } - else - { - angles[ 1 ] = angles[ 1 ] + fTurnAmount; - } - } - else - { - angles[ 1 ] = vTargAngles[ 1 ]; - } + if (trace.fraction == 1.0f) { + setAngles(vNewAngles); + m_iIdleHitCount = 0; + return; + } - setAngles( angles ); + int iTry; + for (iTry = 3; iTry > 0; iTry--) { + vNewAngles[0] = angles[0] + level.frametime * m_fIdlePitchSpeed * iTry * 0.25f; + if (vNewAngles[0] < m_fMaxIdlePitch) { + continue; + } - if( fabs( fDiff ) < 2.0f ) - { - Unregister( STRING_ONTARGET ); - } + vNewAngles.AngleVectorsLeft(&vDir); + vEnd = origin + vDir * m_vIdleCheckOffset[0]; + + trace = G_Trace(origin, vec_zero, vec_zero, vEnd, this, edict->clipmask, false, "TurretGun::Think"); + + if (trace.fraction == 1) { + setAngles(vNewAngles); + + m_iIdleHitCount = 0; + m_fIdlePitchSpeed *= 0.25f * iTry; + break; + } + } + + if (!iTry) { + m_fIdlePitchSpeed = 0; + + Entity *ent = G_GetEntity(trace.entityNum); + + if (ent && ent == world) { + m_iIdleHitCount++; + } else { + m_iIdleHitCount = 0; + } + } } -void TurretGun::ThinkActive - ( - void - ) +void TurretGun::AI_SetTargetAngles(vec3_t vTargAngles, float speed) { - Vector vTarg; - Vector vTargAngles; - Vector vDelta; - Vector vAngles; + float fDiff; + float fPitchDiff, fYawDiff; + float fTurnYawSpeed; + float fTurnPitchSpeed; - if( ( owner ) && owner->IsSubclassOfPlayer() ) - { - if( m_vUserViewAng[ 0 ] < m_fPitchUpCap ) - { - m_vUserViewAng[ 0 ] = m_fPitchUpCap; - } - else if( m_vUserViewAng[ 0 ] > m_fPitchDownCap ) - { - m_vUserViewAng[ 0 ] = m_fPitchDownCap; - } + if (vTargAngles[0] > 180.0f) { + vTargAngles[0] -= 360.0f; + } else if (vTargAngles[0] < -180.0f) { + vTargAngles[0] += 360.0f; + } - float fDiff = AngleSubtract( m_vUserViewAng[ 1 ], m_fStartYaw ); + if (vTargAngles[0] < m_fPitchUpCap) { + vTargAngles[0] = m_fPitchUpCap; + } else if (vTargAngles[0] > m_fPitchDownCap) { + vTargAngles[0] = m_fPitchDownCap; + } - if( fDiff <= m_fMaxYawOffset ) - { - m_vUserViewAng[ 1 ] = fDiff + m_fStartYaw; + fDiff = AngleSubtract(vTargAngles[1], m_fStartYaw); + if (fDiff > m_fMaxYawOffset) { + vTargAngles[1] = m_fStartYaw + m_fMaxYawOffset; + } else if (fDiff < -m_fMaxYawOffset) { + vTargAngles[1] = m_fStartYaw - m_fMaxYawOffset; + } - if( -( m_fMaxYawOffset ) > fDiff ) - { - m_vUserViewAng[ 1 ] = m_fStartYaw - m_fMaxYawOffset; - } - } - else - { - m_vUserViewAng[ 1 ] = m_fMaxYawOffset + m_fStartYaw; - } + fYawDiff = AngleSubtract(vTargAngles[1], angles[1]); + fPitchDiff = AngleSubtract(vTargAngles[0], angles[0]); - owner->SetViewAngles( m_vUserViewAng ); - vTarg = owner->GunTarget( false ) - origin; - vTargAngles = vTarg.toAngles(); + if (speed == 0) { + fTurnYawSpeed = m_fTurnSpeed * level.frametime; + fTurnPitchSpeed = m_fAIPitchSpeed * level.frametime; + } else { + float pitchFrameSpeed, yawFrameSpeed; - SetTargetAngles( vTargAngles ); - } - else if( aim_target ) - { - Vector vNewOfs; + // pitch + pitchFrameSpeed = fabs(fPitchDiff) / speed; + if (pitchFrameSpeed > 720) { + pitchFrameSpeed = 720; + } + fTurnPitchSpeed = pitchFrameSpeed * level.frametime; - vDelta = aim_target->centroid - origin; - vNewOfs = vDelta + m_Aim_offset; + // yaw + yawFrameSpeed = fabs(fYawDiff) / speed; + if (yawFrameSpeed > 720) { + yawFrameSpeed = 720; + } + fTurnYawSpeed = yawFrameSpeed * level.frametime; + } - vectoangles( vDelta, vTargAngles ); - SetTargetAngles( vTargAngles ); + if (fabs(fPitchDiff) < fTurnPitchSpeed) { + angles[0] = vTargAngles[0]; + } else if (fPitchDiff > 0) { + angles[0] += fTurnPitchSpeed; + } else { + angles[0] -= fTurnPitchSpeed; + } - if( owner ) - { - Vector forward; + if (fabs(fYawDiff) < fTurnYawSpeed) { + angles[1] = vTargAngles[1]; + } else if (fYawDiff > 0) { + angles[1] += fTurnYawSpeed; + } else { + angles[1] -= fTurnYawSpeed; + } - AngleVectorsLeft( angles, forward, NULL, NULL ); + setAngles(angles); - origin = forward * vNewOfs.length(); - } - } - - if( m_iFiring ) - { - if( m_fMaxBurstTime == 0 || ( owner != NULL && owner->client ) ) - { - m_iFiring = 2; - if( ReadyToFire( FIRE_PRIMARY ) ) - { - Fire( FIRE_PRIMARY ); - - if( owner->IsSubclassOfPlayer() ) - { - m_fCurrViewJitter = m_fViewJitter; - } - } - } - else if( m_iFiring != 2 ) - { - if( level.time > m_fFireToggleTime ) - { - m_iFiring = 2; - m_fFireToggleTime = G_Random( m_fMaxBurstTime - m_fMinBurstTime ) + ( level.time + m_fMinBurstTime ); - } - } - else if( ReadyToFire( FIRE_PRIMARY ) ) - { - Fire( FIRE_PRIMARY ); - - if( owner->IsSubclassOfPlayer() ) - { - m_fCurrViewJitter = m_fViewJitter; - } - } - else if( level.time > m_fFireToggleTime ) - { - m_iFiring = 1; - m_fFireToggleTime = G_Random( m_fMaxBurstDelay - m_fMaxBurstDelay) + ( level.time + m_fMinBurstDelay ); - } - } - - if( owner && owner->IsSubclassOfPlayer() ) - { - vAngles = m_vUserViewAng; - - if( !m_pUserCamera ) { - m_pUserCamera = new Camera; - } - - if( m_fCurrViewJitter > 0.0f ) - { - float x = ( float )( rand() & 0x7FFF ); - float y = ( float )( rand() & 0x7FFF ); - float z = ( float )( rand() & 0x7FFF ); - - vAngles[ 0 ] += ( x * 0.00003f + x * 0.00003f - 1.0f ) * m_fCurrViewJitter; - vAngles[ 1 ] += ( y * 0.00003f + y * 0.00003f - 1.0f ) * m_fCurrViewJitter; - vAngles[ 2 ] += ( z * 0.00003f + z * 0.00003f - 1.0f ) * m_fCurrViewJitter; - - m_fCurrViewJitter -= level.frametime * 6.0f; - - if( m_fCurrViewJitter < 0.0f ) { - m_fCurrViewJitter = 0.0f; - } - } - - m_pUserCamera->setOrigin( origin ); - m_pUserCamera->setAngles( vAngles ); - m_pUserCamera->SetPositionOffset( m_vViewOffset ); - - owner->client->ps.camera_flags |= CF_CAMERA_ANGLES_ALLOWOFFSET; - - Player *player = ( Player * )owner.Pointer(); - - if( !player->IsZoomed() ) - { - player->ToggleZoom( 80 ); - } - } - - if( owner && owner->client ) - { - Vector vPos; - Vector vEnd; - Vector vAng; - Vector vForward; - Vector vMins; - Vector vMaxs; - trace_t trace; - - Vector( 0, angles[ 1 ], 0 ).AngleVectorsLeft( &vForward ); - - vPos = origin - vForward * m_fUserDistance; - vPos[ 2 ] -= 16.0f; - - vEnd = vPos; - vEnd[ 2 ] -= 64.0f; - - vMins = owner->mins; - vMaxs = owner->maxs; - vMaxs[ 2 ] = owner->mins[ 2 ] + 4.0f; - - trace = G_Trace( - vPos, - vMins, - vMaxs, - vEnd, - owner, - MASK_PLAYERSOLID, - qtrue, - "TurretGun::ThinkActive 1" - ); - - vPos = trace.endpos; - - trace = G_Trace( - vPos, - owner->mins, - owner->maxs, - vPos, - owner, - MASK_PLAYERSOLID, - qtrue, - "TurretGun::ThinkActive 2" - ); - - if( !trace.allsolid && !trace.startsolid ) - { - owner->setOrigin( vPos ); - } - } + if (fabs(fDiff) < 2) { + Unregister(STRING_ONTARGET); + } } -void TurretGun::ThinkIdle - ( - void - ) +void TurretGun::AI_SetDesiredTargetAngles(const vec3_t angles, float speed) { - Vector vDir, vNewAngles, vEnd; - trace_t trace; - - if( !m_bRestable ) { - return; - } - - if( angles[ 0 ] > 180.0f ) - { - angles[ 0 ] -= 360.0f; - } - - if( angles[ 0 ] < -80.0f ) - { - m_fIdlePitchSpeed = 0; - m_iIdleHitCount = 0; - return; - } - - if( m_iIdleHitCount > 1 ) - { - return; - } - - m_fIdlePitchSpeed -= level.frametime * 300.0f; - - vNewAngles = Vector( angles[ 0 ] + level.frametime * m_fIdlePitchSpeed, angles[ 1 ], angles[ 2 ] ); - vNewAngles.AngleVectorsLeft( &vDir ); - vEnd = origin + vDir * m_vIdleCheckOffset[ 0 ]; - - trace = G_Trace( - origin, - vec_zero, - vec_zero, - vEnd, - this, - edict->clipmask, - false, - "TurretGun::Think" ); - - if( trace.fraction == 1.0f ) - { - setAngles( vNewAngles ); - m_iIdleHitCount = 0; - return; - } - - int iTry; - for( iTry = 3; iTry > 0; iTry-- ) - { - vNewAngles[ 0 ] = angles[ 0 ] + level.frametime * m_fIdlePitchSpeed * iTry * 0.25f; - vNewAngles.AngleVectorsLeft( &vDir ); - vEnd = origin + vDir * m_vIdleCheckOffset[ 0 ]; - - trace = G_Trace( - origin, - vec_zero, - vec_zero, - vEnd, - this, - edict->clipmask, - false, - "TurretGun::Think" ); - - if( trace.fraction == 1.0f ) - { - setAngles( vNewAngles ); - - m_iIdleHitCount = 0; - m_fIdlePitchSpeed *= 0.25f * iTry; - break; - } - } - - if( !iTry ) - { - m_fIdlePitchSpeed = 0; - - Entity *ent = G_GetEntity( trace.entityNum ); - - if( ent && ent == world ) - { - m_iIdleHitCount++; - } - else - { - m_iIdleHitCount = 0; - } - } + VectorCopy(angles, m_vDesiredTargetAngles); + m_fAIDesiredTargetSpeed = speed; } -void TurretGun::P_ThinkActive() +void TurretGun::P_SetTargetAngles(Vector& vTargAngles) { - // FIXME: unimplemented + float fDiff; + + if (vTargAngles[0] > 180.0f) { + vTargAngles[0] -= 360.0f; + } else if (vTargAngles[0] < -180.0f) { + vTargAngles[0] += 360.0f; + } + + if (vTargAngles[0] < m_fPitchUpCap) { + vTargAngles[0] = m_fPitchUpCap; + } else if (vTargAngles[0] > m_fPitchDownCap) { + vTargAngles[0] = m_fPitchDownCap; + } + + fDiff = AngleSubtract(m_fPitchDownCap, angles[0]); + if (fabs(fDiff) >= 180) { + if (fDiff > 0.0f) { + angles[0] += 180; + } else { + angles[0] -= 180; + } + } else { + angles[0] = vTargAngles[0]; + } + + fDiff = AngleSubtract(vTargAngles[1], m_fStartYaw); + if (fDiff > m_fMaxYawOffset) { + fDiff = m_fMaxYawOffset; + } else if (fDiff < -m_fMaxYawOffset) { + fDiff = -m_fMaxYawOffset; + } + vTargAngles[1] = m_fStartYaw + fDiff; + + fDiff = AngleSubtract(vTargAngles[1], angles[1]); + + if (fabs(fDiff) >= 180) { + if (fDiff > 0.0f) { + angles[1] += 180; + } else { + angles[1] -= 180; + } + } else { + angles[1] = vTargAngles[1]; + } + + setAngles(angles); } -void TurretGun::Think - ( - void - ) +bool TurretGun::AI_CanTarget(const vec3_t pos) { - if (owner || (!m_bHadOwner && aim_target)) - { - ThinkActive(); - } - else - { - ThinkIdle(); - } + vec3_t delta; + Vector vAngles; + float ang; + float yawCap; + + VectorSubtract(pos, origin, delta); + vectoangles(delta, vAngles); + + ang = AngleSubtract(vAngles[1], m_fStartYaw); + + if (vAngles[0] > 180) { + vAngles[0] -= 360; + } else if (vAngles[0] < -180) { + vAngles[0] += 360; + } + + if (vAngles[0] < m_fPitchUpCap || vAngles[0] > m_fPitchDownCap) { + return false; + } + + yawCap = AngleSubtract(vAngles[1], m_fStartYaw); + if (yawCap > m_fMaxYawOffset) { + return false; + } else if (yawCap < -m_fMaxYawOffset) { + return false; + } + + return true; } -void TurretGun::P_UserAim(usercmd_t* cmd) +void TurretGun::P_ThinkActive(void) { - // FIXME: unimplemented + Vector vTarg; + Vector vTargAngles; + Vector vDelta; + Vector vAngles; + + if ((owner) && owner->IsSubclassOfPlayer()) { + if (m_vUserViewAng[0] < m_fPitchUpCap) { + m_vUserViewAng[0] = m_fPitchUpCap; + } else if (m_vUserViewAng[0] > m_fPitchDownCap) { + m_vUserViewAng[0] = m_fPitchDownCap; + } + + float fDiff = AngleSubtract(m_vUserViewAng[1], m_fStartYaw); + + if (fDiff <= m_fMaxYawOffset) { + m_vUserViewAng[1] = fDiff + m_fStartYaw; + + if (-(m_fMaxYawOffset) > fDiff) { + m_vUserViewAng[1] = m_fStartYaw - m_fMaxYawOffset; + } + } else { + m_vUserViewAng[1] = m_fMaxYawOffset + m_fStartYaw; + } + + owner->SetViewAngles(m_vUserViewAng); + vTarg = owner->GunTarget(false) - origin; + vTargAngles = vTarg.toAngles(); + + P_SetTargetAngles(vTargAngles); + } else if (aim_target) { + Vector vNewOfs; + + vDelta = aim_target->centroid - origin; + vNewOfs = vDelta + m_Aim_offset; + + vectoangles(vDelta, vTargAngles); + P_SetTargetAngles(vTargAngles); + + if (owner) { + Vector forward; + + AngleVectorsLeft(angles, forward, NULL, NULL); + + origin = forward * vNewOfs.length(); + } + } + + if (m_iFiring) { + if (m_fMaxBurstTime == 0 || (owner != NULL && owner->client)) { + m_iFiring = 2; + if (ReadyToFire(FIRE_PRIMARY)) { + Fire(FIRE_PRIMARY); + + if (owner->IsSubclassOfPlayer()) { + m_fCurrViewJitter = m_fViewJitter; + } + } + } else if (m_iFiring != 2) { + if (level.time > m_fFireToggleTime) { + m_iFiring = 2; + m_fFireToggleTime = G_Random(m_fMaxBurstTime - m_fMinBurstTime) + (level.time + m_fMinBurstTime); + } + } else if (ReadyToFire(FIRE_PRIMARY)) { + Fire(FIRE_PRIMARY); + + if (owner->IsSubclassOfPlayer()) { + m_fCurrViewJitter = m_fViewJitter; + } + } else if (level.time > m_fFireToggleTime) { + m_iFiring = 1; + m_fFireToggleTime = G_Random(m_fMaxBurstDelay - m_fMaxBurstDelay) + (level.time + m_fMinBurstDelay); + } + } + + if (owner && owner->IsSubclassOfPlayer()) { + vAngles = m_vUserViewAng; + + if (!m_pUserCamera) { + m_pUserCamera = new Camera; + } + + if (m_fCurrViewJitter > 0.0f) { + float x = (float)(rand() & 0x7FFF); + float y = (float)(rand() & 0x7FFF); + float z = (float)(rand() & 0x7FFF); + + vAngles[0] += (x * 0.00003f + x * 0.00003f - 1.0f) * m_fCurrViewJitter; + vAngles[1] += (y * 0.00003f + y * 0.00003f - 1.0f) * m_fCurrViewJitter; + vAngles[2] += (z * 0.00003f + z * 0.00003f - 1.0f) * m_fCurrViewJitter; + + m_fCurrViewJitter -= level.frametime * 6.0f; + + if (m_fCurrViewJitter < 0.0f) { + m_fCurrViewJitter = 0.0f; + } + } + + m_pUserCamera->setOrigin(origin); + m_pUserCamera->setAngles(vAngles); + m_pUserCamera->SetPositionOffset(m_vViewOffset); + + owner->client->ps.camera_flags |= CF_CAMERA_ANGLES_TURRETMODE; + + Player *player = (Player *)owner.Pointer(); + + if (!player->IsZoomed()) { + player->ToggleZoom(80); + } + } + + if (owner && owner->client) { + Vector vPos; + Vector vEnd; + Vector vAng; + Vector vForward; + Vector vMins; + Vector vMaxs; + trace_t trace; + + Vector(0, angles[1], 0).AngleVectorsLeft(&vForward); + + vPos = origin - vForward * m_fUserDistance; + vPos[2] -= 16.0f; + + vEnd = vPos; + vEnd[2] -= 64.0f; + + vMins = owner->mins; + vMaxs = owner->maxs; + vMaxs[2] = owner->mins[2] + 4.0f; + + trace = G_Trace(vPos, vMins, vMaxs, vEnd, owner, MASK_PLAYERSOLID, qtrue, "TurretGun::ThinkActive 1"); + + vPos = trace.endpos; + + trace = + G_Trace(vPos, owner->mins, owner->maxs, vPos, owner, MASK_PLAYERSOLID, qtrue, "TurretGun::ThinkActive 2"); + + if (!trace.allsolid && !trace.startsolid) { + owner->setOrigin(vPos); + } + } } -qboolean TurretGun::UserAim - ( - usercmd_s *ucmd - ) +void TurretGun::AI_DoTargetNone() { - Vector vNewCmdAng; + vec3_t desiredAngles; + vec3_t delta; - if( owner == NULL ) - { - return qfalse; - } + if (!aim_target) { + return; + } - vNewCmdAng = Vector(SHORT2ANGLE(ucmd->angles[0]), SHORT2ANGLE(ucmd->angles[1]), SHORT2ANGLE(ucmd->angles[2])); - - if( vNewCmdAng[ 0 ] || vNewCmdAng[ 1 ] || vNewCmdAng[ 2 ] ) - { - m_vUserViewAng[ 0 ] += AngleSubtract( vNewCmdAng[ 0 ], m_vUserLastCmdAng[ 0 ] ); - m_vUserViewAng[ 1 ] += AngleSubtract( vNewCmdAng[ 1 ], m_vUserLastCmdAng[ 1 ] ); - m_vUserViewAng[ 2 ] += AngleSubtract( vNewCmdAng[ 2 ], m_vUserLastCmdAng[ 2 ] ); - } - - m_vUserLastCmdAng = vNewCmdAng; - - if( ( ucmd->buttons & BUTTON_ATTACKLEFT ) || ( ucmd->buttons & BUTTON_ATTACKRIGHT ) ) - { - if( !m_iFiring ) { - m_iFiring = 1; - } - } - else - { - m_iFiring = 0; - } - - flags |= FL_THINK; - - return qtrue; + VectorSubtract(aim_target->centroid, origin, delta); + VectorAdd(delta, m_Aim_offset, delta); + vectoangles(delta, desiredAngles); + AI_SetTargetAngles(desiredAngles, 0); } -void TurretGun::PlaceTurret - ( - Event *ev - ) +void TurretGun::AI_MoveToDefaultPosition() { - // Don't make the turret solid - setSolidType( SOLID_NOT ); + vec3_t desiredAngles; + // get the first client number + Entity *pEnt = G_GetEntity(0); + if (pEnt) { + vec3_t delta; - // The turret shouldn't move - setMoveType( MOVETYPE_NONE ); + VectorSubtract(pEnt->centroid, origin, delta); + vectoangles(delta, desiredAngles); + } else { + desiredAngles[0] = 0; + } - showModel(); - - groundentity = NULL; - m_fStartYaw = angles[ 1 ]; - - if( m_bFakeBullets ) { - firetype[ FIRE_PRIMARY ] = FT_FAKEBULLET; - } - - flags |= FL_THINK; + desiredAngles[1] = m_fStartYaw; + desiredAngles[2] = 0; + AI_SetDesiredTargetAngles(desiredAngles, 0); } -void TurretGun::TurretBeginUsed - ( - Sentient *pEnt - ) +void TurretGun::AI_DoTargetAutoDefault() { - owner = pEnt; - - edict->r.ownerNum = pEnt->entnum; - m_bHadOwner = true; - - Sound( sPickupSound ); - - if( m_vUserViewAng[ 0 ] > 180.0f ) { - m_vUserViewAng[ 0 ] -= 360.0f; - } - - m_vUserLastCmdAng = vec_zero; - - if( owner->IsSubclassOfPlayer() ) - { - Player *player = ( Player * )owner.Pointer(); - - player->EnterTurret( this ); - - if( !m_pUserCamera ) { - m_pUserCamera = new Camera; - } - - player->SetCamera( m_pUserCamera, 0.0f ); - } - - current_attachToTag = ""; - ForceIdle(); - CreateViewModel(); + m_iFiring = 0; + if (owner->m_Enemy) { + Actor *actor = static_cast(owner.Pointer()); + if (actor->CanSeeEnemy(200)) { + AI_StartTrack(); + } else { + AI_MoveToDefaultPosition(); + } + } } -void TurretGun::P_TurretBeginUsed(Player* pEnt) +void TurretGun::AI_StartDefault() { - // FIXME: unimplemented + m_iFiring = 0; + m_iAIState = 0; +} + +void TurretGun::AI_StartSuppress() +{ + m_iAIStartSuppressTime = level.inttime; + m_iAIState = 2; + VectorCopy(m_vAIDesiredTargetPosition, m_vAITargetPosition); + VectorClear(m_vAICurrentTargetPosition); + VectorClear(m_vAITargetSpeed); + m_iAINextSuppressTime = 0; +} + +void TurretGun::AI_StartSuppressWait() +{ + m_iAIStartSuppressTime = level.inttime; + m_iAIState = 3; +} + +void TurretGun::AI_StartTrack() +{ + if (m_iAIState == 0) { + m_iAILastTrackTime = level.inttime; + } + m_iAIState = 1; +} + +void TurretGun::AI_DoTargetAutoTrack() +{ + Actor *actor; + Vector end; + Vector delta; + vec3_t desiredAngles; + float turnSpeed; + + if (!owner->m_Enemy) { + AI_StartDefault(); + return; + } + + if (owner->m_Enemy != m_pAIEnemy) { + if (m_pAIEnemy) { + m_iAILastTrackTime = level.inttime; + } + m_pAIEnemy = owner->m_Enemy; + } + + actor = static_cast(owner.Pointer()); + if (!actor->CanSeeEnemy(0)) { + AI_StartSuppress(); + return; + } + + if (m_iFiring == 0) { + m_iFiring = 1; + } + + end = owner->m_Enemy->centroid; + if (!G_SightTrace( + m_vMuzzlePosition, + vec_zero, + vec_zero, + end, + this, + owner->m_Enemy, + MASK_AITURRET, + qfalse, + "TurretGun::AI_DoTargetAutoTrack" + )) { + end = owner->m_Enemy->EyePosition(); + } + + VectorCopy(end, m_vAIDesiredTargetPosition); + delta = m_vAIDesiredTargetPosition - origin; + vectoangles(delta, desiredAngles); + + turnSpeed = m_fAIConvergeTime - (level.inttime - m_iAILastTrackTime) / 1000; + if (turnSpeed < 0) { + turnSpeed = 0; + } + + AI_SetDesiredTargetAngles(desiredAngles, turnSpeed); +} + +void TurretGun::AI_DoSuppressionAiming() +{ + float suppressRatio; + float suppressTimeRatio; + float height; + float length; + vec2_t dir; + vec3_t deltaPos; + vec2_t speedxy; + vec3_t desiredAngles; + + suppressRatio = m_fAISuppressHeight / m_fAISuppressWidth; + + if (level.inttime >= m_iAINextSuppressTime) { + suppressTimeRatio = this->m_fAISuppressWidth / 250.0; + dir[0] = m_vAIDesiredTargetPosition[1] - origin[1]; + dir[1] = m_vAIDesiredTargetPosition[0] - origin[0]; + VectorNormalize2D(dir); + + m_iAINextSuppressTime = level.inttime + (((random() + 1) / 2 * suppressTimeRatio) * 1000); + + VectorSubtract(m_vAITargetPosition, m_vAIDesiredTargetPosition, deltaPos); + + // + // calculate the speed at which the AI should turn + // + speedxy[0] = DotProduct2D(deltaPos, dir); + speedxy[1] = deltaPos[2]; + VectorNormalize2D(speedxy); + + speedxy[0] += crandom() / 2.0; + speedxy[1] += crandom() / 2.0; + VectorNormalize2D(speedxy); + + speedxy[0] = 250 / (suppressTimeRatio * 0.5) * speedxy[0]; + speedxy[1] = 250 / (suppressTimeRatio * 0.5) * speedxy[1]; + speedxy[1] *= suppressRatio; + m_vAITargetSpeed[0] = speedxy[0] * dir[0]; + m_vAITargetSpeed[1] = speedxy[0] * dir[1]; + m_vAITargetSpeed[1] = speedxy[1]; + } + + VectorMA(m_vAICurrentTargetPosition, level.frametime, m_vAITargetSpeed, m_vAICurrentTargetPosition); + + height = suppressRatio * 250; + if (m_vAICurrentTargetPosition[2] > height) { + m_vAICurrentTargetPosition[2] = height; + } else if (m_vAICurrentTargetPosition[2] < -height) { + m_vAICurrentTargetPosition[2] = -height; + } + + length = VectorLength2D(m_vAICurrentTargetPosition); + if (length > 250) { + VectorScale2D(m_vAICurrentTargetPosition, 250 / length, m_vAICurrentTargetPosition); + } + + VectorSubtract(m_vAIDesiredTargetPosition, m_vAITargetPosition, deltaPos); + VectorMA(deltaPos, level.frametime, m_vAICurrentTargetPosition, deltaPos); + + if (deltaPos[2] > m_fAISuppressHeight) { + deltaPos[2] = m_fAISuppressHeight; + m_iAINextSuppressTime = 0; + } else if (deltaPos[2] < -m_fAISuppressHeight) { + deltaPos[2] = -m_fAISuppressHeight; + m_iAINextSuppressTime = 0; + } + + length = VectorLength2D(deltaPos); + if (length > m_fAISuppressWidth) { + VectorScale(deltaPos, m_fAISuppressWidth / length, deltaPos); + m_iAINextSuppressTime = 0; + } + + // calculate the target angles + VectorAdd(m_vAITargetPosition, deltaPos, m_vAIDesiredTargetPosition); + VectorSubtract(m_vAIDesiredTargetPosition, origin, deltaPos); + + // set the desired angles + vectoangles(deltaPos, desiredAngles); + AI_SetDesiredTargetAngles(desiredAngles, 0); +} + +void TurretGun::AI_DoTargetAutoSuppress() +{ + Actor *actor; + + if (!owner->m_Enemy) { + AI_StartDefault(); + return; + } + + actor = static_cast(owner.Pointer()); + if (actor->CanSeeEnemy(200)) { + AI_StartTrack(); + return; + } + + if (level.inttime >= m_iAISuppressTime + m_iAIStartSuppressTime) { + AI_StartSuppressWait(); + return; + } + + if (m_iFiring == 0) { + m_iFiring = 1; + } + AI_DoSuppressionAiming(); +} + +void TurretGun::AI_DoTargetAutoSuppressWait() +{ + m_iFiring = 0; + Actor *actor; + + if (!owner->m_Enemy) { + AI_StartDefault(); + return; + } + + actor = static_cast(owner.Pointer()); + if (actor->CanSeeEnemy(200)) { + AI_StartTrack(); + return; + } + + if (level.inttime >= m_iAISuppressWaitTime + m_iAIStartSuppressTime) { + AI_StartDefault(); + return; + } + + AI_DoSuppressionAiming(); +} + +void TurretGun::AI_DoTargetAuto() +{ + if (!owner) { + return; + } + + GetMuzzlePosition(m_vMuzzlePosition, NULL, NULL, NULL, NULL); + + switch (m_iAIState) { + case TURRETAISTATE_DEFAULT: + AI_DoTargetAutoDefault(); + break; + case TURRETAISTATE_TRACK: + AI_DoTargetAutoTrack(); + break; + case TURRETAISTATE_SUPPRESS: + AI_DoTargetAutoSuppress(); + break; + case TURRETAISTATE_SUPPRESS_WAIT: + AI_DoTargetAutoSuppressWait(); + break; + default: + break; + } + + AI_SetTargetAngles(m_vDesiredTargetAngles, m_fAIDesiredTargetSpeed); +} + +void TurretGun::AI_DoAiming() +{ + switch (m_iTargetType) { + case 0: + AI_DoTargetNone(); + break; + case 1: + AI_DoTargetAuto(); + break; + default: + break; + } +} + +void TurretGun::AI_DoFiring() +{ + float minBurstTime, maxBurstTime; + float minBurstDelay, maxBurstDelay; + + if (g_target_game == target_game_e::TG_MOH) { + // + // Removed in 2.0 + // The fire delay is always constant on 1.11 and below + // + if (m_iFiring == 1) { + m_iFiring = 4; + } + + if (IsFiring() && ReadyToFire(FIRE_PRIMARY)) { + Fire(FIRE_PRIMARY); + } + + return; + } + + minBurstTime = m_fMinBurstTime; + maxBurstTime = m_fMaxBurstTime; + minBurstDelay = m_fMinBurstDelay; + maxBurstDelay = m_fMaxBurstDelay; + + if (!maxBurstTime) { + // Added in OPM + // default values if not set + maxBurstTime = minBurstTime = 0.001f; + maxBurstDelay = minBurstDelay = fire_delay[FIRE_PRIMARY] / 10.f; + } + + if (m_iFiring == 1) { + if (m_fMaxBurstTime > 0) { + if (m_fFireToggleTime < level.time) { + m_iFiring = 4; + m_fFireToggleTime = level.time + m_fMinBurstTime + (m_fMaxBurstTime - m_fMinBurstTime) * random(); + } + } else { + m_iFiring = 4; + } + } else if (m_iFiring == 4) { + Fire(FIRE_PRIMARY); + + if (m_fMaxBurstTime > 0) { + if (m_fFireToggleTime < level.time) { + m_iFiring = 1; + m_fFireToggleTime = level.time + m_fMinBurstDelay + (m_fMaxBurstDelay - m_fMinBurstDelay) * random(); + } + } + } +} + +void TurretGun::AI_ThinkActive() +{ + if (!g_ai->integer) { + return; + } + + AI_DoAiming(); + AI_DoFiring(); +} + +void TurretGun::Think(void) +{ + if (!owner && (m_bHadOwner || !aim_target)) { + ThinkIdle(); + } else if (owner && owner->IsSubclassOfPlayer()) { + P_ThinkActive(); + } else { + AI_ThinkActive(); + } +} + +void TurretGun::P_UserAim(usercmd_t *ucmd) +{ + Vector vNewCmdAng; + + vNewCmdAng = Vector(SHORT2ANGLE(ucmd->angles[0]), SHORT2ANGLE(ucmd->angles[1]), SHORT2ANGLE(ucmd->angles[2])); + + if (m_vUserLastCmdAng[0] || m_vUserLastCmdAng[1] || m_vUserLastCmdAng[2]) { + m_vUserViewAng[0] += AngleSubtract(vNewCmdAng[0], m_vUserLastCmdAng[0]); + m_vUserViewAng[1] += AngleSubtract(vNewCmdAng[1], m_vUserLastCmdAng[1]); + m_vUserViewAng[2] += AngleSubtract(vNewCmdAng[2], m_vUserLastCmdAng[2]); + } + + m_vUserLastCmdAng = vNewCmdAng; + + if (ucmd->buttons & BUTTON_ATTACKLEFT) { + if (m_iFiring == 0) { + m_iFiring = 1; + } + } else { + m_iFiring = 0; + } + + flags |= FL_THINK; +} + +qboolean TurretGun::UserAim(usercmd_t *ucmd) +{ + P_UserAim(ucmd); + return qtrue; +} + +void TurretGun::P_SetViewangles(Event *ev) +{ + m_vUserViewAng = ev->GetVector(1); +} + +void TurretGun::P_SetViewAnglesForTurret(Event *ev) +{ + m_vUserViewAng = ev->GetVector(1); +} + +void TurretGun::P_GetViewangles(Event *ev) +{ + ev->AddVector(m_vUserViewAng); +} + +void TurretGun::AI_TurretBeginUsed(Sentient *pEnt) +{ + owner = pEnt; + + edict->r.ownerNum = pEnt->entnum; + m_bHadOwner = true; + + Sound(sPickupSound); + + current_attachToTag = ""; + ForceIdle(); +} + +void TurretGun::P_TurretBeginUsed(Player *pEnt) +{ + Player *player; + + if (!pTurretCameras) { + pTurretCameras = gi.Cvar_Get("g_turretcameras", "1", 0); + } + + owner = pEnt; + + edict->r.ownerNum = pEnt->entnum; + m_bHadOwner = true; + + Sound(sPickupSound); + + if (m_vUserViewAng[0] > 180.0f) { + m_vUserViewAng[0] -= 360.0f; + } + + m_vUserLastCmdAng = vec_zero; + + player = static_cast(owner.Pointer()); + player->EnterTurret(this); + + if (!m_pUserCamera) { + m_pUserCamera = new Camera; + } + + m_pUserCamera->setOrigin(origin); + m_pUserCamera->setAngles(angles); + + if (pTurretCameras->integer) { + player->SetCamera(m_pUserCamera, 0.5f); + } + + current_attachToTag = ""; + ForceIdle(); + P_CreateViewModel(); +} + +void TurretGun::TurretBeginUsed(Sentient *pEnt) +{ + AI_TurretBeginUsed(pEnt); +} + +void TurretGun::AI_TurretEndUsed() +{ + owner = NULL; + edict->r.ownerNum = ENTITYNUM_NONE; + + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + m_iFiring = 0; +} + +void TurretGun::RemoveUserCamera() +{ + if (!m_pUserCamera) { + return; + } + + if (owner && owner->IsSubclassOfPlayer()) { + Player *player = static_cast(owner.Pointer()); + + player->SetCamera(NULL, 1.0f); + player->ZoomOff(); + player->client->ps.camera_flags &= ~CF_CAMERA_ANGLES_TURRETMODE; + } + + m_pUserCamera->PostEvent(EV_Remove, 0); + m_pUserCamera = NULL; } void TurretGun::P_TurretEndUsed() { - // FIXME: unimplemented + Player *player = (Player *)owner.Pointer(); + float yawCap; + + if (m_pUserCamera) { + player->SetCamera(NULL, 1.0f); + player->ZoomOff(); + player->client->ps.camera_flags &= ~CF_CAMERA_ANGLES_TURRETMODE; + } + + player->ExitTurret(); + P_DeleteViewModel(); + + owner = NULL; + edict->r.ownerNum = ENTITYNUM_NONE; + + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; + m_iFiring = 0; + + yawCap = AngleSubtract(angles[1], m_fStartYaw); + if (yawCap > m_fMaxIdleYaw) { + yawCap = m_fMaxIdleYaw; + } else if (yawCap < -m_fMaxIdleYaw) { + yawCap = -m_fMaxIdleYaw; + } + + angles[1] = m_fStartYaw + yawCap; + setAngles(angles); } -void TurretGun::TurretEndUsed - ( - void - ) +void TurretGun::TurretEndUsed(void) { - if( owner->IsSubclassOfPlayer() ) - { - Player *player = ( Player * )owner.Pointer(); - - if( m_pUserCamera ) - { - player->SetCamera( NULL, 1.0f ); - player->ZoomOff(); - player->client->ps.camera_flags &= ~CF_CAMERA_ANGLES_TURRETMODE; - - m_pUserCamera->PostEvent( EV_Remove, 0 ); - m_pUserCamera = NULL; - } - - player->ExitTurret(); - DeleteViewModel(); - } - - owner = NULL; - edict->r.ownerNum = ENTITYNUM_NONE; - - m_fIdlePitchSpeed = 0; - m_iIdleHitCount = 0; - m_iFiring = 0; + AI_TurretEndUsed(); } -void TurretGun::P_TurretUsed(Player* player) +void TurretGun::P_TurretUsed(Player *player) { - // FIXME: unimplemented + if (player == owner) { + if ((!m_bPlayerUsable || !m_bUsable) && owner->health > 0.0f) { + return; + } + } + + if (owner) { + if (owner == player) { + P_TurretEndUsed(); + m_iFiring = 0; + } + } else { + m_vUserViewAng = player->GetViewAngles(); + + if (fabs(AngleSubtract(m_vUserViewAng[1], angles[1])) <= m_fMaxUseAngle) { + if (player->charge_start_time) { + return; + } + + P_TurretBeginUsed(player); + + flags &= ~FL_THINK; + m_iFiring = 0; + m_UseThread.Execute(this); + } + } } -void TurretGun::TurretUsed - ( - Sentient *pEnt - ) +void TurretGun::TurretUsed(Sentient *pEnt) { - if( ( pEnt->IsSubclassOfPlayer() ) && ( pEnt == owner ) ) - { - if( ( !m_bPlayerUsable || !m_bUsable ) && - owner->health > 0.0f ) - { - return; - } - } - - if( owner ) - { - if( owner == pEnt ) - { - TurretEndUsed(); - m_iFiring = 0; - } - } - else - { - m_vUserViewAng = pEnt->GetViewAngles(); - - if( fabs( AngleSubtract( m_vUserViewAng[ 1 ], angles[ 1 ] ) ) <= 80.0f ) - { - TurretBeginUsed( pEnt ); - - flags &= ~FL_THINK; - m_iFiring = 0; - - if( pEnt->IsSubclassOfPlayer() ) - { - m_UseThread.Execute( this ); - } - } - } + P_TurretUsed(static_cast(pEnt)); } -void TurretGun::SetAimTarget - ( - Entity *ent - ) +void TurretGun::TurretUsed(Event *ev) { - aim_target = ent; + Entity *pEnt = ev->GetEntity(1); + + if (!pEnt || !pEnt->IsSubclassOfPlayer()) { + ScriptError("Bad entity trying to use turret"); + return; + } + + if (m_bUsable && m_bPlayerUsable) { + // Make the sentient use the turret + P_TurretUsed(static_cast(pEnt)); + } } -void TurretGun::SetAimOffset - ( - const Vector& offset - ) +void TurretGun::P_SetPlayerUsable(Event *ev) { - m_Aim_offset = offset; + if (ev->GetInteger(1)) { + m_bPlayerUsable = true; + } else { + m_bPlayerUsable = false; + } } -void TurretGun::ClearAimTarget - ( - void - ) +void TurretGun::EventSetUsable(Event *ev) { - aim_target = NULL; - - // Clear idle values - m_fIdlePitchSpeed = 0; - m_iIdleHitCount = 0; + if (ev->GetInteger(1)) { + m_bUsable = true; + m_bRestable = true; + } else { + m_bUsable = false; + m_bRestable = false; + } } -void TurretGun::StartFiring - ( - void - ) +void TurretGun::P_SetViewOffset(Event *ev) { - m_iFiring = 1; + m_vViewOffset = ev->GetVector(1); } -void TurretGun::StopFiring - ( - void - ) +void TurretGun::EventMaxIdlePitch(Event *ev) { - m_iFiring = 0; + m_fMaxIdlePitch = ev->GetFloat(1); } -bool TurretGun::IsFiring - ( - void - ) +void TurretGun::EventMaxIdleYaw(Event *ev) { - return m_iFiring == 2; + m_fMaxIdleYaw = ev->GetFloat(1); } -void TurretGun::CalcFiringViewJitter - ( - void - ) +void TurretGun::SetIdleCheckOffset(Event *ev) { - if( owner && owner->IsSubclassOfPlayer() ) - { - m_fCurrViewJitter = m_fViewJitter; - } + m_vIdleCheckOffset = ev->GetVector(1); } -void TurretGun::ApplyFiringViewJitter - ( - Vector& vAng - ) +void TurretGun::AI_EventSetAimTarget(Event *ev) { + aim_target = ev->GetEntity(1); } -void TurretGun::TurnSpeed - ( - float speed - ) +void TurretGun::AI_EventSetAimOffset(Event *ev) { - m_fTurnSpeed = speed; + m_Aim_offset = ev->GetVector(1); } -void TurretGun::PitchCaps - ( - float upcap, - float downcap - ) +void TurretGun::AI_EventClearAimTarget(Event *ev) { - m_fPitchUpCap = upcap; - m_fPitchDownCap = downcap; + aim_target = NULL; - if( upcap > downcap ) - { - m_fPitchUpCap = -30.0f; - m_fPitchDownCap = 10.0f; - } + // Clear idle values + m_fIdlePitchSpeed = 0; + m_iIdleHitCount = 0; } -void TurretGun::MaxYawOffset - ( - float max - ) +void TurretGun::AI_EventStartFiring(Event *ev) { - m_fMaxYawOffset = max; - if( max < 0.0f ) - { - m_fMaxYawOffset = 0.0f; - } - else if( max > 180.0f ) - { - m_fMaxYawOffset = 180.0f; - } + if (m_iFiring == 0) { + m_iFiring = 1; + } } -void TurretGun::YawCenter - ( - float center - ) +void TurretGun::AI_EventStopFiring(Event *ev) { - m_fStartYaw = center; + m_iFiring = 0; } -void TurretGun::UserDistance - ( - float dist - ) +void TurretGun::AI_EventTurnSpeed(Event *ev) { - m_fUserDistance = dist; + AI_TurnSpeed(ev->GetFloat(1)); } -void TurretGun::BurstFireSettings - ( - float min_bursttime, - float max_bursttime, - float min_burstdelay, - float max_burstdelay - ) +void TurretGun::AI_EventPitchSpeed(Event *ev) { - m_fMinBurstTime = min_bursttime; - m_fMaxBurstTime = max_bursttime; - m_fMinBurstDelay = min_burstdelay; - m_fMaxBurstDelay = max_burstdelay; + AI_PitchSpeed(ev->GetFloat(1)); } -void TurretGun::CreateViewModel - ( - void - ) +void TurretGun::EventPitchCaps(Event *ev) { - char newmodel[ MAX_STRING_TOKENS ]; - int tagnum; - - // Owner must be a client - if( !owner->IsSubclassOfPlayer() ) { - return; - } - - m_pViewModel = new Animate; - - COM_StripExtension( model.c_str(), newmodel, sizeof( newmodel ) ); - strcat( newmodel, "_viewmodel.tik" ); - - m_pViewModel->setScale( edict->s.scale ); - m_pViewModel->detach_at_death = qtrue; - m_pViewModel->setModel( newmodel ); - m_pViewModel->edict->s.renderfx |= RF_VIEWMODEL; - - if( !m_pViewModel->edict->tiki ) - { - delete m_pViewModel; - m_pViewModel = NULL; - - warning( "CreateViewModel", "Couldn't find turret view model tiki %s", newmodel ); - return; - } - - // Get the eyes bone - tagnum = gi.Tag_NumForName( owner->edict->tiki, "eyes bone" ); - if( tagnum < 0 ) - { - warning( "CreateViewModel", "Tag eyes bone not found" ); - } - else if( !m_pViewModel->attach( owner->entnum, tagnum ) ) - { - warning( "CreateViewModel", "Could not attach model %s", newmodel ); - DeleteViewModel(); - return; - } - - m_pViewModel->NewAnim( "idle" ); - - // Make the world model invisible to the owner - edict->r.svFlags |= SVF_NOTSINGLECLIENT; - edict->r.singleClient |= owner->edict->s.number; - - // Make the viewmodel visible only to the owner - m_pViewModel->edict->r.svFlags |= SVF_SINGLECLIENT; - m_pViewModel->edict->r.singleClient |= owner->edict->s.number; + Vector caps = ev->GetVector(1); + PitchCaps(caps[0], caps[1]); } -void TurretGun::DeleteViewModel - ( - void - ) +void TurretGun::EventMaxYawOffset(Event *ev) { - delete m_pViewModel; - m_pViewModel = NULL; - - edict->r.svFlags &= ~SVF_NOTSINGLECLIENT; + MaxYawOffset(ev->GetFloat(1)); } -qboolean TurretGun::SetWeaponAnim - ( - const char *anim, - Event *ev - ) +void TurretGun::EventYawCenter(Event *ev) { - int slot; - int animnum; - - if( !Weapon::SetWeaponAnim( anim, ev ) ) - { - return qfalse; - } - - if( !m_pViewModel ) - { - return qtrue; - } - - slot = ( m_iAnimSlot + 3 ) & 3; - - animnum = gi.Anim_NumForName( m_pViewModel->edict->tiki, anim ); - if( animnum < 0 ) - { - return qtrue; - } - - m_pViewModel->StopAnimating( slot ); - m_pViewModel->SetTime( slot ); - - m_pViewModel->edict->s.frameInfo[ slot ].index = gi.Anim_NumForName( m_pViewModel->edict->tiki, "idle" ); - - m_pViewModel->NewAnim( animnum, m_iAnimSlot ); - m_pViewModel->SetOnceType(); - m_pViewModel->SetTime( slot ); - - return qtrue; + YawCenter(ev->GetFloat(1)); } -void TurretGun::StopWeaponAnim - ( - void - ) +void TurretGun::P_EventUserDistance(Event *ev) { - if( m_pViewModel ) - { - m_pViewModel->SetTime( m_iAnimSlot ); - m_pViewModel->StopAnimating( m_iAnimSlot ); - - m_pViewModel->edict->s.frameInfo[ m_iAnimSlot ].index = gi.Anim_NumForName( m_pViewModel->edict->tiki, "idle" ); - m_pViewModel->edict->s.frameInfo[ m_iAnimSlot ].weight = 1.0f; - m_pViewModel->edict->s.frameInfo[ m_iAnimSlot ].time = 0.0f; - } - - Weapon::StopWeaponAnim(); + P_UserDistance(ev->GetFloat(1)); } -bool TurretGun::CanTarget - ( - float *pos - ) +void TurretGun::P_EventViewJitter(Event *ev) { - Vector vAngles; - float ang; - - vectoangles( pos, vAngles ); - - ang = AngleSubtract( vAngles[ 1 ], m_fStartYaw ); - - if( vAngles[ 0 ] <= 180.0f ) - { - if( vAngles[ 0 ] >= -180.0f ) - { - return m_fPitchUpCap <= vAngles[ 0 ] && - m_fPitchDownCap >= vAngles[ 0 ] && - ang <= m_fMaxYawOffset && - -m_fMaxYawOffset <= ang; - } - - vAngles[ 0 ] += 360.0f; - } - else - { - vAngles[ 0 ] -= 360.0f; - } - - return m_fPitchUpCap <= vAngles[ 0 ] && - m_fPitchDownCap >= vAngles[ 0 ] && - ang <= m_fMaxYawOffset && - -m_fMaxYawOffset <= ang; + m_fViewJitter = ev->GetFloat(1); } -float TurretGun::FireDelay - ( - firemode_t mode - ) +void TurretGun::P_EventDoJitter(Event *ev) { - if( owner && owner->IsSubclassOfPlayer() ) - { - return 0.06f; - } - else - { - return Weapon::FireDelay( mode ); - } + if (ev->NumArgs() > 0) { + m_fCurrViewJitter = ev->GetFloat(1); + } else { + m_fCurrViewJitter = m_fViewJitter; + } } -void TurretGun::ShowInfo - ( - float fDot, - float fDist - ) +void TurretGun::AI_EventBurstFireSettings(Event *ev) { - if( fDot <= 0.90f && ( fDot <= 0.0f || fDist >= 256.0f ) ) { - return; - } + if (ev->NumArgs() < 4) { + return; + } - if( fDist >= 2048.0f || fDist <= 64.0f ) { - return; - } - - G_DebugString( origin + Vector( 0, 0, maxs[ 2 ] + 56.0f ), 1.0f, 1.0f, 1.0f, 1.0f, "%d:%d:%s", entnum, radnum, targetname.c_str() ); - G_DebugString( origin + Vector( 0, 0, maxs[ 2 ] + 38.0f ), 1.0f, 1.0f, 1.0f, 1.0f, "aim_target: %d", aim_target ? aim_target->entnum : -1 ); - G_DebugString( origin + Vector( 0, 0, maxs[ 2 ] + 20.0f ), 1.0f, 1.0f, 1.0f, 1.0f, "owner: %d", owner ? owner->entnum : -1 ); + AI_BurstFireSettings(ev->GetFloat(1), ev->GetFloat(2), ev->GetFloat(3), ev->GetFloat(4)); } -void TurretGun::TurretUsed - ( - Event *ev - ) +bool TurretGun::IsFiring(void) { - Entity *pEnt = ev->GetEntity( 1 ); - - if( !pEnt ) { - return; - } - - // Must be a player - if( !pEnt->IsSubclassOfPlayer() ) { - return; - } - - if( !m_bUsable ) { - return; - } - - if( m_bPlayerUsable ) - { - // Make the sentient use the turret - TurretUsed( ( Sentient * )pEnt ); - } + return m_iFiring == 4; } -void TurretGun::SetPlayerUsable - ( - Event *ev - ) +void TurretGun::P_ApplyFiringViewJitter(Vector& vAng) { - m_bPlayerUsable = ( ev->GetInteger( 1 ) != 0 ); + if (m_fCurrViewJitter > 0) { + vAng[0] += G_CRandom() * m_fCurrViewJitter; + vAng[1] += G_CRandom() * m_fCurrViewJitter; + vAng[2] += G_CRandom() * m_fCurrViewJitter * 0.8; + + // decrease the jittering over time + m_fCurrViewJitter -= level.frametime * 6; + if (m_fCurrViewJitter < 0) { + m_fCurrViewJitter = 0; + } + } } -void TurretGun::SetViewOffset - ( - Event *ev - ) +void TurretGun::AI_TurnSpeed(float speed) { - m_vViewOffset = ev->GetVector( 1 ); + m_fTurnSpeed = speed; } -void TurretGun::SetIdleCheckOffset - ( - Event *ev - ) +void TurretGun::AI_PitchSpeed(float speed) { - m_vIdleCheckOffset = ev->GetVector( 1 ); + m_fAIPitchSpeed = speed; } -void TurretGun::EventSetAimTarget - ( - Event *ev - ) +void TurretGun::PitchCaps(float upcap, float downcap) { - SetAimTarget( ev->GetEntity( 1 ) ); + m_fPitchUpCap = upcap; + m_fPitchDownCap = downcap; + + if (upcap > downcap) { + m_fPitchUpCap = -30.0f; + m_fPitchDownCap = 10.0f; + } } -void TurretGun::EventSetAimOffset - ( - Event *ev - ) +void TurretGun::MaxYawOffset(float max) { - SetAimOffset( ev->GetVector( 1 ) ); + m_fMaxYawOffset = max; + if (max < 0.0f) { + m_fMaxYawOffset = 0.0f; + } else if (max > 180.0f) { + m_fMaxYawOffset = 180.0f; + } } -void TurretGun::EventClearAimTarget - ( - Event *ev - ) +void TurretGun::YawCenter(float center) { - ClearAimTarget(); + m_fStartYaw = center; } -void TurretGun::EventStartFiring - ( - Event *ev - ) +void TurretGun::P_UserDistance(float dist) { - StartFiring(); + m_fUserDistance = dist; } -void TurretGun::EventStopFiring - ( - Event *ev - ) +void TurretGun::AI_BurstFireSettings( + float min_bursttime, float max_bursttime, float min_burstdelay, float max_burstdelay +) { - StopFiring(); + m_fMinBurstTime = min_bursttime; + m_fMaxBurstTime = max_bursttime; + m_fMinBurstDelay = min_burstdelay; + m_fMaxBurstDelay = max_burstdelay; } -void TurretGun::EventTurnSpeed - ( - Event *ev - ) +void TurretGun::P_EventSetThread(Event *ev) { - TurnSpeed( ev->GetFloat( 1 ) ); + if (ev->IsFromScript()) { + m_UseThread.SetThread(ev->GetValue(1)); + } else { + m_UseThread.Set(ev->GetString(1)); + } } -void TurretGun::EventPitchCaps - ( - Event *ev - ) +void TurretGun::P_SetMaxUseAngle(Event *ev) { - Vector caps = ev->GetVector( 1 ); - PitchCaps( caps[ 0 ], caps[ 1 ] ); + m_fMaxUseAngle = ev->GetFloat(1); } -void TurretGun::EventMaxYawOffset - ( - Event *ev - ) +void TurretGun::P_SetStartYaw(Event *ev) { - MaxYawOffset( ev->GetFloat( 1 ) ); + m_fStartYaw = ev->GetFloat(1); } -void TurretGun::EventYawCenter - ( - Event *ev - ) +void TurretGun::P_CreateViewModel(void) { - YawCenter( ev->GetFloat( 1 ) ); + char newmodel[MAX_STRING_TOKENS]; + int tagnum; + + if (!pTurretCameras) { + pTurretCameras = gi.Cvar_Get("g_turretcameras", "1", 0); + } + + if (!pTurretCameras->integer) { + // no camera + return; + } + + m_pViewModel = new Animate; + + COM_StripExtension(model.c_str(), newmodel, sizeof(newmodel)); + strcat(newmodel, "_viewmodel.tik"); + + m_pViewModel->setScale(edict->s.scale); + m_pViewModel->detach_at_death = qtrue; + m_pViewModel->setModel(newmodel); + m_pViewModel->edict->s.renderfx |= RF_VIEWMODEL; + + if (!m_pViewModel->edict->tiki) { + m_pViewModel->Delete(); + m_pViewModel = NULL; + + warning("CreateViewModel", "Couldn't find turret view model tiki %s", newmodel); + return; + } + + // Get the eyes bone + tagnum = gi.Tag_NumForName(owner->edict->tiki, "eyes bone"); + if (tagnum < 0) { + warning("CreateViewModel", "Tag eyes bone not found"); + } else if (!m_pViewModel->attach(owner->entnum, tagnum)) { + warning("CreateViewModel", "Could not attach model %s", newmodel); + P_DeleteViewModel(); + return; + } + + m_pViewModel->NewAnim("idle"); + + // Make the world model invisible to the owner + edict->r.svFlags |= SVF_NOTSINGLECLIENT; + edict->r.singleClient |= owner->edict->s.number; + + // Make the viewmodel visible only to the owner + m_pViewModel->edict->r.svFlags |= SVF_SINGLECLIENT; + m_pViewModel->edict->r.singleClient |= owner->edict->s.number; } -void TurretGun::EventUserDistance - ( - Event *ev - ) +void TurretGun::P_DeleteViewModel(void) { - UserDistance( ev->GetFloat( 1 ) ); + if (!m_pViewModel) { + return; + } + + m_pViewModel->Delete(); + m_pViewModel = NULL; + + edict->r.svFlags &= ~SVF_NOTSINGLECLIENT; } -void TurretGun::EventViewJitter - ( - Event *ev - ) +void TurretGun::Archive(Archiver& arc) { - m_fViewJitter = ev->GetFloat( 1 ); + Weapon::Archive(arc); + + arc.ArchiveBool(&m_bFakeBullets); + arc.ArchiveBool(&m_bPlayerUsable); + + arc.ArchiveFloat(&m_fIdlePitchSpeed); + arc.ArchiveInteger(&m_iIdleHitCount); + arc.ArchiveVector(&m_vIdleCheckOffset); + arc.ArchiveFloat(&m_fMaxIdlePitch); + arc.ArchiveFloat(&m_fMaxIdleYaw); + arc.ArchiveVector(&m_vViewOffset); + + arc.ArchiveFloat(&m_fTurnSpeed); + arc.ArchiveFloat(&m_fAIPitchSpeed); + arc.ArchiveFloat(&m_fPitchUpCap); + arc.ArchiveFloat(&m_fPitchDownCap); + arc.ArchiveFloat(&m_fStartYaw); + arc.ArchiveFloat(&m_fMaxYawOffset); + arc.ArchiveFloat(&m_fUserDistance); + + arc.ArchiveFloat(&m_fMinBurstTime); + arc.ArchiveFloat(&m_fMaxBurstTime); + arc.ArchiveFloat(&m_fMinBurstDelay); + arc.ArchiveFloat(&m_fMaxBurstDelay); + + arc.ArchiveFloat(&m_fFireToggleTime); + arc.ArchiveInteger(&m_iFiring); + arc.ArchiveVector(&m_vUserViewAng); + arc.ArchiveSafePointer(&m_pUserCamera); + + arc.ArchiveFloat(&m_fViewJitter); + arc.ArchiveFloat(&m_fCurrViewJitter); + + arc.ArchiveVector(&m_Aim_offset); + arc.ArchiveVector(&m_vAIBulletSpread[FIRE_PRIMARY]); + arc.ArchiveVector(&m_vAIBulletSpread[FIRE_SECONDARY]); + arc.ArchiveSafePointer(&m_pViewModel); + arc.ArchiveBool(&m_bUsable); + + m_UseThread.Archive(arc); + + arc.ArchiveBool(&m_bHadOwner); + arc.ArchiveBool(&m_bRestable); + + arc.ArchiveVector(&m_vUserLastCmdAng); + arc.ArchiveInteger(&m_iTargetType); + arc.ArchiveInteger(&m_iAIState); + arc.ArchiveFloat(&m_fAIConvergeTime); + arc.ArchiveInteger(&m_iAISuppressTime); + arc.ArchiveInteger(&m_iAISuppressWaitTime); + arc.ArchiveInteger(&m_iAILastTrackTime); + arc.ArchiveInteger(&m_iAIStartSuppressTime); + arc.ArchiveVec3(m_vDesiredTargetAngles); + arc.ArchiveFloat(&m_fAIDesiredTargetSpeed); + arc.ArchiveSafePointer(&m_pAIEnemy); + arc.ArchiveVec3(m_vAIDesiredTargetPosition); + arc.ArchiveVec3(m_vAITargetPosition); + arc.ArchiveVec3(m_vAICurrentTargetPosition); + arc.ArchiveVec3(m_vAITargetSpeed); + arc.ArchiveInteger(&m_iAINextSuppressTime); + arc.ArchiveFloat(&m_fAISuppressWidth); + arc.ArchiveFloat(&m_fAISuppressHeight); + arc.ArchiveVec3(m_vMuzzlePosition); + arc.ArchiveFloat(&m_fMaxUseAngle); + + // + // Added in 2.30 + // Clear the last command angles when loading + // otherwise it would cause the player to face (0,0,0) when loading + if (arc.Loading()) { + m_vUserLastCmdAng = vec_zero; + } } -void TurretGun::EventBurstFireSettings - ( - Event *ev - ) +qboolean TurretGun::AI_SetWeaponAnim(const char *anim, Event *ev) { - if( ev->NumArgs() <= 3 ) { - return; - } - - BurstFireSettings( ev->GetFloat( 1 ), ev->GetFloat( 2 ), ev->GetFloat( 3 ), ev->GetFloat( 4 ) ); + return Weapon::SetWeaponAnim(anim, ev); } -void TurretGun::EventSetThread - ( - Event *ev - ) +qboolean TurretGun::P_SetWeaponAnim(const char *anim, Event *ev) { - if( ev->IsFromScript() ) - { - m_UseThread.SetThread( ev->GetValue( 1 ) ); - } - else - { - m_UseThread.Set( ev->GetString( 1 ) ); - } + int slot; + int animnum; + + if (!Weapon::SetWeaponAnim(anim, ev)) { + return qfalse; + } + + if (!m_pViewModel) { + return qtrue; + } + + slot = (m_iAnimSlot + 3) & 3; + + animnum = gi.Anim_NumForName(m_pViewModel->edict->tiki, anim); + if (animnum < 0) { + return qtrue; + } + + m_pViewModel->StopAnimating(slot); + m_pViewModel->RestartAnimSlot(slot); + + m_pViewModel->edict->s.frameInfo[slot].index = gi.Anim_NumForName(m_pViewModel->edict->tiki, "idle"); + + m_pViewModel->NewAnim(animnum, m_iAnimSlot); + m_pViewModel->SetOnceType(m_iAnimSlot); + m_pViewModel->RestartAnimSlot(m_iAnimSlot); + + return qtrue; } -void TurretGun::SetViewangles - ( - Event *ev - ) +qboolean TurretGun::SetWeaponAnim(const char *anim, Event *ev) { - m_vUserViewAng = ev->GetVector( 1 ); + if (owner && owner->IsSubclassOfPlayer()) { + return P_SetWeaponAnim(anim, ev); + } else { + return AI_SetWeaponAnim(anim, ev); + } } -void TurretGun::GetViewangles - ( - Event *ev - ) +void TurretGun::AI_StopWeaponAnim() { - ev->AddVector( m_vUserViewAng ); + Weapon::StopWeaponAnim(); } +void TurretGun::P_StopWeaponAnim() +{ + if (m_pViewModel) { + m_pViewModel->RestartAnimSlot(m_iAnimSlot); + m_pViewModel->StopAnimating(m_iAnimSlot); + m_pViewModel->StartAnimSlot(m_iAnimSlot, gi.Anim_NumForName(m_pViewModel->edict->tiki, "idle"), 1); + } + + Weapon::StopWeaponAnim(); +} + +void TurretGun::StopWeaponAnim(void) +{ + if (owner && owner->IsSubclassOfPlayer()) { + P_StopWeaponAnim(); + } else { + AI_StopWeaponAnim(); + } +} + +float TurretGun::FireDelay(firemode_t mode) +{ + if (g_target_game == target_game_e::TG_MOH) { + // + // Removed in 2.0 + // + // On 1.11 and below, the firedelay for players is always 0.06. + // Some maps like m1l1 sets the turret firedelay higher for AI + if (owner && owner->IsSubclassOfPlayer()) { + return 0.06f; + } + } + + return fire_delay[mode]; +} + +void TurretGun::SetFireDelay(Event *ev) +{ + fire_delay[FIRE_PRIMARY] = ev->GetFloat(1); +} + +void TurretGun::ShowInfo(float fDot, float fDist) +{ + if (fDot <= 0.90f && (fDot <= 0.0f || fDist >= 256.0f)) { + return; + } + + if (fDist >= 2048.0f || fDist <= 64.0f) { + return; + } + + G_DebugString( + origin + Vector(0, 0, maxs[2] + 56.0f), 1.0f, 1.0f, 1.0f, 1.0f, "%d:%d:%s", entnum, radnum, targetname.c_str() + ); + G_DebugString( + origin + Vector(0, 0, maxs[2] + 38.0f), + 1.0f, + 1.0f, + 1.0f, + 1.0f, + "aim_target: %d", + aim_target ? aim_target->entnum : -1 + ); + G_DebugString( + origin + Vector(0, 0, maxs[2] + 20.0f), 1.0f, 1.0f, 1.0f, 1.0f, "owner: %d", owner ? owner->entnum : -1 + ); +} + +void TurretGun::AI_EventSetTargetType(Event *ev) +{ + int targettype; + + switch (ev->GetConstString(1)) { + case STRING_DISGUISE_NONE: + targettype = 0; + break; + case STRING_AUTO: + targettype = 1; + break; + default: + ScriptError("Unknown targettype '%s'", ev->GetString(1).c_str()); + break; + } + + if (targettype != m_iTargetType) { + m_iFiring = 0; + m_iTargetType = targettype; + } +} + +void TurretGun::AI_EventGetTargetType(Event *ev) +{ + switch (m_iTargetType) { + case 0: + ev->AddConstString(STRING_DISGUISE_NONE); + case 1: + ev->AddConstString(STRING_AUTO); + break; + default: + break; + } +} + +void TurretGun::AI_EventSetConvergeTime(Event *ev) +{ + float value = ev->GetFloat(1); + if (value <= 0) { + ScriptError("negative value %f not allowed", value); + } + + m_fAIConvergeTime = value; +} + +void TurretGun::AI_EventSetSuppressTime(Event *ev) +{ + float value = ev->GetFloat(1); + if (value <= 0) { + ScriptError("negative value %f not allowed", value); + } + + m_iAISuppressTime = value * 1000; +} + +void TurretGun::AI_EventSetSuppressWaitTime(Event *ev) +{ + float value = ev->GetFloat(1); + if (value <= 0) { + ScriptError("negative value %f not allowed", value); + } + + m_iAISuppressWaitTime = value * 1000; +} + +void TurretGun::AI_EventSetSuppressWidth(Event *ev) +{ + float value = ev->GetFloat(1); + if (value <= 0) { + ScriptError("nonpositive value %f not allowed", value); + } + + m_fAISuppressWidth = value; +} + +void TurretGun::AI_EventSetSuppressHeight(Event *ev) +{ + float value = ev->GetFloat(1); + if (value <= 0) { + ScriptError("nonpositive value %f not allowed", value); + } + + m_fAISuppressHeight = value; +} + +void TurretGun::AI_EventSetBulletSpread(Event *ev) +{ + m_vAIBulletSpread[firemodeindex].x = ev->GetFloat(1); + m_vAIBulletSpread[firemodeindex].y = ev->GetFloat(1); +} + +void TurretGun::GetMuzzlePosition(vec3_t position, vec3_t vBarrelPos, vec3_t forward, vec3_t right, vec3_t up) +{ + Vector delta; + Vector aim_angles; + Sentient *viewer; + orientation_t barrel_or; + vec3_t weap_axis[3]; + float mat[3][3]; + int i; + + viewer = owner; + if (!viewer && IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *vehTurret = static_cast(this); + viewer = vehTurret->GetRemoteOwner(); + } + + if (!viewer) { + if (forward || right || up) { + AngleVectors(angles, forward, right, up); + } + + VectorCopy(origin, position); + + if (GetRawTag(GetTagBarrel(), &barrel_or)) { + AnglesToAxis(angles, weap_axis); + + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_axis[i], position); + } + } + + if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } + } else if (viewer->IsSubclassOfPlayer()) { + VectorCopy(origin, position); + + if (GetRawTag(GetTagBarrel(), &barrel_or)) { + AnglesToAxis(angles, weap_axis); + + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_axis[i], position); + } + } + + if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } + + delta = viewer->GunTarget(false, position) - position; + aim_angles = delta.toAngles(); + + if (IsSubclassOfVehicleTurretGun()) { + vec3_t ang; + + MatrixMultiply(barrel_or.axis, weap_axis, mat); + vectoangles(mat[0], ang); + + for (i = 0; i < 2; i++) { + float diff; + + diff = AngleSubtract(aim_angles[i], ang[i]); + if (diff > 90) { + aim_angles[i] = ang[i]; + } else if (diff > 20) { + aim_angles[i] = ang[i] + 20; + } else if (diff < -20) { + if (diff >= -90) { + aim_angles[i] = ang[i] - 20; + } else { + aim_angles[i] = ang[i]; + } + } + } + } + + if (forward || right || up) { + AngleVectors(aim_angles, forward, right, up); + } + } else { + VectorCopy(origin, position); + + if (GetRawTag(GetTagBarrel(), &barrel_or)) { + AnglesToAxis(angles, weap_axis); + + for (i = 0; i < 3; i++) { + VectorMA(position, barrel_or.origin[i], weap_axis[i], position); + } + } + + if (vBarrelPos) { + VectorCopy(position, vBarrelPos); + } + + if (forward || right || up) { + float spread_x, spread_y; + + AngleVectors(angles, forward, right, up); + + spread_x = crandom() * m_vAIBulletSpread[FIRE_PRIMARY].x / bulletrange[FIRE_PRIMARY]; + spread_y = crandom() * m_vAIBulletSpread[FIRE_PRIMARY].y / bulletrange[FIRE_PRIMARY]; + + VectorMA(forward, spread_x, right, forward); + VectorMA(forward, spread_y, up, forward); + } + } +} + +Vector TurretGun::EyePosition() +{ + return m_vMuzzlePosition; +} + +void TurretGun::setAngles(Vector ang) +{ + Entity::setAngles(ang); + + VectorCopy(ang, m_vDesiredTargetAngles); +} + +void TurretGun::CalcFiringViewJitter(void) +{ + if (owner && owner->IsSubclassOfPlayer()) { + m_fCurrViewJitter = m_fViewJitter; + } +} + +const Vector& TurretGun::GetUserViewAngles() const +{ + return m_vUserViewAng; +} + +void TurretGun::SetUserViewAngles(const Vector& vAngles) +{ + m_vUserViewAng = vAngles; +} diff --git a/code/fgame/weapturret.h b/code/fgame/weapturret.h index c314f75e..6646dbf9 100644 --- a/code/fgame/weapturret.h +++ b/code/fgame/weapturret.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,123 +23,206 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // weapturret.h: MOH Turret. Usable by sentients and monsters. // -#ifndef __WEAPTURRET_H__ -#define __WEAPTURRET_H__ +#pragma once #include "weapon.h" #include "camera.h" extern Event EV_Turret_Enter; extern Event EV_Turret_Exit; -extern Event EV_Turret_TurnSpeed; +extern Event EV_Turret_AI_TurnSpeed; +extern Event EV_Turret_SetMaxUseAngle; -#define FAKEBULLETS 1 +typedef enum { + TURRETAISTATE_DEFAULT, + TURRETAISTATE_TRACK, + TURRETAISTATE_SUPPRESS, + TURRETAISTATE_SUPPRESS_WAIT +} turretaistate_e; -class TurretGun : public Weapon { - friend class Vehicle; +#define FAKEBULLETS 1 + +class TurretGun : public Weapon +{ + friend class Vehicle; protected: - bool m_bFakeBullets; - bool m_bPlayerUsable; - bool m_bUsable; - bool m_bRestable; - Vector m_vIdleCheckOffset; - Vector m_vViewOffset; - Vector m_vUserViewAng; - Vector m_vUserLastCmdAng; - float m_fIdlePitchSpeed; - float m_fTurnSpeed; - float m_fPitchUpCap; - float m_fPitchDownCap; - float m_fStartYaw; - float m_fMaxYawOffset; - float m_fUserDistance; - float m_fMinBurstTime; - float m_fMaxBurstTime; - float m_fMinBurstDelay; - float m_fMaxBurstDelay; - float m_fFireToggleTime; - int m_iFiring; - int m_iIdleHitCount; - CameraPtr m_pUserCamera; - float m_fViewJitter; - float m_fCurrViewJitter; - Vector m_Aim_offset; - SafePtr m_pViewModel; - ScriptThreadLabel m_UseThread; + bool m_bFakeBullets; + bool m_bPlayerUsable; + bool m_bUsable; + bool m_bRestable; + Vector m_vIdleCheckOffset; + Vector m_vViewOffset; + float m_fMaxIdlePitch; + float m_fMaxIdleYaw; + Vector m_vUserViewAng; + Vector m_vUserLastCmdAng; + float m_fIdlePitchSpeed; + float m_fTurnSpeed; + float m_fAIPitchSpeed; + float m_fPitchUpCap; + float m_fPitchDownCap; + float m_fStartYaw; + float m_fMaxYawOffset; + float m_fUserDistance; + float m_fMinBurstTime; + float m_fMaxBurstTime; + float m_fMinBurstDelay; + float m_fMaxBurstDelay; + float m_fFireToggleTime; + int m_iFiring; + int m_iIdleHitCount; + CameraPtr m_pUserCamera; + float m_fViewJitter; + float m_fCurrViewJitter; + Vector m_vAIBulletSpread[MAX_FIREMODES]; + int m_iTargetType; + SentientPtr m_pAIEnemy; + Vector m_Aim_offset; + SafePtr m_pViewModel; + ScriptThreadLabel m_UseThread; public: - bool m_bHadOwner; + bool m_bHadOwner; + +private: + int m_iAIState; + float m_fAIConvergeTime; + int m_iAISuppressTime; + int m_iAISuppressWaitTime; + int m_iAILastTrackTime; + int m_iAIStartSuppressTime; + vec3_t m_vDesiredTargetAngles; + float m_fAIDesiredTargetSpeed; + vec3_t m_vAIDesiredTargetPosition; + vec3_t m_vAITargetPosition; + vec3_t m_vAICurrentTargetPosition; + vec3_t m_vAITargetSpeed; + int m_iAINextSuppressTime; + float m_fAISuppressWidth; + float m_fAISuppressHeight; + Vector m_vMuzzlePosition; + float m_fMaxUseAngle; protected: - void ThinkIdle( void ); - void SetTargetAngles( Vector& vTargAngles ); - void ThinkActive( void ); + void ThinkIdle(); + void P_SetTargetAngles(Vector &vTargAngles); + virtual void P_ThinkActive(); public: - CLASS_PROTOTYPE( TurretGun ); + CLASS_PROTOTYPE(TurretGun); - TurretGun(); - virtual ~TurretGun(); + TurretGun(); + virtual ~TurretGun(); - void Think( void ) override; + // added in 2.0 + //==== + void AI_SetTargetAngles(vec3_t vTargAngles, float speed); + void AI_SetDesiredTargetAngles(const vec3_t angles, float speed); + void AI_DoTargetNone(); + void AI_MoveToDefaultPosition(); + void AI_DoTargetAutoDefault(); + void AI_StartDefault(); + void AI_StartSuppress(); + void AI_StartSuppressWait(); + void AI_StartTrack(); + void AI_DoTargetAutoTrack(); + void AI_DoSuppressionAiming(); + void AI_DoTargetAutoSuppress(); + void AI_DoTargetAutoSuppressWait(); + void AI_DoTargetAuto(); + void AI_DoAiming(); + void AI_DoFiring(); + void AI_ThinkActive(); + //==== - void PlaceTurret( Event *ev ); + void Think() override; - virtual void P_ThinkActive(); - virtual void P_UserAim(usercmd_t* cmd); - qboolean UserAim(usercmd_t* ucmd); - virtual void TurretBeginUsed(Sentient* pEnt); - virtual void P_TurretBeginUsed(Player* pEnt); - virtual void TurretEndUsed(void); - virtual void P_TurretEndUsed(); - virtual void TurretUsed(Sentient* pEnt); - virtual void P_TurretUsed(Player* player); + void PlaceTurret(Event *ev); - void TurretUsed( Event *ev ); - void SetPlayerUsable( Event *ev ); - void SetViewOffset( Event *ev ); - void SetIdleCheckOffset( Event *ev ); - void SetAimTarget( Entity *ent ); - void SetAimOffset( const Vector& offset ); - void ClearAimTarget( void ); - void StartFiring( void ); - void StopFiring( void ); - bool IsFiring( void ); - void CalcFiringViewJitter( void ); - void ApplyFiringViewJitter( Vector& vAng ); - void TurnSpeed( float speed ); - void PitchCaps( float upcap, float downcap ); - void MaxYawOffset( float max ); - void YawCenter( float center ); - void UserDistance( float dist ); - void BurstFireSettings( float min_bursttime, float max_bursttime, float min_burstdelay, float max_burstdelay ); - void EventSetAimTarget( Event *ev ); - void EventSetAimOffset( Event *ev ); - void EventClearAimTarget( Event *ev ); - void EventStartFiring( Event *ev ); - void EventStopFiring( Event *ev ); - void EventTurnSpeed( Event *ev ); - void EventPitchCaps( Event *ev ); - void EventMaxYawOffset( Event *ev ); - void EventYawCenter( Event *ev ); - void EventUserDistance( Event *ev ); - void EventViewJitter( Event *ev ); - void EventBurstFireSettings( Event *ev ); - void EventSetThread( Event *ev ); - void SetViewangles( Event *ev ); - void GetViewangles( Event *ev ); - void CreateViewModel( void ); - void DeleteViewModel( void ); + virtual void P_UserAim(usercmd_t *ucmd); + qboolean UserAim(usercmd_t *ucmd); + virtual void TurretBeginUsed(Sentient *pEnt); + virtual void P_TurretBeginUsed(Player *pEnt); + virtual void AI_TurretBeginUsed(Sentient *pEnt); // added in 2.0 + virtual void TurretEndUsed(); + virtual void P_TurretEndUsed(); + virtual void AI_TurretEndUsed(); // added in 2.0 + void RemoveUserCamera(); // added in 2.0 + virtual void TurretUsed(Sentient *pEnt); + virtual void P_TurretUsed(Player *player); - qboolean SetWeaponAnim( const char *anim, Event *ev = NULL ) override; - void StopWeaponAnim( void ) override; + void TurretUsed(Event *ev); + void P_SetPlayerUsable(Event *ev); + void EventSetUsable(Event *ev); // added in 2.0 + void P_SetViewOffset(Event *ev); + void EventMaxIdlePitch(Event *ev); // added in 2.0 + void EventMaxIdleYaw(Event *ev); // added in 2.0 + void SetIdleCheckOffset(Event *ev); + bool IsFiring(); + void CalcFiringViewJitter(); + void P_ApplyFiringViewJitter(Vector& vAng); + void AI_TurnSpeed(float speed); + void AI_PitchSpeed(float speed); + void PitchCaps(float upcap, float downcap); + void MaxYawOffset(float max); + void YawCenter(float center); + void P_UserDistance(float dist); + void AI_BurstFireSettings(float min_bursttime, float max_bursttime, float min_burstdelay, float max_burstdelay); + void AI_EventSetAimTarget(Event *ev); + void AI_EventSetAimOffset(Event *ev); + void AI_EventClearAimTarget(Event *ev); + void AI_EventStartFiring(Event *ev); + void AI_EventStopFiring(Event *ev); + void AI_EventTurnSpeed(Event *ev); + void AI_EventPitchSpeed(Event *ev); // added in 2.0 + void EventPitchCaps(Event *ev); + void EventMaxYawOffset(Event *ev); + void EventYawCenter(Event *ev); + void P_EventUserDistance(Event *ev); + void P_EventViewJitter(Event *ev); + void P_EventDoJitter(Event *ev); // added in 2.0 + void AI_EventBurstFireSettings(Event *ev); + void P_EventSetThread(Event *ev); + void P_SetMaxUseAngle(Event *ev); // added in 2.0 + void P_SetStartYaw(Event *ev); // added in 2.0 + void P_SetViewangles(Event *ev); + void P_SetViewAnglesForTurret(Event *ev); + void P_GetViewangles(Event *ev); + void P_CreateViewModel(); + void P_DeleteViewModel(); - virtual bool CanTarget( float *pos ); - virtual float FireDelay( firemode_t mode ); - void ShowInfo( float fDot, float fDist ) override; + qboolean AI_SetWeaponAnim(const char *anim, Event *ev = NULL); + qboolean P_SetWeaponAnim(const char *anim, Event *ev = NULL); + qboolean SetWeaponAnim(const char *anim, Event *ev = NULL) override; + void AI_StopWeaponAnim(); + void P_StopWeaponAnim(); + void StopWeaponAnim() override; - void Archive( Archiver& arc ) override; + bool AI_CanTarget(const vec3_t org); + virtual float FireDelay(firemode_t mode) override; + virtual void SetFireDelay(Event *ev) override; // added in 2.0 + void ShowInfo(float fDot, float fDist) override; + + // added in 2.0 + //==== + void AI_EventSetTargetType(Event *ev); + void AI_EventGetTargetType(Event *ev); + void AI_EventSetConvergeTime(Event *ev); + void AI_EventSetSuppressTime(Event *ev); + void AI_EventSetSuppressWaitTime(Event *ev); + void AI_EventSetSuppressWidth(Event *ev); + void AI_EventSetSuppressHeight(Event *ev); + void AI_EventSetBulletSpread(Event *ev); + void GetMuzzlePosition( + vec3_t position, vec3_t vBarrelPos = NULL, vec3_t forward = NULL, vec3_t right = NULL, vec3_t up = NULL + ) override; + Vector EyePosition(); + void setAngles(Vector ang) override; + //==== + + const Vector& GetUserViewAngles() const; + void SetUserViewAngles(const Vector& vAngles); + + void Archive(Archiver& arc) override; }; - -#endif // __WEAPTURRET_H__ diff --git a/code/fgame/weaputils.cpp b/code/fgame/weaputils.cpp index 888a15b0..62acae3e 100644 --- a/code/fgame/weaputils.cpp +++ b/code/fgame/weaputils.cpp @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -37,53 +37,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "earthquake.h" #include "trigger.h" #include "debuglines.h" +#include "smokegrenade.h" constexpr unsigned long MAX_TRAVEL_DIST = 16216; -static void FlashPlayers - ( - Vector org, - float r, - float g, - float b, - float a, - float rad, - float time, - int type - ); +static void FlashPlayers(Vector org, float r, float g, float b, float a, float rad, float time, int type); -qboolean MeleeAttack - ( - Vector pos, - Vector end, - float damage, - Entity *attacker, - meansOfDeath_t means_of_death, - float attack_width, - float attack_min_height, - float attack_max_height, - float knockback, - qboolean hit_dead, - Container*victimlist - ) +qboolean MeleeAttack( + Vector pos, + Vector end, + float damage, + Entity *attacker, + meansOfDeath_t means_of_death, + float attack_width, + float attack_min_height, + float attack_max_height, + float knockback, + qboolean hit_dead, + Container *victimlist +) { - trace_t trace; - Entity *victim; - Vector dir; - float world_dist; - Vector new_pos; - Entity *skip_ent; - qboolean hit_something = false; - Vector mins; - Vector maxs; + trace_t trace; + Entity *victim; + Vector dir; + float world_dist; + Vector new_pos; + Entity *skip_ent; + qboolean hit_something = false; + Vector mins; + Vector maxs; Container potential_victimlist; - int i; - int num_traces; - Vector start; + int i; + int num_traces; + Vector start; // See how far the world is away - dir = end - pos; + dir = end - pos; world_dist = dir.length(); new_pos = pos; @@ -92,42 +82,37 @@ qboolean MeleeAttack num_traces = 0; - while( new_pos != end ) - { - trace = G_Trace( pos, vec_zero, vec_zero, end, skip_ent, MASK_SOLID, false, "MeleeAttack - World test" ); + while (new_pos != end) { + trace = G_Trace(pos, vec_zero, vec_zero, end, skip_ent, MASK_SOLID, false, "MeleeAttack - World test"); num_traces++; - if( trace.fraction < 1 ) - { - if( ( trace.entityNum == ENTITYNUM_WORLD ) || ( trace.ent && trace.ent->entity && !trace.ent->entity->takedamage ) ) - { - dir = trace.endpos - pos; + if (trace.fraction < 1) { + if ((trace.entityNum == ENTITYNUM_WORLD) + || (trace.ent && trace.ent->entity && !trace.ent->entity->takedamage)) { + dir = trace.endpos - pos; world_dist = dir.length(); break; - } - else - { + } else { // Make sure we don't go backwards any in our trace - if( Vector( new_pos - pos ).length() + 0.001 >= Vector( trace.endpos - pos ).length() ) + if (Vector(new_pos - pos).length() + 0.001 >= Vector(trace.endpos - pos).length()) { break; + } - if( num_traces > 10 ) - { + if (num_traces > 10) { // We have done too many traces, stop here - dir = trace.endpos - pos; + dir = trace.endpos - pos; world_dist = dir.length(); break; } new_pos = trace.endpos; - if( trace.ent ) + if (trace.ent) { skip_ent = trace.ent->entity; + } } - } - else - { + } else { break; } } @@ -136,17 +121,17 @@ qboolean MeleeAttack dir = end - pos; dir.normalize(); - end = pos + ( dir * world_dist ); + end = pos + (dir * world_dist); - start = pos - dir * ( attack_width * 1.2f ); - start.z = pos.z - dir.z * ( end.z - start.z ); + start = pos - dir * (attack_width * 1.2f); + start.z = pos.z - dir.z * (end.z - start.z); victim = NULL; - mins = Vector( -attack_width, -attack_width, attack_min_height ); - maxs = Vector( attack_width, attack_width, attack_max_height ); + mins = Vector(-attack_width, -attack_width, attack_min_height); + maxs = Vector(attack_width, attack_width, attack_max_height); - G_TraceEntities( pos, mins, maxs, end, &potential_victimlist, MASK_MELEE ); + G_TraceEntities(pos, mins, maxs, end, &potential_victimlist, MASK_MELEE); /*int previous_contents = attacker->edict->r.contents; attacker->edict->r.contents = 0; @@ -160,34 +145,31 @@ qboolean MeleeAttack attacker->edict->r.contents = previous_contents;*/ - for( i = 1; i <= potential_victimlist.NumObjects(); i++ ) - { - victim = potential_victimlist.ObjectAt( i ); + for (i = 1; i <= potential_victimlist.NumObjects(); i++) { + victim = potential_victimlist.ObjectAt(i); - if( victim && victim->takedamage && victim != attacker ) - { + if (victim && victim->takedamage && victim != attacker) { dir = end - pos; dir.normalize(); - if( dir == vec_zero ) - { + if (dir == vec_zero) { dir = victim->centroid - pos; dir.normalize(); } - if( victim->IsSubclassOfSentient() && !victim->IsDead() ) + if (victim->IsSubclassOfSentient() && !victim->IsDead()) { hit_something = true; + } - if( victim->health > 0 || hit_dead ) - { - if( victimlist && victim->IsSubclassOfSentient() && !victim->IsDead() ) - victimlist->AddObject( victim ); + if (victim->health > 0 || hit_dead) { + if (victimlist && victim->IsSubclassOfSentient() && !victim->IsDead()) { + victimlist->AddObject(victim); + } - victim->Damage( attacker, attacker, damage, pos, dir, vec_zero, knockback, 0, means_of_death ); + victim->Damage(attacker, attacker, damage, pos, dir, vec_zero, knockback, 0, means_of_death); - if( victim->edict->r.contents & CONTENTS_SOLID ) - { - victim->Sound( "pistol_hit" ); + if (!(victim->edict->r.contents & CONTENTS_CLAYPIDGEON)) { + victim->Sound("pistol_hit"); } } } @@ -196,464 +178,469 @@ qboolean MeleeAttack return hit_something; } -#define DEFAULT_SWORD_DAMAGE 10 +#define DEFAULT_SWORD_DAMAGE 10 #define DEFAULT_SWORD_KNOCKBACK 50 Event EV_Projectile_Speed - ( - "speed", - EV_DEFAULT, - "f", - "projectileSpeed", - "set the speed of the projectile", - EV_NORMAL - ); +( + "speed", + EV_DEFAULT, + "f", + "projectileSpeed", + "set the speed of the projectile", + EV_NORMAL +); Event EV_Projectile_MinSpeed - ( - "minspeed", - EV_DEFAULT, - "f", - "minspeed", - "set the minimum speed of the projectile (this is for charge up weapons)", - EV_NORMAL - ); +( + "minspeed", + EV_DEFAULT, + "f", + "minspeed", + "set the minimum speed of the projectile (this is for charge up weapons)", + EV_NORMAL +); Event EV_Projectile_ChargeSpeed - ( - "chargespeed", - EV_DEFAULT, - NULL, - NULL, - "set the projectile's speed to be determined by the charge time", - EV_NORMAL - ); +( + "chargespeed", + EV_DEFAULT, + NULL, + NULL, + "set the projectile's speed to be determined by the charge time", + EV_NORMAL +); Event EV_Projectile_Damage - ( - "hitdamage", - EV_DEFAULT, - "f", - "projectileHitDamage", - "set the damage a projectile does when it hits something", - EV_NORMAL - ); +( + "hitdamage", + EV_DEFAULT, + "f", + "projectileHitDamage", + "set the damage a projectile does when it hits something", + EV_NORMAL +); Event EV_Projectile_Life - ( - "life", - EV_DEFAULT, - "f", - "projectileLife", - "set the life of the projectile", - EV_NORMAL - ); +( + "life", + EV_DEFAULT, + "f", + "projectileLife", + "set the life of the projectile", + EV_NORMAL +); Event EV_Projectile_DMLife - ( - "dmlife", - EV_DEFAULT, - "f", - "projectileLife", - "set the life of the projectile in DM", - EV_NORMAL - ); +( + "dmlife", + EV_DEFAULT, + "f", + "projectileLife", + "set the life of the projectile in DM", + EV_NORMAL +); Event EV_Projectile_MinLife - ( - "minlife", - EV_DEFAULT, - "f", - "minProjectileLife", - "set the minimum life of the projectile (this is for charge up weapons)", - EV_NORMAL - ); +( + "minlife", + EV_DEFAULT, + "f", + "minProjectileLife", + "set the minimum life of the projectile (this is for charge up weapons)", + EV_NORMAL +); Event EV_Projectile_ChargeLife - ( - "chargelife", - EV_DEFAULT, - NULL, - NULL, - "set the projectile's life to be determined by the charge time", - EV_NORMAL - ); -Event EV_Projectile_SetFuse // Added in 2.0 - ( - "fuse", - EV_DEFAULT, - "i", - "fuse", - "set the projectile's life to be determined by the charge time", - EV_NORMAL - ); +( + "chargelife", + EV_DEFAULT, + NULL, + NULL, + "set the projectile's life to be determined by the charge time", + EV_NORMAL +); +// Added in 2.0 +Event EV_Projectile_SetFuse +( + "fuse", + EV_DEFAULT, + "i", + "fuse", + "set the projectile's life to be determined by the charge time", + EV_NORMAL +); Event EV_Projectile_Knockback - ( - "knockback", - EV_DEFAULT, - "f", - "projectileKnockback", - "set the knockback of the projectile when it hits something", - EV_NORMAL - ); +( + "knockback", + EV_DEFAULT, + "f", + "projectileKnockback", + "set the knockback of the projectile when it hits something", + EV_NORMAL +); Event EV_Projectile_DLight - ( - "dlight", - EV_DEFAULT, - "ffff", - "red green blue intensity", - "set the color and intensity of the dynamic light on the projectile", - EV_NORMAL - ); +( + "dlight", + EV_DEFAULT, + "ffff", + "red green blue intensity", + "set the color and intensity of the dynamic light on the projectile", + EV_NORMAL +); Event EV_Projectile_Avelocity - ( - "avelocity", - EV_DEFAULT, - "SFSFSF", - "[random|crandom] yaw [random|crandom] pitch [random|crandom] roll", - "set the angular velocity of the projectile", - EV_NORMAL - ); +( + "avelocity", + EV_DEFAULT, + "SFSFSF", + "[random|crandom] yaw [random|crandom] pitch [random|crandom] roll", + "set the angular velocity of the projectile", + EV_NORMAL +); Event EV_Projectile_MeansOfDeath - ( - "meansofdeath", - EV_DEFAULT, - "s", - "meansOfDeath", - "set the meansOfDeath of the projectile", - EV_NORMAL - ); +( + "meansofdeath", + EV_DEFAULT, + "s", + "meansOfDeath", + "set the meansOfDeath of the projectile", + EV_NORMAL +); Event EV_Projectile_BeamCommand - ( - "beam", - EV_DEFAULT, - "sSSSSSS", - "command arg1 arg2 arg3 arg4 arg5 arg6", - "send a command to the beam of this projectile", - EV_NORMAL - ); +( + "beam", + EV_DEFAULT, + "sSSSSSS", + "command arg1 arg2 arg3 arg4 arg5 arg6", + "send a command to the beam of this projectile", + EV_NORMAL +); Event EV_Projectile_UpdateBeam - ( - "updatebeam", - EV_DEFAULT, - NULL, - NULL, - "Update the attached beam", - EV_NORMAL - ); +( + "updatebeam", + EV_DEFAULT, + NULL, + NULL, + "Update the attached beam", + EV_NORMAL +); Event EV_Projectile_BounceTouch - ( - "bouncetouch", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile bounce when it hits a non-damageable solid", - EV_NORMAL - ); +( + "bouncetouch", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile bounce when it hits a non-damageable solid", + EV_NORMAL +); Event EV_Projectile_BounceSound - ( - "bouncesound", - EV_DEFAULT, - NULL, - NULL, - "Set the name of the sound that is played when the projectile bounces", - EV_NORMAL - ); +( + "bouncesound", + EV_DEFAULT, + NULL, + NULL, + "Set the name of the sound that is played when the projectile bounces", + EV_NORMAL +); Event EV_Projectile_BounceSound_Metal - ( - "bouncesound_metal", - EV_DEFAULT, - NULL, - NULL, - "Set the name of the sound that is played when the projectile bounces off metal", - EV_NORMAL - ); +( + "bouncesound_metal", + EV_DEFAULT, + NULL, + NULL, + "Set the name of the sound that is played when the projectile bounces off metal", + EV_NORMAL +); Event EV_Projectile_BounceSound_Hard - ( - "bouncesound_hard", - EV_DEFAULT, - NULL, - NULL, - "Set the name of the sound that is played when the projectile bounces off hard surfaces", - EV_NORMAL - ); +( + "bouncesound_hard", + EV_DEFAULT, + NULL, + NULL, + "Set the name of the sound that is played when the projectile bounces off hard surfaces", + EV_NORMAL +); Event EV_Projectile_BounceSound_Water - ( - "bouncesound_water", - EV_DEFAULT, - NULL, - NULL, - "Set the name of the sound that is played when the projectile bounces off water", - EV_NORMAL - ); +( + "bouncesound_water", + EV_DEFAULT, + NULL, + NULL, + "Set the name of the sound that is played when the projectile bounces off water", + EV_NORMAL +); Event EV_Projectile_Explode - ( - "explode", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile explode", - EV_NORMAL - ); +( + "explode", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile explode", + EV_NORMAL +); Event EV_Projectile_ImpactMarkShader - ( - "impactmarkshader", - EV_DEFAULT, - "s", - "shader", - "Set the impact mark of the shader", - EV_NORMAL - ); +( + "impactmarkshader", + EV_DEFAULT, + "s", + "shader", + "Set the impact mark of the shader", + EV_NORMAL +); Event EV_Projectile_ImpactMarkRadius - ( - "impactmarkradius", - EV_DEFAULT, - "f", - "radius", - "Set the radius of the impact mark", - EV_NORMAL - ); +( + "impactmarkradius", + EV_DEFAULT, + "f", + "radius", + "Set the radius of the impact mark", + EV_NORMAL +); Event EV_Projectile_ImpactMarkOrientation - ( - "impactmarkorientation", - EV_DEFAULT, - "f", - "degrees", - "Set the orientation of the impact mark", - EV_NORMAL - ); +( + "impactmarkorientation", + EV_DEFAULT, + "f", + "degrees", + "Set the orientation of the impact mark", + EV_NORMAL +); Event EV_Projectile_SetExplosionModel - ( - "explosionmodel", - EV_DEFAULT, - "s", - "modelname", - "Set the modelname of the explosion to be spawned", - EV_NORMAL - ); +( + "explosionmodel", + EV_DEFAULT, + "s", + "modelname", + "Set the modelname of the explosion to be spawned", + EV_NORMAL +); Event EV_Projectile_SetAddVelocity - ( - "addvelocity", - EV_DEFAULT, - "fff", - "velocity_x velocity_y velocity_z", - "Set a velocity to be added to the projectile when it is created", - EV_NORMAL - ); +( + "addvelocity", + EV_DEFAULT, + "fff", + "velocity_x velocity_y velocity_z", + "Set a velocity to be added to the projectile when it is created", + EV_NORMAL +); Event EV_Projectile_AddOwnerVelocity - ( - "addownervelocity", - EV_DEFAULT, - "b", - "bool", - "Set whether or not the owner's velocity is added to the projectile's velocity", - EV_NORMAL - ); +( + "addownervelocity", + EV_DEFAULT, + "b", + "bool", + "Set whether or not the owner's velocity is added to the projectile's velocity", + EV_NORMAL +); Event EV_Projectile_HeatSeek - ( - "heatseek", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile heat seek", - EV_NORMAL - ); +( + "heatseek", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile heat seek", + EV_NORMAL +); Event EV_Projectile_Drunk - ( - "drunk", - EV_DEFAULT, - "ff", - "amount rate", - "Make the projectile drunk", - EV_NORMAL - ); +( + "drunk", + EV_DEFAULT, + "ff", + "amount rate", + "Make the projectile drunk", + EV_NORMAL +); Event EV_Projectile_Prethink - ( - "prethink", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile think to update it's velocity", - EV_NORMAL - ); +( + "prethink", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile think to update it's velocity", + EV_NORMAL +); Event EV_Projectile_SetCanHitOwner - ( - "canhitowner", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile be able to hit its owner", - EV_NORMAL - ); +( + "canhitowner", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile be able to hit its owner", + EV_NORMAL +); Event EV_Projectile_ClearOwner - ( - "clearowner", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile be able to hit its owner now", - EV_NORMAL - ); +( + "clearowner", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile be able to hit its owner now", + EV_NORMAL +); Event EV_Projectile_RemoveWhenStopped - ( - "removewhenstopped", - EV_DEFAULT, - NULL, - NULL, - "Make the projectile get removed when it stops", - EV_NORMAL - ); +( + "removewhenstopped", + EV_DEFAULT, + NULL, + NULL, + "Make the projectile get removed when it stops", + EV_NORMAL +); Event EV_Projectile_ExplodeOnTouch - ( +( "explodeontouch", EV_DEFAULT, NULL, NULL, "Make the projectile explode when it touches something damagable", EV_NORMAL - ); +); Event EV_Projectile_NoTouchDamage - ( +( "notouchdamage", EV_DEFAULT, NULL, NULL, "Makes the projectile not blow up or deal damage when it touches a damagable object", EV_NORMAL - ); +); Event EV_Projectile_SetSmashThroughGlass - ( +( "smashthroughglass", EV_DEFAULT, "i", "speed", "Makes the projectile smash through windows & other damageble glass objects when going above a set speed", EV_NORMAL - ); +); Event EV_Projectile_SmashThroughGlass - ( +( "_smashthroughglass", EV_DEFAULT, NULL, NULL, "Think function for smashing through glass", EV_NORMAL - ); -Event EV_Projectile_ArcToTarget // Added in 2.0 - ( +); +// Added in 2.0 +Event EV_Projectile_ArcToTarget +( "arctotarget", EV_DEFAULT, NULL, NULL, "Make the projectile follow a normal arc on its way to its target", EV_NORMAL - ); -Event EV_Projectile_BecomeBomb // Added in 2.0 - ( +); +// Added in 2.0 +Event EV_Projectile_BecomeBomb +( "becomebomb", EV_DEFAULT, NULL, NULL, "Make the projectile into a bomb", EV_NORMAL - ); -Event EV_Projectile_DieInWater // Added in 2.30 - ( +); +// Added in 2.30 +Event EV_Projectile_DieInWater +( "dieinwater", EV_DEFAULT, NULL, NULL, "Make the projectile die when gets wet", EV_NORMAL - ); +); - -CLASS_DECLARATION( Animate, Projectile, NULL ) -{ - { &EV_Touch, &Projectile::Touch }, - { &EV_Projectile_Speed, &Projectile::SetSpeed }, - { &EV_Projectile_MinSpeed, &Projectile::SetMinSpeed }, - { &EV_Projectile_ChargeSpeed, &Projectile::SetChargeSpeed }, - { &EV_Projectile_Damage, &Projectile::SetDamage }, - { &EV_Projectile_Life, &Projectile::SetLife }, - { &EV_Projectile_DMLife, &Projectile::SetDMLife }, - { &EV_Projectile_MinLife, &Projectile::SetMinLife }, - { &EV_Projectile_ChargeLife, &Projectile::SetChargeLife }, - { &EV_Projectile_SetFuse, &Projectile::SetFuse }, - { &EV_Projectile_Knockback, &Projectile::SetKnockback }, - { &EV_Projectile_DLight, &Projectile::SetDLight }, - { &EV_Projectile_Avelocity, &Projectile::SetAvelocity }, - { &EV_Projectile_MeansOfDeath, &Projectile::SetMeansOfDeath }, - { &EV_Projectile_BounceTouch, &Projectile::SetBounceTouch }, - { &EV_Projectile_BounceSound, &Projectile::SetBounceSound }, - { &EV_Projectile_BounceSound_Metal, &Projectile::SetBounceSoundMetal }, - { &EV_Projectile_BounceSound_Hard, &Projectile::SetBounceSoundHard }, - { &EV_Projectile_BounceSound_Water, &Projectile::SetBounceSoundWater }, - { &EV_Projectile_BeamCommand, &Projectile::BeamCommand }, - { &EV_Projectile_UpdateBeam, &Projectile::UpdateBeam }, - { &EV_Projectile_Explode, &Projectile::Explode }, - { &EV_Projectile_ImpactMarkShader, &Projectile::SetImpactMarkShader }, - { &EV_Projectile_ImpactMarkRadius, &Projectile::SetImpactMarkRadius }, - { &EV_Projectile_ImpactMarkOrientation, &Projectile::SetImpactMarkOrientation }, - { &EV_Projectile_SetExplosionModel, &Projectile::SetExplosionModel }, - { &EV_Projectile_SetAddVelocity, &Projectile::SetAddVelocity }, - { &EV_Projectile_AddOwnerVelocity, &Projectile::AddOwnerVelocity }, - { &EV_Projectile_HeatSeek, &Projectile::HeatSeek }, - { &EV_Projectile_Drunk, &Projectile::Drunk }, - { &EV_Projectile_Prethink, &Projectile::Prethink }, - { &EV_Projectile_SetCanHitOwner, &Projectile::SetCanHitOwner }, - { &EV_Projectile_ClearOwner, &Projectile::ClearOwner }, - { &EV_Projectile_RemoveWhenStopped, &Projectile::RemoveWhenStopped }, - { &EV_Projectile_ExplodeOnTouch, &Projectile::ExplodeOnTouch }, - { &EV_Projectile_NoTouchDamage, &Projectile::SetNoTouchDamage }, - { &EV_Projectile_SetSmashThroughGlass, &Projectile::SetSmashThroughGlass }, - { &EV_Projectile_SmashThroughGlass, &Projectile::SmashThroughGlassThink }, - { &EV_Projectile_BecomeBomb, &Projectile::BecomeBomb }, - { &EV_Killed, &Projectile::Explode }, - { &EV_Stop, &Projectile::Stopped }, - { &EV_Projectile_ArcToTarget, &Projectile::ArcToTarget }, - { &EV_Projectile_DieInWater, &Projectile::DieInWater }, - { NULL, NULL } +CLASS_DECLARATION(Animate, Projectile, NULL) { + {&EV_Touch, &Projectile::Touch }, + {&EV_Projectile_Speed, &Projectile::SetSpeed }, + {&EV_Projectile_MinSpeed, &Projectile::SetMinSpeed }, + {&EV_Projectile_ChargeSpeed, &Projectile::SetChargeSpeed }, + {&EV_Projectile_Damage, &Projectile::SetDamage }, + {&EV_Projectile_Life, &Projectile::SetLife }, + {&EV_Projectile_DMLife, &Projectile::SetDMLife }, + {&EV_Projectile_MinLife, &Projectile::SetMinLife }, + {&EV_Projectile_ChargeLife, &Projectile::SetChargeLife }, + {&EV_Projectile_SetFuse, &Projectile::SetFuse }, + {&EV_Projectile_Knockback, &Projectile::SetKnockback }, + {&EV_Projectile_DLight, &Projectile::SetDLight }, + {&EV_Projectile_Avelocity, &Projectile::SetAvelocity }, + {&EV_Projectile_MeansOfDeath, &Projectile::SetMeansOfDeath }, + {&EV_Projectile_BounceTouch, &Projectile::SetBounceTouch }, + {&EV_Projectile_BounceSound, &Projectile::SetBounceSound }, + {&EV_Projectile_BounceSound_Metal, &Projectile::SetBounceSoundMetal }, + {&EV_Projectile_BounceSound_Hard, &Projectile::SetBounceSoundHard }, + {&EV_Projectile_BounceSound_Water, &Projectile::SetBounceSoundWater }, + {&EV_Projectile_BeamCommand, &Projectile::BeamCommand }, + {&EV_Projectile_UpdateBeam, &Projectile::UpdateBeam }, + {&EV_Projectile_Explode, &Projectile::Explode }, + {&EV_Projectile_ImpactMarkShader, &Projectile::SetImpactMarkShader }, + {&EV_Projectile_ImpactMarkRadius, &Projectile::SetImpactMarkRadius }, + {&EV_Projectile_ImpactMarkOrientation, &Projectile::SetImpactMarkOrientation}, + {&EV_Projectile_SetExplosionModel, &Projectile::SetExplosionModel }, + {&EV_Projectile_SetAddVelocity, &Projectile::SetAddVelocity }, + {&EV_Projectile_AddOwnerVelocity, &Projectile::AddOwnerVelocity }, + {&EV_Projectile_HeatSeek, &Projectile::HeatSeek }, + {&EV_Projectile_Drunk, &Projectile::Drunk }, + {&EV_Projectile_Prethink, &Projectile::Prethink }, + {&EV_Projectile_SetCanHitOwner, &Projectile::SetCanHitOwner }, + {&EV_Projectile_ClearOwner, &Projectile::ClearOwner }, + {&EV_Projectile_RemoveWhenStopped, &Projectile::RemoveWhenStopped }, + {&EV_Projectile_ExplodeOnTouch, &Projectile::ExplodeOnTouch }, + {&EV_Projectile_NoTouchDamage, &Projectile::SetNoTouchDamage }, + {&EV_Projectile_SetSmashThroughGlass, &Projectile::SetSmashThroughGlass }, + {&EV_Projectile_SmashThroughGlass, &Projectile::SmashThroughGlassThink }, + {&EV_Projectile_BecomeBomb, &Projectile::BecomeBomb }, + {&EV_Killed, &Projectile::Explode }, + {&EV_Stop, &Projectile::Stopped }, + {&EV_Projectile_ArcToTarget, &Projectile::ArcToTarget }, + {&EV_Projectile_DieInWater, &Projectile::DieInWater }, + {NULL, NULL } }; Projectile::Projectile() { - entflags |= EF_PROJECTILE; + entflags |= ECF_PROJECTILE; - if( LoadingSavegame ) - { + if (LoadingSavegame) { // Archive function will setup all necessary data return; } - m_beam = NULL; - speed = 0; - minspeed = 0; - damage = 0; - life = 5; - dmlife = 0; - knockback = 0; - dlight_radius = 0; - dlight_color = Vector( 1, 1, 1 ); - avelocity = Vector( 0, 0, 0 ); - mins = Vector( -1, -1, -1 ); - maxs = Vector( 1, 1, 1 ); - meansofdeath = MOD_NONE; - projFlags = 0; - fLastBounceTime = 0; - gravity = 0; - impactmarkradius = 10; - charge_fraction = 1.0; - target = NULL; - fDrunk = 0; - fDrunkRate = 0; + minlife = 0; + m_beam = NULL; + speed = 0; + minspeed = 0; + damage = 0; + life = 5; + dmlife = 0; + knockback = 0; + dlight_radius = 0; + dlight_color = Vector(1, 1, 1); + avelocity = Vector(0, 0, 0); + mins = Vector(-1, -1, -1); + maxs = Vector(1, 1, 1); + meansofdeath = MOD_NONE; + projFlags = 0; + fLastBounceTime = 0; + gravity = 0; + impactmarkradius = 10; + charge_fraction = 1.0; + target = NULL; + addownervelocity = false; + fDrunk = 0; + fDrunkRate = 0; + can_hit_owner = false; + remove_when_stopped = false; + m_bExplodeOnTouch = false; + m_bHurtOwnerOnly = false; m_iSmashThroughGlass = 0; - addownervelocity = qtrue; - can_hit_owner = false; - remove_when_stopped = false; - m_bExplodeOnTouch = false; - m_bHurtOwnerOnly = false; - takedamage = DAMAGE_NO; - owner = ENTITYNUM_NONE; - edict->r.ownerNum = ENTITYNUM_NONE; + takedamage = DAMAGE_NO; + owner = ENTITYNUM_NONE; + edict->r.ownerNum = ENTITYNUM_NONE; + + // Added in 2.0 m_bArcToTarget = false; + // Added in 2.30 m_bDieInWater = false; // make this shootable but non-solid on the client - setContents( CONTENTS_SHOOTONLY ); + setContents(CONTENTS_SHOOTONLY); // // touch triggers by default @@ -661,22 +648,19 @@ Projectile::Projectile() flags |= FL_TOUCH_TRIGGERS; m_iTeam = 0; + + // Added in OPM m_bHadPlayerOwner = false; } -float Projectile::ResolveMinimumDistance - ( - Entity *potential_target, - float currmin - ) - - { - float currdist; - float dot; - Vector angle; - Vector delta; - Vector norm; - float sine = 0.4f; +float Projectile::ResolveMinimumDistance(Entity *potential_target, float currmin) +{ + float currdist; + float dot; + Vector angle; + Vector delta; + Vector norm; + float sine = 0.4f; delta = potential_target->centroid - this->origin; @@ -684,192 +668,153 @@ float Projectile::ResolveMinimumDistance norm.normalize(); // Test if the target is in front of the missile - dot = norm * orientation[ 0 ]; - if ( dot < 0 ) - { + dot = norm * orientation[0]; + if (dot < 0) { return currmin; - } - - // Test if we're within the rocket's viewcone (45 degree cone) - dot = norm * orientation[ 1 ]; - if ( fabs( dot ) > sine ) - { - return currmin; - } - - dot = norm * orientation[ 2 ]; - if ( fabs( dot ) > sine ) - { - return currmin; - } - - currdist = delta.length(); - if ( currdist < currmin ) - { - currmin = currdist; - target = potential_target; - } - - return currmin; } -float Projectile::AdjustAngle - ( - float maxadjust, - float currangle, - float targetangle - ) + // Test if we're within the rocket's viewcone (45 degree cone) + dot = norm * orientation[1]; + if (fabs(dot) > sine) { + return currmin; + } - { - float dangle; + dot = norm * orientation[2]; + if (fabs(dot) > sine) { + return currmin; + } + + currdist = delta.length(); + if (currdist < currmin) { + currmin = currdist; + target = potential_target; + } + + return currmin; +} + +float Projectile::AdjustAngle(float maxadjust, float currangle, float targetangle) +{ + float dangle; float magangle; dangle = currangle - targetangle; - if ( dangle ) - { - magangle = ( float )fabs( dangle ); + if (dangle) { + magangle = (float)fabs(dangle); - while( magangle >= 360.0f ) - { + while (magangle >= 360.0f) { magangle -= 360.0f; - } + } - if ( magangle < maxadjust ) - { + if (magangle < maxadjust) { currangle = targetangle; + } else { + if (magangle > 180.0f) { + maxadjust = -maxadjust; } - else - { - if ( magangle > 180.0f ) - { + if (dangle > 0) { maxadjust = -maxadjust; - } - if ( dangle > 0 ) - { - maxadjust = -maxadjust; - } + } currangle += maxadjust; - } } - - while( currangle >= 360.0f ) - { - currangle -= 360.0f; - } - - while( currangle < 0.0f ) - { - currangle += 360.0f; - } - - return currangle; } -void Projectile::Drunk - ( - Event *ev - ) + while (currangle >= 360.0f) { + currangle -= 360.0f; + } + + while (currangle < 0.0f) { + currangle += 360.0f; + } + + return currangle; +} + +void Projectile::Drunk(Event *ev) { - if( fDrunk ) { + if (fDrunk) { return; } - fDrunk = ev->GetFloat( 1 ); - fDrunkRate = ev->GetFloat( 2 ); + fDrunk = ev->GetFloat(1); + fDrunkRate = ev->GetFloat(2); - PostEvent( EV_Projectile_Prethink, 0 ); + PostEvent(EV_Projectile_Prethink, 0); } -void Projectile::HeatSeek - ( - Event *ev - ) +void Projectile::HeatSeek(Event *ev) +{ + float mindist; + Entity *ent; + trace_t trace; + Vector delta; + Vector v; + int n; + int i; - { - float mindist; - Entity *ent; - trace_t trace; - Vector delta; - Vector v; - int n; - int i; - - if ( ( !target ) || ( target == world ) ) - { + if ((!target) || (target == world)) { mindist = 8192.0f; - n = SentientList.NumObjects(); - for( i = 1; i <= n; i++ ) - { - ent = SentientList.ObjectAt( i ); - if ( ent->entnum == owner ) - { + n = SentientList.NumObjects(); + for (i = 1; i <= n; i++) { + ent = SentientList.ObjectAt(i); + if (ent->entnum == owner) { continue; - } - - if ( ( ( ent->takedamage != DAMAGE_AIM ) || ( ent->health <= 0 ) ) ) - { - continue; - } - - trace = G_Trace( this->origin, vec_zero, vec_zero, ent->centroid, this, MASK_SHOT, qfalse, "DrunkMissile::HeatSeek" ); - if ( ( trace.fraction != 1.0 ) && ( trace.ent != ent->edict ) ) - { - continue; - } - - mindist = ResolveMinimumDistance( ent, mindist ); } - } - else - { - float angspeed; - delta = target->centroid - this->origin; - v = delta.toAngles(); + if (((ent->takedamage != DAMAGE_AIM) || (ent->health <= 0))) { + continue; + } - angspeed = 5.0f; - angles.x = AdjustAngle( angspeed, angles.x, v.x ); - angles.y = AdjustAngle( angspeed, angles.y, v.y ); - angles.z = AdjustAngle( angspeed, angles.z, v.z ); + trace = G_Trace( + this->origin, vec_zero, vec_zero, ent->centroid, this, MASK_SHOT, qfalse, "DrunkMissile::HeatSeek" + ); + if ((trace.fraction != 1.0) && (trace.ent != ent->edict)) { + continue; + } + + mindist = ResolveMinimumDistance(ent, mindist); } - PostEvent( EV_Projectile_HeatSeek, 0.1f ); - PostEvent( EV_Projectile_Prethink, 0 ); + } else { + float angspeed; + + delta = target->centroid - this->origin; + v = delta.toAngles(); + + angspeed = 5.0f; + angles.x = AdjustAngle(angspeed, angles.x, v.x); + angles.y = AdjustAngle(angspeed, angles.y, v.y); + angles.z = AdjustAngle(angspeed, angles.z, v.z); } + PostEvent(EV_Projectile_HeatSeek, 0.1f); + PostEvent(EV_Projectile_Prethink, 0); +} -void Projectile::Prethink - ( - Event *ev - ) +void Projectile::Prethink(Event *ev) { Vector end; - if( fDrunk >= 0.0f ) - { - if( fDrunk ) - { + if (fDrunk >= 0.0f) { + if (fDrunk) { float rnd1 = G_Random(); float rnd2 = G_Random(); - angles += Vector( ( rnd1 + rnd1 - 1.0f ) * fDrunk, ( rnd2 + rnd2 - 1.0f ) * fDrunk, 0 ); + angles += Vector((rnd1 + rnd1 - 1.0f) * fDrunk, (rnd2 + rnd2 - 1.0f) * fDrunk, 0); speed *= 0.98f; fDrunk += fDrunkRate; - if( speed < 500.0f ) - { + if (speed < 500.0f) { fDrunk = -fDrunk; } } - setAngles( angles ); - velocity = Vector( orientation[ 0 ] ) * speed; - } - else - { + setAngles(angles); + velocity = Vector(orientation[0]) * speed; + } else { fDrunk *= 0.80f; - if( fDrunk > -1.0f ) { + if (fDrunk > -1.0f) { fDrunk = -1.0f; } @@ -877,285 +822,215 @@ void Projectile::Prethink //float rnd2 = rand() & 0x7FFF; //angles += Vector( ( rnd1 * 0.00003f + rnd1 * 0.00003f - 1.0f ) * fDrunk, ( rnd2 * 0.00003f + rnd2 * 0.00003f - 1.0f ) * fDrunk, 0 ); - velocity[ 2 ] -= 0.05f * sv_gravity->integer * 0.15f; + velocity[2] -= 0.05f * sv_gravity->integer * 0.15f; angles = velocity.toAngles(); - setAngles( angles ); + setAngles(angles); } - PostEvent( EV_Projectile_Prethink, 0.05f ); + PostEvent(EV_Projectile_Prethink, 0.05f); } -void Projectile::AddOwnerVelocity - ( - Event *ev - ) +void Projectile::AddOwnerVelocity(Event *ev) +{ + addownervelocity = ev->GetBoolean(1); +} - { - addownervelocity = ev->GetBoolean( 1 ); - } +void Projectile::SetAddVelocity(Event *ev) +{ + addvelocity.x = ev->GetFloat(1); + addvelocity.y = ev->GetFloat(2); + addvelocity.z = ev->GetFloat(3); +} -void Projectile::SetAddVelocity - ( - Event *ev - ) +void Projectile::SetExplosionModel(Event *ev) +{ + explosionmodel = ev->GetString(1); +} - { - addvelocity.x = ev->GetFloat( 1 ); - addvelocity.y = ev->GetFloat( 2 ); - addvelocity.z = ev->GetFloat( 3 ); - } +void Projectile::SetImpactMarkShader(Event *ev) +{ + impactmarkshader = ev->GetString(1); +} -void Projectile::SetExplosionModel - ( - Event *ev - ) +void Projectile::SetImpactMarkRadius(Event *ev) +{ + impactmarkradius = ev->GetFloat(1); +} - { - explosionmodel = ev->GetString( 1 ); - } +void Projectile::SetImpactMarkOrientation(Event *ev) +{ + impactmarkorientation = ev->GetString(1); +} -void Projectile::SetImpactMarkShader - ( - Event *ev - ) - - { - impactmarkshader = ev->GetString( 1 ); - } - -void Projectile::SetImpactMarkRadius - ( - Event *ev - ) - - { - impactmarkradius = ev->GetFloat( 1 ); - } - -void Projectile::SetImpactMarkOrientation - ( - Event *ev - ) - - { - impactmarkorientation = ev->GetString( 1 ); - } - -void Projectile::Explode - ( - Event *ev - ) +void Projectile::Explode(Event *ev) { Entity *owner; Entity *ignoreEnt = NULL; - if( !CheckTeams() ) - { - PostEvent( EV_Remove, EV_REMOVE ); + if (!CheckTeams()) { + PostEvent(EV_Remove, EV_REMOVE); return; } - if( ev->NumArgs() == 1 ) - ignoreEnt = ev->GetEntity( 1 ); + if (ev->NumArgs() == 1) { + ignoreEnt = ev->GetEntity(1); + } // Get the owner of this projectile - owner = G_GetEntity( this->owner ); + owner = G_GetEntity(this->owner); // If the owner's not here, make the world the owner - if( !owner ) + if (!owner) { owner = world; + } - if( owner->IsDead() || owner == world ) + if (owner->IsDead() || owner == world) { weap = NULL; + } - health = 0; - deadflag = DEAD_DEAD; + health = 0; + deadflag = DEAD_DEAD; takedamage = DAMAGE_NO; // Spawn an explosion model - if( explosionmodel.length() ) - { + if (explosionmodel.length()) { // Move the projectile back off the surface a bit so we can see // explosion effects. Vector dir, v; - v = velocity; - v.normalize(); - dir = v; - v = origin - v * 36; - setOrigin( v ); + dir = velocity; + if (dir.normalize() == 0) { + vec3_t forward; + AngleVectors(angles, forward, NULL, NULL); + dir = forward; + } + v = origin; - ExplosionAttack( v, owner, explosionmodel, dir, ignoreEnt, 1.0f, weap, m_bHurtOwnerOnly ); + ExplosionAttack(v, owner, explosionmodel, dir, ignoreEnt, 1.0f, weap, m_bHurtOwnerOnly); } - CancelEventsOfType( EV_Projectile_UpdateBeam ); + CancelEventsOfType(EV_Projectile_UpdateBeam); // Kill the beam - if( m_beam ) - { - m_beam->ProcessEvent( EV_Remove ); + if (m_beam) { + m_beam->ProcessEvent(EV_Remove); m_beam = NULL; } // Remove the projectile - PostEvent( EV_Remove, level.frametime ); + PostEvent(EV_Remove, level.frametime); } -void Projectile::SetBounceTouch - ( - Event *ev - ) +void Projectile::SetBounceTouch(Event *ev) { projFlags |= P_BOUNCE_TOUCH; - setMoveType( MOVETYPE_BOUNCE ); + setMoveType(MOVETYPE_BOUNCE); } -void Projectile::SetNoTouchDamage - ( - Event *ev - ) +void Projectile::SetNoTouchDamage(Event *ev) { projFlags |= P_NO_TOUCH_DAMAGE; } -void Projectile::SetSmashThroughGlass - ( - Event *ev - ) +void Projectile::SetSmashThroughGlass(Event *ev) { - m_iSmashThroughGlass = ev->GetInteger( 1 ); + m_iSmashThroughGlass = ev->GetInteger(1); - PostEvent( EV_Projectile_SmashThroughGlass, level.frametime ); + PostEvent(EV_Projectile_SmashThroughGlass, level.frametime); } -void Projectile::SmashThroughGlassThink - ( - Event *ev - ) +void Projectile::SmashThroughGlassThink(Event *ev) { - if( velocity.length() > m_iSmashThroughGlass ) - { - Vector vEnd; + SmashThroughGlassThink(); + + PostEvent(EV_Projectile_SmashThroughGlass, level.frametime); +} + +void Projectile::SmashThroughGlassThink() +{ + if (velocity.length() > m_iSmashThroughGlass) { + Vector vEnd; trace_t trace; - Entity *ent = G_GetEntity( owner ); + Entity *ent = G_GetEntity(owner); vEnd = velocity * level.frametime + velocity * level.frametime + origin; - trace = G_Trace( origin, - vec_zero, - vec_zero, - vEnd, - ent, - MASK_BEAM, - false, - "SmashThroughGlassThink" ); + trace = G_Trace(origin, vec_zero, vec_zero, vEnd, ent, MASK_BEAM, false, "SmashThroughGlassThink"); - if( ( trace.ent ) && ( trace.ent->entity != world ) ) - { + if ((trace.ent) && (trace.ent->entity != world)) { Entity *obj = trace.ent->entity; - if( ( trace.surfaceFlags & SURF_GLASS ) && ( obj->takedamage ) ) - { - obj->Damage( this, - ent, - obj->health + 1, - origin, - velocity, - trace.plane.normal, - knockback, - 0, - meansofdeath - ); + if ((trace.surfaceFlags & SURF_GLASS) && (obj->takedamage)) { + obj->Damage( + this, ent, obj->health + 1, origin, velocity, trace.plane.normal, knockback, 0, meansofdeath + ); } } } - - PostEvent( EV_Projectile_SmashThroughGlass, level.frametime ); } -void Projectile::BeamCommand - ( - Event *ev - ) - - { - int i; - - if ( !m_beam ) - { - m_beam = new FuncBeam; - - m_beam->setOrigin( this->origin ); - m_beam->Ghost( NULL ); - } - - Event *beamev = new Event( ev->GetToken( 1 ) ); - - for( i=2; i<=ev->NumArgs(); i++ ) - { - beamev->AddToken( ev->GetToken( i ) ); - } - - m_beam->ProcessEvent( beamev ); - PostEvent( EV_Projectile_UpdateBeam, level.frametime ); - } - -void Projectile::UpdateBeam - ( - Event *ev - ) - - { - if ( m_beam ) - { - m_beam->setOrigin( this->origin ); - PostEvent( EV_Projectile_UpdateBeam, level.frametime ); - } - } - -void Projectile::SetBounceSound - ( - Event *ev - ) +void Projectile::BeamCommand(Event *ev) { - bouncesound = ev->GetString( 1 ); + int i; + + if (!m_beam) { + m_beam = new FuncBeam; + + m_beam->setOrigin(this->origin); + m_beam->Ghost(NULL); + } + + Event *beamev = new Event(ev->GetToken(1)); + + for (i = 2; i <= ev->NumArgs(); i++) { + beamev->AddToken(ev->GetToken(i)); + } + + m_beam->ProcessEvent(beamev); + PostEvent(EV_Projectile_UpdateBeam, level.frametime); } -void Projectile::SetBounceSoundMetal - ( - Event *ev - ) +void Projectile::UpdateBeam(Event *ev) { - bouncesound_metal = ev->GetString( 1 ); + if (m_beam) { + m_beam->setOrigin(this->origin); + PostEvent(EV_Projectile_UpdateBeam, level.frametime); + } } -void Projectile::SetBounceSoundHard - ( - Event *ev - ) +void Projectile::SetBounceSound(Event *ev) { - bouncesound_hard = ev->GetString( 1 ); + bouncesound = ev->GetString(1); } -void Projectile::SetBounceSoundWater - ( - Event *ev - ) +void Projectile::SetBounceSoundMetal(Event *ev) { - bouncesound_water = ev->GetString( 1 ); + bouncesound_metal = ev->GetString(1); } -void Projectile::SetChargeLife - ( - Event *ev - ) +void Projectile::SetBounceSoundHard(Event *ev) +{ + bouncesound_hard = ev->GetString(1); +} - { - projFlags |= P_CHARGE_LIFE; - } +void Projectile::SetBounceSoundWater(Event *ev) +{ + bouncesound_water = ev->GetString(1); +} -void Projectile::SetFuse(Event* ev) +void Projectile::SetChargeLife(Event *ev) +{ + if (ev->NumArgs() <= 0 || ev->GetInteger(1)) { + projFlags |= P_CHARGE_LIFE; + } else { + // Added in 2.0 + // Allow disabling the charge life when set to 0 + projFlags &= ~P_CHARGE_LIFE; + } +} + +void Projectile::SetFuse(Event *ev) { if (ev->GetInteger(1)) { projFlags |= P_FUSE; @@ -1164,398 +1039,340 @@ void Projectile::SetFuse(Event* ev) } } -void Projectile::SetMinLife - ( - Event *ev - ) - - { - minlife = ev->GetFloat( 1 ); - projFlags |= P_CHARGE_LIFE; - } - -void Projectile::SetLife - ( - Event *ev - ) +void Projectile::SetMinLife(Event *ev) { - life = ev->GetFloat( 1 ); -} - -void Projectile::SetDMLife - ( - Event *ev - ) -{ - dmlife = ev->GetFloat( 1 ); -} - -void Projectile::SetSpeed - ( - Event *ev - ) - - { - speed = ev->GetFloat( 1 ); - } - -void Projectile::SetMinSpeed - ( - Event *ev - ) - - { - minspeed = ev->GetFloat( 1 ); - projFlags |= P_CHARGE_SPEED; - } - -void Projectile::SetChargeSpeed - ( - Event *ev - ) - - { - projFlags |= P_CHARGE_SPEED; - } - -void Projectile::SetAvelocity - ( - Event *ev - ) - - { - int i=1; - int j=0; - str vel; - - if ( ev->NumArgs() < 3 ) - { - warning( "ClientGameCommandManager::SetAngularVelocity", "Expecting at least 3 args for command randvel" ); - } - - while ( j < 3 ) - { - vel = ev->GetString( i++ ); - if ( vel == "crandom" ) - { - avelocity[j++] = ev->GetFloat( i++ ) * crandom(); - } - else if ( vel == "random" ) - { - avelocity[j++] = ev->GetFloat( i++ ) * random(); - } - else - { - avelocity[j++] = atof( vel.c_str() ); - } - } - } - -void Projectile::SetDamage - ( - Event *ev - ) - - { - damage = ev->GetFloat( 1 ); - } - -void Projectile::SetKnockback - ( - Event *ev - ) - - { - knockback = ev->GetFloat( 1 ); - } - -void Projectile::SetDLight - ( - Event *ev - ) - - { - dlight_color[0] = ev->GetFloat( 1 ); - dlight_color[1] = ev->GetFloat( 2 ); - dlight_color[2] = ev->GetFloat( 3 ); - dlight_radius = ev->GetFloat( 4 ); - } - -void Projectile::SetMeansOfDeath - ( - Event *ev - ) - - { - meansofdeath = (meansOfDeath_t )MOD_string_to_int( ev->GetString( 1 ) ); - } - -void Projectile::DoDecal - ( - void - ) -{ - if( impactmarkshader.length() ) - { - Decal *decal = new Decal; - decal->setShader( impactmarkshader ); - decal->setOrigin( level.impact_trace.endpos ); - decal->setDirection( level.impact_trace.plane.normal ); - decal->setOrientation( impactmarkorientation ); - decal->setRadius( impactmarkradius ); + minlife = ev->GetFloat(1); + if (minlife > 0) { + projFlags |= P_CHARGE_LIFE; + } else { + // Added in 2.0 + // Allow disabling the charge life when set to 0 + projFlags &= ~P_CHARGE_LIFE; } } -void Projectile::Touch - ( - Event *ev - ) +void Projectile::SetLife(Event *ev) { - Entity *other; - Entity *owner; - str realname; + life = ev->GetFloat(1); +} + +void Projectile::SetDMLife(Event *ev) +{ + dmlife = ev->GetFloat(1); +} + +void Projectile::SetSpeed(Event *ev) + +{ + speed = ev->GetFloat(1); +} + +void Projectile::SetMinSpeed(Event *ev) +{ + minspeed = ev->GetFloat(1); + projFlags |= P_CHARGE_SPEED; +} + +void Projectile::SetChargeSpeed(Event *ev) +{ + projFlags |= P_CHARGE_SPEED; +} + +void Projectile::SetAvelocity(Event *ev) +{ + int i = 1; + int j = 0; + str vel; + + if (ev->NumArgs() < 3) { + warning("ClientGameCommandManager::SetAngularVelocity", "Expecting at least 3 args for command randvel"); + } + + while (j < 3) { + vel = ev->GetString(i++); + if (vel == "crandom") { + avelocity[j++] = ev->GetFloat(i++) * crandom(); + } else if (vel == "random") { + avelocity[j++] = ev->GetFloat(i++) * random(); + } else { + avelocity[j++] = atof(vel.c_str()); + } + } +} + +void Projectile::SetDamage(Event *ev) +{ + damage = ev->GetFloat(1); +} + +void Projectile::SetKnockback(Event *ev) +{ + knockback = ev->GetFloat(1); +} + +void Projectile::SetDLight(Event *ev) +{ + dlight_color[0] = ev->GetFloat(1); + dlight_color[1] = ev->GetFloat(2); + dlight_color[2] = ev->GetFloat(3); + dlight_radius = ev->GetFloat(4); +} + +void Projectile::SetMeansOfDeath(Event *ev) +{ + meansofdeath = (meansOfDeath_t)MOD_string_to_int(ev->GetString(1)); +} + +void Projectile::DoDecal(void) +{ + if (impactmarkshader.length()) { + Decal *decal = new Decal; + decal->setShader(impactmarkshader); + decal->setOrigin(level.impact_trace.endpos); + decal->setDirection(level.impact_trace.plane.normal); + decal->setOrientation(impactmarkorientation); + decal->setRadius(impactmarkradius); + } +} + +void Projectile::Touch(Event *ev) +{ + Entity *other; + Entity *owner; + str realname; // Other is what got hit - other = ev->GetEntity( 1 ); - assert( other ); + other = ev->GetEntity(1); + assert(other); // Don't touch teleporters - if( other->isSubclassOf( Teleporter ) ) - { + if (other->isSubclassOf(Teleporter)) { return; } // Can't hit yourself with a projectile - if( other->entnum == this->owner ) - { + if (other->entnum == this->owner) { return; } // Remove it if we hit the sky - if( HitSky() ) - { - PostEvent( EV_Remove, 0 ); + if (HitSky()) { + PostEvent(EV_Remove, 0); return; } - if( !CheckTeams() ) - { - PostEvent( EV_Remove, EV_REMOVE ); + if (!CheckTeams()) { + PostEvent(EV_Remove, EV_REMOVE); return; } // Bouncy Projectile - if( ( projFlags & P_BOUNCE_TOUCH ) ) - { + if ((projFlags & P_BOUNCE_TOUCH)) { str snd; + int flags; - if( level.time - fLastBounceTime < 0.1f ) - { + if (level.time - fLastBounceTime < 0.1f) { fLastBounceTime = level.time; return; } - if( level.impact_trace.surfaceFlags & SURF_PUDDLE || ( gi.pointcontents( level.impact_trace.endpos, 0 ) & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) ) - { - if( bouncesound_water.length() ) - this->Sound( bouncesound_water, CHAN_BODY ); + if (level.impact_trace.surfaceFlags & SURF_PUDDLE + || (gi.pointcontents(level.impact_trace.endpos, 0) & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA))) { + if (bouncesound_water.length()) { + this->Sound(bouncesound_water, CHAN_BODY); + } + + // + // Added in 2.30 + // + if (m_bDieInWater) { + PostEvent(EV_Remove, 0.5f); + } + + return; } - else - { - if( bouncesound_metal.length() ) - { - snd = bouncesound_metal; - } - else if( bouncesound_hard.length() ) - { - snd = bouncesound_hard; - } - else - { - snd = bouncesound; - } - int flags = level.impact_trace.surfaceFlags; + if (bouncesound_metal.length()) { + snd = bouncesound_metal; + } else if (bouncesound_hard.length()) { + snd = bouncesound_hard; + } else { + snd = bouncesound; + } - if( flags & SURF_MUD ) - { - if( bouncesound.length() ) - Sound( bouncesound, CHAN_BODY ); + flags = level.impact_trace.surfaceFlags; + + if (flags & SURF_MUD) { + if (bouncesound.length()) { + Sound(bouncesound, CHAN_BODY); } - else if( flags & SURF_ROCK ) - { - if( bouncesound_hard.length() ) - Sound( bouncesound_hard, CHAN_BODY ); + } else if (flags & SURF_ROCK) { + if (bouncesound_hard.length()) { + Sound(bouncesound_hard, CHAN_BODY); } - else if( flags & SURF_GRILL ) - { - if( bouncesound_metal.length() ) - Sound( bouncesound_metal, CHAN_BODY ); + } else if (flags & SURF_GRILL) { + if (bouncesound_metal.length()) { + Sound(bouncesound_metal, CHAN_BODY); } - else if( flags & SURF_WOOD ) - { - if( bouncesound_hard.length() ) - Sound( bouncesound_hard, CHAN_BODY ); + } else if (flags & SURF_WOOD) { + if (bouncesound_hard.length()) { + Sound(bouncesound_hard, CHAN_BODY); } - else if( flags & SURF_METAL ) - { - if( bouncesound_metal.length() ) - Sound( bouncesound_metal, CHAN_BODY ); + } else if (flags & SURF_METAL) { + if (bouncesound_metal.length()) { + Sound(bouncesound_metal, CHAN_BODY); } - else if( flags & SURF_GLASS ) - { - if( bouncesound_hard.length() ) - Sound( bouncesound_hard, CHAN_BODY ); + } else if (flags & SURF_GLASS) { + if (bouncesound_hard.length()) { + Sound(bouncesound_hard, CHAN_BODY); } - else - { - if( bouncesound.length() ) - Sound( bouncesound, CHAN_BODY ); + } else { + if (bouncesound.length()) { + Sound(bouncesound, CHAN_BODY); } } - BroadcastAIEvent( AI_EVENT_WEAPON_IMPACT ); + BroadcastAIEvent(AI_EVENT_WEAPON_IMPACT); + fLastBounceTime = level.time; + return; } - if( !m_bExplodeOnTouch && damage == 0.0f ) + if (!m_bExplodeOnTouch && damage == 0.0f) { return; + } // Get the owner of this projectile - owner = G_GetEntity( this->owner ); + owner = G_GetEntity(this->owner); // If the owner's not here, make the world the owner - if( !owner ) + if (!owner) { owner = world; - - if( owner->IsDead() || owner == world ) - weap = NULL; - - // Damage the thing that got hit - if( other->takedamage ) - { - other->Damage( this, - owner, - damage, - origin, - velocity, - level.impact_trace.plane.normal, - knockback, - 0, - meansofdeath - ); } - if( !g_gametype->integer && weap ) - { - if( other->IsSubclassOfPlayer() || - other->IsSubclassOfVehicle() || - other->IsSubclassOfVehicleTank() || - other->isSubclassOf( VehicleCollisionEntity ) ) - { - weap->m_iNumHits++; - weap->m_iNumTorsoShots++; + if (owner->IsDead() || owner == world) { + weap = NULL; + } - if( weap->IsSubclassOfVehicleTurretGun() ) - { - VehicleTurretGun *t = ( VehicleTurretGun * )weap.Pointer(); - Player *p = ( Player * )t->GetRemoteOwner().Pointer(); + // Damage the thing that got hit + if (other->takedamage) { + other->Damage( + this, owner, damage, origin, velocity, level.impact_trace.plane.normal, knockback, 0, meansofdeath + ); - if( p && p->IsSubclassOfPlayer() ) - { - p->m_iNumHits++; - p->m_iNumTorsoShots++; + if (g_gametype->integer == GT_SINGLE_PLAYER && weap) { + if (other->IsSubclassOfSentient() || other->IsSubclassOfVehicle() || other->IsSubclassOfVehicleTank() + || other->isSubclassOf(VehicleCollisionEntity)) { + weap->m_iNumHits++; + weap->m_iNumTorsoShots++; + + if (weap->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *t = (VehicleTurretGun *)weap.Pointer(); + Player *p = (Player *)t->GetRemoteOwner().Pointer(); + + if (p && p->IsSubclassOfPlayer()) { + p->m_iNumHits++; + p->m_iNumTorsoShots++; + } } } } } - if( !m_bExplodeOnTouch ) + if (!m_bExplodeOnTouch) { return; + } // Make the projectile not solid - setSolidType( SOLID_NOT ); - setMoveType( MOVETYPE_NONE ); + setSolidType(SOLID_NOT); + setMoveType(MOVETYPE_NONE); hideModel(); // Do a decal DoDecal(); - BroadcastAIEvent( AI_EVENT_WEAPON_FIRE ); + BroadcastAIEvent(AI_EVENT_WEAPON_FIRE); // Remove the projectile - PostEvent( EV_Remove, 0 ); + PostEvent(EV_Remove, 0); // Call the explosion event Event *explEv; - explEv = new Event( EV_Projectile_Explode ); - explEv->AddEntity( other ); - ProcessEvent( explEv ); + explEv = new Event(EV_Projectile_Explode); + explEv->AddEntity(other); + ProcessEvent(explEv); + + // + // Added in 2.30 + // Check for projectile vulnerability + // + + Vehicle *pVehicle = NULL; + + if (other->IsSubclassOfVehicle()) { + pVehicle = static_cast(other); + } else if (other->IsSubclassOfVehicleTurretGun()) { + VehicleTurretGun *pTurret = static_cast(other); + Entity *pEnt = pTurret->GetVehicle(); + if (pEnt && pEnt->IsSubclassOfVehicle()) { + pVehicle = static_cast(pEnt); + } + } else if (other->isSubclassOf(VehicleCollisionEntity)) { + VehicleCollisionEntity *pCollision = static_cast(other); + + if (pCollision && pCollision->GetOwner()->IsSubclassOfVehicle()) { + pVehicle = static_cast(pCollision->GetOwner()); + } + } + + if (pVehicle && pVehicle->GetProjectileHitsRemaining() > 0) { + pVehicle->DoProjectileVulnerability(this, owner, meansofdeath); + } } -void Projectile::SetCanHitOwner - ( - Event *ev - ) - - { +void Projectile::SetCanHitOwner(Event *ev) +{ can_hit_owner = true; - } +} -void Projectile::ClearOwner - ( - Event *ev - ) - - { - this->owner = ENTITYNUM_NONE; +void Projectile::ClearOwner(Event *ev) +{ + this->owner = ENTITYNUM_NONE; edict->r.ownerNum = ENTITYNUM_NONE; - } +} -void Projectile::RemoveWhenStopped - ( - Event *ev - ) +void Projectile::RemoveWhenStopped(Event *ev) { remove_when_stopped = true; } -void Projectile::ExplodeOnTouch - ( - Event *ev - ) +void Projectile::ExplodeOnTouch(Event *ev) { m_bExplodeOnTouch = true; } -Sentient *Projectile::GetOwner - ( - void - ) +Sentient *Projectile::GetOwner(void) { Sentient *pOwner = (Sentient *)G_GetEntity(owner); - if (!pOwner || !pOwner->IsSubclassOfSentient()) + if (!pOwner || !pOwner->IsSubclassOfSentient()) { return NULL; - else + } else { return pOwner; + } } -void Projectile::SetOwner - ( - Entity *owner - ) +void Projectile::SetOwner(Entity *owner) { - if (owner) - { - this->owner = owner->entnum; + if (owner) { + this->owner = owner->entnum; edict->r.ownerNum = owner->entnum; - if (owner->IsSubclassOfPlayer()) - { - Player* p = (Player*)owner; - m_iTeam = p->GetTeam(); - // this was added in openmohaa to prevent glitches - // like when the player disconnects or when the player spectates + if (owner->IsSubclassOfPlayer()) { + Player *p = (Player *)owner; + m_iTeam = p->GetTeam(); + // Added in OPM + // this was added to prevent glitches, like when the player + // disconnects or when the player spectates m_bHadPlayerOwner = true; } @@ -1563,19 +1380,17 @@ void Projectile::SetOwner } } -void Projectile::ArcToTarget(Event* ev) +void Projectile::ArcToTarget(Event *ev) { m_bArcToTarget = true; PostEvent(EV_Projectile_Prethink, 0); } -void Projectile::BecomeBomb(Event* ev) +void Projectile::BecomeBomb(Event *ev) { - if (ev->NumArgs() > 0) - { - Entity* ent = ev->GetEntity(1); - if (ent) - { + if (ev->NumArgs() > 0) { + Entity *ent = ev->GetEntity(1); + if (ent) { owner = ent->entnum; setOrigin(ent->origin - Vector(0, 0, 48)); setAngles(ent->angles); @@ -1584,27 +1399,24 @@ void Projectile::BecomeBomb(Event* ev) } m_bExplodeOnTouch = true; - gravity = 1.f; + gravity = 1.f; setMoveType(MOVETYPE_BOUNCE); setSolidType(SOLID_BBOX); edict->clipmask = MASK_PROJECTILE; setSize(mins, maxs); } -void Projectile::DieInWater(Event* ev) +void Projectile::DieInWater(Event *ev) { m_bDieInWater = true; } -void Projectile::Stopped - ( - Event *ev - ) - - { - if ( remove_when_stopped ) - PostEvent( EV_Remove, 0 ); +void Projectile::Stopped(Event *ev) +{ + if (remove_when_stopped) { + PostEvent(EV_Remove, 0); } +} void Projectile::Think() { @@ -1612,14 +1424,13 @@ void Projectile::Think() avelocity.x *= 1.3f; angle = AngleNormalize180(angles.x); - spin = avelocity.x * level.frametime + angle; + spin = avelocity.x * level.frametime + angle; if ((angle >= 0 || spin <= 0) && (angle <= 0 || spin >= 0)) { angle = AngleNormalize360(angles.x); - spin = avelocity.x * level.frametime + angle; + spin = avelocity.x * level.frametime + angle; - if ((angle < 180 && spin > 180) || (angle > 180 && spin < 180)) - { + if ((angle < 180 && spin > 180) || (angle > 180 && spin < 180)) { setAngles(Vector(0, angles.y + 180, angles.z)); avelocity = vec_zero; flags &= ~FL_THINK; @@ -1631,45 +1442,32 @@ void Projectile::Think() } } -bool Projectile::CheckTeams - ( - void - ) +bool Projectile::CheckTeams(void) { - Player* pOwner; + Player *pOwner; - if (g_gametype->integer == GT_SINGLE_PLAYER) - { + if (g_gametype->integer == GT_SINGLE_PLAYER) { // Ignore in single-player mode return true; } - pOwner = (Player*)m_pOwnerPtr.Pointer(); + pOwner = (Player *)m_pOwnerPtr.Pointer(); - if (!pOwner) - { + if (!pOwner) { // Owner disconnected - if (m_bHadPlayerOwner) - { + if (m_bHadPlayerOwner) { return false; - } - else - { + } else { return true; } } - if (pOwner->IsSubclassOfPlayer()) - { - if (m_iTeam != TEAM_NONE && m_iTeam != pOwner->GetTeam()) - { + if (pOwner->IsSubclassOfPlayer()) { + if (m_iTeam != TEAM_NONE && m_iTeam != pOwner->GetTeam()) { return false; } - } - else if (pOwner->IsSubclassOfSentient()) - { - if (m_iTeam != pOwner->m_Team) - { + } else if (pOwner->IsSubclassOfSentient()) { + if (m_iTeam != pOwner->m_Team) { return false; } } @@ -1678,233 +1476,196 @@ bool Projectile::CheckTeams } Event EV_Explosion_Radius - ( - "radius", - EV_DEFAULT, - "f", - "projectileRadius", - "set the radius for the explosion", - EV_NORMAL - ); +( + "radius", + EV_DEFAULT, + "f", + "projectileRadius", + "set the radius for the explosion", + EV_NORMAL +); Event EV_Explosion_ConstantDamage - ( - "constantdamage", - EV_DEFAULT, - NULL, - NULL, - "Makes the explosion do constant damage over the radius", - EV_NORMAL - ); +( + "constantdamage", + EV_DEFAULT, + NULL, + NULL, + "Makes the explosion do constant damage over the radius", + EV_NORMAL +); Event EV_Explosion_DamageEveryFrame - ( - "damageeveryframe", - EV_DEFAULT, - NULL, - NULL, - "Makes the explosion damage every frame", - EV_NORMAL - ); +( + "damageeveryframe", + EV_DEFAULT, + NULL, + NULL, + "Makes the explosion damage every frame", + EV_NORMAL +); Event EV_Explosion_DamageAgain - ( - "damageagain", - EV_DEFAULT, - NULL, - NULL, - "This event is generated each frame if explosion is set to damage each frame", - EV_NORMAL - ); +( + "damageagain", + EV_DEFAULT, + NULL, + NULL, + "This event is generated each frame if explosion is set to damage each frame", + EV_NORMAL +); Event EV_Explosion_Flash - ( - "flash", - EV_DEFAULT, - "fffff", - "time r g b radius", - "Flash player screens", - EV_NORMAL - ); +( + "flash", + EV_DEFAULT, + "fffff", + "time r g b radius", + "Flash player screens", + EV_NORMAL +); Event EV_Explosion_RadiusDamage - ( - "radiusdamage", - EV_DEFAULT, - "f", - "radiusDamage", - "set the radius damage an explosion does", - EV_NORMAL - ); +( + "radiusdamage", + EV_DEFAULT, + "f", + "radiusDamage", + "set the radius damage an explosion does", + EV_NORMAL +); Event EV_Explosion_Effect - ( +( "explosioneffect", EV_DEFAULT, "s", "explosiontype", "Make an explosionType explosion effect", EV_NORMAL - ); +); - -CLASS_DECLARATION( Projectile, Explosion, NULL ) -{ - { &EV_Explosion_Radius, &Explosion::SetRadius }, - { &EV_Explosion_ConstantDamage, &Explosion::SetConstantDamage }, - { &EV_Explosion_DamageEveryFrame, &Explosion::SetDamageEveryFrame }, - { &EV_Explosion_DamageAgain, &Explosion::DamageAgain }, - { &EV_Explosion_Flash, &Explosion::SetFlash }, - { &EV_Explosion_RadiusDamage, &Explosion::SetRadiusDamage }, - { &EV_Explosion_Effect, &Explosion::MakeExplosionEffect }, - { NULL, NULL } +CLASS_DECLARATION(Projectile, Explosion, NULL) { + {&EV_Explosion_Radius, &Explosion::SetRadius }, + {&EV_Explosion_ConstantDamage, &Explosion::SetConstantDamage }, + {&EV_Explosion_DamageEveryFrame, &Explosion::SetDamageEveryFrame}, + {&EV_Explosion_DamageAgain, &Explosion::DamageAgain }, + {&EV_Explosion_Flash, &Explosion::SetFlash }, + {&EV_Explosion_RadiusDamage, &Explosion::SetRadiusDamage }, + {&EV_Explosion_Effect, &Explosion::MakeExplosionEffect}, + {NULL, NULL } }; Explosion::Explosion() { - if( LoadingSavegame ) - { + if (LoadingSavegame) { // Archive function will setup all necessary data return; } - radius = 0; - constant_damage = false; + flash_r = 0; + flash_g = 0; + flash_b = 0; + flash_a = 0; + flash_radius = 0; + radius = 0; + constant_damage = false; damage_every_frame = false; - flash_time = 0; - flash_type = 0; - owner = ENTITYNUM_NONE; - hurtOwnerOnly = false; + flash_time = 0; + flash_type = 0; + owner = ENTITYNUM_NONE; + hurtOwnerOnly = false; } -void Explosion::SetFlash - ( - Event *ev - ) +void Explosion::SetFlash(Event *ev) +{ + flash_time = ev->GetFloat(1); + flash_r = ev->GetFloat(2); + flash_g = ev->GetFloat(3); + flash_b = ev->GetFloat(4); + flash_a = ev->GetFloat(5); + flash_radius = ev->GetFloat(6); + flash_type = 0; - { - flash_time = ev->GetFloat( 1 ); - flash_r = ev->GetFloat( 2 ); - flash_g = ev->GetFloat( 3 ); - flash_b = ev->GetFloat( 4 ); - flash_a = ev->GetFloat( 5 ); - flash_radius = ev->GetFloat( 6 ); - flash_type = 0; + if (ev->NumArgs() > 6) { + str t = ev->GetString(7); - if ( ev->NumArgs() > 6 ) - { - str t = ev->GetString( 7 ); - - if ( !t.icmp( "addblend" ) ) - flash_type = 1; - else if ( !t.icmp( "alphablend" ) ) - flash_type = 0; - } - } + if (!t.icmp("addblend")) { + flash_type = 1; + } else if (!t.icmp("alphablend")) { + flash_type = 0; + } + } +} -void Explosion::SetRadius - ( - Event *ev - ) +void Explosion::SetRadius(Event *ev) +{ + radius = ev->GetFloat(1); +} - { - radius = ev->GetFloat( 1 ); - } +void Explosion::SetRadiusDamage(Event *ev) +{ + radius_damage = ev->GetFloat(1); +} -void Explosion::SetRadiusDamage - ( - Event *ev - ) +void Explosion::SetConstantDamage(Event *ev) +{ + constant_damage = true; +} - { - radius_damage = ev->GetFloat( 1 ); - } +void Explosion::SetDamageEveryFrame(Event *ev) +{ + damage_every_frame = true; +} -void Explosion::SetConstantDamage - ( - Event *ev - ) - - { - constant_damage = true; - } - -void Explosion::SetDamageEveryFrame - ( - Event *ev - ) - - { - damage_every_frame = true; - } - -void Explosion::DamageAgain - ( - Event *ev - ) +void Explosion::DamageAgain(Event *ev) { Entity *owner_ent; Weapon *weapon; - float dmg; - float rad; + float dmg; + float rad; - if( !CheckTeams() ) - { - PostEvent( EV_Remove, EV_REMOVE ); + if (!CheckTeams()) { + PostEvent(EV_Remove, EV_REMOVE); return; } - owner_ent = G_GetEntity( owner ); + owner_ent = G_GetEntity(owner); - if( !owner_ent ) + if (!owner_ent) { owner_ent = world; + } weapon = weap; - if( owner_ent == world || owner_ent->IsDead() ) - { + if (owner_ent == world || owner_ent->IsDead()) { weap = NULL; } dmg = radius_damage; rad = radius; - if( rad == 0.0f ) - { + if (rad == 0.0f) { rad = radius_damage + 60.0f; } - RadiusDamage( origin, this, owner_ent, dmg, NULL, meansofdeath, rad, knockback, constant_damage, weapon, false ); + RadiusDamage(origin, this, owner_ent, dmg, NULL, meansofdeath, rad, knockback, constant_damage, weapon, false); - PostEvent( EV_Explosion_DamageAgain, level.frametime ); + PostEvent(EV_Explosion_DamageAgain, level.frametime); } -void Explosion::MakeExplosionEffect - ( - Event *ev - ) +void Explosion::MakeExplosionEffect(Event *ev) { str sEffect = ev->GetString(1); gi.SetBroadcastAll(); - if (!sEffect.icmp("grenade")) - { + if (!sEffect.icmp("grenade")) { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_EXPLOSION_EFFECT_1)); - } - else - { - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) - { - if (!sEffect.icmp("heavyshell")) - { + } else { + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + if (!sEffect.icmp("heavyshell")) { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_EXPLOSION_EFFECT_3)); - } - else if (!sEffect.icmp("tank")) - { + } else if (!sEffect.icmp("tank")) { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_EXPLOSION_EFFECT_4)); - } - else - { + } else { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_EXPLOSION_EFFECT_2)); } - } - else - { + } else { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_EXPLOSION_EFFECT_2)); } } @@ -1915,17 +1676,18 @@ void Explosion::MakeExplosionEffect gi.MSG_EndCGM(); } -Entity* FindDefusableObject(const Vector& dir, Entity* owner, float maxdist) { +Entity *FindDefusableObject(const Vector& dir, Entity *owner, float maxdist) +{ Vector startOrg; Vector endOrg; Vector mins, maxs; - float fCos; - int numAreaEntities; - int i; - int entNums[MAX_GENTITIES]; + float fCos; + int numAreaEntities; + int i; + int entNums[MAX_GENTITIES]; startOrg = owner->origin; - endOrg = startOrg + dir * maxdist; + endOrg = startOrg + dir * maxdist; if (startOrg.z > endOrg.z) { endOrg.z -= 10; @@ -1957,9 +1719,9 @@ Entity* FindDefusableObject(const Vector& dir, Entity* owner, float maxdist) { numAreaEntities = gi.AreaEntities(mins, maxs, entNums, ARRAY_LEN(entNums)); for (i = 0; i < numAreaEntities; i++) { - gentity_t* pgEnt = &g_entities[entNums[i]]; - Entity* pEnt; - vec3_t delta; + gentity_t *pgEnt = &g_entities[entNums[i]]; + Entity *pEnt; + vec3_t delta; if (!pgEnt->solid) { continue; @@ -1978,15 +1740,16 @@ Entity* FindDefusableObject(const Vector& dir, Entity* owner, float maxdist) { return pEnt; } } - + return NULL; } -void DefuseObject(const Vector& dir, Entity* owner, float maxdist) { - Entity* defusableObj = FindDefusableObject(dir, owner, maxdist); - ScriptVariable* defuseThreadVar; - str defuseThreadName; - +void DefuseObject(const Vector& dir, Entity *owner, float maxdist) +{ + Entity *defusableObj = FindDefusableObject(dir, owner, maxdist); + ScriptVariable *defuseThreadVar; + str defuseThreadName; + if (!defusableObj) { return; } @@ -1998,14 +1761,15 @@ void DefuseObject(const Vector& dir, Entity* owner, float maxdist) { ScriptThreadLabel label; label.Set(defuseThreadName); - label.Execute(defusableObj, ListenerPtr()); + label.Execute(defusableObj, owner, ListenerPtr()); } -qboolean CanPlaceLandmine(const Vector& origin, Entity* owner) { - Vector vEnd; - Vector vDelta; +qboolean CanPlaceLandmine(const Vector& origin, Entity *owner) +{ + Vector vEnd; + Vector vDelta; trace_t trace; - + if (!level.RoundStarted()) { gi.DPrintf("Can't place landmine until the round starts\n"); return qfalse; @@ -2013,17 +1777,7 @@ qboolean CanPlaceLandmine(const Vector& origin, Entity* owner) { vEnd = origin - Vector(0, 0, 256); - trace = G_Trace( - origin, - vec_zero, - vec_zero, - vEnd, - owner, - MASK_LANDMINE_PLACE, - qfalse, - "LandminePlace", - qtrue - ); + trace = G_Trace(origin, vec_zero, vec_zero, vEnd, owner, MASK_LANDMINE_PLACE, qfalse, "LandminePlace", qtrue); vDelta = origin - trace.endpos; if (vDelta.length() > 90) { @@ -2050,7 +1804,7 @@ qboolean CanPlaceLandmine(const Vector& origin, Entity* owner) { gi.DPrintf("Can't place landmine on carpet\n"); return qfalse; } - + if (!(trace.contents & CONTENTS_SOLID)) { gi.DPrintf("Can't place landmine on nonsolid things\n"); return qfalse; @@ -2059,10 +1813,11 @@ qboolean CanPlaceLandmine(const Vector& origin, Entity* owner) { return qtrue; } -void PlaceLandmine(const Vector& origin, Entity* owner, const str& model, Weapon* weap) { - SpawnArgs args; - Listener* l; - TriggerLandmine* trigger; +void PlaceLandmine(const Vector& origin, Entity *owner, const str& model, Weapon *weap) +{ + SpawnArgs args; + Listener *l; + TriggerLandmine *trigger; if (!model.length()) { gi.DPrintf("PlaceLandmine : No model specified for PlaceLandmine"); @@ -2085,7 +1840,7 @@ void PlaceLandmine(const Vector& origin, Entity* owner, const str& model, Weapon return; } - trigger = static_cast(l); + trigger = static_cast(l); trigger->droptofloor(256); trigger->ProcessInitCommands(); trigger->SetDamageable(qtrue); @@ -2094,10 +1849,11 @@ void PlaceLandmine(const Vector& origin, Entity* owner, const str& model, Weapon } trigger->setOrigin(origin); + VectorCopy(trigger->origin, trigger->edict->s.origin2); - if (owner->inheritsFrom(&Player::ClassInfo)) { + if (owner->isSubclassOf(Player)) { if (g_gametype->integer >= GT_TEAM) { - Player* p = static_cast(owner); + Player *p = static_cast(owner); trigger->SetTeam(p->GetTeam()); } else { trigger->SetTeam(0); @@ -2106,77 +1862,70 @@ void PlaceLandmine(const Vector& origin, Entity* owner, const str& model, Weapon trigger->NewAnim("idle"); - if (g_gametype->integer == GT_SINGLE_PLAYER) - { - if (owner) { - if (owner->IsDead()) { - weap = NULL; - } - } else { + if (g_gametype->integer == GT_SINGLE_PLAYER) { + if (!owner) { + weap = NULL; + } else if (owner->IsDead() || owner == world) { weap = NULL; } if (weap) { weap->m_iNumShotsFired++; - if (owner) { - if (owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { - TurretGun* turret = static_cast(weap); - // FIXME: find what to increment - } + if (owner && owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { + Player *p = static_cast(owner); + p->m_iNumShotsFired++; } } } } -Projectile *ProjectileAttack - ( - Vector start, - Vector dir, - Entity *owner, - str projectileModel, - float fraction, - float real_speed, - Weapon *weap - ) +Projectile *ProjectileAttack( + Vector start, Vector dir, Entity *owner, str projectileModel, float fraction, float real_speed, Weapon *weap +) { - Event *ev; - Projectile *proj = NULL; - float newspeed, newlife; - SpawnArgs args; - Entity *obj; - float dot = 0; + Event *ev; + Projectile *proj = NULL; + float newspeed, newlife; + SpawnArgs args; + Entity *obj; + float dot = 0; - if( !projectileModel.length() ) - { - gi.DPrintf( "ProjectileAttack : No model specified for ProjectileAttack" ); + if (!projectileModel.length()) { + gi.DPrintf("ProjectileAttack : No model specified for ProjectileAttack"); return NULL; } - args.setArg( "model", projectileModel ); - obj = ( Entity * )args.Spawn(); + args.setArg("model", projectileModel); + // Added in 2.0 + // Set the projectile targetname + // so they can be managed from scripts + args.setArg("targetname", "projectile"); - if( !obj ) - { - gi.DPrintf( "projectile model '%s' not found\n", projectileModel.c_str() ); + obj = (Entity *)args.Spawn(); + + if (!obj) { + gi.DPrintf("projectile model '%s' not found\n", projectileModel.c_str()); return NULL; } - if( obj->isSubclassOf(Projectile) ) - proj = ( Projectile * )obj; - else - gi.DPrintf( "%s is not of class projectile\n", projectileModel.c_str() ); + if (obj->isSubclassOf(Projectile)) { + proj = (Projectile *)obj; + } else { + gi.DPrintf("%s is not of class projectile\n", projectileModel.c_str()); + } - if( !proj ) + if (!proj) { return NULL; + } // Create a new projectile entity and set it off - proj->setMoveType( MOVETYPE_BOUNCE ); + proj->setMoveType(MOVETYPE_BOUNCE); proj->ProcessInitCommands(); - proj->SetOwner( owner ); - proj->edict->r.ownerNum = owner->entnum; - proj->angles = dir.toAngles(); - proj->charge_fraction = fraction; + proj->SetOwner(owner); + proj->angles = dir.toAngles(); + proj->charge_fraction = fraction; + proj->weap = weap; if (!real_speed) { if (proj->projFlags & P_CHARGE_SPEED) { @@ -2188,92 +1937,85 @@ Projectile *ProjectileAttack newspeed = real_speed; } - if( proj->addownervelocity ) - { - dot = DotProduct( owner->velocity, dir ); - if( dot < 0 ) + if (proj->addownervelocity) { + dot = DotProduct(owner->velocity, dir); + if (dot < 0) { dot = 0; + } } - proj->velocity = dir * ( newspeed + dot ); + proj->velocity = dir * (newspeed + dot); proj->velocity += proj->addvelocity; - proj->setAngles( proj->angles ); - proj->setSolidType( SOLID_BBOX ); + proj->setAngles(proj->angles); + proj->setSolidType(SOLID_BBOX); proj->edict->clipmask = MASK_PROJECTILE; - proj->setSize( proj->mins, proj->maxs ); - proj->setOrigin( start ); - proj->origin.copyTo( proj->edict->s.origin2 ); + proj->setSize(proj->mins, proj->maxs); + proj->setOrigin(start); + proj->origin.copyTo(proj->edict->s.origin2); - if( proj->m_beam ) - { - proj->m_beam->setOrigin( start ); - proj->m_beam->origin.copyTo( proj->m_beam->edict->s.origin2 ); + if (proj->m_beam) { + proj->m_beam->setOrigin(start); + proj->m_beam->origin.copyTo(proj->m_beam->edict->s.origin2); } - if( proj->dlight_radius ) - { - G_SetConstantLight( &proj->edict->s.constantLight, - &proj->dlight_color[ 0 ], - &proj->dlight_color[ 1 ], - &proj->dlight_color[ 2 ], + if (proj->dlight_radius) { + G_SetConstantLight( + &proj->edict->s.constantLight, + &proj->dlight_color[0], + &proj->dlight_color[1], + &proj->dlight_color[2], &proj->dlight_radius - ); + ); } // Calc the life of the projectile - if( proj->projFlags & P_CHARGE_LIFE ) - { - if( g_gametype->integer != GT_SINGLE_PLAYER && proj->dmlife ) + if (proj->projFlags & P_CHARGE_LIFE) { + if (g_gametype->integer != GT_SINGLE_PLAYER && proj->dmlife) { newlife = proj->dmlife * (1 - fraction); - else + } else { newlife = proj->life * (1 - fraction); + } - if( newlife < proj->minlife ) + if (newlife < proj->minlife) { newlife = proj->minlife; - } - else - { - if( g_gametype->integer != GT_SINGLE_PLAYER && proj->dmlife ) + } + } else { + if (g_gametype->integer != GT_SINGLE_PLAYER && proj->dmlife) { newlife = proj->dmlife; - else + } else { newlife = proj->life; + } } // Remove the projectile after it's life expires - ev = new Event( EV_Projectile_Explode ); - proj->PostEvent( ev, newlife ); + ev = new Event(EV_Projectile_Explode); + proj->PostEvent(ev, newlife); - proj->NewAnim( "idle" ); + proj->NewAnim("idle"); // If can hit owner clear the owner of this projectile in a second - if( proj->can_hit_owner ) - proj->PostEvent( EV_Projectile_ClearOwner, 1 ); + if (proj->can_hit_owner) { + proj->PostEvent(EV_Projectile_ClearOwner, 1); + } - if (owner) - { + if (owner) { if (owner->IsDead() || owner == world) { // clear the weapon as the owner died weap = NULL; } - } - else - { + } else { // clear the weapon as there is no owner weap = NULL; } - if( g_gametype->integer == GT_SINGLE_PLAYER ) - { - if( weap ) - { + if (g_gametype->integer == GT_SINGLE_PLAYER) { + if (weap) { weap->m_iNumShotsFired++; - if( owner->IsSubclassOfPlayer() && - weap->IsSubclassOfTurretGun() ) - { - Player *p = ( Player * )owner; + if (owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { + Player *p = (Player *)owner; p->m_iNumShotsFired++; } } @@ -2282,19 +2024,19 @@ Projectile *ProjectileAttack return proj; } -void BulletAttack_Stat(Entity* owner, Entity* target, trace_t* trace, Weapon* weap) { - Sentient* targetSen; - +void BulletAttack_Stat(Entity *owner, Entity *target, trace_t *trace, Weapon *weap) +{ + Sentient *targetSen; + if (!target->IsSubclassOfSentient() || !weap) { return; } - targetSen = static_cast(target); + targetSen = static_cast(target); targetSen->m_iLastHitTime = level.inttime; weap->m_iNumHits++; - switch (trace->location) - { + switch (trace->location) { case HITLOC_HEAD: case HITLOC_HELMET: case HITLOC_NECK: @@ -2334,12 +2076,11 @@ void BulletAttack_Stat(Entity* owner, Entity* target, trace_t* trace, Weapon* we } if (owner && owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { - Player* p = static_cast(owner); + Player *p = static_cast(owner); p->m_iNumHits++; - switch (trace->location) - { + switch (trace->location) { case HITLOC_HEAD: case HITLOC_HELMET: case HITLOC_NECK: @@ -2380,66 +2121,63 @@ void BulletAttack_Stat(Entity* owner, Entity* target, trace_t* trace, Weapon* we } } -float BulletAttack -( - Vector start, - Vector vBarrel, - Vector dir, - Vector right, - Vector up, - float range, - float damage, - int bulletlarge, - float knockback, - int dflags, - int meansofdeath, - Vector spread, - int count, - Entity* owner, - int iTracerFrequency, - int* piTracerCount, - float bulletthroughwood, - float bulletthroughmetal, - Weapon* weap, - float tracerspeed +float BulletAttack( + Vector start, + Vector vBarrel, + Vector dir, + Vector right, + Vector up, + float range, + float damage, + int bulletlarge, + float knockback, + int dflags, + int meansofdeath, + Vector spread, + int count, + Entity *owner, + int iTracerFrequency, + int *piTracerCount, + float bulletthroughwood, + float bulletthroughmetal, + Weapon *weap, + float tracerspeed ) { - Vector vDir; - Vector vTmpEnd; - Vector vTraceStart; - Vector vTraceEnd; - int i; - int iTravelDist; - trace_t trace; - Entity* ent; - Entity* newowner; + Vector vDir; + Vector vTmpEnd; + Vector vOldTmpEnd; + Vector vTraceStart; + Vector vTraceEnd; + int i; + int iTravelDist; + trace_t trace; + Entity *ent; + Entity *newowner; //Entity *tmpSkipEnt; - float damage_total = 0; - float original_value; - qboolean bBulletDone; - qboolean bThroughThing; - int iContinueCount; - float vEndArray[64][3]; - int iTracerCount = 0; - int iNumHit; - int lastSurfaceFlags; - float bulletdist; - float newdamage; - float throughThingFrac; - float oldfrac; - int bulletbits; + float damage_total = 0; + float original_value; + qboolean bBulletDone; + qboolean bThroughThing; + int iContinueCount; + vec3_t vEndArray[64]; + int iTracerCount = 0; + int iNumHit; + int lastSurfaceFlags; + float bulletdist; + float newdamage; + float throughThingFrac; + float oldfrac; + int bulletbits; lastSurfaceFlags = 0; - iNumHit = 0; + iNumHit = 0; - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) - { + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { bulletbits = 2; - } - else - { + } else { bulletlarge = damage >= 41.f; - bulletbits = 1; + bulletbits = 1; } if (count > 63) { @@ -2450,53 +2188,42 @@ float BulletAttack weap = NULL; } - for (i = 0; i < count; i++) - { + for (i = 0; i < count; i++) { trace_t tracethrough; - vTraceEnd = start + (dir * range) + - (right * grandom() * spread.x) + - (up * grandom() * spread.y); + vTraceEnd = start + (dir * range) + (right * grandom() * spread.x) + (up * grandom() * spread.y); vDir = vTraceEnd - start; VectorNormalizeFast(vDir); iContinueCount = 0; - iTravelDist = 0; - bBulletDone = qfalse; - bThroughThing = qfalse; - newowner = owner; - newdamage = damage; + iTravelDist = 0; + bBulletDone = qfalse; + bThroughThing = qfalse; + newowner = owner; + newdamage = damage; - while (!bBulletDone && iTravelDist < MAX_TRAVEL_DIST) - { + while (!bBulletDone && iTravelDist < MAX_TRAVEL_DIST) { iTravelDist += MAX_TRAVEL_DIST; vTraceStart = start; - vTraceEnd = start + vDir * iTravelDist; + vTraceEnd = start + vDir * iTravelDist; + vOldTmpEnd = vTraceStart; memset(&trace, 0, sizeof(trace_t)); oldfrac = -1; - while (trace.fraction < 1.0f) - { + while (trace.fraction < 1.0f) { + Vector vDeltaTrace; + trace = G_Trace( - vTraceStart, - vec_zero, - vec_zero, - vTraceEnd, - newowner, - MASK_SHOT_TRIG, - false, - "BulletAttack", - true + vTraceStart, vec_zero, vec_zero, vTraceEnd, newowner, MASK_SHOT_TRIG, false, "BulletAttack", true ); vTmpEnd = trace.endpos; - if (bThroughThing) - { + if (bThroughThing) { bThroughThing = qfalse; tracethrough = G_Trace( @@ -2512,13 +2239,11 @@ float BulletAttack ); if (!(tracethrough.surfaceFlags & (SURF_FOLIAGE | SURF_GLASS | SURF_PUDDLE | SURF_PAPER)) - && (!(tracethrough.surfaceFlags & SURF_WOOD) || bulletthroughwood) - && (!(tracethrough.surfaceFlags & (SURF_GRILL | SURF_METAL)) || bulletthroughmetal) - ) - { - vTmpEnd = vTraceStart + vDir * -4; + && (!(tracethrough.surfaceFlags & SURF_WOOD) || !bulletthroughwood) + && (!(tracethrough.surfaceFlags & (SURF_GRILL | SURF_METAL)) || !bulletthroughmetal)) { + vTmpEnd = vTraceStart + vDir * -4; trace.fraction = 1.f; - bBulletDone = qtrue; + bBulletDone = qtrue; if (g_showbullettrace->integer) { bThroughThing = qtrue; @@ -2526,16 +2251,13 @@ float BulletAttack break; } - if (lastSurfaceFlags & SURF_WOOD) - { + if (lastSurfaceFlags & SURF_WOOD) { if (tracethrough.surfaceFlags & SURF_WOOD) { throughThingFrac = 1.f / bulletthroughwood; } else { throughThingFrac = 2.f / (bulletthroughwood + bulletthroughmetal); } - } - else - { + } else { if (tracethrough.surfaceFlags & SURF_WOOD) { throughThingFrac = 2.f / (bulletthroughwood + bulletthroughmetal); } else { @@ -2550,10 +2272,15 @@ float BulletAttack } newdamage -= damage * bulletdist * throughThingFrac; + + if (g_showbullettrace->integer) { + gi.Printf("%.2f\n", newdamage); + } + if (newdamage < 1.f) { - vTmpEnd = vTraceStart + vDir * -4; + vTmpEnd = vTraceStart + vDir * -4; trace.fraction = 1.f; - bBulletDone = qtrue; + bBulletDone = qtrue; if (g_showbullettrace->integer) { bThroughThing = qtrue; @@ -2562,27 +2289,43 @@ float BulletAttack } if (g_showbullettrace->integer) { - G_DebugLine(tracethrough.endpos + Vector(8, 0, 0), tracethrough.endpos - Vector(8, 0, 0), 0.5f, 0.5f, 1.f, 1.f); - G_DebugLine(tracethrough.endpos + Vector(0, 8, 0), tracethrough.endpos - Vector(0, 8, 0), 0.5f, 0.5f, 1.f, 1.f); - G_DebugLine(tracethrough.endpos + Vector(0, 0, 8), tracethrough.endpos - Vector(0, 0, 8), 0.5f, 0.5f, 1.f, 1.f); + G_DebugLine( + tracethrough.endpos + Vector(8, 0, 0), + tracethrough.endpos - Vector(8, 0, 0), + 0.5f, + 0.5f, + 1.f, + 1.f + ); + G_DebugLine( + tracethrough.endpos + Vector(0, 8, 0), + tracethrough.endpos - Vector(0, 8, 0), + 0.5f, + 0.5f, + 1.f, + 1.f + ); + G_DebugLine( + tracethrough.endpos + Vector(0, 0, 8), + tracethrough.endpos - Vector(0, 0, 8), + 0.5f, + 0.5f, + 1.f, + 1.f + ); } } - if (trace.ent) - { + if (trace.ent) { ent = trace.ent->entity; - } - else - { + } else { ent = NULL; } - if (ent && ent != world && ent != newowner) - { - if (ent->takedamage) - { + if (ent && ent != world && ent != owner) { + if (ent->takedamage) { if (g_gametype->integer == GT_SINGLE_PLAYER && !iNumHit) { - BulletAttack_Stat(newowner, ent, &trace, weap); + BulletAttack_Stat(owner, ent, &trace, weap); } iNumHit++; @@ -2593,7 +2336,7 @@ float BulletAttack ent->Damage( world, - newowner, + owner, newdamage, trace.endpos, dir, @@ -2609,12 +2352,28 @@ float BulletAttack damage_total += original_value - ent->health; } - if (ent->edict->solid == SOLID_BBOX && !(trace.contents & CONTENTS_CLAYPIDGEON)) - { - if (trace.surfaceFlags & MASK_SURF_TYPE) - { + if (ent->edict->solid == SOLID_BBOX && !(trace.contents & CONTENTS_CLAYPIDGEON)) { + if (trace.surfaceFlags & MASK_SURF_TYPE) { gi.SetBroadcastVisible(vTmpEnd, NULL); - gi.MSG_StartCGM(CGM_BULLET_6); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_6)); + gi.MSG_WriteCoord(vTmpEnd[0]); + gi.MSG_WriteCoord(vTmpEnd[1]); + gi.MSG_WriteCoord(vTmpEnd[2]); + gi.MSG_WriteDir(trace.plane.normal); + gi.MSG_WriteBits(bulletlarge, bulletbits); + gi.MSG_EndCGM(); + } else if (trace.location >= 0 && ent->IsSubclassOfSentient()) { + gi.SetBroadcastVisible(vTmpEnd, NULL); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_8)); + gi.MSG_WriteCoord(vTmpEnd[0]); + gi.MSG_WriteCoord(vTmpEnd[1]); + gi.MSG_WriteCoord(vTmpEnd[2]); + gi.MSG_WriteDir(trace.plane.normal); + gi.MSG_WriteBits(bulletlarge, bulletbits); + gi.MSG_EndCGM(); + } else if (ent->edict->r.contents & CONTENTS_SOLID) { + gi.SetBroadcastVisible(vTmpEnd, NULL); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_7)); gi.MSG_WriteCoord(vTmpEnd[0]); gi.MSG_WriteCoord(vTmpEnd[1]); gi.MSG_WriteCoord(vTmpEnd[2]); @@ -2622,33 +2381,9 @@ float BulletAttack gi.MSG_WriteBits(bulletlarge, bulletbits); gi.MSG_EndCGM(); } - else if (trace.location >= 0 && ent->IsSubclassOfPlayer()) - { - gi.SetBroadcastVisible(vTmpEnd, NULL); - gi.MSG_StartCGM(CGM_BULLET_8); - gi.MSG_WriteCoord(vTmpEnd[0]); - gi.MSG_WriteCoord(vTmpEnd[1]); - gi.MSG_WriteCoord(vTmpEnd[2]); - gi.MSG_WriteDir(trace.plane.normal); - gi.MSG_WriteBits(bulletlarge, bulletbits); - gi.MSG_EndCGM(); - } - else if (ent->edict->r.contents & CONTENTS_SOLID) - { - gi.SetBroadcastVisible(vTmpEnd, NULL); - gi.MSG_StartCGM(CGM_BULLET_7); - gi.MSG_WriteCoord(vTmpEnd[0]); - gi.MSG_WriteCoord(vTmpEnd[1]); - gi.MSG_WriteCoord(vTmpEnd[2]); - gi.MSG_WriteDir(trace.plane.normal); - gi.MSG_WriteBits(bulletlarge, bulletbits); - gi.MSG_EndCGM(); - } - } - else if (ent->edict->solid == SOLID_BSP && !(trace.contents & CONTENTS_CLAYPIDGEON)) - { + } else if (ent->edict->solid == SOLID_BSP && !(trace.contents & CONTENTS_CLAYPIDGEON)) { gi.SetBroadcastVisible(vTmpEnd, NULL); - gi.MSG_StartCGM(CGM_BULLET_6); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_6)); gi.MSG_WriteCoord(vTmpEnd[0]); gi.MSG_WriteCoord(vTmpEnd[1]); gi.MSG_WriteCoord(vTmpEnd[2]); @@ -2658,24 +2393,19 @@ float BulletAttack } } - if (trace.fraction < 1.0f) - { - if (trace.surfaceFlags & (SURF_FOLIAGE | SURF_GLASS | SURF_PUDDLE | SURF_PAPER) || - trace.contents & (CONTENTS_CLAYPIDGEON | CONTENTS_WATER) || - (bulletlarge - && trace.ent - && trace.ent->r.contents & CONTENTS_BBOX - && !trace.ent->r.bmodel - && trace.ent->entity->takedamage) + if (trace.fraction < 1.0f) { + if (trace.surfaceFlags & (SURF_FOLIAGE | SURF_GLASS | SURF_PUDDLE | SURF_PAPER) + || trace.contents & (CONTENTS_CLAYPIDGEON | CONTENTS_WATER) + || (g_protocol < protocol_e::PROTOCOL_MOHTA && trace.startsolid) + || (bulletlarge && trace.ent + && (g_protocol < protocol_e::PROTOCOL_MOHTA || (trace.ent->r.contents & CONTENTS_BBOX)) + && !trace.ent->r.bmodel && trace.ent->entity->takedamage) || ((trace.surfaceFlags & SURF_WOOD) && bulletthroughwood) - || ((trace.surfaceFlags & (SURF_GRILL|SURF_METAL)) && bulletthroughmetal) - && iContinueCount < 5) - { + || ((trace.surfaceFlags & (SURF_GRILL | SURF_METAL)) && bulletthroughmetal && iContinueCount < 5 + )) { if (((trace.surfaceFlags & SURF_WOOD) && bulletthroughwood) - || ((trace.surfaceFlags & (SURF_GRILL | SURF_METAL)) && bulletthroughmetal)) - { - if (trace.contents & CONTENTS_FENCE) - { + || ((trace.surfaceFlags & (SURF_GRILL | SURF_METAL)) && bulletthroughmetal)) { + if (trace.contents & CONTENTS_FENCE) { float damageMultiplier; if (lastSurfaceFlags & SURF_WOOD) { @@ -2686,10 +2416,18 @@ float BulletAttack newdamage -= damageMultiplier * 2 * damage; - if (newdamage < 0) - { + if (newdamage < 0) { trace.fraction = 1; - bBulletDone = qtrue; + bBulletDone = qtrue; + + if (g_showbullettrace->integer) { + bThroughThing = qtrue; + VectorScale(vDir, 2, tracethrough.endpos); + VectorAdd(tracethrough.endpos, vTmpEnd, tracethrough.endpos); + } + } else { + trace.fraction = 1; + bBulletDone = qtrue; if (g_showbullettrace->integer) { bThroughThing = qtrue; @@ -2697,28 +2435,13 @@ float BulletAttack VectorAdd(tracethrough.endpos, vTmpEnd, tracethrough.endpos); } } - else - { - trace.fraction = 1.f; - bBulletDone = qtrue; - - if (g_showbullettrace->integer) - { - bThroughThing = qtrue; - VectorScale(vDir, 2, tracethrough.endpos); - VectorAdd(tracethrough.endpos, vTmpEnd, tracethrough.endpos); - } - } - } - else - { - bThroughThing = qtrue; + } else { + bThroughThing = qtrue; lastSurfaceFlags = trace.surfaceFlags; } } - if (!bBulletDone) - { + if (!bBulletDone) { vTraceStart = vTmpEnd + vDir * 4; if (trace.ent) { @@ -2735,42 +2458,55 @@ float BulletAttack iContinueCount++; } - } - else - { - trace.fraction = 1.f; - bBulletDone = qtrue; - } - - if (oldfrac != trace.fraction) { - oldfrac = trace.fraction; } else { - trace.fraction = 1.f; + trace.fraction = 1; + bBulletDone = qtrue; } } + + if (oldfrac != trace.fraction) { + oldfrac = trace.fraction; + } else { + trace.fraction = 1; + } + + vDeltaTrace = vTmpEnd - vOldTmpEnd; + if (!bBulletDone && DotProduct(vDeltaTrace, vDir) < 0) { + // Fixed in OPM + // Make sure the new trace doesn't start behind the last one + // This can happen in rare circumstances if the trace is out of the world limit + // Or if entities being shot are almost at the same origin + break; + } + + vOldTmpEnd = vTmpEnd; } } if (bBulletDone && g_showbullettrace->integer && bThroughThing) { - G_DebugLine(tracethrough.endpos + Vector(8, 0, 0), tracethrough.endpos - Vector(8, 0, 0), 0.25f, 0.25f, 0.5f, 1.f); - G_DebugLine(tracethrough.endpos + Vector(0, 8, 0), tracethrough.endpos - Vector(0, 8, 0), 0.25f, 0.25f, 0.5f, 1.f); - G_DebugLine(tracethrough.endpos + Vector(0, 0, 8), tracethrough.endpos - Vector(0, 0, 8), 0.25f, 0.25f, 0.5f, 1.f); + G_DebugLine( + tracethrough.endpos + Vector(8, 0, 0), tracethrough.endpos - Vector(8, 0, 0), 0.25f, 0.25f, 0.5f, 1.f + ); + G_DebugLine( + tracethrough.endpos + Vector(0, 8, 0), tracethrough.endpos - Vector(0, 8, 0), 0.25f, 0.25f, 0.5f, 1.f + ); + G_DebugLine( + tracethrough.endpos + Vector(0, 0, 8), tracethrough.endpos - Vector(0, 0, 8), 0.25f, 0.25f, 0.5f, 1.f + ); } - VectorCopy(vTraceEnd, vEndArray[i]); + VectorCopy(vTmpEnd, vEndArray[i]); - if (iTracerFrequency && piTracerCount) - { + if (iTracerFrequency && piTracerCount) { (*piTracerCount)++; - if (*piTracerCount == iTracerFrequency) - { + if (*piTracerCount == iTracerFrequency) { iTracerCount++; *piTracerCount = 0; } } - // Draw a debug trace line to show bullet fire + // Draw a debug trace line to show bullet fire if (g_showbullettrace->integer) { G_DebugLine(start, vTmpEnd, 1, 1, 1, 1); G_DebugLine(vTmpEnd + Vector(8, 0, 0), vTmpEnd - Vector(8, 0, 0), 0.5f, 0.25f, 0.25f, 1.f); @@ -2780,165 +2516,149 @@ float BulletAttack } } - if(g_gametype->integer == GT_SINGLE_PLAYER && weap) - { + if (g_gametype->integer == GT_SINGLE_PLAYER && weap) { weap->m_iNumShotsFired++; - if (owner && owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) - { - Player* p = (Player*)owner; + if (owner && owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { + Player *p = (Player *)owner; p->m_iNumShotsFired++; } } - gi.SetBroadcastVisible(start, trace.endpos); + gi.SetBroadcastVisible(start, vEndArray[0]); - if( count == 1 ) - { - if( iTracerCount ) - { - gi.MSG_StartCGM(CGM_BULLET_1); + if (count == 1) { + if (iTracerCount) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_1)); - gi.MSG_WriteCoord( vBarrel[ 0 ] ); - gi.MSG_WriteCoord( vBarrel[ 1 ] ); - gi.MSG_WriteCoord( vBarrel[ 2 ] ); - } - else - { - gi.MSG_StartCGM(CGM_BULLET_2); + gi.MSG_WriteCoord(vBarrel[0]); + gi.MSG_WriteCoord(vBarrel[1]); + gi.MSG_WriteCoord(vBarrel[2]); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_2)); } - gi.MSG_WriteCoord( start[ 0 ] ); - gi.MSG_WriteCoord( start[ 1 ] ); - gi.MSG_WriteCoord( start[ 2 ] ); - gi.MSG_WriteCoord( trace.endpos[ 0 ] ); - gi.MSG_WriteCoord( trace.endpos[ 1 ] ); - gi.MSG_WriteCoord( trace.endpos[ 2 ] ); - gi.MSG_WriteBits( bulletlarge, bulletbits ); - - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { - if (tracerspeed == 1.f) { - gi.MSG_WriteBits(0, 1); - } else { - gi.MSG_WriteBits(1, 1); - gi.MSG_WriteBits(Q_clamp(tracerspeed, 1, 1023), 10); - } - } - } - else - { - if( iTracerCount ) - { - gi.MSG_StartCGM(CGM_BULLET_3); - - gi.MSG_WriteCoord( vBarrel[ 0 ] ); - gi.MSG_WriteCoord( vBarrel[ 1 ] ); - gi.MSG_WriteCoord( vBarrel[ 2 ] ); - - if (iTracerCount > 63) { - iTracerCount = 63; - } - - gi.MSG_WriteBits( Q_min(iTracerCount, 63), 6); - } - else - { - gi.MSG_StartCGM(CGM_BULLET_4); - } - - gi.MSG_WriteCoord( start[ 0 ] ); - gi.MSG_WriteCoord( start[ 1 ] ); - gi.MSG_WriteCoord( start[ 2 ] ); + gi.MSG_WriteCoord(start[0]); + gi.MSG_WriteCoord(start[1]); + gi.MSG_WriteCoord(start[2]); + gi.MSG_WriteCoord(vEndArray[0][0]); + gi.MSG_WriteCoord(vEndArray[0][1]); + gi.MSG_WriteCoord(vEndArray[0][2]); gi.MSG_WriteBits(bulletlarge, bulletbits); if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { if (tracerspeed == 1.f) { gi.MSG_WriteBits(0, 1); } else { + int speed; + + speed = tracerspeed * (1 << 9); + gi.MSG_WriteBits(1, 1); - gi.MSG_WriteBits(Q_clamp(tracerspeed, 1, 1023), 10); + gi.MSG_WriteBits(Q_clamp(speed, 1, 1023), 10); + } + } + } else { + if (iTracerCount) { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_3)); + + gi.MSG_WriteCoord(vBarrel[0]); + gi.MSG_WriteCoord(vBarrel[1]); + gi.MSG_WriteCoord(vBarrel[2]); + + if (iTracerCount > 63) { + iTracerCount = 63; + } + + gi.MSG_WriteBits(Q_min(iTracerCount, 63), 6); + } else { + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_4)); + } + + gi.MSG_WriteCoord(start[0]); + gi.MSG_WriteCoord(start[1]); + gi.MSG_WriteCoord(start[2]); + gi.MSG_WriteBits(bulletlarge, bulletbits); + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + if (tracerspeed == 1.f) { + gi.MSG_WriteBits(0, 1); + } else { + int speed; + + speed = tracerspeed * (1 << 9); + + gi.MSG_WriteBits(1, 1); + gi.MSG_WriteBits(Q_clamp(speed, 1, 1023), 10); } } - gi.MSG_WriteBits( count, 6 ); + gi.MSG_WriteBits(count, 6); - for( int i = count; i > 0; i-- ) - { - gi.MSG_WriteCoord( vEndArray[ i ][ 0 ] ); - gi.MSG_WriteCoord( vEndArray[ i ][ 1 ] ); - gi.MSG_WriteCoord( vEndArray[ i ][ 2 ] ); + for (int i = 0; i < count; i++) { + gi.MSG_WriteCoord(vEndArray[i][0]); + gi.MSG_WriteCoord(vEndArray[i][1]); + gi.MSG_WriteCoord(vEndArray[i][2]); } } gi.MSG_EndCGM(); - if( damage_total > 0 ) + if (damage_total > 0) { return damage_total; - else + } else { return 0; + } } -void FakeBulletAttack - ( - Vector start, - Vector vBarrel, - Vector dir, - Vector right, - Vector up, - float range, - float damage, - int large, - Vector spread, - int count, - Entity* owner, - int iTracerFrequency, - int* piTracerCount, - float tracerspeed - ) +void FakeBulletAttack( + Vector start, + Vector vBarrel, + Vector dir, + Vector right, + Vector up, + float range, + float damage, + int large, + Vector spread, + int count, + Entity *owner, + int iTracerFrequency, + int *piTracerCount, + float tracerspeed +) { Vector vDir; Vector vTraceEnd; - int i; - int bulletbits; + int i; + int bulletbits; - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) - { + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { bulletbits = 2; - } - else - { - large = damage >= 41.f; + } else { + large = damage >= 41.f; bulletbits = 1; } - for (i = 0; i < count; i++) - { - vTraceEnd = start + (dir * range) + - (right * grandom() * spread.x) + - (up * grandom() * spread.y); + for (i = 0; i < count; i++) { + vTraceEnd = start + (dir * range) + (right * grandom() * spread.x) + (up * grandom() * spread.y); vDir = vTraceEnd - start; VectorNormalize(vDir); vTraceEnd = start + vDir * 9216.0f; gi.SetBroadcastVisible(start, vTraceEnd); - if (iTracerFrequency && piTracerCount) - { + if (iTracerFrequency && piTracerCount) { (*piTracerCount)++; - if (*piTracerCount == iTracerFrequency) - { + if (*piTracerCount == iTracerFrequency) { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_NO_BARREL_1)); gi.MSG_WriteCoord(vBarrel[0]); gi.MSG_WriteCoord(vBarrel[1]); gi.MSG_WriteCoord(vBarrel[2]); *piTracerCount = 0; - } - else - { + } else { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_NO_BARREL_2)); } - } - else - { + } else { gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_BULLET_NO_BARREL_2)); } @@ -2954,8 +2674,12 @@ void FakeBulletAttack if (tracerspeed == 1.f) { gi.MSG_WriteBits(0, 1); } else { + int speed; + + speed = tracerspeed * (1 << 9); + gi.MSG_WriteBits(1, 1); - gi.MSG_WriteBits(Q_clamp(tracerspeed, 1, 1023), 10); + gi.MSG_WriteBits(Q_clamp(speed, 1, 1023), 10); } } @@ -2963,170 +2687,150 @@ void FakeBulletAttack } } -void ClickItemAttack - ( - Vector vStart, - Vector vForward, - float fRange, - Entity *pOwner - ) +void ClickItemAttack(Vector vStart, Vector vForward, float fRange, Entity *pOwner) { - Vector vEnd; + Event *ev; + Vector vEnd; trace_t trace; vEnd = vStart + vForward * fRange; - trace = G_Trace( - vStart, - vec_zero, - vec_zero, - vEnd, - pOwner, - MASK_ALL, - qfalse, - "ClickItemAttack" ); + trace = G_Trace(vStart, vec_zero, vec_zero, vEnd, pOwner, MASK_CLICKITEM, qfalse, "ClickItemAttack"); - if( g_showbullettrace->integer ) - G_DebugLine( vStart, vEnd, 1, 1, 1, 1 ); - - if( trace.entityNum != ENTITYNUM_NONE && trace.ent && - trace.ent->entity && trace.ent->entity->isSubclassOf( TriggerClickItem ) ) - { - Event *ev = new Event( EV_Activate ); - ev->AddEntity( pOwner ); - trace.ent->entity->PostEvent( ev, 0 ); + if (g_showbullettrace->integer) { + //G_DebugLine(vStart, vEnd, 1, 1, 1, 1); + // Added in OPM + // White line between start and end trace position + G_DebugLine(vStart, trace.endpos, 1, 1, 1, 1); + G_DebugLine(trace.endpos, vEnd, 1, 0, 0, 1); } - else - { + + if (trace.entityNum == ENTITYNUM_WORLD || !trace.ent || !trace.ent->entity + || !trace.ent->entity->isSubclassOf(TriggerClickItem)) { ScriptThreadLabel failThread; // Try to execute a fail thread - if( failThread.TrySet( "clickitem_fail" ) ) + if (failThread.TrySet("clickitem_fail")) { failThread.Execute(); + } + + return; } + + ev = new Event(EV_Activate); + ev->AddEntity(pOwner); + trace.ent->entity->PostEvent(ev, 0); } -Projectile *HeavyAttack - ( - Vector start, - Vector dir, - str projectileModel, - float real_speed, - Entity *owner, - Weapon *weap - ) +Projectile *HeavyAttack(Vector start, Vector dir, str projectileModel, float real_speed, Entity *owner, Weapon *weap) { - Event *ev; - Projectile *proj = NULL; - float newspeed, newlife; - SpawnArgs args; - Entity *obj; - float dot = 0; + Event *ev; + Projectile *proj = NULL; + float newspeed, newlife; + SpawnArgs args; + Entity *obj; + float dot = 0; - if( !projectileModel.length() ) - { - gi.DPrintf( "ProjectileAttack : No model specified for ProjectileAttack" ); + if (!projectileModel.length()) { + gi.DPrintf("ProjectileAttack : No model specified for ProjectileAttack"); return NULL; } - args.setArg( "model", projectileModel ); - obj = ( Entity * )args.Spawn(); + args.setArg("model", projectileModel); + obj = (Entity *)args.Spawn(); - if( !obj ) - { - gi.DPrintf( "projectile model '%s' not found\n", projectileModel.c_str() ); + if (!obj) { + gi.DPrintf("projectile model '%s' not found\n", projectileModel.c_str()); return NULL; } - if( obj->IsSubclassOfProjectile() ) - proj = ( Projectile * )obj; - else - gi.DPrintf( "%s is not of class projectile\n", projectileModel.c_str() ); + if (obj->IsSubclassOfProjectile()) { + proj = (Projectile *)obj; + } else { + gi.DPrintf("%s is not of class projectile\n", projectileModel.c_str()); + } - if( !proj ) + if (!proj) { return NULL; + } // Create a new projectile entity and set it off - proj->setModel( projectileModel ); - proj->setMoveType( MOVETYPE_BOUNCE ); + proj->setModel(projectileModel); + proj->setMoveType(MOVETYPE_BOUNCE); proj->ProcessInitCommands(); - proj->SetOwner( owner ); + proj->SetOwner(owner); proj->edict->r.ownerNum = owner->entnum; - proj->angles = dir.toAngles(); - proj->charge_fraction = 1.0f; + proj->angles = dir.toAngles(); + proj->charge_fraction = 1.0f; newspeed = real_speed; - if( real_speed == 0.0f ) + if (real_speed == 0.0f) { newspeed = proj->speed; - - if( proj->addownervelocity ) - { - dot = DotProduct( owner->velocity, dir ); - if( dot < 0 ) - dot = 0; } - proj->velocity = dir * ( newspeed + dot ); + if (proj->addownervelocity) { + dot = DotProduct(owner->velocity, dir); + if (dot < 0) { + dot = 0; + } + } + + proj->velocity = dir * (newspeed + dot); proj->velocity += proj->addvelocity; - proj->setAngles( proj->angles ); - proj->setSolidType( SOLID_BBOX ); + proj->setAngles(proj->angles); + proj->setSolidType(SOLID_BBOX); proj->edict->clipmask = MASK_PROJECTILE; - proj->setSize( proj->mins, proj->maxs ); - proj->setOrigin( start ); - proj->origin.copyTo( proj->edict->s.origin2 ); + proj->setSize(proj->mins, proj->maxs); + proj->setOrigin(start); + proj->origin.copyTo(proj->edict->s.origin2); - if( proj->m_beam ) - { - proj->m_beam->setOrigin( start ); - proj->m_beam->origin.copyTo( proj->m_beam->edict->s.origin2 ); + if (proj->m_beam) { + proj->m_beam->setOrigin(start); + proj->m_beam->origin.copyTo(proj->m_beam->edict->s.origin2); } - if( proj->dlight_radius ) - { - G_SetConstantLight( &proj->edict->s.constantLight, - &proj->dlight_color[ 0 ], - &proj->dlight_color[ 1 ], - &proj->dlight_color[ 2 ], + if (proj->dlight_radius) { + G_SetConstantLight( + &proj->edict->s.constantLight, + &proj->dlight_color[0], + &proj->dlight_color[1], + &proj->dlight_color[2], &proj->dlight_radius - ); + ); } // Calc the life of the projectile - if( proj->projFlags & P_CHARGE_LIFE ) - { - if( g_gametype->integer && proj->dmlife ) + if (proj->projFlags & P_CHARGE_LIFE) { + if (g_gametype->integer != GT_SINGLE_PLAYER && proj->dmlife) { newlife = proj->dmlife; - else + } else { newlife = proj->life; + } - if( newlife < proj->minlife ) + if (newlife < proj->minlife) { newlife = proj->minlife; - } - else - { - if( g_gametype->integer && proj->dmlife ) + } + } else { + if (g_gametype->integer != GT_SINGLE_PLAYER && proj->dmlife) { newlife = proj->dmlife; - else + } else { newlife = proj->life; + } } // Remove the projectile after it's life expires - ev = new Event( EV_Projectile_Explode ); - proj->PostEvent( ev, newlife ); + ev = new Event(EV_Projectile_Explode); + proj->PostEvent(ev, newlife); - proj->NewAnim( "idle" ); + proj->NewAnim("idle"); - if( !g_gametype->integer ) - { - if( weap ) - { + if (g_gametype->integer == GT_SINGLE_PLAYER) { + if (weap) { weap->m_iNumShotsFired++; - if( owner->IsSubclassOfPlayer() && - weap->IsSubclassOfTurretGun() ) - { - Player *p = ( Player * )owner; + if (owner->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { + Player *p = (Player *)owner; p->m_iNumShotsFired++; } } @@ -3135,305 +2839,299 @@ Projectile *HeavyAttack return proj; } -void ExplosionAttack - ( - Vector pos, - Entity *owner, - str explosionModel, - Vector dir, - Entity *ignore, - float scale, - Weapon *weap, - bool hurtOwnerOnly - ) +void ExplosionAttack( + Vector pos, + Entity *owner, + str explosionModel, + Vector dir, + Entity *ignore, + float scale, + Weapon *weap, + bool hurtOwnerOnly +) { - Explosion *explosion; - Event *ev; + Explosion *explosion; + Event *ev; - - if( !owner ) + if (!owner) { owner = world; + } - if( owner->IsDead() || owner == world ) + if (owner->IsDead() || owner == world) { weap = NULL; + } - if( explosionModel.length() ) - { - explosion = new Explosion; + if (explosionModel.length() && gi.modeltiki(CanonicalTikiName(explosionModel))) { + SpawnArgs sp; + ClassDef *c; - // Create a new explosion entity and set it off - explosion->setModel( explosionModel ); + sp.setArg("model", explosionModel); + c = sp.getClassDef(); + if (c && c != Explosion::classinfostatic() && checkInheritance(Entity::classinfostatic(), c)) { + Entity *newent = static_cast(c->newInstance()); - explosion->setSolidType( SOLID_NOT ); + newent->setModel(explosionModel); + newent->setSolidType(SOLID_NOT); + newent->setOrigin(pos); + newent->setAngles(dir.toAngles()); + newent->ProcessInitCommands(); - // Process the INIT commands right away - explosion->ProcessInitCommands(); + if (c == SmokeGrenade::classinfostatic()) { + // + // try to set the owner of the smoke grenade + // + SmokeGrenade *smoke = static_cast(newent); - explosion->SetOwner( owner ); + if (owner && owner->IsSubclassOfSentient()) { + smoke->setOwner(static_cast(owner)); + } + } + } else { + explosion = new Explosion; - explosion->edict->r.ownerNum = owner->entnum; - explosion->angles = dir.toAngles(); - explosion->velocity = dir * explosion->speed; - explosion->edict->s.scale = scale; - explosion->setAngles( explosion->angles ); - explosion->setMoveType( MOVETYPE_FLYMISSILE ); - explosion->edict->clipmask = MASK_PROJECTILE; - explosion->setSize( explosion->mins, explosion->maxs ); - explosion->setOrigin( pos ); - explosion->origin.copyTo( explosion->edict->s.origin2 ); - explosion->hurtOwnerOnly = hurtOwnerOnly; + // Create a new explosion entity and set it off + explosion->setModel(explosionModel); - if( explosion->dlight_radius ) - { - G_SetConstantLight( &explosion->edict->s.constantLight, - &explosion->dlight_color[ 0 ], - &explosion->dlight_color[ 1 ], - &explosion->dlight_color[ 2 ], - &explosion->dlight_radius + explosion->setSolidType(SOLID_NOT); + + // Process the INIT commands right away + explosion->ProcessInitCommands(); + + explosion->SetOwner(owner); + + explosion->edict->r.ownerNum = owner->entnum; + explosion->angles = dir.toAngles(); + explosion->velocity = dir * explosion->speed; + explosion->edict->s.scale = scale; + explosion->setAngles(explosion->angles); + explosion->setMoveType(MOVETYPE_FLYMISSILE); + explosion->edict->clipmask = MASK_PROJECTILE; + explosion->setSize(explosion->mins, explosion->maxs); + explosion->setOrigin(pos); + explosion->origin.copyTo(explosion->edict->s.origin2); + explosion->hurtOwnerOnly = hurtOwnerOnly; + + if (explosion->dlight_radius) { + G_SetConstantLight( + &explosion->edict->s.constantLight, + &explosion->dlight_color[0], + &explosion->dlight_color[1], + &explosion->dlight_color[2], + &explosion->dlight_radius ); - } + } - explosion->BroadcastAIEvent( AI_EVENT_WEAPON_FIRE ); - explosion->NewAnim( "idle" ); + explosion->BroadcastAIEvent(AI_EVENT_WEAPON_FIRE); + explosion->NewAnim("idle"); - RadiusDamage( explosion->origin, - explosion, - owner, - explosion->radius_damage * scale, - ignore, - explosion->meansofdeath, - explosion->radius * scale, - explosion->knockback, - explosion->constant_damage, - weap, - explosion->hurtOwnerOnly + RadiusDamage( + explosion->origin, + explosion, + owner, + explosion->radius_damage * scale, + ignore, + explosion->meansofdeath, + explosion->radius * scale, + explosion->knockback, + explosion->constant_damage, + weap, + explosion->hurtOwnerOnly ); - if( explosion->flash_radius ) - { - FlashPlayers( explosion->origin, - explosion->flash_r, - explosion->flash_g, - explosion->flash_b, - explosion->flash_a, - explosion->flash_radius * scale, - explosion->flash_time, - explosion->flash_type + if (explosion->flash_radius) { + FlashPlayers( + explosion->origin, + explosion->flash_r, + explosion->flash_g, + explosion->flash_b, + explosion->flash_a, + explosion->flash_radius * scale, + explosion->flash_time, + explosion->flash_type ); - } + } - if( explosion->damage_every_frame ) - { - explosion->PostEvent( EV_Explosion_DamageAgain, FRAMETIME ); - } + if (explosion->damage_every_frame) { + explosion->PostEvent(EV_Explosion_DamageAgain, FRAMETIME); + } - // Remove explosion after the life has expired - if( explosion->life || ( g_gametype->integer && explosion->dmlife ) ) - { - ev = new Event( EV_Remove ); + // Remove explosion after the life has expired + if (explosion->life || (g_gametype->integer != GT_SINGLE_PLAYER && explosion->dmlife)) { + ev = new Event(EV_Remove); - if( g_gametype->integer && explosion->dmlife ) - explosion->PostEvent( ev, explosion->dmlife ); - else - explosion->PostEvent( ev, explosion->life ); + if (g_gametype->integer != GT_SINGLE_PLAYER && explosion->dmlife) { + explosion->PostEvent(ev, explosion->dmlife); + } else { + explosion->PostEvent(ev, explosion->life); + } + } } } } -static float radiusdamage_origin[ 3 ]; +static float radiusdamage_origin[3]; -static int radiusdamage_compare( const void *elem1, const void *elem2 ) +static int radiusdamage_compare(const void *elem1, const void *elem2) { Entity *e1, *e2; - float delta[ 3 ]; - float d1, d2; + float delta[3]; + float d1, d2; - e1 = *( Entity ** )elem1; - e2 = *( Entity ** )elem2; + e1 = *(Entity **)elem1; + e2 = *(Entity **)elem2; - VectorSubtract( radiusdamage_origin, e1->origin, delta ); - d1 = VectorLengthSquared( delta ); + VectorSubtract(radiusdamage_origin, e1->origin, delta); + d1 = VectorLengthSquared(delta); - VectorSubtract( radiusdamage_origin, e2->origin, delta ); - d2 = VectorLengthSquared( delta ); + VectorSubtract(radiusdamage_origin, e2->origin, delta); + d2 = VectorLengthSquared(delta); - if( d2 <= d1 ) - { + if (d2 <= d1) { return d1 > d2; - } - else - { + } else { return -1; } } -void RadiusDamage - ( - Vector origin, - Entity *inflictor, - Entity *attacker, - float damage, - Entity *ignore, - int mod, - float radius, - float knockback, - qboolean constant_damage, - Weapon *weap, - bool hurtOwnerOnly - ) +void RadiusDamage( + Vector origin, + Entity *inflictor, + Entity *attacker, + float damage, + Entity *ignore, + int mod, + float radius, + float knockback, + qboolean constant_damage, + Weapon *weap, + bool hurtOwnerOnly +) { - float points; - Entity *ent; - Vector org; - Vector dir; - float dist; - int i; - Container< Entity * > ents; + float points; + Entity *ent; + Vector org; + Vector dir; + float dist; + int i; + Container ents; - if( g_showdamage->integer ) - { - Com_Printf( "radiusdamage" ); - Com_Printf( "{\n" ); - Com_Printf( "origin: %f %f %f\n", origin[ 0 ], origin[ 1 ], origin[ 2 ] ); + if (g_showdamage->integer) { + Com_Printf("radiusdamage"); + Com_Printf("{\n"); + Com_Printf("origin: %f %f %f\n", origin[0], origin[1], origin[2]); - if( inflictor ) { - Com_Printf( "inflictor: (entnum %d, radnum %d)\n", inflictor->entnum, inflictor->radnum ); + if (inflictor) { + Com_Printf("inflictor: (entnum %d, radnum %d)\n", inflictor->entnum, inflictor->radnum); } - if( attacker ) { - Com_Printf( "attacker: (entnum %d, radnum %d)\n", attacker->entnum, attacker->radnum ); + if (attacker) { + Com_Printf("attacker: (entnum %d, radnum %d)\n", attacker->entnum, attacker->radnum); } - Com_Printf( "damage: %f\n", damage ); + Com_Printf("damage: %f\n", damage); - if( ignore ) { - Com_Printf( "ignore: (entnum %d, radnum %d)\n", ignore->entnum, ignore->radnum ); + if (ignore) { + Com_Printf("ignore: (entnum %d, radnum %d)\n", ignore->entnum, ignore->radnum); } - Com_Printf( "mod: %d\n", mod ); - Com_Printf( "radius: %f\n", radius ); - Com_Printf( "knockback: %f\n", knockback ); - Com_Printf( "constant_damage: %d\n", constant_damage ); + Com_Printf("mod: %d\n", mod); + Com_Printf("radius: %f\n", radius); + Com_Printf("knockback: %f\n", knockback); + Com_Printf("constant_damage: %d\n", constant_damage); - if( weap ) - { - Com_Printf( "weapon %s\n", weap->getName().c_str() ); + if (weap) { + Com_Printf("weapon %s\n", weap->getName().c_str()); } - Com_Printf( "hurtOwnerOnly: %d\n", hurtOwnerOnly ); - Com_Printf( "}\n" ); + Com_Printf("hurtOwnerOnly: %d\n", hurtOwnerOnly); + Com_Printf("}\n"); } - ent = findradius( NULL, origin, radius ); + ent = findradius(NULL, origin, radius); - while( ent ) - { + while (ent) { // Add ents that has contents - if( ent->getContents() ) - { - ents.AddObject( ent ); + if (ent->getContents()) { + ents.AddObject(ent); } - ent = findradius( ent, origin, radius ); + ent = findradius(ent, origin, radius); } // Sort by the nearest to the fartest entity - if( ents.NumObjects() ) - { - VectorCopy( origin, radiusdamage_origin ); - ents.Sort( radiusdamage_compare ); + if (ents.NumObjects()) { + VectorCopy(origin, radiusdamage_origin); + ents.Sort(radiusdamage_compare); } - for( i = 1; i <= ents.NumObjects(); i++ ) - { - ent = ents.ObjectAt( i ); + for (i = 1; i <= ents.NumObjects(); i++) { + ent = ents.ObjectAt(i); - if( ent == ignore || !( ent->takedamage ) || ( hurtOwnerOnly && ent != attacker ) ) { + if (ent == ignore || !(ent->takedamage) || (hurtOwnerOnly && ent != attacker)) { continue; } // Add this in for deathmatch maybe - if( ent->getContents() == CONTENTS_NOTTEAM1 || - G_SightTrace( origin, vec_zero, vec_zero, ent->centroid, inflictor, ent, MASK_EXPLOSION, false, "RadiusDamage" ) ) - { - if( constant_damage ) - { + if (ent->getContents() == CONTENTS_CLAYPIDGEON + || G_SightTrace( + origin, vec_zero, vec_zero, ent->centroid, inflictor, ent, MASK_EXPLOSION, false, "RadiusDamage" + )) { + if (constant_damage) { points = damage; - } - else - { + } else { float ent_rad; - ent_rad = fabs( ent->maxs[ 0 ] - ent->mins[ 0 ] ); + ent_rad = fabs(ent->maxs[0] - ent->mins[0]); - if( ent_rad < fabs( ent->maxs[ 1 ] - ent->mins[ 1 ] ) ) - { - ent_rad = fabs( ent->maxs[ 1 ] - ent->mins[ 1 ] ); + if (ent_rad < fabs(ent->maxs[1] - ent->mins[1])) { + ent_rad = fabs(ent->maxs[1] - ent->mins[1]); } - if( ent_rad < fabs( ent->maxs[ 2 ] - ent->mins[ 2 ] ) ) - { - ent_rad = fabs( ent->maxs[ 2 ] - ent->mins[ 2 ] ); + if (ent_rad < fabs(ent->maxs[2] - ent->mins[2])) { + ent_rad = fabs(ent->maxs[2] - ent->mins[2]); } org = ent->centroid; dir = org - origin; dist = dir.length() - ent_rad; - if( dist < 0.0f ) { + if (dist < 0.0f) { dist = 0.0f; } - points = damage - damage * ( dist / radius ); + points = damage - damage * (dist / radius); - knockback -= knockback * ( dist / radius ); + knockback -= knockback * (dist / radius); - if( points < 0 ) + if (points < 0) { points = 0; + } - if( knockback < 0 ) + if (knockback < 0) { knockback = 0; + } } // reduce the damage a little for self-damage - if( ent == attacker ) - { + if (ent == attacker) { points *= 0.9f; } - if( points > 0 ) - { - ent->Damage( inflictor, - attacker, - points, - org, - dir, - vec_zero, - knockback, - DAMAGE_RADIUS, - mod - ); + if (points > 0) { + ent->Damage(inflictor, attacker, points, org, dir, vec_zero, knockback, DAMAGE_RADIUS, mod); - if( !g_gametype->integer && weap ) - { - if( ent->IsSubclassOfPlayer() || - ent->IsSubclassOfVehicle() || - ent->IsSubclassOfVehicleTank() || - ent->isSubclassOf( VehicleCollisionEntity ) ) - { + if (g_gametype->integer == GT_SINGLE_PLAYER && weap) { + if (ent->IsSubclassOfPlayer() || ent->IsSubclassOfVehicle() || ent->IsSubclassOfVehicleTank() + || ent->isSubclassOf(VehicleCollisionEntity)) { weap->m_iNumHits++; weap->m_iNumTorsoShots++; - if( attacker && attacker->IsSubclassOfPlayer() ) - { - Player *player = ( Player * )attacker; + if (attacker && attacker->IsSubclassOfPlayer() && weap->IsSubclassOfTurretGun()) { + Player *player = static_cast(attacker); - if( weap->IsSubclassOfTurretGun() ) - { - player->m_iNumHits++; - player->m_iNumTorsoShots++; - } + player->m_iNumHits++; + player->m_iNumTorsoShots++; } } } @@ -3441,85 +3139,71 @@ void RadiusDamage } } - if( mod == MOD_EXPLOSION ) - { + if (mod == MOD_EXPLOSION) { // Create an earthquake new ViewJitter( - origin, - radius + 128.0f, - 0.05f, - Vector( damage * 0.05f, damage * 0.05f, damage * 0.06f ), - 0, - vec_zero, - 0 - ); + origin, radius + 128.0f, 0.05f, Vector(damage * 0.05f, damage * 0.05f, damage * 0.06f), 0, vec_zero, 0 + ); } } +void FlashPlayers(Vector org, float r, float g, float b, float a, float radius, float time, int type) +{ + trace_t trace; + Vector delta; + float length; + Player *player; + gentity_t *ed; + int i; + Entity *ent; + float newa = 1; -void FlashPlayers - ( - Vector org, - float r, - float g, - float b, - float a, - float radius, - float time, - int type - ) - - { - trace_t trace; - Vector delta; - float length; - Player *player; - gentity_t *ed; - int i; - Entity *ent; - float newa = 1; - - for( i = 0; i < game.maxclients; i++ ) - { - ed = &g_entities[ i ]; - if ( !ed->inuse || !ed->entity ) + for (i = 0; i < game.maxclients; i++) { + ed = &g_entities[i]; + if (!ed->inuse || !ed->entity) { continue; + } - ent = ed->entity; - if ( !ent->IsSubclassOfPlayer() ) - continue; + ent = ed->entity; + if (!ent->IsSubclassOfPlayer()) { + continue; + } - player = ( Player * )ent; + player = (Player *)ent; - if ( !player->WithinDistance( org, radius ) ) - continue; + if (!player->WithinDistance(org, radius)) { + continue; + } - trace = G_Trace( org, vec_zero, vec_zero, player->origin, player, MASK_OPAQUE, qfalse, "FlashPlayers" ); - if ( trace.fraction != 1.0 ) - continue; + trace = G_Trace(org, vec_zero, vec_zero, player->origin, player, MASK_OPAQUE, qfalse, "FlashPlayers"); + if (trace.fraction != 1.0) { + continue; + } - delta = org - trace.endpos; - length = delta.length(); + delta = org - trace.endpos; + length = delta.length(); - // If alpha is specified, then modify it by the amount of distance away from the flash the player is - if ( a != -1 ) - newa = a * ( 1 - length / radius ); + // If alpha is specified, then modify it by the amount of distance away from the flash the player is + if (a != -1) { + newa = a * (1 - length / radius); + } - level.m_fade_alpha = newa; - level.m_fade_color[0] = r; - level.m_fade_color[1] = g; - level.m_fade_color[2] = b; - level.m_fade_time = time; - level.m_fade_time_start = time; + level.m_fade_alpha = newa; + level.m_fade_color[0] = r; + level.m_fade_color[1] = g; + level.m_fade_color[2] = b; + level.m_fade_time = time; + level.m_fade_time_start = time; - if ( type == 1 ) - level.m_fade_style = additive; - else - level.m_fade_style = alphablend; + if (type == 1) { + level.m_fade_style = additive; + } else { + level.m_fade_style = alphablend; + } -// gi.SendServerCommand( NULL, va( "fadein %0.2f %0.2f %0.2f %0.2f %i",time*1000,r*newa,g*newa,b*newa,type ) ); - } - } + // gi.SendServerCommand( NULL, va( "fadein %0.2f %0.2f %0.2f %0.2f %i",time*1000,r*newa,g*newa,b*newa,type ) ); + } +} const char *G_LocationNumToDispString(int iLocation) { @@ -3569,4 +3253,3 @@ const char *G_LocationNumToDispString(int iLocation) return ""; } } - diff --git a/code/fgame/weaputils.h b/code/fgame/weaputils.h index 7d611123..2cff35ed 100644 --- a/code/fgame/weaputils.h +++ b/code/fgame/weaputils.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2015 the OpenMoHAA team +Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -23,8 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // weaputils.h: // -#ifndef __WEAPUTILS_H__ -#define __WEAPUTILS_H__ +#pragma once #include "g_local.h" #include "animate.h" @@ -82,11 +81,18 @@ public: bool m_bExplodeOnTouch; bool m_bHurtOwnerOnly; int m_iSmashThroughGlass; + // Added in 2.0 bool m_bArcToTarget; + // Added in 2.30 bool m_bDieInWater; + // Added in 2.0 int m_iTeam; + + // + // Added in OPM + // bool m_bHadPlayerOwner; - SafePtr m_pOwnerPtr; + SafePtr m_pOwnerPtr; Projectile(); void Archive( Archiver &arc ) override; @@ -125,6 +131,7 @@ public: void HeatSeek( Event *ev ); void Drunk( Event *ev ); void SmashThroughGlassThink( Event *ev ); + void SmashThroughGlassThink(); // Added in OPM void AddOwnerVelocity( Event *ev ); void Prethink( Event *ev ); float ResolveMinimumDistance( Entity *potential_target, float currmin ); @@ -142,11 +149,17 @@ public: void BecomeBomb(Event* ev); void DieInWater(Event* ev); // - // Openmohaa additions + // Added in OPM // - bool CheckTeams( void ); + bool CheckTeams(void); }; +inline void Projectile::SetMartyr(int entnum) +{ + owner = entnum; + m_bHurtOwnerOnly = true; +} + inline void Projectile::Archive ( Archiver &arc @@ -355,5 +368,3 @@ Entity* FindDefusableObject(const Vector& dir, Entity* owner, float maxdist); void DefuseObject(const Vector& dir, Entity* owner, float maxdist); qboolean CanPlaceLandmine(const Vector& origin, Entity* owner); void PlaceLandmine(const Vector& origin, Entity* owner, const str& model, Weapon* weap); - -#endif // __WEAPUTILS_H__ diff --git a/code/fgame/windows.cpp b/code/fgame/windows.cpp index 93053e5c..b485987c 100644 --- a/code/fgame/windows.cpp +++ b/code/fgame/windows.cpp @@ -29,162 +29,162 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Event EV_Window_Setup ( - "_Windowsetup", - EV_CODEONLY, - NULL, - NULL, - "Does the post spawn setup of the Window" + "_Windowsetup", + EV_CODEONLY, + NULL, + NULL, + "Does the post spawn setup of the Window" ); Event EV_Window_SetDebris ( - "debristype", - EV_DEFAULT, - "i", - "type", - "Sets the debris type of the Window" + "debristype", + EV_DEFAULT, + "i", + "type", + "Sets the debris type of the Window" ); -CLASS_DECLARATION( Entity, WindowObject, "func_window" ) -{ - { &EV_Window_Setup, &WindowObject::WindowSetup }, - { &EV_Damage, &WindowObject::WindowDamaged }, - { &EV_Killed, &WindowObject::WindowKilled }, - { &EV_Window_SetDebris, &WindowObject::WindowDebrisType }, - { NULL, NULL } +CLASS_DECLARATION(Entity, WindowObject, "func_window") { + {&EV_Window_Setup, &WindowObject::WindowSetup }, + {&EV_Damage, &WindowObject::WindowDamaged }, + {&EV_Killed, &WindowObject::WindowKilled }, + {&EV_Window_SetDebris, &WindowObject::WindowDebrisType}, + {NULL, NULL } }; WindowObject::WindowObject() { - m_iDebrisType = WINDOW_GLASS; + if (LoadingSavegame) { + return; + } - PostEvent( EV_Window_Setup, EV_POSTSPAWN ); + edict->s.eType = ET_GENERAL; + health = 250; + max_health = health; + deadflag = 0; + takedamage = DAMAGE_YES; + + m_iDebrisType = WINDOW_GLASS; + + PostEvent(EV_Window_Setup, EV_POSTSPAWN); } -void WindowObject::Archive( Archiver& arc ) +void WindowObject::Archive(Archiver& arc) { - arc.ArchiveInteger( &m_iDebrisType ); - arc.ArchiveString( &m_sBrokenModel ); + Entity::Archive(arc); + + arc.ArchiveInteger(&m_iDebrisType); + arc.ArchiveString(&m_sBrokenModel); } -void WindowObject::WindowSetup( Event *ev ) +void WindowObject::WindowSetup(Event *ev) { - Entity *pEnt; + Entity *pEnt; - setSolidType( SOLID_BSP ); + setMoveType(MOVETYPE_NONE); + setSolidType(SOLID_BSP); + setContents(CONTENTS_TRIGGER); - if( Target().length() ) - { - pEnt = ( Entity * )G_FindTarget( NULL, Target() ); + if (Target().length()) { + // If a target is defined, + // find it and set the model from it + pEnt = (Entity *)G_FindTarget(NULL, Target()); - if( pEnt ) - { - // set the broken model to the target model - m_sBrokenModel = pEnt->model; + if (pEnt) { + m_sBrokenModel = pEnt->model; - pEnt->PostEvent( EV_Remove, 0 ); - } - } - - takedamage = DAMAGE_YES; - - if( health <= 0.1f ) { - health = 100.0f; - } + // Don't keep the original entity + pEnt->PostEvent(EV_Remove, 0); + } + } } -void WindowObject::WindowDebrisType( Event *ev ) +void WindowObject::WindowDebrisType(Event *ev) { - m_iDebrisType = ev->GetInteger( 1 ); + m_iDebrisType = ev->GetInteger(1); } -void WindowObject::WindowDamaged( Event *ev ) +void WindowObject::WindowDamaged(Event *ev) { - int iMeansOfDeath; - int iDamage; - Vector vRight; - Vector vForward; - Vector vDir; - Event *event; + int iMeansOfDeath; + int iDamage; + Vector vRight; + Vector vForward; + Vector vDir; + Event *event; - if( !takedamage ) { - return; - } + if (!takedamage) { + return; + } - iDamage = ev->GetInteger( 2 ); - iMeansOfDeath = ev->GetInteger( 9 ); + iDamage = ev->GetInteger(2); + iMeansOfDeath = ev->GetInteger(9); - if( iMeansOfDeath == MOD_BASH ) - { - // double damage for bash - iDamage *= 2; - } - else if( iMeansOfDeath == MOD_EXPLOSION ) - { - // instant break - iDamage = health; - } + if (iMeansOfDeath == MOD_BASH) { + // double damage for bash + iDamage *= 2; + } else if (iMeansOfDeath == MOD_EXPLOSION) { + // instant break + iDamage *= 10; + } - health -= iDamage; + health -= iDamage; - if( health <= 0.0f ) - { - event = new Event( EV_Killed ); + if (health <= 0.0f) { + event = new Event(EV_Killed); - event->AddEntity( ev->GetEntity( 1 ) ); - event->AddInteger( ev->GetInteger( 2 ) ); - event->AddEntity( ev->GetEntity( 3 ) ); + event->AddEntity(ev->GetEntity(1)); + event->AddInteger(ev->GetInteger(2)); + event->AddEntity(ev->GetEntity(3)); - ProcessEvent( event ); - } + ProcessEvent(event); + } } -void WindowObject::WindowKilled( Event *ev ) +void WindowObject::WindowKilled(Event *ev) { - Vector vCenter; + Vector vCenter; - setSolidType( SOLID_NOT ); + setSolidType(SOLID_NOT); - hideModel(); - takedamage = DAMAGE_NO; + hideModel(); + takedamage = DAMAGE_NO; - vCenter = origin + mins + maxs; + vCenter = (mins + maxs) * 0.5; + vCenter += origin; - gi.SetBroadcastVisible( vCenter, vCenter ); - gi.MSG_StartCGM(CGM_MAKE_WINDOW_DEBRIS); - gi.MSG_WriteCoord( vCenter[ 0 ] ); - gi.MSG_WriteCoord( vCenter[ 1 ] ); - gi.MSG_WriteCoord( vCenter[ 2 ] ); - gi.MSG_WriteByte( m_iDebrisType ); - gi.MSG_EndCGM(); + gi.SetBroadcastVisible(vCenter, vCenter); + gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_WINDOW_DEBRIS)); + gi.MSG_WriteCoord(vCenter[0]); + gi.MSG_WriteCoord(vCenter[1]); + gi.MSG_WriteCoord(vCenter[2]); + gi.MSG_WriteByte(m_iDebrisType); + gi.MSG_EndCGM(); - if( m_sBrokenModel.length() ) - { - Entity *ent = new Entity; + if (m_sBrokenModel.length()) { + Entity *ent = new Entity; - ent->takedamage = DAMAGE_NO; - ent->setModel( m_sBrokenModel ); + ent->takedamage = DAMAGE_NO; + ent->setModel(m_sBrokenModel); - ent->setMoveType( MOVETYPE_NONE ); - ent->setSolidType( SOLID_BSP ); + ent->setMoveType(MOVETYPE_NONE); + ent->setSolidType(SOLID_BSP); - setModel( m_sBrokenModel ); + setModel(m_sBrokenModel); - if( spawnflags & WINDOW_BROKEN_BLOCK ) - { - ent->setContents( CONTENTS_MONSTERCLIP | CONTENTS_PLAYERCLIP ); - } - else - { - ent->setContents( CONTENTS_SHOOTONLY ); - } + if (spawnflags & WINDOW_BROKEN_BLOCK) { + ent->setContents(CONTENTS_MONSTERCLIP | CONTENTS_PLAYERCLIP); + } else { + ent->setContents(CONTENTS_SHOOTONLY); + } - ent->setOrigin( origin ); - ent->showModel(); - } + ent->setOrigin(origin); + ent->showModel(); + } - deadflag = DEAD_DEAD; + deadflag = DEAD_DEAD; - // remove the window - PostEvent( EV_Remove, 0 ); + // remove the window + PostEvent(EV_Remove, 0); } diff --git a/code/fgame/windows.h b/code/fgame/windows.h index ce0f9e20..871f0763 100644 --- a/code/fgame/windows.h +++ b/code/fgame/windows.h @@ -23,29 +23,31 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // windows.h: Window class // +#pragma once + #include "entity.h" -#define WINDOW_BROKEN_BLOCK 1 +#define WINDOW_BROKEN_BLOCK 1 -enum -{ - WINDOW_GLASS +enum { + WINDOW_GLASS }; -class WindowObject : public Entity { +class WindowObject : public Entity +{ private: - int m_iDebrisType; - str m_sBrokenModel; + int m_iDebrisType; + str m_sBrokenModel; public: - CLASS_PROTOTYPE( WindowObject ); + CLASS_PROTOTYPE(WindowObject); - WindowObject(); + WindowObject(); - void Archive( Archiver& arc ) override; + void Archive(Archiver& arc) override; - void WindowSetup( Event *ev ); - void WindowDebrisType( Event *ev ); - void WindowDamaged( Event *ev ); - void WindowKilled( Event *ev ); + void WindowSetup(Event *ev); + void WindowDebrisType(Event *ev); + void WindowDamaged(Event *ev); + void WindowKilled(Event *ev); }; \ No newline at end of file diff --git a/code/fgame/world.cpp b/code/fgame/world.cpp deleted file mode 100644 index 9c2058fc..00000000 --- a/code/fgame/world.cpp +++ /dev/null @@ -1,1125 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2015 the OpenMoHAA team - -This file is part of OpenMoHAA source code. - -OpenMoHAA source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -OpenMoHAA source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with OpenMoHAA source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -// world.cpp : Holds the target list, and general info (fog and such). - -#include "g_phys.h" -#include "world.h" -#include "level.h" -#include "scriptmaster.h" -#include "scriptexception.h" -#include "player.h" - -#ifdef GAME_DLL -#include "../fgame/soundman.h" -#endif - -WorldPtr world; - -Event EV_World_MapTime -( - "map_time", - EV_DEFAULT, - "i", - "version", - "Internal usage." -); -Event EV_World_SetSoundtrack -( - "soundtrack", - EV_DEFAULT, - "s", - "MusicFile", - "Set music soundtrack for this level." -); -Event EV_World_SetGravity -( - "gravity", - EV_DEFAULT, - "f", - "worldGravity", - "Set the gravity for the whole world." -); -Event EV_World_SetNextMap -( - "nextmap", - EV_DEFAULT, - "s", - "nextMap", - "Set the next map to change to" -); -Event EV_World_SetMessage -( - "message", - EV_DEFAULT, - "s", - "worldMessage", - "Set a message for the world" -); -Event EV_World_SetWaterColor -( - "watercolor", - EV_DEFAULT, - "v", - "waterColor", - "Set the watercolor screen blend" -); -Event EV_World_SetWaterAlpha -( - "wateralpha", - EV_DEFAULT, - "f", - "waterAlpha", - "Set the alpha of the water screen blend" -); -Event EV_World_SetLavaColor -( - "lavacolor", - EV_DEFAULT, - "v", - "lavaColor", - "Set the color of lava screen blend" -); -Event EV_World_SetLavaAlpha -( - "lavaalpha", - EV_DEFAULT, - "f", - "lavaAlpha", - "Set the alpha of lava screen blend" -); -Event EV_World_GetFarPlane_Color -( - "farplane_color", - EV_DEFAULT, - NULL, - NULL, - "Get the color of the far clipping plane fog", - EV_GETTER -); -Event EV_World_SetFarPlane_Color -( - "farplane_color", - EV_DEFAULT, - "v", - "farplaneColor", - "Set the color of the far clipping plane fog", - EV_SETTER -); -Event EV_World_SetFarPlane_Color2 -( - "farplane_color", - EV_DEFAULT, - "v", - "farplaneColor", - "Set the color of the far clipping plane fog", - EV_NORMAL -); -Event EV_World_SetAnimatedFarPlaneColor -( - "animated_farplane_color", - EV_DEFAULT, - "vvff", - "colorStart colorEnd ZStart ZEnd", - "Set the color of the far clipping plane based on a color range and a Z range", - EV_NORMAL -); -Event EV_World_SetFarPlane_Cull -( - "farplane_cull", - EV_DEFAULT, - "i", - "farplaneCull", - "Whether or not the far clipping plane should cull things out of the world\n" - "0 - no cull\n" - "1 - normal cull\n" - "2 - cull but no bsp culling" -); -Event EV_World_GetFarPlane -( - "farplane", - EV_DEFAULT, - NULL, - NULL, - "Get the distance of the far clipping plane", - EV_GETTER -); -Event EV_World_SetFarPlane -( - "farplane", - EV_DEFAULT, - "f", - "farplaneDistance", - "Set the distance of the far clipping plane", - EV_SETTER -); -Event EV_World_SetFarClipOverride -( - "farclipoverride", - EV_DEFAULT, - "f", - "farclipoverride", - "Override the min config default for the far clip distance", - EV_NORMAL -); -Event EV_World_SetFarPlaneColorOverride -( - "farplaneclipcolor", - EV_DEFAULT, - "v", - "farplaneclipcolor", - "Override the fog color for the min config", - EV_NORMAL -); -Event EV_World_SetFarPlane2 -( - "farplane", - EV_DEFAULT, - "f", - "farplaneDistance", - "Set the distance of the far clipping plane", - EV_NORMAL -); -Event EV_World_SetAnimatedFarPlane -( - "animated_farplane", - EV_DEFAULT, - "ffff", - "farplaneStart farplaneEnd ZStart ZEnd", - "Set the distance of the far clipping plane based on a farplane range and a Z range", - EV_NORMAL -); -Event EV_World_GetFarPlaneBias -( - "farplane_bias", - EV_DEFAULT, - NULL, - NULL, - "Get the distance bias of the far clipping plane", - EV_GETTER -); -Event EV_World_SetFarPlaneBias -( - "farplane_bias", - EV_DEFAULT, - "f", - "farplaneDistanceBias", - "Set the distance bias of the far clipping plane", - EV_SETTER -); -Event EV_World_SetFarPlaneBias2 -( - "farplane_bias", - EV_DEFAULT, - "f", - "farplaneDistanceBias", - "Set the distance bias of the far clipping plane", - EV_NORMAL -); -Event EV_World_SetAnimatedFarPlaneBias -( - "animated_farplane_bias", - EV_DEFAULT, - "ffff", - "biasStart biasEnd ZStart ZEnd", - "Set the bias of the far clipping plane based on a bias range and a Z range", - EV_NORMAL -); -Event EV_World_UpdateAnimatedFarplane -( - "_update_animated_farplane", - EV_DEFAULT, - NULL, - NULL, - "Updates the farplane if it is being animated.", - EV_NORMAL -); -Event EV_World_GetSkyboxFarPlane -( - "skybox_farplane", - EV_DEFAULT, - NULL, - NULL, - "Get the distance of the skybox far clipping plane", - EV_GETTER -); -Event EV_World_SetSkyboxFarPlane -( - "skybox_farplane", - EV_DEFAULT, - "f", - "farplaneDistance", - "Set the distance of the skybox far clipping plane", - EV_SETTER -); -Event EV_World_SetSkyboxFarPlane2 -( - "skybox_farplane", - EV_DEFAULT, - "f", - "farplaneDistance", - "Set the distance of the skybox far clipping plane", - EV_NORMAL -); -Event EV_World_GetSkyboxSpeed -( - "skybox_speed", - EV_DEFAULT, - NULL, - NULL, - "Get the speed of the skybox", - EV_GETTER -); -Event EV_World_SetSkyboxSpeed -( - "skybox_speed", - EV_DEFAULT, - "f", - "speed", - "Set the speed of the skybox", - EV_SETTER -); -Event EV_World_SetSkyboxSpeed2 -( - "skybox_speed", - EV_DEFAULT, - "f", - "speed", - "Set the speed of the skybox", - EV_NORMAL -); -Event EV_World_SetRenderTerrain -( - "render_terrain", - EV_DEFAULT, - "b", - "render_terrain", - "Set to draw or not draw terrain", - EV_NORMAL -); -Event EV_World_GetRenderTerrain -( - "get_render_terrain", - EV_DEFAULT, - NULL, - NULL, - "Get the render terrain switch", - EV_GETTER -); -Event EV_World_SetAmbientLight -( - "ambientlight", - EV_DEFAULT, - "b", - "ambientLight", - "Set whether or not ambient light should be used" -); -Event EV_World_SetAmbientIntensity -( - "ambient", - EV_DEFAULT, - "f", - "ambientIntensity", - "Set the intensity of the ambient light" -); -Event EV_World_SetSunColor -( - "suncolor", - EV_DEFAULT, - "v", - "sunColor", - "Set the color of the sun" -); -Event EV_World_SetSunLight -( - "sunlight", - EV_DEFAULT, - "b", - "sunlight", - "Set whether or not there should be sunlight" -); -Event EV_World_SetSunDirection -( - "sundirection", - EV_DEFAULT, - "v", - "sunlightDirection", - "Set the direction of the sunlight" -); -Event EV_World_LightmapDensity -( - "lightmapdensity", - EV_DEFAULT, - "f", - "density", - "Set the default lightmap density for all world surfaces" -); -Event EV_World_SunFlareName -( - "sunflarename", - EV_DEFAULT, - "s", - "flarename", - "Set the flare to use for the sunflare" -); -Event EV_World_SunFlareDirection -( - "sunflaredirection", - EV_DEFAULT, - "v", - "angles", - "Set the direction of the sunflare" -); -Event EV_World_SetSkyAlpha -( - "skyalpha", - EV_DEFAULT, - "f", - "newAlphaForPortalSky", - "Set the alpha on the sky" -); -Event EV_World_SetSkyPortal -( - "skyportal", - EV_DEFAULT, - "b", - "newSkyPortalState", - "Whether or not to use the sky portal at all" -); -Event EV_World_SetNumArenas -( - "numarenas", - EV_DEFAULT, - "i", - "numarenas", - "Set the number of arenas in the world", - EV_NORMAL -); -Event EV_World_SetAIVisionDistance -( - "ai_visiondistance", - EV_DEFAULT, - "f", - "vision_distance", - "Sets the default AI Vision Distance", - EV_NORMAL -); -Event EV_World_SetNorthYaw -( - "northyaw", - EV_DEFAULT, - "f", - "yaw", - "Sets the yaw direction that is considered to be north" -); -Event EV_World_SetSunDiffuse -( - "sundiffuse", - EV_DEFAULT, - "f", - "factor", - "Sets the fraction of the sunlight to use for diffuse sun" -); - -Event EV_World_SetSunDiffuseColor -( - "sundiffusecolor", - EV_DEFAULT, - "v", - "diffusecolor", - "Sets an alternate sun color to use for clcing diffuse sun" -); -Event EV_World_Overbright -( - "overbright", - EV_DEFAULT, - "i", - "use", - "When set to non-zero, removes the overbright cutoff of lightmaps", - EV_NORMAL -); -Event EV_World_VisDerived -( - "vis_derived", - EV_DEFAULT, - "i", - "use", - "whether or not the vis compiler derives additional vis info from the manual vis", - EV_NORMAL -); - -CLASS_DECLARATION( Entity, World, "worldspawn" ) -{ - { &EV_World_SetSoundtrack, &World::SetSoundtrack }, - { &EV_World_SetGravity, &World::SetGravity }, - { &EV_World_SetNextMap, &World::SetNextMap }, - { &EV_World_SetMessage, &World::SetMessage }, - { &EV_World_SetWaterColor, &World::SetWaterColor }, - { &EV_World_SetWaterAlpha, &World::SetWaterAlpha }, - { &EV_World_SetLavaColor, &World::SetLavaColor }, - { &EV_World_SetLavaAlpha, &World::SetLavaAlpha }, - { &EV_World_GetFarPlane_Color, &World::GetFarPlane_Color }, - { &EV_World_SetFarPlane_Color, &World::SetFarPlane_Color }, - { &EV_World_SetFarPlane_Color2, &World::SetFarPlane_Color }, - { &EV_World_SetFarPlane_Cull, &World::SetFarPlane_Cull }, - { &EV_World_GetFarPlane, &World::GetFarPlane }, - { &EV_World_SetFarPlane, &World::SetFarPlane }, - { &EV_World_SetFarClipOverride, &World::SetFarClipOverride }, - { &EV_World_SetFarPlaneColorOverride, &World::SetFarPlaneColorOverride }, - { &EV_World_SetFarPlane2, &World::SetFarPlane }, - { &EV_World_GetFarPlaneBias, &World::GetFarPlaneBias }, - { &EV_World_SetFarPlaneBias, &World::SetFarPlaneBias }, - { &EV_World_SetFarPlaneBias2, &World::SetFarPlaneBias }, - { &EV_World_GetSkyboxFarPlane, &World::GetSkyboxFarplane }, - { &EV_World_SetSkyboxFarPlane, &World::SetSkyboxFarplane }, - { &EV_World_SetSkyboxFarPlane2, &World::SetSkyboxFarplane }, - { &EV_World_GetSkyboxSpeed, &World::GetSkyboxSpeed }, - { &EV_World_SetSkyboxSpeed, &World::SetSkyboxSpeed }, - { &EV_World_SetSkyboxSpeed2, &World::SetSkyboxSpeed }, - { &EV_World_GetRenderTerrain, &World::GetRenderTerrain }, - { &EV_World_SetRenderTerrain, &World::SetRenderTerrain }, - { &EV_World_SetSkyAlpha, &World::SetSkyAlpha }, - { &EV_World_SetSkyPortal, &World::SetSkyPortal }, - { &EV_World_SetNorthYaw, &World::SetNorthYaw }, - { &EV_World_SetAmbientLight, NULL }, - { &EV_World_SetAmbientIntensity, NULL }, - { &EV_World_SetSunColor, NULL }, - { &EV_World_SetSunLight, NULL }, - { &EV_World_SetSunDirection, NULL }, - { &EV_World_LightmapDensity, NULL }, - { &EV_World_SunFlareName, NULL }, - { &EV_World_SunFlareDirection, NULL }, - { &EV_World_SetNumArenas, NULL }, - { &EV_World_SetSunDiffuse, NULL }, - { &EV_World_SetSunDiffuseColor, NULL }, - { &EV_World_Overbright, NULL }, - { &EV_World_VisDerived, NULL }, - { &EV_World_SetAIVisionDistance, &World::SetAIVisionDistance }, - { &EV_World_SetNorthYaw, &World::SetNorthYaw }, - { &EV_World_SetAnimatedFarPlaneColor, &World::SetAnimatedFarplaneColor }, - { &EV_World_SetAnimatedFarPlane, &World::SetAnimatedFarplane }, - { &EV_World_SetAnimatedFarPlaneBias, &World::SetAnimatedFarplaneBias }, - { &EV_World_UpdateAnimatedFarplane, &World::UpdateAnimatedFarplane }, - { NULL, NULL } -}; - -World::World() -{ - world = this; - world_dying = qfalse; - - // Anything that modifies configstrings, or spawns things is ignored when loading savegames - if( LoadingSavegame ) - { - return; - } - - assert( entnum == ENTITYNUM_WORLD ); - - setMoveType( MOVETYPE_NONE ); - setSolidType( SOLID_BSP ); - - // world model is always index 1 - edict->s.modelindex = 1; - model = "*1"; - - UpdateConfigStrings(); - - // clear out the soundtrack from the last level - ChangeSoundtrack( "" ); - - // set the default gravity - gi.cvar_set( "sv_gravity", "800" ); - - // set the default farplane parameters - farplane_distance = 0; - farplane_bias = 0.0; - farplane_color = vec_zero; - farplane_cull = qtrue; - skybox_farplane = 0.0; - render_terrain = qtrue; - skybox_speed = 0.0; - farclip_override = 0.f; - farplane_color_override = Vector(-1, -1, -1); - animated_farplane_start = 0.0; - animated_farplane_end = 0.0; - animated_farplane_start_z = 8192.0; - animated_farplane_end_z = 0.0; - animated_farplane_bias_start = 0.0; - animated_farplane_bias_end = 0.0; - animated_farplane_bias_start_z = 8192.0; - animated_farplane_bias_end_z = 0.0; - animated_farplane_color_start = vec_zero; - animated_farplane_color_end = vec_zero; - animated_farplane_color_start_z = 8192.0; - animated_farplane_color_end_z = 0.0; - - UpdateFog(); - - sky_alpha = 1.0f; - sky_portal = qtrue; - UpdateSky(); - - m_fAIVisionDistance = 2048.0f; - - level.cinematic = spawnflags & WORLD_CINEMATIC; - - if( level.cinematic ) - gi.cvar_set( "sv_cinematic", "1" ); - else - gi.cvar_set( "sv_cinematic", "0" ); - - level.nextmap = ""; - level.level_name = level.mapname; - - SoundMan.Load(); - - // Set the color for the blends. - level.water_color = Vector( 0, 0, 1 ); - level.water_alpha = 0.1f; - level.lava_color = Vector( 1.0f, 0.3f, 0 ); - level.lava_alpha = 0.6f; - - // - // set the targetname of the world - // - SetTargetName( "world" ); - - m_fNorth = 0; -} - -void World::UpdateConfigStrings( void ) -{ - // - // make some data visible to connecting client - // - gi.setConfigstring( CS_GAME_VERSION, GAME_VERSION ); - gi.setConfigstring( CS_LEVEL_START_TIME, va( "%i", level.svsStartTime ) ); - - // make some data visible to the server - gi.setConfigstring( CS_MESSAGE, level.level_name.c_str() ); -}; - -void World::UpdateFog(void) -{ - const char* fogInfoString; - gi.SetFarPlane(farplane_distance); - - if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { - fogInfoString = va( - "%d %.0f %.0f %.0f %.6f %.4f %.4f %.4f %d %.0f %.2f %.2f %.2f", - farplane_cull, - farplane_distance, - farplane_bias, - skybox_farplane, - skybox_speed, - farplane_color.x, - farplane_color.y, - farplane_color.z, - render_terrain, - farclip_override, - farplane_color_override.x, - farplane_color_override.y, - farplane_color_override.z - ); - } else { - fogInfoString = va( - "%d %.0f %.4f %.4f %.4f", - farplane_cull, - farplane_distance, - farplane_color.x, - farplane_color.y, - farplane_color.z - ); - } - - gi.setConfigstring(CS_FOGINFO, fogInfoString); -} - -void World::SetFarClipOverride(Event* ev) -{ - farplane_color_override = ev->GetVector(1); - UpdateFog(); -} - -void World::SetFarPlaneColorOverride(Event* ev) -{ - farclip_override = ev->GetFloat(1); - UpdateFog(); -} - -void World::UpdateSky( void ) -{ - gi.SetSkyPortal( sky_portal ); - gi.setConfigstring( CS_SKYINFO, va( "%.4f %d", sky_alpha, sky_portal ) ); -} - -void World::SetSoundtrack( Event *ev ) -{ - const char *text; - - text = ev->GetString( 1 ); - ChangeSoundtrack( text ); -} - -void World::SetGravity( Event *ev ) -{ - gi.cvar_set( "sv_gravity", ev->GetString( 1 ) ); -} - -void World::GetFarPlane(Event* ev) -{ - ev->AddFloat(farplane_distance); -} - -void World::SetFarPlane( Event *ev ) -{ - farplane_distance = ev->GetFloat( 1 ); - UpdateFog(); -} - -void World::GetFarPlaneBias(Event* ev) -{ - ev->AddFloat(farplane_bias); -} - -void World::SetFarPlaneBias(Event* ev) -{ - farplane_bias = ev->GetFloat(1); -} - -void World::GetFarPlane_Color(Event* ev) -{ - ev->AddVector(farplane_color); -} - -void World::SetFarPlane_Color(Event* ev) -{ - farplane_color = ev->GetVector(1); - UpdateFog(); -} - -void World::SetFarPlane_Cull( Event *ev ) -{ - farplane_cull = ev->GetBoolean( 1 ); - UpdateFog(); -} - -void World::GetSkyboxFarplane(Event* ev) -{ - ev->AddFloat(skybox_farplane); -} - -void World::SetSkyboxFarplane(Event* ev) -{ - skybox_farplane = ev->GetFloat(1); -} - -void World::SetAnimatedFarplaneColor(Event* ev) -{ - - animated_farplane_color_start = ev->GetVector(1); - animated_farplane_color_end = ev->GetVector(2); - animated_farplane_color_start_z = ev->GetFloat(3); - animated_farplane_color_end_z = ev->GetFloat(4); - - if (animated_farplane_color_start_z > animated_farplane_color_end_z) - { - float end_z = animated_farplane_color_end_z; - animated_farplane_color_end_z = animated_farplane_color_start_z; - animated_farplane_color_start_z = end_z; - - Vector end = animated_farplane_color_end; - animated_farplane_color_end = animated_farplane_color_start; - animated_farplane_color_start = end; - } - - PostEvent(EV_World_UpdateAnimatedFarplane, 0); -} - -void World::SetAnimatedFarplane(Event* ev) -{ - animated_farplane_start = ev->GetFloat(1); - animated_farplane_end = ev->GetFloat(2); - animated_farplane_start_z = ev->GetFloat(3); - animated_farplane_end_z = ev->GetFloat(4); - - if (animated_farplane_start_z > animated_farplane_end_z) - { - float end_z = animated_farplane_end_z; - animated_farplane_end_z = animated_farplane_start_z; - animated_farplane_start_z = end_z; - - float end = animated_farplane_end; - animated_farplane_end = animated_farplane_start; - animated_farplane_start = end; - } - - PostEvent(EV_World_UpdateAnimatedFarplane, 0); -} - -void World::SetAnimatedFarplaneBias(Event* ev) -{ - animated_farplane_bias_start = ev->GetFloat(1); - animated_farplane_bias_end = ev->GetFloat(2); - animated_farplane_bias_start_z = ev->GetFloat(3); - animated_farplane_bias_end_z = ev->GetFloat(4); - - if (animated_farplane_bias_start_z > animated_farplane_bias_end_z) - { - float end_z = animated_farplane_bias_end_z; - animated_farplane_bias_end_z = animated_farplane_bias_start_z; - animated_farplane_bias_start_z = end_z; - - float end = animated_farplane_end; - animated_farplane_bias_end = animated_farplane_bias_start; - animated_farplane_bias_start = end; - } - - PostEvent(EV_World_UpdateAnimatedFarplane, 0); -} - -void World::UpdateAnimatedFarplane(Event* ev) -{ - Entity* player; - - CancelEventsOfType(EV_World_UpdateAnimatedFarplane); - - if (g_gametype->integer != GT_SINGLE_PLAYER) { - return; - } - - PostEvent(EV_World_UpdateAnimatedFarplane, level.frametime); - - player = g_entities[0].entity; - if (!player) { - return; - } - - if (animated_farplane_start_z != 8192) - { - float alpha; - - if (player->origin.z < animated_farplane_start_z) - { - alpha = 0; - } else if (player->origin.z > animated_farplane_end_z) { - alpha = 1; - } else { - alpha = (player->origin.z - animated_farplane_start_z) / (animated_farplane_end_z - animated_farplane_start_z); - } - - farplane_distance = alpha * (animated_farplane_end - animated_farplane_start) + animated_farplane_start; - } - - if (animated_farplane_bias_start_z != 8192) - { - float alpha; - - if (player->origin.z < animated_farplane_bias_start_z) - { - alpha = 0; - } else if (player->origin.z > animated_farplane_bias_end_z) { - alpha = 1; - } else { - alpha = (player->origin.z - animated_farplane_bias_start_z) / (animated_farplane_bias_end_z - animated_farplane_bias_start_z); - } - - farplane_bias = alpha * (animated_farplane_bias_end - animated_farplane_bias_start) + animated_farplane_bias_start; - } - - if (animated_farplane_color_start_z != 8192) - { - float alpha, startAlpha, endAlpha; - Vector start, end; - float dot; - - if (player->origin.z < animated_farplane_color_start_z) - { - alpha = 0; - } else if (player->origin.z > animated_farplane_color_end_z) { - alpha = 1; - } else { - alpha = (player->origin.z - animated_farplane_color_start_z) / (animated_farplane_color_end_z - animated_farplane_color_start_z); - } - - start = animated_farplane_color_start; - end = animated_farplane_color_end; - VectorNormalize(start); - VectorNormalize(end); - - dot = Vector::Dot(start, end); - if (1.f - dot > 0.000001) - { - startAlpha = sin((1.f - alpha) * acos(dot)) / sin(acos(dot)); - endAlpha = sin(acos(dot) * alpha) / sin(acos(dot)); - } - else - { - startAlpha = 1.f - alpha; - endAlpha = alpha; - } - - farplane_color = end * endAlpha + start * startAlpha; - } - - UpdateFog(); -} - -void World::GetRenderTerrain(Event* ev) -{ - ev->AddInteger(render_terrain); -} - -void World::SetRenderTerrain(Event* ev) -{ - render_terrain = ev->GetInteger(1); -} - -void World::GetSkyboxSpeed(Event* ev) -{ - ev->AddInteger(skybox_speed); -} - -void World::SetSkyboxSpeed(Event* ev) -{ - skybox_speed = ev->GetInteger(1); -} - -void World::SetSkyAlpha( Event *ev ) -{ - sky_alpha = ev->GetFloat( 1 ); - UpdateSky(); -} - -void World::SetSkyPortal( Event *ev ) -{ - sky_portal = ev->GetBoolean( 1 ); - UpdateSky(); -} - -void World::SetNextMap( Event *ev ) -{ - level.nextmap = ev->GetString( 1 ); -} - -void World::SetMessage( Event *ev ) -{ - const char *text; - - text = ev->GetString( 1 ); - level.level_name = text; - gi.setConfigstring( CS_MESSAGE, text ); -} - -void World::SetWaterColor( Event *ev ) -{ - level.water_color = ev->GetVector( 1 ); -} - -void World::SetWaterAlpha( Event *ev ) -{ - level.water_alpha = ev->GetFloat( 1 ); -} -void World::SetLavaColor( Event *ev ) -{ - level.lava_color = ev->GetVector( 1 ); -} - -void World::SetLavaAlpha( Event *ev ) -{ - level.lava_alpha = ev->GetFloat( 1 ); -} - -void World::SetNumArenas(Event* ev) -{ - level.m_numArenas = ev->GetInteger(1); -} - -void World::SetAIVisionDistance(Event* ev) -{ - m_fAIVisionDistance = ev->GetFloat(1); -} - -void World::SetNorthYaw( Event *ev ) -{ - m_fNorth = anglemod( ev->GetFloat( 1 ) ); -} - -SimpleEntity *World::GetTarget( str targetname, bool quiet ) -{ - return GetTarget( Director.AddString( targetname ), quiet ); -} - -SimpleEntity *World::GetTarget( const_str targetname, bool quiet ) -{ - ConSimple* list = GetTargetList( targetname ); - - if( list->NumObjects() == 1 ) - { - return list->ObjectAt( 1 ); - } - else if( list->NumObjects() > 1 ) - { - if( !quiet ) { - warning( "World::GetTarget", "There are %d entities with targetname '%s'. You are using a command that requires exactly one.", list->NumObjects(), Director.GetString( targetname ).c_str() ); - } - } - - return NULL; -} - -SimpleEntity *World::GetScriptTarget( str targetname ) -{ - return GetScriptTarget( Director.AddString( targetname ) ); -} - -SimpleEntity *World::GetScriptTarget( const_str targetname ) -{ - ConSimple* list = GetTargetList( targetname ); - - if( list->NumObjects() == 1 ) - { - return list->ObjectAt( 1 ); - } - else if( list->NumObjects() > 1 ) - { - ScriptError( "There are %d entities with targetname '%s'. You are using a command that requires exactly one.", list->NumObjects(), Director.GetString( targetname ).c_str() ); - } - - return NULL; -} - -ConSimple *World::GetExistingTargetList( const str& targetname ) -{ - return GetExistingTargetList( Director.AddString( targetname ) ); -} - -ConSimple *World::GetExistingTargetList( const_str targetname ) -{ - return m_targetList.findKeyValue( targetname ); -} - -ConSimple *World::GetTargetList( str& targetname ) -{ - return GetTargetList( Director.AddString( targetname ) ); -} - -ConSimple *World::GetTargetList( const_str targetname ) -{ - return &m_targetList.addKeyValue( targetname ); -} - -void World::AddTargetEntity( SimpleEntity *ent ) -{ - str targetname = ent->TargetName(); - - if( !targetname.length() ) - { - return; - } - - ConSimple* list = GetTargetList( targetname ); - - list->AddObject( ent ); -} - -void World::AddTargetEntityAt( SimpleEntity *ent, int index ) -{ - str targetname = ent->TargetName(); - - if( !targetname.length() ) - { - return; - } - - ConSimple* list = GetTargetList( targetname ); - - list->AddObjectAt( index, ent ); -} - -int World::GetTargetnameIndex(SimpleEntity* ent) -{ - ConSimple* list = GetTargetList(ent->TargetName()); - - return list->IndexOfObject(ent); -} - -void World::RemoveTargetEntity( SimpleEntity *ent ) -{ - if (world->world_dying) { - return; - } - - const str targetname = ent->TargetName(); - - if( !targetname.length() ) - { - return; - } - - ConSimple* list = GetExistingTargetList( targetname ); - - if( list ) - { - list->RemoveObject( ent ); - - if( list->NumObjects() <= 0 ) - { - m_targetList.remove( Director.AddString( targetname ) ); - } - } -} - -SimpleEntity *World::GetNextEntity( str targetname, SimpleEntity *ent ) -{ - return GetNextEntity( Director.AddString( targetname ), ent ); -} - -SimpleEntity *World::GetNextEntity( const_str targetname, SimpleEntity *ent ) -{ - ConSimple* list = GetTargetList( targetname ); - int index; - - if( ent ) - { - index = list->IndexOfObject( ent ) + 1; - } - else - { - index = 1; - } - - if( list->NumObjects() >= index ) - { - return list->ObjectAt( index ); - } - else - { - return NULL; - } -} - -void World::FreeTargetList() -{ - m_targetList.clear(); -} diff --git a/code/fgame/world.h b/code/fgame/world.h deleted file mode 100644 index 0b4ec600..00000000 --- a/code/fgame/world.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2015 the OpenMoHAA team - -This file is part of OpenMoHAA source code. - -OpenMoHAA source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -OpenMoHAA source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with OpenMoHAA source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -// world.h: Global world information (fog and such). - -#ifndef __WORLD_H__ -#define __WORLD_H__ - -#if defined ( CGAME_DLL ) -#include "../cgame_hook/script/centity.h" -#elif defined ( GAME_DLL ) -#include "entity.h" -#else -#include "glb_local.h" -#include "simpleentity.h" -#endif - -#include "gamescript.h" - -#define WORLD_CINEMATIC 1 - -typedef Container< SafePtr< SimpleEntity > > ConSimple; - -class World : public Entity { - con_set < const_str, ConSimple > m_targetList; // moh could have used con_set instead of TargetList - qboolean world_dying; - -public: - // farplane variables - float farplane_distance; - float farplane_bias; - Vector farplane_color; - qboolean farplane_cull; - float skybox_farplane; - qboolean render_terrain; - float skybox_speed; - float farclip_override; - Vector farplane_color_override; - float animated_farplane_start; - float animated_farplane_end; - float animated_farplane_start_z; - float animated_farplane_end_z; - float animated_farplane_bias_start; - float animated_farplane_bias_end; - float animated_farplane_bias_start_z; - float animated_farplane_bias_end_z; - Vector animated_farplane_color_start; - Vector animated_farplane_color_end; - float animated_farplane_color_start_z; - float animated_farplane_color_end_z; - - // sky variables - float sky_alpha; - qboolean sky_portal; - - // orientation variables - float m_fAIVisionDistance; - float m_fNorth; - -public: - CLASS_PROTOTYPE( World ); - - World(); - - void AddTargetEntity( SimpleEntity *ent ); - void AddTargetEntityAt( SimpleEntity *ent, int index ); - void RemoveTargetEntity( SimpleEntity *ent ); - - void FreeTargetList(); - - SimpleEntity *GetNextEntity( str targetname, SimpleEntity *ent ); - SimpleEntity *GetNextEntity( const_str targetname, SimpleEntity *ent ); - SimpleEntity *GetScriptTarget( str targetname ); - SimpleEntity *GetScriptTarget( const_str targetname ); - SimpleEntity *GetTarget( str targetname, bool quiet ); - SimpleEntity *GetTarget( const_str targetname, bool quiet ); - int GetTargetnameIndex( SimpleEntity *ent ); - - ConSimple *GetExistingTargetList( const str& targetname ); - ConSimple *GetExistingTargetList( const_str targetname ); - ConSimple *GetTargetList( str& targetname ); - ConSimple *GetTargetList( const_str targetname ); - - void SetFarClipOverride(Event* ev); - void SetFarPlaneColorOverride(Event* ev); - void SetSoundtrack( Event *ev ); - void SetGravity( Event *ev ); - void SetNextMap( Event *ev ); - void SetMessage( Event *ev ); - void SetWaterColor( Event *ev ); - void SetWaterAlpha( Event *ev ); - void SetLavaColor( Event *ev ); - void SetLavaAlpha( Event *ev ); - void GetFarPlane_Color(Event* ev); - void SetFarPlane_Color( Event *ev ); - void GetFarPlaneBias(Event* ev); - void SetFarPlaneBias(Event* ev); - void SetFarPlane_Cull( Event *ev ); - void GetSkyboxFarplane( Event *ev ); - void SetSkyboxFarplane(Event* ev); - void SetAnimatedFarplaneColor(Event* ev); - void SetAnimatedFarplane(Event* ev); - void SetAnimatedFarplaneBias(Event* ev); - void UpdateAnimatedFarplane(Event* ev); - void GetRenderTerrain(Event* ev); - void SetRenderTerrain(Event* ev); - void GetSkyboxSpeed(Event* ev); - void SetSkyboxSpeed(Event* ev); - void GetFarPlane( Event *ev ); - void SetFarPlane( Event *ev ); - void SetSkyAlpha( Event *ev ); - void SetSkyPortal( Event *ev ); - void SetNumArenas(Event* ev); - void SetAIVisionDistance(Event* ev); - void SetNorthYaw( Event *ev ); - void UpdateConfigStrings( void ); - void UpdateFog( void ); - void UpdateSky( void ); -}; - -typedef SafePtr< World > WorldPtr; -extern WorldPtr world; - -#endif /* __WORLD_H__ */ diff --git a/code/fgame/worldspawn.cpp b/code/fgame/worldspawn.cpp new file mode 100644 index 00000000..cbe476fc --- /dev/null +++ b/code/fgame/worldspawn.cpp @@ -0,0 +1,1300 @@ +/* +=========================================================================== +Copyright (C) 2015 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// world.cpp : Holds the target list, and general info (fog and such). + +#include "g_phys.h" +#include "worldspawn.h" +#include "level.h" +#include "scriptmaster.h" +#include "scriptexception.h" +#include "player.h" + +#ifdef GAME_DLL +# include "../fgame/soundman.h" +#endif + +WorldPtr world; + +Event EV_World_MapTime +( + "map_time", + EV_DEFAULT, + "i", + "version", + "Internal usage.", + EV_NORMAL +); +Event EV_World_SetSoundtrack +( + "soundtrack", + EV_DEFAULT, + "s", + "MusicFile", + "Set music soundtrack for this level.", + EV_NORMAL +); +Event EV_World_SetGravity +( + "gravity", + EV_DEFAULT, + "f", + "worldGravity", + "Set the gravity for the whole world.", + EV_NORMAL +); +Event EV_World_SetNextMap +( + "nextmap", + EV_DEFAULT, + "s", + "nextMap", + "Set the next map to change to", + EV_NORMAL +); +Event EV_World_SetMessage +( + "message", + EV_DEFAULT, + "s", + "worldMessage", + "Set a message for the world", + EV_NORMAL +); +Event EV_World_SetWaterColor +( + "watercolor", + EV_DEFAULT, + "v", + "waterColor", + "Set the watercolor screen blend", + EV_NORMAL +); +Event EV_World_SetWaterAlpha +( + "wateralpha", + EV_DEFAULT, + "f", + "waterAlpha", + "Set the alpha of the water screen blend", + EV_NORMAL +); +Event EV_World_SetLavaColor +( + "lavacolor", + EV_DEFAULT, + "v", + "lavaColor", + "Set the color of lava screen blend", + EV_NORMAL +); +Event EV_World_SetLavaAlpha +( + "lavaalpha", + EV_DEFAULT, + "f", + "lavaAlpha", + "Set the alpha of lava screen blend", + EV_NORMAL +); +Event EV_World_GetFarPlane_Color +( + "farplane_color", + EV_DEFAULT, + NULL, + NULL, + "Get the color of the far clipping plane fog", + EV_GETTER +); +Event EV_World_SetFarPlane_Color +( + "farplane_color", + EV_DEFAULT, + "v", + "farplaneColor", + "Set the color of the far clipping plane fog", + EV_SETTER +); +Event EV_World_SetFarPlane_Color2 +( + "farplane_color", + EV_DEFAULT, + "v", + "farplaneColor", + "Set the color of the far clipping plane fog", + EV_NORMAL +); +Event EV_World_SetAnimatedFarPlaneColor +( + "animated_farplane_color", + EV_DEFAULT, + "vvff", + "colorStart colorEnd ZStart ZEnd", + "Set the color of the far clipping plane based on a color range and a Z range", + EV_NORMAL +); +Event EV_World_SetFarPlane_Cull( + "farplane_cull", + EV_DEFAULT, + "i", + "farplaneCull", + "Whether or not the far clipping plane should cull things out of the world\n" + "0 - no cull\n" + "1 - normal cull\n" + "2 - cull but no bsp culling" +); +Event EV_World_GetFarPlane +( + "farplane", + EV_DEFAULT, + NULL, + NULL, + "Get the distance of the far clipping plane", + EV_GETTER +); +Event EV_World_SetFarPlane +( + "farplane", + EV_DEFAULT, + "f", + "farplaneDistance", + "Set the distance of the far clipping plane", + EV_SETTER +); +Event EV_World_SetFarClipOverride +( + "farclipoverride", + EV_DEFAULT, + "f", + "farclipoverride", + "Override the min config default for the far clip distance", + EV_NORMAL +); +Event EV_World_SetFarPlaneColorOverride +( + "farplaneclipcolor", + EV_DEFAULT, + "v", + "farplaneclipcolor", + "Override the fog color for the min config", + EV_NORMAL +); +Event EV_World_SetFarPlane2 +( + "farplane", + EV_DEFAULT, + "f", + "farplaneDistance", + "Set the distance of the far clipping plane", + EV_NORMAL +); +Event EV_World_SetAnimatedFarPlane +( + "animated_farplane", + EV_DEFAULT, + "ffff", + "farplaneStart farplaneEnd ZStart ZEnd", + "Set the distance of the far clipping plane based on a farplane range and a Z range", + EV_NORMAL +); +Event EV_World_GetFarPlaneBias +( + "farplane_bias", + EV_DEFAULT, + NULL, + NULL, + "Get the distance bias of the far clipping plane", + EV_GETTER +); +Event EV_World_SetFarPlaneBias +( + "farplane_bias", + EV_DEFAULT, + "f", + "farplaneDistanceBias", + "Set the distance bias of the far clipping plane", + EV_SETTER +); +Event EV_World_SetFarPlaneBias2 +( + "farplane_bias", + EV_DEFAULT, + "f", + "farplaneDistanceBias", + "Set the distance bias of the far clipping plane", + EV_NORMAL +); +Event EV_World_SetAnimatedFarPlaneBias +( + "animated_farplane_bias", + EV_DEFAULT, + "ffff", + "biasStart biasEnd ZStart ZEnd", + "Set the bias of the far clipping plane based on a bias range and a Z range", + EV_NORMAL +); +Event EV_World_UpdateAnimatedFarplane +( + "_update_animated_farplane", + EV_DEFAULT, + NULL, + NULL, + "Updates the farplane if it is being animated.", + EV_NORMAL +); +Event EV_World_GetSkyboxFarPlane +( + "skybox_farplane", + EV_DEFAULT, + NULL, + NULL, + "Get the distance of the skybox far clipping plane", + EV_GETTER +); +Event EV_World_SetSkyboxFarPlane +( + "skybox_farplane", + EV_DEFAULT, + "f", + "farplaneDistance", + "Set the distance of the skybox far clipping plane", + EV_SETTER +); +Event EV_World_SetSkyboxFarPlane2 +( + "skybox_farplane", + EV_DEFAULT, + "f", + "farplaneDistance", + "Set the distance of the skybox far clipping plane", + EV_NORMAL +); +Event EV_World_GetSkyboxSpeed +( + "skybox_speed", + EV_DEFAULT, + NULL, + NULL, + "Get the speed of the skybox", + EV_GETTER +); +Event EV_World_SetSkyboxSpeed +( + "skybox_speed", + EV_DEFAULT, + "f", + "speed", + "Set the speed of the skybox", + EV_SETTER +); +Event EV_World_SetSkyboxSpeed2 +( + "skybox_speed", + EV_DEFAULT, + "f", + "speed", + "Set the speed of the skybox", + EV_NORMAL +); +Event EV_World_SetRenderTerrain +( + "render_terrain", + EV_DEFAULT, + "b", + "render_terrain", + "Set to draw or not draw terrain", + EV_NORMAL +); +Event EV_World_GetRenderTerrain +( + "get_render_terrain", + EV_DEFAULT, + NULL, + NULL, + "Get the render terrain switch", + EV_GETTER +); +Event EV_World_SetAmbientLight +( + "ambientlight", + EV_DEFAULT, + "b", + "ambientLight", + "Set whether or not ambient light should be used", + EV_NORMAL +); +Event EV_World_SetAmbientIntensity +( + "ambient", + EV_DEFAULT, + "f", + "ambientIntensity", + "Set the intensity of the ambient light", + EV_NORMAL +); +Event EV_World_SetSunColor +( + "suncolor", + EV_DEFAULT, + "v", + "sunColor", + "Set the color of the sun", + EV_NORMAL +); +Event EV_World_SetSunLight +( + "sunlight", + EV_DEFAULT, + "b", + "sunlight", + "Set whether or not there should be sunlight", + EV_NORMAL +); +Event EV_World_SetSunDirection +( + "sundirection", + EV_DEFAULT, + "v", + "sunlightDirection", + "Set the direction of the sunlight", + EV_NORMAL +); +Event EV_World_LightmapDensity +( + "lightmapdensity", + EV_DEFAULT, + "f", + "density", + "Set the default lightmap density for all world surfaces", + EV_NORMAL +); +Event EV_World_SunFlareName +( + "sunflarename", + EV_DEFAULT, + "s", + "flarename", + "Set the flare to use for the sunflare", + EV_NORMAL +); +Event EV_World_SunFlareDirection +( + "sunflaredirection", + EV_DEFAULT, + "v", + "angles", + "Set the direction of the sunflare", + EV_NORMAL +); +Event EV_World_SetSkyAlpha +( + "skyalpha", + EV_DEFAULT, + "f", + "newAlphaForPortalSky", + "Set the alpha on the sky", + EV_NORMAL +); +Event EV_World_SetSkyPortal +( + "skyportal", + EV_DEFAULT, + "b", + "newSkyPortalState", + "Whether or not to use the sky portal at all", + EV_NORMAL +); +Event EV_World_SetNumArenas +( + "numarenas", + EV_DEFAULT, + "i", + "numarenas", + "Set the number of arenas in the world", + EV_NORMAL +); +Event EV_World_SetAIVisionDistance +( + "ai_visiondistance", + EV_DEFAULT, + "f", + "vision_distance", + "Sets the default AI Vision Distance", + EV_NORMAL +); +Event EV_World_SetNorthYaw +( + "northyaw", + EV_DEFAULT, + "f", + "yaw", + "Sets the yaw direction that is considered to be north", + EV_NORMAL +); +Event EV_World_SetSunDiffuse +( + "sundiffuse", + EV_DEFAULT, + "f", + "factor", + "Sets the fraction of the sunlight to use for diffuse sun", + EV_NORMAL +); + +Event EV_World_SetSunDiffuseColor +( + "sundiffusecolor", + EV_DEFAULT, + "v", + "diffusecolor", + "Sets an alternate sun color to use for clcing diffuse sun", + EV_NORMAL +); +Event EV_World_Overbright +( + "overbright", + EV_DEFAULT, + "i", + "use", + "When set to non-zero, removes the overbright cutoff of lightmaps ", + EV_NORMAL +); +Event EV_World_VisDerived +( + "vis_derived", + EV_DEFAULT, + "i", + "use", + "whether or not the vis compiler derives additional vis info from the manual vis", + EV_NORMAL +); + +CLASS_DECLARATION(Entity, World, "worldspawn") { + {&EV_World_SetSoundtrack, &World::SetSoundtrack }, + {&EV_World_SetGravity, &World::SetGravity }, + {&EV_World_SetNextMap, &World::SetNextMap }, + {&EV_World_SetMessage, &World::SetMessage }, + {&EV_World_SetWaterColor, &World::SetWaterColor }, + {&EV_World_SetWaterAlpha, &World::SetWaterAlpha }, + {&EV_World_SetLavaColor, &World::SetLavaColor }, + {&EV_World_SetLavaAlpha, &World::SetLavaAlpha }, + {&EV_World_GetFarPlane_Color, &World::GetFarPlane_Color }, + {&EV_World_SetFarPlane_Color, &World::SetFarPlane_Color }, + {&EV_World_SetFarPlane_Color2, &World::SetFarPlane_Color }, + {&EV_World_SetFarPlane_Cull, &World::SetFarPlane_Cull }, + {&EV_World_GetFarPlane, &World::GetFarPlane }, + {&EV_World_SetFarPlane, &World::SetFarPlane }, + {&EV_World_SetFarClipOverride, &World::SetFarClipOverride }, + {&EV_World_SetFarPlaneColorOverride, &World::SetFarPlaneColorOverride}, + {&EV_World_SetFarPlane2, &World::SetFarPlane }, + {&EV_World_GetFarPlaneBias, &World::GetFarPlaneBias }, + {&EV_World_SetFarPlaneBias, &World::SetFarPlaneBias }, + {&EV_World_SetFarPlaneBias2, &World::SetFarPlaneBias }, + {&EV_World_GetSkyboxFarPlane, &World::GetSkyboxFarplane }, + {&EV_World_SetSkyboxFarPlane, &World::SetSkyboxFarplane }, + {&EV_World_SetSkyboxFarPlane2, &World::SetSkyboxFarplane }, + {&EV_World_GetSkyboxSpeed, &World::GetSkyboxSpeed }, + {&EV_World_SetSkyboxSpeed, &World::SetSkyboxSpeed }, + {&EV_World_SetSkyboxSpeed2, &World::SetSkyboxSpeed }, + {&EV_World_GetRenderTerrain, &World::GetRenderTerrain }, + {&EV_World_SetRenderTerrain, &World::SetRenderTerrain }, + {&EV_World_SetSkyAlpha, &World::SetSkyAlpha }, + {&EV_World_SetSkyPortal, &World::SetSkyPortal }, + {&EV_World_SetNorthYaw, &World::SetNorthYaw }, + {&EV_World_SetAmbientLight, NULL }, + {&EV_World_SetAmbientIntensity, NULL }, + {&EV_World_SetSunColor, NULL }, + {&EV_World_SetSunLight, NULL }, + {&EV_World_SetSunDirection, NULL }, + {&EV_World_LightmapDensity, NULL }, + {&EV_World_SunFlareName, NULL }, + {&EV_World_SunFlareDirection, NULL }, + {&EV_World_SetNumArenas, NULL }, + {&EV_World_SetSunDiffuse, NULL }, + {&EV_World_SetSunDiffuseColor, NULL }, + {&EV_World_Overbright, NULL }, + {&EV_World_VisDerived, NULL }, + {&EV_World_SetAIVisionDistance, &World::SetAIVisionDistance }, + {&EV_World_SetNorthYaw, &World::SetNorthYaw }, + {&EV_World_SetAnimatedFarPlaneColor, &World::SetAnimatedFarplaneColor}, + {&EV_World_SetAnimatedFarPlane, &World::SetAnimatedFarplane }, + {&EV_World_SetAnimatedFarPlaneBias, &World::SetAnimatedFarplaneBias }, + {&EV_World_UpdateAnimatedFarplane, &World::UpdateAnimatedFarplane }, + {NULL, NULL } +}; + +World::World() +{ + world = this; + world_dying = qfalse; + + // Anything that modifies configstrings, or spawns things is ignored when loading savegames + if (LoadingSavegame) { + return; + } + + assert(entnum == ENTITYNUM_WORLD); + + setMoveType(MOVETYPE_NONE); + setSolidType(SOLID_BSP); + + // world model is always index 1 + edict->s.modelindex = 1; + model = "*1"; + + UpdateConfigStrings(); + + // clear out the soundtrack from the last level + ChangeSoundtrack(""); + + // set the default gravity + gi.cvar_set("sv_gravity", "800"); + + // set the default farplane parameters + farplane_distance = 0; + farplane_bias = 0.0; + farplane_color = vec_zero; + farplane_cull = qtrue; + skybox_farplane = 0.0; + render_terrain = qtrue; + skybox_speed = 0.0; + farclip_override = 0.f; + farplane_color_override = Vector(-1, -1, -1); + animated_farplane_start = 0.0; + animated_farplane_end = 0.0; + animated_farplane_start_z = 8192.0; + animated_farplane_end_z = 0.0; + animated_farplane_bias_start = 0.0; + animated_farplane_bias_end = 0.0; + animated_farplane_bias_start_z = 8192.0; + animated_farplane_bias_end_z = 0.0; + animated_farplane_color_start = vec_zero; + animated_farplane_color_end = vec_zero; + animated_farplane_color_start_z = 8192.0; + animated_farplane_color_end_z = 0.0; + + UpdateFog(); + + sky_alpha = 1.0f; + sky_portal = qtrue; + UpdateSky(); + + m_fAIVisionDistance = 2048.0f; + + level.cinematic = spawnflags & WORLD_CINEMATIC; + + if (level.cinematic) { + gi.cvar_set("sv_cinematic", "1"); + } else { + gi.cvar_set("sv_cinematic", "0"); + } + + level.nextmap = ""; + level.level_name = level.mapname; + + SoundMan.Load(); + + // Set the color for the blends. + level.water_color = Vector(0, 0, 1); + level.water_alpha = 0.1f; + level.lava_color = Vector(1.0f, 0.3f, 0); + level.lava_alpha = 0.6f; + + // + // set the targetname of the world + // + SetTargetName("world"); + + m_fNorth = 0; +} + +World::~World() +{ + world_dying = false; + FreeTargetList(); +} + +void World::UpdateConfigStrings(void) +{ + // + // make some data visible to connecting client + // + gi.setConfigstring(CS_GAME_VERSION, GAME_VERSION); + gi.setConfigstring(CS_LEVEL_START_TIME, va("%i", level.svsStartTime)); + + // make some data visible to the server + gi.setConfigstring(CS_MESSAGE, level.level_name.c_str()); +}; + +void World::UpdateFog(void) +{ + const char *fogInfoString; + gi.SetFarPlane(farplane_distance); + + if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) { + fogInfoString = + va("%d %.0f %.0f %.0f %.6f %.4f %.4f %.4f %d %.0f %.2f %.2f %.2f", + farplane_cull, + farplane_distance, + farplane_bias, + skybox_farplane, + skybox_speed, + farplane_color.x, + farplane_color.y, + farplane_color.z, + render_terrain, + farclip_override, + farplane_color_override.x, + farplane_color_override.y, + farplane_color_override.z); + } else { + fogInfoString = + va("%d %.0f %.4f %.4f %.4f", + farplane_cull, + farplane_distance, + farplane_color.x, + farplane_color.y, + farplane_color.z); + } + + gi.setConfigstring(CS_FOGINFO, fogInfoString); +} + +void World::SetFarClipOverride(Event *ev) +{ + farclip_override = ev->GetFloat(1); + UpdateFog(); +} + +void World::SetFarPlaneColorOverride(Event *ev) +{ + farplane_color_override = ev->GetVector(1); + UpdateFog(); +} + +void World::UpdateSky(void) +{ + gi.SetSkyPortal(sky_portal); + gi.setConfigstring(CS_SKYINFO, va("%.4f %d", sky_alpha, sky_portal)); +} + +void World::SetSoundtrack(Event *ev) +{ + str text; + + text = ev->GetString(1); + ChangeSoundtrack(text); +} + +void World::SetGravity(Event *ev) +{ + gi.cvar_set("sv_gravity", ev->GetString(1)); +} + +void World::GetFarPlane(Event *ev) +{ + ev->AddFloat(farplane_distance); +} + +void World::SetFarPlane(Event *ev) +{ + animated_farplane_start_z = 8192; + if (animated_farplane_start_z == 8192 && animated_farplane_bias_start_z == 8192 + && animated_farplane_color_start_z == 8192) { + CancelEventsOfType(EV_World_UpdateAnimatedFarplane); + } + + farplane_distance = ev->GetFloat(1); + UpdateFog(); +} + +void World::GetFarPlaneBias(Event *ev) +{ + ev->AddFloat(farplane_bias); +} + +void World::SetFarPlaneBias(Event *ev) +{ + animated_farplane_bias_start_z = 8192; + if (animated_farplane_start_z == 8192 && animated_farplane_bias_start_z == 8192 + && animated_farplane_color_start_z == 8192) { + CancelEventsOfType(EV_World_UpdateAnimatedFarplane); + } + + farplane_bias = ev->GetFloat(1); +} + +void World::GetFarPlane_Color(Event *ev) +{ + ev->AddVector(farplane_color); +} + +void World::SetFarPlane_Color(Event *ev) +{ + animated_farplane_color_start_z = 8192; + if (animated_farplane_start_z == 8192 && animated_farplane_bias_start_z == 8192 + && animated_farplane_color_start_z == 8192) { + CancelEventsOfType(EV_World_UpdateAnimatedFarplane); + } + + farplane_color = ev->GetVector(1); + UpdateFog(); +} + +void World::SetFarPlane_Cull(Event *ev) +{ + farplane_cull = ev->GetBoolean(1); + UpdateFog(); +} + +void World::GetSkyboxFarplane(Event *ev) +{ + ev->AddFloat(skybox_farplane); +} + +void World::SetSkyboxFarplane(Event *ev) +{ + skybox_farplane = ev->GetFloat(1); +} + +void World::SetAnimatedFarplaneColor(Event *ev) +{ + animated_farplane_color_start = ev->GetVector(1); + animated_farplane_color_end = ev->GetVector(2); + animated_farplane_color_start_z = ev->GetFloat(3); + animated_farplane_color_end_z = ev->GetFloat(4); + + if (animated_farplane_color_start_z > animated_farplane_color_end_z) { + float end_z = animated_farplane_color_end_z; + animated_farplane_color_end_z = animated_farplane_color_start_z; + animated_farplane_color_start_z = end_z; + + Vector end = animated_farplane_color_end; + animated_farplane_color_end = animated_farplane_color_start; + animated_farplane_color_start = end; + } + + PostEvent(EV_World_UpdateAnimatedFarplane, 0); +} + +void World::SetAnimatedFarplane(Event *ev) +{ + animated_farplane_start = ev->GetFloat(1); + animated_farplane_end = ev->GetFloat(2); + animated_farplane_start_z = ev->GetFloat(3); + animated_farplane_end_z = ev->GetFloat(4); + + if (animated_farplane_start_z > animated_farplane_end_z) { + float end_z = animated_farplane_end_z; + animated_farplane_end_z = animated_farplane_start_z; + animated_farplane_start_z = end_z; + + float end = animated_farplane_end; + animated_farplane_end = animated_farplane_start; + animated_farplane_start = end; + } + + PostEvent(EV_World_UpdateAnimatedFarplane, 0); +} + +void World::SetAnimatedFarplaneBias(Event *ev) +{ + animated_farplane_bias_start = ev->GetFloat(1); + animated_farplane_bias_end = ev->GetFloat(2); + animated_farplane_bias_start_z = ev->GetFloat(3); + animated_farplane_bias_end_z = ev->GetFloat(4); + + if (animated_farplane_bias_start_z > animated_farplane_bias_end_z) { + float end_z = animated_farplane_bias_end_z; + animated_farplane_bias_end_z = animated_farplane_bias_start_z; + animated_farplane_bias_start_z = end_z; + + float end = animated_farplane_end; + animated_farplane_bias_end = animated_farplane_bias_start; + animated_farplane_bias_start = end; + } + + PostEvent(EV_World_UpdateAnimatedFarplane, 0); +} + +void World::UpdateAnimatedFarplane(Event *ev) +{ + Entity *player; + + CancelEventsOfType(EV_World_UpdateAnimatedFarplane); + + if (g_gametype->integer != GT_SINGLE_PLAYER) { + return; + } + + PostEvent(EV_World_UpdateAnimatedFarplane, level.frametime); + + player = g_entities[0].entity; + if (!player) { + return; + } + + if (animated_farplane_start_z != 8192) { + float alpha; + + if (player->origin.z < animated_farplane_start_z) { + alpha = 0; + } else if (player->origin.z > animated_farplane_end_z) { + alpha = 1; + } else { + alpha = + (player->origin.z - animated_farplane_start_z) / (animated_farplane_end_z - animated_farplane_start_z); + } + + farplane_distance = alpha * (animated_farplane_end - animated_farplane_start) + animated_farplane_start; + } + + if (animated_farplane_bias_start_z != 8192) { + float alpha; + + if (player->origin.z < animated_farplane_bias_start_z) { + alpha = 0; + } else if (player->origin.z > animated_farplane_bias_end_z) { + alpha = 1; + } else { + alpha = (player->origin.z - animated_farplane_bias_start_z) + / (animated_farplane_bias_end_z - animated_farplane_bias_start_z); + } + + farplane_bias = + alpha * (animated_farplane_bias_end - animated_farplane_bias_start) + animated_farplane_bias_start; + } + + if (animated_farplane_color_start_z != 8192) { + float alpha, startAlpha, endAlpha; + Vector start, end; + float dot; + + if (player->origin.z < animated_farplane_color_start_z) { + alpha = 0; + } else if (player->origin.z > animated_farplane_color_end_z) { + alpha = 1; + } else { + alpha = (player->origin.z - animated_farplane_color_start_z) + / (animated_farplane_color_end_z - animated_farplane_color_start_z); + } + + start = animated_farplane_color_start; + end = animated_farplane_color_end; + VectorNormalize(start); + VectorNormalize(end); + + dot = Vector::Dot(start, end); + if (1.f - dot > 0.000001) { + startAlpha = sin((1.f - alpha) * acos(dot)) / sin(acos(dot)); + endAlpha = sin(acos(dot) * alpha) / sin(acos(dot)); + } else { + startAlpha = 1.f - alpha; + endAlpha = alpha; + } + + farplane_color = end * endAlpha + start * startAlpha; + } + + UpdateFog(); +} + +void World::GetRenderTerrain(Event *ev) +{ + ev->AddInteger(render_terrain); +} + +void World::SetRenderTerrain(Event *ev) +{ + render_terrain = ev->GetInteger(1); + UpdateFog(); +} + +void World::GetSkyboxSpeed(Event *ev) +{ + ev->AddFloat(skybox_speed); +} + +void World::SetSkyboxSpeed(Event *ev) +{ + skybox_speed = ev->GetFloat(1); +} + +void World::SetSkyAlpha(Event *ev) +{ + sky_alpha = ev->GetFloat(1); + UpdateSky(); +} + +void World::SetSkyPortal(Event *ev) +{ + sky_portal = ev->GetBoolean(1); + UpdateSky(); +} + +void World::SetNextMap(Event *ev) +{ + level.nextmap = ev->GetString(1); +} + +void World::SetMessage(Event *ev) +{ + str text; + + text = ev->GetString(1); + level.level_name = text; + gi.setConfigstring(CS_MESSAGE, text); +} + +void World::SetWaterColor(Event *ev) +{ + level.water_color = ev->GetVector(1); +} + +void World::SetWaterAlpha(Event *ev) +{ + level.water_alpha = ev->GetFloat(1); +} + +void World::SetLavaColor(Event *ev) +{ + level.lava_color = ev->GetVector(1); +} + +void World::SetLavaAlpha(Event *ev) +{ + level.lava_alpha = ev->GetFloat(1); +} + +void World::SetNumArenas(Event *ev) +{ + level.m_numArenas = ev->GetInteger(1); +} + +void World::SetAIVisionDistance(Event *ev) +{ + m_fAIVisionDistance = ev->GetFloat(1); +} + +void World::SetNorthYaw(Event *ev) +{ + m_fNorth = anglemod(ev->GetFloat(1)); +} + +Listener *World::GetTarget(str targetname, bool quiet) +{ + TargetList *targetList = GetTargetList(targetname); + + if (!targetList) { + return NULL; + } + + if (targetList->list.NumObjects() == 1) { + return targetList->list.ObjectAt(1); + } else if (targetList->list.NumObjects() > 1) { + if (!quiet) { + warning( + "World::GetTarget", + "There are %d entities with targetname '%s'. You are using a command that requires exactly one.", + targetList->list.NumObjects(), + targetname.c_str() + ); + } + } + + return NULL; +} + +Listener *World::GetScriptTarget(str targetname) +{ + TargetList *targetList = GetTargetList(targetname); + + if (!targetList) { + return NULL; + } + + if (targetList->list.NumObjects() == 1) { + return targetList->list.ObjectAt(1); + } else if (targetList->list.NumObjects() > 1) { + ScriptError( + "There are %d entities with targetname '%s'. You are using a command that requires exactly one.", + targetList->list.NumObjects(), + targetname.c_str() + ); + } + + return NULL; +} + +TargetList *World::GetExistingTargetList(const str& targetname) +{ + TargetList *targetList; + int i; + + if (!targetname.length()) { + return NULL; + } + + for (i = m_targetListContainer.NumObjects(); i > 0; i--) { + targetList = m_targetListContainer.ObjectAt(i); + if (targetname == targetList->targetname) { + return targetList; + } + } + + return NULL; +} + +TargetList *World::GetTargetList(str& targetname) +{ + TargetList *targetList; + int i; + + if (!targetname.length()) { + // Fixed in OPM + // Don't create a targetlist for the empty target name + return NULL; + } + + for (i = m_targetListContainer.NumObjects(); i > 0; i--) { + targetList = m_targetListContainer.ObjectAt(i); + if (targetname == targetList->targetname) { + return targetList; + } + } + + targetList = new TargetList(targetname); + m_targetListContainer.AddObject(targetList); + + return targetList; +} + +void World::AddTargetEntity(SimpleEntity *ent) +{ + TargetList *targetList = GetTargetList(ent->TargetName()); + + if (!targetList) { + return; + } + + targetList->AddEntity(ent); +} + +void World::AddTargetEntityAt(SimpleEntity *ent, int index) +{ + TargetList *targetList = GetTargetList(ent->TargetName()); + + if (!targetList || !index) { + return; + } + + targetList->AddEntityAt(ent, index); +} + +int World::GetTargetnameIndex(SimpleEntity *ent) +{ + TargetList *targetList = GetTargetList(ent->TargetName()); + + if (!targetList) { + return 0; + } + + return targetList->GetEntityIndex(ent); +} + +void World::RemoveTargetEntity(SimpleEntity *ent) +{ + if (world->world_dying) { + return; + } + + TargetList *targetList = GetExistingTargetList(ent->TargetName()); + if (!targetList) { + return; + } + + targetList->RemoveEntity(ent); +} + +SimpleEntity *World::GetNextEntity(str targetname, SimpleEntity *ent) +{ + TargetList *targetList = GetExistingTargetList(targetname); + if (!targetList) { + return NULL; + } + + return targetList->GetNextEntity(ent); +} + +void World::FreeTargetList() +{ + int i; + + for (i = 1; i <= m_targetListContainer.NumObjects(); i++) { + delete m_targetListContainer.ObjectAt(i); + } + + m_targetListContainer.FreeObjectList(); +} + +void World::Archive(Archiver& arc) +{ + int num; + int num2; + int i; + TargetList *targetList; + + if (arc.Loading()) { + str targetname; + + arc.ArchiveInteger(&num); + for (i = 1; i <= num; i++) { + arc.ArchiveString(&targetname); + + targetList = new TargetList(targetname); + m_targetListContainer.AddObject(targetList); + + arc.ArchiveObjectPosition((LightClass *)&targetList->list); + arc.ArchiveInteger(&num2); + + targetList->list.Resize(num2); + } + } else { + num = m_targetListContainer.NumObjects(); + arc.ArchiveInteger(&num); + + for (i = 1; i <= num; i++) { + targetList = m_targetListContainer.ObjectAt(i); + + arc.ArchiveString(&targetList->targetname); + arc.ArchiveObjectPosition((LightClass *)&targetList->list); + + num2 = targetList->list.NumObjects(); + arc.ArchiveInteger(&num2); + } + } + + Entity::Archive(arc); + + arc.ArchiveFloat(&farplane_distance); + arc.ArchiveFloat(&farplane_bias); + arc.ArchiveVector(&farplane_color); + arc.ArchiveBoolean(&farplane_cull); + arc.ArchiveFloat(&skybox_farplane); + arc.ArchiveBoolean(&render_terrain); + arc.ArchiveFloat(&skybox_speed); + arc.ArchiveFloat(&sky_alpha); + arc.ArchiveBoolean(&sky_portal); + arc.ArchiveFloat(&m_fAIVisionDistance); + arc.ArchiveFloat(&m_fNorth); + arc.ArchiveFloat(&farclip_override); + arc.ArchiveFloat(&farplane_color_override.x); + arc.ArchiveFloat(&farplane_color_override.y); + arc.ArchiveFloat(&farplane_color_override.z); + arc.ArchiveFloat(&farplane_color.x); + arc.ArchiveFloat(&farplane_color.y); + arc.ArchiveFloat(&farplane_color.z); + arc.ArchiveFloat(&animated_farplane_start); + arc.ArchiveFloat(&animated_farplane_end); + arc.ArchiveFloat(&animated_farplane_start_z); + arc.ArchiveFloat(&animated_farplane_end_z); + arc.ArchiveFloat(&animated_farplane_bias_start); + arc.ArchiveFloat(&animated_farplane_bias_end); + arc.ArchiveFloat(&animated_farplane_bias_start_z); + arc.ArchiveFloat(&animated_farplane_bias_end_z); + arc.ArchiveVector(&animated_farplane_color_start); + arc.ArchiveVector(&animated_farplane_color_end); + arc.ArchiveFloat(&animated_farplane_color_start_z); + arc.ArchiveFloat(&animated_farplane_color_end_z); + if (arc.Loading()) { + UpdateConfigStrings(); + UpdateFog(); + UpdateSky(); + } + UpdateConfigStrings(); +} + +bool WithinFarplaneDistance(const Vector& org) +{ + float distance = world->farplane_distance; + + if (!distance) { + // no farplane + return true; + } + + return org.lengthSquared() < (Square(distance) * Square(0.828f)); +} + +CLASS_DECLARATION(Class, TargetList, NULL) { + {NULL, NULL} +}; + +TargetList::TargetList() {} + +TargetList::TargetList(const str& tname) + : targetname(tname) +{} + +void TargetList::AddEntity(Listener *ent) +{ + list.AddObject(static_cast(ent)); +} + +void TargetList::AddEntityAt(Listener *ent, int i) +{ + list.AddObjectAt(i, static_cast(ent)); +} + +int TargetList::GetEntityIndex(Listener *ent) +{ + return list.IndexOfObject(static_cast(ent)); +} + +void TargetList::RemoveEntity(Listener *ent) +{ + list.RemoveObject(static_cast(ent)); +} + +SimpleEntity *TargetList::GetNextEntity(SimpleEntity *ent) +{ + int index; + + if (ent) { + index = list.IndexOfObject(ent); + } else { + index = 0; + } + + index++; + + for (; index <= list.NumObjects(); index++) { + Listener *objptr; + + objptr = list.ObjectAt(index); + if (objptr->isSubclassOf(SimpleEntity)) { + return static_cast(objptr); + } + } + + return NULL; +} diff --git a/code/fgame/worldspawn.h b/code/fgame/worldspawn.h new file mode 100644 index 00000000..b7ced3c8 --- /dev/null +++ b/code/fgame/worldspawn.h @@ -0,0 +1,197 @@ +/* +=========================================================================== +Copyright (C) 2015 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// world.h: Global world information (fog and such). + +#pragma once + +#if defined(CGAME_DLL) +# include "../cgame_hook/script/centity.h" +#elif defined(GAME_DLL) +# include "entity.h" +#else +# include "glb_local.h" +# include "simpleentity.h" +#endif + +#include "gamescript.h" + +#define WORLD_CINEMATIC 1 + +typedef Container> ConSimple; + +class TargetList : public Class { +public: + CLASS_PROTOTYPE(TargetList); + +public: + ConSimple list; + str targetname; + +public: + TargetList(); + TargetList(const str& tname); + + void AddEntity(Listener* ent); + void AddEntityAt(Listener* ent, int i); + int GetEntityIndex(Listener* ent); + void RemoveEntity(Listener* ent); + SimpleEntity* GetNextEntity(SimpleEntity* ent); +}; + +template<> +class con_set_Entry +{ + friend con_set; + friend con_set_enum; + +private: + con_set_Entry *next; + +public: + const_str key; + ConSimple value; + +public: + void *operator new(size_t size) { return con_set::NewEntry(size); } + + void operator delete(void *ptr) { con_set::DeleteEntry(ptr); } + + void Archive(Archiver& arc) { + int num; + + arc.ArchiveUnsigned(&key); + arc.ArchiveObjectPosition((LightClass*)&value); + + if (arc.Loading()) { + arc.ArchiveInteger(&num); + value.Resize(num); + } else { + num = value.NumObjects(); + arc.ArchiveInteger(&num); + } + } + const_str& GetKey() { return key; } + + void SetKey(const const_str& newKey) { key = newKey; } +}; + +class World : public Entity +{ + Container m_targetListContainer; + qboolean world_dying; + +public: + // farplane variables + float farplane_distance; + float farplane_bias; + Vector farplane_color; + qboolean farplane_cull; + float skybox_farplane; + qboolean render_terrain; + float skybox_speed; + float farclip_override; + Vector farplane_color_override; + float animated_farplane_start; + float animated_farplane_end; + float animated_farplane_start_z; + float animated_farplane_end_z; + float animated_farplane_bias_start; + float animated_farplane_bias_end; + float animated_farplane_bias_start_z; + float animated_farplane_bias_end_z; + Vector animated_farplane_color_start; + Vector animated_farplane_color_end; + float animated_farplane_color_start_z; + float animated_farplane_color_end_z; + + // sky variables + float sky_alpha; + qboolean sky_portal; + + // orientation variables + float m_fAIVisionDistance; + float m_fNorth; + +public: + CLASS_PROTOTYPE(World); + + World(); + ~World(); + + void AddTargetEntity(SimpleEntity *ent); + void AddTargetEntityAt(SimpleEntity *ent, int index); + void RemoveTargetEntity(SimpleEntity *ent); + + void FreeTargetList(); + + SimpleEntity *GetNextEntity(str targetname, SimpleEntity *ent); + Listener *GetScriptTarget(str targetname); + Listener *GetTarget(str targetname, bool quiet); + int GetTargetnameIndex(SimpleEntity *ent); + + TargetList *GetExistingTargetList(const str& targetname); + TargetList *GetTargetList(str& targetname); + + void SetFarClipOverride(Event *ev); + void SetFarPlaneColorOverride(Event *ev); + void SetSoundtrack(Event *ev); + void SetGravity(Event *ev); + void SetNextMap(Event *ev); + void SetMessage(Event *ev); + void SetWaterColor(Event *ev); + void SetWaterAlpha(Event *ev); + void SetLavaColor(Event *ev); + void SetLavaAlpha(Event *ev); + void GetFarPlane_Color(Event *ev); + void SetFarPlane_Color(Event *ev); + void GetFarPlaneBias(Event *ev); + void SetFarPlaneBias(Event *ev); + void SetFarPlane_Cull(Event *ev); + void GetSkyboxFarplane(Event *ev); + void SetSkyboxFarplane(Event *ev); + void SetAnimatedFarplaneColor(Event *ev); + void SetAnimatedFarplane(Event *ev); + void SetAnimatedFarplaneBias(Event *ev); + void UpdateAnimatedFarplane(Event *ev); + void GetRenderTerrain(Event *ev); + void SetRenderTerrain(Event *ev); + void GetSkyboxSpeed(Event *ev); + void SetSkyboxSpeed(Event *ev); + void GetFarPlane(Event *ev); + void SetFarPlane(Event *ev); + void SetSkyAlpha(Event *ev); + void SetSkyPortal(Event *ev); + void SetNumArenas(Event *ev); + void SetAIVisionDistance(Event *ev); + void SetNorthYaw(Event *ev); + void UpdateConfigStrings(void); + void UpdateFog(void); + void UpdateSky(void); + + void Archive(Archiver& arc) override; +}; + +typedef SafePtr WorldPtr; +extern WorldPtr world; + +bool WithinFarplaneDistance(const Vector& org); diff --git a/code/gamespy/CMakeLists.txt b/code/gamespy/CMakeLists.txt index fedbf2b8..db690703 100644 --- a/code/gamespy/CMakeLists.txt +++ b/code/gamespy/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) include_directories("./common") include_directories("./gcdkey") @@ -11,6 +11,7 @@ file(GLOB SRCS_common "./hashtable.c" "./md5c.c" "./gutil.c" + "./gcrypt.c" ) file(GLOB SRCS_gcdkey @@ -101,4 +102,5 @@ foreach(LIB ${DEPENDENT_LIBS}) target_link_libraries(${LIB} PUBLIC gcd_common) endforeach() +target_link_libraries(gcd_key PRIVATE gcd_qr2) target_link_libraries(gcd_qr2 PRIVATE gcd_natneg) diff --git a/code/renderer/tr_swipe.cpp b/code/gamespy/cl_gamespy.c similarity index 66% rename from code/renderer/tr_swipe.cpp rename to code/gamespy/cl_gamespy.c index 08cdbc32..203497ed 100644 --- a/code/renderer/tr_swipe.cpp +++ b/code/gamespy/cl_gamespy.c @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,30 +20,30 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -// tr_swipe.cpp -- swipe rendering +#pragma once -#include "tr_local.h" +#include "cl_gamespy.h" +#include "q_gamespy.h" -void RB_DrawSwipeSurface(surfaceType_t* pswipe) { - // FIXME: unimplemented -} - -void RE_SwipeBegin(float thistime, float life, qhandle_t shader) +unsigned int ServerListGetNumMasters() { - // FIXME: unimplemented + return Com_GetNumMasterEntries(); } -void RE_SwipePoint(vec3_t point1, vec3_t point2, float time) +const char *ServerListGetHost(int index) { - // FIXME: unimplemented + master_entry_t entry; + Com_GetMasterEntry(index, &entry); + + return entry.host; } -void RE_SwipeEnd() +int ServerListGetMsPort(int index) { - // FIXME: unimplemented + master_entry_t entry; + Com_GetMasterEntry(index, &entry); + + return entry.queryport; } -void R_AddSwipeSurfaces() -{ - // FIXME: unimplemented -} +void CL_RestartGamespy_f() {} diff --git a/code/renderer/tr_ghost.h b/code/gamespy/cl_gamespy.h similarity index 88% rename from code/renderer/tr_ghost.h rename to code/gamespy/cl_gamespy.h index 64b139d4..45e38ee4 100644 --- a/code/renderer/tr_ghost.h +++ b/code/gamespy/cl_gamespy.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,4 +20,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +// cl_gamespy.h -- Game-specific client GameSpy code + #pragma once + +void CL_RestartGamespy_f(); diff --git a/code/gamespy/common/gsAssert.c b/code/gamespy/common/gsAssert.c index c4c56861..d8a9b658 100644 --- a/code/gamespy/common/gsAssert.c +++ b/code/gamespy/common/gsAssert.c @@ -96,7 +96,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi // continues rendering void _gsDebugAssert (const char *string) { - printf(string); + printf("%s", string); while(1) { @@ -118,7 +118,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi void _gsDebugAssert (const char *string) { - scePrintf(string); + scePrintf("%s", string); while(1);; } @@ -127,7 +127,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi #elif defined _MACOSX void _gsDebugAssert (const char *string) { - printf(string); + printf("%s", string); while(1) { @@ -139,7 +139,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi #elif defined _LINUX void _gsDebugAssert (const char *string) { - printf(string); + printf("%s", string); while(1) { @@ -170,7 +170,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi void _gsDebugAssert (const char *string) { - printf(string); + printf("%s", string); while(1);; } diff --git a/code/gamespy/common/gsPlatform.h b/code/gamespy/common/gsPlatform.h index a4daf16e..10916417 100644 --- a/code/gamespy/common/gsPlatform.h +++ b/code/gamespy/common/gsPlatform.h @@ -8,7 +8,7 @@ // Windows: _WIN32 // Xbox: _WIN32 + _XBOX // Xbox360: _WIN32 + _XBOX + _X360 -// MacOSX: _MACOSX + _UNIX +// MacOSX: _MACOSX + _UNIX + __APPLE__ // Linux: _LINUX + _UNIX // Nintendo DS: _NITRO // PSP: _PSP @@ -23,7 +23,9 @@ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Set the platform define -#ifdef __mips64 +#if defined (__linux__) || defined(_LINUX) || defined(_MACOSX) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + #define _UNIX +#elif __mips64 #ifndef _PS2 #define _PS2 #endif @@ -34,10 +36,6 @@ #endif #endif -#if defined(_LINUX) || defined(_MACOSX) - #define _UNIX -#endif - #if defined(_XBOX) || defined (_X360) #if _XBOX_VER >= 200 #define _X360 diff --git a/code/gamespy/common/gsPlatformThread.h b/code/gamespy/common/gsPlatformThread.h index 85421ea8..7b5cf779 100644 --- a/code/gamespy/common/gsPlatformThread.h +++ b/code/gamespy/common/gsPlatformThread.h @@ -89,7 +89,11 @@ extern "C" { } GSICriticalSection; typedef void (*GSThreadFunc)(void *arg); -#elif defined(_UNIX) //_LINUX || _MACOSX +#elif defined(_UNIX) // Linux, Mac OS X, openbsd, etc. + #if defined(__OpenBSD__) + #include + #endif + typedef pthread_mutex_t GSICriticalSection; typedef struct { diff --git a/code/gamespy/darray.c b/code/gamespy/darray.c index 3db363e2..688729fb 100644 --- a/code/gamespy/darray.c +++ b/code/gamespy/darray.c @@ -20,30 +20,30 @@ #define DEF_GROWBY 8 #ifdef _NO_NOPORT_H_ - #define gsimalloc malloc - #define gsifree free - #define gsirealloc realloc - #include "common/gsAssert.h" + #define gsimalloc malloc + #define gsifree free + #define gsirealloc realloc + #include "common/gsAssert.h" #else - #include "nonport.h" //for gsimalloc/realloc/free/GS_ASSERT + #include "nonport.h" //for gsimalloc/realloc/free/GS_ASSERT #endif // STRUCTURES struct DArrayImplementation { - int count, capacity; - int elemsize; - int growby; - ArrayElementFreeFn elemfreefn; - void *list; //array of elements + int count, capacity; + int elemsize; + int growby; + ArrayElementFreeFn elemfreefn; + void *list; //array of elements }; // PROTOTYPES static void *mylsearch(const void *key, void *base, int count, int size, - ArrayCompareFn comparator); + ArrayCompareFn comparator); static void *mybsearch(const void *elem, void *base, int num, int elemsize, - ArrayCompareFn comparator, int *found); + ArrayCompareFn comparator, int *found); // FUNCTIONS /* FreeElement @@ -51,8 +51,8 @@ static void *mybsearch(const void *elem, void *base, int num, int elemsize, */ static void FreeElement(DArray array, int n) { - if (array->elemfreefn != NULL) - array->elemfreefn(ArrayNth(array,n)); + if (array->elemfreefn != NULL) + array->elemfreefn(ArrayNth(array,n)); } /* ArrayGrow @@ -60,10 +60,10 @@ static void FreeElement(DArray array, int n) */ static void ArrayGrow(DArray array) { - GS_ASSERT(array->elemsize) // sanity check -mj Oct 31st - array->capacity += array->growby; - array->list = gsirealloc(array->list, (size_t) array->capacity * array->elemsize); - GS_ASSERT(array->list); + GS_ASSERT(array->elemsize) // sanity check -mj Oct 31st + array->capacity += array->growby; + array->list = gsirealloc(array->list, (size_t) array->capacity * array->elemsize); + GS_ASSERT(array->list); } /* SetElement @@ -71,94 +71,94 @@ static void ArrayGrow(DArray array) */ static void SetElement(DArray array, const void *elem, int pos) { - GS_ASSERT(array) // safety check -mj Oct 31st - GS_ASSERT(elem) - GS_ASSERT(array->elemsize) + GS_ASSERT(array) // safety check -mj Oct 31st + GS_ASSERT(elem) + GS_ASSERT(array->elemsize) - memcpy(ArrayNth(array,pos), elem, (size_t)array->elemsize); + memcpy(ArrayNth(array,pos), elem, (size_t)array->elemsize); } DArray ArrayNew(int elemSize, int numElemsToAllocate, ArrayElementFreeFn elemFreeFn) { - DArray array; + DArray array; - array = (DArray) gsimalloc(sizeof(struct DArrayImplementation)); - GS_ASSERT(array); - GS_ASSERT(elemSize); - if (numElemsToAllocate == 0) - numElemsToAllocate = DEF_GROWBY; - array->count = 0; - array->capacity = numElemsToAllocate;; - array->elemsize = elemSize; - array->growby = numElemsToAllocate; - array->elemfreefn = elemFreeFn; - if (array->capacity != 0) - { - array->list = gsimalloc((size_t)array->capacity * array->elemsize); - GS_ASSERT(array->list); - } else - array->list = NULL; + array = (DArray) gsimalloc(sizeof(struct DArrayImplementation)); + GS_ASSERT(array); + GS_ASSERT(elemSize); + if (numElemsToAllocate == 0) + numElemsToAllocate = DEF_GROWBY; + array->count = 0; + array->capacity = numElemsToAllocate;; + array->elemsize = elemSize; + array->growby = numElemsToAllocate; + array->elemfreefn = elemFreeFn; + if (array->capacity != 0) + { + array->list = gsimalloc((size_t)array->capacity * array->elemsize); + GS_ASSERT(array->list); + } else + array->list = NULL; - return array; + return array; } void ArrayFree(DArray array) { - int i; - - GS_ASSERT(array); - for (i = 0; i < array->count; i++) - { - FreeElement(array, i); - } - // mj to do: move these asserts into gsi_free. maybe, depends on whether user overloads them - GS_ASSERT(array->list) - GS_ASSERT(array) - gsifree(array->list); - gsifree(array); + int i; + + GS_ASSERT(array); + for (i = 0; i < array->count; i++) + { + FreeElement(array, i); + } + // mj to do: move these asserts into gsi_free. maybe, depends on whether user overloads them + GS_ASSERT(array->list) + GS_ASSERT(array) + gsifree(array->list); + gsifree(array); } void *ArrayGetDataPtr(DArray array) { - GS_ASSERT(array); - return array->list; + GS_ASSERT(array); + return array->list; } void ArraySetDataPtr(DArray array, void *ptr, int count, int capacity) { - int i; - - GS_ASSERT(array); - if (array->list != NULL) - { - for (i = 0; i < array->count; i++) - { - FreeElement(array, i); - } - gsifree(array->list); - } - array->list = ptr; - array->count = count; - array->capacity = capacity; + int i; + + GS_ASSERT(array); + if (array->list != NULL) + { + for (i = 0; i < array->count; i++) + { + FreeElement(array, i); + } + gsifree(array->list); + } + array->list = ptr; + array->count = count; + array->capacity = capacity; } int ArrayLength(const DArray array) { - GS_ASSERT(array) - return array->count; + GS_ASSERT(array) + return array->count; } void *ArrayNth(DArray array, int n) { - // 2004.Nov.16.JED - modified GS_ASSERT to include "if" to add robustness - GS_ASSERT( (n >= 0) && (n < array->count)); - if( ! ((n >= 0) && (n < array->count)) ) - return NULL; - - return (char *)array->list + array->elemsize*n; + // 2004.Nov.16.JED - modified GS_ASSERT to include "if" to add robustness + GS_ASSERT( (n >= 0) && (n < array->count)); + if( ! ((n >= 0) && (n < array->count)) ) + return NULL; + + return (char *)array->list + array->elemsize*n; } /* ArrayAppend @@ -166,166 +166,166 @@ void *ArrayNth(DArray array, int n) */ void ArrayAppend(DArray array, const void *newElem) { - GS_ASSERT(array); - if(array) - ArrayInsertAt(array, newElem, array->count); + GS_ASSERT(array); + if(array) + ArrayInsertAt(array, newElem, array->count); } void ArrayInsertAt(DArray array, const void *newElem, int n) { - GS_ASSERT (array) - GS_ASSERT ( (n >= 0) && (n <= array->count)); + GS_ASSERT (array) + GS_ASSERT ( (n >= 0) && (n <= array->count)); - if (array->count == array->capacity) - ArrayGrow(array); - array->count++; - if (n < array->count - 1) //if we aren't appending - memmove(ArrayNth(array, n+1), ArrayNth(array,n), - (size_t)(array->count - 1 - n) * array->elemsize); - SetElement(array, newElem, n); + if (array->count == array->capacity) + ArrayGrow(array); + array->count++; + if (n < array->count - 1) //if we aren't appending + memmove(ArrayNth(array, n+1), ArrayNth(array,n), + (size_t)(array->count - 1 - n) * array->elemsize); + SetElement(array, newElem, n); } void ArrayInsertSorted(DArray array, const void *newElem, ArrayCompareFn comparator) { - int n; - void *res; - int found; + int n; + void *res; + int found; - GS_ASSERT (array) - GS_ASSERT (comparator); + GS_ASSERT (array) + GS_ASSERT (comparator); - res=mybsearch(newElem, array->list, array->count, array->elemsize, comparator, &found); - n = (((char *)res - (char *)array->list) / array->elemsize); - ArrayInsertAt(array, newElem, n); + res=mybsearch(newElem, array->list, array->count, array->elemsize, comparator, &found); + n = (((char *)res - (char *)array->list) / array->elemsize); + ArrayInsertAt(array, newElem, n); } void ArrayRemoveAt(DArray array, int n) { - GS_ASSERT (array) - GS_ASSERT( (n >= 0) && (n < array->count)); + GS_ASSERT (array) + GS_ASSERT( (n >= 0) && (n < array->count)); - if (n < array->count - 1) //if not last element - memmove(ArrayNth(array,n),ArrayNth(array,n+1), - (size_t)(array->count - 1 - n) * array->elemsize); - array->count--; + if (n < array->count - 1) //if not last element + memmove(ArrayNth(array,n),ArrayNth(array,n+1), + (size_t)(array->count - 1 - n) * array->elemsize); + array->count--; } void ArrayDeleteAt(DArray array, int n) { - GS_ASSERT (array) - GS_ASSERT ( (n >= 0) && (n < array->count)); + GS_ASSERT (array) + GS_ASSERT ( (n >= 0) && (n < array->count)); - FreeElement(array,n); - ArrayRemoveAt(array, n); + FreeElement(array,n); + ArrayRemoveAt(array, n); } void ArrayReplaceAt(DArray array, const void *newElem, int n) { - GS_ASSERT (array) - GS_ASSERT ( (n >= 0) && (n < array->count)); + GS_ASSERT (array) + GS_ASSERT ( (n >= 0) && (n < array->count)); - FreeElement(array, n); - SetElement(array, newElem,n); + FreeElement(array, n); + SetElement(array, newElem,n); } void ArraySort(DArray array, ArrayCompareFn comparator) { - GS_ASSERT (array) - qsort(array->list, (size_t)array->count, (size_t)array->elemsize, comparator); + GS_ASSERT (array) + qsort(array->list, (size_t)array->count, (size_t)array->elemsize, comparator); } //GS_ASSERT will be raised by ArrayNth if fromindex out of range int ArraySearch(DArray array, const void *key, ArrayCompareFn comparator, int fromIndex, int isSorted) { - void *res; - int found = 1; - if (!array || array->count == 0) - return NOT_FOUND; + void *res; + int found = 1; + if (!array || array->count == 0) + return NOT_FOUND; - if (isSorted) - res=mybsearch(key, ArrayNth(array,fromIndex), - array->count - fromIndex, array->elemsize, comparator, &found); - else - res=mylsearch(key, ArrayNth(array, fromIndex), - array->count - fromIndex, array->elemsize, comparator); - if (res != NULL && found) - return (((char *)res - (char *)array->list) / array->elemsize); - else - return NOT_FOUND; + if (isSorted) + res=mybsearch(key, ArrayNth(array,fromIndex), + array->count - fromIndex, array->elemsize, comparator, &found); + else + res=mylsearch(key, ArrayNth(array, fromIndex), + array->count - fromIndex, array->elemsize, comparator); + if (res != NULL && found) + return (((char *)res - (char *)array->list) / array->elemsize); + else + return NOT_FOUND; } void ArrayMap(DArray array, ArrayMapFn fn, void *clientData) { - int i; + int i; - GS_ASSERT (array) - GS_ASSERT(fn); + GS_ASSERT (array) + GS_ASSERT(fn); - for (i = 0; i < array->count; i++) - fn(ArrayNth(array,i), clientData); - + for (i = 0; i < array->count; i++) + fn(ArrayNth(array,i), clientData); + } void ArrayMapBackwards(DArray array, ArrayMapFn fn, void *clientData) { - int i; + int i; - GS_ASSERT(fn); + GS_ASSERT(fn); - for (i = (array->count - 1) ; i >= 0 ; i--) - fn(ArrayNth(array,i), clientData); - + for (i = (array->count - 1) ; i >= 0 ; i--) + fn(ArrayNth(array,i), clientData); + } void * ArrayMap2(DArray array, ArrayMapFn2 fn, void *clientData) { - int i; - void * pcurr; + int i; + void * pcurr; - GS_ASSERT(fn); - GS_ASSERT(clientData); + GS_ASSERT(fn); + GS_ASSERT(clientData); - for (i = 0; i < array->count; i++) - { - pcurr = ArrayNth(array,i); - if(!fn(pcurr, clientData)) - return pcurr; - } + for (i = 0; i < array->count; i++) + { + pcurr = ArrayNth(array,i); + if(!fn(pcurr, clientData)) + return pcurr; + } - return NULL; + return NULL; } void * ArrayMapBackwards2(DArray array, ArrayMapFn2 fn, void *clientData) { - int i; - void * pcurr; + int i; + void * pcurr; - GS_ASSERT(fn); - GS_ASSERT(clientData); + GS_ASSERT(fn); + GS_ASSERT(clientData); - for (i = (array->count - 1) ; i >= 0 ; i--) - { - pcurr = ArrayNth(array,i); - if(!fn(pcurr, clientData)) - return pcurr; - } + for (i = (array->count - 1) ; i >= 0 ; i--) + { + pcurr = ArrayNth(array,i); + if(!fn(pcurr, clientData)) + return pcurr; + } - return NULL; + return NULL; } void ArrayClear(DArray array) { - int i; + int i; - // This could be more optimal! - ////////////////////////////// - for(i = (ArrayLength(array) - 1) ; i >= 0 ; i--) - ArrayDeleteAt(array, i); + // This could be more optimal! + ////////////////////////////// + for(i = (ArrayLength(array) - 1) ; i >= 0 ; i--) + ArrayDeleteAt(array, i); } /* mylsearch @@ -333,17 +333,17 @@ void ArrayClear(DArray array) * couldn't use lfind */ static void *mylsearch(const void *key, void *base, int count, int size, - ArrayCompareFn comparator) + ArrayCompareFn comparator) { - int i; - GS_ASSERT(key); - GS_ASSERT(base); - for (i = 0; i < count; i++) - { - if (comparator(key, (char *)base + size*i) == 0) - return (char *)base + size*i; - } - return NULL; + int i; + GS_ASSERT(key); + GS_ASSERT(base); + for (i = 0; i < count; i++) + { + if (comparator(key, (char *)base + size*i) == 0) + return (char *)base + size*i; + } + return NULL; } /* mybsearch @@ -351,27 +351,27 @@ static void *mylsearch(const void *key, void *base, int count, int size, */ static void *mybsearch(const void *elem, void *base, int num, int elemsize, ArrayCompareFn comparator, int *found) { - int L, H, I, C; - - GS_ASSERT(elem); - GS_ASSERT(base); - GS_ASSERT(found); + int L, H, I, C; + + GS_ASSERT(elem); + GS_ASSERT(base); + GS_ASSERT(found); - L = 0; - H = num - 1; - *found = 0; - while (L <= H) - { - I = (L + H) >> 1; - C = comparator(((char *)base) + I * elemsize,elem); - if (C == 0) - *found = 1; - if (C < 0) - L = I + 1; - else - { - H = I - 1; - } - } - return ((char *)base) + L * elemsize; + L = 0; + H = num - 1; + *found = 0; + while (L <= H) + { + I = (L + H) >> 1; + C = comparator(((char *)base) + I * elemsize,elem); + if (C == 0) + *found = 1; + if (C < 0) + L = I + 1; + else + { + H = I - 1; + } + } + return ((char *)base) + L * elemsize; } diff --git a/code/gamespy/darray.h b/code/gamespy/darray.h index ad84b13f..29ed76cc 100644 --- a/code/gamespy/darray.h +++ b/code/gamespy/darray.h @@ -43,9 +43,9 @@ typedef struct DArrayImplementation *DArray; * If the two elements are "equal", return 0. */ #if defined(WIN32) - typedef int (__cdecl *ArrayCompareFn)(const void *elem1, const void *elem2); + typedef int (__cdecl *ArrayCompareFn)(const void *elem1, const void *elem2); #else - typedef int (*ArrayCompareFn)(const void *elem1, const void *elem2); + typedef int (*ArrayCompareFn)(const void *elem1, const void *elem2); #endif diff --git a/code/gamespy/gcrypt.c b/code/gamespy/gcrypt.c new file mode 100644 index 00000000..372e239d --- /dev/null +++ b/code/gamespy/gcrypt.c @@ -0,0 +1,223 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "gcrypt.h" +#include "../qcommon/q_platform.h" +#include "../qcommon/q_shared.h" + +static unsigned int rotl32(unsigned int value, unsigned int count) +{ + return (value << count) | (value >> (-count & 31)); +} + +static unsigned int crypt_seek(GCryptInfo *info, unsigned int n1, unsigned int n2) +{ + int part; + int i; + int keyIndex; + int xorKey; + int current; + + current = 0x8000; + xorKey = n1; + keyIndex = 0; + i = 1; + + info->offset = 0; + + while (current > 0) { + xorKey += i; + keyIndex += xorKey; + xorKey += keyIndex; + + if (n2 & current) { + part = rotl32(~xorKey, 24); + xorKey = rotl32(info->key[part & 0xff] ^ part, 24); + part = rotl32(info->key[keyIndex & 0xff] ^ keyIndex, 8); + xorKey ^= info->key[xorKey & 0xff]; + keyIndex = rotl32(info->key[part & 0xff] ^ part, 8); + + i += 1 + i; + } else { + info->msg[info->offset] = xorKey; + info->msg[info->offset + 16] = keyIndex; + info->msg[info->offset + 32] = i; + info->offset++; + + part = rotl32(keyIndex, 24); + keyIndex = rotl32(info->key[part & 0xff] ^ part, 24); + part = rotl32(info->key[xorKey & 0xff] ^ xorKey, 8); + keyIndex ^= info->key[keyIndex & 0xff]; + xorKey = rotl32(info->key[part & 0xff] ^ part, 8); + + i *= 2; + } + + current >>= 1; + } + + info->xorKey = xorKey; + info->keyIndex = keyIndex; + info->i = i; + info->start = n1; + + return keyIndex ^ xorKey; +} + +static void crypt_encrypt(GCryptInfo *info, unsigned int *words, int len) +{ + int part; + unsigned int i; + unsigned int w; + int keyIndex; + int xorKey; + int offset; + + offset = info->offset; + xorKey = info->xorKey; + keyIndex = info->keyIndex; + i = info->i; + + for (w = 0; w < len; w++) { + while (i < 0x10000) { + xorKey += i; + keyIndex += xorKey; + xorKey += keyIndex; + + info->msg[offset] = xorKey; + info->msg[offset + 16] = keyIndex; + info->msg[offset + 32] = i; + offset++; + + part = rotl32(keyIndex, 24); + keyIndex = rotl32(info->key[part & 0xff] ^ part, 24); + part = rotl32(info->key[xorKey & 0xff] ^ xorKey, 8); + keyIndex ^= info->key[keyIndex & 0xff]; + xorKey = rotl32(info->key[part & 0xff] ^ part, 8); + + i *= 2; + } + + words[w] = LittleLong(keyIndex ^ xorKey); + offset--; + if (offset < 0) { + offset = 0; + } + + part = rotl32(~info->msg[offset], 24); + xorKey = rotl32(info->key[part & 0xff] ^ part, 24); + part = rotl32(info->key[info->msg[offset + 16] & 0xff] ^ info->msg[offset + 16], 8); + xorKey ^= info->key[xorKey & 0xff]; + keyIndex = rotl32(info->key[part & 0xff] ^ part, 8); + + i = info->msg[offset + 32] + 1 + info->msg[offset + 32]; + } + + info->offset = offset; + info->xorKey = xorKey; + info->keyIndex = keyIndex; + info->i = i; +} + +void init_crypt_key(unsigned char *src, unsigned int len, GCryptInfo *info) +{ + int index; + int i, j, k; + int tmp; + + info->wordPtr = NULL; + for (k = 0; k < 256; k++) { + info->key[k] = 0; + } + + for (i = 0; i < 4; i++) { + for (k = 0; k < 256; k++) { + info->key[k] = (info->key[k] << 8) + k; + } + + index = i; + + for (j = 0; j < 2; j++) { + for (k = 0; k < 256; k++) { + index = ((info->key[k] & 0xff) + src[k % len] + index) & 0xff; + + tmp = info->key[k]; + info->key[k] = info->key[index]; + info->key[index] = tmp; + } + } + } + + for (k = 0; k < 256; k++) { + info->key[k] ^= k; + } + + crypt_seek(info, 0, 0); +} + +void crypt_docrypt(GCryptInfo *info, unsigned char *out, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (!info->wordPtr || ((char *)info->wordPtr - (char *)info->words) >= (sizeof(info->words) - 1)) { + info->wordPtr = (unsigned char *)info->words; + crypt_encrypt(info, info->words, ARRAY_LEN(info->words)); + } + + out[i] ^= *info->wordPtr; + info->wordPtr++; + } +} + +int enctype2_encoder(unsigned char *secKey, unsigned char *data, int size) +{ + GCryptInfo info = {0}; + int i; + int header_size = 8; + + // move the data and put it after the header + for (i = size - 1; i >= 0; i--) { + data[1 + header_size + i] = data[i]; + } + + // initialize the header + for (i = 0; i < header_size; i++) { + data[i + 1] = 0; + } + + // initialize the crypt key + init_crypt_key(data + 1, header_size, &info); + + for (i = 0; i < 6; i++) { + data[1 + header_size + size + i] = 0; + } + crypt_docrypt(&info, data + 1 + header_size, size + 6); + + for (i = 0; secKey[i]; i++) { + data[i + 1] ^= secKey[i]; + } + + size += 1 + header_size + 6; + *data = header_size ^ 0xec; + return size; +} diff --git a/code/gamespy/gcrypt.h b/code/gamespy/gcrypt.h new file mode 100644 index 00000000..dfe6993c --- /dev/null +++ b/code/gamespy/gcrypt.h @@ -0,0 +1,40 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#pragma once + +typedef struct { + int key[256]; + int msg[48]; + + int offset; + int xorKey; + int keyIndex; + int i; + int start; + + unsigned int words[16]; + unsigned char *wordPtr; +} GCryptInfo; + +void init_crypt_key(unsigned char *src, unsigned int len, GCryptInfo *info); +void crypt_docrypt(GCryptInfo *info, unsigned char *out, int len); diff --git a/code/gamespy/goaceng.h b/code/gamespy/goaceng.h index ab98882a..b278af78 100644 --- a/code/gamespy/goaceng.h +++ b/code/gamespy/goaceng.h @@ -57,7 +57,7 @@ extern "C" { #endif -#define ENGINE_VERSION "1.5" +#define ENGINE_VERSION "3.0" #define SERVER_TIMEOUT 3000 /* GServerList and GServer are the abstracted serverlist and server data types. All access to their internal data structures is done via the functions below */ @@ -74,7 +74,9 @@ idle - no processing or querying underway, ready to being updates listreq - a server list request has been or is being sent listxfer - we are transfering the server list lanlist - we are waiting for replies from servers on the LAN -querying - the servers on the list are being queried */ +querying - the servers on the list are being queried +connecting (added in OPM) - socket is currently connecting to the master server +*/ typedef enum {sl_idle, sl_listxfer, sl_lanlist, sl_querying} GServerListState; /* Comparision types for the ServerListSort function @@ -85,7 +87,7 @@ stricase - assume the values are strings and do a case insensitive compare */ typedef enum {cm_int, cm_float, cm_strcase, cm_stricase} GCompareMode; -typedef enum {qt_basic, qt_info, qt_rules, qt_players, qt_info_rules, qt_status} GQueryType; +typedef enum {qt_basic, qt_info, qt_rules, qt_players, qt_info_rules, qt_status, qt_grouprooms, qt_masterinfo} GQueryType; /* Messages that are passed to the ListCallBackFn */ #define LIST_STATECHANGED 1 // ServerListState changed, no parameters diff --git a/code/gamespy/gserver.c b/code/gamespy/gserver.c index 7a300558..13571064 100644 --- a/code/gamespy/gserver.c +++ b/code/gamespy/gserver.c @@ -13,17 +13,17 @@ Fax(714)549-0757 ****** Updated 10-15-99 (BGW) - Modified ServerParseKeyVals to actually parse and store empty - values for keys (i.e. "\delete\\" adds key="delete" and value="") + Modified ServerParseKeyVals to actually parse and store empty + values for keys (i.e. "\delete\\" adds key="delete" and value="") Updated 6-17-99 (DDW) - Added new tokenize function to handle empty values for keys + Added new tokenize function to handle empty values for keys - + *******/ #if defined(applec) || defined(THINK_C) || defined(__MWERKS__) && !defined(__KATANA__) - #include "::nonport.h" + #include "::nonport.h" #else - #include "../nonport.h" + #include "../nonport.h" #endif #include "goaceng.h" #include "gserver.h" @@ -36,121 +36,177 @@ Updated 6-17-99 (DDW) static int KeyValHashKeyP(const void *elem, int numbuckets); static int KeyValCompareKeyP(const void *entry1, const void *entry2); +static char *mytok(char *instr, char delim); +static char *LookupKey(GServer server, char *k); void ServerFree(void *elem) { - //free a server! - GServer server = *(GServer *)elem; - - TableFree(server->keyvals); - free(server); + //free a server! + GServer server = *(GServer *)elem; + + TableFree(server->keyvals); + free(server); +} + +static void ServerSetAddressFromString (GServer server, char *address) +{ + char *cpos; + + cpos = strchr(address, ':'); + if (!cpos) { + return; + } + + *cpos = 0; + server->ip = inet_addr(address); + server->port = atoi(cpos + 1); +} + +GServer ServerNewData(char **fieldlist, int fieldcount, char *serverdata, GQueryType qtype, HashTable keylist) +{ + GServer server; + char *k; + char *v; + int curfield; + GKeyValuePair kvpair; + + curfield = 0; + server = (GServer)ServerNew(0, 0, qtype, keylist); + v = mytok(serverdata + 1, '\\'); + + while (curfield < fieldcount) { + k = fieldlist[curfield]; + if (!v) { + v = ""; + } + + if (!strcmp(k, "ip")) { + ServerSetAddressFromString(server, v); + } else if (qtype == qt_grouprooms && !strcmp(k, "other")) { + for (char *p = v; *p; ++p) { + if (*p == 1) { + *p = '\\'; + } + } + ServerParseKeyVals(server, v); + } else { + kvpair.key = (char *)LookupKey(server, k); + kvpair.value = (char *)LookupKey(server, v); + TableEnter(server->keyvals, &kvpair); + } + if (++curfield < fieldcount) { + v = mytok(0, '\\'); + } + } + + return server; } GServer ServerNew(unsigned long ip, unsigned short port, GQueryType qtype, HashTable keylist) { - GServer server; - int nBuckets, nChains; + GServer server; + int nBuckets, nChains; - server = malloc(sizeof(struct GServerImplementation)); - server->ip = ip; - server->port = port; - server->ping = 9999; - server->querytype = qtype; - /* optimize the number of buckets / chains based on query type */ - switch (qtype) - { - case qt_basic: - nBuckets = 4; - nChains = 2; - break; - case qt_info: - nBuckets = 6; - nChains = 2; - break; - case qt_players: - case qt_rules: - nBuckets = 8; - nChains = 2; - break; - case qt_info_rules: - case qt_status: - default: - nBuckets = 8; - nChains= 4; - break; - } - server->keyvals = TableNew2(sizeof(GKeyValuePair),nBuckets,nChains, KeyValHashKeyP, KeyValCompareKeyP, NULL); - server->keylist = keylist; - return server; + server = malloc(sizeof(struct GServerImplementation)); + server->ip = ip; + server->port = port; + server->ping = 9999; + server->querytype = qtype; + /* optimize the number of buckets / chains based on query type */ + switch (qtype) + { + case qt_basic: + nBuckets = 4; + nChains = 2; + break; + case qt_info: + nBuckets = 6; + nChains = 2; + break; + case qt_players: + case qt_rules: + nBuckets = 8; + nChains = 2; + break; + case qt_info_rules: + case qt_status: + default: + nBuckets = 8; + nChains= 4; + break; + } + server->keyvals = TableNew2(sizeof(GKeyValuePair),nBuckets,nChains, KeyValHashKeyP, KeyValCompareKeyP, NULL); + server->keylist = keylist; + return server; } static char *mytok(char *instr, char delim) { - char *result; - static char *thestr; + char *result; + static char *thestr; - if (instr) - thestr = instr; - result=thestr; - while (*thestr && *thestr != delim) - { - thestr++; - } - if (thestr == result) - result = NULL; - if (*thestr) //not the null term - *thestr++ = '\0'; - return result; + if (instr) + thestr = instr; + result=thestr; + while (*thestr && *thestr != delim) + { + thestr++; + } + if (thestr == result) + result = NULL; + if (*thestr) //not the null term + *thestr++ = '\0'; + return result; } static int CheckValidKey(char *key) { - const char *InvalidKeys[]={"queryid","final"}; - int i; - for (i = 0; i < sizeof(InvalidKeys)/sizeof(InvalidKeys[0]); i++) - { - if (strcmp(key,InvalidKeys[i]) == 0) - return 0; - } - return 1; + const char *InvalidKeys[]={"queryid","final"}; + int i; + for (i = 0; i < sizeof(InvalidKeys)/sizeof(InvalidKeys[0]); i++) + { + if (strcmp(key,InvalidKeys[i]) == 0) + return 0; + } + return 1; } static char *LookupKey(GServer server, char *k) { - char **keyindex; + char **keyindex; - keyindex = (char **)TableLookup(server->keylist,&k); - if (keyindex != NULL) - return *keyindex; - k = strdup(k); - TableEnter(server->keylist,&k); - return k; + keyindex = (char **)TableLookup(server->keylist,&k); + if (keyindex != NULL) + return *keyindex; + k = strdup(k); + TableEnter(server->keylist,&k); + return k; } void ServerParseKeyVals(GServer server, char *keyvals) { - char *k, *v; - GKeyValuePair kvpair; + char *k, *v; + GKeyValuePair kvpair; - k = mytok(++keyvals,'\\'); //skip over starting backslash - while (k != NULL) - { - v = mytok(NULL,'\\'); - if (v == NULL) - v = ""; - if (CheckValidKey(k)) - { - kvpair.key = LookupKey(server, k); - kvpair.value = LookupKey(server, v); - TableEnter(server->keyvals, &kvpair); - } - k = mytok(NULL,'\\'); + k = mytok(++keyvals,'\\'); //skip over starting backslash + while (k != NULL) + { + v = mytok(NULL,'\\'); + if (v == NULL) + v = ""; + if (CheckValidKey(k)) + { + kvpair.key = LookupKey(server, k); + kvpair.value = LookupKey(server, v); + TableEnter(server->keyvals, &kvpair); + } + k = mytok(NULL,'\\'); - } + } } @@ -159,7 +215,7 @@ void ServerParseKeyVals(GServer server, char *keyvals) Returns the ping for the specified server. */ int ServerGetPing(GServer server) { - return server->ping; + return server->ping; } /* ServerGetAddress @@ -167,7 +223,7 @@ int ServerGetPing(GServer server) Returns the string, dotted IP address for the specified server */ char *ServerGetAddress(GServer server) { - return (char *)inet_ntoa(*(struct in_addr*)&server->ip); + return (char *)inet_ntoa(*(struct in_addr*)&server->ip); } /* ServerGetInetAddress @@ -175,7 +231,7 @@ char *ServerGetAddress(GServer server) Returns the IP address for the specified server */ unsigned int ServerGetInetAddress(GServer server) { - return server->ip; + return server->ip; } @@ -184,18 +240,18 @@ unsigned int ServerGetInetAddress(GServer server) Returns the "query" port for the specified server. */ int ServerGetQueryPort(GServer server) { - return server->port; + return server->port; } static GKeyValuePair *ServerRuleLookup(GServer server, char *key) { - GKeyValuePair kvp; - char **keyindex; - keyindex = (char **)TableLookup(server->keylist, &key); - if (keyindex == NULL) - return NULL; //otherwise, the keyindex->keyindex is valid, so use it to lookup - kvp.key = *keyindex; - return (GKeyValuePair *)TableLookup(server->keyvals, &kvp); + GKeyValuePair kvp; + char **keyindex; + keyindex = (char **)TableLookup(server->keylist, &key); + if (keyindex == NULL) + return NULL; //otherwise, the keyindex->keyindex is valid, so use it to lookup + kvp.key = *keyindex; + return (GKeyValuePair *)TableLookup(server->keyvals, &kvp); } /* ServerGet[]Value @@ -203,60 +259,60 @@ static GKeyValuePair *ServerRuleLookup(GServer server, char *key) Returns the value for the specified key. */ char *ServerGetStringValue(GServer server, char *key, char *sdefault) { - GKeyValuePair *kv; + GKeyValuePair *kv; - if (strcmp(key,"hostaddr") == 0) //ooh! they want the hostaddr! - return ServerGetAddress(server); - kv = ServerRuleLookup(server,key); - if (!kv) - return sdefault; - return kv->value; + if (strcmp(key,"hostaddr") == 0) //ooh! they want the hostaddr! + return ServerGetAddress(server); + kv = ServerRuleLookup(server,key); + if (!kv) + return sdefault; + return kv->value; } int ServerGetIntValue(GServer server, char *key, int idefault) { - GKeyValuePair *kv; + GKeyValuePair *kv; - if (strcmp(key,"ping") == 0) //ooh! they want the ping! - return ServerGetPing(server); - kv = ServerRuleLookup(server,key); - if (!kv) - return idefault; - return atoi(kv->value); + if (strcmp(key,"ping") == 0) //ooh! they want the ping! + return ServerGetPing(server); + kv = ServerRuleLookup(server,key); + if (!kv) + return idefault; + return atoi(kv->value); } double ServerGetFloatValue(GServer server, char *key, double fdefault) { - GKeyValuePair *kv; + GKeyValuePair *kv; - kv = ServerRuleLookup(server,key); - if (!kv) - return fdefault; - return atof(kv->value); + kv = ServerRuleLookup(server,key); + if (!kv) + return fdefault; + return atof(kv->value); } char *ServerGetPlayerStringValue(GServer server, int playernum, char *key, char *sdefault) { - char newkey[32]; - - sprintf(newkey,"%s_%d",key,playernum); - return ServerGetStringValue(server, newkey, sdefault); + char newkey[32]; + + sprintf(newkey,"%s_%d",key,playernum); + return ServerGetStringValue(server, newkey, sdefault); } int ServerGetPlayerIntValue(GServer server, int playernum, char *key, int idefault) { - char newkey[32]; - - sprintf(newkey,"%s_%d",key,playernum); - return ServerGetIntValue(server, newkey, idefault); + char newkey[32]; + + sprintf(newkey,"%s_%d",key,playernum); + return ServerGetIntValue(server, newkey, idefault); } double ServerGetPlayerFloatValue(GServer server, int playernum, char *key, double fdefault) { - char newkey[32]; - - sprintf(newkey,"%s_%d",key,playernum); - return ServerGetFloatValue(server, newkey, fdefault); + char newkey[32]; + + sprintf(newkey,"%s_%d",key,playernum); + return ServerGetFloatValue(server, newkey, fdefault); } @@ -268,20 +324,20 @@ key/value. The user-defined instance data will be passed to the KeyFn callback * static void KeyMapF(void *elem, void *clientData) { - GKeyValuePair *kv = (GKeyValuePair *)elem; - GEnumData *ped = (GEnumData *)clientData; - ped->EnumFn(kv->key, kv->value, ped->instance); + GKeyValuePair *kv = (GKeyValuePair *)elem; + GEnumData *ped = (GEnumData *)clientData; + ped->EnumFn(kv->key, kv->value, ped->instance); } void ServerEnumKeys(GServer server, KeyEnumFn KeyFn, void *instance) { - GEnumData ed; + GEnumData ed; - ed.EnumFn = KeyFn; - ed.instance = instance; - ed.keylist = server->keylist; - TableMap(server->keyvals, KeyMapF, &ed); + ed.EnumFn = KeyFn; + ed.instance = instance; + ed.keylist = server->keylist; + TableMap(server->keyvals, KeyMapF, &ed); } @@ -293,21 +349,21 @@ void ServerEnumKeys(GServer server, KeyEnumFn KeyFn, void *instance) #define MULTIPLIER -1664117991 static int StringHash(char *s, int numbuckets) { - unsigned long hashcode = 0; - while (*s != 0) - hashcode = hashcode * MULTIPLIER + tolower(*s++); + unsigned long hashcode = 0; + while (*s != 0) + hashcode = hashcode * MULTIPLIER + tolower(*s++); return (hashcode % numbuckets); } int GStringHash(const void *elem, int numbuckets) { - return StringHash(*(char **)elem, numbuckets); + return StringHash(*(char **)elem, numbuckets); } static int KeyValHashKeyP(const void *elem, int numbuckets) { - return StringHash(((GKeyValuePair *)elem)->key, numbuckets); + return StringHash(((GKeyValuePair *)elem)->key, numbuckets); } @@ -328,12 +384,12 @@ int GCaseInsensitiveCompare(const void *entry1, const void *entry2) */ static int KeyValCompareKeyP(const void *entry1, const void *entry2) { - return ((GKeyValuePair *)entry1)->key - ((GKeyValuePair *)entry2)->key; + return ((GKeyValuePair *)entry1)->key - ((GKeyValuePair *)entry2)->key; } void GStringFree(void *elem) { - free(*(char **)elem); + free(*(char **)elem); } /* keyval @@ -341,8 +397,8 @@ void GStringFree(void *elem) * static int KeyValCompareKeyA(const void *entry1, const void *entry2) { - return CaseInsensitiveCompare(&((GKeyValuePair *)entry1)->key, - &((GKeyValuePair *)entry2)->key); + return CaseInsensitiveCompare(&((GKeyValuePair *)entry1)->key, + &((GKeyValuePair *)entry2)->key); } */ \ No newline at end of file diff --git a/code/gamespy/gserver.h b/code/gamespy/gserver.h index a62822fd..b7b9dcf6 100644 --- a/code/gamespy/gserver.h +++ b/code/gamespy/gserver.h @@ -27,41 +27,42 @@ extern "C" { #endif #if defined(applec) || defined(THINK_C) || defined(__MWERKS__) && !defined(__KATANA__) - #include "::hashtable.h" + #include "::hashtable.h" #else - #include "../hashtable.h" + #include "../hashtable.h" #endif struct GServerImplementation { - unsigned long ip; - unsigned short port; - short ping; - GQueryType querytype; - HashTable keyvals; - HashTable keylist; + unsigned long ip; + unsigned short port; + short ping; + GQueryType querytype; + HashTable keyvals; + HashTable keylist; }; typedef struct { - char *key; - char *value; + char *key; + char *value; } GKeyValuePair; /* typedef struct { - char *key, *value; + char *key, *value; } GKeyValuePair; */ typedef struct { - KeyEnumFn EnumFn; - void *instance; - HashTable keylist; + KeyEnumFn EnumFn; + void *instance; + HashTable keylist; } GEnumData; void ServerFree(void *elem); +GServer ServerNewData(char **fieldlist, int fieldcount, char *serverdata, GQueryType qtype, HashTable keylist); GServer ServerNew(unsigned long ip, unsigned short port, GQueryType qtype, HashTable keylist); void ServerParseKeyVals(GServer server, char *keyvals); int GStringHash(const void *elem, int numbuckets); diff --git a/code/gamespy/gserverlist.c b/code/gamespy/gserverlist.c index 378c3eac..fefd9f31 100644 --- a/code/gamespy/gserverlist.c +++ b/code/gamespy/gserverlist.c @@ -19,19 +19,37 @@ Fax(714)549-0757 for this SDK. It also has a change history for the SDK. ******/ + +/** + * The following modifications were made: + * + * 1) Non-blocking server list sockets. List requests are asynchronous and won't block the game. The only blocking request could be due to DNS resolution. + * 2) Server list sockets will timeout after 10 seconds of no reply. + * 3) Parallel server list requests. + * 3.1) A pool of sockets is initially created + * 3.2) The server list connects idling sockets to available masters, afterwards the server list state is set to `sl_listxfer`. + * 3.3) The server list sends the list request to connected masters, and receives the data for each. + * 3.4) When finished fetching 1 master (got `\final`), the server list state transitions to `sl_querying`. + * 3.5) The server list queries all fetched servers. It can still continue fetching list from currently connected masters + * but it will not connect to other masters while servers are being queried. It won't be sending more queries if remaining masters replied in under 500 ms. + * 3.6) When finished querying all fetched servers, the server list restarts from 3.2 and queries next masters. + * + * The idea here is to ensure the redundancy of the server list between multiple masters even if the results are combined. + * Optionally for best results, the game should return a list of masters from the same community. + */ #include "goaceng.h" #include "gserver.h" #if defined(applec) || defined(THINK_C) || defined(__MWERKS__) && !defined(__KATANA__) - #include "::nonport.h" + #include "::nonport.h" #else - #include "../nonport.h" + #include "../nonport.h" #endif #ifdef _MACOS - #include "::darray.h" - #include "::hashtable.h" + #include "::darray.h" + #include "::hashtable.h" #else - #include "../darray.h" - #include "../hashtable.h" + #include "../darray.h" + #include "../hashtable.h" #endif #include "common/gsPlatformSocket.h" #include "gutil.h" @@ -45,10 +63,24 @@ Fax(714)549-0757 #include #include -#define MSHOST MASTER_SERVER_HOST -#define MSPORT 28900 +// Added in 2.0 +#include "gcrypt.h" + +/** + * @brief Custom function used to return the master host, based on game settings + * + * @return const char* The master host + */ +extern unsigned int ServerListGetNumMasters(); +extern const char *ServerListGetHost(int index); +extern int ServerListGetMsPort(int index); + +//#define MSHOST ServerListGetHost(0) +//#define MSPORT ServerListGetMsPort(0) #define SERVER_GROWBY 64 #define LAN_SEARCH_TIME 3000 //3 sec +#define SERVER_QUERY_MAX_PAUSE 500 +#define INTERNET_SEARCH_TIME 10000 //10 sec #define LIST_NUMKEYBUCKETS 500 #define LIST_NUMKEYCHAINS 4 @@ -60,33 +92,58 @@ extern "C" { //todo: check state changes on error typedef struct { - SOCKET s; - GServer currentserver; - unsigned long starttime; - struct sockaddr_in saddr; + SOCKET s; + GServer currentserver; + unsigned long starttime; + struct sockaddr_in saddr; } UpdateInfo; +typedef enum { pi_fieldcount, pi_fields, pi_servers } GParseInfoState; +typedef enum { ls_none, ls_connecting, ls_connected } GListSocketState; +typedef struct GServerListSocketImplementation +{ + SOCKET s; + GListSocketState socketstate; + char data[2048]; + int oldlen; + gsi_time lastreplytime; + GCryptInfo cryptinfo; +} *GServerListSocket; struct GServerListImplementation { - GServerListState state; - DArray servers; - UpdateInfo *updatelist; //dynamic array of updateinfos - char gamename[32]; - char seckey[32]; - char enginename[32]; - int maxupdates; - int nextupdate; - int abortupdate; - ListCallBackFn CallBackFn; - void *instance; - char *sortkey; - gbool sortascending; - SOCKET slsocket; - unsigned long lanstarttime; - GQueryType querytype; - HashTable keylist; + GServerListState state; + DArray servers; + UpdateInfo *updatelist; //dynamic array of updateinfos + char gamename[32]; + char seckey[32]; + char enginename[32]; + char filter[256]; + int maxupdates; + int nextupdate; + int abortupdate; + ListCallBackFn CallBackFn; + void *instance; + char *sortkey; + gbool sortascending; + GServerListSocket slsockets; + int numslsockets; + int startslindex; + gsi_time lastsltime; + unsigned long lanstarttime; + GQueryType querytype; + HashTable keylist; + + // Added in 2.0 + int numservers; + // Added in 2.0 + //GCryptInfo cryptinfo; + // Added in OPM + int encryptdata; + gbool async; + + GParseInfoState pistate; }; GServerList g_sortserverlist; //global serverlist for sorting info!! @@ -94,39 +151,57 @@ GServerList g_sortserverlist; //global serverlist for sorting info!! /* these correspond to the qt_ constants */ #define NUM_QUERYTYPES 6 const char *querystrings[NUM_QUERYTYPES] = {"\\basic\\","\\info\\","\\rules\\", - "\\players\\","\\info\\\\rules\\","\\status\\"}; + "\\players\\","\\info\\\\rules\\","\\status\\"}; const int querylengths[NUM_QUERYTYPES] = {7,6,7,9,13,8}; static void KeyValFree(void *elem); static int KeyValCompareKeyA(const void *entry1, const void *entry2); static int KeyValHashKeyA(const void *elem, int numbuckets); - +static gbool ServerListHasFinishedFetchingList(GServerList serverlist); /* ServerListNew ---------------- Creates and returns a new (empty) GServerList. */ GServerList ServerListNew(const char *gamename, const char *enginename, const char *seckey, int maxconcupdates, void *CallBackFn, int CallBackFnType, void *instance) { - GServerList list; + GServerList list; - list = (GServerList) malloc(sizeof(struct GServerListImplementation)); - assert(list != NULL); - list->state = sl_idle; - list->servers = ArrayNew(sizeof(GServer), SERVER_GROWBY, ServerFree); - list->keylist = TableNew2(sizeof(char *),LIST_NUMKEYBUCKETS,LIST_NUMKEYCHAINS,GStringHash, GCaseInsensitiveCompare, GStringFree); - list->maxupdates = maxconcupdates; - list->updatelist = malloc(maxconcupdates * sizeof(UpdateInfo)); - memset(list->updatelist, 0, maxconcupdates * sizeof(UpdateInfo)); - assert(list->updatelist != NULL); - strcpy(list->gamename, gamename); - strcpy(list->seckey, seckey); - strcpy(list->enginename, enginename); - list->CallBackFn = CallBackFn; - assert(CallBackFn != NULL); - list->instance = instance; - list->sortkey = ""; - SocketStartUp(); - return list; + list = (GServerList) malloc(sizeof(struct GServerListImplementation)); + assert(list != NULL); + list->state = sl_idle; + list->servers = ArrayNew(sizeof(GServer), SERVER_GROWBY, ServerFree); + list->keylist = TableNew2(sizeof(char *),LIST_NUMKEYBUCKETS,LIST_NUMKEYCHAINS,GStringHash, GCaseInsensitiveCompare, GStringFree); + list->maxupdates = maxconcupdates; + list->updatelist = malloc(maxconcupdates * sizeof(UpdateInfo)); + memset(list->updatelist, 0, maxconcupdates * sizeof(UpdateInfo)); + assert(list->updatelist != NULL); + strcpy(list->gamename, gamename); + strcpy(list->seckey, seckey); + strcpy(list->enginename, enginename); + list->CallBackFn = CallBackFn; + assert(CallBackFn != NULL); + list->instance = instance; + list->sortkey = ""; + // Added in 2.0 + list->numservers = 0; + // Added in OPM + list->encryptdata = 1; + list->async = 0; + + list->numslsockets = maxconcupdates / 4; + if (list->numslsockets < 1) { + list->numslsockets = 1; + } else if (list->numslsockets > 4) { + // Above 4 seems too much + list->numslsockets = 4; + } + list->slsockets = (GServerListSocket)malloc(sizeof(struct GServerListSocketImplementation) * list->numslsockets); + memset(list->slsockets, 0, sizeof(struct GServerListSocketImplementation) * list->numslsockets); + list->startslindex = 0; + list->lastsltime = current_time(); + + SocketStartUp(); + return list; } /* ServerListFree @@ -134,33 +209,34 @@ GServerList ServerListNew(const char *gamename, const char *enginename, const ch Free a GServerList and all internal sturctures and servers */ void ServerListFree(GServerList serverlist) { - ArrayFree(serverlist->servers); - TableFree(serverlist->keylist); - free(serverlist->updatelist); + ArrayFree(serverlist->servers); + TableFree(serverlist->keylist); + free(serverlist->updatelist); + free(serverlist->slsockets); - free(serverlist); - SocketShutDown(); + free(serverlist); + SocketShutDown(); } //create update sockets and init structures static GError InitUpdateList(GServerList serverlist) { - int i; + int i; - for (i = 0 ; i < serverlist->maxupdates ; i++) - { - serverlist->updatelist[i].s = socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); - if (serverlist->updatelist[i].s == INVALID_SOCKET) - { //ran out of sockets, just cap maxupdates here, unless we don't have any - if (i == 0) - return GE_NOSOCKET; - serverlist->maxupdates = i; - return 0; - } - serverlist->updatelist[i].currentserver = NULL; - serverlist->updatelist[i].starttime = 0; - } - return 0; + for (i = 0 ; i < serverlist->maxupdates ; i++) + { + serverlist->updatelist[i].s = socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); + if (serverlist->updatelist[i].s == INVALID_SOCKET) + { //ran out of sockets, just cap maxupdates here, unless we don't have any + if (i == 0) + return GE_NOSOCKET; + serverlist->maxupdates = i; + return 0; + } + serverlist->updatelist[i].currentserver = NULL; + serverlist->updatelist[i].starttime = 0; + } + return 0; } @@ -168,61 +244,105 @@ static GError InitUpdateList(GServerList serverlist) //free update sockets static GError FreeUpdateList(GServerList serverlist) { - int i; - for (i = 0 ; i < serverlist->maxupdates ; i++) - { - closesocket(serverlist->updatelist[i].s); - } - return 0; + int i; + for (i = 0 ; i < serverlist->maxupdates ; i++) + { + closesocket(serverlist->updatelist[i].s); + } + return 0; } //create and connect a server list socket -static GError CreateServerListSocket(GServerList serverlist) +static GError CreateServerListSocket(GServerList serverlist, GServerListSocket slsocket, gbool async) { - struct sockaddr_in saddr; - struct hostent *hent; + struct sockaddr_in saddr; + struct hostent *hent; + int lasterr; + int i; + int port; + const char *host; - saddr.sin_family = AF_INET; - saddr.sin_port = htons(MSPORT); - saddr.sin_addr.s_addr = inet_addr(MSHOST); - if (saddr.sin_addr.s_addr == INADDR_NONE) - { - hent = gethostbyname(MSHOST); - if (!hent) - return GE_NODNS; - saddr.sin_addr.s_addr = *(u_long *)hent->h_addr_list[0]; - } - serverlist->slsocket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if (serverlist->slsocket == INVALID_SOCKET) - return GE_NOSOCKET; - if (connect ( serverlist->slsocket, (struct sockaddr *) &saddr, sizeof saddr ) != 0) - { - closesocket(serverlist->slsocket); - return GE_NOCONNECT; - } + if (serverlist->startslindex >= ServerListGetNumMasters()) { + return GE_NODNS; + } - //else we are connected - return 0; + if (slsocket->socketstate != ls_none) { + closesocket(slsocket->s); + slsocket->s = INVALID_SOCKET; + } + + port = ServerListGetMsPort(serverlist->startslindex); + host = ServerListGetHost(serverlist->startslindex); + + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + saddr.sin_addr.s_addr = inet_addr(host); + if (saddr.sin_addr.s_addr == INADDR_NONE) + { + hent = gethostbyname(host); + if (!hent) + return GE_NODNS; + saddr.sin_addr.s_addr = *(u_long *)hent->h_addr_list[0]; + } + slsocket->s = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if (slsocket->s == INVALID_SOCKET) + return GE_NOSOCKET; + + if (async) { + SetSockBlocking(slsocket->s, 0); + } + + if (connect ( slsocket->s, (struct sockaddr *) &saddr, sizeof saddr ) != 0 + && (lasterr = GOAGetLastError(slsocket->slsocket), lasterr != WSAEWOULDBLOCK && lasterr != WSAEINPROGRESS)) + { + closesocket(slsocket->s); + slsocket->s = INVALID_SOCKET; + return GE_NOCONNECT; + } + + slsocket->socketstate = ls_connecting; + slsocket->oldlen = 0; + slsocket->cryptinfo.offset = -1; + slsocket->lastreplytime = current_time(); + serverlist->startslindex++; + + //else we are connected + return 0; } +//create and connect a server list sockets +static GError CreateServerListForAvailableSockets(GServerList serverlist, gbool async) +{ + int i; + + for(i = 0; i < serverlist->numslsockets; i++) { + if (serverlist->slsockets[i].socketstate == ls_none) { + CreateServerListSocket(serverlist, &serverlist->slsockets[i], async); + } + } + + return 0; +} + //create and connect a server list socket static GError CreateServerListLANSocket(GServerList serverlist) { - int optval = 1; + int optval = 1; + GServerListSocket slsocket = &serverlist->slsockets[0]; - serverlist->slsocket = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); - if (serverlist->slsocket == INVALID_SOCKET) - return GE_NOSOCKET; - if (setsockopt(serverlist->slsocket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) - return GE_NOSOCKET; + slsocket->s = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + if (slsocket->s == INVALID_SOCKET) + return GE_NOSOCKET; + if (setsockopt(slsocket->s, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) + return GE_NOSOCKET; - //else we are ready to broadcast - return 0; + //else we are ready to broadcast + return 0; } @@ -230,69 +350,99 @@ static GError CreateServerListLANSocket(GServerList serverlist) //trigger the callback and set the new mode static void ServerListModeChange(GServerList serverlist, GServerListState newstate) { - serverlist->state = newstate; - serverlist->CallBackFn(serverlist, LIST_STATECHANGED, serverlist->instance, NULL, NULL); + serverlist->state = newstate; + serverlist->CallBackFn(serverlist, LIST_STATECHANGED, serverlist->instance, NULL, NULL); } // validate us to the master and send a list request #define SECURE "\\secure\\" -static GError SendListRequest(GServerList serverlist, char *filter) +static GError SendListRequest(GServerList serverlist, GServerListSocket slsocket, char *filter) { - char data[256], *ptr, result[64]; - int len; + char data[256], *ptr, result[64]; + int len; + int i; + char *modifier; + + len = recv(slsocket->s, data, sizeof(data) - 1, 0); + if (gsiSocketIsError(len)) { + return GE_NOCONNECT; + } + data[len] = '\0'; //null terminate it + + ptr = strstr ( data, SECURE ); + if (!ptr) + return GE_DATAERROR; + ptr = ptr + strlen(SECURE); + gs_encrypt ( (uchar *) serverlist->seckey, 6, (uchar *)ptr, 6 ); + if (serverlist->encryptdata) { + // Added in 2.0 + for(i = 0; i < 6; i++) { + ptr[i] ^= serverlist->seckey[i]; + } + } + gs_encode ( (uchar *)ptr, 6, (uchar *) result ); - - len = recv(serverlist->slsocket, data, sizeof(data) - 1, 0); - if (gsiSocketIsError(len)) - return GE_NOCONNECT; - data[len] = '\0'; //null terminate it - - ptr = strstr ( data, SECURE ); - if (!ptr) - return GE_DATAERROR; - ptr = ptr + strlen(SECURE); - gs_encrypt ( (uchar *) serverlist->seckey, 6, (uchar *)ptr, 6 ); - gs_encode ( (uchar *)ptr, 6, (uchar *) result ); + if (serverlist->encryptdata) { + // Added in 2.0 + // Encrypt data + //validate to the master + sprintf(data, "\\gamename\\%s\\gamever\\%s\\location\\0\\validate\\%s\\enctype\\2\\final\\\\queryid\\1.1\\", + serverlist->enginename, "2", result); //validate us + } else { + //validate to the master + sprintf(data, "\\gamename\\%s\\gamever\\%s\\location\\0\\validate\\%s\\final\\\\queryid\\1.1\\", + serverlist->enginename, ENGINE_VERSION, result); //validate us + } + + len = send ( slsocket->s, data, strlen(data), 0 ); + if (gsiSocketIsError(len) || len == 0) + return GE_NOCONNECT; - //validate to the master - sprintf(data, "\\gamename\\%s\\gamever\\%s\\location\\0\\validate\\%s\\final\\\\queryid\\1.1\\", - serverlist->enginename, ENGINE_VERSION, result); //validate us - - len = send ( serverlist->slsocket, data, strlen(data), 0 ); - if (gsiSocketIsError(len) || len == 0) - return GE_NOCONNECT; + if (serverlist->querytype == qt_grouprooms) { + modifier = "groups"; - //send the list request - if (filter) - sprintf(data, "\\list\\cmp\\gamename\\%s\\where\\%s\\final\\", serverlist->gamename, filter); - else - sprintf(data, "\\list\\cmp\\gamename\\%s\\final\\", serverlist->gamename); - len = send ( serverlist->slsocket, data, strlen(data), 0 ); - if (gsiSocketIsError(len) || len == 0) - return GE_NOCONNECT; + serverlist->pistate = pi_fieldcount; + } else if (serverlist->querytype == qt_masterinfo) { + modifier = "info2"; - ServerListModeChange(serverlist, sl_listxfer); - return 0; + serverlist->pistate = pi_fieldcount; + } else { + modifier = "cmp"; + } + + //send the list request + if (filter) + sprintf(data, "\\list\\%s\\gamename\\%s\\where\\%s\\final\\", modifier, serverlist->gamename, filter); + else + sprintf(data, "\\list\\%s\\gamename\\%s\\final\\", modifier, serverlist->gamename); + len = send ( slsocket->s, data, strlen(data), 0 ); + if (gsiSocketIsError(len) || len == 0) + return GE_NOCONNECT; + + if (serverlist->state == sl_idle) { + ServerListModeChange(serverlist, sl_listxfer); + } + return 0; } static GError SendBroadcastRequest(GServerList serverlist, int startport, int endport, int delta) { - struct sockaddr_in saddr; - short i; + struct sockaddr_in saddr; + short i; - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = 0xFFFFFFFF; //broadcast - for (i = startport ; i <= endport ; i += delta) - { - saddr.sin_port = htons(i); - sendto(serverlist->slsocket, "\\status\\",8,0,(struct sockaddr *)&saddr,sizeof(saddr)); - } - ServerListModeChange(serverlist, sl_lanlist); - serverlist->lanstarttime = current_time(); - return 0; + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = 0xFFFFFFFF; //broadcast + for (i = startport ; i <= endport ; i += delta) + { + saddr.sin_port = htons(i); + sendto(serverlist->slsockets[0].s, "\\status\\",8,0,(struct sockaddr *)&saddr,sizeof(saddr)); + } + ServerListModeChange(serverlist, sl_lanlist); + serverlist->lanstarttime = current_time(); + return 0; @@ -301,13 +451,13 @@ static GError SendBroadcastRequest(GServerList serverlist, int startport, int en //just wait for the server list to become idle static void DoSyncLoop(GServerList serverlist) { - while (serverlist->state != sl_idle) - { - ServerListThink(serverlist); - msleep(10); - - } - + while (serverlist->state != sl_idle) + { + ServerListThink(serverlist); + msleep(10); + + } + } /* ServerListUpdate @@ -315,7 +465,71 @@ static void DoSyncLoop(GServerList serverlist) Start updating a GServerList without filters */ GError ServerListUpdate(GServerList serverlist, gbool async) { - return ServerListUpdate2(serverlist, async, NULL, qt_status); + return ServerListUpdate2(serverlist, async, NULL, qt_status); +} + +/* ServerListCheckSocketError +------------------------- +Verify if the server list socket has an error or has timed out, and abort. */ +GError ServerListCheckSocketError(GServerList serverlist, GServerListSocket slsocket) +{ + int so_error; + int len = sizeof(so_error); + getsockopt(slsocket->s, SOL_SOCKET, SO_ERROR, &so_error, &len); + + // Abort if the socket has an error or if it connect/recv has timed out + if (so_error || current_time() >= slsocket->lastreplytime + INTERNET_SEARCH_TIME) { + closesocket(slsocket->s); + slsocket->s = INVALID_SOCKET; + slsocket->socketstate = ls_none; + return GE_NOCONNECT; + } + + return 0; +} + +/* ServerListStartQuery +------------------------- +Start querying a GServerList. */ +GError ServerListStartQuery(GServerList serverlist, GServerListSocket slsocket, gbool async) +{ + GError error; + int i; + + if (slsocket->socketstate != ls_connecting) { + return GE_BUSY; + } + + if (serverlist->abortupdate) { + for(i = 0; i < serverlist->numslsockets; i++) { + closesocket(serverlist->slsockets[i].s); + serverlist->slsockets[i].s = INVALID_SOCKET; + } + ServerListModeChange(serverlist, sl_idle); + return GE_NOCONNECT; + } + + if (async) { + // Check for pending data + char buf; + if (recv(slsocket->s, &buf, 1, MSG_PEEK) == -1) { + return GE_BUSY; + } + } + + slsocket->socketstate = ls_connected; + + error = SendListRequest(serverlist, slsocket, serverlist->filter); + if (error) return error; + if (serverlist->querytype != qt_grouprooms && serverlist->querytype != qt_masterinfo) { + error = InitUpdateList(serverlist); + if (error) return error; + } + + if (!async) + DoSyncLoop(serverlist); + + return 0; } /* ServerListUpdate2 @@ -323,24 +537,41 @@ GError ServerListUpdate(GServerList serverlist, gbool async) Start updating a GServerList. */ GError ServerListUpdate2(GServerList serverlist, gbool async, char *filter, GQueryType querytype) { - GError error; + GError error; + int i; - if (serverlist->state != sl_idle) - return GE_BUSY; + if (serverlist->state != sl_idle) + return GE_BUSY; - serverlist->querytype = querytype; - error = CreateServerListSocket(serverlist); - if (error) return error; - error = SendListRequest(serverlist, filter); - if (error) return error; - error = InitUpdateList(serverlist); - if (error) return error; - serverlist->nextupdate = 0; - serverlist->abortupdate = 0; - if (!async) - DoSyncLoop(serverlist); + serverlist->querytype = querytype; + error = CreateServerListForAvailableSockets(serverlist, async); + //if (error) return error; - return 0; + serverlist->nextupdate = 0; + serverlist->abortupdate = 0; + // Added in 2.0 + serverlist->numservers = ServerListCount(serverlist); + // Added in 2.0 + //serverlist->cryptinfo.offset = -1; + if (filter) { + strncpy(serverlist->filter, filter, sizeof(serverlist->filter)); + } else { + serverlist->filter[0] = 0; + } + + serverlist->async = async; + + if (async) { + // As it's asynchronous, set the state to transfering + ServerListModeChange(serverlist, sl_listxfer); + return 0; + } + + for(i = 0; i < serverlist->numslsockets; i++) { + ServerListStartQuery(serverlist, &serverlist->slsockets[i], async); + } + + return 0; } /* ServerListLANUpdate @@ -348,75 +579,90 @@ GError ServerListUpdate2(GServerList serverlist, gbool async, char *filter, GQue Start updating a GServerList from servers on the LAN. */ GError ServerListLANUpdate(GServerList serverlist, gbool async, int startsearchport, int endsearchport, int searchdelta) { - GError error; + GError error; - assert(searchdelta > 0); + assert(searchdelta > 0); - if (serverlist->state != sl_idle) - return GE_BUSY; + if (serverlist->state != sl_idle) + return GE_BUSY; - error = InitUpdateList(serverlist); - if (error) return error; - error = CreateServerListLANSocket(serverlist); - if (error) return error; - error = SendBroadcastRequest(serverlist, startsearchport, endsearchport, searchdelta); - if (error) return error; - serverlist->nextupdate = 0; - serverlist->abortupdate = 0; - if (!async) - DoSyncLoop(serverlist); + error = InitUpdateList(serverlist); + if (error) return error; + error = CreateServerListLANSocket(serverlist); + if (error) return error; + error = SendBroadcastRequest(serverlist, startsearchport, endsearchport, searchdelta); + if (error) return error; + serverlist->nextupdate = 0; + serverlist->abortupdate = 0; + if (!async) + DoSyncLoop(serverlist); - return 0; + return 0; } +//add a new server based on the data +static GServer ServerListAddServerData(GServerList serverlist, char **fieldlist, int fieldcount, char *serverdata, GQueryType qtype) +{ + GServer server; + + server = ServerNewData(fieldlist, fieldcount, serverdata, qtype, serverlist->keylist); + ArrayAppend(serverlist->servers, &server); + return server; +} //add the server to the list with the given ip, port static void ServerListAddServer(GServerList serverlist, unsigned long ip, unsigned short port, GQueryType qtype) { - GServer server; - server = ServerNew(ip, port, qtype, serverlist->keylist); - ArrayAppend(serverlist->servers,&server); + GServer server; + server = ServerNew(ip, port, qtype, serverlist->keylist); + ArrayAppend(serverlist->servers,&server); //printf("%d %s:%d\n",++count, ip,port); } //add the server to the list with the given ip, port static void ServerListInsertServer(GServerList serverlist, unsigned long ip, unsigned short port, int pos, GQueryType qtype) { - GServer server; - server = ServerNew(ip, port, qtype, serverlist->keylist); - ArrayInsertAt(serverlist->servers,&server,pos); + GServer server; + server = ServerNew(ip, port, qtype, serverlist->keylist); + ArrayInsertAt(serverlist->servers,&server,pos); //printf("%d %s:%d\n",++count, ip,port); } +//find the server in the list, returns -1 if it does not exist +static int ServerListFindServerMax(GServerList serverlist, unsigned int ip, int port, int count) +{ + int i; + GServer server; + + for (i = 0; i < count ; i++) + { + server = *(GServer *)ArrayNth(serverlist->servers,i); + if (port == ServerGetQueryPort(server) && ServerGetInetAddress(server)==ip) + { + return i; + } + } + return -1; +} + //find the server in the list, returns -1 if it does not exist static int ServerListFindServer(GServerList serverlist, unsigned int ip, int port) { - int i; - GServer server; - - for (i = 0; i < ArrayLength(serverlist->servers) ; i++) - { - server = *(GServer *)ArrayNth(serverlist->servers,i); - if (port == ServerGetQueryPort(server) && ServerGetInetAddress(server)==ip) - { - return i; - } - } - return -1; + return ServerListFindServerMax(serverlist, ip, port, ArrayLength(serverlist->servers)); } //finds the server in the list of servers currently being queried // returns -1 if it does not exist static int ServerListFindServerInUpdateList(GServerList serverlist, GServer server) { - int i; + int i; - for (i = 0 ; i < serverlist->maxupdates ; i++) - { - if (serverlist->updatelist[i].currentserver == server) - return i; - } - return -1; + for (i = 0 ; i < serverlist->maxupdates ; i++) + { + if (serverlist->updatelist[i].currentserver == server) + return i; + } + return -1; } /* ServerListRemoveServer @@ -424,22 +670,22 @@ static int ServerListFindServerInUpdateList(GServerList serverlist, GServer serv Removes a single server from the list. Frees the memory associated with the GServer */ void ServerListRemoveServer(GServerList serverlist, char *ip, int port) { - int currentindex = ServerListFindServer(serverlist, inet_addr(ip), port); - int updateindex; + int currentindex = ServerListFindServer(serverlist, inet_addr(ip), port); + int updateindex; - if (currentindex == -1) - return; //can't do anything, it doesn't exist + if (currentindex == -1) + return; //can't do anything, it doesn't exist - //check to see whether we need to change the updatelist or move the nextupdate - if (serverlist->state != sl_idle && serverlist->nextupdate > currentindex) - { - GServer holdserver = *(GServer *)ArrayNth(serverlist->servers,currentindex); - updateindex = ServerListFindServerInUpdateList(serverlist, holdserver); - if (updateindex != -1) //is currently being queried, stop it - serverlist->updatelist[updateindex].currentserver = NULL; - serverlist->nextupdate--; //decrement the next update, since we are removing a server - } - ArrayDeleteAt(serverlist->servers, currentindex); + //check to see whether we need to change the updatelist or move the nextupdate + if (serverlist->state != sl_idle && serverlist->nextupdate > currentindex) + { + GServer holdserver = *(GServer *)ArrayNth(serverlist->servers,currentindex); + updateindex = ServerListFindServerInUpdateList(serverlist, holdserver); + if (updateindex != -1) //is currently being queried, stop it + serverlist->updatelist[updateindex].currentserver = NULL; + serverlist->nextupdate--; //decrement the next update, since we are removing a server + } + ArrayDeleteAt(serverlist->servers, currentindex); } /* ServerListUpdate @@ -448,159 +694,297 @@ Adds an auxilliary (non-fetched) server to the update list. If the engine is idle, the server is added and the engine started. */ GError ServerListAuxUpdate(GServerList serverlist, const char *ip, int port, gbool async, GQueryType querytype) { - GError error; - int currentindex; - int updateindex; - unsigned int real_ip = inet_addr(ip); - //first, see if the server already exists - currentindex = ServerListFindServer(serverlist,real_ip,port); + GError error; + int currentindex; + int updateindex; + unsigned int real_ip = inet_addr(ip); + //first, see if the server already exists + currentindex = ServerListFindServer(serverlist,real_ip,port); - //if we're idle, start things up - if (serverlist->state == sl_idle) - { - //prepare as if we're going to do a normal list fetch, - //but skip the call to SendListRequest(). + //if we're idle, start things up + if (serverlist->state == sl_idle) + { + //prepare as if we're going to do a normal list fetch, + //but skip the call to SendListRequest(). - - error = InitUpdateList(serverlist); - if (error) return error; - if (currentindex != -1) //we need to "move" this server to the end of the list - { //move the server to the end of the array - GServer holdserver = *(GServer *)ArrayNth(serverlist->servers,currentindex); - holdserver->ping = 9999;//clear the ping so it gets recalculated - ArrayRemoveAt(serverlist->servers,currentindex); - ArrayAppend(serverlist->servers,&holdserver); - } else - { //add the aux server - ServerListAddServer(serverlist, real_ip, (unsigned short)port, querytype); - } - - serverlist->nextupdate = ArrayLength(serverlist->servers) - 1; - serverlist->abortupdate = 0; + + error = InitUpdateList(serverlist); + if (error) return error; + if (currentindex != -1) //we need to "move" this server to the end of the list + { //move the server to the end of the array + GServer holdserver = *(GServer *)ArrayNth(serverlist->servers,currentindex); + holdserver->ping = 9999;//clear the ping so it gets recalculated + ArrayRemoveAt(serverlist->servers,currentindex); + ArrayAppend(serverlist->servers,&holdserver); + } else + { //add the aux server + ServerListAddServer(serverlist, real_ip, (unsigned short)port, querytype); + } + + serverlist->nextupdate = ArrayLength(serverlist->servers) - 1; + serverlist->abortupdate = 0; - //chane the mode straight to querying - ServerListModeChange(serverlist, sl_querying); - //is it's a sync call, do it until done - if (!async) - DoSyncLoop(serverlist); + //chane the mode straight to querying + ServerListModeChange(serverlist, sl_querying); + //is it's a sync call, do it until done + if (!async) + DoSyncLoop(serverlist); - } - else - { - //if we're in the middle of an update, we should - //be able to just slip the aux server in for querying - //ServerListAddServer(serverlist, ip, port); - //crt -- make it the next server to be queried - //note: this should NEVER be called in a different thread from think!! - if (currentindex == -1) //it doesn't exist yet - ServerListInsertServer(serverlist, real_ip, (unsigned short)port, serverlist->nextupdate, querytype); - else - { //it exists, find out whats happening to it - GServer holdserver = *(GServer *)ArrayNth(serverlist->servers,currentindex); - if (currentindex >= serverlist->nextupdate) //hasn't been queried yet! - return 0; //it will be queried soon anyway - holdserver->ping = 9999;//clear the ping so it gets recalculated - updateindex = ServerListFindServerInUpdateList(serverlist, holdserver); - if (updateindex != -1) //is currently being queried, stop it - serverlist->updatelist[updateindex].currentserver = NULL; - ArrayInsertAt(serverlist->servers,&holdserver, serverlist->nextupdate); //insert at new place - ArrayRemoveAt(serverlist->servers,currentindex); //remove the old one - serverlist->nextupdate--; //decrement the next update, since we are removing a server - } - } - return 0; + } + else + { + //if we're in the middle of an update, we should + //be able to just slip the aux server in for querying + //ServerListAddServer(serverlist, ip, port); + //crt -- make it the next server to be queried + //note: this should NEVER be called in a different thread from think!! + if (currentindex == -1) //it doesn't exist yet + ServerListInsertServer(serverlist, real_ip, (unsigned short)port, serverlist->nextupdate, querytype); + else + { //it exists, find out whats happening to it + GServer holdserver = *(GServer *)ArrayNth(serverlist->servers,currentindex); + if (currentindex >= serverlist->nextupdate) //hasn't been queried yet! + return 0; //it will be queried soon anyway + holdserver->ping = 9999;//clear the ping so it gets recalculated + updateindex = ServerListFindServerInUpdateList(serverlist, holdserver); + if (updateindex != -1) //is currently being queried, stop it + serverlist->updatelist[updateindex].currentserver = NULL; + ArrayInsertAt(serverlist->servers,&holdserver, serverlist->nextupdate); //insert at new place + ArrayRemoveAt(serverlist->servers,currentindex); //remove the old one + serverlist->nextupdate--; //decrement the next update, since we are removing a server + } + } + return 0; } -static GError ServerListLANList(GServerList serverlist) +static GError ServerListLANList(GServerList serverlist, GServerListSocket slsocket) { - struct timeval timeout = {0,0}; - fd_set set; - char indata[1500]; - struct sockaddr_in saddr; - int saddrlen = sizeof(saddr); - int error; - - while (1) //we break if the select fails - { - FD_ZERO(&set); - FD_SET( serverlist->slsocket, &set); - error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); - if (gsiSocketIsError(error) || 0 == error) //no data - break; - error = recvfrom(serverlist->slsocket, indata, sizeof(indata) - 1, 0, (struct sockaddr *)&saddr, &saddrlen ); - if (gsiSocketIsError(error)) - continue; - //we got data, add the server to the list to update - if (strstr(indata,"\\final\\") != NULL) - ServerListAddServer(serverlist,saddr.sin_addr.s_addr, ntohs(saddr.sin_port), qt_status); - } - if (current_time() - serverlist->lanstarttime > LAN_SEARCH_TIME) //done waiting for replies - { - closesocket(serverlist->slsocket); - serverlist->slsocket = INVALID_SOCKET; - ServerListModeChange(serverlist, sl_querying); - } - return 0; + struct timeval timeout = {0,0}; + fd_set set; + char indata[1500]; + struct sockaddr_in saddr; + int saddrlen = sizeof(saddr); + int error; + while (1) //we break if the select fails + { + FD_ZERO(&set); + FD_SET( slsocket->s, &set); + error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); + if (gsiSocketIsError(error) || 0 == error) //no data + break; + error = recvfrom(slsocket->s, indata, sizeof(indata) - 1, 0, (struct sockaddr *)&saddr, &saddrlen ); + if (gsiSocketIsError(error)) + continue; + //we got data, add the server to the list to update + if (strstr(indata,"\\final\\") != NULL) + ServerListAddServer(serverlist,saddr.sin_addr.s_addr, ntohs(saddr.sin_port), qt_status); + } + if (current_time() - serverlist->lanstarttime > LAN_SEARCH_TIME) //done waiting for replies + { + closesocket(slsocket->s); + slsocket->s = INVALID_SOCKET; + ServerListModeChange(serverlist, sl_querying); + } + return 0; } - + +static int CountSlashOffset(char *data, int len, int slashcount) +{ + char *p; + + for (p = data; slashcount && p != data + len; ++p) { + if (*p == '\\') { + slashcount--; + } + } + + if (slashcount) { + return -1; + } + + return p - data; +} + +//parses and retrieve servers based on fields +static int ServerListParseInfoList(GServerList serverlist, char *data, int len) +{ + char *fieldlist[20]; + char tempfield[64]; + char *tempptr; + static int fieldcount; + int offset; + int i; + GServer server; + + switch (serverlist->pistate) { + case pi_fieldcount: + offset = CountSlashOffset(data, len, 3); + if (offset == -1) { + return 0; + } + if (offset < 12) { + return 0; + } + + strncpy(tempfield, data + 12, offset - 12); + tempfield[offset - 13] = 0; + + fieldcount = atoi(tempfield); + if (fieldcount > 20) { + return -1; + } + + serverlist->pistate = pi_fields; + + for (i = 0; i < fieldcount; ++i) { + fieldlist[i] = 0; + } + + return offset - 1; + case pi_fields: + offset = CountSlashOffset(data, len, 2); + if (offset == -1) { + return 0; + } + + strncpy(tempfield, data + 1, offset - 2); + tempfield[offset - 2] = 0; + tempptr = goastrdup(tempfield); + + for (i = 0; i < fieldcount; ++i) { + if (!fieldlist[i]) { + fieldlist[i] = tempptr; + if (i == fieldcount - 1) { + serverlist->pistate = pi_servers; + } + return offset - 1; + } + } + + return -1; + case pi_servers: + offset = CountSlashOffset(data, len, fieldcount + 1); + if (offset == -1) { + return 0; + } + + server = ServerListAddServerData(serverlist, (char **)fieldlist, fieldcount, data, serverlist->querytype); + data[offset - 1] = '\\'; + serverlist->CallBackFn(serverlist, 2, serverlist->instance, server, 0); + return offset - 1; + default: + return -1; + } +} + //reads the server list from the socket and parses it -static GError ServerListReadList(GServerList serverlist) +static GError ServerListReadList(GServerList serverlist, GServerListSocket slsocket) { - static char data[2048]; //static input buffer - static int oldlen = 0; - fd_set set; - struct timeval timeout = {0,0}; - int len, i; - char *p; - unsigned long ip; - unsigned short port; + //static char data[2048]; //static input buffer + //static int oldlen = 0; + fd_set set; + struct timeval timeout = {0,0}; + int len, i; + char *p; + unsigned long ip; + unsigned short port; - FD_ZERO(&set); - FD_SET(serverlist->slsocket, &set); + FD_ZERO(&set); + FD_SET(slsocket->s, &set); #ifndef KGTRN_ACCESS - i = select( FD_SETSIZE, &set, NULL, NULL, &timeout ); - if (i <= 0) - return GE_NOERROR; + i = select( FD_SETSIZE, &set, NULL, NULL, &timeout ); + if (i <= 0) + return GE_NOERROR; #endif //append to data - len = recv(serverlist->slsocket, data + oldlen, sizeof(data) - oldlen - 1, 0); - if (gsiSocketIsError(len) || len == 0) - { - closesocket(serverlist->slsocket); - serverlist->slsocket = INVALID_SOCKET; - oldlen = 0; //clear data so it can be used again - ServerListHalt(serverlist); - ServerListModeChange(serverlist, sl_querying); - return GE_NOCONNECT; + len = recv(slsocket->s, slsocket->data + slsocket->oldlen, sizeof(slsocket->data) - slsocket->oldlen - 1, 0); + if (gsiSocketIsError(len) || len == 0) + { + closesocket(slsocket->s); + slsocket->s = INVALID_SOCKET; + slsocket->socketstate = ls_none; + slsocket->oldlen = 0; //clear data so it can be used again + //ServerListHalt(serverlist); + ServerListModeChange(serverlist, sl_querying); + return GE_NOCONNECT; - } - oldlen += len; + } - p = data; - while (p - data <= oldlen - 6) - { - if (strncmp(p,"\\final\\",7) == 0 || serverlist->abortupdate) - { - closesocket(serverlist->slsocket); - serverlist->slsocket = INVALID_SOCKET; - oldlen = 0; //clear data so it can be used again - ServerListModeChange(serverlist, sl_querying); - return 0; //get out!! - } - if (oldlen < 6) //no way it could be a full IP, quit - break; - memcpy(&ip,p,4); - p += 4; - memcpy(&port,p,2); - p += 2; - ServerListAddServer(serverlist,ip, ntohs(port), serverlist->querytype ); - } - oldlen = oldlen - (p - data); - memmove(data,p,oldlen); //shift it over - return 0; + slsocket->lastreplytime = current_time(); + serverlist->lastsltime = slsocket->lastreplytime; + + if (serverlist->encryptdata && slsocket->cryptinfo.offset != -1) { + // Added in 2.0 + crypt_docrypt(&slsocket->cryptinfo, slsocket->data + slsocket->oldlen, len); + } + + slsocket->oldlen += len; + + p = slsocket->data; + + if (!serverlist->encryptdata) { + slsocket->cryptinfo.offset = 0; + } else if (slsocket->cryptinfo.offset == -1) { + // Added in 2.0 + if (slsocket->oldlen > (*p ^ 0xEC)) { + *p ^= 0xEC; + len = strlen(serverlist->seckey); + for (i = 0; i < len; i++) { + p[i + 1] ^= serverlist->seckey[i]; + } + init_crypt_key((unsigned char *)p + 1, *p, &slsocket->cryptinfo); + p += *p + 1; + crypt_docrypt(&slsocket->cryptinfo, (unsigned char *)p, slsocket->oldlen - (p - slsocket->data)); + } + } + + if (slsocket->cryptinfo.offset != -1) + { + while (p - slsocket->data <= slsocket->oldlen - 6) + { + if (strncmp(p,"\\final\\",7) == 0 || serverlist->abortupdate) + { + closesocket(slsocket->s); + slsocket->s = INVALID_SOCKET; + slsocket->socketstate = ls_none; + slsocket->oldlen = 0; //clear data so it can be used again + if (serverlist->querytype == qt_grouprooms || serverlist->querytype == qt_masterinfo) { + ServerListModeChange(serverlist, sl_idle); + } else { + ServerListModeChange(serverlist, sl_querying); + } + return 0; //get out!! + } + if (slsocket->oldlen < 6) //no way it could be a full IP, quit + break; + + if (serverlist->querytype == qt_grouprooms || serverlist->querytype == qt_masterinfo) { + i = ServerListParseInfoList(serverlist, p, slsocket->oldlen - (p - slsocket->data)); + if (i < 0) { + serverlist->abortupdate = 1; + } else if (!i) { + // finished + break; + } + } else { + memcpy(&ip, p, 4); + p += 4; + memcpy(&port, p, 2); + p += 2; + // Added in 2.0 + // Skip adding the server if already exists + if (ServerListFindServer(serverlist, ip, ntohs(port)) == -1) { + ServerListAddServer(serverlist, ip, ntohs(port), serverlist->querytype); + } + } + } + } + slsocket->oldlen = slsocket->oldlen - (p - slsocket->data); + memmove(slsocket->data,p,slsocket->oldlen); //shift it over + return 0; } @@ -608,96 +992,172 @@ static GError ServerListReadList(GServerList serverlist) static GError ServerListQueryLoop(GServerList serverlist) { - int i, scount = 0, error, final; - fd_set set; - struct timeval timeout = {0,0}; - char indata[1500]; - struct sockaddr_in saddr; - int saddrlen = sizeof(saddr); - GServer server; + int i, scount = 0, error, final; + fd_set set; + struct timeval timeout = {0,0}; + char indata[1500]; + struct sockaddr_in saddr; + int saddrlen = sizeof(saddr); + GServer server; //first, check for available data - FD_ZERO(&set); - for (i = 0 ; i < serverlist->maxupdates ; i++) - if (serverlist->updatelist[i].currentserver != NULL) //there is a server waiting - { - scount++; - FD_SET( serverlist->updatelist[i].s, &set); + FD_ZERO(&set); + for (i = 0 ; i < serverlist->maxupdates ; i++) + if (serverlist->updatelist[i].currentserver != NULL) //there is a server waiting + { + scount++; + FD_SET( serverlist->updatelist[i].s, &set); - } - if (scount > 0) //there are sockets to check for data - { + } + if (scount > 0) //there are sockets to check for data + { - error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); - if (!gsiSocketIsError(error) && 0 != error) - for (i = 0 ; i < serverlist->maxupdates ; i++) - if (serverlist->updatelist[i].currentserver != NULL && FD_ISSET(serverlist->updatelist[i].s, &set) ) //there is a server waiting - { //we can read data!! - saddrlen = sizeof(saddr); - error = recvfrom(serverlist->updatelist[i].s, indata, sizeof(indata) - 1, 0,(struct sockaddr *)&saddr, &saddrlen); + error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); + if (!gsiSocketIsError(error) && 0 != error) + for (i = 0 ; i < serverlist->maxupdates ; i++) + if (serverlist->updatelist[i].currentserver != NULL && FD_ISSET(serverlist->updatelist[i].s, &set) ) //there is a server waiting + { //we can read data!! + saddrlen = sizeof(saddr); + error = recvfrom(serverlist->updatelist[i].s, indata, sizeof(indata) - 1, 0,(struct sockaddr *)&saddr, &saddrlen); - if (saddr.sin_addr.s_addr != serverlist->updatelist[i].saddr.sin_addr.s_addr || - saddr.sin_port != serverlist->updatelist[i].saddr.sin_port) - continue; //it wasn't from this server + if (saddr.sin_addr.s_addr != serverlist->updatelist[i].saddr.sin_addr.s_addr || + saddr.sin_port != serverlist->updatelist[i].saddr.sin_port) + continue; //it wasn't from this server + + if (!gsiSocketIsError(error)) //we got data + { + indata[error] = 0; //truncate and parse it + final = (strstr(indata,"\\final\\") != NULL); + server = serverlist->updatelist[i].currentserver; + if (server->ping == 9999) //set the ping + server->ping = (short)(current_time() - serverlist->updatelist[i].starttime); + ServerParseKeyVals(server, indata); + if (final) //it's all done + { + serverlist->CallBackFn(serverlist, + LIST_PROGRESS, + serverlist->instance, + server, + (void *)((serverlist->nextupdate * 100) / ArrayLength(serverlist->servers))); //percent done + serverlist->updatelist[i].currentserver = NULL; //reuse the updatelist + } + } else + serverlist->updatelist[i].currentserver = NULL; //reuse the updatelist + + } + } + //kill expired ones + for (i = 0 ; i < serverlist->maxupdates ; i++) + if (serverlist->updatelist[i].currentserver != NULL && current_time() - serverlist->updatelist[i].starttime > SERVER_TIMEOUT ) + { + /* serverlist->CallBackFn(serverlist, //do we want to notify of dead servers? if so, uncomment! + LIST_PROGRESS, + serverlist->instance, + *(GServer *)serverlist->updatelist[i].currentserver, + (void *)((serverlist->nextupdate * 100) / ArrayLength(serverlist->servers))); //percent done + */ + serverlist->updatelist[i].currentserver = NULL; //reuse the updatelist + } + + if (serverlist->abortupdate || (serverlist->nextupdate >= ArrayLength(serverlist->servers) && scount == 0)) + { //we are done!! + FreeUpdateList(serverlist); + if (serverlist->abortupdate) { + ServerListModeChange(serverlist, sl_idle); + return 0; + } + + if (serverlist->startslindex < ServerListGetNumMasters() || !ServerListHasFinishedFetchingList(serverlist)) { + ServerListModeChange(serverlist, sl_listxfer); + } else { + // No more masters + ServerListModeChange(serverlist, sl_idle); + } + return 0; + } + + if (!ServerListHasFinishedFetchingList(serverlist) && current_time() < serverlist->lastsltime + SERVER_QUERY_MAX_PAUSE) { + // Make sure to not send out other queries if currently fetching from other lists + // to avoid overloading the network + return GE_BUSY; + } - if (!gsiSocketIsError(error)) //we got data - { - indata[error] = 0; //truncate and parse it - final = (strstr(indata,"\\final\\") != NULL); - server = serverlist->updatelist[i].currentserver; - if (server->ping == 9999) //set the ping - server->ping = (short)(current_time() - serverlist->updatelist[i].starttime); - ServerParseKeyVals(server, indata); - if (final) //it's all done - { - serverlist->CallBackFn(serverlist, - LIST_PROGRESS, - serverlist->instance, - server, - (void *)((serverlist->nextupdate * 100) / ArrayLength(serverlist->servers))); //percent done - serverlist->updatelist[i].currentserver = NULL; //reuse the updatelist - } - } else - serverlist->updatelist[i].currentserver = NULL; //reuse the updatelist - - } - } - //kill expired ones - for (i = 0 ; i < serverlist->maxupdates ; i++) - if (serverlist->updatelist[i].currentserver != NULL && current_time() - serverlist->updatelist[i].starttime > SERVER_TIMEOUT ) - { - /* serverlist->CallBackFn(serverlist, //do we want to notify of dead servers? if so, uncomment! - LIST_PROGRESS, - serverlist->instance, - *(GServer *)serverlist->updatelist[i].currentserver, - (void *)((serverlist->nextupdate * 100) / ArrayLength(serverlist->servers))); //percent done - */ - serverlist->updatelist[i].currentserver = NULL; //reuse the updatelist - } - - if (serverlist->abortupdate || (serverlist->nextupdate >= ArrayLength(serverlist->servers) && scount == 0)) - { //we are done!! - FreeUpdateList(serverlist); - ServerListModeChange(serverlist, sl_idle); - return 0; - } - //now, send out queries on available sockets - for (i = 0 ; i < serverlist->maxupdates && serverlist->nextupdate < ArrayLength(serverlist->servers) ; i++) - if (serverlist->updatelist[i].currentserver == NULL) //it's availalbe - { - server = *(GServer *)ArrayNth(serverlist->servers,serverlist->nextupdate); - serverlist->nextupdate++; - serverlist->updatelist[i].currentserver = server; - serverlist->updatelist[i].saddr.sin_family = AF_INET; - serverlist->updatelist[i].saddr.sin_addr.s_addr = inet_addr(ServerGetAddress(server)); - serverlist->updatelist[i].saddr.sin_port = htons((short)ServerGetQueryPort(server)); - sendto(serverlist->updatelist[i].s,querystrings[server->querytype] ,querylengths[server->querytype],0,(struct sockaddr *)&serverlist->updatelist[i].saddr,sizeof(struct sockaddr_in)); - serverlist->updatelist[i].starttime = current_time(); - } + for (i = 0 ; i < serverlist->maxupdates && serverlist->nextupdate < ArrayLength(serverlist->servers) ; i++) + if (serverlist->updatelist[i].currentserver == NULL) //it's availalbe + { + server = *(GServer *)ArrayNth(serverlist->servers,serverlist->nextupdate); + serverlist->nextupdate++; + serverlist->updatelist[i].currentserver = server; + serverlist->updatelist[i].saddr.sin_family = AF_INET; + serverlist->updatelist[i].saddr.sin_addr.s_addr = inet_addr(ServerGetAddress(server)); + serverlist->updatelist[i].saddr.sin_port = htons((short)ServerGetQueryPort(server)); + sendto(serverlist->updatelist[i].s,querystrings[server->querytype] ,querylengths[server->querytype],0,(struct sockaddr *)&serverlist->updatelist[i].saddr,sizeof(struct sockaddr_in)); + serverlist->updatelist[i].starttime = current_time(); + } - return 0; + return 0; +} + +/* ServerListThinkSocket +------------------ +For use with Async Updates. This needs to be called every ~10ms for list processing and +updating to occur during async server list updates */ +GError ServerListThinkSocket(GServerList serverlist, GServerListSocket slsocket) +{ + GError socketerror; + + if (slsocket->s == INVALID_SOCKET) { + return GE_NOSOCKET; + } + + socketerror = ServerListCheckSocketError(serverlist, slsocket); + if (socketerror) { + return socketerror; + } + + switch(slsocket->socketstate) + { + case ls_connecting: + ServerListStartQuery(serverlist, slsocket, 1); + break; + case ls_connected: + //read the data + return ServerListReadList(serverlist, slsocket); + break; + default: + break; + } + + switch (serverlist->state) + { + case sl_idle: return 0; + case sl_listxfer: + //read the data + //return ServerListReadList(serverlist, slsocket); + break; + case sl_lanlist: + return ServerListLANList(serverlist, slsocket); + } + + return 0; +} + +/* ServerListHasFinishedFetchingList +------------------ +Whether or not the list has finished fetching */ +static gbool ServerListHasFinishedFetchingList(GServerList serverlist) +{ + int i; + + for(i = 0; i < serverlist->numslsockets; i++) { + if (serverlist->slsockets[i].s != INVALID_SOCKET) { + return 0; + } + } + + return 1; } /* ServerListThink @@ -706,24 +1166,32 @@ For use with Async Updates. This needs to be called every ~10ms for list process updating to occur during async server list updates */ GError ServerListThink(GServerList serverlist) { + int i; - switch (serverlist->state) - { - case sl_idle: return 0; - case sl_listxfer: - //read the data - return ServerListReadList(serverlist); - break; - case sl_lanlist: - return ServerListLANList(serverlist); - case sl_querying: - //do some queries - return ServerListQueryLoop(serverlist); - break; - } + for(i = 0; i < serverlist->numslsockets; i++) { + ServerListThinkSocket(serverlist, &serverlist->slsockets[i]); + } + switch(serverlist->state) + { + case sl_idle: + case sl_listxfer: + if (!serverlist->abortupdate) { + if (serverlist->startslindex < ServerListGetNumMasters()) { + CreateServerListForAvailableSockets(serverlist, serverlist->async); + } else if (serverlist->state == sl_listxfer && ServerListHasFinishedFetchingList(serverlist)) { + ServerListModeChange(serverlist, sl_idle); + } + } + break; + case sl_querying: + //do some queries + return ServerListQueryLoop(serverlist); + break; + default: break; + } - return 0; + return 0; } /* ServerListHalt @@ -731,10 +1199,10 @@ GError ServerListThink(GServerList serverlist) Halts the current update batch */ GError ServerListHalt(GServerList serverlist) { - if (serverlist->state != sl_idle) - serverlist->abortupdate = 1; + if (serverlist->state != sl_idle) + serverlist->abortupdate = 1; - return 0; + return 0; } /* ServerListClear @@ -743,13 +1211,13 @@ Clear and free all of the servers from the server list. List must be in the sl_idle state */ GError ServerListClear(GServerList serverlist) { - - if (serverlist->state != sl_idle) - return GE_BUSY; - //fastest way to clear is kill and recreate - ArrayFree(serverlist->servers); - serverlist->servers = ArrayNew(sizeof(GServer), SERVER_GROWBY, ServerFree); - return 0; + + if (serverlist->state != sl_idle) + return GE_BUSY; + //fastest way to clear is kill and recreate + ArrayFree(serverlist->servers); + serverlist->servers = ArrayNew(sizeof(GServer), SERVER_GROWBY, ServerFree); + return 0; } /* ServerListState @@ -757,7 +1225,7 @@ GError ServerListClear(GServerList serverlist) Returns the current state of the server list */ GServerListState ServerListState(GServerList serverlist) { - return serverlist->state; + return serverlist->state; } /* ServerListErrorDesc @@ -765,16 +1233,16 @@ GServerListState ServerListState(GServerList serverlist) Returns a static string description of the specified error */ char *ServerListErrorDesc(GServerList serverlist, GError error) { - switch (error) - { - case GE_NOERROR: return ""; - case GE_NOSOCKET: return "Unable to create socket"; - case GE_NODNS: return "Unable to resolve master"; - case GE_NOCONNECT: return "Connection to master reset"; - case GE_BUSY: return "Server List is busy"; - case GE_DATAERROR: return "Unexpected data in server list"; - } - return "UNKNOWN ERROR CODE"; + switch (error) + { + case GE_NOERROR: return ""; + case GE_NOSOCKET: return "Unable to create socket"; + case GE_NODNS: return "Unable to resolve master"; + case GE_NOCONNECT: return "Connection to master reset"; + case GE_BUSY: return "Server List is busy"; + case GE_DATAERROR: return "Unexpected data in server list"; + } + return "UNKNOWN ERROR CODE"; } @@ -783,9 +1251,9 @@ char *ServerListErrorDesc(GServerList serverlist, GError error) Returns the server at the specified index, or NULL if the index is out of bounds */ GServer ServerListGetServer(GServerList serverlist, int index) { - if (index < 0 || index >= ArrayLength(serverlist->servers)) - return NULL; - return *(GServer *)ArrayNth(serverlist->servers,index); + if (index < 0 || index >= ArrayLength(serverlist->servers)) + return NULL; + return *(GServer *)ArrayNth(serverlist->servers,index); } /* ServerListCount @@ -794,7 +1262,7 @@ Returns the number of servers on the specified list. Indexing is 0 based, so the actual server indexes are 0 <= valid index < Count */ int ServerListCount(GServerList serverlist) { - return ArrayLength(serverlist->servers); + return ArrayLength(serverlist->servers); } /**** @@ -802,50 +1270,50 @@ Comparision Functions ***/ static int IntKeyCompare(const void *entry1, const void *entry2) { - GServer server1 = *(GServer *)entry1, server2 = *(GServer *)entry2; - int diff; - diff = ServerGetIntValue(server1, g_sortserverlist->sortkey, 0) - - ServerGetIntValue(server2, g_sortserverlist->sortkey, 0); - if (!g_sortserverlist->sortascending) - diff = -diff; - return diff; - + GServer server1 = *(GServer *)entry1, server2 = *(GServer *)entry2; + int diff; + diff = ServerGetIntValue(server1, g_sortserverlist->sortkey, 0) - + ServerGetIntValue(server2, g_sortserverlist->sortkey, 0); + if (!g_sortserverlist->sortascending) + diff = -diff; + return diff; + } static int FloatKeyCompare(const void *entry1, const void *entry2) { GServer server1 = *(GServer *)entry1, server2 = *(GServer *)entry2; - double f = ServerGetFloatValue(server1, g_sortserverlist->sortkey, 0) - - ServerGetFloatValue(server2, g_sortserverlist->sortkey, 0); - if (!g_sortserverlist->sortascending) - f = -f; - if ((float)f > (float)0.0) - return 1; - else if ((float)f < (float)0.0) - return -1; - else - return 0; + double f = ServerGetFloatValue(server1, g_sortserverlist->sortkey, 0) - + ServerGetFloatValue(server2, g_sortserverlist->sortkey, 0); + if (!g_sortserverlist->sortascending) + f = -f; + if ((float)f > (float)0.0) + return 1; + else if ((float)f < (float)0.0) + return -1; + else + return 0; } static int StrCaseKeyCompare(const void *entry1, const void *entry2) { - + GServer server1 = *(GServer *)entry1, server2 = *(GServer *)entry2; int diff = strcmp(ServerGetStringValue(server1, g_sortserverlist->sortkey, ""), - ServerGetStringValue(server2, g_sortserverlist->sortkey, "")); - if (!g_sortserverlist->sortascending) - diff = -diff; - return diff; + ServerGetStringValue(server2, g_sortserverlist->sortkey, "")); + if (!g_sortserverlist->sortascending) + diff = -diff; + return diff; } static int StrNoCaseKeyCompare(const void *entry1, const void *entry2) { - GServer server1 = *(GServer *)entry1, server2 = *(GServer *)entry2; - int diff = strcasecmp(ServerGetStringValue(server1, g_sortserverlist->sortkey, ""), - ServerGetStringValue(server2, g_sortserverlist->sortkey, "")); - if (!g_sortserverlist->sortascending) - diff = -diff; - return diff; + GServer server1 = *(GServer *)entry1, server2 = *(GServer *)entry2; + int diff = strcasecmp(ServerGetStringValue(server1, g_sortserverlist->sortkey, ""), + ServerGetStringValue(server2, g_sortserverlist->sortkey, "")); + if (!g_sortserverlist->sortascending) + diff = -diff; + return diff; } /* ServerListSort @@ -855,22 +1323,22 @@ specified comparemode. sortkey can be a normal server key, or "ping" or "hostaddr" */ void ServerListSort(GServerList serverlist, gbool ascending, char *sortkey, GCompareMode comparemode) { - ArrayCompareFn comparator; - switch (comparemode) - { - case cm_int: comparator = IntKeyCompare; - break; - case cm_float: comparator = FloatKeyCompare; - break; - case cm_strcase: comparator = StrCaseKeyCompare; - break; - case cm_stricase: comparator = StrNoCaseKeyCompare; - break; - } - serverlist->sortkey = sortkey; - serverlist->sortascending = ascending; - g_sortserverlist = serverlist; - ArraySort(serverlist->servers,comparator); + ArrayCompareFn comparator; + switch (comparemode) + { + case cm_int: comparator = IntKeyCompare; + break; + case cm_float: comparator = FloatKeyCompare; + break; + case cm_strcase: comparator = StrCaseKeyCompare; + break; + case cm_stricase: comparator = StrNoCaseKeyCompare; + break; + } + serverlist->sortkey = sortkey; + serverlist->sortascending = ascending; + g_sortserverlist = serverlist; + ArraySort(serverlist->servers,comparator); } diff --git a/code/gamespy/gstats/gp_stats/gp_stats.rc b/code/gamespy/gstats/gp_stats/gp_stats.rc index dee94b35..d0b03cff 100644 --- a/code/gamespy/gstats/gp_stats/gp_stats.rc +++ b/code/gamespy/gstats/gp_stats/gp_stats.rc @@ -90,7 +90,7 @@ BEGIN EDITTEXT IDC_PASSWORD,65,50,110,12,ES_PASSWORD | ES_AUTOHSCROLL EDITTEXT IDC_PROFILE_ID,65,65,110,12,ES_AUTOHSCROLL | ES_READONLY PUSHBUTTON "Authenticate",IDC_AUTHENTICATE,35,85,50,14 - GROUPBOX "Persistant Data",IDC_STATIC,10,115,175,140 + GROUPBOX "Persistent Data",IDC_STATIC,10,115,175,140 CONTROL "Private Read/Write",IDC_PRIVATE_RW,"Button", BS_AUTORADIOBUTTON | WS_GROUP,20,130,77,10 CONTROL "Private Read-Only",IDC_PRIVATE_RO,"Button", diff --git a/code/gamespy/gutil.c b/code/gamespy/gutil.c index 698aa946..136c2c77 100644 --- a/code/gamespy/gutil.c +++ b/code/gamespy/gutil.c @@ -18,68 +18,68 @@ typedef unsigned char uchar; static void swap_byte(uchar* a, uchar* b) { - uchar swapByte; + uchar swapByte; - swapByte = *a; - *a = *b; - *b = swapByte; + swapByte = *a; + *a = *b; + *b = swapByte; } static uchar encode_ct(uchar c) { - if (c < 26) return (uchar)('A' + c); - if (c < 52) return (uchar)('a' + c - 26); - if (c < 62) return (uchar)('0' + c - 52); - if (c == 62) return (uchar)('+'); - if (c == 63) return (uchar)('/'); + if (c < 26) return (uchar)('A' + c); + if (c < 52) return (uchar)('a' + c - 26); + if (c < 62) return (uchar)('0' + c - 52); + if (c == 62) return (uchar)('+'); + if (c == 63) return (uchar)('/'); - return 0; + return 0; } void gs_encode(uchar* ins, int size, uchar* result) { - int i, pos; - uchar trip[3]; - uchar kwart[4]; + int i, pos; + uchar trip[3]; + uchar kwart[4]; - i = 0; - while (i < size) - { - for (pos = 0; pos <= 2; pos++, i++) - if (i < size) trip[pos] = *ins++; - else trip[pos] = '\0'; - kwart[0] = (unsigned char)((trip[0]) >> 2); - kwart[1] = (unsigned char)((((trip[0]) & 3) << 4) + ((trip[1]) >> 4)); - kwart[2] = (unsigned char)((((trip[1]) & 15) << 2) + ((trip[2]) >> 6)); - kwart[3] = (unsigned char)((trip[2]) & 63); - for (pos = 0; pos <= 3; pos++) *result++ = encode_ct(kwart[pos]); - } - *result = '\0'; + i = 0; + while (i < size) + { + for (pos = 0; pos <= 2; pos++, i++) + if (i < size) trip[pos] = *ins++; + else trip[pos] = '\0'; + kwart[0] = (unsigned char)((trip[0]) >> 2); + kwart[1] = (unsigned char)((((trip[0]) & 3) << 4) + ((trip[1]) >> 4)); + kwart[2] = (unsigned char)((((trip[1]) & 15) << 2) + ((trip[2]) >> 6)); + kwart[3] = (unsigned char)((trip[2]) & 63); + for (pos = 0; pos <= 3; pos++) *result++ = encode_ct(kwart[pos]); + } + *result = '\0'; } void gs_encrypt(uchar* key, int key_len, uchar* buffer_ptr, int buffer_len) { - int counter; - uchar x, y, xorIndex; - uchar state[256]; + int counter; + uchar x, y, xorIndex; + uchar state[256]; - for (counter = 0; counter < 256; counter++) state[counter] = (uchar)counter; + for (counter = 0; counter < 256; counter++) state[counter] = (uchar)counter; - x = 0; y = 0; - for (counter = 0; counter < 256; counter++) - { - y = (uchar)((key[x] + state[counter] + y) % 256); - x = (uchar)((x + 1) % key_len); - swap_byte(&state[counter], &state[y]); - } + x = 0; y = 0; + for (counter = 0; counter < 256; counter++) + { + y = (uchar)((key[x] + state[counter] + y) % 256); + x = (uchar)((x + 1) % key_len); + swap_byte(&state[counter], &state[y]); + } - x = 0; y = 0; - for (counter = 0; counter < buffer_len; counter++) - { - x = (uchar)((x + buffer_ptr[counter] + 1) % 256); - y = (uchar)((state[x] + y) % 256); - swap_byte(&state[x], &state[y]); - xorIndex = (uchar)((state[x] + state[y]) % 256); - buffer_ptr[counter] ^= state[xorIndex]; - } + x = 0; y = 0; + for (counter = 0; counter < buffer_len; counter++) + { + x = (uchar)((x + buffer_ptr[counter] + 1) % 256); + y = (uchar)((state[x] + y) % 256); + swap_byte(&state[x], &state[y]); + xorIndex = (uchar)((state[x] + state[y]) % 256); + buffer_ptr[counter] ^= state[xorIndex]; + } } diff --git a/code/gamespy/gutil.h b/code/gamespy/gutil.h index b35d0f6c..f1889513 100644 --- a/code/gamespy/gutil.h +++ b/code/gamespy/gutil.h @@ -27,7 +27,7 @@ size: size of the buffer OUT --- result: pointer to buffer to store result. Size should be (4 * size) / 3 + 1 - result will be null terminated. + result will be null terminated. **********/ void gs_encode(uchar* ins, int size, uchar* result); diff --git a/code/gamespy/hashtable.c b/code/gamespy/hashtable.c index 9313e503..84ad6275 100644 --- a/code/gamespy/hashtable.c +++ b/code/gamespy/hashtable.c @@ -22,208 +22,208 @@ #ifdef _NO_NOPORT_H_ - #define gsimalloc malloc - #define gsifree free - #define gsirealloc realloc - #include + #define gsimalloc malloc + #define gsifree free + #define gsirealloc realloc + #include #else - #include "nonport.h" //for gsimalloc/realloc/free/assert + #include "nonport.h" //for gsimalloc/realloc/free/assert #endif struct HashImplementation { - DArray *buckets; - int nbuckets; - TableElementFreeFn freefn; - TableHashFn hashfn; - TableCompareFn compfn; + DArray *buckets; + int nbuckets; + TableElementFreeFn freefn; + TableHashFn hashfn; + TableCompareFn compfn; }; HashTable TableNew(int elemSize, int nBuckets, TableHashFn hashFn, TableCompareFn compFn, - TableElementFreeFn freeFn) + TableElementFreeFn freeFn) { - return TableNew2(elemSize, nBuckets, 4, hashFn, compFn, freeFn); + return TableNew2(elemSize, nBuckets, 4, hashFn, compFn, freeFn); } HashTable TableNew2(int elemSize, int nBuckets, int nChains, TableHashFn hashFn, TableCompareFn compFn, - TableElementFreeFn freeFn) + TableElementFreeFn freeFn) { - HashTable table; - int i; + HashTable table; + int i; - assert(hashFn); - assert(compFn); - assert(elemSize); - assert(nBuckets); + assert(hashFn); + assert(compFn); + assert(elemSize); + assert(nBuckets); - table = (HashTable)gsimalloc(sizeof(struct HashImplementation)); - assert(table); - - table->buckets = (DArray *)gsimalloc(nBuckets * sizeof(DArray)); - assert(table->buckets); - for (i = 0; i < nBuckets; i++) //ArrayNew will assert if allocation fails - table->buckets[i] = ArrayNew(elemSize, nChains, freeFn); - table->nbuckets = nBuckets; - table->freefn = freeFn; - table->compfn = compFn; - table->hashfn = hashFn; + table = (HashTable)gsimalloc(sizeof(struct HashImplementation)); + assert(table); + + table->buckets = (DArray *)gsimalloc(nBuckets * sizeof(DArray)); + assert(table->buckets); + for (i = 0; i < nBuckets; i++) //ArrayNew will assert if allocation fails + table->buckets[i] = ArrayNew(elemSize, nChains, freeFn); + table->nbuckets = nBuckets; + table->freefn = freeFn; + table->compfn = compFn; + table->hashfn = hashFn; - return table; + return table; } void TableFree(HashTable table) { - int i; - - assert(table); + int i; + + assert(table); - if (NULL == table ) - return; - - for (i = 0 ; i < table->nbuckets ; i++) - ArrayFree(table->buckets[i]); - gsifree(table->buckets); - gsifree(table); + if (NULL == table ) + return; + + for (i = 0 ; i < table->nbuckets ; i++) + ArrayFree(table->buckets[i]); + gsifree(table->buckets); + gsifree(table); } int TableCount(HashTable table) { - int i, count = 0; - - assert(table); + int i, count = 0; + + assert(table); - if (NULL == table ) - return count; + if (NULL == table ) + return count; - for (i = 0 ; i < table->nbuckets ; i++) - count += ArrayLength(table->buckets[i]); - - return count; + for (i = 0 ; i < table->nbuckets ; i++) + count += ArrayLength(table->buckets[i]); + + return count; } void TableEnter(HashTable table, const void *newElem) { - int hash, itempos; - - assert(table); + int hash, itempos; + + assert(table); - if (NULL == table ) - return; + if (NULL == table ) + return; - hash = table->hashfn(newElem, table->nbuckets); - itempos = ArraySearch(table->buckets[hash], newElem, table->compfn, 0,0); - if (itempos == NOT_FOUND) - ArrayAppend(table->buckets[hash], newElem); - else - ArrayReplaceAt(table->buckets[hash], newElem, itempos); + hash = table->hashfn(newElem, table->nbuckets); + itempos = ArraySearch(table->buckets[hash], newElem, table->compfn, 0,0); + if (itempos == NOT_FOUND) + ArrayAppend(table->buckets[hash], newElem); + else + ArrayReplaceAt(table->buckets[hash], newElem, itempos); } int TableRemove(HashTable table, const void *delElem) { - int hash, itempos; - - assert(table); + int hash, itempos; + + assert(table); - if (NULL == table ) - return 0; + if (NULL == table ) + return 0; - hash = table->hashfn(delElem, table->nbuckets); - itempos = ArraySearch(table->buckets[hash], delElem, table->compfn, 0,0); - if (itempos == NOT_FOUND) - return 0; - else - ArrayDeleteAt(table->buckets[hash], itempos); - return 1; + hash = table->hashfn(delElem, table->nbuckets); + itempos = ArraySearch(table->buckets[hash], delElem, table->compfn, 0,0); + if (itempos == NOT_FOUND) + return 0; + else + ArrayDeleteAt(table->buckets[hash], itempos); + return 1; } void *TableLookup(HashTable table, const void *elemKey) { - int hash, itempos; - - assert(table); + int hash, itempos; + + assert(table); - if (NULL == table ) - return NULL; + if (NULL == table ) + return NULL; - hash = table->hashfn(elemKey, table->nbuckets); - itempos = ArraySearch(table->buckets[hash], elemKey, table->compfn, 0, - 0); - if (itempos == NOT_FOUND) - return NULL; - else - return ArrayNth(table->buckets[hash], itempos); + hash = table->hashfn(elemKey, table->nbuckets); + itempos = ArraySearch(table->buckets[hash], elemKey, table->compfn, 0, + 0); + if (itempos == NOT_FOUND) + return NULL; + else + return ArrayNth(table->buckets[hash], itempos); } void TableMap(HashTable table, TableMapFn fn, void *clientData) { - int i; - - assert(table); - assert(fn); + int i; + + assert(table); + assert(fn); - if (NULL == table || NULL == fn) - return; - - for (i = 0 ; i < table->nbuckets ; i++) - ArrayMap(table->buckets[i], fn, clientData); - + if (NULL == table || NULL == fn) + return; + + for (i = 0 ; i < table->nbuckets ; i++) + ArrayMap(table->buckets[i], fn, clientData); + } void TableMapSafe(HashTable table, TableMapFn fn, void *clientData) { - int i; - - assert(fn); - - for (i = 0 ; i < table->nbuckets ; i++) - ArrayMapBackwards(table->buckets[i], fn, clientData); - + int i; + + assert(fn); + + for (i = 0 ; i < table->nbuckets ; i++) + ArrayMapBackwards(table->buckets[i], fn, clientData); + } void * TableMap2(HashTable table, TableMapFn2 fn, void *clientData) { - int i; - void * pcurr; - - assert(fn); - - for (i = 0 ; i < table->nbuckets ; i++) - { - pcurr = ArrayMap2(table->buckets[i], fn, clientData); - if(pcurr) - return pcurr; - } + int i; + void * pcurr; + + assert(fn); + + for (i = 0 ; i < table->nbuckets ; i++) + { + pcurr = ArrayMap2(table->buckets[i], fn, clientData); + if(pcurr) + return pcurr; + } - return NULL; + return NULL; } void * TableMapSafe2(HashTable table, TableMapFn2 fn, void *clientData) { - int i; - void * pcurr; - - assert(fn); - - for (i = 0 ; i < table->nbuckets ; i++) - { - pcurr = ArrayMapBackwards2(table->buckets[i], fn, clientData); - if(pcurr) - return pcurr; - } + int i; + void * pcurr; + + assert(fn); + + for (i = 0 ; i < table->nbuckets ; i++) + { + pcurr = ArrayMapBackwards2(table->buckets[i], fn, clientData); + if(pcurr) + return pcurr; + } - return NULL; + return NULL; } void TableClear(HashTable table) { - int i; + int i; - for (i = 0 ; i < table->nbuckets ; i++) - ArrayClear(table->buckets[i]); + for (i = 0 ; i < table->nbuckets ; i++) + ArrayClear(table->buckets[i]); } diff --git a/code/gamespy/hashtable.h b/code/gamespy/hashtable.h index d6c8a4a3..fa00c2ec 100644 --- a/code/gamespy/hashtable.h +++ b/code/gamespy/hashtable.h @@ -126,11 +126,11 @@ extern "C" { HashTable TableNew(int elemSize, int nBuckets, TableHashFn hashFn, TableCompareFn compFn, - TableElementFreeFn freeFn); + TableElementFreeFn freeFn); HashTable TableNew2(int elemSize, int nBuckets, int nChains, TableHashFn hashFn, TableCompareFn compFn, - TableElementFreeFn freeFn); + TableElementFreeFn freeFn); /* TableFree diff --git a/code/gamespy/md5.h b/code/gamespy/md5.h index 0fccee0c..0d324291 100644 --- a/code/gamespy/md5.h +++ b/code/gamespy/md5.h @@ -38,7 +38,7 @@ The following makes PROTOTYPES default to 0 if it has not already #ifdef __cplusplus extern "C" { #endif - + #ifndef PROTOTYPES #define PROTOTYPES 1 #endif diff --git a/code/gamespy/md5c.c b/code/gamespy/md5c.c index de31fc6a..8383e62f 100644 --- a/code/gamespy/md5c.c +++ b/code/gamespy/md5c.c @@ -305,7 +305,7 @@ static void Decode (UINT4 *output, unsigned char *input, unsigned int len) */ static void MD5_memcpy (POINTER output, POINTER input, unsigned int len) { - memcpy(output, input, len); + memcpy(output, input, len); /* unsigned int i; for (i = 0; i < len; i++) @@ -316,7 +316,7 @@ static void MD5_memcpy (POINTER output, POINTER input, unsigned int len) */ static void MD5_memset (POINTER output, int value, unsigned int len) { - memset(output, value, len); + memset(output, value, len); /* unsigned int i; for (i = 0; i < len; i++) @@ -327,26 +327,26 @@ static void MD5_memset (POINTER output, int value, unsigned int len) void MD5Print (unsigned char digest[16], char output[33]) { - static const char hex_digits[] = "0123456789abcdef"; - unsigned int i; + static const char hex_digits[] = "0123456789abcdef"; + unsigned int i; - for (i = 0; i < 16; i++) - { - output[i*2 ] = hex_digits[digest[i] / 16]; - output[i*2+1] = hex_digits[digest[i] % 16]; - } - output[32] = '\0'; + for (i = 0; i < 16; i++) + { + output[i*2 ] = hex_digits[digest[i] / 16]; + output[i*2+1] = hex_digits[digest[i] % 16]; + } + output[32] = '\0'; } void MD5Digest (unsigned char *input, unsigned int len, char output[33]) { - MD5_CTX ctx; - unsigned char digest[16]; + MD5_CTX ctx; + unsigned char digest[16]; - MD5Init(&ctx); - MD5Update(&ctx, input, len); - MD5Final(digest, &ctx); - MD5Print(digest, output); + MD5Init(&ctx); + MD5Update(&ctx, input, len); + MD5Final(digest, &ctx); + MD5Print(digest, output); } #ifdef __cplusplus diff --git a/code/gamespy/q_gamespy.c b/code/gamespy/q_gamespy.c new file mode 100644 index 00000000..69d98981 --- /dev/null +++ b/code/gamespy/q_gamespy.c @@ -0,0 +1,170 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#pragma once + +#include "q_gamespy.h" +#include "../qcommon/qcommon.h" +#include "cl_gamespy.h" +#include "sv_gamespy.h" + +#define MAX_MASTERS 8 +#define MASTER_DEFAULT_MSPORT 28900 +#define MASTER_DEFAULT_HBPORT 27900 + +cvar_t *com_master_host[MAX_MASTERS]; +cvar_t *com_master_msport[MAX_MASTERS]; +cvar_t *com_master_hbport[MAX_MASTERS]; + +master_entry_t entries[MAX_MASTERS]; +int num_entries = 0; + +static void Com_RestartGameSpy_f(void); + +static qboolean ShouldRefreshMasters() +{ + int i; + + for (i = 0; i < MAX_MASTERS; i++) { + if (com_master_host[i] && com_master_host[i]->latchedString) { + return qtrue; + } + if (com_master_msport[i] && com_master_msport[i]->latchedString) { + return qtrue; + } + if (com_master_hbport[i] && com_master_hbport[i]->latchedString) { + return qtrue; + } + } + + return qfalse; +} + +static void CreateMasterVar(int index, const char *host, int msport, int hbport) +{ + assert(index < MAX_MASTERS); + + // + // These variables should be modified for testing purposes only. + // So prevent them to be saved in the configuration file. + // + com_master_host[index] = Cvar_Get(va("com_master%d_host", index), host, CVAR_LATCH | CVAR_TEMP); + com_master_msport[index] = Cvar_Get(va("com_master%d_msport", index), va("%d", msport), CVAR_LATCH | CVAR_TEMP); + com_master_hbport[index] = Cvar_Get(va("com_master%d_hbport", index), va("%d", hbport), CVAR_LATCH | CVAR_TEMP); + + com_master_host[index]->flags &= ~CVAR_ARCHIVE; + com_master_msport[index]->flags &= ~CVAR_ARCHIVE; + com_master_hbport[index]->flags &= ~CVAR_ARCHIVE; +} + +qboolean Com_RefreshGameSpyMasters() +{ + int msIndex = 0; + int i; + qboolean shouldRestart; + + shouldRestart = ShouldRefreshMasters(); + + // + // These masters come from the 333networks community and use the same software + // that emulate the GameSpy protocol -- see https://333networks.com/ + // They are managed by different entities, are independent and sync with eachother. + // + CreateMasterVar(msIndex++, "master.333networks.com", MASTER_DEFAULT_MSPORT, MASTER_DEFAULT_HBPORT); + CreateMasterVar(msIndex++, "master.errorist.eu", MASTER_DEFAULT_MSPORT, MASTER_DEFAULT_HBPORT); + CreateMasterVar(msIndex++, "master.noccer.de", MASTER_DEFAULT_MSPORT, MASTER_DEFAULT_HBPORT); + CreateMasterVar(msIndex++, "master-au.unrealarchive.org", MASTER_DEFAULT_MSPORT, MASTER_DEFAULT_HBPORT); + CreateMasterVar(msIndex++, "master.frag-net.com", MASTER_DEFAULT_MSPORT, MASTER_DEFAULT_HBPORT); + + for (; msIndex < MAX_MASTERS; msIndex++) { + CreateMasterVar(msIndex, "", MASTER_DEFAULT_MSPORT, MASTER_DEFAULT_HBPORT); + } + + num_entries = 0; + + // + // Find and insert valid entries + // + for (i = 0; i < MAX_MASTER_SERVERS; i++) { + master_entry_t *entry = &entries[num_entries]; + + if (com_master_host[i]->string && com_master_host[i]->string[0]) { + entry->host = com_master_host[i]->string; + entry->queryport = com_master_msport[i]->integer; + entry->hbport = com_master_hbport[i]->integer; + num_entries++; + } + } + + return shouldRestart; +} + +void Com_InitGameSpy() +{ + Com_RefreshGameSpyMasters(); + + Cmd_AddCommand("net_gamespy_restart", Com_RestartGameSpy_f); +} + +static void Com_RestartGameSpy_f(void) +{ + Com_RefreshGameSpyMasters(); + +#ifndef DEDICATED + CL_RestartGamespy_f(); +#endif + SV_RestartGamespy_f(); +} + +unsigned int Com_GetNumMasterEntries() +{ + return num_entries; +} + +void Com_GetMasterEntry(int index, master_entry_t *entry) +{ + if (index >= num_entries) { + entry->host = NULL; + entry->hbport = 0; + entry->queryport = 0; + return; + } + + entry->host = com_master_host[index]->string; + entry->queryport = com_master_msport[index]->integer; + entry->hbport = com_master_hbport[index]->integer; +} + +const char *Com_GetMasterHost() +{ + return com_master_host[0]->string; +} + +int Com_GetMasterQueryPort() +{ + return com_master_msport[0]->integer; +} + +int Com_GetMasterHeartbeatPort() +{ + return com_master_hbport[0]->integer; +} diff --git a/code/gamespy/q_gamespy.h b/code/gamespy/q_gamespy.h new file mode 100644 index 00000000..a60baa3e --- /dev/null +++ b/code/gamespy/q_gamespy.h @@ -0,0 +1,42 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// q_gamespy.h -- Common game-specific GameSpy code shared between client and server + +#pragma once + +#include "../qcommon/q_shared.h" + +typedef struct { + const char *host; + int queryport; + int hbport; +} master_entry_t; + +void Com_InitGameSpy(); +qboolean Com_RefreshGameSpyMasters(); + +unsigned int Com_GetNumMasterEntries(); +void Com_GetMasterEntry(int index, master_entry_t* entry); +const char *Com_GetMasterHost(); +int Com_GetMasterQueryPort(); +int Com_GetMasterHeartbeatPort(); diff --git a/code/gamespy/sc/sciInterface.c b/code/gamespy/sc/sciInterface.c index 1bf05252..f572337c 100644 --- a/code/gamespy/sc/sciInterface.c +++ b/code/gamespy/sc/sciInterface.c @@ -9,7 +9,7 @@ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -// This is declared as an extern so it can be overriden when testing +// This is declared as an extern so it can be overridden when testing #define SC_SERVICE_URL_FORMAT "http://%s.comp.pubsvs." GSI_DOMAIN_NAME "/CompetitionService/CompetitionService.asmx" char scServiceURL[SC_SERVICE_MAX_URL_LEN] = ""; diff --git a/code/gamespy/sv_gamespy.c b/code/gamespy/sv_gamespy.c index 61055699..6f2cc451 100644 --- a/code/gamespy/sv_gamespy.c +++ b/code/gamespy/sv_gamespy.c @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -22,36 +22,74 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/q_shared.h" #include "../server/server.h" +#include "../qcommon/q_version.h" #include "sv_gqueryreporting.h" #include "sv_gamespy.h" +#include "q_gamespy.h" #include "gcdkey/gcdkeys.h" +#include "common/gsCommon.h" +#include "common/gsAvailable.h" -static char gamemode[128]; -static qboolean gcdInitialized = qfalse; +static char gamemode[128]; +static qboolean gcdInitialized = qfalse; +static qboolean gcdValid = qfalse; +static qboolean gsRunning = qfalse; +extern GSIACResult __GSIACResult; -static const char *SECRET_GS_KEYS[] = {"M5Fdwc", "h2P1c9", "y32FDc"}; +cvar_t *net_ip = NULL; +cvar_t *net_gamespy_port = NULL; -static const unsigned int GCD_GAME_IDS[] = { +static const char *SECRET_GS_KEYS[] = +{ + "M5Fdwc", + "h2P1c9", + "y32FDc" +}; + +static const unsigned int GCD_GAME_IDS[] = +{ 0, 641, 802, }; -static const char *GS_GAME_NAME[] = {"mohaa", "mohaas", "mohaab"}; +static const char *GS_GAME_NAME[] = +{ + "mohaa", + "mohaas", + "mohaab" +}; + +static const char *GS_GAME_NAME_DEMO[] = +{ + "mohaa", + "mohaas", + "mohaabd" +}; + +static const char *GS_GAME_VERSION[] = +{ + TARGET_GAME_VERSION_MOH "+" PRODUCT_VERSION, + TARGET_GAME_VERSION_MOHTA "+" PRODUCT_VERSION, + TARGET_GAME_VERSION_MOHTT "+" PRODUCT_VERSION, +}; + +static const char* GS_GAME_VERSION_DEMO[] = +{ + TARGET_GAME_VERSION_MOH "+" PRODUCT_VERSION, + "d" TARGET_GAME_VERSION_MOHTA "+" PRODUCT_VERSION, + "d" TARGET_GAME_VERSION_MOHTT_DEMO "+" PRODUCT_VERSION, +}; static const unsigned int GAMESPY_DEFAULT_PORT = 12300; -void qr_send_statechanged(qr_t qrec); -void qr_shutdown(qr_t qrec); -void qr_process_queries(qr_t qrec); - int qr_init( qr_t *qrec, - const char *ip, + const char *ip, int baseport, - const char *gamename, - const char *secret_key, + const char *gamename, + const char *secret_key, qr_querycallback_t qr_basic_callback, qr_querycallback_t qr_info_callback, qr_querycallback_t qr_rules_callback, @@ -59,30 +97,54 @@ int qr_init( void *userdata ); -const char* GS_GetGameKey(unsigned int index) { +const char *GS_GetGameKey(unsigned int index) +{ return SECRET_GS_KEYS[index]; } -const char* GS_GetCurrentGameKey() { +const char *GS_GetCurrentGameKey() +{ return GS_GetGameKey(com_target_game->integer); } -unsigned int GS_GetGameID(unsigned int index) { +unsigned int GS_GetGameID(unsigned int index) +{ return GCD_GAME_IDS[index]; } -unsigned int GS_GetCurrentGameID() { +unsigned int GS_GetCurrentGameID() +{ return GS_GetGameID(com_target_game->integer); } -const char* GS_GetGameName(unsigned int index) { - return GS_GAME_NAME[index]; +const char *GS_GetGameName(unsigned int index) +{ + if (!com_target_demo->integer) { + return GS_GAME_NAME[index]; + } else { + return GS_GAME_NAME_DEMO[index]; + } } -const char* GS_GetCurrentGameName() { +const char *GS_GetCurrentGameName() +{ return GS_GetGameName(com_target_game->integer); } +const char *GS_GetGameVersion(unsigned int index) +{ + if (!com_target_demo->integer) { + return GS_GAME_VERSION[index]; + } else { + return GS_GAME_VERSION_DEMO[index]; + } +} + +const char *GS_GetCurrentGameVersion() +{ + return GS_GetGameVersion(com_target_game->integer); +} + static const char *ConvertMapFilename(const char *mapname) { static char converted[1024]; @@ -98,21 +160,8 @@ static const char *ConvertMapFilename(const char *mapname) static void basic_callback(char *outbuf, int maxlen, void *userdata) { - switch (com_target_game->integer) { - case TG_MOH: - Info_SetValueForKey(outbuf, "gamename", TARGET_GAME_NAME_MOH); - Info_SetValueForKey(outbuf, "gamever", TARGET_GAME_VERSION_MOH); - break; - case TG_MOHTA: - Info_SetValueForKey(outbuf, "gamename", TARGET_GAME_NAME_MOHTA); - Info_SetValueForKey(outbuf, "gamever", TARGET_GAME_VERSION_MOHTA); - break; - case TG_MOHTT: - Info_SetValueForKey(outbuf, "gamename", TARGET_GAME_NAME_MOH); - Info_SetValueForKey(outbuf, "gamever", TARGET_GAME_VERSION_MOHTT); - break; - } - + Info_SetValueForKey(outbuf, "gamename", GS_GetCurrentGameName()); + Info_SetValueForKey(outbuf, "gamever", GS_GetCurrentGameVersion()); Info_SetValueForKey(outbuf, "location", va("%i", sv_location->integer)); if (sv_debug_gamespy->integer) { @@ -127,7 +176,7 @@ static void info_callback(char *outbuf, int maxlen, void *userdata) infostring[0] = 0; Info_SetValueForKey(infostring, "hostname", sv_hostname->string); - Info_SetValueForKey(infostring, "hostport", Cvar_Get("net_port", "12203", 32)->string); + Info_SetValueForKey(infostring, "hostport", Cvar_Get("net_port", "12203", CVAR_LATCH)->string); Info_SetValueForKey(infostring, "mapname", ConvertMapFilename(svs.mapName)); Info_SetValueForKey(infostring, "gametype", g_gametypestring->string); Info_SetValueForKey(infostring, "numplayers", va("%i", SV_NumClients())); @@ -138,7 +187,7 @@ static void info_callback(char *outbuf, int maxlen, void *userdata) Info_SetValueForKey(infostring, "sprinton", Cvar_Get("sv_sprinton", "1", 0)->string); Info_SetValueForKey(infostring, "realism", Cvar_Get("g_realismmode", "0", 0)->string); Info_SetValueForKey(infostring, "pure", va("%i", sv_pure->integer)); - if ((Cvar_VariableIntegerValue("dmflags") & 0x40000) != 0) { + if ((Cvar_VariableIntegerValue("dmflags") & DF_ALLOW_LEAN_MOVEMENT) != 0) { allowlean = 1; } @@ -173,39 +222,60 @@ static void rules_callback(char *outbuf, int maxlen, void *userdata) static void players_callback(char *outbuf, int maxlen, void *userdata) { - int i; - char infostring[128]; - size_t infolen; - size_t currlen = 0; + client_t *cl; + playerState_t *ps; + size_t infolen; + size_t currlen = 0; + int i; + int index; + char infostring[128]; - for (i = 0; i < svs.iNumClients; i++) { - playerState_t *ps = SV_GameClientNum(i); + outbuf[0] = 0; - Com_sprintf( + if (!svs.clients) { + return; + } + + for (i = 0, index = 0; i < svs.iNumClients; i++) { + cl = &svs.clients[i]; + + if (cl->state == CS_FREE) { + // ignore inactive clients + continue; + } + + ps = SV_GameClientNum(i); + + infolen = Com_sprintf( infostring, - 128, + sizeof(infostring), "\\player_%d\\%s\\frags_%d\\%d\\deaths_%d\\%d\\ping_%d\\%d", - i, - svs.clients[i].name, - i, + index, + cl->name, + index, ps->stats[STAT_KILLS], - i, + index, ps->stats[STAT_DEATHS], - i, - svs.clients[i].ping + index, + cl->ping ); - infolen = strlen(infostring); if (currlen + infolen < maxlen) { strcat(outbuf, infostring); currlen += infolen; } + + // + // Fixed in OPM + // Some programs enumerate by testing indexes, and stop iterating if the index doesn't exist + // + index++; } } void SV_GamespyHeartbeat() { - if (!g_gametype->integer || !sv_gamespy->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER || !sv_gamespy->integer) { return; } @@ -218,17 +288,27 @@ void SV_GamespyHeartbeat() void SV_ProcessGamespyQueries() { - if (!g_gametype->integer || !sv_gamespy->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER || !sv_gamespy->integer) { return; } qr_process_queries(NULL); - gcd_think(); + + if (gcdValid) { + // in case the game supports gcd + gcd_think(); + } } void SV_ShutdownGamespy() { - if (!g_gametype->integer || !sv_gamespy->integer) { + if (g_gametype->integer == GT_SINGLE_PLAYER || !sv_gamespy->integer) { + return; + } + + if (!gsRunning) { + // Added in OPM + // Gamespy is not running return; } @@ -236,17 +316,17 @@ void SV_ShutdownGamespy() if (gcdInitialized) { gcd_shutdown(); - gcdInitialized = 0; + gcdInitialized = qfalse; } qr_send_statechanged(NULL); qr_shutdown(NULL); + + gsRunning = qfalse; } qboolean SV_InitGamespy() { - cvar_t *net_ip; - cvar_t *net_gamespy_port; char secret_key[9]; const char *secret_gs_key; const char *gs_game_name; @@ -257,15 +337,15 @@ qboolean SV_InitGamespy() return qfalse; } - secret_gs_key = SECRET_GS_KEYS[com_target_game->integer]; - gcd_game_id = GCD_GAME_IDS[com_target_game->integer]; - gs_game_name = GS_GAME_NAME[com_target_game->integer]; + secret_gs_key = GS_GetCurrentGameKey(); + gcd_game_id = GS_GetCurrentGameID(); + gs_game_name = GS_GetCurrentGameName(); sv_debug_gamespy = Cvar_Get("sv_debuggamespy", "0", 0); sv_location = Cvar_Get("sv_location", "1", CVAR_ARCHIVE); sv_gamespy = Cvar_Get("sv_gamespy", "1", CVAR_LATCH); - if (!sv_gamespy->integer || !g_gametype->integer) { + if (!sv_gamespy->integer || g_gametype->integer == GT_SINGLE_PLAYER) { return qfalse; } @@ -296,13 +376,196 @@ qboolean SV_InitGamespy() qr_send_statechanged(NULL); } + // this will set the GSI as available for cdkey authorization + __GSIACResult = GSIACAvailable; + if (!gcdInitialized) { if (gcd_game_id) { gcd_init(gcd_game_id); + gcdValid = qtrue; } - gcdInitialized = 1; + gcdInitialized = qtrue; } + gsRunning = qtrue; + return qtrue; } + +void SV_CreateGamespyChallenge(char *challenge) +{ + int i; + + for (i = 0; i < 8; i++) { + challenge[i] = rand() % ('Z' - 'A' + 1) + 'A'; // random letters between A and Z + } + challenge[i] = 0; +} + +challenge_t *FindChallengeById(int gameid) +{ + challenge_t *challenge; + int i; + + for (i = 0; i < MAX_CHALLENGES; i++) { + challenge = &svs.challenges[i]; + if (challenge->connected == gameid) { + return challenge; + } + } + + return NULL; +} + +void AuthenticateCallback(int gameid, int localid, int authenticated, char *errmsg, void *instance) +{ + challenge_t *challenge; + qboolean valid = qfalse; + + if (localid || !Q_stricmp(errmsg, "CD Key in use")) { + valid = qtrue; + } + + challenge = FindChallengeById(gameid); + if (valid) { + challenge->cdkeyState = 2; + challenge->pingTime = svs.time; + + SV_NET_OutOfBandPrint(&svs.netprofile, challenge->adr, "challengeResponse %i", challenge->challenge); + } else { + char buf[32]; + + if (!challenge) { + return; + } + + Com_sprintf( + buf, + sizeof(buf), + "%d.%d.%d.%d", + challenge->adr.ip[0], + challenge->adr.ip[1], + challenge->adr.ip[2], + challenge->adr.ip[3] + ); + Com_Printf("%s failed cdkey authorization\n", buf); + challenge->cdkeyState = 3; + // tell the client about the reason + SV_NET_OutOfBandPrint(&svs.netprofile, challenge->adr, "droperror\nServer rejected connection:\n%s", errmsg); + } +} + +void RefreshAuthCallback(int gameid, int localid, int hint, char *challenge, void *instance) {} + +void SV_GamespyAuthorize(netadr_t from, const char *response) +{ + char buf[64]; + challenge_t *challenge = FindChallenge(from, qtrue); + if (!challenge) { + return; + } + + switch (challenge->cdkeyState) { + case CDKS_NONE: + challenge->cdkeyState = CDKS_AUTHENTICATING; + challenge->firstTime = svs.time; + + gcd_authenticate_user( + GS_GetCurrentGameID(), + challenge->gamespyId, + LittleLong(*(unsigned int *)from.ip), + challenge->gsChallenge, + response, + AuthenticateCallback, + RefreshAuthCallback, + NULL + ); + break; + case CDKS_AUTHENTICATING: + // the server can't reach the authentication server + // let the client connect + if (svs.time - challenge->firstTime > 5000) { + Com_DPrintf("authorize server timed out\n"); + challenge->cdkeyState = CDKS_AUTHENTICATED; + challenge->pingTime = svs.time; + SV_NET_OutOfBandPrint(&svs.netprofile, from, "challengeResponse %i", challenge->challenge); + } + break; + case CDKS_AUTHENTICATED: + SV_NET_OutOfBandPrint(&svs.netprofile, from, "challengeResponse %i", challenge->challenge); + break; + case CDKS_FAILED: + // authentication server told the cdkey was invalid + Com_sprintf( + buf, + sizeof(buf), + "%d.%d.%d.%d", + challenge->adr.ip[0], + challenge->adr.ip[1], + challenge->adr.ip[2], + challenge->adr.ip[3] + ); + Com_Printf("%s failed cdkey authorization\n", buf); + // reject the client + SV_NET_OutOfBandPrint(&svs.netprofile, from, "droperror\nServer rejected connection:\nInvalid CD Key"); + break; + default: + break; + } +} + +void SV_RestartGamespy() +{ + if (gsRunning) { + // + // Reinitialize Gamespy + // + SV_ShutdownGamespy(); + SV_InitGamespy(); + } +} + +void SV_RestartGamespy_f() +{ + SV_RestartGamespy(); +} + +void SV_TryRestartGamespy() +{ + if (Com_RefreshGameSpyMasters()) { + SV_RestartGamespy(); + return; + } + + if (net_gamespy_port && net_gamespy_port->latchedString) { + SV_RestartGamespy(); + return; + } + + if (sv_gamespy && sv_gamespy->latchedString) { + SV_RestartGamespy(); + return; + } +} + +unsigned int qr_get_num_masters() +{ + return Com_GetNumMasterEntries(); +} + +const char *qr_get_master_host(int index) +{ + master_entry_t entry; + Com_GetMasterEntry(index, &entry); + + return entry.host; +} + +int qr_get_master_port(int index) +{ + master_entry_t entry; + Com_GetMasterEntry(index, &entry); + + return entry.hbport; +} diff --git a/code/gamespy/sv_gamespy.h b/code/gamespy/sv_gamespy.h index 5d62eaeb..769a8afe 100644 --- a/code/gamespy/sv_gamespy.h +++ b/code/gamespy/sv_gamespy.h @@ -1,5 +1,31 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// sv_gamespy.h -- Game-specific server GameSpy code + #pragma once +#include "q_gamespy.h" + #ifdef __cplusplus extern "C" { #endif @@ -11,6 +37,16 @@ extern const char* GS_GetCurrentGameKey(); extern unsigned int GS_GetCurrentGameID(); extern const char* GS_GetCurrentGameName(); +void SV_CreateGamespyChallenge(char* challenge); +void SV_GamespyAuthorize(netadr_t from, const char* response); +void SV_GamespyHeartbeat(); +void SV_ProcessGamespyQueries(); +qboolean SV_InitGamespy(); +void SV_ShutdownGamespy(); +void SV_RestartGamespy(); +void SV_RestartGamespy_f(); +void SV_TryRestartGamespy(); + #ifdef __cplusplus } #endif diff --git a/code/gamespy/sv_gqueryreporting.c b/code/gamespy/sv_gqueryreporting.c index 7bf666ad..0196a538 100644 --- a/code/gamespy/sv_gqueryreporting.c +++ b/code/gamespy/sv_gqueryreporting.c @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,329 +20,776 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -#include "../qcommon/q_shared.h" +/****** +.c +GameSpy Query & Reporting SDK + +Copyright 2000 GameSpy Industries, Inc + +18002 Skypark Circle +Irvine, CA 92614 +(949)798-4200 +Fax(949)798-4299 +****** + + + Please see the GameSpy Query & Reporting SDK documentation for more + information + + Updated 6/9/99 - DDW + Added get_sockaddrin function, and use for resolving + Made portable with additions from CEngine code + Double check that we don't bind to localhost (instead use INADDR_ANY) + + Updated 9/1/99 - DDW + Add the ability to pass in 0 as the queryport, to allocate it + automatically. + + Updated 10/11/99 - DDW + TCP Heartbeat support (#define TCP_HEARTBEATS) + + Updated 11/20/99 - BGW + Split goa_process_queries into two functions: goa_check_queries() and + goa_check_send_heartbeat(). + + Updated 3/19/00 - DDW + Added Dreamcast CE Support + + Updated 4/5/00 - DDW + Added Dreamcast Shinobi Support (use sendto/recvfrom for UDP sockets to work + around connect bug) + + Updated 4/17/00 - DDW + Use a single socket for heartbeats/queries (conserve sockets on DC) + + Updated 5/23/00 - DDW + Developer SDK renamed "Query & Reporting SDK" + Encapsulate global data in a structure so multiple simultaneous instances + can run in the same process. Most developers can just pass NULL for the extra + parameter. + qr_init now scans for an open port, starting from a base port. + heartbeats are sent every 30 seconds now until the first query is received, + then they are sent every 5 minutes as recommened by the developer spec + this helps remove the problem of dropped heartbeats causing a server to not + show up for 5 minutes. + + Updated 10/2/00 - DDW + Added qr_process_queries_no_heartbeat, so you can advertise a server on the + LAN only. + Updated 11/9/00 - DDW + Use common alloc/re-alloc functions +******/ + +/******** +INCLUDES +********/ +#if defined(applec) || defined(THINK_C) || defined(__MWERKS__) && !defined(__KATANA__) && !defined(__mips64) +#include "::nonport.h" +#else +#include "nonport.h" +#endif #include "sv_gqueryreporting.h" +#include +#include -#include "common/gsPlatformSocket.h" -#include "common/gsPlatformUtil.h" -#include "gutil.h" +#include +#if !defined(UNDER_CE) && !defined(__KATANA__) +#include +#else +#define assert(a) +#endif -static char *queries[] = {"basic", "info", "rules", "players", "status", "packets", "echo", "secure"}; +#ifdef __cplusplus +extern "C" { +#endif -static qr_implementation_t static_rec; -static qr_implementation_t *current_rec = &static_rec; -struct sockaddr_in hbaddr; -char qr_hostname[64]; +/***** +TCP_HEARTBEATS +Define this to use reliable heartbeats. Only needed for certain +classes of peer-to-peer games, please contact us if you are unsure +whether you need this or not. +******/ +//#define TCP_HEARTBEATS -void qr_check_queries(qr_t qrec); -void qr_check_send_heartbeat(qr_t qrec); -static void parse_query(qr_t qrec, char *query, struct sockaddr *sender); -static void send_heartbeat(qr_t qrec, int statechanged); +/******** +TYPEDEFS +********/ +typedef unsigned char uchar; +#if defined(_LINUX) || defined(__linux__) +typedef unsigned int qrsocklen_t; +#else +typedef int qrsocklen_t; +#endif -void qr_process_queries(qr_t qrec) +typedef enum { - if (!qrec) { - qrec = current_rec; + qtunknown, + qtbasic, + qtinfo, + qtrules, + qtplayers, + qtstatus, + qtpackets, + qtecho, + qtsecure +} query_t; + +typedef struct qr_implementation_s +{ + SOCKET querysock; + SOCKET hbsock; + char gamename[64]; + char secret_key[128]; + qr_querycallback_t qr_basic_callback; + qr_querycallback_t qr_info_callback; + qr_querycallback_t qr_rules_callback; + qr_querycallback_t qr_players_callback; + unsigned long lastheartbeat; + int queryid; + int packetnumber; + int qport; + char no_query; + struct sockaddr_in hbaddr; + qr_cdkey_process_t cdkeyprocess; + void* udata; +}* qr_t; + +/******** +VARS +********/ +static const char* queries[] = {"", "basic", "info", "rules", "players", "status", "packets", "echo", "secure"}; +static struct sockaddr_in hbaddr; +struct qr_implementation_s static_rec = {INVALID_SOCKET, INVALID_SOCKET}; +static qr_t current_rec = &static_rec; +//char qr_hostname[64] = MASTER_ADDR; + +//static struct sockaddr_in MasterList[8]; +static struct sockaddr_in *MasterList = NULL; +static char keyvalue[8192]; +static int MasterCount; +static int MasterMaxCount; + +/******** +PROTOTYPES +********/ +static void send_heartbeat(qr_t qrec, int statechanged); +static void qr_parse_query(qr_t qrec, char* query, int len, struct sockaddr* sender); +static int do_connect(SOCKET sock, char* addr, int port, struct sockaddr_in* hbaddr); +static int do_connect_multi(); +void qr_check_queries(qr_t qrec); +void qr_check_send_heartbeat(qr_t qrec); + +static void init_qrec(qr_t* qrec, + int baseport, + SOCKET hbsock, + SOCKET querysock, + const char* gamename, + const char* secret_key, + qr_querycallback_t qr_basic_callback, + qr_querycallback_t qr_info_callback, + qr_querycallback_t qr_rules_callback, + qr_querycallback_t qr_players_callback, + void* userdata); + +/****************************************************************************/ +/* PUBLIC FUNCTIONS */ +/****************************************************************************/ + +/* qr_init: Initializes the sockets, etc. Returns an error value +if an error occured, or 0 otherwise */ +int qr_init(qr_t* qrec, + const char* ip, + int baseport, + const char* gamename, + const char* secret_key, + qr_querycallback_t qr_basic_callback, + qr_querycallback_t qr_info_callback, + qr_querycallback_t qr_rules_callback, + qr_querycallback_t qr_players_callback, + void* userdata) +{ + int lasterror; + struct sockaddr_in saddr; + qrsocklen_t saddrlen; + int maxport; + SOCKET querysock; + SOCKET hbsock; + + if (qrec != NULL) //init it to empty + *qrec = NULL; + //create our sockets + SocketStartUp(); + + querysock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +#ifdef TCP_HEARTBEATS + hbsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); +#else + hbsock = querysock; //share the socket +#endif + if (INVALID_SOCKET == querysock || INVALID_SOCKET == hbsock) { + return E_GOA_WSOCKERROR; } + lasterror = 0; + maxport = baseport + NUM_PORTS_TO_TRY; + while (baseport < maxport) { + get_sockaddrin(ip, baseport, &saddr, NULL); + if (saddr.sin_addr.s_addr == htonl(0x7F000001)) //localhost -- we don't want that! + saddr.sin_addr.s_addr = INADDR_ANY; + + lasterror = bind(querysock, (struct sockaddr*)&saddr, sizeof(saddr)); + if (lasterror == 0) + break; //we found a port + baseport++; + } + + if (lasterror != 0) //we weren't able to find a port + { + return E_GOA_BINDERROR; + } + + if (baseport == 0) //we bound it dynamically + { + saddrlen = sizeof(saddr); + lasterror = getsockname(querysock, (struct sockaddr*)&saddr, &saddrlen); + if (lasterror) + return E_GOA_BINDERROR; + baseport = ntohs(saddr.sin_port); + } + + init_qrec(qrec, + baseport, + hbsock, + querysock, + gamename, + secret_key, + qr_basic_callback, + qr_info_callback, + qr_rules_callback, + qr_players_callback, + userdata); + + if (!qrec) { + qrec = ¤t_rec; + } + + return do_connect_multi(); +} + +void init_qrec(qr_t* qrec, + int qport, + SOCKET hbsock, + SOCKET querysock, + const char* gamename, + const char* secret_key, + qr_querycallback_t qr_basic_callback, + qr_querycallback_t qr_info_callback, + qr_querycallback_t qr_rules_callback, + qr_querycallback_t qr_players_callback, + void* userdata) +{ + qr_t cr; + + if (qrec == NULL) { + cr = &static_rec; + } else { + *qrec = (qr_t)malloc(sizeof(struct qr_implementation_s)); + cr = *qrec; + } + + strcpy(cr->gamename, gamename); + strcpy(cr->secret_key, secret_key); + + cr->qport = qport; + cr->lastheartbeat = 0; + cr->hbsock = hbsock; + cr->querysock = querysock; + cr->packetnumber = 0; + cr->queryid = 1; + cr->no_query = 1; + cr->udata = userdata; + cr->qr_basic_callback = qr_basic_callback; + cr->qr_info_callback = qr_info_callback; + cr->qr_players_callback = qr_players_callback; + cr->qr_rules_callback = qr_rules_callback; + cr->cdkeyprocess = NULL; +} + +int qr_init_socket(qr_t* qrec, + unsigned int s, + const char* gamename, + const char* secret_key, + qr_querycallback_t qr_basic_callback, + qr_querycallback_t qr_info_callback, + qr_querycallback_t qr_rules_callback, + qr_querycallback_t qr_players_callback, + void* userdata) +{ + if (qrec) { + *qrec = NULL; + } + + SocketStartUp(); + init_qrec(qrec, + 0, + s, + s, + gamename, + secret_key, + qr_basic_callback, + qr_info_callback, + qr_rules_callback, + qr_players_callback, + userdata); + + return do_connect_multi(); +} + +/* qr_process_queries: Processes any waiting queries, and sends a +heartbeat if 5 minutes have elapsed */ +void qr_process_queries(qr_t qrec) +{ + if (qrec == NULL) + qrec = current_rec; qr_check_send_heartbeat(qrec); qr_check_queries(qrec); } +/* qr_process_queries_no_heartbeat: Processes any waiting queries, but +never sends heartbeats */ void qr_process_queries_no_heartbeat(qr_t qrec) { - if (!qrec) { + if (qrec == NULL) qrec = current_rec; - } - qr_check_queries(qrec); } +/* qr_check_queries: Processes any waiting queries */ void qr_check_queries(qr_t qrec) { -#define INBUF_LEN 256 - static char indata[INBUF_LEN]; //256 byte input buffer + static char indata[INBUF_LEN]; //256 byte input buffer struct sockaddr_in saddr; - int error; + qrsocklen_t saddrlen = sizeof(struct sockaddr_in); + fd_set set; + struct timeval timeout = {0, 0}; + int error; -#if defined(_LINUX) - unsigned int saddrlen = sizeof(struct sockaddr_in); -#else - int saddrlen = sizeof(struct sockaddr_in); -#endif + if (0 == qrec->qport) + return; - while (CanReceiveOnSocket((SOCKET)qrec->hbsock)) { + FD_ZERO(&set); + FD_SET(qrec->querysock, &set); + + while (1) { + error = select(FD_SETSIZE, &set, NULL, NULL, &timeout); + if (gsiSocketIsError(error) || error == 0) + return; //else we have data - error = (int)recvfrom((SOCKET)qrec->hbsock, indata, (INBUF_LEN - 1), 0, (struct sockaddr *)&saddr, &saddrlen); - + error = recvfrom(qrec->querysock, indata, INBUF_LEN - 1, 0, (struct sockaddr*)&saddr, &saddrlen); if (gsiSocketIsNotError(error)) { indata[error] = '\0'; - parse_query(qrec, indata, (struct sockaddr *)&saddr); + qr_parse_query(qrec, indata, error, (struct sockaddr*)&saddr); } } } +/* check_send_heartbeat: Perform any scheduled outgoing +heartbeats, (every 5 minutes) */ void qr_check_send_heartbeat(qr_t qrec) { - unsigned long tc; + unsigned long tc = current_time(); - tc = current_time(); + if (INVALID_SOCKET == qrec->hbsock) + return; //no sockets to work with! - if ((SOCKET)qrec->hbsock != INVALID_SOCKET) { - if (tc - qrec->lastheartbeat <= 300000 && qrec->lastheartbeat && tc >= qrec->lastheartbeat) { - if (qrec->no_query > 0 && tc - qrec->lastheartbeat > 30000) { - send_heartbeat(qrec, 0); - if (qrec->no_query++ > 10) { - qrec->no_query = 0; - } - } - } else { - send_heartbeat(qrec, 0); - } + //check if we need to send a heartbet + if (tc - qrec->lastheartbeat > HB_TIME || qrec->lastheartbeat == 0 || tc < qrec->lastheartbeat) + send_heartbeat(qrec, 0); + else if (qrec->no_query > 0 + && tc - qrec->lastheartbeat > FIRST_HB_TIME) { //check to see if we haven't gotten a query yet + send_heartbeat(qrec, 0); + qrec->no_query++; + if (qrec->no_query > MAX_FIRST_COUNT) + qrec->no_query = 0; //stop trying to get first query } } +/* qr_send_statechanged: Sends a statechanged heartbeat, call when +your gamemode changes */ void qr_send_statechanged(qr_t qrec) { - if (!qrec) { + if (qrec == NULL) qrec = current_rec; - } send_heartbeat(qrec, 1); } +void qr_send_exiting(qr_t qrec) +{ + if (qrec == NULL) + qrec = current_rec; + send_heartbeat(qrec, 2); +} + +/* qr_shutdown: Cleans up the sockets and shuts down */ void qr_shutdown(qr_t qrec) { - if (qrec == NULL) { + if (qrec == NULL) qrec = current_rec; + if (INVALID_SOCKET != qrec->querysock && qrec->qport != 0) { + closesocket(qrec->querysock); } - if (INVALID_SOCKET != (SOCKET)qrec->hbsock && (SOCKET)qrec->querysock) //if we own the socket - { - closesocket((SOCKET)qrec->hbsock); + if (INVALID_SOCKET != qrec->hbsock && qrec->hbsock != qrec->querysock) { + closesocket(qrec->hbsock); } - qrec->hbsock = (void *)INVALID_SOCKET; + qrec->hbsock = INVALID_SOCKET; + qrec->querysock = INVALID_SOCKET; qrec->lastheartbeat = 0; - if (qrec->querysock) //if we own the socket + if (qrec != &static_rec) //need to gsifree it, it was dynamically allocated { - SocketShutDown(); + gsifree(qrec); } - if (qrec != &static_rec) //need to free it, it was dynamically allocated - { - free(qrec); + + if (MasterList) { + gsifree(MasterList); + MasterList = NULL; } + + MasterCount = 0; + + SocketShutDown(); +} + +/****************************************************************************/ + +static int do_connect(SOCKET sock, char* addr, int port, struct sockaddr_in* hbaddr) +{ +#ifdef TCP_HEARTBEATS + struct sockaddr_in saddr; + + get_sockaddrin(addr, port, &saddr, NULL); + + if (connect(sock, (struct sockaddr*)&saddr, sizeof(saddr)) == SOCKET_ERROR) { + return E_GOA_CONNERROR; + } + + add_master(&saddr); +#else + get_sockaddrin(addr, port, hbaddr, NULL); + add_master(hbaddr); +#endif + return 0; +} + +static int do_connect_multi() +{ + int i; + + MasterMaxCount = qr_get_num_masters(); + if (MasterList) { + gsifree(MasterList); + MasterList = NULL; + } + + MasterList = gsimalloc(sizeof(struct sockaddr_in) * MasterMaxCount); + MasterCount = 0; + + for(i = 0; i < MasterMaxCount; i++) { + struct sockaddr_in hbaddr; + if (get_sockaddrin(qr_get_master_host(i), qr_get_master_port(i), &hbaddr, NULL)) { + // Valid, add it + add_master(&hbaddr); + } + } + + return 0; } /* Return a sockaddrin for the given host (numeric or DNS) and port) Returns the hostent in savehent if it is not NULL */ -static int get_sockaddrin(const char *host, int port, struct sockaddr_in *saddr, struct hostent **savehent) +int get_sockaddrin(const char* host, int port, struct sockaddr_in* saddr, struct hostent** savehent) { - struct hostent *hent = NULL; + struct hostent* hent; + char broadcast_t[] = { + '2', '5', '5', '.', '2', '5', '5', '.', '2', '5', '5', '.', '2', '5', '5', '\0'}; //255.255.255.255 + hent = 0; + memset(saddr, 0, sizeof(struct sockaddr_in)); saddr->sin_family = AF_INET; - saddr->sin_port = htons((unsigned short)port); - if (host == NULL) { + saddr->sin_port = htons((unsigned short)port); + if (host == NULL) saddr->sin_addr.s_addr = INADDR_ANY; - } else { + else saddr->sin_addr.s_addr = inet_addr(host); - } - if (saddr->sin_addr.s_addr == INADDR_NONE && strcmp(host, "255.255.255.255") != 0) { + if (saddr->sin_addr.s_addr == INADDR_NONE && strcmp(host, broadcast_t) != 0) { hent = gethostbyname(host); - if (!hent) { + if (!hent) return 0; - } - saddr->sin_addr.s_addr = *(unsigned int *)hent->h_addr_list[0]; + saddr->sin_addr.s_addr = *(u_long*)hent->h_addr_list[0]; } - if (savehent != NULL) { + if (savehent != NULL) *savehent = hent; - } return 1; } /* value_for_key: this returns a value for a certain key in s, where s is a string -containing key\value pairs. If the key does not exist, it returns NULL. +containing key\value pairs. If the key does not exist, it returns NULL. Note: the value is stored in a common buffer. If you want to keep it, make a copy! */ -static char *value_for_key(const char *s, const char *key) +static char* value_for_key(const char* s, const char* key) { - static int valueindex; - char *pos, *pos2; - char keyspec[256] = "\\"; + static int valueindex; + char *pos, *pos2; + char keyspec[256] = "\\"; static char value[2][256]; valueindex ^= 1; strcat(keyspec, key); strcat(keyspec, "\\"); pos = strstr(s, keyspec); - if (!pos) { + if (!pos) return NULL; - } pos += strlen(keyspec); pos2 = value[valueindex]; - while (*pos && *pos != '\\') { + while (*pos && *pos != '\\') *pos2++ = *pos++; - } *pos2 = '\0'; return value[valueindex]; } -static void packet_send(qr_t qrec, struct sockaddr *addr, char *buffer) +/*****************************************************************************/ +/* Various encryption / encoding routines */ + +#ifndef _GUTIL +#define _GUTIL +static void swap_byte(uchar* a, uchar* b) +{ + uchar swapByte; + + swapByte = *a; + *a = *b; + *b = swapByte; +} + +static uchar encode_ct(uchar c) +{ + if (c < 26) + return ('A' + c); + if (c < 52) + return ('a' + c - 26); + if (c < 62) + return ('0' + c - 52); + if (c == 62) + return ('+'); + if (c == 63) + return ('/'); + + return 0; +} + +void gs_encode(uchar* ins, int size, uchar* result) +{ + int i, pos; + uchar trip[3]; + uchar kwart[4]; + + i = 0; + while (i < size) { + for (pos = 0; pos <= 2; pos++, i++) + if (i < size) + trip[pos] = *ins++; + else + trip[pos] = '\0'; + kwart[0] = (trip[0]) >> 2; + kwart[1] = (((trip[0]) & 3) << 4) + ((trip[1]) >> 4); + kwart[2] = (((trip[1]) & 15) << 2) + ((trip[2]) >> 6); + kwart[3] = (trip[2]) & 63; + for (pos = 0; pos <= 3; pos++) + *result++ = encode_ct(kwart[pos]); + } + *result = '\0'; +} + +void gs_encrypt(uchar* key, int key_len, uchar* buffer_ptr, int buffer_len) +{ + short counter; + uchar x, y, xorIndex; + uchar state[256]; + + for (counter = 0; counter < 256; counter++) + state[counter] = (uchar)counter; + + x = 0; + y = 0; + for (counter = 0; counter < 256; counter++) { + y = (key[x] + state[counter] + y) % 256; + x = (x + 1) % key_len; + swap_byte(&state[counter], &state[y]); + } + + x = 0; + y = 0; + for (counter = 0; counter < buffer_len; counter++) { + x = (x + buffer_ptr[counter] + 1) % 256; + y = (state[x] + y) % 256; + swap_byte(&state[x], &state[y]); + xorIndex = (state[x] + state[y]) % 256; + buffer_ptr[counter] ^= state[xorIndex]; + } +} +/*****************************************************************************/ +#endif + +/* packet_send: sends a key\value packet. Appends the queryid +key\value pair. Clears the buffer */ +static void packet_send(qr_t qrec, struct sockaddr* addr, char* buffer) { char keyvalue[80]; - if (!strlen(buffer)) { - return; - } - - sprintf(keyvalue, "\\queryid\\%d.%d", qrec->queryid, qrec->packetnumber++); + if (strlen(buffer) == 0) + return; //dont need to send an empty one! + qrec->packetnumber++; //packet numbers start at 1 + snprintf(keyvalue, sizeof(keyvalue), "\\queryid\\%d.%d", qrec->queryid, qrec->packetnumber); strcat(buffer, keyvalue); - - sendto((SOCKET)qrec->querysock, buffer, (int)strlen(buffer), 0, addr, 16); - *buffer = 0; + sendto(qrec->querysock, buffer, (int)strlen(buffer), 0, addr, sizeof(struct sockaddr_in)); + buffer[0] = '\0'; } -static void buffer_send(qr_t qrec, struct sockaddr *sender, char *buffer, char *newdata) +/* buffer_send: appends buffer with newdata. If the combined +size would be too large, it flushes buffer first. Space is reserved +on the total size to allow for the queryid key\value */ +static void buffer_send(qr_t qrec, struct sockaddr* sender, char* buffer, char* newdata) { - int bcount; - int i; - char *lastkey; - char *pos; + char *pos, *lastkey; + int bcount = 0; - bcount = 0; - if (strlen(newdata) + strlen(buffer) < 1350) { + if (strlen(buffer) + strlen(newdata) < MAX_DATA_SIZE - 50) { strcat(buffer, newdata); - return; - } - - pos = newdata; - while (strlen(pos) > 1350) { - lastkey = pos; - - for (i = 0; i < 1350; ++i) { - if (pos[i] == '\\') { - if (!(bcount % 2)) { - lastkey = pos + i; + } else { + if (strlen(newdata) > MAX_DATA_SIZE - 50) //incoming data is too big already! + { + lastkey = pos = newdata; + while (pos - newdata < MAX_DATA_SIZE - 50) { + if ('\\' == *pos) { + if (bcount % 2 == 0) + lastkey = pos; + bcount++; } - - ++bcount; + pos++; } - } - - if (lastkey == pos) { - return; - } - - *lastkey = 0; - buffer_send(qrec, sender, buffer, pos); - *lastkey = '\\'; - pos = lastkey; - bcount = 0; - - if (strlen(buffer) + strlen(lastkey) < 1350) { - strcat(buffer, pos); - return; + if (lastkey == newdata) + return; //endless loop - single key was too big! + *lastkey = '\0'; + buffer_send(qrec, sender, buffer, newdata); + *lastkey = '\\'; + buffer_send(qrec, sender, buffer, lastkey); //send the rest! + } else { + packet_send(qrec, sender, buffer); + strcpy(buffer, newdata); } } - - packet_send(qrec, sender, buffer); - strcpy(buffer, pos); } -static void send_basic(qr_t qrec, struct sockaddr *sender, char *outbuf) +/* send_basic: sends a response to the basic query */ +static void send_basic(qr_t qrec, struct sockaddr* sender, char* outbuf) { - char keyvalue[1400] = {0}; + char keyvalue[BUF_SIZE] = ""; - qrec->qr_basic_callback(keyvalue, 1400, qrec->udata); + assert(qrec->qr_basic_callback); + qrec->qr_basic_callback(keyvalue, sizeof(keyvalue), qrec->udata); buffer_send(qrec, sender, outbuf, keyvalue); } -static void send_info(qr_t qrec, struct sockaddr *sender, char *outbuf) +/* send_info: sends a response to the info query */ +static void send_info(qr_t qrec, struct sockaddr* sender, char* outbuf) { - char keyvalue[1400] = {0}; + char keyvalue[BUF_SIZE] = ""; - qrec->qr_info_callback(keyvalue, 1400, qrec->udata); + assert(qrec->qr_info_callback); + qrec->qr_info_callback(keyvalue, sizeof(keyvalue), qrec->udata); buffer_send(qrec, sender, outbuf, keyvalue); } -static void send_rules(qr_t qrec, struct sockaddr *sender, char *outbuf) +/* send_rules: sends a response to the rules query. */ +static void send_rules(qr_t qrec, struct sockaddr* sender, char* outbuf) { - char keyvalue[1400] = {0}; + char keyvalue[BUF_SIZE] = ""; - qrec->qr_rules_callback(keyvalue, 1400, qrec->udata); + assert(qrec->qr_rules_callback); + qrec->qr_rules_callback(keyvalue, sizeof(keyvalue), qrec->udata); buffer_send(qrec, sender, outbuf, keyvalue); } -static void send_players(qr_t qrec, struct sockaddr *sender, char *outbuf) +/* send_players: sends the players and their information.*/ +static void send_players(qr_t qrec, struct sockaddr* sender, char* outbuf) { - char keyvalue[1400] = {0}; - - qrec->qr_players_callback(keyvalue, 1400, qrec->udata); + assert(qrec->qr_players_callback); + qrec->qr_players_callback(keyvalue, sizeof(keyvalue), qrec->udata); buffer_send(qrec, sender, outbuf, keyvalue); } -static void send_echo(qr_t qrec, struct sockaddr *sender, char *outbuf, const char *echostr) +/* send_echo: bounces the echostr back to sender +Note: you should always make sure that your echostr doesn't exceed the MAX_DATA_SIZE*/ +static void send_echo(qr_t qrec, struct sockaddr* sender, char* outbuf, char* echostr) { - char keyvalue[1400] = {0}; + char keyvalue[MAX_DATA_SIZE]; - if (strlen(echostr) <= 50) { - sprintf(keyvalue, "\\echoresponse\\%s", echostr); - buffer_send(qrec, sender, outbuf, keyvalue); - } + if (strlen(echostr) > MAX_DATA_SIZE - 50) + return; + snprintf(keyvalue, sizeof(keyvalue), "\\echo\\%s", echostr); + buffer_send(qrec, sender, outbuf, keyvalue); } -static void send_final(qr_t qrec, struct sockaddr *sender, char *outbuf, char *validation) +/* send_final: sends the remaining data in outbuf. Appends the final +key\value to the end. Also adds validation if required. */ +static void send_final(qr_t qrec, struct sockaddr* sender, char* outbuf, char* validation) { char keyvalue[256]; - char encrypted_val[128]; + char encrypted_val[128]; //don't need to null terminate char encoded_val[200]; - int keylen; + int keylen; - if (*validation) { + if (validation[0]) { keylen = (int)strlen(validation); - - if (keylen > 128) { + if (keylen > 128) return; - } - strcpy(encrypted_val, validation); - - gs_encrypt((uchar *)qrec->secret_key, (int)strlen(qrec->secret_key), encrypted_val, keylen); - gs_encode(encrypted_val, keylen, encoded_val); - - sprintf(keyvalue, "\\validate\\%s", encoded_val); + gs_encrypt((uchar*)qrec->secret_key, (int)strlen(qrec->secret_key), (uchar*)encrypted_val, keylen); + gs_encode((uchar*)encrypted_val, keylen, (uchar*)encoded_val); + snprintf(keyvalue, sizeof(keyvalue), "\\validate\\%s", encoded_val); buffer_send(qrec, sender, outbuf, keyvalue); } - sprintf(keyvalue, "\\final\\"); + snprintf(keyvalue, sizeof(keyvalue), "\\final\\"); buffer_send(qrec, sender, outbuf, keyvalue); packet_send(qrec, sender, outbuf); } -static void parse_query(qr_t qrec, char *query, struct sockaddr *sender) +/* parse_query: parse an incoming query (which may contain 1 or more +individual queries) and reply to each query */ +static void qr_parse_query(qr_t qrec, char* query, int len, struct sockaddr* sender) { - query_t querytype = qtunknown; - char buffer[1400] = {0}; - const char *value; - char validation[256] = {0}; + int querytype; + char buffer[MAX_DATA_SIZE] = ""; + char* value; + char validation[256] = ""; - if (!qrec) { + if (qrec == NULL) qrec = current_rec; - } - - if (*query == ';') { - // custom handler - qrec->qr_custom_handler(query, sender); + if (query[0] == 0x3B) /* a cdkey query */ + { + if (qrec->cdkeyprocess != NULL) { + qrec->cdkeyprocess(query, len, sender); + } return; } - qrec->packetnumber = 0; qrec->queryid++; - - if (qrec->no_query > 0) { + qrec->packetnumber = 0; + if (qrec->no_query > 0) qrec->no_query = 0; - } - for (querytype = qtbasic; querytype <= qtsecure; ++querytype) { - value = value_for_key(query, queries[querytype]); - if (value) { + for (querytype = qtbasic; querytype <= qtsecure; querytype++) { + if ((value = value_for_key(query, queries[querytype]))) switch (querytype) { case qtbasic: send_basic(qrec, sender, buffer); @@ -363,6 +810,7 @@ static void parse_query(qr_t qrec, char *query, struct sockaddr *sender) send_players(qrec, sender, buffer); break; case qtpackets: + /*note: "packets" is NOT a real query type. It is simply here to illustrate how a large query would look if broken into packets */ send_basic(qrec, sender, buffer); packet_send(qrec, sender, buffer); send_info(qrec, sender, buffer); @@ -372,160 +820,65 @@ static void parse_query(qr_t qrec, char *query, struct sockaddr *sender) send_players(qrec, sender, buffer); break; case qtecho: + //note: \echo\value is the syntax here send_echo(qrec, sender, buffer, value); break; case qtsecure: strcpy(validation, value); break; - default: - continue; + case qtunknown: + break; } - } } - send_final(qrec, sender, buffer, validation); } +int get_master_count() +{ + return MasterCount; +} + +void clear_master_list() +{ + memset(MasterList, 0, sizeof(MasterList)); + MasterCount = 0; +} + +void add_master(struct sockaddr_in* addr) +{ + int i; + for (i = 0; i < MasterCount; i++) { + if (memcmp(addr, &MasterList[i], sizeof(MasterList[i])) == 0) { + return; + } + } + if (i == MasterMaxCount) { + return; + } else { + MasterList[i] = *addr; + MasterCount++; + } +} + +/* send_heartbeat: Sends a heartbeat to the gamemaster, +adds \statechanged\ if statechanged != 0 */ static void send_heartbeat(qr_t qrec, int statechanged) { char buf[256]; + int ret; + int i; - sprintf(buf, "\\heartbeat\\%d\\gamename\\%s", qrec->qport, qrec->gamename); + snprintf(buf, sizeof(buf), "\\heartbeat\\%d\\gamename\\%s", qrec->qport, qrec->gamename); + if (statechanged) + snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "\\statechanged\\"); - if (statechanged) { - sprintf(buf + strlen(buf), "\\statechanged\\%d", statechanged); + for (i = 0; i < MasterCount; i++) { + ret = sendto(qrec->hbsock, buf, (int)strlen(buf), 0, (struct sockaddr*)&MasterList[i], sizeof(MasterList[i])); } - sendto((SOCKET)qrec->hbsock, buf, (int)strlen(buf), 0, (const struct sockaddr *)&qrec->master_saddr, 16); qrec->lastheartbeat = current_time(); } -static int do_connect(void *sock, char *addr, int port, struct sockaddr_in *master_saddr) -{ - get_sockaddrin(addr, port, master_saddr, NULL); - return 0; +#ifdef __cplusplus } - -void init_qrec( - qr_t *qrec, - int baseport, - SOCKET hbsock, - SOCKET querysock, - const char *gamename, - const char *secret_key, - qr_querycallback_t qr_basic_callback, - qr_querycallback_t qr_info_callback, - qr_querycallback_t qr_rules_callback, - qr_querycallback_t qr_players_callback, - void *userdata -) -{ - qr_t qr; - - if (qrec) { - qr = (qr_t)malloc(sizeof(qr_implementation_t)); - *qrec = qr; - } else { - qr = &static_rec; - } - - strcpy(qr->gamename, gamename); - strcpy(qr->secret_key, secret_key); - - qr->qport = baseport; - qr->hbsock = (void *)hbsock; - qr->querysock = (void *)querysock; - qr->queryid = 1; - qr->no_query = 1; - qr->udata = userdata; - qr->qr_basic_callback = qr_basic_callback; - qr->qr_info_callback = qr_info_callback; - qr->lastheartbeat = 0; - qr->packetnumber = 0; - qr->qr_players_callback = qr_players_callback; - qr->qr_rules_callback = qr_rules_callback; - qr->qr_custom_handler = 0; -} - -#define NUM_PORTS_TO_TRY 100 - -int qr_init( - qr_t *qrec, - const char *ip, - int baseport, - const char *gamename, - const char *secret_key, - qr_querycallback_t qr_basic_callback, - qr_querycallback_t qr_info_callback, - qr_querycallback_t qr_rules_callback, - qr_querycallback_t qr_players_callback, - void *userdata -) -{ - struct sockaddr_in saddr; - SOCKET hbsock; - int maxport; - int lasterror = 0; - -#if defined(_LINUX) - unsigned int saddrlen; -#else - int saddrlen; #endif - - hbsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (hbsock == INVALID_SOCKET) { - return 1; - } - - maxport = baseport + NUM_PORTS_TO_TRY; - while (baseport < maxport) { - get_sockaddrin(ip, baseport, &saddr, NULL); - if (saddr.sin_addr.s_addr == htonl(0x7F000001)) { //localhost -- we don't want that! - saddr.sin_addr.s_addr = INADDR_ANY; - } - - lasterror = bind(hbsock, (struct sockaddr *)&saddr, sizeof(saddr)); - if (lasterror == 0) { - break; //we found a port - } - baseport++; - } - - if (lasterror != 0) //we weren't able to find a port - { - return 2; - } - - if (baseport == 0) //we bound it dynamically - { - saddrlen = sizeof(saddr); - - lasterror = getsockname(hbsock, (struct sockaddr *)&saddr, &saddrlen); - - if (lasterror) { - return 2; - } - baseport = ntohs(saddr.sin_port); - } - - init_qrec( - qrec, - baseport, - hbsock, - hbsock, - gamename, - secret_key, - qr_basic_callback, - qr_info_callback, - qr_rules_callback, - qr_players_callback, - userdata - ); - - if (!qrec) { - qrec = ¤t_rec; - } - - return do_connect((void *)hbsock, MASTER_SERVER_HOST, 27900, &(*qrec)->master_saddr); -} diff --git a/code/gamespy/sv_gqueryreporting.h b/code/gamespy/sv_gqueryreporting.h index c2b6136b..23823568 100644 --- a/code/gamespy/sv_gqueryreporting.h +++ b/code/gamespy/sv_gqueryreporting.h @@ -1,6 +1,6 @@ /* =========================================================================== -Copyright (C) 2023 the OpenMoHAA team +Copyright (C) 2025 the OpenMoHAA team This file is part of OpenMoHAA source code. @@ -20,45 +20,200 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +/****** +gqueryreporting.h +GameSpy Query & Reporting SDK + +Copyright 2000 GameSpy Industries, Inc + +18002 Skypark Circle +Irvine, CA 92614 +(949)798-4200 +Fax(949)798-4299 +****** + + Please see the GameSpy Query & Reporting SDK documentation for more + information + +******/ + #pragma once -#include "common/gsPlatformSocket.h" +#ifdef __cplusplus +extern "C" { +#endif -typedef void (*qr_querycallback_t)(char *outbuf, int maxlen, void *userdata); -typedef void (*qr_custom_handler_t)(const char *query, struct sockaddr *sender); +/******** +ERROR CONSTANTS +--------------- +These constants are returned from qr_init to signal an error condition +***************/ -typedef enum query_e { - qtunknown, - qtbasic, - qtinfo, - qtrules, - qtplayers, - qtstatus, - qtpackets, - qtecho, - qtsecure -} query_t; +#define E_GOA_WSOCKERROR 1 +#define E_GOA_BINDERROR 2 +#define E_GOA_DNSERROR 3 +#define E_GOA_CONNERROR 4 +/********* +NUM_PORTS_TO_TRY +---------------- +This value is the maximum number of ports that will be scanned to +find an open query port, starting from the value passed to qr_init +as the base port. Generally there is no reason to modify this value. +***********/ +#define NUM_PORTS_TO_TRY 100 -typedef struct qr_implementation_s { - void *querysock; - void *hbsock; - char gamename[64]; - char secret_key[128]; - qr_querycallback_t qr_basic_callback; - qr_querycallback_t qr_info_callback; - qr_querycallback_t qr_rules_callback; - qr_querycallback_t qr_players_callback; - long unsigned int lastheartbeat; - int queryid; - int packetnumber; - int qport; - char no_query; - struct sockaddr_in master_saddr; - int unk2; - int unk3; - int unk4; - qr_custom_handler_t qr_custom_handler; - void *udata; -} qr_implementation_t, *qr_t; +/******** +DEFINES +********/ +#define MASTER_PORT qr_get_master_port(0) +//#define MASTER_ADDR "master." GSI_DOMAIN_NAME +#define MASTER_ADDR qr_get_master_host(0) +#define FIRST_HB_TIME 30000 /* 30 sec */ +#define HB_TIME 300000 /* 5 minutes */ +#define MAX_FIRST_COUNT 10 /* 10 tries = 5 minutes */ +#define MAX_DATA_SIZE 1400 +#define INBUF_LEN 256 +#define BUF_SIZE 1400 -#define MASTER_SERVER_HOST "master.x-null.net" +/* The hostname of the master server. +If the app resolves the hostname, an +IP can be stored here before calling +qr_init */ +extern char qr_hostname[64]; + +/** + * @brief Custom function used to return the master host, based on game settings + * + * @return const char* The full master server address + */ +extern unsigned int qr_get_num_masters(); +extern const char *qr_get_master_host(int index); +extern int qr_get_master_port(int index); + +/******** +qr_querycallback_t +------------------- +This is the prototype for the callback functions your game needs to +implement for each of the four basic query types. The callback works the +same for each query type. + +[outbuf] is a pre-allocated buffer for you to place the query reply. It's size is +[maxlen] (default is 1400). If you need larger, you can adjust the + defines in gqueryreporting.c +[userdata] is the pointer that was passed into qr_init. You can use this for an + object or structure pointer if needed. + +Simply fill outbuf with the correct data for the query type (consult the sample +apps and the GameSpy Developer Spec). +outbuf should be a NULL terminated ANSI string. +********/ +typedef void (*qr_querycallback_t)(char* outbuf, int maxlen, void* userdata); + +typedef void (*qr_cdkey_process_t)(char* buf, int len, struct sockaddr* fromaddr); + +/*********** +qr_t +---- +This abstract type is used to instantiate multiple instances of the +Query & Reporting SDK (for example, if you are running multiple servers +in the same process). +For most games, you can ignore this value and pass NULL in to all functions +that require it. A single global instance will be used, similar to how the +original Developer SDK worked +************/ +typedef struct qr_implementation_s *qr_t; +/************ +QR_INIT +-------- +This creates/binds the sockets needed for heartbeats and queries/replies. +[qrec] if not null, will be filled with the qr_t instance for this server. + If you are not using more than one instance of the Query & Reporting SDK you + can pass in NULL for this value. +[ip] is an optional parameter that determines which dotted IP address to bind to on + a multi-homed machine. You can pass NULL to bind to all IP addresses. +[baseport] is the port to accept queries on. If baseport is not available, the + Query and Reporting SDK will scan for an available port in the range of + baseport -> baseport + NUM_PORTS_TO_TRY + Optionally, you can pass in 0 to have a port chosen automatically + (makes it harder for debugging/testing). +[gamename] is the unique gamename that you were given +[secretkey] is your unique secret key +[qr_*_callback] are your data callback functions, this cannot be NULL +[userdata] is an optional, implementation specific parameter that will be + passed to all callback functions. Use it to store an object or structure + pointer if needed. + +Returns +0 is successful, otherwise one of the E_GOA constants above. +************/ +int qr_init(/*[out]*/ qr_t* qrec, + const char* ip, + int baseport, + const char* gamename, + const char* secret_key, + qr_querycallback_t qr_basic_callback, + qr_querycallback_t qr_info_callback, + qr_querycallback_t qr_rules_callback, + qr_querycallback_t qr_players_callback, + void* userdata); + +/******************* +QR_PROCESS_QUERIES +------------------- +This function should be called somewhere in your main program loop to +process any pending server queries and send a heartbeat if 5 minutes has +elapsed. + +Query replies are very latency sensative, so you should make sure this +function is called at least every 100ms while your game is in progress. +The function has very low overhead and should not cause any performance +problems. +Unless you are using multiple instances of the SDK, you should pass NULl +for qrec. +The no_heartbeat version will not send any heartbeats to the master - use +this if you only want to advertise your server on the LAN. +********************/ +void qr_process_queries(qr_t qrec); +void qr_process_queries_no_heartbeat(qr_t qrec); + +/***************** +QR_SEND_STATECHANGED +-------------------- +This function forces a \statechanged\ heartbeat to be sent immediately. +Use it any time you have changed the gamestate of your game to signal the +master to update your status. +Also use it before your game exits by changing the gamestate to "exiting" +and sending a statechanged heartbeat. This will insure that your game +is removed from the list promptly. +Unless you are using multiple instances of the SDK, you should pass NULl +for qrec. +*******************/ +void qr_send_statechanged(qr_t qrec); + +/***************** +QR_SHUTDOWN +------------ +This function closes the sockets created in qr_init and takes care of +any misc. cleanup. You should try to call it when before exiting the server +if qr_init was called. +If you pass in a qrec that was returned from qr_init, all resources associated +with that qrec will be freed. If you passed NULL into qr_int, you can pass +NULL in here as well. +******************/ +void qr_shutdown(qr_t qrec); + +void qr_check_queries(qr_t qrec); + +void qr_send_exiting(qr_t qrec); + +int get_master_count(); + +void clear_master_list(); + +int get_sockaddrin(const char *host, int port, struct sockaddr_in *saddr, struct hostent **savehent); + +void add_master(struct sockaddr_in *addr); + +#ifdef __cplusplus +} +#endif diff --git a/code/gamespy/webservices/AuthService.c b/code/gamespy/webservices/AuthService.c index 0ad0ac51..11ecd459 100644 --- a/code/gamespy/webservices/AuthService.c +++ b/code/gamespy/webservices/AuthService.c @@ -51,7 +51,7 @@ const char WS_AUTHSERVICE_SIGNATURE_KEY[] = const char WS_AUTHSERVICE_SIGNATURE_EXP[] = "010001"; -// This is declared as an extern so it can be overriden when testing +// This is declared as an extern so it can be overridden when testing #define WS_LOGIN_SERVICE_URL_FORMAT "https://%s.auth.pubsvs." GSI_DOMAIN_NAME "/AuthService/AuthService.asmx" char wsAuthServiceURL[WS_LOGIN_MAX_URL_LEN] = ""; diff --git a/code/libmad-0.15.1b/CMakeLists.txt b/code/libmad-0.15.1b/CMakeLists.txt deleted file mode 100644 index 5b6b659a..00000000 --- a/code/libmad-0.15.1b/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(libmad) - -set(SRCS - "./bit.c" - "./decoder.c" - "./fixed.c" - "./frame.c" - "./huffman.c" - "./layer3.c" - "./layer12.c" - "./stream.c" - "./synth.c" - "./timer.c" - "./version.c" -) - -add_library(libmad STATIC ${SRCS}) -target_compile_definitions(libmad PUBLIC FPM_64BIT) diff --git a/code/libmad-0.15.1b/INSTALL b/code/libmad-0.15.1b/INSTALL deleted file mode 100644 index 50dbe439..00000000 --- a/code/libmad-0.15.1b/INSTALL +++ /dev/null @@ -1,183 +0,0 @@ -Basic Installation -================== - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. - - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. You can give `configure' -initial values for variables by setting them in the environment. Using -a Bourne-compatible shell, you can do that on the command line like -this: - CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure - -Or on systems that have the `env' program, you can do it like this: - env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: - CPU-COMPANY-SYSTEM - -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. - - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Operation Controls -================== - - `configure' recognizes the following options to control how it -operates. - -`--cache-file=FILE' - Use and save the results of the tests in FILE instead of - `./config.cache'. Set FILE to `/dev/null' to disable caching, for - debugging `configure'. - -`--help' - Print a summary of the options to `configure', and exit. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--version' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`configure' also accepts some other, not widely useful, options. - diff --git a/code/libmad-0.15.1b/Makefile.am b/code/libmad-0.15.1b/Makefile.am deleted file mode 100644 index ad5c596d..00000000 --- a/code/libmad-0.15.1b/Makefile.am +++ /dev/null @@ -1,140 +0,0 @@ -## -## libmad - MPEG audio decoder library -## Copyright (C) 2000-2004 Underbit Technologies, Inc. -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -## -## $Id: Makefile.am,v 1.23 2004/02/17 02:02:03 rob Exp $ -## - -## Process this file with automake to produce Makefile.in - -SUBDIRS = -DIST_SUBDIRS = msvc++ - -lib_LTLIBRARIES = libmad.la -include_HEADERS = mad.h - -EXTRA_PROGRAMS = minimad - -minimad_SOURCES = minimad.c -minimad_INCLUDES = -minimad_LDADD = libmad.la - -EXTRA_DIST = mad.h.sed \ - CHANGES COPYRIGHT CREDITS README TODO VERSION - -exported_headers = version.h fixed.h bit.h timer.h stream.h frame.h \ - synth.h decoder.h - -headers = $(exported_headers) \ - global.h layer12.h layer3.h huffman.h - -data_includes = D.dat imdct_s.dat qc_table.dat rq_table.dat \ - sf_table.dat - -libmad_la_SOURCES = version.c fixed.c bit.c timer.c stream.c frame.c \ - synth.c decoder.c layer12.c layer3.c huffman.c \ - $(headers) $(data_includes) - -EXTRA_libmad_la_SOURCES = imdct_l_arm.S #synth_mmx.S - -libmad_la_DEPENDENCIES = @ASO_OBJS@ -libmad_la_LIBADD = @ASO_OBJS@ - -INCLUDES = $(FPM) $(ASO) - -BUILT_SOURCES = mad.h -CLEANFILES = mad.h - -## From the libtool documentation on library versioning: -## -## CURRENT -## The most recent interface number that this library implements. -## -## REVISION -## The implementation number of the CURRENT interface. -## -## AGE -## The difference between the newest and oldest interfaces that this -## library implements. In other words, the library implements all the -## interface numbers in the range from number `CURRENT - AGE' to -## `CURRENT'. -## -## If two libraries have identical CURRENT and AGE numbers, then the -## dynamic linker chooses the library with the greater REVISION number. -## -## 1. Start with version information of `0:0:0' for each libtool library. -## -## 2. Update the version information only immediately before a public -## release of your software. More frequent updates are unnecessary, -## and only guarantee that the current interface number gets larger -## faster. -## -## 3. If the library source code has changed at all since the last -## update, then increment REVISION (`C:R:A' becomes `C:r+1:A'). -## -## 4. If any interfaces have been added, removed, or changed since the -## last update, increment CURRENT, and set REVISION to 0. -## -## 5. If any interfaces have been added since the last public release, -## then increment AGE. -## -## 6. If any interfaces have been removed since the last public release, -## then set AGE to 0. - -version_current = 2 -version_revision = 1 -version_age = 2 - -version_info = $(version_current):$(version_revision):$(version_age) - -libmad_la_LDFLAGS = -version-info $(version_info) - -mad.h: config.status config.h Makefile.am \ - $(srcdir)/COPYRIGHT $(srcdir)/mad.h.sed $(exported_headers) - (sed -e '1s|.*|/*|' -e '1b' -e '$$s|.*| */|' -e '$$b' \ - -e 's/^.*/ *&/' $(srcdir)/COPYRIGHT; echo; \ - echo "# ifdef __cplusplus"; \ - echo 'extern "C" {'; \ - echo "# endif"; echo; \ - if [ ".$(FPM)" != "." ]; then \ - echo ".$(FPM)" | sed -e 's|^\.-D|# define |'; echo; \ - fi; \ - sed -ne 's/^# *define *\(HAVE_.*_ASM\).*/# define \1/p' \ - config.h; echo; \ - sed -ne 's/^# *define *OPT_\(SPEED\|ACCURACY\).*/# define OPT_\1/p' \ - config.h; echo; \ - sed -ne 's/^# *define *\(SIZEOF_.*\)/# define \1/p' \ - config.h; echo; \ - for header in $(exported_headers); do \ - echo; \ - sed -n -f $(srcdir)/mad.h.sed $(srcdir)/$$header; \ - done; echo; \ - echo "# ifdef __cplusplus"; \ - echo '}'; \ - echo "# endif") >$@ - -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck - -.c.s: - $(COMPILE) -S $< - -again: - $(MAKE) clean - $(MAKE) - -.PHONY: again diff --git a/code/libmad-0.15.1b/Makefile.in b/code/libmad-0.15.1b/Makefile.in deleted file mode 100644 index 723070ad..00000000 --- a/code/libmad-0.15.1b/Makefile.in +++ /dev/null @@ -1,821 +0,0 @@ -# Makefile.in generated by automake 1.8.2 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - -SOURCES = $(libmad_la_SOURCES) $(EXTRA_libmad_la_SOURCES) $(minimad_SOURCES) - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = . -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_triplet = @host@ -EXTRA_PROGRAMS = minimad$(EXEEXT) -DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/config.h.in $(srcdir)/libmad.list.in \ - $(top_srcdir)/configure COPYING INSTALL TODO config.guess \ - config.sub depcomp install-sh ltmain.sh missing mkinstalldirs -subdir = . -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno configure.status.lineno -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = libmad.list -am__installdirs = $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) -libLTLIBRARIES_INSTALL = $(INSTALL) -LTLIBRARIES = $(lib_LTLIBRARIES) -am__objects_1 = -am__objects_2 = $(am__objects_1) -am_libmad_la_OBJECTS = version.lo fixed.lo bit.lo timer.lo stream.lo \ - frame.lo synth.lo decoder.lo layer12.lo layer3.lo huffman.lo \ - $(am__objects_2) $(am__objects_1) -libmad_la_OBJECTS = $(am_libmad_la_OBJECTS) -am_minimad_OBJECTS = minimad.$(OBJEXT) -minimad_OBJECTS = $(am_minimad_OBJECTS) -minimad_DEPENDENCIES = libmad.la -DEFAULT_INCLUDES = -I. -I$(srcdir) -I. -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/bit.Plo ./$(DEPDIR)/decoder.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/fixed.Plo ./$(DEPDIR)/frame.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/huffman.Plo ./$(DEPDIR)/layer12.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/layer3.Plo ./$(DEPDIR)/minimad.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/stream.Plo ./$(DEPDIR)/synth.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/timer.Plo ./$(DEPDIR)/version.Plo -CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) -LTCCASCOMPILE = $(LIBTOOL) --mode=compile $(CCAS) $(AM_CCASFLAGS) \ - $(CCASFLAGS) -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libmad_la_SOURCES) $(EXTRA_libmad_la_SOURCES) \ - $(minimad_SOURCES) -DIST_SOURCES = $(libmad_la_SOURCES) $(EXTRA_libmad_la_SOURCES) \ - $(minimad_SOURCES) -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-exec-recursive install-info-recursive \ - install-recursive installcheck-recursive installdirs-recursive \ - pdf-recursive ps-recursive uninstall-info-recursive \ - uninstall-recursive -includeHEADERS_INSTALL = $(INSTALL_HEADER) -HEADERS = $(include_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - { test ! -d $(distdir) \ - || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr $(distdir); }; } -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -distuninstallcheck_listfiles = find . -type f -print -distcleancheck_listfiles = find . -type f -print -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -ASO = @ASO@ -ASO_OBJS = @ASO_OBJS@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -FPM = @FPM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBTOOL_DEPS = @LIBTOOL_DEPS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -SUBDIRS = -DIST_SUBDIRS = msvc++ -lib_LTLIBRARIES = libmad.la -include_HEADERS = mad.h -minimad_SOURCES = minimad.c -minimad_INCLUDES = -minimad_LDADD = libmad.la -EXTRA_DIST = mad.h.sed \ - CHANGES COPYRIGHT CREDITS README TODO VERSION - -exported_headers = version.h fixed.h bit.h timer.h stream.h frame.h \ - synth.h decoder.h - -headers = $(exported_headers) \ - global.h layer12.h layer3.h huffman.h - -data_includes = D.dat imdct_s.dat qc_table.dat rq_table.dat \ - sf_table.dat - -libmad_la_SOURCES = version.c fixed.c bit.c timer.c stream.c frame.c \ - synth.c decoder.c layer12.c layer3.c huffman.c \ - $(headers) $(data_includes) - -EXTRA_libmad_la_SOURCES = imdct_l_arm.S #synth_mmx.S -libmad_la_DEPENDENCIES = @ASO_OBJS@ -libmad_la_LIBADD = @ASO_OBJS@ -INCLUDES = $(FPM) $(ASO) -BUILT_SOURCES = mad.h -CLEANFILES = mad.h -version_current = 2 -version_revision = 1 -version_age = 2 -version_info = $(version_current):$(version_revision):$(version_age) -libmad_la_LDFLAGS = -version-info $(version_info) -all: $(BUILT_SOURCES) config.h - $(MAKE) $(AM_MAKEFLAGS) all-recursive - -.SUFFIXES: -.SUFFIXES: .S .c .lo .o .obj .s -am--refresh: - @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ - cd $(srcdir) && $(AUTOMAKE) --foreign \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - echo ' $(SHELL) ./config.status'; \ - $(SHELL) ./config.status;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - $(SHELL) ./config.status --recheck - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) - -config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) stamp-h1; \ - else :; fi - -stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status config.h -$(srcdir)/config.h.in: $(am__configure_deps) - cd $(top_srcdir) && $(AUTOHEADER) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f config.h stamp-h1 -libmad.list: $(top_builddir)/config.status $(srcdir)/libmad.list.in - cd $(top_builddir) && $(SHELL) ./config.status $@ -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - $(mkdir_p) $(DESTDIR)$(libdir) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f="`echo $$p | sed -e 's|^.*/||'`"; \ - echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \ - $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \ - else :; fi; \ - done - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - p="`echo $$p | sed -e 's|^.*/||'`"; \ - echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \ - $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" = "$$p" && dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libmad.la: $(libmad_la_OBJECTS) $(libmad_la_DEPENDENCIES) - $(LINK) -rpath $(libdir) $(libmad_la_LDFLAGS) $(libmad_la_OBJECTS) $(libmad_la_LIBADD) $(LIBS) -minimad$(EXEEXT): $(minimad_OBJECTS) $(minimad_DEPENDENCIES) - @rm -f minimad$(EXEEXT) - $(LINK) $(minimad_LDFLAGS) $(minimad_OBJECTS) $(minimad_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bit.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decoder.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fixed.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frame.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huffman.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layer12.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layer3.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimad.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/synth.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ - -.S.o: - $(CCASCOMPILE) -c $< - -.S.obj: - $(CCASCOMPILE) -c `$(CYGPATH_W) '$<'` - -.S.lo: - $(LTCCASCOMPILE) -c -o $@ $< - -.c.o: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: -install-includeHEADERS: $(include_HEADERS) - @$(NORMAL_INSTALL) - $(mkdir_p) $(DESTDIR)$(includedir) - @list='$(include_HEADERS)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f="`echo $$p | sed -e 's|^.*/||'`"; \ - echo " $(includeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(includedir)/$$f"; \ - $(includeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(includedir)/$$f; \ - done - -uninstall-includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(include_HEADERS)'; for p in $$list; do \ - f="`echo $$p | sed -e 's|^.*/||'`"; \ - echo " rm -f $(DESTDIR)$(includedir)/$$f"; \ - rm -f $(DESTDIR)$(includedir)/$$f; \ - done - -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. -$(RECURSIVE_TARGETS): - @set fnord $$MAKEFLAGS; amf=$$2; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -mostlyclean-recursive clean-recursive distclean-recursive \ -maintainer-clean-recursive: - @set fnord $$MAKEFLAGS; amf=$$2; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ - done - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - if (etags --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - else \ - include_option=--include; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && \ - tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$tags$$unique" \ - || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - $(am__remove_distdir) - mkdir $(distdir) - $(mkdir_p) $(distdir)/. - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done - list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || mkdir "$(distdir)/$$subdir" \ - || exit 1; \ - (cd $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="../$(top_distdir)" \ - distdir="../$(distdir)/$$subdir" \ - distdir) \ - || exit 1; \ - fi; \ - done - -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r $(distdir) -dist-gzip: distdir - $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -dist-bzip2: distdir - $(AMTAR) chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2 - $(am__remove_distdir) - -dist-tarZ: distdir - $(AMTAR) chof - $(distdir) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) - -dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) - -dist dist-all: distdir - $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - ;;\ - *.tar.bz2*) \ - bunzip2 -c $(distdir).tar.bz2 | $(AMTAR) xf - ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\ - *.shar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst - chmod a-w $(distdir) - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && cd $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && $(mkdir_p) "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck - $(am__remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' -distuninstallcheck: - @cd $(distuninstallcheck_dir) \ - && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 -check-am: all-am -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-recursive -all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h -installdirs: installdirs-recursive -installdirs-am: - $(mkdir_p) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-recursive - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-hdr distclean-libtool distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -info: info-recursive - -info-am: - -install-data-am: install-includeHEADERS - -install-exec-am: install-libLTLIBRARIES - -install-info: install-info-recursive - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: uninstall-includeHEADERS uninstall-info-am \ - uninstall-libLTLIBRARIES - -uninstall-info: uninstall-info-recursive - -.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ - check-am clean clean-generic clean-libLTLIBRARIES \ - clean-libtool clean-recursive ctags ctags-recursive dist \ - dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip \ - distcheck distclean distclean-compile distclean-generic \ - distclean-hdr distclean-libtool distclean-recursive \ - distclean-tags distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-exec install-exec-am \ - install-includeHEADERS install-info install-info-am \ - install-libLTLIBRARIES install-man install-strip installcheck \ - installcheck-am installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic maintainer-clean-recursive \ - mostlyclean mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \ - tags tags-recursive uninstall uninstall-am \ - uninstall-includeHEADERS uninstall-info-am \ - uninstall-libLTLIBRARIES - - -mad.h: config.status config.h Makefile.am \ - $(srcdir)/COPYRIGHT $(srcdir)/mad.h.sed $(exported_headers) - (sed -e '1s|.*|/*|' -e '1b' -e '$$s|.*| */|' -e '$$b' \ - -e 's/^.*/ *&/' $(srcdir)/COPYRIGHT; echo; \ - echo "# ifdef __cplusplus"; \ - echo 'extern "C" {'; \ - echo "# endif"; echo; \ - if [ ".$(FPM)" != "." ]; then \ - echo ".$(FPM)" | sed -e 's|^\.-D|# define |'; echo; \ - fi; \ - sed -ne 's/^# *define *\(HAVE_.*_ASM\).*/# define \1/p' \ - config.h; echo; \ - sed -ne 's/^# *define *OPT_\(SPEED\|ACCURACY\).*/# define OPT_\1/p' \ - config.h; echo; \ - sed -ne 's/^# *define *\(SIZEOF_.*\)/# define \1/p' \ - config.h; echo; \ - for header in $(exported_headers); do \ - echo; \ - sed -n -f $(srcdir)/mad.h.sed $(srcdir)/$$header; \ - done; echo; \ - echo "# ifdef __cplusplus"; \ - echo '}'; \ - echo "# endif") >$@ - -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck - -.c.s: - $(COMPILE) -S $< - -again: - $(MAKE) clean - $(MAKE) - -.PHONY: again -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/code/libmad-0.15.1b/README b/code/libmad-0.15.1b/README deleted file mode 100644 index b3f15ea4..00000000 --- a/code/libmad-0.15.1b/README +++ /dev/null @@ -1,241 +0,0 @@ - - libmad - MPEG audio decoder library - Copyright (C) 2000-2004 Underbit Technologies, Inc. - - $Id: README,v 1.4 2004/01/23 09:41:32 rob Exp $ - -=============================================================================== - -INTRODUCTION - - MAD (libmad) is a high-quality MPEG audio decoder. It currently supports - MPEG-1 and the MPEG-2 extension to Lower Sampling Frequencies, as well as - the so-called MPEG 2.5 format. All three audio layers (Layer I, Layer II, - and Layer III a.k.a. MP3) are fully implemented. - - MAD does not yet support MPEG-2 multichannel audio (although it should be - backward compatible with such streams) nor does it currently support AAC. - - MAD has the following special features: - - - 24-bit PCM output - - 100% fixed-point (integer) computation - - completely new implementation based on the ISO/IEC standards - - distributed under the terms of the GNU General Public License (GPL) - - Because MAD provides full 24-bit PCM output, applications using MAD are - able to produce high quality audio. Even when the output device supports - only 16-bit PCM, applications can use the extra resolution to increase the - audible dynamic range through the use of dithering or noise shaping. - - Because MAD uses integer computation rather than floating point, it is - well suited for architectures without a floating point unit. All - calculations are performed with a 32-bit fixed-point integer - representation. - - Because MAD is a new implementation of the ISO/IEC standards, it is - unencumbered by the errors of other implementations. MAD is NOT a - derivation of the ISO reference source or any other code. Considerable - effort has been expended to ensure a correct implementation, even in cases - where the standards are ambiguous or misleading. - - Because MAD is distributed under the terms of the GPL, its redistribution - is not generally restricted, so long as the terms of the GPL are followed. - This means MAD can be incorporated into other software as long as that - software is also distributed under the GPL. (Should this be undesirable, - alternate arrangements may be possible by contacting Underbit.) - -=============================================================================== - -ABOUT THE CODE - - The code is optimized and performs very well, although specific - improvements can still be made. The output from the decoder library - consists of 32-bit signed linear fixed-point values that can be easily - scaled for any size PCM output, up to 24 bits per sample. - - The API for libmad can be found in the `mad.h' header file. Note that this - file is automatically generated, and will not exist until after you have - built the library. - - There are two APIs available, one high-level, and the other low-level. - With the low-level API, each step of the decoding process must be handled - explicitly, offering the greatest amount of control. With the high-level - API, after callbacks are configured, a single routine will decode an - entire bitstream. - - The high-level API may either be used synchronously or asynchronously. If - used asynchronously, decoding will occur in a separate process. - Communication is possible with the decoding process by passing control - messages. - - The file `minimad.c' contains an example usage of the libmad API that - shows only the bare minimum required to implement a useful decoder. It - expects a regular file to be redirected to standard input, and it sends - decoded 16-bit signed little-endian PCM samples to standard output. If a - decoding error occurs, it is reported to standard error and decoding - continues. Note that the scale() routine in this code is only provided as - an example; it rounds MAD's high-resolution samples down to 16 bits, but - does not perform any dithering or noise shaping. It is therefore not - recommended to use this routine as-is in your own code if sound quality is - important. - -Integer Performance - - To get the best possible performance, it is recommended that an assembly - version of the fixed-point multiply and related routines be selected. - Several such assembly routines have been written for various CPUs. - - If an assembly version is not available, a fast approximation version will - be used. This will result in reduced accuracy of the decoder. - - Alternatively, if 64-bit integers are supported as a datatype by the - compiler, another version can be used that is much more accurate. - However, using an assembly version is generally much faster and just as - accurate. - - More information can be gathered from the `fixed.h' header file. - - MAD's CPU-intensive subband synthesis routine can be further optimized at - the expense of a slight loss in output accuracy due to a modified method - for fixed-point multiplication with a small windowing constant. While this - is helpful for performance and the output accuracy loss is generally - undetectable, it is disabled by default and must be explicitly enabled. - - Under some architectures, other special optimizations may also be - available. - -Audio Quality - - The output from MAD has been found to satisfy the ISO/IEC 11172-4 - computational accuracy requirements for compliance. In most - configurations, MAD is a Full Layer III ISO/IEC 11172-3 audio decoder as - defined by the standard. - - When the approximation version of the fixed-point multiply is used, MAD is - a limited accuracy ISO/IEC 11172-3 audio decoder as defined by the - standard. - - MAD can alternatively be configured to produce output with less or more - accuracy than the default, as a tradeoff with performance. - - MAD produces output samples with a precision greater than 24 bits. Because - most output formats use fewer bits, typically 16, it is recommended that a - dithering algorithm be used (rather than rounding or truncating) to obtain - the highest quality audio. However, dithering may unfavorably affect an - analytic examination of the output (such as compliance testing); you may - therefore wish to use rounding in this case instead. - -Portability Issues - - GCC is preferred to compile the code, but other compilers may also work. - The assembly code in `fixed.h' depends on the inline assembly features of - your compiler. If you're not using GCC or MSVC++, you can either write - your own assembly macros or use the default (low quality output) version. - - The union initialization of `huffman.c' may not be portable to all - platforms when GCC is not used. - - The code should not be sensitive to word sizes or byte ordering, however - it does assume A % B has the same sign as A. - -=============================================================================== - -BUILDING AND INSTALLING - -Windows Platforms - - MAD can be built under Windows using either MSVC++ or Cygwin. A MSVC++ - project file can be found under the `msvc++' subdirectory. - - To build libmad using Cygwin, you will first need to install the Cygwin - tools: - - http://www.cygwin.com/ - - You may then proceed with the following POSIX instructions within the - Cygwin shell. - - Note that by default Cygwin will build a library that depends on the - Cygwin DLL. You can use MinGW to build a library that does not depend on - the Cygwin DLL. To do so, give the option --host=mingw32 to `configure'. - -POSIX Platforms (including Cygwin) - - The code is distributed with a `configure' script that will generate for - you a `Makefile' and a `config.h' for your platform. See the file - `INSTALL' for generic instructions. - - The specific options you may want to give `configure' are: - - --enable-speed optimize for speed over accuracy - - --enable-accuracy optimize for accuracy over speed - - --disable-debugging do not compile with debugging support, and - use more optimizations - - --disable-shared do not build a shared library - - Note that you need not specify one of --enable-speed or --enable-accuracy; - in its default configuration, MAD is optimized for both. You should only - use one of these options if you wish to compromise speed or accuracy for - the other. - - By default the package will build a shared library if possible for your - platform. If you want only a static library, use --disable-shared. - - It is not normally necessary to use the following options, but you may - fine-tune the configuration with them if desired: - - --enable-fpm=ARCH use the ARCH-specific version of the - fixed-point math assembly routines - (current options are: intel, arm, mips, - sparc, ppc; also allowed are: 64bit, approx) - - --enable-sso use the subband synthesis optimization, - with reduced accuracy - - --disable-aso do not use certain architecture-specific - optimizations - - By default an appropriate fixed-point assembly routine will be selected - for the configured host type, if it can be determined. Thus if you are - cross-compiling for another architecture, you should be sure either to - give `configure' a host type argument (--host) or to use an explicit - --enable-fpm option. - - If an appropriate assembly routine cannot be determined, the default - approximation version will be used. In this case, use of an alternate - --enable-fpm is highly recommended. - -Experimenting and Developing - - Further options for `configure' that may be useful to developers and - experimenters are: - - --enable-debugging enable diagnostic debugging support and - debugging symbols - - --enable-profiling generate `gprof' profiling code - - --enable-experimental enable code using the EXPERIMENTAL - preprocessor define - -=============================================================================== - -COPYRIGHT - - Please read the `COPYRIGHT' file for copyright and warranty information. - Also, the file `COPYING' contains the full text of the GNU GPL. - - Send inquiries, comments, bug reports, suggestions, patches, etc. to: - - Underbit Technologies, Inc. - - See also the MAD home page on the Web: - - http://www.underbit.com/products/mad/ - -=============================================================================== - diff --git a/code/libmad-0.15.1b/VERSION b/code/libmad-0.15.1b/VERSION deleted file mode 100644 index d4e8f64a..00000000 --- a/code/libmad-0.15.1b/VERSION +++ /dev/null @@ -1,7 +0,0 @@ -0.15.1b -configure.ac:24 -version.h:25-28 -msvc++/config.h:99,105,120 -msvc++/mad.h:41-44 - -Makefile.am:98-100 diff --git a/code/libmad-0.15.1b/aclocal.m4 b/code/libmad-0.15.1b/aclocal.m4 deleted file mode 100644 index 1d15e0b9..00000000 --- a/code/libmad-0.15.1b/aclocal.m4 +++ /dev/null @@ -1,6849 +0,0 @@ -# generated automatically by aclocal 1.8.2 -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 -# Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- - -# serial 47 AC_PROG_LIBTOOL -# Debian $Rev: 192 $ - - -# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) -# ----------------------------------------------------------- -# If this macro is not defined by Autoconf, define it here. -m4_ifdef([AC_PROVIDE_IFELSE], - [], - [m4_define([AC_PROVIDE_IFELSE], - [m4_ifdef([AC_PROVIDE_$1], - [$2], [$3])])]) - - -# AC_PROG_LIBTOOL -# --------------- -AC_DEFUN([AC_PROG_LIBTOOL], -[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl -dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX -dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. - AC_PROVIDE_IFELSE([AC_PROG_CXX], - [AC_LIBTOOL_CXX], - [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX - ])]) -dnl And a similar setup for Fortran 77 support - AC_PROVIDE_IFELSE([AC_PROG_F77], - [AC_LIBTOOL_F77], - [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 -])]) - -dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. -dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run -dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. - AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [ifdef([AC_PROG_GCJ], - [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) - ifdef([A][M_PROG_GCJ], - [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) - ifdef([LT_AC_PROG_GCJ], - [define([LT_AC_PROG_GCJ], - defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) -])])# AC_PROG_LIBTOOL - - -# _AC_PROG_LIBTOOL -# ---------------- -AC_DEFUN([_AC_PROG_LIBTOOL], -[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl -AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl -AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl -AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -# Prevent multiple expansion -define([AC_PROG_LIBTOOL], []) -])# _AC_PROG_LIBTOOL - - -# AC_LIBTOOL_SETUP -# ---------------- -AC_DEFUN([AC_LIBTOOL_SETUP], -[AC_PREREQ(2.50)dnl -AC_REQUIRE([AC_ENABLE_SHARED])dnl -AC_REQUIRE([AC_ENABLE_STATIC])dnl -AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_LD])dnl -AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl -AC_REQUIRE([AC_PROG_NM])dnl - -AC_REQUIRE([AC_PROG_LN_S])dnl -AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl -# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! -AC_REQUIRE([AC_OBJEXT])dnl -AC_REQUIRE([AC_EXEEXT])dnl -dnl - -AC_LIBTOOL_SYS_MAX_CMD_LEN -AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -AC_LIBTOOL_OBJDIR - -AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl -_LT_AC_PROG_ECHO_BACKSLASH - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' -[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] - -# Same as above, but do not quote variable references. -[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Constants: -rm="rm -f" - -# Global variables: -default_ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except M$VC, -# which needs '.lib'). -libext=a -ltmain="$ac_aux_dir/ltmain.sh" -ofile="$default_ofile" -with_gnu_ld="$lt_cv_prog_gnu_ld" - -AC_CHECK_TOOL(AR, ar, false) -AC_CHECK_TOOL(RANLIB, ranlib, :) -AC_CHECK_TOOL(STRIP, strip, :) - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -test -z "$AS" && AS=as -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$LD" && LD=ld -test -z "$LN_S" && LN_S="ln -s" -test -z "$MAGIC_CMD" && MAGIC_CMD=file -test -z "$NM" && NM=nm -test -z "$SED" && SED=sed -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$RANLIB" && RANLIB=: -test -z "$STRIP" && STRIP=: -test -z "$ac_objext" && ac_objext=o - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" - ;; - *) - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - -# Only perform the check for file, if the check method requires it -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - AC_PATH_MAGIC - fi - ;; -esac - -AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) -AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], -enable_win32_dll=yes, enable_win32_dll=no) - -AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -AC_ARG_WITH([pic], - [AC_HELP_STRING([--with-pic], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [pic_mode="$withval"], - [pic_mode=default]) -test -z "$pic_mode" && pic_mode=default - -# Use C for the default configuration in the libtool script -tagname= -AC_LIBTOOL_LANG_C_CONFIG -_LT_AC_TAGCONFIG -])# AC_LIBTOOL_SETUP - - -# _LT_AC_SYS_COMPILER -# ------------------- -AC_DEFUN([_LT_AC_SYS_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_AC_SYS_COMPILER - - -# _LT_AC_SYS_LIBPATH_AIX -# ---------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], -[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi],[]) -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -])# _LT_AC_SYS_LIBPATH_AIX - - -# _LT_AC_SHELL_INIT(ARG) -# ---------------------- -AC_DEFUN([_LT_AC_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_AC_SHELL_INIT - - -# _LT_AC_PROG_ECHO_BACKSLASH -# -------------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. -AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], -[_LT_AC_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -echo=${ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null && - echo_test_string="`eval $cmd`" && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null - then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : -else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - echo='printf %s\n' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -ECHO=$echo -if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi - -AC_SUBST(ECHO) -])])# _LT_AC_PROG_ECHO_BACKSLASH - - -# _LT_AC_LOCK -# ----------- -AC_DEFUN([_LT_AC_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case "`/usr/bin/file conftest.o`" in - *32-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], -[*-*-cygwin* | *-*-mingw* | *-*-pw32*) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; - ]) -esac - -need_locks="$enable_libtool_lock" - -])# _LT_AC_LOCK - - -# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], -[AC_REQUIRE([LT_AC_PROG_SED]) -AC_CACHE_CHECK([$1], [$2], - [$2=no - ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - $2=yes - fi - fi - $rm conftest* -]) - -if test x"[$]$2" = xyes; then - ifelse([$5], , :, [$5]) -else - ifelse([$6], , :, [$6]) -fi -])# AC_LIBTOOL_COMPILER_OPTION - - -# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ------------------------------------------------------------ -# Check whether the given compiler option works -AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], -[AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $3" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - else - $2=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" -]) - -if test x"[$]$2" = xyes; then - ifelse([$4], , :, [$4]) -else - ifelse([$5], , :, [$5]) -fi -])# AC_LIBTOOL_LINKER_OPTION - - -# AC_LIBTOOL_SYS_MAX_CMD_LEN -# -------------------------- -AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], -[# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - testring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - *) - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \ - = "XX$testring") >/dev/null 2>&1 && - new_result=`expr "X$testring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - testring=$testring$testring - done - testring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - ;; - esac -]) -if test -n $lt_cv_sys_max_cmd_len ; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -])# AC_LIBTOOL_SYS_MAX_CMD_LEN - - -# _LT_AC_CHECK_DLFCN -# -------------------- -AC_DEFUN([_LT_AC_CHECK_DLFCN], -[AC_CHECK_HEADERS(dlfcn.h)dnl -])# _LT_AC_CHECK_DLFCN - - -# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ------------------------------------------------------------------ -AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], -[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl -if test "$cross_compiling" = yes; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -}] -EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_unknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_AC_TRY_DLOPEN_SELF - - -# AC_LIBTOOL_DLOPEN_SELF -# ------------------- -AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], -[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_AC_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_AC_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -])# AC_LIBTOOL_DLOPEN_SELF - - -# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) -# --------------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler -AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], -[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s out/conftest.err; then - _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* -]) -])# AC_LIBTOOL_PROG_CC_C_O - - -# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) -# ----------------------------------------- -# Check to see if we can do hard links to lock some files if needed -AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], -[AC_REQUIRE([_LT_AC_LOCK])dnl - -hard_links="nottested" -if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS - - -# AC_LIBTOOL_OBJDIR -# ----------------- -AC_DEFUN([AC_LIBTOOL_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -])# AC_LIBTOOL_OBJDIR - - -# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) -# ---------------------------------------------- -# Check hardcoding attributes. -AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_AC_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ - test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ - test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then - - # We can hardcode non-existant directories. - if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then - # Linking always hardcodes the temporary library directory. - _LT_AC_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_AC_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_AC_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) - -if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi -])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH - - -# AC_LIBTOOL_SYS_LIB_STRIP -# ------------------------ -AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], -[striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) -fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -])# AC_LIBTOOL_SYS_LIB_STRIP - - -# AC_LIBTOOL_SYS_DYNAMIC_LINKER -# ----------------------------- -# PORTME Fill in your ld.so characteristics -AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], -[AC_MSG_CHECKING([dynamic linker characteristics]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext='$(test .$module = .yes && echo .so || echo .dylib)' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case "$host_cpu" in - ia64*) - shrext='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf` - sys_lib_dlsearch_path_spec="/lib /usr/lib $ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - need_lib_prefix=no - need_version=yes - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no -])# AC_LIBTOOL_SYS_DYNAMIC_LINKER - - -# _LT_AC_TAGCONFIG -# ---------------- -AC_DEFUN([_LT_AC_TAGCONFIG], -[AC_ARG_WITH([tags], - [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], - [include additional configurations @<:@automatic@:>@])], - [tagnames="$withval"]) - -if test -f "$ltmain" && test -n "$tagnames"; then - if test ! -f "${ofile}"; then - AC_MSG_WARN([output file `$ofile' does not exist]) - fi - - if test -z "$LTCC"; then - eval "`$SHELL ${ofile} --config | grep '^LTCC='`" - if test -z "$LTCC"; then - AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) - else - AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) - fi - fi - - # Extract list of available tagged configurations in $ofile. - # Note that this assumes the entire list is on one line. - available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` - - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for tagname in $tagnames; do - IFS="$lt_save_ifs" - # Check whether tagname contains only valid characters - case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in - "") ;; - *) AC_MSG_ERROR([invalid tag name: $tagname]) - ;; - esac - - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null - then - AC_MSG_ERROR([tag name \"$tagname\" already exists]) - fi - - # Update the list of available tags. - if test -n "$tagname"; then - echo appending configuration tag \"$tagname\" to $ofile - - case $tagname in - CXX) - if test -n "$CXX" && test "X$CXX" != "Xno"; then - AC_LIBTOOL_LANG_CXX_CONFIG - else - tagname="" - fi - ;; - - F77) - if test -n "$F77" && test "X$F77" != "Xno"; then - AC_LIBTOOL_LANG_F77_CONFIG - else - tagname="" - fi - ;; - - GCJ) - if test -n "$GCJ" && test "X$GCJ" != "Xno"; then - AC_LIBTOOL_LANG_GCJ_CONFIG - else - tagname="" - fi - ;; - - RC) - AC_LIBTOOL_LANG_RC_CONFIG - ;; - - *) - AC_MSG_ERROR([Unsupported tag name: $tagname]) - ;; - esac - - # Append the new tag name to the list of available tags. - if test -n "$tagname" ; then - available_tags="$available_tags $tagname" - fi - fi - done - IFS="$lt_save_ifs" - - # Now substitute the updated list of available tags. - if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then - mv "${ofile}T" "$ofile" - chmod +x "$ofile" - else - rm -f "${ofile}T" - AC_MSG_ERROR([unable to update list of available tagged configurations.]) - fi -fi -])# _LT_AC_TAGCONFIG - - -# AC_LIBTOOL_DLOPEN -# ----------------- -# enable checks for dlopen support -AC_DEFUN([AC_LIBTOOL_DLOPEN], - [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) -])# AC_LIBTOOL_DLOPEN - - -# AC_LIBTOOL_WIN32_DLL -# -------------------- -# declare package support for building win32 dll's -AC_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) -])# AC_LIBTOOL_WIN32_DLL - - -# AC_ENABLE_SHARED([DEFAULT]) -# --------------------------- -# implement the --enable-shared flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_SHARED], -[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([shared], - [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_shared=]AC_ENABLE_SHARED_DEFAULT) -])# AC_ENABLE_SHARED - - -# AC_DISABLE_SHARED -# ----------------- -#- set the default shared flag to --disable-shared -AC_DEFUN([AC_DISABLE_SHARED], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_SHARED(no) -])# AC_DISABLE_SHARED - - -# AC_ENABLE_STATIC([DEFAULT]) -# --------------------------- -# implement the --enable-static flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_STATIC], -[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([static], - [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_static=]AC_ENABLE_STATIC_DEFAULT) -])# AC_ENABLE_STATIC - - -# AC_DISABLE_STATIC -# ----------------- -# set the default static flag to --disable-static -AC_DEFUN([AC_DISABLE_STATIC], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_STATIC(no) -])# AC_DISABLE_STATIC - - -# AC_ENABLE_FAST_INSTALL([DEFAULT]) -# --------------------------------- -# implement the --enable-fast-install flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_FAST_INSTALL], -[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([fast-install], - [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) -])# AC_ENABLE_FAST_INSTALL - - -# AC_DISABLE_FAST_INSTALL -# ----------------------- -# set the default to --disable-fast-install -AC_DEFUN([AC_DISABLE_FAST_INSTALL], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_FAST_INSTALL(no) -])# AC_DISABLE_FAST_INSTALL - - -# AC_LIBTOOL_PICMODE([MODE]) -# -------------------------- -# implement the --with-pic flag -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -AC_DEFUN([AC_LIBTOOL_PICMODE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -pic_mode=ifelse($#,1,$1,default) -])# AC_LIBTOOL_PICMODE - - -# AC_PROG_EGREP -# ------------- -# This is predefined starting with Autoconf 2.54, so this conditional -# definition can be removed once we require Autoconf 2.54 or later. -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], -[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], - [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi]) - EGREP=$ac_cv_prog_egrep - AC_SUBST([EGREP]) -])]) - - -# AC_PATH_TOOL_PREFIX -# ------------------- -# find a file program which can recognise shared library -AC_DEFUN([AC_PATH_TOOL_PREFIX], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="ifelse([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -])# AC_PATH_TOOL_PREFIX - - -# AC_PATH_MAGIC -# ------------- -# find a file program which can recognise a shared library -AC_DEFUN([AC_PATH_MAGIC], -[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# AC_PATH_MAGIC - - -# AC_PROG_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([AC_PROG_LD], -[AC_ARG_WITH([gnu-ld], - [AC_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], - [with_gnu_ld=no]) -AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case "$host_cpu" in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -nto-qnx*) - lt_cv_deplibs_check_method=unknown - ;; - -openbsd*) - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' - else - lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -sco3.2v5*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown -])# AC_DEPLIBS_CHECK_METHOD - - -# AC_PROG_NM -# ---------- -# find the pathname to a BSD-compatible name lister -AC_DEFUN([AC_PROG_NM], -[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/${ac_tool_prefix}nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - esac - fi - done - IFS="$lt_save_ifs" - test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm -fi]) -NM="$lt_cv_path_NM" -])# AC_PROG_NM - - -# AC_CHECK_LIBM -# ------------- -# check for math library -AC_DEFUN([AC_CHECK_LIBM], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM="-lm") - ;; -esac -])# AC_CHECK_LIBM - - -# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl convenience library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL -# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If -# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will -# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with -# '${top_srcdir}/' (note the single quotes!). If your package is not -# flat and you're not using automake, define top_builddir and -# top_srcdir appropriately in the Makefiles. -AC_DEFUN([AC_LIBLTDL_CONVENIENCE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - case $enable_ltdl_convenience in - no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; - "") enable_ltdl_convenience=yes - ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; - esac - LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la - LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) - # For backwards non-gettext consistent compatibility... - INCLTDL="$LTDLINCL" -])# AC_LIBLTDL_CONVENIENCE - - -# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl installable library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-install to the configure arguments. Note that LIBLTDL -# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If -# DIRECTORY is not provided and an installed libltdl is not found, it is -# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' -# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single -# quotes!). If your package is not flat and you're not using automake, -# define top_builddir and top_srcdir appropriately in the Makefiles. -# In the future, this macro may have to be called after AC_PROG_LIBTOOL. -AC_DEFUN([AC_LIBLTDL_INSTALLABLE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - AC_CHECK_LIB(ltdl, lt_dlinit, - [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], - [if test x"$enable_ltdl_install" = xno; then - AC_MSG_WARN([libltdl not installed, but installation disabled]) - else - enable_ltdl_install=yes - fi - ]) - if test x"$enable_ltdl_install" = x"yes"; then - ac_configure_args="$ac_configure_args --enable-ltdl-install" - LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la - LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) - else - ac_configure_args="$ac_configure_args --enable-ltdl-install=no" - LIBLTDL="-lltdl" - LTDLINCL= - fi - # For backwards non-gettext consistent compatibility... - INCLTDL="$LTDLINCL" -])# AC_LIBLTDL_INSTALLABLE - - -# AC_LIBTOOL_CXX -# -------------- -# enable support for C++ libraries -AC_DEFUN([AC_LIBTOOL_CXX], -[AC_REQUIRE([_LT_AC_LANG_CXX]) -])# AC_LIBTOOL_CXX - - -# _LT_AC_LANG_CXX -# --------------- -AC_DEFUN([_LT_AC_LANG_CXX], -[AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([AC_PROG_CXXCPP]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) -])# _LT_AC_LANG_CXX - - -# AC_LIBTOOL_F77 -# -------------- -# enable support for Fortran 77 libraries -AC_DEFUN([AC_LIBTOOL_F77], -[AC_REQUIRE([_LT_AC_LANG_F77]) -])# AC_LIBTOOL_F77 - - -# _LT_AC_LANG_F77 -# --------------- -AC_DEFUN([_LT_AC_LANG_F77], -[AC_REQUIRE([AC_PROG_F77]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) -])# _LT_AC_LANG_F77 - - -# AC_LIBTOOL_GCJ -# -------------- -# enable support for GCJ libraries -AC_DEFUN([AC_LIBTOOL_GCJ], -[AC_REQUIRE([_LT_AC_LANG_GCJ]) -])# AC_LIBTOOL_GCJ - - -# _LT_AC_LANG_GCJ -# --------------- -AC_DEFUN([_LT_AC_LANG_GCJ], -[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], - [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], - [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], - [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], - [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) -])# _LT_AC_LANG_GCJ - - -# AC_LIBTOOL_RC -# -------------- -# enable support for Windows resource files -AC_DEFUN([AC_LIBTOOL_RC], -[AC_REQUIRE([LT_AC_PROG_RC]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) -])# AC_LIBTOOL_RC - - -# AC_LIBTOOL_LANG_C_CONFIG -# ------------------------ -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) -AC_DEFUN([_LT_AC_LANG_C_CONFIG], -[lt_save_CC="$CC" -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}\n' - -_LT_AC_SYS_COMPILER - -# -# Check for any special shared library compilation flags. -# -_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= -if test "$GCC" = no; then - case $host_os in - sco3.2v5*) - _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' - ;; - esac -fi -if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then - AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) - if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then : - else - AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) - _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no - fi -fi - - -# -# Check to make sure the static flag actually works. -# -AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), - $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), - [], - [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) - - -AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) - -# Report which librarie types wil actually be built -AC_MSG_CHECKING([if libtool supports shared libraries]) -AC_MSG_RESULT([$can_build_shared]) - -AC_MSG_CHECKING([whether to build shared libraries]) -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - darwin* | rhapsody*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; -esac -AC_MSG_RESULT([$enable_shared]) - -AC_MSG_CHECKING([whether to build static libraries]) -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -AC_MSG_RESULT([$enable_static]) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC="$lt_save_CC" -])# AC_LIBTOOL_LANG_C_CONFIG - - -# AC_LIBTOOL_LANG_CXX_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) -AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], -[AC_LANG_PUSH(C++) -AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([AC_PROG_CXXCPP]) - -_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_AC_TAGVAR(allow_undefined_flag, $1)= -_LT_AC_TAGVAR(always_export_symbols, $1)=no -_LT_AC_TAGVAR(archive_expsym_cmds, $1)= -_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_direct, $1)=no -_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= -_LT_AC_TAGVAR(hardcode_minus_L, $1)=no -_LT_AC_TAGVAR(hardcode_automatic, $1)=no -_LT_AC_TAGVAR(module_cmds, $1)= -_LT_AC_TAGVAR(module_expsym_cmds, $1)= -_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown -_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_AC_TAGVAR(no_undefined_flag, $1)= -_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= -_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Dependencies to place before and after the object being linked: -_LT_AC_TAGVAR(predep_objects, $1)= -_LT_AC_TAGVAR(postdep_objects, $1)= -_LT_AC_TAGVAR(predeps, $1)= -_LT_AC_TAGVAR(postdeps, $1)= -_LT_AC_TAGVAR(compiler_lib_search_path, $1)= - -# Source file extension for C++ test sources. -ac_ext=cc - -# Object file extension for compiled C++ test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_AC_SYS_COMPILER - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_LD=$LD -lt_save_GCC=$GCC -GCC=$GXX -lt_save_with_gnu_ld=$with_gnu_ld -lt_save_path_LD=$lt_cv_path_LD -if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx -else - unset lt_cv_prog_gnu_ld -fi -if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX -else - unset lt_cv_path_LD -fi -test -z "${LDCXX+set}" || LD=$LDCXX -CC=${CXX-"c++"} -compiler=$CC -_LT_AC_TAGVAR(compiler, $1)=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` - -# We don't want -fno-exception wen compiling C++ code, so set the -# no_builtin_flag separately -if test "$GXX" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' -else - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -fi - -if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - AC_PROG_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ - grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - -else - GXX=no - with_gnu_ld=no - wlarc= -fi - -# PORTME: fill in a description of your system's C++ link characteristics -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -_LT_AC_TAGVAR(ld_shlibs, $1)=yes -case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_AC_TAGVAR(archive_cmds, $1)='' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - else - # We have old collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds it's shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - dgux*) - case $cc_basename in - ec++) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - freebsd[12]*) - # C++ shared libraries reported to be fairly broken before switch to ELF - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - freebsd-elf*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - freebsd* | kfreebsd*-gnu) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - ;; - gnu*) - ;; - hpux9*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aCC) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - ;; - *) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - esac - fi - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - *) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aCC) - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case "$host_cpu" in - ia64*|hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - irix5* | irix6*) - case $cc_basename in - CC) - # SGI C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' - fi - fi - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - linux*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc) - # Intel C++ - with_gnu_ld=yes - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - cxx) - # Compaq C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - esac - ;; - lynxos*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - m88k*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - mvs*) - case $cc_basename in - cxx) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - osf3*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - - ;; - RCC) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - cxx) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - osf4* | osf5*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' - ;; - RCC) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - cxx) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ - $rm $lib.exp' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - psos*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - sco*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - lcc) - # Lucid - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - solaris*) - case $cc_basename in - CC) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The C++ compiler is used as linker so we must use $wl - # flag to pass the commands to the underlying system - # linker. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' - if $CC --version | grep -v '^2\.7' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - fi - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' - fi - ;; - esac - ;; - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - tandem*) - case $cc_basename in - NCC) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - vxworks*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; -esac -AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -_LT_AC_TAGVAR(GCC, $1)="$GXX" -_LT_AC_TAGVAR(LD, $1)="$LD" - -AC_LIBTOOL_POSTDEP_PREDEP($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC=$lt_save_CC -LDCXX=$LD -LD=$lt_save_LD -GCC=$lt_save_GCC -with_gnu_ldcxx=$with_gnu_ld -with_gnu_ld=$lt_save_with_gnu_ld -lt_cv_path_LDCXX=$lt_cv_path_LD -lt_cv_path_LD=$lt_save_path_LD -lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld -lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -])# AC_LIBTOOL_LANG_CXX_CONFIG - -# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) -# ------------------------ -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" -ifelse([$1], [], -[#! $SHELL - -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. -# -# This file is part of GNU Libtool: -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -# The names of the tagged configurations supported by this script. -available_tags= - -# ### BEGIN LIBTOOL CONFIG], -[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) - -# Is the compiler the GNU C compiler? -with_gcc=$_LT_AC_TAGVAR(GCC, $1) - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_[]_LT_AC_TAGVAR(LD, $1) - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext='$shrext' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) - -# Commands used to build and install a shared archive. -archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) -archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) -module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" - -# Set to yes if exported symbols are required. -always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) - -# The commands to list exported symbols. -export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) - -# Symbols that must always be exported. -include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) - -ifelse([$1],[], -[# ### END LIBTOOL CONFIG], -[# ### END LIBTOOL TAG CONFIG: $tagname]) - -__EOF__ - -ifelse([$1],[], [ - case $host_os in - aix3*) - cat <<\EOF >> "$cfgfile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || \ - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -]) -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi -])# AC_LIBTOOL_CONFIG - - -# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------------------- -AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], -[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl - -_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test "$GCC" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - - AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI - - -# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -# --------------------------------- -AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], -[AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([AC_PROG_NM]) -AC_REQUIRE([AC_OBJEXT]) -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - -# Transform an extracted symbol line into a proper C declaration -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) # Its linker distinguishes data from code symbols - if test "$host_cpu" = ia64; then - symcode='[[ABCDEGRST]]' - fi - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris* | sysv5*) - symcode='[[BDRT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if grep ' nm_test_var$' "$nlist" >/dev/null; then - if grep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' - - cat <> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[[]] = -{ -EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext - cat <<\EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -f conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi -]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE - - -# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) -# --------------------------------------- -AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], -[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= - -AC_MSG_CHECKING([for $compiler option to produce PIC]) - ifelse([$1],[CXX],[ - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | os2* | pw32*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix4* | aix5*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68) - # Green Hills C++ Compiler - # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | kfreebsd*-gnu) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - if test "$host_cpu" != ia64; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux*) - case $cc_basename in - KCC) - # KAI C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - icpc) - # Intel C++ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - cxx) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | knetbsd*-gnu) - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC) - # Rational C++ 2.4.1 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx) - # Digital/Compaq C++ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - sco*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - *) - ;; - esac - ;; - solaris*) - case $cc_basename in - CC) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC) - # Sun C++ 4.x - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc) - # Lucid - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC) - # NonStop-UX NCC 3.20 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - unixware*) - ;; - vxworks*) - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test "$GCC" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - newsos6) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - linux*) - case $CC in - icc* | ecc*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - ccc*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - sco3.2v5*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' - ;; - - solaris*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sunos4*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - uts4*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then - AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), - [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -case "$host_os" in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" - ;; -esac -]) - - -# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) -# ------------------------------------ -# See if the linker supports building shared libraries. -AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], -[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -ifelse([$1],[CXX],[ - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix4* | aix5*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - else - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' - ;; - *) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac -],[ - runpath_var= - _LT_AC_TAGVAR(allow_undefined_flag, $1)= - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)= - _LT_AC_TAGVAR(archive_expsym_cmds, $1)= - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= - _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_minus_L, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown - _LT_AC_TAGVAR(hardcode_automatic, $1)=no - _LT_AC_TAGVAR(module_cmds, $1)= - _LT_AC_TAGVAR(module_expsym_cmds, $1)= - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_AC_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - ld_shlibs=no - fi - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sunos4*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - linux*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" - fi - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - else - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_AC_TAGVAR(archive_cmds, $1)='' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - else - # We have old collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds it's shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - # see comment about different semantics on the GNU ld section - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - bsdi4*) - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes ; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - dgux*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - freebsd1*) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - - hpux10* | hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - ;; - *) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - openbsd*) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - else - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - sco3.2v5*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; - esac - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4.2uw2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - runpath_var='LD_RUN_PATH' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv5*) - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - fi -]) -AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -# -# Do we need to explicitly link libc? -# -case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $_LT_AC_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) - _LT_AC_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) - then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) - ;; - esac - fi - ;; -esac -])# AC_LIBTOOL_PROG_LD_SHLIBS - - -# _LT_AC_FILE_LTDLL_C -# ------------------- -# Be careful that the start marker always follows a newline. -AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ -# /* ltdll.c starts here */ -# #define WIN32_LEAN_AND_MEAN -# #include -# #undef WIN32_LEAN_AND_MEAN -# #include -# -# #ifndef __CYGWIN__ -# # ifdef __CYGWIN32__ -# # define __CYGWIN__ __CYGWIN32__ -# # endif -# #endif -# -# #ifdef __cplusplus -# extern "C" { -# #endif -# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); -# #ifdef __cplusplus -# } -# #endif -# -# #ifdef __CYGWIN__ -# #include -# DECLARE_CYGWIN_DLL( DllMain ); -# #endif -# HINSTANCE __hDllInstance_base; -# -# BOOL APIENTRY -# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) -# { -# __hDllInstance_base = hInst; -# return TRUE; -# } -# /* ltdll.c ends here */ -])# _LT_AC_FILE_LTDLL_C - - -# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) -# --------------------------------- -AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) - - -# old names -AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) -AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) -AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) -AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) -AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) - -# This is just to silence aclocal about the macro not being used -ifelse([AC_DISABLE_FAST_INSTALL]) - -AC_DEFUN([LT_AC_PROG_GCJ], -[AC_CHECK_TOOL(GCJ, gcj, no) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS) -]) - -AC_DEFUN([LT_AC_PROG_RC], -[AC_CHECK_TOOL(RC, windres, no) -]) - -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -# LT_AC_PROG_SED -# -------------- -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -AC_DEFUN([LT_AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && break - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -SED=$lt_cv_path_SED -]) -AC_MSG_RESULT([$SED]) -]) - -# -*- Autoconf -*- -# Copyright (C) 2002, 2003 Free Software Foundation, Inc. -# Generated from amversion.in; do not edit by hand. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"]) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION so it can be traced. -# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.8.2])]) - -# Figure out how to run the assembler. -*- Autoconf -*- - -# serial 3 - -# Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# AM_PROG_AS -# ---------- -AC_DEFUN([AM_PROG_AS], -[# By default we simply use the C compiler to build assembly code. -AC_REQUIRE([AC_PROG_CC]) -test "${CCAS+set}" = set || CCAS=$CC -test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS -AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) -AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) -]) - -# AM_AUX_DIR_EXPAND - -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 6 - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE]) -AC_SUBST([$1_FALSE]) -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]) -fi])]) - -# serial 6 -*- Autoconf -*- - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 -# Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - - -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - : > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # (even with -Werror). So we grep stderr for any message - # that says an option was ignored. - if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH]) -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -#serial 2 - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue - # Extract the definition of DEP_FILES from the Makefile without - # running `make'. - DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` - test -z "$DEPDIR" && continue - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n -e '/^U = / s///p' < "$mf"` - test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" - # We invoke sed twice because it is the simplest approach to - # changing $(DEPDIR) to its actual value in the expansion. - for file in `sed -n -e ' - /^DEP_FILES = .*\\\\$/ { - s/^DEP_FILES = // - :loop - s/\\\\$// - p - n - /\\\\$/ b loop - p - } - /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done -done -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 7 - -# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. -AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) - -# Do all the work for Automake. -*- Autoconf -*- - -# This macro actually does too much some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 -# Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 11 - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.58])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) -AM_MISSING_PROG(AMTAR, tar) -AM_PROG_INSTALL_SH -AM_PROG_INSTALL_STRIP -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl - -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl -]) -]) - - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $1 | $1:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. - -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -install_sh=${install_sh-"$am_aux_dir/install-sh"} -AC_SUBST(install_sh)]) - -# -*- Autoconf -*- -# Copyright (C) 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 1 - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 2 - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo done -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# -*- Autoconf -*- - - -# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 3 - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) -fi -]) - -# AM_PROG_MKDIR_P -# --------------- -# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. - -# Copyright (C) 2003, 2004 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories -# created by `make install' are always world readable, even if the -# installer happens to have an overly restrictive umask (e.g. 077). -# This was a mistake. There are at least two reasons why we must not -# use `-m 0755': -# - it causes special bits like SGID to be ignored, -# - it may be too restrictive (some setups expect 775 directories). -# -# Do not use -m 0755 and let people choose whatever they expect by -# setting umask. -AC_DEFUN([AM_PROG_MKDIR_P], -[if mkdir -p -- . 2>/dev/null; then - # Keeping the `.' argument allows $(mkdir_p) to be used without - # argument. Indeed, we sometimes output rules like - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. - # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more - # expensive solution, as it forces Make to start a sub-shell.) - mkdir_p='mkdir -p -- .' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' - else - mkdir_p='$(install_sh) -d' - fi -fi -AC_SUBST([mkdir_p])]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 2 - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# ------------------------------ -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) - -# _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# -# Check to make sure that the build environment is sane. -# - -# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# serial 3 - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT(yes)]) - -# AM_PROG_INSTALL_STRIP - -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# One issue with vendor `install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - diff --git a/code/libmad-0.15.1b/bit.h b/code/libmad-0.15.1b/bit.h deleted file mode 100644 index 5a51570b..00000000 --- a/code/libmad-0.15.1b/bit.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: bit.h,v 1.12 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_BIT_H -# define LIBMAD_BIT_H - -struct mad_bitptr { - unsigned char const *byte; - unsigned short cache; - unsigned short left; -}; - -void mad_bit_init(struct mad_bitptr *, unsigned char const *); - -# define mad_bit_finish(bitptr) /* nothing */ - -unsigned int mad_bit_length(struct mad_bitptr const *, - struct mad_bitptr const *); - -# define mad_bit_bitsleft(bitptr) ((bitptr)->left) -unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); - -void mad_bit_skip(struct mad_bitptr *, unsigned int); -unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); -void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); - -unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); - -# endif diff --git a/code/libmad-0.15.1b/config.guess b/code/libmad-0.15.1b/config.guess deleted file mode 100644 index e8c6fc0c..00000000 --- a/code/libmad-0.15.1b/config.guess +++ /dev/null @@ -1,1432 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -timestamp='2004-01-05' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - macppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvmeppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pegasos:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mipseb-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sun3:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha*:OpenVMS:*:*) - echo alpha-hp-vms - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit 0;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit 0 ;; - DRS?6000:UNIX_SV:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7 && exit 0 ;; - esac ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c \ - && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && exit 0 - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit 0 ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - # avoid double evaluation of $set_cc_for_build - test -n "$CC_FOR_BUILD" || eval $set_cc_for_build - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - *:UNICOS/mp:*:*) - echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - # Determine whether the default compiler uses glibc. - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #if __GLIBC__ >= 2 - LIBC=gnu - #else - LIBC= - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - # GNU/KFreeBSD systems have a "k" prefix to indicate we are using - # FreeBSD's kernel, but not the complete OS. - case ${LIBC} in gnu) kernel_only='k' ;; esac - echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - x86:Interix*:[34]*) - echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' - exit 0 ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit 0 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #ifdef __INTEL_COMPILER - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit 0 ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i*86:*:5:[78]*) - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit 0 ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - case `uname -p` in - *86) UNAME_PROCESSOR=i686 ;; - powerpc) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit 0 ;; - *:DRAGONFLY:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly${UNAME_RELEASE} - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/code/libmad-0.15.1b/config.h.in b/code/libmad-0.15.1b/config.h.in deleted file mode 100644 index a29b5820..00000000 --- a/code/libmad-0.15.1b/config.h.in +++ /dev/null @@ -1,135 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to enable diagnostic debugging support. */ -#undef DEBUG - -/* Define to enable experimental code. */ -#undef EXPERIMENTAL - -/* Define to 1 if you have the header file. */ -#undef HAVE_ASSERT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_ERRNO_H - -/* Define to 1 if you have the `fcntl' function. */ -#undef HAVE_FCNTL - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define if your MIPS CPU supports a 2-operand MADD16 instruction. */ -#undef HAVE_MADD16_ASM - -/* Define if your MIPS CPU supports a 2-operand MADD instruction. */ -#undef HAVE_MADD_ASM - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `pipe' function. */ -#undef HAVE_PIPE - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have that is POSIX.1 compatible. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `waitpid' function. */ -#undef HAVE_WAITPID - -/* Define to disable debugging assertions. */ -#undef NDEBUG - -/* Define to optimize for accuracy over speed. */ -#undef OPT_ACCURACY - -/* Define to optimize for speed over accuracy. */ -#undef OPT_SPEED - -/* Define to enable a fast subband synthesis approximation optimization. */ -#undef OPT_SSO - -/* Define to influence a strict interpretation of the ISO/IEC standards, even - if this is in opposition with best accepted practices. */ -#undef OPT_STRICT - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* The size of a `int', as computed by sizeof. */ -#undef SIZEOF_INT - -/* The size of a `long', as computed by sizeof. */ -#undef SIZEOF_LONG - -/* The size of a `long long', as computed by sizeof. */ -#undef SIZEOF_LONG_LONG - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Version number of package */ -#undef VERSION - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#undef WORDS_BIGENDIAN - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to `int' if does not define. */ -#undef pid_t diff --git a/code/libmad-0.15.1b/config.sub b/code/libmad-0.15.1b/config.sub deleted file mode 100644 index 463186db..00000000 --- a/code/libmad-0.15.1b/config.sub +++ /dev/null @@ -1,1537 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -timestamp='2004-01-05' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ - kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | msp430 \ - | ns16k | ns32k \ - | openrisc | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xscale | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32r-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - or32 | or32-*) - basic_machine=or32-unknown - os=-coff - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/code/libmad-0.15.1b/configure b/code/libmad-0.15.1b/configure deleted file mode 100644 index ee421cc3..00000000 --- a/code/libmad-0.15.1b/configure +++ /dev/null @@ -1,23106 +0,0 @@ -#! /bin/sh -# From configure.ac Id: configure.ac,v 1.9 2004/01/23 09:41:32 rob Exp . -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for MPEG Audio Decoder 0.15.1b. -# -# Report bugs to . -# -# Copyright (C) 2003 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - - - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -echo=${ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null && - echo_test_string="`eval $cmd`" && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null - then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : -else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - echo='printf %s\n' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -ECHO=$echo -if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - - -tagnames=${tagnames+${tagnames},}CXX - -tagnames=${tagnames+${tagnames},}F77 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -exec 6>&1 - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_config_libobj_dir=. -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} - -# Identity of this package. -PACKAGE_NAME='MPEG Audio Decoder' -PACKAGE_TARNAME='libmad' -PACKAGE_VERSION='0.15.1b' -PACKAGE_STRING='MPEG Audio Decoder 0.15.1b' -PACKAGE_BUGREPORT='support@underbit.com' - -ac_unique_file="decoder.h" -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#if HAVE_SYS_TYPES_H -# include -#endif -#if HAVE_SYS_STAT_H -# include -#endif -#if STDC_HEADERS -# include -# include -#else -# if HAVE_STDLIB_H -# include -# endif -#endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H -# include -# endif -# include -#endif -#if HAVE_STRINGS_H -# include -#endif -#if HAVE_INTTYPES_H -# include -#else -# if HAVE_STDINT_H -# include -# endif -#endif -#if HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS CCASFLAGS EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS FPM ASO ASO_OBJS LIBOBJS LTLIBOBJS' -ac_subst_files='' - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -ac_prev= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_option in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "enable_$ac_feature='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "with_$ac_package='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi -fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS -ac_env_CCAS_set=${CCAS+set} -ac_env_CCAS_value=$CCAS -ac_cv_env_CCAS_set=${CCAS+set} -ac_cv_env_CCAS_value=$CCAS -ac_env_CCASFLAGS_set=${CCASFLAGS+set} -ac_env_CCASFLAGS_value=$CCASFLAGS -ac_cv_env_CCASFLAGS_set=${CCASFLAGS+set} -ac_cv_env_CCASFLAGS_value=$CCASFLAGS -ac_env_CPP_set=${CPP+set} -ac_env_CPP_value=$CPP -ac_cv_env_CPP_set=${CPP+set} -ac_cv_env_CPP_value=$CPP -ac_env_CXX_set=${CXX+set} -ac_env_CXX_value=$CXX -ac_cv_env_CXX_set=${CXX+set} -ac_cv_env_CXX_value=$CXX -ac_env_CXXFLAGS_set=${CXXFLAGS+set} -ac_env_CXXFLAGS_value=$CXXFLAGS -ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} -ac_cv_env_CXXFLAGS_value=$CXXFLAGS -ac_env_CXXCPP_set=${CXXCPP+set} -ac_env_CXXCPP_value=$CXXCPP -ac_cv_env_CXXCPP_set=${CXXCPP+set} -ac_cv_env_CXXCPP_value=$CXXCPP -ac_env_F77_set=${F77+set} -ac_env_F77_value=$F77 -ac_cv_env_F77_set=${F77+set} -ac_cv_env_F77_value=$F77 -ac_env_FFLAGS_set=${FFLAGS+set} -ac_env_FFLAGS_value=$FFLAGS -ac_cv_env_FFLAGS_set=${FFLAGS+set} -ac_cv_env_FFLAGS_value=$FFLAGS - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures MPEG Audio Decoder 0.15.1b to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -_ACEOF - - cat <<_ACEOF -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of MPEG Audio Decoder 0.15.1b:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors - --enable-shared[=PKGS] - build shared libraries [default=yes] - --enable-static[=PKGS] - build static libraries [default=yes] - --enable-fast-install[=PKGS] - optimize for fast installation [default=yes] - --disable-libtool-lock avoid locking (might break parallel builds) - --enable-speed optimize for speed over accuracy - --enable-accuracy optimize for accuracy over speed - --enable-fpm=ARCH use ARCH-specific fixed-point math routines (one of: - intel, arm, mips, sparc, ppc, 64bit, default) - --enable-sso use subband synthesis optimization - --disable-aso disable architecture-specific optimizations - --enable-strict-iso use strict ISO/IEC interpretations - --enable-profiling generate profiling code - --enable-debugging enable diagnostic debugging support - --disable-debugging do not enable debugging and use more optimization - --enable-experimental enable experimental code - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-pic try to use only PIC/non-PIC objects [default=use - both] - --with-tags[=TAGS] - include additional configurations [automatic] - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have - headers in a nonstandard directory - CCAS assembler compiler command (defaults to CC) - CCASFLAGS assembler compiler flags (defaults to CFLAGS) - CPP C preprocessor - CXX C++ compiler command - CXXFLAGS C++ compiler flags - CXXCPP C++ preprocessor - F77 Fortran 77 compiler command - FFLAGS Fortran 77 compiler flags - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -_ACEOF -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - ac_popdir=`pwd` - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd "$ac_popdir" - done -fi - -test -n "$ac_init_help" && exit 0 -if $ac_init_version; then - cat <<\_ACEOF -MPEG Audio Decoder configure 0.15.1b -generated by GNU Autoconf 2.59 - -Copyright (C) 2003 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit 0 -fi -exec 5>config.log -cat >&5 <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by MPEG Audio Decoder $as_me 0.15.1b, which was -generated by GNU Autoconf 2.59. Invocation command line was - - $ $0 $@ - -_ACEOF -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_sep= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -{ - (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) - sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; - *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - sed "/^$/d" confdefs.h | sort - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status - ' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo >confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . $cache_file;; - *) . ./$cache_file;; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -am__api_version="1.8" -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f $ac_dir/shtool; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 -echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} - { (exit 1); exit 1; }; } -fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - done - done - ;; -esac -done - - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the path is relative. - INSTALL=$ac_install_sh - fi -fi -echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6 - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -echo "$as_me:$LINENO: checking whether build environment is sane" >&5 -echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 -# Just in case -sleep 1 -echo timestamp > conftest.file -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` - fi - rm -f conftest.file - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&5 -echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&2;} - { (exit 1); exit 1; }; } - fi - - test "$2" = conftest.file - ) -then - # Ok. - : -else - { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! -Check your system clock" >&5 -echo "$as_me: error: newly created file is older than distributed files! -Check your system clock" >&2;} - { (exit 1); exit 1; }; } -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -test "$program_prefix" != NONE && - program_transform_name="s,^,$program_prefix,;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s,\$,$program_suffix,;$program_transform_name" -# Double any \ or $. echo might interpret backslashes. -# By default was `s,x,x', remove it if useless. -cat <<\_ACEOF >conftest.sed -s/[\\$]/&&/g;s/;s,x,x,$// -_ACEOF -program_transform_name=`echo $program_transform_name | sed -f conftest.sed` -rm conftest.sed - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 -echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} -fi - -if mkdir -p -- . 2>/dev/null; then - # Keeping the `.' argument allows $(mkdir_p) to be used without - # argument. Indeed, we sometimes output rules like - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. - # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more - # expensive solution, as it forces Make to start a sub-shell.) - mkdir_p='mkdir -p -- .' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' - else - mkdir_p='$(install_sh) -d' - fi -fi - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_AWK+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - echo "$as_me:$LINENO: result: $AWK" >&5 -echo "${ECHO_T}$AWK" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$AWK" && break -done - -echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` -if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.make <<\_ACEOF -all: - @echo 'ac_maketemp="$(MAKE)"' -_ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` -if test -n "$ac_maketemp"; then - eval ac_cv_prog_make_${ac_make}_set=yes -else - eval ac_cv_prog_make_${ac_make}_set=no -fi -rm -f conftest.make -fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - SET_MAKE= -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 -echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} - { (exit 1); exit 1; }; } -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE='libmad' - VERSION='0.15.1b' - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - - -AMTAR=${AMTAR-"${am_missing_run}tar"} - -install_sh=${install_sh-"$am_aux_dir/install-sh"} - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - STRIP=$ac_ct_STRIP -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. - - - - - ac_config_headers="$ac_config_headers config.h" - - - -# Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } - -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 -build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 -host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; - * ) - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 - -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -DEPDIR="${am__leading_dot}deps" - - ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo done -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 -echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi -fi - - -echo "$as_me:$LINENO: result: $_am_result" >&5 -echo "${ECHO_T}$_am_result" >&6 -rm -f confinc confmf - -# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then - enableval="$enable_dependency_tracking" - -fi; -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi - - -if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - - - -depcc="$CC" am_compiler_list= - -echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - : > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # (even with -Werror). So we grep stderr for any message - # that says an option was ignored. - if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - - -if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - -# By default we simply use the C compiler to build assembly code. - -test "${CCAS+set}" = set || CCAS=$CC -test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS - - - - -if test "$GCC" = yes -then - case "$host" in - *-*-mingw*) - case "$build" in - *-*-cygwin*) - CPPFLAGS="$CPPFLAGS -mno-cygwin" - LDFLAGS="$LDFLAGS -mno-cygwin" - ;; - esac - esac - -fi - - -# Check whether --enable-shared or --disable-shared was given. -if test "${enable_shared+set}" = set; then - enableval="$enable_shared" - p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_shared=yes -fi; - -# Check whether --enable-static or --disable-static was given. -if test "${enable_static+set}" = set; then - enableval="$enable_static" - p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_static=yes -fi; - -# Check whether --enable-fast-install or --disable-fast-install was given. -if test "${enable_fast_install+set}" = set; then - enableval="$enable_fast_install" - p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_fast_install=yes -fi; - -echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 -echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 -if test "${lt_cv_path_SED+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && break - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -SED=$lt_cv_path_SED - -fi - -echo "$as_me:$LINENO: result: $SED" >&5 -echo "${ECHO_T}$SED" >&6 - -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep - - - -# Check whether --with-gnu-ld or --without-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then - withval="$with_gnu_ld" - test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi; -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo "$as_me:$LINENO: checking for ld used by $CC" >&5 -echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - echo "$as_me:$LINENO: checking for GNU ld" >&5 -echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 -else - echo "$as_me:$LINENO: checking for non-GNU ld" >&5 -echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 -fi -if test "${lt_cv_path_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -echo "${ECHO_T}$LD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 -echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 -if test "${lt_cv_prog_gnu_ld+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # I'd rather use --version here, but apparently some GNU ld's only accept -v. -case `$LD -v 2>&1 &5 -echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 -with_gnu_ld=$lt_cv_prog_gnu_ld - - -echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 -echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 -if test "${lt_cv_ld_reload_flag+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_ld_reload_flag='-r' -fi -echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 -echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' - -echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 -echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 -if test "${lt_cv_path_NM+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/${ac_tool_prefix}nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - esac - fi - done - IFS="$lt_save_ifs" - test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm -fi -fi -echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 -echo "${ECHO_T}$lt_cv_path_NM" >&6 -NM="$lt_cv_path_NM" - -echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else - echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&6 -fi - -echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 -echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 -if test "${lt_cv_deplibs_check_method+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. - -case $host_os in -aix4* | aix5*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi4*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # win32_libid shell function, so use a weaker test based on 'objdump'. - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | kfreebsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case "$host_cpu" in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -nto-qnx*) - lt_cv_deplibs_check_method=unknown - ;; - -openbsd*) - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' - else - lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -sco3.2v5*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 -echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Check whether --enable-libtool-lock or --disable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then - enableval="$enable_libtool_lock" - -fi; -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '#line 3683 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case "`/usr/bin/file conftest.o`" in - *32-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 -echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 -if test "${lt_cv_cc_needs_belf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - lt_cv_cc_needs_belf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -lt_cv_cc_needs_belf=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 -echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; - -esac - -need_locks="$enable_libtool_lock" - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6 -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - -for ac_header in dlfcn.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ----------------------------------- ## -## Report this to support@underbit.com ## -## ----------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -n "$ac_tool_prefix"; then - for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - echo "$as_me:$LINENO: result: $CXX" >&5 -echo "${ECHO_T}$CXX" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 -echo "${ECHO_T}$ac_ct_CXX" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CXX" && break -done -test -n "$ac_ct_CXX" || ac_ct_CXX="g++" - - CXX=$ac_ct_CXX -fi - - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C++ compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 -GXX=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -CXXFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 -echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cxx_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cxx_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cxx_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -depcc="$CXX" am_compiler_list= - -echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 -if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - : > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # (even with -Werror). So we grep stderr for any message - # that says an option was ignored. - if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - - -if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 -echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 -if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -echo "$as_me:$LINENO: result: $CXXCPP" >&5 -echo "${ECHO_T}$CXXCPP" >&6 -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -ac_ext=f -ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' -ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_f77_compiler_gnu -if test -n "$ac_tool_prefix"; then - for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$F77"; then - ac_cv_prog_F77="$F77" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_F77="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -F77=$ac_cv_prog_F77 -if test -n "$F77"; then - echo "$as_me:$LINENO: result: $F77" >&5 -echo "${ECHO_T}$F77" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$F77" && break - done -fi -if test -z "$F77"; then - ac_ct_F77=$F77 - for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_F77"; then - ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_F77="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_F77=$ac_cv_prog_ac_ct_F77 -if test -n "$ac_ct_F77"; then - echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 -echo "${ECHO_T}$ac_ct_F77" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_F77" && break -done - - F77=$ac_ct_F77 -fi - - -# Provide some information about the compiler. -echo "$as_me:5240:" \ - "checking for Fortran 77 compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -rm -f a.out - -# If we don't use `.F' as extension, the preprocessor is not run on the -# input file. (Note that this only needs to work for GNU compilers.) -ac_save_ext=$ac_ext -ac_ext=F -echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6 -if test "${ac_cv_f77_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF - program main -#ifndef __GNUC__ - choke me -#endif - - end -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_f77_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6 -ac_ext=$ac_save_ext -ac_test_FFLAGS=${FFLAGS+set} -ac_save_FFLAGS=$FFLAGS -FFLAGS= -echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 -echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_f77_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - FFLAGS=-g -cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_f77_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_f77_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 -echo "${ECHO_T}$ac_cv_prog_f77_g" >&6 -if test "$ac_test_FFLAGS" = set; then - FFLAGS=$ac_save_FFLAGS -elif test $ac_cv_prog_f77_g = yes; then - if test "x$ac_cv_f77_compiler_gnu" = xyes; then - FFLAGS="-g -O2" - else - FFLAGS="-g" - fi -else - if test "x$ac_cv_f77_compiler_gnu" = xyes; then - FFLAGS="-O2" - else - FFLAGS= - fi -fi - -G77=`test $ac_compiler_gnu = yes && echo yes` -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! - -# find the maximum length of command line arguments -echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 -echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6 -if test "${lt_cv_sys_max_cmd_len+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - i=0 - testring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - *) - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while (test "X"`$CONFIG_SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ - = "XX$testring") >/dev/null 2>&1 && - new_result=`expr "X$testring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - testring=$testring$testring - done - testring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - ;; - esac - -fi - -if test -n $lt_cv_sys_max_cmd_len ; then - echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 -echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6 -else - echo "$as_me:$LINENO: result: none" >&5 -echo "${ECHO_T}none" >&6 -fi - - - - -# Check for command to grab the raw symbol name followed by C symbol from nm. -echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 -echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6 -if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - -# Transform an extracted symbol line into a proper C declaration -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw* | pw32*) - symcode='[ABCDGISTW]' - ;; -hpux*) # Its linker distinguishes data from code symbols - if test "$host_cpu" = ia64; then - symcode='[ABCDEGRST]' - fi - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - ;; -irix* | nonstopux*) - symcode='[BCDEGRST]' - ;; -osf*) - symcode='[BCDEGQRST]' - ;; -solaris* | sysv5*) - symcode='[BDRT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[ABCDGIRSTW]' ;; -esac - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Now try to grab the symbols. - nlist=conftest.nm - if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if grep ' nm_test_var$' "$nlist" >/dev/null; then - if grep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' - - cat <> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{ -EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext - cat <<\EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - fi - rm -f conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done - -fi - -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - echo "$as_me:$LINENO: result: failed" >&5 -echo "${ECHO_T}failed" >&6 -else - echo "$as_me:$LINENO: result: ok" >&5 -echo "${ECHO_T}ok" >&6 -fi - -echo "$as_me:$LINENO: checking for objdir" >&5 -echo $ECHO_N "checking for objdir... $ECHO_C" >&6 -if test "${lt_cv_objdir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null -fi -echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 -echo "${ECHO_T}$lt_cv_objdir" >&6 -objdir=$lt_cv_objdir - - - - - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' -sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Constants: -rm="rm -f" - -# Global variables: -default_ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except M$VC, -# which needs '.lib'). -libext=a -ltmain="$ac_aux_dir/ltmain.sh" -ofile="$default_ofile" -with_gnu_ld="$lt_cv_prog_gnu_ld" - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="${ac_tool_prefix}ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - echo "$as_me:$LINENO: result: $AR" >&5 -echo "${ECHO_T}$AR" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_AR"; then - ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false" -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 -echo "${ECHO_T}$ac_ct_AR" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - AR=$ac_ct_AR -else - AR="$ac_cv_prog_AR" -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - RANLIB=$ac_ct_RANLIB -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - STRIP=$ac_ct_STRIP -else - STRIP="$ac_cv_prog_STRIP" -fi - - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -test -z "$AS" && AS=as -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$LD" && LD=ld -test -z "$LN_S" && LN_S="ln -s" -test -z "$MAGIC_CMD" && MAGIC_CMD=file -test -z "$NM" && NM=nm -test -z "$SED" && SED=sed -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$RANLIB" && RANLIB=: -test -z "$STRIP" && STRIP=: -test -z "$ac_objext" && ac_objext=o - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" - ;; - *) - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - -# Only perform the check for file, if the check method requires it -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 -echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 -echo "${ECHO_T}$MAGIC_CMD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - echo "$as_me:$LINENO: checking for file" >&5 -echo $ECHO_N "checking for file... $ECHO_C" >&6 -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 -echo "${ECHO_T}$MAGIC_CMD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - else - MAGIC_CMD=: - fi -fi - - fi - ;; -esac - -enable_dlopen=no -enable_win32_dll=no - -# Check whether --enable-libtool-lock or --disable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then - enableval="$enable_libtool_lock" - -fi; -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - - -# Check whether --with-pic or --without-pic was given. -if test "${with_pic+set}" = set; then - withval="$with_pic" - pic_mode="$withval" -else - pic_mode=default -fi; -test -z "$pic_mode" && pic_mode=default - -# Use C for the default configuration in the libtool script -tagname= -lt_save_CC="$CC" -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -objext=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}\n' - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# -# Check for any special shared library compilation flags. -# -lt_prog_cc_shlib= -if test "$GCC" = no; then - case $host_os in - sco3.2v5*) - lt_prog_cc_shlib='-belf' - ;; - esac -fi -if test -n "$lt_prog_cc_shlib"; then - { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5 -echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;} - if echo "$old_CC $old_CFLAGS " | grep "[ ]$lt_prog_cc_shlib[ ]" >/dev/null; then : - else - { echo "$as_me:$LINENO: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 -echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} - lt_cv_prog_cc_can_build_shared=no - fi -fi - - -# -# Check to make sure the static flag actually works. -# -echo "$as_me:$LINENO: checking if $compiler static flag $lt_prog_compiler_static works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_prog_compiler_static works... $ECHO_C" >&6 -if test "${lt_prog_compiler_static_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_prog_compiler_static" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - else - lt_prog_compiler_static_works=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 - -if test x"$lt_prog_compiler_static_works" = xyes; then - : -else - lt_prog_compiler_static= -fi - - - - -lt_prog_compiler_no_builtin_flag= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' - - -echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6272: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:6276: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" -else - : -fi - -fi - -lt_prog_compiler_wl= -lt_prog_compiler_pic= -lt_prog_compiler_static= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - if test "$GCC" = yes; then - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_static='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - linux*) - case $CC in - icc* | ecc*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-static' - ;; - ccc*) - lt_prog_compiler_wl='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - - sco3.2v5*) - lt_prog_compiler_pic='-Kpic' - lt_prog_compiler_static='-dn' - ;; - - solaris*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sunos4*) - lt_prog_compiler_wl='-Qoption ld ' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic='-Kconform_pic' - lt_prog_compiler_static='-Bstatic' - fi - ;; - - uts4*) - lt_prog_compiler_pic='-pic' - lt_prog_compiler_static='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6505: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:6509: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - lt_prog_compiler_pic_works=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6 - -if test x"$lt_prog_compiler_pic_works" = xyes; then - case $lt_prog_compiler_pic in - "" | " "*) ;; - *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; - esac -else - lt_prog_compiler_pic= - lt_prog_compiler_can_build_shared=no -fi - -fi -case "$host_os" in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic= - ;; - *) - lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" - ;; -esac - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6565: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:6569: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s out/conftest.err; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - runpath_var= - allow_undefined_flag= - enable_shared_with_static_runtimes=no - archive_cmds= - archive_expsym_cmds= - old_archive_From_new_cmds= - old_archive_from_expsyms_cmds= - export_dynamic_flag_spec= - whole_archive_flag_spec= - thread_safe_flag_spec= - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld= - hardcode_libdir_separator= - hardcode_direct=no - hardcode_minus_L=no - hardcode_shlibpath_var=unsupported - link_all_deplibs=unknown - hardcode_automatic=no - module_cmds= - module_expsym_cmds= - always_export_symbols=no - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=no - enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - ld_shlibs=no - fi - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - linux*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_cmds="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - archive_expsym_cmds="$tmp_archive_cmds" - fi - else - ld_shlibs=no - fi - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds='' - hardcode_direct=yes - hardcode_libdir_separator=':' - link_all_deplibs=yes - - if test "$GCC" = yes; then - case $host_os in aix4.012|aix4.012.*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct=yes - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols=yes - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec=' ' - archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - - bsdi4*) - export_dynamic_flag_spec=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes=yes - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes ; then - archive_cmds_need_lc=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='-all_load $convenience' - link_all_deplibs=yes - else - ld_shlibs=no - fi - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' - ;; - - hpux10* | hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' - ;; - *) - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld='+b $libdir' - hardcode_libdir_separator=: - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - ia64*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=no - hardcode_shlibpath_var=no - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - *) - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld='-rpath $libdir' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - link_all_deplibs=yes - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - newsos6) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_shlibpath_var=no - ;; - - openbsd*) - hardcode_direct=yes - hardcode_shlibpath_var=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - hardcode_libdir_separator=: - ;; - - sco3.2v5*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - no_undefined_flag=' -z text' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; - esac - link_all_deplibs=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds='$CC -r -o $output$reload_objs' - hardcode_direct=no - ;; - motorola) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4.2uw2*) - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=no - hardcode_shlibpath_var=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - no_undefined_flag='${wl}-z ${wl}text' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv5*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - hardcode_libdir_flag_spec= - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $ld_shlibs" >&5 -echo "${ECHO_T}$ld_shlibs" >&6 -test "$ld_shlibs" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 -echo "${ECHO_T}$archive_cmds_need_lc" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext='$(test .$module = .yes && echo .so || echo .dylib)' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.01* | freebsdelf3.01*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case "$host_cpu" in - ia64*) - shrext='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` - sys_lib_dlsearch_path_spec="/lib /usr/lib $ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - need_lib_prefix=no - need_version=yes - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var " || \ - test "X$hardcode_automatic"="Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action" >&5 -echo "${ECHO_T}$hardcode_action" >&6 - -if test "$hardcode_action" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -char (*f) () = shl_load; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shl_load; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6 -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -int -main () -{ -shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -char (*f) () = dlopen; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != dlopen; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6 -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_svld_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dld_link (); -int -main () -{ -dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_dld_link=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6 - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - -# Report which librarie types wil actually be built -echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 -echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $can_build_shared" >&5 -echo "${ECHO_T}$can_build_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 -echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - darwin* | rhapsody*) - if test "$GCC" = yes; then - archive_cmds_need_lc=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - output_verbose_link_cmd='echo' - archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='-all_load $convenience' - link_all_deplibs=yes - else - ld_shlibs=no - fi - ;; -esac -echo "$as_me:$LINENO: result: $enable_shared" >&5 -echo "${ECHO_T}$enable_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build static libraries" >&5 -echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -echo "$as_me:$LINENO: result: $enable_static" >&5 -echo "${ECHO_T}$enable_static" >&6 - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler \ - CC \ - LD \ - lt_prog_compiler_wl \ - lt_prog_compiler_pic \ - lt_prog_compiler_static \ - lt_prog_compiler_no_builtin_flag \ - export_dynamic_flag_spec \ - thread_safe_flag_spec \ - whole_archive_flag_spec \ - enable_shared_with_static_runtimes \ - old_archive_cmds \ - old_archive_from_new_cmds \ - predep_objects \ - postdep_objects \ - predeps \ - postdeps \ - compiler_lib_search_path \ - archive_cmds \ - archive_expsym_cmds \ - postinstall_cmds \ - postuninstall_cmds \ - old_archive_from_expsyms_cmds \ - allow_undefined_flag \ - no_undefined_flag \ - export_symbols_cmds \ - hardcode_libdir_flag_spec \ - hardcode_libdir_flag_spec_ld \ - hardcode_libdir_separator \ - hardcode_automatic \ - module_cmds \ - module_expsym_cmds \ - lt_cv_prog_compiler_c_o \ - exclude_expsyms \ - include_expsyms; do - - case $var in - old_archive_cmds | \ - old_archive_from_new_cmds | \ - archive_cmds | \ - archive_expsym_cmds | \ - module_cmds | \ - module_expsym_cmds | \ - old_archive_from_expsyms_cmds | \ - export_symbols_cmds | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="${ofile}T" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - $rm -f "$cfgfile" - { echo "$as_me:$LINENO: creating $ofile" >&5 -echo "$as_me: creating $ofile" >&6;} - - cat <<__EOF__ >> "$cfgfile" -#! $SHELL - -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. -# -# This file is part of GNU Libtool: -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -# The names of the tagged configurations supported by this script. -available_tags= - -# ### BEGIN LIBTOOL CONFIG - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU C compiler? -with_gcc=$GCC - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext='$shrext' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# ### END LIBTOOL CONFIG - -__EOF__ - - - case $host_os in - aix3*) - cat <<\EOF >> "$cfgfile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || \ - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - -# Check whether --with-tags or --without-tags was given. -if test "${with_tags+set}" = set; then - withval="$with_tags" - tagnames="$withval" -fi; - -if test -f "$ltmain" && test -n "$tagnames"; then - if test ! -f "${ofile}"; then - { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 -echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} - fi - - if test -z "$LTCC"; then - eval "`$SHELL ${ofile} --config | grep '^LTCC='`" - if test -z "$LTCC"; then - { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 -echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} - else - { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 -echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} - fi - fi - - # Extract list of available tagged configurations in $ofile. - # Note that this assumes the entire list is on one line. - available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` - - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for tagname in $tagnames; do - IFS="$lt_save_ifs" - # Check whether tagname contains only valid characters - case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in - "") ;; - *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 -echo "$as_me: error: invalid tag name: $tagname" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null - then - { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 -echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} - { (exit 1); exit 1; }; } - fi - - # Update the list of available tags. - if test -n "$tagname"; then - echo appending configuration tag \"$tagname\" to $ofile - - case $tagname in - CXX) - if test -n "$CXX" && test "X$CXX" != "Xno"; then - ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - - -archive_cmds_need_lc_CXX=no -allow_undefined_flag_CXX= -always_export_symbols_CXX=no -archive_expsym_cmds_CXX= -export_dynamic_flag_spec_CXX= -hardcode_direct_CXX=no -hardcode_libdir_flag_spec_CXX= -hardcode_libdir_flag_spec_ld_CXX= -hardcode_libdir_separator_CXX= -hardcode_minus_L_CXX=no -hardcode_automatic_CXX=no -module_cmds_CXX= -module_expsym_cmds_CXX= -link_all_deplibs_CXX=unknown -old_archive_cmds_CXX=$old_archive_cmds -no_undefined_flag_CXX= -whole_archive_flag_spec_CXX= -enable_shared_with_static_runtimes_CXX=no - -# Dependencies to place before and after the object being linked: -predep_objects_CXX= -postdep_objects_CXX= -predeps_CXX= -postdeps_CXX= -compiler_lib_search_path_CXX= - -# Source file extension for C++ test sources. -ac_ext=cc - -# Object file extension for compiled C++ test sources. -objext=o -objext_CXX=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *) { return(0); }\n' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_LD=$LD -lt_save_GCC=$GCC -GCC=$GXX -lt_save_with_gnu_ld=$with_gnu_ld -lt_save_path_LD=$lt_cv_path_LD -if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx -else - unset lt_cv_prog_gnu_ld -fi -if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX -else - unset lt_cv_path_LD -fi -test -z "${LDCXX+set}" || LD=$LDCXX -CC=${CXX-"c++"} -compiler=$CC -compiler_CXX=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` - -# We don't want -fno-exception wen compiling C++ code, so set the -# no_builtin_flag separately -if test "$GXX" = yes; then - lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' -else - lt_prog_compiler_no_builtin_flag_CXX= -fi - -if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - -# Check whether --with-gnu-ld or --without-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then - withval="$with_gnu_ld" - test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi; -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo "$as_me:$LINENO: checking for ld used by $CC" >&5 -echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - echo "$as_me:$LINENO: checking for GNU ld" >&5 -echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 -else - echo "$as_me:$LINENO: checking for non-GNU ld" >&5 -echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 -fi -if test "${lt_cv_path_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -echo "${ECHO_T}$LD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 -echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 -if test "${lt_cv_prog_gnu_ld+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # I'd rather use --version here, but apparently some GNU ld's only accept -v. -case `$LD -v 2>&1 &5 -echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ - grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_CXX= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - -else - GXX=no - with_gnu_ld=no - wlarc= -fi - -# PORTME: fill in a description of your system's C++ link characteristics -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 -ld_shlibs_CXX=yes -case $host_os in - aix3*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_CXX='' - hardcode_direct_CXX=yes - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - - if test "$GXX" = yes; then - case $host_os in aix4.012|aix4.012.*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct_CXX=yes - else - # We have old collect2 - hardcode_direct_CXX=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_CXX=yes - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_libdir_separator_CXX= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_CXX=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_CXX='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - - archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' ${wl}-bernotok' - allow_undefined_flag_CXX=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols_CXX=yes - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX=' ' - archive_cmds_need_lc_CXX=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - ld_shlibs_CXX=no - fi - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes; then - archive_cmds_need_lc_CXX=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag_CXX='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_CXX='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_CXX='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag_CXX='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_CXX='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_CXX='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - whole_archive_flag_spec_CXX='-all_load $convenience' - link_all_deplibs_CXX=yes - else - ld_shlibs_CXX=no - fi - ;; - - dgux*) - case $cc_basename in - ec++) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - ghcx) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - freebsd12*) - # C++ shared libraries reported to be fairly broken before switch to ELF - ld_shlibs_CXX=no - ;; - freebsd-elf*) - archive_cmds_need_lc_CXX=no - ;; - freebsd* | kfreebsd*-gnu) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - ld_shlibs_CXX=yes - ;; - gnu*) - ;; - hpux9*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='${wl}-E' - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC) - archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld_CXX='+b $libdir' - hardcode_libdir_separator_CXX=: - ;; - ia64*) - hardcode_libdir_flag_spec_CXX='-L$libdir' - ;; - *) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='${wl}-E' - ;; - esac - fi - case "$host_cpu" in - hppa*64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - ;; - ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - *) - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC) - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' - ;; - *) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case "$host_cpu" in - ia64*|hppa*64*) - archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' - ;; - *) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - irix5* | irix6*) - case $cc_basename in - CC) - # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' - fi - fi - link_all_deplibs_CXX=yes - ;; - esac - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - ;; - linux*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc) - # Intel C++ - with_gnu_ld=yes - archive_cmds_need_lc_CXX=no - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - cxx) - # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - esac - ;; - lynxos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - m88k*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - mvs*) - case $cc_basename in - cxx) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - osf3*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - - ;; - RCC) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx) - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - osf4* | osf5*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' - ;; - RCC) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx) - allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ - $rm $lib.exp' - - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - psos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - sco*) - archive_cmds_need_lc_CXX=no - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - lcc) - # Lucid - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - solaris*) - case $cc_basename in - CC) - # Sun C++ 4.2, 5.x and Centerline C++ - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_shlibpath_var_CXX=no - case $host_os in - solaris2.0-5 | solaris2.0-5.*) ;; - *) - # The C++ compiler is used as linker so we must use $wl - # flag to pass the commands to the underlying system - # linker. - # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - link_all_deplibs_CXX=yes - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - gcx) - # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - no_undefined_flag_CXX=' ${wl}-z ${wl}defs' - if $CC --version | grep -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - fi - - hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' - fi - ;; - esac - ;; - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - archive_cmds_need_lc_CXX=no - ;; - tandem*) - case $cc_basename in - NCC) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - vxworks*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; -esac -echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 -echo "${ECHO_T}$ld_shlibs_CXX" >&6 -test "$ld_shlibs_CXX" = no && can_build_shared=no - -GCC_CXX="$GXX" -LD_CXX="$LD" - - -cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - # The `*' in the case matches for architectures that use `case' in - # $output_verbose_cmd can trigger glob expansion during the loop - # eval without this substitution. - output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" - - for p in `eval $output_verbose_link_cmd`; do - case $p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" \ - || test $p = "-R"; then - prev=$p - continue - else - prev= - fi - - if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX="${prev}${p}" - else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$postdeps_CXX"; then - postdeps_CXX="${prev}${p}" - else - postdeps_CXX="${postdeps_CXX} ${prev}${p}" - fi - fi - ;; - - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$predep_objects_CXX"; then - predep_objects_CXX="$p" - else - predep_objects_CXX="$predep_objects_CXX $p" - fi - else - if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX="$p" - else - postdep_objects_CXX="$postdep_objects_CXX $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling CXX test program" -fi - -$rm -f confest.$objext - -case " $postdeps_CXX " in -*" -lc "*) archive_cmds_need_lc_CXX=no ;; -esac - -lt_prog_compiler_wl_CXX= -lt_prog_compiler_pic_CXX= -lt_prog_compiler_static_CXX= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' - ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | os2* | pw32*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_CXX='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - lt_prog_compiler_pic_CXX= - ;; - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_CXX=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - else - case $host_os in - aix4* | aix5*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68) - # Green Hills C++ Compiler - # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++) - lt_prog_compiler_pic_CXX='-KPIC' - ;; - ghcx) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | kfreebsd*-gnu) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - if test "$host_cpu" != ia64; then - lt_prog_compiler_pic_CXX='+Z' - fi - ;; - aCC) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_CXX='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux*) - case $cc_basename in - KCC) - # KAI C++ Compiler - lt_prog_compiler_wl_CXX='--backend -Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - ;; - icpc) - # Intel C++ - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-static' - ;; - cxx) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx) - lt_prog_compiler_pic_CXX='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | knetbsd*-gnu) - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC) - lt_prog_compiler_wl_CXX='--backend -Wl,' - ;; - RCC) - # Rational C++ 2.4.1 - lt_prog_compiler_pic_CXX='-pic' - ;; - cxx) - # Digital/Compaq C++ - lt_prog_compiler_wl_CXX='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - sco*) - case $cc_basename in - CC) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - *) - ;; - esac - ;; - solaris*) - case $cc_basename in - CC) - # Sun C++ 4.2, 5.x and Centerline C++ - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - gcx) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC) - # Sun C++ 4.x - lt_prog_compiler_pic_CXX='-pic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - lcc) - # Lucid - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC) - # NonStop-UX NCC 3.20 - lt_prog_compiler_pic_CXX='-KPIC' - ;; - *) - ;; - esac - ;; - unixware*) - ;; - vxworks*) - ;; - *) - lt_prog_compiler_can_build_shared_CXX=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_CXX"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_CXX=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11015: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:11019: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - lt_prog_compiler_pic_works_CXX=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6 - -if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then - case $lt_prog_compiler_pic_CXX in - "" | " "*) ;; - *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; - esac -else - lt_prog_compiler_pic_CXX= - lt_prog_compiler_can_build_shared_CXX=no -fi - -fi -case "$host_os" in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_CXX= - ;; - *) - lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" - ;; -esac - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11075: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:11079: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s out/conftest.err; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix4* | aix5*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - export_symbols_cmds_CXX="$ltdll_cmds" - ;; - cygwin* | mingw*) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - -echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 -echo "${ECHO_T}$ld_shlibs_CXX" >&6 -test "$ld_shlibs_CXX" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_CXX" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_CXX=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_CXX in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_CXX=no - else - archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext='$(test .$module = .yes && echo .so || echo .dylib)' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.01* | freebsdelf3.01*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case "$host_cpu" in - ia64*) - shrext='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` - sys_lib_dlsearch_path_spec="/lib /usr/lib $ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - need_lib_prefix=no - need_version=yes - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action_CXX= -if test -n "$hardcode_libdir_flag_spec_CXX" || \ - test -n "$runpath_var CXX" || \ - test "X$hardcode_automatic_CXX"="Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_CXX" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && - test "$hardcode_minus_L_CXX" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_CXX=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_CXX=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_CXX=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 -echo "${ECHO_T}$hardcode_action_CXX" >&6 - -if test "$hardcode_action_CXX" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -char (*f) () = shl_load; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shl_load; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6 -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -int -main () -{ -shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -char (*f) () = dlopen; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != dlopen; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6 -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_svld_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dld_link (); -int -main () -{ -dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_dld_link=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6 - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_CXX \ - CC_CXX \ - LD_CXX \ - lt_prog_compiler_wl_CXX \ - lt_prog_compiler_pic_CXX \ - lt_prog_compiler_static_CXX \ - lt_prog_compiler_no_builtin_flag_CXX \ - export_dynamic_flag_spec_CXX \ - thread_safe_flag_spec_CXX \ - whole_archive_flag_spec_CXX \ - enable_shared_with_static_runtimes_CXX \ - old_archive_cmds_CXX \ - old_archive_from_new_cmds_CXX \ - predep_objects_CXX \ - postdep_objects_CXX \ - predeps_CXX \ - postdeps_CXX \ - compiler_lib_search_path_CXX \ - archive_cmds_CXX \ - archive_expsym_cmds_CXX \ - postinstall_cmds_CXX \ - postuninstall_cmds_CXX \ - old_archive_from_expsyms_cmds_CXX \ - allow_undefined_flag_CXX \ - no_undefined_flag_CXX \ - export_symbols_cmds_CXX \ - hardcode_libdir_flag_spec_CXX \ - hardcode_libdir_flag_spec_ld_CXX \ - hardcode_libdir_separator_CXX \ - hardcode_automatic_CXX \ - module_cmds_CXX \ - module_expsym_cmds_CXX \ - lt_cv_prog_compiler_c_o_CXX \ - exclude_expsyms_CXX \ - include_expsyms_CXX; do - - case $var in - old_archive_cmds_CXX | \ - old_archive_from_new_cmds_CXX | \ - archive_cmds_CXX | \ - archive_expsym_cmds_CXX | \ - module_cmds_CXX | \ - module_expsym_cmds_CXX | \ - old_archive_from_expsyms_cmds_CXX | \ - export_symbols_cmds_CXX | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_CXX - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_compiler_CXX - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_CXX - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_CXX - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext='$shrext' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_CXX -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_CXX - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_CXX -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_CXX -archive_expsym_cmds=$lt_archive_expsym_cmds_CXX -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_CXX -module_expsym_cmds=$lt_module_expsym_cmds_CXX - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_CXX - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_CXX - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_CXX - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_CXX - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_CXX - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_CXX - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_CXX - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_CXX - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_CXX - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_CXX - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_CXX - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_CXX - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_CXX" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_CXX - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_CXX - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_CXX - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_CXX - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC=$lt_save_CC -LDCXX=$LD -LD=$lt_save_LD -GCC=$lt_save_GCC -with_gnu_ldcxx=$with_gnu_ld -with_gnu_ld=$lt_save_with_gnu_ld -lt_cv_path_LDCXX=$lt_cv_path_LD -lt_cv_path_LD=$lt_save_path_LD -lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld -lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld - - else - tagname="" - fi - ;; - - F77) - if test -n "$F77" && test "X$F77" != "Xno"; then - -ac_ext=f -ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' -ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_f77_compiler_gnu - - -archive_cmds_need_lc_F77=no -allow_undefined_flag_F77= -always_export_symbols_F77=no -archive_expsym_cmds_F77= -export_dynamic_flag_spec_F77= -hardcode_direct_F77=no -hardcode_libdir_flag_spec_F77= -hardcode_libdir_flag_spec_ld_F77= -hardcode_libdir_separator_F77= -hardcode_minus_L_F77=no -hardcode_automatic_F77=no -module_cmds_F77= -module_expsym_cmds_F77= -link_all_deplibs_F77=unknown -old_archive_cmds_F77=$old_archive_cmds -no_undefined_flag_F77= -whole_archive_flag_spec_F77= -enable_shared_with_static_runtimes_F77=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -objext_F77=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code=" subroutine t\n return\n end\n" - -# Code to be used in simple link tests -lt_simple_link_test_code=" program t\n end\n" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${F77-"f77"} -compiler=$CC -compiler_F77=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` - -echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 -echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $can_build_shared" >&5 -echo "${ECHO_T}$can_build_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 -echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; -aix4*) - test "$enable_shared" = yes && enable_static=no - ;; -esac -echo "$as_me:$LINENO: result: $enable_shared" >&5 -echo "${ECHO_T}$enable_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build static libraries" >&5 -echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -echo "$as_me:$LINENO: result: $enable_static" >&5 -echo "${ECHO_T}$enable_static" >&6 - -test "$ld_shlibs_F77" = no && can_build_shared=no - -GCC_F77="$G77" -LD_F77="$LD" - -lt_prog_compiler_wl_F77= -lt_prog_compiler_pic_F77= -lt_prog_compiler_static_F77= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - if test "$GCC" = yes; then - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_static_F77='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_F77='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_F77='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_F77='-fno-common' - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared_F77=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_F77=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_F77='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic_F77='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl_F77='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_F77='-Bstatic' - else - lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_F77='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl_F77='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_F77='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static_F77='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl_F77='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static_F77='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - linux*) - case $CC in - icc* | ecc*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-static' - ;; - ccc*) - lt_prog_compiler_wl_F77='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static_F77='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl_F77='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static_F77='-non_shared' - ;; - - sco3.2v5*) - lt_prog_compiler_pic_F77='-Kpic' - lt_prog_compiler_static_F77='-dn' - ;; - - solaris*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sunos4*) - lt_prog_compiler_wl_F77='-Qoption ld ' - lt_prog_compiler_pic_F77='-PIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic_F77='-Kconform_pic' - lt_prog_compiler_static_F77='-Bstatic' - fi - ;; - - uts4*) - lt_prog_compiler_pic_F77='-pic' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared_F77=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_F77"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_F77=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_F77" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13354: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:13358: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - lt_prog_compiler_pic_works_F77=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6 - -if test x"$lt_prog_compiler_pic_works_F77" = xyes; then - case $lt_prog_compiler_pic_F77 in - "" | " "*) ;; - *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; - esac -else - lt_prog_compiler_pic_F77= - lt_prog_compiler_can_build_shared_F77=no -fi - -fi -case "$host_os" in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_F77= - ;; - *) - lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" - ;; -esac - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_F77=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13414: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:13418: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s out/conftest.err; then - lt_cv_prog_compiler_c_o_F77=yes - fi - fi - chmod u+w . - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - runpath_var= - allow_undefined_flag_F77= - enable_shared_with_static_runtimes_F77=no - archive_cmds_F77= - archive_expsym_cmds_F77= - old_archive_From_new_cmds_F77= - old_archive_from_expsyms_cmds_F77= - export_dynamic_flag_spec_F77= - whole_archive_flag_spec_F77= - thread_safe_flag_spec_F77= - hardcode_libdir_flag_spec_F77= - hardcode_libdir_flag_spec_ld_F77= - hardcode_libdir_separator_F77= - hardcode_direct_F77=no - hardcode_minus_L_F77=no - hardcode_shlibpath_var_F77=unsupported - link_all_deplibs_F77=unknown - hardcode_automatic_F77=no - module_cmds_F77= - module_expsym_cmds_F77= - always_export_symbols_F77=no - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms_F77= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs_F77=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs_F77=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs_F77=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_F77=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_F77=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_F77='-L$libdir' - allow_undefined_flag_F77=unsupported - always_export_symbols_F77=no - enable_shared_with_static_runtimes_F77=yes - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - ld_shlibs=no - fi - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs_F77=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - - sunos4*) - archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - linux*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_cmds_F77="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - archive_expsym_cmds_F77="$tmp_archive_cmds" - fi - else - ld_shlibs_F77=no - fi - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - esac - - if test "$ld_shlibs_F77" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_F77='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_F77= - fi - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag_F77=unsupported - always_export_symbols_F77=yes - archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L_F77=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct_F77=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_F77='' - hardcode_direct_F77=yes - hardcode_libdir_separator_F77=':' - link_all_deplibs_F77=yes - - if test "$GCC" = yes; then - case $host_os in aix4.012|aix4.012.*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct_F77=yes - else - # We have old collect2 - hardcode_direct_F77=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_F77=yes - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_libdir_separator_F77= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_F77=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_F77='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_F77="-z nodefs" - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_F77=' ${wl}-bernotok' - allow_undefined_flag_F77=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols_F77=yes - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_F77=' ' - archive_cmds_need_lc_F77=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - # see comment about different semantics on the GNU ld section - ld_shlibs_F77=no - ;; - - bsdi4*) - export_dynamic_flag_spec_F77=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_F77=' ' - allow_undefined_flag_F77=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds_F77='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes_F77=yes - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes ; then - archive_cmds_need_lc_F77=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag_F77='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_F77='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_F77='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag_F77='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_F77='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_F77='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_F77='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct_F77=no - hardcode_automatic_F77=yes - hardcode_shlibpath_var_F77=unsupported - whole_archive_flag_spec_F77='-all_load $convenience' - link_all_deplibs_F77=yes - else - ld_shlibs_F77=no - fi - ;; - - dgux*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_shlibpath_var_F77=no - ;; - - freebsd1*) - ld_shlibs_F77=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_minus_L_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) - archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_direct_F77=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - ;; - - hpux10* | hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' - ;; - *) - archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld_F77='+b $libdir' - hardcode_libdir_separator_F77=: - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - ;; - ia64*) - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - ;; - *) - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_direct_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' - fi - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - link_all_deplibs_F77=yes - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - newsos6) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_shlibpath_var_F77=no - ;; - - openbsd*) - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - export_dynamic_flag_spec_F77='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - ;; - *) - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - allow_undefined_flag_F77=unsupported - archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag_F77=' -expect_unresolved \*' - archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag_F77=' -expect_unresolved \*' - archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec_F77='-rpath $libdir' - fi - hardcode_libdir_separator_F77=: - ;; - - sco3.2v5*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - export_dynamic_flag_spec_F77='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - no_undefined_flag_F77=' -z text' - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_shlibpath_var_F77=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; - esac - link_all_deplibs_F77=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_direct_F77=yes - hardcode_minus_L_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds_F77='$CC -r -o $output$reload_objs' - hardcode_direct_F77=no - ;; - motorola) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_F77=no - ;; - - sysv4.3*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - export_dynamic_flag_spec_F77='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs_F77=yes - fi - ;; - - sysv4.2uw2*) - archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_minus_L_F77=no - hardcode_shlibpath_var_F77=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - no_undefined_flag_F77='${wl}-z ${wl}text' - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_F77=no - ;; - - sysv5*) - no_undefined_flag_F77=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - hardcode_libdir_flag_spec_F77= - hardcode_shlibpath_var_F77=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_shlibpath_var_F77=no - ;; - - *) - ld_shlibs_F77=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 -echo "${ECHO_T}$ld_shlibs_F77" >&6 -test "$ld_shlibs_F77" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_F77" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_F77=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_F77 in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_F77 - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_F77 - allow_undefined_flag_F77= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_F77=no - else - archive_cmds_need_lc_F77=yes - fi - allow_undefined_flag_F77=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext='$(test .$module = .yes && echo .so || echo .dylib)' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.01* | freebsdelf3.01*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case "$host_cpu" in - ia64*) - shrext='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` - sys_lib_dlsearch_path_spec="/lib /usr/lib $ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - need_lib_prefix=no - need_version=yes - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action_F77= -if test -n "$hardcode_libdir_flag_spec_F77" || \ - test -n "$runpath_var F77" || \ - test "X$hardcode_automatic_F77"="Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_F77" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && - test "$hardcode_minus_L_F77" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_F77=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_F77=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_F77=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 -echo "${ECHO_T}$hardcode_action_F77" >&6 - -if test "$hardcode_action_F77" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_F77 \ - CC_F77 \ - LD_F77 \ - lt_prog_compiler_wl_F77 \ - lt_prog_compiler_pic_F77 \ - lt_prog_compiler_static_F77 \ - lt_prog_compiler_no_builtin_flag_F77 \ - export_dynamic_flag_spec_F77 \ - thread_safe_flag_spec_F77 \ - whole_archive_flag_spec_F77 \ - enable_shared_with_static_runtimes_F77 \ - old_archive_cmds_F77 \ - old_archive_from_new_cmds_F77 \ - predep_objects_F77 \ - postdep_objects_F77 \ - predeps_F77 \ - postdeps_F77 \ - compiler_lib_search_path_F77 \ - archive_cmds_F77 \ - archive_expsym_cmds_F77 \ - postinstall_cmds_F77 \ - postuninstall_cmds_F77 \ - old_archive_from_expsyms_cmds_F77 \ - allow_undefined_flag_F77 \ - no_undefined_flag_F77 \ - export_symbols_cmds_F77 \ - hardcode_libdir_flag_spec_F77 \ - hardcode_libdir_flag_spec_ld_F77 \ - hardcode_libdir_separator_F77 \ - hardcode_automatic_F77 \ - module_cmds_F77 \ - module_expsym_cmds_F77 \ - lt_cv_prog_compiler_c_o_F77 \ - exclude_expsyms_F77 \ - include_expsyms_F77; do - - case $var in - old_archive_cmds_F77 | \ - old_archive_from_new_cmds_F77 | \ - archive_cmds_F77 | \ - archive_expsym_cmds_F77 | \ - module_cmds_F77 | \ - module_expsym_cmds_F77 | \ - old_archive_from_expsyms_cmds_F77 | \ - export_symbols_cmds_F77 | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_F77 - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_compiler_F77 - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_F77 - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_F77 - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_F77 - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext='$shrext' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_F77 -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_F77 - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_F77 -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_F77 -archive_expsym_cmds=$lt_archive_expsym_cmds_F77 -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_F77 -module_expsym_cmds=$lt_module_expsym_cmds_F77 - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_F77 - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_F77 - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_F77 - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_F77 - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_F77 - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_F77 - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_F77 - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_F77 - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_F77 - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_F77 - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_F77 - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_F77 - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_F77" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_F77 - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_F77 - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_F77 - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_F77 - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - else - tagname="" - fi - ;; - - GCJ) - if test -n "$GCJ" && test "X$GCJ" != "Xno"; then - - - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -objext_GCJ=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String argv) {}; }\n' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${GCJ-"gcj"} -compiler=$CC -compiler_GCJ=$CC - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -archive_cmds_need_lc_GCJ=no - - -lt_prog_compiler_no_builtin_flag_GCJ= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' - - -echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15446: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:15450: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" -else - : -fi - -fi - -lt_prog_compiler_wl_GCJ= -lt_prog_compiler_pic_GCJ= -lt_prog_compiler_static_GCJ= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - if test "$GCC" = yes; then - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_static_GCJ='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_GCJ='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_GCJ='-fno-common' - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared_GCJ=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_GCJ=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_GCJ='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic_GCJ='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl_GCJ='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_GCJ='-Bstatic' - else - lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl_GCJ='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_GCJ='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl_GCJ='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - linux*) - case $CC in - icc* | ecc*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-static' - ;; - ccc*) - lt_prog_compiler_wl_GCJ='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl_GCJ='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - sco3.2v5*) - lt_prog_compiler_pic_GCJ='-Kpic' - lt_prog_compiler_static_GCJ='-dn' - ;; - - solaris*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sunos4*) - lt_prog_compiler_wl_GCJ='-Qoption ld ' - lt_prog_compiler_pic_GCJ='-PIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic_GCJ='-Kconform_pic' - lt_prog_compiler_static_GCJ='-Bstatic' - fi - ;; - - uts4*) - lt_prog_compiler_pic_GCJ='-pic' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared_GCJ=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_GCJ"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_GCJ=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_GCJ" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15679: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:15683: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - lt_prog_compiler_pic_works_GCJ=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6 - -if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then - case $lt_prog_compiler_pic_GCJ in - "" | " "*) ;; - *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; - esac -else - lt_prog_compiler_pic_GCJ= - lt_prog_compiler_can_build_shared_GCJ=no -fi - -fi -case "$host_os" in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_GCJ= - ;; - *) - lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" - ;; -esac - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_GCJ=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15739: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:15743: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s out/conftest.err; then - lt_cv_prog_compiler_c_o_GCJ=yes - fi - fi - chmod u+w . - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - runpath_var= - allow_undefined_flag_GCJ= - enable_shared_with_static_runtimes_GCJ=no - archive_cmds_GCJ= - archive_expsym_cmds_GCJ= - old_archive_From_new_cmds_GCJ= - old_archive_from_expsyms_cmds_GCJ= - export_dynamic_flag_spec_GCJ= - whole_archive_flag_spec_GCJ= - thread_safe_flag_spec_GCJ= - hardcode_libdir_flag_spec_GCJ= - hardcode_libdir_flag_spec_ld_GCJ= - hardcode_libdir_separator_GCJ= - hardcode_direct_GCJ=no - hardcode_minus_L_GCJ=no - hardcode_shlibpath_var_GCJ=unsupported - link_all_deplibs_GCJ=unknown - hardcode_automatic_GCJ=no - module_cmds_GCJ= - module_expsym_cmds_GCJ= - always_export_symbols_GCJ=no - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms_GCJ= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs_GCJ=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs_GCJ=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs_GCJ=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_GCJ=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_GCJ='-L$libdir' - allow_undefined_flag_GCJ=unsupported - always_export_symbols_GCJ=no - enable_shared_with_static_runtimes_GCJ=yes - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - ld_shlibs=no - fi - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs_GCJ=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - sunos4*) - archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - linux*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_cmds_GCJ="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - archive_expsym_cmds_GCJ="$tmp_archive_cmds" - fi - else - ld_shlibs_GCJ=no - fi - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - esac - - if test "$ld_shlibs_GCJ" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_GCJ= - fi - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag_GCJ=unsupported - always_export_symbols_GCJ=yes - archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L_GCJ=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct_GCJ=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_GCJ='' - hardcode_direct_GCJ=yes - hardcode_libdir_separator_GCJ=':' - link_all_deplibs_GCJ=yes - - if test "$GCC" = yes; then - case $host_os in aix4.012|aix4.012.*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct_GCJ=yes - else - # We have old collect2 - hardcode_direct_GCJ=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_GCJ=yes - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_libdir_separator_GCJ= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_GCJ=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_GCJ='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_GCJ="-z nodefs" - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_GCJ=' ${wl}-bernotok' - allow_undefined_flag_GCJ=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols_GCJ=yes - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_GCJ=' ' - archive_cmds_need_lc_GCJ=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - # see comment about different semantics on the GNU ld section - ld_shlibs_GCJ=no - ;; - - bsdi4*) - export_dynamic_flag_spec_GCJ=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_GCJ=' ' - allow_undefined_flag_GCJ=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds_GCJ='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes_GCJ=yes - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes ; then - archive_cmds_need_lc_GCJ=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag_GCJ='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag_GCJ='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_GCJ='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_GCJ='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_GCJ='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct_GCJ=no - hardcode_automatic_GCJ=yes - hardcode_shlibpath_var_GCJ=unsupported - whole_archive_flag_spec_GCJ='-all_load $convenience' - link_all_deplibs_GCJ=yes - else - ld_shlibs_GCJ=no - fi - ;; - - dgux*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_shlibpath_var_GCJ=no - ;; - - freebsd1*) - ld_shlibs_GCJ=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) - archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_direct_GCJ=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - ;; - - hpux10* | hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' - ;; - *) - archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' - hardcode_libdir_separator_GCJ=: - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - ;; - ia64*) - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - ;; - *) - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_direct_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' - fi - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - link_all_deplibs_GCJ=yes - ;; - - netbsd* | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - newsos6) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_shlibpath_var_GCJ=no - ;; - - openbsd*) - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - export_dynamic_flag_spec_GCJ='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - ;; - *) - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - allow_undefined_flag_GCJ=unsupported - archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag_GCJ=' -expect_unresolved \*' - archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag_GCJ=' -expect_unresolved \*' - archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec_GCJ='-rpath $libdir' - fi - hardcode_libdir_separator_GCJ=: - ;; - - sco3.2v5*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - export_dynamic_flag_spec_GCJ='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - no_undefined_flag_GCJ=' -z text' - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_shlibpath_var_GCJ=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; - esac - link_all_deplibs_GCJ=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds_GCJ='$CC -r -o $output$reload_objs' - hardcode_direct_GCJ=no - ;; - motorola) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_GCJ=no - ;; - - sysv4.3*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - export_dynamic_flag_spec_GCJ='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs_GCJ=yes - fi - ;; - - sysv4.2uw2*) - archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=no - hardcode_shlibpath_var_GCJ=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - no_undefined_flag_GCJ='${wl}-z ${wl}text' - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_GCJ=no - ;; - - sysv5*) - no_undefined_flag_GCJ=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - hardcode_libdir_flag_spec_GCJ= - hardcode_shlibpath_var_GCJ=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_shlibpath_var_GCJ=no - ;; - - *) - ld_shlibs_GCJ=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 -echo "${ECHO_T}$ld_shlibs_GCJ" >&6 -test "$ld_shlibs_GCJ" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_GCJ" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_GCJ=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_GCJ in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_GCJ - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ - allow_undefined_flag_GCJ= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_GCJ=no - else - archive_cmds_need_lc_GCJ=yes - fi - allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext='$(test .$module = .yes && echo .so || echo .dylib)' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.01* | freebsdelf3.01*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case "$host_cpu" in - ia64*) - shrext='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf` - sys_lib_dlsearch_path_spec="/lib /usr/lib $ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - need_lib_prefix=no - need_version=yes - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action_GCJ= -if test -n "$hardcode_libdir_flag_spec_GCJ" || \ - test -n "$runpath_var GCJ" || \ - test "X$hardcode_automatic_GCJ"="Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_GCJ" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && - test "$hardcode_minus_L_GCJ" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_GCJ=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_GCJ=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_GCJ=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 -echo "${ECHO_T}$hardcode_action_GCJ" >&6 - -if test "$hardcode_action_GCJ" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -char (*f) () = shl_load; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shl_load; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6 -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -int -main () -{ -shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -char (*f) () = dlopen; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != dlopen; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6 -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_svld_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dld_link (); -int -main () -{ -dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_dld_link=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6 - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_GCJ \ - CC_GCJ \ - LD_GCJ \ - lt_prog_compiler_wl_GCJ \ - lt_prog_compiler_pic_GCJ \ - lt_prog_compiler_static_GCJ \ - lt_prog_compiler_no_builtin_flag_GCJ \ - export_dynamic_flag_spec_GCJ \ - thread_safe_flag_spec_GCJ \ - whole_archive_flag_spec_GCJ \ - enable_shared_with_static_runtimes_GCJ \ - old_archive_cmds_GCJ \ - old_archive_from_new_cmds_GCJ \ - predep_objects_GCJ \ - postdep_objects_GCJ \ - predeps_GCJ \ - postdeps_GCJ \ - compiler_lib_search_path_GCJ \ - archive_cmds_GCJ \ - archive_expsym_cmds_GCJ \ - postinstall_cmds_GCJ \ - postuninstall_cmds_GCJ \ - old_archive_from_expsyms_cmds_GCJ \ - allow_undefined_flag_GCJ \ - no_undefined_flag_GCJ \ - export_symbols_cmds_GCJ \ - hardcode_libdir_flag_spec_GCJ \ - hardcode_libdir_flag_spec_ld_GCJ \ - hardcode_libdir_separator_GCJ \ - hardcode_automatic_GCJ \ - module_cmds_GCJ \ - module_expsym_cmds_GCJ \ - lt_cv_prog_compiler_c_o_GCJ \ - exclude_expsyms_GCJ \ - include_expsyms_GCJ; do - - case $var in - old_archive_cmds_GCJ | \ - old_archive_from_new_cmds_GCJ | \ - archive_cmds_GCJ | \ - archive_expsym_cmds_GCJ | \ - module_cmds_GCJ | \ - module_expsym_cmds_GCJ | \ - old_archive_from_expsyms_cmds_GCJ | \ - export_symbols_cmds_GCJ | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_GCJ - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_compiler_GCJ - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_GCJ - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_GCJ - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_GCJ - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext='$shrext' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_GCJ -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_GCJ - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_GCJ -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_GCJ -archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_GCJ -module_expsym_cmds=$lt_module_expsym_cmds_GCJ - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_GCJ - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_GCJ - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_GCJ - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_GCJ - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_GCJ - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_GCJ - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_GCJ - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_GCJ - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_GCJ - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_GCJ - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_GCJ - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_GCJ" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_GCJ - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_GCJ - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_GCJ - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_GCJ - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - else - tagname="" - fi - ;; - - RC) - - - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -objext_RC=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${RC-"windres"} -compiler=$CC -compiler_RC=$CC -lt_cv_prog_compiler_c_o_RC=yes - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_RC \ - CC_RC \ - LD_RC \ - lt_prog_compiler_wl_RC \ - lt_prog_compiler_pic_RC \ - lt_prog_compiler_static_RC \ - lt_prog_compiler_no_builtin_flag_RC \ - export_dynamic_flag_spec_RC \ - thread_safe_flag_spec_RC \ - whole_archive_flag_spec_RC \ - enable_shared_with_static_runtimes_RC \ - old_archive_cmds_RC \ - old_archive_from_new_cmds_RC \ - predep_objects_RC \ - postdep_objects_RC \ - predeps_RC \ - postdeps_RC \ - compiler_lib_search_path_RC \ - archive_cmds_RC \ - archive_expsym_cmds_RC \ - postinstall_cmds_RC \ - postuninstall_cmds_RC \ - old_archive_from_expsyms_cmds_RC \ - allow_undefined_flag_RC \ - no_undefined_flag_RC \ - export_symbols_cmds_RC \ - hardcode_libdir_flag_spec_RC \ - hardcode_libdir_flag_spec_ld_RC \ - hardcode_libdir_separator_RC \ - hardcode_automatic_RC \ - module_cmds_RC \ - module_expsym_cmds_RC \ - lt_cv_prog_compiler_c_o_RC \ - exclude_expsyms_RC \ - include_expsyms_RC; do - - case $var in - old_archive_cmds_RC | \ - old_archive_from_new_cmds_RC | \ - archive_cmds_RC | \ - archive_expsym_cmds_RC | \ - module_cmds_RC | \ - module_expsym_cmds_RC | \ - old_archive_from_expsyms_cmds_RC | \ - export_symbols_cmds_RC | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_RC - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_compiler_RC - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_RC - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_RC - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_RC - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext='$shrext' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_RC -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_RC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_RC -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_RC -archive_expsym_cmds=$lt_archive_expsym_cmds_RC -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_RC -module_expsym_cmds=$lt_module_expsym_cmds_RC - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_RC - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_RC - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_RC - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_RC - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_RC - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_RC - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_RC - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_RC - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_RC - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_RC - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_RC - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_RC - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_RC - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_RC" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_RC - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_RC - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_RC - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_RC - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - ;; - - *) - { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 -echo "$as_me: error: Unsupported tag name: $tagname" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - # Append the new tag name to the list of available tags. - if test -n "$tagname" ; then - available_tags="$available_tags $tagname" - fi - fi - done - IFS="$lt_save_ifs" - - # Now substitute the updated list of available tags. - if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then - mv "${ofile}T" "$ofile" - chmod +x "$ofile" - else - rm -f "${ofile}T" - { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 -echo "$as_me: error: unable to update list of available tagged configurations." >&2;} - { (exit 1); exit 1; }; } - fi -fi - - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - -# Prevent multiple expansion - - - - - - - - - - - - - - - - - - - - - - - - -arch="" -debug="" -optimize="" -profile="" - -set -- $CFLAGS -CFLAGS="" - -if test "$GCC" = yes -then - CFLAGS="-Wall" -fi - -while test $# -gt 0 -do - case "$1" in - -Wall) - if test "$GCC" = yes - then - : - else - CFLAGS="$CFLAGS $1" - fi - shift - ;; - -g) - debug="-g" - shift - ;; - -mno-cygwin) - shift - ;; - -m*) - arch="$arch $1" - shift - ;; - -O2) - optimize="-O" - shift - ;; - -fomit-frame-pointer) - shift - ;; - -O*|-f*) - optimize="$optimize $1" - shift - ;; - *) - CFLAGS="$CFLAGS $1" - shift - ;; - esac -done - -if test "$GCC" = yes -then - if test -z "$arch" - then - case "$host" in - i386-*) ;; - i?86-*) arch="-march=i486" ;; - arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;; - armv4*-*) arch="-march=armv4 -mtune=strongarm" ;; - powerpc-*) ;; - mips*-agenda-*) arch="-mcpu=vr4100" ;; - mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;; - esac - fi - - case "$optimize" in - -O|"-O "*) - optimize="-O" - optimize="$optimize -fforce-mem" - optimize="$optimize -fforce-addr" - : #x optimize="$optimize -finline-functions" - : #- optimize="$optimize -fstrength-reduce" - optimize="$optimize -fthread-jumps" - optimize="$optimize -fcse-follow-jumps" - optimize="$optimize -fcse-skip-blocks" - : #x optimize="$optimize -frerun-cse-after-loop" - : #x optimize="$optimize -frerun-loop-opt" - : #x optimize="$optimize -fgcse" - optimize="$optimize -fexpensive-optimizations" - optimize="$optimize -fregmove" - : #* optimize="$optimize -fdelayed-branch" - : #x optimize="$optimize -fschedule-insns" - optimize="$optimize -fschedule-insns2" - : #? optimize="$optimize -ffunction-sections" - : #? optimize="$optimize -fcaller-saves" - : #> optimize="$optimize -funroll-loops" - : #> optimize="$optimize -funroll-all-loops" - : #x optimize="$optimize -fmove-all-movables" - : #x optimize="$optimize -freduce-all-givs" - : #? optimize="$optimize -fstrict-aliasing" - : #* optimize="$optimize -fstructure-noalias" - - case "$host" in - arm*-*) - optimize="$optimize -fstrength-reduce" - ;; - mips*-*) - optimize="$optimize -fstrength-reduce" - optimize="$optimize -finline-functions" - ;; - i?86-*) - optimize="$optimize -fstrength-reduce" - ;; - powerpc-apple-*) - # this triggers an internal compiler error with gcc2 - : #optimize="$optimize -fstrength-reduce" - - # this is really only beneficial with gcc3 - : #optimize="$optimize -finline-functions" - ;; - *) - # this sometimes provokes bugs in gcc 2.95.2 - : #optimize="$optimize -fstrength-reduce" - ;; - esac - ;; - esac -fi - -case "$host" in - mips*-agenda-*) - -cat >>confdefs.h <<\_ACEOF -#define HAVE_MADD16_ASM 1 -_ACEOF - - ;; - mips*-luxsonor-*) - -cat >>confdefs.h <<\_ACEOF -#define HAVE_MADD_ASM 1 -_ACEOF - - ;; -esac - - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 -echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6 -if test "${ac_cv_header_sys_wait_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) -#endif -#ifndef WIFEXITED -# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif - -int -main () -{ - int s; - wait (&s); - s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_sys_wait_h=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_sys_wait_h=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6 -if test $ac_cv_header_sys_wait_h = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_SYS_WAIT_H 1 -_ACEOF - -fi - - - - - - - -for ac_header in assert.h limits.h unistd.h sys/types.h fcntl.h errno.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ----------------------------------- ## -## Report this to support@underbit.com ## -## ----------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - -echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 -echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 -if test "${ac_cv_c_const+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -/* FIXME: Include the comments suggested by Paul. */ -#ifndef __cplusplus - /* Ultrix mips cc rejects this. */ - typedef int charset[2]; - const charset x; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *ccp; - char **p; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - ccp = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++ccp; - p = (char**) ccp; - ccp = (char const *const *) p; - { /* SCO 3.2v4 cc rejects this. */ - char *t; - char const *s = 0 ? (char *) 0 : (char const *) 0; - - *t++ = 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - } -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_const=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_const=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 -echo "${ECHO_T}$ac_cv_c_const" >&6 -if test $ac_cv_c_const = no; then - -cat >>confdefs.h <<\_ACEOF -#define const -_ACEOF - -fi - -echo "$as_me:$LINENO: checking for inline" >&5 -echo $ECHO_N "checking for inline... $ECHO_C" >&6 -if test "${ac_cv_c_inline+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_c_inline=no -for ac_kw in inline __inline__ __inline; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifndef __cplusplus -typedef int foo_t; -static $ac_kw foo_t static_foo () {return 0; } -$ac_kw foo_t foo () {return 0; } -#endif - -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_inline=$ac_kw; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 -echo "${ECHO_T}$ac_cv_c_inline" >&6 - - -case $ac_cv_c_inline in - inline | yes) ;; - *) - case $ac_cv_c_inline in - no) ac_val=;; - *) ac_val=$ac_cv_c_inline;; - esac - cat >>confdefs.h <<_ACEOF -#ifndef __cplusplus -#define inline $ac_val -#endif -_ACEOF - ;; -esac - -echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 -echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 -if test "${ac_cv_c_bigendian+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # See if sys/param.h defines the BYTE_ORDER macro. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include - -int -main () -{ -#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN - bogus endian macros -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - # It does; now see whether it defined to BIG_ENDIAN or not. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include - -int -main () -{ -#if BYTE_ORDER != BIG_ENDIAN - not big endian -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_bigendian=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_bigendian=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -# It does not; compile a test program. -if test "$cross_compiling" = yes; then - # try to guess the endianness by grepping values into an object file - ac_cv_c_bigendian=unknown - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; -short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; -void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } -short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; -short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; -void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } -int -main () -{ - _ascii (); _ebcdic (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then - ac_cv_c_bigendian=yes -fi -if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -int -main () -{ - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long l; - char c[sizeof (long)]; - } u; - u.l = 1; - exit (u.c[sizeof (long) - 1] == 1); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_bigendian=no -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_c_bigendian=yes -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 -echo "${ECHO_T}$ac_cv_c_bigendian" >&6 -case $ac_cv_c_bigendian in - yes) - -cat >>confdefs.h <<\_ACEOF -#define WORDS_BIGENDIAN 1 -_ACEOF - ;; - no) - ;; - *) - { { echo "$as_me:$LINENO: error: unknown endianness -presetting ac_cv_c_bigendian=no (or yes) will help" >&5 -echo "$as_me: error: unknown endianness -presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} - { (exit 1); exit 1; }; } ;; -esac - -echo "$as_me:$LINENO: checking for pid_t" >&5 -echo $ECHO_N "checking for pid_t... $ECHO_C" >&6 -if test "${ac_cv_type_pid_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((pid_t *) 0) - return 0; -if (sizeof (pid_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_pid_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_pid_t=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 -echo "${ECHO_T}$ac_cv_type_pid_t" >&6 -if test $ac_cv_type_pid_t = yes; then - : -else - -cat >>confdefs.h <<_ACEOF -#define pid_t int -_ACEOF - -fi - - -echo "$as_me:$LINENO: checking for int" >&5 -echo $ECHO_N "checking for int... $ECHO_C" >&6 -if test "${ac_cv_type_int+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((int *) 0) - return 0; -if (sizeof (int)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_int=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_int=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 -echo "${ECHO_T}$ac_cv_type_int" >&6 - -echo "$as_me:$LINENO: checking size of int" >&5 -echo $ECHO_N "checking size of int... $ECHO_C" >&6 -if test "${ac_cv_sizeof_int+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$ac_cv_type_int" = yes; then - # The cast to unsigned long works around a bug in the HP C Compiler - # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects - # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. - # This bug is HP SR number 8606223364. - if test "$cross_compiling" = yes; then - # Depending upon the size, compute the lo and hi bounds. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_lo=0 ac_mid=0 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo=`expr $ac_mid + 1` - if test $ac_lo -le $ac_mid; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid + 1` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=-1 ac_mid=-1 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_lo=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_hi=`expr '(' $ac_mid ')' - 1` - if test $ac_mid -le $ac_hi; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo= ac_hi= -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -# Binary search between lo and hi bounds. -while test "x$ac_lo" != "x$ac_hi"; do - ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=$ac_mid -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo=`expr '(' $ac_mid ')' + 1` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -case $ac_lo in -?*) ac_cv_sizeof_int=$ac_lo;; -'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (int), 77 -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } ;; -esac -else - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 -echo "$as_me: error: internal error: not reached in cross-compile" >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -long longval () { return (long) (sizeof (int)); } -unsigned long ulongval () { return (long) (sizeof (int)); } -#include -#include -int -main () -{ - - FILE *f = fopen ("conftest.val", "w"); - if (! f) - exit (1); - if (((long) (sizeof (int))) < 0) - { - long i = longval (); - if (i != ((long) (sizeof (int)))) - exit (1); - fprintf (f, "%ld\n", i); - } - else - { - unsigned long i = ulongval (); - if (i != ((long) (sizeof (int)))) - exit (1); - fprintf (f, "%lu\n", i); - } - exit (ferror (f) || fclose (f) != 0); - - ; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_sizeof_int=`cat conftest.val` -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (int), 77 -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -rm -f conftest.val -else - ac_cv_sizeof_int=0 -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 -echo "${ECHO_T}$ac_cv_sizeof_int" >&6 -cat >>confdefs.h <<_ACEOF -#define SIZEOF_INT $ac_cv_sizeof_int -_ACEOF - - -echo "$as_me:$LINENO: checking for long" >&5 -echo $ECHO_N "checking for long... $ECHO_C" >&6 -if test "${ac_cv_type_long+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((long *) 0) - return 0; -if (sizeof (long)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_long=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_long=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 -echo "${ECHO_T}$ac_cv_type_long" >&6 - -echo "$as_me:$LINENO: checking size of long" >&5 -echo $ECHO_N "checking size of long... $ECHO_C" >&6 -if test "${ac_cv_sizeof_long+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$ac_cv_type_long" = yes; then - # The cast to unsigned long works around a bug in the HP C Compiler - # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects - # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. - # This bug is HP SR number 8606223364. - if test "$cross_compiling" = yes; then - # Depending upon the size, compute the lo and hi bounds. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_lo=0 ac_mid=0 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo=`expr $ac_mid + 1` - if test $ac_lo -le $ac_mid; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid + 1` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=-1 ac_mid=-1 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_lo=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_hi=`expr '(' $ac_mid ')' - 1` - if test $ac_mid -le $ac_hi; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo= ac_hi= -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -# Binary search between lo and hi bounds. -while test "x$ac_lo" != "x$ac_hi"; do - ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=$ac_mid -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo=`expr '(' $ac_mid ')' + 1` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -case $ac_lo in -?*) ac_cv_sizeof_long=$ac_lo;; -'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (long), 77 -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } ;; -esac -else - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 -echo "$as_me: error: internal error: not reached in cross-compile" >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -long longval () { return (long) (sizeof (long)); } -unsigned long ulongval () { return (long) (sizeof (long)); } -#include -#include -int -main () -{ - - FILE *f = fopen ("conftest.val", "w"); - if (! f) - exit (1); - if (((long) (sizeof (long))) < 0) - { - long i = longval (); - if (i != ((long) (sizeof (long)))) - exit (1); - fprintf (f, "%ld\n", i); - } - else - { - unsigned long i = ulongval (); - if (i != ((long) (sizeof (long)))) - exit (1); - fprintf (f, "%lu\n", i); - } - exit (ferror (f) || fclose (f) != 0); - - ; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_sizeof_long=`cat conftest.val` -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (long), 77 -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -rm -f conftest.val -else - ac_cv_sizeof_long=0 -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 -echo "${ECHO_T}$ac_cv_sizeof_long" >&6 -cat >>confdefs.h <<_ACEOF -#define SIZEOF_LONG $ac_cv_sizeof_long -_ACEOF - - -echo "$as_me:$LINENO: checking for long long" >&5 -echo $ECHO_N "checking for long long... $ECHO_C" >&6 -if test "${ac_cv_type_long_long+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((long long *) 0) - return 0; -if (sizeof (long long)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_long_long=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_long_long=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 -echo "${ECHO_T}$ac_cv_type_long_long" >&6 - -echo "$as_me:$LINENO: checking size of long long" >&5 -echo $ECHO_N "checking size of long long... $ECHO_C" >&6 -if test "${ac_cv_sizeof_long_long+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$ac_cv_type_long_long" = yes; then - # The cast to unsigned long works around a bug in the HP C Compiler - # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects - # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. - # This bug is HP SR number 8606223364. - if test "$cross_compiling" = yes; then - # Depending upon the size, compute the lo and hi bounds. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_lo=0 ac_mid=0 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo=`expr $ac_mid + 1` - if test $ac_lo -le $ac_mid; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid + 1` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long long))) < 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=-1 ac_mid=-1 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_lo=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_hi=`expr '(' $ac_mid ')' - 1` - if test $ac_mid -le $ac_hi; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo= ac_hi= -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -# Binary search between lo and hi bounds. -while test "x$ac_lo" != "x$ac_hi"; do - ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_hi=$ac_mid -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_lo=`expr '(' $ac_mid ')' + 1` -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -case $ac_lo in -?*) ac_cv_sizeof_long_long=$ac_lo;; -'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77 -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (long long), 77 -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } ;; -esac -else - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 -echo "$as_me: error: internal error: not reached in cross-compile" >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -long longval () { return (long) (sizeof (long long)); } -unsigned long ulongval () { return (long) (sizeof (long long)); } -#include -#include -int -main () -{ - - FILE *f = fopen ("conftest.val", "w"); - if (! f) - exit (1); - if (((long) (sizeof (long long))) < 0) - { - long i = longval (); - if (i != ((long) (sizeof (long long)))) - exit (1); - fprintf (f, "%ld\n", i); - } - else - { - unsigned long i = ulongval (); - if (i != ((long) (sizeof (long long)))) - exit (1); - fprintf (f, "%lu\n", i); - } - exit (ferror (f) || fclose (f) != 0); - - ; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_sizeof_long_long=`cat conftest.val` -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77 -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (long long), 77 -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -rm -f conftest.val -else - ac_cv_sizeof_long_long=0 -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 -echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6 -cat >>confdefs.h <<_ACEOF -#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long -_ACEOF - - - - - - - - -for ac_func in waitpid fcntl pipe fork -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - - - - - - - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -{ - (set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} | - sed ' - t clear - : clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" - cat confcache >$cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -echo "$as_me:$LINENO: checking whether to optimize for speed or for accuracy" >&5 -echo $ECHO_N "checking whether to optimize for speed or for accuracy... $ECHO_C" >&6 - -# Check whether --enable-speed or --disable-speed was given. -if test "${enable_speed+set}" = set; then - enableval="$enable_speed" - - case "$enableval" in - yes) - optimize_for="speed" - -cat >>confdefs.h <<\_ACEOF -#define OPT_SPEED 1 -_ACEOF - - ;; - esac - -fi; - -# Check whether --enable-accuracy or --disable-accuracy was given. -if test "${enable_accuracy+set}" = set; then - enableval="$enable_accuracy" - - case "$enableval" in - yes) - if test "$optimize_for" = "speed" - then - optimize_for="both" - else - optimize_for="accuracy" - fi - -cat >>confdefs.h <<\_ACEOF -#define OPT_ACCURACY 1 -_ACEOF - - ;; - esac - -fi; - -echo "$as_me:$LINENO: result: ${optimize_for-default}" >&5 -echo "${ECHO_T}${optimize_for-default}" >&6 - -if test "$optimize_for" = "both" -then - { { echo "$as_me:$LINENO: error: cannot optimize for both speed and accuracy" >&5 -echo "$as_me: error: cannot optimize for both speed and accuracy" >&2;} - { (exit 1); exit 1; }; } -fi - -echo "$as_me:$LINENO: checking for architecture-specific fixed-point math routines" >&5 -echo $ECHO_N "checking for architecture-specific fixed-point math routines... $ECHO_C" >&6 -# Check whether --enable-fpm or --disable-fpm was given. -if test "${enable_fpm+set}" = set; then - enableval="$enable_fpm" - - case "$enableval" in - yes) ;; - no|default|approx) FPM="DEFAULT" ;; - intel|i?86) FPM="INTEL" ;; - arm) FPM="ARM" ;; - mips) FPM="MIPS" ;; - sparc) FPM="SPARC" ;; - ppc|powerpc) FPM="PPC" ;; - 64bit) FPM="64BIT" ;; - float) FPM="FLOAT" ;; - *) - echo "$as_me:$LINENO: result: failed" >&5 -echo "${ECHO_T}failed" >&6 - { { echo "$as_me:$LINENO: error: bad --enable-fpm option" >&5 -echo "$as_me: error: bad --enable-fpm option" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - -fi; - -if test -z "$FPM" && test "$GCC" = yes -then - case "$host" in - i?86-*) FPM="INTEL" ;; - arm*-*) FPM="ARM" ;; - mips*-*) FPM="MIPS" ;; - sparc*-*) FPM="SPARC" ;; - powerpc*-*) FPM="PPC" ;; - # FIXME: need to test for 64-bit long long... - esac -fi - -echo "$as_me:$LINENO: result: ${FPM=DEFAULT}" >&5 -echo "${ECHO_T}${FPM=DEFAULT}" >&6 - -if test "$FPM" = "DEFAULT" -then - { echo "$as_me:$LINENO: WARNING: default fixed-point math will yield limited accuracy" >&5 -echo "$as_me: WARNING: default fixed-point math will yield limited accuracy" >&2;} -fi - -FPM="-DFPM_$FPM" - -# Check whether --enable-sso or --disable-sso was given. -if test "${enable_sso+set}" = set; then - enableval="$enable_sso" - - case "$enableval" in - yes) - -cat >>confdefs.h <<\_ACEOF -#define OPT_SSO 1 -_ACEOF - - ;; - esac - -fi; - -# Check whether --enable-aso or --disable-aso was given. -if test "${enable_aso+set}" = set; then - enableval="$enable_aso" - -else - enable_aso=yes -fi; - -if test "$enable_aso" = yes -then - case "$host" in - i?86-*) - : #ASO="$ASO -DASO_INTERLEAVE1" - ASO="$ASO -DASO_ZEROCHECK" - : #not yet #ASO="$ASO -DASO_SYNTH" - : #not yet #ASO_OBJS="synth_mmx.lo" - ;; - arm*-*) - ASO="$ASO -DASO_INTERLEAVE1" - ASO="$ASO -DASO_IMDCT" - ASO_OBJS="imdct_l_arm.lo" - ;; - mips*-*) - ASO="$ASO -DASO_INTERLEAVE2" - ASO="$ASO -DASO_ZEROCHECK" - ;; - esac -fi - -echo "$as_me:$LINENO: checking for ISO/IEC interpretation" >&5 -echo $ECHO_N "checking for ISO/IEC interpretation... $ECHO_C" >&6 -# Check whether --enable-strict-iso or --disable-strict-iso was given. -if test "${enable_strict_iso+set}" = set; then - enableval="$enable_strict_iso" - - case "$enableval" in - yes) - -cat >>confdefs.h <<\_ACEOF -#define OPT_STRICT 1 -_ACEOF - - interpretation="strict" - ;; - esac - -fi; -echo "$as_me:$LINENO: result: ${interpretation-best accepted practices}" >&5 -echo "${ECHO_T}${interpretation-best accepted practices}" >&6 - -echo "$as_me:$LINENO: checking whether to enable profiling" >&5 -echo $ECHO_N "checking whether to enable profiling... $ECHO_C" >&6 -# Check whether --enable-profiling or --disable-profiling was given. -if test "${enable_profiling+set}" = set; then - enableval="$enable_profiling" - - case "$enableval" in - yes) profile="-pg" ;; - esac - -fi; -echo "$as_me:$LINENO: result: ${enable_profiling-no}" >&5 -echo "${ECHO_T}${enable_profiling-no}" >&6 - -echo "$as_me:$LINENO: checking whether to enable debugging" >&5 -echo $ECHO_N "checking whether to enable debugging... $ECHO_C" >&6 -# Check whether --enable-debugging or --disable-debugging was given. -if test "${enable_debugging+set}" = set; then - enableval="$enable_debugging" - - case "$enableval" in - yes) - -cat >>confdefs.h <<\_ACEOF -#define DEBUG 1 -_ACEOF - - optimize="" - ;; - no) - if test -n "$profile" - then - { { echo "$as_me:$LINENO: error: --enable-profiling and --disable-debugging are incompatible" >&5 -echo "$as_me: error: --enable-profiling and --disable-debugging are incompatible" >&2;} - { (exit 1); exit 1; }; } - fi - - -cat >>confdefs.h <<\_ACEOF -#define NDEBUG 1 -_ACEOF - - debug="" - if test "$GCC" = yes - then - optimize="$optimize -fomit-frame-pointer" - fi - ;; - esac - -fi; -echo "$as_me:$LINENO: result: ${enable_debugging-default}" >&5 -echo "${ECHO_T}${enable_debugging-default}" >&6 - -echo "$as_me:$LINENO: checking whether to enable experimental code" >&5 -echo $ECHO_N "checking whether to enable experimental code... $ECHO_C" >&6 -# Check whether --enable-experimental or --disable-experimental was given. -if test "${enable_experimental+set}" = set; then - enableval="$enable_experimental" - - case "$enableval" in - yes) - -cat >>confdefs.h <<\_ACEOF -#define EXPERIMENTAL 1 -_ACEOF - - ;; - esac - -fi; -echo "$as_me:$LINENO: result: ${enable_experimental-no}" >&5 -echo "${ECHO_T}${enable_experimental-no}" >&6 - - -test -n "$arch" && CFLAGS="$CFLAGS $arch" -test -n "$debug" && CFLAGS="$CFLAGS $debug" -test -n "$optimize" && CFLAGS="$CFLAGS $optimize" -test -n "$profile" && CFLAGS="$CFLAGS $profile" LDFLAGS="$LDFLAGS $profile" - - - ac_config_files="$ac_config_files Makefile msvc++/Makefile libmad.list" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -{ - (set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} | - sed ' - t clear - : clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" - cat confcache >$cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - -DEFS=-DHAVE_CONFIG_H - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - -exec 6>&1 - -# Open the log real soon, to keep \$[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - -This file was extended by MPEG Audio Decoder $as_me 0.15.1b, which was -generated by GNU Autoconf 2.59. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 -_ACEOF - -# Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi - -cat >>$CONFIG_STATUS <<\_ACEOF - -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Configuration commands: -$config_commands - -Report bugs to ." -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -MPEG Audio Decoder config.status 0.15.1b -configured by $0, generated by GNU Autoconf 2.59, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2003 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -INSTALL="$INSTALL" -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` - ac_shift=: - ;; - -*) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; - esac - - case $ac_option in - # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" - ac_need_defaults=false;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -# -# INIT-COMMANDS section. -# - -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - -_ACEOF - - - -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_config_target in $ac_config_targets -do - case "$ac_config_target" in - # Handling of arguments. - "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "msvc++/Makefile" ) CONFIG_FILES="$CONFIG_FILES msvc++/Makefile" ;; - "libmad.list" ) CONFIG_FILES="$CONFIG_FILES libmad.list" ;; - "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. -$debug || -{ - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF - -# -# CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s,@SHELL@,$SHELL,;t t -s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t -s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t -s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s,@exec_prefix@,$exec_prefix,;t t -s,@prefix@,$prefix,;t t -s,@program_transform_name@,$program_transform_name,;t t -s,@bindir@,$bindir,;t t -s,@sbindir@,$sbindir,;t t -s,@libexecdir@,$libexecdir,;t t -s,@datadir@,$datadir,;t t -s,@sysconfdir@,$sysconfdir,;t t -s,@sharedstatedir@,$sharedstatedir,;t t -s,@localstatedir@,$localstatedir,;t t -s,@libdir@,$libdir,;t t -s,@includedir@,$includedir,;t t -s,@oldincludedir@,$oldincludedir,;t t -s,@infodir@,$infodir,;t t -s,@mandir@,$mandir,;t t -s,@build_alias@,$build_alias,;t t -s,@host_alias@,$host_alias,;t t -s,@target_alias@,$target_alias,;t t -s,@DEFS@,$DEFS,;t t -s,@ECHO_C@,$ECHO_C,;t t -s,@ECHO_N@,$ECHO_N,;t t -s,@ECHO_T@,$ECHO_T,;t t -s,@LIBS@,$LIBS,;t t -s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t -s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t -s,@INSTALL_DATA@,$INSTALL_DATA,;t t -s,@CYGPATH_W@,$CYGPATH_W,;t t -s,@PACKAGE@,$PACKAGE,;t t -s,@VERSION@,$VERSION,;t t -s,@ACLOCAL@,$ACLOCAL,;t t -s,@AUTOCONF@,$AUTOCONF,;t t -s,@AUTOMAKE@,$AUTOMAKE,;t t -s,@AUTOHEADER@,$AUTOHEADER,;t t -s,@MAKEINFO@,$MAKEINFO,;t t -s,@AMTAR@,$AMTAR,;t t -s,@install_sh@,$install_sh,;t t -s,@STRIP@,$STRIP,;t t -s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t -s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t -s,@mkdir_p@,$mkdir_p,;t t -s,@AWK@,$AWK,;t t -s,@SET_MAKE@,$SET_MAKE,;t t -s,@am__leading_dot@,$am__leading_dot,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t -s,@DEPDIR@,$DEPDIR,;t t -s,@am__include@,$am__include,;t t -s,@am__quote@,$am__quote,;t t -s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t -s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t -s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t -s,@CCDEPMODE@,$CCDEPMODE,;t t -s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t -s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t -s,@CCAS@,$CCAS,;t t -s,@CCASFLAGS@,$CCASFLAGS,;t t -s,@EGREP@,$EGREP,;t t -s,@LN_S@,$LN_S,;t t -s,@ECHO@,$ECHO,;t t -s,@AR@,$AR,;t t -s,@ac_ct_AR@,$ac_ct_AR,;t t -s,@RANLIB@,$RANLIB,;t t -s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t -s,@CPP@,$CPP,;t t -s,@CXX@,$CXX,;t t -s,@CXXFLAGS@,$CXXFLAGS,;t t -s,@ac_ct_CXX@,$ac_ct_CXX,;t t -s,@CXXDEPMODE@,$CXXDEPMODE,;t t -s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t -s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t -s,@CXXCPP@,$CXXCPP,;t t -s,@F77@,$F77,;t t -s,@FFLAGS@,$FFLAGS,;t t -s,@ac_ct_F77@,$ac_ct_F77,;t t -s,@LIBTOOL@,$LIBTOOL,;t t -s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t -s,@FPM@,$FPM,;t t -s,@ASO@,$ASO,;t t -s,@ASO_OBJS@,$ASO_OBJS,;t t -s,@LIBOBJS@,$LIBOBJS,;t t -s,@LTLIBOBJS@,$LTLIBOBJS,;t t -CEOF - -_ACEOF - - cat >>$CONFIG_STATUS <<\_ACEOF - # Split the substitutions into bite-sized pieces for seds with - # small command number limits, like on Digital OSF/1 and HP-UX. - ac_max_sed_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # Line after last line for current file. - ac_more_lines=: - ac_sed_cmds= - while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat - fi -fi # test -n "$CONFIG_FILES" - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_builddir$INSTALL ;; - esac - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s,@configure_input@,$configure_input,;t t -s,@srcdir@,$ac_srcdir,;t t -s,@abs_srcdir@,$ac_abs_srcdir,;t t -s,@top_srcdir@,$ac_top_srcdir,;t t -s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s,@builddir@,$ac_builddir,;t t -s,@abs_builddir@,$ac_abs_builddir,;t t -s,@top_builddir@,$ac_top_builddir,;t t -s,@abs_top_builddir@,$ac_abs_top_builddir,;t t -s,@INSTALL@,$ac_INSTALL,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi - -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -# -# CONFIG_HEADER section. -# - -# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where -# NAME is the cpp macro being defined and VALUE is the value it is being given. -# -# ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' -ac_dC=' ' -ac_dD=',;t' -# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='$,\1#\2define\3' -ac_uC=' ' -ac_uD=',;t' - -for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - # Do quote $f, to prevent DOS paths from being IFS'd. - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in - -_ACEOF - -# Transform confdefs.h into two sed scripts, `conftest.defines' and -# `conftest.undefs', that substitutes the proper values into -# config.h.in to produce config.h. The first handles `#define' -# templates, and the second `#undef' templates. -# And first: Protect against being on the right side of a sed subst in -# config.status. Protect against being in an unquoted here document -# in config.status. -rm -f conftest.defines conftest.undefs -# Using a here document instead of a string reduces the quoting nightmare. -# Putting comments in sed scripts is not portable. -# -# `end' is used to avoid that the second main sed command (meant for -# 0-ary CPP macros) applies to n-ary macro definitions. -# See the Autoconf documentation for `clear'. -cat >confdef2sed.sed <<\_ACEOF -s/[\\&,]/\\&/g -s,[\\$`],\\&,g -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp -t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp -: end -_ACEOF -# If some macros were called several times there might be several times -# the same #defines, which is useless. Nevertheless, we may not want to -# sort them, since we want the *last* AC-DEFINE to be honored. -uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines -sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs -rm -f confdef2sed.sed - -# This sed command replaces #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, -_ACEOF - -# Break up conftest.defines because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS -echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS -echo ' :' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.defines >/dev/null -do - # Write a limited-size here document to $tmp/defines.sed. - echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/defines.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail - rm -f conftest.defines - mv conftest.tail conftest.defines -done -rm -f conftest.defines -echo ' fi # grep' >>$CONFIG_STATUS -echo >>$CONFIG_STATUS - -# Break up conftest.undefs because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #undef templates' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.undefs >/dev/null -do - # Write a limited-size here document to $tmp/undefs.sed. - echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/undefs.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail - rm -f conftest.undefs - mv conftest.tail conftest.undefs -done -rm -f conftest.undefs - -cat >>$CONFIG_STATUS <<\_ACEOF - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - echo "/* Generated by configure. */" >$tmp/config.h - else - echo "/* $ac_file. Generated by configure. */" >$tmp/config.h - fi - cat $tmp/in >>$tmp/config.h - rm -f $tmp/in - if test x"$ac_file" != x-; then - if diff $ac_file $tmp/config.h >/dev/null 2>&1; then - { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 -echo "$as_me: $ac_file is unchanged" >&6;} - else - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - rm -f $ac_file - mv $tmp/config.h $ac_file - fi - else - cat $tmp/config.h - rm -f $tmp/config.h - fi -# Compute $ac_file's index in $config_headers. -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $ac_file | $ac_file:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || -$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X$ac_file : 'X\(//\)[^/]' \| \ - X$ac_file : 'X\(//\)$' \| \ - X$ac_file : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X$ac_file | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'`/stamp-h$_am_stamp_count -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -# -# CONFIG_COMMANDS section. -# -for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue - ac_dest=`echo "$ac_file" | sed 's,:.*,,'` - ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_dir=`(dirname "$ac_dest") 2>/dev/null || -$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_dest" : 'X\(//\)[^/]' \| \ - X"$ac_dest" : 'X\(//\)$' \| \ - X"$ac_dest" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_dest" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - - { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 -echo "$as_me: executing $ac_dest commands" >&6;} - case $ac_dest in - depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then - dirpart=`(dirname "$mf") 2>/dev/null || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - else - continue - fi - grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue - # Extract the definition of DEP_FILES from the Makefile without - # running `make'. - DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` - test -z "$DEPDIR" && continue - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n -e '/^U = / s///p' < "$mf"` - test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" - # We invoke sed twice because it is the simplest approach to - # changing $(DEPDIR) to its actual value in the expansion. - for file in `sed -n -e ' - /^DEP_FILES = .*\\\\$/ { - s/^DEP_FILES = // - :loop - s/\\\\$// - p - n - /\\\\$/ b loop - p - } - /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`(dirname "$file") 2>/dev/null || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p $dirpart/$fdir - else - as_dir=$dirpart/$fdir - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 -echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} - { (exit 1); exit 1; }; }; } - - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done -done - ;; - esac -done -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - diff --git a/code/libmad-0.15.1b/configure.ac b/code/libmad-0.15.1b/configure.ac deleted file mode 100644 index 9b793995..00000000 --- a/code/libmad-0.15.1b/configure.ac +++ /dev/null @@ -1,433 +0,0 @@ -dnl -*- m4 -*- -dnl -dnl libmad - MPEG audio decoder library -dnl Copyright (C) 2000-2004 Underbit Technologies, Inc. -dnl -dnl This program is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 2 of the License, or -dnl (at your option) any later version. -dnl -dnl This program is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with this program; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -AC_REVISION([$Id: configure.ac,v 1.9 2004/01/23 09:41:32 rob Exp $])dnl - -dnl Process this file with autoconf to produce a configure script. - -AC_INIT([MPEG Audio Decoder], [0.15.1b], [support@underbit.com], [libmad]) -AC_PREREQ(2.53) - -AC_CONFIG_SRCDIR([decoder.h]) - -AM_INIT_AUTOMAKE - -AM_CONFIG_HEADER([config.h]) - -dnl System type. - -AC_CANONICAL_HOST - -dnl Checks for programs. - -AC_PROG_CC -AM_PROG_AS - -if test "$GCC" = yes -then - case "$host" in - *-*-mingw*) - case "$build" in - *-*-cygwin*) - CPPFLAGS="$CPPFLAGS -mno-cygwin" - LDFLAGS="$LDFLAGS -mno-cygwin" - ;; - esac - esac - -dnl case "$host" in -dnl *-*-cygwin* | *-*-mingw*) -dnl LDFLAGS="$LDFLAGS -no-undefined -mdll" -dnl ;; -dnl esac -fi - -dnl Support for libtool. - -dnl AC_DISABLE_SHARED -dnl AC_LIBTOOL_WIN32_DLL -AC_PROG_LIBTOOL - -AC_SUBST(LIBTOOL_DEPS) - -dnl Compiler options. - -arch="" -debug="" -optimize="" -profile="" - -set -- $CFLAGS -CFLAGS="" - -if test "$GCC" = yes -then - CFLAGS="-Wall" -fi - -while test $# -gt 0 -do - case "$1" in - -Wall) - if test "$GCC" = yes - then - : - else - CFLAGS="$CFLAGS $1" - fi - shift - ;; - -g) - debug="-g" - shift - ;; - -mno-cygwin) - shift - ;; - -m*) - arch="$arch $1" - shift - ;; - -O2) - optimize="-O" - shift - ;; - -fomit-frame-pointer) - shift - ;; - -O*|-f*) - optimize="$optimize $1" - shift - ;; - *) - CFLAGS="$CFLAGS $1" - shift - ;; - esac -done - -if test "$GCC" = yes -then - if test -z "$arch" - then - case "$host" in - i386-*) ;; - i?86-*) arch="-march=i486" ;; - arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;; - armv4*-*) arch="-march=armv4 -mtune=strongarm" ;; - powerpc-*) ;; - mips*-agenda-*) arch="-mcpu=vr4100" ;; - mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;; - esac - fi - - case "$optimize" in - -O|"-O "*) - optimize="-O" - optimize="$optimize -fforce-mem" - optimize="$optimize -fforce-addr" - : #x optimize="$optimize -finline-functions" - : #- optimize="$optimize -fstrength-reduce" - optimize="$optimize -fthread-jumps" - optimize="$optimize -fcse-follow-jumps" - optimize="$optimize -fcse-skip-blocks" - : #x optimize="$optimize -frerun-cse-after-loop" - : #x optimize="$optimize -frerun-loop-opt" - : #x optimize="$optimize -fgcse" - optimize="$optimize -fexpensive-optimizations" - optimize="$optimize -fregmove" - : #* optimize="$optimize -fdelayed-branch" - : #x optimize="$optimize -fschedule-insns" - optimize="$optimize -fschedule-insns2" - : #? optimize="$optimize -ffunction-sections" - : #? optimize="$optimize -fcaller-saves" - : #> optimize="$optimize -funroll-loops" - : #> optimize="$optimize -funroll-all-loops" - : #x optimize="$optimize -fmove-all-movables" - : #x optimize="$optimize -freduce-all-givs" - : #? optimize="$optimize -fstrict-aliasing" - : #* optimize="$optimize -fstructure-noalias" - - case "$host" in - arm*-*) - optimize="$optimize -fstrength-reduce" - ;; - mips*-*) - optimize="$optimize -fstrength-reduce" - optimize="$optimize -finline-functions" - ;; - i?86-*) - optimize="$optimize -fstrength-reduce" - ;; - powerpc-apple-*) - # this triggers an internal compiler error with gcc2 - : #optimize="$optimize -fstrength-reduce" - - # this is really only beneficial with gcc3 - : #optimize="$optimize -finline-functions" - ;; - *) - # this sometimes provokes bugs in gcc 2.95.2 - : #optimize="$optimize -fstrength-reduce" - ;; - esac - ;; - esac -fi - -case "$host" in - mips*-agenda-*) - AC_DEFINE(HAVE_MADD16_ASM, 1, - [Define if your MIPS CPU supports a 2-operand MADD16 instruction.]) - ;; - mips*-luxsonor-*) - AC_DEFINE(HAVE_MADD_ASM, 1, - [Define if your MIPS CPU supports a 2-operand MADD instruction.]) - ;; -esac - -dnl Checks for header files. - -AC_HEADER_STDC -AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(assert.h limits.h unistd.h sys/types.h fcntl.h errno.h) - -dnl Checks for typedefs, structures, and compiler characteristics. - -AC_C_CONST -AC_C_INLINE -AC_C_BIGENDIAN -AC_TYPE_PID_T - -AC_CHECK_SIZEOF(int, 2) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_SIZEOF(long long, 8) - -dnl Checks for library functions. - -AC_CHECK_FUNCS(waitpid fcntl pipe fork) - -dnl Other options. - -AC_SUBST(FPM) -AC_SUBST(ASO) -AC_SUBST(ASO_OBJS) - -dnl handle --enable and --disable options - -AC_CACHE_SAVE - -AC_MSG_CHECKING(whether to optimize for speed or for accuracy) - -AC_ARG_ENABLE(speed, AC_HELP_STRING([--enable-speed], - [optimize for speed over accuracy]), -[ - case "$enableval" in - yes) - optimize_for="speed" - AC_DEFINE(OPT_SPEED, 1, - [Define to optimize for speed over accuracy.]) - ;; - esac -]) - -AC_ARG_ENABLE(accuracy, AC_HELP_STRING([--enable-accuracy], - [optimize for accuracy over speed]), -[ - case "$enableval" in - yes) - if test "$optimize_for" = "speed" - then - optimize_for="both" - else - optimize_for="accuracy" - fi - AC_DEFINE(OPT_ACCURACY, 1, - [Define to optimize for accuracy over speed.]) - ;; - esac -]) - -AC_MSG_RESULT(${optimize_for-default}) - -if test "$optimize_for" = "both" -then - AC_MSG_ERROR(cannot optimize for both speed and accuracy) -fi - -AC_MSG_CHECKING(for architecture-specific fixed-point math routines) -AC_ARG_ENABLE(fpm, AC_HELP_STRING([--enable-fpm=ARCH], - [use ARCH-specific fixed-point math routines - (one of: intel, arm, mips, sparc, ppc, 64bit, default)]), -[ - case "$enableval" in - yes) ;; - no|default|approx) FPM="DEFAULT" ;; - intel|i?86) FPM="INTEL" ;; - arm) FPM="ARM" ;; - mips) FPM="MIPS" ;; - sparc) FPM="SPARC" ;; - ppc|powerpc) FPM="PPC" ;; - 64bit) FPM="64BIT" ;; - float) FPM="FLOAT" ;; - *) - AC_MSG_RESULT(failed) - AC_MSG_ERROR([bad --enable-fpm option]) - ;; - esac -]) - -if test -z "$FPM" && test "$GCC" = yes -then - case "$host" in - i?86-*) FPM="INTEL" ;; - arm*-*) FPM="ARM" ;; - mips*-*) FPM="MIPS" ;; - sparc*-*) FPM="SPARC" ;; - powerpc*-*) FPM="PPC" ;; - # FIXME: need to test for 64-bit long long... - esac -fi - -AC_MSG_RESULT(${FPM=DEFAULT}) - -if test "$FPM" = "DEFAULT" -then - AC_MSG_WARN([default fixed-point math will yield limited accuracy]) -fi - -FPM="-DFPM_$FPM" - -AC_ARG_ENABLE(sso, AC_HELP_STRING([--enable-sso], - [use subband synthesis optimization]), -[ - case "$enableval" in - yes) - AC_DEFINE(OPT_SSO, 1, - [Define to enable a fast subband synthesis approximation optimization.]) - ;; - esac -]) - -AC_ARG_ENABLE(aso, AC_HELP_STRING([--disable-aso], - [disable architecture-specific optimizations]), - [], [enable_aso=yes]) - -if test "$enable_aso" = yes -then - case "$host" in - i?86-*) - : #ASO="$ASO -DASO_INTERLEAVE1" - ASO="$ASO -DASO_ZEROCHECK" - : #not yet #ASO="$ASO -DASO_SYNTH" - : #not yet #ASO_OBJS="synth_mmx.lo" - ;; - arm*-*) - ASO="$ASO -DASO_INTERLEAVE1" - ASO="$ASO -DASO_IMDCT" - ASO_OBJS="imdct_l_arm.lo" - ;; - mips*-*) - ASO="$ASO -DASO_INTERLEAVE2" - ASO="$ASO -DASO_ZEROCHECK" - ;; - esac -fi - -AC_MSG_CHECKING(for ISO/IEC interpretation) -AC_ARG_ENABLE(strict-iso, AC_HELP_STRING([--enable-strict-iso], - [use strict ISO/IEC interpretations]), -[ - case "$enableval" in - yes) - AC_DEFINE(OPT_STRICT, 1, - [Define to influence a strict interpretation of the ISO/IEC standards, - even if this is in opposition with best accepted practices.]) - interpretation="strict" - ;; - esac -]) -AC_MSG_RESULT(${interpretation-best accepted practices}) - -AC_MSG_CHECKING(whether to enable profiling) -AC_ARG_ENABLE(profiling, AC_HELP_STRING([--enable-profiling], - [generate profiling code]), -[ - case "$enableval" in - yes) profile="-pg" ;; - esac -]) -AC_MSG_RESULT(${enable_profiling-no}) - -AC_MSG_CHECKING(whether to enable debugging) -AC_ARG_ENABLE(debugging, AC_HELP_STRING([--enable-debugging], - [enable diagnostic debugging support]) -AC_HELP_STRING([--disable-debugging], - [do not enable debugging and use more optimization]), -[ - case "$enableval" in - yes) - AC_DEFINE(DEBUG, 1, - [Define to enable diagnostic debugging support.]) - optimize="" - ;; - no) - if test -n "$profile" - then - AC_MSG_ERROR(--enable-profiling and --disable-debugging are incompatible) - fi - - AC_DEFINE(NDEBUG, 1, - [Define to disable debugging assertions.]) - debug="" - if test "$GCC" = yes - then - optimize="$optimize -fomit-frame-pointer" - fi - ;; - esac -]) -AC_MSG_RESULT(${enable_debugging-default}) - -AC_MSG_CHECKING(whether to enable experimental code) -AC_ARG_ENABLE(experimental, AC_HELP_STRING([--enable-experimental], - [enable experimental code]), -[ - case "$enableval" in - yes) - AC_DEFINE(EXPERIMENTAL, 1, - [Define to enable experimental code.]) - ;; - esac -]) -AC_MSG_RESULT(${enable_experimental-no}) - -dnl Create output files. - -test -n "$arch" && CFLAGS="$CFLAGS $arch" -test -n "$debug" && CFLAGS="$CFLAGS $debug" -test -n "$optimize" && CFLAGS="$CFLAGS $optimize" -test -n "$profile" && CFLAGS="$CFLAGS $profile" LDFLAGS="$LDFLAGS $profile" - -dnl LTLIBOBJS=`echo "$LIBOBJS" | sed -e 's/\.o/.lo/g'` -dnl AC_SUBST(LTLIBOBJS) - -AC_CONFIG_FILES([Makefile msvc++/Makefile \ - libmad.list]) -AC_OUTPUT diff --git a/code/libmad-0.15.1b/decoder.h b/code/libmad-0.15.1b/decoder.h deleted file mode 100644 index f0ad758d..00000000 --- a/code/libmad-0.15.1b/decoder.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: decoder.h,v 1.17 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_DECODER_H -# define LIBMAD_DECODER_H - -# include "stream.h" -# include "frame.h" -# include "synth.h" - -enum mad_decoder_mode { - MAD_DECODER_MODE_SYNC = 0, - MAD_DECODER_MODE_ASYNC -}; - -enum mad_flow { - MAD_FLOW_CONTINUE = 0x0000, /* continue normally */ - MAD_FLOW_STOP = 0x0010, /* stop decoding normally */ - MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */ - MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */ -}; - -struct mad_decoder { - enum mad_decoder_mode mode; - - int options; - - struct { - long pid; - int in; - int out; - } async; - - struct { - struct mad_stream stream; - struct mad_frame frame; - struct mad_synth synth; - } *sync; - - void *cb_data; - - enum mad_flow (*input_func)(void *, struct mad_stream *); - enum mad_flow (*header_func)(void *, struct mad_header const *); - enum mad_flow (*filter_func)(void *, - struct mad_stream const *, struct mad_frame *); - enum mad_flow (*output_func)(void *, - struct mad_header const *, struct mad_pcm *); - enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); - enum mad_flow (*message_func)(void *, void *, unsigned int *); -}; - -void mad_decoder_init(struct mad_decoder *, void *, - enum mad_flow (*)(void *, struct mad_stream *), - enum mad_flow (*)(void *, struct mad_header const *), - enum mad_flow (*)(void *, - struct mad_stream const *, - struct mad_frame *), - enum mad_flow (*)(void *, - struct mad_header const *, - struct mad_pcm *), - enum mad_flow (*)(void *, - struct mad_stream *, - struct mad_frame *), - enum mad_flow (*)(void *, void *, unsigned int *)); -int mad_decoder_finish(struct mad_decoder *); - -# define mad_decoder_options(decoder, opts) \ - ((void) ((decoder)->options = (opts))) - -int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); -int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); - -# endif diff --git a/code/libmad-0.15.1b/depcomp b/code/libmad-0.15.1b/depcomp deleted file mode 100644 index 51606f8c..00000000 --- a/code/libmad-0.15.1b/depcomp +++ /dev/null @@ -1,464 +0,0 @@ -#! /bin/sh - -# depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi -# `libtool' can also be set to `yes' or `no'. - -if test -z "$depfile"; then - base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` - dir=`echo "$object" | sed 's,/.*$,/,'` - if test "$dir" = "$object"; then - dir= - fi - # FIXME: should be _deps on DOS. - depfile="$dir.deps/$base" -fi - -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. - "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. This file always lives in the current directory. - # Also, the AIX compiler puts `$object:' at the start of each line; - # $object doesn't have directory information. - stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" - outname="$stripped.o" - if test "$libtool" = yes; then - "$@" -Wc,-M - else - "$@" -M - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - - if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -icc) - # Must come before tru64. - - # Intel's C compiler understands `-MD -MF file'. However - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want: - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^[^:]*: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - rm -f "$tmpdepfile" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - tmpdepfile1="$dir.libs/$base.lo.d" - tmpdepfile2="$dir.libs/$base.d" - "$@" -Wc,-MD - else - tmpdepfile1="$dir$base.o.d" - tmpdepfile2="$dir$base.d" - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - if test -f "$tmpdepfile1"; then - tmpdepfile="$tmpdepfile1" - else - tmpdepfile="$tmpdepfile2" - fi - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a space and a tab in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. - "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no - for arg in "$@"; do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - "$@" || exit $? - IFS=" " - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 diff --git a/code/libmad-0.15.1b/fixed.h b/code/libmad-0.15.1b/fixed.h deleted file mode 100644 index 4b58abf5..00000000 --- a/code/libmad-0.15.1b/fixed.h +++ /dev/null @@ -1,499 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: fixed.h,v 1.38 2004/02/17 02:02:03 rob Exp $ - */ - -# ifndef LIBMAD_FIXED_H -# define LIBMAD_FIXED_H - -# if SIZEOF_INT >= 4 -typedef signed int mad_fixed_t; - -typedef signed int mad_fixed64hi_t; -typedef unsigned int mad_fixed64lo_t; -# else -typedef signed long mad_fixed_t; - -typedef signed long mad_fixed64hi_t; -typedef unsigned long mad_fixed64lo_t; -# endif - -# if defined(_MSC_VER) -# define mad_fixed64_t signed __int64 -# elif 1 || defined(__GNUC__) -# define mad_fixed64_t signed long long -# endif - -# if defined(FPM_FLOAT) -typedef double mad_sample_t; -# else -typedef mad_fixed_t mad_sample_t; -# endif - -/* - * Fixed-point format: 0xABBBBBBB - * A == whole part (sign + 3 bits) - * B == fractional part (28 bits) - * - * Values are signed two's complement, so the effective range is: - * 0x80000000 to 0x7fffffff - * -8.0 to +7.9999999962747097015380859375 - * - * The smallest representable value is: - * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) - * - * 28 bits of fractional accuracy represent about - * 8.6 digits of decimal accuracy. - * - * Fixed-point numbers can be added or subtracted as normal - * integers, but multiplication requires shifting the 64-bit result - * from 56 fractional bits back to 28 (and rounding.) - * - * Changing the definition of MAD_F_FRACBITS is only partially - * supported, and must be done with care. - */ - -# define MAD_F_FRACBITS 28 - -# if MAD_F_FRACBITS == 28 -# define MAD_F(x) ((mad_fixed_t) (x##L)) -# else -# if MAD_F_FRACBITS < 28 -# warning "MAD_F_FRACBITS < 28" -# define MAD_F(x) ((mad_fixed_t) \ - (((x##L) + \ - (1L << (28 - MAD_F_FRACBITS - 1))) >> \ - (28 - MAD_F_FRACBITS))) -# elif MAD_F_FRACBITS > 28 -# error "MAD_F_FRACBITS > 28 not currently supported" -# define MAD_F(x) ((mad_fixed_t) \ - ((x##L) << (MAD_F_FRACBITS - 28))) -# endif -# endif - -# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) -# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) - -# define MAD_F_ONE MAD_F(0x10000000) - -# define mad_f_tofixed(x) ((mad_fixed_t) \ - ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) -# define mad_f_todouble(x) ((double) \ - ((x) / (double) (1L << MAD_F_FRACBITS))) - -# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) -# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) - /* (x should be positive) */ - -# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) - -# define mad_f_add(x, y) ((x) + (y)) -# define mad_f_sub(x, y) ((x) - (y)) - -# if defined(FPM_FLOAT) -# error "FPM_FLOAT not yet supported" - -# undef MAD_F -# define MAD_F(x) mad_f_todouble(x) - -# define mad_f_mul(x, y) ((x) * (y)) -# define mad_f_scale64 - -# undef ASO_ZEROCHECK - -# elif defined(FPM_64BIT) - -/* - * This version should be the most accurate if 64-bit types are supported by - * the compiler, although it may not be the most efficient. - */ -# if defined(OPT_ACCURACY) -# define mad_f_mul(x, y) \ - ((mad_fixed_t) \ - ((((mad_fixed64_t) (x) * (y)) + \ - (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) -# else -# define mad_f_mul(x, y) \ - ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS)) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Intel --------------------------------------------------------------- */ - -# elif defined(FPM_INTEL) - -# if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4035) /* no return value */ -static __forceinline -mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) -{ - enum { - fracbits = MAD_F_FRACBITS - }; - - __asm { - mov eax, x - imul y - shrd eax, edx, fracbits - } - - /* implicit return of eax */ -} -# pragma warning(pop) - -# define mad_f_mul mad_f_mul_inline -# define mad_f_scale64 -# else -/* - * This Intel version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("imull %3" \ - : "=a" (lo), "=d" (hi) \ - : "%a" (x), "rm" (y) \ - : "cc") - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addl %2,%0\n\t" \ - "adcl %3,%1" \ - : "=rm" (lo), "=rm" (hi) \ - : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ - : "cc"); \ - }) -# endif /* OPT_ACCURACY */ - -# if defined(OPT_ACCURACY) -/* - * Surprisingly, this is faster than SHRD followed by ADC. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed64hi_t __hi_; \ - mad_fixed64lo_t __lo_; \ - mad_fixed_t __result; \ - asm ("addl %4,%2\n\t" \ - "adcl %5,%3" \ - : "=rm" (__lo_), "=rm" (__hi_) \ - : "0" (lo), "1" (hi), \ - "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ - : "cc"); \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# elif defined(OPT_INTEL) -/* - * Alternate Intel scaling that may or may not perform better. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("shrl %3,%1\n\t" \ - "shll %4,%2\n\t" \ - "orl %2,%1" \ - : "=rm" (__result) \ - : "0" (lo), "r" (hi), \ - "I" (MAD_F_SCALEBITS), "I" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif /* OPT_ACCURACY */ - -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- ARM ----------------------------------------------------------------- */ - -# elif defined(FPM_ARM) - -/* - * This ARM V4 version is as accurate as FPM_64BIT but much faster. The - * least significant bit is properly rounded at no CPU cycle cost! - */ -# if 1 -/* - * This is faster than the default implementation via MAD_F_MLX() and - * mad_f_scale64(). - */ -# define mad_f_mul(x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - mad_fixed_t __result; \ - asm ("smull %0, %1, %3, %4\n\t" \ - "movs %0, %0, lsr %5\n\t" \ - "adc %2, %0, %1, lsl %6" \ - : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ - : "%r" (x), "r" (y), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif - -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smull %0, %1, %2, %3" \ - : "=&r" (lo), "=&r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("smlal %0, %1, %2, %3" \ - : "+r" (lo), "+r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLN(hi, lo) \ - asm ("rsbs %0, %2, #0\n\t" \ - "rsc %1, %3, #0" \ - : "=r" (lo), "=r" (hi) \ - : "0" (lo), "1" (hi) \ - : "cc") - -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("movs %0, %1, lsr %3\n\t" \ - "adc %0, %0, %2, lsl %4" \ - : "=&r" (__result) \ - : "r" (lo), "r" (hi), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- MIPS ---------------------------------------------------------------- */ - -# elif defined(FPM_MIPS) - -/* - * This MIPS version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" (x), "r" (y)) - -# if defined(HAVE_MADD_ASM) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" (x), "r" (y)) -# elif defined(HAVE_MADD16_ASM) -/* - * This loses significant accuracy due to the 16-bit integer limit in the - * multiply/accumulate instruction. - */ -# define MAD_F_ML0(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd16 %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) -# endif - -# if defined(OPT_SPEED) -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- SPARC --------------------------------------------------------------- */ - -# elif defined(FPM_SPARC) - -/* - * This SPARC V8 version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smul %2, %3, %0\n\t" \ - "rd %%y, %1" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (x), "rI" (y)) - -/* --- PowerPC ------------------------------------------------------------- */ - -# elif defined(FPM_PPC) - -/* - * This PowerPC version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - do { \ - asm ("mullw %0,%1,%2" \ - : "=r" (lo) \ - : "%r" (x), "r" (y)); \ - asm ("mulhw %0,%1,%2" \ - : "=r" (hi) \ - : "%r" (x), "r" (y)); \ - } \ - while (0) - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addc %0,%2,%3\n\t" \ - "adde %1,%4,%5" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (lo), "r" (__lo), \ - "%r" (hi), "r" (__hi) \ - : "xer"); \ - }) -# endif - -# if defined(OPT_ACCURACY) -/* - * This is slower than the truncating version below it. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result, __round; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("extrwi %0,%1,1,0" \ - : "=r" (__round) \ - : "r" (__result)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - asm ("add %0,%1,%2" \ - : "=r" (__result) \ - : "%r" (__result), "r" (__round)); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - __result; \ - }) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Default ------------------------------------------------------------- */ - -# elif defined(FPM_DEFAULT) - -/* - * This version is the most portable but it loses significant accuracy. - * Furthermore, accuracy is biased against the second argument, so care - * should be taken when ordering operands. - * - * The scale factors are constant as this is not used with SSO. - * - * Pre-rounding is required to stay within the limits of compliance. - */ -# if defined(OPT_SPEED) -# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) -# else -# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ - (((y) + (1L << 15)) >> 16)) -# endif - -/* ------------------------------------------------------------------------- */ - -# else -# error "no FPM selected" -# endif - -/* default implementations */ - -# if !defined(mad_f_mul) -# define mad_f_mul(x, y) \ - ({ register mad_fixed64hi_t __hi; \ - register mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - mad_f_scale64(__hi, __lo); \ - }) -# endif - -# if !defined(MAD_F_MLA) -# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) -# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) -# define MAD_F_MLN(hi, lo) ((lo) = -(lo)) -# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) -# endif - -# if !defined(MAD_F_ML0) -# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) -# endif - -# if !defined(MAD_F_MLN) -# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) -# endif - -# if !defined(MAD_F_MLZ) -# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) -# endif - -# if !defined(mad_f_scale64) -# if defined(OPT_ACCURACY) -# define mad_f_scale64(hi, lo) \ - ((((mad_fixed_t) \ - (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ - ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) -# else -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) \ - (((hi) << (32 - MAD_F_SCALEBITS)) | \ - ((lo) >> MAD_F_SCALEBITS))) -# endif -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* C routines */ - -mad_fixed_t mad_f_abs(mad_fixed_t); -mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); - -# endif diff --git a/code/libmad-0.15.1b/frame.h b/code/libmad-0.15.1b/frame.h deleted file mode 100644 index 3f5bf37e..00000000 --- a/code/libmad-0.15.1b/frame.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: frame.h,v 1.20 2004/01/23 09:41:32 rob Exp $ - */ - -# ifndef LIBMAD_FRAME_H -# define LIBMAD_FRAME_H - -# include "fixed.h" -# include "timer.h" -# include "stream.h" - -enum mad_layer { - MAD_LAYER_I = 1, /* Layer I */ - MAD_LAYER_II = 2, /* Layer II */ - MAD_LAYER_III = 3 /* Layer III */ -}; - -enum mad_mode { - MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ - MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ - MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ - MAD_MODE_STEREO = 3 /* normal LR stereo */ -}; - -enum mad_emphasis { - MAD_EMPHASIS_NONE = 0, /* no emphasis */ - MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ - MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */ - MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */ -}; - -struct mad_header { - enum mad_layer layer; /* audio layer (1, 2, or 3) */ - enum mad_mode mode; /* channel mode (see above) */ - int mode_extension; /* additional mode info */ - enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ - - unsigned long bitrate; /* stream bitrate (bps) */ - unsigned int samplerate; /* sampling frequency (Hz) */ - - unsigned short crc_check; /* frame CRC accumulator */ - unsigned short crc_target; /* final target CRC checksum */ - - int flags; /* flags (see below) */ - int private_bits; /* private bits (see below) */ - - mad_timer_t duration; /* audio playing time of frame */ -}; - -struct mad_frame { - struct mad_header header; /* MPEG audio header */ - - int options; /* decoding options (from stream) */ - - mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ - mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ -}; - -# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) -# define MAD_NSBSAMPLES(header) \ - ((header)->layer == MAD_LAYER_I ? 12 : \ - (((header)->layer == MAD_LAYER_III && \ - ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) - -enum { - MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ - MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ - - MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ - MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ - MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ - MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ - - MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ - MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ - MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ - - MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ - MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ - MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ -}; - -enum { - MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ - MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ -}; - -void mad_header_init(struct mad_header *); - -# define mad_header_finish(header) /* nothing */ - -int mad_header_decode(struct mad_header *, struct mad_stream *); - -void mad_frame_init(struct mad_frame *); -void mad_frame_finish(struct mad_frame *); - -int mad_frame_decode(struct mad_frame *, struct mad_stream *); - -void mad_frame_mute(struct mad_frame *); - -# endif diff --git a/code/libmad-0.15.1b/install-sh b/code/libmad-0.15.1b/install-sh deleted file mode 100644 index 36f96f3e..00000000 --- a/code/libmad-0.15.1b/install-sh +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd=$cpprog - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "$0: no input file specified" >&2 - exit 1 -else - : -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d "$dst" ]; then - instcmd=: - chmodcmd="" - else - instcmd=$mkdirprog - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f "$src" ] || [ -d "$src" ] - then - : - else - echo "$0: $src does not exist" >&2 - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "$0: no destination specified" >&2 - exit 1 - else - : - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d "$dst" ] - then - dst=$dst/`basename "$src"` - else - : - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' - ' -IFS="${IFS-$defaultIFS}" - -oIFS=$IFS -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS=$oIFS - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp=$pathcomp$1 - shift - - if [ ! -d "$pathcomp" ] ; - then - $mkdirprog "$pathcomp" - else - : - fi - - pathcomp=$pathcomp/ -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd "$dst" && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename "$dst"` - else - dstfile=`basename "$dst" $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename "$dst"` - else - : - fi - -# Make a couple of temp file names in the proper directory. - - dsttmp=$dstdir/#inst.$$# - rmtmp=$dstdir/#rm.$$# - -# Trap to clean up temp files at exit. - - trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 - trap '(exit $?); exit' 1 2 13 15 - -# Move or copy the file name to the temp name - - $doit $instcmd "$src" "$dsttmp" && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && - -# Now remove or move aside any old file at destination location. We try this -# two ways since rm can't unlink itself on some systems and the destination -# file might be busy for other reasons. In this case, the final cleanup -# might fail but the new file should still install successfully. - -{ - if [ -f "$dstdir/$dstfile" ] - then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || - $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || - { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit - } - else - : - fi -} && - -# Now rename the file to the real destination. - - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - -fi && - -# The final little trick to "correctly" pass the exit status to the exit trap. - -{ - (exit 0); exit -} diff --git a/code/libmad-0.15.1b/libmad.list.in b/code/libmad-0.15.1b/libmad.list.in deleted file mode 100644 index 4718fef3..00000000 --- a/code/libmad-0.15.1b/libmad.list.in +++ /dev/null @@ -1,21 +0,0 @@ -# @configure_input@ - -# Directories... -$prefix=@prefix@ -$exec_prefix=@exec_prefix@ -$srcdir=@srcdir@ - -# Product information -%product @PACKAGE@ -%copyright GPL -%vendor Underbit Technologies, Inc. -%license @srcdir@/COPYING -%readme @srcdir@/README -%description libmad is an MPEG audio decoder library. -%version @VERSION@ -%packager Giuseppe "Cowo" Corbelli - -%system all -f 0755 root root @libdir@/libmad.la .libs/libmad.lai -f 0644 root root @libdir@/libmad.a .libs/libmad.a -f 0644 root root @includedir@/mad.h mad.h diff --git a/code/libmad-0.15.1b/ltmain.sh b/code/libmad-0.15.1b/ltmain.sh deleted file mode 100644 index 4b9f9405..00000000 --- a/code/libmad-0.15.1b/ltmain.sh +++ /dev/null @@ -1,6399 +0,0 @@ -# ltmain.sh - Provide generalized library-building support services. -# NOTE: Changing this file will not affect anything until you rerun configure. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003 -# Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Check that we have a working $echo. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell, and then maybe $echo will work. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 -fi - -# Global variables. -mode=$default_mode -nonopt= -prev= -prevopt= -run= -show="$echo" -show_help= -execute_dlfiles= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" - -##################################### -# Shell function definitions: -# This seems to be the best place for them - -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -win32_libid () { - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ - grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then - win32_nmres=`eval $NM -f posix -A $1 | \ - sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'` - if test "X$win32_nmres" = "Ximport" ; then - win32_libid_type="x86 archive import" - else - win32_libid_type="x86 archive static" - fi - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $echo $win32_libid_type -} - -# End of Shell function definitions -##################################### - -# Parse our command line options once, thoroughly. -while test "$#" -gt 0 -do - arg="$1" - shift - - case $arg in - -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - execute_dlfiles) - execute_dlfiles="$execute_dlfiles $arg" - ;; - tag) - tagname="$arg" - preserve_args="${preserve_args}=$arg" - - # Check whether tagname contains only valid characters - case $tagname in - *[!-_A-Za-z0-9,/]*) - $echo "$progname: invalid tag name: $tagname" 1>&2 - exit 1 - ;; - esac - - case $tagname in - CC) - # Don't test for the "default" C tag, as we know, it's there, but - # not specially marked. - ;; - *) - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$0" > /dev/null; then - taglist="$taglist $tagname" - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`" - else - $echo "$progname: ignoring unknown tag $tagname" 1>&2 - fi - ;; - esac - ;; - *) - eval "$prev=\$arg" - ;; - esac - - prev= - prevopt= - continue - fi - - # Have we seen a non-optional argument yet? - case $arg in - --help) - show_help=yes - ;; - - --version) - $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" - $echo - $echo "Copyright (C) 2003 Free Software Foundation, Inc." - $echo "This is free software; see the source for copying conditions. There is NO" - $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - exit 0 - ;; - - --config) - ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 - # Now print the configurations for the tags. - for tagname in $taglist; do - ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$0" - done - exit 0 - ;; - - --debug) - $echo "$progname: enabling shell trace mode" - set -x - preserve_args="$preserve_args $arg" - ;; - - --dry-run | -n) - run=: - ;; - - --features) - $echo "host: $host" - if test "$build_libtool_libs" = yes; then - $echo "enable shared libraries" - else - $echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - $echo "enable static libraries" - else - $echo "disable static libraries" - fi - exit 0 - ;; - - --finish) mode="finish" ;; - - --mode) prevopt="--mode" prev=mode ;; - --mode=*) mode="$optarg" ;; - - --preserve-dup-deps) duplicate_deps="yes" ;; - - --quiet | --silent) - show=: - preserve_args="$preserve_args $arg" - ;; - - --tag) prevopt="--tag" prev=tag ;; - --tag=*) - set tag "$optarg" ${1+"$@"} - shift - prev=tag - preserve_args="$preserve_args --tag" - ;; - - -dlopen) - prevopt="-dlopen" - prev=execute_dlfiles - ;; - - -*) - $echo "$modename: unrecognized option \`$arg'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - - *) - nonopt="$arg" - break - ;; - esac -done - -if test -n "$prevopt"; then - $echo "$modename: option \`$prevopt' requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 -fi - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -if test -z "$show_help"; then - - # Infer the operation mode. - if test -z "$mode"; then - $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 - $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2 - case $nonopt in - *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) - mode=link - for arg - do - case $arg in - -c) - mode=compile - break - ;; - esac - done - ;; - *db | *dbx | *strace | *truss) - mode=execute - ;; - *install*|cp|mv) - mode=install - ;; - *rm) - mode=uninstall - ;; - *) - # If we have no mode, but dlfiles were specified, then do execute mode. - test -n "$execute_dlfiles" && mode=execute - - # Just use the default operation mode. - if test -z "$mode"; then - if test -n "$nonopt"; then - $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 - else - $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 - fi - fi - ;; - esac - fi - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$execute_dlfiles" && test "$mode" != execute; then - $echo "$modename: unrecognized option \`-dlopen'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$modename --help --mode=$mode' for more information." - - # These modes are in order of execution frequency so that they run quickly. - case $mode in - # libtool compile mode - compile) - modename="$modename: compile" - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - - for arg - do - case "$arg_mode" in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - if test -n "$libobj" ; then - $echo "$modename: you cannot specify \`-o' more than once" 1>&2 - exit 1 - fi - arg_mode=target - continue - ;; - - -static | -prefer-pic | -prefer-non-pic) - later="$later $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - lastarg="$lastarg $arg" - done - IFS="$save_ifs" - lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` - - # Add the arguments to base_compile. - base_compile="$base_compile $lastarg" - continue - ;; - - * ) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` - - case $lastarg in - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - lastarg="\"$lastarg\"" - ;; - esac - - base_compile="$base_compile $lastarg" - done # for arg - - case $arg_mode in - arg) - $echo "$modename: you must specify an argument for -Xcompile" - exit 1 - ;; - target) - $echo "$modename: you must specify a target with \`-o'" 1>&2 - exit 1 - ;; - *) - # Get the name of the library object. - [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - xform='[cCFSifmso]' - case $libobj in - *.ada) xform=ada ;; - *.adb) xform=adb ;; - *.ads) xform=ads ;; - *.asm) xform=asm ;; - *.c++) xform=c++ ;; - *.cc) xform=cc ;; - *.ii) xform=ii ;; - *.class) xform=class ;; - *.cpp) xform=cpp ;; - *.cxx) xform=cxx ;; - *.f90) xform=f90 ;; - *.for) xform=for ;; - *.java) xform=java ;; - esac - - libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` - - case $libobj in - *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; - *) - $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 - exit 1 - ;; - esac - - # Infer tagged configuration to use if any are available and - # if one wasn't chosen via the "--tag" command line option. - # Only attempt this if the compiler in the base compile - # command doesn't match the default compiler. - if test -n "$available_tags" && test -z "$tagname"; then - case $base_compile in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" - case "$base_compile " in - "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - $echo "$modename: unable to infer tagged configuration" - $echo "$modename: specify a tag with \`--tag'" 1>&2 - exit 1 -# else -# $echo "$modename: using $tagname tagged configuration" - fi - ;; - esac - fi - - for arg in $later; do - case $arg in - -static) - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir= - else - xdir=$xdir/ - fi - lobj=${xdir}$objdir/$objname - - if test -z "$base_compile"; then - $echo "$modename: you must specify a compilation command" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - $run $rm $removelist - trap "$run $rm $removelist; exit 1" 1 2 15 - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - removelist="$removelist $output_obj $lockfile" - trap "$run $rm $removelist; exit 1" 1 2 15 - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $run ln "$0" "$lockfile" 2>/dev/null; do - $show "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $echo "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - $echo $srcfile > "$lockfile" - fi - - if test -n "$fix_srcfile_path"; then - eval srcfile=\"$fix_srcfile_path\" - fi - - $run $rm "$libobj" "${libobj}T" - - # Create a libtool object file (analogous to a ".la" file), - # but don't create it if we're doing a dry run. - test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then - $echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - $show "$mv $output_obj $lobj" - if $run $mv $output_obj $lobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Append the name of the PIC object to the libtool object file. - test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then - $echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - $show "$mv $output_obj $obj" - if $run $mv $output_obj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Append the name of the non-PIC object the libtool object file. - # Only append if the libtool object file exists. - test -z "$run" && cat >> ${libobj}T <> ${libobj}T < /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" - case $base_compile in - "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) - # The compiler in $compile_command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - $echo "$modename: unable to infer tagged configuration" - $echo "$modename: specify a tag with \`--tag'" 1>&2 - exit 1 -# else -# $echo "$modename: using $tagname tagged configuration" - fi - ;; - esac - fi - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -all-static | -static) - if test "X$arg" = "X-all-static"; then - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then - $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - else - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - fi - build_libtool_libs=no - build_old_libs=yes - prefer_static_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test - ;; - *) qarg=$arg ;; - esac - libtool_args="$libtool_args $qarg" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - compile_command="$compile_command @OUTPUT@" - finalize_command="$finalize_command @OUTPUT@" - ;; - esac - - case $prev in - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - compile_command="$compile_command @SYMFILE@" - finalize_command="$finalize_command @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - else - dlprefiles="$dlprefiles $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - if test ! -f "$arg"; then - $echo "$modename: symbol file \`$arg' does not exist" - exit 1 - fi - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat $save_arg` - do -# moreargs="$moreargs $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - pic_object= - non_pic_object= - - # Read the .lo file - # If there is no directory component, then add one. - case $arg in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - if test -z "$pic_object" || \ - test -z "$non_pic_object" || - test "$pic_object" = none && \ - test "$non_pic_object" = none; then - $echo "$modename: cannot find name of object for \`$arg'" 1>&2 - exit 1 - fi - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" - prev= - fi - - # A PIC object. - libobjs="$libobjs $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - fi - else - # Only an error if not doing a dry-run. - if test -z "$run"; then - $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 - exit 1 - else - # Dry-run case. - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` - non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - fi - done - else - $echo "$modename: link input file \`$save_arg' does not exist" - exit 1 - fi - arg=$save_arg - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit 1 - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) rpath="$rpath $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) xrpath="$xrpath $arg" ;; - esac - fi - prev= - continue - ;; - xcompiler) - compiler_flags="$compiler_flags $qarg" - prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" - continue - ;; - xlinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $wl$qarg" - prev= - compile_command="$compile_command $wl$qarg" - finalize_command="$finalize_command $wl$qarg" - continue - ;; - xcclinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $qarg" - prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 - continue - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: more than one -exported-symbols argument is not allowed" - exit 1 - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - ;; - esac - continue - ;; - - -L*) - dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 - exit 1 - fi - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "*) ;; - *) - deplibs="$deplibs -L$dir" - lib_search_path="$lib_search_path $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - case :$dllsearchpath: in - *":$dir:"*) ;; - *) dllsearchpath="$dllsearchpath:$dir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-pw32* | *-*-beos*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-mingw* | *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - deplibs="$deplibs -framework System" - continue - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - deplibs="$deplibs $arg" - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) - deplibs="$deplibs $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # gcc -m* arguments should be passed to the linker via $compiler_flags - # in order to pass architecture information to the linker - # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo - # but this is not reliable with gcc because gcc may use -mfoo to - # select a different linker, different libraries, etc, while - # -Wl,-mfoo simply passes -mfoo to the linker. - -m*) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - if test "$with_gcc" = "yes" ; then - compiler_flags="$compiler_flags $arg" - fi - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - # The PATH hackery in wrapper scripts is required on Windows - # in order for the loader to find any dlls it needs. - $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 - $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit 1 - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - continue - ;; - - -static) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -Wc,*) - args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - case $flag in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - flag="\"$flag\"" - ;; - esac - arg="$arg $wl$flag" - compiler_flags="$compiler_flags $flag" - done - IFS="$save_ifs" - arg=`$echo "X$arg" | $Xsed -e "s/^ //"` - ;; - - -Wl,*) - args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - case $flag in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - flag="\"$flag\"" - ;; - esac - arg="$arg $wl$flag" - compiler_flags="$compiler_flags $wl$flag" - linker_flags="$linker_flags $flag" - done - IFS="$save_ifs" - arg=`$echo "X$arg" | $Xsed -e "s/^ //"` - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # Some other compiler flag. - -* | +*) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - ;; - - *.$objext) - # A standard object. - objs="$objs $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - pic_object= - non_pic_object= - - # Read the .lo file - # If there is no directory component, then add one. - case $arg in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - if test -z "$pic_object" || \ - test -z "$non_pic_object" || - test "$pic_object" = none && \ - test "$non_pic_object" = none; then - $echo "$modename: cannot find name of object for \`$arg'" 1>&2 - exit 1 - fi - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" - prev= - fi - - # A PIC object. - libobjs="$libobjs $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - fi - else - # Only an error if not doing a dry-run. - if test -z "$run"; then - $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 - exit 1 - else - # Dry-run case. - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` - non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - fi - ;; - - *.$libext) - # An archive. - deplibs="$deplibs $arg" - old_deplibs="$old_deplibs $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - dlfiles="$dlfiles $arg" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - dlprefiles="$dlprefiles $arg" - prev= - else - deplibs="$deplibs $arg" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - done # argument parsing loop - - if test -n "$prev"; then - $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - # Create the object directory. - if test ! -d "$output_objdir"; then - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - status=$? - if test "$status" -ne 0 && test ! -d "$output_objdir"; then - exit $status - fi - fi - - # Determine the type of output - case $output in - "") - $echo "$modename: you must specify an output file" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - case $host in - *cygwin* | *mingw* | *pw32*) - # don't eliminate duplcations in $postdeps and $predeps - duplicate_compiler_generated_deps=yes - ;; - *) - duplicate_compiler_generated_deps=$duplicate_deps - ;; - esac - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if test "X$duplicate_deps" = "Xyes" ; then - case "$libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - libs="$libs $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; - esac - pre_post_deps="$pre_post_deps $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - case $linkmode in - lib) - passes="conv link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 - exit 1 - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - for pass in $passes; do - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; - esac - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 - continue - fi - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` - for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do - for search_ext in .la $shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if (${SED} -e '2q' $lib | - grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - library_names= - old_library= - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` - test "X$ladir" = "X$lib" && ladir="." - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - ;; - *) - $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) lib="$deplib" ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - if test "$deplibs_check_method" != pass_all; then - $echo - $echo "*** Warning: Trying to link with static lib archive $deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because the file extensions .$libext of this argument makes me believe" - $echo "*** that it is just a static archive that I should not used here." - else - $echo - $echo "*** Warning: Linking the shared library $output against the" - $echo "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - newdlprefiles="$newdlprefiles $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - newdlfiles="$newdlfiles $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - if test "$found" = yes || test -f "$lib"; then : - else - $echo "$modename: cannot find the library \`$lib'" 1>&2 - exit 1 - fi - - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit 1 - fi - - ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` - test "X$ladir" = "X$lib" && ladir="." - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - - # Read the .la file - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && dlfiles="$dlfiles $dlopen" - test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 - exit 1 - fi - # It is a libtool convenience library, so add in its objects. - convenience="$convenience $ladir/$objdir/$old_library" - old_convenience="$old_convenience $ladir/$objdir/$old_library" - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done - elif test "$linkmode" != prog && test "$linkmode" != lib; then - $echo "$modename: \`$lib' is not a convenience library" 1>&2 - exit 1 - fi - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - for l in $old_library $library_names; do - linklib="$l" - done - if test -z "$linklib"; then - $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 - exit 1 - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 - exit 1 - fi - if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - dlprefiles="$dlprefiles $lib $dependency_libs" - else - newdlfiles="$newdlfiles $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - abs_ladir="$ladir" - fi - ;; - esac - laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - $echo "$modename: warning: library \`$lib' was moved." 1>&2 - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$libdir" - absdir="$libdir" - fi - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - notinst_path="$notinst_path $abs_ladir" - fi # $installed = yes - name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 - exit 1 - fi - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - newdlprefiles="$newdlprefiles $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - newdlprefiles="$newdlprefiles $dir/$dlname" - else - newdlprefiles="$newdlprefiles $dir/$linklib" - fi - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - newlib_search_path="$newlib_search_path $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var"; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath " in - *" $dir "*) ;; - *" $absdir "*) ;; - *) temp_rpath="$temp_rpath $dir" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then - if test "$installed" = no; then - notinst_deplibs="$notinst_deplibs $lib" - need_relink=yes - fi - # This is a shared library - - # Warn about portability, can't link against -module's on some systems (darwin) - if test "$shouldnotlink" = yes && test "$pass" = link ; then - $echo - if test "$linkmode" = prog; then - $echo "*** Warning: Linking the executable $output against the loadable module" - else - $echo "*** Warning: Linking the shared library $output against the loadable module" - fi - $echo "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - realname="$2" - shift; shift - libname=`eval \\$echo \"$libname_spec\"` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw*) - major=`expr $current - $age` - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - soname=`$echo $soroot | ${SED} -e 's/^.*\///'` - newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - $show "extracting exported symbol list from \`$soname'" - save_ifs="$IFS"; IFS='~' - cmds=$extract_expsyms_cmds - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - $show "generating import library for \`$soname'" - save_ifs="$IFS"; IFS='~' - cmds=$old_archive_from_expsyms_cmds - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5* ) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a module then we can not link against it, someone - # is ignoring the new warnings I added - if /usr/bin/file -L $add 2> /dev/null | grep "bundle" >/dev/null ; then - $echo "** Warning, lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - $echo - $echo "** And there doesn't seem to be a static archive available" - $echo "** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$dir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case "$libdir" in - [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - $echo "$modename: configuration error: unsupported hardcode properties" - exit 1 - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && \ - test "$hardcode_minus_L" != yes && \ - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case "$libdir" in - [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - $echo - $echo "*** Warning: This system can not link to static lib archive $lib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - $echo "*** But as you try to build a module library, libtool will still create " - $echo "*** a static module, that should work as long as the dlopening application" - $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - $echo - $echo "*** However, this would only work if libtool was able to extract symbol" - $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - $echo "*** not find such a program. So, this module is probably useless." - $echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - convenience="$convenience $dir/$old_library" - old_convenience="$old_convenience $dir/$old_library" - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) xrpath="$xrpath $temp_xrpath";; - esac;; - *) temp_deplibs="$temp_deplibs $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - newlib_search_path="$newlib_search_path $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - case $deplib in - -L*) path="$deplib" ;; - *.la) - dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$deplib" && dir="." - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - absdir="$dir" - fi - ;; - esac - if grep "^installed=no" $deplib > /dev/null; then - path="$absdir/$objdir" - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - if test -z "$libdir"; then - $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 - exit 1 - fi - if test "$absdir" != "$libdir"; then - $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 - fi - path="$absdir" - fi - depdepl= - case $host in - *-*-darwin*) - # we do not want to link against static libs, but need to link against shared - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$path/$depdepl" ; then - depdepl="$path/$depdepl" - fi - # do not add paths which are already there - case " $newlib_search_path " in - *" $path "*) ;; - *) newlib_search_path="$newlib_search_path $path";; - esac - fi - path="" - ;; - *) - path="-L$path" - ;; - esac - - ;; - -l*) - case $host in - *-*-darwin*) - # Again, we only want to link against shared libraries - eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` - for tmp in $newlib_search_path ; do - if test -f "$tmp/lib$tmp_libs.dylib" ; then - eval depdepl="$tmp/lib$tmp_libs.dylib" - break - fi - done - path="" - ;; - *) continue ;; - esac - ;; - *) continue ;; - esac - case " $deplibs " in - *" $depdepl "*) ;; - *) deplibs="$deplibs $depdepl" ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$deplibs $path" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) lib_search_path="$lib_search_path $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) tmp_libs="$tmp_libs $deplib" ;; - esac - ;; - *) tmp_libs="$tmp_libs $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - tmp_libs="$tmp_libs $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 - fi - - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 - fi - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - objs="$objs$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - eval shared_ext=\"$shrext\" - eval libname=\"$libname_spec\" - ;; - *) - if test "$module" = no; then - $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - eval shared_ext=\"$shrext\" - eval libname=\"$libname_spec\" - else - libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 - exit 1 - else - $echo - $echo "*** Warning: Linking the shared library $output against the non-libtool" - $echo "*** objects $objs is not portable!" - libobjs="$libobjs $objs" - fi - fi - - if test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 - fi - - set dummy $rpath - if test "$#" -gt 2; then - $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 - fi - install_libdir="$2" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 - fi - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - IFS="$save_ifs" - - if test -n "$8"; then - $echo "$modename: too many parameters to \`-version-info'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$2" - number_minor="$3" - number_revision="$4" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - darwin|linux|osf|windows) - current=`expr $number_major + $number_minor` - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - current=`expr $number_major + $number_minor - 1` - age="$number_minor" - revision="$number_minor" - ;; - esac - ;; - no) - current="$2" - revision="$3" - age="$4" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; - *) - $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - case $revision in - 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; - *) - $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - case $age in - 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; - *) - $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - if test "$age" -gt "$current"; then - $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - minor_current=`expr $current + 1` - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current"; - ;; - - irix | nonstopux) - major=`expr $current - $age + 1` - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - iface=`expr $revision - $loop` - loop=`expr $loop - 1` - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - ;; - - osf) - major=.`expr $current - $age` - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - iface=`expr $current - $loop` - loop=`expr $loop - 1` - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - verstring="$verstring:${current}.0" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - major=`expr $current - $age` - versuffix="-$major" - ;; - - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - fi - - if test "$mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$echo "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - removelist="$removelist $p" - ;; - *) ;; - esac - done - if test -n "$removelist"; then - $show "${rm}r $removelist" - $run ${rm}r $removelist - fi - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - oldlibs="$oldlibs $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - for path in $notinst_path; do - lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'` - deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'` - dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` - done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - temp_xrpath="$temp_xrpath -R$libdir" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) dlfiles="$dlfiles $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) dlprefiles="$dlprefiles $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - deplibs="$deplibs -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $rm conftest.c - cat > conftest.c </dev/null` - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null \ - | grep " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ - | ${SED} 10q \ - | $EGREP "$file_magic_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - $echo - $echo "*** Warning: linker path does not have real file for library $a_deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $echo "*** with $libname but no candidates were found. (...for file magic test)" - else - $echo "*** with $libname and none of the candidates passed a file format test" - $echo "*** using a file magic. Last file checked: $potlib" - fi - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method - match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` - for a_deplib in $deplibs; do - name="`expr $a_deplib : '-l\(.*\)'`" - # If $name is empty we are operating on a -L argument. - if test -n "$name" && test "$name" != "0"; then - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval \\$echo \"$libname_spec\"` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval $echo \"$potent_lib\" 2>/dev/null \ - | ${SED} 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - $echo - $echo "*** Warning: linker path does not have real file for library $a_deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $echo "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $echo "*** with $libname and none of the candidates passed a file format test" - $echo "*** using a regex pattern. Last file checked: $potlib" - fi - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ - -e 's/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` - done - fi - if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ - | grep . >/dev/null; then - $echo - if test "X$deplibs_check_method" = "Xnone"; then - $echo "*** Warning: inter-library dependencies are not supported in this platform." - else - $echo "*** Warning: inter-library dependencies are not known to be supported." - fi - $echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - fi - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - $echo - $echo "*** Warning: libtool could not satisfy all declared inter-library" - $echo "*** dependencies of module $libname. Therefore, libtool will create" - $echo "*** a static module, that should work as long as the dlopening" - $echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - $echo - $echo "*** However, this would only work if libtool was able to extract symbol" - $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - $echo "*** not find such a program. So, this module is probably useless." - $echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - $echo "*** The inter-library dependencies that have been dropped here will be" - $echo "*** automatically added whenever a program is linked with this library" - $echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - $echo - $echo "*** Since this library must not contain undefined symbols," - $echo "*** because either the platform does not support them or" - $echo "*** it was explicitly requested with -no-undefined," - $echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - dep_rpath="$dep_rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - if test -n "$hardcode_libdir_flag_spec_ld"; then - eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" - else - eval dep_rpath=\"$hardcode_libdir_flag_spec\" - fi - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - realname="$2" - shift; shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - for link - do - linknames="$linknames $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - if len=`expr "X$cmd" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - $show "$cmd" - $run eval "$cmd" || exit $? - skipped_export=false - else - # The command line is too long to execute in one step. - $show "using reloadable object file for export list..." - skipped_export=: - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex"; then - $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" - $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - $show "$mv \"${export_symbols}T\" \"$export_symbols\"" - $run eval '$mv "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - tmp_deplibs="$tmp_deplibs $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - for xlib in $convenience; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - linker_flags="$linker_flags $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise. - $echo "creating reloadable object files..." - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - delfiles= - last_robj= - k=1 - output=$output_objdir/$save_output-${k}.$objext - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - eval test_cmds=\"$reload_cmds $objlist $last_robj\" - if test "X$objlist" = X || - { len=`expr "X$test_cmds" : ".*"` && - test "$len" -le "$max_cmd_len"; }; then - objlist="$objlist $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - eval concat_cmds=\"$reload_cmds $objlist $last_robj\" - else - # All subsequent reloadable object files will link in - # the last one created. - eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" - fi - last_robj=$output_objdir/$save_output-${k}.$objext - k=`expr $k + 1` - output=$output_objdir/$save_output-${k}.$objext - objlist=$obj - len=1 - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" - - if ${skipped_export-false}; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - libobjs=$output - # Append the command to create the export file. - eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" - fi - - # Set up a command to remove the reloadale object files - # after they are used. - i=0 - while test "$i" -lt "$k" - do - i=`expr $i + 1` - delfiles="$delfiles $output_objdir/$save_output-${i}.$objext" - done - - $echo "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - - # Append the command to remove the reloadable object files - # to the just-reset $cmds. - eval cmds=\"\$cmds~\$rm $delfiles\" - fi - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? - exit 0 - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 - fi - - case $output in - *.lo) - if test -n "$objs$old_deplibs"; then - $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 - exit 1 - fi - libobj="$output" - obj=`$echo "X$output" | $Xsed -e "$lo2o"` - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $run $rm $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${obj}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - for xlib in $convenience; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done - fi - fi - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - cmds=$reload_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit 0 - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $run eval "echo timestamp > $libobj" || exit $? - exit 0 - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - cmds=$reload_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit 0 - ;; - - prog) - case $host in - *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; - esac - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 - fi - - if test "$preload" = yes; then - if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && - test "$dlopen_self_static" = unknown; then - $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." - fi - fi - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` - finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` - ;; - esac - - case $host in - *darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - if test "$tagname" = CXX ; then - compile_command="$compile_command ${wl}-bind_at_load" - finalize_command="$finalize_command ${wl}-bind_at_load" - fi - ;; - esac - - compile_command="$compile_command $compile_deplibs" - finalize_command="$finalize_command $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - case :$dllsearchpath: in - *":$libdir:"*) ;; - *) dllsearchpath="$dllsearchpath:$libdir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - fi - - dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - dlsyms="${outputname}S.c" - else - $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 - fi - fi - - if test -n "$dlsyms"; then - case $dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${outputname}.nm" - - $show "$rm $nlist ${nlist}S ${nlist}T" - $run $rm "$nlist" "${nlist}S" "${nlist}T" - - # Parse the name list into a source file. - $show "creating $output_objdir/$dlsyms" - - test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ -/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ -/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -/* Prevent the only kind of declaration conflicts we can make. */ -#define lt_preloaded_symbols some_other_symbol - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - $show "generating symbol list for \`$output'" - - test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - for arg in $progfiles; do - $show "extracting global C symbols from \`$arg'" - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - if test -n "$export_symbols_regex"; then - $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$output.exp" - $run $rm $export_symbols - $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - else - $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' - $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' - $run eval 'mv "$nlist"T "$nlist"' - fi - fi - - for arg in $dlprefiles; do - $show "extracting global C symbols from \`$arg'" - name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` - $run eval '$echo ": $name " >> "$nlist"' - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -z "$run"; then - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $mv "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if grep -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - grep -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' - else - $echo '/* NONE */' >> "$output_objdir/$dlsyms" - fi - - $echo >> "$output_objdir/$dlsyms" "\ - -#undef lt_preloaded_symbols - -#if defined (__STDC__) && __STDC__ -# define lt_ptr void * -#else -# define lt_ptr char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr address; -} -lt_preloaded_symbols[] = -{\ -" - - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" - - $echo >> "$output_objdir/$dlsyms" "\ - {0, (lt_ptr) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - fi - - pic_flag_for_symtable= - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; - esac;; - *-*-hpux*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag";; - esac - esac - - # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? - - # Clean up the generated files. - $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" - $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" - - # Transform the symbol file into the correct name. - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - ;; - *) - $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 - exit 1 - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` - fi - - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - # Replace the output file specification. - compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - $show "$link_command" - $run eval "$link_command" - status=$? - - # Delete the generated files. - if test -n "$dlsyms"; then - $show "$rm $output_objdir/${outputname}S.${objext}" - $run $rm "$output_objdir/${outputname}S.${objext}" - fi - - exit $status - fi - - if test -n "$shlibpath_var"; then - # We should set the shlibpath_var - rpath= - for dir in $temp_rpath; do - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) - # Absolute path. - rpath="$rpath$dir:" - ;; - *) - # Relative path: add a thisdir entry. - rpath="$rpath\$thisdir/$dir:" - ;; - esac - done - temp_rpath="$rpath" - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - rpath="$rpath$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $run $rm $output - # Link the executable and exit - $show "$link_command" - $run eval "$link_command" || exit $? - exit 0 - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 - $echo "$modename: \`$output' will be relinked during installation" 1>&2 - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname - - $show "$link_command" - $run eval "$link_command" || exit $? - - # Now create the wrapper script. - $show "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` - relink_command="$var=\"$var_value\"; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` - fi - - # Quote $echo for shipping. - if test "X$echo" = "X$SHELL $0 --fallback-echo"; then - case $0 in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; - *) qecho="$SHELL `pwd`/$0 --fallback-echo";; - esac - qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` - fi - - # Only actually do things if our run command is non-null. - if test -z "$run"; then - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - cwrappersource=`$echo ${objdir}/lt-${output}.c` - cwrapper=`$echo ${output}.exe` - $rm $cwrappersource $cwrapper - trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15 - - cat > $cwrappersource <> $cwrappersource<<"EOF" -#include -#include -#include -#include -#include -#include - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef DIR_SEPARATOR -#define DIR_SEPARATOR '/' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -#define HAVE_DOS_BASED_FILE_SYSTEM -#ifndef DIR_SEPARATOR_2 -#define DIR_SEPARATOR_2 '\\' -#endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -const char *program_name = NULL; - -void * xmalloc (size_t num); -char * xstrdup (const char *string); -char * basename (const char *name); -char * fnqualify(const char *path); -char * strendzap(char *str, const char *pat); -void lt_fatal (const char *message, ...); - -int -main (int argc, char *argv[]) -{ - char **newargz; - int i; - - program_name = (char *) xstrdup ((char *) basename (argv[0])); - newargz = XMALLOC(char *, argc+2); -EOF - - cat >> $cwrappersource <> $cwrappersource <<"EOF" - newargz[1] = fnqualify(argv[0]); - /* we know the script has the same name, without the .exe */ - /* so make sure newargz[1] doesn't end in .exe */ - strendzap(newargz[1],".exe"); - for (i = 1; i < argc; i++) - newargz[i+1] = xstrdup(argv[i]); - newargz[argc+1] = NULL; -EOF - - cat >> $cwrappersource <> $cwrappersource <<"EOF" -} - -void * -xmalloc (size_t num) -{ - void * p = (void *) malloc (num); - if (!p) - lt_fatal ("Memory exhausted"); - - return p; -} - -char * -xstrdup (const char *string) -{ - return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL -; -} - -char * -basename (const char *name) -{ - const char *base; - -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - /* Skip over the disk name in MSDOS pathnames. */ - if (isalpha (name[0]) && name[1] == ':') - name += 2; -#endif - - for (base = name; *name; name++) - if (IS_DIR_SEPARATOR (*name)) - base = name + 1; - return (char *) base; -} - -char * -fnqualify(const char *path) -{ - size_t size; - char *p; - char tmp[LT_PATHMAX + 1]; - - assert(path != NULL); - - /* Is it qualified already? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha (path[0]) && path[1] == ':') - return xstrdup (path); -#endif - if (IS_DIR_SEPARATOR (path[0])) - return xstrdup (path); - - /* prepend the current directory */ - /* doesn't handle '~' */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); - size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ - p = XMALLOC(char, size); - sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path); - return p; -} - -char * -strendzap(char *str, const char *pat) -{ - size_t len, patlen; - - assert(str != NULL); - assert(pat != NULL); - - len = strlen(str); - patlen = strlen(pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp(str, pat) == 0) - *str = '\0'; - } - return str; -} - -static void -lt_error_core (int exit_status, const char * mode, - const char * message, va_list ap) -{ - fprintf (stderr, "%s: %s: ", program_name, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, "FATAL", message, ap); - va_end (ap); -} -EOF - # we should really use a build-platform specific compiler - # here, but OTOH, the wrappers (shell script and this C one) - # are only useful if you want to execute the "real" binary. - # Since the "real" binary is built for $host, then this - # wrapper might as well be built for $host, too. - $run $LTCC -s -o $cwrapper $cwrappersource - ;; - esac - $rm $output - trap "$rm $output; exit 1" 1 2 15 - - $echo > $output "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='${SED} -e 1s/^X//' -sed_quote_subst='$sed_quote_subst' - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variable: - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$echo are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - echo=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$echo works! - : - else - # Restart under the correct shell, and then maybe \$echo will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ -" - $echo >> $output "\ - - # Find the directory that this script lives in. - thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` - done - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $echo >> $output "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || \\ - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $mkdir \"\$progdir\" - else - $rm \"\$progdir/\$file\" - fi" - - $echo >> $output "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $echo \"\$relink_command_output\" >&2 - $rm \"\$progdir/\$file\" - exit 1 - fi - fi - - $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $rm \"\$progdir/\$program\"; - $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $rm \"\$progdir/\$file\" - fi" - else - $echo >> $output "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $echo >> $output "\ - - if test -f \"\$progdir/\$program\"; then" - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $echo >> $output "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` - - export $shlibpath_var -" - fi - - # fixup the dll searchpath if we need to. - if test -n "$dllsearchpath"; then - $echo >> $output "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - $echo >> $output "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2*) - $echo >> $output "\ - exec \$progdir\\\\\$program \${1+\"\$@\"} -" - ;; - - *) - $echo >> $output "\ - exec \$progdir/\$program \${1+\"\$@\"} -" - ;; - esac - $echo >> $output "\ - \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" - exit 1 - fi - else - # The program doesn't exist. - \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 - \$echo \"This script is just a wrapper for \$program.\" 1>&2 - $echo \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" - chmod +x $output - fi - exit 0 - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - # Add in members from convenience archives. - for xlib in $addlibs; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` - done - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - eval cmds=\"$old_archive_cmds\" - - if len=`expr "X$cmds" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - $echo "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - # GNU ar 2.10+ was changed to match POSIX; thus no paths are - # encoded into archives. This makes 'ar r' malfunction in - # this piecewise linking case whenever conflicting object - # names appear in distinct ar calls; check, warn and compensate. - if (for obj in $save_oldobjs - do - $echo "X$obj" | $Xsed -e 's%^.*/%%' - done | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2 - $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2 - AR_FLAGS=cq - fi - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - for obj in $save_oldobjs - do - oldobjs="$objlist $obj" - objlist="$objlist $obj" - eval test_cmds=\"$old_archive_cmds\" - if len=`expr "X$test_cmds" : ".*"` && - test "$len" -le "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - eval cmd=\"$cmd\" - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$generated"; then - $show "${rm}r$generated" - $run ${rm}r$generated - fi - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - $show "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` - relink_command="$var=\"$var_value\"; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $0 $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - # Only create the output if not a dry run. - if test -z "$run"; then - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - if test -z "$libdir"; then - $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 - exit 1 - fi - newdependency_libs="$newdependency_libs $libdir/$name" - ;; - *) newdependency_libs="$newdependency_libs $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - for lib in $dlfiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit 1 - fi - newdlfiles="$newdlfiles $libdir/$name" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit 1 - fi - newdlprefiles="$newdlprefiles $libdir/$name" - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - newdlfiles="$newdlfiles $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - newdlprefiles="$newdlprefiles $abs" - done - dlprefiles="$newdlprefiles" - fi - $rm $output - # place dlname in correct position for cygwin - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; - esac - $echo > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $echo >> $output "\ -relink_command=\"$relink_command\"" - fi - done - fi - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" - $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? - ;; - esac - exit 0 - ;; - - # libtool install mode - install) - modename="$modename: install" - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then - # Aesthetically quote it. - arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$arg " - arg="$1" - shift - else - install_prog= - arg="$nonopt" - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog$arg" - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - for arg - do - if test -n "$dest"; then - files="$files $dest" - dest="$arg" - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) prev="-f" ;; - -g) prev="-g" ;; - -m) prev="-m" ;; - -o) prev="-o" ;; - -s) - stripme=" -s" - continue - ;; - -*) ;; - - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - prev= - else - dest="$arg" - continue - fi - ;; - esac - - # Aesthetically quote the argument. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog $arg" - done - - if test -z "$install_prog"; then - $echo "$modename: you must specify an install program" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test -n "$prev"; then - $echo "$modename: the \`$prev' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test -z "$files"; then - if test -z "$dest"; then - $echo "$modename: no file or destination specified" 1>&2 - else - $echo "$modename: you must specify a destination" 1>&2 - fi - $echo "$help" 1>&2 - exit 1 - fi - - # Strip any trailing slash from the destination. - dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` - test "X$destdir" = "X$dest" && destdir=. - destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` - - # Not a directory, so check to see that there is only one file specified. - set dummy $files - if test "$#" -gt 2; then - $echo "$modename: \`$dest' is not a directory" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - staticlibs="$staticlibs $file" - ;; - - *.la) - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - library_names= - old_library= - relink_command= - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) current_libdirs="$current_libdirs $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) future_libdirs="$future_libdirs $libdir" ;; - esac - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ - test "X$dir" = "X$file/" && dir= - dir="$dir$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - if test "$inst_prefix_dir" = "$destdir"; then - $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 - exit 1 - fi - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - $echo "$modename: warning: relinking \`$file'" 1>&2 - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - exit 1 - fi - fi - - # See the names of the shared library. - set dummy $library_names - if test -n "$2"; then - realname="$2" - shift - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - $show "$install_prog $dir/$srcname $destdir/$realname" - $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? - if test -n "$stripme" && test -n "$striplib"; then - $show "$striplib $destdir/$realname" - $run eval "$striplib $destdir/$realname" || exit $? - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - for linkname - do - if test "$linkname" != "$realname"; then - $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - fi - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - cmds=$postinstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - # Install the pseudo-library for information purposes. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - instname="$dir/$name"i - $show "$install_prog $instname $destdir/$name" - $run eval "$install_prog $instname $destdir/$name" || exit $? - - # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - esac - - # Install the libtool object if requested. - if test -n "$destfile"; then - $show "$install_prog $file $destfile" - $run eval "$install_prog $file $destfile" || exit $? - fi - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` - - $show "$install_prog $staticobj $staticdest" - $run eval "$install_prog \$staticobj \$staticdest" || exit $? - fi - exit 0 - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - file=`$echo $file|${SED} 's,.exe$,,'` - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin*|*mingw*) - wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` - ;; - *) - wrapper=$file - ;; - esac - if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then - notinst_deplibs= - relink_command= - - # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." - # which disallows the automatic-append-.exe behavior. - case $build in - *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; - *) wrapperdot=${wrapper} ;; - esac - # If there is no directory component, then add one. - case $file in - */* | *\\*) . ${wrapperdot} ;; - *) . ./${wrapperdot} ;; - esac - - # Check the variables that should have been set. - if test -z "$notinst_deplibs"; then - $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 - exit 1 - fi - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - # If there is no directory component, then add one. - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - fi - libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 - finalize=no - fi - done - - relink_command= - # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." - # which disallows the automatic-append-.exe behavior. - case $build in - *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; - *) wrapperdot=${wrapper} ;; - esac - # If there is no directory component, then add one. - case $file in - */* | *\\*) . ${wrapperdot} ;; - *) . ./${wrapperdot} ;; - esac - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - if test "$finalize" = yes && test -z "$run"; then - tmpdir="/tmp" - test -n "$TMPDIR" && tmpdir="$TMPDIR" - tmpdir="$tmpdir/libtool-$$" - if $mkdir "$tmpdir" && chmod 700 "$tmpdir"; then : - else - $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 - continue - fi - file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` - - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - ${rm}r "$tmpdir" - continue - fi - file="$outputname" - else - $echo "$modename: warning: cannot relink \`$file'" 1>&2 - fi - else - # Install the binary that we compiled earlier. - file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyways - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` - ;; - esac - ;; - esac - $show "$install_prog$stripme $file $destfile" - $run eval "$install_prog\$stripme \$file \$destfile" || exit $? - test -n "$outputname" && ${rm}r "$tmpdir" - ;; - esac - done - - for file in $staticlibs; do - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - - $show "$install_prog $file $oldlib" - $run eval "$install_prog \$file \$oldlib" || exit $? - - if test -n "$stripme" && test -n "$old_striplib"; then - $show "$old_striplib $oldlib" - $run eval "$old_striplib $oldlib" || exit $? - fi - - # Do each command in the postinstall commands. - cmds=$old_postinstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$future_libdirs"; then - $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 - fi - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - test -n "$run" && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $0 $preserve_args --finish$current_libdirs' - else - exit 0 - fi - ;; - - # libtool finish mode - finish) - modename="$modename: finish" - libdirs="$nonopt" - admincmds= - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for dir - do - libdirs="$libdirs $dir" - done - - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - cmds=$finish_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || admincmds="$admincmds - $cmd" - done - IFS="$save_ifs" - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $run eval "$cmds" || admincmds="$admincmds - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - test "$show" = : && exit 0 - - $echo "----------------------------------------------------------------------" - $echo "Libraries have been installed in:" - for libdir in $libdirs; do - $echo " $libdir" - done - $echo - $echo "If you ever happen to want to link against installed libraries" - $echo "in a given directory, LIBDIR, you must either use libtool, and" - $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - $echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - $echo " during execution" - fi - if test -n "$runpath_var"; then - $echo " - add LIBDIR to the \`$runpath_var' environment variable" - $echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $echo " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $echo " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - $echo - $echo "See any operating system documentation about shared libraries for" - $echo "more information, such as the ld(1) and ld.so(8) manual pages." - $echo "----------------------------------------------------------------------" - exit 0 - ;; - - # libtool execute mode - execute) - modename="$modename: execute" - - # The first argument is the command name. - cmd="$nonopt" - if test -z "$cmd"; then - $echo "$modename: you must specify a COMMAND" 1>&2 - $echo "$help" - exit 1 - fi - - # Handle -dlopen flags immediately. - for file in $execute_dlfiles; do - if test ! -f "$file"; then - $echo "$modename: \`$file' is not a file" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - dir= - case $file in - *.la) - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Read the libtool library. - dlname= - library_names= - - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" - continue - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - - if test -f "$dir/$objdir/$dlname"; then - dir="$dir/$objdir" - else - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit 1 - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - ;; - - *) - $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -*) ;; - *) - # Do a test to see if this is really a libtool program. - if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` - args="$args \"$file\"" - done - - if test -z "$run"; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - if test "${save_LC_ALL+set}" = set; then - LC_ALL="$save_LC_ALL"; export LC_ALL - fi - if test "${save_LANG+set}" = set; then - LANG="$save_LANG"; export LANG - fi - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" - $echo "export $shlibpath_var" - fi - $echo "$cmd$args" - exit 0 - fi - ;; - - # libtool clean and uninstall mode - clean | uninstall) - modename="$modename: $mode" - rm="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) rm="$rm $arg"; rmforce=yes ;; - -*) rm="$rm $arg" ;; - *) files="$files $arg" ;; - esac - done - - if test -z "$rm"; then - $echo "$modename: you must specify an RM program" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - rmdirs= - - origobjdir="$objdir" - for file in $files; do - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$file"; then - dir=. - objdir="$origobjdir" - else - objdir="$dir/$origobjdir" - fi - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - test "$mode" = uninstall && objdir="$dir" - - # Remember objdir for removal later, being careful to avoid duplicates - if test "$mode" = clean; then - case " $rmdirs " in - *" $objdir "*) ;; - *) rmdirs="$rmdirs $objdir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if (test -L "$file") >/dev/null 2>&1 \ - || (test -h "$file") >/dev/null 2>&1 \ - || test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - . $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - rmfiles="$rmfiles $objdir/$n" - done - test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" - test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" - - if test "$mode" = uninstall; then - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - cmds=$postuninstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" - if test "$?" -ne 0 && test "$rmforce" != yes; then - exit_status=1 - fi - done - IFS="$save_ifs" - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - cmds=$old_postuninstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" - if test "$?" -ne 0 && test "$rmforce" != yes; then - exit_status=1 - fi - done - IFS="$save_ifs" - fi - # FIXME: should reinstall the best remaining shared library. - fi - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - - # Read the .lo file - . $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" \ - && test "$pic_object" != none; then - rmfiles="$rmfiles $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" \ - && test "$non_pic_object" != none; then - rmfiles="$rmfiles $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$mode" = clean ; then - noexename=$name - case $file in - *.exe) - file=`$echo $file|${SED} 's,.exe$,,'` - noexename=`$echo $name|${SED} 's,.exe$,,'` - # $file with .exe has already been added to rmfiles, - # add $file without .exe - rmfiles="$rmfiles $file" - ;; - esac - # Do a test to see if this is a libtool program. - if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - relink_command= - . $dir/$noexename - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - rmfiles="$rmfiles $objdir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - rmfiles="$rmfiles $objdir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - $show "$rm $rmfiles" - $run $rm $rmfiles || exit_status=1 - done - objdir="$origobjdir" - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - $show "rmdir $dir" - $run rmdir $dir >/dev/null 2>&1 - fi - done - - exit $exit_status - ;; - - "") - $echo "$modename: you must specify a MODE" 1>&2 - $echo "$generic_help" 1>&2 - exit 1 - ;; - esac - - if test -z "$exec_cmd"; then - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$generic_help" 1>&2 - exit 1 - fi -fi # test -z "$show_help" - -if test -n "$exec_cmd"; then - eval exec $exec_cmd - exit 1 -fi - -# We need to display help for each of the modes. -case $mode in -"") $echo \ -"Usage: $modename [OPTION]... [MODE-ARG]... - -Provide generalized library-building support services. - - --config show all configuration variables - --debug enable verbose shell tracing --n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --finish same as \`--mode=finish' - --help display this help message and exit - --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] - --quiet same as \`--silent' - --silent don't print informational messages - --tag=TAG use configuration variables from tag TAG - --version print version information - -MODE must be one of the following: - - clean remove files from the build directory - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for -a more detailed description of MODE. - -Report bugs to ." - exit 0 - ;; - -clean) - $echo \ -"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - -compile) - $echo \ -"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -prefer-pic try to building PIC objects only - -prefer-non-pic try to building non-PIC objects only - -static always build a \`.o' file suitable for static linking - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - -execute) - $echo \ -"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - -finish) - $echo \ -"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - -install) - $echo \ -"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - -link) - $echo \ -"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -static do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - -uninstall) - $echo \ -"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - -*) - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; -esac - -$echo -$echo "Try \`$modename --help' for more information about other modes." - -exit 0 - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/code/libmad-0.15.1b/mad.h.sed b/code/libmad-0.15.1b/mad.h.sed deleted file mode 100644 index 70287854..00000000 --- a/code/libmad-0.15.1b/mad.h.sed +++ /dev/null @@ -1,36 +0,0 @@ -# -# libmad - MPEG audio decoder library -# Copyright (C) 2000-2004 Underbit Technologies, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# $Id: mad.h.sed,v 1.9 2004/01/23 09:41:32 rob Exp $ -# - -/^\/\*$/{ -N -s/ \* libmad - /&/ -t copy -b next -: copy -g -n -s|^ \* \$\(Id: .*\) \$$|/* \1 */|p -/^ \*\/$/d -b copy -} -/^# *include "/d -: next -p diff --git a/code/libmad-0.15.1b/missing b/code/libmad-0.15.1b/missing deleted file mode 100644 index 6a37006e..00000000 --- a/code/libmad-0.15.1b/missing +++ /dev/null @@ -1,336 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch]" - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.4 - GNU automake" - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - - aclocal*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. - You can get \`$1Help2man' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then - # We have makeinfo, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - tar) - shift - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - fi - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 diff --git a/code/libmad-0.15.1b/mkinstalldirs b/code/libmad-0.15.1b/mkinstalldirs deleted file mode 100644 index d2d5f21b..00000000 --- a/code/libmad-0.15.1b/mkinstalldirs +++ /dev/null @@ -1,111 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -errstatus=0 -dirmode="" - -usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." - -# process command line arguments -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) # -h for help - echo "$usage" 1>&2 - exit 0 - ;; - -m) # -m PERM arg - shift - test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } - dirmode=$1 - shift - ;; - --) # stop option processing - shift - break - ;; - -*) # unknown option - echo "$usage" 1>&2 - exit 1 - ;; - *) # first non-opt arg - break - ;; - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in - 0) exit 0 ;; -esac - -case $dirmode in - '') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi - ;; - *) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi - ;; -esac - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case $pathcomp in - -*) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# End: -# mkinstalldirs ends here diff --git a/code/libmad-0.15.1b/msvc++/Makefile.am b/code/libmad-0.15.1b/msvc++/Makefile.am deleted file mode 100644 index 96865c7f..00000000 --- a/code/libmad-0.15.1b/msvc++/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -## -## libmad - MPEG audio decoder library -## Copyright (C) 2000-2004 Underbit Technologies, Inc. -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -## -## $Id: Makefile.am,v 1.3 2004/01/23 09:41:33 rob Exp $ -## - -## Process this file with automake to produce Makefile.in - -EXTRA_DIST = mad.h config.h libmad.dsp diff --git a/code/libmad-0.15.1b/msvc++/Makefile.in b/code/libmad-0.15.1b/msvc++/Makefile.in deleted file mode 100644 index eaeb8634..00000000 --- a/code/libmad-0.15.1b/msvc++/Makefile.in +++ /dev/null @@ -1,312 +0,0 @@ -# Makefile.in generated by automake 1.8.2 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_triplet = @host@ -subdir = msvc++ -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -ASO = @ASO@ -ASO_OBJS = @ASO_OBJS@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -FPM = @FPM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBTOOL_DEPS = @LIBTOOL_DEPS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -EXTRA_DIST = mad.h config.h libmad.dsp -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign msvc++/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign msvc++/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-libtool - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-info-am - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - distclean distclean-generic distclean-libtool distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-exec install-exec-am \ - install-info install-info-am install-man install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ - uninstall-info-am - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/code/libmad-0.15.1b/msvc++/config.h b/code/libmad-0.15.1b/msvc++/config.h deleted file mode 100644 index 02683a5f..00000000 --- a/code/libmad-0.15.1b/msvc++/config.h +++ /dev/null @@ -1,130 +0,0 @@ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to enable diagnostic debugging support. */ -/* #undef DEBUG */ - -/* Define to enable experimental code. */ -/* #undef EXPERIMENTAL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the `fcntl' function. */ -/* #undef HAVE_FCNTL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `fork' function. */ -/* #undef HAVE_FORK */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define if your MIPS CPU supports a 2-operand MADD16 instruction. */ -/* #undef HAVE_MADD16_ASM */ - -/* Define if your MIPS CPU supports a 2-operand MADD instruction. */ -/* #undef HAVE_MADD_ASM */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `pipe' function. */ -/* #undef HAVE_PIPE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have that is POSIX.1 compatible. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to 1 if you have the `waitpid' function. */ -/* #undef HAVE_WAITPID */ - -/* Define to disable debugging assertions. */ -/* #undef NDEBUG */ - -/* Define to optimize for accuracy over speed. */ -/* #undef OPT_ACCURACY */ - -/* Define to optimize for speed over accuracy. */ -/* #undef OPT_SPEED */ - -/* Define to enable a fast subband synthesis approximation optimization. */ -/* #undef OPT_SSO */ - -/* Define to influence a strict interpretation of the ISO/IEC standards, even - if this is in opposition with best accepted practices. */ -/* #undef OPT_STRICT */ - -/* Name of package */ -#define PACKAGE "libmad" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "support@underbit.com" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "MPEG Audio Decoder" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "MPEG Audio Decoder 0.15.1b" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libmad" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.15.1b" - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of a `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "0.15.1b" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -#define inline __inline - -/* Define to `int' if does not define. */ -/* #undef pid_t */ diff --git a/code/libmad-0.15.1b/msvc++/libmad.dsp b/code/libmad-0.15.1b/msvc++/libmad.dsp deleted file mode 100644 index faf83132..00000000 --- a/code/libmad-0.15.1b/msvc++/libmad.dsp +++ /dev/null @@ -1,214 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libmad" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=libmad - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libmad.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libmad.mak" CFG="libmad - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libmad - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libmad - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libmad - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /GX /O2 /I "." /D "NDEBUG" /D "FPM_INTEL" /D "WIN32" /D "_MBCS" /D "_LIB" /D "HAVE_CONFIG_H" /D "ASO_ZEROCHECK" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "libmad - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /Gm /GX /ZI /Od /I "." /D "FPM_DEFAULT" /D "_LIB" /D "HAVE_CONFIG_H" /D "ASO_ZEROCHECK" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "DEBUG" /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "libmad - Win32 Release" -# Name "libmad - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "c" -# Begin Source File - -SOURCE=..\bit.c -# End Source File -# Begin Source File - -SOURCE=..\decoder.c -# End Source File -# Begin Source File - -SOURCE=..\fixed.c -# End Source File -# Begin Source File - -SOURCE=..\frame.c -# End Source File -# Begin Source File - -SOURCE=..\huffman.c -# End Source File -# Begin Source File - -SOURCE=..\layer12.c -# End Source File -# Begin Source File - -SOURCE=..\layer3.c -# End Source File -# Begin Source File - -SOURCE=..\stream.c -# End Source File -# Begin Source File - -SOURCE=..\synth.c -# End Source File -# Begin Source File - -SOURCE=..\timer.c -# End Source File -# Begin Source File - -SOURCE=..\version.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h" -# Begin Source File - -SOURCE=..\bit.h -# End Source File -# Begin Source File - -SOURCE=.\config.h -# End Source File -# Begin Source File - -SOURCE=..\decoder.h -# End Source File -# Begin Source File - -SOURCE=..\fixed.h -# End Source File -# Begin Source File - -SOURCE=..\frame.h -# End Source File -# Begin Source File - -SOURCE=..\global.h -# End Source File -# Begin Source File - -SOURCE=..\huffman.h -# End Source File -# Begin Source File - -SOURCE=..\layer12.h -# End Source File -# Begin Source File - -SOURCE=..\layer3.h -# End Source File -# Begin Source File - -SOURCE=..\stream.h -# End Source File -# Begin Source File - -SOURCE=..\synth.h -# End Source File -# Begin Source File - -SOURCE=..\timer.h -# End Source File -# Begin Source File - -SOURCE=..\version.h -# End Source File -# End Group -# Begin Group "Data Files" - -# PROP Default_Filter "dat" -# Begin Source File - -SOURCE=..\D.dat -# End Source File -# Begin Source File - -SOURCE=..\imdct_s.dat -# End Source File -# Begin Source File - -SOURCE=..\qc_table.dat -# End Source File -# Begin Source File - -SOURCE=..\rq_table.dat -# End Source File -# Begin Source File - -SOURCE=..\sf_table.dat -# End Source File -# End Group -# End Target -# End Project diff --git a/code/libmad-0.15.1b/msvc++/mad.h b/code/libmad-0.15.1b/msvc++/mad.h deleted file mode 100644 index d4834785..00000000 --- a/code/libmad-0.15.1b/msvc++/mad.h +++ /dev/null @@ -1,948 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * If you would like to negotiate alternate licensing terms, you may do - * so by contacting: Underbit Technologies, Inc. - */ - -# ifdef __cplusplus -extern "C" { -# endif - -# define FPM_INTEL - - - -# define SIZEOF_INT 4 -# define SIZEOF_LONG 4 -# define SIZEOF_LONG_LONG 8 - - -/* Id: version.h,v 1.24 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_VERSION_H -# define LIBMAD_VERSION_H - -# define MAD_VERSION_MAJOR 0 -# define MAD_VERSION_MINOR 15 -# define MAD_VERSION_PATCH 1 -# define MAD_VERSION_EXTRA " (beta)" - -# define MAD_VERSION_STRINGIZE(str) #str -# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) - -# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_PATCH) \ - MAD_VERSION_EXTRA - -# define MAD_PUBLISHYEAR "2000-2003" -# define MAD_AUTHOR "Underbit Technologies, Inc." -# define MAD_EMAIL "info@underbit.com" - -extern char const mad_version[]; -extern char const mad_copyright[]; -extern char const mad_author[]; -extern char const mad_build[]; - -# endif - -/* Id: fixed.h,v 1.36 2003/05/28 04:36:00 rob Exp */ - -# ifndef LIBMAD_FIXED_H -# define LIBMAD_FIXED_H - -# if SIZEOF_INT >= 4 -typedef signed int mad_fixed_t; - -typedef signed int mad_fixed64hi_t; -typedef unsigned int mad_fixed64lo_t; -# else -typedef signed long mad_fixed_t; - -typedef signed long mad_fixed64hi_t; -typedef unsigned long mad_fixed64lo_t; -# endif - -# if defined(_MSC_VER) -# define mad_fixed64_t signed __int64 -# elif 1 || defined(__GNUC__) -# define mad_fixed64_t signed long long -# endif - -# if defined(FPM_FLOAT) -typedef double mad_sample_t; -# else -typedef mad_fixed_t mad_sample_t; -# endif - -/* - * Fixed-point format: 0xABBBBBBB - * A == whole part (sign + 3 bits) - * B == fractional part (28 bits) - * - * Values are signed two's complement, so the effective range is: - * 0x80000000 to 0x7fffffff - * -8.0 to +7.9999999962747097015380859375 - * - * The smallest representable value is: - * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) - * - * 28 bits of fractional accuracy represent about - * 8.6 digits of decimal accuracy. - * - * Fixed-point numbers can be added or subtracted as normal - * integers, but multiplication requires shifting the 64-bit result - * from 56 fractional bits back to 28 (and rounding.) - * - * Changing the definition of MAD_F_FRACBITS is only partially - * supported, and must be done with care. - */ - -# define MAD_F_FRACBITS 28 - -# if MAD_F_FRACBITS == 28 -# define MAD_F(x) ((mad_fixed_t) (x##L)) -# else -# if MAD_F_FRACBITS < 28 -# warning "MAD_F_FRACBITS < 28" -# define MAD_F(x) ((mad_fixed_t) \ - (((x##L) + \ - (1L << (28 - MAD_F_FRACBITS - 1))) >> \ - (28 - MAD_F_FRACBITS))) -# elif MAD_F_FRACBITS > 28 -# error "MAD_F_FRACBITS > 28 not currently supported" -# define MAD_F(x) ((mad_fixed_t) \ - ((x##L) << (MAD_F_FRACBITS - 28))) -# endif -# endif - -# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) -# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) - -# define MAD_F_ONE MAD_F(0x10000000) - -# define mad_f_tofixed(x) ((mad_fixed_t) \ - ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) -# define mad_f_todouble(x) ((double) \ - ((x) / (double) (1L << MAD_F_FRACBITS))) - -# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) -# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) - /* (x should be positive) */ - -# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) - -# define mad_f_add(x, y) ((x) + (y)) -# define mad_f_sub(x, y) ((x) - (y)) - -# if defined(FPM_FLOAT) -# error "FPM_FLOAT not yet supported" - -# undef MAD_F -# define MAD_F(x) mad_f_todouble(x) - -# define mad_f_mul(x, y) ((x) * (y)) -# define mad_f_scale64 - -# undef ASO_ZEROCHECK - -# elif defined(FPM_64BIT) - -/* - * This version should be the most accurate if 64-bit types are supported by - * the compiler, although it may not be the most efficient. - */ -# if defined(OPT_ACCURACY) -# define mad_f_mul(x, y) \ - ((mad_fixed_t) \ - ((((mad_fixed64_t) (x) * (y)) + \ - (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) -# else -# define mad_f_mul(x, y) \ - ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS)) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Intel --------------------------------------------------------------- */ - -# elif defined(FPM_INTEL) - -# if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4035) /* no return value */ -static __forceinline -mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) -{ - enum { - fracbits = MAD_F_FRACBITS - }; - - __asm { - mov eax, x - imul y - shrd eax, edx, fracbits - } - - /* implicit return of eax */ -} -# pragma warning(pop) - -# define mad_f_mul mad_f_mul_inline -# define mad_f_scale64 -# else -/* - * This Intel version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("imull %3" \ - : "=a" (lo), "=d" (hi) \ - : "%a" (x), "rm" (y) \ - : "cc") - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addl %2,%0\n\t" \ - "adcl %3,%1" \ - : "=rm" (lo), "=rm" (hi) \ - : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ - : "cc"); \ - }) -# endif /* OPT_ACCURACY */ - -# if defined(OPT_ACCURACY) -/* - * Surprisingly, this is faster than SHRD followed by ADC. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed64hi_t __hi_; \ - mad_fixed64lo_t __lo_; \ - mad_fixed_t __result; \ - asm ("addl %4,%2\n\t" \ - "adcl %5,%3" \ - : "=rm" (__lo_), "=rm" (__hi_) \ - : "0" (lo), "1" (hi), \ - "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ - : "cc"); \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("shrdl %3,%2,%1" \ - : "=rm" (__result) \ - : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif /* OPT_ACCURACY */ - -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- ARM ----------------------------------------------------------------- */ - -# elif defined(FPM_ARM) - -/* - * This ARM V4 version is as accurate as FPM_64BIT but much faster. The - * least significant bit is properly rounded at no CPU cycle cost! - */ -# if 1 -/* - * This is faster than the default implementation via MAD_F_MLX() and - * mad_f_scale64(). - */ -# define mad_f_mul(x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - mad_fixed_t __result; \ - asm ("smull %0, %1, %3, %4\n\t" \ - "movs %0, %0, lsr %5\n\t" \ - "adc %2, %0, %1, lsl %6" \ - : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ - : "%r" (x), "r" (y), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) -# endif - -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smull %0, %1, %2, %3" \ - : "=&r" (lo), "=&r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("smlal %0, %1, %2, %3" \ - : "+r" (lo), "+r" (hi) \ - : "%r" (x), "r" (y)) - -# define MAD_F_MLN(hi, lo) \ - asm ("rsbs %0, %2, #0\n\t" \ - "rsc %1, %3, #0" \ - : "=r" (lo), "=r" (hi) \ - : "0" (lo), "1" (hi) \ - : "cc") - -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("movs %0, %1, lsr %3\n\t" \ - "adc %0, %0, %2, lsl %4" \ - : "=&r" (__result) \ - : "r" (lo), "r" (hi), \ - "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ - : "cc"); \ - __result; \ - }) - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- MIPS ---------------------------------------------------------------- */ - -# elif defined(FPM_MIPS) - -/* - * This MIPS version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" (x), "r" (y)) - -# if defined(HAVE_MADD_ASM) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" (x), "r" (y)) -# elif defined(HAVE_MADD16_ASM) -/* - * This loses significant accuracy due to the 16-bit integer limit in the - * multiply/accumulate instruction. - */ -# define MAD_F_ML0(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd16 %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) -# endif - -# if defined(OPT_SPEED) -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* --- SPARC --------------------------------------------------------------- */ - -# elif defined(FPM_SPARC) - -/* - * This SPARC V8 version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("smul %2, %3, %0\n\t" \ - "rd %%y, %1" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (x), "rI" (y)) - -/* --- PowerPC ------------------------------------------------------------- */ - -# elif defined(FPM_PPC) - -/* - * This PowerPC version is fast and accurate; the disposition of the least - * significant bit depends on OPT_ACCURACY via mad_f_scale64(). - */ -# define MAD_F_MLX(hi, lo, x, y) \ - do { \ - asm ("mullw %0,%1,%2" \ - : "=r" (lo) \ - : "%r" (x), "r" (y)); \ - asm ("mulhw %0,%1,%2" \ - : "=r" (hi) \ - : "%r" (x), "r" (y)); \ - } \ - while (0) - -# if defined(OPT_ACCURACY) -/* - * This gives best accuracy but is not very fast. - */ -# define MAD_F_MLA(hi, lo, x, y) \ - ({ mad_fixed64hi_t __hi; \ - mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - asm ("addc %0,%2,%3\n\t" \ - "adde %1,%4,%5" \ - : "=r" (lo), "=r" (hi) \ - : "%r" (lo), "r" (__lo), \ - "%r" (hi), "r" (__hi) \ - : "xer"); \ - }) -# endif - -# if defined(OPT_ACCURACY) -/* - * This is slower than the truncating version below it. - */ -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result, __round; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("extrwi %0,%1,1,0" \ - : "=r" (__round) \ - : "r" (__result)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - asm ("add %0,%1,%2" \ - : "=r" (__result) \ - : "%r" (__result), "r" (__round)); \ - __result; \ - }) -# else -# define mad_f_scale64(hi, lo) \ - ({ mad_fixed_t __result; \ - asm ("rotrwi %0,%1,%2" \ - : "=r" (__result) \ - : "r" (lo), "i" (MAD_F_SCALEBITS)); \ - asm ("insrwi %0,%1,%2,0" \ - : "+r" (__result) \ - : "r" (hi), "i" (MAD_F_SCALEBITS)); \ - __result; \ - }) -# endif - -# define MAD_F_SCALEBITS MAD_F_FRACBITS - -/* --- Default ------------------------------------------------------------- */ - -# elif defined(FPM_DEFAULT) - -/* - * This version is the most portable but it loses significant accuracy. - * Furthermore, accuracy is biased against the second argument, so care - * should be taken when ordering operands. - * - * The scale factors are constant as this is not used with SSO. - * - * Pre-rounding is required to stay within the limits of compliance. - */ -# if defined(OPT_SPEED) -# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) -# else -# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ - (((y) + (1L << 15)) >> 16)) -# endif - -/* ------------------------------------------------------------------------- */ - -# else -# error "no FPM selected" -# endif - -/* default implementations */ - -# if !defined(mad_f_mul) -# define mad_f_mul(x, y) \ - ({ register mad_fixed64hi_t __hi; \ - register mad_fixed64lo_t __lo; \ - MAD_F_MLX(__hi, __lo, (x), (y)); \ - mad_f_scale64(__hi, __lo); \ - }) -# endif - -# if !defined(MAD_F_MLA) -# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) -# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) -# define MAD_F_MLN(hi, lo) ((lo) = -(lo)) -# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) -# endif - -# if !defined(MAD_F_ML0) -# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) -# endif - -# if !defined(MAD_F_MLN) -# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) -# endif - -# if !defined(MAD_F_MLZ) -# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) -# endif - -# if !defined(mad_f_scale64) -# if defined(OPT_ACCURACY) -# define mad_f_scale64(hi, lo) \ - ((((mad_fixed_t) \ - (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ - ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) -# else -# define mad_f_scale64(hi, lo) \ - ((mad_fixed_t) \ - (((hi) << (32 - MAD_F_SCALEBITS)) | \ - ((lo) >> MAD_F_SCALEBITS))) -# endif -# define MAD_F_SCALEBITS MAD_F_FRACBITS -# endif - -/* C routines */ - -mad_fixed_t mad_f_abs(mad_fixed_t); -mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); - -# endif - -/* Id: bit.h,v 1.11 2003/05/27 22:40:36 rob Exp */ - -# ifndef LIBMAD_BIT_H -# define LIBMAD_BIT_H - -struct mad_bitptr { - unsigned char const *byte; - unsigned short cache; - unsigned short left; -}; - -void mad_bit_init(struct mad_bitptr *, unsigned char const *); - -# define mad_bit_finish(bitptr) /* nothing */ - -unsigned int mad_bit_length(struct mad_bitptr const *, - struct mad_bitptr const *); - -# define mad_bit_bitsleft(bitptr) ((bitptr)->left) -unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); - -void mad_bit_skip(struct mad_bitptr *, unsigned int); -unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); -void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); - -unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); - -# endif - -/* Id: timer.h,v 1.15 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_TIMER_H -# define LIBMAD_TIMER_H - -typedef struct { - signed long seconds; /* whole seconds */ - unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ -} mad_timer_t; - -extern mad_timer_t const mad_timer_zero; - -# define MAD_TIMER_RESOLUTION 352800000UL - -enum mad_units { - MAD_UNITS_HOURS = -2, - MAD_UNITS_MINUTES = -1, - MAD_UNITS_SECONDS = 0, - - /* metric units */ - - MAD_UNITS_DECISECONDS = 10, - MAD_UNITS_CENTISECONDS = 100, - MAD_UNITS_MILLISECONDS = 1000, - - /* audio sample units */ - - MAD_UNITS_8000_HZ = 8000, - MAD_UNITS_11025_HZ = 11025, - MAD_UNITS_12000_HZ = 12000, - - MAD_UNITS_16000_HZ = 16000, - MAD_UNITS_22050_HZ = 22050, - MAD_UNITS_24000_HZ = 24000, - - MAD_UNITS_32000_HZ = 32000, - MAD_UNITS_44100_HZ = 44100, - MAD_UNITS_48000_HZ = 48000, - - /* video frame/field units */ - - MAD_UNITS_24_FPS = 24, - MAD_UNITS_25_FPS = 25, - MAD_UNITS_30_FPS = 30, - MAD_UNITS_48_FPS = 48, - MAD_UNITS_50_FPS = 50, - MAD_UNITS_60_FPS = 60, - - /* CD audio frames */ - - MAD_UNITS_75_FPS = 75, - - /* video drop-frame units */ - - MAD_UNITS_23_976_FPS = -24, - MAD_UNITS_24_975_FPS = -25, - MAD_UNITS_29_97_FPS = -30, - MAD_UNITS_47_952_FPS = -48, - MAD_UNITS_49_95_FPS = -50, - MAD_UNITS_59_94_FPS = -60 -}; - -# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero)) - -int mad_timer_compare(mad_timer_t, mad_timer_t); - -# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) - -void mad_timer_negate(mad_timer_t *); -mad_timer_t mad_timer_abs(mad_timer_t); - -void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); -void mad_timer_add(mad_timer_t *, mad_timer_t); -void mad_timer_multiply(mad_timer_t *, signed long); - -signed long mad_timer_count(mad_timer_t, enum mad_units); -unsigned long mad_timer_fraction(mad_timer_t, unsigned long); -void mad_timer_string(mad_timer_t, char *, char const *, - enum mad_units, enum mad_units, unsigned long); - -# endif - -/* Id: stream.h,v 1.18 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_STREAM_H -# define LIBMAD_STREAM_H - - -# define MAD_BUFFER_GUARD 8 -# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) - -enum mad_error { - MAD_ERROR_NONE = 0x0000, /* no error */ - - MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ - MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ - - MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ - - MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ - MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ - MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ - MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ - MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ - - MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ - MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ - MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ - MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ - MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ - MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ - MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ - MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ - MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ - MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ - MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ - MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ -}; - -# define MAD_RECOVERABLE(error) ((error) & 0xff00) - -struct mad_stream { - unsigned char const *buffer; /* input bitstream buffer */ - unsigned char const *bufend; /* end of buffer */ - unsigned long skiplen; /* bytes to skip before next frame */ - - int sync; /* stream sync found */ - unsigned long freerate; /* free bitrate (fixed) */ - - unsigned char const *this_frame; /* start of current frame */ - unsigned char const *next_frame; /* start of next frame */ - struct mad_bitptr ptr; /* current processing bit pointer */ - - struct mad_bitptr anc_ptr; /* ancillary bits pointer */ - unsigned int anc_bitlen; /* number of ancillary bits */ - - unsigned char (*main_data)[MAD_BUFFER_MDLEN]; - /* Layer III main_data() */ - unsigned int md_len; /* bytes in main_data */ - - int options; /* decoding options (see below) */ - enum mad_error error; /* error code (see above) */ -}; - -enum { - MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ - MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */ -# if 0 /* not yet implemented */ - MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ - MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ - MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */ -# endif -}; - -void mad_stream_init(struct mad_stream *); -void mad_stream_finish(struct mad_stream *); - -# define mad_stream_options(stream, opts) \ - ((void) ((stream)->options = (opts))) - -void mad_stream_buffer(struct mad_stream *, - unsigned char const *, unsigned long); -void mad_stream_skip(struct mad_stream *, unsigned long); - -int mad_stream_sync(struct mad_stream *); - -char const *mad_stream_errorstr(struct mad_stream const *); - -# endif - -/* Id: frame.h,v 1.19 2003/05/27 22:40:36 rob Exp */ - -# ifndef LIBMAD_FRAME_H -# define LIBMAD_FRAME_H - - -enum mad_layer { - MAD_LAYER_I = 1, /* Layer I */ - MAD_LAYER_II = 2, /* Layer II */ - MAD_LAYER_III = 3 /* Layer III */ -}; - -enum mad_mode { - MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ - MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ - MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ - MAD_MODE_STEREO = 3 /* normal LR stereo */ -}; - -enum mad_emphasis { - MAD_EMPHASIS_NONE = 0, /* no emphasis */ - MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ - MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */ - MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */ -}; - -struct mad_header { - enum mad_layer layer; /* audio layer (1, 2, or 3) */ - enum mad_mode mode; /* channel mode (see above) */ - int mode_extension; /* additional mode info */ - enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ - - unsigned long bitrate; /* stream bitrate (bps) */ - unsigned int samplerate; /* sampling frequency (Hz) */ - - unsigned short crc_check; /* frame CRC accumulator */ - unsigned short crc_target; /* final target CRC checksum */ - - int flags; /* flags (see below) */ - int private_bits; /* private bits (see below) */ - - mad_timer_t duration; /* audio playing time of frame */ -}; - -struct mad_frame { - struct mad_header header; /* MPEG audio header */ - - int options; /* decoding options (from stream) */ - - mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ - mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ -}; - -# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) -# define MAD_NSBSAMPLES(header) \ - ((header)->layer == MAD_LAYER_I ? 12 : \ - (((header)->layer == MAD_LAYER_III && \ - ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) - -enum { - MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ - MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ - - MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ - MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ - MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ - MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ - - MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ - MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ - MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ - - MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ - MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ - MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ -}; - -enum { - MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ - MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ -}; - -void mad_header_init(struct mad_header *); - -# define mad_header_finish(header) /* nothing */ - -int mad_header_decode(struct mad_header *, struct mad_stream *); - -void mad_frame_init(struct mad_frame *); -void mad_frame_finish(struct mad_frame *); - -int mad_frame_decode(struct mad_frame *, struct mad_stream *); - -void mad_frame_mute(struct mad_frame *); - -# endif - -/* Id: synth.h,v 1.14 2003/05/27 22:40:37 rob Exp */ - -# ifndef LIBMAD_SYNTH_H -# define LIBMAD_SYNTH_H - - -struct mad_pcm { - unsigned int samplerate; /* sampling frequency (Hz) */ - unsigned short channels; /* number of channels */ - unsigned short length; /* number of samples per channel */ - mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */ -}; - -struct mad_synth { - mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ - /* [ch][eo][peo][s][v] */ - - unsigned int phase; /* current processing phase */ - - struct mad_pcm pcm; /* PCM output */ -}; - -/* single channel PCM selector */ -enum { - MAD_PCM_CHANNEL_SINGLE = 0 -}; - -/* dual channel PCM selector */ -enum { - MAD_PCM_CHANNEL_DUAL_1 = 0, - MAD_PCM_CHANNEL_DUAL_2 = 1 -}; - -/* stereo PCM selector */ -enum { - MAD_PCM_CHANNEL_STEREO_LEFT = 0, - MAD_PCM_CHANNEL_STEREO_RIGHT = 1 -}; - -void mad_synth_init(struct mad_synth *); - -# define mad_synth_finish(synth) /* nothing */ - -void mad_synth_mute(struct mad_synth *); - -void mad_synth_frame(struct mad_synth *, struct mad_frame const *); - -# endif - -/* Id: decoder.h,v 1.16 2003/05/27 22:40:36 rob Exp */ - -# ifndef LIBMAD_DECODER_H -# define LIBMAD_DECODER_H - - -enum mad_decoder_mode { - MAD_DECODER_MODE_SYNC = 0, - MAD_DECODER_MODE_ASYNC -}; - -enum mad_flow { - MAD_FLOW_CONTINUE = 0x0000, /* continue normally */ - MAD_FLOW_STOP = 0x0010, /* stop decoding normally */ - MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */ - MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */ -}; - -struct mad_decoder { - enum mad_decoder_mode mode; - - int options; - - struct { - long pid; - int in; - int out; - } async; - - struct { - struct mad_stream stream; - struct mad_frame frame; - struct mad_synth synth; - } *sync; - - void *cb_data; - - enum mad_flow (*input_func)(void *, struct mad_stream *); - enum mad_flow (*header_func)(void *, struct mad_header const *); - enum mad_flow (*filter_func)(void *, - struct mad_stream const *, struct mad_frame *); - enum mad_flow (*output_func)(void *, - struct mad_header const *, struct mad_pcm *); - enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); - enum mad_flow (*message_func)(void *, void *, unsigned int *); -}; - -void mad_decoder_init(struct mad_decoder *, void *, - enum mad_flow (*)(void *, struct mad_stream *), - enum mad_flow (*)(void *, struct mad_header const *), - enum mad_flow (*)(void *, - struct mad_stream const *, - struct mad_frame *), - enum mad_flow (*)(void *, - struct mad_header const *, - struct mad_pcm *), - enum mad_flow (*)(void *, - struct mad_stream *, - struct mad_frame *), - enum mad_flow (*)(void *, void *, unsigned int *)); -int mad_decoder_finish(struct mad_decoder *); - -# define mad_decoder_options(decoder, opts) \ - ((void) ((decoder)->options = (opts))) - -int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); -int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); - -# endif - -# ifdef __cplusplus -} -# endif diff --git a/code/libmad-0.15.1b/stream.h b/code/libmad-0.15.1b/stream.h deleted file mode 100644 index 8bff8b49..00000000 --- a/code/libmad-0.15.1b/stream.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: stream.h,v 1.20 2004/02/05 09:02:39 rob Exp $ - */ - -# ifndef LIBMAD_STREAM_H -# define LIBMAD_STREAM_H - -# include "bit.h" - -# define MAD_BUFFER_GUARD 8 -# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) - -enum mad_error { - MAD_ERROR_NONE = 0x0000, /* no error */ - - MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ - MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ - - MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ - - MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ - MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ - MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ - MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ - MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ - - MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ - MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ - MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ - MAD_ERROR_BADMODE = 0x0222, /* bad bitrate/mode combination */ - MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ - MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ - MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ - MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ - MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ - MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ - MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ - MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ - MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ -}; - -# define MAD_RECOVERABLE(error) ((error) & 0xff00) - -struct mad_stream { - unsigned char const *buffer; /* input bitstream buffer */ - unsigned char const *bufend; /* end of buffer */ - unsigned long skiplen; /* bytes to skip before next frame */ - - int sync; /* stream sync found */ - unsigned long freerate; /* free bitrate (fixed) */ - - unsigned char const *this_frame; /* start of current frame */ - unsigned char const *next_frame; /* start of next frame */ - struct mad_bitptr ptr; /* current processing bit pointer */ - - struct mad_bitptr anc_ptr; /* ancillary bits pointer */ - unsigned int anc_bitlen; /* number of ancillary bits */ - - unsigned char (*main_data)[MAD_BUFFER_MDLEN]; - /* Layer III main_data() */ - unsigned int md_len; /* bytes in main_data */ - - int options; /* decoding options (see below) */ - enum mad_error error; /* error code (see above) */ -}; - -enum { - MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ - MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */ -# if 0 /* not yet implemented */ - MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ - MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ - MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */ -# endif -}; - -void mad_stream_init(struct mad_stream *); -void mad_stream_finish(struct mad_stream *); - -# define mad_stream_options(stream, opts) \ - ((void) ((stream)->options = (opts))) - -void mad_stream_buffer(struct mad_stream *, - unsigned char const *, unsigned long); -void mad_stream_skip(struct mad_stream *, unsigned long); - -int mad_stream_sync(struct mad_stream *); - -char const *mad_stream_errorstr(struct mad_stream const *); - -# endif diff --git a/code/libmad-0.15.1b/synth.h b/code/libmad-0.15.1b/synth.h deleted file mode 100644 index 8ae4bc95..00000000 --- a/code/libmad-0.15.1b/synth.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: synth.h,v 1.15 2004/01/23 09:41:33 rob Exp $ - */ - -# ifndef LIBMAD_SYNTH_H -# define LIBMAD_SYNTH_H - -# include "fixed.h" -# include "frame.h" - -struct mad_pcm { - unsigned int samplerate; /* sampling frequency (Hz) */ - unsigned short channels; /* number of channels */ - unsigned short length; /* number of samples per channel */ - mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */ -}; - -struct mad_synth { - mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ - /* [ch][eo][peo][s][v] */ - - unsigned int phase; /* current processing phase */ - - struct mad_pcm pcm; /* PCM output */ -}; - -/* single channel PCM selector */ -enum { - MAD_PCM_CHANNEL_SINGLE = 0 -}; - -/* dual channel PCM selector */ -enum { - MAD_PCM_CHANNEL_DUAL_1 = 0, - MAD_PCM_CHANNEL_DUAL_2 = 1 -}; - -/* stereo PCM selector */ -enum { - MAD_PCM_CHANNEL_STEREO_LEFT = 0, - MAD_PCM_CHANNEL_STEREO_RIGHT = 1 -}; - -void mad_synth_init(struct mad_synth *); - -# define mad_synth_finish(synth) /* nothing */ - -void mad_synth_mute(struct mad_synth *); - -void mad_synth_frame(struct mad_synth *, struct mad_frame const *); - -# endif diff --git a/code/libmad-0.15.1b/timer.h b/code/libmad-0.15.1b/timer.h deleted file mode 100644 index eb4542bb..00000000 --- a/code/libmad-0.15.1b/timer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: timer.h,v 1.16 2004/01/23 09:41:33 rob Exp $ - */ - -# ifndef LIBMAD_TIMER_H -# define LIBMAD_TIMER_H - -typedef struct { - signed long seconds; /* whole seconds */ - unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ -} mad_timer_t; - -extern mad_timer_t const mad_timer_zero; - -# define MAD_TIMER_RESOLUTION 352800000UL - -enum mad_units { - MAD_UNITS_HOURS = -2, - MAD_UNITS_MINUTES = -1, - MAD_UNITS_SECONDS = 0, - - /* metric units */ - - MAD_UNITS_DECISECONDS = 10, - MAD_UNITS_CENTISECONDS = 100, - MAD_UNITS_MILLISECONDS = 1000, - - /* audio sample units */ - - MAD_UNITS_8000_HZ = 8000, - MAD_UNITS_11025_HZ = 11025, - MAD_UNITS_12000_HZ = 12000, - - MAD_UNITS_16000_HZ = 16000, - MAD_UNITS_22050_HZ = 22050, - MAD_UNITS_24000_HZ = 24000, - - MAD_UNITS_32000_HZ = 32000, - MAD_UNITS_44100_HZ = 44100, - MAD_UNITS_48000_HZ = 48000, - - /* video frame/field units */ - - MAD_UNITS_24_FPS = 24, - MAD_UNITS_25_FPS = 25, - MAD_UNITS_30_FPS = 30, - MAD_UNITS_48_FPS = 48, - MAD_UNITS_50_FPS = 50, - MAD_UNITS_60_FPS = 60, - - /* CD audio frames */ - - MAD_UNITS_75_FPS = 75, - - /* video drop-frame units */ - - MAD_UNITS_23_976_FPS = -24, - MAD_UNITS_24_975_FPS = -25, - MAD_UNITS_29_97_FPS = -30, - MAD_UNITS_47_952_FPS = -48, - MAD_UNITS_49_95_FPS = -50, - MAD_UNITS_59_94_FPS = -60 -}; - -# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero)) - -int mad_timer_compare(mad_timer_t, mad_timer_t); - -# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) - -void mad_timer_negate(mad_timer_t *); -mad_timer_t mad_timer_abs(mad_timer_t); - -void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); -void mad_timer_add(mad_timer_t *, mad_timer_t); -void mad_timer_multiply(mad_timer_t *, signed long); - -signed long mad_timer_count(mad_timer_t, enum mad_units); -unsigned long mad_timer_fraction(mad_timer_t, unsigned long); -void mad_timer_string(mad_timer_t, char *, char const *, - enum mad_units, enum mad_units, unsigned long); - -# endif diff --git a/code/libmad-0.15.1b/version.h b/code/libmad-0.15.1b/version.h deleted file mode 100644 index d215d4c1..00000000 --- a/code/libmad-0.15.1b/version.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * libmad - MPEG audio decoder library - * Copyright (C) 2000-2004 Underbit Technologies, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: version.h,v 1.26 2004/01/23 09:41:33 rob Exp $ - */ - -# ifndef LIBMAD_VERSION_H -# define LIBMAD_VERSION_H - -# define MAD_VERSION_MAJOR 0 -# define MAD_VERSION_MINOR 15 -# define MAD_VERSION_PATCH 1 -# define MAD_VERSION_EXTRA " (beta)" - -# define MAD_VERSION_STRINGIZE(str) #str -# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) - -# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ - MAD_VERSION_STRING(MAD_VERSION_PATCH) \ - MAD_VERSION_EXTRA - -# define MAD_PUBLISHYEAR "2000-2004" -# define MAD_AUTHOR "Underbit Technologies, Inc." -# define MAD_EMAIL "info@underbit.com" - -extern char const mad_version[]; -extern char const mad_copyright[]; -extern char const mad_author[]; -extern char const mad_build[]; - -# endif diff --git a/code/libmad/.github/workflows/build.yml b/code/libmad/.github/workflows/build.yml new file mode 100644 index 00000000..ba50e409 --- /dev/null +++ b/code/libmad/.github/workflows/build.yml @@ -0,0 +1,44 @@ +name: build + +on: + push: + pull_request: + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - name: Ubuntu + os: ubuntu-latest + install_dir: ~/libmad + cmake_extras: -DCMAKE_BUILD_TYPE=RelWithDebInfo + - name: macOS + os: macos-latest + install_dir: ~/libmad + cmake_extras: -DCMAKE_BUILD_TYPE=RelWithDebInfo + - name: Windows + os: windows-latest + install_dir: C:\libmad + cmake_config: --config RelWithDebInfo + + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + - name: Configure + run: cmake -DCMAKE_INSTALL_PREFIX=${{ matrix.install_dir }} ${{ matrix.cmake_extras }} -S . -B build + - name: Build + run: cmake --build build ${{ matrix.cmake_config }} + env: + CMAKE_BUILD_PARALLEL_LEVEL: 2 + - name: Install + run: cmake --install . ${{ matrix.cmake_config }} + working-directory: build + - name: Upload Build Artifact + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.name }} libmad build + path: ${{ matrix.install_dir }} diff --git a/code/libmad/.gitignore b/code/libmad/.gitignore new file mode 100644 index 00000000..378eac25 --- /dev/null +++ b/code/libmad/.gitignore @@ -0,0 +1 @@ +build diff --git a/code/libmad-0.15.1b/CHANGES b/code/libmad/CHANGES similarity index 94% rename from code/libmad-0.15.1b/CHANGES rename to code/libmad/CHANGES index 9291760b..45a94436 100644 --- a/code/libmad-0.15.1b/CHANGES +++ b/code/libmad/CHANGES @@ -6,6 +6,28 @@ =============================================================================== +Verison 0.16.4 + * Fix compatibility with libmad 0.15.1b + +Version 0.16.3 + * Disable assembly optimizations for all 64 bit CPU architectures; they are + only for 32 and 16 bit architectures + * Fix CPU architecture detection for PowerPC + +Version 0.16.2 + * Fix building assembly file on ARM + * Fix pkgconfig file when CMAKE_INSTALL_{INCLUDE,LIB}DIR are absolute paths + +Version 0.16.1 + * Fix generation of mad.h broken by move to CMake + * Add CMake options for CPU architecture-specific optimizations + +Version 0.16.0 + * Add CMake build system + * Remove autotools build system + * Add pkgconfig and CMake config files + * Apply patches from Debian and Fedora + Version 0.15.1 (beta) * Updated to autoconf 2.59, automake 1.8.2, libtool 1.5.2. diff --git a/code/libmad/CMakeLists.txt b/code/libmad/CMakeLists.txt new file mode 100644 index 00000000..3d3e16db --- /dev/null +++ b/code/libmad/CMakeLists.txt @@ -0,0 +1,240 @@ +cmake_minimum_required(VERSION 3.5) +project(mad VERSION 0.16.4) + +option(BUILD_SHARED_LIBS "Build dynamic library" ON) + +# The library SOVERSION. This is set to 0 for backward compatibility. +# The general policy is that minor versions of the library (e.g., 0.16.1, +# 0.16.2) don't constitute a major ABI breakage. Major versions (e.g., 0.17, +# 0.18) do. +set(LIBRARY_SOVERSION 0) + +include(GNUInstallDirs) +include(CheckTypeSize) + +# +# Build +# + +add_library(mad + bit.c + decoder.c + fixed.c + frame.c + huffman.c + layer12.c + layer3.c + stream.c + synth.c + timer.c + version.c +) +target_include_directories(mad PUBLIC + $ + $ + $ +) + +if(WIN32 AND BUILD_SHARED_LIBS) + set_target_properties(mad PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) +endif() + +set_target_properties(mad PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${LIBRARY_SOVERSION} +) + +# +# Compile definitions +# + +option(OPTIMIZE "Optimize for SPEED (default) or ACCURACY" SPEED) +if(OPTIMIZE STREQUAL "SPEED") + message(STATUS "Optimizing for speed over accuracy.") + target_compile_definitions(mad PRIVATE OPT_SPEED) +else() + message(STATUS "Optimizing for accuracy over speed.") + target_compile_definitions(mad PRIVATE OPT_ACCURACY) +endif() + +option(ASO "Enable CPU Architecture Specific Optimizations (x86, ARM, and MIPS only)" ON) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "Using 64 bit fixed point math") + option(FPM_64BIT "64 bit fixed point math" ON) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86" OR "i386") + message(STATUS "Using x86 fixed point math") + option (FPM_INTEL "x86 fixed point math" ON) + if(ASO) + target_compile_definitions(mad PRIVATE ASO_ZEROCHECK) + endif() +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES ".*(arm|ARM).*") + message(STATUS "Using ARM fixed point math") + option (FPM_ARM "ARM fixed point math" ON) + if(ASO) + enable_language(ASM) + target_compile_definitions(mad PRIVATE ASO_INTERLEAVE1 ASO_IMDCT) + target_sources(mad PRIVATE imdct_l_arm.S) + endif() +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES ".*(mips|MIPS).*") + message(STATUS "Using MIPS fixed point math") + option(FPM_MIPS "MIPS fixed point math" ON) + if(ASO) + target_compile_definitions(mad PRIVATE ASO_INTERLEAVE2 ASO_ZEROCHECK) + endif() +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES ".*(sparc|SPARC).*") + message(STATUS "Using SPARC fixed point math") + option(FPM_SPARC "SPARC fixed point math" ON) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES ".(ppc|PPC|powerpc).*") + message(STATUS "Using PowerPC fixed point math") + option(FPM_PPC "PowerPC fixed point math" ON) +else() + message(WARNING "Target CPU architecture not detected. Fixed-point math will yield limited accuracy.") + option(FPM_DEFAULT "Generic fixed-point math" ON) +endif() + + +check_type_size(int SIZEOF_INT BUILTIN_TYPES_ONLY LANGUAGE C) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mad.h.in ${CMAKE_CURRENT_BINARY_DIR}/mad.h @ONLY) + +include(CheckIncludeFile) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +if(HAVE_SYS_TYPES_H) + target_compile_definitions(mad PRIVATE HAVE_SYS_TYPES_H) +endif() + +check_include_file(sys/wait.h HAVE_SYS_WAIT_H) +if(HAVE_SYS_WAIT_H) + target_compile_definitions(mad PRIVATE HAVE_SYS_WAIT_H) +endif() + +check_include_file(sys/mman.h HAVE_SYS_MMAN_H) +if(HAVE_SYS_MMAN_H) + target_compile_definitions(mad PRIVATE HAVE_SYS_MMAN_H) +endif() + +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +if(HAVE_SYS_STAT_H) + target_compile_definitions(mad PRIVATE HAVE_SYS_STAT_H) +endif() + +check_include_file(unistd.h HAVE_UNISTD_H) +if(HAVE_UNISTD_H) + target_compile_definitions(mad PRIVATE HAVE_UNISTD_H) +endif() + +check_include_file(assert.h HAVE_ASSERT_H) +if(HAVE_ASSERT_H) + target_compile_definitions(mad PRIVATE HAVE_ASSERT_H) +endif() + +check_include_file(fcntl.h HAVE_FCNTL_H) +if(HAVE_FCNTL_H) + target_compile_definitions(mad PRIVATE HAVE_FCNTL_H) +endif() + +check_include_file(limits.h HAVE_LIMITS_H) +if(HAVE_LIMITS_H) + target_compile_definitions(mad PRIVATE HAVE_LIMITS_H) +endif() + +include(CheckFunctionExists) +check_function_exists(ftruncate HAVE_FTRUNCATE) +if(HAVE_FTRUNCATE) + target_compile_definitions(mad PRIVATE HAVE_FTRUNCATE) +endif() + +check_function_exists(pipe HAVE_PIPE) +if(HAVE_PIPE) + target_compile_definitions(mad PRIVATE HAVE_PIPE) +endif() + +check_function_exists(fork HAVE_FORK) +if(HAVE_FORK) + target_compile_definitions(mad PRIVATE HAVE_FORK) +endif() + +check_function_exists(waitpid HAVE_WAITPID) +if(HAVE_WAITPID) + target_compile_definitions(mad PRIVATE HAVE_WAITPID) +endif() + +option(MADD_ASM "Enable if your MIPS CPU supports a 2-operand MADD instruction." OFF) +if(MADD_ASM) + target_compile_definitions(mad PRIVATE HAVE_MADD_ASM) +endif() + +option(MADD16_ASM "Enable if your MIPS CPU supports a 2-operand MADD16 instruction." OFF) +if(MADD16_ASM) + target_compile_definitions(mad PRIVATE HAVE_MADD_ASM) +endif() + +# +# Example application +# + +include(CMakeDependentOption) +cmake_dependent_option(EXAMPLE "Build example executable" ON "HAVE_UNISTD_H;HAVE_SYS_STAT_H;HAVE_SYS_MMAN_H" OFF) +if(EXAMPLE) + add_executable(mad_example minimad.c) + target_link_libraries(mad_example PRIVATE mad) +endif() + +# +# Installation +# + +include(CMakePackageConfigHelpers) + +# Library files +install(TARGETS mad + EXPORT madTargets + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +# Header files +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/mad.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +# pkgconfig +if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(PKGCONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}") +else() + set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") +endif() +if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") + set(PKGCONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") +else() + set(PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +endif() +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packaging/mad.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/packaging/mad.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/packaging/mad.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +# CMake config +set(MAD_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/mad") +install( + EXPORT madTargets + FILE madTargets.cmake + NAMESPACE mad:: + DESTINATION "${MAD_INSTALL_CMAKEDIR}" +) +configure_package_config_file(packaging/madConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/packaging/madConfig.cmake" + INSTALL_DESTINATION "${MAD_INSTALL_CMAKEDIR}" +) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/packaging/madConfigVersion.cmake" + VERSION "${PROJECT_VERSION}" + COMPATIBILITY SameMajorVersion +) +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/packaging/madConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/packaging/madConfigVersion.cmake" + DESTINATION "${MAD_INSTALL_CMAKEDIR}" +) diff --git a/code/libmad-0.15.1b/COPYING b/code/libmad/COPYING similarity index 100% rename from code/libmad-0.15.1b/COPYING rename to code/libmad/COPYING diff --git a/code/libmad-0.15.1b/COPYRIGHT b/code/libmad/COPYRIGHT similarity index 100% rename from code/libmad-0.15.1b/COPYRIGHT rename to code/libmad/COPYRIGHT diff --git a/code/libmad-0.15.1b/CREDITS b/code/libmad/CREDITS similarity index 100% rename from code/libmad-0.15.1b/CREDITS rename to code/libmad/CREDITS diff --git a/code/libmad-0.15.1b/D.dat b/code/libmad/D.dat similarity index 100% rename from code/libmad-0.15.1b/D.dat rename to code/libmad/D.dat diff --git a/code/libmad/README.md b/code/libmad/README.md new file mode 100644 index 00000000..fa8a2db6 --- /dev/null +++ b/code/libmad/README.md @@ -0,0 +1,178 @@ +# libmad - MPEG audio decoder library +Copyright (C) 2000-2004 Underbit Technologies, Inc. +Copyright (C) 2021-2023 Tenacity Team and Contributors + +`$Id: README,v 1.4 2004/01/23 09:41:32 rob Exp $` + +--- + +# Introduction + +MAD (libmad) is a high-quality MPEG audio decoder. It currently supports +MPEG-1 and the MPEG-2 extension to Lower Sampling Frequencies, as well as +the so-called MPEG 2.5 format. All three audio layers (Layer I, Layer II, +and Layer III a.k.a. MP3) are fully implemented. + +MAD does not yet support MPEG-2 multichannel audio (although it should be +backward compatible with such streams) nor does it currently support AAC. + +MAD has the following special features: + + - 24-bit PCM output + - 100% fixed-point (integer) computation + - completely new implementation based on the ISO/IEC standards + - distributed under the terms of the GNU General Public License (GPL) + +Because MAD provides full 24-bit PCM output, applications using MAD are +able to produce high quality audio. Even when the output device supports +only 16-bit PCM, applications can use the extra resolution to increase the +audible dynamic range through the use of dithering or noise shaping. + +Because MAD uses integer computation rather than floating point, it is +well suited for architectures without a floating point unit. All +calculations are performed with a 32-bit fixed-point integer +representation. + +Because MAD is a new implementation of the ISO/IEC standards, it is +unencumbered by the errors of other implementations. MAD is NOT a +derivation of the ISO reference source or any other code. Considerable +effort has been expended to ensure a correct implementation, even in cases +where the standards are ambiguous or misleading. + +Because MAD is distributed under the terms of the GPL, its redistribution +is not generally restricted, so long as the terms of the GPL are followed. +This means MAD can be incorporated into other software as long as that +software is also distributed under the GPL. (Should this be undesirable, +alternate arrangements may be possible by contacting Underbit.) + +# About The Code + +The code is optimized and performs very well, although specific +improvements can still be made. The output from the decoder library +consists of 32-bit signed linear fixed-point values that can be easily +scaled for any size PCM output, up to 24 bits per sample. + +The API for libmad can be found in the `mad.h' header file. Note that this +file is automatically generated, and will not exist until after you have +built the library. + +There are two APIs available, one high-level, and the other low-level. +With the low-level API, each step of the decoding process must be handled +explicitly, offering the greatest amount of control. With the high-level +API, after callbacks are configured, a single routine will decode an +entire bitstream. + +The high-level API may either be used synchronously or asynchronously. If +used asynchronously, decoding will occur in a separate process. +Communication is possible with the decoding process by passing control +messages. + +The file `minimad.c' contains an example usage of the libmad API that +shows only the bare minimum required to implement a useful decoder. It +expects a regular file to be redirected to standard input, and it sends +decoded 16-bit signed little-endian PCM samples to standard output. If a +decoding error occurs, it is reported to standard error and decoding +continues. Note that the scale() routine in this code is only provided as +an example; it rounds MAD's high-resolution samples down to 16 bits, but +does not perform any dithering or noise shaping. It is therefore not +recommended to use this routine as-is in your own code if sound quality is +important. + +## Integer Performance + +To get the best possible performance, it is recommended that an assembly +version of the fixed-point multiply and related routines be selected. +Several such assembly routines have been written for various CPUs. + +If an assembly version is not available, a fast approximation version will +be used. This will result in reduced accuracy of the decoder. + +Alternatively, if 64-bit integers are supported as a datatype by the +compiler, another version can be used that is much more accurate. +However, using an assembly version is generally much faster and just as +accurate. + +More information can be gathered from the `fixed.h' header file. + +MAD's CPU-intensive subband synthesis routine can be further optimized at +the expense of a slight loss in output accuracy due to a modified method +for fixed-point multiplication with a small windowing constant. While this +is helpful for performance and the output accuracy loss is generally +undetectable, it is disabled by default and must be explicitly enabled. + +Under some architectures, other special optimizations may also be +available. + +## Audio Quality + +The output from MAD has been found to satisfy the ISO/IEC 11172-4 +computational accuracy requirements for compliance. In most +configurations, MAD is a Full Layer III ISO/IEC 11172-3 audio decoder as +defined by the standard. + +When the approximation version of the fixed-point multiply is used, MAD is +a limited accuracy ISO/IEC 11172-3 audio decoder as defined by the +standard. + +MAD can alternatively be configured to produce output with less or more +accuracy than the default, as a tradeoff with performance. + +MAD produces output samples with a precision greater than 24 bits. Because +most output formats use fewer bits, typically 16, it is recommended that a +dithering algorithm be used (rather than rounding or truncating) to obtain +the highest quality audio. However, dithering may unfavorably affect an +analytic examination of the output (such as compliance testing); you may +therefore wish to use rounding in this case instead. + +## Portability Issues + +GCC is preferred to compile the code, but other compilers may also work. +The assembly code in `fixed.h' depends on the inline assembly features of +your compiler. If you're not using GCC or MSVC++, you can either write +your own assembly macros or use the default (low quality output) version. + +The union initialization of `huffman.c' may not be portable to all +platforms when GCC is not used. + +The code should not be sensitive to word sizes or byte ordering, however +it does assume A % B has the same sign as A. + +# Building and Installing + +libmad uses the CMake build system and has no dependencies. To build it, run: + +``` bash +cmake -D CMAKE_INSTALL_PREFIX=/where/you/want/to/install/to -S . -B build +cmake --build build --parallel number-of-cpu-cores +cmake --install build +``` + +The following CMake options are available which can be toggled by passing +'-D OPTION=VALUE' to the CMake configure step (the first call to cmake above): + + * ASO (ON|OFF): Enable CPU Architecture Specific Optimizations + (x86, ARM, and MIPS only). ON by default. + * EXAMPLE (ON|OFF): Build the example application. Only works on POSIX + operating systems. ON by default on POSIX operating systems. The example + application is not installed. + +## Supported Platforms + +libmad relies on a POSIX environment. On Windows, you should use Cygwin to +build libmad. + +It is planned that in a future release + +# Copyright + +Please read the `COPYRIGHT` file for copyright and warranty information. +Also, the file `COPYING` contains the full text of the GNU GPL. + +Send inquiries, comments, bug reports, suggestions, patches, etc. to: + + Underbit Technologies, Inc. + +See also the MAD home page on the Web: + + http://www.underbit.com/products/mad/ + diff --git a/code/libmad-0.15.1b/TODO b/code/libmad/TODO similarity index 100% rename from code/libmad-0.15.1b/TODO rename to code/libmad/TODO diff --git a/code/libmad-0.15.1b/bit.c b/code/libmad/bit.c similarity index 98% rename from code/libmad-0.15.1b/bit.c rename to code/libmad/bit.c index c2bfb243..72a094ca 100644 --- a/code/libmad-0.15.1b/bit.c +++ b/code/libmad/bit.c @@ -19,10 +19,6 @@ * $Id: bit.c,v 1.12 2004/01/23 09:41:32 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # ifdef HAVE_LIMITS_H @@ -31,7 +27,7 @@ # define CHAR_BIT 8 # endif -# include "bit.h" +# include "mad.h" /* * This is the lookup table for computing the CRC-check word. @@ -138,6 +134,9 @@ unsigned long mad_bit_read(struct mad_bitptr *bitptr, unsigned int len) { register unsigned long value; + if (len == 0) + return 0; + if (bitptr->left == CHAR_BIT) bitptr->cache = *bitptr->byte; diff --git a/code/libmad-0.15.1b/decoder.c b/code/libmad/decoder.c similarity index 78% rename from code/libmad-0.15.1b/decoder.c rename to code/libmad/decoder.c index 6d6df0db..b631a686 100644 --- a/code/libmad-0.15.1b/decoder.c +++ b/code/libmad/decoder.c @@ -19,10 +19,6 @@ * $Id: decoder.c,v 1.22 2004/01/23 09:41:32 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # ifdef HAVE_SYS_TYPES_H @@ -47,10 +43,7 @@ # include # endif -# include "stream.h" -# include "frame.h" -# include "synth.h" -# include "decoder.h" +# include "mad.h" /* * NAME: decoder->init() @@ -236,9 +229,9 @@ enum mad_flow receive(int fd, void **message, unsigned int *size) if (*size > 0) { if (*message == 0) { - *message = malloc(*size); - if (*message == 0) - return MAD_FLOW_BREAK; + *message = malloc(*size); + if (*message == 0) + return MAD_FLOW_BREAK; } result = receive_io_blocking(fd, *message, *size); @@ -277,8 +270,8 @@ enum mad_flow check_message(struct mad_decoder *decoder) result = decoder->message_func(decoder->cb_data, message, &size); if (result == MAD_FLOW_IGNORE || - result == MAD_FLOW_BREAK) - size = 0; + result == MAD_FLOW_BREAK) + size = 0; } if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE) @@ -347,114 +340,128 @@ int run_sync(struct mad_decoder *decoder) do { switch (decoder->input_func(decoder->cb_data, stream)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - continue; - case MAD_FLOW_CONTINUE: - break; + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; } - while (1) { -# if defined(USE_ASYNC) + while (1) + { + #if defined(USE_ASYNC) if (decoder->mode == MAD_DECODER_MODE_ASYNC) { - switch (check_message(decoder)) { - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - break; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_STOP: - goto done; - } + switch (check_message(decoder)) { + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + break; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_STOP: + goto done; + } } -# endif + #endif - if (decoder->header_func) { - if (mad_header_decode(&frame->header, stream) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - break; + if (decoder->header_func) + { + if (mad_header_decode(&frame->header, stream) == -1) + { + if (!MAD_RECOVERABLE(stream->error)) + { + break; + } - switch (error_func(error_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - default: - continue; - } - } + switch (error_func(error_data, stream, frame)) + { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + default: + continue; + } + } - switch (decoder->header_func(decoder->cb_data, &frame->header)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - continue; - case MAD_FLOW_CONTINUE: - break; - } + switch (decoder->header_func(decoder->cb_data, &frame->header)) + { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } } - if (mad_frame_decode(frame, stream) == -1) { - if (!MAD_RECOVERABLE(stream->error)) - break; + if (mad_frame_decode(frame, stream) == -1) + { + if (!MAD_RECOVERABLE(stream->error)) + break; - switch (error_func(error_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - break; - case MAD_FLOW_CONTINUE: - default: - continue; - } + switch (error_func(error_data, stream, frame)) + { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + break; + case MAD_FLOW_CONTINUE: + default: + continue; + } + } else + { + bad_last_frame = 0; } - else - bad_last_frame = 0; - if (decoder->filter_func) { - switch (decoder->filter_func(decoder->cb_data, stream, frame)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - continue; - case MAD_FLOW_CONTINUE: - break; - } + if (decoder->filter_func) + { + switch (decoder->filter_func(decoder->cb_data, stream, frame)) + { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } } mad_synth_frame(synth, frame); - if (decoder->output_func) { - switch (decoder->output_func(decoder->cb_data, - &frame->header, &synth->pcm)) { - case MAD_FLOW_STOP: - goto done; - case MAD_FLOW_BREAK: - goto fail; - case MAD_FLOW_IGNORE: - case MAD_FLOW_CONTINUE: - break; - } + if (decoder->output_func) + { + switch (decoder->output_func(decoder->cb_data, + &frame->header, &synth->pcm)) + { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + break; + } } } } while (stream->error == MAD_ERROR_BUFLEN); - fail: +fail: result = -1; - done: +done: mad_synth_finish(synth); mad_frame_finish(frame); mad_stream_finish(stream); diff --git a/code/libmad-0.15.1b/fixed.c b/code/libmad/fixed.c similarity index 95% rename from code/libmad-0.15.1b/fixed.c rename to code/libmad/fixed.c index 9785466f..3e4055f8 100644 --- a/code/libmad-0.15.1b/fixed.c +++ b/code/libmad/fixed.c @@ -19,13 +19,9 @@ * $Id: fixed.c,v 1.13 2004/01/23 09:41:32 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" -# include "fixed.h" +# include "mad.h" /* * NAME: fixed->abs() diff --git a/code/libmad-0.15.1b/frame.c b/code/libmad/frame.c similarity index 95% rename from code/libmad-0.15.1b/frame.c rename to code/libmad/frame.c index 0cb3d0f3..03c94bfe 100644 --- a/code/libmad-0.15.1b/frame.c +++ b/code/libmad/frame.c @@ -19,18 +19,11 @@ * $Id: frame.c,v 1.29 2004/02/04 22:59:19 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # include -# include "bit.h" -# include "stream.h" -# include "frame.h" -# include "timer.h" +# include "mad.h" # include "layer12.h" # include "layer3.h" @@ -120,11 +113,18 @@ static int decode_header(struct mad_header *header, struct mad_stream *stream) { unsigned int index; + struct mad_bitptr bufend_ptr; header->flags = 0; header->private_bits = 0; + mad_bit_init(&bufend_ptr, stream->bufend); + /* header() */ + if (mad_bit_length(&stream->ptr, &bufend_ptr) < 32) { + stream->error = MAD_ERROR_BUFLEN; + return -1; + } /* syncword */ mad_bit_skip(&stream->ptr, 11); @@ -225,8 +225,13 @@ int decode_header(struct mad_header *header, struct mad_stream *stream) /* error_check() */ /* crc_check */ - if (header->flags & MAD_FLAG_PROTECTION) + if (header->flags & MAD_FLAG_PROTECTION) { + if (mad_bit_length(&stream->ptr, &bufend_ptr) < 16) { + stream->error = MAD_ERROR_BUFLEN; + return -1; + } header->crc_target = mad_bit_read(&stream->ptr, 16); + } return 0; } @@ -338,7 +343,7 @@ int mad_header_decode(struct mad_header *header, struct mad_stream *stream) stream->error = MAD_ERROR_BUFLEN; goto fail; } - else if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { + else if ((end - ptr >= 2) && !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { /* mark point where frame sync word was expected */ stream->this_frame = ptr; stream->next_frame = ptr + 1; @@ -361,6 +366,8 @@ int mad_header_decode(struct mad_header *header, struct mad_stream *stream) ptr = mad_bit_nextbyte(&stream->ptr); } + stream->error = MAD_ERROR_NONE; + /* begin processing */ stream->this_frame = ptr; stream->next_frame = ptr + 1; /* possibly bogus sync word */ @@ -413,7 +420,7 @@ int mad_header_decode(struct mad_header *header, struct mad_stream *stream) /* check that a valid frame header follows this frame */ ptr = stream->next_frame; - if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { + if ((end - ptr >= 2) && !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { ptr = stream->next_frame = stream->this_frame + 1; goto sync; } diff --git a/code/libmad-0.15.1b/global.h b/code/libmad/global.h similarity index 100% rename from code/libmad-0.15.1b/global.h rename to code/libmad/global.h diff --git a/code/libmad-0.15.1b/huffman.c b/code/libmad/huffman.c similarity index 99% rename from code/libmad-0.15.1b/huffman.c rename to code/libmad/huffman.c index a230a9c1..9050c700 100644 --- a/code/libmad-0.15.1b/huffman.c +++ b/code/libmad/huffman.c @@ -19,10 +19,6 @@ * $Id: huffman.c,v 1.10 2004/01/23 09:41:32 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # include "huffman.h" diff --git a/code/libmad-0.15.1b/huffman.h b/code/libmad/huffman.h similarity index 100% rename from code/libmad-0.15.1b/huffman.h rename to code/libmad/huffman.h diff --git a/code/libmad-0.15.1b/imdct_l_arm.S b/code/libmad/imdct_l_arm.S similarity index 99% rename from code/libmad-0.15.1b/imdct_l_arm.S rename to code/libmad/imdct_l_arm.S index badec5bc..92d67e1a 100644 --- a/code/libmad-0.15.1b/imdct_l_arm.S +++ b/code/libmad/imdct_l_arm.S @@ -468,7 +468,7 @@ _III_imdct_l: @---- - add r2, pc, #(imdct36_long_karray-.-8) @ r2 = base address of Knn array (PIC safe ?) + adr r2, imdct36_long_karray loop: diff --git a/code/libmad-0.15.1b/imdct_s.dat b/code/libmad/imdct_s.dat similarity index 100% rename from code/libmad-0.15.1b/imdct_s.dat rename to code/libmad/imdct_s.dat diff --git a/code/libmad-0.15.1b/layer12.c b/code/libmad/layer12.c similarity index 81% rename from code/libmad-0.15.1b/layer12.c rename to code/libmad/layer12.c index 6981f9ce..a334a27e 100644 --- a/code/libmad-0.15.1b/layer12.c +++ b/code/libmad/layer12.c @@ -19,10 +19,6 @@ * $Id: layer12.c,v 1.17 2004/02/05 09:02:39 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # ifdef HAVE_LIMITS_H @@ -31,10 +27,7 @@ # define CHAR_BIT 8 # endif -# include "fixed.h" -# include "bit.h" -# include "stream.h" -# include "frame.h" +# include "mad.h" # include "layer12.h" /* @@ -72,10 +65,18 @@ mad_fixed_t const linear_table[14] = { * DESCRIPTION: decode one requantized Layer I sample from a bitstream */ static -mad_fixed_t I_sample(struct mad_bitptr *ptr, unsigned int nb) +mad_fixed_t I_sample(struct mad_bitptr *ptr, unsigned int nb, struct mad_stream *stream) { mad_fixed_t sample; + struct mad_bitptr frameend_ptr; + mad_bit_init(&frameend_ptr, stream->next_frame); + + if (mad_bit_length(ptr, &frameend_ptr) < nb) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return 0; + } sample = mad_bit_read(ptr, nb); /* invert most significant bit, extend sign, then scale to fixed format */ @@ -106,6 +107,10 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) struct mad_header *header = &frame->header; unsigned int nch, bound, ch, s, sb, nb; unsigned char allocation[2][32], scalefactor[2][32]; + struct mad_bitptr bufend_ptr, frameend_ptr; + + mad_bit_init(&bufend_ptr, stream->bufend); + mad_bit_init(&frameend_ptr, stream->next_frame); nch = MAD_NCHANNELS(header); @@ -118,6 +123,11 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) /* check CRC word */ if (header->flags & MAD_FLAG_PROTECTION) { + if (mad_bit_length(&stream->ptr, &bufend_ptr) + < 4 * (bound * nch + (32 - bound))) { + stream->error = MAD_ERROR_BADCRC; + return -1; + } header->crc_check = mad_bit_crc(stream->ptr, 4 * (bound * nch + (32 - bound)), header->crc_check); @@ -133,6 +143,11 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) for (sb = 0; sb < bound; ++sb) { for (ch = 0; ch < nch; ++ch) { + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 4) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } nb = mad_bit_read(&stream->ptr, 4); if (nb == 15) { @@ -145,6 +160,11 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) } for (sb = bound; sb < 32; ++sb) { + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 4) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } nb = mad_bit_read(&stream->ptr, 4); if (nb == 15) { @@ -161,6 +181,11 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) for (sb = 0; sb < 32; ++sb) { for (ch = 0; ch < nch; ++ch) { if (allocation[ch][sb]) { + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 6) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } scalefactor[ch][sb] = mad_bit_read(&stream->ptr, 6); # if defined(OPT_STRICT) @@ -185,8 +210,10 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) for (ch = 0; ch < nch; ++ch) { nb = allocation[ch][sb]; frame->sbsample[ch][s][sb] = nb ? - mad_f_mul(I_sample(&stream->ptr, nb), + mad_f_mul(I_sample(&stream->ptr, nb, stream), sf_table[scalefactor[ch][sb]]) : 0; + if (stream->error != 0) + return -1; } } @@ -194,7 +221,14 @@ int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) if ((nb = allocation[0][sb])) { mad_fixed_t sample; - sample = I_sample(&stream->ptr, nb); + if (mad_bit_length(&stream->ptr, &frameend_ptr) < nb) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } + sample = I_sample(&stream->ptr, nb, stream); + if (stream->error != 0) + return -1; for (ch = 0; ch < nch; ++ch) { frame->sbsample[ch][s][sb] = @@ -280,13 +314,21 @@ struct quantclass { static void II_samples(struct mad_bitptr *ptr, struct quantclass const *quantclass, - mad_fixed_t output[3]) + mad_fixed_t output[3], struct mad_stream *stream) { unsigned int nb, s, sample[3]; + struct mad_bitptr frameend_ptr; + + mad_bit_init(&frameend_ptr, stream->next_frame); if ((nb = quantclass->group)) { unsigned int c, nlevels; + if (mad_bit_length(ptr, &frameend_ptr) < quantclass->bits) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return; + } /* degrouping */ c = mad_bit_read(ptr, quantclass->bits); nlevels = quantclass->nlevels; @@ -299,8 +341,14 @@ void II_samples(struct mad_bitptr *ptr, else { nb = quantclass->bits; - for (s = 0; s < 3; ++s) + for (s = 0; s < 3; ++s) { + if (mad_bit_length(ptr, &frameend_ptr) < nb) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return; + } sample[s] = mad_bit_read(ptr, nb); + } } for (s = 0; s < 3; ++s) { @@ -336,6 +384,9 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) unsigned char const *offsets; unsigned char allocation[2][32], scfsi[2][32], scalefactor[2][32][3]; mad_fixed_t samples[3]; + struct mad_bitptr frameend_ptr; + + mad_bit_init(&frameend_ptr, stream->next_frame); nch = MAD_NCHANNELS(header); @@ -402,13 +453,24 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) for (sb = 0; sb < bound; ++sb) { nbal = bitalloc_table[offsets[sb]].nbal; - for (ch = 0; ch < nch; ++ch) + for (ch = 0; ch < nch; ++ch) { + if (mad_bit_length(&stream->ptr, &frameend_ptr) < nbal) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } allocation[ch][sb] = mad_bit_read(&stream->ptr, nbal); + } } for (sb = bound; sb < sblimit; ++sb) { nbal = bitalloc_table[offsets[sb]].nbal; + if (mad_bit_length(&stream->ptr, &frameend_ptr) < nbal) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } allocation[0][sb] = allocation[1][sb] = mad_bit_read(&stream->ptr, nbal); } @@ -417,8 +479,14 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) for (sb = 0; sb < sblimit; ++sb) { for (ch = 0; ch < nch; ++ch) { - if (allocation[ch][sb]) + if (allocation[ch][sb]) { + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 2) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } scfsi[ch][sb] = mad_bit_read(&stream->ptr, 2); + } } } @@ -441,6 +509,11 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) for (sb = 0; sb < sblimit; ++sb) { for (ch = 0; ch < nch; ++ch) { if (allocation[ch][sb]) { + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 6) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } scalefactor[ch][sb][0] = mad_bit_read(&stream->ptr, 6); switch (scfsi[ch][sb]) { @@ -451,11 +524,21 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) break; case 0: + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 6) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } scalefactor[ch][sb][1] = mad_bit_read(&stream->ptr, 6); /* fall through */ case 1: case 3: + if (mad_bit_length(&stream->ptr, &frameend_ptr) < 6) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } scalefactor[ch][sb][2] = mad_bit_read(&stream->ptr, 6); } @@ -487,7 +570,9 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) if ((index = allocation[ch][sb])) { index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; - II_samples(&stream->ptr, &qc_table[index], samples); + II_samples(&stream->ptr, &qc_table[index], samples, stream); + if (stream->error != 0) + return -1; for (s = 0; s < 3; ++s) { frame->sbsample[ch][3 * gr + s][sb] = @@ -505,7 +590,9 @@ int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) if ((index = allocation[0][sb])) { index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; - II_samples(&stream->ptr, &qc_table[index], samples); + II_samples(&stream->ptr, &qc_table[index], samples, stream); + if (stream->error != 0) + return -1; for (ch = 0; ch < nch; ++ch) { for (s = 0; s < 3; ++s) { diff --git a/code/libmad-0.15.1b/layer12.h b/code/libmad/layer12.h similarity index 96% rename from code/libmad-0.15.1b/layer12.h rename to code/libmad/layer12.h index e1c49969..8caa3f75 100644 --- a/code/libmad-0.15.1b/layer12.h +++ b/code/libmad/layer12.h @@ -22,8 +22,7 @@ # ifndef LIBMAD_LAYER12_H # define LIBMAD_LAYER12_H -# include "stream.h" -# include "frame.h" +# include "mad.h" int mad_layer_I(struct mad_stream *, struct mad_frame *); int mad_layer_II(struct mad_stream *, struct mad_frame *); diff --git a/code/libmad-0.15.1b/layer3.c b/code/libmad/layer3.c similarity index 93% rename from code/libmad-0.15.1b/layer3.c rename to code/libmad/layer3.c index 4e5d3fa0..7f18fd72 100644 --- a/code/libmad-0.15.1b/layer3.c +++ b/code/libmad/layer3.c @@ -19,10 +19,6 @@ * $Id: layer3.c,v 1.43 2004/01/23 09:41:32 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # include @@ -38,10 +34,7 @@ # define CHAR_BIT 8 # endif -# include "fixed.h" -# include "bit.h" -# include "stream.h" -# include "frame.h" +# include "mad.h" # include "huffman.h" # include "layer3.h" @@ -598,7 +591,8 @@ enum mad_error III_sideinfo(struct mad_bitptr *ptr, unsigned int nch, static unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, struct channel *channel, - struct channel *gr1ch, int mode_extension) + struct channel *gr1ch, int mode_extension, + unsigned int bits_left, unsigned int *part2_length) { struct mad_bitptr start; unsigned int scalefac_compress, index, slen[4], part, n, i; @@ -644,8 +638,12 @@ unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, n = 0; for (part = 0; part < 4; ++part) { - for (i = 0; i < nsfb[part]; ++i) + for (i = 0; i < nsfb[part]; ++i) { + if (bits_left < slen[part]) + return MAD_ERROR_BADSCFSI; channel->scalefac[n++] = mad_bit_read(ptr, slen[part]); + bits_left -= slen[part]; + } } while (n < 39) @@ -690,7 +688,10 @@ unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, max = (1 << slen[part]) - 1; for (i = 0; i < nsfb[part]; ++i) { + if (bits_left < slen[part]) + return MAD_ERROR_BADSCFSI; is_pos = mad_bit_read(ptr, slen[part]); + bits_left -= slen[part]; channel->scalefac[n] = is_pos; gr1ch->scalefac[n++] = (is_pos == max); @@ -703,7 +704,8 @@ unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, } } - return mad_bit_length(&start, ptr); + *part2_length = mad_bit_length(&start, ptr); + return MAD_ERROR_NONE; } /* @@ -712,7 +714,8 @@ unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, */ static unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, - struct channel const *gr0ch, unsigned int scfsi) + struct channel const *gr0ch, unsigned int scfsi, + unsigned int bits_left, unsigned int *part2_length) { struct mad_bitptr start; unsigned int slen1, slen2, sfbi; @@ -728,12 +731,20 @@ unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, sfbi = 0; nsfb = (channel->flags & mixed_block_flag) ? 8 + 3 * 3 : 6 * 3; - while (nsfb--) + while (nsfb--) { + if (bits_left < slen1) + return MAD_ERROR_BADSCFSI; channel->scalefac[sfbi++] = mad_bit_read(ptr, slen1); + bits_left -= slen1; + } nsfb = 6 * 3; - while (nsfb--) + while (nsfb--) { + if (bits_left < slen2) + return MAD_ERROR_BADSCFSI; channel->scalefac[sfbi++] = mad_bit_read(ptr, slen2); + bits_left -= slen2; + } nsfb = 1 * 3; while (nsfb--) @@ -745,8 +756,12 @@ unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; } else { - for (sfbi = 0; sfbi < 6; ++sfbi) + for (sfbi = 0; sfbi < 6; ++sfbi) { + if (bits_left < slen1) + return MAD_ERROR_BADSCFSI; channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); + bits_left -= slen1; + } } if (scfsi & 0x4) { @@ -754,8 +769,12 @@ unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; } else { - for (sfbi = 6; sfbi < 11; ++sfbi) + for (sfbi = 6; sfbi < 11; ++sfbi) { + if (bits_left < slen1) + return MAD_ERROR_BADSCFSI; channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); + bits_left -= slen1; + } } if (scfsi & 0x2) { @@ -763,8 +782,12 @@ unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; } else { - for (sfbi = 11; sfbi < 16; ++sfbi) + for (sfbi = 11; sfbi < 16; ++sfbi) { + if (bits_left < slen2) + return MAD_ERROR_BADSCFSI; channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); + bits_left -= slen2; + } } if (scfsi & 0x1) { @@ -772,14 +795,19 @@ unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; } else { - for (sfbi = 16; sfbi < 21; ++sfbi) + for (sfbi = 16; sfbi < 21; ++sfbi) { + if (bits_left < slen2) + return MAD_ERROR_BADSCFSI; channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); + bits_left -= slen2; + } } channel->scalefac[21] = 0; } - return mad_bit_length(&start, ptr); + *part2_length = mad_bit_length(&start, ptr); + return MAD_ERROR_NONE; } /* @@ -933,19 +961,17 @@ static enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], struct channel *channel, unsigned char const *sfbwidth, - unsigned int part2_length) + signed int part3_length) { signed int exponents[39], exp; signed int const *expptr; struct mad_bitptr peek; - signed int bits_left, cachesz; + signed int bits_left, cachesz, fakebits; register mad_fixed_t *xrptr; mad_fixed_t const *sfbound; register unsigned long bitcache; - bits_left = (signed) channel->part2_3_length - (signed) part2_length; - if (bits_left < 0) - return MAD_ERROR_BADPART3LEN; + bits_left = part3_length; III_exponents(channel, sfbwidth, exponents); @@ -956,8 +982,12 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], cachesz = mad_bit_bitsleft(&peek); cachesz += ((32 - 1 - 24) + (24 - cachesz)) & ~7; + if (bits_left < cachesz) { + cachesz = bits_left; + } bitcache = mad_bit_read(&peek, cachesz); bits_left -= cachesz; + fakebits = 0; xrptr = &xr[0]; @@ -986,7 +1016,7 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], big_values = channel->big_values; - while (big_values-- && cachesz + bits_left > 0) { + while (big_values-- && cachesz + bits_left - fakebits > 0) { union huffpair const *pair; unsigned int clumpsz, value; register mad_fixed_t requantized; @@ -1023,10 +1053,19 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], unsigned int bits; bits = ((32 - 1 - 21) + (21 - cachesz)) & ~7; + if (bits_left < bits) { + bits = bits_left; + } bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); cachesz += bits; bits_left -= bits; } + if (cachesz < 21) { + unsigned int bits = 21 - cachesz; + bitcache <<= bits; + cachesz += bits; + fakebits += bits; + } /* hcod (0..19) */ @@ -1041,6 +1080,8 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], } cachesz -= pair->value.hlen; + if (cachesz < fakebits) + return MAD_ERROR_BADHUFFDATA; if (linbits) { /* x (0..14) */ @@ -1054,10 +1095,15 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], case 15: if (cachesz < linbits + 2) { - bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); - cachesz += 16; - bits_left -= 16; + unsigned int bits = 16; + if (bits_left < 16) + bits = bits_left; + bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); + cachesz += bits; + bits_left -= bits; } + if (cachesz - fakebits < linbits) + return MAD_ERROR_BADHUFFDATA; value += MASK(bitcache, cachesz, linbits); cachesz -= linbits; @@ -1074,6 +1120,8 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], } x_final: + if (cachesz - fakebits < 1) + return MAD_ERROR_BADHUFFDATA; xrptr[0] = MASK1BIT(bitcache, cachesz--) ? -requantized : requantized; } @@ -1089,10 +1137,15 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], case 15: if (cachesz < linbits + 1) { - bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); - cachesz += 16; - bits_left -= 16; + unsigned int bits = 16; + if (bits_left < 16) + bits = bits_left; + bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); + cachesz += bits; + bits_left -= bits; } + if (cachesz - fakebits < linbits) + return MAD_ERROR_BADHUFFDATA; value += MASK(bitcache, cachesz, linbits); cachesz -= linbits; @@ -1109,6 +1162,8 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], } y_final: + if (cachesz - fakebits < 1) + return MAD_ERROR_BADHUFFDATA; xrptr[1] = MASK1BIT(bitcache, cachesz--) ? -requantized : requantized; } @@ -1128,6 +1183,8 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], requantized = reqcache[value] = III_requantize(value, exp); } + if (cachesz - fakebits < 1) + return MAD_ERROR_BADHUFFDATA; xrptr[0] = MASK1BIT(bitcache, cachesz--) ? -requantized : requantized; } @@ -1146,6 +1203,8 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], requantized = reqcache[value] = III_requantize(value, exp); } + if (cachesz - fakebits < 1) + return MAD_ERROR_BADHUFFDATA; xrptr[1] = MASK1BIT(bitcache, cachesz--) ? -requantized : requantized; } @@ -1155,9 +1214,6 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], } } - if (cachesz + bits_left < 0) - return MAD_ERROR_BADHUFFDATA; /* big_values overrun */ - /* count1 */ { union huffquad const *table; @@ -1167,15 +1223,24 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], requantized = III_requantize(1, exp); - while (cachesz + bits_left > 0 && xrptr <= &xr[572]) { + while (cachesz + bits_left - fakebits > 0 && xrptr <= &xr[572]) { union huffquad const *quad; /* hcod (1..6) */ if (cachesz < 10) { - bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); - cachesz += 16; - bits_left -= 16; + unsigned int bits = 16; + if (bits_left < 16) + bits = bits_left; + bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); + cachesz += bits; + bits_left -= bits; + } + if (cachesz < 10) { + unsigned int bits = 10 - cachesz; + bitcache <<= bits; + cachesz += bits; + fakebits += bits; } quad = &table[MASK(bitcache, cachesz, 4)]; @@ -1188,6 +1253,11 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], MASK(bitcache, cachesz, quad->ptr.bits)]; } + if (cachesz - fakebits < quad->value.hlen + quad->value.v + + quad->value.w + quad->value.x + quad->value.y) + /* We don't have enough bits to read one more entry, consider them + * stuffing bits. */ + break; cachesz -= quad->value.hlen; if (xrptr == sfbound) { @@ -1236,22 +1306,8 @@ enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], xrptr += 2; } - - if (cachesz + bits_left < 0) { -# if 0 && defined(DEBUG) - fprintf(stderr, "huffman count1 overrun (%d bits)\n", - -(cachesz + bits_left)); -# endif - - /* technically the bitstream is misformatted, but apparently - some encoders are just a bit sloppy with stuffing bits */ - - xrptr -= 4; - } } - assert(-bits_left <= MAD_BUFFER_GUARD * CHAR_BIT); - # if 0 && defined(DEBUG) if (bits_left < 0) fprintf(stderr, "read %d bits too many\n", -bits_left); @@ -2348,10 +2404,11 @@ void III_freqinver(mad_fixed_t sample[18][32], unsigned int sb) */ static enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame, - struct sideinfo *si, unsigned int nch) + struct sideinfo *si, unsigned int nch, unsigned int md_len) { struct mad_header *header = &frame->header; unsigned int sfreqi, ngr, gr; + int bits_left = md_len * CHAR_BIT; { unsigned int sfreq; @@ -2383,6 +2440,7 @@ enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame, for (ch = 0; ch < nch; ++ch) { struct channel *channel = &granule->ch[ch]; unsigned int part2_length; + unsigned int part3_length; sfbwidth[ch] = sfbwidth_table[sfreqi].l; if (channel->block_type == 2) { @@ -2391,18 +2449,30 @@ enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame, } if (header->flags & MAD_FLAG_LSF_EXT) { - part2_length = III_scalefactors_lsf(ptr, channel, + error = III_scalefactors_lsf(ptr, channel, ch == 0 ? 0 : &si->gr[1].ch[1], - header->mode_extension); + header->mode_extension, bits_left, &part2_length); } else { - part2_length = III_scalefactors(ptr, channel, &si->gr[0].ch[ch], - gr == 0 ? 0 : si->scfsi[ch]); + error = III_scalefactors(ptr, channel, &si->gr[0].ch[ch], + gr == 0 ? 0 : si->scfsi[ch], bits_left, &part2_length); } + if (error) + return error; - error = III_huffdecode(ptr, xr[ch], channel, sfbwidth[ch], part2_length); + bits_left -= part2_length; + + if (part2_length > channel->part2_3_length) + return MAD_ERROR_BADPART3LEN; + + part3_length = channel->part2_3_length - part2_length; + if (part3_length > bits_left) + return MAD_ERROR_BADPART3LEN; + + error = III_huffdecode(ptr, xr[ch], channel, sfbwidth[ch], part3_length); if (error) return error; + bits_left -= part3_length; } /* joint stereo processing */ @@ -2519,11 +2589,13 @@ int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) unsigned int nch, priv_bitlen, next_md_begin = 0; unsigned int si_len, data_bitlen, md_len; unsigned int frame_space, frame_used, frame_free; - struct mad_bitptr ptr; + struct mad_bitptr ptr, bufend_ptr; struct sideinfo si; enum mad_error error; int result = 0; + mad_bit_init(&bufend_ptr, stream->bufend); + /* allocate Layer III dynamic structures */ if (stream->main_data == 0) { @@ -2587,14 +2659,15 @@ int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) unsigned long header; mad_bit_init(&peek, stream->next_frame); + if (mad_bit_length(&peek, &bufend_ptr) >= 57) { + header = mad_bit_read(&peek, 32); + if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) { + if (!(header & 0x00010000L)) /* protection_bit */ + mad_bit_skip(&peek, 16); /* crc_check */ - header = mad_bit_read(&peek, 32); - if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) { - if (!(header & 0x00010000L)) /* protection_bit */ - mad_bit_skip(&peek, 16); /* crc_check */ - - next_md_begin = - mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8); + next_md_begin = + mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8); + } } mad_bit_finish(&peek); @@ -2608,6 +2681,11 @@ int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) next_md_begin = 0; md_len = si.main_data_begin + frame_space - next_md_begin; + if (md_len + MAD_BUFFER_GUARD > MAD_BUFFER_MDLEN) { + stream->error = MAD_ERROR_LOSTSYNC; + stream->sync = 0; + return -1; + } frame_used = 0; @@ -2625,8 +2703,11 @@ int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) } } else { - mad_bit_init(&ptr, - *stream->main_data + stream->md_len - si.main_data_begin); + memmove(stream->main_data, + *stream->main_data + stream->md_len - si.main_data_begin, + si.main_data_begin); + stream->md_len = si.main_data_begin; + mad_bit_init(&ptr, *stream->main_data); if (md_len > si.main_data_begin) { assert(stream->md_len + md_len - @@ -2645,7 +2726,7 @@ int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) /* decode main_data */ if (result == 0) { - error = III_decode(&ptr, frame, &si, nch); + error = III_decode(&ptr, frame, &si, nch, md_len); if (error) { stream->error = error; result = -1; diff --git a/code/libmad-0.15.1b/layer3.h b/code/libmad/layer3.h similarity index 96% rename from code/libmad-0.15.1b/layer3.h rename to code/libmad/layer3.h index 2504d461..618951b0 100644 --- a/code/libmad-0.15.1b/layer3.h +++ b/code/libmad/layer3.h @@ -22,8 +22,7 @@ # ifndef LIBMAD_LAYER3_H # define LIBMAD_LAYER3_H -# include "stream.h" -# include "frame.h" +# include "mad.h" int mad_layer_III(struct mad_stream *, struct mad_frame *); diff --git a/code/libmad-0.15.1b/mad.h b/code/libmad/mad.h.in similarity index 95% rename from code/libmad-0.15.1b/mad.h rename to code/libmad/mad.h.in index 9ef6cc8f..0e790d3e 100644 --- a/code/libmad-0.15.1b/mad.h +++ b/code/libmad/mad.h.in @@ -24,24 +24,25 @@ extern "C" { # endif -# define FPM_INTEL - - - -# define SIZEOF_INT 4 -# define SIZEOF_LONG 4 -# define SIZEOF_LONG_LONG 8 +#cmakedefine FPM_INTEL +#cmakedefine FPM_ARM +#cmakedefine FPM_MIPS +#cmakedefine FPM_SPARC +#cmakedefine FPM_PPC +#cmakedefine FPM_64BIT +#cmakedefine FPM_DEFAULT +# define SIZEOF_INT @SIZEOF_INT@ /* Id: version.h,v 1.26 2004/01/23 09:41:33 rob Exp */ # ifndef LIBMAD_VERSION_H # define LIBMAD_VERSION_H -# define MAD_VERSION_MAJOR 0 -# define MAD_VERSION_MINOR 15 -# define MAD_VERSION_PATCH 1 -# define MAD_VERSION_EXTRA " (beta)" +# define MAD_VERSION_MAJOR @CMAKE_PROJECT_VERSION_MAJOR@ +# define MAD_VERSION_MINOR @CMAKE_PROJECT_VERSION_MINOR@ +# define MAD_VERSION_PATCH @CMAKE_PROJECT_VERSION_PATCH@ +# define MAD_VERSION_EXTRA "" # define MAD_VERSION_STRINGIZE(str) #str # define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) @@ -67,23 +68,19 @@ extern char const mad_build[]; # ifndef LIBMAD_FIXED_H # define LIBMAD_FIXED_H +# include + # if SIZEOF_INT >= 4 typedef signed int mad_fixed_t; - typedef signed int mad_fixed64hi_t; typedef unsigned int mad_fixed64lo_t; # else typedef signed long mad_fixed_t; - typedef signed long mad_fixed64hi_t; typedef unsigned long mad_fixed64lo_t; # endif -# if defined(_MSC_VER) -# define mad_fixed64_t signed __int64 -# elif 1 || defined(__GNUC__) -# define mad_fixed64_t signed long long -# endif +typedef int64_t mad_fixed64_t; # if defined(FPM_FLOAT) typedef double mad_sample_t; @@ -320,12 +317,25 @@ mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) : "+r" (lo), "+r" (hi) \ : "%r" (x), "r" (y)) +#ifdef __thumb__ +/* In Thumb-2, the RSB-immediate instruction is only allowed with a zero + operand. If needed this code can also support Thumb-1 + (simply append "s" to the end of the second two instructions). */ +# define MAD_F_MLN(hi, lo) \ + asm ("rsbs %0, %0, #0\n\t" \ + "sbc %1, %1, %1\n\t" \ + "sub %1, %1, %2" \ + : "+&r" (lo), "=&r" (hi) \ + : "r" (hi) \ + : "cc") +#else /* ! __thumb__ */ # define MAD_F_MLN(hi, lo) \ asm ("rsbs %0, %2, #0\n\t" \ "rsc %1, %3, #0" \ - : "=r" (lo), "=r" (hi) \ + : "=&r" (lo), "=r" (hi) \ : "0" (lo), "1" (hi) \ : "cc") +#endif /* __thumb__ */ # define mad_f_scale64(hi, lo) \ ({ mad_fixed_t __result; \ @@ -348,31 +358,13 @@ mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) * This MIPS version is fast and accurate; the disposition of the least * significant bit depends on OPT_ACCURACY via mad_f_scale64(). */ -# define MAD_F_MLX(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" (x), "r" (y)) - -# if defined(HAVE_MADD_ASM) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" (x), "r" (y)) -# elif defined(HAVE_MADD16_ASM) -/* - * This loses significant accuracy due to the 16-bit integer limit in the - * multiply/accumulate instruction. - */ -# define MAD_F_ML0(hi, lo, x, y) \ - asm ("mult %2,%3" \ - : "=l" (lo), "=h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLA(hi, lo, x, y) \ - asm ("madd16 %2,%3" \ - : "+l" (lo), "+h" (hi) \ - : "%r" ((x) >> 12), "r" ((y) >> 16)) -# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) -# endif + typedef unsigned int u64_di_t __attribute__ ((mode (DI))); +# define MAD_F_MLX(hi, lo, x, y) \ + do { \ + u64_di_t __ll = (u64_di_t) (x) * (y); \ + hi = __ll >> 32; \ + lo = __ll; \ + } while (0) # if defined(OPT_SPEED) # define mad_f_scale64(hi, lo) \ @@ -424,8 +416,8 @@ mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) asm ("addc %0,%2,%3\n\t" \ "adde %1,%4,%5" \ : "=r" (lo), "=r" (hi) \ - : "%r" (lo), "r" (__lo), \ - "%r" (hi), "r" (__hi) \ + : "0" (lo), "r" (__lo), \ + "1" (hi), "r" (__hi) \ : "xer"); \ }) # endif diff --git a/code/libmad-0.15.1b/minimad.c b/code/libmad/minimad.c similarity index 100% rename from code/libmad-0.15.1b/minimad.c rename to code/libmad/minimad.c diff --git a/code/libmad/packaging/mad.pc.in b/code/libmad/packaging/mad.pc.in new file mode 100644 index 00000000..7cb5dbb1 --- /dev/null +++ b/code/libmad/packaging/mad.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +includedir=@PKGCONFIG_INCLUDEDIR@ +libdir=@PKGCONFIG_LIBDIR@ + +Name: MAD +Description: MPEG audio decoder library +Version: @CMAKE_PROJECT_VERSION@ +URL: https://codeberg.org/tenacityteam/libmad +Libs: -L${libdir} -lmad +Cflags: -I${includedir} diff --git a/code/libmad/packaging/madConfig.cmake.in b/code/libmad/packaging/madConfig.cmake.in new file mode 100644 index 00000000..2b2e2ce0 --- /dev/null +++ b/code/libmad/packaging/madConfig.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/madTargets.cmake") + +check_required_components(mad) diff --git a/code/libmad-0.15.1b/qc_table.dat b/code/libmad/qc_table.dat similarity index 100% rename from code/libmad-0.15.1b/qc_table.dat rename to code/libmad/qc_table.dat diff --git a/code/libmad-0.15.1b/rq_table.dat b/code/libmad/rq_table.dat similarity index 100% rename from code/libmad-0.15.1b/rq_table.dat rename to code/libmad/rq_table.dat diff --git a/code/libmad-0.15.1b/sf_table.dat b/code/libmad/sf_table.dat similarity index 100% rename from code/libmad-0.15.1b/sf_table.dat rename to code/libmad/sf_table.dat diff --git a/code/libmad-0.15.1b/stream.c b/code/libmad/stream.c similarity index 97% rename from code/libmad-0.15.1b/stream.c rename to code/libmad/stream.c index 8bb4d6a4..18ce95ae 100644 --- a/code/libmad-0.15.1b/stream.c +++ b/code/libmad/stream.c @@ -19,16 +19,11 @@ * $Id: stream.c,v 1.12 2004/02/05 09:02:39 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # include -# include "bit.h" -# include "stream.h" +# include "mad.h" /* * NAME: stream->init() diff --git a/code/libmad-0.15.1b/synth.c b/code/libmad/synth.c similarity index 99% rename from code/libmad-0.15.1b/synth.c rename to code/libmad/synth.c index 1d28d438..110c9b28 100644 --- a/code/libmad-0.15.1b/synth.c +++ b/code/libmad/synth.c @@ -19,15 +19,9 @@ * $Id: synth.c,v 1.25 2004/01/23 09:41:33 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" -# include "fixed.h" -# include "frame.h" -# include "synth.h" +# include "mad.h" /* * NAME: synth->init() diff --git a/code/libmad-0.15.1b/timer.c b/code/libmad/timer.c similarity index 99% rename from code/libmad-0.15.1b/timer.c rename to code/libmad/timer.c index 4b909aba..df11316c 100644 --- a/code/libmad-0.15.1b/timer.c +++ b/code/libmad/timer.c @@ -19,10 +19,6 @@ * $Id: timer.c,v 1.18 2004/01/23 09:41:33 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" # include @@ -31,7 +27,7 @@ # include # endif -# include "timer.h" +# include "mad.h" mad_timer_t const mad_timer_zero = { 0, 0 }; diff --git a/code/libmad-0.15.1b/version.c b/code/libmad/version.c similarity index 96% rename from code/libmad-0.15.1b/version.c rename to code/libmad/version.c index e643fa71..f3747567 100644 --- a/code/libmad-0.15.1b/version.c +++ b/code/libmad/version.c @@ -19,13 +19,9 @@ * $Id: version.c,v 1.15 2004/01/23 09:41:33 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - # include "global.h" -# include "version.h" +# include "mad.h" char const mad_version[] = "MPEG Audio Decoder " MAD_VERSION; char const mad_copyright[] = "Copyright (C) " MAD_PUBLISHYEAR " " MAD_AUTHOR; diff --git a/code/null/null_client.c b/code/null/null_client.c index 4027e404..3c70de34 100644 --- a/code/null/null_client.c +++ b/code/null/null_client.c @@ -62,6 +62,9 @@ void CL_CharEvent( int key ) { void CL_Disconnect() { } +void CL_AbnormalDisconnect() { +} + void CL_MapLoading( qboolean flush, const char *pszMapName ) { } @@ -125,3 +128,11 @@ void SCR_DebugGraph( float value ) { qboolean CL_FinishedIntro( void ) { return qtrue; } + +int R_CountTextureMemory() { + return 0; +} + +qboolean CL_UseLargeLightmap(const char* mapName) { + return qtrue; +} diff --git a/code/null/null_snddma.c b/code/null/null_snddma.c index 28cfb1ec..9b782fa7 100644 --- a/code/null/null_snddma.c +++ b/code/null/null_snddma.c @@ -47,15 +47,30 @@ void SNDDMA_Submit(void) { } -void SNDDMA_Activate(void) { +#ifdef USE_VOIP +void SNDDMA_StartCapture(void) +{ } -sfxHandle_t S_RegisterSound( const char *sample, qboolean compressed ) +int SNDDMA_AvailableCaptureSamples(void) { return 0; } -void S_StartLocalSound( sfxHandle_t sfx, int channelNum ) { +void SNDDMA_Capture(int samples, byte *data) +{ +} + +void SNDDMA_StopCapture(void) +{ +} + +void SNDDMA_MasterGain( float val ) +{ +} +#endif + +void SNDDMA_Activate(void) { } void S_ClearSoundBuffer( void ) { @@ -64,3 +79,17 @@ void S_ClearSoundBuffer( void ) { int S_IsSoundPlaying( int channel_number, const char *sfxName ){ return 0; } + +#if defined(NO_MODERN_DMA) && NO_MODERN_DMA +void S_StartLocalSound(sfxHandle_t sfx, int channelNum) { +} +sfxHandle_t S_RegisterSound(const char* sample, qboolean compressed) { + return 0; +} +#else +void S_StartLocalSound(const char* sound_name, qboolean force_load) { +} +sfxHandle_t S_RegisterSound(const char* name, int streamed, qboolean force_load) { + return 0; +} +#endif diff --git a/code/parser/bison_source.txt b/code/parser/bison_source.txt index e5d393ef..b3ba1d42 100644 --- a/code/parser/bison_source.txt +++ b/code/parser/bison_source.txt @@ -1,7 +1,7 @@ %{ /* * =========================================================================== -* Copyright (C) 2015 the OpenMoHAA team +* Copyright (C) 2025 the OpenMoHAA team * * This file is part of OpenMoHAA source code. * @@ -57,7 +57,7 @@ int success_pos; %precedence TOKEN_EOL %union { - stype_t s; + stype_t s; } %left TOKEN_COMMA @@ -71,11 +71,11 @@ int success_pos; %left TOKEN_LEFT_BRACKET TOKEN_RIGHT_BRACKET %token TOKEN_LEFT_SQUARE_BRACKET TOKEN_RIGHT_SQUARE_BRACKET -%right TOKEN_ASSIGNMENT - TOKEN_PLUS_EQUALS TOKEN_MINUS_EQUALS TOKEN_MULTIPLY_EQUALS TOKEN_DIVIDE_EQUALS TOKEN_MODULUS_EQUALS - TOKEN_AND_EQUALS TOKEN_EXCL_OR_EQUALS TOKEN_OR_EQUALS - TOKEN_SHIFT_LEFT_EQUALS TOKEN_SHIFT_RIGHT_EQUALS - TOKEN_TERNARY TOKEN_COLON +%right TOKEN_ASSIGNMENT + TOKEN_PLUS_EQUALS TOKEN_MINUS_EQUALS TOKEN_MULTIPLY_EQUALS TOKEN_DIVIDE_EQUALS TOKEN_MODULUS_EQUALS + TOKEN_AND_EQUALS TOKEN_EXCL_OR_EQUALS TOKEN_OR_EQUALS + TOKEN_SHIFT_LEFT_EQUALS TOKEN_SHIFT_RIGHT_EQUALS + TOKEN_TERNARY TOKEN_COLON %left TOKEN_LOGICAL_OR %left TOKEN_LOGICAL_AND @@ -103,19 +103,18 @@ int success_pos; %left TOKEN_DOUBLE_COLON %left TOKEN_SEMICOLON %right TOKEN_DOLLAR -%left TOKEN_NUMBER %token TOKEN_INCREMENT TOKEN_DECREMENT TOKEN_PERIOD %right TOKEN_INCREMENT TOKEN_DECREMENT TOKEN_NEG TOKEN_NOT TOKEN_COMPLEMENT %left TOKEN_LEFT_SQUARE_BRACKET TOKEN_RIGHT_SQUARE_BRACKET TOKEN_PERIOD -%precedence TOKEN_CATCH TOKEN_TRY - TOKEN_SWITCH TOKEN_CASE - TOKEN_BREAK TOKEN_CONTINUE - TOKEN_SIZE - TOKEN_END TOKEN_RETURN - TOKEN_MAKEARRAY TOKEN_ENDARRAY +%precedence TOKEN_CATCH TOKEN_TRY + TOKEN_SWITCH TOKEN_CASE + TOKEN_BREAK TOKEN_CONTINUE + TOKEN_SIZE + TOKEN_END TOKEN_RETURN + TOKEN_MAKEARRAY TOKEN_ENDARRAY %type event_parameter_list event_parameter_list_need event_parameter %type statement_list statement statement_declaration makearray_statement_list makearray_statement statement_for_condition @@ -125,6 +124,7 @@ int success_pos; %type prim_expr %type listener_identifier %type nonident_prim_expr +%type nonident_prim_expr_base %type const_array_list %type const_array %type identifier_prim @@ -135,203 +135,207 @@ int success_pos; %% program - : statement_list[list] { parsedata.val = node1(ENUM_statement_list, $list); } - | line_opt { parsedata.val = node0(ENUM_NOP); } - ; + : statement_list[list] { parsedata.val = node1(ENUM_statement_list, $list); } + | line_opt { parsedata.val = node0(ENUM_NOP); } + ; statement_list - : statement { $$ = linked_list_end($1); } - | statement_list statement[stmt] { $$ = append_node($1, $stmt); } - ; + : statement { $$ = linked_list_end($1); } + | statement_list statement[stmt] { $$ = append_node($1, $stmt); } + ; statement - : line_opt statement_declaration[stmt_decl] line_opt { $$ = $stmt_decl; } - ; + : line_opt statement_declaration[stmt_decl] line_opt { $$ = $stmt_decl; } + ; statement_declaration - : TOKEN_IDENTIFIER event_parameter_list TOKEN_COLON { $$ = node3(ENUM_labeled_statement, $1, $2, TOKPOS(@1)); } - | TOKEN_CASE prim_expr event_parameter_list TOKEN_COLON { $$ = node3(ENUM_int_labeled_statement, $2, $3, TOKPOS(@1)); } - | compound_statement - | selection_statement - | iteration_statement - | TOKEN_TRY compound_statement[C1] TOKEN_CATCH compound_statement[C2] { $$ = node3(ENUM_try, $C1, $C2, TOKPOS(@1)); } - | TOKEN_BREAK { $$ = node1(ENUM_break, TOKPOS(@1)); } - | TOKEN_CONTINUE { $$ = node1(ENUM_continue, TOKPOS(@1)); } - | TOKEN_IDENTIFIER event_parameter_list { $$ = node3(ENUM_cmd_event_statement, $1, $2, TOKPOS(@1)); } - | nonident_prim_expr TOKEN_IDENTIFIER event_parameter_list { $$ = node4(ENUM_method_event_statement, $1, $2, $3, TOKPOS(@2)); } - | nonident_prim_expr TOKEN_ASSIGNMENT expr { $$ = node3(ENUM_assignment_statement, $1, $3, TOKPOS(@2)); } - | nonident_prim_expr TOKEN_PLUS_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_PLUS), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_MINUS_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_MINUS), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_MULTIPLY_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_MULTIPLY), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_DIVIDE_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_DIVIDE), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_MODULUS_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_PERCENTAGE), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_AND_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_BITWISE_AND), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_EXCL_OR_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_BITWISE_EXCL_OR), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_OR_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_BITWISE_OR), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_SHIFT_LEFT_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_SHIFT_LEFT), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_SHIFT_RIGHT_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_SHIFT_RIGHT), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_INCREMENT { $$ = node3(ENUM_assignment_statement, $1, node3(ENUM_func1_expr, node1b(OP_UN_INC), $1, TOKPOS(@2)), TOKPOS(@2)); } - | nonident_prim_expr TOKEN_DECREMENT { $$ = node3(ENUM_assignment_statement, $1, node3(ENUM_func1_expr, node1b(OP_UN_DEC), $1, TOKPOS(@2)), TOKPOS(@2)); } - | TOKEN_SEMICOLON { $$ = node0(ENUM_NOP); } - //| TOKEN_IDENTIFIER TOKEN_DOUBLE_COLON TOKEN_IDENTIFIER event_parameter_list { $$ = node3( ENUM_method_event_statement, node_string( parsetree_string( str( $1.stringValue ) + "::" + $3.stringValue ) ), node1( ENUM_NOP, $4 ), TOKPOS(@1) ); } - //| nonident_prim_expr TOKEN_IDENTIFIER TOKEN_DOUBLE_COLON TOKEN_IDENTIFIER event_parameter_list { $$ = node4( ENUM_method_event_statement, $1, node_string( parsetree_string( str( $2.stringValue ) + "::" + $4.stringValue ) ), node1( ENUM_NOP, $5 ), TOKPOS(@2) ); } - ; - + : TOKEN_IDENTIFIER event_parameter_list TOKEN_COLON { $$ = node3(ENUM_labeled_statement, $1, $2, TOKPOS(@1)); } + | TOKEN_CASE prim_expr event_parameter_list TOKEN_COLON { $$ = node3(ENUM_int_labeled_statement, $2, $3, TOKPOS(@1)); } + | compound_statement + | selection_statement + | iteration_statement + | TOKEN_TRY compound_statement[C1] TOKEN_CATCH compound_statement[C2] { $$ = node3(ENUM_try, $C1, $C2, TOKPOS(@1)); } + | TOKEN_BREAK { $$ = node1(ENUM_break, TOKPOS(@1)); } + | TOKEN_CONTINUE { $$ = node1(ENUM_continue, TOKPOS(@1)); } + | TOKEN_IDENTIFIER event_parameter_list { $$ = node3(ENUM_cmd_event_statement, $1, $2, TOKPOS(@1)); } + | nonident_prim_expr TOKEN_IDENTIFIER event_parameter_list { $$ = node4(ENUM_method_event_statement, $1, $2, $3, TOKPOS(@2)); } + | nonident_prim_expr TOKEN_ASSIGNMENT expr { $$ = node3(ENUM_assignment_statement, $1, $3, TOKPOS(@2)); } + | nonident_prim_expr TOKEN_PLUS_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_PLUS), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_MINUS_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_MINUS), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_MULTIPLY_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_MULTIPLY), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_DIVIDE_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_DIVIDE), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_MODULUS_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_PERCENTAGE), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_AND_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_BITWISE_AND), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_EXCL_OR_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_BITWISE_EXCL_OR), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_OR_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_BITWISE_OR), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_SHIFT_LEFT_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_SHIFT_LEFT), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_SHIFT_RIGHT_EQUALS expr { $$ = node3(ENUM_assignment_statement, $1, node4(ENUM_func2_expr, node1b(OP_BIN_SHIFT_RIGHT), $1, $3, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_INCREMENT { $$ = node3(ENUM_assignment_statement, $1, node3(ENUM_func1_expr, node1b(OP_UN_INC), $1, TOKPOS(@2)), TOKPOS(@2)); } + | nonident_prim_expr TOKEN_DECREMENT { $$ = node3(ENUM_assignment_statement, $1, node3(ENUM_func1_expr, node1b(OP_UN_DEC), $1, TOKPOS(@2)), TOKPOS(@2)); } + | TOKEN_SEMICOLON { $$ = node0(ENUM_NOP); } + //| TOKEN_IDENTIFIER TOKEN_DOUBLE_COLON TOKEN_IDENTIFIER event_parameter_list { $$ = node3( ENUM_method_event_statement, node_string( parsetree_string( str( $1.stringValue ) + "::" + $3.stringValue ) ), node1( ENUM_NOP, $4 ), TOKPOS(@1) ); } + //| nonident_prim_expr TOKEN_IDENTIFIER TOKEN_DOUBLE_COLON TOKEN_IDENTIFIER event_parameter_list { $$ = node4( ENUM_method_event_statement, $1, node_string( parsetree_string( str( $2.stringValue ) + "::" + $4.stringValue ) ), node1( ENUM_NOP, $5 ), TOKPOS(@2) ); } + ; + statement_for_condition - : line_opt statement_declaration[stmt_decl] line_opt { $$ = $stmt_decl; } - | line_opt statement_declaration[stmt_decl] TOKEN_SEMICOLON line_opt { $$ = $stmt_decl; } - ; + : line_opt statement_declaration[stmt_decl] line_opt { $$ = $stmt_decl; } + | line_opt statement_declaration[stmt_decl] TOKEN_SEMICOLON line_opt { $$ = $stmt_decl; } + ; compound_statement - : TOKEN_LEFT_BRACES statement_list TOKEN_RIGHT_BRACES { $$ = node1(ENUM_statement_list, $2); } - | TOKEN_LEFT_BRACES line_opt TOKEN_RIGHT_BRACES { $$ = node0(ENUM_NOP); } - | line_opt compound_statement[comp_stmt] line_opt { $$ = $comp_stmt; } - ; + : TOKEN_LEFT_BRACES statement_list TOKEN_RIGHT_BRACES { $$ = node1(ENUM_statement_list, $2); } + | TOKEN_LEFT_BRACES line_opt TOKEN_RIGHT_BRACES { $$ = node0(ENUM_NOP); } + | line_opt compound_statement[comp_stmt] line_opt { $$ = $comp_stmt; } + ; selection_statement - : TOKEN_IF prim_expr[exp] statement_for_condition[stmt] %prec THEN { $$ = node3(ENUM_if_statement, $exp, $stmt, TOKPOS(@1)); } - | TOKEN_IF prim_expr[exp] statement_for_condition[if_stmt] TOKEN_ELSE statement_for_condition[else_stmt] { $$ = node4(ENUM_if_else_statement, $exp, $if_stmt, $else_stmt, TOKPOS(@1)); } - | TOKEN_SWITCH prim_expr[exp] compound_statement[comp_stmt] { $$ = node3(ENUM_switch, $exp, $comp_stmt, TOKPOS(@1)); } - ; + : TOKEN_IF prim_expr[exp] statement_for_condition[stmt] %prec THEN { $$ = node3(ENUM_if_statement, $exp, $stmt, TOKPOS(@1)); } + | TOKEN_IF prim_expr[exp] statement_for_condition[if_stmt] TOKEN_ELSE statement_for_condition[else_stmt] { $$ = node4(ENUM_if_else_statement, $exp, $if_stmt, $else_stmt, TOKPOS(@1)); } + | TOKEN_SWITCH prim_expr[exp] compound_statement[comp_stmt] { $$ = node3(ENUM_switch, $exp, $comp_stmt, TOKPOS(@1)); } + ; iteration_statement - : TOKEN_WHILE prim_expr[exp] statement_for_condition[stmt]{ $$ = node4(ENUM_while_statement, $exp, $stmt, node0(ENUM_NOP), TOKPOS(@1)); } - | TOKEN_FOR TOKEN_LEFT_BRACKET statement[init_stmt] TOKEN_SEMICOLON expr[exp] TOKEN_SEMICOLON statement_list[inc_stmt] TOKEN_RIGHT_BRACKET statement_for_condition[stmt] - { - sval_t while_stmt = node4(ENUM_while_statement, $exp, $stmt, node1(ENUM_statement_list, $inc_stmt), TOKPOS(@1)); - $$ = node1(ENUM_statement_list, append_node(linked_list_end($init_stmt), while_stmt)); - } - | TOKEN_FOR TOKEN_LEFT_BRACKET TOKEN_SEMICOLON expr[exp] TOKEN_SEMICOLON statement_list[inc_stmt] TOKEN_RIGHT_BRACKET statement_for_condition[stmt] - { - $$ = node4(ENUM_while_statement, $exp, $stmt, node1(ENUM_statement_list, $inc_stmt), TOKPOS(@1)); - } - | TOKEN_DO statement_for_condition[stmt] TOKEN_WHILE prim_expr[exp]{ $$ = node3(ENUM_do, $stmt, $exp, TOKPOS(@1)); } - ; + : TOKEN_WHILE prim_expr[exp] statement_for_condition[stmt]{ $$ = node4(ENUM_while_statement, $exp, $stmt, node0(ENUM_NOP), TOKPOS(@1)); } + | TOKEN_FOR TOKEN_LEFT_BRACKET statement[init_stmt] TOKEN_SEMICOLON expr[exp] TOKEN_SEMICOLON statement_list[inc_stmt] TOKEN_RIGHT_BRACKET statement_for_condition[stmt] + { + sval_t while_stmt = node4(ENUM_while_statement, $exp, $stmt, node1(ENUM_statement_list, $inc_stmt), TOKPOS(@1)); + $$ = node1(ENUM_statement_list, append_node(linked_list_end($init_stmt), while_stmt)); + } + | TOKEN_FOR TOKEN_LEFT_BRACKET TOKEN_SEMICOLON expr[exp] TOKEN_SEMICOLON statement_list[inc_stmt] TOKEN_RIGHT_BRACKET statement_for_condition[stmt] + { + $$ = node4(ENUM_while_statement, $exp, $stmt, node1(ENUM_statement_list, $inc_stmt), TOKPOS(@1)); + } + | TOKEN_DO statement_for_condition[stmt] TOKEN_WHILE prim_expr[exp]{ $$ = node3(ENUM_do, $stmt, $exp, TOKPOS(@1)); } + ; expr: - expr TOKEN_LOGICAL_AND expr { $$ = node3( ENUM_logical_and, $1, $3, TOKPOS(@2) ); } - | expr TOKEN_LOGICAL_OR expr { $$ = node3( ENUM_logical_or, $1, $3, TOKPOS(@2) ); } - | expr TOKEN_BITWISE_AND expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_BITWISE_AND ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_BITWISE_OR expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_BITWISE_OR ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_BITWISE_EXCL_OR expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_BITWISE_EXCL_OR ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_EQUALITY expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_EQUALITY ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_INEQUALITY expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_INEQUALITY ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_LESS_THAN expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_LESS_THAN ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_GREATER_THAN expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_GREATER_THAN ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_LESS_THAN_OR_EQUAL expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_LESS_THAN_OR_EQUAL ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_GREATER_THAN_OR_EQUAL expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_GREATER_THAN_OR_EQUAL ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_PLUS expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_PLUS ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_MINUS expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_MINUS ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_MULTIPLY expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_MULTIPLY ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_DIVIDE expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_DIVIDE ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_MODULUS expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_PERCENTAGE ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_SHIFT_LEFT expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_SHIFT_LEFT ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_SHIFT_RIGHT expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_SHIFT_RIGHT ), $1, $3, TOKPOS(@2) ); } - | expr TOKEN_TERNARY expr TOKEN_COLON expr { $$ = node4( ENUM_if_else_statement, $1, $3, $5, TOKPOS(@2) ); } - | TOKEN_EOL expr[exp] { $$ = $exp; } - | nonident_prim_expr - | func_prim_expr - | TOKEN_IDENTIFIER { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } - ; + expr TOKEN_LOGICAL_AND expr { $$ = node3( ENUM_logical_and, $1, $3, TOKPOS(@2) ); } + | expr TOKEN_LOGICAL_OR expr { $$ = node3( ENUM_logical_or, $1, $3, TOKPOS(@2) ); } + | expr TOKEN_BITWISE_AND expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_BITWISE_AND ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_BITWISE_OR expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_BITWISE_OR ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_BITWISE_EXCL_OR expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_BITWISE_EXCL_OR ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_EQUALITY expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_EQUALITY ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_INEQUALITY expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_INEQUALITY ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_LESS_THAN expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_LESS_THAN ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_GREATER_THAN expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_GREATER_THAN ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_LESS_THAN_OR_EQUAL expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_LESS_THAN_OR_EQUAL ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_GREATER_THAN_OR_EQUAL expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_GREATER_THAN_OR_EQUAL ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_PLUS expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_PLUS ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_MINUS expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_MINUS ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_MULTIPLY expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_MULTIPLY ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_DIVIDE expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_DIVIDE ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_MODULUS expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_PERCENTAGE ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_SHIFT_LEFT expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_SHIFT_LEFT ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_SHIFT_RIGHT expr { $$ = node4( ENUM_func2_expr, node1b( OP_BIN_SHIFT_RIGHT ), $1, $3, TOKPOS(@2) ); } + | expr TOKEN_TERNARY expr TOKEN_COLON expr { $$ = node4( ENUM_if_else_statement, $1, $3, $5, TOKPOS(@2) ); } + | TOKEN_EOL expr[exp] { $$ = $exp; } + | nonident_prim_expr + | func_prim_expr + | TOKEN_IDENTIFIER { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } + ; func_prim_expr: - TOKEN_IDENTIFIER event_parameter_list_need { $$ = node3(ENUM_cmd_event_expr, $1, $2, TOKPOS(@1)); } - | nonident_prim_expr TOKEN_IDENTIFIER event_parameter_list { $$ = node4(ENUM_method_event_expr, $1, $2, $3, TOKPOS(@2)); } - | TOKEN_NEG func_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_MINUS), $2, TOKPOS(@1)); } - | TOKEN_COMPLEMENT func_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_COMPLEMENT), $2, TOKPOS(@1)); } - | TOKEN_NOT func_prim_expr { $$ = node2(ENUM_bool_not, $2, TOKPOS(@1)); } - | TOKEN_IDENTIFIER TOKEN_DOUBLE_COLON const_array_list - { - $$ = node3(ENUM_const_array_expr, node2(ENUM_string, $1, TOKPOS(@1)), $3, TOKPOS(@2)); - } - | nonident_prim_expr TOKEN_DOUBLE_COLON const_array_list - { - $$ = node3(ENUM_const_array_expr, $1, $3, TOKPOS(@2)); - } - | TOKEN_MAKEARRAY makearray_statement_list[stmt] TOKEN_ENDARRAY - { - $$ = node2(ENUM_makearray, $stmt, TOKPOS(@1)); - } - ; + TOKEN_IDENTIFIER event_parameter_list_need { $$ = node3(ENUM_cmd_event_expr, $1, $2, TOKPOS(@1)); } + | nonident_prim_expr_base TOKEN_IDENTIFIER event_parameter_list { $$ = node4(ENUM_method_event_expr, $1, $2, $3, TOKPOS(@2)); } + | TOKEN_NEG func_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_MINUS), $2, TOKPOS(@1)); } + | TOKEN_COMPLEMENT func_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_COMPLEMENT), $2, TOKPOS(@1)); } + | TOKEN_NOT func_prim_expr { $$ = node2(ENUM_bool_not, $2, TOKPOS(@1)); } + | TOKEN_IDENTIFIER TOKEN_DOUBLE_COLON const_array_list + { + $$ = node3(ENUM_const_array_expr, node2(ENUM_string, $1, TOKPOS(@1)), $3, TOKPOS(@2)); + } + | nonident_prim_expr TOKEN_DOUBLE_COLON const_array_list + { + $$ = node3(ENUM_const_array_expr, $1, $3, TOKPOS(@2)); + } + | TOKEN_MAKEARRAY makearray_statement_list[stmt] TOKEN_ENDARRAY + { + $$ = node2(ENUM_makearray, $stmt, TOKPOS(@1)); + } + ; event_parameter_list - : { $$ = sval_u{}; $$.node = NULL; } - | event_parameter { $$ = $1; } - ; + : { $$ = sval_u{}; $$.node = NULL; } + | event_parameter { $$ = $1; } + ; event_parameter_list_need - : event_parameter { $$ = $1; } - ; + : event_parameter { $$ = $1; } + ; event_parameter - : prim_expr { $$ = linked_list_end($1); } - | event_parameter prim_expr { $$ = append_node($1, $2); } - ; + : prim_expr { $$ = linked_list_end($1); } + | event_parameter prim_expr { $$ = append_node($1, $2); } + ; const_array_list - : const_array { $$ = linked_list_end($1); } - | const_array_list TOKEN_DOUBLE_COLON const_array { $$ = append_node($1, $3); } - ; + : const_array { $$ = linked_list_end($1); } + | const_array_list TOKEN_DOUBLE_COLON const_array { $$ = append_node($1, $3); } + ; const_array - : nonident_prim_expr - | identifier_prim { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } - ; + : nonident_prim_expr + | identifier_prim { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } + ; prim_expr - : nonident_prim_expr - | identifier_prim { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } - | prim_expr TOKEN_DOUBLE_COLON const_array_list { $$ = node3(ENUM_const_array_expr, $1, $3, TOKPOS(@2)); } - ; + : nonident_prim_expr + | identifier_prim { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } + | const_array TOKEN_DOUBLE_COLON const_array_list { $$ = node3(ENUM_const_array_expr, $1, $3, TOKPOS(@2)); } + ; identifier_prim: - TOKEN_IDENTIFIER { $$ = $1; @$ = @1; } - ; + TOKEN_IDENTIFIER { $$ = $1; @$ = @1; } + ; identifier - : TOKEN_IDENTIFIER { $$ = $1; @$ = @1; } - | TOKEN_STRING { $$ = $1; @$ = @1; } - ; + : TOKEN_IDENTIFIER { $$ = $1; @$ = @1; } + | TOKEN_STRING { $$ = $1; @$ = @1; } + ; listener_identifier - : identifier_prim { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } - | TOKEN_LEFT_BRACKET expr TOKEN_RIGHT_BRACKET { $$ = $2; } - ; + : identifier { $$ = node_listener($1, TOKPOS(@1)); } + | TOKEN_LEFT_BRACKET expr TOKEN_RIGHT_BRACKET { $$ = $2; } + ; nonident_prim_expr - : TOKEN_DOLLAR listener_identifier { $$ = node3(ENUM_func1_expr, node1b(OP_UN_TARGETNAME), $2, TOKPOS(@1)); } - | nonident_prim_expr TOKEN_PERIOD identifier { $$ = node3(ENUM_field, $1, $3, TOKPOS(@3)); } - | nonident_prim_expr TOKEN_PERIOD TOKEN_SIZE { $$ = node3(ENUM_func1_expr, node1b(OP_UN_SIZE), $1, TOKPOS(@3)); } - | nonident_prim_expr TOKEN_LEFT_SQUARE_BRACKET expr TOKEN_RIGHT_SQUARE_BRACKET { $$ = node3(ENUM_array_expr, $1, $3, TOKPOS(@2)); } - | TOKEN_STRING { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } - | TOKEN_INTEGER { $$ = node2(ENUM_integer, $1, TOKPOS(@1)); } - | TOKEN_FLOAT { $$ = node2(ENUM_float, $1, TOKPOS(@1)); } - | TOKEN_LEFT_BRACKET expr[exp1] expr[exp2] expr[exp3] TOKEN_RIGHT_BRACKET { $$ = node4(ENUM_vector, $exp1, $exp2, $exp3, TOKPOS(@1)); } - | TOKEN_LISTENER { $$ = node2(ENUM_listener, $1, TOKPOS(@1)); } - | TOKEN_LEFT_BRACKET expr TOKEN_RIGHT_BRACKET { $$ = $2; } - | TOKEN_LEFT_BRACKET expr TOKEN_EOL TOKEN_RIGHT_BRACKET { $$ = $2; } - | TOKEN_NEG nonident_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_MINUS), $2, TOKPOS(@1)); } - | TOKEN_COMPLEMENT nonident_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_COMPLEMENT), $2, TOKPOS(@1)); } - | TOKEN_NOT nonident_prim_expr { $$ = node2(ENUM_bool_not, $2, TOKPOS(@1)); } - | TOKEN_NULL { $$ = node1(ENUM_NULL, TOKPOS(@1)); } - | TOKEN_NIL { $$ = node1(ENUM_NIL, TOKPOS(@1)); } - ; + : nonident_prim_expr_base + | TOKEN_NEG nonident_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_MINUS), $2, TOKPOS(@1)); } + | TOKEN_COMPLEMENT nonident_prim_expr { $$ = node3(ENUM_func1_expr, node1b(OP_UN_COMPLEMENT), $2, TOKPOS(@1)); } + | TOKEN_NOT nonident_prim_expr { $$ = node2(ENUM_bool_not, $2, TOKPOS(@1)); } + ; + +nonident_prim_expr_base + : TOKEN_DOLLAR listener_identifier { $$ = node3(ENUM_func1_expr, node1b(OP_UN_TARGETNAME), $2, TOKPOS(@1)); } + | nonident_prim_expr TOKEN_PERIOD identifier { $$ = node3(ENUM_field, $1, $3, TOKPOS(@3)); } + | nonident_prim_expr TOKEN_PERIOD TOKEN_SIZE { $$ = node3(ENUM_func1_expr, node1b(OP_UN_SIZE), $1, TOKPOS(@3)); } + | nonident_prim_expr TOKEN_LEFT_SQUARE_BRACKET expr TOKEN_RIGHT_SQUARE_BRACKET { $$ = node3(ENUM_array_expr, $1, $3, TOKPOS(@2)); } + | TOKEN_STRING { $$ = node2(ENUM_string, $1, TOKPOS(@1)); } + | TOKEN_INTEGER { $$ = node2(ENUM_integer, $1, TOKPOS(@1)); } + | TOKEN_FLOAT { $$ = node2(ENUM_float, $1, TOKPOS(@1)); } + | TOKEN_LEFT_BRACKET expr[exp1] expr[exp2] expr[exp3] TOKEN_RIGHT_BRACKET { $$ = node4(ENUM_vector, $exp1, $exp2, $exp3, TOKPOS(@1)); } + | TOKEN_LISTENER { $$ = node2(ENUM_listener, $1, TOKPOS(@1)); } + | TOKEN_LEFT_BRACKET expr TOKEN_RIGHT_BRACKET { $$ = $2; } + | TOKEN_LEFT_BRACKET expr TOKEN_EOL TOKEN_RIGHT_BRACKET { $$ = $2; } + | TOKEN_NULL { $$ = node1(ENUM_NULL, TOKPOS(@1)); } + | TOKEN_NIL { $$ = node1(ENUM_NIL, TOKPOS(@1)); } + ; makearray_statement_list: - { $$ = node0(ENUM_NOP); } - | makearray_statement_list[list] makearray_statement[ma_stmt] TOKEN_EOL { $$ = append_node($list, node2(ENUM_makearray, $ma_stmt, TOKPOS(@ma_stmt))); } - | makearray_statement[ma_stmt] TOKEN_EOL { $$ = linked_list_end(node2(ENUM_makearray, $ma_stmt, TOKPOS(@ma_stmt))); } - | TOKEN_EOL makearray_statement_list { $$ = $2; @$ = @2; } - ; + { $$ = node0(ENUM_NOP); } + | makearray_statement_list[list] makearray_statement[ma_stmt] TOKEN_EOL { $$ = append_node($list, node2(ENUM_makearray, $ma_stmt, TOKPOS(@ma_stmt))); } + | makearray_statement[ma_stmt] TOKEN_EOL { $$ = linked_list_end(node2(ENUM_makearray, $ma_stmt, TOKPOS(@ma_stmt))); } + | TOKEN_EOL makearray_statement_list { $$ = $2; @$ = @2; } + ; makearray_statement: - prim_expr { $$ = linked_list_end( $1 ); } - | makearray_statement prim_expr { $$ = append_node( $1, $2 ); } - ; + prim_expr { $$ = linked_list_end( $1 ); } + | makearray_statement prim_expr { $$ = append_node( $1, $2 ); } + ; line_opt - : {} - | TOKEN_EOL - ; + : {} + | TOKEN_EOL + ; %% diff --git a/code/parser/lex.yy.cpp b/code/parser/lex.yy.cpp index a7175203..225052d9 100644 --- a/code/parser/lex.yy.cpp +++ b/code/parser/lex.yy.cpp @@ -1,3 +1,28 @@ +/* +* =========================================================================== +* Copyright (C) 2025 the OpenMoHAA team +* +* This file is part of OpenMoHAA source code. +* +* OpenMoHAA source code is free software; you can redistribute it +* and/or modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of the License, +* or (at your option) any later version. +* +* OpenMoHAA source code is distributed in the hope that it will be +* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with OpenMoHAA source code; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +* =========================================================================== +* +* +* lex.yy.cpp: original lex generated file (unimplemented) +*/ + #include "scriptcompiler.h" #include diff --git a/code/parser/lex_source.txt b/code/parser/lex_source.txt index e1545c94..d97038b0 100644 --- a/code/parser/lex_source.txt +++ b/code/parser/lex_source.txt @@ -1,7 +1,7 @@ %{ /* * =========================================================================== -* Copyright (C) 2015 the OpenMoHAA team +* Copyright (C) 2025 the OpenMoHAA team * * This file is part of OpenMoHAA source code. * @@ -29,147 +29,144 @@ #include -void fprintf2( FILE *f, const char *format, ... ) +void fprintf2(FILE * f, const char *format, ...) { - va_list va; - static char buffer[ 4200 ]; + va_list va; + static char buffer[4200]; - va_start( va, format ); - vsprintf( buffer, format, va ); - va_end( va ); + va_start(va, format); + vsprintf(buffer, format, va); + va_end(va); - gi.Printf( buffer ); + gi.Printf(buffer); } #define fprintf fprintf2 -const char* start_ptr; -const char* in_ptr; -extern int prev_yylex; -extern int out_pos; -extern int success_pos; +const char *start_ptr; +const char *in_ptr; +extern int prev_yylex; +extern int out_pos; +extern int success_pos; parseStage_e parseStage; extern yyparsedata parsedata; -void yyllocset(YYLTYPE *loc, uint32_t off) +void yyllocset(YYLTYPE * loc, uint32_t off) { - success_pos = out_pos - yyleng + off; - loc->sourcePos = success_pos; - parsedata.pos = success_pos; + success_pos = out_pos - yyleng + off; + loc->sourcePos = success_pos; + parsedata.pos = success_pos; } void yyreducepos(uint32_t off) { - out_pos -= off; + out_pos -= off; } -#define YYLEX(n) { yyllocset(&yylloc, 0); prev_yylex = n; return n; } -#define YYLEXOFF(n, off) { yyllocset(&yylloc, off); prev_yylex = n; return n; } +#define YYLEX(n) \ + { \ + yyllocset(&yylloc, 0); \ + prev_yylex = n; \ + return n; \ + } +#define YYLEXOFF(n, off) \ + { \ + yyllocset(&yylloc, off); \ + prev_yylex = n; \ + return n; \ + } -#define YY_USER_ACTION \ -{ \ - out_pos += yyleng - yy_more_len; \ - yylloc.sourcePos = out_pos; \ - parsedata.pos = out_pos; \ -} +#define YY_USER_ACTION \ + { \ + out_pos += yyleng - yy_more_len; \ + yylloc.sourcePos = out_pos; \ + parsedata.pos = out_pos; \ + } -#define YY_FATAL_ERROR( n ) yylexerror( n ) +#define YY_FATAL_ERROR(n) yylexerror(n) -void yylexerror( const char *msg ) +void yylexerror(const char *msg) { - gi.DPrintf( "%s\n%s", msg, yytext ); - assert( 0 ); + gi.DPrintf("%s\n%s", msg, yytext); + assert(0); } -static void TextEscapeValue( char *str, size_t len ) +static void TextEscapeValue(char *str, size_t len) { - char *to = parsetree_malloc( len + 1 ); + char *to = parsetree_malloc(len + 1); - yylval.s.val.stringValue = to; + yylval.s.val.stringValue = to; - while( len ) - { - if( *str == '\\' ) - { - len--; + while (len) { + if (*str == '\\') { + if (len == 1) { + break; + } - if( !len ) - break; + if (str[1] == 'n') { + *to = '\n'; + to++; + } else if (str[1] == 't') { + *to = '\t'; + to++; + } else if (str[1] == '"') { + *to = '\"'; + to++; + } else { + *to = str[1]; + to++; + } - str++; - if( *str == 'n' ) - { - *to = '\n'; - } - else if( *str == 't' ) - { - *to = '\t'; - } - else if( *str == '"' ) - { - *to = '\"'; - } - else - { - *to = *str; - } - } - else - { - *to = *str; - } + len -= 2; + str += 2; + } else { + *to = *str; + to++; + len--; + str++; + } + } - len--; - str++; - to++; - } - - *to = 0; + *to = 0; } - -static void TextValue( char *str, size_t len ) +static void TextValue(char *str, size_t len) { - char* s = parsetree_malloc(len + 1); - strncpy(s, str, len); - s[len] = 0; - yylval.s.val.stringValue = s; + char *s = parsetree_malloc(len + 1); + strncpy(s, str, len); + s[len] = 0; + yylval.s.val.stringValue = s; } -static bool UseField( void ) +static bool UseField(void) { - return prev_yylex == TOKEN_PERIOD - || prev_yylex == TOKEN_DOLLAR; + return prev_yylex == TOKEN_PERIOD || prev_yylex == TOKEN_DOLLAR; } -#define YY_INPUT(buf,result,max_size) \ -{ \ - char c; \ - int n; \ - \ - c = '*'; \ - for(n = 0; n < max_size; n++) \ - { \ - c = *in_ptr++; \ - if (!c || c == '\n') { \ - break; \ - } \ - \ - buf[n] = c; \ - } \ - \ - if (c == '\n') \ - { \ - buf[n++] = c; \ - } \ - else if (!c) \ - { \ - in_ptr--; \ - } \ - \ - result = n; \ -} +#define YY_INPUT(buf, result, max_size) \ + { \ + char c; \ + int n; \ + \ + c = '*'; \ + for (n = 0; n < max_size; n++) { \ + c = *in_ptr++; \ + if (!c || c == '\n') { \ + break; \ + } \ + \ + buf[n] = c; \ + } \ + \ + if (c == '\n') { \ + buf[n++] = c; \ + } else if (!c) { \ + in_ptr--; \ + } \ + \ + result = n; \ + } %} @@ -186,174 +183,193 @@ static bool UseField( void ) %x VARIABLES %x IDENTIFIER -string ([^\\\"]|\\.)* -identifier [^\{\}\(\)\[\]\r\n\,:; \t] -alphanum [a-zA-Z0-9_]+ -varname [a-zA-Z0-9_\"]+ +string ([^\\\"\r\n]|\\.)* +identifier [^\{\}\(\)\[\]\r\n\,:; \t] +nonexpr [0-9a-zA-Z_\"'?@#`\.\x80-\xff] +nonnumeric [a-zA-Z_\"'?@#`\x80-\xff] +alphanum [a-zA-Z0-9_]+ +varname [a-zA-Z0-9_\"$\\]+ %% -"/*" { BEGIN( C_COMMENT ); } -"*/" { BEGIN( INITIAL ); } -\n { ; } -. { ; } -"*/" { Compiler.CompileError( parsedata.pos - yyleng, "'*/' found outside of comment" ); } +"/*" { BEGIN(C_COMMENT); } +"*/" { BEGIN(INITIAL); } +\n { ; } +. { ; } +"*/" { Compiler.CompileError( parsedata.pos - yyleng, "'*/' found outside of comment" ); } -\\[\r\n]+ { ; } -"//"[^\r\n]* { if( prev_yylex != TOKEN_EOL ) YYLEX( TOKEN_EOL ); } +\\[\r\n]+ { ; } +"//"[^\r\n]* { if(prev_yylex != TOKEN_EOL) YYLEX(TOKEN_EOL); } -"size" { BEGIN(INITIAL); YYLEX(TOKEN_SIZE); } -"." { YYLEX(TOKEN_PERIOD); } -\"{string}\" { BEGIN(INITIAL); TextEscapeValue(yytext + 1, strlen( yytext ) - 2 ); YYLEX(TOKEN_STRING); } -{varname} { - TextValue(yytext, strlen(yytext)); - YYLEX(TOKEN_IDENTIFIER); - } -[ \t\r\n] { - BEGIN(INITIAL); - unput(yytext[yyleng - 1]); - yyreducepos(1); - } -. { - BEGIN(INITIAL); - unput(yytext[yyleng - 1]); - yyreducepos(1); - } +"size" { BEGIN(INITIAL); YYLEX(TOKEN_SIZE); } +[ \t]*\./([0-9]*[^0-9[:space:]]) { YYLEX(TOKEN_PERIOD); } +\"{string}\" { BEGIN(INITIAL); TextEscapeValue(yytext + 1, strlen( yytext ) - 2 ); YYLEX(TOKEN_STRING); } +{varname} { + TextEscapeValue(yytext, strlen(yytext)); + YYLEX(TOKEN_IDENTIFIER); + } +[ \t\r\n] { + BEGIN(INITIAL); + unput(yytext[yyleng - 1]); + yyreducepos(1); + } +. { + BEGIN(INITIAL); + unput(yytext[yyleng - 1]); + yyreducepos(1); + } -\"{string}\" { TextEscapeValue( yytext + 1, strlen( yytext ) - 2 ); YYLEX( TOKEN_STRING ); } +\"{string}\"{nonexpr} { + BEGIN(IDENTIFIER); + yymore(); + } +\"{string}\" { TextEscapeValue(yytext + 1, yyleng - 2); YYLEX(TOKEN_STRING); } -"?" { YYLEX( TOKEN_TERNARY ); } -"if" { YYLEX( TOKEN_IF ); } -"else" { YYLEX( TOKEN_ELSE ); } -"while" { YYLEX( TOKEN_WHILE ); } -"for" { YYLEX( TOKEN_FOR ); } -"do" { YYLEX( TOKEN_DO ); } +"?" { YYLEX(TOKEN_TERNARY); } +"if" { YYLEX(TOKEN_IF); } +"else" { YYLEX(TOKEN_ELSE); } +"while" { YYLEX(TOKEN_WHILE); } +"for" { YYLEX(TOKEN_FOR); } +"do" { YYLEX(TOKEN_DO); } -"game" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_game ); YYLEX( TOKEN_LISTENER ); } -"group" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_group ); YYLEX( TOKEN_LISTENER ); } -"level" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_level ); YYLEX( TOKEN_LISTENER ); } -"local" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_local ); YYLEX( TOKEN_LISTENER ); } -"parm" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_parm ); YYLEX( TOKEN_LISTENER ); } -"owner" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_owner ); YYLEX( TOKEN_LISTENER ); } -"self" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_self ); YYLEX( TOKEN_LISTENER ); } +"game" { BEGIN(VARIABLES); yylval.s.val = node1_(method_game); YYLEX(TOKEN_LISTENER); } +"group" { BEGIN(VARIABLES); yylval.s.val = node1_(method_group); YYLEX(TOKEN_LISTENER); } +"level" { BEGIN(VARIABLES); yylval.s.val = node1_(method_level); YYLEX(TOKEN_LISTENER); } +"local" { BEGIN(VARIABLES); yylval.s.val = node1_(method_local); YYLEX(TOKEN_LISTENER); } +"parm" { BEGIN(VARIABLES); yylval.s.val = node1_(method_parm); YYLEX(TOKEN_LISTENER); } +"owner" { BEGIN(VARIABLES); yylval.s.val = node1_(method_owner); YYLEX(TOKEN_LISTENER); } +"self" { BEGIN(VARIABLES); yylval.s.val = node1_(method_self); YYLEX(TOKEN_LISTENER); } -"{" { parsedata.braces_count++; YYLEX( TOKEN_LEFT_BRACES ); } -"}" { parsedata.braces_count--; YYLEX( TOKEN_RIGHT_BRACES ); } -"(" { YYLEX(TOKEN_LEFT_BRACKET); } -")" { BEGIN(VARIABLES); YYLEX(TOKEN_RIGHT_BRACKET); } -"[" { YYLEX(TOKEN_LEFT_SQUARE_BRACKET); } -"]" { BEGIN(VARIABLES); YYLEX(TOKEN_RIGHT_SQUARE_BRACKET); } +"{" { parsedata.braces_count++; YYLEX(TOKEN_LEFT_BRACES); } +"}" { parsedata.braces_count--; YYLEX(TOKEN_RIGHT_BRACES); } +"(" { YYLEX(TOKEN_LEFT_BRACKET); } +")" { BEGIN(VARIABLES); YYLEX(TOKEN_RIGHT_BRACKET); } +"[" { YYLEX(TOKEN_LEFT_SQUARE_BRACKET); } +"]" { BEGIN(VARIABLES); YYLEX(TOKEN_RIGHT_SQUARE_BRACKET); } -"=" { YYLEX( TOKEN_ASSIGNMENT ); } -":" { YYLEX( TOKEN_COLON ); } -"::" { YYLEX( TOKEN_DOUBLE_COLON ); } -";" { YYLEX( TOKEN_SEMICOLON ); } +"=" { YYLEX(TOKEN_ASSIGNMENT); } +":" { YYLEX(TOKEN_COLON); } +"::" { YYLEX(TOKEN_DOUBLE_COLON); } +";" { YYLEX(TOKEN_SEMICOLON); } -"==" { YYLEX( TOKEN_EQUALITY ); } -"||" { YYLEX( TOKEN_LOGICAL_OR ); } -"&&" { YYLEX( TOKEN_LOGICAL_AND ); } +"==" { YYLEX(TOKEN_EQUALITY); } +"ifequal" { YYLEX(TOKEN_EQUALITY); } +"ifstrequal" { YYLEX(TOKEN_EQUALITY); } +"||" { YYLEX(TOKEN_LOGICAL_OR); } +"&&" { YYLEX(TOKEN_LOGICAL_AND); } -"|" { YYLEX( TOKEN_BITWISE_OR ); } -"^" { YYLEX( TOKEN_BITWISE_EXCL_OR ); } -"&" { YYLEX( TOKEN_BITWISE_AND ); } -"!=" { YYLEX( TOKEN_INEQUALITY ); } -"<" { YYLEX( TOKEN_LESS_THAN ); } -">" { YYLEX( TOKEN_GREATER_THAN ); } -"<=" { YYLEX( TOKEN_LESS_THAN_OR_EQUAL ); } -">=" { YYLEX( TOKEN_GREATER_THAN_OR_EQUAL ); } -[ ]"-" { YYLEX( TOKEN_NEG ); } +"|" { YYLEX(TOKEN_BITWISE_OR); } +"^" { YYLEX(TOKEN_BITWISE_EXCL_OR); } +"&" { YYLEX(TOKEN_BITWISE_AND); } +"!=" { YYLEX(TOKEN_INEQUALITY); } +"ifnotequal" { YYLEX(TOKEN_INEQUALITY); } +"ifstrnotequal" { YYLEX(TOKEN_INEQUALITY); } +"<" { YYLEX(TOKEN_LESS_THAN); } +"ifless" { YYLEX(TOKEN_LESS_THAN); } +">" { YYLEX(TOKEN_GREATER_THAN); } +"ifgreater" { YYLEX(TOKEN_GREATER_THAN); } +"<=" { YYLEX(TOKEN_LESS_THAN_OR_EQUAL); } +"iflessequal" { YYLEX(TOKEN_LESS_THAN_OR_EQUAL); } +">=" { YYLEX(TOKEN_GREATER_THAN_OR_EQUAL); } +"ifgreaterequal" { YYLEX(TOKEN_GREATER_THAN_OR_EQUAL); } +[ \t]"-" { YYLEX(TOKEN_NEG); } -"+" { YYLEX( TOKEN_PLUS ); } -"+=" { YYLEX( TOKEN_PLUS_EQUALS ); } -"++"|[ ]"++" { YYLEX( TOKEN_INCREMENT ); } -"-"|"-"[ ]|[ ]"-"[ ] { YYLEX( TOKEN_MINUS ); } -"-=" { YYLEX( TOKEN_MINUS_EQUALS ); } -[ ]"-=" { YYLEX( TOKEN_MINUS_EQUALS ); } -"--"|[ ]"--" { YYLEX( TOKEN_DECREMENT ); } -"*" { YYLEX( TOKEN_MULTIPLY ); } -"*=" { YYLEX( TOKEN_MULTIPLY_EQUALS ); } -"/" { YYLEX( TOKEN_DIVIDE ); } -"/=" { YYLEX( TOKEN_DIVIDE_EQUALS ); } -"%" { YYLEX( TOKEN_MODULUS ); } -"%=" { YYLEX( TOKEN_MODULUS_EQUALS ); } -"<<" { YYLEX( TOKEN_SHIFT_LEFT ); } -"<<=" { YYLEX( TOKEN_SHIFT_LEFT_EQUALS ); } -">>" { YYLEX( TOKEN_SHIFT_RIGHT ); } -">>=" { YYLEX( TOKEN_SHIFT_RIGHT_EQUALS ); } -"&=" { YYLEX( TOKEN_AND_EQUALS ); } -"^=" { YYLEX( TOKEN_EXCL_OR_EQUALS ); } -"|=" { YYLEX( TOKEN_OR_EQUALS ); } -"$" { BEGIN( VARIABLES ); YYLEX( TOKEN_DOLLAR ); } -"!" { YYLEX( TOKEN_NOT ); } -"~" { YYLEX( TOKEN_COMPLEMENT ); } +"+" { YYLEX(TOKEN_PLUS); } +"+=" { YYLEX(TOKEN_PLUS_EQUALS); } +"++"|[ \t]"++" { YYLEX(TOKEN_INCREMENT); } +"-"|"-"[ \t]|[ \t]"-"[ \t] { YYLEX(TOKEN_MINUS); } +"-=" { YYLEX(TOKEN_MINUS_EQUALS); } +[ \t]"-=" { YYLEX(TOKEN_MINUS_EQUALS); } +"--"|[ \t]"--" { YYLEX(TOKEN_DECREMENT); } +"*" { YYLEX(TOKEN_MULTIPLY); } +"*=" { YYLEX(TOKEN_MULTIPLY_EQUALS); } +"/" { YYLEX(TOKEN_DIVIDE); } +"/=" { YYLEX(TOKEN_DIVIDE_EQUALS); } +"%" { YYLEX(TOKEN_MODULUS); } +"%=" { YYLEX(TOKEN_MODULUS_EQUALS); } +"<<" { YYLEX(TOKEN_SHIFT_LEFT); } +"<<=" { YYLEX(TOKEN_SHIFT_LEFT_EQUALS); } +">>" { YYLEX(TOKEN_SHIFT_RIGHT); } +">>=" { YYLEX(TOKEN_SHIFT_RIGHT_EQUALS); } +"&=" { YYLEX(TOKEN_AND_EQUALS); } +"^=" { YYLEX(TOKEN_EXCL_OR_EQUALS); } +"|=" { YYLEX(TOKEN_OR_EQUALS); } +[$]+ { BEGIN( VARIABLES ); YYLEX(TOKEN_DOLLAR); } +"!" { YYLEX(TOKEN_NOT); } +"~" { YYLEX(TOKEN_COMPLEMENT); } -"." { YYLEX( TOKEN_PERIOD ); } +"." { YYLEX(TOKEN_PERIOD); } -"," { YYLEX( TOKEN_COMMA ); } -"#" { YYLEX( TOKEN_NUMBER ); } +"," { YYLEX(TOKEN_COMMA); } -"NULL" { YYLEX( TOKEN_NULL ); } -"NIL" { YYLEX( TOKEN_NIL ); } +"NULL" { YYLEX(TOKEN_NULL); } +"NIL" { YYLEX(TOKEN_NIL); } -"try" { YYLEX( TOKEN_TRY ); } -"catch" { YYLEX( TOKEN_CATCH ); } -"switch" { YYLEX( TOKEN_SWITCH ); } +"try" { YYLEX(TOKEN_TRY); } +"catch" { YYLEX(TOKEN_CATCH); } +"switch" { YYLEX(TOKEN_SWITCH); } -"case" { YYLEX( TOKEN_CASE ); } -"break" { YYLEX( TOKEN_BREAK ); } -"continue" { YYLEX( TOKEN_CONTINUE ); } +"case" { YYLEX(TOKEN_CASE); } +"break" { YYLEX(TOKEN_BREAK); } +"continue" { YYLEX(TOKEN_CONTINUE); } -"makearray"|"makeArray" { YYLEX( TOKEN_MAKEARRAY ); } -"endarray"|"endArray" { YYLEX( TOKEN_ENDARRAY ); } +"makearray"|"makeArray" { YYLEX(TOKEN_MAKEARRAY); } +"endarray"|"endArray" { YYLEX(TOKEN_ENDARRAY); } -[\r\n]+ { if (prev_yylex != TOKEN_EOL) YYLEX(TOKEN_EOL); } -[ \t] { ; } +[\r\n]+ { if (prev_yylex != TOKEN_EOL) YYLEX(TOKEN_EOL); } +[ \t] { ; } -[0-9]+ { - char* p = nullptr; - yylval.s.val.intValue = std::strtol(yytext, &p, 10); - YYLEX(TOKEN_INTEGER); - } -[0-9\.]+|[0-9\.]+("e+"|"e-")+[0-9\.] { - char* p = nullptr; - yylval.s.val.floatValue = std::strtof(yytext, &p); - YYLEX(TOKEN_FLOAT); - } +[0-9]+ { + char* p = nullptr; + yylval.s.val.intValue = std::strtol(yytext, &p, 10); + YYLEX(TOKEN_INTEGER); + } -{identifier}* { - BEGIN(INITIAL); - TextEscapeValue(yytext, yyleng); - YYLEX(TOKEN_IDENTIFIER); - } -[ \t\r\n] { - BEGIN(INITIAL); - unput(yytext[yyleng - 1]); - yyreducepos(1); - TextEscapeValue(yytext, yyleng - 1); - YYLEXOFF(TOKEN_IDENTIFIER, 1); - } -. { - BEGIN(INITIAL); - unput(yytext[yyleng - 1]); - yyreducepos(1); - TextEscapeValue(yytext, yyleng - 1); - YYLEXOFF(TOKEN_IDENTIFIER, 1); - } +[0-9\.]+{nonnumeric} { + BEGIN(IDENTIFIER); + yymore(); + } -{identifier} { - BEGIN(IDENTIFIER); - yymore(); - } +[0-9\.]+|[0-9\.]+("e+"|"e-")+[0-9\.] { + char* p = nullptr; + yylval.s.val.floatValue = std::strtof(yytext, &p); + YYLEX(TOKEN_FLOAT); + } -[a-zA-Z0-9_]+ { - BEGIN(IDENTIFIER); - yymore(); - } +{identifier}* { + BEGIN(INITIAL); + TextEscapeValue(yytext, yyleng); + YYLEX(TOKEN_IDENTIFIER); + } +[ \t\r\n] { + BEGIN(INITIAL); + unput(yytext[yyleng - 1]); + yyreducepos(1); + TextEscapeValue(yytext, yyleng - 1); + YYLEXOFF(TOKEN_IDENTIFIER, 1); + } +. { + BEGIN(INITIAL); + unput(yytext[yyleng - 1]); + yyreducepos(1); + TextEscapeValue(yytext, yyleng - 1); + YYLEXOFF(TOKEN_IDENTIFIER, 1); + } - diff --git a/code/win32/RCa13168 b/code/win32/RCa13168 deleted file mode 100644 index 063466fc..00000000 Binary files a/code/win32/RCa13168 and /dev/null differ diff --git a/code/win32/background.bmp b/code/win32/background.bmp deleted file mode 100644 index 88b3dabf..00000000 Binary files a/code/win32/background.bmp and /dev/null differ diff --git a/code/win32/clear.bmp b/code/win32/clear.bmp deleted file mode 100644 index 14516380..00000000 Binary files a/code/win32/clear.bmp and /dev/null differ diff --git a/code/win32/glw_win.h b/code/win32/glw_win.h deleted file mode 100644 index e90377bd..00000000 --- a/code/win32/glw_win.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#ifndef _WIN32 -# error You should not be including this file on this platform -#endif - -#ifndef __GLW_WIN_H__ -#define __GLW_WIN_H__ - -typedef struct -{ - WNDPROC wndproc; - - HDC hDC; // handle to device context - HGLRC hGLRC; // handle to GL rendering context - - HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library - - qboolean allowdisplaydepthchange; - qboolean pixelFormatSet; - - int desktopBitsPixel; - int desktopWidth, desktopHeight; - - qboolean cdsFullscreen; - - FILE *log_fp; -} glwstate_t; - -extern glwstate_t glw_state; - -#endif diff --git a/code/win32/icon2.ico b/code/win32/icon2.ico deleted file mode 100644 index 8ba93283..00000000 Binary files a/code/win32/icon2.ico and /dev/null differ diff --git a/code/win32/mod-sdk-setup/GameSource.VCT b/code/win32/mod-sdk-setup/GameSource.VCT deleted file mode 100644 index b9dda618..00000000 Binary files a/code/win32/mod-sdk-setup/GameSource.VCT and /dev/null differ diff --git a/code/win32/mod-sdk-setup/QIIIA Game Source License.doc b/code/win32/mod-sdk-setup/QIIIA Game Source License.doc deleted file mode 100644 index 790e7fe4..00000000 Binary files a/code/win32/mod-sdk-setup/QIIIA Game Source License.doc and /dev/null differ diff --git a/code/win32/mod-sdk-setup/bin/lcc.exe b/code/win32/mod-sdk-setup/bin/lcc.exe deleted file mode 100644 index ff0b2864..00000000 Binary files a/code/win32/mod-sdk-setup/bin/lcc.exe and /dev/null differ diff --git a/code/win32/mod-sdk-setup/bin/q3asm.exe b/code/win32/mod-sdk-setup/bin/q3asm.exe deleted file mode 100644 index ba9fd3d6..00000000 Binary files a/code/win32/mod-sdk-setup/bin/q3asm.exe and /dev/null differ diff --git a/code/win32/mod-sdk-setup/bin/q3cpp.exe b/code/win32/mod-sdk-setup/bin/q3cpp.exe deleted file mode 100644 index 55e68a10..00000000 Binary files a/code/win32/mod-sdk-setup/bin/q3cpp.exe and /dev/null differ diff --git a/code/win32/mod-sdk-setup/bin/q3rcc.exe b/code/win32/mod-sdk-setup/bin/q3rcc.exe deleted file mode 100644 index 8f09cab7..00000000 Binary files a/code/win32/mod-sdk-setup/bin/q3rcc.exe and /dev/null differ diff --git a/code/win32/qe3.ico b/code/win32/qe3.ico deleted file mode 100644 index a7f4f0a3..00000000 Binary files a/code/win32/qe3.ico and /dev/null differ diff --git a/code/win32/resource.h b/code/win32/resource.h deleted file mode 100644 index 21899cae..00000000 --- a/code/win32/resource.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by winquake.rc -// -#define IDS_STRING1 1 -#define IDI_ICON1 1 -#define IDB_BITMAP1 1 -#define IDB_BITMAP2 128 -#define IDC_CURSOR1 129 -#define IDC_CURSOR2 130 -#define IDC_CURSOR3 131 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 132 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1005 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/code/win32/win_gamma.c b/code/win32/win_gamma.c deleted file mode 100644 index 1473dffa..00000000 --- a/code/win32/win_gamma.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -/* -** WIN_GAMMA.C -*/ -#include -#include "../renderer/tr_local.h" -#include "../qcommon/qcommon.h" -#include "glw_win.h" -#include "win_local.h" - -static unsigned short s_oldHardwareGamma[3][256]; - -/* -** WG_CheckHardwareGamma -** -** Determines if the underlying hardware supports the Win32 gamma correction API. -*/ -void WG_CheckHardwareGamma( void ) -{ - HDC hDC; - - glConfig.deviceSupportsGamma = qfalse; - - if ( qwglSetDeviceGammaRamp3DFX ) - { - glConfig.deviceSupportsGamma = qtrue; - - hDC = GetDC( GetDesktopWindow() ); - glConfig.deviceSupportsGamma = qwglGetDeviceGammaRamp3DFX( hDC, s_oldHardwareGamma ); - ReleaseDC( GetDesktopWindow(), hDC ); - - return; - } - - // non-3Dfx standalone drivers don't support gamma changes, period - if ( glConfig.driverType == GLDRV_STANDALONE ) - { - return; - } - - if ( !r_ignorehwgamma->integer ) - { - hDC = GetDC( GetDesktopWindow() ); - glConfig.deviceSupportsGamma = GetDeviceGammaRamp( hDC, s_oldHardwareGamma ); - ReleaseDC( GetDesktopWindow(), hDC ); - - if ( glConfig.deviceSupportsGamma ) - { - // - // do a sanity check on the gamma values - // - if ( ( HIBYTE( s_oldHardwareGamma[0][255] ) <= HIBYTE( s_oldHardwareGamma[0][0] ) ) || - ( HIBYTE( s_oldHardwareGamma[1][255] ) <= HIBYTE( s_oldHardwareGamma[1][0] ) ) || - ( HIBYTE( s_oldHardwareGamma[2][255] ) <= HIBYTE( s_oldHardwareGamma[2][0] ) ) ) - { - glConfig.deviceSupportsGamma = qfalse; - ri.Printf( PRINT_WARNING, "WARNING: device has broken gamma support, generated gamma.dat\n" ); - } - - // - // make sure that we didn't have a prior crash in the game, and if so we need to - // restore the gamma values to at least a linear value - // - if ( ( HIBYTE( s_oldHardwareGamma[0][181] ) == 255 ) ) - { - int g; - - ri.Printf( PRINT_WARNING, "WARNING: suspicious gamma tables, using linear ramp for restoration\n" ); - - for ( g = 0; g < 255; g++ ) - { - s_oldHardwareGamma[0][g] = g << 8; - s_oldHardwareGamma[1][g] = g << 8; - s_oldHardwareGamma[2][g] = g << 8; - } - } - } - } -} - -/* -void mapGammaMax( void ) { - int i, j; - unsigned short table[3][256]; - - // try to figure out what win2k will let us get away with setting - for ( i = 0 ; i < 256 ; i++ ) { - if ( i >= 128 ) { - table[0][i] = table[1][i] = table[2][i] = 0xffff; - } else { - table[0][i] = table[1][i] = table[2][i] = i<<9; - } - } - - for ( i = 0 ; i < 128 ; i++ ) { - for ( j = i*2 ; j < 255 ; j++ ) { - table[0][i] = table[1][i] = table[2][i] = j<<8; - if ( !SetDeviceGammaRamp( glw_state.hDC, table ) ) { - break; - } - } - table[0][i] = table[1][i] = table[2][i] = i<<9; - Com_Printf( "index %i max: %i\n", i, j-1 ); - } -} -*/ - -/* -** GLimp_SetGamma -** -** This routine should only be called if glConfig.deviceSupportsGamma is TRUE -*/ -void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) { - unsigned short table[3][256]; - int i, j; - int ret; - OSVERSIONINFO vinfo; - - if ( !glConfig.deviceSupportsGamma || r_ignorehwgamma->integer || !glw_state.hDC ) { - return; - } - -//mapGammaMax(); - - for ( i = 0; i < 256; i++ ) { - table[0][i] = ( ( ( unsigned short ) red[i] ) << 8 ) | red[i]; - table[1][i] = ( ( ( unsigned short ) green[i] ) << 8 ) | green[i]; - table[2][i] = ( ( ( unsigned short ) blue[i] ) << 8 ) | blue[i]; - } - - // Win2K puts this odd restriction on gamma ramps... - vinfo.dwOSVersionInfoSize = sizeof(vinfo); - GetVersionEx( &vinfo ); - if ( vinfo.dwMajorVersion == 5 && vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) { - Com_DPrintf( "performing W2K gamma clamp.\n" ); - for ( j = 0 ; j < 3 ; j++ ) { - for ( i = 0 ; i < 128 ; i++ ) { - if ( table[j][i] > ( (128+i) << 8 ) ) { - table[j][i] = (128+i) << 8; - } - } - if ( table[j][127] > 254<<8 ) { - table[j][127] = 254<<8; - } - } - } else { - Com_DPrintf( "skipping W2K gamma clamp.\n" ); - } - - // enforce constantly increasing - for ( j = 0 ; j < 3 ; j++ ) { - for ( i = 1 ; i < 256 ; i++ ) { - if ( table[j][i] < table[j][i-1] ) { - table[j][i] = table[j][i-1]; - } - } - } - - - if ( qwglSetDeviceGammaRamp3DFX ) - { - qwglSetDeviceGammaRamp3DFX( glw_state.hDC, table ); - } - else - { - ret = SetDeviceGammaRamp( glw_state.hDC, table ); - if ( !ret ) { - Com_Printf( "SetDeviceGammaRamp failed.\n" ); - } - } -} - -/* -** WG_RestoreGamma -*/ -void WG_RestoreGamma( void ) -{ - if ( glConfig.deviceSupportsGamma ) - { - if ( qwglSetDeviceGammaRamp3DFX ) - { - qwglSetDeviceGammaRamp3DFX( glw_state.hDC, s_oldHardwareGamma ); - } - else - { - HDC hDC; - - hDC = GetDC( GetDesktopWindow() ); - SetDeviceGammaRamp( hDC, s_oldHardwareGamma ); - ReleaseDC( GetDesktopWindow(), hDC ); - } - } -} - diff --git a/code/win32/win_glimp.c b/code/win32/win_glimp.c deleted file mode 100644 index ecc02546..00000000 --- a/code/win32/win_glimp.c +++ /dev/null @@ -1,1669 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -/* -** WIN_GLIMP.C -** -** This file contains ALL Win32 specific stuff having to do with the -** OpenGL refresh. When a port is being made the following functions -** must be implemented by the port: -** -** GLimp_EndFrame -** GLimp_Init -** GLimp_LogComment -** GLimp_Shutdown -** -** Note that the GLW_xxx functions are Windows specific GL-subsystem -** related functions that are relevant ONLY to win_glimp.c -*/ -#include -#include "../renderer/tr_local.h" -#include "../qcommon/qcommon.h" -#include "resource.h" -#include "glw_win.h" -#include "win_local.h" - -extern void WG_CheckHardwareGamma( void ); -extern void WG_RestoreGamma( void ); - -typedef enum { - RSERR_OK, - - RSERR_INVALID_FULLSCREEN, - RSERR_INVALID_MODE, - - RSERR_UNKNOWN -} rserr_t; - -#define TRY_PFD_SUCCESS 0 -#define TRY_PFD_FAIL_SOFT 1 -#define TRY_PFD_FAIL_HARD 2 - -#define WINDOW_CLASS_NAME PRODUCT_NAME_FULL -#define WINDOW_TITLE_NAME PRODUCT_NAME_FULL - -static void GLW_InitExtensions( void ); -static rserr_t GLW_SetMode( const char *drivername, - int mode, - int colorbits, - qboolean cdsFullscreen ); - -static qboolean s_classRegistered = qfalse; - -// -// function declaration -// -void QGL_EnableLogging( qboolean enable ); -qboolean QGL_Init( const char *dllname ); -void QGL_Shutdown( void ); - -// -// variable declarations -// -glwstate_t glw_state; - -cvar_t *r_allowSoftwareGL; // don't abort out if the pixelformat claims software -cvar_t *r_maskMinidriver; // allow a different dll name to be treated as if it were opengl32.dll - - - -/* -** GLW_StartDriverAndSetMode -*/ -static qboolean GLW_StartDriverAndSetMode( const char *drivername, - int mode, - int colorbits, - qboolean cdsFullscreen ) -{ - rserr_t err; - - err = GLW_SetMode( drivername, r_mode->integer, colorbits, cdsFullscreen ); - - switch ( err ) - { - case RSERR_INVALID_FULLSCREEN: - ri.Printf( PRINT_ALL, "...WARNING: fullscreen unavailable in this mode\n" ); - return qfalse; - case RSERR_INVALID_MODE: - ri.Printf( PRINT_ALL, "...WARNING: could not set the given mode (%d)\n", mode ); - return qfalse; - default: - break; - } - return qtrue; -} - -/* -** ChoosePFD -** -** Helper function that replaces ChoosePixelFormat. -*/ -#define MAX_PFDS 256 - -static int GLW_ChoosePFD( HDC hDC, PIXELFORMATDESCRIPTOR *pPFD ) -{ - PIXELFORMATDESCRIPTOR pfds[MAX_PFDS+1]; - int maxPFD = 0; - int i; - int bestMatch = 0; - - ri.Printf( PRINT_ALL, "...GLW_ChoosePFD( %d, %d, %d )\n", ( int ) pPFD->cColorBits, ( int ) pPFD->cDepthBits, ( int ) pPFD->cStencilBits ); - - // count number of PFDs - if ( glConfig.driverType > GLDRV_ICD ) - { - maxPFD = qwglDescribePixelFormat( hDC, 1, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[0] ); - } - else - { - maxPFD = DescribePixelFormat( hDC, 1, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[0] ); - } - if ( maxPFD > MAX_PFDS ) - { - ri.Printf( PRINT_WARNING, "...numPFDs > MAX_PFDS (%d > %d)\n", maxPFD, MAX_PFDS ); - maxPFD = MAX_PFDS; - } - - ri.Printf( PRINT_ALL, "...%d PFDs found\n", maxPFD - 1 ); - - // grab information - for ( i = 1; i <= maxPFD; i++ ) - { - if ( glConfig.driverType > GLDRV_ICD ) - { - qwglDescribePixelFormat( hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[i] ); - } - else - { - DescribePixelFormat( hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfds[i] ); - } - } - - // look for a best match - for ( i = 1; i <= maxPFD; i++ ) - { - // - // make sure this has hardware acceleration - // - if ( ( pfds[i].dwFlags & PFD_GENERIC_FORMAT ) != 0 ) - { - if ( !r_allowSoftwareGL->integer ) - { - if ( r_verbose->integer ) - { - ri.Printf( PRINT_ALL, "...PFD %d rejected, software acceleration\n", i ); - } - continue; - } - } - - // verify pixel type - if ( pfds[i].iPixelType != PFD_TYPE_RGBA ) - { - if ( r_verbose->integer ) - { - ri.Printf( PRINT_ALL, "...PFD %d rejected, not RGBA\n", i ); - } - continue; - } - - // verify proper flags - if ( ( ( pfds[i].dwFlags & pPFD->dwFlags ) & pPFD->dwFlags ) != pPFD->dwFlags ) - { - if ( r_verbose->integer ) - { - ri.Printf( PRINT_ALL, "...PFD %d rejected, improper flags (%x instead of %x)\n", i, pfds[i].dwFlags, pPFD->dwFlags ); - } - continue; - } - - // verify enough bits - if ( pfds[i].cDepthBits < 15 ) - { - continue; - } - if ( ( pfds[i].cStencilBits < 4 ) && ( pPFD->cStencilBits > 0 ) ) - { - continue; - } - - // - // selection criteria (in order of priority): - // - // PFD_STEREO - // colorBits - // depthBits - // stencilBits - // - if ( bestMatch ) - { - // check stereo - if ( ( pfds[i].dwFlags & PFD_STEREO ) && ( !( pfds[bestMatch].dwFlags & PFD_STEREO ) ) && ( pPFD->dwFlags & PFD_STEREO ) ) - { - bestMatch = i; - continue; - } - - if ( !( pfds[i].dwFlags & PFD_STEREO ) && ( pfds[bestMatch].dwFlags & PFD_STEREO ) && ( pPFD->dwFlags & PFD_STEREO ) ) - { - bestMatch = i; - continue; - } - - // check color - if ( pfds[bestMatch].cColorBits != pPFD->cColorBits ) - { - // prefer perfect match - if ( pfds[i].cColorBits == pPFD->cColorBits ) - { - bestMatch = i; - continue; - } - // otherwise if this PFD has more bits than our best, use it - else if ( pfds[i].cColorBits > pfds[bestMatch].cColorBits ) - { - bestMatch = i; - continue; - } - } - - // check depth - if ( pfds[bestMatch].cDepthBits != pPFD->cDepthBits ) - { - // prefer perfect match - if ( pfds[i].cDepthBits == pPFD->cDepthBits ) - { - bestMatch = i; - continue; - } - // otherwise if this PFD has more bits than our best, use it - else if ( pfds[i].cDepthBits > pfds[bestMatch].cDepthBits ) - { - bestMatch = i; - continue; - } - } - - // check stencil - if ( pfds[bestMatch].cStencilBits != pPFD->cStencilBits ) - { - // prefer perfect match - if ( pfds[i].cStencilBits == pPFD->cStencilBits ) - { - bestMatch = i; - continue; - } - // otherwise if this PFD has more bits than our best, use it - else if ( ( pfds[i].cStencilBits > pfds[bestMatch].cStencilBits ) && - ( pPFD->cStencilBits > 0 ) ) - { - bestMatch = i; - continue; - } - } - } - else - { - bestMatch = i; - } - } - - if ( !bestMatch ) - return 0; - - if ( ( pfds[bestMatch].dwFlags & PFD_GENERIC_FORMAT ) != 0 ) - { - if ( !r_allowSoftwareGL->integer ) - { - ri.Printf( PRINT_ALL, "...no hardware acceleration found\n" ); - return 0; - } - else - { - ri.Printf( PRINT_ALL, "...using software emulation\n" ); - } - } - else if ( pfds[bestMatch].dwFlags & PFD_GENERIC_ACCELERATED ) - { - ri.Printf( PRINT_ALL, "...MCD acceleration found\n" ); - } - else - { - ri.Printf( PRINT_ALL, "...hardware acceleration found\n" ); - } - - *pPFD = pfds[bestMatch]; - - return bestMatch; -} - -/* -** void GLW_CreatePFD -** -** Helper function zeros out then fills in a PFD -*/ -static void GLW_CreatePFD( PIXELFORMATDESCRIPTOR *pPFD, int colorbits, int depthbits, int stencilbits, qboolean stereo ) -{ - PIXELFORMATDESCRIPTOR src = - { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - PFD_DRAW_TO_WINDOW | // support window - PFD_SUPPORT_OPENGL | // support OpenGL - PFD_DOUBLEBUFFER, // double buffered - PFD_TYPE_RGBA, // RGBA type - 24, // 24-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 0, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 24, // 24-bit z-buffer - 8, // 8-bit stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - - src.cColorBits = colorbits; - src.cDepthBits = depthbits; - src.cStencilBits = stencilbits; - - if ( stereo ) - { - ri.Printf( PRINT_ALL, "...attempting to use stereo\n" ); - src.dwFlags |= PFD_STEREO; - glConfig.stereoEnabled = qtrue; - } - else - { - glConfig.stereoEnabled = qfalse; - } - - *pPFD = src; -} - -/* -** GLW_MakeContext -*/ -static int GLW_MakeContext( PIXELFORMATDESCRIPTOR *pPFD ) -{ - int pixelformat; - - // - // don't putz around with pixelformat if it's already set (e.g. this is a soft - // reset of the graphics system) - // - if ( !glw_state.pixelFormatSet ) - { - // - // choose, set, and describe our desired pixel format. If we're - // using a minidriver then we need to bypass the GDI functions, - // otherwise use the GDI functions. - // - if ( ( pixelformat = GLW_ChoosePFD( glw_state.hDC, pPFD ) ) == 0 ) - { - ri.Printf( PRINT_ALL, "...GLW_ChoosePFD failed\n"); - return TRY_PFD_FAIL_SOFT; - } - ri.Printf( PRINT_ALL, "...PIXELFORMAT %d selected\n", pixelformat ); - - if ( glConfig.driverType > GLDRV_ICD ) - { - qwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( *pPFD ), pPFD ); - if ( qwglSetPixelFormat( glw_state.hDC, pixelformat, pPFD ) == FALSE ) - { - ri.Printf ( PRINT_ALL, "...qwglSetPixelFormat failed\n"); - return TRY_PFD_FAIL_SOFT; - } - } - else - { - DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( *pPFD ), pPFD ); - - if ( SetPixelFormat( glw_state.hDC, pixelformat, pPFD ) == FALSE ) - { - ri.Printf (PRINT_ALL, "...SetPixelFormat failed\n", glw_state.hDC ); - return TRY_PFD_FAIL_SOFT; - } - } - - glw_state.pixelFormatSet = qtrue; - } - - // - // startup the OpenGL subsystem by creating a context and making it current - // - if ( !glw_state.hGLRC ) - { - ri.Printf( PRINT_ALL, "...creating GL context: " ); - if ( ( glw_state.hGLRC = qwglCreateContext( glw_state.hDC ) ) == 0 ) - { - ri.Printf (PRINT_ALL, "failed\n"); - - return TRY_PFD_FAIL_HARD; - } - ri.Printf( PRINT_ALL, "succeeded\n" ); - - ri.Printf( PRINT_ALL, "...making context current: " ); - if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) - { - qwglDeleteContext( glw_state.hGLRC ); - glw_state.hGLRC = NULL; - ri.Printf (PRINT_ALL, "failed\n"); - return TRY_PFD_FAIL_HARD; - } - ri.Printf( PRINT_ALL, "succeeded\n" ); - } - - return TRY_PFD_SUCCESS; -} - - -/* -** GLW_InitDriver -** -** - get a DC if one doesn't exist -** - create an HGLRC if one doesn't exist -*/ -static qboolean GLW_InitDriver( const char *drivername, int colorbits ) -{ - int tpfd; - int depthbits, stencilbits; - static PIXELFORMATDESCRIPTOR pfd; // save between frames since 'tr' gets cleared - - ri.Printf( PRINT_ALL, "Initializing OpenGL driver\n" ); - - // - // get a DC for our window if we don't already have one allocated - // - if ( glw_state.hDC == NULL ) - { - ri.Printf( PRINT_ALL, "...getting DC: " ); - - if ( ( glw_state.hDC = GetDC( g_wv.hWnd ) ) == NULL ) - { - ri.Printf( PRINT_ALL, "failed\n" ); - return qfalse; - } - ri.Printf( PRINT_ALL, "succeeded\n" ); - } - - if ( colorbits == 0 ) - { - colorbits = glw_state.desktopBitsPixel; - } - - // - // implicitly assume Z-buffer depth == desktop color depth - // - if ( r_depthbits->integer == 0 ) { - if ( colorbits > 16 ) { - depthbits = 24; - } else { - depthbits = 16; - } - } else { - depthbits = r_depthbits->integer; - } - - // - // do not allow stencil if Z-buffer depth likely won't contain it - // - stencilbits = r_stencilbits->integer; - if ( depthbits < 24 ) - { - stencilbits = 0; - } - - // - // make two attempts to set the PIXELFORMAT - // - - // - // first attempt: r_colorbits, depthbits, and r_stencilbits - // - if ( !glw_state.pixelFormatSet ) - { - GLW_CreatePFD( &pfd, colorbits, depthbits, stencilbits, r_stereo->integer ); - if ( ( tpfd = GLW_MakeContext( &pfd ) ) != TRY_PFD_SUCCESS ) - { - if ( tpfd == TRY_PFD_FAIL_HARD ) - { - ri.Printf( PRINT_WARNING, "...failed hard\n" ); - return qfalse; - } - - // - // punt if we've already tried the desktop bit depth and no stencil bits - // - if ( ( r_colorbits->integer == glw_state.desktopBitsPixel ) && - ( stencilbits == 0 ) ) - { - ReleaseDC( g_wv.hWnd, glw_state.hDC ); - glw_state.hDC = NULL; - - ri.Printf( PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n" ); - - return qfalse; - } - - // - // second attempt: desktop's color bits and no stencil - // - if ( colorbits > glw_state.desktopBitsPixel ) - { - colorbits = glw_state.desktopBitsPixel; - } - GLW_CreatePFD( &pfd, colorbits, depthbits, 0, r_stereo->integer ); - if ( GLW_MakeContext( &pfd ) != TRY_PFD_SUCCESS ) - { - if ( glw_state.hDC ) - { - ReleaseDC( g_wv.hWnd, glw_state.hDC ); - glw_state.hDC = NULL; - } - - ri.Printf( PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n" ); - - return qfalse; - } - } - - /* - ** report if stereo is desired but unavailable - */ - if ( !( pfd.dwFlags & PFD_STEREO ) && ( r_stereo->integer != 0 ) ) - { - ri.Printf( PRINT_ALL, "...failed to select stereo pixel format\n" ); - glConfig.stereoEnabled = qfalse; - } - } - - /* - ** store PFD specifics - */ - glConfig.colorBits = ( int ) pfd.cColorBits; - glConfig.depthBits = ( int ) pfd.cDepthBits; - glConfig.stencilBits = ( int ) pfd.cStencilBits; - - return qtrue; -} - -/* -** GLW_CreateWindow -** -** Responsible for creating the Win32 window and initializing the OpenGL driver. -*/ -#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE) -static qboolean GLW_CreateWindow( const char *drivername, int width, int height, int colorbits, qboolean cdsFullscreen ) -{ - RECT r; - cvar_t *vid_xpos, *vid_ypos; - int stylebits; - int x, y, w, h; - int exstyle; - - // - // register the window class if necessary - // - if ( !s_classRegistered ) - { - WNDCLASS wc; - - memset( &wc, 0, sizeof( wc ) ); - - wc.style = 0; - wc.lpfnWndProc = (WNDPROC) glw_state.wndproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = g_wv.hInstance; - wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1)); - wc.hCursor = LoadCursor (NULL,IDC_ARROW); - wc.hbrBackground = (void *)COLOR_GRAYTEXT; - wc.lpszMenuName = 0; - wc.lpszClassName = WINDOW_CLASS_NAME; - - if ( !RegisterClass( &wc ) ) - { - ri.Error( ERR_FATAL, "GLW_CreateWindow: could not register window class" ); - } - s_classRegistered = qtrue; - ri.Printf( PRINT_ALL, "...registered window class\n" ); - } - - // - // create the HWND if one does not already exist - // - if ( !g_wv.hWnd ) - { - // - // compute width and height - // - r.left = 0; - r.top = 0; - r.right = width; - r.bottom = height; - - if ( cdsFullscreen || !Q_stricmp( _3DFX_DRIVER_NAME, drivername ) ) - { - exstyle = WS_EX_TOPMOST; - stylebits = WS_POPUP|WS_VISIBLE|WS_SYSMENU; - } - else - { - exstyle = 0; - stylebits = WINDOW_STYLE|WS_SYSMENU; - AdjustWindowRect (&r, stylebits, FALSE); - } - - w = r.right - r.left; - h = r.bottom - r.top; - - if ( cdsFullscreen || !Q_stricmp( _3DFX_DRIVER_NAME, drivername ) ) - { - x = 0; - y = 0; - } - else - { - vid_xpos = ri.Cvar_Get ("vid_xpos", "", 0); - vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0); - x = vid_xpos->integer; - y = vid_ypos->integer; - - // adjust window coordinates if necessary - // so that the window is completely on screen - if ( x < 0 ) - x = 0; - if ( y < 0 ) - y = 0; - - if ( w < glw_state.desktopWidth && - h < glw_state.desktopHeight ) - { - if ( x + w > glw_state.desktopWidth ) - x = ( glw_state.desktopWidth - w ); - if ( y + h > glw_state.desktopHeight ) - y = ( glw_state.desktopHeight - h ); - } - } - - g_wv.hWnd = CreateWindowEx ( - exstyle, - WINDOW_CLASS_NAME, - WINDOW_TITLE_NAME, - stylebits, - x, y, w, h, - NULL, - NULL, - g_wv.hInstance, - NULL); - - if ( !g_wv.hWnd ) - { - ri.Error (ERR_FATAL, "GLW_CreateWindow() - Couldn't create window"); - } - - ShowWindow( g_wv.hWnd, SW_SHOW ); - UpdateWindow( g_wv.hWnd ); - ri.Printf( PRINT_ALL, "...created window@%d,%d (%dx%d)\n", x, y, w, h ); - } - else - { - ri.Printf( PRINT_ALL, "...window already present, CreateWindowEx skipped\n" ); - } - - if ( !GLW_InitDriver( drivername, colorbits ) ) - { - ShowWindow( g_wv.hWnd, SW_HIDE ); - DestroyWindow( g_wv.hWnd ); - g_wv.hWnd = NULL; - - return qfalse; - } - - SetForegroundWindow( g_wv.hWnd ); - SetFocus( g_wv.hWnd ); - - return qtrue; -} - -static void PrintCDSError( int value ) -{ - switch ( value ) - { - case DISP_CHANGE_RESTART: - ri.Printf( PRINT_ALL, "restart required\n" ); - break; - case DISP_CHANGE_BADPARAM: - ri.Printf( PRINT_ALL, "bad param\n" ); - break; - case DISP_CHANGE_BADFLAGS: - ri.Printf( PRINT_ALL, "bad flags\n" ); - break; - case DISP_CHANGE_FAILED: - ri.Printf( PRINT_ALL, "DISP_CHANGE_FAILED\n" ); - break; - case DISP_CHANGE_BADMODE: - ri.Printf( PRINT_ALL, "bad mode\n" ); - break; - case DISP_CHANGE_NOTUPDATED: - ri.Printf( PRINT_ALL, "not updated\n" ); - break; - default: - ri.Printf( PRINT_ALL, "unknown error %d\n", value ); - break; - } -} - -/* -** GLW_SetMode -*/ -static rserr_t GLW_SetMode( const char *drivername, - int mode, - int colorbits, - qboolean cdsFullscreen ) -{ - HDC hDC; - const char *win_fs[] = { "W", "FS" }; - int cdsRet; - DEVMODE dm; - - // - // print out informational messages - // - ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); - if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) - { - ri.Printf( PRINT_ALL, " invalid mode\n" ); - return RSERR_INVALID_MODE; - } - ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[cdsFullscreen] ); - - // - // check our desktop attributes - // - hDC = GetDC( GetDesktopWindow() ); - glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); - glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); - glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); - ReleaseDC( GetDesktopWindow(), hDC ); - - // - // verify desktop bit depth - // - if ( glConfig.driverType != GLDRV_VOODOO ) - { - if ( glw_state.desktopBitsPixel < 15 || glw_state.desktopBitsPixel == 24 ) - { - if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) - { - if ( MessageBox( NULL, - "It is highly unlikely that a correct\n" - "windowed display can be initialized with\n" - "the current desktop display depth. Select\n" - "'OK' to try anyway. Press 'Cancel' if you\n" - "have a 3Dfx Voodoo, Voodoo-2, or Voodoo Rush\n" - "3D accelerator installed, or if you otherwise\n" - "wish to quit.", - "Low Desktop Color Depth", - MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) - { - return RSERR_INVALID_MODE; - } - } - } - } - - // do a CDS if needed - if ( cdsFullscreen ) - { - memset( &dm, 0, sizeof( dm ) ); - - dm.dmSize = sizeof( dm ); - - dm.dmPelsWidth = glConfig.vidWidth; - dm.dmPelsHeight = glConfig.vidHeight; - dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - - if ( r_displayRefresh->integer != 0 ) - { - dm.dmDisplayFrequency = r_displayRefresh->integer; - dm.dmFields |= DM_DISPLAYFREQUENCY; - } - - // try to change color depth if possible - if ( colorbits != 0 ) - { - if ( glw_state.allowdisplaydepthchange ) - { - dm.dmBitsPerPel = colorbits; - dm.dmFields |= DM_BITSPERPEL; - ri.Printf( PRINT_ALL, "...using colorsbits of %d\n", colorbits ); - } - else - { - ri.Printf( PRINT_ALL, "WARNING:...changing depth not supported on Win95 < pre-OSR 2.x\n" ); - } - } - else - { - ri.Printf( PRINT_ALL, "...using desktop display depth of %d\n", glw_state.desktopBitsPixel ); - } - - // - // if we're already in fullscreen then just create the window - // - if ( glw_state.cdsFullscreen ) - { - ri.Printf( PRINT_ALL, "...already fullscreen, avoiding redundant CDS\n" ); - - if ( !GLW_CreateWindow ( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue ) ) - { - ri.Printf( PRINT_ALL, "...restoring display settings\n" ); - ChangeDisplaySettings( 0, 0 ); - return RSERR_INVALID_MODE; - } - } - // - // need to call CDS - // - else - { - ri.Printf( PRINT_ALL, "...calling CDS: " ); - - // try setting the exact mode requested, because some drivers don't report - // the low res modes in EnumDisplaySettings, but still work - if ( ( cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) - { - ri.Printf( PRINT_ALL, "ok\n" ); - - if ( !GLW_CreateWindow ( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) - { - ri.Printf( PRINT_ALL, "...restoring display settings\n" ); - ChangeDisplaySettings( 0, 0 ); - return RSERR_INVALID_MODE; - } - - glw_state.cdsFullscreen = qtrue; - } - else - { - // - // the exact mode failed, so scan EnumDisplaySettings for the next largest mode - // - DEVMODE devmode; - int modeNum; - - ri.Printf( PRINT_ALL, "failed, " ); - - PrintCDSError( cdsRet ); - - ri.Printf( PRINT_ALL, "...trying next higher resolution:" ); - - // we could do a better matching job here... - for ( modeNum = 0 ; ; modeNum++ ) { - if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { - modeNum = -1; - break; - } - if ( devmode.dmPelsWidth >= glConfig.vidWidth - && devmode.dmPelsHeight >= glConfig.vidHeight - && devmode.dmBitsPerPel >= 15 ) { - break; - } - } - - if ( modeNum != -1 && ( cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) - { - ri.Printf( PRINT_ALL, " ok\n" ); - if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) - { - ri.Printf( PRINT_ALL, "...restoring display settings\n" ); - ChangeDisplaySettings( 0, 0 ); - return RSERR_INVALID_MODE; - } - - glw_state.cdsFullscreen = qtrue; - } - else - { - ri.Printf( PRINT_ALL, " failed, " ); - - PrintCDSError( cdsRet ); - - ri.Printf( PRINT_ALL, "...restoring display settings\n" ); - ChangeDisplaySettings( 0, 0 ); - - glw_state.cdsFullscreen = qfalse; - glConfig.isFullscreen = qfalse; - if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse) ) - { - return RSERR_INVALID_MODE; - } - return RSERR_INVALID_FULLSCREEN; - } - } - } - } - else - { - if ( glw_state.cdsFullscreen ) - { - ChangeDisplaySettings( 0, 0 ); - } - - glw_state.cdsFullscreen = qfalse; - if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse ) ) - { - return RSERR_INVALID_MODE; - } - } - - // - // success, now check display frequency, although this won't be valid on Voodoo(2) - // - memset( &dm, 0, sizeof( dm ) ); - dm.dmSize = sizeof( dm ); - if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) - { - glConfig.displayFrequency = dm.dmDisplayFrequency; - } - - // NOTE: this is overridden later on standalone 3Dfx drivers - glConfig.isFullscreen = cdsFullscreen; - - return RSERR_OK; -} - -/* -** GLW_InitExtensions -*/ -static void GLW_InitExtensions( void ) -{ - if ( !r_allowExtensions->integer ) - { - ri.Printf( PRINT_ALL, "*** IGNORING OPENGL EXTENSIONS ***\n" ); - return; - } - - ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" ); - - // GL_S3_s3tc - qglCompressedTexImage2DARB = NULL; - glConfig.textureCompression = TC_NONE; - if ( strstr( glConfig.extensions_string, "GL_EXT_texture_compression_s3tc" ) && strstr(glConfig.extensions_string, "GL_ARB_texture_compression")) - { - if ( r_ext_compressed_textures->integer ) - { - qglCompressedTexImage2DARB = wglGetProcAddress("glCompressedTexImage2DARB"); - glConfig.textureCompression = TC_S3TC; - ri.Printf( PRINT_ALL, "...using GL_S3_s3tc\n" ); - } - else - { - glConfig.textureCompression = TC_NONE; - ri.Printf( PRINT_ALL, "...ignoring GL_S3_s3tc\n" ); - } - } - else if (!strstr(glConfig.extensions_string, "GL_EXT_texture_compression_s3tc")) - { - ri.Printf(PRINT_ALL, "...GL_ARB_texture_compression not found\n"); - } - else if (strstr(glConfig.extensions_string, "GL_ARB_texture_compression")) - { - ri.Printf(PRINT_ALL, "...GL_EXT_texture_compression_s3tc not found\n"); - } - else - { - ri.Printf(PRINT_ALL, "...GL_EXT_texture_compression_s3tc not found\n"); - ri.Printf(PRINT_ALL, "...GL_ARB_texture_compression not found\n"); - } - - // GL_EXT_texture_env_add - glConfig.textureEnvAddAvailable = qfalse; - if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) ) - { - if ( r_ext_texture_env_add->integer ) - { - glConfig.textureEnvAddAvailable = qtrue; - ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" ); - } - else - { - glConfig.textureEnvAddAvailable = qfalse; - ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" ); - } - } - else - { - ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" ); - } - - // WGL_EXT_swap_control - qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" ); - if ( qwglSwapIntervalEXT ) - { - ri.Printf( PRINT_ALL, "...using WGL_EXT_swap_control\n" ); - r_swapInterval->modified = qtrue; // force a set next frame - } - else - { - ri.Printf( PRINT_ALL, "...WGL_EXT_swap_control not found\n" ); - } - - // GL_ARB_multitexture - qglMultiTexCoord2fARB = NULL; - qglActiveTextureARB = NULL; - qglClientActiveTextureARB = NULL; - if ( strstr( glConfig.extensions_string, "GL_ARB_multitexture" ) ) - { - if ( r_ext_multitexture->integer ) - { - qglMultiTexCoord2fARB = ( PFNGLMULTITEXCOORD2FARBPROC ) qwglGetProcAddress( "glMultiTexCoord2fARB" ); - qglActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC ) qwglGetProcAddress( "glActiveTextureARB" ); - qglClientActiveTextureARB = ( PFNGLCLIENTACTIVETEXTUREARBPROC ) qwglGetProcAddress( "glClientActiveTextureARB" ); - - if ( qglActiveTextureARB ) - { - qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures ); - - if ( glConfig.maxActiveTextures > 1 ) - { - ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" ); - } - else - { - qglMultiTexCoord2fARB = NULL; - qglActiveTextureARB = NULL; - qglClientActiveTextureARB = NULL; - ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" ); - } - } - } - else - { - ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" ); - } - } - else - { - ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" ); - } - - // GL_EXT_compiled_vertex_array - qglLockArraysEXT = NULL; - qglUnlockArraysEXT = NULL; - if ( strstr( glConfig.extensions_string, "GL_EXT_compiled_vertex_array" ) && ( glConfig.hardwareType != GLHW_RIVA128 ) ) - { - if ( r_ext_compiled_vertex_array->integer ) - { - ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" ); - qglLockArraysEXT = ( void ( APIENTRY * )( int, int ) ) qwglGetProcAddress( "glLockArraysEXT" ); - qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) qwglGetProcAddress( "glUnlockArraysEXT" ); - if (!qglLockArraysEXT || !qglUnlockArraysEXT) { - ri.Error (ERR_FATAL, "bad getprocaddress"); - } - } - else - { - ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" ); - } - } - else - { - ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" ); - } - - // WGL_3DFX_gamma_control - qwglGetDeviceGammaRamp3DFX = NULL; - qwglSetDeviceGammaRamp3DFX = NULL; - - if ( strstr( glConfig.extensions_string, "WGL_3DFX_gamma_control" ) ) - { - if ( !r_ignorehwgamma->integer && r_ext_gamma_control->integer ) - { - qwglGetDeviceGammaRamp3DFX = ( BOOL ( WINAPI * )( HDC, LPVOID ) ) qwglGetProcAddress( "wglGetDeviceGammaRamp3DFX" ); - qwglSetDeviceGammaRamp3DFX = ( BOOL ( WINAPI * )( HDC, LPVOID ) ) qwglGetProcAddress( "wglSetDeviceGammaRamp3DFX" ); - - if ( qwglGetDeviceGammaRamp3DFX && qwglSetDeviceGammaRamp3DFX ) - { - ri.Printf( PRINT_ALL, "...using WGL_3DFX_gamma_control\n" ); - } - else - { - qwglGetDeviceGammaRamp3DFX = NULL; - qwglSetDeviceGammaRamp3DFX = NULL; - } - } - else - { - ri.Printf( PRINT_ALL, "...ignoring WGL_3DFX_gamma_control\n" ); - } - } - else - { - ri.Printf( PRINT_ALL, "...WGL_3DFX_gamma_control not found\n" ); - } -} - -/* -** GLW_CheckOSVersion -*/ -static qboolean GLW_CheckOSVersion( void ) -{ -#define OSR2_BUILD_NUMBER 1111 - - OSVERSIONINFO vinfo; - - vinfo.dwOSVersionInfoSize = sizeof(vinfo); - - glw_state.allowdisplaydepthchange = qfalse; - - if ( GetVersionEx( &vinfo) ) - { - if ( vinfo.dwMajorVersion > 4 ) - { - glw_state.allowdisplaydepthchange = qtrue; - } - else if ( vinfo.dwMajorVersion == 4 ) - { - if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) - { - glw_state.allowdisplaydepthchange = qtrue; - } - else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) - { - if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER ) - { - glw_state.allowdisplaydepthchange = qtrue; - } - } - } - } - else - { - ri.Printf( PRINT_ALL, "GLW_CheckOSVersion() - GetVersionEx failed\n" ); - return qfalse; - } - - return qtrue; -} - -/* -** GLW_LoadOpenGL -** -** GLimp_win.c internal function that attempts to load and use -** a specific OpenGL DLL. -*/ -static qboolean GLW_LoadOpenGL( const char *drivername ) -{ - char buffer[1024]; - qboolean cdsFullscreen; - - Q_strncpyz( buffer, drivername, sizeof(buffer) ); - Q_strlwr(buffer); - - // - // determine if we're on a standalone driver - // - if ( strstr( buffer, "opengl32" ) != 0 || r_maskMinidriver->integer ) - { - glConfig.driverType = GLDRV_ICD; - } - else - { - glConfig.driverType = GLDRV_STANDALONE; - - ri.Printf( PRINT_ALL, "...assuming '%s' is a standalone driver\n", drivername ); - - if ( strstr( buffer, _3DFX_DRIVER_NAME ) ) - { - glConfig.driverType = GLDRV_VOODOO; - } - } - - // disable the 3Dfx splash screen - _putenv("FX_GLIDE_NO_SPLASH=0"); - - // - // load the driver and bind our function pointers to it - // - if ( QGL_Init( buffer ) ) - { - cdsFullscreen = r_fullscreen->integer; - - // create the window and set up the context - if ( !GLW_StartDriverAndSetMode( drivername, r_mode->integer, r_colorbits->integer, cdsFullscreen ) ) - { - // if we're on a 24/32-bit desktop and we're going fullscreen on an ICD, - // try it again but with a 16-bit desktop - if ( glConfig.driverType == GLDRV_ICD ) - { - if ( r_colorbits->integer != 16 || - cdsFullscreen != qtrue || - r_mode->integer != 3 ) - { - if ( !GLW_StartDriverAndSetMode( drivername, 3, 16, qtrue ) ) - { - goto fail; - } - } - } - else - { - goto fail; - } - } - - if ( glConfig.driverType == GLDRV_VOODOO ) - { - glConfig.isFullscreen = qtrue; - } - - return qtrue; - } -fail: - - QGL_Shutdown(); - - return qfalse; -} - -/* -** GLimp_EndFrame -*/ -void GLimp_EndFrame (void) -{ - // - // swapinterval stuff - // - if ( r_swapInterval->modified ) { - r_swapInterval->modified = qfalse; - - if ( !glConfig.stereoEnabled ) { // why? - if ( qwglSwapIntervalEXT ) { - qwglSwapIntervalEXT( r_swapInterval->integer ); - } - } - } - - // don't flip if drawing to front buffer - if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 ) - { - if ( glConfig.driverType > GLDRV_ICD ) - { - if ( !qwglSwapBuffers( glw_state.hDC ) ) - { - ri.Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" ); - } - } - else - { - SwapBuffers( glw_state.hDC ); - } - } - - // check logging - QGL_EnableLogging( r_logFile->integer ); -} - -static void GLW_StartOpenGL( void ) -{ - qboolean attemptedOpenGL32 = qfalse; - qboolean attempted3Dfx = qfalse; - - // - // load and initialize the specific OpenGL driver - // - if ( !GLW_LoadOpenGL( r_glDriver->string ) ) - { - if ( !Q_stricmp( r_glDriver->string, OPENGL_DRIVER_NAME ) ) - { - attemptedOpenGL32 = qtrue; - } - else if ( !Q_stricmp( r_glDriver->string, _3DFX_DRIVER_NAME ) ) - { - attempted3Dfx = qtrue; - } - - if ( !attempted3Dfx ) - { - attempted3Dfx = qtrue; - if ( GLW_LoadOpenGL( _3DFX_DRIVER_NAME ) ) - { - ri.Cvar_Set( "r_glDriver", _3DFX_DRIVER_NAME ); - r_glDriver->modified = qfalse; - } - else - { - if ( !attemptedOpenGL32 ) - { - if ( !GLW_LoadOpenGL( OPENGL_DRIVER_NAME ) ) - { - ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" ); - } - ri.Cvar_Set( "r_glDriver", OPENGL_DRIVER_NAME ); - r_glDriver->modified = qfalse; - } - else - { - ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" ); - } - } - } - else if ( !attemptedOpenGL32 ) - { - attemptedOpenGL32 = qtrue; - if ( GLW_LoadOpenGL( OPENGL_DRIVER_NAME ) ) - { - ri.Cvar_Set( "r_glDriver", OPENGL_DRIVER_NAME ); - r_glDriver->modified = qfalse; - } - else - { - ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" ); - } - } - } -} - -/* -** GLimp_Init -** -** This is the platform specific OpenGL initialization function. It -** is responsible for loading OpenGL, initializing it, setting -** extensions, creating a window of the appropriate size, doing -** fullscreen manipulations, etc. Its overall responsibility is -** to make sure that a functional OpenGL subsystem is operating -** when it returns to the ref. -*/ -void GLimp_Init( void ) -{ - char buf[1024]; - cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE ); - cvar_t *cv; - - ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" ); - - // - // check OS version to see if we can do fullscreen display changes - // - if ( !GLW_CheckOSVersion() ) - { - ri.Error( ERR_FATAL, "GLimp_Init() - incorrect operating system\n" ); - } - - // save off hInstance and wndproc - cv = ri.Cvar_Get( "win_hinstance", "", 0 ); - sscanf( cv->string, "%zu", (uintptr_t*)&g_wv.hInstance); - - cv = ri.Cvar_Get( "win_wndproc", "", 0 ); - sscanf( cv->string, "%zu", (uintptr_t*)&glw_state.wndproc ); - - r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); - r_maskMinidriver = ri.Cvar_Get( "r_maskMinidriver", "0", CVAR_LATCH ); - - // load appropriate DLL and initialize subsystem - GLW_StartOpenGL(); - - // get our config strings - Q_strncpyz( glConfig.vendor_string, qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) ); - Q_strncpyz( glConfig.renderer_string, qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) ); - Q_strncpyz( glConfig.version_string, qglGetString (GL_VERSION), sizeof( glConfig.version_string ) ); - Q_strncpyz( glConfig.extensions_string, qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) ); - - // - // chipset specific configuration - // - Q_strncpyz( buf, glConfig.renderer_string, sizeof(buf) ); - Q_strlwr( buf ); - - // - // NOTE: if changing cvars, do it within this block. This allows them - // to be overridden when testing driver fixes, etc. but only sets - // them to their default state when the hardware is first installed/run. - // - if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) ) - { - glConfig.hardwareType = GLHW_GENERIC; - - ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" ); - - // VOODOO GRAPHICS w/ 2MB - if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) ) - { - ri.Cvar_Set( "r_picmip", "2" ); - ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); - } - else - { - ri.Cvar_Set( "r_picmip", "1" ); - - if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) ) - { - ri.Cvar_Set( "r_finish", "0" ); - } - // Savage3D and Savage4 should always have trilinear enabled - else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) ) - { - ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); - } - } - } - - // - // this is where hardware specific workarounds that should be - // detected/initialized every startup should go. - // - if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) ) - { - glConfig.hardwareType = GLHW_3DFX_2D3D; - } - // VOODOO GRAPHICS w/ 2MB - else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) ) - { - } - else if ( strstr( buf, "glzicd" ) ) - { - } - else if ( strstr( buf, "rage pro" ) || strstr( buf, "Rage Pro" ) || strstr( buf, "ragepro" ) ) - { - glConfig.hardwareType = GLHW_RAGEPRO; - } - else if ( strstr( buf, "rage 128" ) ) - { - } - else if ( strstr( buf, "permedia2" ) ) - { - glConfig.hardwareType = GLHW_PERMEDIA2; - } - else if ( strstr( buf, "riva 128" ) ) - { - glConfig.hardwareType = GLHW_RIVA128; - } - else if ( strstr( buf, "riva tnt " ) ) - { - } - - ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string ); - - GLW_InitExtensions(); - WG_CheckHardwareGamma(); -} - -/* -** GLimp_Shutdown -** -** This routine does all OS specific shutdown procedures for the OpenGL -** subsystem. -*/ -void GLimp_Shutdown( void ) -{ -// const char *strings[] = { "soft", "hard" }; - const char *success[] = { "failed", "success" }; - int retVal; - - // FIXME: Brian, we need better fallbacks from partially initialized failures - if ( !qwglMakeCurrent ) { - return; - } - - ri.Printf( PRINT_ALL, "Shutting down OpenGL subsystem\n" ); - - // restore gamma. We do this first because 3Dfx's extension needs a valid OGL subsystem - WG_RestoreGamma(); - - // set current context to NULL - if ( qwglMakeCurrent ) - { - retVal = qwglMakeCurrent( NULL, NULL ) != 0; - - ri.Printf( PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal] ); - } - - // delete HGLRC - if ( glw_state.hGLRC ) - { - retVal = qwglDeleteContext( glw_state.hGLRC ) != 0; - ri.Printf( PRINT_ALL, "...deleting GL context: %s\n", success[retVal] ); - glw_state.hGLRC = NULL; - } - - // release DC - if ( glw_state.hDC ) - { - retVal = ReleaseDC( g_wv.hWnd, glw_state.hDC ) != 0; - ri.Printf( PRINT_ALL, "...releasing DC: %s\n", success[retVal] ); - glw_state.hDC = NULL; - } - - // destroy window - if ( g_wv.hWnd ) - { - ri.Printf( PRINT_ALL, "...destroying window\n" ); - ShowWindow( g_wv.hWnd, SW_HIDE ); - DestroyWindow( g_wv.hWnd ); - g_wv.hWnd = NULL; - glw_state.pixelFormatSet = qfalse; - } - - // close the r_logFile - if ( glw_state.log_fp ) - { - fclose( glw_state.log_fp ); - glw_state.log_fp = 0; - } - - // reset display settings - if ( glw_state.cdsFullscreen ) - { - ri.Printf( PRINT_ALL, "...resetting display\n" ); - ChangeDisplaySettings( 0, 0 ); - glw_state.cdsFullscreen = qfalse; - } - - // shutdown QGL subsystem - QGL_Shutdown(); - - memset( &glConfig, 0, sizeof( glConfig ) ); - memset( &glState, 0, sizeof( glState ) ); -} - -/* -** GLimp_LogComment -*/ -void GLimp_LogComment( char *comment ) -{ - if ( glw_state.log_fp ) { - fprintf( glw_state.log_fp, "%s", comment ); - } -} - - -/* -=========================================================== - -SMP acceleration - -=========================================================== -*/ - -HANDLE renderCommandsEvent; -HANDLE renderCompletedEvent; -HANDLE renderActiveEvent; - -void (*glimpRenderThread)( void ); - -void GLimp_RenderThreadWrapper( void ) { - glimpRenderThread(); - - // unbind the context before we die - qwglMakeCurrent( glw_state.hDC, NULL ); -} - -/* -======================= -GLimp_SpawnRenderThread -======================= -*/ -HANDLE renderThreadHandle; -int renderThreadId; -qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) { - - renderCommandsEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); - renderCompletedEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); - renderActiveEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); - - glimpRenderThread = function; - - renderThreadHandle = CreateThread( - NULL, // LPSECURITY_ATTRIBUTES lpsa, - 0, // DWORD cbStack, - (LPTHREAD_START_ROUTINE)GLimp_RenderThreadWrapper, // LPTHREAD_START_ROUTINE lpStartAddr, - 0, // LPVOID lpvThreadParm, - 0, // DWORD fdwCreate, - &renderThreadId ); - - if ( !renderThreadHandle ) { - return qfalse; - } - - return qtrue; -} - -static void *smpData; -static int wglErrors; - -void *GLimp_RendererSleep( void ) { - void *data; - - if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) { - wglErrors++; - } - - ResetEvent( renderActiveEvent ); - - // after this, the front end can exit GLimp_FrontEndSleep - SetEvent( renderCompletedEvent ); - - WaitForSingleObject( renderCommandsEvent, INFINITE ); - - if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) { - wglErrors++; - } - - ResetEvent( renderCompletedEvent ); - ResetEvent( renderCommandsEvent ); - - data = smpData; - - // after this, the main thread can exit GLimp_WakeRenderer - SetEvent( renderActiveEvent ); - - return data; -} - - -void GLimp_FrontEndSleep( void ) { - WaitForSingleObject( renderCompletedEvent, INFINITE ); - - if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) { - wglErrors++; - } -} - - -void GLimp_WakeRenderer( void *data ) { - smpData = data; - - if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) { - wglErrors++; - } - - // after this, the renderer can continue through GLimp_RendererSleep - SetEvent( renderCommandsEvent ); - - WaitForSingleObject( renderActiveEvent, INFINITE ); -} - diff --git a/code/win32/win_input.c b/code/win32/win_input.c deleted file mode 100644 index 60e600dc..00000000 --- a/code/win32/win_input.c +++ /dev/null @@ -1,1149 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// win_input.c -- win32 mouse and joystick code -// 02/21/97 JCB Added extended DirectInput code to support external controllers. - -#include "../client/client.h" -#include "win_local.h" - - -typedef struct { - int oldButtonState; - - qboolean mouseActive; - qboolean mouseInitialized; - qboolean mouseStartupDelayed; // delay mouse init to try DI again when we have a window -} WinMouseVars_t; - -static WinMouseVars_t s_wmv; - -static int window_center_x, window_center_y; - -// -// MIDI definitions -// -static void IN_StartupMIDI( void ); -static void IN_ShutdownMIDI( void ); - -#define MAX_MIDIIN_DEVICES 8 - -typedef struct { - int numDevices; - MIDIINCAPS caps[MAX_MIDIIN_DEVICES]; - - HMIDIIN hMidiIn; -} MidiInfo_t; - -static MidiInfo_t s_midiInfo; - -// -// Joystick definitions -// -#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V - -typedef struct { - qboolean avail; - int id; // joystick number - JOYCAPS jc; - - int oldbuttonstate; - int oldpovstate; - - JOYINFOEX ji; -} joystickInfo_t; - -static joystickInfo_t joy; - - - -cvar_t *in_midi; -cvar_t *in_midiport; -cvar_t *in_midichannel; -cvar_t *in_mididevice; - -cvar_t *in_mouse; -cvar_t *in_logitechbug; -cvar_t *in_joystick; -cvar_t *in_joyBallScale; -cvar_t *in_debugJoystick; -cvar_t *joy_threshold; - -qboolean in_appactive; - -// forward-referenced functions -void IN_StartupJoystick (void); -void IN_JoyMove(void); - -static void MidiInfo_f( void ); - -/* -============================================================ - -WIN32 MOUSE CONTROL - -============================================================ -*/ - -/* -================ -IN_InitWin32Mouse -================ -*/ -void IN_InitWin32Mouse( void ) -{ -} - -/* -================ -IN_ShutdownWin32Mouse -================ -*/ -void IN_ShutdownWin32Mouse( void ) { -} - -/* -================ -IN_ActivateWin32Mouse -================ -*/ -void IN_ActivateWin32Mouse( void ) { - int width, height; - RECT window_rect; - - width = GetSystemMetrics (SM_CXSCREEN); - height = GetSystemMetrics (SM_CYSCREEN); - - GetWindowRect ( g_wv.hWnd, &window_rect); - if (window_rect.left < 0) - window_rect.left = 0; - if (window_rect.top < 0) - window_rect.top = 0; - if (window_rect.right >= width) - window_rect.right = width-1; - if (window_rect.bottom >= height-1) - window_rect.bottom = height-1; - window_center_x = (window_rect.right + window_rect.left)/2; - window_center_y = (window_rect.top + window_rect.bottom)/2; - - SetCursorPos (window_center_x, window_center_y); - - SetCapture ( g_wv.hWnd ); - ClipCursor (&window_rect); - while (ShowCursor (FALSE) >= 0) - ; -} - -/* -================ -IN_DeactivateWin32Mouse -================ -*/ -void IN_DeactivateWin32Mouse( void ) -{ - ClipCursor (NULL); - ReleaseCapture (); - while (ShowCursor (TRUE) < 0) - ; -} - -/* -================ -IN_Win32Mouse -================ -*/ -void IN_Win32Mouse( int *mx, int *my ) { - POINT current_pos; - - // find mouse movement - GetCursorPos (¤t_pos); - - // force the mouse to the center, so there's room to move - SetCursorPos (window_center_x, window_center_y); - - *mx = current_pos.x - window_center_x; - *my = current_pos.y - window_center_y; -} - - -/* -============================================================ - -DIRECT INPUT MOUSE CONTROL - -============================================================ -*/ - -#undef DEFINE_GUID - -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - EXTERN_C const GUID name \ - = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } - -DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - - -#define DINPUT_BUFFERSIZE 16 -#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) - -HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, - LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); - -static HINSTANCE hInstDI; - -typedef struct MYDATA { - LONG lX; // X axis goes here - LONG lY; // Y axis goes here - LONG lZ; // Z axis goes here - BYTE bButtonA; // One button goes here - BYTE bButtonB; // Another button goes here - BYTE bButtonC; // Another button goes here - BYTE bButtonD; // Another button goes here -} MYDATA; - -static DIOBJECTDATAFORMAT rgodf[] = { - { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, -}; - -#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) - -// NOTE TTimo: would be easier using c_dfDIMouse or c_dfDIMouse2 -static DIDATAFORMAT df = { - sizeof(DIDATAFORMAT), // this structure - sizeof(DIOBJECTDATAFORMAT), // size of object data format - DIDF_RELAXIS, // absolute axis coordinates - sizeof(MYDATA), // device data size - NUM_OBJECTS, // number of objects - rgodf, // and here they are -}; - -static LPDIRECTINPUT g_pdi; -static LPDIRECTINPUTDEVICE g_pMouse; - -void IN_DIMouse( int *mx, int *my ); - -/* -======================== -IN_InitDIMouse -======================== -*/ -qboolean IN_InitDIMouse( void ) { - HRESULT hr; - int x, y; - DIPROPDWORD dipdw = { - { - sizeof(DIPROPDWORD), // diph.dwSize - sizeof(DIPROPHEADER), // diph.dwHeaderSize - 0, // diph.dwObj - DIPH_DEVICE, // diph.dwHow - }, - DINPUT_BUFFERSIZE, // dwData - }; - - Com_Printf( "Initializing DirectInput...\n"); - - if (!hInstDI) { - hInstDI = LoadLibrary("dinput.dll"); - - if (hInstDI == NULL) { - Com_Printf ("Couldn't load dinput.dll\n"); - return qfalse; - } - } - - if (!pDirectInputCreate) { - pDirectInputCreate = (long (__stdcall *)(void *,unsigned long ,struct IDirectInputA ** ,struct IUnknown *)) - GetProcAddress(hInstDI,"DirectInputCreateA"); - - if (!pDirectInputCreate) { - Com_Printf ("Couldn't get DI proc addr\n"); - return qfalse; - } - } - - // register with DirectInput and get an IDirectInput to play with. - hr = iDirectInputCreate( g_wv.hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); - - if (FAILED(hr)) { - Com_Printf ("iDirectInputCreate failed\n"); - return qfalse; - } - - // obtain an interface to the system mouse device. - hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); - - if (FAILED(hr)) { - Com_Printf ("Couldn't open DI mouse device\n"); - return qfalse; - } - - // set the data format to "mouse format". - hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); - - if (FAILED(hr)) { - Com_Printf ("Couldn't set DI mouse format\n"); - return qfalse; - } - - // set the cooperativity level. - hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, g_wv.hWnd, - DISCL_EXCLUSIVE | DISCL_FOREGROUND); - - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=50 - if (FAILED(hr)) { - Com_Printf ("Couldn't set DI coop level\n"); - return qfalse; - } - - - // set the buffer size to DINPUT_BUFFERSIZE elements. - // the buffer size is a DWORD property associated with the device - hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); - - if (FAILED(hr)) { - Com_Printf ("Couldn't set DI buffersize\n"); - return qfalse; - } - - // clear any pending samples - IN_DIMouse( &x, &y ); - IN_DIMouse( &x, &y ); - - Com_Printf( "DirectInput initialized.\n"); - return qtrue; -} - -/* -========================== -IN_ShutdownDIMouse -========================== -*/ -void IN_ShutdownDIMouse( void ) { - if (g_pMouse) { - IDirectInputDevice_Release(g_pMouse); - g_pMouse = NULL; - } - - if (g_pdi) { - IDirectInput_Release(g_pdi); - g_pdi = NULL; - } -} - -/* -========================== -IN_ActivateDIMouse -========================== -*/ -void IN_ActivateDIMouse( void ) { - HRESULT hr; - - if (!g_pMouse) { - return; - } - - // we may fail to reacquire if the window has been recreated - hr = IDirectInputDevice_Acquire( g_pMouse ); - if (FAILED(hr)) { - if ( !IN_InitDIMouse() ) { - Com_Printf ("Falling back to Win32 mouse support...\n"); - Cvar_Set( "in_mouse", "-1" ); - } - } -} - -/* -========================== -IN_DeactivateDIMouse -========================== -*/ -void IN_DeactivateDIMouse( void ) { - if (!g_pMouse) { - return; - } - IDirectInputDevice_Unacquire( g_pMouse ); -} - - -/* -=================== -IN_DIMouse -=================== -*/ -void IN_DIMouse( int *mx, int *my ) { - DIDEVICEOBJECTDATA od; - DIMOUSESTATE state; - DWORD dwElements; - HRESULT hr; - int value; - static float oldSysTime; - - if ( !g_pMouse ) { - return; - } - - // fetch new events - for (;;) - { - dwElements = 1; - - hr = IDirectInputDevice_GetDeviceData(g_pMouse, - sizeof(DIDEVICEOBJECTDATA), &od, &dwElements, 0); - if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED)) { - IDirectInputDevice_Acquire(g_pMouse); - return; - } - - /* Unable to read data or no data available */ - if ( FAILED(hr) ) { - break; - } - - if ( dwElements == 0 ) { - break; - } - - switch (od.dwOfs) { - case DIMOFS_BUTTON0: - if (od.dwData & 0x80) - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE1, qtrue, 0, NULL ); - else - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE1, qfalse, 0, NULL ); - break; - - case DIMOFS_BUTTON1: - if (od.dwData & 0x80) - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE2, qtrue, 0, NULL ); - else - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE2, qfalse, 0, NULL ); - break; - - case DIMOFS_BUTTON2: - if (od.dwData & 0x80) - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE3, qtrue, 0, NULL ); - else - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE3, qfalse, 0, NULL ); - break; - - case DIMOFS_BUTTON3: - if (od.dwData & 0x80) - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE4, qtrue, 0, NULL ); - else - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MOUSE4, qfalse, 0, NULL ); - break; - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=50 - case DIMOFS_Z: - value = od.dwData; - if (value == 0) { - - } else if (value < 0) { - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL ); - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL ); - } else { - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MWHEELUP, qtrue, 0, NULL ); - Sys_QueEvent( od.dwTimeStamp, SE_KEY, K_MWHEELUP, qfalse, 0, NULL ); - } - break; - } - } - - // read the raw delta counter and ignore - // the individual sample time / values - hr = IDirectInputDevice_GetDeviceState(g_pMouse, - sizeof(DIDEVICEOBJECTDATA), &state); - if ( FAILED(hr) ) { - *mx = *my = 0; - return; - } - *mx = state.lX; - *my = state.lY; -} - -/* -============================================================ - - MOUSE CONTROL - -============================================================ -*/ - -/* -=========== -IN_ActivateMouse - -Called when the window gains focus or changes in some way -=========== -*/ -void IN_ActivateMouse( void ) -{ - if (!s_wmv.mouseInitialized ) { - return; - } - if ( !in_mouse->integer ) - { - s_wmv.mouseActive = qfalse; - return; - } - if ( s_wmv.mouseActive ) - { - return; - } - - s_wmv.mouseActive = qtrue; - - if ( in_mouse->integer != -1 ) { - IN_ActivateDIMouse(); - } - IN_ActivateWin32Mouse(); -} - - -/* -=========== -IN_DeactivateMouse - -Called when the window loses focus -=========== -*/ -void IN_DeactivateMouse( void ) { - if (!s_wmv.mouseInitialized ) { - return; - } - if (!s_wmv.mouseActive ) { - return; - } - s_wmv.mouseActive = qfalse; - - IN_DeactivateDIMouse(); - IN_DeactivateWin32Mouse(); -} - - - -/* -=========== -IN_StartupMouse -=========== -*/ -void IN_StartupMouse( void ) -{ - s_wmv.mouseInitialized = qfalse; - s_wmv.mouseStartupDelayed = qfalse; - - if ( in_mouse->integer == 0 ) { - Com_Printf ("Mouse control not active.\n"); - return; - } - - // nt4.0 direct input is screwed up - if ( ( g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ) && - ( g_wv.osversion.dwMajorVersion == 4 ) ) - { - Com_Printf ("Disallowing DirectInput on NT 4.0\n"); - Cvar_Set( "in_mouse", "-1" ); - } - - if ( in_mouse->integer == -1 ) { - Com_Printf ("Skipping check for DirectInput\n"); - } else { - if (!g_wv.hWnd) - { - Com_Printf ("No window for DirectInput mouse init, delaying\n"); - s_wmv.mouseStartupDelayed = qtrue; - return; - } - if ( IN_InitDIMouse() ) { - s_wmv.mouseInitialized = qtrue; - return; - } - Com_Printf ("Falling back to Win32 mouse support...\n"); - } - s_wmv.mouseInitialized = qtrue; - IN_InitWin32Mouse(); -} - -/* -=========== -IN_MouseEvent -=========== -*/ -void IN_MouseEvent (int mstate) -{ - int i; - - if ( !s_wmv.mouseInitialized ) - return; - -// perform button actions - for (i = 0 ; i < 3 ; i++ ) - { - if ( (mstate & (1<modified = qfalse; - in_joystick->modified = qfalse; -} - -/* -=========== -IN_Shutdown -=========== -*/ -void IN_Shutdown( void ) { - IN_DeactivateMouse(); - IN_ShutdownDIMouse(); - IN_ShutdownMIDI(); - Cmd_RemoveCommand("midiinfo" ); -} - - -/* -=========== -IN_Init -=========== -*/ -void IN_Init( void ) { - // MIDI input controler variables - in_midi = Cvar_Get ("in_midi", "0", CVAR_ARCHIVE); - in_midiport = Cvar_Get ("in_midiport", "1", CVAR_ARCHIVE); - in_midichannel = Cvar_Get ("in_midichannel", "1", CVAR_ARCHIVE); - in_mididevice = Cvar_Get ("in_mididevice", "0", CVAR_ARCHIVE); - - Cmd_AddCommand( "midiinfo", MidiInfo_f ); - - // mouse variables - in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE|CVAR_LATCH); - in_logitechbug = Cvar_Get ("in_logitechbug", "0", CVAR_ARCHIVE); - - // joystick variables - in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH); - in_joyBallScale = Cvar_Get ("in_joyBallScale", "0.02", CVAR_ARCHIVE); - in_debugJoystick = Cvar_Get ("in_debugjoystick", "0", CVAR_TEMP); - - joy_threshold = Cvar_Get ("joy_threshold", "0.15", CVAR_ARCHIVE); - - IN_Startup(); -} - - -/* -=========== -IN_Activate - -Called when the main window gains or loses focus. -The window may have been destroyed and recreated -between a deactivate and an activate. -=========== -*/ -void IN_Activate (qboolean active) { - in_appactive = active; - - if ( !active ) - { - IN_DeactivateMouse(); - } -} - - -/* -================== -IN_Frame - -Called every frame, even if not generating commands -================== -*/ -void IN_Frame (void) { - // post joystick events - IN_JoyMove(); - - if ( !s_wmv.mouseInitialized ) { - if (s_wmv.mouseStartupDelayed && g_wv.hWnd) - { - Com_Printf("Proceeding with delayed mouse init\n"); - IN_StartupMouse(); - s_wmv.mouseStartupDelayed = qfalse; - } - return; - } - - if ( cls.keyCatchers & KEYCATCH_CONSOLE ) { - // temporarily deactivate if not in the game and - // running on the desktop - // voodoo always counts as full screen - if (Cvar_VariableValue ("r_fullscreen") == 0 - && strcmp( Cvar_VariableString("r_glDriver"), _3DFX_DRIVER_NAME) ) { - IN_DeactivateMouse (); - return; - } - } - - if ( !in_appactive ) { - IN_DeactivateMouse (); - return; - } - - IN_ActivateMouse(); - - // post events to the system que - IN_MouseMove(); - -} - - -/* -=================== -IN_ClearStates -=================== -*/ -void IN_ClearStates (void) -{ - s_wmv.oldButtonState = 0; -} - - -/* -========================================================================= - -JOYSTICK - -========================================================================= -*/ - -/* -=============== -IN_StartupJoystick -=============== -*/ -void IN_StartupJoystick (void) { - int numdevs; - MMRESULT mmr; - - // assume no joystick - joy.avail = qfalse; - - if (! in_joystick->integer ) { - Com_Printf ("Joystick is not active.\n"); - return; - } - - // verify joystick driver is present - if ((numdevs = joyGetNumDevs ()) == 0) - { - Com_Printf ("joystick not found -- driver not present\n"); - return; - } - - // cycle through the joystick ids for the first valid one - mmr = 0; - for (joy.id=0 ; joy.id 1 ) { - fValue = 1; - } - return fValue; -} - -int JoyToI( int value ) { - // move centerpoint to zero - value -= 32768; - - return value; -} - -int joyDirectionKeys[16] = { - K_LEFTARROW, K_RIGHTARROW, - K_UPARROW, K_DOWNARROW, - K_JOY16, K_JOY17, - K_JOY18, K_JOY19, - K_JOY20, K_JOY21, - K_JOY22, K_JOY23, - - K_JOY24, K_JOY25, - K_JOY26, K_JOY27 -}; - -/* -=========== -IN_JoyMove -=========== -*/ -void IN_JoyMove( void ) { - float fAxisValue; - int i; - DWORD buttonstate, povstate; - int x, y; - - // verify joystick is available and that the user wants to use it - if ( !joy.avail ) { - return; - } - - // collect the joystick data, if possible - Com_Memset (&joy.ji, 0, sizeof(joy.ji)); - joy.ji.dwSize = sizeof(joy.ji); - joy.ji.dwFlags = JOY_RETURNALL; - - if ( joyGetPosEx (joy.id, &joy.ji) != JOYERR_NOERROR ) { - // read error occurred - // turning off the joystick seems too harsh for 1 read error,\ - // but what should be done? - // Com_Printf ("IN_ReadJoystick: no response\n"); - // joy.avail = false; - return; - } - - if ( in_debugJoystick->integer ) { - Com_Printf( "%8x %5i %5.2f %5.2f %5.2f %5.2f %6i %6i\n", - joy.ji.dwButtons, - joy.ji.dwPOV, - JoyToF( joy.ji.dwXpos ), JoyToF( joy.ji.dwYpos ), - JoyToF( joy.ji.dwZpos ), JoyToF( joy.ji.dwRpos ), - JoyToI( joy.ji.dwUpos ), JoyToI( joy.ji.dwVpos ) ); - } - - // loop through the joystick buttons - // key a joystick event or auxillary event for higher number buttons for each state change - buttonstate = joy.ji.dwButtons; - for ( i=0 ; i < joy.jc.wNumButtons ; i++ ) { - if ( (buttonstate & (1<value ) { - povstate |= (1<<(i*2)); - } else if ( fAxisValue > joy_threshold->value ) { - povstate |= (1<<(i*2+1)); - } - } - - // convert POV information from a direction into 4 button bits - if ( joy.jc.wCaps & JOYCAPS_HASPOV ) { - if ( joy.ji.dwPOV != JOY_POVCENTERED ) { - if (joy.ji.dwPOV == JOY_POVFORWARD) - povstate |= 1<<12; - if (joy.ji.dwPOV == JOY_POVBACKWARD) - povstate |= 1<<13; - if (joy.ji.dwPOV == JOY_POVRIGHT) - povstate |= 1<<14; - if (joy.ji.dwPOV == JOY_POVLEFT) - povstate |= 1<<15; - } - } - - // determine which bits have changed and key an auxillary event for each change - for (i=0 ; i < 16 ; i++) { - if ( (povstate & (1<= 6 ) { - x = JoyToI( joy.ji.dwUpos ) * in_joyBallScale->value; - y = JoyToI( joy.ji.dwVpos ) * in_joyBallScale->value; - if ( x || y ) { - Sys_QueEvent( g_wv.sysMsgTime, SE_MOUSE, x, y, 0, NULL ); - } - } -} - -/* -========================================================================= - -MIDI - -========================================================================= -*/ - -static void MIDI_NoteOff( int note ) -{ - int qkey; - - qkey = note - 60 + K_AUX1; - - if ( qkey > 255 || qkey < K_AUX1 ) - return; - - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qkey, qfalse, 0, NULL ); -} - -static void MIDI_NoteOn( int note, int velocity ) -{ - int qkey; - - if ( velocity == 0 ) - MIDI_NoteOff( note ); - - qkey = note - 60 + K_AUX1; - - if ( qkey > 255 || qkey < K_AUX1 ) - return; - - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qkey, qtrue, 0, NULL ); -} - -static void CALLBACK MidiInProc( HMIDIIN hMidiIn, UINT uMsg, DWORD dwInstance, - DWORD dwParam1, DWORD dwParam2 ) -{ - int message; - - switch ( uMsg ) - { - case MIM_OPEN: - break; - case MIM_CLOSE: - break; - case MIM_DATA: - message = dwParam1 & 0xff; - - // note on - if ( ( message & 0xf0 ) == 0x90 ) - { - if ( ( ( message & 0x0f ) + 1 ) == in_midichannel->integer ) - MIDI_NoteOn( ( dwParam1 & 0xff00 ) >> 8, ( dwParam1 & 0xff0000 ) >> 16 ); - } - else if ( ( message & 0xf0 ) == 0x80 ) - { - if ( ( ( message & 0x0f ) + 1 ) == in_midichannel->integer ) - MIDI_NoteOff( ( dwParam1 & 0xff00 ) >> 8 ); - } - break; - case MIM_LONGDATA: - break; - case MIM_ERROR: - break; - case MIM_LONGERROR: - break; - } - -// Sys_QueEvent( sys_msg_time, SE_KEY, wMsg, qtrue, 0, NULL ); -} - -static void MidiInfo_f( void ) -{ - int i; - - const char *enableStrings[] = { "disabled", "enabled" }; - - Com_Printf( "\nMIDI control: %s\n", enableStrings[in_midi->integer != 0] ); - Com_Printf( "port: %d\n", in_midiport->integer ); - Com_Printf( "channel: %d\n", in_midichannel->integer ); - Com_Printf( "current device: %d\n", in_mididevice->integer ); - Com_Printf( "number of devices: %d\n", s_midiInfo.numDevices ); - for ( i = 0; i < s_midiInfo.numDevices; i++ ) - { - if ( i == Cvar_VariableValue( "in_mididevice" ) ) - Com_Printf( "***" ); - else - Com_Printf( "..." ); - Com_Printf( "device %2d: %s\n", i, s_midiInfo.caps[i].szPname ); - Com_Printf( "...manufacturer ID: 0x%hx\n", s_midiInfo.caps[i].wMid ); - Com_Printf( "...product ID: 0x%hx\n", s_midiInfo.caps[i].wPid ); - - Com_Printf( "\n" ); - } -} - -static void IN_StartupMIDI( void ) -{ - int i; - - if ( !Cvar_VariableValue( "in_midi" ) ) - return; - - // - // enumerate MIDI IN devices - // - s_midiInfo.numDevices = midiInGetNumDevs(); - - for ( i = 0; i < s_midiInfo.numDevices; i++ ) - { - midiInGetDevCaps( i, &s_midiInfo.caps[i], sizeof( s_midiInfo.caps[i] ) ); - } - - // - // open the MIDI IN port - // - if ( midiInOpen( &s_midiInfo.hMidiIn, - in_mididevice->integer, - ( DWORD_PTR ) MidiInProc, - ( DWORD_PTR ) NULL, - CALLBACK_FUNCTION ) != MMSYSERR_NOERROR ) - { - Com_Printf( "WARNING: could not open MIDI device %d: '%s'\n", in_mididevice->integer , s_midiInfo.caps[( int ) in_mididevice->value] ); - return; - } - - midiInStart( s_midiInfo.hMidiIn ); -} - -static void IN_ShutdownMIDI( void ) -{ - if ( s_midiInfo.hMidiIn ) - { - midiInClose( s_midiInfo.hMidiIn ); - } - Com_Memset( &s_midiInfo, 0, sizeof( s_midiInfo ) ); -} - diff --git a/code/win32/win_local.h b/code/win32/win_local.h deleted file mode 100644 index 86d512b2..00000000 --- a/code/win32/win_local.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// win_local.h: Win32-specific Quake3 header file - -#if defined (_MSC_VER) && (_MSC_VER >= 1200) -#pragma warning(disable : 4201) -#pragma warning( push ) -#endif -#include -#if defined (_MSC_VER) && (_MSC_VER >= 1200) -#pragma warning( pop ) -#endif - -#define DIRECTSOUND_VERSION 0x0300 -#define DIRECTINPUT_VERSION 0x0300 - -#include -#include -#include -#include - -void IN_MouseEvent (int mstate); - -void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr ); - -void Sys_CreateConsole( void ); -void Sys_DestroyConsole( void ); - -char *Sys_ConsoleInput (void); - -qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message ); - -// Input subsystem - -void IN_Init (void); -void IN_Shutdown (void); -void IN_JoystickCommands (void); - -void IN_Move (usercmd_t *cmd); -// add additional non keyboard / non mouse movement on top of the keyboard move cmd - -void IN_DeactivateWin32Mouse( void); - -void IN_Activate (qboolean active); -void IN_Frame (void); - -// window procedure -LONG WINAPI MainWndProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam); - -void Conbuf_AppendText( const char *msg ); - -void SNDDMA_Activate( void ); -int SNDDMA_InitDS (); - -typedef struct -{ - - HINSTANCE reflib_library; // Handle to refresh DLL - qboolean reflib_active; - - HWND hWnd; - HINSTANCE hInstance; - qboolean activeApp; - qboolean isMinimized; - OSVERSIONINFO osversion; - - // when we get a windows message, we store the time off so keyboard processing - // can know the exact time of an event - unsigned sysMsgTime; -} WinVars_t; - -extern WinVars_t g_wv; diff --git a/code/win32/win_main.c b/code/win32/win_main.c deleted file mode 100644 index 3e607511..00000000 --- a/code/win32/win_main.c +++ /dev/null @@ -1,1608 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// win_main.c - -#include "../client/client.h" -#include "../qcommon/qcommon.h" -#include "win_local.h" -#include "win_localization.h" -#include "resource.h" -#include -#include -#include -#include -#include -#include -#include - -#define CD_BASEDIR "openmohaa" -#define CD_EXE "openmohaa.exe" -#define CD_BASEDIR_LINUX "bin\\x86\\glibc-2.1" -#define CD_EXE_LINUX "openmohaa" -#define MEM_THRESHOLD 96*1024*1024 - -static char sys_cmdline[MAX_STRING_CHARS]; -static void* game_library = NULL; -static void* cgame_library = NULL; - -// define this to use alternate spanking method -// I found out that the regular way doesn't work on my box for some reason -// see the associated spank.sh script -#define ALT_SPANK -#ifdef ALT_SPANK -#include -#include - -int fh = 0; - -void Spk_Open(char *name) -{ - fh = open( name, O_TRUNC | O_CREAT | O_WRONLY, S_IREAD | S_IWRITE ); -}; - -void Spk_Close() -{ - if (!fh) - return; - - close( fh ); - fh = 0; -} - -void Spk_Printf (const char *text, ...) -{ - va_list argptr; - char buf[32768]; - - if (!fh) - return; - - va_start (argptr,text); - vsprintf (buf, text, argptr); - write(fh, buf, strlen(buf)); - _commit(fh); - va_end (argptr); - -}; -#endif - -/* -================== -Sys_LowPhysicalMemory() -================== -*/ - -qboolean Sys_LowPhysicalMemory() { - MEMORYSTATUS stat; - GlobalMemoryStatus (&stat); - return (stat.dwTotalPhys <= MEM_THRESHOLD) ? qtrue : qfalse; -} - -/* -================== -Sys_BeginProfiling -================== -*/ -void Sys_BeginProfiling( void ) { - // this is just used on the mac build -} - -/* -============= -Sys_Error - -Show the early console as an error dialog -============= -*/ -void QDECL Sys_Error( const char *error, ... ) { - va_list argptr; - char text[4096]; - MSG msg; - - va_start (argptr, error); - vsprintf (text, error, argptr); - va_end (argptr); - - Conbuf_AppendText( text ); - Conbuf_AppendText( "\n" ); - - Sys_SetErrorText( text ); - Sys_ShowConsole( 1, qtrue ); - - timeEndPeriod( 1 ); - - IN_Shutdown(); - - // wait for the user to quit - while ( 1 ) { - if (!GetMessage (&msg, NULL, 0, 0)) - Com_Quit_f (); - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sys_DestroyConsole(); - - exit (1); -} - -/* -============== -Sys_Quit -============== -*/ -void Sys_Quit( void ) { - timeEndPeriod( 1 ); - IN_Shutdown(); - Sys_DestroyConsole(); - - exit (0); -} - -/* -============== -Sys_Print -============== -*/ -void Sys_Print( const char *msg ) { - Conbuf_AppendText( msg ); -} - - -/* -============== -Sys_Mkdir -============== -*/ -void Sys_Mkdir( const char *path ) { - _mkdir (path); -} - -/* -============== -Sys_Cwd -============== -*/ -char *Sys_Cwd( void ) { - static char cwd[MAX_OSPATH]; - - _getcwd( cwd, sizeof( cwd ) - 1 ); - cwd[MAX_OSPATH-1] = 0; - - return cwd; -} - -/* -============== -Sys_DefaultCDPath -============== -*/ -char *Sys_DefaultCDPath( void ) { - return ""; -} - -/* -============== -Sys_DefaultBasePath -============== -*/ -char *Sys_DefaultBasePath( void ) { - return Sys_Cwd(); -} - -/* -============================================================== - -DIRECTORY SCANNING - -============================================================== -*/ - -#define MAX_FOUND_FILES 0x1000 - -void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) { - char search[MAX_OSPATH], newsubdirs[MAX_OSPATH]; - char filename[MAX_OSPATH]; - intptr_t findhandle; - struct _finddata_t findinfo; - - if ( *numfiles >= MAX_FOUND_FILES - 1 ) { - return; - } - - if (strlen(subdirs)) { - Com_sprintf( search, sizeof(search), "%s\\%s\\*", basedir, subdirs ); - } - else { - Com_sprintf( search, sizeof(search), "%s\\*", basedir ); - } - - findhandle = _findfirst (search, &findinfo); - if (findhandle == -1) { - return; - } - - do { - if (findinfo.attrib & _A_SUBDIR) { - if (Q_stricmp(findinfo.name, ".") && Q_stricmp(findinfo.name, "..")) { - if (strlen(subdirs)) { - Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s\\%s", subdirs, findinfo.name); - } - else { - Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", findinfo.name); - } - Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles ); - } - } - if ( *numfiles >= MAX_FOUND_FILES - 1 ) { - break; - } - Com_sprintf( filename, sizeof(filename), "%s\\%s", subdirs, findinfo.name ); - if (!Com_FilterPath( filter, filename, qfalse )) - continue; - list[ *numfiles ] = CopyString( filename ); - (*numfiles)++; - } while ( _findnext (findhandle, &findinfo) != -1 ); - - _findclose (findhandle); -} - -static qboolean strgtr(const char *s0, const char *s1) { - size_t l0, l1, i; - - l0 = strlen(s0); - l1 = strlen(s1); - - if (l1 s0[i]) { - return qtrue; - } - if (s1[i] < s0[i]) { - return qfalse; - } - } - return qfalse; -} - -char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs ) { - char search[MAX_OSPATH]; - int nfiles; - char **listCopy; - char *list[MAX_FOUND_FILES]; - struct _finddata_t findinfo; - intptr_t findhandle; - int flag; - int i; - - if (filter) { - - nfiles = 0; - Sys_ListFilteredFiles( directory, "", filter, list, &nfiles ); - - list[ nfiles ] = 0; - *numfiles = nfiles; - - if (!nfiles) - return NULL; - - listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) ); - for ( i = 0 ; i < nfiles ; i++ ) { - listCopy[i] = list[i]; - } - listCopy[i] = NULL; - - return listCopy; - } - - if ( !extension) { - extension = ""; - } - - // passing a slash as extension will find directories - if ( extension[0] == '/' && extension[1] == 0 ) { - extension = ""; - flag = 0; - } else { - flag = _A_SUBDIR; - } - - Com_sprintf( search, sizeof(search), "%s\\*%s", directory, extension ); - - // search - nfiles = 0; - - findhandle = _findfirst (search, &findinfo); - if (findhandle == -1) { - *numfiles = 0; - return NULL; - } - - do { - if ( (!wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR )) || (wantsubs && findinfo.attrib & _A_SUBDIR) ) { - if ( nfiles == MAX_FOUND_FILES - 1 ) { - break; - } - list[ nfiles ] = CopyString( findinfo.name ); - nfiles++; - } - } while ( _findnext (findhandle, &findinfo) != -1 ); - - list[ nfiles ] = 0; - - _findclose (findhandle); - - // return a copy of the list - *numfiles = nfiles; - - if ( !nfiles ) { - return NULL; - } - - listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) ); - for ( i = 0 ; i < nfiles ; i++ ) { - listCopy[i] = list[i]; - } - listCopy[i] = NULL; - - do { - flag = 0; - for(i=1; i (5 * 60000)) && !Cvar_VariableIntegerValue( "dedicated" ) - && !Cvar_VariableIntegerValue( "com_blindlyLoadDLLs" ) ) { - if (FS_FileExists(filename)) { - lastWarning = timestamp; - ret = MessageBoxEx( NULL, "You are about to load a .DLL executable that\n" - "has not been verified for use with Quake III Arena.\n" - "This type of file can compromise the security of\n" - "your computer.\n\n" - "Select 'OK' if you choose to load it anyway.", - "Security Warning", MB_OKCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON2 | MB_TOPMOST | MB_SETFOREGROUND, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) ); - if( ret != IDOK ) { - return NULL; - } - } - } -#endif - -#ifndef NDEBUG - libHandle = LoadLibrary( filename ); - if (libHandle) - Com_Printf("LoadLibrary '%s' ok\n", filename); - else - Com_Printf("LoadLibrary '%s' failed\n", filename); - if ( !libHandle ) { -#endif - basepath = Cvar_VariableString( "fs_basepath" ); - cdpath = Cvar_VariableString( "fs_cdpath" ); - gamedir = Cvar_VariableString( "fs_game" ); - - fn = FS_BuildOSPath( basepath, gamedir, filename ); - libHandle = LoadLibrary( fn ); -#ifndef NDEBUG - if (libHandle) - Com_Printf("LoadLibrary '%s' ok\n", fn); - else - Com_Printf("LoadLibrary '%s' failed\n", fn); -#endif - - if ( !libHandle ) { - if( cdpath[0] ) { - fn = FS_BuildOSPath( cdpath, gamedir, filename ); - libHandle = LoadLibrary( fn ); -#ifndef NDEBUG - if (libHandle) - Com_Printf("LoadLibrary '%s' ok\n", fn); - else - Com_Printf("LoadLibrary '%s' failed\n", fn); -#endif - } - - if ( !libHandle ) { - return NULL; - } - } -#ifndef NDEBUG - } -#endif - - dllEntry = ( void (QDECL *)( int (QDECL *)( int, ... ) ) )GetProcAddress( libHandle, "dllEntry" ); - *entryPoint = (int (QDECL *)(int,...))GetProcAddress( libHandle, "vmMain" ); - if ( !*entryPoint || !dllEntry ) { - FreeLibrary( libHandle ); - return NULL; - } - dllEntry( systemcalls ); - - if ( libHandle ) Q_strncpyz ( fqpath , filename , MAX_QPATH ) ; // added 7/20/02 by T.Ray - return libHandle; -} - - -/* -======================================================================== - -BACKGROUND FILE STREAMING - -======================================================================== -*/ - -#if 1 - -void Sys_InitStreamThread( void ) { -} - -void Sys_ShutdownStreamThread( void ) { -} - -void Sys_BeginStreamedFile( fileHandle_t f, int readAhead ) { -} - -void Sys_EndStreamedFile( fileHandle_t f ) { -} - -int Sys_StreamedRead( void *buffer, int size, int count, fileHandle_t f ) { - return FS_Read( buffer, size * count, f ); -} - -void Sys_StreamSeek( fileHandle_t f, int offset, int origin ) { - FS_Seek( f, offset, origin ); -} - - -#else - -typedef struct { - fileHandle_t file; - byte *buffer; - qboolean eof; - qboolean active; - int bufferSize; - int streamPosition; // next byte to be returned by Sys_StreamRead - int threadPosition; // next byte to be read from file -} streamsIO_t; - -typedef struct { - HANDLE threadHandle; - int threadId; - CRITICAL_SECTION crit; - streamsIO_t sIO[MAX_FILE_HANDLES]; -} streamState_t; - -streamState_t stream; - -/* -=============== -Sys_StreamThread - -A thread will be sitting in this loop forever -================ -*/ -void Sys_StreamThread( void ) { - int buffer; - int count; - int readCount; - int bufferPoint; - int r, i; - - while (1) { - Sleep( 10 ); -// EnterCriticalSection (&stream.crit); - - for (i=1;i 0 ) { - available = stream.sIO[f].threadPosition - stream.sIO[f].streamPosition; - if ( !available ) { - if ( stream.sIO[f].eof ) { - break; - } - if ( sleepCount == 1 ) { - Com_DPrintf( "Sys_StreamedRead: waiting\n" ); - } - if ( ++sleepCount > 100 ) { - Com_Error( ERR_FATAL, "Sys_StreamedRead: thread has died"); - } - Sleep( 10 ); - continue; - } - - EnterCriticalSection( &stream.crit ); - - bufferPoint = stream.sIO[f].streamPosition % stream.sIO[f].bufferSize; - bufferCount = stream.sIO[f].bufferSize - bufferPoint; - - copy = available < bufferCount ? available : bufferCount; - if ( copy > remaining ) { - copy = remaining; - } - memcpy( dest, stream.sIO[f].buffer + bufferPoint, copy ); - stream.sIO[f].streamPosition += copy; - dest += copy; - remaining -= copy; - - LeaveCriticalSection( &stream.crit ); - } - - return (count * size - remaining) / size; -} - -/* -=============== -Sys_StreamSeek - -================ -*/ -void Sys_StreamSeek( fileHandle_t f, int offset, int origin ) { - - // halt the thread - EnterCriticalSection( &stream.crit ); - - // clear to that point - FS_Seek( f, offset, origin ); - stream.sIO[f].streamPosition = 0; - stream.sIO[f].threadPosition = 0; - stream.sIO[f].eof = qfalse; - - // let the thread start running at the new position - LeaveCriticalSection( &stream.crit ); -} - -#endif - -/* -======================================================================== - -EVENT LOOP - -======================================================================== -*/ - -#define MAX_QUED_EVENTS 256 -#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 ) - -sysEvent_t eventQue[MAX_QUED_EVENTS]; -int eventHead, eventTail; -byte sys_packetReceived[MAX_MSGLEN]; - -/* -================ -Sys_QueEvent - -A time of 0 will get the current time -Ptr should either be null, or point to a block of data that can -be freed by the game later. -================ -*/ -void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr ) { - sysEvent_t *ev; - - ev = &eventQue[ eventHead & MASK_QUED_EVENTS ]; - if ( eventHead - eventTail >= MAX_QUED_EVENTS ) { - Com_Printf("Sys_QueEvent: overflow\n"); - // we are discarding an event, but don't leak memory - if ( ev->evPtr ) { - Z_Free( ev->evPtr ); - } - eventTail++; - } - - eventHead++; - - if ( time == 0 ) { - time = Sys_Milliseconds(); - } - - ev->evTime = time; - ev->evType = type; - ev->evValue = value; - ev->evValue2 = value2; - ev->evPtrLength = ptrLength; - ev->evPtr = ptr; -} - -/* -================ -Sys_GetEvent - -================ -*/ -sysEvent_t Sys_GetEvent( void ) { - MSG msg; - sysEvent_t ev; - char *s; - msg_t netmsg; - netadr_t adr; - - // return if we have data - if ( eventHead > eventTail ) { - eventTail++; - return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ]; - } - - // pump the message loop - while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) { - if ( !GetMessage (&msg, NULL, 0, 0) ) { - Com_Quit_f(); - } - - // save the msg time, because wndprocs don't have access to the timestamp - g_wv.sysMsgTime = msg.time; - - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - // check for console commands - s = Sys_ConsoleInput(); - if ( s ) { - char *b; - int len; - - len = strlen( s ) + 1; - b = Z_Malloc( len ); - Q_strncpyz( b, s, len-1 ); - Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b ); - } - - // check for network packets - MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) ); - if ( Sys_GetPacket ( &adr, &netmsg ) ) { - netadr_t *buf; - int len; - - // copy out to a seperate buffer for qeueing - // the readcount stepahead is for SOCKS support - len = sizeof( netadr_t ) + netmsg.cursize - netmsg.readcount; - buf = Z_Malloc( len ); - *buf = adr; - memcpy( buf+1, &netmsg.data[netmsg.readcount], netmsg.cursize - netmsg.readcount ); - Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf ); - } - - // return if we have data - if ( eventHead > eventTail ) { - eventTail++; - return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ]; - } - - // create an empty event to return - - memset( &ev, 0, sizeof( ev ) ); - ev.evTime = timeGetTime(); - - return ev; -} - -//================================================================ - -/* -================= -Sys_In_Restart_f - -Restart the input subsystem -================= -*/ -void Sys_In_Restart_f( void ) { - IN_Shutdown(); - IN_Init(); -} - - -/* -================= -Sys_Net_Restart_f - -Restart the network subsystem -================= -*/ -void Sys_Net_Restart_f( void ) { - NET_Restart(); -} - - -/* -================ -Sys_Init - -Called after the common systems (cvars, files, etc) -are initialized -================ -*/ -#define OSR2_BUILD_NUMBER 1111 -#define WIN98_BUILD_NUMBER 1998 - -void Sys_Init( void ) { - int cpuid; - - // make sure the timer is high precision, otherwise - // NT gets 18ms resolution - timeBeginPeriod( 1 ); - - Cmd_AddCommand ("in_restart", Sys_In_Restart_f); - Cmd_AddCommand ("net_restart", Sys_Net_Restart_f); - - g_wv.osversion.dwOSVersionInfoSize = sizeof( g_wv.osversion ); - - if (!GetVersionEx (&g_wv.osversion)) - Sys_Error ("Couldn't get OS info"); - - if (g_wv.osversion.dwMajorVersion < 4) - Sys_Error ("OpenMoHAA requires Windows version 4 or greater"); - if (g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32s) - Sys_Error ("OpenMoHAA doesn't run on Win32s"); - - if ( g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ) - { - Cvar_Set( "arch", "winnt" ); - } - else if ( g_wv.osversion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) - { - if ( LOWORD( g_wv.osversion.dwBuildNumber ) >= WIN98_BUILD_NUMBER ) - { - Cvar_Set( "arch", "win98" ); - } - else if ( LOWORD( g_wv.osversion.dwBuildNumber ) >= OSR2_BUILD_NUMBER ) - { - Cvar_Set( "arch", "win95 osr2.x" ); - } - else - { - Cvar_Set( "arch", "win95" ); - } - } - else - { - Cvar_Set( "arch", "unknown Windows variant" ); - } - - // save out a couple things in rom cvars for the renderer to access - Cvar_Get( "win_hinstance", va("%zu", (uintptr_t)g_wv.hInstance), CVAR_ROM ); - Cvar_Get( "win_wndproc", va("%zu", (uintptr_t)MainWndProc), CVAR_ROM ); - - // - // figure out our CPU - // - Cvar_Get( "sys_cpustring", "detect", 0 ); - if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring"), "detect" ) ) - { - Com_Printf( "...detecting CPU, found " ); - - cpuid = Sys_GetProcessorId(); - - switch ( cpuid ) - { - case CPUID_GENERIC: - Cvar_Set( "sys_cpustring", "generic" ); - break; - case CPUID_INTEL_UNSUPPORTED: - Cvar_Set( "sys_cpustring", "x86 (pre-Pentium)" ); - break; - case CPUID_INTEL_PENTIUM: - Cvar_Set( "sys_cpustring", "x86 (P5/PPro, non-MMX)" ); - break; - case CPUID_INTEL_MMX: - Cvar_Set( "sys_cpustring", "x86 (P5/Pentium2, MMX)" ); - break; - case CPUID_INTEL_KATMAI: - Cvar_Set( "sys_cpustring", "Intel Pentium III" ); - break; - case CPUID_AMD_3DNOW: - Cvar_Set( "sys_cpustring", "AMD w/ 3DNow!" ); - break; - case CPUID_AXP: - Cvar_Set( "sys_cpustring", "Alpha AXP" ); - break; - default: - Com_Error( ERR_FATAL, "Unknown cpu type %d\n", cpuid ); - break; - } - } - else - { - Com_Printf( "...forcing CPU type to " ); - if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "generic" ) ) - { - cpuid = CPUID_GENERIC; - } - else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "x87" ) ) - { - cpuid = CPUID_INTEL_PENTIUM; - } - else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "mmx" ) ) - { - cpuid = CPUID_INTEL_MMX; - } - else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "3dnow" ) ) - { - cpuid = CPUID_AMD_3DNOW; - } - else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "PentiumIII" ) ) - { - cpuid = CPUID_INTEL_KATMAI; - } - else if ( !Q_stricmp( Cvar_VariableString( "sys_cpustring" ), "axp" ) ) - { - cpuid = CPUID_AXP; - } - else - { - Com_Printf( "WARNING: unknown sys_cpustring '%s'\n", Cvar_VariableString( "sys_cpustring" ) ); - cpuid = CPUID_GENERIC; - } - } - Cvar_SetValue( "sys_cpuid", cpuid ); - Com_Printf( "%s\n", Cvar_VariableString( "sys_cpustring" ) ); - - Cvar_Set( "username", Sys_GetCurrentUser() ); - - IN_Init(); // FIXME: not in dedicated? -} - -/* -================ -RecoverLostAutodialData -================ -*/ -void RecoverLostAutodialData(void) -{ - // FIXME: stub -} - -/* -============== -Sys_CloseMutex -============== -*/ -void Sys_CloseMutex(void) -{ - // FIXME: stub -} - -/* -============== -Sys_PumpMessageLoop -============== -*/ -void Sys_PumpMessageLoop(void) -{ - MSG msg; - - while (PeekMessageA(&msg, 0, 0, 0, 0)) - { - if (!GetMessageA(&msg, 0, 0, 0)) { - Com_Quit_f(); - } - - g_wv.sysMsgTime = msg.time; - - TranslateMessage(&msg); - DispatchMessageA(&msg); - } -} - -/* -============== -SaveRegistryInfo -============== -*/ -qboolean SaveRegistryInfo(qboolean user, const char* pszName, void* pvBuf, long lSize) -{ - STUB_DESC("not implemented"); - return qfalse; -} - -/* -============== -LoadRegistryInfo -============== -*/ -qboolean LoadRegistryInfo(qboolean user, const char* pszName, void* pvBuf, long* plSize) -{ - STUB_DESC("not implemented"); - return qfalse; -} - -/* -============== -IsFirstRun -============== -*/ -qboolean IsFirstRun(void) -{ - STUB_DESC("wtf"); - return qfalse; -} - -/* -============== -IsNewConfig -============== -*/ -qboolean IsNewConfig(void) -{ - STUB_DESC("wtf"); - return qfalse; -} - -/* -============== -IsSafeMode -============== -*/ -qboolean IsSafeMode(void) -{ - STUB_DESC("wtf"); - return qfalse; -} - -/* -============== -ClearNewConfigFlag -============== -*/ -void ClearNewConfigFlag(void) -{ -} - -/* -============== -Sys_GetWholeClipboard -============== -*/ -const char* Sys_GetWholeClipboard(void) -{ - return NULL; -} - -/* -============== -Sys_SetClipboard -============== -*/ -void Sys_SetClipboard(const char* contents) -{ -} - -/* -================== -SetNormalThreadPriority -================== -*/ -void SetNormalThreadPriority(void) -{ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); -} - -/* -================== -SetBelowNormalThreadPriority -================== -*/ -void SetBelowNormalThreadPriority(void) -{ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); -} - -/* -================= -Sys_UnloadGame -================= -*/ -void Sys_UnloadGame(void) -{ - Com_Printf("------ Unloading Game ------\n"); - - if (game_library) { - FreeLibrary(game_library); - } - - game_library = NULL; -} - -/* -================= -Sys_GetGameAPI -================= -*/ -void* Sys_GetGameAPI(void* parms) -{ - void* (*GetGameAPI) (void*); - const char* basepath; - const char* cdpath; - const char* gamedir; - const char* homepath; - const char* fn; - const char* gamename = "game" ARCH_STRING DLL_SUFFIX DLL_EXT; - - if (game_library) - Com_Error(ERR_FATAL, "Sys_GetGameAPI without calling Sys_UnloadGame"); - - // check the current debug directory first for development purposes - homepath = Cvar_VariableString("fs_homepath"); - basepath = Cvar_VariableString("fs_basepath"); - cdpath = Cvar_VariableString("fs_cdpath"); - gamedir = Cvar_VariableString("fs_game"); - - fn = FS_BuildOSPath(basepath, gamedir, gamename); - - game_library = LoadLibrary(fn); - - //First try in mod directories. basepath -> homepath -> cdpath - if (!game_library) { - if (homepath[0]) { - Com_Printf("Sys_GetGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(homepath, gamedir, gamename); - game_library = LoadLibrary(fn); - } - } - if (!game_library) { - if (cdpath[0]) { - Com_Printf("Sys_GetGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(cdpath, gamedir, gamename); - game_library = LoadLibrary(fn); - } - } - - //Now try in base. basepath -> homepath -> cdpath - if (!game_library) { - Com_Printf("Sys_GetGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(basepath, PRODUCT_NAME, gamename); - game_library = LoadLibrary(fn); - } - - if (!game_library) { - if (homepath[0]) { - Com_Printf("Sys_GetGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(homepath, PRODUCT_NAME, gamename); - game_library = LoadLibrary(fn); - } - } - if (!game_library) { - if (cdpath[0]) { - Com_Printf("Sys_GetGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(cdpath, PRODUCT_NAME, gamename); - game_library = LoadLibrary(fn); - } - } - - //Still couldn't find it. - if (!game_library) { - Com_Printf("Sys_GetGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - Com_Error(ERR_FATAL, "Couldn't load game"); - } - - Com_Printf("Sys_GetGameAPI(%s): succeeded ...\n", fn); - GetGameAPI = (void* (*)(void*))GetProcAddress(game_library, "GetGameAPI"); - - if (!GetGameAPI) - { - Sys_UnloadGame(); - return NULL; - } - - return GetGameAPI(parms); -} - -/* -================= -Sys_UnloadCGame -================= -*/ -void Sys_UnloadCGame(void) -{ - Com_Printf("------ Unloading ClientGame ------\n"); - - if (cgame_library) { - FreeLibrary(cgame_library); - } - - cgame_library = NULL; -} - -/* -================= -Sys_GetCGameAPI -================= -*/ -void* Sys_GetCGameAPI(void* parms) -{ - void* (*GetCGameAPI) (void*); - const char* basepath; - const char* cdpath; - const char* gamedir; - const char* homepath; - const char* fn; - const char* gamename = "cgame" ARCH_STRING DLL_SUFFIX DLL_EXT; - - if (cgame_library) - Com_Error(ERR_FATAL, "Sys_GetCGameAPI without calling Sys_UnloadCGame"); - - // check the current debug directory first for development purposes - homepath = Cvar_VariableString("fs_homepath"); - basepath = Cvar_VariableString("fs_basepath"); - cdpath = Cvar_VariableString("fs_cdpath"); - gamedir = Cvar_VariableString("fs_game"); - - fn = FS_BuildOSPath(basepath, gamedir, gamename); - - cgame_library = LoadLibrary(fn); - - //First try in mod directories. basepath -> homepath -> cdpath - if (!cgame_library) { - if (homepath[0]) { - Com_Printf("Sys_GetCGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(homepath, gamedir, gamename); - cgame_library = LoadLibrary(fn); - } - } - if (!cgame_library) { - if (cdpath[0]) { - Com_Printf("Sys_GetCGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(cdpath, gamedir, gamename); - cgame_library = LoadLibrary(fn); - } - } - - //Now try in base. basepath -> homepath -> cdpath - if (!cgame_library) { - Com_Printf("Sys_GetCGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(basepath, PRODUCT_NAME, gamename); - cgame_library = LoadLibrary(fn); - } - - if (!cgame_library) { - if (homepath[0]) { - Com_Printf("Sys_GetCGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(homepath, PRODUCT_NAME, gamename); - cgame_library = LoadLibrary(fn); - } - } - if (!cgame_library) { - if (cdpath[0]) { - Com_Printf("Sys_GetCGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - fn = FS_BuildOSPath(cdpath, PRODUCT_NAME, gamename); - cgame_library = LoadLibrary(fn); - } - } - - //Still couldn't find it. - if (!cgame_library) { - Com_Printf("Sys_GetCGameAPI(%s) failed: \"%d\"\n", fn, GetLastError()); - Com_Error(ERR_FATAL, "Couldn't load game"); - } - - Com_Printf("Sys_GetCGameAPI(%s): succeeded ...\n", fn); - GetCGameAPI = (void* (*)(void*))GetProcAddress(cgame_library, "GetCGameAPI"); - - if (!GetCGameAPI) - { - Sys_UnloadCGame(); - return NULL; - } - - return GetCGameAPI(parms); -} - -//======================================================================= - -int totalMsec, countMsec; - -/* -================== -WinMain - -================== -*/ -int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { - char cwd[MAX_OSPATH]; - int startTime, endTime; - - // should never get a previous instance in Win32 - if ( hPrevInstance ) { - return 0; - } - - g_wv.hInstance = hInstance; - Q_strncpyz( sys_cmdline, lpCmdLine, sizeof( sys_cmdline ) ); - - // done before Com/Sys_Init since we need this for error output - Sys_CreateConsole(); - - // no abort/retry/fail errors - SetErrorMode( SEM_FAILCRITICALERRORS ); - - // get the initial time base - Sys_Milliseconds(); -#if 0 - // if we find the CD, add a +set cddir xxx command line - Sys_ScanForCD(); -#endif - - Sys_InitStreamThread(); - - Com_Init( sys_cmdline ); - Sys_InitLocalization(); - // Already called inside Com_Init - //NET_Init(); - - _getcwd (cwd, sizeof(cwd)); - Com_Printf("Working directory: %s\n", cwd); - - // hide the early console since we've reached the point where we - // have a working graphics subsystems -#ifndef DEDICATED - if ( !com_dedicated->integer && !com_viewlog->integer ) { - Sys_ShowConsole( 0, qfalse ); - } -#endif - - // main game loop - while( 1 ) { - // if not running as a game client, sleep a bit -#ifndef DEDICATED - if ( g_wv.isMinimized || ( com_dedicated && com_dedicated->integer ) ) { - Sleep( 5 ); - } -#else - Sleep(5); -#endif - - // set low precision every frame, because some system calls - // reset it arbitrarily -// _controlfp( _PC_24, _MCW_PC ); -// _controlfp( -1, _MCW_EM ); // no exceptions, even if some crappy - // syscall turns them back on! - - startTime = Sys_Milliseconds(); - - // make sure mouse and joystick are only called once a frame - IN_Frame(); - - // run the game - Com_Frame(); - - endTime = Sys_Milliseconds(); - totalMsec += endTime - startTime; - countMsec++; - } - - // never gets here -} - - diff --git a/code/win32/win_manifest.xml b/code/win32/win_manifest.xml deleted file mode 100644 index ae5906dc..00000000 --- a/code/win32/win_manifest.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True/PM - PerMonitorV2, PerMonitor - - - diff --git a/code/win32/win_net.c b/code/win32/win_net.c deleted file mode 100644 index 07c762e0..00000000 --- a/code/win32/win_net.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// net_wins.c - -#include "../qcommon/q_shared.h" -#include "../qcommon/qcommon.h" -#include "win_local.h" - -static WSADATA winsockdata; -static qboolean winsockInitialized = qfalse; -static qboolean usingSocks = qfalse; -static qboolean networkingEnabled = qfalse; - -static cvar_t *net_noudp; -static cvar_t *net_noipx; - -static cvar_t *net_socksEnabled; -static cvar_t *net_socksServer; -static cvar_t *net_socksPort; -static cvar_t *net_socksUsername; -static cvar_t *net_socksPassword; -static struct sockaddr socksRelayAddr; - -static SOCKET ip_socket; -static SOCKET socks_socket; -static SOCKET ipx_socket; - -#define MAX_IPS 16 -static int numIP; -static byte localIP[MAX_IPS][4]; - -//============================================================================= - - -/* -==================== -NET_ErrorString -==================== -*/ -char *NET_ErrorString( void ) { - int code; - - code = WSAGetLastError(); - switch( code ) { - case WSAEINTR: return "WSAEINTR"; - case WSAEBADF: return "WSAEBADF"; - case WSAEACCES: return "WSAEACCES"; - case WSAEDISCON: return "WSAEDISCON"; - case WSAEFAULT: return "WSAEFAULT"; - case WSAEINVAL: return "WSAEINVAL"; - case WSAEMFILE: return "WSAEMFILE"; - case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK"; - case WSAEINPROGRESS: return "WSAEINPROGRESS"; - case WSAEALREADY: return "WSAEALREADY"; - case WSAENOTSOCK: return "WSAENOTSOCK"; - case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ"; - case WSAEMSGSIZE: return "WSAEMSGSIZE"; - case WSAEPROTOTYPE: return "WSAEPROTOTYPE"; - case WSAENOPROTOOPT: return "WSAENOPROTOOPT"; - case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT"; - case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT"; - case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP"; - case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT"; - case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT"; - case WSAEADDRINUSE: return "WSAEADDRINUSE"; - case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL"; - case WSAENETDOWN: return "WSAENETDOWN"; - case WSAENETUNREACH: return "WSAENETUNREACH"; - case WSAENETRESET: return "WSAENETRESET"; - case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR"; - case WSAECONNRESET: return "WSAECONNRESET"; - case WSAENOBUFS: return "WSAENOBUFS"; - case WSAEISCONN: return "WSAEISCONN"; - case WSAENOTCONN: return "WSAENOTCONN"; - case WSAESHUTDOWN: return "WSAESHUTDOWN"; - case WSAETOOMANYREFS: return "WSAETOOMANYREFS"; - case WSAETIMEDOUT: return "WSAETIMEDOUT"; - case WSAECONNREFUSED: return "WSAECONNREFUSED"; - case WSAELOOP: return "WSAELOOP"; - case WSAENAMETOOLONG: return "WSAENAMETOOLONG"; - case WSAEHOSTDOWN: return "WSAEHOSTDOWN"; - case WSASYSNOTREADY: return "WSASYSNOTREADY"; - case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED"; - case WSANOTINITIALISED: return "WSANOTINITIALISED"; - case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND"; - case WSATRY_AGAIN: return "WSATRY_AGAIN"; - case WSANO_RECOVERY: return "WSANO_RECOVERY"; - case WSANO_DATA: return "WSANO_DATA"; - default: return "NO ERROR"; - } -} - -void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) { - memset( s, 0, sizeof(*s) ); - - if( a->type == NA_BROADCAST ) { - ((struct sockaddr_in *)s)->sin_family = AF_INET; - ((struct sockaddr_in *)s)->sin_port = a->port; - ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; - } - else if( a->type == NA_IP ) { - ((struct sockaddr_in *)s)->sin_family = AF_INET; - ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; - ((struct sockaddr_in *)s)->sin_port = a->port; - } - else if( a->type == NA_IPX ) { - ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; - memcpy( ((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4 ); - memcpy( ((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6 ); - ((struct sockaddr_ipx *)s)->sa_socket = a->port; - } - else if( a->type == NA_BROADCAST_IPX ) { - ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; - memset( ((struct sockaddr_ipx *)s)->sa_netnum, 0, 4 ); - memset( ((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6 ); - ((struct sockaddr_ipx *)s)->sa_socket = a->port; - } -} - - -void SockadrToNetadr( struct sockaddr *s, netadr_t *a ) { - if (s->sa_family == AF_INET) { - a->type = NA_IP; - *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; - a->port = ((struct sockaddr_in *)s)->sin_port; - } - else if( s->sa_family == AF_IPX ) { - a->type = NA_IPX; - memcpy( &a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4 ); - memcpy( &a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6 ); - a->port = ((struct sockaddr_ipx *)s)->sa_socket; - } -} - - -/* -============= -Sys_StringToAdr - -idnewt -192.246.40.70 -12121212.121212121212 -============= -*/ -#define DO(src,dest) \ - copy[0] = s[src]; \ - copy[1] = s[src + 1]; \ - sscanf (copy, "%x", &val); \ - ((struct sockaddr_ipx *)sadr)->dest = val - -qboolean Sys_StringToSockaddr( const char *s, struct sockaddr *sadr ) { - struct hostent *h; - int val; - char copy[MAX_STRING_CHARS]; - - memset( sadr, 0, sizeof( *sadr ) ); - - // check for an IPX address - if( ( strlen( s ) == 21 ) && ( s[8] == '.' ) ) { - ((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX; - ((struct sockaddr_ipx *)sadr)->sa_socket = 0; - copy[2] = 0; - DO(0, sa_netnum[0]); - DO(2, sa_netnum[1]); - DO(4, sa_netnum[2]); - DO(6, sa_netnum[3]); - DO(9, sa_nodenum[0]); - DO(11, sa_nodenum[1]); - DO(13, sa_nodenum[2]); - DO(15, sa_nodenum[3]); - DO(17, sa_nodenum[4]); - DO(19, sa_nodenum[5]); - } - else { - ((struct sockaddr_in *)sadr)->sin_family = AF_INET; - ((struct sockaddr_in *)sadr)->sin_port = 0; - - if( s[0] >= '0' && s[0] <= '9' ) { - *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s); - } else { - if( ( h = gethostbyname( s ) ) == 0 ) { - return 0; - } - *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; - } - } - - return qtrue; -} - -#undef DO - -/* -============= -Sys_StringToAdr - -idnewt -192.246.40.70 -============= -*/ -qboolean Sys_StringToAdr( const char *s, netadr_t *a ) { - struct sockaddr sadr; - - if ( !Sys_StringToSockaddr( s, &sadr ) ) { - return qfalse; - } - - SockadrToNetadr( &sadr, a ); - return qtrue; -} - -//============================================================================= - -/* -================== -Sys_GetPacket - -Never called by the game logic, just the system event queing -================== -*/ -int recvfromCount; - -qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { - int ret; - struct sockaddr from; - int fromlen; - int net_socket; - int protocol; - int err; - - for( protocol = 0 ; protocol < 2 ; protocol++ ) { - if( protocol == 0 ) { - net_socket = ip_socket; - } - else { - net_socket = ipx_socket; - } - - if( !net_socket ) { - continue; - } - - fromlen = sizeof(from); - recvfromCount++; // performance check - ret = recvfrom( net_socket, net_message->data, net_message->maxsize, 0, (struct sockaddr *)&from, &fromlen ); - if (ret == SOCKET_ERROR) - { - err = WSAGetLastError(); - - if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) { - continue; - } - Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() ); - continue; - } - - if ( net_socket == ip_socket ) { - memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 ); - } - - if ( usingSocks && net_socket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) { - if ( ret < 10 || net_message->data[0] != 0 || net_message->data[1] != 0 || net_message->data[2] != 0 || net_message->data[3] != 1 ) { - continue; - } - net_from->type = NA_IP; - net_from->ip[0] = net_message->data[4]; - net_from->ip[1] = net_message->data[5]; - net_from->ip[2] = net_message->data[6]; - net_from->ip[3] = net_message->data[7]; - net_from->port = *(short *)&net_message->data[8]; - net_message->readcount = 10; - } - else { - SockadrToNetadr( &from, net_from ); - net_message->readcount = 0; - } - - if( ret == net_message->maxsize ) { - Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); - continue; - } - - net_message->cursize = ret; - return qtrue; - } - - return qfalse; -} - -//============================================================================= - -static char socksBuf[4096]; - -/* -================== -Sys_SendPacket -================== -*/ -void Sys_SendPacket( size_t length, const void *data, netadr_t to ) { - int ret; - struct sockaddr addr; - SOCKET net_socket; - - if( to.type == NA_BROADCAST ) { - net_socket = ip_socket; - } - else if( to.type == NA_IP ) { - net_socket = ip_socket; - } - else if( to.type == NA_IPX ) { - net_socket = ipx_socket; - } - else if( to.type == NA_BROADCAST_IPX ) { - net_socket = ipx_socket; - } - else { - Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" ); - return; - } - - if( !net_socket ) { - return; - } - - NetadrToSockadr( &to, &addr ); - - if( usingSocks && to.type == NA_IP ) { - socksBuf[0] = 0; // reserved - socksBuf[1] = 0; - socksBuf[2] = 0; // fragment (not fragmented) - socksBuf[3] = 1; // address type: IPV4 - *(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr; - *(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port; - memcpy( &socksBuf[10], data, length ); - ret = sendto( net_socket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr) ); - } - else { - ret = sendto( net_socket, data, length, 0, &addr, sizeof(addr) ); - } - if( ret == SOCKET_ERROR ) { - int err = WSAGetLastError(); - - // wouldblock is silent - if( err == WSAEWOULDBLOCK ) { - return; - } - - // some PPP links do not allow broadcasts and return an error - if( ( err == WSAEADDRNOTAVAIL ) && ( ( to.type == NA_BROADCAST ) || ( to.type == NA_BROADCAST_IPX ) ) ) { - return; - } - - Com_Printf( "NET_SendPacket: %s\n", NET_ErrorString() ); - } -} - - -//============================================================================= - -/* -================== -Sys_IsLANAddress - -LAN clients will have their rate var ignored -================== -*/ -qboolean Sys_IsLANAddress( netadr_t adr ) { - int i; - - if( adr.type == NA_LOOPBACK ) { - return qtrue; - } - - if( adr.type == NA_IPX ) { - return qtrue; - } - - if( adr.type != NA_IP ) { - return qfalse; - } - - // choose which comparison to use based on the class of the address being tested - // any local adresses of a different class than the address being tested will fail based on the first byte - - if( adr.ip[0] == 127 && adr.ip[1] == 0 && adr.ip[2] == 0 && adr.ip[3] == 1 ) { - return qtrue; - } - - // Class A - if( (adr.ip[0] & 0x80) == 0x00 ) { - for ( i = 0 ; i < numIP ; i++ ) { - if( adr.ip[0] == localIP[i][0] ) { - return qtrue; - } - } - // the RFC1918 class a block will pass the above test - return qfalse; - } - - // Class B - if( (adr.ip[0] & 0xc0) == 0x80 ) { - for ( i = 0 ; i < numIP ; i++ ) { - if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) { - return qtrue; - } - // also check against the RFC1918 class b blocks - if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) { - return qtrue; - } - } - return qfalse; - } - - // Class C - for ( i = 0 ; i < numIP ; i++ ) { - if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) { - return qtrue; - } - // also check against the RFC1918 class c blocks - if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) { - return qtrue; - } - } - return qfalse; -} - -/* -================== -Sys_ShowIP -================== -*/ -void Sys_ShowIP(void) { - int i; - - for (i = 0; i < numIP; i++) { - Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] ); - } -} - - -//============================================================================= - - -/* -==================== -NET_IPSocket -==================== -*/ -int NET_IPSocket( char *net_interface, int port ) { - SOCKET newsocket; - struct sockaddr_in address; - qboolean _true = qtrue; - int i = 1; - int err; - - if( net_interface ) { - Com_Printf( "Opening IP socket: %s:%i\n", net_interface, port ); - } - else { - Com_Printf( "Opening IP socket: localhost:%i\n", port ); - } - - if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) { - err = WSAGetLastError(); - if( err != WSAEAFNOSUPPORT ) { - Com_Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() ); - } - return 0; - } - - // make it non-blocking - if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() ); - return 0; - } - - // make it broadcast capable - if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) { - Com_Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); - return 0; - } - - if( !net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost") ) { - address.sin_addr.s_addr = INADDR_ANY; - } - else { - Sys_StringToSockaddr( net_interface, (struct sockaddr *)&address ); - } - - if( port == PORT_ANY ) { - address.sin_port = 0; - } - else { - address.sin_port = htons( (short)port ); - } - - address.sin_family = AF_INET; - - if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { - Com_Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() ); - closesocket( newsocket ); - return 0; - } - - return newsocket; -} - - -/* -==================== -NET_OpenSocks -==================== -*/ -void NET_OpenSocks( int port ) { - struct sockaddr_in address; - int err; - struct hostent *h; - int len; - qboolean rfc1929; - unsigned char buf[64]; - - usingSocks = qfalse; - - Com_Printf( "Opening connection to SOCKS server.\n" ); - - if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) { - err = WSAGetLastError(); - Com_Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() ); - return; - } - - h = gethostbyname( net_socksServer->string ); - if ( h == NULL ) { - err = WSAGetLastError(); - Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() ); - return; - } - if ( h->h_addrtype != AF_INET ) { - Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" ); - return; - } - address.sin_family = AF_INET; - address.sin_addr.s_addr = *(int *)h->h_addr_list[0]; - address.sin_port = htons( (short)net_socksPort->integer ); - - if ( connect( socks_socket, (struct sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() ); - return; - } - - // send socks authentication handshake - if ( *net_socksUsername->string || *net_socksPassword->string ) { - rfc1929 = qtrue; - } - else { - rfc1929 = qfalse; - } - - buf[0] = 5; // SOCKS version - // method count - if ( rfc1929 ) { - buf[1] = 2; - len = 4; - } - else { - buf[1] = 1; - len = 3; - } - buf[2] = 0; // method #1 - method id #00: no authentication - if ( rfc1929 ) { - buf[2] = 2; // method #2 - method id #02: username/password - } - if ( send( socks_socket, buf, len, 0 ) == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); - return; - } - - // get the response - len = recv( socks_socket, buf, 64, 0 ); - if ( len == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); - return; - } - if ( len != 2 || buf[0] != 5 ) { - Com_Printf( "NET_OpenSocks: bad response\n" ); - return; - } - switch( buf[1] ) { - case 0: // no authentication - break; - case 2: // username/password authentication - break; - default: - Com_Printf( "NET_OpenSocks: request denied\n" ); - return; - } - - // do username/password authentication if needed - if ( buf[1] == 2 ) { - int ulen; - int plen; - - // build the request - ulen = strlen( net_socksUsername->string ); - plen = strlen( net_socksPassword->string ); - - buf[0] = 1; // username/password authentication version - buf[1] = ulen; - if ( ulen ) { - memcpy( &buf[2], net_socksUsername->string, ulen ); - } - buf[2 + ulen] = plen; - if ( plen ) { - memcpy( &buf[3 + ulen], net_socksPassword->string, plen ); - } - - // send it - if ( send( socks_socket, buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); - return; - } - - // get the response - len = recv( socks_socket, buf, 64, 0 ); - if ( len == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); - return; - } - if ( len != 2 || buf[0] != 1 ) { - Com_Printf( "NET_OpenSocks: bad response\n" ); - return; - } - if ( buf[1] != 0 ) { - Com_Printf( "NET_OpenSocks: authentication failed\n" ); - return; - } - } - - // send the UDP associate request - buf[0] = 5; // SOCKS version - buf[1] = 3; // command: UDP associate - buf[2] = 0; // reserved - buf[3] = 1; // address type: IPV4 - *(int *)&buf[4] = INADDR_ANY; - *(short *)&buf[8] = htons( (short)port ); // port - if ( send( socks_socket, buf, 10, 0 ) == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); - return; - } - - // get the response - len = recv( socks_socket, buf, 64, 0 ); - if( len == SOCKET_ERROR ) { - err = WSAGetLastError(); - Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); - return; - } - if( len < 2 || buf[0] != 5 ) { - Com_Printf( "NET_OpenSocks: bad response\n" ); - return; - } - // check completion code - if( buf[1] != 0 ) { - Com_Printf( "NET_OpenSocks: request denied: %i\n", buf[1] ); - return; - } - if( buf[3] != 1 ) { - Com_Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] ); - return; - } - ((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET; - ((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4]; - ((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8]; - memset( ((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 ); - - usingSocks = qtrue; -} - - -/* -===================== -NET_GetLocalAddress -===================== -*/ -void NET_GetLocalAddress( void ) { - char hostname[256]; - struct hostent *hostInfo; - int error; - char *p; - int ip; - int n; - - if( gethostname( hostname, 256 ) == SOCKET_ERROR ) { - error = WSAGetLastError(); - return; - } - - hostInfo = gethostbyname( hostname ); - if( !hostInfo ) { - error = WSAGetLastError(); - return; - } - - Com_Printf( "Hostname: %s\n", hostInfo->h_name ); - n = 0; - while( ( p = hostInfo->h_aliases[n++] ) != NULL ) { - Com_Printf( "Alias: %s\n", p ); - } - - if ( hostInfo->h_addrtype != AF_INET ) { - return; - } - - numIP = 0; - while( ( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS ) { - ip = ntohl( *(int *)p ); - localIP[ numIP ][0] = p[0]; - localIP[ numIP ][1] = p[1]; - localIP[ numIP ][2] = p[2]; - localIP[ numIP ][3] = p[3]; - Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff ); - numIP++; - } -} - -/* -==================== -NET_OpenIP -==================== -*/ -void NET_OpenIP( void ) { - cvar_t *ip; - int port; - int i; - - ip = Cvar_Get( "net_ip", "localhost", CVAR_LATCH ); - port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer; - - // automatically scan for a valid port, so multiple - // dedicated servers can be started without requiring - // a different net_port for each one - for( i = 0 ; i < 10 ; i++ ) { - ip_socket = NET_IPSocket( ip->string, port + i ); - if ( ip_socket ) { - Cvar_SetValue( "net_port", port + i ); - if ( net_socksEnabled->integer ) { - NET_OpenSocks( port + i ); - } - NET_GetLocalAddress(); - return; - } - } - Com_Printf( "WARNING: Couldn't allocate IP port\n"); -} - - -/* -==================== -NET_IPXSocket -==================== -*/ -int NET_IPXSocket( int port ) { - SOCKET newsocket; - struct sockaddr_ipx address; - int _true = 1; - int err; - - if( ( newsocket = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX ) ) == INVALID_SOCKET ) { - err = WSAGetLastError(); - if (err != WSAEAFNOSUPPORT) { - Com_Printf( "WARNING: IPX_Socket: socket: %s\n", NET_ErrorString() ); - } - return 0; - } - - // make it non-blocking - if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_Printf( "WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString() ); - return 0; - } - - // make it broadcast capable - if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof( _true ) ) == SOCKET_ERROR ) { - Com_Printf( "WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); - return 0; - } - - address.sa_family = AF_IPX; - memset( address.sa_netnum, 0, 4 ); - memset( address.sa_nodenum, 0, 6 ); - if( port == PORT_ANY ) { - address.sa_socket = 0; - } - else { - address.sa_socket = htons( (short)port ); - } - - if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { - Com_Printf( "WARNING: IPX_Socket: bind: %s\n", NET_ErrorString() ); - closesocket( newsocket ); - return 0; - } - - return newsocket; -} - - -/* -==================== -NET_OpenIPX -==================== -*/ -void NET_OpenIPX( void ) { - int port; - - port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer; - ipx_socket = NET_IPXSocket( port ); -} - - - -//=================================================================== - - -/* -==================== -NET_GetCvars -==================== -*/ -static qboolean NET_GetCvars( void ) { - qboolean modified; - - modified = qfalse; - - if( net_noudp && net_noudp->modified ) { - modified = qtrue; - } - net_noudp = Cvar_Get( "net_noudp", "0", CVAR_LATCH | CVAR_ARCHIVE ); - - if( net_noipx && net_noipx->modified ) { - modified = qtrue; - } - net_noipx = Cvar_Get( "net_noipx", "0", CVAR_LATCH | CVAR_ARCHIVE ); - - - if( net_socksEnabled && net_socksEnabled->modified ) { - modified = qtrue; - } - net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE ); - - if( net_socksServer && net_socksServer->modified ) { - modified = qtrue; - } - net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE ); - - if( net_socksPort && net_socksPort->modified ) { - modified = qtrue; - } - net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE ); - - if( net_socksUsername && net_socksUsername->modified ) { - modified = qtrue; - } - net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE ); - - if( net_socksPassword && net_socksPassword->modified ) { - modified = qtrue; - } - net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE ); - - - return modified; -} - - -/* -==================== -NET_Config -==================== -*/ -void NET_Config( qboolean enableNetworking ) { - qboolean modified; - qboolean stop; - qboolean start; - - // get any latched changes to cvars - modified = NET_GetCvars(); - - if( net_noudp->integer && net_noipx->integer ) { - enableNetworking = qfalse; - } - - // if enable state is the same and no cvars were modified, we have nothing to do - if( enableNetworking == networkingEnabled && !modified ) { - return; - } - - if( enableNetworking == networkingEnabled ) { - if( enableNetworking ) { - stop = qtrue; - start = qtrue; - } - else { - stop = qfalse; - start = qfalse; - } - } - else { - if( enableNetworking ) { - stop = qfalse; - start = qtrue; - } - else { - stop = qtrue; - start = qfalse; - } - networkingEnabled = enableNetworking; - } - - if( stop ) { - if ( ip_socket && ip_socket != INVALID_SOCKET ) { - closesocket( ip_socket ); - ip_socket = 0; - } - - if ( socks_socket && socks_socket != INVALID_SOCKET ) { - closesocket( socks_socket ); - socks_socket = 0; - } - - if ( ipx_socket && ipx_socket != INVALID_SOCKET ) { - closesocket( ipx_socket ); - ipx_socket = 0; - } - } - - if( start ) { - if (! net_noudp->integer ) { - NET_OpenIP(); - } - if (! net_noipx->integer ) { - NET_OpenIPX(); - } - } -} - - -/* -==================== -NET_Init -==================== -*/ -void NET_Init( void ) { - int r; - - r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata ); - if( r ) { - Com_Printf( "WARNING: Winsock initialization failed, returned %d\n", r ); - return; - } - - winsockInitialized = qtrue; - Com_Printf( "Winsock Initialized\n" ); - - // this is really just to get the cvars registered - NET_GetCvars(); - - //FIXME testing! - NET_Config( qtrue ); -} - - -/* -==================== -NET_Shutdown -==================== -*/ -void NET_Shutdown( void ) { - if ( !winsockInitialized ) { - return; - } - NET_Config( qfalse ); - WSACleanup(); - winsockInitialized = qfalse; -} - - -/* -==================== -NET_Sleep - -sleeps msec or until net socket is ready -==================== -*/ -void NET_Sleep( int msec ) { -} - - -/* -==================== -NET_Restart_f -==================== -*/ -void NET_Restart( void ) { - NET_Config( networkingEnabled ); -} diff --git a/code/win32/win_qgl.c b/code/win32/win_qgl.c deleted file mode 100644 index b7bfdf5f..00000000 --- a/code/win32/win_qgl.c +++ /dev/null @@ -1,4396 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -/* -** QGL_WIN.C -** -** This file implements the operating system binding of GL to QGL function -** pointers. When doing a port of Quake3 you must implement the following -** two functions: -** -** QGL_Init() - loads libraries, assigns function pointers, etc. -** QGL_Shutdown() - unloads libraries, NULLs function pointers -*/ -#include -#include "../renderer/tr_local.h" -#include "glw_win.h" - -void QGL_EnableLogging( qboolean enable ); - -int ( WINAPI * qwglSwapIntervalEXT)( int interval ); -BOOL ( WINAPI * qwglGetDeviceGammaRamp3DFX)( HDC, LPVOID ); -BOOL ( WINAPI * qwglSetDeviceGammaRamp3DFX)( HDC, LPVOID ); - -int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); -int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); -int ( WINAPI * qwglGetPixelFormat)(HDC); -BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); -BOOL ( WINAPI * qwglSwapBuffers)(HDC); - -BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT); -HGLRC ( WINAPI * qwglCreateContext)(HDC); -HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int); -BOOL ( WINAPI * qwglDeleteContext)(HGLRC); -HGLRC ( WINAPI * qwglGetCurrentContext)(VOID); -HDC ( WINAPI * qwglGetCurrentDC)(VOID); -PROC ( WINAPI * qwglGetProcAddress)(LPCSTR); -BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC); -BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC); -BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD); - -BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT, - FLOAT, int, LPGLYPHMETRICSFLOAT); - -BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, - LPLAYERPLANEDESCRIPTOR); -int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, - CONST COLORREF *); -int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, - COLORREF *); -BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL); -BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT); - -void ( APIENTRY * qglAccum )(GLenum op, GLfloat value); -void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref); -GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); -void ( APIENTRY * qglArrayElement )(GLint i); -void ( APIENTRY * qglBegin )(GLenum mode); -void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture); -void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); -void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor); -void ( APIENTRY * qglCallList )(GLuint list); -void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists); -void ( APIENTRY * qglClear )(GLbitfield mask); -void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -void ( APIENTRY * qglClearDepth )(GLclampd depth); -void ( APIENTRY * qglClearIndex )(GLfloat c); -void ( APIENTRY * qglClearStencil )(GLint s); -void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation); -void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue); -void ( APIENTRY * qglColor3bv )(const GLbyte *v); -void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue); -void ( APIENTRY * qglColor3dv )(const GLdouble *v); -void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue); -void ( APIENTRY * qglColor3fv )(const GLfloat *v); -void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue); -void ( APIENTRY * qglColor3iv )(const GLint *v); -void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue); -void ( APIENTRY * qglColor3sv )(const GLshort *v); -void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue); -void ( APIENTRY * qglColor3ubv )(const GLubyte *v); -void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue); -void ( APIENTRY * qglColor3uiv )(const GLuint *v); -void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue); -void ( APIENTRY * qglColor3usv )(const GLushort *v); -void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); -void ( APIENTRY * qglColor4bv )(const GLbyte *v); -void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); -void ( APIENTRY * qglColor4dv )(const GLdouble *v); -void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void ( APIENTRY * qglColor4fv )(const GLfloat *v); -void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha); -void ( APIENTRY * qglColor4iv )(const GLint *v); -void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); -void ( APIENTRY * qglColor4sv )(const GLshort *v); -void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -void ( APIENTRY * qglColor4ubv )(const GLubyte *v); -void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); -void ( APIENTRY * qglColor4uiv )(const GLuint *v); -void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); -void ( APIENTRY * qglColor4usv )(const GLushort *v); -void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode); -void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); -void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); -void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -void ( APIENTRY * qglCullFace )(GLenum mode); -void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range); -void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures); -void ( APIENTRY * qglDepthFunc )(GLenum func); -void ( APIENTRY * qglDepthMask )(GLboolean flag); -void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar); -void ( APIENTRY * qglDisable )(GLenum cap); -void ( APIENTRY * qglDisableClientState )(GLenum array); -void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count); -void ( APIENTRY * qglDrawBuffer )(GLenum mode); -void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY * qglEdgeFlag )(GLboolean flag); -void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); -void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag); -void ( APIENTRY * qglEnable )(GLenum cap); -void ( APIENTRY * qglEnableClientState )(GLenum array); -void ( APIENTRY * qglEnd )(void); -void ( APIENTRY * qglEndList )(void); -void ( APIENTRY * qglEvalCoord1d )(GLdouble u); -void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u); -void ( APIENTRY * qglEvalCoord1f )(GLfloat u); -void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u); -void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v); -void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u); -void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v); -void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u); -void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2); -void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); -void ( APIENTRY * qglEvalPoint1 )(GLint i); -void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j); -void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); -void ( APIENTRY * qglFinish )(void); -void ( APIENTRY * qglFlush )(void); -void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param); -void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params); -void ( APIENTRY * qglFogi )(GLenum pname, GLint param); -void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params); -void ( APIENTRY * qglFrontFace )(GLenum mode); -void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -GLuint ( APIENTRY * qglGenLists )(GLsizei range); -void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures); -void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params); -void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation); -void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params); -GLenum ( APIENTRY * qglGetError )(void); -void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params); -void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params); -void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v); -void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v); -void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v); -void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params); -void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values); -void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values); -void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values); -void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params); -void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask); -const GLubyte * ( APIENTRY * qglGetString )(GLenum name); -void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params); -void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); -void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); -void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); -void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); -void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); -void ( APIENTRY * qglHint )(GLenum target, GLenum mode); -void ( APIENTRY * qglIndexMask )(GLuint mask); -void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY * qglIndexd )(GLdouble c); -void ( APIENTRY * qglIndexdv )(const GLdouble *c); -void ( APIENTRY * qglIndexf )(GLfloat c); -void ( APIENTRY * qglIndexfv )(const GLfloat *c); -void ( APIENTRY * qglIndexi )(GLint c); -void ( APIENTRY * qglIndexiv )(const GLint *c); -void ( APIENTRY * qglIndexs )(GLshort c); -void ( APIENTRY * qglIndexsv )(const GLshort *c); -void ( APIENTRY * qglIndexub )(GLubyte c); -void ( APIENTRY * qglIndexubv )(const GLubyte *c); -void ( APIENTRY * qglInitNames )(void); -void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); -GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap); -GLboolean ( APIENTRY * qglIsList )(GLuint list); -GLboolean ( APIENTRY * qglIsTexture )(GLuint texture); -void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param); -void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params); -void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param); -void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params); -void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param); -void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params); -void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param); -void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params); -void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern); -void ( APIENTRY * qglLineWidth )(GLfloat width); -void ( APIENTRY * qglListBase )(GLuint base); -void ( APIENTRY * qglLoadIdentity )(void); -void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m); -void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m); -void ( APIENTRY * qglLoadName )(GLuint name); -void ( APIENTRY * qglLogicOp )(GLenum opcode); -void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); -void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); -void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); -void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); -void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param); -void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); -void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param); -void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params); -void ( APIENTRY * qglMatrixMode )(GLenum mode); -void ( APIENTRY * qglMultMatrixd )(const GLdouble *m); -void ( APIENTRY * qglMultMatrixf )(const GLfloat *m); -void ( APIENTRY * qglNewList )(GLuint list, GLenum mode); -void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); -void ( APIENTRY * qglNormal3bv )(const GLbyte *v); -void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); -void ( APIENTRY * qglNormal3dv )(const GLdouble *v); -void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); -void ( APIENTRY * qglNormal3fv )(const GLfloat *v); -void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz); -void ( APIENTRY * qglNormal3iv )(const GLint *v); -void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz); -void ( APIENTRY * qglNormal3sv )(const GLshort *v); -void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -void ( APIENTRY * qglPassThrough )(GLfloat token); -void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); -void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); -void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); -void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param); -void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param); -void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param); -void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param); -void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor); -void ( APIENTRY * qglPointSize )(GLfloat size); -void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode); -void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units); -void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask); -void ( APIENTRY * qglPopAttrib )(void); -void ( APIENTRY * qglPopClientAttrib )(void); -void ( APIENTRY * qglPopMatrix )(void); -void ( APIENTRY * qglPopName )(void); -void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); -void ( APIENTRY * qglPushAttrib )(GLbitfield mask); -void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask); -void ( APIENTRY * qglPushMatrix )(void); -void ( APIENTRY * qglPushName )(GLuint name); -void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y); -void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v); -void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y); -void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v); -void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y); -void ( APIENTRY * qglRasterPos2iv )(const GLint *v); -void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y); -void ( APIENTRY * qglRasterPos2sv )(const GLshort *v); -void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v); -void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v); -void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z); -void ( APIENTRY * qglRasterPos3iv )(const GLint *v); -void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z); -void ( APIENTRY * qglRasterPos3sv )(const GLshort *v); -void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v); -void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v); -void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w); -void ( APIENTRY * qglRasterPos4iv )(const GLint *v); -void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); -void ( APIENTRY * qglRasterPos4sv )(const GLshort *v); -void ( APIENTRY * qglReadBuffer )(GLenum mode); -void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); -void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2); -void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); -void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2); -void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2); -void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2); -void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); -void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2); -GLint ( APIENTRY * qglRenderMode )(GLenum mode); -void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height); -void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer); -void ( APIENTRY * qglShadeModel )(GLenum mode); -void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask); -void ( APIENTRY * qglStencilMask )(GLuint mask); -void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); -void ( APIENTRY * qglTexCoord1d )(GLdouble s); -void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v); -void ( APIENTRY * qglTexCoord1f )(GLfloat s); -void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v); -void ( APIENTRY * qglTexCoord1i )(GLint s); -void ( APIENTRY * qglTexCoord1iv )(const GLint *v); -void ( APIENTRY * qglTexCoord1s )(GLshort s); -void ( APIENTRY * qglTexCoord1sv )(const GLshort *v); -void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t); -void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v); -void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t); -void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v); -void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t); -void ( APIENTRY * qglTexCoord2iv )(const GLint *v); -void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t); -void ( APIENTRY * qglTexCoord2sv )(const GLshort *v); -void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); -void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v); -void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); -void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v); -void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r); -void ( APIENTRY * qglTexCoord3iv )(const GLint *v); -void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r); -void ( APIENTRY * qglTexCoord3sv )(const GLshort *v); -void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); -void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v); -void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); -void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v); -void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q); -void ( APIENTRY * qglTexCoord4iv )(const GLint *v); -void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); -void ( APIENTRY * qglTexCoord4sv )(const GLshort *v); -void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param); -void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); -void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param); -void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params); -void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param); -void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); -void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param); -void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); -void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param); -void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params); -void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param); -void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); -void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param); -void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params); -void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y); -void ( APIENTRY * qglVertex2dv )(const GLdouble *v); -void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y); -void ( APIENTRY * qglVertex2fv )(const GLfloat *v); -void ( APIENTRY * qglVertex2i )(GLint x, GLint y); -void ( APIENTRY * qglVertex2iv )(const GLint *v); -void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y); -void ( APIENTRY * qglVertex2sv )(const GLshort *v); -void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY * qglVertex3dv )(const GLdouble *v); -void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY * qglVertex3fv )(const GLfloat *v); -void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z); -void ( APIENTRY * qglVertex3iv )(const GLint *v); -void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z); -void ( APIENTRY * qglVertex3sv )(const GLshort *v); -void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void ( APIENTRY * qglVertex4dv )(const GLdouble *v); -void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void ( APIENTRY * qglVertex4fv )(const GLfloat *v); -void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w); -void ( APIENTRY * qglVertex4iv )(const GLint *v); -void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); -void ( APIENTRY * qglVertex4sv )(const GLshort *v); -void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height); -void (APIENTRY* qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -void (APIENTRY* qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -void (APIENTRY* qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -void (APIENTRY* qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -void (APIENTRY* qglGetCompressedTexImageARB)(GLenum target, GLint lod, void* img); - -void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t ); -void ( APIENTRY * qglActiveTextureARB )( GLenum texture ); -void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture ); - -void ( APIENTRY* qglLockArraysEXT )(GLint, GLint); -void ( APIENTRY* qglUnlockArraysEXT ) (void); - -static void ( APIENTRY * dllAccum )(GLenum op, GLfloat value); -static void ( APIENTRY * dllAlphaFunc )(GLenum func, GLclampf ref); -GLboolean ( APIENTRY * dllAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); -static void ( APIENTRY * dllArrayElement )(GLint i); -static void ( APIENTRY * dllBegin )(GLenum mode); -static void ( APIENTRY * dllBindTexture )(GLenum target, GLuint texture); -static void ( APIENTRY * dllBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); -static void ( APIENTRY * dllBlendFunc )(GLenum sfactor, GLenum dfactor); -static void ( APIENTRY * dllCallList )(GLuint list); -static void ( APIENTRY * dllCallLists )(GLsizei n, GLenum type, const GLvoid *lists); -static void ( APIENTRY * dllClear )(GLbitfield mask); -static void ( APIENTRY * dllClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -static void ( APIENTRY * dllClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -static void ( APIENTRY * dllClearDepth )(GLclampd depth); -static void ( APIENTRY * dllClearIndex )(GLfloat c); -static void ( APIENTRY * dllClearStencil )(GLint s); -static void ( APIENTRY * dllClipPlane )(GLenum plane, const GLdouble *equation); -static void ( APIENTRY * dllColor3b )(GLbyte red, GLbyte green, GLbyte blue); -static void ( APIENTRY * dllColor3bv )(const GLbyte *v); -static void ( APIENTRY * dllColor3d )(GLdouble red, GLdouble green, GLdouble blue); -static void ( APIENTRY * dllColor3dv )(const GLdouble *v); -static void ( APIENTRY * dllColor3f )(GLfloat red, GLfloat green, GLfloat blue); -static void ( APIENTRY * dllColor3fv )(const GLfloat *v); -static void ( APIENTRY * dllColor3i )(GLint red, GLint green, GLint blue); -static void ( APIENTRY * dllColor3iv )(const GLint *v); -static void ( APIENTRY * dllColor3s )(GLshort red, GLshort green, GLshort blue); -static void ( APIENTRY * dllColor3sv )(const GLshort *v); -static void ( APIENTRY * dllColor3ub )(GLubyte red, GLubyte green, GLubyte blue); -static void ( APIENTRY * dllColor3ubv )(const GLubyte *v); -static void ( APIENTRY * dllColor3ui )(GLuint red, GLuint green, GLuint blue); -static void ( APIENTRY * dllColor3uiv )(const GLuint *v); -static void ( APIENTRY * dllColor3us )(GLushort red, GLushort green, GLushort blue); -static void ( APIENTRY * dllColor3usv )(const GLushort *v); -static void ( APIENTRY * dllColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); -static void ( APIENTRY * dllColor4bv )(const GLbyte *v); -static void ( APIENTRY * dllColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); -static void ( APIENTRY * dllColor4dv )(const GLdouble *v); -static void ( APIENTRY * dllColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -static void ( APIENTRY * dllColor4fv )(const GLfloat *v); -static void ( APIENTRY * dllColor4i )(GLint red, GLint green, GLint blue, GLint alpha); -static void ( APIENTRY * dllColor4iv )(const GLint *v); -static void ( APIENTRY * dllColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); -static void ( APIENTRY * dllColor4sv )(const GLshort *v); -static void ( APIENTRY * dllColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -static void ( APIENTRY * dllColor4ubv )(const GLubyte *v); -static void ( APIENTRY * dllColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); -static void ( APIENTRY * dllColor4uiv )(const GLuint *v); -static void ( APIENTRY * dllColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); -static void ( APIENTRY * dllColor4usv )(const GLushort *v); -static void ( APIENTRY * dllColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -static void ( APIENTRY * dllColorMaterial )(GLenum face, GLenum mode); -static void ( APIENTRY * dllColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -static void ( APIENTRY * dllCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); -static void ( APIENTRY * dllCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); -static void ( APIENTRY * dllCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -static void ( APIENTRY * dllCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -static void ( APIENTRY * dllCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -static void ( APIENTRY * dllCullFace )(GLenum mode); -static void ( APIENTRY * dllDeleteLists )(GLuint list, GLsizei range); -static void ( APIENTRY * dllDeleteTextures )(GLsizei n, const GLuint *textures); -static void ( APIENTRY * dllDepthFunc )(GLenum func); -static void ( APIENTRY * dllDepthMask )(GLboolean flag); -static void ( APIENTRY * dllDepthRange )(GLclampd zNear, GLclampd zFar); -static void ( APIENTRY * dllDisable )(GLenum cap); -static void ( APIENTRY * dllDisableClientState )(GLenum array); -static void ( APIENTRY * dllDrawArrays )(GLenum mode, GLint first, GLsizei count); -static void ( APIENTRY * dllDrawBuffer )(GLenum mode); -static void ( APIENTRY * dllDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -static void ( APIENTRY * dllDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -static void ( APIENTRY * dllEdgeFlag )(GLboolean flag); -static void ( APIENTRY * dllEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); -static void ( APIENTRY * dllEdgeFlagv )(const GLboolean *flag); -static void ( APIENTRY * dllEnable )(GLenum cap); -static void ( APIENTRY * dllEnableClientState )(GLenum array); -static void ( APIENTRY * dllEnd )(void); -static void ( APIENTRY * dllEndList )(void); -static void ( APIENTRY * dllEvalCoord1d )(GLdouble u); -static void ( APIENTRY * dllEvalCoord1dv )(const GLdouble *u); -static void ( APIENTRY * dllEvalCoord1f )(GLfloat u); -static void ( APIENTRY * dllEvalCoord1fv )(const GLfloat *u); -static void ( APIENTRY * dllEvalCoord2d )(GLdouble u, GLdouble v); -static void ( APIENTRY * dllEvalCoord2dv )(const GLdouble *u); -static void ( APIENTRY * dllEvalCoord2f )(GLfloat u, GLfloat v); -static void ( APIENTRY * dllEvalCoord2fv )(const GLfloat *u); -static void ( APIENTRY * dllEvalMesh1 )(GLenum mode, GLint i1, GLint i2); -static void ( APIENTRY * dllEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); -static void ( APIENTRY * dllEvalPoint1 )(GLint i); -static void ( APIENTRY * dllEvalPoint2 )(GLint i, GLint j); -static void ( APIENTRY * dllFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); -static void ( APIENTRY * dllFinish )(void); -static void ( APIENTRY * dllFlush )(void); -static void ( APIENTRY * dllFogf )(GLenum pname, GLfloat param); -static void ( APIENTRY * dllFogfv )(GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllFogi )(GLenum pname, GLint param); -static void ( APIENTRY * dllFogiv )(GLenum pname, const GLint *params); -static void ( APIENTRY * dllFrontFace )(GLenum mode); -static void ( APIENTRY * dllFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -GLuint ( APIENTRY * dllGenLists )(GLsizei range); -static void ( APIENTRY * dllGenTextures )(GLsizei n, GLuint *textures); -static void ( APIENTRY * dllGetBooleanv )(GLenum pname, GLboolean *params); -static void ( APIENTRY * dllGetClipPlane )(GLenum plane, GLdouble *equation); -static void ( APIENTRY * dllGetDoublev )(GLenum pname, GLdouble *params); -GLenum ( APIENTRY * dllGetError )(void); -static void ( APIENTRY * dllGetFloatv )(GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetIntegerv )(GLenum pname, GLint *params); -static void ( APIENTRY * dllGetLightfv )(GLenum light, GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetLightiv )(GLenum light, GLenum pname, GLint *params); -static void ( APIENTRY * dllGetMapdv )(GLenum target, GLenum query, GLdouble *v); -static void ( APIENTRY * dllGetMapfv )(GLenum target, GLenum query, GLfloat *v); -static void ( APIENTRY * dllGetMapiv )(GLenum target, GLenum query, GLint *v); -static void ( APIENTRY * dllGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetMaterialiv )(GLenum face, GLenum pname, GLint *params); -static void ( APIENTRY * dllGetPixelMapfv )(GLenum map, GLfloat *values); -static void ( APIENTRY * dllGetPixelMapuiv )(GLenum map, GLuint *values); -static void ( APIENTRY * dllGetPixelMapusv )(GLenum map, GLushort *values); -static void ( APIENTRY * dllGetPointerv )(GLenum pname, GLvoid* *params); -static void ( APIENTRY * dllGetPolygonStipple )(GLubyte *mask); -const GLubyte * ( APIENTRY * dllGetString )(GLenum name); -static void ( APIENTRY * dllGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetTexEnviv )(GLenum target, GLenum pname, GLint *params); -static void ( APIENTRY * dllGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); -static void ( APIENTRY * dllGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); -static void ( APIENTRY * dllGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -static void ( APIENTRY * dllGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); -static void ( APIENTRY * dllGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); -static void ( APIENTRY * dllGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); -static void ( APIENTRY * dllHint )(GLenum target, GLenum mode); -static void ( APIENTRY * dllIndexMask )(GLuint mask); -static void ( APIENTRY * dllIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -static void ( APIENTRY * dllIndexd )(GLdouble c); -static void ( APIENTRY * dllIndexdv )(const GLdouble *c); -static void ( APIENTRY * dllIndexf )(GLfloat c); -static void ( APIENTRY * dllIndexfv )(const GLfloat *c); -static void ( APIENTRY * dllIndexi )(GLint c); -static void ( APIENTRY * dllIndexiv )(const GLint *c); -static void ( APIENTRY * dllIndexs )(GLshort c); -static void ( APIENTRY * dllIndexsv )(const GLshort *c); -static void ( APIENTRY * dllIndexub )(GLubyte c); -static void ( APIENTRY * dllIndexubv )(const GLubyte *c); -static void ( APIENTRY * dllInitNames )(void); -static void ( APIENTRY * dllInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); -GLboolean ( APIENTRY * dllIsEnabled )(GLenum cap); -GLboolean ( APIENTRY * dllIsList )(GLuint list); -GLboolean ( APIENTRY * dllIsTexture )(GLuint texture); -static void ( APIENTRY * dllLightModelf )(GLenum pname, GLfloat param); -static void ( APIENTRY * dllLightModelfv )(GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllLightModeli )(GLenum pname, GLint param); -static void ( APIENTRY * dllLightModeliv )(GLenum pname, const GLint *params); -static void ( APIENTRY * dllLightf )(GLenum light, GLenum pname, GLfloat param); -static void ( APIENTRY * dllLightfv )(GLenum light, GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllLighti )(GLenum light, GLenum pname, GLint param); -static void ( APIENTRY * dllLightiv )(GLenum light, GLenum pname, const GLint *params); -static void ( APIENTRY * dllLineStipple )(GLint factor, GLushort pattern); -static void ( APIENTRY * dllLineWidth )(GLfloat width); -static void ( APIENTRY * dllListBase )(GLuint base); -static void ( APIENTRY * dllLoadIdentity )(void); -static void ( APIENTRY * dllLoadMatrixd )(const GLdouble *m); -static void ( APIENTRY * dllLoadMatrixf )(const GLfloat *m); -static void ( APIENTRY * dllLoadName )(GLuint name); -static void ( APIENTRY * dllLogicOp )(GLenum opcode); -static void ( APIENTRY * dllMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -static void ( APIENTRY * dllMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -static void ( APIENTRY * dllMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -static void ( APIENTRY * dllMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -static void ( APIENTRY * dllMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); -static void ( APIENTRY * dllMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); -static void ( APIENTRY * dllMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); -static void ( APIENTRY * dllMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); -static void ( APIENTRY * dllMaterialf )(GLenum face, GLenum pname, GLfloat param); -static void ( APIENTRY * dllMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllMateriali )(GLenum face, GLenum pname, GLint param); -static void ( APIENTRY * dllMaterialiv )(GLenum face, GLenum pname, const GLint *params); -static void ( APIENTRY * dllMatrixMode )(GLenum mode); -static void ( APIENTRY * dllMultMatrixd )(const GLdouble *m); -static void ( APIENTRY * dllMultMatrixf )(const GLfloat *m); -static void ( APIENTRY * dllNewList )(GLuint list, GLenum mode); -static void ( APIENTRY * dllNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); -static void ( APIENTRY * dllNormal3bv )(const GLbyte *v); -static void ( APIENTRY * dllNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); -static void ( APIENTRY * dllNormal3dv )(const GLdouble *v); -static void ( APIENTRY * dllNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); -static void ( APIENTRY * dllNormal3fv )(const GLfloat *v); -static void ( APIENTRY * dllNormal3i )(GLint nx, GLint ny, GLint nz); -static void ( APIENTRY * dllNormal3iv )(const GLint *v); -static void ( APIENTRY * dllNormal3s )(GLshort nx, GLshort ny, GLshort nz); -static void ( APIENTRY * dllNormal3sv )(const GLshort *v); -static void ( APIENTRY * dllNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -static void ( APIENTRY * dllOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -static void ( APIENTRY * dllPassThrough )(GLfloat token); -static void ( APIENTRY * dllPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); -static void ( APIENTRY * dllPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); -static void ( APIENTRY * dllPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); -static void ( APIENTRY * dllPixelStoref )(GLenum pname, GLfloat param); -static void ( APIENTRY * dllPixelStorei )(GLenum pname, GLint param); -static void ( APIENTRY * dllPixelTransferf )(GLenum pname, GLfloat param); -static void ( APIENTRY * dllPixelTransferi )(GLenum pname, GLint param); -static void ( APIENTRY * dllPixelZoom )(GLfloat xfactor, GLfloat yfactor); -static void ( APIENTRY * dllPointSize )(GLfloat size); -static void ( APIENTRY * dllPolygonMode )(GLenum face, GLenum mode); -static void ( APIENTRY * dllPolygonOffset )(GLfloat factor, GLfloat units); -static void ( APIENTRY * dllPolygonStipple )(const GLubyte *mask); -static void ( APIENTRY * dllPopAttrib )(void); -static void ( APIENTRY * dllPopClientAttrib )(void); -static void ( APIENTRY * dllPopMatrix )(void); -static void ( APIENTRY * dllPopName )(void); -static void ( APIENTRY * dllPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); -static void ( APIENTRY * dllPushAttrib )(GLbitfield mask); -static void ( APIENTRY * dllPushClientAttrib )(GLbitfield mask); -static void ( APIENTRY * dllPushMatrix )(void); -static void ( APIENTRY * dllPushName )(GLuint name); -static void ( APIENTRY * dllRasterPos2d )(GLdouble x, GLdouble y); -static void ( APIENTRY * dllRasterPos2dv )(const GLdouble *v); -static void ( APIENTRY * dllRasterPos2f )(GLfloat x, GLfloat y); -static void ( APIENTRY * dllRasterPos2fv )(const GLfloat *v); -static void ( APIENTRY * dllRasterPos2i )(GLint x, GLint y); -static void ( APIENTRY * dllRasterPos2iv )(const GLint *v); -static void ( APIENTRY * dllRasterPos2s )(GLshort x, GLshort y); -static void ( APIENTRY * dllRasterPos2sv )(const GLshort *v); -static void ( APIENTRY * dllRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); -static void ( APIENTRY * dllRasterPos3dv )(const GLdouble *v); -static void ( APIENTRY * dllRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); -static void ( APIENTRY * dllRasterPos3fv )(const GLfloat *v); -static void ( APIENTRY * dllRasterPos3i )(GLint x, GLint y, GLint z); -static void ( APIENTRY * dllRasterPos3iv )(const GLint *v); -static void ( APIENTRY * dllRasterPos3s )(GLshort x, GLshort y, GLshort z); -static void ( APIENTRY * dllRasterPos3sv )(const GLshort *v); -static void ( APIENTRY * dllRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -static void ( APIENTRY * dllRasterPos4dv )(const GLdouble *v); -static void ( APIENTRY * dllRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -static void ( APIENTRY * dllRasterPos4fv )(const GLfloat *v); -static void ( APIENTRY * dllRasterPos4i )(GLint x, GLint y, GLint z, GLint w); -static void ( APIENTRY * dllRasterPos4iv )(const GLint *v); -static void ( APIENTRY * dllRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); -static void ( APIENTRY * dllRasterPos4sv )(const GLshort *v); -static void ( APIENTRY * dllReadBuffer )(GLenum mode); -static void ( APIENTRY * dllReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -static void ( APIENTRY * dllRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); -static void ( APIENTRY * dllRectdv )(const GLdouble *v1, const GLdouble *v2); -static void ( APIENTRY * dllRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); -static void ( APIENTRY * dllRectfv )(const GLfloat *v1, const GLfloat *v2); -static void ( APIENTRY * dllRecti )(GLint x1, GLint y1, GLint x2, GLint y2); -static void ( APIENTRY * dllRectiv )(const GLint *v1, const GLint *v2); -static void ( APIENTRY * dllRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); -static void ( APIENTRY * dllRectsv )(const GLshort *v1, const GLshort *v2); -GLint ( APIENTRY * dllRenderMode )(GLenum mode); -static void ( APIENTRY * dllRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -static void ( APIENTRY * dllRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -static void ( APIENTRY * dllScaled )(GLdouble x, GLdouble y, GLdouble z); -static void ( APIENTRY * dllScalef )(GLfloat x, GLfloat y, GLfloat z); -static void ( APIENTRY * dllScissor )(GLint x, GLint y, GLsizei width, GLsizei height); -static void ( APIENTRY * dllSelectBuffer )(GLsizei size, GLuint *buffer); -static void ( APIENTRY * dllShadeModel )(GLenum mode); -static void ( APIENTRY * dllStencilFunc )(GLenum func, GLint ref, GLuint mask); -static void ( APIENTRY * dllStencilMask )(GLuint mask); -static void ( APIENTRY * dllStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); -static void ( APIENTRY * dllTexCoord1d )(GLdouble s); -static void ( APIENTRY * dllTexCoord1dv )(const GLdouble *v); -static void ( APIENTRY * dllTexCoord1f )(GLfloat s); -static void ( APIENTRY * dllTexCoord1fv )(const GLfloat *v); -static void ( APIENTRY * dllTexCoord1i )(GLint s); -static void ( APIENTRY * dllTexCoord1iv )(const GLint *v); -static void ( APIENTRY * dllTexCoord1s )(GLshort s); -static void ( APIENTRY * dllTexCoord1sv )(const GLshort *v); -static void ( APIENTRY * dllTexCoord2d )(GLdouble s, GLdouble t); -static void ( APIENTRY * dllTexCoord2dv )(const GLdouble *v); -static void ( APIENTRY * dllTexCoord2f )(GLfloat s, GLfloat t); -static void ( APIENTRY * dllTexCoord2fv )(const GLfloat *v); -static void ( APIENTRY * dllTexCoord2i )(GLint s, GLint t); -static void ( APIENTRY * dllTexCoord2iv )(const GLint *v); -static void ( APIENTRY * dllTexCoord2s )(GLshort s, GLshort t); -static void ( APIENTRY * dllTexCoord2sv )(const GLshort *v); -static void ( APIENTRY * dllTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); -static void ( APIENTRY * dllTexCoord3dv )(const GLdouble *v); -static void ( APIENTRY * dllTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); -static void ( APIENTRY * dllTexCoord3fv )(const GLfloat *v); -static void ( APIENTRY * dllTexCoord3i )(GLint s, GLint t, GLint r); -static void ( APIENTRY * dllTexCoord3iv )(const GLint *v); -static void ( APIENTRY * dllTexCoord3s )(GLshort s, GLshort t, GLshort r); -static void ( APIENTRY * dllTexCoord3sv )(const GLshort *v); -static void ( APIENTRY * dllTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); -static void ( APIENTRY * dllTexCoord4dv )(const GLdouble *v); -static void ( APIENTRY * dllTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); -static void ( APIENTRY * dllTexCoord4fv )(const GLfloat *v); -static void ( APIENTRY * dllTexCoord4i )(GLint s, GLint t, GLint r, GLint q); -static void ( APIENTRY * dllTexCoord4iv )(const GLint *v); -static void ( APIENTRY * dllTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); -static void ( APIENTRY * dllTexCoord4sv )(const GLshort *v); -static void ( APIENTRY * dllTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -static void ( APIENTRY * dllTexEnvf )(GLenum target, GLenum pname, GLfloat param); -static void ( APIENTRY * dllTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllTexEnvi )(GLenum target, GLenum pname, GLint param); -static void ( APIENTRY * dllTexEnviv )(GLenum target, GLenum pname, const GLint *params); -static void ( APIENTRY * dllTexGend )(GLenum coord, GLenum pname, GLdouble param); -static void ( APIENTRY * dllTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); -static void ( APIENTRY * dllTexGenf )(GLenum coord, GLenum pname, GLfloat param); -static void ( APIENTRY * dllTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllTexGeni )(GLenum coord, GLenum pname, GLint param); -static void ( APIENTRY * dllTexGeniv )(GLenum coord, GLenum pname, const GLint *params); -static void ( APIENTRY * dllTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -static void ( APIENTRY * dllTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -static void ( APIENTRY * dllTexParameterf )(GLenum target, GLenum pname, GLfloat param); -static void ( APIENTRY * dllTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); -static void ( APIENTRY * dllTexParameteri )(GLenum target, GLenum pname, GLint param); -static void ( APIENTRY * dllTexParameteriv )(GLenum target, GLenum pname, const GLint *params); -static void ( APIENTRY * dllTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -static void ( APIENTRY * dllTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -static void ( APIENTRY * dllTranslated )(GLdouble x, GLdouble y, GLdouble z); -static void ( APIENTRY * dllTranslatef )(GLfloat x, GLfloat y, GLfloat z); -static void ( APIENTRY * dllVertex2d )(GLdouble x, GLdouble y); -static void ( APIENTRY * dllVertex2dv )(const GLdouble *v); -static void ( APIENTRY * dllVertex2f )(GLfloat x, GLfloat y); -static void ( APIENTRY * dllVertex2fv )(const GLfloat *v); -static void ( APIENTRY * dllVertex2i )(GLint x, GLint y); -static void ( APIENTRY * dllVertex2iv )(const GLint *v); -static void ( APIENTRY * dllVertex2s )(GLshort x, GLshort y); -static void ( APIENTRY * dllVertex2sv )(const GLshort *v); -static void ( APIENTRY * dllVertex3d )(GLdouble x, GLdouble y, GLdouble z); -static void ( APIENTRY * dllVertex3dv )(const GLdouble *v); -static void ( APIENTRY * dllVertex3f )(GLfloat x, GLfloat y, GLfloat z); -static void ( APIENTRY * dllVertex3fv )(const GLfloat *v); -static void ( APIENTRY * dllVertex3i )(GLint x, GLint y, GLint z); -static void ( APIENTRY * dllVertex3iv )(const GLint *v); -static void ( APIENTRY * dllVertex3s )(GLshort x, GLshort y, GLshort z); -static void ( APIENTRY * dllVertex3sv )(const GLshort *v); -static void ( APIENTRY * dllVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -static void ( APIENTRY * dllVertex4dv )(const GLdouble *v); -static void ( APIENTRY * dllVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -static void ( APIENTRY * dllVertex4fv )(const GLfloat *v); -static void ( APIENTRY * dllVertex4i )(GLint x, GLint y, GLint z, GLint w); -static void ( APIENTRY * dllVertex4iv )(const GLint *v); -static void ( APIENTRY * dllVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); -static void ( APIENTRY * dllVertex4sv )(const GLshort *v); -static void ( APIENTRY * dllVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -static void ( APIENTRY * dllViewport )(GLint x, GLint y, GLsizei width, GLsizei height); - -void (APIENTRY* dllCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -void (APIENTRY* dllCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -void (APIENTRY* dllCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -void (APIENTRY* dllCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -void (APIENTRY* dllGetCompressedTexImageARB)(GLenum target, GLint lod, void* img); - -static const char * BooleanToString( GLboolean b ) -{ - if ( b == GL_FALSE ) - return "GL_FALSE"; - else if ( b == GL_TRUE ) - return "GL_TRUE"; - else - return "OUT OF RANGE FOR BOOLEAN"; -} - -static const char * FuncToString( GLenum f ) -{ - switch ( f ) - { - case GL_ALWAYS: - return "GL_ALWAYS"; - case GL_NEVER: - return "GL_NEVER"; - case GL_LEQUAL: - return "GL_LEQUAL"; - case GL_LESS: - return "GL_LESS"; - case GL_EQUAL: - return "GL_EQUAL"; - case GL_GREATER: - return "GL_GREATER"; - case GL_GEQUAL: - return "GL_GEQUAL"; - case GL_NOTEQUAL: - return "GL_NOTEQUAL"; - default: - return "!!! UNKNOWN !!!"; - } -} - -static const char * PrimToString( GLenum mode ) -{ - static char prim[1024]; - - if ( mode == GL_TRIANGLES ) - strcpy( prim, "GL_TRIANGLES" ); - else if ( mode == GL_TRIANGLE_STRIP ) - strcpy( prim, "GL_TRIANGLE_STRIP" ); - else if ( mode == GL_TRIANGLE_FAN ) - strcpy( prim, "GL_TRIANGLE_FAN" ); - else if ( mode == GL_QUADS ) - strcpy( prim, "GL_QUADS" ); - else if ( mode == GL_QUAD_STRIP ) - strcpy( prim, "GL_QUAD_STRIP" ); - else if ( mode == GL_POLYGON ) - strcpy( prim, "GL_POLYGON" ); - else if ( mode == GL_POINTS ) - strcpy( prim, "GL_POINTS" ); - else if ( mode == GL_LINES ) - strcpy( prim, "GL_LINES" ); - else if ( mode == GL_LINE_STRIP ) - strcpy( prim, "GL_LINE_STRIP" ); - else if ( mode == GL_LINE_LOOP ) - strcpy( prim, "GL_LINE_LOOP" ); - else - sprintf( prim, "0x%x", mode ); - - return prim; -} - -static const char * CapToString( GLenum cap ) -{ - static char buffer[1024]; - - switch ( cap ) - { - case GL_TEXTURE_2D: - return "GL_TEXTURE_2D"; - case GL_BLEND: - return "GL_BLEND"; - case GL_DEPTH_TEST: - return "GL_DEPTH_TEST"; - case GL_CULL_FACE: - return "GL_CULL_FACE"; - case GL_CLIP_PLANE0: - return "GL_CLIP_PLANE0"; - case GL_COLOR_ARRAY: - return "GL_COLOR_ARRAY"; - case GL_TEXTURE_COORD_ARRAY: - return "GL_TEXTURE_COORD_ARRAY"; - case GL_VERTEX_ARRAY: - return "GL_VERTEX_ARRAY"; - case GL_ALPHA_TEST: - return "GL_ALPHA_TEST"; - case GL_STENCIL_TEST: - return "GL_STENCIL_TEST"; - default: - sprintf( buffer, "0x%x", cap ); - } - - return buffer; -} - -static const char * TypeToString( GLenum t ) -{ - switch ( t ) - { - case GL_BYTE: - return "GL_BYTE"; - case GL_UNSIGNED_BYTE: - return "GL_UNSIGNED_BYTE"; - case GL_SHORT: - return "GL_SHORT"; - case GL_UNSIGNED_SHORT: - return "GL_UNSIGNED_SHORT"; - case GL_INT: - return "GL_INT"; - case GL_UNSIGNED_INT: - return "GL_UNSIGNED_INT"; - case GL_FLOAT: - return "GL_FLOAT"; - case GL_DOUBLE: - return "GL_DOUBLE"; - default: - return "!!! UNKNOWN !!!"; - } -} - -static void APIENTRY logAccum(GLenum op, GLfloat value) -{ - fprintf( glw_state.log_fp, "glAccum\n" ); - dllAccum( op, value ); -} - -static void APIENTRY logAlphaFunc(GLenum func, GLclampf ref) -{ - fprintf( glw_state.log_fp, "glAlphaFunc( 0x%x, %f )\n", func, ref ); - dllAlphaFunc( func, ref ); -} - -static GLboolean APIENTRY logAreTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences) -{ - fprintf( glw_state.log_fp, "glAreTexturesResident\n" ); - return dllAreTexturesResident( n, textures, residences ); -} - -static void APIENTRY logArrayElement(GLint i) -{ - fprintf( glw_state.log_fp, "glArrayElement\n" ); - dllArrayElement( i ); -} - -static void APIENTRY logBegin(GLenum mode) -{ - fprintf( glw_state.log_fp, "glBegin( %s )\n", PrimToString( mode )); - dllBegin( mode ); -} - -static void APIENTRY logBindTexture(GLenum target, GLuint texture) -{ - fprintf( glw_state.log_fp, "glBindTexture( 0x%x, %u )\n", target, texture ); - dllBindTexture( target, texture ); -} - -static void APIENTRY logBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) -{ - fprintf( glw_state.log_fp, "glBitmap\n" ); - dllBitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); -} - -static void BlendToName( char *n, GLenum f ) -{ - switch ( f ) - { - case GL_ONE: - strcpy( n, "GL_ONE" ); - break; - case GL_ZERO: - strcpy( n, "GL_ZERO" ); - break; - case GL_SRC_ALPHA: - strcpy( n, "GL_SRC_ALPHA" ); - break; - case GL_ONE_MINUS_SRC_ALPHA: - strcpy( n, "GL_ONE_MINUS_SRC_ALPHA" ); - break; - case GL_DST_COLOR: - strcpy( n, "GL_DST_COLOR" ); - break; - case GL_ONE_MINUS_DST_COLOR: - strcpy( n, "GL_ONE_MINUS_DST_COLOR" ); - break; - case GL_DST_ALPHA: - strcpy( n, "GL_DST_ALPHA" ); - break; - default: - sprintf( n, "0x%x", f ); - } -} -static void APIENTRY logBlendFunc(GLenum sfactor, GLenum dfactor) -{ - char sf[128], df[128]; - - BlendToName( sf, sfactor ); - BlendToName( df, dfactor ); - - fprintf( glw_state.log_fp, "glBlendFunc( %s, %s )\n", sf, df ); - dllBlendFunc( sfactor, dfactor ); -} - -static void APIENTRY logCallList(GLuint list) -{ - fprintf( glw_state.log_fp, "glCallList( %u )\n", list ); - dllCallList( list ); -} - -static void APIENTRY logCallLists(GLsizei n, GLenum type, const void *lists) -{ - fprintf( glw_state.log_fp, "glCallLists\n" ); - dllCallLists( n, type, lists ); -} - -static void APIENTRY logClear(GLbitfield mask) -{ - fprintf( glw_state.log_fp, "glClear( 0x%x = ", mask ); - - if ( mask & GL_COLOR_BUFFER_BIT ) - fprintf( glw_state.log_fp, "GL_COLOR_BUFFER_BIT " ); - if ( mask & GL_DEPTH_BUFFER_BIT ) - fprintf( glw_state.log_fp, "GL_DEPTH_BUFFER_BIT " ); - if ( mask & GL_STENCIL_BUFFER_BIT ) - fprintf( glw_state.log_fp, "GL_STENCIL_BUFFER_BIT " ); - if ( mask & GL_ACCUM_BUFFER_BIT ) - fprintf( glw_state.log_fp, "GL_ACCUM_BUFFER_BIT " ); - - fprintf( glw_state.log_fp, ")\n" ); - dllClear( mask ); -} - -static void APIENTRY logClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -{ - fprintf( glw_state.log_fp, "glClearAccum\n" ); - dllClearAccum( red, green, blue, alpha ); -} - -static void APIENTRY logClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - fprintf( glw_state.log_fp, "glClearColor\n" ); - dllClearColor( red, green, blue, alpha ); -} - -static void APIENTRY logClearDepth(GLclampd depth) -{ - fprintf( glw_state.log_fp, "glClearDepth( %f )\n", ( float ) depth ); - dllClearDepth( depth ); -} - -static void APIENTRY logClearIndex(GLfloat c) -{ - fprintf( glw_state.log_fp, "glClearIndex\n" ); - dllClearIndex( c ); -} - -static void APIENTRY logClearStencil(GLint s) -{ - fprintf( glw_state.log_fp, "glClearStencil( %d )\n", s ); - dllClearStencil( s ); -} - -static void APIENTRY logClipPlane(GLenum plane, const GLdouble *equation) -{ - fprintf( glw_state.log_fp, "glClipPlane\n" ); - dllClipPlane( plane, equation ); -} - -static void APIENTRY logColor3b(GLbyte red, GLbyte green, GLbyte blue) -{ - fprintf( glw_state.log_fp, "glColor3b\n" ); - dllColor3b( red, green, blue ); -} - -static void APIENTRY logColor3bv(const GLbyte *v) -{ - fprintf( glw_state.log_fp, "glColor3bv\n" ); - dllColor3bv( v ); -} - -static void APIENTRY logColor3d(GLdouble red, GLdouble green, GLdouble blue) -{ - fprintf( glw_state.log_fp, "glColor3d\n" ); - dllColor3d( red, green, blue ); -} - -static void APIENTRY logColor3dv(const GLdouble *v) -{ - fprintf( glw_state.log_fp, "glColor3dv\n" ); - dllColor3dv( v ); -} - -static void APIENTRY logColor3f(GLfloat red, GLfloat green, GLfloat blue) -{ - fprintf( glw_state.log_fp, "glColor3f\n" ); - dllColor3f( red, green, blue ); -} - -static void APIENTRY logColor3fv(const GLfloat *v) -{ - fprintf( glw_state.log_fp, "glColor3fv\n" ); - dllColor3fv( v ); -} - -static void APIENTRY logColor3i(GLint red, GLint green, GLint blue) -{ - fprintf( glw_state.log_fp, "glColor3i\n" ); - dllColor3i( red, green, blue ); -} - -static void APIENTRY logColor3iv(const GLint *v) -{ - fprintf( glw_state.log_fp, "glColor3iv\n" ); - dllColor3iv( v ); -} - -static void APIENTRY logColor3s(GLshort red, GLshort green, GLshort blue) -{ - fprintf( glw_state.log_fp, "glColor3s\n" ); - dllColor3s( red, green, blue ); -} - -static void APIENTRY logColor3sv(const GLshort *v) -{ - fprintf( glw_state.log_fp, "glColor3sv\n" ); - dllColor3sv( v ); -} - -static void APIENTRY logColor3ub(GLubyte red, GLubyte green, GLubyte blue) -{ - fprintf( glw_state.log_fp, "glColor3ub\n" ); - dllColor3ub( red, green, blue ); -} - -static void APIENTRY logColor3ubv(const GLubyte *v) -{ - fprintf( glw_state.log_fp, "glColor3ubv\n" ); - dllColor3ubv( v ); -} - -#define SIG( x ) fprintf( glw_state.log_fp, x "\n" ) - -static void APIENTRY logColor3ui(GLuint red, GLuint green, GLuint blue) -{ - SIG( "glColor3ui" ); - dllColor3ui( red, green, blue ); -} - -static void APIENTRY logColor3uiv(const GLuint *v) -{ - SIG( "glColor3uiv" ); - dllColor3uiv( v ); -} - -static void APIENTRY logColor3us(GLushort red, GLushort green, GLushort blue) -{ - SIG( "glColor3us" ); - dllColor3us( red, green, blue ); -} - -static void APIENTRY logColor3usv(const GLushort *v) -{ - SIG( "glColor3usv" ); - dllColor3usv( v ); -} - -static void APIENTRY logColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) -{ - SIG( "glColor4b" ); - dllColor4b( red, green, blue, alpha ); -} - -static void APIENTRY logColor4bv(const GLbyte *v) -{ - SIG( "glColor4bv" ); - dllColor4bv( v ); -} - -static void APIENTRY logColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) -{ - SIG( "glColor4d" ); - dllColor4d( red, green, blue, alpha ); -} -static void APIENTRY logColor4dv(const GLdouble *v) -{ - SIG( "glColor4dv" ); - dllColor4dv( v ); -} -static void APIENTRY logColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -{ - fprintf( glw_state.log_fp, "glColor4f( %f,%f,%f,%f )\n", red, green, blue, alpha ); - dllColor4f( red, green, blue, alpha ); -} -static void APIENTRY logColor4fv(const GLfloat *v) -{ - fprintf( glw_state.log_fp, "glColor4fv( %f,%f,%f,%f )\n", v[0], v[1], v[2], v[3] ); - dllColor4fv( v ); -} -static void APIENTRY logColor4i(GLint red, GLint green, GLint blue, GLint alpha) -{ - SIG( "glColor4i" ); - dllColor4i( red, green, blue, alpha ); -} -static void APIENTRY logColor4iv(const GLint *v) -{ - SIG( "glColor4iv" ); - dllColor4iv( v ); -} -static void APIENTRY logColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) -{ - SIG( "glColor4s" ); - dllColor4s( red, green, blue, alpha ); -} -static void APIENTRY logColor4sv(const GLshort *v) -{ - SIG( "glColor4sv" ); - dllColor4sv( v ); -} -static void APIENTRY logColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) -{ - SIG( "glColor4b" ); - dllColor4b( red, green, blue, alpha ); -} -static void APIENTRY logColor4ubv(const GLubyte *v) -{ - SIG( "glColor4ubv" ); - dllColor4ubv( v ); -} -static void APIENTRY logColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha) -{ - SIG( "glColor4ui" ); - dllColor4ui( red, green, blue, alpha ); -} -static void APIENTRY logColor4uiv(const GLuint *v) -{ - SIG( "glColor4uiv" ); - dllColor4uiv( v ); -} -static void APIENTRY logColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha) -{ - SIG( "glColor4us" ); - dllColor4us( red, green, blue, alpha ); -} -static void APIENTRY logColor4usv(const GLushort *v) -{ - SIG( "glColor4usv" ); - dllColor4usv( v ); -} -static void APIENTRY logColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) -{ - SIG( "glColorMask" ); - dllColorMask( red, green, blue, alpha ); -} -static void APIENTRY logColorMaterial(GLenum face, GLenum mode) -{ - SIG( "glColorMaterial" ); - dllColorMaterial( face, mode ); -} - -static void APIENTRY logColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) -{ - fprintf( glw_state.log_fp, "glColorPointer( %d, %s, %d, MEM )\n", size, TypeToString( type ), stride ); - dllColorPointer( size, type, stride, pointer ); -} - -static void APIENTRY logCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) -{ - SIG( "glCopyPixels" ); - dllCopyPixels( x, y, width, height, type ); -} - -static void APIENTRY logCopyTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border) -{ - SIG( "glCopyTexImage1D" ); - dllCopyTexImage1D( target, level, internalFormat, x, y, width, border ); -} - -static void APIENTRY logCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) -{ - SIG( "glCopyTexImage2D" ); - dllCopyTexImage2D( target, level, internalFormat, x, y, width, height, border ); -} - -static void APIENTRY logCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) -{ - SIG( "glCopyTexSubImage1D" ); - dllCopyTexSubImage1D( target, level, xoffset, x, y, width ); -} - -static void APIENTRY logCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) -{ - SIG( "glCopyTexSubImage2D" ); - dllCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height ); -} - -static void APIENTRY logCullFace(GLenum mode) -{ - fprintf( glw_state.log_fp, "glCullFace( %s )\n", ( mode == GL_FRONT ) ? "GL_FRONT" : "GL_BACK" ); - dllCullFace( mode ); -} - -static void APIENTRY logDeleteLists(GLuint list, GLsizei range) -{ - SIG( "glDeleteLists" ); - dllDeleteLists( list, range ); -} - -static void APIENTRY logDeleteTextures(GLsizei n, const GLuint *textures) -{ - SIG( "glDeleteTextures" ); - dllDeleteTextures( n, textures ); -} - -static void APIENTRY logDepthFunc(GLenum func) -{ - fprintf( glw_state.log_fp, "glDepthFunc( %s )\n", FuncToString( func ) ); - dllDepthFunc( func ); -} - -static void APIENTRY logDepthMask(GLboolean flag) -{ - fprintf( glw_state.log_fp, "glDepthMask( %s )\n", BooleanToString( flag ) ); - dllDepthMask( flag ); -} - -static void APIENTRY logDepthRange(GLclampd zNear, GLclampd zFar) -{ - fprintf( glw_state.log_fp, "glDepthRange( %f, %f )\n", ( float ) zNear, ( float ) zFar ); - dllDepthRange( zNear, zFar ); -} - -static void APIENTRY logDisable(GLenum cap) -{ - fprintf( glw_state.log_fp, "glDisable( %s )\n", CapToString( cap ) ); - dllDisable( cap ); -} - -static void APIENTRY logDisableClientState(GLenum array) -{ - fprintf( glw_state.log_fp, "glDisableClientState( %s )\n", CapToString( array ) ); - dllDisableClientState( array ); -} - -static void APIENTRY logDrawArrays(GLenum mode, GLint first, GLsizei count) -{ - SIG( "glDrawArrays" ); - dllDrawArrays( mode, first, count ); -} - -static void APIENTRY logDrawBuffer(GLenum mode) -{ - SIG( "glDrawBuffer" ); - dllDrawBuffer( mode ); -} - -static void APIENTRY logDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) -{ - fprintf( glw_state.log_fp, "glDrawElements( %s, %d, %s, MEM )\n", PrimToString( mode ), count, TypeToString( type ) ); - dllDrawElements( mode, count, type, indices ); -} - -static void APIENTRY logDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) -{ - SIG( "glDrawPixels" ); - dllDrawPixels( width, height, format, type, pixels ); -} - -static void APIENTRY logEdgeFlag(GLboolean flag) -{ - SIG( "glEdgeFlag" ); - dllEdgeFlag( flag ); -} - -static void APIENTRY logEdgeFlagPointer(GLsizei stride, const void *pointer) -{ - SIG( "glEdgeFlagPointer" ); - dllEdgeFlagPointer( stride, pointer ); -} - -static void APIENTRY logEdgeFlagv(const GLboolean *flag) -{ - SIG( "glEdgeFlagv" ); - dllEdgeFlagv( flag ); -} - -static void APIENTRY logEnable(GLenum cap) -{ - fprintf( glw_state.log_fp, "glEnable( %s )\n", CapToString( cap ) ); - dllEnable( cap ); -} - -static void APIENTRY logEnableClientState(GLenum array) -{ - fprintf( glw_state.log_fp, "glEnableClientState( %s )\n", CapToString( array ) ); - dllEnableClientState( array ); -} - -static void APIENTRY logEnd(void) -{ - SIG( "glEnd" ); - dllEnd(); -} - -static void APIENTRY logEndList(void) -{ - SIG( "glEndList" ); - dllEndList(); -} - -static void APIENTRY logEvalCoord1d(GLdouble u) -{ - SIG( "glEvalCoord1d" ); - dllEvalCoord1d( u ); -} - -static void APIENTRY logEvalCoord1dv(const GLdouble *u) -{ - SIG( "glEvalCoord1dv" ); - dllEvalCoord1dv( u ); -} - -static void APIENTRY logEvalCoord1f(GLfloat u) -{ - SIG( "glEvalCoord1f" ); - dllEvalCoord1f( u ); -} - -static void APIENTRY logEvalCoord1fv(const GLfloat *u) -{ - SIG( "glEvalCoord1fv" ); - dllEvalCoord1fv( u ); -} -static void APIENTRY logEvalCoord2d(GLdouble u, GLdouble v) -{ - SIG( "glEvalCoord2d" ); - dllEvalCoord2d( u, v ); -} -static void APIENTRY logEvalCoord2dv(const GLdouble *u) -{ - SIG( "glEvalCoord2dv" ); - dllEvalCoord2dv( u ); -} -static void APIENTRY logEvalCoord2f(GLfloat u, GLfloat v) -{ - SIG( "glEvalCoord2f" ); - dllEvalCoord2f( u, v ); -} -static void APIENTRY logEvalCoord2fv(const GLfloat *u) -{ - SIG( "glEvalCoord2fv" ); - dllEvalCoord2fv( u ); -} - -static void APIENTRY logEvalMesh1(GLenum mode, GLint i1, GLint i2) -{ - SIG( "glEvalMesh1" ); - dllEvalMesh1( mode, i1, i2 ); -} -static void APIENTRY logEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) -{ - SIG( "glEvalMesh2" ); - dllEvalMesh2( mode, i1, i2, j1, j2 ); -} -static void APIENTRY logEvalPoint1(GLint i) -{ - SIG( "glEvalPoint1" ); - dllEvalPoint1( i ); -} -static void APIENTRY logEvalPoint2(GLint i, GLint j) -{ - SIG( "glEvalPoint2" ); - dllEvalPoint2( i, j ); -} - -static void APIENTRY logFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer) -{ - SIG( "glFeedbackBuffer" ); - dllFeedbackBuffer( size, type, buffer ); -} - -static void APIENTRY logFinish(void) -{ - SIG( "glFinish" ); - dllFinish(); -} - -static void APIENTRY logFlush(void) -{ - SIG( "glFlush" ); - dllFlush(); -} - -static void APIENTRY logFogf(GLenum pname, GLfloat param) -{ - SIG( "glFogf" ); - dllFogf( pname, param ); -} - -static void APIENTRY logFogfv(GLenum pname, const GLfloat *params) -{ - SIG( "glFogfv" ); - dllFogfv( pname, params ); -} - -static void APIENTRY logFogi(GLenum pname, GLint param) -{ - SIG( "glFogi" ); - dllFogi( pname, param ); -} - -static void APIENTRY logFogiv(GLenum pname, const GLint *params) -{ - SIG( "glFogiv" ); - dllFogiv( pname, params ); -} - -static void APIENTRY logFrontFace(GLenum mode) -{ - SIG( "glFrontFace" ); - dllFrontFace( mode ); -} - -static void APIENTRY logFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) -{ - SIG( "glFrustum" ); - dllFrustum( left, right, bottom, top, zNear, zFar ); -} - -static GLuint APIENTRY logGenLists(GLsizei range) -{ - SIG( "glGenLists" ); - return dllGenLists( range ); -} - -static void APIENTRY logGenTextures(GLsizei n, GLuint *textures) -{ - SIG( "glGenTextures" ); - dllGenTextures( n, textures ); -} - -static void APIENTRY logGetBooleanv(GLenum pname, GLboolean *params) -{ - SIG( "glGetBooleanv" ); - dllGetBooleanv( pname, params ); -} - -static void APIENTRY logGetClipPlane(GLenum plane, GLdouble *equation) -{ - SIG( "glGetClipPlane" ); - dllGetClipPlane( plane, equation ); -} - -static void APIENTRY logGetDoublev(GLenum pname, GLdouble *params) -{ - SIG( "glGetDoublev" ); - dllGetDoublev( pname, params ); -} - -static GLenum APIENTRY logGetError(void) -{ - SIG( "glGetError" ); - return dllGetError(); -} - -static void APIENTRY logGetFloatv(GLenum pname, GLfloat *params) -{ - SIG( "glGetFloatv" ); - dllGetFloatv( pname, params ); -} - -static void APIENTRY logGetIntegerv(GLenum pname, GLint *params) -{ - SIG( "glGetIntegerv" ); - dllGetIntegerv( pname, params ); -} - -static void APIENTRY logGetLightfv(GLenum light, GLenum pname, GLfloat *params) -{ - SIG( "glGetLightfv" ); - dllGetLightfv( light, pname, params ); -} - -static void APIENTRY logGetLightiv(GLenum light, GLenum pname, GLint *params) -{ - SIG( "glGetLightiv" ); - dllGetLightiv( light, pname, params ); -} - -static void APIENTRY logGetMapdv(GLenum target, GLenum query, GLdouble *v) -{ - SIG( "glGetMapdv" ); - dllGetMapdv( target, query, v ); -} - -static void APIENTRY logGetMapfv(GLenum target, GLenum query, GLfloat *v) -{ - SIG( "glGetMapfv" ); - dllGetMapfv( target, query, v ); -} - -static void APIENTRY logGetMapiv(GLenum target, GLenum query, GLint *v) -{ - SIG( "glGetMapiv" ); - dllGetMapiv( target, query, v ); -} - -static void APIENTRY logGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) -{ - SIG( "glGetMaterialfv" ); - dllGetMaterialfv( face, pname, params ); -} - -static void APIENTRY logGetMaterialiv(GLenum face, GLenum pname, GLint *params) -{ - SIG( "glGetMaterialiv" ); - dllGetMaterialiv( face, pname, params ); -} - -static void APIENTRY logGetPixelMapfv(GLenum map, GLfloat *values) -{ - SIG( "glGetPixelMapfv" ); - dllGetPixelMapfv( map, values ); -} - -static void APIENTRY logGetPixelMapuiv(GLenum map, GLuint *values) -{ - SIG( "glGetPixelMapuiv" ); - dllGetPixelMapuiv( map, values ); -} - -static void APIENTRY logGetPixelMapusv(GLenum map, GLushort *values) -{ - SIG( "glGetPixelMapusv" ); - dllGetPixelMapusv( map, values ); -} - -static void APIENTRY logGetPointerv(GLenum pname, GLvoid* *params) -{ - SIG( "glGetPointerv" ); - dllGetPointerv( pname, params ); -} - -static void APIENTRY logGetPolygonStipple(GLubyte *mask) -{ - SIG( "glGetPolygonStipple" ); - dllGetPolygonStipple( mask ); -} - -static const GLubyte * APIENTRY logGetString(GLenum name) -{ - SIG( "glGetString" ); - return dllGetString( name ); -} - -static void APIENTRY logGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) -{ - SIG( "glGetTexEnvfv" ); - dllGetTexEnvfv( target, pname, params ); -} - -static void APIENTRY logGetTexEnviv(GLenum target, GLenum pname, GLint *params) -{ - SIG( "glGetTexEnviv" ); - dllGetTexEnviv( target, pname, params ); -} - -static void APIENTRY logGetTexGendv(GLenum coord, GLenum pname, GLdouble *params) -{ - SIG( "glGetTexGendv" ); - dllGetTexGendv( coord, pname, params ); -} - -static void APIENTRY logGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) -{ - SIG( "glGetTexGenfv" ); - dllGetTexGenfv( coord, pname, params ); -} - -static void APIENTRY logGetTexGeniv(GLenum coord, GLenum pname, GLint *params) -{ - SIG( "glGetTexGeniv" ); - dllGetTexGeniv( coord, pname, params ); -} - -static void APIENTRY logGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void *pixels) -{ - SIG( "glGetTexImage" ); - dllGetTexImage( target, level, format, type, pixels ); -} -static void APIENTRY logGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params ) -{ - SIG( "glGetTexLevelParameterfv" ); - dllGetTexLevelParameterfv( target, level, pname, params ); -} - -static void APIENTRY logGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) -{ - SIG( "glGetTexLevelParameteriv" ); - dllGetTexLevelParameteriv( target, level, pname, params ); -} - -static void APIENTRY logGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) -{ - SIG( "glGetTexParameterfv" ); - dllGetTexParameterfv( target, pname, params ); -} - -static void APIENTRY logGetTexParameteriv(GLenum target, GLenum pname, GLint *params) -{ - SIG( "glGetTexParameteriv" ); - dllGetTexParameteriv( target, pname, params ); -} - -static void APIENTRY logHint(GLenum target, GLenum mode) -{ - fprintf( glw_state.log_fp, "glHint( 0x%x, 0x%x )\n", target, mode ); - dllHint( target, mode ); -} - -static void APIENTRY logIndexMask(GLuint mask) -{ - SIG( "glIndexMask" ); - dllIndexMask( mask ); -} - -static void APIENTRY logIndexPointer(GLenum type, GLsizei stride, const void *pointer) -{ - SIG( "glIndexPointer" ); - dllIndexPointer( type, stride, pointer ); -} - -static void APIENTRY logIndexd(GLdouble c) -{ - SIG( "glIndexd" ); - dllIndexd( c ); -} - -static void APIENTRY logIndexdv(const GLdouble *c) -{ - SIG( "glIndexdv" ); - dllIndexdv( c ); -} - -static void APIENTRY logIndexf(GLfloat c) -{ - SIG( "glIndexf" ); - dllIndexf( c ); -} - -static void APIENTRY logIndexfv(const GLfloat *c) -{ - SIG( "glIndexfv" ); - dllIndexfv( c ); -} - -static void APIENTRY logIndexi(GLint c) -{ - SIG( "glIndexi" ); - dllIndexi( c ); -} - -static void APIENTRY logIndexiv(const GLint *c) -{ - SIG( "glIndexiv" ); - dllIndexiv( c ); -} - -static void APIENTRY logIndexs(GLshort c) -{ - SIG( "glIndexs" ); - dllIndexs( c ); -} - -static void APIENTRY logIndexsv(const GLshort *c) -{ - SIG( "glIndexsv" ); - dllIndexsv( c ); -} - -static void APIENTRY logIndexub(GLubyte c) -{ - SIG( "glIndexub" ); - dllIndexub( c ); -} - -static void APIENTRY logIndexubv(const GLubyte *c) -{ - SIG( "glIndexubv" ); - dllIndexubv( c ); -} - -static void APIENTRY logInitNames(void) -{ - SIG( "glInitNames" ); - dllInitNames(); -} - -static void APIENTRY logInterleavedArrays(GLenum format, GLsizei stride, const void *pointer) -{ - SIG( "glInterleavedArrays" ); - dllInterleavedArrays( format, stride, pointer ); -} - -static GLboolean APIENTRY logIsEnabled(GLenum cap) -{ - SIG( "glIsEnabled" ); - return dllIsEnabled( cap ); -} -static GLboolean APIENTRY logIsList(GLuint list) -{ - SIG( "glIsList" ); - return dllIsList( list ); -} -static GLboolean APIENTRY logIsTexture(GLuint texture) -{ - SIG( "glIsTexture" ); - return dllIsTexture( texture ); -} - -static void APIENTRY logLightModelf(GLenum pname, GLfloat param) -{ - SIG( "glLightModelf" ); - dllLightModelf( pname, param ); -} - -static void APIENTRY logLightModelfv(GLenum pname, const GLfloat *params) -{ - SIG( "glLightModelfv" ); - dllLightModelfv( pname, params ); -} - -static void APIENTRY logLightModeli(GLenum pname, GLint param) -{ - SIG( "glLightModeli" ); - dllLightModeli( pname, param ); - -} - -static void APIENTRY logLightModeliv(GLenum pname, const GLint *params) -{ - SIG( "glLightModeliv" ); - dllLightModeliv( pname, params ); -} - -static void APIENTRY logLightf(GLenum light, GLenum pname, GLfloat param) -{ - SIG( "glLightf" ); - dllLightf( light, pname, param ); -} - -static void APIENTRY logLightfv(GLenum light, GLenum pname, const GLfloat *params) -{ - SIG( "glLightfv" ); - dllLightfv( light, pname, params ); -} - -static void APIENTRY logLighti(GLenum light, GLenum pname, GLint param) -{ - SIG( "glLighti" ); - dllLighti( light, pname, param ); -} - -static void APIENTRY logLightiv(GLenum light, GLenum pname, const GLint *params) -{ - SIG( "glLightiv" ); - dllLightiv( light, pname, params ); -} - -static void APIENTRY logLineStipple(GLint factor, GLushort pattern) -{ - SIG( "glLineStipple" ); - dllLineStipple( factor, pattern ); -} - -static void APIENTRY logLineWidth(GLfloat width) -{ - SIG( "glLineWidth" ); - dllLineWidth( width ); -} - -static void APIENTRY logListBase(GLuint base) -{ - SIG( "glListBase" ); - dllListBase( base ); -} - -static void APIENTRY logLoadIdentity(void) -{ - SIG( "glLoadIdentity" ); - dllLoadIdentity(); -} - -static void APIENTRY logLoadMatrixd(const GLdouble *m) -{ - SIG( "glLoadMatrixd" ); - dllLoadMatrixd( m ); -} - -static void APIENTRY logLoadMatrixf(const GLfloat *m) -{ - SIG( "glLoadMatrixf" ); - dllLoadMatrixf( m ); -} - -static void APIENTRY logLoadName(GLuint name) -{ - SIG( "glLoadName" ); - dllLoadName( name ); -} - -static void APIENTRY logLogicOp(GLenum opcode) -{ - SIG( "glLogicOp" ); - dllLogicOp( opcode ); -} - -static void APIENTRY logMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) -{ - SIG( "glMap1d" ); - dllMap1d( target, u1, u2, stride, order, points ); -} - -static void APIENTRY logMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) -{ - SIG( "glMap1f" ); - dllMap1f( target, u1, u2, stride, order, points ); -} - -static void APIENTRY logMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) -{ - SIG( "glMap2d" ); - dllMap2d( target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points ); -} - -static void APIENTRY logMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) -{ - SIG( "glMap2f" ); - dllMap2f( target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points ); -} - -static void APIENTRY logMapGrid1d(GLint un, GLdouble u1, GLdouble u2) -{ - SIG( "glMapGrid1d" ); - dllMapGrid1d( un, u1, u2 ); -} - -static void APIENTRY logMapGrid1f(GLint un, GLfloat u1, GLfloat u2) -{ - SIG( "glMapGrid1f" ); - dllMapGrid1f( un, u1, u2 ); -} - -static void APIENTRY logMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) -{ - SIG( "glMapGrid2d" ); - dllMapGrid2d( un, u1, u2, vn, v1, v2 ); -} -static void APIENTRY logMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) -{ - SIG( "glMapGrid2f" ); - dllMapGrid2f( un, u1, u2, vn, v1, v2 ); -} -static void APIENTRY logMaterialf(GLenum face, GLenum pname, GLfloat param) -{ - SIG( "glMaterialf" ); - dllMaterialf( face, pname, param ); -} -static void APIENTRY logMaterialfv(GLenum face, GLenum pname, const GLfloat *params) -{ - SIG( "glMaterialfv" ); - dllMaterialfv( face, pname, params ); -} - -static void APIENTRY logMateriali(GLenum face, GLenum pname, GLint param) -{ - SIG( "glMateriali" ); - dllMateriali( face, pname, param ); -} - -static void APIENTRY logMaterialiv(GLenum face, GLenum pname, const GLint *params) -{ - SIG( "glMaterialiv" ); - dllMaterialiv( face, pname, params ); -} - -static void APIENTRY logMatrixMode(GLenum mode) -{ - SIG( "glMatrixMode" ); - dllMatrixMode( mode ); -} - -static void APIENTRY logMultMatrixd(const GLdouble *m) -{ - SIG( "glMultMatrixd" ); - dllMultMatrixd( m ); -} - -static void APIENTRY logMultMatrixf(const GLfloat *m) -{ - SIG( "glMultMatrixf" ); - dllMultMatrixf( m ); -} - -static void APIENTRY logNewList(GLuint list, GLenum mode) -{ - SIG( "glNewList" ); - dllNewList( list, mode ); -} - -static void APIENTRY logNormal3b(GLbyte nx, GLbyte ny, GLbyte nz) -{ - SIG ("glNormal3b" ); - dllNormal3b( nx, ny, nz ); -} - -static void APIENTRY logNormal3bv(const GLbyte *v) -{ - SIG( "glNormal3bv" ); - dllNormal3bv( v ); -} - -static void APIENTRY logNormal3d(GLdouble nx, GLdouble ny, GLdouble nz) -{ - SIG( "glNormal3d" ); - dllNormal3d( nx, ny, nz ); -} - -static void APIENTRY logNormal3dv(const GLdouble *v) -{ - SIG( "glNormal3dv" ); - dllNormal3dv( v ); -} - -static void APIENTRY logNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) -{ - SIG( "glNormal3f" ); - dllNormal3f( nx, ny, nz ); -} - -static void APIENTRY logNormal3fv(const GLfloat *v) -{ - SIG( "glNormal3fv" ); - dllNormal3fv( v ); -} -static void APIENTRY logNormal3i(GLint nx, GLint ny, GLint nz) -{ - SIG( "glNormal3i" ); - dllNormal3i( nx, ny, nz ); -} -static void APIENTRY logNormal3iv(const GLint *v) -{ - SIG( "glNormal3iv" ); - dllNormal3iv( v ); -} -static void APIENTRY logNormal3s(GLshort nx, GLshort ny, GLshort nz) -{ - SIG( "glNormal3s" ); - dllNormal3s( nx, ny, nz ); -} -static void APIENTRY logNormal3sv(const GLshort *v) -{ - SIG( "glNormal3sv" ); - dllNormal3sv( v ); -} -static void APIENTRY logNormalPointer(GLenum type, GLsizei stride, const void *pointer) -{ - SIG( "glNormalPointer" ); - dllNormalPointer( type, stride, pointer ); -} -static void APIENTRY logOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) -{ - SIG( "glOrtho" ); - dllOrtho( left, right, bottom, top, zNear, zFar ); -} - -static void APIENTRY logPassThrough(GLfloat token) -{ - SIG( "glPassThrough" ); - dllPassThrough( token ); -} - -static void APIENTRY logPixelMapfv(GLenum map, GLsizei mapsize, const GLfloat *values) -{ - SIG( "glPixelMapfv" ); - dllPixelMapfv( map, mapsize, values ); -} - -static void APIENTRY logPixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values) -{ - SIG( "glPixelMapuiv" ); - dllPixelMapuiv( map, mapsize, values ); -} - -static void APIENTRY logPixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values) -{ - SIG( "glPixelMapusv" ); - dllPixelMapusv( map, mapsize, values ); -} -static void APIENTRY logPixelStoref(GLenum pname, GLfloat param) -{ - SIG( "glPixelStoref" ); - dllPixelStoref( pname, param ); -} -static void APIENTRY logPixelStorei(GLenum pname, GLint param) -{ - SIG( "glPixelStorei" ); - dllPixelStorei( pname, param ); -} -static void APIENTRY logPixelTransferf(GLenum pname, GLfloat param) -{ - SIG( "glPixelTransferf" ); - dllPixelTransferf( pname, param ); -} - -static void APIENTRY logPixelTransferi(GLenum pname, GLint param) -{ - SIG( "glPixelTransferi" ); - dllPixelTransferi( pname, param ); -} - -static void APIENTRY logPixelZoom(GLfloat xfactor, GLfloat yfactor) -{ - SIG( "glPixelZoom" ); - dllPixelZoom( xfactor, yfactor ); -} - -static void APIENTRY logPointSize(GLfloat size) -{ - SIG( "glPointSize" ); - dllPointSize( size ); -} - -static void APIENTRY logPolygonMode(GLenum face, GLenum mode) -{ - fprintf( glw_state.log_fp, "glPolygonMode( 0x%x, 0x%x )\n", face, mode ); - dllPolygonMode( face, mode ); -} - -static void APIENTRY logPolygonOffset(GLfloat factor, GLfloat units) -{ - SIG( "glPolygonOffset" ); - dllPolygonOffset( factor, units ); -} -static void APIENTRY logPolygonStipple(const GLubyte *mask ) -{ - SIG( "glPolygonStipple" ); - dllPolygonStipple( mask ); -} -static void APIENTRY logPopAttrib(void) -{ - SIG( "glPopAttrib" ); - dllPopAttrib(); -} - -static void APIENTRY logPopClientAttrib(void) -{ - SIG( "glPopClientAttrib" ); - dllPopClientAttrib(); -} - -static void APIENTRY logPopMatrix(void) -{ - SIG( "glPopMatrix" ); - dllPopMatrix(); -} - -static void APIENTRY logPopName(void) -{ - SIG( "glPopName" ); - dllPopName(); -} - -static void APIENTRY logPrioritizeTextures(GLsizei n, const GLuint *textures, const GLclampf *priorities) -{ - SIG( "glPrioritizeTextures" ); - dllPrioritizeTextures( n, textures, priorities ); -} - -static void APIENTRY logPushAttrib(GLbitfield mask) -{ - SIG( "glPushAttrib" ); - dllPushAttrib( mask ); -} - -static void APIENTRY logPushClientAttrib(GLbitfield mask) -{ - SIG( "glPushClientAttrib" ); - dllPushClientAttrib( mask ); -} - -static void APIENTRY logPushMatrix(void) -{ - SIG( "glPushMatrix" ); - dllPushMatrix(); -} - -static void APIENTRY logPushName(GLuint name) -{ - SIG( "glPushName" ); - dllPushName( name ); -} - -static void APIENTRY logRasterPos2d(GLdouble x, GLdouble y) -{ - SIG ("glRasterPot2d" ); - dllRasterPos2d( x, y ); -} - -static void APIENTRY logRasterPos2dv(const GLdouble *v) -{ - SIG( "glRasterPos2dv" ); - dllRasterPos2dv( v ); -} - -static void APIENTRY logRasterPos2f(GLfloat x, GLfloat y) -{ - SIG( "glRasterPos2f" ); - dllRasterPos2f( x, y ); -} -static void APIENTRY logRasterPos2fv(const GLfloat *v) -{ - SIG( "glRasterPos2dv" ); - dllRasterPos2fv( v ); -} -static void APIENTRY logRasterPos2i(GLint x, GLint y) -{ - SIG( "glRasterPos2if" ); - dllRasterPos2i( x, y ); -} -static void APIENTRY logRasterPos2iv(const GLint *v) -{ - SIG( "glRasterPos2iv" ); - dllRasterPos2iv( v ); -} -static void APIENTRY logRasterPos2s(GLshort x, GLshort y) -{ - SIG( "glRasterPos2s" ); - dllRasterPos2s( x, y ); -} -static void APIENTRY logRasterPos2sv(const GLshort *v) -{ - SIG( "glRasterPos2sv" ); - dllRasterPos2sv( v ); -} -static void APIENTRY logRasterPos3d(GLdouble x, GLdouble y, GLdouble z) -{ - SIG( "glRasterPos3d" ); - dllRasterPos3d( x, y, z ); -} -static void APIENTRY logRasterPos3dv(const GLdouble *v) -{ - SIG( "glRasterPos3dv" ); - dllRasterPos3dv( v ); -} -static void APIENTRY logRasterPos3f(GLfloat x, GLfloat y, GLfloat z) -{ - SIG( "glRasterPos3f" ); - dllRasterPos3f( x, y, z ); -} -static void APIENTRY logRasterPos3fv(const GLfloat *v) -{ - SIG( "glRasterPos3fv" ); - dllRasterPos3fv( v ); -} -static void APIENTRY logRasterPos3i(GLint x, GLint y, GLint z) -{ - SIG( "glRasterPos3i" ); - dllRasterPos3i( x, y, z ); -} -static void APIENTRY logRasterPos3iv(const GLint *v) -{ - SIG( "glRasterPos3iv" ); - dllRasterPos3iv( v ); -} -static void APIENTRY logRasterPos3s(GLshort x, GLshort y, GLshort z) -{ - SIG( "glRasterPos3s" ); - dllRasterPos3s( x, y, z ); -} -static void APIENTRY logRasterPos3sv(const GLshort *v) -{ - SIG( "glRasterPos3sv" ); - dllRasterPos3sv( v ); -} -static void APIENTRY logRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{ - SIG( "glRasterPos4d" ); - dllRasterPos4d( x, y, z, w ); -} -static void APIENTRY logRasterPos4dv(const GLdouble *v) -{ - SIG( "glRasterPos4dv" ); - dllRasterPos4dv( v ); -} -static void APIENTRY logRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - SIG( "glRasterPos4f" ); - dllRasterPos4f( x, y, z, w ); -} -static void APIENTRY logRasterPos4fv(const GLfloat *v) -{ - SIG( "glRasterPos4fv" ); - dllRasterPos4fv( v ); -} -static void APIENTRY logRasterPos4i(GLint x, GLint y, GLint z, GLint w) -{ - SIG( "glRasterPos4i" ); - dllRasterPos4i( x, y, z, w ); -} -static void APIENTRY logRasterPos4iv(const GLint *v) -{ - SIG( "glRasterPos4iv" ); - dllRasterPos4iv( v ); -} -static void APIENTRY logRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) -{ - SIG( "glRasterPos4s" ); - dllRasterPos4s( x, y, z, w ); -} -static void APIENTRY logRasterPos4sv(const GLshort *v) -{ - SIG( "glRasterPos4sv" ); - dllRasterPos4sv( v ); -} -static void APIENTRY logReadBuffer(GLenum mode) -{ - SIG( "glReadBuffer" ); - dllReadBuffer( mode ); -} -static void APIENTRY logReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) -{ - SIG( "glReadPixels" ); - dllReadPixels( x, y, width, height, format, type, pixels ); -} - -static void APIENTRY logRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) -{ - SIG( "glRectd" ); - dllRectd( x1, y1, x2, y2 ); -} - -static void APIENTRY logRectdv(const GLdouble *v1, const GLdouble *v2) -{ - SIG( "glRectdv" ); - dllRectdv( v1, v2 ); -} - -static void APIENTRY logRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) -{ - SIG( "glRectf" ); - dllRectf( x1, y1, x2, y2 ); -} - -static void APIENTRY logRectfv(const GLfloat *v1, const GLfloat *v2) -{ - SIG( "glRectfv" ); - dllRectfv( v1, v2 ); -} -static void APIENTRY logRecti(GLint x1, GLint y1, GLint x2, GLint y2) -{ - SIG( "glRecti" ); - dllRecti( x1, y1, x2, y2 ); -} -static void APIENTRY logRectiv(const GLint *v1, const GLint *v2) -{ - SIG( "glRectiv" ); - dllRectiv( v1, v2 ); -} -static void APIENTRY logRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) -{ - SIG( "glRects" ); - dllRects( x1, y1, x2, y2 ); -} -static void APIENTRY logRectsv(const GLshort *v1, const GLshort *v2) -{ - SIG( "glRectsv" ); - dllRectsv( v1, v2 ); -} -static GLint APIENTRY logRenderMode(GLenum mode) -{ - SIG( "glRenderMode" ); - return dllRenderMode( mode ); -} -static void APIENTRY logRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) -{ - SIG( "glRotated" ); - dllRotated( angle, x, y, z ); -} - -static void APIENTRY logRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) -{ - SIG( "glRotatef" ); - dllRotatef( angle, x, y, z ); -} - -static void APIENTRY logScaled(GLdouble x, GLdouble y, GLdouble z) -{ - SIG( "glScaled" ); - dllScaled( x, y, z ); -} - -static void APIENTRY logScalef(GLfloat x, GLfloat y, GLfloat z) -{ - SIG( "glScalef" ); - dllScalef( x, y, z ); -} - -static void APIENTRY logScissor(GLint x, GLint y, GLsizei width, GLsizei height) -{ - fprintf( glw_state.log_fp, "glScissor( %d, %d, %d, %d )\n", x, y, width, height ); - dllScissor( x, y, width, height ); -} - -static void APIENTRY logSelectBuffer(GLsizei size, GLuint *buffer) -{ - SIG( "glSelectBuffer" ); - dllSelectBuffer( size, buffer ); -} - -static void APIENTRY logShadeModel(GLenum mode) -{ - SIG( "glShadeModel" ); - dllShadeModel( mode ); -} - -static void APIENTRY logStencilFunc(GLenum func, GLint ref, GLuint mask) -{ - SIG( "glStencilFunc" ); - dllStencilFunc( func, ref, mask ); -} - -static void APIENTRY logStencilMask(GLuint mask) -{ - SIG( "glStencilMask" ); - dllStencilMask( mask ); -} - -static void APIENTRY logStencilOp(GLenum fail, GLenum zfail, GLenum zpass) -{ - SIG( "glStencilOp" ); - dllStencilOp( fail, zfail, zpass ); -} - -static void APIENTRY logTexCoord1d(GLdouble s) -{ - SIG( "glTexCoord1d" ); - dllTexCoord1d( s ); -} - -static void APIENTRY logTexCoord1dv(const GLdouble *v) -{ - SIG( "glTexCoord1dv" ); - dllTexCoord1dv( v ); -} - -static void APIENTRY logTexCoord1f(GLfloat s) -{ - SIG( "glTexCoord1f" ); - dllTexCoord1f( s ); -} -static void APIENTRY logTexCoord1fv(const GLfloat *v) -{ - SIG( "glTexCoord1fv" ); - dllTexCoord1fv( v ); -} -static void APIENTRY logTexCoord1i(GLint s) -{ - SIG( "glTexCoord1i" ); - dllTexCoord1i( s ); -} -static void APIENTRY logTexCoord1iv(const GLint *v) -{ - SIG( "glTexCoord1iv" ); - dllTexCoord1iv( v ); -} -static void APIENTRY logTexCoord1s(GLshort s) -{ - SIG( "glTexCoord1s" ); - dllTexCoord1s( s ); -} -static void APIENTRY logTexCoord1sv(const GLshort *v) -{ - SIG( "glTexCoord1sv" ); - dllTexCoord1sv( v ); -} -static void APIENTRY logTexCoord2d(GLdouble s, GLdouble t) -{ - SIG( "glTexCoord2d" ); - dllTexCoord2d( s, t ); -} - -static void APIENTRY logTexCoord2dv(const GLdouble *v) -{ - SIG( "glTexCoord2dv" ); - dllTexCoord2dv( v ); -} -static void APIENTRY logTexCoord2f(GLfloat s, GLfloat t) -{ - SIG( "glTexCoord2f" ); - dllTexCoord2f( s, t ); -} -static void APIENTRY logTexCoord2fv(const GLfloat *v) -{ - SIG( "glTexCoord2fv" ); - dllTexCoord2fv( v ); -} -static void APIENTRY logTexCoord2i(GLint s, GLint t) -{ - SIG( "glTexCoord2i" ); - dllTexCoord2i( s, t ); -} -static void APIENTRY logTexCoord2iv(const GLint *v) -{ - SIG( "glTexCoord2iv" ); - dllTexCoord2iv( v ); -} -static void APIENTRY logTexCoord2s(GLshort s, GLshort t) -{ - SIG( "glTexCoord2s" ); - dllTexCoord2s( s, t ); -} -static void APIENTRY logTexCoord2sv(const GLshort *v) -{ - SIG( "glTexCoord2sv" ); - dllTexCoord2sv( v ); -} -static void APIENTRY logTexCoord3d(GLdouble s, GLdouble t, GLdouble r) -{ - SIG( "glTexCoord3d" ); - dllTexCoord3d( s, t, r ); -} -static void APIENTRY logTexCoord3dv(const GLdouble *v) -{ - SIG( "glTexCoord3dv" ); - dllTexCoord3dv( v ); -} -static void APIENTRY logTexCoord3f(GLfloat s, GLfloat t, GLfloat r) -{ - SIG( "glTexCoord3f" ); - dllTexCoord3f( s, t, r ); -} -static void APIENTRY logTexCoord3fv(const GLfloat *v) -{ - SIG( "glTexCoord3fv" ); - dllTexCoord3fv( v ); -} -static void APIENTRY logTexCoord3i(GLint s, GLint t, GLint r) -{ - SIG( "glTexCoord3i" ); - dllTexCoord3i( s, t, r ); -} -static void APIENTRY logTexCoord3iv(const GLint *v) -{ - SIG( "glTexCoord3iv" ); - dllTexCoord3iv( v ); -} -static void APIENTRY logTexCoord3s(GLshort s, GLshort t, GLshort r) -{ - SIG( "glTexCoord3s" ); - dllTexCoord3s( s, t, r ); -} -static void APIENTRY logTexCoord3sv(const GLshort *v) -{ - SIG( "glTexCoord3sv" ); - dllTexCoord3sv( v ); -} -static void APIENTRY logTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q) -{ - SIG( "glTexCoord4d" ); - dllTexCoord4d( s, t, r, q ); -} -static void APIENTRY logTexCoord4dv(const GLdouble *v) -{ - SIG( "glTexCoord4dv" ); - dllTexCoord4dv( v ); -} -static void APIENTRY logTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) -{ - SIG( "glTexCoord4f" ); - dllTexCoord4f( s, t, r, q ); -} -static void APIENTRY logTexCoord4fv(const GLfloat *v) -{ - SIG( "glTexCoord4fv" ); - dllTexCoord4fv( v ); -} -static void APIENTRY logTexCoord4i(GLint s, GLint t, GLint r, GLint q) -{ - SIG( "glTexCoord4i" ); - dllTexCoord4i( s, t, r, q ); -} -static void APIENTRY logTexCoord4iv(const GLint *v) -{ - SIG( "glTexCoord4iv" ); - dllTexCoord4iv( v ); -} -static void APIENTRY logTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q) -{ - SIG( "glTexCoord4s" ); - dllTexCoord4s( s, t, r, q ); -} -static void APIENTRY logTexCoord4sv(const GLshort *v) -{ - SIG( "glTexCoord4sv" ); - dllTexCoord4sv( v ); -} -static void APIENTRY logTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) -{ - fprintf( glw_state.log_fp, "glTexCoordPointer( %d, %s, %d, MEM )\n", size, TypeToString( type ), stride ); - dllTexCoordPointer( size, type, stride, pointer ); -} - -static void APIENTRY logTexEnvf(GLenum target, GLenum pname, GLfloat param) -{ - fprintf( glw_state.log_fp, "glTexEnvf( 0x%x, 0x%x, %f )\n", target, pname, param ); - dllTexEnvf( target, pname, param ); -} - -static void APIENTRY logTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) -{ - SIG( "glTexEnvfv" ); - dllTexEnvfv( target, pname, params ); -} - -static void APIENTRY logTexEnvi(GLenum target, GLenum pname, GLint param) -{ - fprintf( glw_state.log_fp, "glTexEnvi( 0x%x, 0x%x, 0x%x )\n", target, pname, param ); - dllTexEnvi( target, pname, param ); -} -static void APIENTRY logTexEnviv(GLenum target, GLenum pname, const GLint *params) -{ - SIG( "glTexEnviv" ); - dllTexEnviv( target, pname, params ); -} - -static void APIENTRY logTexGend(GLenum coord, GLenum pname, GLdouble param) -{ - SIG( "glTexGend" ); - dllTexGend( coord, pname, param ); -} - -static void APIENTRY logTexGendv(GLenum coord, GLenum pname, const GLdouble *params) -{ - SIG( "glTexGendv" ); - dllTexGendv( coord, pname, params ); -} - -static void APIENTRY logTexGenf(GLenum coord, GLenum pname, GLfloat param) -{ - SIG( "glTexGenf" ); - dllTexGenf( coord, pname, param ); -} -static void APIENTRY logTexGenfv(GLenum coord, GLenum pname, const GLfloat *params) -{ - SIG( "glTexGenfv" ); - dllTexGenfv( coord, pname, params ); -} -static void APIENTRY logTexGeni(GLenum coord, GLenum pname, GLint param) -{ - SIG( "glTexGeni" ); - dllTexGeni( coord, pname, param ); -} -static void APIENTRY logTexGeniv(GLenum coord, GLenum pname, const GLint *params) -{ - SIG( "glTexGeniv" ); - dllTexGeniv( coord, pname, params ); -} -static void APIENTRY logTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels) -{ - SIG( "glTexImage1D" ); - dllTexImage1D( target, level, internalformat, width, border, format, type, pixels ); -} -static void APIENTRY logTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) -{ - SIG( "glTexImage2D" ); - dllTexImage2D( target, level, internalformat, width, height, border, format, type, pixels ); -} - -static void APIENTRY logTexParameterf(GLenum target, GLenum pname, GLfloat param) -{ - fprintf( glw_state.log_fp, "glTexParameterf( 0x%x, 0x%x, %f )\n", target, pname, param ); - dllTexParameterf( target, pname, param ); -} - -static void APIENTRY logTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) -{ - SIG( "glTexParameterfv" ); - dllTexParameterfv( target, pname, params ); -} -static void APIENTRY logTexParameteri(GLenum target, GLenum pname, GLint param) -{ - fprintf( glw_state.log_fp, "glTexParameteri( 0x%x, 0x%x, 0x%x )\n", target, pname, param ); - dllTexParameteri( target, pname, param ); -} -static void APIENTRY logTexParameteriv(GLenum target, GLenum pname, const GLint *params) -{ - SIG( "glTexParameteriv" ); - dllTexParameteriv( target, pname, params ); -} -static void APIENTRY logTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels) -{ - SIG( "glTexSubImage1D" ); - dllTexSubImage1D( target, level, xoffset, width, format, type, pixels ); -} -static void APIENTRY logTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) -{ - SIG( "glTexSubImage2D" ); - dllTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels ); -} -static void APIENTRY logTranslated(GLdouble x, GLdouble y, GLdouble z) -{ - SIG( "glTranslated" ); - dllTranslated( x, y, z ); -} - -static void APIENTRY logTranslatef(GLfloat x, GLfloat y, GLfloat z) -{ - SIG( "glTranslatef" ); - dllTranslatef( x, y, z ); -} - -static void APIENTRY logVertex2d(GLdouble x, GLdouble y) -{ - SIG( "glVertex2d" ); - dllVertex2d( x, y ); -} - -static void APIENTRY logVertex2dv(const GLdouble *v) -{ - SIG( "glVertex2dv" ); - dllVertex2dv( v ); -} -static void APIENTRY logVertex2f(GLfloat x, GLfloat y) -{ - SIG( "glVertex2f" ); - dllVertex2f( x, y ); -} -static void APIENTRY logVertex2fv(const GLfloat *v) -{ - SIG( "glVertex2fv" ); - dllVertex2fv( v ); -} -static void APIENTRY logVertex2i(GLint x, GLint y) -{ - SIG( "glVertex2i" ); - dllVertex2i( x, y ); -} -static void APIENTRY logVertex2iv(const GLint *v) -{ - SIG( "glVertex2iv" ); - dllVertex2iv( v ); -} -static void APIENTRY logVertex2s(GLshort x, GLshort y) -{ - SIG( "glVertex2s" ); - dllVertex2s( x, y ); -} -static void APIENTRY logVertex2sv(const GLshort *v) -{ - SIG( "glVertex2sv" ); - dllVertex2sv( v ); -} -static void APIENTRY logVertex3d(GLdouble x, GLdouble y, GLdouble z) -{ - SIG( "glVertex3d" ); - dllVertex3d( x, y, z ); -} -static void APIENTRY logVertex3dv(const GLdouble *v) -{ - SIG( "glVertex3dv" ); - dllVertex3dv( v ); -} -static void APIENTRY logVertex3f(GLfloat x, GLfloat y, GLfloat z) -{ - SIG( "glVertex3f" ); - dllVertex3f( x, y, z ); -} -static void APIENTRY logVertex3fv(const GLfloat *v) -{ - SIG( "glVertex3fv" ); - dllVertex3fv( v ); -} -static void APIENTRY logVertex3i(GLint x, GLint y, GLint z) -{ - SIG( "glVertex3i" ); - dllVertex3i( x, y, z ); -} -static void APIENTRY logVertex3iv(const GLint *v) -{ - SIG( "glVertex3iv" ); - dllVertex3iv( v ); -} -static void APIENTRY logVertex3s(GLshort x, GLshort y, GLshort z) -{ - SIG( "glVertex3s" ); - dllVertex3s( x, y, z ); -} -static void APIENTRY logVertex3sv(const GLshort *v) -{ - SIG( "glVertex3sv" ); - dllVertex3sv( v ); -} -static void APIENTRY logVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) -{ - SIG( "glVertex4d" ); - dllVertex4d( x, y, z, w ); -} -static void APIENTRY logVertex4dv(const GLdouble *v) -{ - SIG( "glVertex4dv" ); - dllVertex4dv( v ); -} -static void APIENTRY logVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - SIG( "glVertex4f" ); - dllVertex4f( x, y, z, w ); -} -static void APIENTRY logVertex4fv(const GLfloat *v) -{ - SIG( "glVertex4fv" ); - dllVertex4fv( v ); -} -static void APIENTRY logVertex4i(GLint x, GLint y, GLint z, GLint w) -{ - SIG( "glVertex4i" ); - dllVertex4i( x, y, z, w ); -} -static void APIENTRY logVertex4iv(const GLint *v) -{ - SIG( "glVertex4iv" ); - dllVertex4iv( v ); -} -static void APIENTRY logVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) -{ - SIG( "glVertex4s" ); - dllVertex4s( x, y, z, w ); -} -static void APIENTRY logVertex4sv(const GLshort *v) -{ - SIG( "glVertex4sv" ); - dllVertex4sv( v ); -} -static void APIENTRY logVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) -{ - fprintf( glw_state.log_fp, "glVertexPointer( %d, %s, %d, MEM )\n", size, TypeToString( type ), stride ); - dllVertexPointer( size, type, stride, pointer ); -} -static void APIENTRY logViewport(GLint x, GLint y, GLsizei width, GLsizei height) -{ - fprintf( glw_state.log_fp, "glViewport( %d, %d, %d, %d )\n", x, y, width, height ); - dllViewport( x, y, width, height ); -} - -/* -** QGL_Shutdown -** -** Unloads the specified DLL then nulls out all the proc pointers. This -** is only called during a hard shutdown of the OGL subsystem (e.g. vid_restart). -*/ -void QGL_Shutdown( void ) -{ - ri.Printf( PRINT_ALL, "...shutting down QGL\n" ); - - if ( glw_state.hinstOpenGL ) - { - ri.Printf( PRINT_ALL, "...unloading OpenGL DLL\n" ); - FreeLibrary( glw_state.hinstOpenGL ); - } - - glw_state.hinstOpenGL = NULL; - - qglAccum = NULL; - qglAlphaFunc = NULL; - qglAreTexturesResident = NULL; - qglArrayElement = NULL; - qglBegin = NULL; - qglBindTexture = NULL; - qglBitmap = NULL; - qglBlendFunc = NULL; - qglCallList = NULL; - qglCallLists = NULL; - qglClear = NULL; - qglClearAccum = NULL; - qglClearColor = NULL; - qglClearDepth = NULL; - qglClearIndex = NULL; - qglClearStencil = NULL; - qglClipPlane = NULL; - qglColor3b = NULL; - qglColor3bv = NULL; - qglColor3d = NULL; - qglColor3dv = NULL; - qglColor3f = NULL; - qglColor3fv = NULL; - qglColor3i = NULL; - qglColor3iv = NULL; - qglColor3s = NULL; - qglColor3sv = NULL; - qglColor3ub = NULL; - qglColor3ubv = NULL; - qglColor3ui = NULL; - qglColor3uiv = NULL; - qglColor3us = NULL; - qglColor3usv = NULL; - qglColor4b = NULL; - qglColor4bv = NULL; - qglColor4d = NULL; - qglColor4dv = NULL; - qglColor4f = NULL; - qglColor4fv = NULL; - qglColor4i = NULL; - qglColor4iv = NULL; - qglColor4s = NULL; - qglColor4sv = NULL; - qglColor4ub = NULL; - qglColor4ubv = NULL; - qglColor4ui = NULL; - qglColor4uiv = NULL; - qglColor4us = NULL; - qglColor4usv = NULL; - qglColorMask = NULL; - qglColorMaterial = NULL; - qglColorPointer = NULL; - qglCopyPixels = NULL; - qglCopyTexImage1D = NULL; - qglCopyTexImage2D = NULL; - qglCopyTexSubImage1D = NULL; - qglCopyTexSubImage2D = NULL; - qglCullFace = NULL; - qglDeleteLists = NULL; - qglDeleteTextures = NULL; - qglDepthFunc = NULL; - qglDepthMask = NULL; - qglDepthRange = NULL; - qglDisable = NULL; - qglDisableClientState = NULL; - qglDrawArrays = NULL; - qglDrawBuffer = NULL; - qglDrawElements = NULL; - qglDrawPixels = NULL; - qglEdgeFlag = NULL; - qglEdgeFlagPointer = NULL; - qglEdgeFlagv = NULL; - qglEnable = NULL; - qglEnableClientState = NULL; - qglEnd = NULL; - qglEndList = NULL; - qglEvalCoord1d = NULL; - qglEvalCoord1dv = NULL; - qglEvalCoord1f = NULL; - qglEvalCoord1fv = NULL; - qglEvalCoord2d = NULL; - qglEvalCoord2dv = NULL; - qglEvalCoord2f = NULL; - qglEvalCoord2fv = NULL; - qglEvalMesh1 = NULL; - qglEvalMesh2 = NULL; - qglEvalPoint1 = NULL; - qglEvalPoint2 = NULL; - qglFeedbackBuffer = NULL; - qglFinish = NULL; - qglFlush = NULL; - qglFogf = NULL; - qglFogfv = NULL; - qglFogi = NULL; - qglFogiv = NULL; - qglFrontFace = NULL; - qglFrustum = NULL; - qglGenLists = NULL; - qglGenTextures = NULL; - qglGetBooleanv = NULL; - qglGetClipPlane = NULL; - qglGetDoublev = NULL; - qglGetError = NULL; - qglGetFloatv = NULL; - qglGetIntegerv = NULL; - qglGetLightfv = NULL; - qglGetLightiv = NULL; - qglGetMapdv = NULL; - qglGetMapfv = NULL; - qglGetMapiv = NULL; - qglGetMaterialfv = NULL; - qglGetMaterialiv = NULL; - qglGetPixelMapfv = NULL; - qglGetPixelMapuiv = NULL; - qglGetPixelMapusv = NULL; - qglGetPointerv = NULL; - qglGetPolygonStipple = NULL; - qglGetString = NULL; - qglGetTexEnvfv = NULL; - qglGetTexEnviv = NULL; - qglGetTexGendv = NULL; - qglGetTexGenfv = NULL; - qglGetTexGeniv = NULL; - qglGetTexImage = NULL; - qglGetTexLevelParameterfv = NULL; - qglGetTexLevelParameteriv = NULL; - qglGetTexParameterfv = NULL; - qglGetTexParameteriv = NULL; - qglHint = NULL; - qglIndexMask = NULL; - qglIndexPointer = NULL; - qglIndexd = NULL; - qglIndexdv = NULL; - qglIndexf = NULL; - qglIndexfv = NULL; - qglIndexi = NULL; - qglIndexiv = NULL; - qglIndexs = NULL; - qglIndexsv = NULL; - qglIndexub = NULL; - qglIndexubv = NULL; - qglInitNames = NULL; - qglInterleavedArrays = NULL; - qglIsEnabled = NULL; - qglIsList = NULL; - qglIsTexture = NULL; - qglLightModelf = NULL; - qglLightModelfv = NULL; - qglLightModeli = NULL; - qglLightModeliv = NULL; - qglLightf = NULL; - qglLightfv = NULL; - qglLighti = NULL; - qglLightiv = NULL; - qglLineStipple = NULL; - qglLineWidth = NULL; - qglListBase = NULL; - qglLoadIdentity = NULL; - qglLoadMatrixd = NULL; - qglLoadMatrixf = NULL; - qglLoadName = NULL; - qglLogicOp = NULL; - qglMap1d = NULL; - qglMap1f = NULL; - qglMap2d = NULL; - qglMap2f = NULL; - qglMapGrid1d = NULL; - qglMapGrid1f = NULL; - qglMapGrid2d = NULL; - qglMapGrid2f = NULL; - qglMaterialf = NULL; - qglMaterialfv = NULL; - qglMateriali = NULL; - qglMaterialiv = NULL; - qglMatrixMode = NULL; - qglMultMatrixd = NULL; - qglMultMatrixf = NULL; - qglNewList = NULL; - qglNormal3b = NULL; - qglNormal3bv = NULL; - qglNormal3d = NULL; - qglNormal3dv = NULL; - qglNormal3f = NULL; - qglNormal3fv = NULL; - qglNormal3i = NULL; - qglNormal3iv = NULL; - qglNormal3s = NULL; - qglNormal3sv = NULL; - qglNormalPointer = NULL; - qglOrtho = NULL; - qglPassThrough = NULL; - qglPixelMapfv = NULL; - qglPixelMapuiv = NULL; - qglPixelMapusv = NULL; - qglPixelStoref = NULL; - qglPixelStorei = NULL; - qglPixelTransferf = NULL; - qglPixelTransferi = NULL; - qglPixelZoom = NULL; - qglPointSize = NULL; - qglPolygonMode = NULL; - qglPolygonOffset = NULL; - qglPolygonStipple = NULL; - qglPopAttrib = NULL; - qglPopClientAttrib = NULL; - qglPopMatrix = NULL; - qglPopName = NULL; - qglPrioritizeTextures = NULL; - qglPushAttrib = NULL; - qglPushClientAttrib = NULL; - qglPushMatrix = NULL; - qglPushName = NULL; - qglRasterPos2d = NULL; - qglRasterPos2dv = NULL; - qglRasterPos2f = NULL; - qglRasterPos2fv = NULL; - qglRasterPos2i = NULL; - qglRasterPos2iv = NULL; - qglRasterPos2s = NULL; - qglRasterPos2sv = NULL; - qglRasterPos3d = NULL; - qglRasterPos3dv = NULL; - qglRasterPos3f = NULL; - qglRasterPos3fv = NULL; - qglRasterPos3i = NULL; - qglRasterPos3iv = NULL; - qglRasterPos3s = NULL; - qglRasterPos3sv = NULL; - qglRasterPos4d = NULL; - qglRasterPos4dv = NULL; - qglRasterPos4f = NULL; - qglRasterPos4fv = NULL; - qglRasterPos4i = NULL; - qglRasterPos4iv = NULL; - qglRasterPos4s = NULL; - qglRasterPos4sv = NULL; - qglReadBuffer = NULL; - qglReadPixels = NULL; - qglRectd = NULL; - qglRectdv = NULL; - qglRectf = NULL; - qglRectfv = NULL; - qglRecti = NULL; - qglRectiv = NULL; - qglRects = NULL; - qglRectsv = NULL; - qglRenderMode = NULL; - qglRotated = NULL; - qglRotatef = NULL; - qglScaled = NULL; - qglScalef = NULL; - qglScissor = NULL; - qglSelectBuffer = NULL; - qglShadeModel = NULL; - qglStencilFunc = NULL; - qglStencilMask = NULL; - qglStencilOp = NULL; - qglTexCoord1d = NULL; - qglTexCoord1dv = NULL; - qglTexCoord1f = NULL; - qglTexCoord1fv = NULL; - qglTexCoord1i = NULL; - qglTexCoord1iv = NULL; - qglTexCoord1s = NULL; - qglTexCoord1sv = NULL; - qglTexCoord2d = NULL; - qglTexCoord2dv = NULL; - qglTexCoord2f = NULL; - qglTexCoord2fv = NULL; - qglTexCoord2i = NULL; - qglTexCoord2iv = NULL; - qglTexCoord2s = NULL; - qglTexCoord2sv = NULL; - qglTexCoord3d = NULL; - qglTexCoord3dv = NULL; - qglTexCoord3f = NULL; - qglTexCoord3fv = NULL; - qglTexCoord3i = NULL; - qglTexCoord3iv = NULL; - qglTexCoord3s = NULL; - qglTexCoord3sv = NULL; - qglTexCoord4d = NULL; - qglTexCoord4dv = NULL; - qglTexCoord4f = NULL; - qglTexCoord4fv = NULL; - qglTexCoord4i = NULL; - qglTexCoord4iv = NULL; - qglTexCoord4s = NULL; - qglTexCoord4sv = NULL; - qglTexCoordPointer = NULL; - qglTexEnvf = NULL; - qglTexEnvfv = NULL; - qglTexEnvi = NULL; - qglTexEnviv = NULL; - qglTexGend = NULL; - qglTexGendv = NULL; - qglTexGenf = NULL; - qglTexGenfv = NULL; - qglTexGeni = NULL; - qglTexGeniv = NULL; - qglTexImage1D = NULL; - qglTexImage2D = NULL; - qglTexParameterf = NULL; - qglTexParameterfv = NULL; - qglTexParameteri = NULL; - qglTexParameteriv = NULL; - qglTexSubImage1D = NULL; - qglTexSubImage2D = NULL; - qglTranslated = NULL; - qglTranslatef = NULL; - qglVertex2d = NULL; - qglVertex2dv = NULL; - qglVertex2f = NULL; - qglVertex2fv = NULL; - qglVertex2i = NULL; - qglVertex2iv = NULL; - qglVertex2s = NULL; - qglVertex2sv = NULL; - qglVertex3d = NULL; - qglVertex3dv = NULL; - qglVertex3f = NULL; - qglVertex3fv = NULL; - qglVertex3i = NULL; - qglVertex3iv = NULL; - qglVertex3s = NULL; - qglVertex3sv = NULL; - qglVertex4d = NULL; - qglVertex4dv = NULL; - qglVertex4f = NULL; - qglVertex4fv = NULL; - qglVertex4i = NULL; - qglVertex4iv = NULL; - qglVertex4s = NULL; - qglVertex4sv = NULL; - qglVertexPointer = NULL; - qglViewport = NULL; - - qglCompressedTexImage3DARB = NULL; - qglCompressedTexImage2DARB = NULL; - qglCompressedTexSubImage3DARB = NULL; - qglCompressedTexSubImage2DARB = NULL; - qglGetCompressedTexImageARB = NULL; - - qwglCopyContext = NULL; - qwglCreateContext = NULL; - qwglCreateLayerContext = NULL; - qwglDeleteContext = NULL; - qwglDescribeLayerPlane = NULL; - qwglGetCurrentContext = NULL; - qwglGetCurrentDC = NULL; - qwglGetLayerPaletteEntries = NULL; - qwglGetProcAddress = NULL; - qwglMakeCurrent = NULL; - qwglRealizeLayerPalette = NULL; - qwglSetLayerPaletteEntries = NULL; - qwglShareLists = NULL; - qwglSwapLayerBuffers = NULL; - qwglUseFontBitmaps = NULL; - qwglUseFontOutlines = NULL; - - qwglChoosePixelFormat = NULL; - qwglDescribePixelFormat = NULL; - qwglGetPixelFormat = NULL; - qwglSetPixelFormat = NULL; - qwglSwapBuffers = NULL; -} - -#define GR_NUM_BOARDS 0x0f - -static qboolean GlideIsValid( void ) -{ - HMODULE hGlide; -// int numBoards; -// void (__stdcall *grGet)(unsigned int, unsigned int, int*); - - if ( ( hGlide = LoadLibrary("Glide3X") ) != 0 ) - { - // FIXME: 3Dfx needs to fix this shit - return qtrue; - -#if 0 - grGet = (void *)GetProcAddress( hGlide, "_grGet@12"); - - if ( grGet ) - { - grGet( GR_NUM_BOARDS, sizeof(int), &numBoards); - } - else - { - // if we've reached this point, something is seriously wrong - ri.Printf( PRINT_WARNING, "WARNING: could not find grGet in GLIDE3X.DLL\n" ); - numBoards = 0; - } - - FreeLibrary( hGlide ); - hGlide = NULL; - - if ( numBoards > 0 ) - { - return qtrue; - } - - ri.Printf( PRINT_WARNING, "WARNING: invalid Glide installation!\n" ); -#endif - } - - return qfalse; -} - -# pragma warning (disable : 4113 4133 4047 ) -# define GPA( a ) GetProcAddress( glw_state.hinstOpenGL, a ) - -/* -** QGL_Init -** -** This is responsible for binding our qgl function pointers to -** the appropriate GL stuff. In Windows this means doing a -** LoadLibrary and a bunch of calls to GetProcAddress. On other -** operating systems we need to do the right thing, whatever that -** might be. -*/ -qboolean QGL_Init( const char *dllname ) -{ - char systemDir[1024]; - char libName[1024]; - - GetSystemDirectory( systemDir, sizeof( systemDir ) ); - - assert( glw_state.hinstOpenGL == 0 ); - - ri.Printf( PRINT_ALL, "...initializing QGL\n" ); - - // NOTE: this assumes that 'dllname' is lower case (and it should be)! - if ( strstr( dllname, _3DFX_DRIVER_NAME ) ) - { - if ( !GlideIsValid() ) - { - ri.Printf( PRINT_ALL, "...WARNING: missing Glide installation, assuming no 3Dfx available\n" ); - return qfalse; - } - } - - if ( dllname[0] != '!' ) - { - Com_sprintf( libName, sizeof( libName ), "%s\\%s", systemDir, dllname ); - } - else - { - Q_strncpyz( libName, dllname, sizeof( libName ) ); - } - - ri.Printf( PRINT_ALL, "...calling LoadLibrary( '%s.dll' ): ", libName ); - - if ( ( glw_state.hinstOpenGL = LoadLibrary( dllname ) ) == 0 ) - { - ri.Printf( PRINT_ALL, "failed\n" ); - return qfalse; - } - ri.Printf( PRINT_ALL, "succeeded\n" ); - - qglAccum = dllAccum = GPA( "glAccum" ); - qglAlphaFunc = dllAlphaFunc = GPA( "glAlphaFunc" ); - qglAreTexturesResident = dllAreTexturesResident = GPA( "glAreTexturesResident" ); - qglArrayElement = dllArrayElement = GPA( "glArrayElement" ); - qglBegin = dllBegin = GPA( "glBegin" ); - qglBindTexture = dllBindTexture = GPA( "glBindTexture" ); - qglBitmap = dllBitmap = GPA( "glBitmap" ); - qglBlendFunc = dllBlendFunc = GPA( "glBlendFunc" ); - qglCallList = dllCallList = GPA( "glCallList" ); - qglCallLists = dllCallLists = GPA( "glCallLists" ); - qglClear = dllClear = GPA( "glClear" ); - qglClearAccum = dllClearAccum = GPA( "glClearAccum" ); - qglClearColor = dllClearColor = GPA( "glClearColor" ); - qglClearDepth = dllClearDepth = GPA( "glClearDepth" ); - qglClearIndex = dllClearIndex = GPA( "glClearIndex" ); - qglClearStencil = dllClearStencil = GPA( "glClearStencil" ); - qglClipPlane = dllClipPlane = GPA( "glClipPlane" ); - qglColor3b = dllColor3b = GPA( "glColor3b" ); - qglColor3bv = dllColor3bv = GPA( "glColor3bv" ); - qglColor3d = dllColor3d = GPA( "glColor3d" ); - qglColor3dv = dllColor3dv = GPA( "glColor3dv" ); - qglColor3f = dllColor3f = GPA( "glColor3f" ); - qglColor3fv = dllColor3fv = GPA( "glColor3fv" ); - qglColor3i = dllColor3i = GPA( "glColor3i" ); - qglColor3iv = dllColor3iv = GPA( "glColor3iv" ); - qglColor3s = dllColor3s = GPA( "glColor3s" ); - qglColor3sv = dllColor3sv = GPA( "glColor3sv" ); - qglColor3ub = dllColor3ub = GPA( "glColor3ub" ); - qglColor3ubv = dllColor3ubv = GPA( "glColor3ubv" ); - qglColor3ui = dllColor3ui = GPA( "glColor3ui" ); - qglColor3uiv = dllColor3uiv = GPA( "glColor3uiv" ); - qglColor3us = dllColor3us = GPA( "glColor3us" ); - qglColor3usv = dllColor3usv = GPA( "glColor3usv" ); - qglColor4b = dllColor4b = GPA( "glColor4b" ); - qglColor4bv = dllColor4bv = GPA( "glColor4bv" ); - qglColor4d = dllColor4d = GPA( "glColor4d" ); - qglColor4dv = dllColor4dv = GPA( "glColor4dv" ); - qglColor4f = dllColor4f = GPA( "glColor4f" ); - qglColor4fv = dllColor4fv = GPA( "glColor4fv" ); - qglColor4i = dllColor4i = GPA( "glColor4i" ); - qglColor4iv = dllColor4iv = GPA( "glColor4iv" ); - qglColor4s = dllColor4s = GPA( "glColor4s" ); - qglColor4sv = dllColor4sv = GPA( "glColor4sv" ); - qglColor4ub = dllColor4ub = GPA( "glColor4ub" ); - qglColor4ubv = dllColor4ubv = GPA( "glColor4ubv" ); - qglColor4ui = dllColor4ui = GPA( "glColor4ui" ); - qglColor4uiv = dllColor4uiv = GPA( "glColor4uiv" ); - qglColor4us = dllColor4us = GPA( "glColor4us" ); - qglColor4usv = dllColor4usv = GPA( "glColor4usv" ); - qglColorMask = dllColorMask = GPA( "glColorMask" ); - qglColorMaterial = dllColorMaterial = GPA( "glColorMaterial" ); - qglColorPointer = dllColorPointer = GPA( "glColorPointer" ); - qglCopyPixels = dllCopyPixels = GPA( "glCopyPixels" ); - qglCopyTexImage1D = dllCopyTexImage1D = GPA( "glCopyTexImage1D" ); - qglCopyTexImage2D = dllCopyTexImage2D = GPA( "glCopyTexImage2D" ); - qglCopyTexSubImage1D = dllCopyTexSubImage1D = GPA( "glCopyTexSubImage1D" ); - qglCopyTexSubImage2D = dllCopyTexSubImage2D = GPA( "glCopyTexSubImage2D" ); - qglCullFace = dllCullFace = GPA( "glCullFace" ); - qglDeleteLists = dllDeleteLists = GPA( "glDeleteLists" ); - qglDeleteTextures = dllDeleteTextures = GPA( "glDeleteTextures" ); - qglDepthFunc = dllDepthFunc = GPA( "glDepthFunc" ); - qglDepthMask = dllDepthMask = GPA( "glDepthMask" ); - qglDepthRange = dllDepthRange = GPA( "glDepthRange" ); - qglDisable = dllDisable = GPA( "glDisable" ); - qglDisableClientState = dllDisableClientState = GPA( "glDisableClientState" ); - qglDrawArrays = dllDrawArrays = GPA( "glDrawArrays" ); - qglDrawBuffer = dllDrawBuffer = GPA( "glDrawBuffer" ); - qglDrawElements = dllDrawElements = GPA( "glDrawElements" ); - qglDrawPixels = dllDrawPixels = GPA( "glDrawPixels" ); - qglEdgeFlag = dllEdgeFlag = GPA( "glEdgeFlag" ); - qglEdgeFlagPointer = dllEdgeFlagPointer = GPA( "glEdgeFlagPointer" ); - qglEdgeFlagv = dllEdgeFlagv = GPA( "glEdgeFlagv" ); - qglEnable = dllEnable = GPA( "glEnable" ); - qglEnableClientState = dllEnableClientState = GPA( "glEnableClientState" ); - qglEnd = dllEnd = GPA( "glEnd" ); - qglEndList = dllEndList = GPA( "glEndList" ); - qglEvalCoord1d = dllEvalCoord1d = GPA( "glEvalCoord1d" ); - qglEvalCoord1dv = dllEvalCoord1dv = GPA( "glEvalCoord1dv" ); - qglEvalCoord1f = dllEvalCoord1f = GPA( "glEvalCoord1f" ); - qglEvalCoord1fv = dllEvalCoord1fv = GPA( "glEvalCoord1fv" ); - qglEvalCoord2d = dllEvalCoord2d = GPA( "glEvalCoord2d" ); - qglEvalCoord2dv = dllEvalCoord2dv = GPA( "glEvalCoord2dv" ); - qglEvalCoord2f = dllEvalCoord2f = GPA( "glEvalCoord2f" ); - qglEvalCoord2fv = dllEvalCoord2fv = GPA( "glEvalCoord2fv" ); - qglEvalMesh1 = dllEvalMesh1 = GPA( "glEvalMesh1" ); - qglEvalMesh2 = dllEvalMesh2 = GPA( "glEvalMesh2" ); - qglEvalPoint1 = dllEvalPoint1 = GPA( "glEvalPoint1" ); - qglEvalPoint2 = dllEvalPoint2 = GPA( "glEvalPoint2" ); - qglFeedbackBuffer = dllFeedbackBuffer = GPA( "glFeedbackBuffer" ); - qglFinish = dllFinish = GPA( "glFinish" ); - qglFlush = dllFlush = GPA( "glFlush" ); - qglFogf = dllFogf = GPA( "glFogf" ); - qglFogfv = dllFogfv = GPA( "glFogfv" ); - qglFogi = dllFogi = GPA( "glFogi" ); - qglFogiv = dllFogiv = GPA( "glFogiv" ); - qglFrontFace = dllFrontFace = GPA( "glFrontFace" ); - qglFrustum = dllFrustum = GPA( "glFrustum" ); - qglGenLists = dllGenLists = ( GLuint (__stdcall * )(int) ) GPA( "glGenLists" ); - qglGenTextures = dllGenTextures = GPA( "glGenTextures" ); - qglGetBooleanv = dllGetBooleanv = GPA( "glGetBooleanv" ); - qglGetClipPlane = dllGetClipPlane = GPA( "glGetClipPlane" ); - qglGetDoublev = dllGetDoublev = GPA( "glGetDoublev" ); - qglGetError = dllGetError = ( GLenum (__stdcall * )(void) ) GPA( "glGetError" ); - qglGetFloatv = dllGetFloatv = GPA( "glGetFloatv" ); - qglGetIntegerv = dllGetIntegerv = GPA( "glGetIntegerv" ); - qglGetLightfv = dllGetLightfv = GPA( "glGetLightfv" ); - qglGetLightiv = dllGetLightiv = GPA( "glGetLightiv" ); - qglGetMapdv = dllGetMapdv = GPA( "glGetMapdv" ); - qglGetMapfv = dllGetMapfv = GPA( "glGetMapfv" ); - qglGetMapiv = dllGetMapiv = GPA( "glGetMapiv" ); - qglGetMaterialfv = dllGetMaterialfv = GPA( "glGetMaterialfv" ); - qglGetMaterialiv = dllGetMaterialiv = GPA( "glGetMaterialiv" ); - qglGetPixelMapfv = dllGetPixelMapfv = GPA( "glGetPixelMapfv" ); - qglGetPixelMapuiv = dllGetPixelMapuiv = GPA( "glGetPixelMapuiv" ); - qglGetPixelMapusv = dllGetPixelMapusv = GPA( "glGetPixelMapusv" ); - qglGetPointerv = dllGetPointerv = GPA( "glGetPointerv" ); - qglGetPolygonStipple = dllGetPolygonStipple = GPA( "glGetPolygonStipple" ); - qglGetString = dllGetString = GPA( "glGetString" ); - qglGetTexEnvfv = dllGetTexEnvfv = GPA( "glGetTexEnvfv" ); - qglGetTexEnviv = dllGetTexEnviv = GPA( "glGetTexEnviv" ); - qglGetTexGendv = dllGetTexGendv = GPA( "glGetTexGendv" ); - qglGetTexGenfv = dllGetTexGenfv = GPA( "glGetTexGenfv" ); - qglGetTexGeniv = dllGetTexGeniv = GPA( "glGetTexGeniv" ); - qglGetTexImage = dllGetTexImage = GPA( "glGetTexImage" ); - qglGetTexParameterfv = dllGetTexParameterfv = GPA( "glGetTexParameterfv" ); - qglGetTexParameteriv = dllGetTexParameteriv = GPA( "glGetTexParameteriv" ); - qglHint = dllHint = GPA( "glHint" ); - qglIndexMask = dllIndexMask = GPA( "glIndexMask" ); - qglIndexPointer = dllIndexPointer = GPA( "glIndexPointer" ); - qglIndexd = dllIndexd = GPA( "glIndexd" ); - qglIndexdv = dllIndexdv = GPA( "glIndexdv" ); - qglIndexf = dllIndexf = GPA( "glIndexf" ); - qglIndexfv = dllIndexfv = GPA( "glIndexfv" ); - qglIndexi = dllIndexi = GPA( "glIndexi" ); - qglIndexiv = dllIndexiv = GPA( "glIndexiv" ); - qglIndexs = dllIndexs = GPA( "glIndexs" ); - qglIndexsv = dllIndexsv = GPA( "glIndexsv" ); - qglIndexub = dllIndexub = GPA( "glIndexub" ); - qglIndexubv = dllIndexubv = GPA( "glIndexubv" ); - qglInitNames = dllInitNames = GPA( "glInitNames" ); - qglInterleavedArrays = dllInterleavedArrays = GPA( "glInterleavedArrays" ); - qglIsEnabled = dllIsEnabled = GPA( "glIsEnabled" ); - qglIsList = dllIsList = GPA( "glIsList" ); - qglIsTexture = dllIsTexture = GPA( "glIsTexture" ); - qglLightModelf = dllLightModelf = GPA( "glLightModelf" ); - qglLightModelfv = dllLightModelfv = GPA( "glLightModelfv" ); - qglLightModeli = dllLightModeli = GPA( "glLightModeli" ); - qglLightModeliv = dllLightModeliv = GPA( "glLightModeliv" ); - qglLightf = dllLightf = GPA( "glLightf" ); - qglLightfv = dllLightfv = GPA( "glLightfv" ); - qglLighti = dllLighti = GPA( "glLighti" ); - qglLightiv = dllLightiv = GPA( "glLightiv" ); - qglLineStipple = dllLineStipple = GPA( "glLineStipple" ); - qglLineWidth = dllLineWidth = GPA( "glLineWidth" ); - qglListBase = dllListBase = GPA( "glListBase" ); - qglLoadIdentity = dllLoadIdentity = GPA( "glLoadIdentity" ); - qglLoadMatrixd = dllLoadMatrixd = GPA( "glLoadMatrixd" ); - qglLoadMatrixf = dllLoadMatrixf = GPA( "glLoadMatrixf" ); - qglLoadName = dllLoadName = GPA( "glLoadName" ); - qglLogicOp = dllLogicOp = GPA( "glLogicOp" ); - qglMap1d = dllMap1d = GPA( "glMap1d" ); - qglMap1f = dllMap1f = GPA( "glMap1f" ); - qglMap2d = dllMap2d = GPA( "glMap2d" ); - qglMap2f = dllMap2f = GPA( "glMap2f" ); - qglMapGrid1d = dllMapGrid1d = GPA( "glMapGrid1d" ); - qglMapGrid1f = dllMapGrid1f = GPA( "glMapGrid1f" ); - qglMapGrid2d = dllMapGrid2d = GPA( "glMapGrid2d" ); - qglMapGrid2f = dllMapGrid2f = GPA( "glMapGrid2f" ); - qglMaterialf = dllMaterialf = GPA( "glMaterialf" ); - qglMaterialfv = dllMaterialfv = GPA( "glMaterialfv" ); - qglMateriali = dllMateriali = GPA( "glMateriali" ); - qglMaterialiv = dllMaterialiv = GPA( "glMaterialiv" ); - qglMatrixMode = dllMatrixMode = GPA( "glMatrixMode" ); - qglMultMatrixd = dllMultMatrixd = GPA( "glMultMatrixd" ); - qglMultMatrixf = dllMultMatrixf = GPA( "glMultMatrixf" ); - qglNewList = dllNewList = GPA( "glNewList" ); - qglNormal3b = dllNormal3b = GPA( "glNormal3b" ); - qglNormal3bv = dllNormal3bv = GPA( "glNormal3bv" ); - qglNormal3d = dllNormal3d = GPA( "glNormal3d" ); - qglNormal3dv = dllNormal3dv = GPA( "glNormal3dv" ); - qglNormal3f = dllNormal3f = GPA( "glNormal3f" ); - qglNormal3fv = dllNormal3fv = GPA( "glNormal3fv" ); - qglNormal3i = dllNormal3i = GPA( "glNormal3i" ); - qglNormal3iv = dllNormal3iv = GPA( "glNormal3iv" ); - qglNormal3s = dllNormal3s = GPA( "glNormal3s" ); - qglNormal3sv = dllNormal3sv = GPA( "glNormal3sv" ); - qglNormalPointer = dllNormalPointer = GPA( "glNormalPointer" ); - qglOrtho = dllOrtho = GPA( "glOrtho" ); - qglPassThrough = dllPassThrough = GPA( "glPassThrough" ); - qglPixelMapfv = dllPixelMapfv = GPA( "glPixelMapfv" ); - qglPixelMapuiv = dllPixelMapuiv = GPA( "glPixelMapuiv" ); - qglPixelMapusv = dllPixelMapusv = GPA( "glPixelMapusv" ); - qglPixelStoref = dllPixelStoref = GPA( "glPixelStoref" ); - qglPixelStorei = dllPixelStorei = GPA( "glPixelStorei" ); - qglPixelTransferf = dllPixelTransferf = GPA( "glPixelTransferf" ); - qglPixelTransferi = dllPixelTransferi = GPA( "glPixelTransferi" ); - qglPixelZoom = dllPixelZoom = GPA( "glPixelZoom" ); - qglPointSize = dllPointSize = GPA( "glPointSize" ); - qglPolygonMode = dllPolygonMode = GPA( "glPolygonMode" ); - qglPolygonOffset = dllPolygonOffset = GPA( "glPolygonOffset" ); - qglPolygonStipple = dllPolygonStipple = GPA( "glPolygonStipple" ); - qglPopAttrib = dllPopAttrib = GPA( "glPopAttrib" ); - qglPopClientAttrib = dllPopClientAttrib = GPA( "glPopClientAttrib" ); - qglPopMatrix = dllPopMatrix = GPA( "glPopMatrix" ); - qglPopName = dllPopName = GPA( "glPopName" ); - qglPrioritizeTextures = dllPrioritizeTextures = GPA( "glPrioritizeTextures" ); - qglPushAttrib = dllPushAttrib = GPA( "glPushAttrib" ); - qglPushClientAttrib = dllPushClientAttrib = GPA( "glPushClientAttrib" ); - qglPushMatrix = dllPushMatrix = GPA( "glPushMatrix" ); - qglPushName = dllPushName = GPA( "glPushName" ); - qglRasterPos2d = dllRasterPos2d = GPA( "glRasterPos2d" ); - qglRasterPos2dv = dllRasterPos2dv = GPA( "glRasterPos2dv" ); - qglRasterPos2f = dllRasterPos2f = GPA( "glRasterPos2f" ); - qglRasterPos2fv = dllRasterPos2fv = GPA( "glRasterPos2fv" ); - qglRasterPos2i = dllRasterPos2i = GPA( "glRasterPos2i" ); - qglRasterPos2iv = dllRasterPos2iv = GPA( "glRasterPos2iv" ); - qglRasterPos2s = dllRasterPos2s = GPA( "glRasterPos2s" ); - qglRasterPos2sv = dllRasterPos2sv = GPA( "glRasterPos2sv" ); - qglRasterPos3d = dllRasterPos3d = GPA( "glRasterPos3d" ); - qglRasterPos3dv = dllRasterPos3dv = GPA( "glRasterPos3dv" ); - qglRasterPos3f = dllRasterPos3f = GPA( "glRasterPos3f" ); - qglRasterPos3fv = dllRasterPos3fv = GPA( "glRasterPos3fv" ); - qglRasterPos3i = dllRasterPos3i = GPA( "glRasterPos3i" ); - qglRasterPos3iv = dllRasterPos3iv = GPA( "glRasterPos3iv" ); - qglRasterPos3s = dllRasterPos3s = GPA( "glRasterPos3s" ); - qglRasterPos3sv = dllRasterPos3sv = GPA( "glRasterPos3sv" ); - qglRasterPos4d = dllRasterPos4d = GPA( "glRasterPos4d" ); - qglRasterPos4dv = dllRasterPos4dv = GPA( "glRasterPos4dv" ); - qglRasterPos4f = dllRasterPos4f = GPA( "glRasterPos4f" ); - qglRasterPos4fv = dllRasterPos4fv = GPA( "glRasterPos4fv" ); - qglRasterPos4i = dllRasterPos4i = GPA( "glRasterPos4i" ); - qglRasterPos4iv = dllRasterPos4iv = GPA( "glRasterPos4iv" ); - qglRasterPos4s = dllRasterPos4s = GPA( "glRasterPos4s" ); - qglRasterPos4sv = dllRasterPos4sv = GPA( "glRasterPos4sv" ); - qglReadBuffer = dllReadBuffer = GPA( "glReadBuffer" ); - qglReadPixels = dllReadPixels = GPA( "glReadPixels" ); - qglRectd = dllRectd = GPA( "glRectd" ); - qglRectdv = dllRectdv = GPA( "glRectdv" ); - qglRectf = dllRectf = GPA( "glRectf" ); - qglRectfv = dllRectfv = GPA( "glRectfv" ); - qglRecti = dllRecti = GPA( "glRecti" ); - qglRectiv = dllRectiv = GPA( "glRectiv" ); - qglRects = dllRects = GPA( "glRects" ); - qglRectsv = dllRectsv = GPA( "glRectsv" ); - qglRenderMode = dllRenderMode = GPA( "glRenderMode" ); - qglRotated = dllRotated = GPA( "glRotated" ); - qglRotatef = dllRotatef = GPA( "glRotatef" ); - qglScaled = dllScaled = GPA( "glScaled" ); - qglScalef = dllScalef = GPA( "glScalef" ); - qglScissor = dllScissor = GPA( "glScissor" ); - qglSelectBuffer = dllSelectBuffer = GPA( "glSelectBuffer" ); - qglShadeModel = dllShadeModel = GPA( "glShadeModel" ); - qglStencilFunc = dllStencilFunc = GPA( "glStencilFunc" ); - qglStencilMask = dllStencilMask = GPA( "glStencilMask" ); - qglStencilOp = dllStencilOp = GPA( "glStencilOp" ); - qglTexCoord1d = dllTexCoord1d = GPA( "glTexCoord1d" ); - qglTexCoord1dv = dllTexCoord1dv = GPA( "glTexCoord1dv" ); - qglTexCoord1f = dllTexCoord1f = GPA( "glTexCoord1f" ); - qglTexCoord1fv = dllTexCoord1fv = GPA( "glTexCoord1fv" ); - qglTexCoord1i = dllTexCoord1i = GPA( "glTexCoord1i" ); - qglTexCoord1iv = dllTexCoord1iv = GPA( "glTexCoord1iv" ); - qglTexCoord1s = dllTexCoord1s = GPA( "glTexCoord1s" ); - qglTexCoord1sv = dllTexCoord1sv = GPA( "glTexCoord1sv" ); - qglTexCoord2d = dllTexCoord2d = GPA( "glTexCoord2d" ); - qglTexCoord2dv = dllTexCoord2dv = GPA( "glTexCoord2dv" ); - qglTexCoord2f = dllTexCoord2f = GPA( "glTexCoord2f" ); - qglTexCoord2fv = dllTexCoord2fv = GPA( "glTexCoord2fv" ); - qglTexCoord2i = dllTexCoord2i = GPA( "glTexCoord2i" ); - qglTexCoord2iv = dllTexCoord2iv = GPA( "glTexCoord2iv" ); - qglTexCoord2s = dllTexCoord2s = GPA( "glTexCoord2s" ); - qglTexCoord2sv = dllTexCoord2sv = GPA( "glTexCoord2sv" ); - qglTexCoord3d = dllTexCoord3d = GPA( "glTexCoord3d" ); - qglTexCoord3dv = dllTexCoord3dv = GPA( "glTexCoord3dv" ); - qglTexCoord3f = dllTexCoord3f = GPA( "glTexCoord3f" ); - qglTexCoord3fv = dllTexCoord3fv = GPA( "glTexCoord3fv" ); - qglTexCoord3i = dllTexCoord3i = GPA( "glTexCoord3i" ); - qglTexCoord3iv = dllTexCoord3iv = GPA( "glTexCoord3iv" ); - qglTexCoord3s = dllTexCoord3s = GPA( "glTexCoord3s" ); - qglTexCoord3sv = dllTexCoord3sv = GPA( "glTexCoord3sv" ); - qglTexCoord4d = dllTexCoord4d = GPA( "glTexCoord4d" ); - qglTexCoord4dv = dllTexCoord4dv = GPA( "glTexCoord4dv" ); - qglTexCoord4f = dllTexCoord4f = GPA( "glTexCoord4f" ); - qglTexCoord4fv = dllTexCoord4fv = GPA( "glTexCoord4fv" ); - qglTexCoord4i = dllTexCoord4i = GPA( "glTexCoord4i" ); - qglTexCoord4iv = dllTexCoord4iv = GPA( "glTexCoord4iv" ); - qglTexCoord4s = dllTexCoord4s = GPA( "glTexCoord4s" ); - qglTexCoord4sv = dllTexCoord4sv = GPA( "glTexCoord4sv" ); - qglTexCoordPointer = dllTexCoordPointer = GPA( "glTexCoordPointer" ); - qglTexEnvf = dllTexEnvf = GPA( "glTexEnvf" ); - qglTexEnvfv = dllTexEnvfv = GPA( "glTexEnvfv" ); - qglTexEnvi = dllTexEnvi = GPA( "glTexEnvi" ); - qglTexEnviv = dllTexEnviv = GPA( "glTexEnviv" ); - qglTexGend = dllTexGend = GPA( "glTexGend" ); - qglTexGendv = dllTexGendv = GPA( "glTexGendv" ); - qglTexGenf = dllTexGenf = GPA( "glTexGenf" ); - qglTexGenfv = dllTexGenfv = GPA( "glTexGenfv" ); - qglTexGeni = dllTexGeni = GPA( "glTexGeni" ); - qglTexGeniv = dllTexGeniv = GPA( "glTexGeniv" ); - qglTexImage1D = dllTexImage1D = GPA( "glTexImage1D" ); - qglTexImage2D = dllTexImage2D = GPA( "glTexImage2D" ); - qglTexParameterf = dllTexParameterf = GPA( "glTexParameterf" ); - qglTexParameterfv = dllTexParameterfv = GPA( "glTexParameterfv" ); - qglTexParameteri = dllTexParameteri = GPA( "glTexParameteri" ); - qglTexParameteriv = dllTexParameteriv = GPA( "glTexParameteriv" ); - qglTexSubImage1D = dllTexSubImage1D = GPA( "glTexSubImage1D" ); - qglTexSubImage2D = dllTexSubImage2D = GPA( "glTexSubImage2D" ); - qglTranslated = dllTranslated = GPA( "glTranslated" ); - qglTranslatef = dllTranslatef = GPA( "glTranslatef" ); - qglVertex2d = dllVertex2d = GPA( "glVertex2d" ); - qglVertex2dv = dllVertex2dv = GPA( "glVertex2dv" ); - qglVertex2f = dllVertex2f = GPA( "glVertex2f" ); - qglVertex2fv = dllVertex2fv = GPA( "glVertex2fv" ); - qglVertex2i = dllVertex2i = GPA( "glVertex2i" ); - qglVertex2iv = dllVertex2iv = GPA( "glVertex2iv" ); - qglVertex2s = dllVertex2s = GPA( "glVertex2s" ); - qglVertex2sv = dllVertex2sv = GPA( "glVertex2sv" ); - qglVertex3d = dllVertex3d = GPA( "glVertex3d" ); - qglVertex3dv = dllVertex3dv = GPA( "glVertex3dv" ); - qglVertex3f = dllVertex3f = GPA( "glVertex3f" ); - qglVertex3fv = dllVertex3fv = GPA( "glVertex3fv" ); - qglVertex3i = dllVertex3i = GPA( "glVertex3i" ); - qglVertex3iv = dllVertex3iv = GPA( "glVertex3iv" ); - qglVertex3s = dllVertex3s = GPA( "glVertex3s" ); - qglVertex3sv = dllVertex3sv = GPA( "glVertex3sv" ); - qglVertex4d = dllVertex4d = GPA( "glVertex4d" ); - qglVertex4dv = dllVertex4dv = GPA( "glVertex4dv" ); - qglVertex4f = dllVertex4f = GPA( "glVertex4f" ); - qglVertex4fv = dllVertex4fv = GPA( "glVertex4fv" ); - qglVertex4i = dllVertex4i = GPA( "glVertex4i" ); - qglVertex4iv = dllVertex4iv = GPA( "glVertex4iv" ); - qglVertex4s = dllVertex4s = GPA( "glVertex4s" ); - qglVertex4sv = dllVertex4sv = GPA( "glVertex4sv" ); - qglVertexPointer = dllVertexPointer = GPA( "glVertexPointer" ); - qglViewport = dllViewport = GPA( "glViewport" ); - - qwglCopyContext = GPA( "wglCopyContext" ); - qwglCreateContext = GPA( "wglCreateContext" ); - qwglCreateLayerContext = GPA( "wglCreateLayerContext" ); - qwglDeleteContext = GPA( "wglDeleteContext" ); - qwglDescribeLayerPlane = GPA( "wglDescribeLayerPlane" ); - qwglGetCurrentContext = GPA( "wglGetCurrentContext" ); - qwglGetCurrentDC = GPA( "wglGetCurrentDC" ); - qwglGetLayerPaletteEntries = GPA( "wglGetLayerPaletteEntries" ); - qwglGetProcAddress = GPA( "wglGetProcAddress" ); - qwglMakeCurrent = GPA( "wglMakeCurrent" ); - qwglRealizeLayerPalette = GPA( "wglRealizeLayerPalette" ); - qwglSetLayerPaletteEntries = GPA( "wglSetLayerPaletteEntries" ); - qwglShareLists = GPA( "wglShareLists" ); - qwglSwapLayerBuffers = GPA( "wglSwapLayerBuffers" ); - qwglUseFontBitmaps = GPA( "wglUseFontBitmapsA" ); - qwglUseFontOutlines = GPA( "wglUseFontOutlinesA" ); - - qwglChoosePixelFormat = GPA( "wglChoosePixelFormat" ); - qwglDescribePixelFormat = GPA( "wglDescribePixelFormat" ); - qwglGetPixelFormat = GPA( "wglGetPixelFormat" ); - qwglSetPixelFormat = GPA( "wglSetPixelFormat" ); - qwglSwapBuffers = GPA( "wglSwapBuffers" ); - - qwglSwapIntervalEXT = 0; - qglActiveTextureARB = 0; - qglClientActiveTextureARB = 0; - qglMultiTexCoord2fARB = 0; - qglLockArraysEXT = 0; - qglUnlockArraysEXT = 0; - qwglGetDeviceGammaRamp3DFX = NULL; - qwglSetDeviceGammaRamp3DFX = NULL; - - // check logging - QGL_EnableLogging( r_logFile->integer ); - - return qtrue; -} - -void QGL_EnableLogging( qboolean enable ) -{ - static qboolean isEnabled; - - // return if we're already active - if ( isEnabled && enable ) { - // decrement log counter and stop if it has reached 0 - ri.Cvar_Set( "r_logFile", va("%d", r_logFile->integer - 1 ) ); - if ( r_logFile->integer ) { - return; - } - enable = qfalse; - } - - // return if we're already disabled - if ( !enable && !isEnabled ) - return; - - isEnabled = enable; - - if ( enable ) - { - if ( !glw_state.log_fp ) - { - struct tm *newtime; - time_t aclock; - char buffer[1024]; - cvar_t *basedir; - - time( &aclock ); - newtime = localtime( &aclock ); - - asctime( newtime ); - - basedir = ri.Cvar_Get( "fs_basepath", "", 0 ); - Com_sprintf( buffer, sizeof(buffer), "%s/gl.log", basedir->string ); - glw_state.log_fp = fopen( buffer, "wt" ); - - fprintf( glw_state.log_fp, "%s\n", asctime( newtime ) ); - } - - qglAccum = logAccum; - qglAlphaFunc = logAlphaFunc; - qglAreTexturesResident = logAreTexturesResident; - qglArrayElement = logArrayElement; - qglBegin = logBegin; - qglBindTexture = logBindTexture; - qglBitmap = logBitmap; - qglBlendFunc = logBlendFunc; - qglCallList = logCallList; - qglCallLists = logCallLists; - qglClear = logClear; - qglClearAccum = logClearAccum; - qglClearColor = logClearColor; - qglClearDepth = logClearDepth; - qglClearIndex = logClearIndex; - qglClearStencil = logClearStencil; - qglClipPlane = logClipPlane; - qglColor3b = logColor3b; - qglColor3bv = logColor3bv; - qglColor3d = logColor3d; - qglColor3dv = logColor3dv; - qglColor3f = logColor3f; - qglColor3fv = logColor3fv; - qglColor3i = logColor3i; - qglColor3iv = logColor3iv; - qglColor3s = logColor3s; - qglColor3sv = logColor3sv; - qglColor3ub = logColor3ub; - qglColor3ubv = logColor3ubv; - qglColor3ui = logColor3ui; - qglColor3uiv = logColor3uiv; - qglColor3us = logColor3us; - qglColor3usv = logColor3usv; - qglColor4b = logColor4b; - qglColor4bv = logColor4bv; - qglColor4d = logColor4d; - qglColor4dv = logColor4dv; - qglColor4f = logColor4f; - qglColor4fv = logColor4fv; - qglColor4i = logColor4i; - qglColor4iv = logColor4iv; - qglColor4s = logColor4s; - qglColor4sv = logColor4sv; - qglColor4ub = logColor4ub; - qglColor4ubv = logColor4ubv; - qglColor4ui = logColor4ui; - qglColor4uiv = logColor4uiv; - qglColor4us = logColor4us; - qglColor4usv = logColor4usv; - qglColorMask = logColorMask; - qglColorMaterial = logColorMaterial; - qglColorPointer = logColorPointer; - qglCopyPixels = logCopyPixels; - qglCopyTexImage1D = logCopyTexImage1D; - qglCopyTexImage2D = logCopyTexImage2D; - qglCopyTexSubImage1D = logCopyTexSubImage1D; - qglCopyTexSubImage2D = logCopyTexSubImage2D; - qglCullFace = logCullFace; - qglDeleteLists = logDeleteLists ; - qglDeleteTextures = logDeleteTextures ; - qglDepthFunc = logDepthFunc ; - qglDepthMask = logDepthMask ; - qglDepthRange = logDepthRange ; - qglDisable = logDisable ; - qglDisableClientState = logDisableClientState ; - qglDrawArrays = logDrawArrays ; - qglDrawBuffer = logDrawBuffer ; - qglDrawElements = logDrawElements ; - qglDrawPixels = logDrawPixels ; - qglEdgeFlag = logEdgeFlag ; - qglEdgeFlagPointer = logEdgeFlagPointer ; - qglEdgeFlagv = logEdgeFlagv ; - qglEnable = logEnable ; - qglEnableClientState = logEnableClientState ; - qglEnd = logEnd ; - qglEndList = logEndList ; - qglEvalCoord1d = logEvalCoord1d ; - qglEvalCoord1dv = logEvalCoord1dv ; - qglEvalCoord1f = logEvalCoord1f ; - qglEvalCoord1fv = logEvalCoord1fv ; - qglEvalCoord2d = logEvalCoord2d ; - qglEvalCoord2dv = logEvalCoord2dv ; - qglEvalCoord2f = logEvalCoord2f ; - qglEvalCoord2fv = logEvalCoord2fv ; - qglEvalMesh1 = logEvalMesh1 ; - qglEvalMesh2 = logEvalMesh2 ; - qglEvalPoint1 = logEvalPoint1 ; - qglEvalPoint2 = logEvalPoint2 ; - qglFeedbackBuffer = logFeedbackBuffer ; - qglFinish = logFinish ; - qglFlush = logFlush ; - qglFogf = logFogf ; - qglFogfv = logFogfv ; - qglFogi = logFogi ; - qglFogiv = logFogiv ; - qglFrontFace = logFrontFace ; - qglFrustum = logFrustum ; - qglGenLists = logGenLists ; - qglGenTextures = logGenTextures ; - qglGetBooleanv = logGetBooleanv ; - qglGetClipPlane = logGetClipPlane ; - qglGetDoublev = logGetDoublev ; - qglGetError = logGetError ; - qglGetFloatv = logGetFloatv ; - qglGetIntegerv = logGetIntegerv ; - qglGetLightfv = logGetLightfv ; - qglGetLightiv = logGetLightiv ; - qglGetMapdv = logGetMapdv ; - qglGetMapfv = logGetMapfv ; - qglGetMapiv = logGetMapiv ; - qglGetMaterialfv = logGetMaterialfv ; - qglGetMaterialiv = logGetMaterialiv ; - qglGetPixelMapfv = logGetPixelMapfv ; - qglGetPixelMapuiv = logGetPixelMapuiv ; - qglGetPixelMapusv = logGetPixelMapusv ; - qglGetPointerv = logGetPointerv ; - qglGetPolygonStipple = logGetPolygonStipple ; - qglGetString = logGetString ; - qglGetTexEnvfv = logGetTexEnvfv ; - qglGetTexEnviv = logGetTexEnviv ; - qglGetTexGendv = logGetTexGendv ; - qglGetTexGenfv = logGetTexGenfv ; - qglGetTexGeniv = logGetTexGeniv ; - qglGetTexImage = logGetTexImage ; - qglGetTexLevelParameterfv = logGetTexLevelParameterfv ; - qglGetTexLevelParameteriv = logGetTexLevelParameteriv ; - qglGetTexParameterfv = logGetTexParameterfv ; - qglGetTexParameteriv = logGetTexParameteriv ; - qglHint = logHint ; - qglIndexMask = logIndexMask ; - qglIndexPointer = logIndexPointer ; - qglIndexd = logIndexd ; - qglIndexdv = logIndexdv ; - qglIndexf = logIndexf ; - qglIndexfv = logIndexfv ; - qglIndexi = logIndexi ; - qglIndexiv = logIndexiv ; - qglIndexs = logIndexs ; - qglIndexsv = logIndexsv ; - qglIndexub = logIndexub ; - qglIndexubv = logIndexubv ; - qglInitNames = logInitNames ; - qglInterleavedArrays = logInterleavedArrays ; - qglIsEnabled = logIsEnabled ; - qglIsList = logIsList ; - qglIsTexture = logIsTexture ; - qglLightModelf = logLightModelf ; - qglLightModelfv = logLightModelfv ; - qglLightModeli = logLightModeli ; - qglLightModeliv = logLightModeliv ; - qglLightf = logLightf ; - qglLightfv = logLightfv ; - qglLighti = logLighti ; - qglLightiv = logLightiv ; - qglLineStipple = logLineStipple ; - qglLineWidth = logLineWidth ; - qglListBase = logListBase ; - qglLoadIdentity = logLoadIdentity ; - qglLoadMatrixd = logLoadMatrixd ; - qglLoadMatrixf = logLoadMatrixf ; - qglLoadName = logLoadName ; - qglLogicOp = logLogicOp ; - qglMap1d = logMap1d ; - qglMap1f = logMap1f ; - qglMap2d = logMap2d ; - qglMap2f = logMap2f ; - qglMapGrid1d = logMapGrid1d ; - qglMapGrid1f = logMapGrid1f ; - qglMapGrid2d = logMapGrid2d ; - qglMapGrid2f = logMapGrid2f ; - qglMaterialf = logMaterialf ; - qglMaterialfv = logMaterialfv ; - qglMateriali = logMateriali ; - qglMaterialiv = logMaterialiv ; - qglMatrixMode = logMatrixMode ; - qglMultMatrixd = logMultMatrixd ; - qglMultMatrixf = logMultMatrixf ; - qglNewList = logNewList ; - qglNormal3b = logNormal3b ; - qglNormal3bv = logNormal3bv ; - qglNormal3d = logNormal3d ; - qglNormal3dv = logNormal3dv ; - qglNormal3f = logNormal3f ; - qglNormal3fv = logNormal3fv ; - qglNormal3i = logNormal3i ; - qglNormal3iv = logNormal3iv ; - qglNormal3s = logNormal3s ; - qglNormal3sv = logNormal3sv ; - qglNormalPointer = logNormalPointer ; - qglOrtho = logOrtho ; - qglPassThrough = logPassThrough ; - qglPixelMapfv = logPixelMapfv ; - qglPixelMapuiv = logPixelMapuiv ; - qglPixelMapusv = logPixelMapusv ; - qglPixelStoref = logPixelStoref ; - qglPixelStorei = logPixelStorei ; - qglPixelTransferf = logPixelTransferf ; - qglPixelTransferi = logPixelTransferi ; - qglPixelZoom = logPixelZoom ; - qglPointSize = logPointSize ; - qglPolygonMode = logPolygonMode ; - qglPolygonOffset = logPolygonOffset ; - qglPolygonStipple = logPolygonStipple ; - qglPopAttrib = logPopAttrib ; - qglPopClientAttrib = logPopClientAttrib ; - qglPopMatrix = logPopMatrix ; - qglPopName = logPopName ; - qglPrioritizeTextures = logPrioritizeTextures ; - qglPushAttrib = logPushAttrib ; - qglPushClientAttrib = logPushClientAttrib ; - qglPushMatrix = logPushMatrix ; - qglPushName = logPushName ; - qglRasterPos2d = logRasterPos2d ; - qglRasterPos2dv = logRasterPos2dv ; - qglRasterPos2f = logRasterPos2f ; - qglRasterPos2fv = logRasterPos2fv ; - qglRasterPos2i = logRasterPos2i ; - qglRasterPos2iv = logRasterPos2iv ; - qglRasterPos2s = logRasterPos2s ; - qglRasterPos2sv = logRasterPos2sv ; - qglRasterPos3d = logRasterPos3d ; - qglRasterPos3dv = logRasterPos3dv ; - qglRasterPos3f = logRasterPos3f ; - qglRasterPos3fv = logRasterPos3fv ; - qglRasterPos3i = logRasterPos3i ; - qglRasterPos3iv = logRasterPos3iv ; - qglRasterPos3s = logRasterPos3s ; - qglRasterPos3sv = logRasterPos3sv ; - qglRasterPos4d = logRasterPos4d ; - qglRasterPos4dv = logRasterPos4dv ; - qglRasterPos4f = logRasterPos4f ; - qglRasterPos4fv = logRasterPos4fv ; - qglRasterPos4i = logRasterPos4i ; - qglRasterPos4iv = logRasterPos4iv ; - qglRasterPos4s = logRasterPos4s ; - qglRasterPos4sv = logRasterPos4sv ; - qglReadBuffer = logReadBuffer ; - qglReadPixels = logReadPixels ; - qglRectd = logRectd ; - qglRectdv = logRectdv ; - qglRectf = logRectf ; - qglRectfv = logRectfv ; - qglRecti = logRecti ; - qglRectiv = logRectiv ; - qglRects = logRects ; - qglRectsv = logRectsv ; - qglRenderMode = logRenderMode ; - qglRotated = logRotated ; - qglRotatef = logRotatef ; - qglScaled = logScaled ; - qglScalef = logScalef ; - qglScissor = logScissor ; - qglSelectBuffer = logSelectBuffer ; - qglShadeModel = logShadeModel ; - qglStencilFunc = logStencilFunc ; - qglStencilMask = logStencilMask ; - qglStencilOp = logStencilOp ; - qglTexCoord1d = logTexCoord1d ; - qglTexCoord1dv = logTexCoord1dv ; - qglTexCoord1f = logTexCoord1f ; - qglTexCoord1fv = logTexCoord1fv ; - qglTexCoord1i = logTexCoord1i ; - qglTexCoord1iv = logTexCoord1iv ; - qglTexCoord1s = logTexCoord1s ; - qglTexCoord1sv = logTexCoord1sv ; - qglTexCoord2d = logTexCoord2d ; - qglTexCoord2dv = logTexCoord2dv ; - qglTexCoord2f = logTexCoord2f ; - qglTexCoord2fv = logTexCoord2fv ; - qglTexCoord2i = logTexCoord2i ; - qglTexCoord2iv = logTexCoord2iv ; - qglTexCoord2s = logTexCoord2s ; - qglTexCoord2sv = logTexCoord2sv ; - qglTexCoord3d = logTexCoord3d ; - qglTexCoord3dv = logTexCoord3dv ; - qglTexCoord3f = logTexCoord3f ; - qglTexCoord3fv = logTexCoord3fv ; - qglTexCoord3i = logTexCoord3i ; - qglTexCoord3iv = logTexCoord3iv ; - qglTexCoord3s = logTexCoord3s ; - qglTexCoord3sv = logTexCoord3sv ; - qglTexCoord4d = logTexCoord4d ; - qglTexCoord4dv = logTexCoord4dv ; - qglTexCoord4f = logTexCoord4f ; - qglTexCoord4fv = logTexCoord4fv ; - qglTexCoord4i = logTexCoord4i ; - qglTexCoord4iv = logTexCoord4iv ; - qglTexCoord4s = logTexCoord4s ; - qglTexCoord4sv = logTexCoord4sv ; - qglTexCoordPointer = logTexCoordPointer ; - qglTexEnvf = logTexEnvf ; - qglTexEnvfv = logTexEnvfv ; - qglTexEnvi = logTexEnvi ; - qglTexEnviv = logTexEnviv ; - qglTexGend = logTexGend ; - qglTexGendv = logTexGendv ; - qglTexGenf = logTexGenf ; - qglTexGenfv = logTexGenfv ; - qglTexGeni = logTexGeni ; - qglTexGeniv = logTexGeniv ; - qglTexImage1D = logTexImage1D ; - qglTexImage2D = logTexImage2D ; - qglTexParameterf = logTexParameterf ; - qglTexParameterfv = logTexParameterfv ; - qglTexParameteri = logTexParameteri ; - qglTexParameteriv = logTexParameteriv ; - qglTexSubImage1D = logTexSubImage1D ; - qglTexSubImage2D = logTexSubImage2D ; - qglTranslated = logTranslated ; - qglTranslatef = logTranslatef ; - qglVertex2d = logVertex2d ; - qglVertex2dv = logVertex2dv ; - qglVertex2f = logVertex2f ; - qglVertex2fv = logVertex2fv ; - qglVertex2i = logVertex2i ; - qglVertex2iv = logVertex2iv ; - qglVertex2s = logVertex2s ; - qglVertex2sv = logVertex2sv ; - qglVertex3d = logVertex3d ; - qglVertex3dv = logVertex3dv ; - qglVertex3f = logVertex3f ; - qglVertex3fv = logVertex3fv ; - qglVertex3i = logVertex3i ; - qglVertex3iv = logVertex3iv ; - qglVertex3s = logVertex3s ; - qglVertex3sv = logVertex3sv ; - qglVertex4d = logVertex4d ; - qglVertex4dv = logVertex4dv ; - qglVertex4f = logVertex4f ; - qglVertex4fv = logVertex4fv ; - qglVertex4i = logVertex4i ; - qglVertex4iv = logVertex4iv ; - qglVertex4s = logVertex4s ; - qglVertex4sv = logVertex4sv ; - qglVertexPointer = logVertexPointer ; - qglViewport = logViewport ; - } - else - { - if ( glw_state.log_fp ) { - fprintf( glw_state.log_fp, "*** CLOSING LOG ***\n" ); - fclose( glw_state.log_fp ); - glw_state.log_fp = NULL; - } - qglAccum = dllAccum; - qglAlphaFunc = dllAlphaFunc; - qglAreTexturesResident = dllAreTexturesResident; - qglArrayElement = dllArrayElement; - qglBegin = dllBegin; - qglBindTexture = dllBindTexture; - qglBitmap = dllBitmap; - qglBlendFunc = dllBlendFunc; - qglCallList = dllCallList; - qglCallLists = dllCallLists; - qglClear = dllClear; - qglClearAccum = dllClearAccum; - qglClearColor = dllClearColor; - qglClearDepth = dllClearDepth; - qglClearIndex = dllClearIndex; - qglClearStencil = dllClearStencil; - qglClipPlane = dllClipPlane; - qglColor3b = dllColor3b; - qglColor3bv = dllColor3bv; - qglColor3d = dllColor3d; - qglColor3dv = dllColor3dv; - qglColor3f = dllColor3f; - qglColor3fv = dllColor3fv; - qglColor3i = dllColor3i; - qglColor3iv = dllColor3iv; - qglColor3s = dllColor3s; - qglColor3sv = dllColor3sv; - qglColor3ub = dllColor3ub; - qglColor3ubv = dllColor3ubv; - qglColor3ui = dllColor3ui; - qglColor3uiv = dllColor3uiv; - qglColor3us = dllColor3us; - qglColor3usv = dllColor3usv; - qglColor4b = dllColor4b; - qglColor4bv = dllColor4bv; - qglColor4d = dllColor4d; - qglColor4dv = dllColor4dv; - qglColor4f = dllColor4f; - qglColor4fv = dllColor4fv; - qglColor4i = dllColor4i; - qglColor4iv = dllColor4iv; - qglColor4s = dllColor4s; - qglColor4sv = dllColor4sv; - qglColor4ub = dllColor4ub; - qglColor4ubv = dllColor4ubv; - qglColor4ui = dllColor4ui; - qglColor4uiv = dllColor4uiv; - qglColor4us = dllColor4us; - qglColor4usv = dllColor4usv; - qglColorMask = dllColorMask; - qglColorMaterial = dllColorMaterial; - qglColorPointer = dllColorPointer; - qglCopyPixels = dllCopyPixels; - qglCopyTexImage1D = dllCopyTexImage1D; - qglCopyTexImage2D = dllCopyTexImage2D; - qglCopyTexSubImage1D = dllCopyTexSubImage1D; - qglCopyTexSubImage2D = dllCopyTexSubImage2D; - qglCullFace = dllCullFace; - qglDeleteLists = dllDeleteLists ; - qglDeleteTextures = dllDeleteTextures ; - qglDepthFunc = dllDepthFunc ; - qglDepthMask = dllDepthMask ; - qglDepthRange = dllDepthRange ; - qglDisable = dllDisable ; - qglDisableClientState = dllDisableClientState ; - qglDrawArrays = dllDrawArrays ; - qglDrawBuffer = dllDrawBuffer ; - qglDrawElements = dllDrawElements ; - qglDrawPixels = dllDrawPixels ; - qglEdgeFlag = dllEdgeFlag ; - qglEdgeFlagPointer = dllEdgeFlagPointer ; - qglEdgeFlagv = dllEdgeFlagv ; - qglEnable = dllEnable ; - qglEnableClientState = dllEnableClientState ; - qglEnd = dllEnd ; - qglEndList = dllEndList ; - qglEvalCoord1d = dllEvalCoord1d ; - qglEvalCoord1dv = dllEvalCoord1dv ; - qglEvalCoord1f = dllEvalCoord1f ; - qglEvalCoord1fv = dllEvalCoord1fv ; - qglEvalCoord2d = dllEvalCoord2d ; - qglEvalCoord2dv = dllEvalCoord2dv ; - qglEvalCoord2f = dllEvalCoord2f ; - qglEvalCoord2fv = dllEvalCoord2fv ; - qglEvalMesh1 = dllEvalMesh1 ; - qglEvalMesh2 = dllEvalMesh2 ; - qglEvalPoint1 = dllEvalPoint1 ; - qglEvalPoint2 = dllEvalPoint2 ; - qglFeedbackBuffer = dllFeedbackBuffer ; - qglFinish = dllFinish ; - qglFlush = dllFlush ; - qglFogf = dllFogf ; - qglFogfv = dllFogfv ; - qglFogi = dllFogi ; - qglFogiv = dllFogiv ; - qglFrontFace = dllFrontFace ; - qglFrustum = dllFrustum ; - qglGenLists = dllGenLists ; - qglGenTextures = dllGenTextures ; - qglGetBooleanv = dllGetBooleanv ; - qglGetClipPlane = dllGetClipPlane ; - qglGetDoublev = dllGetDoublev ; - qglGetError = dllGetError ; - qglGetFloatv = dllGetFloatv ; - qglGetIntegerv = dllGetIntegerv ; - qglGetLightfv = dllGetLightfv ; - qglGetLightiv = dllGetLightiv ; - qglGetMapdv = dllGetMapdv ; - qglGetMapfv = dllGetMapfv ; - qglGetMapiv = dllGetMapiv ; - qglGetMaterialfv = dllGetMaterialfv ; - qglGetMaterialiv = dllGetMaterialiv ; - qglGetPixelMapfv = dllGetPixelMapfv ; - qglGetPixelMapuiv = dllGetPixelMapuiv ; - qglGetPixelMapusv = dllGetPixelMapusv ; - qglGetPointerv = dllGetPointerv ; - qglGetPolygonStipple = dllGetPolygonStipple ; - qglGetString = dllGetString ; - qglGetTexEnvfv = dllGetTexEnvfv ; - qglGetTexEnviv = dllGetTexEnviv ; - qglGetTexGendv = dllGetTexGendv ; - qglGetTexGenfv = dllGetTexGenfv ; - qglGetTexGeniv = dllGetTexGeniv ; - qglGetTexImage = dllGetTexImage ; - qglGetTexLevelParameterfv = dllGetTexLevelParameterfv ; - qglGetTexLevelParameteriv = dllGetTexLevelParameteriv ; - qglGetTexParameterfv = dllGetTexParameterfv ; - qglGetTexParameteriv = dllGetTexParameteriv ; - qglHint = dllHint ; - qglIndexMask = dllIndexMask ; - qglIndexPointer = dllIndexPointer ; - qglIndexd = dllIndexd ; - qglIndexdv = dllIndexdv ; - qglIndexf = dllIndexf ; - qglIndexfv = dllIndexfv ; - qglIndexi = dllIndexi ; - qglIndexiv = dllIndexiv ; - qglIndexs = dllIndexs ; - qglIndexsv = dllIndexsv ; - qglIndexub = dllIndexub ; - qglIndexubv = dllIndexubv ; - qglInitNames = dllInitNames ; - qglInterleavedArrays = dllInterleavedArrays ; - qglIsEnabled = dllIsEnabled ; - qglIsList = dllIsList ; - qglIsTexture = dllIsTexture ; - qglLightModelf = dllLightModelf ; - qglLightModelfv = dllLightModelfv ; - qglLightModeli = dllLightModeli ; - qglLightModeliv = dllLightModeliv ; - qglLightf = dllLightf ; - qglLightfv = dllLightfv ; - qglLighti = dllLighti ; - qglLightiv = dllLightiv ; - qglLineStipple = dllLineStipple ; - qglLineWidth = dllLineWidth ; - qglListBase = dllListBase ; - qglLoadIdentity = dllLoadIdentity ; - qglLoadMatrixd = dllLoadMatrixd ; - qglLoadMatrixf = dllLoadMatrixf ; - qglLoadName = dllLoadName ; - qglLogicOp = dllLogicOp ; - qglMap1d = dllMap1d ; - qglMap1f = dllMap1f ; - qglMap2d = dllMap2d ; - qglMap2f = dllMap2f ; - qglMapGrid1d = dllMapGrid1d ; - qglMapGrid1f = dllMapGrid1f ; - qglMapGrid2d = dllMapGrid2d ; - qglMapGrid2f = dllMapGrid2f ; - qglMaterialf = dllMaterialf ; - qglMaterialfv = dllMaterialfv ; - qglMateriali = dllMateriali ; - qglMaterialiv = dllMaterialiv ; - qglMatrixMode = dllMatrixMode ; - qglMultMatrixd = dllMultMatrixd ; - qglMultMatrixf = dllMultMatrixf ; - qglNewList = dllNewList ; - qglNormal3b = dllNormal3b ; - qglNormal3bv = dllNormal3bv ; - qglNormal3d = dllNormal3d ; - qglNormal3dv = dllNormal3dv ; - qglNormal3f = dllNormal3f ; - qglNormal3fv = dllNormal3fv ; - qglNormal3i = dllNormal3i ; - qglNormal3iv = dllNormal3iv ; - qglNormal3s = dllNormal3s ; - qglNormal3sv = dllNormal3sv ; - qglNormalPointer = dllNormalPointer ; - qglOrtho = dllOrtho ; - qglPassThrough = dllPassThrough ; - qglPixelMapfv = dllPixelMapfv ; - qglPixelMapuiv = dllPixelMapuiv ; - qglPixelMapusv = dllPixelMapusv ; - qglPixelStoref = dllPixelStoref ; - qglPixelStorei = dllPixelStorei ; - qglPixelTransferf = dllPixelTransferf ; - qglPixelTransferi = dllPixelTransferi ; - qglPixelZoom = dllPixelZoom ; - qglPointSize = dllPointSize ; - qglPolygonMode = dllPolygonMode ; - qglPolygonOffset = dllPolygonOffset ; - qglPolygonStipple = dllPolygonStipple ; - qglPopAttrib = dllPopAttrib ; - qglPopClientAttrib = dllPopClientAttrib ; - qglPopMatrix = dllPopMatrix ; - qglPopName = dllPopName ; - qglPrioritizeTextures = dllPrioritizeTextures ; - qglPushAttrib = dllPushAttrib ; - qglPushClientAttrib = dllPushClientAttrib ; - qglPushMatrix = dllPushMatrix ; - qglPushName = dllPushName ; - qglRasterPos2d = dllRasterPos2d ; - qglRasterPos2dv = dllRasterPos2dv ; - qglRasterPos2f = dllRasterPos2f ; - qglRasterPos2fv = dllRasterPos2fv ; - qglRasterPos2i = dllRasterPos2i ; - qglRasterPos2iv = dllRasterPos2iv ; - qglRasterPos2s = dllRasterPos2s ; - qglRasterPos2sv = dllRasterPos2sv ; - qglRasterPos3d = dllRasterPos3d ; - qglRasterPos3dv = dllRasterPos3dv ; - qglRasterPos3f = dllRasterPos3f ; - qglRasterPos3fv = dllRasterPos3fv ; - qglRasterPos3i = dllRasterPos3i ; - qglRasterPos3iv = dllRasterPos3iv ; - qglRasterPos3s = dllRasterPos3s ; - qglRasterPos3sv = dllRasterPos3sv ; - qglRasterPos4d = dllRasterPos4d ; - qglRasterPos4dv = dllRasterPos4dv ; - qglRasterPos4f = dllRasterPos4f ; - qglRasterPos4fv = dllRasterPos4fv ; - qglRasterPos4i = dllRasterPos4i ; - qglRasterPos4iv = dllRasterPos4iv ; - qglRasterPos4s = dllRasterPos4s ; - qglRasterPos4sv = dllRasterPos4sv ; - qglReadBuffer = dllReadBuffer ; - qglReadPixels = dllReadPixels ; - qglRectd = dllRectd ; - qglRectdv = dllRectdv ; - qglRectf = dllRectf ; - qglRectfv = dllRectfv ; - qglRecti = dllRecti ; - qglRectiv = dllRectiv ; - qglRects = dllRects ; - qglRectsv = dllRectsv ; - qglRenderMode = dllRenderMode ; - qglRotated = dllRotated ; - qglRotatef = dllRotatef ; - qglScaled = dllScaled ; - qglScalef = dllScalef ; - qglScissor = dllScissor ; - qglSelectBuffer = dllSelectBuffer ; - qglShadeModel = dllShadeModel ; - qglStencilFunc = dllStencilFunc ; - qglStencilMask = dllStencilMask ; - qglStencilOp = dllStencilOp ; - qglTexCoord1d = dllTexCoord1d ; - qglTexCoord1dv = dllTexCoord1dv ; - qglTexCoord1f = dllTexCoord1f ; - qglTexCoord1fv = dllTexCoord1fv ; - qglTexCoord1i = dllTexCoord1i ; - qglTexCoord1iv = dllTexCoord1iv ; - qglTexCoord1s = dllTexCoord1s ; - qglTexCoord1sv = dllTexCoord1sv ; - qglTexCoord2d = dllTexCoord2d ; - qglTexCoord2dv = dllTexCoord2dv ; - qglTexCoord2f = dllTexCoord2f ; - qglTexCoord2fv = dllTexCoord2fv ; - qglTexCoord2i = dllTexCoord2i ; - qglTexCoord2iv = dllTexCoord2iv ; - qglTexCoord2s = dllTexCoord2s ; - qglTexCoord2sv = dllTexCoord2sv ; - qglTexCoord3d = dllTexCoord3d ; - qglTexCoord3dv = dllTexCoord3dv ; - qglTexCoord3f = dllTexCoord3f ; - qglTexCoord3fv = dllTexCoord3fv ; - qglTexCoord3i = dllTexCoord3i ; - qglTexCoord3iv = dllTexCoord3iv ; - qglTexCoord3s = dllTexCoord3s ; - qglTexCoord3sv = dllTexCoord3sv ; - qglTexCoord4d = dllTexCoord4d ; - qglTexCoord4dv = dllTexCoord4dv ; - qglTexCoord4f = dllTexCoord4f ; - qglTexCoord4fv = dllTexCoord4fv ; - qglTexCoord4i = dllTexCoord4i ; - qglTexCoord4iv = dllTexCoord4iv ; - qglTexCoord4s = dllTexCoord4s ; - qglTexCoord4sv = dllTexCoord4sv ; - qglTexCoordPointer = dllTexCoordPointer ; - qglTexEnvf = dllTexEnvf ; - qglTexEnvfv = dllTexEnvfv ; - qglTexEnvi = dllTexEnvi ; - qglTexEnviv = dllTexEnviv ; - qglTexGend = dllTexGend ; - qglTexGendv = dllTexGendv ; - qglTexGenf = dllTexGenf ; - qglTexGenfv = dllTexGenfv ; - qglTexGeni = dllTexGeni ; - qglTexGeniv = dllTexGeniv ; - qglTexImage1D = dllTexImage1D ; - qglTexImage2D = dllTexImage2D ; - qglTexParameterf = dllTexParameterf ; - qglTexParameterfv = dllTexParameterfv ; - qglTexParameteri = dllTexParameteri ; - qglTexParameteriv = dllTexParameteriv ; - qglTexSubImage1D = dllTexSubImage1D ; - qglTexSubImage2D = dllTexSubImage2D ; - qglTranslated = dllTranslated ; - qglTranslatef = dllTranslatef ; - qglVertex2d = dllVertex2d ; - qglVertex2dv = dllVertex2dv ; - qglVertex2f = dllVertex2f ; - qglVertex2fv = dllVertex2fv ; - qglVertex2i = dllVertex2i ; - qglVertex2iv = dllVertex2iv ; - qglVertex2s = dllVertex2s ; - qglVertex2sv = dllVertex2sv ; - qglVertex3d = dllVertex3d ; - qglVertex3dv = dllVertex3dv ; - qglVertex3f = dllVertex3f ; - qglVertex3fv = dllVertex3fv ; - qglVertex3i = dllVertex3i ; - qglVertex3iv = dllVertex3iv ; - qglVertex3s = dllVertex3s ; - qglVertex3sv = dllVertex3sv ; - qglVertex4d = dllVertex4d ; - qglVertex4dv = dllVertex4dv ; - qglVertex4f = dllVertex4f ; - qglVertex4fv = dllVertex4fv ; - qglVertex4i = dllVertex4i ; - qglVertex4iv = dllVertex4iv ; - qglVertex4s = dllVertex4s ; - qglVertex4sv = dllVertex4sv ; - qglVertexPointer = dllVertexPointer ; - qglViewport = dllViewport ; - } -} - -#pragma warning (default : 4113 4133 4047 ) - - - diff --git a/code/win32/win_resource.h b/code/win32/win_resource.h deleted file mode 100644 index 93c517ea..00000000 --- a/code/win32/win_resource.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by winquake.rc -// -#define IDS_STRING1 1 -#define IDI_ICON1 1 -#define IDB_BITMAP1 1 -#define IDB_BITMAP2 128 -#define IDC_CURSOR1 129 -#define IDC_CURSOR2 130 -#define IDC_CURSOR3 131 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 132 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1005 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/code/win32/win_resource.rc b/code/win32/win_resource.rc deleted file mode 100644 index 455a6d7d..00000000 --- a/code/win32/win_resource.rc +++ /dev/null @@ -1,82 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "win_resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -#ifndef __MINGW32__ -IDI_ICON1 ICON DISCARDABLE "../../misc/openmohaa.ico" -#else -IDI_ICON1 ICON DISCARDABLE "misc/openmohaa.ico" -#endif - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_STRING1 "OpenMoHAA" -END - -///////////////////////////////////////////////////////////////////////////// -// -// Application Manifest -// -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "win_manifest.xml" - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - diff --git a/code/win32/win_shared.c b/code/win32/win_shared.c deleted file mode 100644 index 33790a71..00000000 --- a/code/win32/win_shared.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "../qcommon/q_shared.h" -#include "../qcommon/qcommon.h" -#include "win_local.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* -================ -Sys_Milliseconds -================ -*/ -int sys_timeBase; -int Sys_Milliseconds (void) -{ - int sys_curtime; - static qboolean initialized = qfalse; - - if (!initialized) { - sys_timeBase = timeGetTime(); - initialized = qtrue; - } - sys_curtime = timeGetTime() - sys_timeBase; - - return sys_curtime; -} - -/* -** -** Disable all optimizations temporarily so this code works correctly! -** -*/ -#pragma optimize( "", off ) - -/* -** -------------------------------------------------------------------------------- -** -** PROCESSOR STUFF -** -** -------------------------------------------------------------------------------- -*/ -static void CPUID( int func, unsigned regs[4] ) -{ - __cpuid(regs, func); - /* - unsigned regEAX, regEBX, regECX, regEDX; - -#ifndef __VECTORC - __asm mov eax, func - __asm __emit 00fh - __asm __emit 0a2h - __asm mov regEAX, eax - __asm mov regEBX, ebx - __asm mov regECX, ecx - __asm mov regEDX, edx - - regs[0] = regEAX; - regs[1] = regEBX; - regs[2] = regECX; - regs[3] = regEDX; -#else - regs[0] = 0; - regs[1] = 0; - regs[2] = 0; - regs[3] = 0; -#endif -*/ -} - -static int IsPentium( void ) -{ -#ifndef _WIN64 - __asm - { - pushfd // save eflags - pop eax - test eax, 0x00200000 // check ID bit - jz set21 // bit 21 is not set, so jump to set_21 - and eax, 0xffdfffff // clear bit 21 - push eax // save new value in register - popfd // store new value in flags - pushfd - pop eax - test eax, 0x00200000 // check ID bit - jz good - jmp err // cpuid not supported -set21: - or eax, 0x00200000 // set ID bit - push eax // store new value - popfd // store new value in EFLAGS - pushfd - pop eax - test eax, 0x00200000 // if bit 21 is on - jnz good - jmp err - } - -err: - return qfalse; -good: - return qtrue; -#else - return qtrue; -#endif -} - -static int Is3DNOW( void ) -{ - unsigned regs[4]; - char pstring[16]; - char processorString[13]; - - // get name of processor - CPUID( 0, ( unsigned int * ) pstring ); - processorString[0] = pstring[4]; - processorString[1] = pstring[5]; - processorString[2] = pstring[6]; - processorString[3] = pstring[7]; - processorString[4] = pstring[12]; - processorString[5] = pstring[13]; - processorString[6] = pstring[14]; - processorString[7] = pstring[15]; - processorString[8] = pstring[8]; - processorString[9] = pstring[9]; - processorString[10] = pstring[10]; - processorString[11] = pstring[11]; - processorString[12] = 0; - -// REMOVED because you can have 3DNow! on non-AMD systems -// if ( strcmp( processorString, "AuthenticAMD" ) ) -// return qfalse; - - // check AMD-specific functions - CPUID( 0x80000000, regs ); - if ( regs[0] < 0x80000000 ) - return qfalse; - - // bit 31 of EDX denotes 3DNOW! support - CPUID( 0x80000001, regs ); - if ( regs[3] & ( 1 << 31 ) ) - return qtrue; - - return qfalse; -} - -static int IsKNI( void ) -{ - unsigned regs[4]; - - // get CPU feature bits - CPUID( 1, regs ); - - // bit 25 of EDX denotes KNI existence - if ( regs[3] & ( 1 << 25 ) ) - return qtrue; - - return qfalse; -} - -static int IsMMX( void ) -{ - unsigned regs[4]; - - // get CPU feature bits - CPUID( 1, regs ); - - // bit 23 of EDX denotes MMX existence - if ( regs[3] & ( 1 << 23 ) ) - return qtrue; - return qfalse; -} - -int Sys_GetProcessorId( void ) -{ -#if defined _M_ALPHA - return CPUID_AXP; -#elif !defined _M_IX86 - return CPUID_GENERIC; -#else - - // verify we're at least a Pentium or 486 w/ CPUID support - if ( !IsPentium() ) - return CPUID_INTEL_UNSUPPORTED; - - // check for MMX - if ( !IsMMX() ) - { - // Pentium or PPro - return CPUID_INTEL_PENTIUM; - } - - // see if we're an AMD 3DNOW! processor - if ( Is3DNOW() ) - { - return CPUID_AMD_3DNOW; - } - - // see if we're an Intel Katmai - if ( IsKNI() ) - { - return CPUID_INTEL_KATMAI; - } - - // by default we're functionally a vanilla Pentium/MMX or P2/MMX - return CPUID_INTEL_MMX; - -#endif -} - -/* -** -** Re-enable optimizations back to what they were -** -*/ -#pragma optimize( "", on ) - -//============================================ - -char *Sys_GetCurrentUser( void ) -{ - static char s_userName[1024]; - unsigned long size = sizeof( s_userName ); - - - if ( !GetUserName( s_userName, &size ) ) - strcpy( s_userName, "player" ); - - if ( !s_userName[0] ) - { - strcpy( s_userName, "player" ); - } - - return s_userName; -} - -char *Sys_DefaultHomePath(void) { - return NULL; -} - -char *Sys_DefaultInstallPath(void) -{ - return Sys_Cwd(); -} - diff --git a/code/win32/win_snd.c b/code/win32/win_snd.c deleted file mode 100644 index 084ed444..00000000 --- a/code/win32/win_snd.c +++ /dev/null @@ -1,388 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include - -#include "../client/snd_local.h" -#include "win_local.h" - -HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter); -#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) - -#define SECONDARY_BUFFER_SIZE 0x10000 - - -static qboolean dsound_init; -static int sample16; -static DWORD gSndBufSize; -static DWORD locksize; -static LPDIRECTSOUND pDS; -static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; -static HINSTANCE hInstDS; - - -static const char *DSoundError( int error ) { - switch ( error ) { - case DSERR_BUFFERLOST: - return "DSERR_BUFFERLOST"; - case DSERR_INVALIDCALL: - return "DSERR_INVALIDCALLS"; - case DSERR_INVALIDPARAM: - return "DSERR_INVALIDPARAM"; - case DSERR_PRIOLEVELNEEDED: - return "DSERR_PRIOLEVELNEEDED"; - } - - return "unknown"; -} - -/* -================== -SNDDMA_Shutdown -================== -*/ -void SNDDMA_Shutdown( void ) { - Com_DPrintf( "Shutting down sound system\n" ); - - if ( pDS ) { - Com_DPrintf( "Destroying DS buffers\n" ); - if ( pDS ) - { - Com_DPrintf( "...setting NORMAL coop level\n" ); - pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ); - } - - if ( pDSBuf ) - { - Com_DPrintf( "...stopping and releasing sound buffer\n" ); - pDSBuf->lpVtbl->Stop( pDSBuf ); - pDSBuf->lpVtbl->Release( pDSBuf ); - } - - // only release primary buffer if it's not also the mixing buffer we just released - if ( pDSPBuf && ( pDSBuf != pDSPBuf ) ) - { - Com_DPrintf( "...releasing primary buffer\n" ); - pDSPBuf->lpVtbl->Release( pDSPBuf ); - } - pDSBuf = NULL; - pDSPBuf = NULL; - - dma.buffer = NULL; - - Com_DPrintf( "...releasing DS object\n" ); - pDS->lpVtbl->Release( pDS ); - } - - if ( hInstDS ) { - Com_DPrintf( "...freeing DSOUND.DLL\n" ); - FreeLibrary( hInstDS ); - hInstDS = NULL; - } - - pDS = NULL; - pDSBuf = NULL; - pDSPBuf = NULL; - dsound_init = qfalse; - memset ((void *)&dma, 0, sizeof (dma)); - CoUninitialize( ); -} - -/* -================== -SNDDMA_Init - -Initialize direct sound -Returns false if failed -================== -*/ -qboolean SNDDMA_Init(void) { - - memset ((void *)&dma, 0, sizeof (dma)); - dsound_init = 0; - - CoInitialize(NULL); - - if ( !SNDDMA_InitDS () ) { - return qfalse; - } - - dsound_init = qtrue; - - Com_DPrintf("Completed successfully\n" ); - - return qtrue; -} - -#undef DEFINE_GUID - -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - EXTERN_C const GUID name \ - = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } - -// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000} -DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); - -// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B} -DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b); - -DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66); -DEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); - - -int SNDDMA_InitDS () -{ - HRESULT hresult; - DSBUFFERDESC dsbuf; - DSBCAPS dsbcaps; - WAVEFORMATEX format; - int use8; - - Com_Printf( "Initializing DirectSound\n"); - - use8 = 1; - // Create IDirectSound using the primary sound device - if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8, (void **)&pDS))) { - use8 = 0; - if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&pDS))) { - Com_Printf ("failed\n"); - SNDDMA_Shutdown (); - return qfalse; - } - } - - hresult = pDS->lpVtbl->Initialize( pDS, NULL); - - Com_DPrintf( "ok\n" ); - - Com_DPrintf("...setting DSSCL_PRIORITY coop level: " ); - - if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ) ) { - Com_Printf ("failed\n"); - SNDDMA_Shutdown (); - return qfalse; - } - Com_DPrintf("ok\n" ); - - - // create the secondary buffer we'll actually work with - dma.channels = 2; - dma.samplebits = 16; - -// if (s_khz->integer == 44) -// dma.speed = 44100; -// else if (s_khz->integer == 22) -// dma.speed = 22050; -// else -// dma.speed = 11025; - - dma.speed = 22050; - memset (&format, 0, sizeof(format)); - format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = dma.channels; - format.wBitsPerSample = dma.samplebits; - format.nSamplesPerSec = dma.speed; - format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; - format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; - - memset (&dsbuf, 0, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - - // Micah: take advantage of 2D hardware.if available. - dsbuf.dwFlags = DSBCAPS_LOCHARDWARE; - if (use8) { - dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; - } - dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; - dsbuf.lpwfxFormat = &format; - - memset(&dsbcaps, 0, sizeof(dsbcaps)); - dsbcaps.dwSize = sizeof(dsbcaps); - - Com_DPrintf( "...creating secondary buffer: " ); - if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { - Com_Printf( "locked hardware. ok\n" ); - } - else { - // Couldn't get hardware, fallback to software. - dsbuf.dwFlags = DSBCAPS_LOCSOFTWARE; - if (use8) { - dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; - } - if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { - Com_Printf( "failed\n" ); - SNDDMA_Shutdown (); - return qfalse; - } - Com_DPrintf( "forced to software. ok\n" ); - } - - // Make sure mixer is active - if ( DS_OK != pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING) ) { - Com_Printf ("*** Looped sound play failed ***\n"); - SNDDMA_Shutdown (); - return qfalse; - } - - // get the returned buffer size - if ( DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps) ) { - Com_Printf ("*** GetCaps failed ***\n"); - SNDDMA_Shutdown (); - return qfalse; - } - - gSndBufSize = dsbcaps.dwBufferBytes; - - dma.channels = format.nChannels; - dma.samplebits = format.wBitsPerSample; - dma.speed = format.nSamplesPerSec; - dma.samples = gSndBufSize/(dma.samplebits/8); - dma.submission_chunk = 1; - dma.buffer = NULL; // must be locked first - - sample16 = (dma.samplebits/8) - 1; - - SNDDMA_BeginPainting (); - if (dma.buffer) - memset(dma.buffer, 0, dma.samples * dma.samplebits/8); - SNDDMA_Submit (); - return 1; -} -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos( void ) { - MMTIME mmtime; - int s; - DWORD dwWrite; - - if ( !dsound_init ) { - return 0; - } - - mmtime.wType = TIME_SAMPLES; - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); - - s = mmtime.u.sample; - - s >>= sample16; - - s &= (dma.samples-1); - - return s; -} - -/* -============== -SNDDMA_BeginPainting - -Makes sure dma.buffer is valid -=============== -*/ -void SNDDMA_BeginPainting( void ) { - int reps; - DWORD dwSize2; - DWORD *pbuf, *pbuf2; - HRESULT hresult; - DWORD dwStatus; - - if ( !pDSBuf ) { - return; - } - - // if the buffer was lost or stopped, restore it and/or restart it - if ( pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK ) { - Com_Printf ("Couldn't get sound buffer status\n"); - } - - if (dwStatus & DSBSTATUS_BUFFERLOST) - pDSBuf->lpVtbl->Restore (pDSBuf); - - if (!(dwStatus & DSBSTATUS_PLAYING)) - pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - - // lock the dsound buffer - - reps = 0; - dma.buffer = NULL; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &locksize, - &pbuf2, &dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Com_Printf( "SNDDMA_BeginPainting: Lock failed with error '%s'\n", DSoundError( hresult ) ); - S_Shutdown (); - return; - } - else - { - pDSBuf->lpVtbl->Restore( pDSBuf ); - } - - if (++reps > 2) - return; - } - dma.buffer = (unsigned char *)pbuf; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -Also unlocks the dsound buffer -=============== -*/ -void SNDDMA_Submit( void ) { - // unlock the dsound buffer - if ( pDSBuf ) { - pDSBuf->lpVtbl->Unlock(pDSBuf, dma.buffer, locksize, NULL, 0); - } -} - - -/* -================= -SNDDMA_Activate - -When we change windows we need to do this -================= -*/ -void SNDDMA_Activate( void ) { - if ( !pDS ) { - return; - } - - if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ) ) { - Com_Printf ("sound SetCooperativeLevel failed\n"); - SNDDMA_Shutdown (); - } -} - - diff --git a/code/win32/win_syscon.c b/code/win32/win_syscon.c deleted file mode 100644 index 0fd2162e..00000000 --- a/code/win32/win_syscon.c +++ /dev/null @@ -1,596 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// win_syscon.h -#include "../client/client.h" -#include "win_local.h" -#include "resource.h" -#include -#include -#include -#include -#include -#include -#include - -#define COPY_ID 1 -#define QUIT_ID 2 -#define CLEAR_ID 3 - -#define ERRORBOX_ID 10 -#define ERRORTEXT_ID 11 - -#define EDIT_ID 100 -#define INPUT_ID 101 - -typedef struct -{ - HWND hWnd; - HWND hwndBuffer; - - HWND hwndButtonClear; - HWND hwndButtonCopy; - HWND hwndButtonQuit; - - HWND hwndErrorBox; - HWND hwndErrorText; - - HBITMAP hbmLogo; - HBITMAP hbmClearBitmap; - - HBRUSH hbrEditBackground; - HBRUSH hbrErrorBackground; - - HFONT hfBufferFont; - HFONT hfButtonFont; - - HWND hwndInputLine; - - char errorString[80]; - - char consoleText[512], returnedText[512]; - int visLevel; - qboolean quitOnClose; - int windowWidth, windowHeight; - - WNDPROC SysInputLineWndProc; - -} WinConData; - -static WinConData s_wcd; - -static LRESULT WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - char *cmdString; - static qboolean s_timePolarity; - - switch (uMsg) - { - case WM_ACTIVATE: - if ( LOWORD( wParam ) != WA_INACTIVE ) - { - SetFocus( s_wcd.hwndInputLine ); - } - - if ( com_viewlog && ( com_dedicated && !com_dedicated->integer ) ) - { - // if the viewlog is open, check to see if it's being minimized - if ( com_viewlog->integer == 1 ) - { - if ( HIWORD( wParam ) ) // minimized flag - { - Cvar_Set( "viewlog", "2" ); - } - } - else if ( com_viewlog->integer == 2 ) - { - if ( !HIWORD( wParam ) ) // minimized flag - { - Cvar_Set( "viewlog", "1" ); - } - } - } - break; - - case WM_CLOSE: - if ( ( com_dedicated && com_dedicated->integer ) ) - { - cmdString = CopyString( "quit" ); - Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString ); - } - else if ( s_wcd.quitOnClose ) - { - PostQuitMessage( 0 ); - } - else - { - Sys_ShowConsole( 0, qfalse ); - Cvar_Set( "viewlog", "0" ); - } - return 0; - case WM_CTLCOLORSTATIC: - if ( ( HWND ) lParam == s_wcd.hwndBuffer ) - { - SetBkColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0xB0 ) ); - SetTextColor( ( HDC ) wParam, RGB( 0xff, 0xff, 0x00 ) ); - -#if 0 // this draws a background in the edit box, but there are issues with this - if ( ( hdcScaled = CreateCompatibleDC( ( HDC ) wParam ) ) != 0 ) - { - if ( SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo ) ) - { - StretchBlt( ( HDC ) wParam, 0, 0, 512, 384, - hdcScaled, 0, 0, 512, 384, - SRCCOPY ); - } - DeleteDC( hdcScaled ); - } -#endif - return (LRESULT) s_wcd.hbrEditBackground; - } - else if ( ( HWND ) lParam == s_wcd.hwndErrorBox ) - { - if ( s_timePolarity & 1 ) - { - SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) ); - SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x0, 0x00 ) ); - } - else - { - SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) ); - SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x0, 0x00 ) ); - } - return (LRESULT) s_wcd.hbrErrorBackground; - } - break; - - case WM_COMMAND: - if ( wParam == COPY_ID ) - { - SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 ); - SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 ); - } - else if ( wParam == QUIT_ID ) - { - if ( s_wcd.quitOnClose ) - { - PostQuitMessage( 0 ); - } - else - { - cmdString = CopyString( "quit" ); - Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString ); - } - } - else if ( wParam == CLEAR_ID ) - { - SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 ); - SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" ); - UpdateWindow( s_wcd.hwndBuffer ); - } - break; - case WM_CREATE: -// s_wcd.hbmLogo = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP1 ) ); -// s_wcd.hbmClearBitmap = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP2 ) ); - s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0xB0 ) ); - s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) ); - SetTimer( hWnd, 1, 1000, NULL ); - break; - case WM_ERASEBKGND: -#if 0 - HDC hdcScaled; - HGDIOBJ oldObject; - -#if 1 // a single, large image - hdcScaled = CreateCompatibleDC( ( HDC ) wParam ); - assert( hdcScaled != 0 ); - - if ( hdcScaled ) - { - oldObject = SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo ); - assert( oldObject != 0 ); - if ( oldObject ) - { - StretchBlt( ( HDC ) wParam, 0, 0, s_wcd.windowWidth, s_wcd.windowHeight, - hdcScaled, 0, 0, 512, 384, - SRCCOPY ); - } - DeleteDC( hdcScaled ); - hdcScaled = 0; - } -#else // a repeating brush - { - HBRUSH hbrClearBrush; - RECT r; - - GetWindowRect( hWnd, &r ); - - r.bottom = r.bottom - r.top + 1; - r.right = r.right - r.left + 1; - r.top = 0; - r.left = 0; - - hbrClearBrush = CreatePatternBrush( s_wcd.hbmClearBitmap ); - - assert( hbrClearBrush != 0 ); - - if ( hbrClearBrush ) - { - FillRect( ( HDC ) wParam, &r, hbrClearBrush ); - DeleteObject( hbrClearBrush ); - } - } -#endif - return 1; -#endif - return DefWindowProc( hWnd, uMsg, wParam, lParam ); - case WM_TIMER: - if ( wParam == 1 ) - { - s_timePolarity = !s_timePolarity; - if ( s_wcd.hwndErrorBox ) - { - InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE ); - } - } - break; - } - - return DefWindowProc( hWnd, uMsg, wParam, lParam ); -} - -LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - char inputBuffer[1024]; - - switch ( uMsg ) - { - case WM_KILLFOCUS: - if ( ( HWND ) wParam == s_wcd.hWnd || - ( HWND ) wParam == s_wcd.hwndErrorBox ) - { - SetFocus( hWnd ); - return 0; - } - break; - - case WM_CHAR: - if ( wParam == 13 ) - { - GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) ); - strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 ); - strcat( s_wcd.consoleText, "\n" ); - SetWindowText( s_wcd.hwndInputLine, "" ); - - Sys_Print( va( "]%s\n", inputBuffer ) ); - - return 0; - } - } - - return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam ); -} - -/* -** Sys_CreateConsole -*/ -void Sys_CreateConsole( void ) -{ - HDC hDC; - WNDCLASS wc; - RECT rect; - const char *DEDCLASS = "Q3 WinConsole"; - int nHeight; - int swidth, sheight; - int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX; - - memset( &wc, 0, sizeof( wc ) ); - - wc.style = 0; - wc.lpfnWndProc = (WNDPROC) ConWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = g_wv.hInstance; - wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1)); - wc.hCursor = LoadCursor (NULL,IDC_ARROW); - wc.hbrBackground = (void *)COLOR_WINDOW; - wc.lpszMenuName = 0; - wc.lpszClassName = DEDCLASS; - - if ( !RegisterClass (&wc) ) - return; - - rect.left = 0; - rect.right = 540; - rect.top = 0; - rect.bottom = 450; - AdjustWindowRect( &rect, DEDSTYLE, FALSE ); - - hDC = GetDC( GetDesktopWindow() ); - swidth = GetDeviceCaps( hDC, HORZRES ); - sheight = GetDeviceCaps( hDC, VERTRES ); - ReleaseDC( GetDesktopWindow(), hDC ); - - s_wcd.windowWidth = rect.right - rect.left + 1; - s_wcd.windowHeight = rect.bottom - rect.top + 1; - - s_wcd.hWnd = CreateWindowEx( 0, - DEDCLASS, - "OpenMoHAA Console", - DEDSTYLE, - ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1, - NULL, - NULL, - g_wv.hInstance, - NULL ); - - if ( s_wcd.hWnd == NULL ) - { - return; - } - - // - // create fonts - // - hDC = GetDC( s_wcd.hWnd ); - nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72); - - s_wcd.hfBufferFont = CreateFont( nHeight, - 0, - 0, - 0, - FW_LIGHT, - 0, - 0, - 0, - DEFAULT_CHARSET, - OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, - DEFAULT_QUALITY, - FF_MODERN | FIXED_PITCH, - "Courier New" ); - - ReleaseDC( s_wcd.hWnd, hDC ); - - // - // create the input line - // - s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | - ES_LEFT | ES_AUTOHSCROLL, - 6, 400, 528, 20, - s_wcd.hWnd, - ( HMENU ) INPUT_ID, // child window ID - g_wv.hInstance, NULL ); - - // - // create the buttons - // - s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, - 5, 425, 72, 24, - s_wcd.hWnd, - ( HMENU ) COPY_ID, // child window ID - g_wv.hInstance, NULL ); - SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "copy" ); - - s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, - 82, 425, 72, 24, - s_wcd.hWnd, - ( HMENU ) CLEAR_ID, // child window ID - g_wv.hInstance, NULL ); - SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "clear" ); - - s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, - 462, 425, 72, 24, - s_wcd.hWnd, - ( HMENU ) QUIT_ID, // child window ID - g_wv.hInstance, NULL ); - SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "quit" ); - - - // - // create the scrollbuffer - // - s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | - ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY, - 6, 40, 526, 354, - s_wcd.hWnd, - ( HMENU ) EDIT_ID, // child window ID - g_wv.hInstance, NULL ); - SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 ); - - s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLongPtr( s_wcd.hwndInputLine, GWLP_WNDPROC, (LONG_PTR)InputLineWndProc ); - SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 ); - - ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT); - UpdateWindow( s_wcd.hWnd ); - SetForegroundWindow( s_wcd.hWnd ); - SetFocus( s_wcd.hwndInputLine ); - - s_wcd.visLevel = 1; -} - -/* -** Sys_DestroyConsole -*/ -void Sys_DestroyConsole( void ) { - if ( s_wcd.hWnd ) { - ShowWindow( s_wcd.hWnd, SW_HIDE ); - CloseWindow( s_wcd.hWnd ); - DestroyWindow( s_wcd.hWnd ); - s_wcd.hWnd = 0; - } -} - -/* -** Sys_ShowConsole -*/ -void Sys_ShowConsole( int visLevel, qboolean quitOnClose ) -{ - s_wcd.quitOnClose = quitOnClose; - - if ( visLevel == s_wcd.visLevel ) - { - return; - } - - s_wcd.visLevel = visLevel; - - if ( !s_wcd.hWnd ) - return; - - switch ( visLevel ) - { - case 0: - ShowWindow( s_wcd.hWnd, SW_HIDE ); - break; - case 1: - ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL ); - SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff ); - break; - case 2: - ShowWindow( s_wcd.hWnd, SW_MINIMIZE ); - break; - default: - Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel ); - break; - } -} - -/* -** Sys_ConsoleInput -*/ -char *Sys_ConsoleInput( void ) -{ - if ( s_wcd.consoleText[0] == 0 ) - { - return NULL; - } - - strcpy( s_wcd.returnedText, s_wcd.consoleText ); - s_wcd.consoleText[0] = 0; - - return s_wcd.returnedText; -} - -/* -** Conbuf_AppendText -*/ -void Conbuf_AppendText( const char *pMsg ) -{ -#define CONSOLE_BUFFER_SIZE 16384 - - char buffer[CONSOLE_BUFFER_SIZE*2]; - char *b = buffer; - const char *msg; - int bufLen; - int i = 0; - static unsigned long s_totalChars; - - // - // if the message is REALLY long, use just the last portion of it - // - if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 ) - { - msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1; - } - else - { - msg = pMsg; - } - - // - // copy into an intermediate buffer - // - while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) ) - { - if ( msg[i] == '\n' && msg[i+1] == '\r' ) - { - b[0] = '\r'; - b[1] = '\n'; - b += 2; - i++; - } - else if ( msg[i] == '\r' ) - { - b[0] = '\r'; - b[1] = '\n'; - b += 2; - } - else if ( msg[i] == '\n' ) - { - b[0] = '\r'; - b[1] = '\n'; - b += 2; - } - else if (pMsg[i + 1] == 0x1B) - { - i++; - } - else - { - *b= msg[i]; - b++; - } - i++; - } - *b = 0; - bufLen = b - buffer; - - s_totalChars += bufLen; - - // - // replace selection instead of appending if we're overflowing - // - if ( s_totalChars > 0x7fff ) - { - SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 ); - s_totalChars = bufLen; - } - - // - // put this text into the windows console - // - SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff ); - SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 ); - SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer ); -} - -/* -** Sys_SetErrorText -*/ -void Sys_SetErrorText( const char *buf ) -{ - Q_strncpyz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) ); - - if ( !s_wcd.hwndErrorBox ) - { - s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN, - 6, 5, 526, 30, - s_wcd.hWnd, - ( HMENU ) ERRORBOX_ID, // child window ID - g_wv.hInstance, NULL ); - SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 ); - SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString ); - - DestroyWindow( s_wcd.hwndInputLine ); - s_wcd.hwndInputLine = NULL; - } -} diff --git a/code/win32/win_wndproc.c b/code/win32/win_wndproc.c deleted file mode 100644 index 08654139..00000000 --- a/code/win32/win_wndproc.c +++ /dev/null @@ -1,440 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "../client/client.h" -#include "win_local.h" - -WinVars_t g_wv; - -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS -#endif - -static UINT MSH_MOUSEWHEEL; - -// Console variables that we need to access from this module -cvar_t *vid_xpos; // X coordinate of window position -cvar_t *vid_ypos; // Y coordinate of window position -cvar_t *r_fullscreen; - -#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) ) - -LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); - -static qboolean s_alttab_disabled; - -static void WIN_DisableAltTab( void ) -{ - if ( s_alttab_disabled ) - return; - - if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) ) - { - RegisterHotKey( 0, 0, MOD_ALT, VK_TAB ); - } - else - { - BOOL old; - - SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 ); - } - s_alttab_disabled = qtrue; -} - -static void WIN_EnableAltTab( void ) -{ - if ( s_alttab_disabled ) - { - if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) ) - { - UnregisterHotKey( 0, 0 ); - } - else - { - BOOL old; - - SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 ); - } - - s_alttab_disabled = qfalse; - } -} - -/* -================== -VID_AppActivate -================== -*/ -static void VID_AppActivate(BOOL fActive, BOOL minimize) -{ - g_wv.isMinimized = minimize; - - Com_DPrintf("VID_AppActivate: %i\n", fActive ); - - //Key_ClearStates(); // FIXME!!! - - // we don't want to act like we're active if we're minimized - if (fActive && !g_wv.isMinimized ) - { - g_wv.activeApp = qtrue; - } - else - { - g_wv.activeApp = qfalse; - } - - // minimize/restore mouse-capture on demand - if (!g_wv.activeApp ) - { - IN_Activate (qfalse); - } - else - { - IN_Activate (qtrue); - } -} - -//========================================================================== - -static byte s_scantokey[128] = -{ - // 0 1 2 3 4 5 6 7 - // 8 9 A B C D E F - 0 , 27, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0 - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', 13 , K_LCTRL,'a', 's', // 1 - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'' , '`', K_LSHIFT,'\\', 'z', 'x', 'c', 'v', // 2 - 'b', 'n', 'm', ',', '.', '/', K_RSHIFT,'*', - K_LALT,' ', K_CAPSLOCK , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 - K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME, - K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,K_END, //4 - K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, - K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 -}; - -/* -======= -MapKey - -Map from windows to quake keynums -======= -*/ -static int MapKey (int key) -{ - int result; - int modified; - qboolean is_extended; - -// Com_Printf( "0x%x\n", key); - - modified = ( key >> 16 ) & 255; - - if ( modified > 127 ) - return 0; - - if ( key & ( 1 << 24 ) ) - { - is_extended = qtrue; - } - else - { - is_extended = qfalse; - } - - result = s_scantokey[modified]; - - if ( !is_extended ) - { - switch ( result ) - { - case K_HOME: - return K_KP_HOME; - case K_UPARROW: - return K_KP_UPARROW; - case K_PGUP: - return K_KP_PGUP; - case K_LEFTARROW: - return K_KP_LEFTARROW; - case K_RIGHTARROW: - return K_KP_RIGHTARROW; - case K_END: - return K_KP_END; - case K_DOWNARROW: - return K_KP_DOWNARROW; - case K_PGDN: - return K_KP_PGDN; - case K_INS: - return K_KP_INS; - case K_DEL: - return K_KP_DEL; - default: - return result; - } - } - else - { - switch ( result ) - { - case K_PAUSE: - return K_KP_NUMLOCK; - case 0x0D: - return K_KP_ENTER; - case 0x2F: - return K_KP_SLASH; - case 0xAF: - return K_KP_PLUS; - } - return result; - } -} - - -/* -==================== -MainWndProc - -main window procedure -==================== -*/ -extern cvar_t *in_mouse; - -LONG WINAPI MainWndProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - static qboolean flip = qtrue; - int zDelta, i; - - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp - // Windows 95, Windows NT 3.51 - uses MSH_MOUSEWHEEL - // only relevant for non-DI input - // - // NOTE: not sure how reliable this is anymore, might trigger double wheel events - if (in_mouse->integer != 1) - { - if ( uMsg == MSH_MOUSEWHEEL ) - { - if ( ( ( int ) wParam ) > 0 ) - { - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL ); - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL ); - } - else - { - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL ); - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL ); - } - return DefWindowProc (hWnd, uMsg, wParam, lParam); - } - } - - switch (uMsg) - { - case WM_MOUSEWHEEL: - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp - // Windows 98/Me, Windows NT 4.0 and later - uses WM_MOUSEWHEEL - // only relevant for non-DI input and when console is toggled in window mode - // if console is toggled in window mode (KEYCATCH_CONSOLE) then mouse is released and DI doesn't see any mouse wheel - if (in_mouse->integer != 1 || (!r_fullscreen->integer && (cls.keyCatchers & KEYCATCH_CONSOLE))) - { - // 120 increments, might be 240 and multiples if wheel goes too fast - // NOTE Logitech: logitech drivers are screwed and send the message twice? - // could add a cvar to interpret the message as successive press/release events - zDelta = ( short ) HIWORD( wParam ) / 120; - if ( zDelta > 0 ) - { - for(i=0; iinteger ) - { - WIN_DisableAltTab(); - } - else - { - WIN_EnableAltTab(); - } - - break; -#if 0 - case WM_DISPLAYCHANGE: - Com_DPrintf( "WM_DISPLAYCHANGE\n" ); - // we need to force a vid_restart if the user has changed - // their desktop resolution while the game is running, - // but don't do anything if the message is a result of - // our own calling of ChangeDisplaySettings - if ( com_insideVidInit ) { - break; // we did this on purpose - } - // something else forced a mode change, so restart all our gl stuff - Cbuf_AddText( "vid_restart\n" ); - break; -#endif - case WM_DESTROY: - // let sound and input know about this? - g_wv.hWnd = NULL; - if ( r_fullscreen->integer ) - { - WIN_EnableAltTab(); - } - break; - - case WM_CLOSE: - Cbuf_ExecuteText( EXEC_APPEND, "quit" ); - break; - - case WM_ACTIVATE: - { - int fActive, fMinimized; - - fActive = LOWORD(wParam); - fMinimized = (BOOL) HIWORD(wParam); - - VID_AppActivate( fActive != WA_INACTIVE, fMinimized); - SNDDMA_Activate(); - } - break; - - case WM_MOVE: - { - int xPos, yPos; - RECT r; - int style; - - if (!r_fullscreen->integer ) - { - xPos = (short) LOWORD(lParam); // horizontal position - yPos = (short) HIWORD(lParam); // vertical position - - r.left = 0; - r.top = 0; - r.right = 1; - r.bottom = 1; - - style = GetWindowLong( hWnd, GWL_STYLE ); - AdjustWindowRect( &r, style, FALSE ); - - Cvar_SetValue( "vid_xpos", xPos + r.left); - Cvar_SetValue( "vid_ypos", yPos + r.top); - vid_xpos->modified = qfalse; - vid_ypos->modified = qfalse; - if ( g_wv.activeApp ) - { - IN_Activate (qtrue); - } - } - } - break; - -// this is complicated because Win32 seems to pack multiple mouse events into -// one update sometimes, so we always check all states and look for events - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MOUSEMOVE: - { - int temp; - - temp = 0; - - if (wParam & MK_LBUTTON) - temp |= 1; - - if (wParam & MK_RBUTTON) - temp |= 2; - - if (wParam & MK_MBUTTON) - temp |= 4; - - IN_MouseEvent (temp); - } - break; - - case WM_SYSCOMMAND: - if ( wParam == SC_SCREENSAVE ) - return 0; - break; - - case WM_SYSKEYDOWN: - if ( wParam == 13 ) - { - if ( r_fullscreen ) - { - Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer ); - Cbuf_AddText( "vid_restart\n" ); - } - return 0; - } - // fall through - case WM_KEYDOWN: - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qtrue, 0, NULL ); - break; - - case WM_SYSKEYUP: - case WM_KEYUP: - Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qfalse, 0, NULL ); - break; - - case WM_CHAR: - Sys_QueEvent( g_wv.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL ); - break; - } - - return DefWindowProc( hWnd, uMsg, wParam, lParam ); -} - diff --git a/code/win32/winquake.rc b/code/win32/winquake.rc deleted file mode 100644 index c99e257e..00000000 --- a/code/win32/winquake.rc +++ /dev/null @@ -1,71 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON DISCARDABLE "qe3.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_STRING1 "Quake3" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - diff --git a/code/zlib/zlib.h b/code/zlib/zlib.h new file mode 100644 index 00000000..02281792 --- /dev/null +++ b/code/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/cross-make-mingw.sh b/cross-make-mingw.sh deleted file mode 100644 index c6dbe377..00000000 --- a/cross-make-mingw.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -export CC=i586-mingw32msvc-gcc -export WINDRES=i586-mingw32msvc-windres -export PLATFORM=mingw32 -exec make $* diff --git a/docker/README.md b/docker/README.md index 30b23b8e..eecfbf4a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,9 +1,6 @@ # Docker -Run with -```sh -mkdir .cmake -cd .cmake -cmake -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -G Ninja ../ -ninja -``` +This contains Docker files for openmohaa development and server. + +- See [Development](dev/README.md) to build dev container images. +- See [Server](server/README.md) to build an OpenMoHAA server container image. diff --git a/docker/build.ps1 b/docker/build.ps1 deleted file mode 100644 index d6165255..00000000 --- a/docker/build.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -docker build -t openmohaa/builder.14_04 x86_64/14.04 && ` -docker build -t openmohaa/builder.16_04 x86_64/16.04 && ` -docker build -t openmohaa/builder.18_04 x86_64/18.04 && ` -docker build -t openmohaa/builder.20_04 x86_64/20.04 && ` -docker build -t openmohaa/builder.22_04 x86_64/22.04 && ` -docker build -t openmohaa/builder.22_10 x86_64/22.10 && ` -docker build -t openmohaa/builder.18_04.i386 i386/18.04 diff --git a/docker/dev/README.md b/docker/dev/README.md new file mode 100644 index 00000000..30b23b8e --- /dev/null +++ b/docker/dev/README.md @@ -0,0 +1,9 @@ +# Docker + +Run with +```sh +mkdir .cmake +cd .cmake +cmake -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -G Ninja ../ +ninja +``` diff --git a/docker/armhf/Dockerfile b/docker/dev/armhf/Dockerfile similarity index 100% rename from docker/armhf/Dockerfile rename to docker/dev/armhf/Dockerfile diff --git a/docker/dev/build.ps1 b/docker/dev/build.ps1 new file mode 100644 index 00000000..61601a22 --- /dev/null +++ b/docker/dev/build.ps1 @@ -0,0 +1,10 @@ +docker build -t openmohaa/builder.14_04 x86_64/14.04 +docker build -t openmohaa/builder.16_04 x86_64/16.04 +docker build -t openmohaa/builder.18_04 x86_64/18.04 +docker build -t openmohaa/builder.20_04 x86_64/20.04 +docker build -t openmohaa/builder.22_04 x86_64/22.04 +docker build -t openmohaa/builder.22_10 x86_64/22.10 +docker build -t openmohaa/builder.debian-11 x86_64/debian-11 +docker build -t openmohaa/builder.debian-12 x86_64/debian-12 + +docker build -t openmohaa/builder.18_04.i386 i386/18.04 diff --git a/docker/i386/18.04/Dockerfile b/docker/dev/i386/18.04/Dockerfile similarity index 100% rename from docker/i386/18.04/Dockerfile rename to docker/dev/i386/18.04/Dockerfile diff --git a/docker/s390x/Dockerfile b/docker/dev/s390x/Dockerfile similarity index 100% rename from docker/s390x/Dockerfile rename to docker/dev/s390x/Dockerfile diff --git a/docker/x86_64/14.04/Dockerfile b/docker/dev/x86_64/14.04/Dockerfile similarity index 61% rename from docker/x86_64/14.04/Dockerfile rename to docker/dev/x86_64/14.04/Dockerfile index 6f8b8207..b6624b02 100644 --- a/docker/x86_64/14.04/Dockerfile +++ b/docker/dev/x86_64/14.04/Dockerfile @@ -2,5 +2,7 @@ FROM ubuntu:14.04 # install dev tools RUN apt update && apt install -y ninja-build cmake make clang-3.5 gcc-4.8 g++-4.8 flex bison +# install some important libraries like SDL +RUN apt install -y --no-install-recommends libsdl2-dev WORKDIR /usr/src/openmohaa/ diff --git a/docker/x86_64/16.04/Dockerfile b/docker/dev/x86_64/16.04/Dockerfile similarity index 62% rename from docker/x86_64/16.04/Dockerfile rename to docker/dev/x86_64/16.04/Dockerfile index 21689689..b5564908 100644 --- a/docker/x86_64/16.04/Dockerfile +++ b/docker/dev/x86_64/16.04/Dockerfile @@ -2,5 +2,7 @@ FROM ubuntu:16.04 # install dev tools RUN apt update && apt install -y ninja-build cmake make clang-5.0 lld-5.0 gcc-5 g++-5 flex bison +# install some important libraries like SDL +RUN apt install -y --no-install-recommends libsdl2-dev WORKDIR /usr/src/openmohaa/ diff --git a/docker/x86_64/18.04/Dockerfile b/docker/dev/x86_64/18.04/Dockerfile similarity index 62% rename from docker/x86_64/18.04/Dockerfile rename to docker/dev/x86_64/18.04/Dockerfile index a967fba4..8ef23bc8 100644 --- a/docker/x86_64/18.04/Dockerfile +++ b/docker/dev/x86_64/18.04/Dockerfile @@ -2,5 +2,7 @@ FROM ubuntu:18.04 # install dev tools RUN apt update && apt install -y ninja-build cmake make clang-6.0 lld-6.0 gcc-6 g++-6 flex bison +# install some important libraries like SDL +RUN apt install -y --no-install-recommends libsdl2-dev WORKDIR /usr/src/openmohaa/ diff --git a/docker/x86_64/20.04/Dockerfile b/docker/dev/x86_64/20.04/Dockerfile similarity index 61% rename from docker/x86_64/20.04/Dockerfile rename to docker/dev/x86_64/20.04/Dockerfile index 93fcf966..44dcdb2d 100644 --- a/docker/x86_64/20.04/Dockerfile +++ b/docker/dev/x86_64/20.04/Dockerfile @@ -2,5 +2,7 @@ FROM ubuntu:20.04 # install dev tools RUN apt update && apt install -y ninja-build cmake make clang-7 lld-7 gcc-7 g++-7 flex bison +# install some important libraries like SDL +RUN apt install -y --no-install-recommends libsdl2-dev WORKDIR /usr/src/openmohaa/ diff --git a/docker/x86_64/22.04/Dockerfile b/docker/dev/x86_64/22.04/Dockerfile similarity index 72% rename from docker/x86_64/22.04/Dockerfile rename to docker/dev/x86_64/22.04/Dockerfile index e2a56e61..fa33bc02 100644 --- a/docker/x86_64/22.04/Dockerfile +++ b/docker/dev/x86_64/22.04/Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu:22.04 # install dev tools RUN apt update && apt install -y ninja-build cmake make clang-15 lld-15 gcc-12 g++-12 flex bison -# install some important libraries like GL -RUN apt install -y --no-install-recommends ncurses-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev libxxf86vm-dev libxxf86dga-dev libsdl2-dev +# install some important libraries like SDL +RUN apt install -y --no-install-recommends libsdl2-dev WORKDIR /usr/src/openmohaa/ #COPY CMakeLists.txt ./ diff --git a/docker/x86_64/22.10/Dockerfile b/docker/dev/x86_64/22.10/Dockerfile similarity index 100% rename from docker/x86_64/22.10/Dockerfile rename to docker/dev/x86_64/22.10/Dockerfile diff --git a/docker/dev/x86_64/debian-11/Dockerfile b/docker/dev/x86_64/debian-11/Dockerfile new file mode 100644 index 00000000..cf3a9e6c --- /dev/null +++ b/docker/dev/x86_64/debian-11/Dockerfile @@ -0,0 +1,8 @@ +FROM debian:11 + +# install dev tools +RUN apt update && apt install -y ninja-build cmake make clang-16 lld-16 gcc-10 g++-10 flex bison +# install some important libraries like GL +RUN apt install -y --no-install-recommends ncurses-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev libxxf86vm-dev libxxf86dga-dev libsdl2-dev + +WORKDIR /usr/src/openmohaa/ diff --git a/docker/dev/x86_64/debian-12/Dockerfile b/docker/dev/x86_64/debian-12/Dockerfile new file mode 100644 index 00000000..19f8d33c --- /dev/null +++ b/docker/dev/x86_64/debian-12/Dockerfile @@ -0,0 +1,8 @@ +FROM debian:12 + +# install dev tools +RUN apt update && apt install -y ninja-build cmake make clang-19 lld-19 gcc-12 g++-12 flex bison +# install some important libraries like GL +RUN apt install -y --no-install-recommends ncurses-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev libxxf86vm-dev libxxf86dga-dev libsdl2-dev + +WORKDIR /usr/src/openmohaa/ diff --git a/docker/server/README.md b/docker/server/README.md new file mode 100644 index 00000000..7dfa48f3 --- /dev/null +++ b/docker/server/README.md @@ -0,0 +1,39 @@ +# Server image + +## Introduction + +Contains Dockerfile for building openmohaa-based server on Debian Bookworm. MOHAA data must be stored in `/usr/local/share/mohaa`, the directory structure should look like this: +``` +[/usr/local/share/mohaa] +├── [main] +│   └── Pak*.pk3 +├── [mainta] +│   └── pak*.pk3 +├── [maintt] +│   └── pak*.pk3 +└── [home] + ├── [main] + │   └── Custom PK3s go here + ├── [mainta] + │   └── Custom PK3s go here + └── [maintt] + └── Custom PK3s go here +``` + +`sound` and `video` folders are not needed. + +There are two ways to handle game data: +1) Create a new image based on this image (with a new Dockerfile) and copy the game directory in `/usr/local/share/mohaa`. This is the recommended solution because game data should be immutable. For mods, a base image can be created, or a volume can be mounted to `/usr/local/share/mohaa/home` which contains files (in main, mainta or maintt subdir) that will modify the game. + +or + +2) Mount a volume to the game directory directly in `/usr/local/share/mohaa`. + +## Building + +1) Put the game data (`main`, `mainta` and `maintt`) inside `full/game`, it should match the directory structure above +2) Execute one of the build.* scripts (depending on if you are running Linux or Windows). + +## Starting + +The server can now be executed using `docker run -p 12203:12203 -p 12300:12300 openmohaa/full`, or by using a docker composition file. diff --git a/docker/server/base/Dockerfile b/docker/server/base/Dockerfile new file mode 100644 index 00000000..bf63cff2 --- /dev/null +++ b/docker/server/base/Dockerfile @@ -0,0 +1,46 @@ +FROM debian:bookworm + +RUN apt update && apt install -y git clang cmake flex bison zlib1g-dev ninja-build + +# Compile with clang +ENV CC=clang +ENV CXX=clang++ + +# Clone the repository +RUN mkdir -p /tmp/openmohaa/build \ + && cd /tmp/openmohaa \ + && git clone --depth 1 --single-branch -b main https://github.com/openmoh/openmohaa.git + +# Build the project +RUN cd /tmp/openmohaa/build \ + && cmake -G "Ninja" -DBUILD_NO_CLIENT=1 -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DTARGET_LOCAL_SYSTEM=1 -DCMAKE_INSTALL_PREFIX="/usr/local/games/openmohaa" /tmp/openmohaa/openmohaa \ + && cmake --build . \ + && cmake --install . + +# Reset to the base debian image, will gain space +FROM debian:bookworm + +# Copy the installed directory +COPY --from=0 /usr/local/games/openmohaa /usr/local/games/openmohaa + +# MOHAA data (main, mainta and maintt) goes inside this directory +# mods can go inside a subdirectory called "home" +VOLUME "/usr/local/share/mohaa" + +# Install tools to check for the health +RUN apt update && apt install -y socat +COPY "health_check.sh" "/usr/local/bin/health_check.sh" +HEALTHCHECK --interval=15s --timeout=20s --start-period=10s --retries=3 CMD [ "bash", "/usr/local/bin/health_check.sh" ] + +# Create an user for starting the server +# This improves the overall security of the server instance +RUN useradd -m openmohaa +USER openmohaa + +ENV GAME_PORT=12203 +ENV GAMESPY_PORT=12300 + +COPY "entrypoint.sh" "/usr/local/bin/entrypoint.sh" +WORKDIR "/usr/local/share/mohaa" + +ENTRYPOINT [ "bash", "entrypoint.sh" ] diff --git a/docker/server/base/entrypoint.sh b/docker/server/base/entrypoint.sh new file mode 100644 index 00000000..a5d26623 --- /dev/null +++ b/docker/server/base/entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# It's amazing that with Docker, one can't put environment variables in the array of the ENTRYPOINT command + +/usr/local/games/openmohaa/lib/openmohaa/omohaaded +set fs_homepath home +set dedicated 2 +set net_port $GAME_PORT:-12203 +set net_gamespy_port $GAMESPY_PORT:-12300 $@ diff --git a/docker/server/base/health_check.sh b/docker/server/base/health_check.sh new file mode 100644 index 00000000..f7f490eb --- /dev/null +++ b/docker/server/base/health_check.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +header=$'\xff\xff\xff\xff\x01disconnect' +# to avoid spamming the log file with getinfo/getstatus +# simply send an unsupported message +# so the server will return the disconnect message +message=$'none' + +query_port=${GAME_PORT:-12203} +data="" + +while [ -z "$data" ] +do + data=$(echo "$message" | socat - UDP:0.0.0.0:$query_port 2>/dev/null) + ret=$? + + if [ $ret != 0 ] + then + echo "Fail (socat returned $ret)" + exit 1 + fi + + if [ -n "$data" ] + then + break + fi +done + +if [ "$data" != "$header" ] +then + echo "Fail (not maching header)" + echo $line + exit 1 +fi + +# Success +exit 0 diff --git a/docker/server/build.ps1 b/docker/server/build.ps1 new file mode 100644 index 00000000..d41125a6 --- /dev/null +++ b/docker/server/build.ps1 @@ -0,0 +1,2 @@ +docker build -t openmohaa/base base +docker build -t openmohaa/full full diff --git a/docker/server/build.sh b/docker/server/build.sh new file mode 100644 index 00000000..d41125a6 --- /dev/null +++ b/docker/server/build.sh @@ -0,0 +1,2 @@ +docker build -t openmohaa/base base +docker build -t openmohaa/full full diff --git a/docker/server/full/.dockerignore b/docker/server/full/.dockerignore new file mode 100644 index 00000000..52417c5b --- /dev/null +++ b/docker/server/full/.dockerignore @@ -0,0 +1,2 @@ +**/.gitignore +**/.gitkeep \ No newline at end of file diff --git a/docker/server/full/Dockerfile b/docker/server/full/Dockerfile new file mode 100644 index 00000000..e2a3d64d --- /dev/null +++ b/docker/server/full/Dockerfile @@ -0,0 +1,6 @@ +FROM openmohaa/base + +USER openmohaa + +COPY --chown=openmohaa:openmohaa "game" "/usr/local/share/mohaa" + diff --git a/docker/server/full/game/.gitkeep b/docker/server/full/game/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docker/server/full/game/home/.gitkeep b/docker/server/full/game/home/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/compiling.md b/docs/compiling.md new file mode 100644 index 00000000..41b4f445 --- /dev/null +++ b/docs/compiling.md @@ -0,0 +1,84 @@ +# Compiling + +OpenMoHAA supports any architecture, thanks to the CMake build system and cross-platform code/libraries. While the most common little-Endian architectures (arm, aarch64, x86, x86_64, ppc64le) have been tested and confirmed to work, big-Endian architectures should be supported as well; however, they remain untested. + +The following tools are required for all platforms: +- CMake >= 3.12 +- Flex (>= 2.6.4) and Bison (>= 3.5.1) +- A C++11 compiler +- [SDL2](https://github.com/libsdl-org/SDL/tree/SDL2) +- [OpenAL SDK](https://github.com/kcat/openal-soft) + +The following tools may be useful: +- [cURL](https://github.com/curl/curl) + +The installation directory can be set to the MOHAA directory with `-DCMAKE_INSTALL_PREFIX=/path/to/mohaa`. + +Compiling debug binaries will result in a `-dbg` suffix appended to the name of the binaries to avoid mixing debug/release code. + +cURL is used to access websites. It is currently used to check for a new release. If the project is compiled without cURL, OpenMoHAA will be unable to check for new updates automatically. + +## Compiling for Linux + +These are the tools required on Linux : +- Clang >= 7.0.1 or GCC >= 9.4.0 +- libsdl2-dev +- libopenal-dev +- libssl-dev +- libcurl4-openssl-dev + +**clang-7** and **gcc-9** has been tested to work on Ubuntu 20.04. Although it's best to use the latest versions. + +1 line install command with clang: +```sh +sudo apt-get install -y cmake ninja-build clang lld flex bison libsdl2-dev libopenal-dev libcurl4-openssl-dev +``` + +Example with **CMake** and **ninja-build** installed: +```sh +mkdir .cmake && cd .cmake +cmake ../ +cmake --build . +cmake --install . +``` + +Usually binaries get installed inside the `/usr/local/lib/openmohaa` directory. + +Other compilers can be specified by appending `-DCMAKE_C_COMPILER=/path/to/compiler -DCMAKE_CXX_COMPILER=path/to/compiler` to the CMake command-line. + +## Compiling for Windows + +Visual Studio (2019 or 2022) is generally preferred. + +- Get Flex/Bison: https://github.com/lexxmark/winflexbison/releases/latest +- Get OpenAL: https://github.com/kcat/openal-soft/releases/latest rename `soft_oal.dll` to `OpenAL64.dll` on 64-bit and `OpenAL32.dll` on 32-bit +- Get cURL: https://github.com/curl/curl + +Optionally, The cURL library can be compiled with the following CMake commands: +``` +cmake -DCMAKE_INSTALL_PREFIX="E:\Src\openmoh\openmohaa\thirdparty\curl\build\install" -DCURL_USE_LIBPSL=OFF -DCURL_USE_SCHANNEL=ON -B build +cmake --build build --config Release +cmake --install build --config Release +``` + +Append `-DFLEX_EXECUTABLE=...\win_flex.exe -DBISON_EXECUTABLE=...\win_bison.exe -DOPENAL_INCLUDE_DIR="path/to/oal/include" -DOPENAL_LIBRARY="path/to/oal"` to the CMake command-line to compile the project. + +Example after cloning the repository: +```sh +mkdir .cmake && cd .cmake +cmake -DFLEX_EXECUTABLE=path/to/win_flex.exe -DBISON_EXECUTABLE=path/to/win_bison.exe -DOPENAL_INCLUDE_DIR="path/to/oal/include" -DOPENAL_LIBRARY="path/to/oal" ../ +cmake --build . +cmake --install . +``` + +Usually binaries get installed inside the `Program Files (x86)` folder. + +afterwards you can can append `-DCURL_ROOT=path\to\curl\install` to specify the install path to cURL. + +## Tweaking the build + +- `-DBUILD_NO_CLIENT=1` Don't build client binaries. This will only build the dedicated server binaries. +- `-DCMAKE_LIB_SUFFIX=suffix` Default suffix to use for the default `lib` directory. For example `-DCMAKE_LIB_SUFFIX=64` +- `-DNO_MODERN_DMA=1` Use the basic DMA sound system from quake3. This lacks many features such as soundtracks and movie audio from the modern OpenAL-based DMA sound system. This option is not recommended, unless openal is not available. +- `-DTARGET_LOCAL_SYSTEM=1` for compiling and installing on the local system. This will remove the architecture suffix at the end of each binary. This option can be useful for packaging builds. +- `-DUSE_SYSTEM_LIBS=1` for third-party libraries, this will make use of system libraries instead of libraries that are embedded within the project. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 00000000..b110713e --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,139 @@ +# Configuration and commands + +## General configuration + +This documentation currently only lists new changes that were introduced in OpenMoHAA. + +If you want to use containers, see [Building a server container in Docker](../../docker/server/README.md) to build an image for your dedicated server. + +### Home directory + +In original MOH:AA, the game installation directory is used to store mods and data, it's not the case in OpenMoHAA as it uses the home directory by default to write data in here, and the home directory can be used to store mods. This behavior can be changed: + +- `set fs_homepath Z:\openmohaa_data`: User data will be read and written in the directory located in `Z:\openmohaa_data` +- `set fs_homepath homedata`: The subdirectory `homedata` in the game directory will be used to read and store user data +- `set fs_homepath .`: Not recommended, the game directory will be used for storing user data, just like the original MOH:AA + +The variable defaults to the following value depending on the OS: + +- `%APPDATA%\openmohaa` on Windows +- `~/.openmohaa` on Linux +- `~/Library/Application Support/openmohaa` on macOS + +### Configure the network components + +The network settings can be adjusted to use either IPv4, IPv6, or both. By default, IPv6 is disabled on dedicated servers. The following commands adjust network settings: + +- `set net_enabled 0`: This networking. +- `set net_enabled 1`: This enables IPv4 only (the default setting for dedicated servers). +- `set net_enabled 2`: This enables IPv6 only. +- `set net_enabled 3`: This enables both IPv4 and IPv6 (the default setting when running the standalone game). + +*Note: The master server (using the GameSpy protocol) does not support IPv6. If IPv4 is disabled, the server won't appear in the online server list for internet games, even if IPv6 is enabled.* + +### Flood protection differences with MOH: Spearhead + +Flood protection is turned on by default in all games (`sv_floodProtection 1`). + +- In MOH: Allied Assault and OpenMoHAA, flood protection checks all commands. +- In MOH: Spearhead 2.0 and later, flood protection only checks for text messages. + +While flood protection prevents spam, it can sometimes be annoying in certain situations like reloading and checking scores within a short period of time. If needed, it can be disabled with `set sv_floodProtection 0`. + +For more details on preventing message spamming, check out the [Chat](#chat) section below. + +### Updates + +The game periodically retrieves the latest version number from the GitHub project page at fixed intervals to check for available updates. This process runs in the background and does not interfere with the main thread, meaning it will not cause hangs or stability issues. Updates are not applied automatically, they must be downloaded and installed manually. + +Update checking is enabled by default, but can be disabled under any of the following conditions: +- `net_enabled` is set to 0, disables networking, as mentioned above +- `com_updatechecker_enabled` is set to 0 +- The project is compiled without libcurl support + +If you disable the update checker, remember to regularly check the project page for new versions. Updates can improve security and provide important fixes against exploits. + +## Server configuration + +### Optimization / Antichams + +A new variable, `sv_netoptimize`, enables a feature that optimizes network bandwidth by not sending players information about others they can't see. For each client, the server optimizes by only transmitting data about players within their view. Clients will not receive information about players they can't see. This feature also helps protect against cheaters: + +- `set sv_netoptimize 0`: This disables the optimization - the default +- `set sv_netoptimize 1`: This enables the optimization for entities that are moving +- `set sv_netoptimize 2`: This enables the optimization, always + +This option exists since **Medal of Honor: Allied Assault Breakthrough** 2.30, however it was improved in OpenMoHAA: sounds like footsteps will be sent so players don't get confused. + +### Managing bans + +A new feature was introduced to ban IP addresses, thanks to the [ioquake3](https://ioquake3.org/) project. Bans are saved by default in `serverbans.dat` but it can be modified with the `sv_banFile` variable. Here are commands to manage bans: + +|Name |Parameters |Description +|-----------|------------------------------------------------|----------- +|rehashbans | |Loads saved bans from the banlist file +|listbans | |Lists all banned IP addresses +|banaddr |ip[*/subnet*] \| clientnum [*subnet*] [reason] |Bans an IP through its address or through a client number, a subnet can be specified to ban a network range +|exceptaddr |ip[*/subnet*] \| clientnum [*subnet*] |Adds an IP as an exception, for example IP ranges can be banned but one or more exceptions can be added +|bandel |ip[*/subnet*] \| num |Unbans an IP address or a subnet, the entry number can be specified as an alternative +|exceptdel |ip[*/subnet*] \| num |Removes a ban exception +|flushbans | |Removes all bans + +Examples: + +- `banaddr 192.168.5.2` will ban the IP address **192.168.5.2**. +- `banaddr 192.168.1.0/24` will ban all **192.168.1.x** IP addresses (in the range **192.168.1.0**-**192.168.1.255**). +- `banaddr 2` will ban the IP address of the client **#2**. +- `banaddr 4 24` will ban the subnet of client **#4** - i.e if client .**#4** has IP **192.168.8.4**, then it will ban all IPs ranging from **192.168.8.0**-**192.168.8.255**. +- `exceptaddr 3` will add the IP of client **#3** as an exception. +- `bandel 192.168.8.4` will unban **192.168.8.4**. +- `bandel 192.168.1.0/24` will unban the entire **192.168.1.0** subnet (IP ranging from **192.168.1.0**-**192.168.1.255**). + +To calculate IP subnets, search for `IP subnet calculator` on Internet. + +### Game + +#### Chat + +Chat messages will be logged in the console and in the logfile without requiring to set the `developer` variable. + +The in-game chat can be tweaked: + +- `set g_instamsg_allowed 0`: This disables voice instant messages. +- `set g_instamsg_minDelay x`: x is the delay in milliseconds, the minimum delay between each instant messages to avoid spamming. Defaults to 1000. +- `set g_textmsg_allowed 0`: This disables text messages. All, team and private messages will be disabled. +- `set g_textmsg_minDelay x`: x is the delay in milliseconds, the minimum delay between each text message to avoid spamming. Defaults to 1000. + +Temporarily disabling text messages can be useful in situations where tensions arise in the chat. Otherwise, it's best to keep them enabled under normal circumstances. + +#### Balancing teams + +This setting prevents clients from joining a team if that team already has more players than the others. By default, it's turned off, but it can be switched on with the command `set g_teambalance 1`. + +This feature is passive: it only checks the team sizes when someone tries to join, so it won't automatically balance teams during the game. + +*Note: This check doesn't apply in server scripts; it only works when clients join teams directly.* + +#### Bots + +OpenMoHAA introduced multiplayer bots which can be used for entertainment or for testing purposes. Bots are players controlled by the computer, they appear in the scoreboard with their ping set to **bot**. + +First get the [mp-navigation](https://github.com/openmoh/mp-navigation) pk3, it is needed so bots can navigate through MP maps. Then the following variables are used to configure bots: + +- `set sv_maxbots x`: **Required**, configure the maximum number of bots allowed in the game. Since the game can only handle a total of 64 players (clients), the number of bots will be limited to 64 minus the number of real players (`sv_maxclients`). For example, if you set `sv_maxclients` to 48, the maximum number of bots (sv_maxbots) can be 16. +- `set sv_numbots x`: Set the number of bots to spawn. It will be capped to the value of `sv_maxbots`. +- `set sv_minPlayers x`: Configure the minimum number of players required. If the number of real players in a team is below the specified value, the game will automatically add bots to fill the gap. For example, if `sv_minPlayers` is set to 8 and only 5 real players are connected and in a team, the game will spawn 3 bots to make sure there are always 8 players in the game. + +Example with the requirement of 6 players: +```cpp +set sv_maxbots 16 // Reserve 16 client slots for bots +set sv_minPlayers 6 // When there is 0 player in a team, there will be 6 bots. When there is 1 player in a team, there will be 5 bots, and so on +``` + +Example with 4 bots playing: +```cpp +set sv_maxbots 16 // Reserve 16 client slots for bots +set sv_numbots 4 // Spawn 4 bots +``` + +*Note: Bots will have their ping set to **bot** so that all players in-game know they are bots. This prevents any confusion and eliminates any doubt about a hacker being in the game.* diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 00000000..6f54759f --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,126 @@ +# Frequently Asked Questions + +
+My OpenMoHAA client has crashed, leaving the desktop brightened up. How can I fix this without restarting the computer? + +## Try one of the following options: + +### 1. Lock and Unlock Your Screen (Windows+L) +Simply pressing **Win+L** to lock your screen and then logging back in can sometimes reset the brightness to its previous state. + +### 2. Command Line Fix (Windows) +If you have an **NVIDIA** or **AMD** GPU, you can try these commands: + +- **For NVIDIA GPUs:** + Open **Command Prompt (cmd.exe)** or **PowerShell** and run: + + ```powershell + nvidia-settings -a "DPY-0/RedBrightness=0.0" -a "DPY-0/GreenBrightness=0.0" -a "DPY-0/BlueBrightness=0.0" + ``` + + (If you have multiple displays, `DPY-0` may need to be replaced with the correct display identifier.) + +- **For AMD GPUs:** + Open the **AMD Radeon Software** and manually adjust brightness or SDR settings to reset them. + +### 3. Use a Third-Party Tool to Reset Gamma & Brightness +Programs like **Gamma Panel** or **f.lux** can help restore modified brightness and gamma settings quickly. + +### 4. Restart the Graphics Driver (Windows) +Press **Win + Ctrl + Shift + B** to restart the graphics driver without rebooting your PC. Your screen will briefly go black, then reset. + +### 5. Reset Gamma via Xrandr (Linux, Xorg Users) +If you’re using Linux with Xorg, try this command to reset gamma settings: + +```bash +xrandr --output eDP-1 --gamma 1:1:1 +``` + +(Replace `eDP-1` with the correct display name, which you can find by running `xrandr` in the terminal.) + +### 6. Changing Display Mode in Windows (Alternative) +If none of the above solutions work, you can manually reset brightness by changing the display mode: +1. Right-click on your desktop and select **Display settings**. +2. Scroll down to **Display resolution** and change it to a different setting. +3. Revert it back to your original resolution. + +This forces Windows to refresh display settings, which may restore brightness. +
+ +--- + +
+I am using a custom map/mod, and I experience glitches that do not occur in the original game. What should I do? + +### 1. Check game file precedences: +As OpenMoHAA has MultiUser Support (on Windows, user game data is stored in `%APPDATA%\openmohaa`), custom files in this directory override existing files in the game installation folder. + +|Example| +|-| +| A custom `grenzuebergang_KE.pk3` (placed in the user game data folder) contains a `scripts/effects.shader` file and it does not declare `bh_wood_puff_simple`. As a result, bullet impact effect has no texture. +However, if `grenzuebergang_KE.pk3` is placed in the game installation folder (`MOHAA/main` or `/mainta` or `/maintt`, where the base `pak*.pk3` files are located) original files take precedence over custom files as they follow the alphabetical order of file naming. +`Pak1.pk3` contains the original `scripts/effects.shader` where the impact effect is declared; therefore, the player does not experience any issue, as the original file is "loaded" after the custom file. | + +### 2. Create a new issue: +If changing the file precedences has no effect on the glitch you discovered, you have probably found a new bug in the OpenMoHAA engine, so please create a new issue for the developers. +
+ +--- + +
+I cannot set my screen resolution in the Options/Video menu. How can I change it? + +### Edit `omconfig.cfg`: + +If they do not exist, add the following console variables (cvars) to your `omconfig.cfg`[^1] + +``` +seta r_mode "-1" +seta r_customwidth "1920" +seta r_customheight "1080" +``` + +### or (alternatively) run the game with command line parameters: + +Launch your OpenMoHAA client with the following: + +``` ++set r_mode -1 +set r_customwidth 1920 +set r_customheight 1080 +``` + +Change the width and height accordingly. + +
+ +--- + +
+Console does not show up in OpenMoHAA. How can I enable it? + +### 1. Check if console is enabled + +In the Options -> Advanced menu, make sure that the checkbox is checked (red "X") at the Console. +Alternatively, check if the value is equal to 1 for the following cvar in `omconfig.cfg`[^1]: +``` +seta ui_console "1" +``` + +### 2. Check Console keys cvar + +OpenMoHAA introduces a new cvar that stores the keys to open up console. Edit the following cvar in your `omconfig.cfg`[^1]: + +``` +seta cl_consoleKeys "~ ` 0x7e 0x60" +``` + +As you see the default variable above, you can add multiple keys (between the quotation marks, divided by spaces) to display/hide the console. + +> bind ` "toggleconsole" is not to be used anymore. +
+ + +--- + +Footnotes: + +[^1]: omconfig.cfg is the OpenMoHAA configuration file that is located in the user game data folder (on Windows, `%APPDATA%\openmohaa\main` or `mainta` or `maintt` `\configs\omconfig.cfg`) diff --git a/docs/features.md b/docs/features.md new file mode 100644 index 00000000..2ebf8105 --- /dev/null +++ b/docs/features.md @@ -0,0 +1,89 @@ +# Features + +A lot of bugs and exploits from MOH:AA were fixed in OpenMoHAA (BOF exploit, grenade crash bug, command overflow...). + +## Summary + +- SDL2 backend +- OpenAL sound support (better sound quality) +- Full 64-bit support +- Cross-platform support +- Multiuser support on OS (On Windows, user game data is stored in "%APPDATA%\openmohaa") +- Many bug fixes and additions from ioquake3 +- Automatic scaling of UI elements on high resolutions like 4K + +Overall, better compatibility on modern systems and bugfixes. + +## Additions + +### General + +- Demo recording +- Features from ioquake3 +- Features from MOH: Spearhead 2.15 and MOH: Breakthrough 2.40 +- IPv6 support (from ioquake3) + +### Client-side + +- Customizable FOV +- OpenAL and SDL are used +- Smoother animations + +#### Stufftext restriction + +Servers can no longer make players run any command. Only a small number of safe commands are now allowed. This change helps prevent abuse, like unbinding player controls, and improves overall security. + +`stufftext` is now limited to trusted, commonly used commands, like those for controlling in-game music. The full list can be found in [cgame/cg_servercmds_filter.c](../code/cgame/cg_servercmds_filter.c). + +### Server-side + +- Bots +- IP ban (from ioquake3) +- More script commands for mods +- Non-PVS optimization +- Packet flood protection +- Ability to enable/disable the text chat and the voice message chat and set a delay between chat/instant messages + +#### Non-PVS optimization + +For each client, the server optimizes by only sending them information about other players that they can see. Clients won't see other players they can't see. + +Enable this feature with `set sv_netoptimize 2`. + +## Fixes + +### Client-side and server-side + +- Fixed background ambient sounds being muted when restarting +- Fixes from SH 2.15, BT 2.40 and ioquake3 +- Buffer overflow fixes +- Directory traversal fix + +### Server-side + +- DM message comment fix +- Callvote fix +- Fix to prevent getting weapons from opposite team +- Fixed grenade crash bug +- Fixed grenade spectator charge bug +- Fixed `leave_team` bug +- Fixed memory leaks issues in long matches +- Fixed sharking issues with ladders +- Fix to prevent being able to spectate while still in the team with a NULL primary deathmatch weapon +- Fix to prevent throwing a projectile and going into spectator to kill anyone +- Fix for `sv_fps` (tickrate), higher values won't cause animation issues anymore +- Grenades with 1 ammo can now be picked up +- Prevent crashing when the last weapon has no ammo and other weapons are inventory items +- Prevent doors from getting blocked + +## Planned features + +This is a non-exhaustive list of objectives and planned features. + +### Server-side + +- 100% compatibility with mohaa content +- More feature for mods +- Anticheat +- Stats system +- Multiple roles/abilities for server admins to reduce password-stealing \ No newline at end of file diff --git a/docs/features_g_allclasses.html b/docs/features_g_allclasses.html new file mode 100644 index 00000000..0c82ecfa --- /dev/null +++ b/docs/features_g_allclasses.html @@ -0,0 +1,8267 @@ + + +Game Module Classes + + +

+
Game Module Classes
+

+

Actor, Animate, Entity, ScriptSlave, ScriptThread, Sentient, StateMap, Trigger, World

+

Actor (Actor) -> SimpleActor -> Sentient -> Animate -> Entity -> SimpleEntity -> Listener -> Class

+
+ +

accuracy( Float value )
+

    Set percent to hit
+ +

accuracy( Float value )
+

    Set percent to hit
+ +

accuracy
+

    Set percent to hit
+ +

aimat( String target )
+

    Specify the target to aim at.
+ +

ai_off
+

    Turns the AI off for this actor.
+ +

ai_on
+

    Turns the AI on for this actor.
+ +

alarmnode( String value )
+

    Sets the name of the alarm node for the actor (must have type set to alarm for effect)
+ +

alarmnode
+

    Gets the name of the alarm node for the actor (must have type set to alarm for effect)
+ +

alarmnode( String value )
+

    Sets the name of the alarm node for the actor (must have type set to alarm for effect)
+ +

alarmthread( String value )
+

    Sets the name of the alarm thread for the actor (must have type set to alarm for effect)
+ +

alarmthread
+

    Gets the name of the alarm thread for the actor (must have type set to alarm for effect)
+ +

alarmthread( String value )
+

    Sets the name of the alarm thread for the actor (must have type set to alarm for effect)
+ +

ammo_grenade( Integer grenade_count )
+

    Gives the AI some grenades
+ +

ammo_grenade
+

    Returns how many grenades an AI has
+ +

ammo_grenade( Integer grenade_count )
+

    Gives the AI some grenades
+ +

anim( String name )
+

    Play animation.
+ +

animfinal
+

    Whether the animation was succesfully finished
+ +

animloop( String name )
+

    Loop animation.
+ +

animname
+

    Sets the animname.
+ +

animname
+

    Gets the animname.
+ +

animscript( String name )
+

    Play the animation script
+ +

animscript_attached( String name )
+

    Play a noclip animation even when attached
+ +

animscript_noclip( String name )
+

    Play the noclip animation script
+ +

animscript_scripted( String name )
+

    Play the scripted animation script
+ +

anim_attached( String name )
+

    Play attached animation.
+ +

anim_noclip( String name )
+

    Play noclip animation.
+ +

anim_scripted( String name )
+

    Play scripted animation.
+ +

attachgrenade
+

    Used only by grenade return animations to tell the code when to attach the grenade to the actor
+ +

attackhandler
+

    Gets the current script that will handle attack events
+ +

attackhandler
+

    Sets the current script that will handle attack events
+ +

attackplayer
+

    Force Actor to attack the player
+ +

avoidplayer( Integer allowavoid )
+

    set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.
    +
+ +

avoidplayer( Integer allowavoid )
+

    set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.
    +
+ +

avoidplayer
+

    is 0 if this AI won't automatically get out of the way, non-zero if he will
    +
+ +

balconyheight( Float height )
+

    minimum height a balcony guy must fall to do special balcony death
+ +

balconyheight
+

    minimum height a balcony guy must fall to do special balcony death
+ +

balconyheight( Float height )
+

    minimum height a balcony guy must fall to do special balcony death
+ +

bedead
+

    Forces the actor to be instantly and totally dead; no death animation is played
+ +

blendtime
+

    Set the crossblend time to something other than the default, in seconds
+ +

blendtime
+

    Get the crossblend time
+ +

breakspecial
+

    tell ai to break special attack
+ +

calcgrenadetoss( Vector target_position )
+

    Called to calculate a grenade toss. Must be called before a grenade throwing animation.
    +Returns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.
    +Should be called infrequently, and never during the middle of a grenade toss.
+ +

calcgrenadetoss2( Vector target_position, Float speed )
+

    Called to calculate a grenade toss. Must be called before a grenade throwing animation.
    +Returns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.
    +Should be called infrequently, and never during the middle of a grenade toss.
    + The speed parameter is optional. Pass a speed if you just want to override and throw no matter what...
+ +

canmoveto( Vector position )
+

    returns a boolean if the AI can move to a point; for use in anim scripts
+ +

canshoot( Vector shootOrigin )
+

    Determines if it would be possible to shoot the sentient's enemy from the given position.
+ +

canshootenemyfrom( Vector shootOrigin )
+

    Determines if it would be possible to shoot the sentient's enemy from the given position.
+ +

crawlto( String dest )
+

    Specify the location to crawl to.
+ +

crouchto( String dest )
+

    Specify the location to crouch to.
+ +

curiousoff
+

    Turn off an actor's curious state
+ +

curiouson
+

    Turn on an actor's curious state
+ +

damagepuff( Vector position, Vector direction )
+

    Spawns a puff of 'blood' smoke at the speficied location in the specified direction.
+ +

deathembalm
+

    preps the dead actor for turning nonsolid gradually over time
+ +

deathhandler
+

    Sets the current script that will handle death events
+ +

deathhandler
+

    Gets the current script that will handle death events
+ +

deathsinkstart
+

    Makes the entity sink into the ground and then get removed (this starts it).
+ +

defaultnonvislevel
+

    updates the default value for 'nonvislevel'
+ +

delete
+

    Removes this listener immediately.
+ +

detachgrenade
+

    Used only by grenade return animations to tell the code when to throw the grenade
+ +

disguise_accept_thread
+

    Gets the name of the thread for the actor to start when accepting papers
+ +

disguise_accept_thread( String value )
+

    Sets the name of the thread for the actor to start when accepting papers
+ +

disguise_accept_thread( String value )
+

    Sets the name of the thread for the actor to start when accepting papers
+ +

disguise_level( Integer value )
+

    Sets the disguise level of the actor. May be 1 or 2
+ +

disguise_level
+

    Gets the disguise level of the actor. May be 1 or 2
+ +

disguise_level( Integer value )
+

    Sets the disguise level of the actor. May be 1 or 2
+ +

disguise_period( Float period_in_seconds )
+

    Sets the time between the end of one disguise behavior and start of the next
+ +

disguise_period( Float period_in_seconds )
+

    Sets the time between the end of one disguise behavior and start of the next
+ +

disguise_period
+

    Gets the time between the end of one disguise behavior and start of the next
+ +

disguise_range( Float range_in_units )
+

    Sets the maximum distance for disguise behavior to get triggered
+ +

disguise_range
+

    Gets the maximum distance for disguise behavior to get triggered
+ +

disguise_range( Float range_in_units )
+

    Sets the maximum distance for disguise behavior to get triggered
+ +

distancetoenemy
+

    Get the distance from the Actor to its enemy
+ +

doActivate( Entity activatingEntity )
+

    General trigger event for all entities
+ +

dumb
+

    Make Actor dumb.
+ +

emotion
+

    The method of setting the facial expression of the Actor
+ +

enableEnemy
+

    sets enableEnemy variable
+ +

enablePain
+

    sets enablePain variable
+ +

endactionanim( )
+

    End any aiming/action animation which is currently playing
+ +

enemy
+

    Get the actor's current enemy
+ +

enemysharerange
+

    gets the range outside which the AI will not receive notification that a teammate has a new enemy
+ +

enemysharerange( Float range )
+

    sets the range outside which the AI will not receive notification that a teammate has a new enemy
+ +

enemysharerange( Float range )
+

    sets the range outside which the AI will not receive notification that a teammate has a new enemy
+ +

enemyswitchdisable
+

    Disable enemy switching...
+ +

enemyswitchenable
+

    Enable enemy switching...
+ +

enemy_visible_change_time
+

    Get the last time whether or not the enemy is visible changed, in seconds
+ +

entitystart
+

    Initialize a Actor.
+ +

eyeslookat( Entity entity )
+

    The actor will look at this entity.
+ +

fallheight( Float height )
+

    Set the fallheight
+ +

fallheight
+

    Set the fallheight
+ +

favoriteenemy( Entity ai_or_player )
+

    Gets this AI's favorite enemy
+ +

favoriteenemy( Entity ai_or_player )
+

    Gets this AI's favorite enemy
+ +

favoriteenemy
+

    Gets this AI's favorite enemy
+ +

findenemy
+

    Finds the best enemy to target
+ +

fire_grenade
+

    Used only by grenade throw animations to tell the code when to throw a grenade
+ +

fixedleash( Float multiplier )
+

    if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset
+ +

fixedleash( Float multiplier )
+

    if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset
+ +

fixedleash
+

    if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset
+ +

fov
+

    The fov angle of the actor
+ +

fov( Float angle )
+

    The fov angle of the actor
+ +

fov( Float angle )
+

    The fov angle of the actor
+ +

GetRunAnim
+

    Internal usage
+ +

GetWalkAnim
+

    Internal usage
+ +

gren_awareness( Float awareness_percent )
+

    sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)
+ +

gren_awareness( Float awareness_percent )
+

    sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)
+ +

gren_awareness
+

    gets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)
+ +

gun( String s )
+

    specifies the gun to use
+ +

gun( String s )
+

    specifies the gun to use
+ +

gun
+

    gets the gun to being used
+ +

hascompletelookahead
+

    returns true if there are no corners to turn on the rest of the AI's current path
+ +

headmodel
+

    gets the head model
+ +

headmodel( String headmodel )
+

    sets the head model
+ +

headskin
+

    gets the head skin
+ +

headskin( String headskin )
+

    sets the head skin
+ +

hearing( Float radius )
+

    The hearing radius of the actor
+ +

hearing( Float radius )
+

    The hearing radius of the actor
+ +

hearing( Float radius )
+

    The hearing radius of the actor
+ +

holster( Integer holster )
+

    If non-zero, affects offhand. Holster weapon
+ +

idlesay( String animation )
+

    The name of an idle dialog animation to play
+ +

ignorebadplaces( Integer ignore )
+

    sets whether or not this AI guy will ignore bad places (0 = not suicidal)
+ +

ignorebadplaces
+

    gets whether or not this AI guy will ignore bad places (0 = not suicidal)
+ +

ignorebadplaces( Integer ignore )
+

    sets whether or not this AI guy will ignore bad places (0 = not suicidal)
+ +

immediateremove
+

    Removes this listener immediately.
+ +

inreload
+

    returns non-zero if the AI is in a reload
+ +

inreload( Integer reloading )
+

    set to non-zero to indicate the AI is in a reload
+ +

interrupt_point
+

    hint from animation scripts to AI code that now is a good time to switch animations
+ +

interval( Float distance )
+

    Sets the distance AI tries to keep between squadmates while moving.
+ +

interval( Float distance )
+

    Sets the distance AI tries to keep between squadmates while moving.
+ +

interval
+

    Gets the distance AI tries to keep between squadmates while moving.
+ +

intervaldir
+

    the direction the AI would like to move to maintain its interval
+ +

is_enemy_visible
+

    0 if the enemy is not currently visible, 1 if he is
+ +

kickdir
+

    Gets the direction the AI wants to kick
+ +

killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
+

    event which is sent to an entity once it as been killed
    +
    +Location values:
    +-1 General
    +0 Pelvis
    +1 Lower Torso
    +2 Mid Torso
    +3 Upper Torso
    +4 Neck
    +5 Head
    +6 RUpperArm
    +7 RForearm
    +8 RHand
    +9 LUpperArm
    +10 LForearm
    +11 LHand
    +12 RThigh
    +13 RCalf
    +14 RFoot
    +15 LThigh
    +16 LCalf
    +17 LFoot
    +
+ +

last_enemy_visible_time
+

    Get the last time the enemy was visible, in seconds
+ +

leash( Float distance )
+

    Sets the maximum distance the AI will wander from its leash home
+ +

leash( Float distance )
+

    Sets the maximum distance the AI will wander from its leash home
+ +

leash
+

    Gets the maximum distance the AI will wander from its leash home
+ +

lookaroundangle( Float angle )
+

    gets the angle in degrees left or right of center that the AI will look around while patrolling
+ +

lookaroundangle
+

    gets the angle in degrees left or right of center that the AI will look around while patrolling
+ +

lookaroundangle( Float angle )
+

    gets the angle in degrees left or right of center that the AI will look around while patrolling
+ +

lookat( Entity entity )
+

    The actor will look at this entity.
+ +

maxdist( Float distance )
+

    Sets the maximum distance the AI tries to allow between itself and the player
+ +

maxdist( Float distance )
+

    Sets the maximum distance the AI tries to allow between itself and the player
+ +

maxdist
+

    Gets the maximum distance the AI tries to keep between itself and the player
+ +

mindist( Float distance )
+

    Sets the minimum distance the AI tries to keep between itself and the player
+ +

mindist
+

    Gets the minimum distance the AI tries to keep between itself and the player
+ +

mindist( Float distance )
+

    Sets the minimum distance the AI tries to keep between itself and the player
+ +

mood
+

    gets the AI mood: 'bored', 'nervous', 'curious', or 'alert'.
+ +

mood( String new_mood )
+

    sets the AI mood... must be 'bored', 'nervous', 'curious', or 'alert'.
+ +

movedir
+

    Returns a unit vector pointing in the current direction of motion, or zero if not moving.This still has meaning if velocity is zero but the AI is starting to move on a path.
+ +

movedoneradius( Float radius )
+

    Set the waittill movedone radius, default 0 means don't use manual radius
+ +

movedoneradius( Float radius )
+

    Set the waittill movedone radius, default 0 means don't use manual radius
+ +

moveto( String anim, String dest )
+

    Specify the location to move to, with animation anim.
+ +

mumble( Integer can_mumble )
+

    Set to 1 if this guy is allowed to mumble, or 0 if he is not
+ +

mumble( Integer can_mumble )
+

    Set to 1 if this guy is allowed to mumble, or 0 if he is not
+ +

mumble
+

    Returns 1 if this guy is allowed to mumble, or 0 if he is not
+ +

nationality
+

    Get the nationality of an actor. Return values are ger, it, usa, uk, ussr and unset.
+ +

nationality( String nationality )
+

    Set the nationality of an actor. Valid entries are default, ger, it, usa, uk, and ussr.
+ +

nationality( String nationality )
+

    Set the nationality of an actor. Valid entries are default, ger, it, usa, uk, and ussr.
+ +

nolongpain( Integer allow )
+

    Set to 1 if long pain is not allowed, or 0 if long pain is allowed.
+ +

nolongpain( Integer allow )
+

    Set to 1 if long pain is not allowed, or 0 if long pain is allowed.
+ +

nolongpain
+

    Returns 1 if long pain is not allowed, or 0 if long pain is allowed.
+ +

nonvislevel
+

    visibility level in range 0-1 below which an enemy is treated as non-visible
+ +

nonvislevel
+

    visibility level in range 0-1 below which an enemy is treated as non-visible
+ +

nonvislevel
+

    visibility level in range 0-1 below which an enemy is treated as non-visible
+ +

nosurprise( Integer nosurprise )
+

    set to 0 to allow this guy to play a surprised animation when first encountering an enemy.
    +
+ +

nosurprise
+

    gets whether or not this guy is allowed to play a surprised animation when first encountering an enemy.
    +
+ +

nosurprise( Integer nosurprise )
+

    set to 0 to allow this guy to play a surprised animation when first encountering an enemy.
    +
+ +

noticescale( Float multiplier )
+

    Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)
+ +

noticescale
+

    Get the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)
+ +

noticescale( Float multiplier )
+

    Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)
+ +

no_idle
+

    Gets if the actor will not go into idle after playing an animation
+ +

no_idle
+

    Specifies if the actor will not go into idle after playing an animation
+ +

pain( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
+

    used to inflict pain to an entity
+ +

painhandler
+

    Gets the current script that will handle pain events
+ +

painhandler
+

    Sets the current script that will handle pain events
+ +

pathdist
+

    returns total distance along current path to the path goal
+ +

patrolpath( String value )
+

    Sets the name of the patrol path for the actor (must have type set to patrol for effect)
+ +

patrolpath( String value )
+

    Sets the name of the patrol path for the actor (must have type set to patrol for effect)
+ +

patrolpath
+

    Gets the name of the patrol path for the actor (must have type set to patrol for effect)
+ +

physics_off
+

    turn physics off.
+ +

physics_on
+

    turn physics on.
+ +

playsound( String soundName, [ Integer channel ], [ Float volume ], [ String min_distance ] )
+

    play a sound coming from this entity.
    +default channel, CHAN_BODY.
+ +

pointat( Entity entity )
+

    The actor will point at this entity.
+ +

position
+

    The Position the Actor wants to be and should animate towards
+ +

position
+

    The Position the Actor wants to be and should animate towards
+ +

prealarmthread( String value )
+

    Sets the name of the pre alarm thread for the actor (must have type set to alarm for effect)
+ +

prealarmthread( String value )
+

    Sets the name of the pre alarm thread for the actor (must have type set to alarm for effect)
+ +

ReadyToFire
+

    Returns if ready to fire
+ +

reload_mg42
+

    Reload the mg42 - only used by machinegunner
+ +

remove
+

    Removes this listener the next time events are processed.
+ +

resetleash
+

    resets the AI's leash to their current position
+ +

runanimrate
+

    Get the rate at which the run animation plays back
+ +

runanimrate( Float multiplier )
+

    Set the rate at which the run animation plays back
+ +

runanimrate( Float multiplier )
+

    Set the rate at which the run animation plays back
+ +

runto( String dest )
+

    Specify the location to run to.
+ +

say( String animation )
+

    The name of a dialog animation to play
+ +

saydone
+

    Even used by sound-only special case of say to trigger waittill saydone
+ +

setactionanim( String base_anim, Float lower_limit, Float upper_limit )
+

    Set the base action animation and range that they cover
+ +

setaimmotionanim( String anim_crouch, String anim_stand )
+

    Set aim motion animation (handler scripts only)
+ +

setaimtarget( Entity entity, Integer bMakeEnemy )
+

    Sets the primary weapon's aim target. if you pass a 1 for p2, the target will become the current enemy...
+ +

setanim( String anim, Integer slot, Float weight, String flagged )
+

    Set animation slot
+ +

setanimlength( Float time )
+

    Set the maximum time an animation will play
+ +

setmotionanim( String anim )
+

    Set motion animation (handler scripts only)
+ +

setreloadcover
+

    do this command to let the ai know it needs to reload; used to reload while going to cover
+ +

setsay( String animation )
+

    The name of a dialog animation to play - used by animation script only
+ +

setupperanim( String anim )
+

    Set the upper body animation - used by animation script only
+ +

share_enemy
+

    internal code use only - shares an AI's enemy with his squad mates.
+ +

share_grenade
+

    internal code use only - shares an AI's grenade with his squad mates.
+ +

sight
+

    Gets the vision distance of the actor.
+ +

sight( Float max_sight_range )
+

    Sets the vision distance of the actor.
+ +

sight( Float max_sight_range )
+

    Sets the vision distance of the actor.
+ +

silent( Integer silent )
+

    set to 0 to prevent this guy from saying stuff besides pain and death sounds.
    +
+ +

silent
+

    gets whether or not this guy is allowed to say stuff besides pain and death sounds
+ +

silent( Integer silent )
+

    set to 0 to prevent this guy from saying stuff besides pain and death sounds.
    +
+ +

sound_awareness( Float awareness_percent )
+

    sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius
+ +

sound_awareness
+

    gets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius
+ +

sound_awareness( Float awareness_percent )
+

    sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius
+ +

stopped
+

    sent when entity has stopped bouncing for MOVETYPE_TOSS.
+ +

suppresschance
+

    sets the percent chance of doing suppressing fire when appropriate (0-100)
+ +

suppresschance
+

    sets the percent chance of doing suppressing fire when appropriate (0-100)
+ +

suppresschance
+

    sets the percent chance of doing suppressing fire when appropriate (0-100)
+ +

tether( Entity entity )
+

    the entity to which the AI's leash should be tethered
+ +

thinkstate
+

    current ai think state; can be void, idle, pain, killed, attack, curious, disguise, or grenade.
+ +

turndoneerror
+

    The error amount that turndone will occur for the turnto command.
+ +

turndoneerror( Float error )
+

    The error amount that turndone will occur for the turnto command.
+ +

turndoneerror( Float error )
+

    The error amount that turndone will occur for the turnto command.
+ +

turnspeed
+

    The turn speed of the actor.
+ +

turnspeed( Float speed )
+

    The turn speed of the actor.
+ +

turnspeed( Float speed )
+

    The turn speed of the actor.
+ +

turnto( Entity entity )
+

    The actor will turn to this entity.
+ +

turret( String turret )
+

    Sets the turret of the actor.
+ +

turret( String turret )
+

    Sets the turret of the actor.
+ +

turret
+

    Gets the turret of the actor.
+ +

type_attack
+

    Gets the attack type of the actor.
+ +

type_attack( String value )
+

    Sets the attack type of the actor.
+ +

type_attack( String value )
+

    Sets the attack type of the actor.
+ +

type_disguise
+

    Gets the disguise type of the actor.
+ +

type_disguise( String value )
+

    Sets the disguise type of the actor.
+ +

type_disguise( String value )
+

    Sets the disguise type of the actor.
+ +

type_grenade( String value )
+

    Sets the grenade type of the actor.
+ +

type_grenade( String value )
+

    Sets the grenade type of the actor.
+ +

type_grenade
+

    Gets the grenade type of the actor.
+ +

type_idle
+

    Gets the idle type of the actor.
+ +

type_idle( String value )
+

    Sets the idle type of the actor.
+ +

type_idle( String value )
+

    Sets the idle type of the actor.
+ +

unholster( Integer holster )
+

    If non-zero, affects offhand. Unholster weapon
+ +

upperanim( String anim )
+

    Set the upper body animation
+ +

use( String name, Integer weapon_hand )
+

    Use the specified weapon or item in the hand choosen (optional).
+ +

voicetype
+

    Set voicetype to magic letter postfix
+ +

voicetype
+

    Set voicetype to magic letter postfix
+ +

voicetype
+

    Gets the voice type
+ +

waittrigger
+

    If true, patrol guys and running men wait until triggered to move
+ +

waittrigger( Boolean bool )
+

    If true, patrol guys and running men wait until triggered to move
+ +

waittrigger( Boolean bool )
+

    If true, patrol guys and running men wait until triggered to move
+ +

walkto( String dest )
+

    Specify the location to walk to.
+ +

weapon( String weapon_modelname )
+

    Sets the weapon.
+ +

weapon
+

    Gets the weapon.
+ +

weapon( String weapon_modelname )
+

    Gives the sentient the weapon specified.
+ +

weapongroup
+

    Specifies weapon animation set to use in anim scripts
+ +

weapontype
+

    The Weapon Type of the Actor
+ +

weapon_internal( String s )
+

    internal use
+ +

writestats
+

    Used internally to write stats to a CSV file.
+
+ +

AISpawnPoint (info_aispawnpoint) -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

+
+ +

accuracy( Float value )
+

    Set percent to hit
+ +

accuracy
+

    Set percent to hit
+ +

alarmnode( String value )
+

    Sets the name of the alarm node for the actor (must have type set to alarm for effect)
+ +

alarmnode
+

    Gets the name of the alarm node for the actor (must have type set to alarm for effect)
+ +

ammo_grenade
+

    Returns how many grenades an AI has
+ +

ammo_grenade( Integer grenade_count )
+

    Gives the AI some grenades
+ +

balconyheight
+

    minimum height a balcony guy must fall to do special balcony death
+ +

balconyheight( Float height )
+

    minimum height a balcony guy must fall to do special balcony death
+ +

disguise_level( Integer value )
+

    Sets the disguise level of the actor. May be 1 or 2
+ +

disguise_level
+

    Gets the disguise level of the actor. May be 1 or 2
+ +

disguise_period( Float period_in_seconds )
+

    Sets the time between the end of one disguise behavior and start of the next
+ +

disguise_period
+

    Gets the time between the end of one disguise behavior and start of the next
+ +

disguise_range
+

    Gets the maximum distance for disguise behavior to get triggered
+ +

disguise_range( Float range_in_units )
+

    Sets the maximum distance for disguise behavior to get triggered
+ +

dontdrophealth
+

    dontdrophealth setter
+ +

dontdrophealth
+

    dontdrophealth getter
+ +

dontdropweapons( [ Boolean dont_drop ] )
+

    Make the sentient not drop weapons
+ +

dontdropweapons
+

    dontdropweapons getter
+ +

enemyname( String enemyname )
+

    + +

    enemyname( String enemyname )
    +

      + +

      enemyname( String enemyname )
      +

        + +

        enemysharerange
        +

          gets the range outside which the AI will not receive notification that a teammate has a new enemy
        + +

        enemysharerange( Float range )
        +

          sets the range outside which the AI will not receive notification that a teammate has a new enemy
        + +

        favoriteenemy( Entity ai_or_player )
        +

          Gets this AI's favorite enemy
        + +

        favoriteenemy
        +

          Gets this AI's favorite enemy
        + +

        fixedleash( Float multiplier )
        +

          if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset
        + +

        fixedleash
        +

          if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset
        + +

        forcedrophealth
        +

          Get if the sentient is forced to drop health no matter what level.nodrophealth is.
        + +

        forcedropweapon
        +

          Force the sentient to drop weapons no matter what level.nodropweapon is.
        + +

        forcedropweapon
        +

          Get if the sentient is forced to drop health no matter what level.nodrophealth is.
        + +

        fov
        +

          The fov angle of the actor
        + +

        fov( Float angle )
        +

          The fov angle of the actor
        + +

        gren_awareness( Float awareness_percent )
        +

          sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)
        + +

        gren_awareness
        +

          gets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied once every 0.4 seconds)
        + +

        gun( String s )
        +

          specifies the gun to use
        + +

        gun
        +

          gets the gun to being used
        + +

        health( Integer newHealth )
        +

          set the health of the entity to newHealth
        + +

        health
        +

          entity's health
        + +

        hearing( Float radius )
        +

          The hearing radius of the actor
        + +

        hearing( Float radius )
        +

          The hearing radius of the actor
        + +

        interval( Float distance )
        +

          Sets the distance AI tries to keep between squadmates while moving.
        + +

        interval
        +

          Gets the distance AI tries to keep between squadmates while moving.
        + +

        leash( Float distance )
        +

          Sets the maximum distance the AI will wander from its leash home
        + +

        leash
        +

          Gets the maximum distance the AI will wander from its leash home
        + +

        maxdist( Float distance )
        +

          Sets the maximum distance the AI tries to allow between itself and the player
        + +

        maxdist
        +

          Gets the maximum distance the AI tries to keep between itself and the player
        + +

        mindist( Float distance )
        +

          Sets the minimum distance the AI tries to keep between itself and the player
        + +

        mindist
        +

          Gets the minimum distance the AI tries to keep between itself and the player
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        model
        +

          get the modelName.
        + +

        nosurprise
        +

          gets whether or not this guy is allowed to play a surprised animation when first encountering an enemy.
          +
        + +

        nosurprise( Integer nosurprise )
        +

          set to 0 to allow this guy to play a surprised animation when first encountering an enemy.
          +
        + +

        noticescale
        +

          Get the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)
        + +

        noticescale( Float multiplier )
        +

          Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)
        + +

        patrolpath( String value )
        +

          Sets the name of the patrol path for the actor (must have type set to patrol for effect)
        + +

        patrolpath
        +

          Gets the name of the patrol path for the actor (must have type set to patrol for effect)
        + +

        sight
        +

          Gets the vision distance of the actor.
        + +

        sight( Float max_sight_range )
        +

          Sets the vision distance of the actor.
        + +

        sound_awareness( Float awareness_percent )
        +

          sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius
        + +

        sound_awareness
        +

          gets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades to zero outside sound's radius
        + +

        target
        +

          entity's target
        + +

        target( String targetname_to_target )
        +

          target another entity with targetname_to_target.
        + +

        turret( String turret )
        +

          Sets the turret of the actor.
        + +

        turret
        +

          Gets the turret of the actor.
        + +

        type_attack
        +

          Gets the attack type of the actor.
        + +

        type_attack( String value )
        +

          Sets the attack type of the actor.
        + +

        type_disguise
        +

          Gets the disguise type of the actor.
        + +

        type_disguise( String value )
        +

          Sets the disguise type of the actor.
        + +

        type_grenade( String value )
        +

          Sets the grenade type of the actor.
        + +

        type_grenade
        +

          Gets the grenade type of the actor.
        + +

        type_idle
        +

          Gets the idle type of the actor.
        + +

        type_idle( String value )
        +

          Sets the idle type of the actor.
        + +

        voicetype
        +

          Set voicetype to magic letter postfix
        + +

        voicetype
        +

          Gets the voice type
        + +

        waittrigger
        +

          If true, patrol guys and running men wait until triggered to move
        + +

        waittrigger( Boolean bool )
        +

          If true, patrol guys and running men wait until triggered to move
        + +

        weapon( String weapon_modelname )
        +

          Sets the weapon.
        + +

        weapon
        +

          Gets the weapon.
        +
        + +

        Ammo -> Class

        +
        +
        + +

        AmmoEntity -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        ammoentity_postspawn
        +

          Ammo Entity Post Spawn
        +
        + +

        Animate (animate) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        anim( String animName )
        +

          Exec anim commands on server or client.
        + +

        isloopinganim( String anim_name )
        +

          returns 1 if the anim is a looping anim, or 0 otherwise
        + +

        pauseanims( Integer pause )
        +

          Pause (or unpause) animations
        + +

        playerspawn( String model_name, [ Float range ], [ Vector vector_offset ], [ Float inFOV ], [ Float speed ] )
        +

          spawn something near the player, either within the player's view or behind him
          +model - name of model to spawn
          +range - how close does this need to be to the player to actually get spawned, default 480 (30 foot radius).
          +vector_offset - oriented vector offset of where to spawn the item, default (0 0 0)
          +inFOV -
          + 1 - Only spawn when this position is within the FOV of the player
          + -1 - Only spawn when this position is outside the FOV of the player
          + 0 - (default) don't care, always spawn
          +speed - how fast the effect should travel, in other words, how long before the effect gets spawned.
          + delay is calculated based on the distance between object and player divided by the speed
          + 0 - no delay
          + 960 - (default) 60 feet per second. If the object is 60 feet from the player, the player effect will spawn one second later.
        + +

        setcontrollerangles( Integer num, Vector angles )
        +

          Sets the control angles for the specified bone.
        + +

        setsynctime( Float synctime )
        +

          Set sync time for entity.
        + +

        setyawfrombone( String bone_name )
        +

          Set the yaw of the model based on the current animation time
        + +

        testmojo( String model_name, Vector vector_offset )
        +

          INTERNAL EVENT
        +
        + +

        AnimationEvent -> Event -> Class

        +
        +
        + +

        Armor -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        AttractiveNode -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        + +

        max_dist
        +

          Get the max distance for this node
        + +

        max_dist( Float max_dist )
        +

          Set the max distance for this node to be attracted, -1 for unlimited distance.
        + +

        priority( Integer priority )
        +

          Set the node priority
        + +

        priority
        +

          Get the node priority
        + +

        respawn_time( Float respawn_time )
        +

          Set the how much time will this node re-attract already attracted AIs. The minimum required value is 1, otherwise AI will get stuck.
        + +

        respawn_time
        +

          Get the how much time will this node re-attract already attracted AIs
        + +

        setuse( Boolean use )
        +

          Set if AI should use or not
        + +

        stay_time
        +

          Get the max stay time for this node
        + +

        stay_time( Float stay_time )
        +

          Set the maximum stay time AI will stay on this node
        + +

        team( String team )
        +

          Set the attractive node team. 'none' for no team.
        + +

        team
        +

          Get the attractive node team. 'none' for no team.
        +
        + +

        BarrelObject (func_barrel) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        barreltype( String type )
        +

          Sets the barrel's type
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        Body -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Camera (func_camera) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angles( Vector newAngles<0.00...360.00><0.00...360.00><0.00...360.00> )
        +

          set the angles of the entity to newAngles.
        + +

        auto_active( Boolean newActiveState )
        +

          Whether or not the auto camera is active.
        + +

        auto_maxfov( Float maxFOV )
        +

          Sets the maximum FOV that should be used when automatically calculating FOV.
        + +

        auto_radius( Float newRadius )
        +

          Sets the radius of the automatic camera.
        + +

        auto_starttime( Float newTime )
        +

          Sets how long it takes for the camera to be switched to.
        + +

        auto_state( String state1, [ String state2 ], [ String state3 ], [ String state4 ], [ String state5 ], [ String state6 ] )
        +

          Sets the states the player needs to be in for this camera to activate.
        + +

        auto_stoptime( Float newTime )
        +

          Sets how long it takes for the camera switch back to the player.
        + +

        camera_think
        +

          Called each frame to allow the camera to adjust its position.
        + +

        continue
        +

          Continue the camera movement.
        + +

        cut
        +

          switch camera states immediately, do not transition
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        fadetime( Float fadetime )
        +

          Sets the fade time for camera transitioning.
        + +

        follow( Entity targetEnt, [ Entity targetWatchEnt ] )
        +

          Makes the camera follow an entity and optionally watch an entity.
        + +

        follow_distance( Float distance )
        +

          Sets the camera follow distance.
        + +

        follow_yaw( Float yaw )
        +

          Sets the yaw offset of the camera following an entity.
        + +

        follow_yaw_absolute
        +

          Makes the follow camera yaw absolute.
        + +

        follow_yaw_relative
        +

          Makes the follow camera yaw relative (not absolute).
        + +

        fov( Float fov, [ Float fadeTime ] )
        +

          Sets the camera's field of view (fov).
          +if fadeTime is specified, camera will fade over that time
          +if fov is less than 3, than an auto_fov will be assumed
          +the value of fov will be the ratio used for keeping a watch
          +entity in the view at the right scale
        + +

        lookat( Entity ent )
        +

          Makes the camera look at an entity.
        + +

        moveto( Entity ent )
        +

          Move the camera's position to that of the specified entities.
        + +

        movetopos( Vector position )
        +

          Move the camera's position to the specified position.
        + +

        nextcamera( String nextCamera )
        +

          Sets the next camera to use.
        + +

        nowatch( [ Float fadeTime ] )
        +

          Stop watching an entity or looking along a path.
          +Camera is now static as far as orientation.
          +if fadeTime is specified, camera will fade over that time
        + +

        orbit( Entity targetEnt, [ Entity targetWatchEnt ] )
        +

          Makes the camera orbit around an entity and optionally watch an entity.
        + +

        orbit_height( Float height )
        +

          Sets the orbit camera's height.
        + +

        pause
        +

          Pause the camera.
        + +

        showquakes( Boolean showquakes )
        +

          Sets the camera to show or not show earthquake effects from the player triggered either from the earthquake command, or a viewjitter.
        + +

        speed( Float speed )
        +

          Sets the camera speed.
        + +

        start
        +

          Start camera moving.
        + +

        stop
        +

          Stop the camera movement.
        + +

        turnto( Vector angle )
        +

          Makes the camera look in the specified direction.
        + +

        watch( Entity watchEnt, [ Float fadeTime ] )
        +

          Makes the camera watch an entity.
          +if fadeTime is specified, camera will fade over that time
        + +

        watchnode( [ Float fadeTime ] )
        +

          Makes the camera watch based on what is stored
          +in the camera nodes.
          +if fadeTime is specified, camera will fade over that time
        + +

        watchpath( [ Float fadeTime ] )
        +

          Makes the camera look along the path of travel.
          +if fadeTime is specified, camera will fade over that time
        + +

        watchstring( String string, [ Float fadeTime ] )
        +

          Makes the camera watch based on a string.
          +if fadeTime is specified, camera will fade over that time
        +
        + +

        CameraManager -> Listener -> Class

        +
        + +

        add
        +

          Add a new point to the camera path where the player is standing.
        + +

        delete
        +

          Delete the current path node.
        + +

        hide
        +

          Hides the paths.
        + +

        load( String filename )
        +

          Loads a camera path.
        + +

        loop( [ Entity path ] )
        +

          Loop the current path or the specified one.
        + +

        moveplayer
        +

          Move the player to the current path node position.
        + +

        new
        +

          Starts a new path.
        + +

        next
        +

          Go to the next path node.
        + +

        nextpath
        +

          Go to the next path.
        + +

        nowatch
        +

          Set the current path node to watch nothing.
        + +

        play( [ Entity path ] )
        +

          Play the current path or the specified one once.
        + +

        prev
        +

          Go to the previous path node.
        + +

        prevpath
        +

          Go to the previous path.
        + +

        renamepath( String newName )
        +

          Rename the path to the new name.
        + +

        replace
        +

          Replace the current path node position/angle with the player's.
        + +

        save( String filename )
        +

          Saves the camera path.
        + +

        savemap( String filename )
        +

          Saves the camera path to a map file.
        + +

        setfadetime( Float newFadeTime )
        +

          Set the fadetime of the current path node.
        + +

        setfov( String newFOV )
        +

          Set the fov at the current path node.
        + +

        setpath( Entity path )
        +

          Sets the new path.
        + +

        setspeed( Float speed )
        +

          Set the speed of the camera at the current path node.
        + +

        settarget( String target )
        +

          Set the trigger target.
        + +

        settargetname( String targetname )
        +

          Set the targetname.
        + +

        show( [ Entity path ] )
        +

          Shows the specified path.
        + +

        stop
        +

          Stop the camera playing path.
        + +

        updateinput
        +

          Updates the current node with user interface values.
        + +

        watch( String watch )
        +

          Set the current path node to watch something.
        +
        + +

        CarryableTurret -> InventoryItem -> Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        dropturret
        +

          Makes the carryable turret have itself dropped
        + +

        item_pickup( Entity item )
        +

          Pickup the specified item.
        + +

        placeturret
        +

          Try to place the carryable turret
        + +

        turrettik
        +

          Tiki of the turret to place
        +
        + +

        Class

        +
        +
        + +

        Conditional -> Class

        +
        +
        + +

        ConsoleEvent -> Event -> Class

        +
        +
        + +

        CrateObject (func_crate) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        debristype( Integer type )
        +

          Sets the debris type of the crate
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        DamageModel (DamageModel) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killthread( String thread )
        +

          Set the thread to execute when this model is killed
        + +

        killtrace( Vector offset, Vector direction, Float radius, Float distance )
        +

          kills all objects along the trace
          +offset - initial offset from origin
          +direction - angular offset orientation for trace
          +radius - thickness of trace
          +distance - how far to trace
        + +

        orientedbbox( Vector mins, Vector maxs, Float yawoffset )
        +

          spawn an oriented bounding box with the given dimensions and an angular offset
          +mins - min dimensions of box
          +maxs - max dimensions of box
          +yawoffset - angular offset orientation of box
        +
        + +

        Decal -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        DM_Manager -> Listener -> Class

        +
        + +

        doroundtransition
        +

          delayed function call to (possibly) determine round winner and restart next round
        + +

        finishroundtransition
        +

          delayed function call to do the actual restart for the next round
        +
        + +

        DM_Team -> Listener -> Class

        +
        +
        + +

        Door (NormalDoor) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        alwaysaway( [ Boolean bAlwaysAway ] )
        +

          Makes the door always open away from the person opening it.
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        close
        +

          Closes the door.
        + +

        dmg( Integer damage )
        +

          Sets the amount of damage the door will do to entities that get stuck in it.
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        doBlocked( Entity obstacle )
        +

          sent to entity when blocked.
        + +

        doorclosed
        +

          Called when the door finishes closing.
        + +

        dooropened
        +

          Called when the door finishes opening.
        + +

        doortype( String door_type )
        +

          Sets the defaults for this door
          +Door Defaults: wood(default)
          +metal
        + +

        door_triggerfield( Entity other )
        +

          Is called when a doors trigger field is touched.
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        linkdoor
        +

          Link doors together.
        + +

        lock
        +

          Lock the door.
        + +

        open( Entity other )
        +

          Opens the door.
        + +

        sound_close_end( String sound_close )
        +

          Sets the sound to use when the door closes.
        + +

        sound_close_start( String sound_close )
        +

          Sets the sound to use when the door closes.
        + +

        sound_locked( String sound_locked )
        +

          Sets the sound to use when the door is locked.
        + +

        sound_message( String sound_message )
        +

          Sets the sound to use when the door displays a message.
        + +

        sound_open_end( String sound_open_end )
        +

          Sets the sound to use when the door stops to opens.
        + +

        sound_open_start( String sound_open_start )
        +

          Sets the sound to use when the door starts to opens.
        + +

        time( Float traveltime )
        +

          Sets the time it takes for the door to open an close.
        + +

        toggledoor( Entity other )
        +

          Toggles the state of the door (open/close).
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        + +

        trysolid
        +

          Trys to make the door solid.
        + +

        tryToOpen( Entity other )
        +

          Tries to open the door.
        + +

        unlock
        +

          Unlock the door.
        + +

        wait( Float wait )
        +

          Sets the amount of time to wait before automatically shutting.
        +
        + +

        DrivableVehicle (script_drivablevehicle) -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        DrivableVehicleTandem (DrivableVehicleTandem) -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        DynItem -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        kill
        +

          console based command to kill yourself if stuck.
        +
        + +

        EffectEntity (effectentity) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Emitter (func_emitter) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        emitter( String name )
        +

          Emitter to use
        +
        + +

        Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        ai_event( [ String type ], [ Float radius ] )
        +

          Let the AI know that this entity made a sound,
          +type is a string specifying what type of sound it is.
          +radius determines how far the sound reaches.
        + +

        alpha( Float newAlpha )
        +

          Set the alpha of the entity to alpha.
        + +

        alwaysdraw
        +

          Sets this entity to always draw
        + +

        attach( Entity parent, String tagname, [ Integer use_angles ] )
        +

          attach this entity to the parent's legs tag called tagname
        + +

        attachedmodelanim( String tagname, String anim_name, Float crossblend_time, String model_name )
        +

          Tells models (or specified model) attached to specified tag to play
          +specified animation. Crossblend time doesn't work yet.
        + +

        attachmodel( String modelname, String tagname, [ Float scale ], [ String targetname ], [ Boolean detach_at_death ], [ Float removetime ], [ Float fadeintime ], [ Float fadeoutdelay ], [ Float fadetime ], [ Vector offset ] )
        +

          attach a entity with modelname to this entity to tag called tagname.
          +scale - scale of attached entities
          +targetname - targetname for attached entities
          +detach_at_death - when entity dies, should this model be detached.
          +removetime - when the entity should be removed, if not specified, never.
          +fadeintime - time to fade the model in over.
          +fadeoutdelay - time to wait until we fade the attached model out
          +fadeoutspeed - time the model fades out over
          +offset - vector offset for the model from the specified tag
        + +

        avelocity
        +

          gets the angular velocity for this entity.
        + +

        bind( Entity parent, [ Boolean bind_child ] )
        +

          bind this entity to the specified entity.
        + +

        brushmodel
        +

          get the brush modelName.
        + +

        cansee( Entity entity, [ Float fov ], [ Float vision_distance ] )
        +

          returns 1 if the entities can see eachother, 0 if not
        + +

        censor
        +

          used to ban certain contact when in parentmode
          +
        + +

        classname( String nameOfClass )
        +

          Determines what class to use for this entity,
          +this is pre-processed from the BSP at the start
          +of the level.
        + +

        classname
        +

          The entity's classname
        + +

        claypidgeon
        +

          turn the entity into a non-solid shootable thing
        + +

        connect_paths
        +

          Connects all navigation paths which intersect with the specified entity's volume
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        damage_type( String meansofdeathstring )
        +

          Set the type of damage that this entity can take
        + +

        deathsinkeachframe
        +

          Makes the entity sink into the ground and then get removed (this gets called each frame).
        + +

        deathsinkstart
        +

          Makes the entity sink into the ground and then get removed (this starts it).
        + +

        delete
        +

          Removes this listener immediately.
        + +

        depthhack( Integer bEnable )
        +

          Enable or disable depth hack.
        + +

        detach
        +

          detach this entity from its parent.
        + +

        detachallchildren
        +

          Detach all the children from the entity.
        + +

        disconnect_paths
        +

          disonnects all navigation paths which intersect with the specified entity's volume
        + +

        dm( String command, [ String parm1 ], [ String parm2 ], [ String ... ] )
        +

          Makes a command be executed only in multiplayer
        + +

        dmrealism( String command, [ String parm1 ], [ String parm2 ], [ String ... ] )
        +

          Makes a command be executed only in multiplayer realism mode
        + +

        droptofloor( [ Float maxRange ] )
        +

          drops the entity to the ground, if maxRange is not specified 8192 is used.
        + +

        duckableglue( Entity parent, [ Integer glueAngles ] )
        +

          glue this entity to the specified entity, but allow ducking.
        + +

        effects( [ String parameter1 ], [ String parameter2 ], [ String parameter3 ], [ String parameter4 ], [ String parameter5 ], [ String parameter6 ] )
        +

          Change the current entity effects flags.
          +Valid flags are as follows:
          ++ sets a flag, - clears a flag
          +antisbjuice - anti sucknblow juiceeveryframe - process commands every time entity is rendered
        + +

        entnum
        +

          The entity's entity number
        + +

        explosionattack( String explosionModel, [ String tagName ] )
        +

          Spawn an explosion optionally from a specific tag
        + +

        fade( [ Float fadetime<0.00...max_float> ], [ Float target_alpha<0.00...1.00> ] )
        +

          Fade the entity's alpha, reducing it by 0.03
          +every FRAMETIME, until it has faded out, does not remove the entity
        + +

        fadein( [ Float fadetime<0.00...max_float> ], [ Float target_alpha<0.00...1.00> ] )
        +

          Fade the entity's alpha and scale in, increasing it by 0.03
          +every FRAMETIME, until it has faded completely in to 1.0.
          +If fadetime or target_alpha are defined, they will override
          +the default values.
        + +

        fadeout( [ Float fadetime<0.00...max_float> ], [ Float target_alpha<0.00...1.00> ] )
        +

          Fade the entity's alpha and scale out, reducing it by 0.03
          +every FRAMETIME, until it has faded out. If fadetime or
          +target_alpha are defined, they will override the defaults.
          +Once the entity has been completely faded, the entity is removed.
        + +

        flags( [ String parameter1 ], [ String parameter2 ], [ String parameter3 ], [ String parameter4 ], [ String parameter5 ], [ String parameter6 ] )
        +

          Change the current entity flags.
          +Valid flags are as follows:
          ++ sets a flag, - clears a flag
          +blood - should it bleed
          +explode - should it explode when dead
          +die_gibs - should it spawn gibs when dead
          +god - makes the entity invincible
          +
        + +

        forceactivate
        +

          Forces an entity to activate outside of the player's PVS
        + +

        getcontrollerangles( Integer num )
        +

          Gets the control angles for the specified bone.
        + +

        GetLocalYawFromVector
        +

          Turn a worldspace vector into a local space yaw
        + +

        getmaxs
        +

          Get the maxs of the bounding box of the entity to maxs.
        + +

        getmins
        +

          Get the mins of the bounding box of the entity to mins.
        + +

        gettagangles( String tag_name )
        +

          Gets the world angles of the tag
        + +

        gettagposition( String tag_name )
        +

          Gets the world position of the tag
        + +

        ghost
        +

          make non-solid but still send to client regardless of hide status.
        + +

        glue( Entity parent, [ Integer glueAngles ] )
        +

          glue this entity to the specified entity.
        + +

        gravity( Float gravityValue )
        +

          Change the gravity on this entity
        + +

        heal( Float health )
        +

          Adds health to an entity,0-1 fraction of max_health
        + +

        health( Integer newHealth )
        +

          set the health of the entity to newHealth
        + +

        health( Integer newHealth )
        +

          set the health of the entity to newHealth
        + +

        health
        +

          entity's health
        + +

        healthonly( Integer newHealth )
        +

          set the health of the entity to newHealth without changing max_health
        + +

        healthonly( Integer newHealth )
        +

          set the health of the entity to newHealth without changing max_health
        + +

        hide
        +

          hide the entity,opposite of show.
        + +

        hurt( Integer damage, [ String means_of_death ], [ Vector direction ] )
        +

          Inflicts damage if the entity is damageable. If the number of damage
          +points specified in the command argument is greater or equal than the
          +entity's current health, it will be killed or destroyed.
        + +

        immediateremove
        +

          Removes this listener immediately.
        + +

        immune( String immune_string1, [ String immune_string2 ], [ String immune_string3 ], [ String immune_string4 ], [ String immune_string5 ], [ String immune_string6 ] )
        +

          Adds to the immunity list for this sentient.
        + +

        inpvs( Entity entity )
        +

          returns 1 if the entities have connected pvs,0 if not
        + +

        isinside( Entity ent )
        +

          returns 1 if the entity is inside,0 if not
        + +

        istouching( Entity ent )
        +

          returns 1 if the entities are touching,0 if not
        + +

        joinTeam( Entity teamMember )
        +

          join a bind team.
        + +

        kill
        +

          console based command to kill yourself if stuck.
        + +

        killattach
        +

          kill all the attached entities.
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killtarget( String targetName )
        +

          when dying kill entities with this targetName.
        + +

        light( Float red, Float green, Float blue, Float radius )
        +

          Create a dynmaic light on this entity.
        + +

        lightBlue( Float red )
        +

          Set the red component of the dynmaic light on this entity.
        + +

        lightGreen( Float red )
        +

          Set the red component of the dynmaic light on this entity.
        + +

        lightOff
        +

          Turn the configured dynamic light on this entity off.
        + +

        lightOn
        +

          Turn the configured dynmaic light on this entity on.
        + +

        lightRadius( Float red )
        +

          Set the red component of the dynmaic light on this entity.
        + +

        lightRed( Float red )
        +

          Set the red component of the dynmaic light on this entity.
        + +

        lightStyle( Integer lightStyleIndex )
        +

          What light style to use for this dynamic light on this entity.
        + +

        loopsound( String soundName, [ Float volume ], [ String minimum_distance ] )
        +

          play a looped-sound with a certain volume and minimum_distance
          +which is attached to the current entity.
        + +

        mass( Float massAmount )
        +

          set the mass of this entity.
        + +

        max_health( Integer newHealth )
        +

          sets max_health without changing health
        + +

        max_health
        +

          gets the entity's max health
        + +

        max_health( Integer newHealth )
        +

          sets max_health without changing health
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        model
        +

          get the modelName.
        + +

        movementstealth( Float scale )
        +

          Sets the current movement stealth scalar for the sentient
        + +

        neverdraw
        +

          Sets this entity to never draw
        + +

        nodamage
        +

          entity does not take damage.
        + +

        normaldraw
        +

          Sets this entity to normal draw
        + +

        normal_damage
        +

          The Normal Health of the Actor (0 - 100)
        + +

        normal_health
        +

          The Normal Health of the Actor
        + +

        notarget( Boolean setNoTarget )
        +

          flag an entity as no target.
        + +

        notsolid
        +

          make non-solid.
        + +

        playsound( String soundName, [ Integer channel ], [ Float volume ], [ String min_distance ] )
        +

          play a sound coming from this entity.
          +default channel, CHAN_BODY.
        + +

        pusher( Entity inflictor, Entity attacker, Vector direction, Float force )
        +

          Push an entity in the specified direction with the specified force
        + +

        quitTeam
        +

          quit the current bind team
        + +

        radnum
        +

          entity's radnum
        + +

        radnum( Integer radnum )
        +

          set the radnum
        + +

        realism( String command, [ String parm1 ], [ String parm2 ], [ String ... ] )
        +

          Makes a command be executed only in realism mode
        + +

        remove
        +

          Removes this listener the next time events are processed.
        + +

        removeattachedmodel( String tagname )
        +

          Removes the model attached to this entity at the specified tag.
        + +

        removeimmune( String immune_string1, [ String immune_string2 ], [ String immune_string3 ], [ String immune_string4 ], [ String immune_string5 ], [ String immune_string6 ] )
        +

          Removes from the immunity list for this sentient.
        + +

        rendereffects( [ String parameter1 ], [ String parameter2 ], [ String parameter3 ], [ String parameter4 ], [ String parameter5 ], [ String parameter6 ] )
        +

          Change the current render effects flags.
          +Valid flags are as follows:
          ++ sets a flag, - clears a flag
          +dontdraw - send the entity to the client, but don't draw
          +betterlighting - do sphere based vertex lighting on the entity
          +lensflare - add a lens glow to the entity at its origin
          +viewlensflare - add a view dependent lens glow to the entity at its origin
          +lightoffset - use the dynamic color values as a light offset to the model
          +skyorigin - this entity is the portal sky origin
          +minlight - this entity always has some lighting on it
          +fullbright - this entity is always fully lit
          +additivedynamiclight - the dynamic light should have an additive effect
          +lightstyledynamiclight - the dynamic light uses a light style, use the
          +'lightstyle' command to set the index of the light style to be used
        + +

        revive( Float health )
        +

          sets the health,even if dead
        + +

        rotatedbbox
        +

          Gets te entity's bbox to rotate with it.
        + +

        rotatedbbox( Integer on_off )
        +

          Sets the entity's bbox to rotate with it.
        + +

        safesolid
        +

          make solid but first make sure no one is in my bounds that is thinking.
        + +

        saydone
        +

          Even used by sound-only special case of say to trigger waittill saydone
        + +

        scale( Float newScale )
        +

          set the scale of the entity
        + +

        scale( Float newScale )
        +

          set the scale of the entity
        + +

        scale( Float newScale )
        +

          set the scale of the entity
        + +

        scriptshader( String shaderCommand, Float argument1, [ Float argument2 ] )
        +

          alias for shader command, change a specific shader parameter for the entity.
          +Valid shader commands are:
          +translation [trans_x] [trans_y] - change the texture translation
          +offset [offset_x] [offset_y] - change the texture offset
          +rotation [rot_speed] - change the texture rotation speed
          +frame [frame_num] - change the animated texture frame
          +wavebase [base] - change the base parameter of the wave function
          +waveamp [amp] - change the amp parameter of the wave function
          +wavebase [phase] - change the phase parameter of the wave function
          +wavefreq [freq] - change the frequency parameter of the wave function
          +
        + +

        setcontrollerangles( Integer num, Vector angles )
        +

          Sets the control angles for the specified bone.
        + +

        sethintstring( String string )
        +

          Sets the hint string for an entity when touching it. '&&1' will be replaced by the +use key on the client. If hideent/hide is called on this entity, the hint string won't be shown for the client
        + +

        setshader( String shadername )
        +

          Sets a shader for the entity. An empty string will revert to the normal entity shader.
        + +

        setshaderdata( Float data0, Float data1 )
        +

          sets the shader controllers for this entity.
        + +

        setshadertime( [ Float timeOffset ], [ Float randomTimeOffset ] )
        +

          reset the shader time for this entity.
        + +

        setsize( Vector mins, Vector maxs )
        +

          Set the bounding box of the entity to mins and maxs.
        + +

        setuselookat( Boolean lookat )
        +

          Sets if the client must look at the entity to use it
        + +

        shader( String shaderCommand, Float argument1, [ Float argument2 ] )
        +

          change a specific shader parameter for the entity.
          +Valid shader commands are:
          +translation [trans_x] [trans_y] - change the texture translation
          +offset [offset_x] [offset_y] - change the texture offset
          +rotation [rot_speed] - change the texture rotation speed
          +frame [frame_num] - change the animated texture frame
          +wavebase [base] - change the base parameter of the wave function
          +waveamp [amp] - change the amp parameter of the wave function
          +wavebase [phase] - change the phase parameter of the wave function
          +wavefreq [freq] - change the frequency parameter of the wave function
          +
        + +

        shootableonly
        +

          Makes the entity shootable only.
        + +

        show
        +

          show the entity,opposite of hide.
        + +

        sighttrace( Vector start, Vector end, [ Integer pass_entities ], [ Vector mins ], [ Vector maxs ] )
        +

          Performs a trace line from the start to the end, returns 0 if something was hit and 1 otherwise.
        + +

        solid
        +

          make solid.
        + +

        sp( String command, [ String parm1 ], [ String parm2 ], [ String ... ] )
        +

          Makes a command be executed only in single player
        + +

        spawnflags( Integer flags )
        +

          spawnflags from the BSP,these are set inside the editor
        + +

        sprealism( String command, [ String parm1 ], [ String parm2 ], [ String ... ] )
        +

          Makes a command be executed only in single player realism mode
        + +

        stationary
        +

          entity does not move,causes no physics to be run on it.
        + +

        stoploopsound
        +

          Stop the looped-sound on this entity.
        + +

        stopsound( [ Integer channel ] )
        +

          stop the current sound on the specified channel.
          +default channel, CHAN_BODY.
        + +

        surface( String surfaceName, [ String parameter1 ], [ String parameter2 ], [ String parameter3 ], [ String parameter4 ], [ String parameter5 ], [ String parameter6 ] )
        +

          change a legs surface parameter for the given surface.
          ++ sets the flag, - clears the flag
          +Valid surface commands are:
          +skin1 - set the skin1 offset bit
          +skin2 - set the skin2 offset bit
          +nodraw - don't draw this surface
        + +

        svflags( [ String parameter1 ], [ String parameter2 ], [ String parameter3 ], [ String parameter4 ], [ String parameter5 ], [ String parameter6 ] )
        +

          Change the current server flags.
          +Valid flags are as follows:
          ++ sets a flag, - clears a flag
          +broadcast - always send this entity to the client
        + +

        takedamage
        +

          makes entity take damage.
        + +

        team( String moveTeam )
        +

          used to make multiple entities move together.
        + +

        toss
        +

          entity has gravity applied to it.
        + +

        touchtriggers
        +

          this entity should touch triggers.
        + +

        trace( Vector start, Vector end, [ Integer pass_entities ], [ Vector mins ], [ Vector maxs ] )
        +

          Performs a Trace Line from the start to the end, returns the end or the position it hit at.
        + +

        trigger( String name )
        +

          Trigger the specified target or entity.
        + +

        unbind
        +

          unbind this entity.
        + +

        unglue
        +

          unglue this entity.
        + +

        usebbox
        +

          do not perform perfect collision,use bounding box instead.
        + +

        velocity( Vector velocity )
        +

          sets the velocity for this entity.
        + +

        velocity
        +

          gets the velocity for this entity.
        + +

        volumedamage( Float damage )
        +

          does damage to any entity within this's volume
        + +

        yaw
        +

          entity's yaw
        +
        + +

        Event -> Class

        +
        +
        + +

        ExplodeObject (func_explodeobject) -> MultiExploder -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        amount( Integer amountOfDebris )
        +

          How much debris to spawn each time.
        + +

        debrismodel( String debrisModel )
        +

          What kind of debris to spawn when triggered.
        + +

        severity( Float newSeverity )
        +

          How violently the debris should be ejected.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        Exploder (func_exploder) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        dmg( Integer damage )
        +

          Sets the damage the explosion does.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        ExplodingWall (func_explodingwall) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        anglespeed( Float speed )
        +

          Set the angle speed.
        + +

        base_velocity( Vector velocity )
        +

          Set the base velocity.
        + +

        checkonground
        +

          Check if exploding wall is on ground.
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        dmg( Integer dmg )
        +

          Set the damage from the exploding wall.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        explosions( Integer explosions )
        +

          Set the number of explosions.
        + +

        land_angles( Vector angles )
        +

          Set the land angles.
        + +

        land_radius( Float radius )
        +

          Set the land radius.
        + +

        random_velocity( Vector velocity )
        +

          Set the amount of random variation of the base velocity.
        + +

        stoprotating
        +

          Stop rotating the wall.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        Explosion -> Projectile -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        constantdamage
        +

          Makes the explosion do constant damage over the radius
        + +

        damageagain
        +

          This event is generated each frame if explosion is set to damage each frame
        + +

        damageeveryframe
        +

          Makes the explosion damage every frame
        + +

        explosioneffect( String explosiontype )
        +

          Make an explosionType explosion effect
        + +

        flash( Float time, Float r, Float g, Float b, Float radius )
        +

          Flash player screens
        + +

        radius( Float projectileRadius )
        +

          set the radius for the explosion
        + +

        radiusdamage( Float radiusDamage )
        +

          set the radius damage an explosion does
        +
        + +

        FallingRock (func_fallingrock) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        bounce
        +

          sent to entity when touched.
        + +

        dmg( Integer dmg )
        +

          Set the damage from the rock.
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        noise( String sound )
        +

          Set the sound to play when the rock bounces
        + +

        rotate
        +

          rotates the falling rock.
        + +

        speed( Float speed )
        +

          Set the speed that the rock moves at.
        + +

        start
        +

          Starts rock falling.
        + +

        wait( Float wait )
        +

          How long to wait before rock starts falling.
        +
        + +

        FencePost (func_fencepost) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        FixedTurret -> VehicleTank -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Fulcrum (func_fulcrum) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        dampening( Float newDampening )
        +

          dampening of fulcrum.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        limit( Float newLimit )
        +

          angular limit for the fulcrum.
        + +

        movesound( String newSinkSound )
        +

          Sound played when fulcrum is moving.
        + +

        reset
        +

          Reset the fulcrum right now.
        + +

        resetspeed( Float newResetspeed )
        +

          Speed at which fulcrum resets itself, defaults to 0.002 * speed.
        + +

        speed( Float speed )
        +

          Speed at which fulcrum operates itself.
        +
        + +

        FuncBeam (func_beam) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activate
        +

          Activate the beam
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        angles( Vector newAngles<0.00...360.00><0.00...360.00><0.00...360.00> )
        +

          set the angles of the entity to newAngles.
        + +

        color( Vector beam_color<0.00...1.00><0.00...1.00><0.00...1.00> )
        +

          Set the color of the beam
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        deactivate
        +

          Deactivate the beam
        + +

        delay( Float delay )
        +

          Set the amount of delay on the beam updater
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        endalpha( Float alpha )
        +

          Set the endpoint alpha value of the beam
        + +

        endpoint( Vector beam_end_point )
        +

          Set the end point of the beam. The beam will be draw from the origin to
          +the end point.
        + +

        findendpoint
        +

          Find the endpoint of a beam
        + +

        ignorewalls( [ Boolean bool ] )
        +

          Set if the beam can traverse walls
        + +

        life( Float beam_life )
        +

          Set the amount of time the beam stays on when activated
        + +

        maxoffset( Float max_offset )
        +

          Set the maximum offset the beam can travel above, below, forward or back of it's endpoints
        + +

        minoffset( Float min_offset )
        +

          Set the minimun offset the beam can travel above, below, forward or back of it's endpoints
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        numsegments( Integer numsegments )
        +

          Set the number of segments for the beam
        + +

        numspherebeams( Integer num )
        +

          Set the number of beams that will be shot out in a sphere like formation
        + +

        overlap( Float beam_overlap )
        +

          Set the amount of overlap the beams have when they are being strung together
        + +

        persist( Boolean bool )
        +

          Set the persist property of the beam
        + +

        radius( Float radius )
        +

          Set the starting radius of the beams if this is a beamsphere
        + +

        shader( String beam_shader )
        +

          Set the shader that the beam will use
        + +

        shoot
        +

          Make the beam cause damage to entities that get in the way
        + +

        shootradius( Float radius )
        +

          Set the radius of the damage area between beam endpoints
        + +

        tileshader( String beam_shader )
        +

          Set the shader that the beam will use. This shader will be tiled.
        + +

        toggledelay( [ String [random] ], [ Float time ] )
        +

          Causes a beam toggling effect. Sets the time between toggling. If random is specified, The time will be between 0 and time
        + +

        updateendpoint
        +

          Update the endpoint of a beam
        + +

        updateorigin
        +

          Update the origin of a beam
        +
        + +

        FuncLadder (func_ladder) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        +
        + +

        FuncRemove (func_remove) -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Game -> Listener -> Class

        +
        + +

        detail
        +

          game.detail
        + +

        skill
        +

          game.skill
        +
        + +

        Gib (gib) -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        stopped
        +

          sent when entity has stopped bouncing for MOVETYPE_TOSS.
        + +

        throwgib( Entity ent, Integer velocity, Float scale )
        +

          Throw a gib.
        +
        + +

        GravPath -> Listener -> Class

        +
        +
        + +

        GravPathManager -> Class

        +
        +
        + +

        GravPathNode (info_grav_pathnode) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activate
        +

          Activate the grav path.
        + +

        deactivate
        +

          Deactivate the grav path.
        + +

        gravpath_create
        +

          Create the grav path.
        + +

        maxspeed( Float maxspeed )
        +

          Set the max speed of the grav path.
        + +

        radius( Float radius )
        +

          Set the radius of the grav path.
        + +

        speed( Float speed )
        +

          Set the speed of the grav path.
        +
        + +

        GrenadeHint (info_grenadehint) -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Health (health_020) -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        health_postspawn
        +

          Health Post Spawn
        + +

        item_pickup( Entity item )
        +

          Pickup the specified item.
        +
        + +

        HelmetObject (helmetobject) -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        HorizontalPipe (func_horizontalpipe) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        +
        + +

        Hud -> Listener -> Class

        +
        + +

        alignx
        +

          Gets the horizontal alignment for the HUD. Specified by 'left', 'center', or 'right'
        + +

        alignx( String align )
        +

          Sets the horizontal alignment for the HUD. Specified by 'left', 'center', or 'right'
        + +

        aligny( String align )
        +

          Sets the vertical alignment for the HUD. Specified by 'top', 'center', or 'bottom'
        + +

        aligny
        +

          Gets the vertical alignment for the HUD
        + +

        alpha
        +

          Gets the HUD alpha
        + +

        alpha( Float alpha )
        +

          Sets the HUD alpha
        + +

        color
        +

          Gets the HUD colors
        + +

        color( Vector color )
        +

          Sets the HUD colors
        + +

        fadeovertime( Float time )
        +

          Sets the HUD to transition in color (or alpha) over time
        + +

        font
        +

          Gets the HUD font
        + +

        font( String font )
        +

          Sets the HUD font
        + +

        getheight
        +

          Gets the HUD height
        + +

        gettime
        +

          Gets the HUD time
        + +

        getwidth
        +

          Gets the HUD width
        + +

        moveovertime( Float time )
        +

          Sets the HUD to move over time
        + +

        refresh
        +

          Refresh the HUD
        + +

        resetdimension
        +

          Bring the HUD back to normal dimension (non-3D)
        + +

        scaleovertime( Float time, Integer width, Integer height )
        +

          Sets the HUD to scale over time
        + +

        setdimension( Vector vector_or_offset, Boolean always_show, Boolean depth, [ Entity entity ] )
        +

          Sets this huddraw element to be a 3D world icon and can specify if this icon is always shown on-screen even if the player isn't looking at.
          +It uses xy pos from huddraw_rect.
          +If entity is specified, the vector will be an offset relative to the entity.
          +depth specify if the icon is shown through walls.
        + +

        setplayer( Entity entity, [ Boolean clears ] )
        +

          Sets to which player this HUD is shown and possibly clears the HUD to the previous player(s) it was shown. A NULL/NIL entity means the HUD will be shown to all players
          +Note : you will need to call in HUD functions again as it won't refresh to the player(s)
        + +

        setshader( String shader, Integer width, Integer height )
        +

          Sets the HUD shader
        + +

        settext( String text )
        +

          Sets the HUD text
        + +

        settimer( Float time, [ Float fade_at_time ] )
        +

          Sets a timer to count down an optionally fade at the specified time
        + +

        settimerup( Float time, [ Float fade_at_time ] )
        +

          Sets a timer to count up an optionally fade at the specified time
        + +

        setvirtualsize( Boolean virtual )
        +

          Sets if the HUD should use virtual screen resolution for positioning and size
        + +

        x
        +

          Gets the HUD horizontal position
        + +

        x( Integer x )
        +

          Sets the HUD horizontal position
        + +

        y( Integer y )
        +

          Sets the HUD vertical position
        + +

        y
        +

          Gets the HUD vertical position
        +
        + +

        InfoLandmark (info_landmark) -> Listener -> Class

        +
        + +

        landmark_name( String name )
        +

          Set the name of this landmark
        + +

        origin( Vector origin )
        +

          Set the origin of the landmark.
        +
        + +

        InfoNotNull (info_notnull) -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        InfoNull (info_null) -> Listener -> Class

        +
        +
        + +

        InteractObject (interactobject) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        hiteffect
        +

          Sets the tiki it will spawn when it's hit
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killedeffect
        +

          Sets the tiki it will spawn when it's destroyed
        +
        + +

        InventoryItem -> Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activateitem( [ String mode ] )
        +

          Activates the item
        + +

        activatepapers
        +

          The activation of the papers item
        +
        + +

        Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        amount( Integer amount )
        +

          Sets the amount of the item.
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        dialogneeded( String dialog_needed )
        +

          Sets the dialog needed string.
        + +

        dmamount( Integer amount )
        +

          Sets the amount of the item for DM.
        + +

        dmmaxamount( Integer max_amount )
        +

          Sets the max amount of the item fmr DM.
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        item_droptofloor
        +

          Drops the item to the ground.
        + +

        item_pickup( Entity item )
        +

          Pickup the specified item.
        + +

        maxamount( Integer max_amount )
        +

          Sets the max amount of the item.
        + +

        name( String item_name )
        +

          Sets the item name.
        + +

        no_remove
        +

          Makes it so the item is not removed from the world when it is picked up.
        + +

        pickupsound( String name )
        +

          sets the item's pickup sound alias
        + +

        pickup_done
        +

          Called when the item pickup is done.
        + +

        respawn
        +

          Respawns the item.
        + +

        respawnsound
        +

          Turns on the respawn sound for this item.
        + +

        respawn_done
        +

          Called when the item respawn is done.
        + +

        set_respawn( Integer respawn )
        +

          Turns respawn on or off.
        + +

        set_respawn_time( Float respawn_time )
        +

          Sets the respawn time.
        + +

        stopped
        +

          sent when entity has stopped bouncing for MOVETYPE_TOSS.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        + +

        viewmodelprefix( String prefix )
        +

          Sets the item's prefix for viewmodelanim.
        +
        + +

        Level -> Listener -> Class

        +
        + +

        alarm
        +

          zero = global level alarm off,non-zero = alarm on
        + +

        alarm( Integer alarm_status )
        +

          zero = global level alarm off,non-zero = alarm on
        + +

        badplace( String name, Vector origin, Float radius, [ String [team] ], [ Float [duration] ] )
        +

          Enables a 'bad place' for AI of team 'american', 'german', or (default) 'both' to avoid, and optionally gives it a duration
        + +

        bombs_planted( Integer num )
        +

          Sets the number of bombs that are set
        + +

        bombs_planted( Integer num )
        +

          the number of bombs that are set
        + +

        bombs_planted
        +

          Gets the number of bombs that are set
        + +

        clockside( String axis_allies_draw_kills )
        +

          Sets which side the clock is on... 'axis' or 'allies' win when time is up, 'kills' gives the win to the team with more live members,'draw' no one wins
        + +

        clockside( String axis_or_allies )
        +

          Sets which side the clock is on... 'axis' or 'allies' win when time is up
        + +

        clockside
        +

          Gets which side the clock is on... 'axis' or 'allies' win when time is up
        + +

        dmrespawning
        +

          returns 1 if wave-based DM, 0 if respawns are disabled within a round
        + +

        dmrespawning( Integer allow_respawn )
        +

          set to 1 to turn on wave-based DM, to 0 to disable respawns within a round
        + +

        dmrespawning( Integer allow_respawn )
        +

          set to 1 to turn on wave-based DM,to 0 to disable respawns within a round
        + +

        dmroundlimit( Integer roundlimit )
        +

          sets the default roundlimit, in minutes; can be overridden by 'roundlimit' cvar
        + +

        dmroundlimit( Integer roundlimit )
        +

          sets the default roundlimit,in minutes; can be overridden by 'roundlimit' cvar
        + +

        dmroundlimit
        +

          gets the actual roundlimit, in minutes; may be 'roundlimit' cvar or the default round limit
        + +

        force_team_objective
        +

          Return 1 if each team has a separate objective location
        + +

        force_team_objective( Integer force )
        +

          Whether or not to force using a separate objective location for each team.
          +1 (forced on TOW/Liberation match): different location for each team
          +0 (default): teams use same location on non-TOW/non-Liberation match
          +
        + +

        found_secrets
        +

          count of found secrets
        + +

        ignoreclock( Integer ignoreclock )
        +

          Tells a level weather or not to ignore the clock
        + +

        loop_protection
        +

          says if infinite loop protection is enabled
        + +

        loop_protection( Integer loop_protection )
        +

          specify if infinite loop protection is enabled
        + +

        nodrophealth( Integer alarm_status )
        +

          zero = automatically drop health according to cvars, non-zero = don't autodrop health (like hard mode)
        + +

        nodropweapon( Integer alarm_status )
        +

          zero = automatically drop weapons according to cvars, non-zero = don't autodrop weapons (like hard mode)
        + +

        objectivebased
        +

          Gets wether or not the game is currently objective based or not
        + +

        papers
        +

          the level of papers the player currently has
        + +

        papers
        +

          the level of papers the player currently has
        + +

        planting_team( String axis_allies_draw_kills )
        +

          which is planting the bomb,'axis' or 'allies'
        + +

        planting_team( String axis_or_allies )
        +

          Sets which is planting the bomb,'axis' or 'allies'
        + +

        planting_team
        +

          Gets which is planting the bomb,'axis' or 'allies'
        + +

        rain_density
        +

          Sets the rain density
        + +

        rain_density
        +

          Sets the rain density
        + +

        rain_length
        +

          Sets the rain length
        + +

        rain_length
        +

          Sets the rain length
        + +

        rain_min_dist
        +

          Sets the rain min_dist
        + +

        rain_min_dist
        +

          Sets the rain min_dist
        + +

        rain_numshaders
        +

          Sets the rain numshaders
        + +

        rain_numshaders
        +

          Sets the rain numshaders
        + +

        rain_shader
        +

          Sets the rain
        + +

        rain_shader
        +

          Sets the rain
        + +

        rain_slant
        +

          Sets the rain slant
        + +

        rain_slant
        +

          Sets the rain slant
        + +

        rain_speed
        +

          Sets the rain speed
        + +

        rain_speed
        +

          Sets the rain speed
        + +

        rain_speed_vary
        +

          Sets the rain speed variance
        + +

        rain_speed_vary
        +

          Sets the rain speed variance
        + +

        rain_width
        +

          Sets the rain width
        + +

        rain_width
        +

          Sets the rain width
        + +

        removebadplace( String name )
        +

          Removes a 'bad place'
        + +

        roundbased
        +

          Gets wether or not the game is currently round based or not
        + +

        roundstarted
        +

          non-zero if round has started
        + +

        targets_destroyed( Integer num )
        +

          Sets the number of bomb targets that have been destroyed
        + +

        targets_destroyed
        +

          Gets the number of bomb targets that have been destroyed
        + +

        targets_destroyed( Integer num )
        +

          the number of bomb targets that have been destroyed
        + +

        targets_to_destroy( Integer num )
        +

          Sets the number of bomb targets that must be destroyed
        + +

        targets_to_destroy
        +

          Gets the number of bomb targets that must be destroyed
        + +

        targets_to_destroy( Integer num )
        +

          the number of bomb targets that must be destroyed
        + +

        time
        +

          current level time
        + +

        total_secrets
        +

          count of total secrets
        +
        + +

        Light (light) -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        LightStyleClass -> Class

        +
        +
        + +

        Listener -> Class

        +
        + +

        cancelFor( String name )
        +

          Cancel for event of type name.
        + +

        classname
        +

          classname variable
        + +

        commanddelay( Float delay, String command, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          executes a command after the given delay.
        + +

        delaythrow( String label )
        +

          Internal usage.
        + +

        delete
        +

          Removes this listener immediately.
        + +

        endon( String name )
        +

          Ends the function when the specified event is triggered.
        + +

        exec( String script )
        +

          Executes the specified script.
        + +

        exec( String script )
        +

          Executes the specified script.
        + +

        immediateremove
        +

          Removes this listener immediately.
        + +

        inheritsfrom( String class )
        +

          Returns 1 if the class inherits from the specified class. 0 otherwise.
        + +

        isinheritedby( String class )
        +

          Returns 1 if the class is inherited by the specified class. 0 otherwise.
        + +

        notify( String name )
        +

          Triggers an event. An undefined event will be automatically created by calling waittill or endon.
        + +

        owner
        +

          Returns the owner.
        + +

        remove
        +

          Removes this listener the next time events are processed.
        + +

        thread( String label )
        +

          Creates a thread starting at label.
        + +

        thread( String label )
        +

          Creates a thread starting at label.
        + +

        throw( String label )
        +

          Throws to the specified label.
        + +

        unregister( String label )
        +

          Unregisters the label from the event of the same name.
        + +

        waitexec( String script )
        +

          Executes the specified script and waits until the called thread group is finished.
        + +

        waitexec( String script )
        +

          Executes the specified script and waits until the called thread group is finished.
        + +

        waitthread( String label )
        +

          Creates a thread starting at label and waits until the called thread is finished.
        + +

        waitthread( String label )
        +

          Creates a thread starting at label and waits until the called thread is finished.
        + +

        waitTill( String name )
        +

          Wait until event of type name
        + +

        waittill_any( String name1, [ String ... ] )
        +

          Wait until any event of type name
        + +

        waittill_any_timeout( Float timeout_time, String name1, [ String ... ] )
        +

          Wait until any event of type name with a timeout time
        + +

        waittill_timeout( Float timeout_time, String name )
        +

          Wait until event of type name with a timeout time
        +
        + +

        LODMaster (lodmaster) -> Listener -> Class

        +
        + +

        lod_angles( Float pitch<0.00...360.00>, Float yaw<0.00...360.00>, Float roll<0.00...360.00> )
        +

          Set the angles of the model
        + +

        lod_discard
        +

          Discard LOD changes
        + +

        lod_roll( Float roll )
        +

          Set the roll of the model
        + +

        lod_spawn( String model )
        +

          Edit LOD on the specified model
        + +

        lod_yaw( Float yaw )
        +

          Set the yaw of the model
        +
        + +

        LODSlave (lodslave) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        lod_discard
        +

          Discard LOD changes
        + +

        lod_model
        +

          Set the model of the current viewthing
        + +

        lod_think
        +

          Called every frame to process the view thing.
        +
        + +

        MiscModel (misc_model) -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        MonkeyBars (func_monkeybars) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        +
        + +

        Mover (mover) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        movedone( Entity finishedEntity )
        +

          Sent to commanding thread when done with move .
        +
        + +

        MultiExploder (func_multi_exploder) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        dmg( Integer damage )
        +

          Sets the damage the explosion does.
        + +

        duration( Float duration )
        +

          Sets the duration of the explosion.
        + +

        random( Float randomness )
        +

          Sets the randomness value of the explosion.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        + +

        wait( Float explodewait )
        +

          Sets the wait time of the explosion.
        +
        + +

        Object -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Objective (func_objective) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        Complete
        +

          Complete this objective.
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        ObjectiveNbr( Integer index )
        +

          Sets the objective number.
        + +

        SetCurrent
        +

          Set this objective as current.
        + +

        Text( String text )
        +

          Set current text.
        + +

        TurnOff
        +

          Turn Off and cancel the current cycle (if any)
        + +

        TurnOn
        +

          Turn On and begin the first cycle
        +
        + +

        Parm -> Listener -> Class

        +
        + +

        motionfail
        +

          motionfail
        + +

        movedone
        +

          movedone
        + +

        movefail
        +

          movefail
        + +

        other
        +

          other
        + +

        owner
        +

          owner
        + +

        previousthread
        +

          previousthread
        + +

        sayfail
        +

          sayfail
        + +

        upperfail
        +

          upperfail
        +
        + +

        PathNode (info_pathnode) -> SimpleEntity -> Listener -> Class

        +
        + +

        delete
        +

          Removes this listener immediately.
        + +

        immediateremove
        +

          Removes this listener immediately.
        + +

        istouching( Entity ent )
        +

          returns 1 if the entities are touching,0 if not
        + +

        low_wall_arc( Float arc_half_angle )
        +

          Marks this node as good for low-wall behavior, and gives the arc
        + +

        spawnflags( Integer node_flags )
        +

          Sets the path nodes flags.
        +
        + +

        PathSearch -> Class

        +
        +
        + +

        Player (player) -> Sentient -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        actor( String modelname, [ String keyname1 ], [ String value1 ], [ String keyname2 ], [ String value2 ], [ String keyname3 ], [ String value3 ], [ String keyname4 ], [ String value4 ] )
        +

          Spawns an actor.
        + +

        actorinfo( Integer actor_number )
        +

          Prints info on the specified actor.
        + +

        adddeaths( Integer deaths )
        +

          adds deaths number to player
        + +

        addkills( Integer kills )
        +

          Give or take kills from the player
        + +

        adminrights
        +

          returns client admin rights
        + +

        animloop_legs
        +

          Called when the legs animation has finished.
        + +

        animloop_pain
        +

          Called when the pain animation has finished.
        + +

        animloop_torso
        +

          Called when the torso animation has finished.
        + +

        armwithweapons
        +

          give player their primary and secondary weapons.
        + +

        attachtoladder
        +

          Attaches the sentient to a ladder
        + +

        auto_join_team
        +

          Join the team with fewer players
        + +

        bindweap( Entity weapon, Integer handnum )
        +

          binds weapon to player and sets him as weapon owner
        + +

        callvote( String arg1, String arg2 )
        +

          Player calls a vote
        + +

        canswitchteams( Boolean allow_team_change, [ Boolean allow_spectate ] )
        +

          Specify if this player is allowed to switch teams and spectate. Doesn't override global canswitchteams.
        + +

        clearcommand( [ String command ] )
        +

          Clears any or a specific client command
        + +

        coord
        +

          Prints out current location and angles
        + +

        correctweaponattachments
        +

          makes sure the weapons is properly attached when interupting a reload
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        damage_multiplier( Float damage_multiplier )
        +

          Sets the current damage multiplier
        + +

        damage_multiplier
        + +

        dead
        +

          Called when the player is dead.
        + +

        deadbody
        +

          Spawn a dead body
        + +

        dive( Float height, [ Float airborne_duration ] )
        +

          Makes the player dive into prone position.
        + +

        dmdeathdrop
        +

          Drops the player inventory in DM after's he's been killed
        + +

        dmmessage( Integer mode, String stuffstrings )
        +

          sends a DM message to the appropriate players
        + +

        dmteam
        +

          returns 'allies','axis','spectator',or 'freeforall'
        + +

        dog( [ Integer god_mode ] )
        +

          Sets the god mode cheat or toggles it.
        + +

        earthquake2( Float duration, Float magnitude, Boolean no_rampup, Boolean no_rampdown, [ Vector location ], [ Float radius ] )
        +

          Create a smooth realistic earthquake for a player. Requires sv_reborn to be set.
        + +

        endlevel
        +

          Called when the player gets to the end of the level.
        + +

        ensureforwardoffladder
        +

          Ensures that the player went forward off the ladder.
        + +

        ensureoverladder
        +

          Ensures that the player is at the proper height when getting off the top of a ladder
        + +

        enter( Entity vehicle, [ String driver_anim ] )
        +

          Called when someone gets into a vehicle.
        + +

        exit( Entity vehicle )
        +

          Called when driver gets out of the vehicle.
        + +

        face( Vector angles )
        +

          Force angles to specified vector
        + +

        finishuseanim
        +

          Fires off all targets associated with a particular useanim.
        + +

        finishuseobject
        +

          Fires off all targets associated with a particular useobject.
        + +

        fireheld
        +

          returns 1 if this player is holding fire,or 0 if he is not
        + +

        forcelegsstate( String legsstate )
        +

          Force the player's legs to a certain state
        + +

        forcetorsostate( String torsostate )
        +

          Force the player's torso to a certain state
        + +

        fov( [ Float fov ] )
        +

          Sets the fov.
        + +

        freezecontrols( Boolean freeze_state )
        +

          Blocks or unblocks control input from this player.
        + +

        fullheal
        +

          Heals player.
        + +

        gameversion
        +

          Prints the game version.
        + +

        getconnstate
        +

          gets connection state. [DEPRECATED]
        + +

        getcurrentdmweapontype
        +

          get the player's current DM weapon type.
        + +

        getdeaths
        +

          gets deaths number of player
        + +

        getkills
        +

          gets kills number of player
        + +

        getlegsstate
        +

          Gets the player's current legs state name
        + +

        getmovement
        +

          returns the player current movement
        + +

        getposition
        +

          returns the player current position
        + +

        gettorsostate
        +

          Gets the player's current torso state name
        + +

        give( String name, [ Integer amount ] )
        +

          Gives the player the specified thing (weapon, ammo, item, etc.) and optionally the amount.
        + +

        giveweapon( String weapon_name )
        +

          Gives the player the specified weapon.
        + +

        gotkill( Entity victim, Integer damage, Entity inflictor, Integer meansofdeath, Boolean gib )
        +

          event sent to attacker when an entity dies
        + +

        gvo
        +

          Retrieves the server's vote options file
        + +

        has_disguise( Integer is_disguised )
        +

          zero = does not have a disguise,non - zero = has a disguise
        + +

        has_disguise
        +

          zero = does not have a disguise,non - zero = has a disguise
        + +

        hideent( Entity entity )
        +

          Hides the specified entity to the player.
        + +

        holster
        +

          Holsters all wielded weapons, or unholsters previously put away weapons
        + +

        injail
        +

          returns 1 if player is in jail,0 if out
        + +

        injail( Integer boolean )
        +

          set to 1 to indicate when player is in jail,0 when they are free
        + +

        inventory( Entity array )
        +

          Set up the player's inventory
        + +

        inventory
        +

          returns player's inventory
        + +

        invnext
        +

          Cycle to player's next item.
        + +

        invprev
        +

          Cycle to player's previous item.
        + +

        iprint( String string, [ Integer bold ] )
        +

          prints a string to the player,optionally in bold
        + +

        isadmin
        +

          checks if player is logged as admin
        + +

        isEscaping
        +

          Return non-zero if escaping or assisting escape
        + +

        isSpectator
        +

          Check to see if player is a spectator (non-zero return value)
        + +

        is_disguised
        +

          zero = not disguisednon-zero = disguised
        + +

        jailassistescape
        +

          Start the assist jail escape animation
        + +

        jailescape
        +

          Start the escape from jail animation
        + +

        jailescapestop
        +

          Stop either the escape from jail or assist animation
        + +

        join_team( String team )
        +

          Join the specified team (allies or axis)
        + +

        jump( Float height )
        +

          Makes the player jump.
        + +

        jumpxy( Float forwardmove, Float sidemove, Float speed )
        +

          Makes the sentient jump.
        + +

        kill
        +

          console based command to kill yourself if stuck.
        + +

        killaxis( Float radius )
        +

          Kills all of the axis that are in the passed radius, or all of them if radius is 0.
        + +

        killclass( String classname, [ Integer except_entity_number ] )
        +

          Kills all of the entities in the specified class.
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killent( Integer entity_number )
        +

          Kills the specified entity.
        + +

        killhandler( String label )
        +

          Gets the player's current killed event handler. Returns NIL if no custom killhandler was set.
        + +

        killhandler( String label )
        +

          Replace the player's killed event by a new scripted handler. None or an empty string will revert to the default killed event handler.
        + +

        leanleftheld
        +

          Returns 1 if this player is holding lean left key, or 0 if he is not
        + +

        leanrightheld
        +

          returns EV_RETURN if this player is holding lean right key, or 0 if he is not
        + +

        leave_team
        +

          Leave the current team
        + +

        listinventory
        +

          List of the player's inventory.
        + +

        logstats( Boolean state )
        +

          Turn on/off the debugging playlog
        + +

        modheight( String height )
        +

          change the maximum height of the player
          +can specify 'stand', 'duck' or 'prone'.
        + +

        modheightfloat( Float height, Float max_z )
        +

          Specify the view height of the player and the height of his bounding box.
        + +

        moveposflags( String position, [ String movement ] )
        +

          used by the state files to tell the game dll what the player is doing
        + +

        moveSpeedScale
        +

          Gets the player's speed multiplier.
        + +

        moveSpeedScale( Float speed )
        +

          Sets the player's speed multiplier (default 1.0).
        + +

        nationalityprefix
        +

          get the three or five letter prefix that denotes the player's nationality
        + +

        netname
        +

          returns player's name
        + +

        nextpaintime( Float seconds )
        +

          Set the next time the player experiences pain (Current time + seconds specified).
        + +

        noclip
        +

          Toggles the noclip cheat.
        + +

        notarget
        +

          Toggles the notarget cheat.
        + +

        notready
        +

          makes this player not ready for the round to start
        + +

        objective( Integer num_completed, Integer out_of )
        +

          Sets the number of objectives completed and the total number of objectives
        + +

        pain( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          used to inflict pain to an entity
        + +

        perferredweapon( String weapon_name )
        +

          Overrides your perferred weapon that is displayed in the stats screen.
        + +

        physics_off
        +

          turn player physics off.
        + +

        physics_on
        +

          turn player physics on.
        + +

        pickweapon
        +

          Pick your weapon.
        + +

        playlocalsound( String soundName, [ Boolean loop ], [ Float time ] )
        +

          Plays a local sound to the player. The sound must be aliased globally. Requires sv_reborn to be set for stereo sounds.
        + +

        poweruptimer( Integer poweruptimer, Integer poweruptype )
        +

          Sets the powerup timer and powerup type.
        + +

        primarydmweapon( String weaptype )
        +

          Sets the player's primary DM weapon
        + +

        primaryfireheld
        +

          returns 1 if this player is holding the primary fire, or 0 if not
        + +

        ready
        +

          makes this player ready for the round to start
        + +

        ready
        +

          returns 1 if this player is ready,0 otherwise
        + +

        reload
        +

          Reloads the player's weapon
        + +

        removeclass( String classname, [ Integer except_entity_number ] )
        +

          Removes all of the entities in the specified class.
        + +

        removeent( Integer entity_number )
        +

          Removes the specified entity.
        + +

        resethaveitem( String weapon_name )
        +

          Resets the game var that keeps track that we have gotten this weapon
        + +

        resetstate
        +

          Reset the player's state table.
        + +

        respawn
        +

          Respawns the player.
        + +

        runheld
        +

          returns 1 if this player is holding run key,or 0 if he is not
        + +

        safeholster( Boolean putaway )
        +

          Holsters all wielded weapons, or unholsters previously put away weapons
          +preserves state, so it will not holster or unholster unless necessary
        + +

        safezoom( Boolean zoomin )
        +

          0 turns off zoom,and 1 returns zoom to previous setting
        + +

        score
        +

          Show the score for the current deathmatch game
        + +

        secfireheld
        +

          returns EV_RETURN if this player is holding secondary fire, or 0 if he is not
        + +

        secondaryfireheld
        +

          returns 1 if this player is holding the secondary fire, or 0 if not
        + +

        setanimspeed( Float speed )
        +

          set the player's animation speed multiplier (default 1.0).
        + +

        setclientflag( String name )
        +

          Calls a flag to the script client.
        + +

        setentshader( Entity entity, String shadername )
        +

          Sets an entity shader for this player. An empty string will revert to the normal entity shader.
        + +

        setlocalsoundrate( String name, Float rate, [ Float time ] )
        +

          Sets the local sound rate.
        + +

        setspeed( Float speed, [ Integer index ] )
        +

          Sets the player's speed multiplier (default 1.0). Index specify which array value will be used (maximum 4).
        + +

        setteam( String team_name )
        +

          sets the player's team without respawning.
          +Available team names are 'none', 'spectator', 'freeforall', 'axis' and 'allies'.
        + +

        setvmaspeed( String name, Float speed )
        +

          Sets the player's animation speed when playing it.
        + +

        show
        +

          show the entity,opposite of hide.
        + +

        showent( Entity entity )
        +

          Shows the specified entity to the player.
        + +

        skipcinematic
        +

          Skip the current cinematic
        + +

        spawn( String entityname, [ String keyname1 ], [ String value1 ], [ String keyname2 ], [ String value2 ], [ String keyname3 ], [ String value3 ], [ String keyname4 ], [ String value4 ] )
        +

          Spawns an entity.
        + +

        spectator
        +

          Become a spectator
        + +

        startuseobject
        +

          starts up the useobject's animations.
        + +

        state
        +

          Dumps the player's state to the console.
        + +

        statefile
        +

          Gets the player's current state file.
        + +

        statefile( [ String statefile ] )
        +

          Sets the player's current state file (setting NIL, NULL or an empty string will revert to the global statefile).
        + +

        stats
        +

          Display the MissionLog.
        + +

        stoplocalsound( String soundName, [ Float time ] )
        +

          Stops the specified sound.
        + +

        stopwatch( Integer duration )
        +

          Starts a stopwatch for a given duration... use 0 to clear the stopwatch
        + +

        stopwatchingactor( Entity actor_to_stop_watching )
        +

          Makes the player's camera stop watching the specified actor.
        + +

        stufftext( String stuffstrings )
        +

          Stuffs text to the player's console
        + +

        takepain( Boolean bool )
        +

          Set whether or not to take pain
        + +

        tele( Vector location )
        +

          Teleport to location
        + +

        testplayeranim( Float weight, [ String anim ] )
        +

          Plays a test animation on the player
        + +

        testthread( String scriptfile, [ String label ] )
        +

          Starts the named thread at label if provided.
        + +

        turn( Float yawangle )
        +

          Causes player to turn the specified amount.
        + +

        turnlegs( Float yawangle )
        +

          Turns the players legs instantly by the specified amount.
        + +

        turnupdate( Float yaw, Float timeleft )
        +

          Causes player to turn the specified amount.
        + +

        turret
        +

          Returns the turret the player is using. NULL if player isn't using a turret.
        + +

        turretenter( Entity turret, [ String driver_anim ] )
        +

          Called when someone gets into a turret.
        + +

        turretexit( Entity turret )
        +

          Called when driver gets out of the turret.
        + +

        tweakladderpos
        +

          Tweaks the player's position on a ladder to be proper
        + +

        unattachfromladder
        +

          Unattaches the sentient from a ladder
        + +

        updatepoweruptime
        +

          Called once a second to decrement powerup time.
        + +

        useheld
        +

          returns 1 if this player is holding use,or 0 if he is not
        + +

        userinfo
        +

          returns userinfo string
        + +

        usestuff
        +

          Makes the player try to use whatever is in front of her.
        + +

        vehicle
        +

          Returns the vehicle the player is using. NULL if player isn't using a vehicle.
        + +

        viewangles
        +

          get the angles of the entity.
        + +

        viewangles( Vector newAngles )
        +

          set the view angles of the entity to newAngles.
        + +

        viewmodelanim( String name, [ Integer force_restart ] )
        +

          Sets the player's view model animation.
        + +

        viewmodelanimfinished
        +

          True if the player's current view model finished its animation.
        + +

        viewmodelanimvalid( String anim, [ Boolean fullanim ] )
        +

          True if the view model animation is valid.
        + +

        viewmodelgetanim( [ Boolean fullanim ] )
        +

          Gets the player's current view model animation.
        + +

        visiongetnaked
        +

          Gets the player's current naked-eye vision.
        + +

        visionsetblur( Float level, [ Float transition_time ] )
        +

          Sets the player's blur level. Level is a fraction from 0-1
        + +

        visionsetnaked( String vision_name, [ Float transition_time ], [ Float phase ] )
        +

          Sets the player's naked-eye vision. Optionally give a transition time from the current vision. If vision_name is an empty string, it will revert to the current global vision.
        + +

        voicetype( String voice_name )
        +

          Sets the voice type to use the player.
        + +

        vote( String arg1 )
        +

          Player votes either yes or no
        + +

        waitForState( String stateToWaitFor )
        +

          When set, the player will clear waitforplayer when this state is hit
          +in the legs or torso.
        + +

        watchactor( Entity actor_to_watch )
        +

          Makes the player's camera watch the specified actor.
        + +

        weapdrop
        +

          Drops the player's current weapon.
        + +

        weapnext
        +

          Cycle to player's next weapon.
        + +

        weapprev
        +

          Cycle to player's previous weapon.
        + +

        whatis( Integer entity_number )
        +

          Prints info on the specified entity.
        + +

        wuss
        +

          Gives player all weapons.
        + +

        zoomoff
        +

          makes sure that zoom is off
        +
        + +

        PlayerAlliedDeathmatchStart (info_player_allied) -> PlayerDeathmatchStart -> PlayerStart -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        PlayerAxisDeathmatchStart (info_player_axis) -> PlayerDeathmatchStart -> PlayerStart -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        PlayerBot -> Player -> Sentient -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        gotkill( Entity victim, Integer damage, Entity inflictor, Integer meansofdeath, Boolean gib )
        +

          event sent to attacker when an entity dies
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        stufftext( String stuffstrings )
        +

          Stuffs text to the player's console
        +
        + +

        PlayerDeathmatchStart (info_player_deathmatch) -> PlayerStart -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        PlayerIntermission (info_player_intermission) -> Camera -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        PlayerStart (info_player_start) -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        deletespawn
        +

          delete this spawnpoint when spawning from this spawnpoint
        + +

        disablespawn
        +

          forbids spawning from this spawnpoint
        + +

        enablespawn
        +

          allows spawning from this spawnpoint
        + +

        keepspawn
        +

          keep this spawnpoint when spawning from this spawnpoint
        +
        + +

        PortableTurret -> TurretGun -> Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        clipsize( Integer ammoClipSize )
        +

          Set the amount of rounds a clip of the weapon holds
        + +

        item_droptofloor
        +

          Drops the item to the ground.
        +
        + +

        PortalCamera (portal_camera) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        roll( Float roll )
        +

          Sets the portal camera's roll.
        +
        + +

        PortalSurface (portal_surface) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        locatecamera
        +

          Locates the camera position.
        +
        + +

        Projectile -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        addownervelocity( Boolean bool )
        +

          Set whether or not the owner's velocity is added to the projectile's velocity
        + +

        addvelocity( Float velocity_x, Float velocity_y, Float velocity_z )
        +

          Set a velocity to be added to the projectile when it is created
        + +

        arctotarget
        +

          Make the projectile follow a normal arc on its way to its target
        + +

        avelocity( [ String [random|crandom] ], [ Float yaw ], [ String [random|crandom] ], [ Float pitch ], [ String [random|crandom] ], [ Float roll ] )
        +

          set the angular velocity of the projectile
        + +

        beam( String command, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          send a command to the beam of this projectile
        + +

        becomebomb
        +

          Make the projectile into a bomb
        + +

        bouncesound
        +

          Set the name of the sound that is played when the projectile bounces
        + +

        bouncesound_hard
        +

          Set the name of the sound that is played when the projectile bounces off hard surfaces
        + +

        bouncesound_metal
        +

          Set the name of the sound that is played when the projectile bounces off metal
        + +

        bouncesound_water
        +

          Set the name of the sound that is played when the projectile bounces off water
        + +

        bouncetouch
        +

          Make the projectile bounce when it hits a non-damageable solid
        + +

        canhitowner
        +

          Make the projectile be able to hit its owner
        + +

        chargelife
        +

          set the projectile's life to be determined by the charge time
        + +

        chargespeed
        +

          set the projectile's speed to be determined by the charge time
        + +

        clearowner
        +

          Make the projectile be able to hit its owner now
        + +

        dieinwater
        +

          Make the projectile die when gets wet
        + +

        dlight( Float red, Float green, Float blue, Float intensity )
        +

          set the color and intensity of the dynamic light on the projectile
        + +

        dmlife( Float projectileLife )
        +

          set the life of the projectile in DM
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        drunk( Float amount, Float rate )
        +

          Make the projectile drunk
        + +

        explode
        +

          Make the projectile explode
        + +

        explodeontouch
        +

          Make the projectile explode when it touches something damagable
        + +

        explosionmodel( String modelname )
        +

          Set the modelname of the explosion to be spawned
        + +

        fuse( Integer fuse )
        +

          set the projectile's life to be determined by the charge time
        + +

        heatseek
        +

          Make the projectile heat seek
        + +

        hitdamage( Float projectileHitDamage )
        +

          set the damage a projectile does when it hits something
        + +

        impactmarkorientation( Float degrees )
        +

          Set the orientation of the impact mark
        + +

        impactmarkradius( Float radius )
        +

          Set the radius of the impact mark
        + +

        impactmarkshader( String shader )
        +

          Set the impact mark of the shader
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        knockback( Float projectileKnockback )
        +

          set the knockback of the projectile when it hits something
        + +

        life( Float projectileLife )
        +

          set the life of the projectile
        + +

        meansofdeath( String meansOfDeath )
        +

          set the meansOfDeath of the projectile
        + +

        minlife( Float minProjectileLife )
        +

          set the minimum life of the projectile (this is for charge up weapons)
        + +

        minspeed( Float minspeed )
        +

          set the minimum speed of the projectile (this is for charge up weapons)
        + +

        notouchdamage
        +

          Makes the projectile not blow up or deal damage when it touches a damagable object
        + +

        prethink
        +

          Make the projectile think to update it's velocity
        + +

        removewhenstopped
        +

          Make the projectile get removed when it stops
        + +

        smashthroughglass( Integer speed )
        +

          Makes the projectile smash through windows & other damageble glass objects when going above a set speed
        + +

        speed( Float projectileSpeed )
        +

          set the speed of the projectile
        + +

        stopped
        +

          sent when entity has stopped bouncing for MOVETYPE_TOSS.
        + +

        updatebeam
        +

          Update the attached beam
        +
        + +

        ProjectileGenerator (ProjectileGenerator) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        Accuracy( Float Accuracy )
        +

          Accuracy 0-25 feet
          +Default=10
        + +

        BeginCycle
        +

          Startup the cycle..
        + +

        Cycles( Integer Cycles )
        +

          Number of cycles. 0=infinte
          +Default=0
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        EndCycle
        +

          End the cycle..
        + +

        FireOnStartUp
        +

          Default=1; Set this to 0 if you don't want the PG to fire on startup.
        + +

        gettargetentity
        +

          Returns entity being targeted by the projectile generator,
        + +

        ID( Integer ID )
        +

          Sets the ID for this projectile generator
          +Default=0:
        + +

        initialize
        +

          Initialize object
        + +

        isturnedon
        +

          Returns whether the generator is on or off.
        + +

        launchsound( String Sound )
        +

          Set a launch sound for the projectile.
        + +

        MaxDelay( Float MaxDelay )
        +

          Maximum time between bursts
          +Default=10
        + +

        MaxDuration( Float MaxDuration )
        +

          Sets the maximum duration of bursts(in seconds)
          +Default=3
        + +

        MaxNumShots( Integer MaxNumShots )
        +

          Sets the maximum # of shots to fire in a cycle
          +Default=1
        + +

        MinDelay( Float MinDelay )
        +

          Minimum time between bursts.
          +
        + +

        MinDuration( Float MinDuration )
        +

          Sets the minimum duration of the bursts (in seconds)
          +Default=3
        + +

        MinNumShots( Integer MinNumShots )
        +

          Sets the minimum # of shots to fire in a cycle
          +Default=1
        + +

        Model( String Model )
        +

          Projectile model to use.
          +Default=models/projectiles/bazookashell.tik
        + +

        target( String targetname_to_target )
        +

          target another entity with targetname_to_target.
        + +

        TickCycle
        +

          Tick the cycle..
        + +

        TurnOff
        +

          Turn Off and cancel the current cycle (if any)
        + +

        TurnOn
        +

          Turn On and begin the first cycle
        +
        + +

        ProjectileGenerator_Gun (ProjectileGenerator_Gun) -> ProjectileGenerator -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        bulletcount( Float bulletCount )
        +

          Set the number of bullets this weapon shoots when fired
        + +

        bulletdamage( Float bulletDamage )
        +

          Set the damage that the bullet causes
        + +

        bulletknockback( Float bulletKnockback )
        +

          Set the knockback that the bullet causes
        + +

        bulletlarge( Integer bulletType )
        +

          Set if the bullets fired are rifle bullets(1), artillery(2) or larger tracers(3)
        + +

        bulletrange( Float bulletRange )
        +

          Set the range of the bullets
        + +

        bulletspread( Float bulletSpreadX, Float bulletSpreadY, [ Float bulletSpreadXmax ], [ Float bulletSpreadYmax ] )
        +

          Set the min & optional max spread of the bullet in the x and y axis
        + +

        fakebullets( Boolean useFakeBullets )
        +

          Whether or not the projectile generator should fire real bullets.
        + +

        firedelay( Float fFireDelay )
        +

          Set the minimum time between shots from the weapon
        + +

        ID( Integer ID )
        +

          Sets the ID for this projectile generator
          +Default=0:
        + +

        meansofdeath( String meansOfDeath )
        +

          Set the meansOfDeath of the weapon.
        + +

        throughmetal( Float dist )
        +

          Sets how far the bullets can go through metal
        + +

        throughwood( Float dist )
        +

          Sets how far the bullets can go through wood
        + +

        tracerfrequency( Float frequenct )
        +

          Set the frequency of making tracers
        + +

        tracerspeed( Float speed )
        +

          Scale factor of how fast a tracer should travel (valid ranges 0-2)
        +
        + +

        ProjectileGenerator_Heavy (ProjectileGenerator_Heavy) -> ProjectileGenerator -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        projectile( String projectileModel )
        +

          Set the model of the projectile that this weapon fires
        +
        + +

        ProjectileGenerator_Projectile (ProjectileGenerator_Projectile) -> ProjectileGenerator -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        arc( Float arc )
        +

          arc in front of the player
        + +

        isdonut( Integer isdonut )
        +

          will target donut
        + +

        maxdonut( Float maxdonut )
        +

          max extent of donut from player
        + +

        mindonut( Float mindonut )
        +

          min extent of donut from player
        + +

        playpreimpact
        +

          Play a pre-impact sound
        + +

        preimpactsound( String Sound )
        +

          Set a pre-impact sound.
        + +

        preimpactsoundprob( Float probability )
        +

          Set the chance for a pre-impact sound to occur.
          +Range: ( 0.0, 1.0 ), with 0 having no chance, and 1 always occurring.
        + +

        preimpactsoundtime( Float delay )
        +

          Set the time before impact to play the preimpact sound.
        + +

        projectile( String projectileModel )
        +

          Set the model of the projectile that this weapon fires
        +
        + +

        ProjectileTarget (ProjectileGenerator_Target) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        ID( Integer ID )
        +

          Sets the ID for this projectile generator
          +Default=0:
        +
        + +

        PuffDaddy (plant_puffdaddy) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        idle
        +

          Animates the puff daddy.
        +
        + +

        PushObject (func_pushobject) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        dmg( Integer damage )
        +

          Set the damage.
        + +

        doBlocked( Entity obstacle )
        +

          sent to entity when blocked.
        + +

        pushsound( String sound )
        +

          Set the pushing sound
        + +

        start
        +

          Sets up the pushobject.
        +
        + +

        Rain (func_rain) -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        RandomSpawn (func_randomspawn) -> Spawn -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        max_time( Float maxTime )
        +

          Maximum time between random spawns.
        + +

        min_time( Float minTime )
        +

          Minimum time between random spawns.
        +
        + +

        RandomSpeaker (sound_randomspeaker) -> TriggerSpeaker -> TriggerPlaySound -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        chance( Float newChance<0.00...1.00> )
        +

          Sets the chance that the sound will play when triggered.
        + +

        maxdelay( Float max_delay )
        +

          Sets the maximum time between playings.
        + +

        mindelay( Float min_delay )
        +

          Sets the minimum time between playings.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        ReSpawn (func_respawn) -> Spawn -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        RotatingDoor (func_rotatingdoor) -> Door -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doclose
        +

          Closes the door (special doors).
        + +

        doopen( Entity other )
        +

          Opens the door (special doors).
        + +

        openangle( Float open_angle )
        +

          Sets the open angle of the door.
        +
        + +

        RunThrough (func_runthrough) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        chance( Float chance )
        +

          chance that trigger will spawn something.
        + +

        delay( Float delay )
        +

          time between RunThrough being activated.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        lip( Float lip )
        +

          distance below trigger we should spawn things.
        + +

        offset( Vector spawn_offset )
        +

          When triggered, what to offset the spawned object by.
        + +

        spawnmodel( String model_to_spawn )
        +

          When triggered, what to spawn.
        + +

        speed( Float speed )
        +

          threshold speed at which RunThrough is activated.
        +
        + +

        Script -> Class

        +
        +
        + +

        ScriptAimedStrafingGunfire (script_aimedstrafinggunfire) -> ScriptSimpleStrafingGunfire -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        aimtarget
        +

          Set the aim target.
        + +

        fire
        +

          Fire.
        +
        + +

        ScriptClass -> Listener -> Class

        +
        +
        + +

        ScriptDoor (script_door) -> Door -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        closethread( String closethread )
        +

          Set the thread to run when the door is closed (required).
        + +

        doclose
        +

          Closes the door (special doors).
        + +

        doinit
        +

          Sets up the script door.
        + +

        doopen( Entity other )
        +

          Opens the door (special doors).
        + +

        initthread( String initthread )
        +

          Set the thread to run when the door is initialized (optional).
        + +

        openthread( String openthread )
        +

          Set the thread to run when the door is opened (required).
        +
        + +

        ScriptEvent -> Class

        +
        +
        + +

        ScriptMaster -> Listener -> Class

        +
        + +

        alias( String alias_name, String real_name, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ] )
        +

          Sets up an alias.
        + +

        aliascache( String alias_name, String real_name, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ] )
        +

          Sets up an alias and caches the resourse.
        + +

        cache( String resourceName )
        +

          pre-cache the given resource.
        +
        + +

        ScriptModel (script_model) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        anim( String anim_name )
        +

          Sets the script model's animation
        + +

        animdone
        +

          Script model animation has finished.
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        moveanim( String animName )
        +

          Makes the script model play an animation and move with the deltas contained in the animation
        + +

        moving_from_anim
        +

          The script model is moving based on an animation
        +
        + +

        ScriptModelRealDamage (script_model_realdamage) -> ScriptModel -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        ScriptOrigin (script_origin) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        +
        + +

        ScriptSimpleStrafingGunfire (script_simplestrafinggunfire) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        bulletcount( Float bulletCount )
        +

          Set the number of bullets this weapon shoots when fired
        + +

        bulletdamage( Float bulletDamage )
        +

          Set the damage that the bullet causes
        + +

        bulletknockback( Float bulletKnockback )
        +

          Set the knockback that the bullet causes
        + +

        bulletrange( Float bulletRange )
        +

          Set the range of the bullets
        + +

        bulletspread( Float bulletSpreadX, Float bulletSpreadY, [ Float bulletSpreadXmax ], [ Float bulletSpreadYmax ] )
        +

          Set the min & optional max spread of the bullet in the x and y axis
        + +

        fire
        +

          Fire.
        + +

        firedelay( Float fFireDelay )
        +

          Set the minimum time between shots from the weapon
        + +

        off
        +

          Turn the gunfire off.
        + +

        on
        +

          Turn the gunfire on.
        + +

        projectile
        +

          Set the projectile model
        + +

        throughmetal( Float dist )
        +

          Sets how far the bullets can go through metal
        + +

        throughwood( Float dist )
        +

          Sets how far the bullets can go through wood
        + +

        tracerfreq
        +

          Set the frequency of the tracers
        +
        + +

        ScriptSkyOrigin (script_skyorigin) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        ScriptSlave (script_object) -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        angles( Vector angles )
        +

          Sets the angles.
        + +

        bind( Entity parent, [ Boolean bind_child ] )
        +

          bind this entity to the specified entity.
        + +

        closeportal
        +

          Close the area portal enclosed in this object
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        dmg( Integer damage )
        +

          Set the damage.
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        doBlocked( Entity obstacle )
        +

          sent to entity when blocked.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        endpath
        +

          Stop following the path
        + +

        explode( Float damage )
        +

          Creates an explosion at the script slave's position
        + +

        flypath( Entity array, Float speed, Float acceleration, Float look_ahead )
        +

          Makes the script slave fly the specified path with speed and acceleration until reached_distance close to position
        + +

        followpath( Entity path, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          Makes the script slave follow the specified path. The allowable arguments are ignoreangles,
          +ignorevelocity, normalangles, loop, and a number specifying the start time.
        + +

        jumpto( String vector_or_entity )
        +

          Jump to specified vector or entity.
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        modifyflypath( Entity array, Float speed, Float acceleration, Float look_ahead )
        +

          Makes the script slave fly the specified path with speed and acceleration until reached_distance close to position
        + +

        move
        +

          Move the script slave.
        + +

        moveBackward( Float dist )
        +

          Move the position backward.
        + +

        moveDown( Float dist )
        +

          Move the position down.
        + +

        moveEast( Float dist )
        +

          Move the position east.
        + +

        moveForward( Float dist )
        +

          Move the position forward.
        + +

        moveLeft( Float dist )
        +

          Move the position left.
        + +

        moveNorth( Float dist )
        +

          Move the position north.
        + +

        moveRight( Float dist )
        +

          Move the position right.
        + +

        moveSouth( Float dist )
        +

          Move the position south.
        + +

        moveto( String vector_or_entity )
        +

          Move to the specified vector or entity.
        + +

        moveUp( Float dist )
        +

          Move the position up.
        + +

        moveWest( Float dist )
        +

          Move the position west.
        + +

        next
        +

          Goto the next waypoint.
        + +

        normalangles( Boolean bUseNormalAngles )
        +

          Sets the object to use normal angles when travelling on a spline path
        + +

        notshootable
        +

          Makes the script slave not shootable
        + +

        openportal
        +

          Open the area portal enclosed in this object
        + +

        path_relativeyaw( Float relativeYaw )
        +

          Makes the script slave follow the specified path with a yaw offset,
        + +

        physics_off
        +

          Turn physics off this script object on
        + +

        physics_on( [ Integer no_collide_entity ] )
        +

          Turn physics on this script object on
          +If no_collide_entity is set to 1 then the script slave will not collide with other entities
        + +

        physics_velocity( Vector impulseVector )
        +

          Add a physical impulse to an object when it is being physically simulated
        + +

        rotateaxis( Integer axis, Float avelocity )
        +

          Rotate about the specified axis at the specified angular velocity.
        + +

        rotateaxisdown( Integer axis, Float angle )
        +

          Rotate the specified axis down by the specified amount.
        + +

        rotateaxisdownto( Integer axis, Float angle )
        +

          Rotate the specified axis down to angle.
        + +

        rotateaxisup( Integer axis, Float angle )
        +

          Rotate the specified axis up by the specified amount.
        + +

        rotateaxisupto( Integer axis, Float angle )
        +

          Rotate the specified axis up to angle.
        + +

        rotatedownto( Vector direction )
        +

          Rotate down to the specified direction.
        + +

        rotateto( Vector direction )
        +

          Rotate to the specified direction.
        + +

        rotateupto( Vector direction )
        +

          Rotate up to the specified direction.
        + +

        rotateX( Float avelocity )
        +

          Rotate about the x axis at the specified angular velocity.
        + +

        rotateXdown( Float angle )
        +

          Rotate the x down by the specified amount.
        + +

        rotateXdownto( Float angle )
        +

          Rotate the x down to angle.
        + +

        rotateXup( Float angle )
        +

          Rotate the x up by the specified amount.
        + +

        rotateXupto( Float angle )
        +

          Rotate the x up to angle.
        + +

        rotateY( Float avelocity )
        +

          Rotate about the y axis at the specified angular velocity.
        + +

        rotateYdown( Float angle )
        +

          Rotate the y down by the specified amount.
        + +

        rotateYdownto( Float angle )
        +

          Rotate the y down to angle.
        + +

        rotateYup( Float angle )
        +

          Rotate the y up by the specified amount.
        + +

        rotateYupto( Float angle )
        +

          Rotate the y up to angle.
        + +

        rotateZ( Float avelocity )
        +

          Rotate about the z axis at the specified angular velocity.
        + +

        rotateZdown( Float angle )
        +

          Rotate the z down by the specified amount.
        + +

        rotateZdownto( Float angle )
        +

          Rotate the z down to angle.
        + +

        rotateZup( Float angle )
        +

          Rotate the z up by the specified amount.
        + +

        rotateZupto( Float angle )
        +

          Rotate the z up to angle.
        + +

        scriptslave_followingpath
        +

          Called every frame to actually follow the path
        + +

        scriptslave_movedone
        +

          Called when the script slave is doen moving
        + +

        setdamage( Integer damage )
        +

          Set the damage.
        + +

        setmeansofdeath( String means_of_death )
        +

          Set the damage means of death.
        + +

        speed( Float speed )
        +

          Sets the speed.
        + +

        time( Float travel_time )
        +

          Sets the travel time.
        + +

        trigger( Entity ent )
        +

          Trigger entities target.
        + +

        unbind
        +

          unbind this entity.
        + +

        waitmove
        +

          Move the script slave and wait until finished.
        +
        + +

        ScriptThread -> Listener -> Class

        +
        + +

        abs( Float arg )
        +

          Absolute value of int or float
        + +

        acos( Float x )
        +

          Compute arc cosine
        + +

        addobjective( Integer objective_number, Integer status, String text, Vector location )
        +

          Adds/Changes an Objective
        + +

        aliascache( String alias, String realPath, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          Create an alias to the specified path and cache the resource
        + +

        all_ai_off
        +

          Turns all AI off.
        + +

        all_ai_on
        +

          Turns all AI on.
        + +

        angles_pointat( Entity parent_entity, Entity entity, Entity target_entity )
        +

          Returns the angles that points at the target_entity given the base orientation of the parent_entity and the position of the entity.
        + +

        angles_toforward( Vector angles )
        +

          Returns the forward vector of the specified angles
        + +

        angles_toleft( Vector angles )
        +

          Returns the left vector of the specified angles
        + +

        angles_toup( Vector angles )
        +

          Returns the up vector of the specified angles
        + +

        asin( Float x )
        +

          Compute arc sine
        + +

        assert( Float value )
        +

          Assert if value is 0.
        + +

        atan( Float arg, [ Float arg2 ] )
        +

          ArcTangent of float (in degrees not radians)
        + +

        atan2( Float x, Float y )
        +

          Compute arc tangent with two parameters
        + +

        bool( Integer value )
        +

          Casts value to a bool.
        + +

        bsptransition( String next_map )
        +

          Transitions to the next BSP. Keeps player data,and game data.
        + +

        cache( String resource_name )
        +

          Cache the specified resource.
        + +

        cam( String command, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          Processes a camera command.
        + +

        canswitchteams( Boolean allow_team_change, [ Boolean allow_spectator ] )
        +

          Specify if players are allowed to switch teams and spectate. Override player's canswitchteams.
        + +

        ceil( Float x )
        +

          Round up value
        + +

        centerprint( String stuffToPrint )
        +

          prints the included message in the middle of all player's screens
        + +

        chartoint( String character )
        +

          Converts char to int
        + +

        cinematic
        +

          Turns on cinematic.
        + +

        clearfade
        +

          Clear the fade from the screen
        + +

        clearletterbox( Float time )
        +

          Clears letterbox mode.
        + +

        clear_objective_pos
        +

          Clears the position of the current objective,for when you don't have one
        + +

        conprintf( String text )
        +

          Prints to console
        + +

        cos( Float arg )
        +

          Cosine of float (expects degrees not radians)
        + +

        cosh( Float x )
        +

          Compute hyperbolic cosine
        + +

        CreateListener
        +

          Creates a Listener instance.
        + +

        cuecamera( Entity entity, [ Float switchTime ] )
        +

          Cue the camera. If switchTime is specified, then the camera
          +will switch over that length of time.
        + +

        cueplayer( [ Float switchTime ] )
        +

          Go back to the normal camera. If switchTime is specified,
          +then the camera will switch over that length of time.
        + +

        debugline( Vector start, Vector end, [ Float red ], [ Float green ], [ Float blue ], [ Float alpha ] )
        +

          Draws a debug line from start to end using the given color and alpha for g_numdebuglinedelays server frames
        + +

        debug_int3
        +

          Generate an asm int 3
        + +

        delaythrow( String label )
        +

          Internal usage.
        + +

        dprintln( String string )
        +

          Prints a debug string.followed by a newline.
        + +

        drawhud( Integer value )
        +

          Specify if hud is to be drawn
        + +

        earthquake( Float duration, Float magnitude, Float no_rampup, Float no_rampdown )
        +

          Create an earthquake
        + +

        earthquake2( Float duration, Float magnitude, Boolean no_rampup, Boolean no_rampdown, [ Vector location ], [ Float radius ] )
        +

          Create a smooth realistic earthquake. Requires sv_reborn to be set.
        + +

        end
        +

          Ends the script
        + +

        entity( Integer value )
        +

          Casts value to an entity.
        + +

        error
        +

          Ends the script
        + +

        exec( String script )
        +

          Executes the specified script.
        + +

        exec( String script )
        +

          Executes the specified script.
        + +

        exp( Float x )
        +

          Compute exponential function
        + +

        fadein( Float time, Float red, Float green, Float blue, Float alpha, [ Integer mode ] )
        +

          Sets up fadein in values.
        + +

        fadeout( Float time, Float red, Float green, Float blue, Float alpha, [ Integer mode ] )
        +

          Sets up fadeout values.
        + +

        fadesound( Float time, [ Float min_vol ], [ Entity player ] )
        +

          Fades the sound out over the given time, optionally to one single player.
          +min_vol being a 0-1 fraction is the minimum volume.
        + +

        fclose( Integer filehandle )
        +

          Closes file of given file handle
        + +

        fcopy( String filename, String copyfilename )
        +

          Copies the file
        + +

        feof( Integer filehandle )
        +

          Checks for end of file
        + +

        ferror( Integer filehandle )
        +

          Checks for last file i/o error
        + +

        fexists( String filename )
        +

          Checks if file exists
        + +

        fflush( Integer filehandle )
        +

          Flushes given stream. Writes all unsaved data from stream buffer to stream
        + +

        fgetc( Integer filehandle )
        +

          Reads single character from file
        + +

        fgets( Integer filehandle, Integer maxbuffsize )
        +

          Reads string line from file
        + +

        flag_clear( String name )
        +

          Clears and deletes a flag.
        + +

        flag_init( String name )
        +

          Initializes a flag so it can be set. Flags MUST be initialized before they can be used for the first time.
        + +

        flag_set( String name )
        +

          Sets a flag which alerts all flag_wait()'s and changes are reflected in flag() checks thereafter.
        + +

        flag_wait( String name )
        +

          Pauses execution flow until a flag has been set.
        + +

        flist( String path, String extension, Integer wantSubs )
        +

          Returns the list of files with given extension
        + +

        float( Integer value )
        +

          Casts value to a float.
        + +

        floor( Float x )
        +

          Round down value
        + +

        fmod( Float x )
        +

          Compute remainder of division
        + +

        fnewdir( String path )
        +

          Creates a new directory
        + +

        fopen( String filename, String accesstype )
        +

          Opens file,returning it's handle
        + +

        forcemusic( String current, [ String fallback ] )
        +

          Forces the current and fallback (optional) music moods.
        + +

        fputc( Integer filehandle, Integer character )
        +

          Writes single character to file
        + +

        fputs( Integer filehandle, String text )
        +

          Writes string line to file
        + +

        fread( Entity player, Integer index, Integer virtual )
        +

          Reads binary buffer from file
        + +

        freadall( Integer filehandle )
        +

          Reads whole file and returns it as string
        + +

        freezeplayer
        +

          Freeze the player.
        + +

        fremove( String filename )
        +

          Removes the file
        + +

        fremovedir( String path )
        +

          Removes a directory
        + +

        frename( String oldfilename, String newfilename )
        +

          Renames the file
        + +

        frewind( Integer filehandle )
        +

          Rewinds file carret to files beginning
        + +

        frexp( Float x )
        +

          Get significand and exponent
        + +

        fsaveall( Integer filehandle, String text )
        +

          Saves whole text to file
        + +

        fseek( Integer filehandle, Integer offset, Integer startpos )
        +

          Sets file carret at given position
        + +

        ftell( Integer filehandle )
        +

          Gets current file carret position
        + +

        fwrite( Entity player, Integer index, Integer virtual )
        +

          Writes binary buffer to file
        + +

        getareaentities( Vector origin, Vector mins, Vector maxs )
        +

          Get all entities around the origin
        + +

        getarraykeys( String array )
        +

          Retrieves a full list containing the name of arrays
        + +

        getarrayvalues( String array )
        +

          Retrieves the full list of an array that was set-up with name, such as local.array[ "name" ] and return their values
        + +

        getboundkey1( String keyname )
        +

          return a string describing the key
        + +

        getboundkey2( String keyname )
        +

          return a string describing the key
        + +

        getclientnum( Entity player )
        +

          Gets player's client number
        + +

        getcvar( String name )
        +

          getcvar
        + +

        getdate
        +

          Gets current date
        + +

        getentarray( String name, String key )
        +

          Gets an array of entities that have the given key, name pair (case sensitive)
        + +

        getentbyentnum( Integer ent_num )
        +

          Gets the specified entity
        + +

        getip( Entity player )
        +

          Gets player's ip
        + +

        getping( Entity player )
        +

          Gets player's ping
        + +

        gettime
        +

          Gets current time
        + +

        gettimezone
        +

          Gets current time zone
        + +

        goto( String label )
        +

          Goes to the specified label.
        + +

        hidemenu( String name, [ Integer bForce ] )
        +

          hide menu,with option to force it off
        + +

        hidemouse
        +

          hide mouse cursor
        + +

        huddraw_3d( Integer index, Vector vector_or_offset, Integer always_show, Integer depth, [ Entity entity ] )
        +

          Sets this huddraw element to be a 3D world icon and can specify if this icon is always shown on-screen even if the player isn't looking at.
          +Uses xy pos from huddraw_rect.
          +If entity is specified, the vector will be an offset relative to the entity.
          +depth specify if the icon is shown through walls.
        + +

        huddraw_align( Integer index, String h_align, String v_align )
        +

          Sets the alignment of a huddraw element for given player. Specified with 'left', 'center', or 'right'
        + +

        huddraw_alpha( Integer index, Float alpha )
        +

          Sets the alpha of a huddraw element for given player
        + +

        huddraw_color( Integer index, Float red, Float green, Float blue )
        +

          Sets the color for a huddraw element for given player
        + +

        huddraw_font( Integer index, String fontname )
        +

          Sets the font to use for given player huddraw element
        + +

        huddraw_rect( Integer index, Integer x, Integer y, Integer width, Integer height )
        +

          Specifies the position of the upper left corner and size of a huddraw element for given player
        + +

        huddraw_shader( Integer index, String shader )
        +

          Sets the shader to use for a particular huddraw element for given player
        + +

        huddraw_string( Integer index, String string )
        +

          Sets a string to be displayed for given player. Clears the shader value
        + +

        huddraw_timer( Integer index, Float duration, Float fade_out_time )
        +

          Sets a timer to be displayed and fade within the given time in seconds. Clears the string value and the shader value of huddraw element.
        + +

        huddraw_virtualsize( Integer index, Integer virtual )
        +

          Sets if the huddraw element for given player should use virutal screen resolution for positioning and size
        + +

        ihuddraw_3d( Entity player, Integer index, Vector vector_or_offset, Integer always_show, Integer depth, [ Entity entity ] )
        +

          Sets this huddraw element to be a 3D world icon for individual player and can specify if this icon is always shown on-screen even if the player isn't looking at.
          +Uses xy pos from huddraw_rect.
          +If entity is specified, the vector will be an offset relative to the entity.
          +depth specify if the icon is shown through walls.
        + +

        ihuddraw_align( Entity player, Integer index, String h_align, String v_align )
        +

          Sets the alignment of a huddraw element for given player. Specified with 'left', 'center', or 'right'
        + +

        ihuddraw_alpha( Entity player, Integer index, Float alpha )
        +

          Sets the alpha of a huddraw element for given player
        + +

        ihuddraw_color( Entity player, Integer index, Float red, Float green, Float blue )
        +

          Sets the color for a huddraw element for given player
        + +

        ihuddraw_font( Entity player, Integer index, String fontname )
        +

          Sets the font to use for given player huddraw element
        + +

        ihuddraw_rect( Entity player, Integer index, Integer x, Integer y, Integer width, Integer height )
        +

          Specifies the position of the upper left corner and size of a huddraw element for given player
        + +

        ihuddraw_shader( Entity player, Integer index, String shader )
        +

          Sets the shader to use for a particular huddraw element for given player
        + +

        ihuddraw_string( Entity player, Integer index, String string )
        +

          Sets a string to be displayed for given player. Clears the shader value
        + +

        ihuddraw_timer( Entity player, Integer index, Float duration, Float fade_out_time )
        +

          Sets a timer to be displayed and fade within the given time in seconds for given player. Clears the string value and the shader value of huddraw element.
        + +

        ihuddraw_virtualsize( Entity player, Integer index, Integer virtual )
        +

          Sets if the huddraw element for given player should use virutal screen resolution for positioning and size
        + +

        int( Integer value )
        +

          Casts value to an int.
        + +

        iprintln( String string )
        +

          Prints a string. followed by a newline.
        + +

        iprintlnbold( String string )
        +

          Prints a string.followed by a newline in a bold/important way.
        + +

        iprintlnbold_noloc( String string )
        +

          Prints a string.followed by a newline in a bold/important way with no localization conversion.
        + +

        iprintln_noloc( String string )
        +

          Prints a string.followed by a newline with no localization conversion.
        + +

        IsAlive( Entity ent )
        +

          Returns true if the specified entity exists and has health > 0.
        + +

        isarray( String object )
        +

          Checks whether this variable is an array
        + +

        isdefined( String object )
        +

          Checks whether this entity/variable is defined
        + +

        isonground( Entity entity )
        +

          Returns 1 if the entity is on ground. 0 otherwise
        + +

        isoutofbounds( Entity entity )
        +

          Returns 1 if the entity is out of bounds. 0 otherwise
        + +

        killclass( String class_name, [ Integer except ] )
        +

          Kills everything in the specified class except for the specified entity (optional).
        + +

        killent( Integer ent_num )
        +

          Kill the specified entity.
        + +

        landminedamage( Entity landmine, Float damage, Float radius )
        +

          radius damage at landmine
        + +

        ldexp( Float x )
        +

          Generate number from significand and exponent
        + +

        letterbox( Float time )
        +

          Puts the game in letterbox mode.
        + +

        leveltransition( String next_map )
        +

          Transitions to the next Level. Statistics to Map Loading,does not keep player data or game data.
        + +

        locprint( Integer xoffset, Integer yoffset, String stuffToPrint )
        +

          prints the included message in the specified location of all player's screens
        + +

        loc_convert_string( String in )
        +

          returns a localized version of the string.
        + +

        log( Float x )
        +

          Compute natural logarithm
        + +

        log10( Float x )
        +

          Compute common logarithm
        + +

        map( String map_name )
        +

          Starts the specified map.
        + +

        md5string( String text )
        +

          generates MD5 hash of given text
        + +

        missionfailed
        +

          Makes the player fail their mission,level restarts.
        + +

        missiontransition( String next_map )
        +

          Transitions to the next Mission. Statistics to Main Menu,Next Level should be unlocked.
        + +

        modf( Float x )
        +

          Break into fractional and integral parts
        + +

        mprint( String string )
        +

          Prints a string.
        + +

        mprintln( String string )
        +

          Prints a string. followed by a newline
        + +

        music( String current, [ String fallback ] )
        +

          Sets the current and fallback (optional) music moods.
        + +

        musicvolume( Float volume, Float fade_time )
        +

          Sets the volume and fade time of the music.
        + +

        netname( Entity player )
        +

          Gets player's netname
        + +

        newhud( [ Entity player ] )
        +

          Create a new HUD element. Optionally for a particular client
        + +

        noncinematic
        +

          Turns off cinematic.
        + +

        pause
        +

          Pauses the thread.
        + +

        PlayMovie( String name )
        +

          Play a Movie...
        + +

        popmenu( Integer index )
        +

          pop menu
        + +

        pow( Float x, Float y )
        +

          Raise to power
        + +

        preg_match( String pattern, String subject )
        +

          Searches subject for a match to the regular expression given in pattern.
        + +

        print( String string )
        +

          Prints a string.
        + +

        print3d( Vector origin, Float scale, String string )
        +

          prints a string in 3D space
        + +

        println( String string )
        +

          Prints a string. followed by a newline.
        + +

        pushmenu( String name )
        +

          push menu
        + +

        radiusdamage( Vector origin, Integer damage, Integer radius, [ Integer constant_damage ] )
        +

          radius damage at origin
        + +

        randomfloat( Float max )
        +

          randomfloat
        + +

        randomint( Integer max )
        +

          randomint
        + +

        registercmd( String name, String label )
        +

          Registers a command.
        + +

        registerev( String eventname, String script )
        +

          Registers script callback handler for specified event
        + +

        releaseplayer
        +

          Release the player.
        + +

        removearchivedclass( String class, [ Integer except_entity_number ] )
        +

          Removes all of the simple archived entities in the specified class.
        + +

        removeclass( String class_name, [ Integer except ] )
        +

          Removes everything in the specified class except for the specified entity (optional).
        + +

        removeent( Integer ent_num )
        +

          Removes the specified entity.
        + +

        restoremusicvolume( Float fade_time )
        +

          Restores the music volume to its previous value.
        + +

        restoresound( Float time, [ Float max_vol ], [ Entity player ] )
        +

          Fades the sound in over the given time, optionally to one single player.
          +max_vol being a 0-1 fraction is the maximum volume.
        + +

        restoresoundtrack
        +

          Restores the soundtrack to the previous one.
        + +

        self
        +

          self
        + +

        server( [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          Server only command.
        + +

        setcurrentobjective( Integer objective_number )
        +

          Sets the specified objective as the current objective
        + +

        setcvar( String cvar_name, String value )
        +

          Sets the value of the specified cvar.
        + +

        setlightstyle( Integer lightstyleindex, String lightstyledata )
        +

          Set up the lightstyle with lightstyleindex to the specified data
        + +

        setscoreboardtoggle( String team, Integer value )
        +

          Sets the specified team's scoreboard toggle
        + +

        settimer( Integer interval, String script )
        +

          Sets timer that will execute script after given interval.
        + +

        set_objective_pos( Vector pos )
        +

          Sets the position in the world of the current objective
        + +

        showmenu( String name, [ Integer bForce ] )
        +

          show menu,with option to force it on
        + +

        sighttrace( Vector start, Vector end, [ Integer pass_entities ], [ Vector mins ], [ Vector maxs ] )
        +

          Performs a trace line from the start to the end, returns 0 if something was hit and 1 otherwise.
        + +

        sin( Float arg )
        +

          Sine of float (expects degrees not radians)
        + +

        sinh( Float x )
        +

          Compute hyperbolic sine
        + +

        soundtrack( String soundtrack_name )
        +

          Changes the soundtrack.
        + +

        spawn( String entityname, [ String keyname1 ], [ String value1 ], [ String keyname2 ], [ String value2 ], [ String keyname3 ], [ String value3 ], [ String keyname4 ], [ String value4 ] )
        +

          Spawns an entity.
        + +

        spawn( String entityname, [ String keyname1 ], [ String value1 ], [ String keyname2 ], [ String value2 ], [ String keyname3 ], [ String value3 ], [ String keyname4 ], [ String value4 ] )
        +

          Spawns an entity.
        + +

        sqrt( Float arg )
        +

          Sqrt of float
        + +

        stopteamrespawn( String team )
        +

          Stops a team (anerican, german, both) from spawning in non-wave deathmatches
        + +

        string( Integer value )
        +

          Casts value to a string.
        + +

        strncpy( Integer bytes, String source )
        +

          Returns the copied string with the specified bytes
        + +

        stuffcmd( [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ] )
        +

          Server only command.
        + +

        stuffsrv( String string )
        +

          Sends command to server
        + +

        tan( Float arg )
        +

          Tangent of float (expects degrees not radians)
        + +

        tanh( Float x )
        +

          Compute hyperbolic tangent
        + +

        teamwin( String axis_or_allies )
        +

          Sets that the 'axis' or the 'allies' have won the map.
        + +

        team_getscore( String team )
        +

          Get a team's current score.
        + +

        team_setscore( String team, Integer score, [ Integer bAdd ] )
        +

          Change/Add score to a team.
        + +

        thread( String label )
        +

          Creates a thread starting at label.
        + +

        thread( String label )
        +

          Creates a thread starting at label.
        + +

        throw( String label )
        +

          Throws to the specified label.
        + +

        timeout( Float time )
        +

          specifies script timeout time
        + +

        trace( Vector start, Vector end, [ Integer pass_entities ], [ Vector mins ], [ Vector maxs ] )
        +

          Performs a Trace Line from the start to the end, returns the end or the position it hit at.
        + +

        traced( Vector start, Vector end, [ Integer pass_entities ], [ Vector mins ], [ Vector maxs ], [ Integer mask ] )
        +

          Performs a Trace Line from the start to the end, returns the array with detailed results
        + +

        trigger( String name )
        +

          Trigger the specified target or entity.
        + +

        typeof( Integer variable )
        +

          Returns the type of variable
        + +

        unregisterev( String eventname )
        +

          Unregisters script callback handler for specified event
        + +

        vector_add( Vector vector1, Vector vector2 )
        +

          Returns vector1 + vector2.
        + +

        vector_closer( Vector vec_a, Vector vec_b, Vector vec_c )
        +

          returns 1 if the first vector is closer than the second vector to the third vector.
        + +

        vector_cross( Vector vector1, Vector vector2 )
        +

          Returns vector1 x vector2.
        + +

        vector_dot( Vector vector1, Vector vector2 )
        +

          Returns vector1 * vector2.
        + +

        vector_length( Vector vector )
        +

          Returns the length of the specified vector.
        + +

        vector_normalize( Vector vector )
        +

          Returns the normalized vector of the specified vector.
        + +

        vector_scale( Vector vector1, Float scale_factor )
        +

          Returns vector1 * scale_factor.
        + +

        vector_subtract( Vector vector1, Vector vector2 )
        +

          Returns vector1 - vector2.
        + +

        vector_toangles( Vector vector1 )
        +

          Returns vector1 converted to angles.
        + +

        vector_within( Vector position1, Vector position2, Float distance )
        +

          returns 1 if the two points are <= distance apart, or 0 if they are greater than distance apart.
        + +

        visiongetnaked
        +

          Gets players' global current naked-eye vision.
        + +

        visionsetnaked( String vision_name, [ Float transition_time ] )
        +

          Sets players' naked-eye vision. Optionally give a transition time from the current vision. If vision_name is an empty string, it will be set to the current map's name.
        + +

        wait( Float wait_time )
        +

          Wait for the specified amount of time.
        + +

        waitframe
        +

          Wait for one server frame.
        +
        + +

        ScriptTimer -> Listener -> Class

        +
        +
        + +

        ScriptVariableList -> Class

        +
        +
        + +

        Sentient -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activatenewweapon
        +

          Activate the new weapon specified by useWeapon. handsurf allows specifying which hand to use for the player
        + +

        american
        +

          Makes the sentient an American.
        + +

        ammo( String type, Integer amount )
        +

          Gives the sentient some ammo.
        + +

        armor( String type, Integer amount )
        +

          Gives the sentient some armor.
        + +

        blockend
        +

          Is the end of the sentient's block.
        + +

        blockstart
        +

          Is the start of the sentient's block.
        + +

        bloodmodel( String bloodModel )
        +

          set the model to be used when showing blood
        + +

        charge( String hand )
        +

          Starts the charging of the weapon in the specified hand
        + +

        checkanims
        +

          Check the animations in the .tik file versus the statefile
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        damagemult( Integer location, Float multiplier )
        +

          Sets the damage multiplier for a particular body location
        + +

        deactivateweapon( String side )
        +

          Deactivate the weapon in the specified hand.
        + +

        dontdropweapons( [ Boolean dont_drop ] )
        +

          Make the sentient not drop weapons
        + +

        dropitems
        +

          drops inventory items
        + +

        fire( [ String hand ], [ String mode ] )
        +

          Fires the weapon in the specified hand.
        + +

        forcedrophealth
        +

          Get if the sentient is forced to drop health no matter what level.nodrophealth is.
        + +

        forcedropweapon
        +

          Force the sentient to drop health no matter what level.nodrophealth is.
        + +

        forcedropweapon
        +

          Force the sentient to drop health no matter what level.nodrophealth is.
        + +

        forcedropweapon
        +

          Get if the sentient is forced to drop health no matter what level.nodrophealth is.
        + +

        forcelandminemeasure
        +

          Force a remeasurement to all landmines
        + +

        german
        +

          Makes the sentient a German.
        + +

        getactiveweap( Integer weaponhand )
        +

          gets currently active weapon in a given hand
        + +

        getnewactiveweap
        +

          gets new active weapon
        + +

        give( String name )
        +

          Gives the sentient the targeted item.
        + +

        givedynitem( String model, String bonename )
        +

          Pass the args to the item.
        + +

        item( String type, Integer amount )
        +

          Gives the sentient the specified amount of the specified item.
        + +

        jumpxy( Float forwardmove, Float sidemove, Float speed )
        +

          Makes the sentient jump.
        + +

        maxgibs( Integer max_number_of_gibs )
        +

          Sets the maximum amount of generic gibs this sentient will spawn when hit.
        + +

        maxmouthangle( Float max_mouth_angle )
        +

          Sets the max mouth angle.
        + +

        meleeattackend
        +

          Is the end of the sentient's melee attack.
        + +

        meleeattackstart
        +

          Is the start of the sentient's melee attack.
        + +

        noshadow
        +

          Turns off the shadow for this sentient.
        + +

        onfire
        +

          Called every frame when the sentient is on fire.
        + +

        pingformines
        +

          actively uncover mines nearby.
        + +

        pophelmet
        +

          Pops a sentient's helmet off if he's got one
        + +

        putawayweapon( String whichHand )
        +

          Put away or deactivate the current weapon, whichHand can be left or right.
        + +

        releasefire( Float fireholdtime )
        +

          Releases the attack in the time specified.
        + +

        reloadweapon( String hand )
        +

          Reloads the weapon in the specified hand
        + +

        sethelmet( String tikifile, Float popspeed, Float dmgmult, String surfacename, String [optional_additional_surface_name] )
        +

          Gives the sentient a helmet and sets the needed info for it
        + +

        setweaponidlestate( Integer state )
        +

          set the idle state of the given weapon.
        + +

        shadow
        +

          Turns on the shadow for this sentient.
        + +

        spawnbloodygibs( [ Integer number_of_gibs ], [ Float scale ] )
        +

          Spawns some bloody generic gibs.
        + +

        stopfire( String hand )
        +

          Stops the firing of the weapon in the specified hand.
        + +

        stoponfire
        +

          Stops the sentient from being on fire.
        + +

        stunend
        +

          Is the end of the sentient's stun.
        + +

        stunstart
        +

          Is the start of the sentient's stun.
        + +

        take( String item_name )
        +

          Takes away the specified item from the sentient.
        + +

        takeall
        +

          Clears out the sentient's entire inventory.
        + +

        team
        +

          returns 'german' or 'american'
        + +

        threatbias( Integer bias )
        +

          Sets the threat bias for this player / AI
        + +

        threatbias( Integer bias )
        +

          Sets the threat bias for this player / AI
        + +

        threatbias
        +

          Gets the threat bias for this player / AI
        + +

        toggleitem
        +

          Toggles the use of the player's item (first item if he has multiple)
        + +

        use( String name, Integer weapon_hand )
        +

          Use the specified weapon or item in the hand choosen (optional).
        + +

        uselast
        +

          Activates the last active weapon
        + +

        useweaponclass( String name, [ Integer weapon_hand ] )
        +

          Use the weapon of the specified class in the hand choosen (optional).
        + +

        weapon( String weapon_modelname )
        +

          Gives the sentient the weapon specified.
        + +

        weaponcommand( String hand, [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ], [ String arg7 ] )
        +

          Pass the args to the active weapon in the specified hand
        +
        + +

        SimpleActor -> Sentient -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        noanimlerp
        +

          Do not LERP to the next animation
        +
        + +

        SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        angle
        +

          get the angles of the entity using just one value.
          +Gets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        angles( Vector newAngles<0.00...360.00><0.00...360.00><0.00...360.00> )
        +

          set the angles of the entity to newAngles.
        + +

        angles
        +

          get the angles of the entity.
        + +

        angles( Vector newAngles<0.00...360.00><0.00...360.00><0.00...360.00> )
        +

          set the angles of the entity to newAngles.
        + +

        centroid
        +

          entity's centroid
        + +

        forwardvector
        +

          get the forward vector of angles
        + +

        leftvector
        +

          get the left vector of angles
        + +

        origin( Vector newOrigin )
        +

          Set the origin of the entity to newOrigin.
        + +

        origin
        +

          entity's origin
        + +

        origin( Vector newOrigin )
        +

          Set the origin of the entity to newOrigin.
        + +

        rightvector
        +

          get the right vector of angles
        + +

        target( String targetname_to_target )
        +

          target another entity with targetname_to_target.
        + +

        target
        +

          entity's target
        + +

        target( String targetname_to_target )
        +

          target another entity with targetname_to_target.
        + +

        targetname( String targetName )
        +

          set the targetname of the entity to targetName.
        + +

        targetname
        +

          entity's targetname
        + +

        targetname( String targetName )
        +

          set the targetname of the entity to targetName.
        + +

        upvector
        +

          get the up vector of angles
        +
        + +

        SinkObject (func_sinkobject) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        active
        +

          make the SinkObject active, so that it will respond to players touching it.
        + +

        dampening( Float newDampening )
        +

          dampening of SinkObject.
        + +

        delay( Float delay )
        +

          Delay until SinkObject starts falling.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        limit( Float newLimit )
        +

          maximum displacement of the SinkObject.
        + +

        notactive
        +

          make the SinkObject not active, so that it won't respond to players touching it.
        + +

        reset
        +

          Reset the SinkObject right now.
        + +

        resetdelay( Float newResetDelay )
        +

          Delay between when sinkobject starts resetting.
        + +

        resetsound( String newResetSound )
        +

          Sound played when sinkobject is resetting.
        + +

        resetspeed( Float newResetspeed )
        +

          Speed at which SinkObject resets itself, defaults to 0.002 * speed.
        + +

        sinksound( String newSinkSound )
        +

          Sound played when sinkobject is sinking.
        + +

        speed( Float speed )
        +

          Speed at which SinkObject starts falling.
        +
        + +

        SlidingDoor (func_door) -> Door -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        doclose
        +

          Closes the door (special doors).
        + +

        doopen( Entity other )
        +

          Opens the door (special doors).
        + +

        lip( Float lip )
        +

          Sets the lip of the sliding door.
        + +

        speed( Float speed )
        +

          Sets the speed of the sliding door.
        +
        + +

        SmokeGrenade (smokegrenade) -> EffectEntity -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        bouncefactor( Float factor )
        +

          sets how far smoke volumes bounce when they collide with something
        + +

        fadedelay( Float time )
        +

          sets how long the entity waits until fading out from 1 alpha to 0 alpha, in seconds
        + +

        fadein( Float time )
        +

          sets fadein time from 0 alpha to 1 alpha, in seconds
        + +

        life( Float life )
        +

          sets how long the smoke emitter lives
        + +

        maxalpha( Float alpha )
        +

          sets maximum opacity of an individual smoke particle, in 0-1 range
        + +

        offset( Float offset_x, Float offset_y, Float offset_z )
        +

          sets offset of the smoke volume from the entity
        + +

        scale( Float scale )
        +

          sets initial scale of each smoke volume
        + +

        scalerate( Float rate )
        +

          sets how fast the smoke volume grows
        + +

        spawnlife( Float life )
        +

          sets how long each smoke volume lives
        + +

        spawnrate( Float rate )
        +

          sets how many smoke volumes are spawned per second
        + +

        spin( Float avel )
        +

          sets the number of rotations per second for this entity around its z axis
        + +

        velocity( Float vel_x, Float vel_y, Float vel_z )
        +

          sets how fast the smoke volume moves away, with x forward and z up
        +
        + +

        SoundManager -> Listener -> Class

        +
        + +

        addmusictrigger
        +

          Add a new music trigger where the player is standing.
        + +

        addrandomspeaker
        +

          Add a new sound where the player is standing.
        + +

        addreverbtrigger
        +

          Add a new reverb trigger where the player is standing.
        + +

        addspeaker
        +

          Add a new sound where the player is standing.
        + +

        delete
        +

          Delete the current sound.
        + +

        globaltranslate( Vector translate_amount )
        +

          Translates all sounds and triggers by specified amount.
        + +

        hide
        +

          Hides the sounds.
        + +

        moveplayer
        +

          Move the player to the current sound position.
        + +

        next
        +

          Go to the next sound.
        + +

        prev
        +

          Go to the previous sound.
        + +

        previewreverb
        +

          Test out the current reverb settings.
        + +

        replace
        +

          Replace the current sound position with the player's.
        + +

        reset
        +

          Resets the state of all sounds and triggers.
        + +

        resetreverb
        +

          reset the reverb settings to a normal.
        + +

        save
        +

          Saves the sounds.
        + +

        show( [ Entity path ] )
        +

          Show all the sounds.
        + +

        switchfacet
        +

          Switch the current facet that we are editing.
        + +

        updateinput
        +

          Updates the current sound with user interface values.
        +
        + +

        Spawn (func_spawn) -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        attackmode( Integer attackmode )
        +

          Sets the attackmode for this spawn entity.
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        modelname( String model_name )
        +

          Sets the model name for this spawn entity.
        + +

        pickup_thread( String threadName )
        +

          Sets the pickup thread for the spawned entity.
        + +

        spawnchance( Float spawn_chance )
        +

          Sets the chance that this spawned entity will spawn something when killed, if it is an actor.
        + +

        spawnitem( String spawn_item_name )
        +

          Adds this named item to what will be spawned when this spawned entity is killed, if it is an actor.
        + +

        spawntarget( String spawntarget )
        +

          Sets spawn target for this spawn entity.
        + +

        spawntargetname( String spawntargetname )
        +

          Sets spawn target name for this spawn entity.
        +
        + +

        SpawnArgs -> Class

        +
        +
        + +

        SpawnChain (func_spawnchain) -> Spawn -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        SpawnOutOfSight (func_spawnoutofsight) -> Spawn -> ScriptSlave -> Mover -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        SplinePath (info_splinepath) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        fadetime( Float fadeTime )
        +

          Sets the fadetime at this node.
        + +

        fov( Float cameraFOV )
        +

          Sets the fov at this node.
        + +

        loop( String loop_name )
        +

          Sets the loop name.
        + +

        speed( Float speed )
        +

          Sets the path speed.
        + +

        SplinePath_create
        +

          Creates the spline path from the target list.
        + +

        triggertarget( String target )
        +

          Sets the trigger target.
        + +

        watch( String watchEntity )
        +

          Sets the entity to watch at this node.
        +
        + +

        TargetList -> Class

        +
        +
        + +

        Teleporter (trigger_teleport) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TeleporterDestination (func_teleportdest) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        +
        + +

        TempWaypoint -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TestPlayerStart (testplayerstart) -> PlayerStart -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        ThrobbingBox_ExplodeFlak88 (ThrobbingBox_ExplodeFlak88) -> ThrobbingBox_Explosive -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        ThrobbingBox_ExplodeNebelwerfer (ThrobbingBox_ExplodeNebelwerfer) -> ThrobbingBox_Explosive -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        ThrobbingBox_ExplodePlayerFlak88 (ThrobbingBox_ExplodePlayerFlak88) -> ThrobbingBox_Explosive -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        ThrobbingBox_ExplodePlayerNebelwerfer (ThrobbingBox_ExplodeNebelwerfer) -> ThrobbingBox_Explosive -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        ThrobbingBox_Explosive (ThrobbingBox_Explosive) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        ActivateSound( String ActivateSound )
        + +

        BlowUp
        + +

        DestroyModel( String DestroyModel )
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        Explode
        +

          Cause the explosion to happen.
        + +

        explosioneffect( String effectModel )
        +

          Set the explosion effect model
        + +

        ExplosionSound( String ExplosionSound )
        + +

        Radius( Float Radius )
        + +

        SetDamage( Float Damage )
        + +

        setthread( String thread )
        +

          Set the thread to execute when this object is used
        + +

        setusethread( String thread )
        +

          Set the thread to execute when this object is used
        + +

        StopWatchDuration( Float StopWatchDuration )
        + +

        TickSound( String TickSound )
        + +

        triggered( Integer triggered )
        +

          Set the triggered status (0 or 1)
        + +

        UsedModel( String UsedModel )
        +

        + +

        ThrobbingBox_Stickybomb (ThrobbingBox_ExplodeNebelwerfer) -> ThrobbingBox_Explosive -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        stickybombwet
        +

        + +

        ThrowObject (func_throwobject) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        pickup( Entity entity, String tag_name )
        +

          Picks up this throw object and attaches it to the entity.
        + +

        pickupoffset( Vector pickup_offset )
        +

          Sets the pickup_offset.
        + +

        throw( Entity owner, Float speed, Entity targetent, [ Float grav ] )
        +

          Throw this throw object.
        + +

        throwsound( String throw_sound )
        +

          Sets the sound to play when object is thrown.
        +
        + +

        TossObject (TossObject) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        bouncesound( String sound )
        +

          When bouncing, what sound to play on impact
        + +

        bouncesoundchance( Float chance<0.00...1.00> )
        +

          When bouncing, the chance that the bounce sound will be played
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        stopped
        +

          sent when entity has stopped bouncing for MOVETYPE_TOSS.
        +
        + +

        TouchAnim (func_touchanim) -> UseAnim -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TouchField -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TOWObjective (func_towobjective) -> Objective -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        AlliesObjNum( Integer AlliesObjNum )
        +

          Sets the objective number for the allies team
        + +

        AxisObjNum( Integer AxisObjNum )
        +

          Sets the objective number for the axis team
        + +

        ControlledBy
        +

          Objective controller
        + +

        ControlledBy( Integer ControlledBy )
        +

          Sets the team controlling the objective
        + +

        initialize
        +

          Initialize object
        + +

        SetCurrent( Integer TeamNum )
        +

          Set this objective as the current objective for the specified team.
        + +

        TakeOver( Integer TeamNum )
        +

          Sets the team controlling the objective. 0 = Axis, 1 = Allies
        +
        + +

        Trigger (trigger_multiple) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activatetrigger( Entity triggering_entity )
        +

          Activates all of the targets for this trigger.
        + +

        activator
        +

          Get's entity who last activated this trigger.
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        cnt( Integer count )
        +

          Set the amount of times this trigger can be triggered
        + +

        cone( Float newTriggerCone )
        +

          Sets the cone in which directed triggers will trigger.
        + +

        delay( Float delay_time )
        +

          Set the delay time (time between triggering and firing) for this trigger
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        edgetriggered( Boolean newEdgeTriggered )
        +

          If true, trigger will only trigger when object enters trigger, not when it is inside it.
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        message( String message )
        +

          Set a message to be displayed when this trigger is activated
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        multifaceted( Integer facetDirection )
        +

          Make this trigger multifaceted. If facet is 1, than trigger is North/South oriented.
          +If facet is 2 than trigger is East/West oriented. If facet is 3 than trigger is Up/Down oriented.
        + +

        noise( String sound )
        +

          Set the sound to play when this trigger is activated
        + +

        nottriggerable
        +

          Turn this trigger off
        + +

        setthread( String thread )
        +

          Set the thread to execute when this trigger is activated
        + +

        sound( String sound )
        +

          Set the sound to play when this trigger is activated
        + +

        triggerable
        +

          Turn this trigger back on
        + +

        triggerthread
        +

          Start the trigger thread.
        + +

        wait( Float wait_time )
        +

          Set the wait time (time bewteen triggerings) for this trigger
        +
        + +

        TriggerAll (trigger_multipleall) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doActivate( Entity activatingEntity )
        +

          General trigger event for all entities
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        +
        + +

        TriggerBox (trigger_box) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        maxs( Vector maxs )
        +

          Sets the maximum bounds of the trigger box.
        + +

        mins( Vector mins )
        +

          Sets the minimum bounds of the trigger box.
        +
        + +

        TriggerByPushObject (trigger_pushobject) -> TriggerOnce -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        triggername( String targetname_of_object )
        +

          If set, trigger will only respond to objects with specified name.
        +
        + +

        TriggerCameraUse (trigger_camerause) -> TriggerUse -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        +
        + +

        TriggerChangeLevel (trigger_changelevel) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        map( String map_name )
        +

          Sets the map to change to when triggered.
        + +

        spawnspot( String spawn_spot )
        +

          Sets the spawn spot to use.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerClickItem (trigger_clickitem) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        +
        + +

        TriggerDamageTargets (trigger_damagetargets) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activatetrigger( Entity triggering_entity )
        +

          Activates all of the targets for this trigger.
        + +

        damage( Integer damage )
        +

          Sets the amount of damage to do.
        +
        + +

        TriggerEntity (trigger_entity) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TriggerExit (trigger_exit) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerGivePowerup (trigger_givepowerup) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        oneshot
        +

          Make this a one time trigger.
        + +

        powerupname( String powerup_name )
        +

          Specifies the powerup to give to the sentient.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerHurt (trigger_hurt) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Integer damage )
        +

          Sets the amount of damage to do.
        + +

        damagetype( String damageType )
        +

          Sets the type of damage a TriggerHurt delivers.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerLandmine (trigger_landmine) -> TriggerEntity -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damageable( Boolean isDamageable )
        +

          Makes the trigger able to take damage, but it is up to the script to watch this damage
        + +

        isabandoned( Entity owner )
        +

          Returns true if the owner has abandoned the mine
        + +

        isimmune( Entity owner )
        +

          Returns true if the given entity is immune to this landmine
        +
        + +

        TriggerMusic (trigger_music) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        altcurrent( String alternate_current_mood )
        +

          Sets the alternate current mood to use when triggered.
        + +

        altfallback( String alterante_fallback_mood )
        +

          Sets the alternate fallback mood to use when triggered.
        + +

        current( String current_mood )
        +

          Sets the current mood to use when triggered.
        + +

        fallback( String fallback_mood )
        +

          Sets the fallback mood to use when triggered.
        + +

        oneshot
        +

          Make this a one time trigger.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        + +

        triggereffectalt( Entity triggering_entity )
        +

          Send event to owner of trigger. This event is only triggered when using a trigger
          +as a multi-faceted edge trigger.
        +
        + +

        TriggerNoDamage (trigger_nodamage) -> TriggerUse -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerOnce (trigger_once) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TriggerPlaySound (play_sound_triggered) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        channel( Integer channel )
        +

          Sets the sound channel to play on.
        + +

        min_dist( Float min_dist )
        +

          Sets the minimum distance.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        + +

        volume( Float volume )
        +

          Sets the volume.
        +
        + +

        TriggerPush (trigger_push) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        angle( Float newAngle )
        +

          set the angles of the entity using just one value.
          +Sets the yaw of the entity or an up and down
          +direction if newAngle is[ 0 - 359 ] or - 1 or - 2
        + +

        speed( Float speed )
        +

          Set the push speed of the TriggerPush
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerPushAny (trigger_pushany) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        speed( Float speed )
        +

          Set the speed.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerRelay (trigger_relay) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TriggerReverb (trigger_music) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        altreverblevel( Float reverbLevel )
        +

          Sets the reverb level to be used when triggered.
        + +

        altreverbtype( Integer reverbType )
        +

          Sets the reverb type.
        + +

        oneshot
        +

          Make this a one time trigger.
        + +

        reverblevel( Float reverbLevel )
        +

          Sets the reverb level to be used when triggered.
        + +

        reverbtype( Integer reverbType )
        +

          Sets the reverb type.
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        + +

        triggereffectalt( Entity triggering_entity )
        +

          Send event to owner of trigger. This event is only triggered when using a trigger
          +as a multi-faceted edge trigger.
        +
        + +

        TriggerSave (trigger_save) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        savename( String name )
        +

          Sets the name which is appended to the world.message for this specific autosave
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerSecret (trigger_secret) -> TriggerOnce -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        TriggerSidedUse (trigger_sideduse) -> TriggerUse -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TriggerSpeaker (sound_speaker) -> TriggerPlaySound -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TriggerUse (trigger_use) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        +
        + +

        TriggerUseOnce (trigger_useonce) -> TriggerUse -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TriggerVehicle (trigger_vehicle) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        TurretGun -> Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        aibulletspread( Float bulletSpreadX, Float bulletSpreadY )
        +

          Set the spread of the bullets in the x and y axis
        + +

        burstFireSettings( Float mintime, Float maxtime, Float mindelay, Float maxdelay )
        +

          Sets the settings for burst mode firing
        + +

        clearAimTarget( [ String target ] )
        +

          Makes the turret aim at an entity
        + +

        convergeTime( Float time )
        +

          Sets the convergence time
        + +

        dojitter( [ Float jitterAmount ] )
        +

          Apply the jitter without firing
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        idleCheckOffset( Vector offset )
        +

          Sets the offset to trace to for collision checking when idling
        + +

        item_droptofloor
        +

          Drops the item to the ground.
        + +

        maxIdlePitch( Float offset )
        +

          Sets the offset to trace to for collision checking when idling
        + +

        maxIdleYaw( Float offset )
        +

          Sets the offset to trace to for collision checking when idling
        + +

        maxuseangle( Float maxuseangle )
        +

          Set max use angle to allow player to mount the turret.
        + +

        maxYawOffset( Float maxoffset )
        +

          Sets the max yaw offset from the turrets central facing direction
        + +

        pitchCaps( Vector caps )
        +

          Sets the pitch caps for the turret. First number is upward cap, second is downward cap, and the third just makes it nice little vector
        + +

        pitchSpeed( Float speed )
        +

          Sets the turret's pitch speed
        + +

        psetviewangles( Vector offset )
        +

          Sets the view angles.
        + +

        setAimOffset( Vector offset )
        +

          Makes the turret aim with specified offset
        + +

        setAimTarget( [ String target ] )
        +

          Makes the turret aim at an entity
        + +

        setPlayerUsable( Integer state )
        +

          Sets wether the turret can be used by players. 0 means no, 1 means yes.
        + +

        setthread( String value )
        +

          Sets the name of the thread called when a player uses the turret
        + +

        setusable( Integer state )
        +

          Sets wether the turret can be used as a weapon. 0 means no, 1 means yes.
        + +

        shoot( [ String mode ] )
        +

          Shoot the weapon
        + +

        startFiring
        +

          Makes the turret start shooting
        + +

        startyaw( Float startyaw )
        +

          Sets the yaw to be used as the center of our allowed turn arc.
        + +

        stopFiring
        +

          Makes the turret stop shooting
        + +

        suppressHeight( Float radius )
        +

          Sets the vertical radius of suppression fire
        + +

        suppressTime( Float time )
        +

          Sets the suppression time
        + +

        suppressWaitTime( Float time )
        +

          Sets the suppression wait nonfiring time before turret returns to default position
        + +

        suppressWidth( Float radius )
        +

          Sets the horizontal radius of suppression fire
        + +

        targettype
        +

          Gets the target type
        + +

        targettype( String value )
        +

          Sets the target type to be none, any, or player
        + +

        targettype( String value )
        +

          Sets the target type to be none any, or player
        + +

        turnSpeed( Float speed )
        +

          Sets the turret's turn speed
        + +

        userdistance( Float dist )
        +

          Sets the distance the user should be placed at while using this turret
        + +

        viewangles
        +

          get the angles of the entity.
        + +

        viewangles( Vector newAngles )
        +

          set the view angles of the entity to newAngles.
        + +

        viewjitter( Float amount )
        +

          Sets the amount that the owner's view should be jittered when fired
        + +

        viewOffset( Vector offset )
        +

          Sets the view offset to use for the turret
        + +

        yawCenter( Float yaw )
        +

          Sets the yaw for the center of the turret's turning arc
        +
        + +

        UseAnim (func_useanim) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        anim( String animName )
        +

          set the animation to use for player.
        + +

        camera( String cameraPosition )
        +

          set the camera to use when in this animation.
          +topdown, behind, front, side, behind_fixed, side_left, side_right
        + +

        count( Integer newCount )
        +

          Sets how many times the UseAnim can be triggered.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        key( String keyName )
        +

          set the key needed to make this UseAnim function.
        + +

        num_loops( Integer loopCount )
        +

          set the number of times to loop an animation per use.
        + +

        setthread( String label )
        +

          Sets which thread to use when this UseAnim is triggered.
        + +

        state( String stateName )
        +

          set the state to use for the player.
        + +

        triggertarget( String targetname )
        +

          Sets what should be triggered, when this UseAnim is triggered.
        +
        + +

        UseAnimDestination (func_useanimdest) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        anim( String animName )
        +

          set the animation to use for player.
        + +

        num_loops( Integer loopCount )
        +

          set the number of times to loop an animation per use.
        + +

        state( String stateName )
        +

          set the state to use for the player.
        +
        + +

        UseObject (func_useobject) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        activate
        +

          Allow the useobject to be used.
        + +

        cone( Float newCone )
        +

          Sets the cone in angles of where the Useobject can be used.
        + +

        count( Integer newCount )
        +

          Sets how many times the UseObject can be triggered.
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        damage_type( String newDamageType )
        +

          Sets what kind of damage is needed to activate the trigger.
        + +

        deactivate
        +

          Do not allow the useobject to be used.
        + +

        move_thread( String label )
        +

          Sets which move thread to use when this UseObject has finshed looping.
        + +

        offset( Vector newOffset )
        +

          Sets the offset to use for this UseObject.
        + +

        reset_thread( String label )
        +

          Sets which thread to call when resetting.
        + +

        reset_time( Float newResetTime )
        +

          Sets the time it takes for the UseObject to reset itself.
        + +

        state( String newState )
        +

          Sets the state to use for this UseObject.
        + +

        state_backwards( String newState )
        +

          Sets the backward state to use for this UseObject.
        + +

        stop_thread( String label )
        +

          Sets which stop thread to use when this UseObject is finished.
        + +

        triggertarget( String targetname )
        +

          Sets what should be triggered, when this UseObject is triggered.
        + +

        usematerial( String nameOfUseMaterial )
        +

          the name of the material that glows when active.
        + +

        yaw_offset( Float newYawOffset )
        +

          Sets the yaw offset to use for this UseObject.
        +
        + +

        Vehicle (script_vehicle) -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        AnimationSet( String animset )
        +

          Sets the Animation Set to use.
        + +

        AttachDriverSlot( Integer slot, Entity entity )
        +

          Attaches an entity to the specified slot.
        + +

        AttachPassengerSlot( Integer slot, Entity entity )
        +

          Attaches an entity to the specified slot.
        + +

        AttachTurretSlot( Integer slot, Entity entity )
        +

          Attaches an entity to the specified slot.
        + +

        back_mass( Float weight )
        +

          Sets the mass of the back of the vehicle
        + +

        BounceBackwardsVelocity( Integer bStayFullSpeed )
        +

          For vehicles on rails that are moving backwards, reverse our velocity. (Optionally pass bStayFullSpeed to keep vehicle at full speed after the bounce)
        + +

        BounceForwardsVelocity
        +

          For vehicles on rails that are moving forwards, reverse our velocity.
        + +

        canjump( Boolean jumpable )
        +

          Sets whether or not the vehicle can jump
        + +

        canuse( Entity entity )
        +

          Returns 1 if passed entity can 'use' this vehicle.
        + +

        collisionent
        +

          Gets the Collision Entity
        + +

        collisionent( Entity entity )
        +

          Gets the Collision Entity
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        damagesounds( Integer on_off )
        +

          Makes the vehicle play damaged sounds.
        + +

        DetachDriverSlot( Integer slot, [ Vector exit_position ] )
        +

          Detaches an entity to the specified slot.
        + +

        DetachPassengerSlot( Integer slot, [ Vector exit_position ] )
        +

          Detaches an entity to the specified slot.
        + +

        DetachTurretSlot( Integer slot, [ Vector exit_position ] )
        +

          Detaches an entity to the specified slot.
        + +

        doBlocked( Entity obstacle )
        +

          sent to entity when blocked.
        + +

        doTouch( Entity touchingEntity )
        +

          sent to entity when touched.
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        drivable
        +

          Make the vehicle drivable
        + +

        drive( Vector position, Float speed, Float acceleration, Float reach_distance, Float look_ahead, [ Vector alternate_position ] )
        +

          Makes the vehicle drive to position with speed and acceleration until reached_distance close to position
        + +

        driveNoWait( Vector position, Float speed, Float acceleration, Float reach_distance )
        +

          Makes the vehicle drive to position with speed and acceleration until reached_distance close to position, thread doesn't wait
        + +

        explosionmodel( String model )
        +

          Sets the TIKI to call when the vehicle dies.
        + +

        front_mass( Float weight )
        +

          Sets the mass of the front of the vehicle
        + +

        fullstop
        +

          Make the Vehicle Stop Moving... Completely!
        + +

        immediateremove
        +

          Removes this listener immediately.
        + +

        lock
        +

          Sets the vehicle to be locked
        + +

        lockmovement
        +

          The Vehicle cannot move.
        + +

        maxuseangle( Float maxuseangle )
        +

          Set max use angle to allow player to mount the turret.
        + +

        model( Entity modelName )
        +

          set the model to modelName.
        + +

        modifydrive( Float desired_speed, Float acceleration, Float look_ahead )
        +

          Modifys the parameters of the current drive.
        + +

        moveanim( String anim_name )
        +

          move the vehicle with an animation
        + +

        name( String vehicleName )
        +

          Set the name for the vehicle
        + +

        nextdrive( Entity next_path )
        +

          appends the specified path to the current path
        + +

        pathDrivable( Boolean pathDrivable )
        +

          Make the vehicle drivable along a path
        + +

        projectilevulnerable( [ Integer number_of_hits ] )
        +

          Make vehicle vulnerable to being one-shot by projectiles. If number_of_hits is given, it will take this many shots.
        + +

        QueryDriverSlotAngles( Integer slot )
        +

          Returns the angles of the specified slot on the vehicle.
        + +

        QueryDriverSlotEntity( Integer slot )
        +

          Returns an entity at the specified slot.
        + +

        QueryDriverSlotPosition( Integer slot )
        +

          Returns the position of the specified slot on the vehicle.
        + +

        QueryDriverSlotStatus( Integer slot )
        +

          Returns the status of the specified slot on the vehicle.
        + +

        QueryFreeDriverSlot
        +

          Returns a number that represents the first free driver slot on the vehicle.
        + +

        QueryFreePassengerSlot
        +

          Returns a number that represents the first free passenger slot on the vehicle.
        + +

        QueryFreeTurretSlot
        +

          Returns a number that represents the first free turret slot on the vehicle.
        + +

        QueryPassengerSlotEntity( Integer slot )
        +

          Returns an entity at the specified slot.
        + +

        QueryPassengerSlotPosition( Integer slot )
        +

          Returns the position of the specified slot on the vehicle.
        + +

        QueryPassengerSlotStatus( Integer slot )
        +

          Returns the status of the specified slot on the vehicle.
        + +

        QuerySpeed( Float speed )
        +

          Returns the current speed of the vehicle.
        + +

        QueryTurretSlotEntity( Integer slot )
        +

          Returns an entity at the specified slot.
        + +

        QueryTurretSlotPosition( Integer slot )
        +

          Returns the position of the specified slot on the vehicle.
        + +

        QueryTurretSlotStatus( Integer slot )
        +

          Returns the status of the specified slot on the vehicle.
        + +

        removeondeath( Integer removeondeath )
        +

          If set to a non-zero value, vehicles will not be removed when they die
        + +

        runsounds( Integer on_off )
        +

          Makes the vehicle play running sounds.
        + +

        seatanglesoffset( Vector angles )
        +

          Set the angles offset of the seat
        + +

        seatoffset( Vector offset )
        +

          Set the offset of the seat
        + +

        setcollisionentity( Entity entity )
        +

          Sets the Collision Entity.
        + +

        setsoundparameters( Float min_speed, Float min_pitch, Float max_speed, Float max_pitch )
        +

          Sets the Sound parameters for this vehicle
        + +

        setvolumeparameters( Float min_speed, Float min_volume, Float max_speed, Float max_volume )
        +

          Sets the Volume parameters for this vehicle
        + +

        setweapon( String weaponname )
        +

          Set the weapon for the vehicle
        + +

        showweapon
        +

          Set the weapon to be show in the view
        + +

        skidding( Integer on_off )
        +

          Makes the vehicle skid around corners.
        + +

        SoundSet( String soundset )
        +

          Sets the Sound Set to use.
        + +

        spawnturret( Integer slot, String tikifile )
        +

          Spawns a turret with the specified model and connects it to the specified slot
        + +

        start
        +

          Initialize the vehicle.
        + +

        steerinplace
        +

          Set the vehicle to turn in place
        + +

        stop
        +

          Make the Vehicle Stop Moving... FULL BREAKS!
        + +

        stopatend
        +

          Makes the vehicle slow down to a complete stop at the end of the path.
        + +

        StopBackwardsVelocity
        +

          Stops any backwards motion for vehicles on rails.
        + +

        turnrate( Float rate )
        +

          Set the turning rate of the vehicle
        + +

        undrivable
        +

          Make the vehicle undrivable
        + +

        unlock
        +

          Sets the vehicle to be unlocked
        + +

        unlockmovement
        +

          The Vehicle can move again.
        + +

        vehicleanim( String anim_name, [ Float weight ] )
        +

          Sets an animation to use in the LD Animation slot.
          +Weight defaults to 1.0
        + +

        vehiclebouncy( Float bouncycoef )
        +

          Sets the Bouncy Coefficient for the shocks.
        + +

        vehicledestroyed
        +

          Driver is dead
        + +

        vehicledrag( Float size )
        +

          Sets the Drag Factor
        + +

        vehicleinit
        +

          Initialized the Vehicle as the specified file
        + +

        vehiclemass( Float weight )
        +

          Sets the mass of the vehicle (backmass = frontmass = mass/2)
        + +

        vehicleradius( Float size )
        +

          Sets the radius of the wheels
        + +

        vehicleRoll( Float min, Float max, Float coef )
        +

          Sets the Roll min and max and the acceleration coefficient for the shocks.
        + +

        vehiclerollingresistance( Float size )
        +

          Sets the radius of the wheels
        + +

        vehiclespeed( Float speed )
        +

          Set the speed of the vehicle
        + +

        vehiclespringy( Float springycoef )
        +

          Sets the Springy Coefficient for the shocks.
        + +

        vehicletread( Float size )
        +

          Sets the size of the wheels
        + +

        VehicleWheelCorners( Vector size, Vector offset )
        +

          Sets the wheel trace corners.
        + +

        vehicleYaw( Float min, Float max, Float coef )
        +

          Sets the Yaw min and max and the acceleration coefficient for the shocks.
        + +

        vehicleZ( Float min, Float max, Float coef )
        +

          Sets the Z min and max and the acceleration coefficient for the shocks.
        +
        + +

        VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        VehicleCollisionEntity -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        owner
        +

          owner
        +
        + +

        VehicleHalfTrack (VehicleHalfTrack) -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        VehiclePoint (info_vehiclepoint) -> Waypoint -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        + +

        spawnflags( Integer spawn_flags )
        +

          Sets the spawn flags.
        +
        + +

        VehicleSoundEntity -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        vehiclesoudnentity_updatetraces
        +

          Updates the traces of a Vehicle Sound Entity
        + +

        vehiclesoundentity_post
        +

          PostSpawn of a Vehicle Sound Entity
        +
        + +

        VehicleTank (VehicleTank) -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        VehicleTankTandem (VehicleTankTandem) -> VehicleTank -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        VehicleTurretGun -> TurretGun -> Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        aimoffset( Vector value )
        +

          Adjust aiming angles by offset.
        + +

        aimtolerance( Vector caps )
        +

          Sets a tolerance for the angles.
        + +

        collisionent
        +

          Gets the Collision Entity
        + +

        collisionent( Entity entity )
        +

          Sets the Collision Entity
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        doUse( Entity activatingEntity )
        +

          sent to entity when it is used by another entity
        + +

        firewarmupdelay( Float value )
        +

          Set the warmup delay before use after mounting the weapon.
        + +

        item_droptofloor
        +

          Drops the item to the ground.
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        lock
        +

          The turret cannot be used.
        + +

        playreloadsound
        +

          Play the turret reload sound.
        + +

        reloaddelay( Float value )
        +

          Set a delay that implies a reload. Will also play a sound
        + +

        reloadshots( Integer value )
        +

          Set the number of shots fired before forcing a reload
        + +

        removeondeath( Integer removeondeath )
        +

          If set to a non-zero value, vehicles will not be removed when they die
        + +

        setbaseentity( Entity base_entity )
        +

          Sets the base entity to take its orientation from.
        + +

        setcollisionentity( Entity entity )
        +

          Sets the Collision Entity.
        + +

        settargetentity( Entity ent )
        +

          Set the entity to point the turret at visually.
        + +

        SoundSet( String soundset )
        +

          Sets the Sound Set to use.
        + +

        unlock
        +

          The turret can be used.
        + +

        warmupdelay( Float value )
        +

          Set the warmup delay before use after mounting the weapon.
        +
        + +

        VehicleTurretGunTandem (VehicleTurretGunTandem) -> VehicleTurretGun -> TurretGun -> Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        linkturret( String name )
        +

          Sets the next turret in the link.
        + +

        setswitchthread( String thread )
        +

          Set the thread to execute when turret is switched
        +
        + +

        VehicleWheelsX2 (VehicleWheelsX2) -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        VehicleWheelsX4 (VehicleWheelsX4) -> DrivableVehicle -> Vehicle -> VehicleBase -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        ViewJitter (func_viewjitter) -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        donedeath
        +

          Makes the view jitter only happen once
        + +

        duration( Float time )
        +

          Sets the length of time it should last. 0 will be instantanious
        + +

        edgeeffect( Float fraction )
        +

          Sets the fraction of the jitter to apply at the max radius
        + +

        jitteramount( Vector jitterangles )
        +

          Sets the jitter angles to apply to the player
        + +

        radius( Float radius )
        +

          Sets the max radius of the view jitter. 0 affects all
        + +

        timedecay( Vector decayrate )
        +

          Sets jitter decay per second
        + +

        triggereffect( Entity triggering_entity )
        +

          Send event to owner of trigger.
        +
        + +

        ViewMaster -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        viewangles( Float pitch<0.00...360.00>, Float yaw<0.00...360.00>, Float roll<0.00...360.00> )
        +

          Set the angles of the current viewthing
        + +

        viewanimate
        +

          Cycle through the animations modes of the current viewthing
          +No Animation
          +Animation with no motion
          +Animation with looping motion
          +Animation with motion
          +
        + +

        viewattach( String tagname, String model )
        +

          Attach a model the the specified tagname
        + +

        viewdelete
        +

          Delete the current viewthing
        + +

        viewdeleteall
        +

          Delete all viewthings
        + +

        viewdetach
        +

          Detach the current viewthing from its parent
        + +

        viewdetachall
        +

          Detach all the models attached to the current viewthing
        + +

        viewmodel( String viewthingModel )
        +

          Set the model of the current viewthing
        + +

        viewnext
        +

          Advance to the next frame of animation of the current viewthing
        + +

        viewnextanim
        +

          Advance to the next animation of the current viewthing
        + +

        vieworigin( Float x, Float y, Float z )
        +

          Set the origin of the current viewthing
        + +

        viewpitch( Float pitch )
        +

          Set the pitch of the current viewthing
        + +

        viewprev
        +

          Advance to the previous frame of animation of the current viewthing
        + +

        viewprevanim
        +

          Advance to the previous animation of the current viewthing
        + +

        viewroll( Float roll )
        +

          Set the roll of the current viewthing
        + +

        viewscale( Float scale )
        +

          Set the scale of the current viewthing
        + +

        viewscaledown
        +

          Decrease the scale of the current viewthing
        + +

        viewscaleup
        +

          Increase the scale of the current viewthing
        + +

        viewsetanim( Float animNum )
        +

          Set the animation absolutely based off a floating point value
        + +

        viewspawn( String model )
        +

          Create a viewthing with the specified model
        + +

        viewthingnext
        +

          Change the active viewthing to the next viewthing
        + +

        viewthingprev
        +

          Change the active viewthing to the previous viewthing
        + +

        viewyaw( Float yaw )
        +

          Set the yaw of the current viewthing
        +
        + +

        Viewthing (viewthing) -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        viewangles( Float pitch<0.00...360.00>, Float yaw<0.00...360.00>, Float roll<0.00...360.00> )
        +

          Set the angles of the current viewthing
        + +

        viewanimate
        +

          Cycle through the animations modes of the current viewthing
          +No Animation
          +Animation with no motion
          +Animation with looping motion
          +Animation with motion
          +
        + +

        viewattach( String tagname, String model )
        +

          Attach a model the the specified tagname
        + +

        viewdelete
        +

          Delete the current viewthing
        + +

        viewdetach
        +

          Detach the current viewthing from its parent
        + +

        viewdetachall
        +

          Detach all the models attached to the current viewthing
        + +

        viewlastframe
        +

          Called when the view things last animation frame is displayed.
        + +

        viewmodel( String viewthingModel )
        +

          Set the model of the current viewthing
        + +

        viewnext
        +

          Advance to the next frame of animation of the current viewthing
        + +

        viewnextanim
        +

          Advance to the next animation of the current viewthing
        + +

        vieworigin( Float x, Float y, Float z )
        +

          Set the origin of the current viewthing
        + +

        viewpitch( Float pitch )
        +

          Set the pitch of the current viewthing
        + +

        viewprev
        +

          Advance to the previous frame of animation of the current viewthing
        + +

        viewprevanim
        +

          Advance to the previous animation of the current viewthing
        + +

        viewroll( Float roll )
        +

          Set the roll of the current viewthing
        + +

        viewsavesurfaces
        +

          Called after the model is spawned to save off the models original surfaces.
        + +

        viewscale( Float scale )
        +

          Set the scale of the current viewthing
        + +

        viewscaledown
        +

          Decrease the scale of the current viewthing
        + +

        viewscaleup
        +

          Increase the scale of the current viewthing
        + +

        viewsetanim( Float animNum )
        +

          Set the animation absolutely based off a floating point value
        + +

        viewthing_think
        +

          Called every frame to process the view thing.
        + +

        viewyaw( Float yaw )
        +

          Set the yaw of the current viewthing
        +
        + +

        VoteOptions -> Class

        +
        +
        + +

        Waypoint (info_waypoint) -> SimpleArchivedEntity -> SimpleEntity -> Listener -> Class

        +
        +
        + +

        Weapon -> Item -> Trigger -> Animate -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        additionalstartammo( String ammotype, Integer amount )
        +

          Gives some additional start ammo of the specified type
        + +

        airange( String airange )
        +

          Set the range of this gun for the ai: short, medium, long, sniper
        + +

        ai_event( [ String type ], [ Float radius ] )
        +

          Let the AI know that this entity made a sound,
          +type is a string specifying what type of sound it is.
          +radius determines how far the sound reaches.
        + +

        ammopickupsound( String name )
        +

          sets the weapon's ammo pickup sound alias
        + +

        ammorequired( Integer amount )
        +

          Set the amount of ammo this weapon requires to fire
        + +

        ammotype( String name )
        +

          Set the type of ammo this weapon uses
        + +

        ammo_in_clip( Integer ammoInClip )
        +

          Set the amount of ammo in the clip
        + +

        anim( String animName )
        +

          Exec anim commands on server or client.
        + +

        attachtohand( String weapon_hand )
        +

          Attaches an active weapon to the specified hand
        + +

        autoaim
        +

          Turn on auto aiming for the weapon
        + +

        autoputaway( Boolean bool )
        +

          Set the weapon to be automatically put away when out of ammo
        + +

        bulletcount( Float bulletCount )
        +

          Set the number of bullets this weapon shoots when fired
        + +

        bulletdamage( Float bulletDamage )
        +

          Set the damage that the bullet causes
        + +

        bulletknockback( Float bulletKnockback )
        +

          Set the knockback that the bullet causes
        + +

        bulletlarge( Integer bulletType )
        +

          Set if the bullets fired are rifle bullets(1), artillery(2) or larger tracers(3)
        + +

        bulletrange( Float bulletRange )
        +

          Set the range of the bullets
        + +

        bulletspread( Float bulletSpreadX, Float bulletSpreadY, [ Float bulletSpreadXmax ], [ Float bulletSpreadYmax ] )
        +

          Set the min & optional max spread of the bullet in the x and y axis
        + +

        cantpartialreload
        +

          Prevents the weapon from being reloaded part way through a clip
        + +

        clipsize( Integer ammoClipSize )
        +

          Set the amount of rounds a clip of the weapon holds
        + +

        clip_add( Integer ammoAmount )
        +

          Add to the weapons ammo clip with ammo from its owner
        + +

        clip_empty
        +

          Empties the weapon's clip of ammo,returning it to the owner
        + +

        clip_fill
        +

          Fills the weapons ammo clip with ammo from its owner
        + +

        cooktime( Float cooktime )
        +

          sets weapons cook time.
        + +

        crosshair( Boolean bool )
        +

          Turn on/off the crosshair for this weapon
        + +

        dmammorequired( Integer amount )
        +

          Set the amount of ammo this weapon requires to fire
        + +

        dmbulletcount( Float bulletCount )
        +

          Set the number of bullets this weapon shoots when fired
        + +

        dmbulletdamage( Float bulletDamage )
        +

          Set the damage that the bullet causes
        + +

        dmbulletrange( Float bulletRange )
        +

          Set the range of the bullets
        + +

        dmbulletspread( Float bulletSpreadX, Float bulletSpreadY, [ Float bulletSpreadXmax ], [ Float bulletSpreadYmax ] )
        +

          Set the min & optional max spread of the bullet in the x and y axis
        + +

        dmcantpartialreload
        +

          Prevents the weapon from being reloaded part way through a clip for DM
        + +

        dmcrosshair( Boolean bool )
        +

          Turn on/off the crosshair for this weapon
        + +

        dmfiredelay( Float fFireDelay )
        +

          Set the minimum time between shots from the weapon
        + +

        dmfirespreadmult( Float scaleadd, Float falloff, Float cap, Float maxtime )
        +

          Sets a time decayed multiplyer to spread when the weapon is fired
        + +

        dmmovementspeed( Float speedmult )
        +

          Alters the movement speed of the player when he has the weapon out
        + +

        dmprojectile( String projectileModel )
        +

          Set the model of the projectile that this weapon fires
        + +

        dmstartammo( Integer amount )
        +

          Set the starting ammo of this weapon
        + +

        dmzoomspreadmult( Float scale )
        +

          Sets the spread multiplier for when using the zoom on a zooming weapon
        + +

        donefiring
        +

          Signals the end of the fire animation
        + +

        donereloading
        +

          Signals the end of the reload animation
        + +

        fallingangleadjust
        +

          Adjusts the weapons angles as it falls to the ground
        + +

        firedelay( Float fFireDelay )
        +

          Set the minimum time between shots from the weapon
        + +

        firespreadmult( Float scaleadd, Float falloff, Float cap, Float maxtime )
        +

          Sets a time decayed multiplyer to spread when the weapon is fired
        + +

        firetype( String firingType )
        +

          Set the firing type of the weapon (projectile or bullet)
        + +

        holsterangles( Vector angles )
        +

          Set the angles of this weapon when it is holstered
        + +

        holsteroffset( Vector offset )
        +

          Set the positional offset when it is holstered
        + +

        holsterscale( Float scale )
        +

          Set the scale of this weapon when it is holstered
        + +

        holstertag( String tagname )
        +

          Set the name of the tag to attach this to when the weapon is holstered.
        + +

        idle
        +

          Puts the weapon into an idle state
        + +

        idleinit
        +

          Puts the weapon into an idle state and clears all the anim slots
        + +

        item_pickup( Entity item )
        +

          Pickup the specified item.
        + +

        loopfire
        +

          Makes the weapon fire by looping the fire animation.
        + +

        mainattachtotag( String tagname )
        +

          Set the name of the tag to attach this to it's owner when being used.
        + +

        makenoise( [ Float noise_radius ], [ Boolean force ] )
        +

          Makes the weapon make noise that actors can hear.
        + +

        maxchargetime( Integer time )
        +

          Set the maximum time the weapon may be charged up
        + +

        maxfiremovement( Float speedmult )
        +

          Sets the max speed the player can be moving to fire the weapon (fraction of weapon's running speed)
        + +

        maxmovementsound( String name )
        +

          sets the weapon's movement fire prevention sound alias
        + +

        maxrange( Float maxRange )
        +

          Set the maximum range of a weapon so the AI knows how to use it
        + +

        meansofdeath( String meansOfDeath )
        +

          Set the meansOfDeath of the weapon.
        + +

        minchargetime( Integer time )
        +

          Set the minimum time the weapon must be charged up
        + +

        minrange( Float minRange )
        +

          Set the minimum range of a weapon so the AI knows how to use it
        + +

        movementspeed( Float speedmult )
        +

          Alters the movement speed of the player when he has the weapon out
        + +

        noammosound( String name )
        +

          sets the weapon's dry fire sound alias
        + +

        notdroppable
        +

          Makes a weapon not droppable
        + +

        numfireanims( Integer value )
        +

          Sets the number of fire animations this weapon uses.
        + +

        offhandattachtotag( String tagname )
        +

          Set the name of the tag to attach this to it's owner's off hand.
        + +

        overcooked
        +

          used when the cookable weapon has been over cooked.
        + +

        overcooked_warning
        +

          causes a warning sound to play that the grenade is about to be overcooked.
        + +

        projectile( String projectileModel )
        +

          Set the model of the projectile that this weapon fires
        + +

        quiet
        +

          Makes the weapon make no noise.
        + +

        range( Float range )
        +

          Set the range of the weapon
        + +

        rank( Integer iOrder, Integer iRank )
        +

          Set the order value and power ranking for the weapon
        + +

        ready
        +

          Signals the end of the ready animation so the weapon can be used
        + +

        secondary( [ String arg1 ], [ String arg2 ], [ String arg3 ], [ String arg4 ], [ String arg5 ], [ String arg6 ], [ String arg7 ], [ String arg8 ] )
        +

          Set the secondary mode of the weapon, by passing commands through
        + +

        secondaryammoinhud
        +

          Makes the weapon show its secondary ammo to the hud.
        + +

        semiauto
        +

          Sets the weapon to fire semi-auto
        + +

        setaimanim( String aimAnimation, Integer aimFrame )
        +

          Set the aim animation and frame for when a weapon fires
        + +

        setcurrentfireanim( Integer value )
        +

          Sets the current firing animation.
        + +

        shareclip( Integer shareClip )
        +

          Sets the weapon to share the same clip between all fire modes
        + +

        shoot( [ String mode ] )
        +

          Shoot the weapon
        + +

        startammo( Integer amount )
        +

          Set the starting ammo of this weapon
        + +

        startingammotoowner
        +

          Internal event used to give ammo to the owner of the weapon
        + +

        startitem( String itemname )
        +

          Adds an item to the starting loadout of the weapon
        + +

        throughmetal( Float dist )
        +

          Sets how far the bullets can go through metal
        + +

        throughwood( Float dist )
        +

          Sets how far the bullets can go through wood
        + +

        tracerfrequency( Float frequenct )
        +

          Set the frequency of making tracers
        + +

        tracerspeed( Float speed )
        +

          Scale factor of how fast a tracer should travel (valid ranges 0-2)
        + +

        usenoammo( Boolean bool )
        +

          Set the weapon to be able to be used when it's out of ammo
        + +

        viewkick( Float pitchmin, Float pitchmax, [ Float yawmin ], [ Float yawmax ] )
        +

          Adds kick to the view of the owner when fired.
        + +

        weapongroup( String weapon_group )
        +

          Sets the weapon group, a set of animations for actor animations scripts to use
        + +

        weapontype( String weapon_type )
        +

          Sets the weapon type
        + +

        worldhitspawn( String modelname )
        +

          Set a model to be spawned when the weapon strikes the world->
        + +

        zoom( Integer zoomfov, [ Integer autozoom ] )
        +

          Sets fov to zoom to on a secondary fire
        + +

        zoommovement( Float speedmult )
        +

          Sets the max speed the player can move while zoomed (fraction of weapon's running speed)
        + +

        zoomspreadmult( Float scale )
        +

          Sets the spread multiplier for when using the zoom on a zooming weapon
        +
        + +

        WindowObject (func_window) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        damage( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          general damage event used by all entities
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        + +

        debristype( Integer type )
        +

          Sets the debris type of the Window
        + +

        killed( Entity attacker, Integer damage, Entity inflictor, Vector position, Vector direction, Vector normal, Integer knockback, Integer damageflags, Integer meansofdeath, Integer location )
        +

          event which is sent to an entity once it as been killed
          +
          +Location values:
          +-1 General
          +0 Pelvis
          +1 Lower Torso
          +2 Mid Torso
          +3 Upper Torso
          +4 Neck
          +5 Head
          +6 RUpperArm
          +7 RForearm
          +8 RHand
          +9 LUpperArm
          +10 LForearm
          +11 LHand
          +12 RThigh
          +13 RCalf
          +14 RFoot
          +15 LThigh
          +16 LCalf
          +17 LFoot
          +
        +
        + +

        World (worldspawn) -> Entity -> SimpleEntity -> Listener -> Class

        +
        + +

        ai_visiondistance( Float vision_distance )
        +

          Sets the default AI Vision Distance
        + +

        animated_farplane( Float farplaneStart, Float farplaneEnd, Float ZStart, Float ZEnd )
        +

          Set the distance of the far clipping plane based on a farplane range and a Z range
        + +

        animated_farplane_bias( Float biasStart, Float biasEnd, Float ZStart, Float ZEnd )
        +

          Set the bias of the far clipping plane based on a bias range and a Z range
        + +

        animated_farplane_color( Vector colorStart, Vector colorEnd, Float ZStart, Float ZEnd )
        +

          Set the color of the far clipping plane based on a color range and a Z range
        + +

        farclipoverride( Float farclipoverride )
        +

          Override the min config default for the far clip distance
        + +

        farplane( Float farplaneDistance )
        +

          Set the distance of the far clipping plane
        + +

        farplane
        +

          Get the distance of the far clipping plane
        + +

        farplane( Float farplaneDistance )
        +

          Set the distance of the far clipping plane
        + +

        farplaneclipcolor( Vector farplaneclipcolor )
        +

          Override the fog color for the min config
        + +

        farplane_bias( Float farplaneDistanceBias )
        +

          Set the distance bias of the far clipping plane
        + +

        farplane_bias( Float farplaneDistanceBias )
        +

          Set the distance bias of the far clipping plane
        + +

        farplane_bias
        +

          Get the distance bias of the far clipping plane
        + +

        farplane_color( Vector farplaneColor )
        +

          Set the color of the far clipping plane fog
        + +

        farplane_color( Vector farplaneColor )
        +

          Set the color of the far clipping plane fog
        + +

        farplane_color
        +

          Get the color of the far clipping plane fog
        + +

        farplane_cull( Integer farplaneCull )
        +

          Whether or not the far clipping plane should cull things out of the world
          +0 - no cull
          +1 - normal cull
          +2 - cull but no bsp culling
        + +

        get_render_terrain
        +

          Get the render terrain switch
        + +

        gravity( Float worldGravity )
        +

          Set the gravity for the whole world.
        + +

        lavaalpha( Float lavaAlpha )
        +

          Set the alpha of lava screen blend
        + +

        lavacolor( Vector lavaColor )
        +

          Set the color of lava screen blend
        + +

        message( String worldMessage )
        +

          Set a message for the world
        + +

        nextmap( String nextMap )
        +

          Set the next map to change to
        + +

        northyaw( Float yaw )
        +

          Sets the yaw direction that is considered to be north
        + +

        render_terrain( Boolean render_terrain )
        +

          Set to draw or not draw terrain
        + +

        skyalpha( Float newAlphaForPortalSky )
        +

          Set the alpha on the sky
        + +

        skybox_farplane( Float farplaneDistance )
        +

          Set the distance of the skybox far clipping plane
        + +

        skybox_farplane
        +

          Get the distance of the skybox far clipping plane
        + +

        skybox_farplane( Float farplaneDistance )
        +

          Set the distance of the skybox far clipping plane
        + +

        skybox_speed( Float speed )
        +

          Set the speed of the skybox
        + +

        skybox_speed( Float speed )
        +

          Set the speed of the skybox
        + +

        skybox_speed
        +

          Get the speed of the skybox
        + +

        skyportal( Boolean newSkyPortalState )
        +

          Whether or not to use the sky portal at all
        + +

        soundtrack( String MusicFile )
        +

          Set music soundtrack for this level.
        + +

        wateralpha( Float waterAlpha )
        +

          Set the alpha of the water screen blend
        + +

        watercolor( Vector waterColor )
        +

          Set the watercolor screen blend
        +
        +

        +191 Game Module Classes.
        2169 Game Module Events. +

        + + diff --git a/docs/getting_started_installation.md b/docs/getting_started_installation.md new file mode 100644 index 00000000..d1edfa69 --- /dev/null +++ b/docs/getting_started_installation.md @@ -0,0 +1,128 @@ +# Installation + +- Windows users can check this [Quick install guide](getting_started_installation_windows.md). +- Linux users may want to check if an OpenMoHAA package is available with the distribution's package manager. + +## Requirements + +- A MOH:AA installation. Common installations include: + - GOG copy (recommended). A fully patched MOH:AA War Chest copy can be acquired [here](https://www.gog.com/en/game/medal_of_honor_allied_assault_war_chest). + - For Linux/macOS, see [Extracting GOG Installer on Linux and macOS](#extracting-gog-setup-file-on-linux-and-macos). + - From a CD. Make sure to [patch your installed copy](#installing-official-patches) + - Demo. See [obtaining a demo version](#obtaining-a-demo-version) +- On Windows, Microsoft Visual C++ 2015/2017/2019/2022 Redistributable from https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170 is required. +- The game should be able to run on any modern hardware. See [System requirements](./getting_started_requirements.md) + +## Installing official patches + +If the **MOH: Warchest** copy is installed, skip directly to the [OpenMoHAA installation](#downloadinginstalling) section. + +Otherwise, install the following patches: + +|Game |Patch to download and install +|---------------|------------------ +|Allied Assault |Depends on the installed language: [English](https://web.archive.org/web/20160229203048/http://largedownloads.ea.com/pub/patches/MOHAA_UKUS_ONLY_patch111v9safedisk.exe), [German](https://web.archive.org/web/20160229203013/http://largedownloads.ea.com/pub/patches/MOHAA_DE_ONLY_patch111v9safedisk.exe), [French](https://web.archive.org/web/20151201080806/http://largedownloads.ea.com/pub/patches/MOHAA_FR_ONLY_patch111v9safedisk.exe) [Italian](https://web.archive.org/web/20141205065317/http://largedownloads.ea.com/pub/patches/MOHAA_IT_ONLY_patch111v9safedisk.exe), [Spanish](https://web.archive.org/web/20151201080738/http://largedownloads.ea.com/pub/patches/MOHAA_ES_ONLY_patch111v9safedisk.exe), or [Dutch](https://web.archive.org/web/20151201080902/http://largedownloads.ea.com/pub/patches/MOHAA_NL_ONLY_patch111v9safedisk.exe) +|Spearhead |[2.0 to 2.11](https://web.archive.org/web/20170130184731/ftp://ftp.ea.com/pub/ea/patches/mohaa_spearhead/mohaas_patch_20_to_211.exe), followed by [2.11 to 2.15](https://web.archive.org/web/20170130184725/ftp://ftp.ea.com/pub/ea/patches/mohaa_spearhead/MOHAAS_Patch_211_to_215.exe) +|Breakthrough |[2.40b](https://web.archive.org/web/20160301122255/http://largedownloads.ea.com/pub/patches/medal_of_honor_allied_assault_breakthrough_patch_2_40.exe) + +These patches are required to connect to multiplayer servers and ensure a smooth, bug-free single-player experience. + +## Downloading/installing OpenMoHAA + +Ensure that you download the binaries compatible with your platform in the [releases](https://github.com/openmoh/openmohaa/releases/latest) section. + +### Which release should be downloaded? + +It depends on the OS that is installed on your device: + +|OS |Kind of hardware (CPU, platform...) |Archive +|---------|-------------------------------------------|----------------------- +|Windows |AMD/Intel |`*-windows-x64.zip` +|Windows |Qualcomm/Snapdragon (ARM-based) |`*-windows-arm64.zip` +|macOS |Apple Silicon (ARM) |`*-macos-arm64.zip` +|macOS |Intel |`*-macos-x86_64.zip` +|Linux |AMD/Intel |`*-linux-amd64` +|Linux |Raspberry Pi 4 or 5 |`*-linux-arm64` + +Once the correct archive was downloaded: + +a) Extract the archive1 to your MOHAA installation directory. + +-or- + +b) Extract the archive1 somewhere on your hard drive, create a shortcut to each of the **launch_openmohaa_\*** executables (or omohaaded.exe), and set the shortcut's 'Start in' directory to your MOHAA installation directory. + +Once you're ready, start one of the three launchers based on whether you want to play the base game, Spearhead, or Breakthrough, and then you can start playing. + +---- + +**Notes:** + +1. For servers, only the `omohaaded.*` and `game.*` binaries from the archive are required. + +## Appendix + +### Cleaning up the game installation directory + +If you want to clean up the mohaa installation directory by keeping only what is needed for OpenMoHAA, the following files/directories can be kept: +```cpp +[MOHAA] +├── [main] +| ├── [sound] +| ├── [video] +│   ├── Pak*.pk3 // all pak files +├── [mainta] +| ├── [sound] +| ├── [video] +│   ├── pak*.pk3 // all pak files +├── [maintt] +| ├── [sound] +| ├── [video] +│   ├── pak*.pk3 // all pak files +├── All files from the OpenMoHAA archive +``` + +### Extracting GOG setup file on Linux and macOS + +If your MOH:AA copy was acquired from GOG then this section will be relevant. + +The MOH:AA Warchest installer files on GOG are Windows binaries. To attain the game files, you can quickly extract them using [Innoextract](https://github.com/dscharrer/innoextract). + +- Install Innoextract using your preferred Package Manager (e.g. [Brew](https://brew.sh/)). + +- Once installed run the command `innoextract setup_medal_of_honor_2.0.0.21.exe`. The MoH:AA game files will be extracted into a folder called 'app'. + +Alternatively, you can use [WINE](https://www.winehq.org/) as well, but this process may take longer if you do not already have WINE installed and configured. + +### Obtaining a demo version + +Alternatively, free demo versions are available online. Here are the links to the demos: + +|Game |Type |Link | +|--------------------|-----------------------------------|--------------------------------------------------------------------------------------| +|MOH:AA | Single-player (0.05) |https://www.gamefront.com/games/medal-of-honor/file/single-player-demo | +|MOH:AA | Multiplayer1 (1.00) |https://www.gamefront.com/games/medal-of-honor/file/multiplayer-demo | +|MOH:AA Spearhead | Multiplayer2 (2.11) |https://www.gamefront.com/games/medal-of-honor/file/mohaa-spearhead-demo-eng | +|MOH:AA Breakthrough | Multiplayer2 (0.30) |https://www.gamefront.com/games/medal-of-honor/file/mohaa-breakthrough-demo | + +- MOH:AA singleplayer demo ships with the level: **Mission 3: Level 3**. +- MOH:AA multiplayer demo ships with the level: **Stalingrad**. **The Hunt** can be added with the [MP Demo addon](https://www.gamefront.com/games/medal-of-honor/file/mp-demo-add-on-the-hunt). +- MOH:AA Spearhead multiplayer demo ships with multiplayer maps: **Malta** and **Druckkammern**. +- MOH:AA Breakthrough multiplayer demo ships with multiplayer maps: **Anzio** and **Palermo**. + +-------- + +**Notes:** + +1. Can play on MOH:AA 1.00 servers only. +2. Only compatible with demo servers. These servers can be identified by having the letter `d` at the start of their version number (e.g: `(d2.11)`). + +--- + +## Ports and other systems + +OpenMoHAA is officially supported on Windows, Linux and macOS. Below is a list of unofficial open-source ports that required custom modifications to the OpenMoHAA source code to build and run: + +- https://github.com/Rinnegatamante/openmohaa + +To stay up to date with the latest features and fixes from the official repository, these ports depend on their respective maintainers to synchronize changes with the main OpenMoHAA codebase. diff --git a/docs/getting_started_installation_windows.md b/docs/getting_started_installation_windows.md new file mode 100644 index 00000000..a446adb8 --- /dev/null +++ b/docs/getting_started_installation_windows.md @@ -0,0 +1,38 @@ +# Quick installation + +This guide assumes you installed **Medal of Honor: Allied Assault Warchest** from GOG, but it also works with CD or other versions. + +You can get it from [GOG here](https://www.gog.com/en/game/medal_of_honor_allied_assault_war_chest). + +## 1. Download + +Grab the latest `openmohaa-*-windows-x64.zip` from the [releases page](https://github.com/openmoh/openmohaa/releases). + +## 2. Find your game folder + +1. Right-click your **Medal of Honor - Allied Assault** desktop shortcut → **Properties** +2. Then check the "**Start in**" field, that's your game folder. + +![Shortcut](screenshots/install_guide/windows_installation_shortcut.png) + +Alternatively, try one of these common locations: +- C:\GOG Games\Medal of Honor - Allied Assault War Chest +- C:\Program Files (x86)\EA Games\MOHAA +- C:\Program Files\Origin Games\Medal of Honor Allied Assault Warchest +- C:\Program Files\GOG Galaxy\Games\Medal of Honor - Allied Assault War Chest + +If not there, you'll need to search where you installed it. + +## 3. Install + +1. **Extract the .zip file** you downloaded into the game folder you found earlier. +2. **Create desktop shortcuts** for these 3 files: + * `launch_openmohaa_base.x86_64.exe` - *Allied Assault* + * `launch_openmohaa_spearhead.x86_64.exe` - *Spearhead* + * `launch_openmohaa_breakthrough.x86_64.exe` - *Breakthrough* + +To do that, **right-click each file**, then choose **Send to → Desktop (create shortcut)**. + +![Send To](screenshots/install_guide/windows_installation_sendto.png) + +Now you can launch any version of the game directly from your desktop using OpenMoHAA. diff --git a/docs/getting_started_requirements.md b/docs/getting_started_requirements.md new file mode 100644 index 00000000..ad76075f --- /dev/null +++ b/docs/getting_started_requirements.md @@ -0,0 +1,88 @@ +# System requirements + +This matches the hardware requirements (x86) of the original game. + +## Medal of Honor: Allied Assault + +1.2 GB of free disk space is required for the full game installation + binaries. + +### x86 (AMD and Intel) + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |450 MHz (Intel Pentium II), or 500 MHz (AMD Athlon) |700 MHz (Intel Pentium III or AMD Athlon) +|Memory |128MB |256MB +|GPU |16MB |32MB + +### ARM + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |600 MHz ARM Cortex-A8 |800 MHz ARM Cortex-A9 +|Memory |128MB |256MB +|GPU |16MB |32MB + +### PowerPC + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |G3 450 MHz |G4 1 GHz +|Memory |128MB |256MB +|GPU |16MB |32MB + +## Spearhead expansion + +1.0 GB of free disk space is required to install Spearhead on top of the base game. + +### x86 (AMD and Intel) + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |450 MHz (Intel Pentium II), or 500 MHz (AMD Athlon) |700 MHz (Intel Pentium III or AMD Athlon) +|Memory |128MB |256MB +|GPU |16MB |32MB + +### ARM + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |600 MHz ARM Cortex-A8 |800 MHz ARM Cortex-A9 +|Memory |128MB |256MB +|GPU |16MB |32MB + +### PowerPC + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |G3 500 MHz |G4 1 GHz +|Memory |256MB |256MB +|GPU |16MB |32MB + +## Breakthrough expansion + +800 MB of free disk space is required to install Breakthrough on top of the base game. + +### x86 (AMD and Intel) + +|Hardware |Minimum |Recommended +|---------------|-----------------------------------------------------|--------------- +|CPU |733 MHz (Intel Pentium III), or 700 MHz (AMD Athlon) |1 GHz (Intel Pentium III or AMD Athlon) +|Memory |128MB |256MB +|GPU |16MB |32MB + +### ARM + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |800 MHz ARM Cortex-A9 |1 GHz ARM Cortex-A15 +|Memory |128MB |256MB +|GPU |16MB |32MB + + +### PowerPC + +|Hardware |Minimum |Recommended +|---------------|----------------------------------------------------|--------------- +|CPU |G3 800 MHz |G4 1 GHz +|Memory |256MB |256MB +|GPU |16MB |32MB diff --git a/docs/getting_started_running.md b/docs/getting_started_running.md new file mode 100644 index 00000000..c89b3288 --- /dev/null +++ b/docs/getting_started_running.md @@ -0,0 +1,64 @@ +# Running + +## Game selection + +**Medal of Honor: Allied Assault** is the default game, but expansions are also supported. + +### From the launchers + +Base game and expansions can be started from one of the 3 launchers: + +- `launch_openmohaa_base`, this starts OpenMoHAA in **Medal of Honor: Allied Assault** mode which is the base game +- `launch_openmohaa_spearhead`, this starts OpenMoHAA in **Medal of Honor: Allied Assault: Spearhead** mode +- `launch_openmohaa_breakthrough`, this starts OpenMoHAA in **Medal of Honor: Allied Assault: Breakthrough** mode + +### From command-line + +**Spearhead** and **Breakthrough** are supported in OpenMoHAA using the `com_target_game` variable. + +To change the target game, append the following command-line arguments to the `openmohaa` and `omohaaded` executable: + +- `+set com_target_game 0` for the default base game (mohaa, uses `main` folder) +- `+set com_target_game 1` for the Spearhead expansion (mohaas, uses `mainta` folder) +- `+set com_target_game 2` for the Breakthrough expansion (mohaab, uses `maintt` folder) + +OpenMoHAA will also use the correct network protocol version accordingly. The default value of `com_target_game` is 0. + +On Windows, a shortcut can be created to the `openmohaa` executable, with the command-line argument appended from above to play an expansion. + +You can now start a local OpenMOHAA server or play on a server. + +### Using a demo version + +The argument `+set com_target_demo 1` must be appended to command-line to play the game or host a server using demo assets. Allied Assault, Spearhead and Breakthrough demos are supported. + +## User data location + +The location of user-writable data, like the console logfile, saves and configuration files can be found in different locations depending on the platform: + +- `%APPDATA%\openmohaa` on Windows +- `~/.openmohaa` on Linux +- `~/Library/Application Support/openmohaa` on macOS + +There will be one or more subdirectories like in the game installation folder, they match the game being used: either base game `main` or expansions `mainta`/`maintt`. + +This is by design since ioquake3 and has two advantages: +- On a multi-user system, each user will have their own configuration file +- It doesn't overwrite the existing MOHAA configuration in the MOHAA installation directory. + +If necessary, the location of user-writable data can be changed manually by setting the `fs_homepath` variable in the command-line argument. This is useful when running a dedicated server that can only use the game directory to store/read data. The value can be a relative path (relative to the current working directory) or an absolute path. Example: +- `+set fs_homepath Z:\openmohaa_data` data will be written inside the fully qualified path `Z:\openmohaa_data` +- `+set fs_homepath homedata` will use the subfolder `homedata` in the process current working directory to write data (will be created automatically) +- `+set fs_homepath .` not recommended, will write data inside the process current working directory + +The game directory is intended to be read-only, which is the reason why the home path exists. This prevents existing files in the game directory from being accidentally overwritten. + +Note that the configuration file isn't created nor written automatically on a dedicated server (**omohaaded**). + +## Playing with bots + +OpenMoHAA has a basic bot system that emulates real players. The maximum number of bots is defined by the `sv_maxbots` variable, and the number of initial bots is defined by the `sv_numbots` variable. Bots can also be added or removed using the `addbot` and `removebot` commands. + +This feature is a great way to test the gameplay and mods. + +Note that maps must have path built for bots to move, multiplayer maps don't have path built by default. The [mp-navigation](https://github.com/openmoh/mp-navigation) PK3 file can be downloaded and installed in the `main` directory, it adds navigation for all multiplayer maps, including multiplayer maps from Spearhead and Breakthrough. diff --git a/docs/images/opm_50a_1.png b/docs/images/v0.50a-x86_64/1.png similarity index 100% rename from docs/images/opm_50a_1.png rename to docs/images/v0.50a-x86_64/1.png diff --git a/docs/images/opm_50b_1.png b/docs/images/v0.50b-x86_64/1.png similarity index 100% rename from docs/images/opm_50b_1.png rename to docs/images/v0.50b-x86_64/1.png diff --git a/docs/images/opm_50b_2.png b/docs/images/v0.50b-x86_64/2.png similarity index 100% rename from docs/images/opm_50b_2.png rename to docs/images/v0.50b-x86_64/2.png diff --git a/docs/images/opm-arm_53_tt_1.png b/docs/images/v0.53-armhf/1.png similarity index 100% rename from docs/images/opm-arm_53_tt_1.png rename to docs/images/v0.53-armhf/1.png diff --git a/docs/images/opm_53_tt_1.png b/docs/images/v0.53-x86_64/1.png similarity index 100% rename from docs/images/opm_53_tt_1.png rename to docs/images/v0.53-x86_64/1.png diff --git a/docs/images/opmtt-x86_64_0.56.0_1.png b/docs/images/v0.56.0-x86_64/1.png similarity index 100% rename from docs/images/opmtt-x86_64_0.56.0_1.png rename to docs/images/v0.56.0-x86_64/1.png diff --git a/docs/images/opmtt-x86_64_0.56.0_2.png b/docs/images/v0.56.0-x86_64/2.png similarity index 100% rename from docs/images/opmtt-x86_64_0.56.0_2.png rename to docs/images/v0.56.0-x86_64/2.png diff --git a/docs/images/opmtt-x86_64_0.56.0_3.png b/docs/images/v0.56.0-x86_64/3.png similarity index 100% rename from docs/images/opmtt-x86_64_0.56.0_3.png rename to docs/images/v0.56.0-x86_64/3.png diff --git a/docs/images/opm-x86_64_0.58.0_1.png b/docs/images/v0.58.0-x86_64/1.png similarity index 100% rename from docs/images/opm-x86_64_0.58.0_1.png rename to docs/images/v0.58.0-x86_64/1.png diff --git a/docs/images/v0.58.0-x86_64/1_old.png b/docs/images/v0.58.0-x86_64/1_old.png new file mode 100644 index 00000000..39e8e791 Binary files /dev/null and b/docs/images/v0.58.0-x86_64/1_old.png differ diff --git a/docs/images/opm-x86_64_0.58.0_2.png b/docs/images/v0.58.0-x86_64/2.png similarity index 100% rename from docs/images/opm-x86_64_0.58.0_2.png rename to docs/images/v0.58.0-x86_64/2.png diff --git a/docs/images/v0.60.0-armhf/1.png b/docs/images/v0.60.0-armhf/1.png new file mode 100644 index 00000000..8d3cb76c Binary files /dev/null and b/docs/images/v0.60.0-armhf/1.png differ diff --git a/docs/images/v0.60.0-x86_64/flughafen_1.png b/docs/images/v0.60.0-x86_64/flughafen_1.png new file mode 100644 index 00000000..e2594f87 Binary files /dev/null and b/docs/images/v0.60.0-x86_64/flughafen_1.png differ diff --git a/docs/images/v0.60.0-x86_64/flughafen_2.png b/docs/images/v0.60.0-x86_64/flughafen_2.png new file mode 100644 index 00000000..db99e529 Binary files /dev/null and b/docs/images/v0.60.0-x86_64/flughafen_2.png differ diff --git a/docs/images/v0.60.0-x86_64/flughafen_3.png b/docs/images/v0.60.0-x86_64/flughafen_3.png new file mode 100644 index 00000000..f71230f3 Binary files /dev/null and b/docs/images/v0.60.0-x86_64/flughafen_3.png differ diff --git a/docs/images/v0.60.0-x86_64/mohdm1_1.png b/docs/images/v0.60.0-x86_64/mohdm1_1.png new file mode 100644 index 00000000..470ca3bd Binary files /dev/null and b/docs/images/v0.60.0-x86_64/mohdm1_1.png differ diff --git a/docs/images/v0.60.0-x86_64/mohdm2_1.png b/docs/images/v0.60.0-x86_64/mohdm2_1.png new file mode 100644 index 00000000..11a0cc34 Binary files /dev/null and b/docs/images/v0.60.0-x86_64/mohdm2_1.png differ diff --git a/docs/images/v0.60.0-x86_64/training_1.png b/docs/images/v0.60.0-x86_64/training_1.png new file mode 100644 index 00000000..36f4f63d Binary files /dev/null and b/docs/images/v0.60.0-x86_64/training_1.png differ diff --git a/docs/images/v0.60.0-x86_64/training_2.png b/docs/images/v0.60.0-x86_64/training_2.png new file mode 100644 index 00000000..75678b0c Binary files /dev/null and b/docs/images/v0.60.0-x86_64/training_2.png differ diff --git a/docs/images/v0.60.0-x86_64/training_3.png b/docs/images/v0.60.0-x86_64/training_3.png new file mode 100644 index 00000000..31b172de Binary files /dev/null and b/docs/images/v0.60.0-x86_64/training_3.png differ diff --git a/docs/screenshots/install_guide/windows_installation_sendto.png b/docs/screenshots/install_guide/windows_installation_sendto.png new file mode 100644 index 00000000..069a18d0 Binary files /dev/null and b/docs/screenshots/install_guide/windows_installation_sendto.png differ diff --git a/docs/screenshots/install_guide/windows_installation_shortcut.png b/docs/screenshots/install_guide/windows_installation_shortcut.png new file mode 100644 index 00000000..014206e7 Binary files /dev/null and b/docs/screenshots/install_guide/windows_installation_shortcut.png differ diff --git a/docs/script/events.md b/docs/script/events.md new file mode 100644 index 00000000..74bad85b --- /dev/null +++ b/docs/script/events.md @@ -0,0 +1,93 @@ +# Events + +OpenMoHAA introduces a new way for scripts to monitor for specific events, like players spawning or getting killed. Multiple scripts can subscribe to the same events. + +## Subscribing + +Commands related to events: +```cpp +event_subscribe event_name script_label + Subscribes to an event, script_label will be called when the event is triggered + +event_unsubscribe event_name script_label + Unsubscribe from an event, script_label will not be called anymore +``` + +When an event is not needed anymore, make sure to call `event_unsubscribe` with the same parameters used when subscribing to the event. + +### Example + +```cpp +main: + event_subscribe "player_spawned" event_player_spawned + // Can specify another script: + //event_subscribe "player_spawned" global/test_script::event_player_spawned +end + +event_player_spawned: + iprintlnbold("player entity number " + self.entnum + " just spawned!") +end +``` + +## List of events + +### Player events + +The `self` object is the player object for all triggered player events. + +#### player_connected + +The player entered the game. + +Called when: +- When a client spawns for the first time +- When the map restarts, or when the map changes (for all players) +- On the next round (for all players) + +This is called after the player finished spawning, and before `player_spawned` event. + +#### player_damaged + +The player just got hit. + +The parameters are the same as the `damage` command: +``` +player_damaged local.attacker local.damage local.inflictor local.position local.direction local.normal local.knockback local.damageflags local.meansofdeath local.location +``` + +#### player_disconnecting + +The player is disconnecting. + +#### player_killed + +The player got killed. + +The parameters are the same as the `killed` command: +``` +player_killed local.attacker local.damage local.inflictor local.position local.direction local.normal local.knockback local.damageflags local.meansofdeath local.location +``` + +#### player_spawned + +The player just spawned. + +Called when: +- The player has entered the battle +- The player respawned or spawned with weapons + +This is called after the player finished spawning. + +The event can be called even for spectators (when the spectator gets respawned). + +#### player_textMessage + +The player sent a text message. + +``` +player_textMessage local.text local.is_team +``` + +Parameters: +- local.text: The raw text message the client sent to the server +- local.is_team: `1` if it's a team message. `0` otherwise (everyone) diff --git a/docs/scripting.md b/docs/scripting.md new file mode 100644 index 00000000..d8130122 --- /dev/null +++ b/docs/scripting.md @@ -0,0 +1,6 @@ +# Scripting + +The documentation is currently incomplete. + +- [Event subscription](./script/events.md) +- [Scripting commands](https://htmlpreview.github.io/?https://github.com/openmoh/openmohaa/blob/main/docs/features_g_allclasses.html) (all classes documentation) \ No newline at end of file diff --git a/make-macosx-ub.sh b/make-macosx-ub.sh deleted file mode 100644 index a7833e2d..00000000 --- a/make-macosx-ub.sh +++ /dev/null @@ -1,232 +0,0 @@ -#!/bin/sh -APPBUNDLE=openmohaa.app -BINARY=openmohaa.ub -DEDBIN=omohaaded.ub -PKGINFO=APPLOMOHAA -ICNS=misc/openmohaa.icns -DESTDIR=build/release-darwin-ub -BASEDIR=main -MPACKDIR=missionpack -Q3_VERSION=`grep "\#define Q3_VERSION" code/qcommon/q_shared.h | \ - sed -e 's/.*".* \([^ ]*\)"/\1/'`; - -BIN_OBJ=" - build/release-darwin-ppc/openmohaa-smp.ppc - build/release-darwin-i386/openmohaa-smp.i386 -" -BIN_DEDOBJ=" - build/release-darwin-ub/omohaaded.ppc - build/release-darwin-i386/omohaaded.i386 -" -BASE_OBJ=" - build/release-darwin-ppc/$BASEDIR/cgameppc.dylib - build/release-darwin-i386/$BASEDIR/cgamei386.dylib - build/release-darwin-ppc/$BASEDIR/uippc.dylib - build/release-darwin-i386/$BASEDIR/uii386.dylib - build/release-darwin-ppc/$BASEDIR/qagameppc.dylib - build/release-darwin-i386/$BASEDIR/qagamei386.dylib -" -MPACK_OBJ=" - build/release-darwin-ppc/$MPACKDIR/cgameppc.dylib - build/release-darwin-i386/$MPACKDIR/cgamei386.dylib - build/release-darwin-ppc/$MPACKDIR/uippc.dylib - build/release-darwin-i386/$MPACKDIR/uii386.dylib - build/release-darwin-ppc/$MPACKDIR/qagameppc.dylib - build/release-darwin-i386/$MPACKDIR/qagamei386.dylib -" -if [ ! -f Makefile ]; then - echo "This script must be run from the openmohaa build directory"; -fi - -TIGERHOST=0 -if uname -r | grep ^8. > /dev/null; then - TIGERHOST=1 -fi - -# we want to use the oldest available SDK for max compatiblity -unset PPC_CLIENT_SDK -PPC_CLIENT_CC=gcc -unset PPC_CLIENT_CFLAGS -unset PPC_CLIENT_LDFLAGS -unset PPC_SERVER_SDK -unset PPC_SERVER_CFLAGS -unset PPC_SERVER_LDFLAGS -unset X86_SDK -unset X86_CFLAGS -unset X86_LDFLAGS -if [ -d /Developer/SDKs/MacOSX10.5.sdk ]; then - PPC_CLIENT_SDK=/Developer/SDKs/MacOSX10.5.sdk - PPC_CLIENT_CC=gcc-4.0 - PPC_CLIENT_CFLAGS="-arch ppc -isysroot /Developer/SDKs/MacOSX10.5.sdk \ - -DMAC_OS_X_VERSION_MIN_REQUIRED=1050" - PPC_CLIENT_LDFLAGS="-arch ppc \ - -isysroot /Developer/SDKs/MacOSX10.5.sdk \ - -mmacosx-version-min=10.5" - PPC_SERVER_SDK=/Developer/SDKs/MacOSX10.5.sdk - PPC_SERVER_CFLAGS=$PPC_CLIENT_CFLAGS - PPC_SERVER_LDFLAGS=$PPC_CLIENT_LDFLAGS - - X86_SDK=/Developer/SDKs/MacOSX10.5.sdk - X86_CFLAGS="-arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk \ - -DMAC_OS_X_VERSION_MIN_REQUIRED=1050" - X86_LDFLAGS="-arch i386 \ - -isysroot /Developer/SDKs/MacOSX10.5.sdk \ - -mmacosx-version-min=10.5" - X86_ENV="CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS" -fi - -if [ -d /Developer/SDKs/MacOSX10.4u.sdk ]; then - PPC_CLIENT_SDK=/Developer/SDKs/MacOSX10.4u.sdk - PPC_CLIENT_CC=gcc-4.0 - PPC_CLIENT_CFLAGS="-arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk \ - -DMAC_OS_X_VERSION_MIN_REQUIRED=1040" - PPC_CLIENT_LDFLAGS="-arch ppc \ - -isysroot /Developer/SDKs/MacOSX10.4u.sdk \ - -mmacosx-version-min=10.4" - PPC_SERVER_SDK=/Developer/SDKs/MacOSX10.4u.sdk - PPC_SERVER_CFLAGS=$PPC_CLIENT_CFLAGS - PPC_SERVER_LDFLAGS=$PPC_CLIENT_LDFLAGS - - X86_SDK=/Developer/SDKs/MacOSX10.4u.sdk - X86_CFLAGS="-arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk \ - -DMAC_OS_X_VERSION_MIN_REQUIRED=1040" - X86_LDFLAGS="-arch i386 \ - -isysroot /Developer/SDKs/MacOSX10.4u.sdk \ - -mmacosx-version-min=10.4" - X86_ENV="CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS" -fi - -if [ -d /Developer/SDKs/MacOSX10.3.9.sdk ] && [ $TIGERHOST ]; then - PPC_CLIENT_SDK=/Developer/SDKs/MacOSX10.3.9.sdk - PPC_CLIENT_CC=gcc-4.0 - PPC_CLIENT_CFLAGS="-arch ppc -isysroot /Developer/SDKs/MacOSX10.3.9.sdk \ - -DMAC_OS_X_VERSION_MIN_REQUIRED=1030" - PPC_CLIENT_LDFLAGS="-arch ppc \ - -isysroot /Developer/SDKs/MacOSX10.3.9.sdk \ - -mmacosx-version-min=10.3" - PPC_SERVER_SDK=/Developer/SDKs/MacOSX10.3.9.sdk - PPC_SERVER_CFLAGS=$PPC_CLIENT_CFLAGS - PPC_SERVER_LDFLAGS=$PPC_CLIENT_LDFLAGS -fi - -if [ -d /Developer/SDKs/MacOSX10.2.8.sdk ] && [ -x /usr/bin/gcc-3.3 ] && [ $TIGERHOST ]; then - PPC_CLIENT_SDK=/Developer/SDKs/MacOSX10.2.8.sdk - PPC_CLIENT_CC=gcc-3.3 - PPC_CLIENT_CFLAGS="-arch ppc \ - -nostdinc \ - -F/Developer/SDKs/MacOSX10.2.8.sdk/System/Library/Frameworks \ - -I/Developer/SDKs/MacOSX10.2.8.sdk/usr/include/gcc/darwin/3.3 \ - -isystem /Developer/SDKs/MacOSX10.2.8.sdk/usr/include \ - -DMAC_OS_X_VERSION_MIN_REQUIRED=1020" - PPC_CLIENT_LDFLAGS="-arch ppc \ - -L/Developer/SDKs/MacOSX10.2.8.sdk/usr/lib/gcc/darwin/3.3 \ - -F/Developer/SDKs/MacOSX10.2.8.sdk/System/Library/Frameworks \ - -Wl,-syslibroot,/Developer/SDKs/MacOSX10.2.8.sdk,-m" -fi - -echo "Building PPC Dedicated Server against \"$PPC_SERVER_SDK\"" -echo "Building PPC Client against \"$PPC_CLIENT_SDK\"" -echo "Building X86 Client/Dedicated Server against \"$X86_SDK\"" -if [ "$PPC_CLIENT_SDK" != "/Developer/SDKs/MacOSX10.2.8.sdk" ] || \ - [ "$PPC_SERVER_SDK" != "/Developer/SDKs/MacOSX10.3.9.sdk" ] || \ - [ "$X86_SDK" != "/Developer/SDKs/MacOSX10.4u.sdk" ]; then - echo "\ -WARNING: in order to build a binary with maximum compatibility you must - build on Mac OS X 10.4 using Xcode 2.3 or 2.5 and have the - MacOSX10.2.8, MacOSX10.3.9, and MacOSX10.4u SDKs installed - from the Xcode install disk Packages folder." -fi - -if [ -z $PPC_CLIENT_SDK ] || [ -z $PPC_SERVER_SDK ] || [ -z $X86_SDK ]; then - echo "\ -ERROR: This script is for building a Universal Binary. You cannot build - for a different architecture unless you have the proper Mac OS X SDKs - installed. If you just want to to compile for your own system run - 'make' instead of this script." - exit 1 -fi -sleep 3 - -if [ ! -d $DESTDIR ]; then - mkdir -p $DESTDIR -fi - -# ppc dedicated server -echo "Building Dedicated Server using $PPC_SERVER_SDK" -sleep 2 -if [ -d build/release-darwin-ppc ]; then - rm -r build/release-darwin-ppc -fi -(ARCH=ppc BUILD_CLIENT_SMP=0 BUILD_CLIENT=0 BUILD_GAME_VM=0 BUILD_GAME_SO=0 \ - CFLAGS=$PPC_SERVER_CFLAGS LDFLAGS=$PPC_SERVER_LDFLAGS make) || exit 1; -cp build/release-darwin-ppc/omohaaded.ppc $DESTDIR - -# ppc client -if [ -d build/release-darwin-ppc ]; then - rm -r build/release-darwin-ppc -fi -(ARCH=ppc USE_OPENAL_DLOPEN=1 BUILD_SERVER=0 CC=$PPC_CLIENT_CC \ - CFLAGS=$PPC_CLIENT_CFLAGS LDFLAGS=$PPC_CLIENT_LDFLAGS make) || exit 1; - -# intel client and server -if [ -d build/release-darwin-i386 ]; then - rm -r build/release-darwin-i386 -fi -(ARCH=i386 CFLAGS=$X86_CFLAGS LDFLAGS=$X86_LDFLAGS make) || exit 1; - -echo "Creating .app bundle $DESTDIR/$APPBUNDLE" -if [ ! -d $DESTDIR/$APPBUNDLE/Contents/MacOS/$BASEDIR ]; then - mkdir -p $DESTDIR/$APPBUNDLE/Contents/MacOS/$BASEDIR || exit 1; -fi -if [ ! -d $DESTDIR/$APPBUNDLE/Contents/MacOS/$MPACKDIR ]; then - mkdir -p $DESTDIR/$APPBUNDLE/Contents/MacOS/$MPACKDIR || exit 1; -fi -if [ ! -d $DESTDIR/$APPBUNDLE/Contents/Resources ]; then - mkdir -p $DESTDIR/$APPBUNDLE/Contents/Resources -fi -cp $ICNS $DESTDIR/$APPBUNDLE/Contents/Resources/openmohaa.icns || exit 1; -echo $PKGINFO > $DESTDIR/$APPBUNDLE/Contents/PkgInfo -echo " - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - $BINARY - CFBundleGetInfoString - openmohaa $Q3_VERSION - CFBundleIconFile - openmohaa.icns - CFBundleIdentifier - org.icculus.quake3 - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - opemohaa - CFBundlePackageType - APPL - CFBundleShortVersionString - $Q3_VERSION - CFBundleSignature - $PKGINFO - CFBundleVersion - $Q3_VERSION - NSExtensions - - NSPrincipalClass - NSApplication - - - " > $DESTDIR/$APPBUNDLE/Contents/Info.plist - -lipo -create -o $DESTDIR/$APPBUNDLE/Contents/MacOS/$BINARY $BIN_OBJ -lipo -create -o $DESTDIR/$APPBUNDLE/Contents/MacOS/$DEDBIN $BIN_DEDOBJ -rm $DESTDIR/omohaaded.ppc -cp $BASE_OBJ $DESTDIR/$APPBUNDLE/Contents/MacOS/$BASEDIR/ -cp $MPACK_OBJ $DESTDIR/$APPBUNDLE/Contents/MacOS/$MPACKDIR/ -cp code/libs/macosx/*.dylib $DESTDIR/$APPBUNDLE/Contents/MacOS/ - diff --git a/misc/build_increment.bat b/misc/build_increment.bat deleted file mode 100644 index a0c38aaf..00000000 --- a/misc/build_increment.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -set BUILD= - -IF EXIST %1.txt ( - set /p BUILD=<%1.txt -) ELSE ( - set BUILD=0 -) - -set /a BUILD=%BUILD%+1 -@echo %BUILD% >%1.txt - -echo Successfully wrote build number to %1.txt. \ No newline at end of file diff --git a/TargetArch.cmake b/misc/cmake/TargetArch.cmake similarity index 91% rename from TargetArch.cmake rename to misc/cmake/TargetArch.cmake index fd4ba8d9..c2c42fb0 100644 --- a/TargetArch.cmake +++ b/misc/cmake/TargetArch.cmake @@ -3,8 +3,12 @@ set(archdetect_c_code " # error cmake_ARCH x86 #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) # error cmake_ARCH x86_64 -#elif defined(__ppc64__) || defined(__powerpc64__) -# error cmake_ARCH ppc64 +#elif defined(__PPC64__) || defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) +# if __BIG_ENDIAN__ +# error cmake_ARCH ppc64 +# else +# error cmake_ARCH ppc64el +# endif #elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) # error cmake_ARCH ppc #elif defined __s390__ @@ -19,10 +23,14 @@ set(archdetect_c_code " # error cmake_ARCH alpha #elif defined __sparc__ # error cmake_ARCH sparc -#elif defined __arm__ || defined (_M_ARM) -# error cmake_ARCH arm #elif defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64) -# error cmake_ARCH aarch64 +# error cmake_ARCH arm64 +#elif defined __arm__ || defined (_M_ARM) +# if defined(__ARM_PCS_VFP) && (__ARM_PCS_VFP) +# error cmake_ARCH armhf +# else +# error cmake_ARCH armel +# endif #elif defined __cris__ # error cmake_ARCH cris #elif defined __hppa__ @@ -63,12 +71,14 @@ function(target_architecture output_var) foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) if("${osx_arch}" STREQUAL "ppc" AND ppc_support) set(osx_arch_ppc TRUE) + elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) + set(osx_arch_ppc64 TRUE) elseif("${osx_arch}" STREQUAL "i386") set(osx_arch_i386 TRUE) elseif("${osx_arch}" STREQUAL "x86_64") set(osx_arch_x86_64 TRUE) - elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) - set(osx_arch_ppc64 TRUE) + elseif("${osx_arch}" STREQUAL "arm64") + set(osx_arch_arm64 TRUE) else() message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}") endif() @@ -79,6 +89,10 @@ function(target_architecture output_var) list(APPEND ARCH ppc) endif() + if(osx_arch_ppc64) + list(APPEND ARCH ppc64) + endif() + if(osx_arch_i386) list(APPEND ARCH i386) endif() @@ -87,8 +101,8 @@ function(target_architecture output_var) list(APPEND ARCH x86_64) endif() - if(osx_arch_ppc64) - list(APPEND ARCH ppc64) + if(osx_arch_arm64) + list(APPEND ARCH arm64) endif() else() # figure out extension for the source file diff --git a/misc/linux/org.openmoh.openmohaa.desktop.in b/misc/linux/org.openmoh.openmohaa.desktop.in new file mode 100644 index 00000000..f9657705 --- /dev/null +++ b/misc/linux/org.openmoh.openmohaa.desktop.in @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Type=Application + +Name=OpenMoHAA +Comment=An open-source game engine compatible with Medal of Honor: Allied Assault +Categories=Game;Shooter; + +Icon=org.openmoh.openmohaa +Exec=launch_openmohaa_base@TARGET_ARCH@ +Terminal=false diff --git a/misc/linux/org.openmoh.openmohaa.metainfo.xml b/misc/linux/org.openmoh.openmohaa.metainfo.xml new file mode 100644 index 00000000..b1229586 --- /dev/null +++ b/misc/linux/org.openmoh.openmohaa.metainfo.xml @@ -0,0 +1,38 @@ + + + org.openmoh.openmohaa + + OpenMoHAA + An open-source game engine compatible with Medal of Honor: Allied Assault and its expansions (Spearhead and Breakthrough) + + FSFAP + GPL-2.0-or-later + + +

        + The main goal of OpenMoHAA is to ensure the future and continuity of Medal of Honor: Allied Assault. It has always been a dream in the community to provide patches and security fixes for the game. Thanks to the ioquake3 project, F.A.K.K SDK and other quality tools, OpenMoHAA has already reached more than half of its goal: to create an open-source version of MoH:AA (based on version 2.40) that is fully compatible with the original game (in terms of protocol, assets, and scripts). +

        +
        + + org.openmoh.openmohaa.desktop + + + https://github.com/openmoh/openmohaa/blob/main/docs/images/v0.60.0-x86_64/mohdm1_1.png?raw=true + Shows a smoke being deployed during multiplayer gameplay + + + https://github.com/openmoh/openmohaa/blob/main/docs/images/v0.60.0-x86_64/flughafen_1.png?raw=true + Shows a turret firing during multiplayer gameplay + + + https://github.com/openmoh/openmohaa/blob/main/docs/images/v0.60.0-x86_64/flughafen_3.png?raw=true + Shows a mortar firing during multiplayer gameplay + + + + + moderate + moderate + intense + +
        diff --git a/misc/linux/org.openmoh.openmohaab.desktop.in b/misc/linux/org.openmoh.openmohaab.desktop.in new file mode 100644 index 00000000..5b2ecf3d --- /dev/null +++ b/misc/linux/org.openmoh.openmohaab.desktop.in @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Type=Application + +Name=OpenMoHAA Breakthrough +Comment=An open-source game engine compatible with Medal of Honor: Allied Assault Breakthrough +Categories=Game;Shooter; + +Icon=org.openmoh.openmohaa +Exec=launch_openmohaa_breakthrough@TARGET_ARCH@ +Terminal=false diff --git a/misc/linux/org.openmoh.openmohaas.desktop.in b/misc/linux/org.openmoh.openmohaas.desktop.in new file mode 100644 index 00000000..66633291 --- /dev/null +++ b/misc/linux/org.openmoh.openmohaas.desktop.in @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Type=Application + +Name=OpenMoHAA Spearhead +Comment=An open-source game engine compatible with Medal of Honor: Allied Assault Spearhead +Categories=Game;Shooter; + +Icon=org.openmoh.openmohaa +Exec=launch_openmohaa_spearhead@TARGET_ARCH@ +Terminal=false diff --git a/misc/openmohaa-lowdetail.svg b/misc/openmohaa-lowdetail.svg new file mode 100644 index 00000000..31994e76 --- /dev/null +++ b/misc/openmohaa-lowdetail.svg @@ -0,0 +1,2254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/openmohaa-text-mono.svg b/misc/openmohaa-text-mono.svg new file mode 100644 index 00000000..ca7dd433 --- /dev/null +++ b/misc/openmohaa-text-mono.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + diff --git a/misc/openmohaa-text-sm.png b/misc/openmohaa-text-sm.png new file mode 100644 index 00000000..e27733be Binary files /dev/null and b/misc/openmohaa-text-sm.png differ diff --git a/misc/openmohaa-text.png b/misc/openmohaa-text.png new file mode 100644 index 00000000..57e1c665 Binary files /dev/null and b/misc/openmohaa-text.png differ diff --git a/misc/openmohaa-text.svg b/misc/openmohaa-text.svg new file mode 100644 index 00000000..8de0f98e --- /dev/null +++ b/misc/openmohaa-text.svg @@ -0,0 +1,8500 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/setup/MacOSX/SLA-dmg.sh b/misc/setup/MacOSX/SLA-dmg.sh deleted file mode 100644 index af268f32..00000000 --- a/misc/setup/MacOSX/SLA-dmg.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash -# -# This script appends the text from Q3A_EULA.txt to a .dmg as a SLA resource -# -# usage is './SLA-dmg.sh /path/to/Q3A_EULA.txt /path/to/ioquake3.dmg' -# - -if [ "x$1" = "x" ] || [ "x$2" = "x" ]; then - echo "usage: ./SLA-dmg.sh /path/to/Q3A_EULA.txt /path/to/ioquake3.dmg" - exit 1; -fi - -if [ ! -r $1 ]; then - echo "$1 is not a readable Q3A_EULA.txt file" - exit 1; -fi -if [ ! -w $2 ]; then - echo "$2 is not writable .dmg file" - exit 1; -fi -touch tmp.r -if [ ! -w tmp.r ]; then - echo "Could not create temporary file tmp.r for writing" - exit 1; -fi - -echo " -data 'LPic' (5000) { - \$\"0002 0011 0003 0001 0000 0000 0002 0000\" - \$\"0008 0003 0000 0001 0004 0000 0004 0005\" - \$\"0000 000E 0006 0001 0005 0007 0000 0007\" - \$\"0008 0000 0047 0009 0000 0034 000A 0001\" - \$\"0035 000B 0001 0020 000C 0000 0011 000D\" - \$\"0000 005B 0004 0000 0033 000F 0001 000C\" - \$\"0010 0000 000B 000E 0000\" -}; - -data 'TEXT' (5002, \"English\") { -" > tmp.r - -sed -e 's/"/\\"/g' -e 's/\(.*\)$/"\1\\n"/g' $1 >> tmp.r - -echo " -}; - -resource 'STR#' (5002, \"English\") { - { - \"English\", - \"Agree\", - \"Disagree\", - \"Print\", - \"Save...\", - \"IMPORTANT - Read this License Agreement carefully before clicking on \" - \"the \\\"Agree\\\" button. By clicking on the \\\"Agree\\\" button, you agree \" - \"to be bound by the terms of the License Agreement.\", - \"Software License Agreement\", - \"This text cannot be saved. This disk may be full or locked, or the \" - \"file may be locked.\", - \"Unable to print. Make sure you have selected a printer.\" - } -}; -" >> tmp.r - -hdiutil convert -format UDCO -o tmp.dmg $2 || exit 1 -hdiutil unflatten tmp.dmg || exit 1 -/Developer/Tools/Rez /Developer/Headers/FlatCarbon/*.r tmp.r -a -o tmp.dmg \ - || exit 1 -hdiutil flatten tmp.dmg || exit 1 -hdiutil internet-enable -yes tmp.dmg || exit 1 -mv tmp.dmg $2 || (echo "Could not copy tmp.dmg to $2" && exit 1) -rm tmp.dmg -rm tmp.r -echo "SLA $1 successfully added to $2" diff --git a/misc/setup/Makefile b/misc/setup/Makefile deleted file mode 100644 index 286831c7..00000000 --- a/misc/setup/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -VERSION=1.34 -RELEASE=svn - -all: - VERSION=$(VERSION) RELEASE=$(RELEASE) ./doit - -sign: - for i in *.run; do \ - gpg -bao $$i.asc $$i; \ - done - -clean: - rm -rf *.run image - -.PHONY: all sign clean diff --git a/misc/setup/Solaris_pkg.sh b/misc/setup/Solaris_pkg.sh deleted file mode 100644 index 6b64201f..00000000 --- a/misc/setup/Solaris_pkg.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash - -# Source directory -MOUNT_DIR="../.." - -# Solaris stuff -PLATFORM=`uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]'` -if [ "X`uname -m`" = "Xi86pc" ]; then - ARCH=i386 -else - ARCH=sparc -fi - -# Packages -PKG_SOLARIS_NAME=ioquake3 -PKG_DATA_NAME=ioquake3d -BUILD_DATE="`/usr/bin/date '+%Y%m%d%H%M%S'`" -SVNVERSION=/usr/local/bin/svnversion -if [ -x /usr/local/bin/svnversion ]; then - SVN_BANNER=`/usr/local/bin/svnversion ${MOUNT_DIR}|sed -e 's/S$//' -e 's/M$//' ` - BUILD_VERSION="1.34-r${SVN_BANNER}" -else - BUILD_VERSION="1.34-rSVN" -fi -PKG_VERSION="`date '+%Y%m%d%H%M'`" -PKG_MAINT_ID="quake@cojot.name" -SOLARIS_PKGFILE="${PKG_SOLARIS_NAME}-${BUILD_VERSION}-${PKG_VERSION}-${ARCH}.pkg" -DATA_PKGFILE="${PKG_DATA_NAME}-${BUILD_VERSION}-${PKG_VERSION}-${ARCH}.pkg" - -# build directories -BUILD_DIR="${MOUNT_DIR}/build/release-${PLATFORM}-${ARCH}" -PKG_SRC_DIR="${MOUNT_DIR}/misc/setup/pkg/${PKG_SOLARIS_NAME}" -PKG_BUILD_DIR="/tmp/ioquake3-build/${PKG_SOLARIS_NAME}-${BUILD_VERSION}" -PKG_DATA_SRC_DIR="${MOUNT_DIR}/misc/setup/pkg/${PKG_DATA_NAME}" -PKG_DATA_BUILD_DIR="/usr/local/src/quake3-data/quake3" - -# Tools -RM="/usr/bin/rm" -TOUCH="/usr/bin/touch" -SED="/usr/bin/sed" -CAT="/usr/bin/cat" -NAWK="/usr/bin/nawk" -MKDIR="gmkdir -v -p" -INSTALL_BIN="ginstall -D -m 755" -INSTALL_DATA="ginstall -D -m 644" -PKGPROTO="/usr/bin/pkgproto" -PKGMK="/usr/bin/pkgmk" -PKGTRANS="/usr/bin/pkgtrans" - -############################################################################# -# SOLARIS PACKAGE -############################################################################# - -if [ -d ${BUILD_DIR} ]; then - if [ ! -d ${BUILD_DIR}/pkg ]; then - ${MKDIR} ${BUILD_DIR}/pkg - fi - echo "Building ${BUILD_DIR}/pkg/${SOLARIS_PKGFILE}" - ${RM} -f ${BUILD_DIR}/pkg/${SOLARIS_PKGFILE} - ${TOUCH} ${BUILD_DIR}/pkg/${SOLARIS_PKGFILE} - ${SED} -e "/VERSION=/s/.*/VERSION=${BUILD_VERSION}-${PKG_VERSION}/" \ - < ${PKG_SRC_DIR}/pkginfo.template \ - > ${PKG_SRC_DIR}/pkginfo - ${CAT} ${PKG_SRC_DIR}/prototype.template > ${PKG_SRC_DIR}/prototype - - ${INSTALL_DATA} ${MOUNT_DIR}/COPYING.txt ${PKG_SRC_DIR}/copyright - for EXEC_READ in README id-readme.txt - do - if [ -f ${MOUNT_DIR}/${EXEC_READ} ]; then - ${INSTALL_DATA} ${MOUNT_DIR}/${EXEC_READ} ${PKG_BUILD_DIR}/${EXEC_READ} - fi - done - - for EXEC_BIN in ioq3ded ioquake3-smp ioquake3 - do - if [ -f ${BUILD_DIR}/${EXEC_BIN}.${ARCH} ]; then - ${INSTALL_BIN} ${BUILD_DIR}/${EXEC_BIN}.${ARCH} ${PKG_BUILD_DIR}/${EXEC_BIN}.${ARCH} - fi - done - - for EXEC_SH in ioq3ded.sh ioquake3.sh - do - if [ -f ${MOUNT_DIR}/misc/setup/pkg/${EXEC_SH} ]; then - ${INSTALL_BIN} ${MOUNT_DIR}/misc/setup/pkg/${EXEC_SH} ${PKG_BUILD_DIR}/${EXEC_SH} - fi - done - - for EXEC_SO in cgamesparc.so qagamesparc.so uisparc.so - do - if [ -f ${BUILD_DIR}/baseq3/${EXEC_SO} ]; then - ${INSTALL_BIN} ${BUILD_DIR}/baseq3/${EXEC_SO} ${PKG_BUILD_DIR}/baseq3/${EXEC_SO} - fi - if [ -f ${BUILD_DIR}/missionpack/${EXEC_SO} ]; then - ${INSTALL_BIN} ${BUILD_DIR}/missionpack/${EXEC_SO} ${PKG_BUILD_DIR}/missionpack/${EXEC_SO} - fi - done - - ${PKGPROTO} ${PKG_BUILD_DIR}=quake3 | \ - ${NAWK} '{ print $1,$2,$3,$4 }' >> ${PKG_SRC_DIR}/prototype - ${PKGMK} -o -p "${PKG_MAINT_ID}${BUILD_DATE}" \ - -b ${PKG_SRC_DIR} -f ${PKG_SRC_DIR}/prototype \ - -d /tmp -a ${ARCH} owner=root group=bin mode=0755 - ${PKGTRANS} -s /tmp ${BUILD_DIR}/pkg/${SOLARIS_PKGFILE} ${PKG_SOLARIS_NAME} - - echo "Building ${BUILD_DIR}/pkg/${DATA_PKGFILE}" - ${RM} -f ${BUILD_DIR}/pkg/${DATA_PKGFILE} - ${TOUCH} ${BUILD_DIR}/pkg/${DATA_PKGFILE} - ${SED} -e "/VERSION=/s/.*/VERSION=${BUILD_VERSION}.${PKG_VERSION}/" \ - < ${PKG_DATA_SRC_DIR}/pkginfo.template \ - > ${PKG_DATA_SRC_DIR}/pkginfo - ${CAT} ${PKG_DATA_SRC_DIR}/prototype.template > ${PKG_DATA_SRC_DIR}/prototype - - if [ -d ${MOUNT_DIR}/../webspace/include ]; then - EULA_DIR=${MOUNT_DIR}/../webspace/include - else - if [ -d ${MOUNT_DIR}/../../webspace/include ]; then - EULA_DIR=${MOUNT_DIR}/../../webspace/include - fi - fi - if [ -f ${EULA_DIR}/id_patch_pk3s_Q3A_EULA.txt ]; then - ${INSTALL_DATA} ${EULA_DIR}/id_patch_pk3s_Q3A_EULA.txt ${PKG_DATA_SRC_DIR}/copyright - fi - - ${PKGPROTO} ${PKG_DATA_BUILD_DIR}=quake3 | \ - ${NAWK} '{ print $1,$2,$3,$4 }' >> ${PKG_DATA_SRC_DIR}/prototype - ${PKGMK} -o -p "${PKG_MAINT_ID}${BUILD_DATE}" \ - -b ${PKG_DATA_SRC_DIR} -f ${PKG_DATA_SRC_DIR}/prototype \ - -d /tmp -a ${ARCH} owner=root group=bin mode=0755 - ${PKGTRANS} -s /tmp ${BUILD_DIR}/pkg/${DATA_PKGFILE} ${PKG_DATA_NAME} -else - echo "Directory ${BUILD_DIR} not found!" - exit 1 -fi - - diff --git a/misc/setup/doit b/misc/setup/doit deleted file mode 100644 index 834cff90..00000000 --- a/misc/setup/doit +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash - -: ${MAKESELF:=/usr/share/loki-setup/makeself} -: ${SETUPIMAGE:=/usr/share/loki-setup/image} - -: ${VERSION:=0.0_`date +%Y%m%d%H%M`} -: ${RELEASE:=0} - -set -e -set -x - -shopt -s nullglob - -rm -rf image -mkdir image - -### loki-setup files -cp -a $SETUPIMAGE/{setup.data,setup.sh} image/ - -### splash -rm -f image/setup.data/splash.xpm -[ -e splash.xpm ] && cp splash.xpm image/setup.data/splash.xpm -rm -f image/quake3.png -cp ../quake3.png image/quake3.png - -### binaries -topdir="../.." - -echo "changequote(\`[', \`]')dnl" > defines.m4 -echo "define(VERSION,$VERSION)dnl" >> defines.m4 - -copystartscript() -{ - local arch="$1" - mkdir -p image/bin/Linux/$arch - if [ "$arch" = x86_64 ]; then - ln -s x86_64 image/bin/Linux/amd64 - fi - install -m 755 ioquake3.sh image/bin/Linux/$arch/ioquake3 - install -m 755 ioq3demo.sh image/bin/Linux/$arch/ioq3demo -} - -archs=() -for arch in $topdir/build/release-*; do - arch=${arch##*-} - case "$arch" in - i386) echo "define(HAVE_I386,yes)dnl" >> defines.m4 - copystartscript x86 - ;; - x86_64) echo "define(HAVE_X86_64,yes)dnl" >> defines.m4 - copystartscript $arch - ;; - ppc) echo "define(HAVE_PPC,yes)dnl" >> defines.m4 - copystartscript $arch - ;; - *) - echo "architecture $arch unsupported" - continue; - ;; - esac - archs[${#archs[@]}]=$arch -done - -for arch in "${archs[@]}"; do - dst=image/tmp - mkdir $dst - mkdir $dst/baseq3 $dst/demoq3 $dst/missionpack - install -m 755 $topdir/build/release-linux-$arch/ioquake3.$arch $dst/ioquake3.$arch - install -m 755 $topdir/build/release-linux-$arch/ioq3ded.$arch $dst/ioq3ded.$arch - install -m 644 $topdir/build/release-linux-$arch/baseq3/*.so $dst/baseq3 - install -m 644 $topdir/build/release-linux-$arch/missionpack/*.so $dst/missionpack - for i in cgame qagame ui; do - ln -s ../baseq3/$i$arch.so $dst/demoq3 - done - - tar --owner=root --group=root -C $dst -cf ./image/ioquake3.$arch.tar . - rm -rf ./image/tmp -done - -# patch pk3 files -if [ -e ./idpatchpk3s.tar -a -e ./idtapatchpk3s.tar ]; then - install -m 644 ./idpatchpk3s.tar image/idpatchpk3s.tar - install -m 644 ./idtapatchpk3s.tar image/idtapatchpk3s.tar - install -m 644 ./id_patch_pk3s_Q3A_EULA.txt image/id_patch_pk3s_Q3A_EULA.txt - echo "define(HAVE_PATCHPK3,yes)dnl" >> defines.m4 -elif [ -e quake3-latest-pk3s.zip ]; then - unzip quake3-latest-pk3s.zip - chmod 644 quake3-latest-pk3s/*/*.pk3 - tar -C quake3-latest-pk3s/baseq3 -cf image/idpatchpk3s.tar . - tar -C quake3-latest-pk3s/missionpack -cf image/idtapatchpk3s.tar . - rm -r quake3-latest-pk3s - install -m 644 id_patch_pk3s_Q3A_EULA.txt image/id_patch_pk3s_Q3A_EULA.txt - echo "define(HAVE_PATCHPK3,yes)dnl" >> defines.m4 -fi - -### uninstall script -install -m 755 ./preuninstall.sh image/preuninstall.sh - - -### README, COPYING and EULA -install -m 644 $topdir/README image/README -install -m 644 $topdir/COPYING.txt image/COPYING - -# create setup.xml -m4 defines.m4 setup.xml.in > image/setup.data/setup.xml - -### makeself installer -ARCH= -if [ "${#archs[@]}" -eq 1 ]; then - ARCH=.$arch -fi -$MAKESELF/makeself.sh image ioquake3-$VERSION-$RELEASE$ARCH.run "ioquake3 $VERSION-$RELEASE" ./setup.sh diff --git a/misc/setup/ioq3demo.sh b/misc/setup/ioq3demo.sh deleted file mode 100644 index 05df7ff8..00000000 --- a/misc/setup/ioq3demo.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -readlink() { - local path=$1 ll - - if [ -L "$path" ]; then - ll="$(LC_ALL=C ls -l "$path" 2> /dev/null)" && - echo "${ll/* -> }" - else - return 1 - fi -} - -script=$0 -count=0 -while [ -L "$script" ] -do - script=$(readlink "$script") - count=`expr $count + 1` - if [ $count -gt 100 ] - then - echo "Too many symbolic links" - exit 1 - fi -done -cd "`dirname $script`" - - -lib=lib -test -e lib64 && lib=lib64 - -if test "x$LD_LIBRARY_PATH" = x; then - LD_LIBRARY_PATH="`pwd`/$lib" -else - LD_LIBRARY_PATH="`pwd`/$lib:$LD_LIBRARY_PATH" -fi -export LD_LIBRARY_PATH - -archs=`uname -m` -case "$archs" in - i?86) archs=i386 ;; - x86_64) archs="x86_64 i386" ;; - ppc64) archs="ppc64 ppc" ;; -esac - -for arch in $archs; do - test -x ./ioquake3.$arch || continue - exec ./ioquake3.$arch +set sv_pure 0 +set vm_cgame 0 +set vm_game 0 +set vm_ui 0 +set fs_game demoq3 "$@" -done -echo "could not execute ioquake3" >&2 diff --git a/misc/setup/ioquake3.SlackBuild b/misc/setup/ioquake3.SlackBuild deleted file mode 100644 index af261b72..00000000 --- a/misc/setup/ioquake3.SlackBuild +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh - -CWD=`pwd` -BASE=$CWD/../.. -if [ "$TMP" = "" ]; then - TMP=/tmp -fi - -# clean, update -make -C $BASE clean || exit 1 -svn up $BASE || exit 1 - -# extract version info -VERSION=`grep "\#define *PRODUCT_VERSION" $BASE/code/qcommon/q_shared.h | \ - sed -e 's/[^"]*"\(.*\)"/\1/'` - -SVN_REV=`LANG=C svnversion $BASE` -if [ ! "$SVN_REV" = "" ]; then - VERSION=${VERSION}_SVN${SVN_REV} -fi - -PKG_VERSION=$VERSION - -ARCH=${ARCH:-i586} - -BUILD=${BUILD:-1_io} - -APP=ioquake3 - -PKG=$TMP/package-$APP - -rm -rf $PKG -mkdir -p $PKG - -# build -make -C $BASE release copyfiles COPYDIR="$PKG"/usr/games/$APP|| exit 1 - -# copy additional files -cp $BASE/BUGS $BASE/COPYING.txt $BASE/ChangeLog $BASE/README $PKG/usr/games/$APP/ -cat $CWD/$APP.SlackBuild > $PKG/usr/games/$APP/$APP.SlackBuild - -mkdir -p $PKG/usr/share/$APP/icons -cp $BASE/misc/quake3.png $PKG/usr/share/$APP/icons/ioquake3.png - -mkdir -p $PKG/usr/bin -cat >> $PKG/usr/bin/ioquake3 << EOF -#!/bin/sh -cd /usr/games/$APP/ -./ioquake3.i386 \$* -exit \$? -EOF -chmod 754 $PKG/usr/bin/ioquake3 - -mkdir -p $PKG/usr/bin -cat >> $PKG/usr/bin/ioq3ded << EOF -#!/bin/sh -cd /usr/games/$APP/ -./ioq3ded.i386 \$* -exit \$? -EOF -chmod 754 $PKG/usr/bin/ioq3ded - -mkdir -p $PKG/install -cat $CWD/slack-desc > $PKG/install/slack-desc - -cat >> $PKG/install/doinst.sh << EOF -chmod 754 /usr/games/$APP/*.i386 -chmod 754 /usr/bin/ioquake3 /usr/bin/ioq3ded -EOF -chmod +x $PKG/install/doinst.sh - -pushd $PKG -chown -R root:root install/ || exit 1 -chown -R root:games usr/ || exit 1 -/sbin/makepkg -l y -c n $TMP/$APP-$VERSION-$ARCH-$BUILD.tgz -popd - diff --git a/misc/setup/ioquake3.sh b/misc/setup/ioquake3.sh deleted file mode 100644 index fbef5676..00000000 --- a/misc/setup/ioquake3.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -readlink() { - local path=$1 ll - - if [ -L "$path" ]; then - ll="$(LC_ALL=C ls -l "$path" 2> /dev/null)" && - echo "${ll##* -> }" - else - return 1 - fi -} - -script=$0 -count=0 -while [ -L "$script" ] -do - script=$(readlink "$script") - count=`expr $count + 1` - if [ $count -gt 100 ] - then - echo "Too many symbolic links" - exit 1 - fi -done -cd "`dirname $script`" - - -lib=lib -test -e lib64 && lib=lib64 - -if test "x$LD_LIBRARY_PATH" = x; then - LD_LIBRARY_PATH="`pwd`/$lib" -else - LD_LIBRARY_PATH="`pwd`/$lib:$LD_LIBRARY_PATH" -fi -export LD_LIBRARY_PATH - -archs=`uname -m` -case "$archs" in - i?86) archs=i386 ;; - x86_64) archs="x86_64 i386" ;; - ppc64) archs="ppc64 ppc" ;; -esac - -for arch in $archs; do - test -x ./ioquake3.$arch || continue - exec ./ioquake3.$arch "$@" -done -echo "could not execute ioquake3" >&2 diff --git a/misc/setup/pkg/ioq3ded.sh b/misc/setup/pkg/ioq3ded.sh deleted file mode 100644 index 5f2d7e50..00000000 --- a/misc/setup/pkg/ioq3ded.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Rev: $Id: ioq3ded.sh,v 1.9 2006/01/18 13:47:42 raistlin Exp raistlin $ -# Needed to make symlinks/shortcuts work. -# the binaries must run with correct working directory - -IOQ3_DIR=/usr/local/share/games/quake3 - -COMPILE_PLATFORM=`uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]'` -COMPILE_ARCH=`uname -p | sed -e s/i.86/i386/` - -EXEC_REL=release - -# EXEC_BIN=ioquake3.${COMPILE_ARCH} -# EXEC_BIN=ioquake3-smp.${COMPILE_ARCH} -EXEC_BIN=ioq3ded.${COMPILE_ARCH} - -EXEC_FLAGS="+set fs_basepath ${IOQ3_DIR} +set vm_game 1 +set vm_cgame 1 +set vm_ui 1 +set sv_pure 1 +set com_ansiColor 0" - -EXEC_DIR_LIST="${IOQ3_DIR}" - -for d in ${EXEC_DIR_LIST} -do - if [ -d $d ]; then - EXEC_DIR=${d} - break - fi -done - -if [ "X${EXEC_DIR}" != "X" ]; then - if [ ! -x ${EXEC_DIR}/${EXEC_BIN} ]; then - echo "Executable ${EXEC_DIR}/${EXEC_BIN} not found!" ; exit 1 - fi - cd ${IOQ3_DIR} && \ - ${EXEC_DIR}/${EXEC_BIN} ${EXEC_FLAGS} $* - exit $? -else - echo "No ioq3 binaries found!" - exit 1 -fi - - diff --git a/misc/setup/pkg/ioquake3.sh b/misc/setup/pkg/ioquake3.sh deleted file mode 100644 index b2fe7856..00000000 --- a/misc/setup/pkg/ioquake3.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Rev: $Id: ioquake3.sh,v 1.11 2006/01/18 13:47:42 raistlin Exp raistlin $ -# Needed to make symlinks/shortcuts work. -# the binaries must run with correct working directory - -IOQ3_DIR=/usr/local/share/games/quake3 - -COMPILE_PLATFORM=`uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]'` -COMPILE_ARCH=`uname -p | sed -e s/i.86/i386/` - -EXEC_REL=release - -EXEC_BIN=ioquake3.${COMPILE_ARCH} -# EXEC_BIN=ioquake3-smp.${COMPILE_ARCH} -# EXEC_BIN=ioq3ded.${COMPILE_ARCH} - -EXEC_FLAGS="+set fs_basepath ${IOQ3_DIR} +set vm_game 1 +set vm_cgame 1 +set vm_ui 1 +set sv_pure 1 +set com_ansiColor 0" - -EXEC_DIR_LIST="${IOQ3_DIR}" - -for d in ${EXEC_DIR_LIST} -do - if [ -d $d ]; then - EXEC_DIR=${d} - break - fi -done - -if [ "X${EXEC_DIR}" != "X" ]; then - if [ ! -x ${EXEC_DIR}/${EXEC_BIN} ]; then - echo "Executable ${EXEC_DIR}/${EXEC_BIN} not found!" ; exit 1 - fi - cd ${IOQ3_DIR} && \ - ${EXEC_DIR}/${EXEC_BIN} ${EXEC_FLAGS} $* - exit $? -else - echo "No ioq3 binaries found!" - exit 1 -fi - - diff --git a/misc/setup/pkg/ioquake3/depend b/misc/setup/pkg/ioquake3/depend deleted file mode 100644 index 11170caf..00000000 --- a/misc/setup/pkg/ioquake3/depend +++ /dev/null @@ -1,3 +0,0 @@ -P SUNWxilrl XIL Runtime Environment -P SFWsdl SDL - Simple DirectMedia Layer library -P ioquake3d Icculus.Org Quake3 game data files for Solaris 10 (X11,GLX,SDL) diff --git a/misc/setup/pkg/ioquake3/pkginfo.template b/misc/setup/pkg/ioquake3/pkginfo.template deleted file mode 100644 index 34d5b1ff..00000000 --- a/misc/setup/pkg/ioquake3/pkginfo.template +++ /dev/null @@ -1,12 +0,0 @@ -CLASSES=none -BASEDIR=/usr/local/share/games -TZ=PST -PATH=/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin -PKG=ioquake3 -NAME=ioquake3 1.34 for Solaris 10 (X11,GLX,SDL) -VERSION= -CATEGORY=application,graphics,opengl -DESC=Icculus.Org Quake3 1.34 for Solaris 10 (http://www.ioquake3.org/) -VENDOR=http://www.ioquake3.org/ -EMAIL=quake@cojot.name -PKGSAV=/var/sadm/pkg/ioquake3/save diff --git a/misc/setup/pkg/ioquake3/postinstall b/misc/setup/pkg/ioquake3/postinstall deleted file mode 100644 index 2775d5ee..00000000 --- a/misc/setup/pkg/ioquake3/postinstall +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: postinstall,v 1.3 2006/01/21 12:54:52 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR/quake3 -dest_dir=${PKG_INSTALL_ROOT}/usr/local/bin - -if [ -d ${dest_dir} ]; then - for inst_script in ioq3ded.sh ioquake3.sh - do - dest_script=${dest_dir}/${inst_script} - if [ ! -h ${dest_script} ]; then - ln -s ${quake3_dir}/${inst_script} ${dest_script} - fi - done -fi - -exit 0 - diff --git a/misc/setup/pkg/ioquake3/postremove b/misc/setup/pkg/ioquake3/postremove deleted file mode 100644 index 37690f61..00000000 --- a/misc/setup/pkg/ioquake3/postremove +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# -# @(#)postremove $Id: postremove,v 1.3 2006/01/21 12:54:52 coyote Exp $ -# -# postremove script for quake3 - -quake3_dir=$BASEDIR -dest_dir=${PKG_INSTALL_ROOT}/usr/local/bin - -if [ -d ${dest_dir} ]; then - for inst_script in ioq3ded.sh ioquake3.sh - do - dest_script=${dest_dir}/${inst_script} - if [ -h ${dest_script} ]; then - rm -f ${dest_script} - fi - done -fi - -exit 0 - diff --git a/misc/setup/pkg/ioquake3/preinstall b/misc/setup/pkg/ioquake3/preinstall deleted file mode 100644 index ad126a11..00000000 --- a/misc/setup/pkg/ioquake3/preinstall +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: preinstall,v 1.2 2006/01/25 13:22:56 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR - -exit 0 - diff --git a/misc/setup/pkg/ioquake3/preremove b/misc/setup/pkg/ioquake3/preremove deleted file mode 100644 index 3f316f3c..00000000 --- a/misc/setup/pkg/ioquake3/preremove +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: preremove,v 1.2 2006/01/25 13:22:56 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR - -exit 0 - diff --git a/misc/setup/pkg/ioquake3/prototype.template b/misc/setup/pkg/ioquake3/prototype.template deleted file mode 100644 index f23af773..00000000 --- a/misc/setup/pkg/ioquake3/prototype.template +++ /dev/null @@ -1,8 +0,0 @@ -!default 0755 root bin -i pkginfo -i copyright -i depend -i postinstall -i postremove -i preinstall -i preremove diff --git a/misc/setup/pkg/ioquake3/space b/misc/setup/pkg/ioquake3/space deleted file mode 100644 index 95b72949..00000000 --- a/misc/setup/pkg/ioquake3/space +++ /dev/null @@ -1 +0,0 @@ -/usr/local/share 20000 15 diff --git a/misc/setup/pkg/ioquake3d/depend b/misc/setup/pkg/ioquake3d/depend deleted file mode 100644 index b55ff884..00000000 --- a/misc/setup/pkg/ioquake3d/depend +++ /dev/null @@ -1,2 +0,0 @@ -P SUNWxilrl XIL Runtime Environment -P SFWsdl SDL - Simple DirectMedia Layer library diff --git a/misc/setup/pkg/ioquake3d/pkginfo.template b/misc/setup/pkg/ioquake3d/pkginfo.template deleted file mode 100644 index a351c4de..00000000 --- a/misc/setup/pkg/ioquake3d/pkginfo.template +++ /dev/null @@ -1,12 +0,0 @@ -CLASSES=none -BASEDIR=/usr/local/share/games -TZ=PST -PATH=/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin -PKG=ioquake3d -NAME=ioquake3 game data files for Solaris 10 (X11,GLX,SDL) -VERSION= -CATEGORY=application,graphics,opengl -DESC=ioquake3 game data files for Solaris 10 (http://www.ioquake3.org/) -VENDOR=http://www.ioquake3.org/ -EMAIL=quake@cojot.name -PKGSAV=/var/sadm/pkg/ioquake3d/save diff --git a/misc/setup/pkg/ioquake3d/postinstall b/misc/setup/pkg/ioquake3d/postinstall deleted file mode 100644 index f116fc3d..00000000 --- a/misc/setup/pkg/ioquake3d/postinstall +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: postinstall,v 1.2 2006/01/25 13:22:56 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR - -exit 0 - diff --git a/misc/setup/pkg/ioquake3d/postremove b/misc/setup/pkg/ioquake3d/postremove deleted file mode 100644 index 7614348d..00000000 --- a/misc/setup/pkg/ioquake3d/postremove +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: postremove,v 1.2 2006/01/25 13:22:56 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR - -exit 0 - diff --git a/misc/setup/pkg/ioquake3d/preinstall b/misc/setup/pkg/ioquake3d/preinstall deleted file mode 100644 index ad126a11..00000000 --- a/misc/setup/pkg/ioquake3d/preinstall +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: preinstall,v 1.2 2006/01/25 13:22:56 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR - -exit 0 - diff --git a/misc/setup/pkg/ioquake3d/preremove b/misc/setup/pkg/ioquake3d/preremove deleted file mode 100644 index 3f316f3c..00000000 --- a/misc/setup/pkg/ioquake3d/preremove +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# @(#)postinstall $Id: preremove,v 1.2 2006/01/25 13:22:56 coyote Exp $ -# -# postinstall script for quake3 - -quake3_dir=$BASEDIR - -exit 0 - diff --git a/misc/setup/pkg/ioquake3d/prototype.template b/misc/setup/pkg/ioquake3d/prototype.template deleted file mode 100644 index 26bd06a1..00000000 --- a/misc/setup/pkg/ioquake3d/prototype.template +++ /dev/null @@ -1,7 +0,0 @@ -!default 0755 root bin -i pkginfo -i depend -i postinstall -i postremove -i preinstall -i preremove diff --git a/misc/setup/pkg/ioquake3d/space b/misc/setup/pkg/ioquake3d/space deleted file mode 100644 index a8d224c3..00000000 --- a/misc/setup/pkg/ioquake3d/space +++ /dev/null @@ -1 +0,0 @@ -/usr/local/share 50000 100 diff --git a/misc/setup/preuninstall.sh b/misc/setup/preuninstall.sh deleted file mode 100644 index 49e80564..00000000 --- a/misc/setup/preuninstall.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -rmdir --ignore-fail-on-non-empty demoq3 missionpack >& /dev/null diff --git a/misc/setup/setup.xml.in b/misc/setup/setup.xml.in deleted file mode 100644 index 65dd1b9d..00000000 --- a/misc/setup/setup.xml.in +++ /dev/null @@ -1,111 +0,0 @@ - - - - README - - - -ifelse(HAVE_X86_64,yes,dnl - -)dnl -ifelse(HAVE_I386,yes,dnl - -)dnl -ifelse(HAVE_PPC,yes,dnl - -)dnl - - -ifelse(HAVE_PATCHPK3,yes,dnl - - - - id_patch_pk3s_Q3A_EULA.txt - - - - - - - - - - id_patch_pk3s_Q3A_EULA.txt - - - - - - - - Quake3/baseq3/pak0.pk3 - - - Setup/missionpack/pak0.pk3 - -)dnl - - diff --git a/misc/setup/slack-desc b/misc/setup/slack-desc deleted file mode 100644 index c88b4bcb..00000000 --- a/misc/setup/slack-desc +++ /dev/null @@ -1,12 +0,0 @@ - |-----handy-ruler------------------------------------------------------| -ioquake3: ioquake 3 - An open source Quake 3 distribution -ioquake3: -ioquake3: ioquake3 aims to build upon id Software's Quake 3 source code release. -ioquake3: The source code was released on August 20, 2005 under the GPL. Since -ioquake3: then code has been cleaned up, bugs have been fixed and features been -ioquake3: added. -ioquake3: The permanent goal is to create THE open source Quake 3 distribution -ioquake3: upon which people base their games and projects. -ioquake3: -ioquake3: http://ioquake3.org/ -ioquake3: diff --git a/misc/setup/splash.xpm b/misc/setup/splash.xpm deleted file mode 100644 index 27677676..00000000 --- a/misc/setup/splash.xpm +++ /dev/null @@ -1,2289 +0,0 @@ -/* XPM */ -static char * splash_xpm[] = { -"296 296 1990 2", -" c #999999", -". c #989797", -"+ c #999898", -"@ c #938B8B", -"# c #979494", -"$ c #8D7D7D", -"% c #958F8F", -"& c #887070", -"* c #928989", -"= c #846666", -"- c #8F7F7F", -"; c #815C5C", -"> c #8B7676", -", c #7D5353", -"' c #876C6C", -") c #7A4949", -"! c #846262", -"~ c #764040", -"{ c #805959", -"] c #733636", -"^ c #7D4F4F", -"/ c #702C2C", -"( c #794646", -"_ c #6C2323", -": c #763C3C", -"< c #691919", -"[ c #733232", -"} c #979595", -"| c #671313", -"1 c #6F2929", -"2 c #969090", -"3 c #660E0E", -"4 c #6C1F1F", -"5 c #948B8B", -"6 c #650A0A", -"7 c #691616", -"8 c #928686", -"9 c #640505", -"0 c #660C0C", -"a c #918181", -"b c #630101", -"c c #640303", -"d c #8D7878", -"e c #630000", -"f c #969292", -"g c #8A6E6E", -"h c #640000", -"i c #938888", -"j c #876565", -"k c #907F7F", -"l c #845B5B", -"m c #650000", -"n c #8D7575", -"o c #815252", -"p c #8A6B6B", -"q c #7E4848", -"r c #660000", -"s c #876262", -"t c #7B3E3E", -"u c #670000", -"v c #845858", -"w c #783535", -"x c #814F4F", -"y c #762B2B", -"z c #680000", -"A c #7E4545", -"B c #732222", -"C c #7B3B3B", -"D c #989696", -"E c #711A1A", -"F c #690000", -"G c #793232", -"H c #701313", -"I c #6A0000", -"J c #762828", -"K c #979191", -"L c #6E0C0C", -"M c #731F1F", -"N c #968F8F", -"O c #6C0505", -"P c #6B0000", -"Q c #711515", -"R c #948A8A", -"S c #6F0D0D", -"T c #928080", -"U c #6C0000", -"V c #6F0909", -"W c #8F7777", -"X c #6E0707", -"Y c #958A8A", -"Z c #8C6D6D", -"` c #6D0000", -" . c #6E0404", -".. c #938383", -"+. c #8A6464", -"@. c #6E0202", -"#. c #917C7C", -"$. c #875A5A", -"%. c #6E0000", -"&. c #8F7474", -"*. c #855050", -"=. c #6F0000", -"-. c #8C6B6B", -";. c #824646", -">. c #8A6161", -",. c #803D3D", -"'. c #700000", -"). c #875757", -"!. c #7E3333", -"~. c #854D4D", -"{. c #7C2929", -"]. c #710000", -"^. c #834444", -"/. c #792020", -"(. c #803A3A", -"_. c #781616", -":. c #720000", -"<. c #7E3131", -"[. c #760D0D", -"}. c #730000", -"|. c #7D2727", -"1. c #740303", -"2. c #7A1D1D", -"3. c #979292", -"4. c #740000", -"5. c #791616", -"6. c #999797", -"7. c #958989", -"8. c #781111", -"9. c #937F7F", -"0. c #750000", -"a. c #780C0C", -"b. c #968E8E", -"c. c #917676", -"d. c #770707", -"e. c #8F6B6B", -"f. c #760000", -"g. c #770202", -"h. c #948484", -"i. c #8D6262", -"j. c #770000", -"k. c #937D7D", -"l. c #8B5858", -"m. c #917373", -"n. c #894F4F", -"o. c #780000", -"p. c #8F6A6A", -"q. c #874545", -"r. c #8D6060", -"s. c #853B3B", -"t. c #790000", -"u. c #8B5656", -"v. c #843232", -"w. c #7A0000", -"x. c #8A4D4D", -"y. c #822828", -"z. c #884343", -"A. c #811F1F", -"B. c #7B0000", -"C. c #863A3A", -"D. c #7F1515", -"E. c #843030", -"F. c #7E0D0D", -"G. c #7C0000", -"H. c #832626", -"I. c #989191", -"J. c #7E0909", -"K. c #821F1F", -"L. c #968A8A", -"M. c #7E0707", -"N. c #7D0000", -"O. c #811717", -"P. c #989595", -"Q. c #958383", -"R. c #7E0404", -"S. c #801010", -"T. c #989292", -"U. c #947C7C", -"V. c #7E0202", -"W. c #7E0000", -"X. c #7F0808", -"Y. c #979090", -"Z. c #937474", -"`. c #7F0000", -" + c #7F0202", -".+ c #978E8E", -"++ c #916A6A", -"@+ c #968585", -"#+ c #906161", -"$+ c #800000", -"%+ c #8E5757", -"&+ c #937373", -"*+ c #8D4D4D", -"=+ c #810000", -"-+ c #916969", -";+ c #8C4444", -">+ c #905F5F", -",+ c #8B3A3A", -"'+ c #820000", -")+ c #8F5555", -"!+ c #8A3131", -"~+ c #830000", -"{+ c #8E4C4C", -"]+ c #892727", -"^+ c #8D4343", -"/+ c #881D1D", -"(+ c #840000", -"_+ c #8C3838", -":+ c #871616", -"<+ c #8A2F2F", -"[+ c #871111", -"}+ c #850000", -"|+ c #8A2525", -"1+ c #988E8E", -"2+ c #870C0C", -"3+ c #891C1C", -"4+ c #978989", -"5+ c #870707", -"6+ c #860000", -"7+ c #881212", -"8+ c #968383", -"9+ c #870202", -"0+ c #870000", -"a+ c #880808", -"b+ c #967C7C", -"c+ c #870101", -"d+ c #957373", -"e+ c #880000", -"f+ c #946969", -"g+ c #978585", -"h+ c #935F5F", -"i+ c #890000", -"j+ c #967B7B", -"k+ c #925656", -"l+ c #8A0000", -"m+ c #957171", -"n+ c #914C4C", -"o+ c #946868", -"p+ c #9F9191", -"q+ c #AB7E7E", -"r+ c #BD6262", -"s+ c #CF4848", -"t+ c #DB3636", -"u+ c #E72525", -"v+ c #EB1F1F", -"w+ c #E12C2C", -"x+ c #CD4B4B", -"y+ c #B76C6C", -"z+ c #9E9191", -"A+ c #914343", -"B+ c #8B0000", -"C+ c #945E5E", -"D+ c #AA7F7F", -"E+ c #C15C5C", -"F+ c #D83A3A", -"G+ c #E82222", -"H+ c #E91F1F", -"I+ c #E02D2D", -"J+ c #D43F3F", -"K+ c #C55555", -"L+ c #B47070", -"M+ c #A38989", -"N+ c #9B9595", -"O+ c #9D9292", -"P+ c #B17474", -"Q+ c #CB4D4D", -"R+ c #E32828", -"S+ c #F70B0B", -"T+ c #FE0000", -"U+ c #FC0202", -"V+ c #EE1919", -"W+ c #D34141", -"X+ c #B76B6B", -"Y+ c #903939", -"Z+ c #935555", -"`+ c #9D9494", -" @ c #AD7B7B", -".@ c #C45757", -"+@ c #E12B2B", -"@@ c #F60A0A", -"#@ c #FD0000", -"$@ c #FB0202", -"%@ c #ED1919", -"&@ c #D63B3B", -"*@ c #BD6161", -"=@ c #A58686", -"-@ c #B46F6F", -";@ c #D63C3C", -">@ c #F11313", -",@ c #FD0101", -"'@ c #EE1717", -")@ c #CE4949", -"!@ c #AC7C7C", -"~@ c #902F2F", -"{@ c #8C0000", -"]@ c #924B4B", -"^@ c #A28B8B", -"/@ c #BC6363", -"(@ c #DE2E2E", -"_@ c #F80707", -":@ c #FC0000", -"<@ c #F70707", -"[@ c #E32525", -"}@ c #C45656", -"|@ c #A58787", -"1@ c #CB4C4C", -"2@ c #EE1515", -"3@ c #FB0101", -"4@ c #DD2F2F", -"5@ c #B37070", -"6@ c #9C9494", -"7@ c #8F2626", -"8@ c #924141", -"9@ c #C94E4E", -"0@ c #F11010", -"a@ c #FB0000", -"b@ c #B86969", -"c@ c #9A9898", -"d@ c #AB7D7D", -"e@ c #D73838", -"f@ c #F90404", -"g@ c #F80505", -"h@ c #D53B3B", -"i@ c #A78383", -"j@ c #8F1E1E", -"k@ c #8D0000", -"l@ c #913838", -"m@ c #9C9595", -"n@ c #BC6161", -"o@ c #EB1717", -"p@ c #FA0000", -"q@ c #EB1818", -"r@ c #BE5E5E", -"s@ c #A88181", -"t@ c #D83636", -"u@ c #F80303", -"v@ c #F90101", -"w@ c #DB3131", -"x@ c #999595", -"y@ c #8F1717", -"z@ c #912E2E", -"A@ c #9D9393", -"B@ c #C35656", -"C@ c #EF1010", -"D@ c #F90000", -"E@ c #ED1414", -"F@ c #BD5F5F", -"G@ c #9F9090", -"H@ c #CD4646", -"I@ c #F40808", -"J@ c #EE1111", -"K@ c #B96666", -"L@ c #999292", -"M@ c #8F1010", -"N@ c #8E0000", -"O@ c #912525", -"P@ c #D73535", -"Q@ c #F70101", -"R@ c #F80000", -"S@ c #E32222", -"T@ c #B17272", -"U@ c #EA1717", -"V@ c #D93232", -"W@ c #989090", -"X@ c #900808", -"Y@ c #8F0000", -"Z@ c #911B1B", -"`@ c #9A9797", -" # c #BA6464", -".# c #F10A0A", -"+# c #F70000", -"@# c #F40404", -"## c #CE4343", -"$# c #CD4444", -"%# c #F70202", -"&# c #C55252", -"*# c #988D8D", -"=# c #8F0101", -"-# c #901111", -";# c #A78282", -"># c #E61A1A", -",# c #F60000", -"'# c #E91616", -")# c #AC7A7A", -"!# c #A18B8B", -"~# c #DD2929", -"{# c #F40505", -"]# c #BD5E5E", -"^# c #988585", -"/# c #900000", -"(# c #910B0B", -"_# c #999696", -":# c #A28A8A", -"<# c #E02222", -"[# c #F50000", -"}# c #F00909", -"|# c #B96363", -"1# c #A88080", -"2# c #E71818", -"3# c #F40303", -"4# c #BD5D5D", -"5# c #977B7B", -"6# c #988F8F", -"7# c #A18C8C", -"8# c #E31D1D", -"9# c #F40000", -"0# c #F20303", -"a# c #C74C4C", -"b# c #E91414", -"c# c #F50101", -"d# c #C84B4B", -"e# c #977171", -"f# c #910000", -"g# c #910606", -"h# c #988888", -"i# c #A48787", -"j# c #EC0D0D", -"k# c #F30101", -"l# c #A68383", -"m# c #E91313", -"n# c #DB2B2B", -"o# c #9B9696", -"p# c #966868", -"q# c #910404", -"r# c #988080", -"s# c #B26F6F", -"t# c #F10303", -"u# c #F30000", -"v# c #C44F4F", -"w# c #E11F1F", -"x# c #EF0707", -"y# c #A58585", -"z# c #965E5E", -"A# c #920000", -"B# c #920101", -"C# c #987979", -"D# c #CE3E3E", -"E# c #F20000", -"F# c #F10202", -"G# c #B76565", -"H# c #CE3D3D", -"I# c #C64C4C", -"J# c #965555", -"K# c #930000", -"L# c #A28989", -"M# c #EA0D0D", -"N# c #F10000", -"O# c #A87F7F", -"P# c #B66767", -"Q# c #F00202", -"R# c #EA0C0C", -"S# c #A08C8C", -"T# c #964B4B", -"U# c #976767", -"V# c #C74949", -"W# c #F00000", -"X# c #DC2323", -"Y# c #E31717", -"Z# c #CB4141", -"`# c #964141", -" $ c #940000", -".$ c #975D5D", -"+$ c #A48585", -"@$ c #EC0606", -"#$ c #EF0000", -"$$ c #BA5E5E", -"%$ c #C25050", -"&$ c #EE0202", -"*$ c #AC7777", -"=$ c #963838", -"-$ c #975353", -";$ c #D72929", -">$ c #EE0000", -",$ c #E51010", -"'$ c #9E8F8F", -")$ c #E41212", -"!$ c #962E2E", -"~$ c #950000", -"{$ c #974A4A", -"]$ c #BE5555", -"^$ c #ED0000", -"/$ c #B86060", -"($ c #D23131", -"_$ c #962424", -":$ c #974040", -"<$ c #A97B7B", -"[$ c #EC0000", -"}$ c #DF1919", -"|$ c #D62929", -"1$ c #C34C4C", -"2$ c #971A1A", -"3$ c #960000", -"4$ c #973737", -"5$ c #EA0202", -"6$ c #EB0000", -"7$ c #AB7777", -"8$ c #E90404", -"9$ c #B76161", -"0$ c #971111", -"a$ c #970000", -"b$ c #982D2D", -"c$ c #E11111", -"d$ c #EA0000", -"e$ c #C14D4D", -"f$ c #AD7373", -"g$ c #B16B6B", -"h$ c #970707", -"i$ c #972323", -"j$ c #DA1C1C", -"k$ c #E90000", -"l$ c #D42929", -"m$ c #BC5656", -"n$ c #AE7272", -"o$ c #980101", -"p$ c #980000", -"q$ c #981A1A", -"r$ c #D72323", -"s$ c #DF1313", -"t$ c #C64343", -"u$ c #B46666", -"v$ c #998D8D", -"w$ c #981414", -"x$ c #DC1717", -"y$ c #E80000", -"z$ c #E40808", -"A$ c #A18A8A", -"B$ c #CC3636", -"C$ c #C93D3D", -"D$ c #998383", -"E$ c #990000", -"F$ c #990F0F", -"G$ c #999191", -"H$ c #A38585", -"I$ c #E70101", -"J$ c #E70000", -"K$ c #E60202", -"L$ c #A48383", -"M$ c #CE3232", -"N$ c #E20A0A", -"O$ c #997A7A", -"P$ c #9A0000", -"Q$ c #9A0A0A", -"R$ c #998C8C", -"S$ c #C73E3E", -"T$ c #E60000", -"U$ c #A58181", -"V$ c #CB3535", -"W$ c #D12929", -"X$ c #997070", -"Y$ c #9A0505", -"Z$ c #998787", -"`$ c #AF6B6B", -" % c #E30404", -".% c #E50000", -"+% c #E40202", -"@% c #C34444", -"#% c #E30000", -"$% c #B23434", -"%% c #6A6A6A", -"&% c #626262", -"*% c #717171", -"=% c #8F8F8F", -"-% c #9A6767", -";% c #9B0000", -">% c #9B0101", -",% c #998282", -"'% c #AC7171", -")% c #DF0A0A", -"!% c #E40000", -"~% c #E00909", -"{% c #A08B8B", -"]% c #B46262", -"^% c #BF0000", -"/% c #450000", -"(% c #050000", -"_% c #000000", -":% c #0A0A0A", -"<% c #494949", -"[% c #929292", -"}% c #9A5D5D", -"|% c #997979", -"1% c #B75A5A", -"2% c #E00707", -"3% c #D61B1B", -"4% c #9F8C8C", -"5% c #E20303", -"6% c #AF0000", -"7% c #120000", -"8% c #272727", -"9% c #9A5353", -"0% c #9C0000", -"a% c #9A7070", -"b% c #C73A3A", -"c% c #E10101", -"d% c #E20000", -"e% c #C14545", -"f% c #CB3131", -"g% c #D90000", -"h% c #1B0000", -"i% c #3D3D3D", -"j% c #989898", -"k% c #9B4A4A", -"l% c #9A6666", -"m% c #919191", -"n% c #868686", -"o% c #8E8E8E", -"p% c #878585", -"q% c #9F5858", -"r% c #D40E0E", -"s% c #E10000", -"t% c #DF0404", -"u% c #A77C7C", -"v% c #A87979", -"w% c #E10303", -"x% c #040404", -"y% c #858585", -"z% c #9B4040", -"A% c #9D0000", -"B% c #9B5C5C", -"C% c #575757", -"D% c #434343", -"E% c #7A7A7A", -"F% c #373737", -"G% c #0B0B0B", -"H% c #010000", -"I% c #250000", -"J% c #CE0000", -"K% c #E00000", -"L% c #C93232", -"M% c #C43D3D", -"N% c #480000", -"O% c #742F2F", -"P% c #A77A7A", -"Q% c #9C3636", -"R% c #9B5353", -"S% c #949494", -"T% c #454545", -"U% c #030303", -"V% c #170000", -"W% c #DF0000", -"X% c #DB0808", -"Y% c #A38383", -"Z% c #D51919", -"`% c #360000", -" & c #DF0303", -".& c #D02323", -"+& c #B45E5E", -"@& c #9D9191", -"#& c #9D2C2C", -"$& c #9E0000", -"%& c #9C4949", -"&& c #979797", -"*& c #3A3A3A", -"=& c #080000", -"-& c #DE0000", -";& c #DD0101", -">& c #B55B5B", -",& c #A57F7F", -"'& c #D90D0D", -")& c #4A0000", -"!& c #DA0C0C", -"~& c #C53838", -"{& c #AD6D6D", -"]& c #9E2323", -"^& c #9F0000", -"/& c #9D4040", -"(& c #5E5E5E", -"_& c #010101", -":& c #0F0000", -"<& c #C90000", -"[& c #BF4444", -"}& c #AA7474", -"|& c #DB0606", -"1& c #090000", -"2& c #C60000", -"3& c #D80D0D", -"4& c #C33C3C", -"5& c #AE6B6B", -"6& c #9D8F8F", -"7& c #9E1919", -"8& c #9D3636", -"9& c #959595", -"0& c #0F0F0F", -"a& c #5E0000", -"b& c #DD0000", -"c& c #C63434", -"d& c #AB7070", -"e& c #D70D0D", -"f& c #D70000", -"g& c #DC0000", -"h& c #D80B0B", -"i& c #C83030", -"j& c #B35D5D", -"k& c #9A9696", -"l& c #9F1010", -"m& c #A00000", -"n& c #9E2C2C", -"o& c #040000", -"p& c #1C0000", -"q& c #130000", -"r& c #180000", -"s& c #D50000", -"t& c #C33838", -"u& c #9C9393", -"v& c #D41313", -"w& c #B70000", -"x& c #1D0000", -"y& c #D30000", -"z& c #DA0404", -"A& c #D01A1A", -"B& c #C04040", -"C& c #AE6969", -"D& c #A08989", -"E& c #A00A0A", -"F& c #9B9494", -"G& c #A67A7A", -"H& c #B65555", -"I& c #681E1E", -"J& c #A80000", -"K& c #D00000", -"L& c #D60000", -"M& c #CC0000", -"N& c #B80000", -"O& c #DA0101", -"P& c #BD4444", -"Q& c #A18686", -"R& c #CB2626", -"S& c #DB0000", -"T& c #580000", -"U& c #1A0000", -"V& c #D80707", -"W& c #C13D3D", -"X& c #B16161", -"Y& c #A28484", -"Z& c #9A8E8E", -"`& c #A10808", -" * c #A10000", -".* c #A01C1C", -"+* c #9C9292", -"@* c #AA7171", -"#* c #B94F4F", -"$* c #C82B2B", -"%* c #D50D0D", -"&* c #D90202", -"** c #DA0000", -"=* c #610000", -"-* c #A40707", -";* c #B35C5C", -">* c #BB4B4B", -",* c #D80404", -"'* c #D40000", -")* c #AD0000", -"!* c #D40F0F", -"~* c #C53232", -"{* c #A77979", -"]* c #9A8686", -"^* c #A10505", -"/* c #A01414", -"(* c #999494", -"_* c #A08787", -":* c #AE6666", -"<* c #BD4343", -"[* c #CC2020", -"}* c #D80202", -"|* c #5C0000", -"1* c #786969", -"2* c #A97272", -"3* c #CD1C1C", -"4* c #D40B0B", -"5* c #CB2222", -"6* c #BF3E3E", -"7* c #9B7F7F", -"8* c #A20303", -"9* c #A20000", -"0* c #A10D0D", -"a* c #9B9393", -"b* c #AD6A6A", -"c* c #B94C4C", -"d* c #C42F2F", -"e* c #CF1616", -"f* c #D70202", -"g* c #D80000", -"h* c #5F0000", -"i* c #060000", -"j* c #260000", -"k* c #737373", -"l* c #747474", -"m* c #5D5D5D", -"n* c #605656", -"o* c #791A1A", -"p* c #B60000", -"q* c #D80101", -"r* c #D40A0A", -"s* c #C13838", -"t* c #B55656", -"u* c #9F8989", -"v* c #9B7878", -"w* c #A30101", -"x* c #A30000", -"y* c #A30606", -"z* c #9A8F8F", -"A* c #A47E7E", -"B* c #AE6464", -"C* c #BB4646", -"D* c #C62929", -"E* c #D01212", -"F* c #D60404", -"G* c #C70000", -"H* c #BC0000", -"I* c #3B3B3B", -"J* c #C00000", -"K* c #3C0000", -"L* c #200000", -"M* c #100000", -"N* c #240000", -"O* c #4C0000", -"P* c #D10000", -"Q* c #D70101", -"R* c #D40707", -"S* c #CF1313", -"T* c #C52C2C", -"U* c #BB4545", -"V* c #B15E5E", -"W* c #A77777", -"X* c #9C6F6F", -"Y* c #9A8B8B", -"Z* c #A28383", -"`* c #AC6A6A", -" = c #B65151", -".= c #C03838", -"+= c #CA1F1F", -"@= c #D20B0B", -"#= c #D50303", -"$= c #CB0000", -"%= c #620000", -"&= c #070000", -"*= c #D01010", -"== c #BB4343", -"-= c #B25B5B", -";= c #A87474", -">= c #9F8A8A", -",= c #7C7C7C", -"'= c #6E6E6E", -")= c #6D6D6D", -"!= c #767676", -"~= c #888888", -"{= c #969696", -"]= c #707070", -"^= c #757575", -"/= c #9D6565", -"(= c #A40000", -"_= c #6D5D5D", -":= c #909090", -"<= c #A37F7F", -"[= c #AD6767", -"}= c #B54E4E", -"|= c #B13535", -"1= c #970505", -"2= c #A70000", -"3= c #C10000", -"4= c #D00D0D", -"5= c #1D1717", -"6= c #BB0000", -"7= c #2F0000", -"8= c #020000", -"9= c #560000", -"0= c #CD0000", -"a= c #D50101", -"b= c #CF0E0E", -"c= c #9F1F1F", -"d= c #3A2525", -"e= c #020202", -"f= c #1F1F1F", -"g= c #5F5F5F", -"h= c #8D8D8D", -"i= c #727272", -"j= c #1C1C1C", -"k= c #9D5B5B", -"l= c #090909", -"m= c #313131", -"n= c #797979", -"o= c #323232", -"p= c #9A9595", -"q= c #9E8B8B", -"r= c #A37E7E", -"s= c #AC6969", -"t= c #B45353", -"u= c #BC3E3E", -"v= c #C42828", -"w= c #CB1616", -"x= c #D10707", -"y= c #3F0000", -"z= c #0B0000", -"A= c #350000", -"B= c #B74C4C", -"C= c #1B1B1B", -"D= c #3C3C3C", -"E= c #673D3D", -"F= c #C32F2F", -"G= c #D40202", -"H= c #2B0000", -"I= c #4E0000", -"J= c #2B2B2B", -"K= c #8B8B8B", -"L= c #9F5252", -"M= c #A50000", -"N= c #515151", -"O= c #444444", -"P= c #020101", -"Q= c #8B4C4C", -"R= c #B64F4F", -"S= c #BD3B3B", -"T= c #C52626", -"U= c #CC1414", -"V= c #D00A0A", -"W= c #D40101", -"X= c #CF0000", -"Y= c #CC1313", -"Z= c #B45252", -"`= c #9E8C8C", -" - c #5B5B5B", -".- c #A47C7C", -"+- c #BC3D3D", -"@- c #500000", -"#- c #222121", -"$- c #948686", -"%- c #9F4848", -"&- c #A18383", -"*- c #5B4F4F", -"=- c #2C0000", -"-- c #C80000", -";- c #D20000", -">- c #420000", -",- c #C71E1E", -"'- c #AF5F5F", -")- c #9C9191", -"!- c #9D8E8E", -"~- c #B35555", -"{- c #CA1717", -"]- c #D30101", -"^- c #B50000", -"/- c #5B0000", -"(- c #D00505", -"_- c #CB1515", -":- c #C42626", -"<- c #BE3737", -"[- c #B74848", -"}- c #B15959", -"|- c #AB6A6A", -"1- c #A57979", -"2- c #9F8888", -"3- c #9C9090", -"4- c #8F8888", -"5- c #A13E3E", -"6- c #A60000", -"7- c #777777", -"8- c #493030", -"9- c #AE6161", -"0- c #B45050", -"a- c #BB3F3F", -"b- c #C12E2E", -"c- c #C71D1D", -"d- c #CE0C0C", -"e- c #D20101", -"f- c #030000", -"g- c #BE0000", -"h- c #CF0808", -"i- c #BE3535", -"j- c #A67676", -"k- c #A87070", -"l- c #BD3737", -"m- c #550505", -"n- c #BA0000", -"o- c #BB1111", -"p- c #0F0202", -"q- c #A67474", -"r- c #A28181", -"s- c #A23535", -"t- c #0D0000", -"u- c #2F2F2F", -"v- c #A08585", -"w- c #A47A7A", -"x- c #A96D6D", -"y- c #AD6161", -"z- c #B25353", -"A- c #B84343", -"B- c #6B1F1F", -"C- c #0E0000", -"D- c #AB0000", -"E- c #D00202", -"F- c #C61D1D", -"G- c #B25555", -"H- c #141414", -"I- c #161414", -"J- c #440000", -"K- c #CA0000", -"L- c #1E0000", -"M- c #340000", -"N- c #470000", -"O- c #380000", -"P- c #D10101", -"Q- c #CF0707", -"R- c #CC0D0D", -"S- c #CA1414", -"T- c #C12B2B", -"U- c #BD3838", -"V- c #B74545", -"W- c #B35252", -"X- c #AE5F5F", -"Y- c #A96C6C", -"Z- c #A57878", -"`- c #795F5F", -" ; c #A32B2B", -".; c #390000", -"+; c #371818", -"@; c #353535", -"#; c #363131", -"$; c #392828", -"%; c #311515", -"&; c #080202", -"*; c #090505", -"=; c #B32222", -"-; c #C81717", -";; c #CA1010", -">; c #CC0A0A", -",; c #CF0303", -"'; c #5A0000", -"); c #0A0000", -"!; c #C40000", -"~; c #2A0000", -"{; c #BA3E3E", -"]; c #A57777", -"^; c #7D7D7D", -"/; c #050505", -"(; c #7B7B7B", -"_; c #3E3E3E", -":; c #570000", -"<; c #D00101", -"[; c #9A0202", -"}; c #A52222", -"|; c #A23E3E", -"1; c #C41F1F", -"2; c #CC0808", -"3; c #CD0505", -"4; c #9C0101", -"5; c #C30000", -"6; c #B90000", -"7; c #160000", -"8; c #BC3737", -"9; c #505050", -"0; c #404040", -"a; c #0E0E0E", -"b; c #070707", -"c; c #4D0000", -"d; c #B10000", -"e; c #5D0000", -"f; c #A61919", -"g; c #A33535", -"h; c #C41C1C", -"i; c #210000", -"j; c #CE0101", -"k; c #CA0D0D", -"l; c #BC3535", -"m; c #AB6565", -"n; c #8A8A8A", -"o; c #0B0707", -"p; c #AC4F4F", -"q; c #C22323", -"r; c #CC0707", -"s; c #1F0000", -"t; c #430000", -"u; c #9A9494", -"v; c #A71313", -"w; c #A90000", -"x; c #A42B2B", -"y; c #C22020", -"z; c #590000", -"A; c #540000", -"B; c #3A0000", -"C; c #600000", -"D; c #CD0101", -"E; c #C71313", -"F; c #B93B3B", -"G; c #A86C6C", -"H; c #9F8787", -"I; c #AD5F5F", -"J; c #BC3333", -"K; c #C90D0D", -"L; c #AE0000", -"M; c #BD0000", -"N; c #A80E0E", -"O; c #AA0000", -"P; c #A62222", -"Q; c #BF2626", -"R; c #C50000", -"S; c #3B0000", -"T; c #CB0303", -"U; c #C21F1F", -"V; c #B34A4A", -"W; c #A57676", -"X; c #9B9292", -"Y; c #282828", -"Z; c #3F3F3F", -"`; c #A67272", -" > c #B54848", -".> c #C12020", -"+> c #9D0202", -"@> c #9B8B8B", -"#> c #A90A0A", -"$> c #A71818", -"%> c #BC2E2E", -"&> c #4F3232", -"*> c #9F8686", -"=> c #777171", -"-> c #9B8686", -";> c #AB0404", -">> c #A90E0E", -",> c #BA3535", -"'> c #CA0101", -")> c #5C0303", -"!> c #484848", -"~> c #AC0000", -"{> c #9C8080", -"]> c #AB0101", -"^> c #510000", -"/> c #510404", -"(> c #571C1C", -"_> c #150000", -":> c #C60A0A", -"<> c #BE2323", -"[> c #B24A4A", -"}> c #A57272", -"|> c #494040", -"1> c #101010", -"2> c #1A0606", -"3> c #C21A1A", -"4> c #C90303", -"5> c #9D7979", -"6> c #4B0000", -"7> c #0C0000", -"8> c #C50D0D", -"9> c #BC2A2A", -"0> c #B14D4D", -"a> c #A67171", -"b> c #464646", -"c> c #151515", -"d> c #9E8989", -"e> c #A86969", -"f> c #B44444", -"g> c #BF2121", -"h> c #C70404", -"i> c #9C7F7F", -"j> c #BF0E0E", -"k> c #590101", -"l> c #2D0101", -"m> c #260D0D", -"n> c #231919", -"o> c #212020", -"p> c #202020", -"q> c #414141", -"r> c #A47474", -"s> c #AF5252", -"t> c #9C2E2E", -"u> c #410000", -"v> c #9C8585", -"w> c #AC0404", -"x> c #302020", -"y> c #9F8585", -"z> c #5C5B5B", -"A> c #828282", -"B> c #1D0202", -"C> c #C60404", -"D> c #9B8A8A", -"E> c #AC0808", -"F> c #190000", -"G> c #C60101", -"H> c #C30B0B", -"I> c #BD1F1F", -"J> c #812828", -"K> c #2C2C2C", -"L> c #171616", -"M> c #9F8383", -"N> c #A76868", -"O> c #B04B4B", -"P> c #B82E2E", -"Q> c #C01616", -"R> c #C50303", -"S> c #AC0D0D", -"T> c #C20C0C", -"U> c #BB2222", -"V> c #B43D3D", -"W> c #AB5959", -"X> c #A27878", -"Y> c #9D8C8C", -"Z> c #363636", -"`> c #424242", -" , c #171717", -"., c #9D8B8B", -"+, c #A47171", -"@, c #AC5555", -"#, c #B53838", -"$, c #BD1C1C", -"%, c #C40404", -"&, c #AC1313", -"*, c #2E0000", -"=, c #631515", -"-, c #595959", -";, c #613C3C", -">, c #140000", -",, c #C00E0E", -"', c #B82B2B", -"), c #B04747", -"!, c #A86464", -"~, c #A08080", -"{, c #9B9191", -"], c #4A4A4A", -"^, c #A07F7F", -"/, c #683030", -"(, c #400000", -"_, c #B40000", -":, c #AC1717", -"<, c #A92C2C", -"[, c #A56D6D", -"}, c #550000", -"|, c #9C0707", -"1, c #B92323", -"2, c #B23D3D", -"3, c #AB5858", -"4, c #A47272", -"5, c #121212", -"6, c #5C5C5C", -"7, c #3A1616", -"8, c #B53333", -"9, c #BB1D1D", -"0, c #C20404", -"a, c #AB2020", -"b, c #B00000", -"c, c #A83636", -"d, c #A37474", -"e, c #C20000", -"f, c #230000", -"g, c #700101", -"h, c #050101", -"i, c #7F7F7F", -"j, c #7E7E7E", -"k, c #9B9090", -"l, c #9F8484", -"m, c #A47070", -"n, c #AA5959", -"o, c #B04343", -"p, c #B62C2C", -"q, c #BC1818", -"r, c #B10707", -"s, c #AA2A2A", -"t, c #A64040", -"u, c #A17B7B", -"v, c #4B2525", -"w, c #A76565", -"x, c #A07C7C", -"y, c #5A5757", -"z, c #8F8585", -"A, c #0C0B0B", -"B, c #A93434", -"C, c #A64949", -"D, c #9F8181", -"E, c #C00101", -"F, c #B81F1F", -"G, c #B23838", -"H, c #AD4D4D", -"I, c #603535", -"J, c #0C0C0C", -"K, c #898989", -"L, c #585858", -"M, c #656565", -"N, c #A73D3D", -"O, c #A45353", -"P, c #9E8585", -"Q, c #BF0404", -"R, c #9F8080", -"S, c #838383", -"T, c #A64747", -"U, c #B20000", -"V, c #A35D5D", -"W, c #9D8989", -"X, c #BD0707", -"Y, c #939393", -"Z, c #161616", -"`, c #A55050", -" ' c #B30000", -".' c #A26666", -"+' c #9C8C8C", -"@' c #BB0B0B", -"#' c #BA0F0F", -"$' c #2D2D2D", -"%' c #212121", -"&' c #555555", -"*' c #A45A5A", -"=' c #A07070", -"-' c #9B8F8F", -";' c #BA0E0E", -">' c #B81717", -",' c #606060", -"'' c #262626", -")' c #343434", -"!' c #292929", -"~' c #A26464", -"{' c #320000", -"]' c #9F7A7A", -"^' c #9A9393", -"/' c #B81111", -"(' c #B42525", -"_' c #616161", -":' c #080808", -"<' c #1D1D1D", -"[' c #686868", -"}' c #333333", -"|' c #A16E6E", -"1' c #715D5D", -"2' c #6E6B6B", -"3' c #820F0F", -"4' c #B03434", -"5' c #6F6F6F", -"6' c #878787", -"7' c #676767", -"8' c #131313", -"9' c #111111", -"0' c #9F7777", -"a' c #B50101", -"b' c #220000", -"c' c #AC4343", -"d' c #222222", -"e' c #808080", -"f' c #9E7E7E", -"g' c #B40303", -"h' c #3D0000", -"i' c #A85252", -"j' c #646464", -"k' c #565656", -"l' c #666666", -"m' c #4C4C4C", -"n' c #9D8585", -"o' c #B50505", -"p' c #300000", -"q' c #A46161", -"r' c #8C8C8C", -"s' c #0D0D0D", -"t' c #787878", -"u' c #9B8C8C", -"v' c #B50808", -"w' c #280000", -"x' c #A17070", -"y' c #1A1A1A", -"z' c #4D4D4D", -"A' c #4F4F4F", -"B' c #B50A0A", -"C' c #330000", -"D' c #520000", -"E' c #B60202", -"F' c #9E7D7D", -"G' c #060606", -"H' c #818181", -"I' c #2E2E2E", -"J' c #181818", -"K' c #232323", -"L' c #636363", -"M' c #2A2A2A", -"N' c #6B6B6B", -"O' c #4D2020", -"P' c #3E0000", -"Q' c #353030", -"R' c #B50E0E", -"S' c #3B0D0D", -"T' c #B40606", -"U' c #9C8888", -"V' c #696969", -"W' c #525252", -"X' c #A74E4E", -"Y' c #B40404", -"Z' c #B31818", -"`' c #AF2E2E", -" ) c #A94444", -".) c #B30A0A", -"+) c #A35E5E", -"@) c #B20A0A", -"#) c #9A9191", -"$) c #B22222", -"%) c #AD3838", -"&) c #A74B4B", -"*) c #B11414", -"=) c #A16C6C", -"-) c #B00F0F", -";) c #9A9292", -">) c #B12B2B", -",) c #AC4141", -"') c #A55252", -")) c #AD2323", -"!) c #9E7C7C", -"~) c #AF1414", -"{) c #AF3535", -"]) c #AA4B4B", -"^) c #A35959", -"/) c #AA3232", -"() c #B20101", -"_) c #AE1919", -":) c #AD3F3F", -"<) c #A85555", -"[) c #A26060", -"}) c #A74141", -"|) c #AF0A0A", -"1) c #AC1F1F", -"2) c #AB4949", -"3) c #A65E5E", -"4) c #A16767", -"5) c #A45050", -"6) c #AD1414", -"7) c #AB2424", -"8) c #A95252", -"9) c #A46868", -"0) c #9F6E6E", -"a) c #A15F5F", -"b) c #AA2020", -"c) c #A92B2B", -"d) c #A75C5C", -"e) c #A27171", -"f) c #9E7474", -"g) c #A82E2E", -"h) c #A73232", -"i) c #A56565", -"j) c #9D7A7A", -"k) c #AD0202", -"l) c #9D7D7D", -"m) c #A53D3D", -"n) c #A63939", -"o) c #A36F6F", -"p) c #BD0202", -"q) c #9E8383", -"r) c #AC0303", -"s) c #A34C4C", -"t) c #A44040", -"u) c #A17979", -"v) c #BC0707", -"w) c #9D8888", -"x) c #9B8585", -"y) c #AA0505", -"z) c #A05B5B", -"A) c #A34747", -"B) c #9F8282", -"C) c #BC0B0B", -"D) c #9C8D8D", -"E) c #A90707", -"F) c #A81212", -"G) c #9E6B6B", -"H) c #A14E4E", -"I) c #BB1010", -"J) c #A90808", -"K) c #A62121", -"L) c #9C7A7A", -"M) c #A05555", -"N) c #BB1515", -"O) c #A80A0A", -"P) c #A43030", -"Q) c #A80404", -"R) c #9F5C5C", -"S) c #BE0606", -"T) c #B91C1C", -"U) c #A70D0D", -"V) c #A23F3F", -"W) c #9A8C8C", -"X) c #A60B0B", -"Y) c #9E6363", -"Z) c #BD1010", -"`) c #B72626", -" ! c #A51414", -".! c #A04E4E", -"+! c #A51313", -"@! c #9D6A6A", -"#! c #BA1A1A", -"$! c #B43030", -"%! c #A41B1B", -"&! c #9E5E5E", -"*! c #A41D1D", -"=! c #9C7171", -"-! c #B33A3A", -";! c #A22222", -">! c #9C6D6D", -",! c #A22C2C", -"'! c #9C7878", -")! c #B72C2C", -"!! c #B14343", -"~! c #A12929", -"{! c #9B7C7C", -"]! c #A03B3B", -"^! c #B43737", -"/! c #AE4D4D", -"(! c #A03030", -"_! c #9A8A8A", -":! c #9E4B4B", -"~ c #BB3232", -",~ c #998B8B", -"'~ c #971E1E", -")~ c #984848", -"!~ c #BF2525", -"~~ c #B83B3B", -"{~ c #972D2D", -"]~ c #984F4F", -"^~ c #BD2E2E", -"/~ c #B54545", -"(~ c #950101", -"_~ c #973C3C", -":~ c #975656", -"<~ c #B93838", -"[~ c #B24F4F", -"}~ c #940707", -"|~ c #940B0B", -"1~ c #B74141", -"2~ c #AF5858", -"3~ c #940E0E", -"4~ c #975A5A", -"5~ c #941A1A", -"6~ c #976464", -"7~ c #B44B4B", -"8~ c #AC6262", -"9~ c #941515", -"0~ c #976969", -"a~ c #942929", -"b~ c #976B6B", -"c~ c #B15555", -"d~ c #A96B6B", -"e~ c #931C1C", -"f~ c #977777", -"g~ c #943838", -"h~ c #977272", -"i~ c #AD5E5E", -"j~ c #A67575", -"k~ c #932323", -"l~ c #988383", -"m~ c #954747", -"n~ c #910101", -"o~ c #977979", -"p~ c #AA6868", -"q~ c #A27F7F", -"r~ c #922A2A", -"s~ c #955656", -"t~ c #900202", -"u~ c #977D7D", -"v~ c #A77171", -"w~ c #923131", -"x~ c #900E0E", -"y~ c #966565", -"z~ c #8F0404", -"A~ c #A47B7B", -"B~ c #923838", -"C~ c #901C1C", -"D~ c #967474", -"E~ c #8E0606", -"F~ c #D00303", -"G~ c #923F3F", -"H~ c #902B2B", -"I~ c #978484", -"J~ c #8E0808", -"K~ c #924646", -"L~ c #913A3A", -"M~ c #8C0404", -"N~ c #8D0A0A", -"O~ c #9D8D8D", -"P~ c #CE0B0B", -"Q~ c #CA1616", -"R~ c #924D4D", -"S~ c #924949", -"T~ c #8C1010", -"U~ c #8C0B0B", -"V~ c #CD1010", -"W~ c #C72020", -"X~ c #925454", -"Y~ c #935858", -"Z~ c #8D1B1B", -"`~ c #8C1111", -" { c #C32929", -".{ c #925B5B", -"+{ c #946767", -"@{ c #8D2828", -"#{ c #8C1919", -"${ c #C91C1C", -"%{ c #C03434", -"&{ c #936262", -"*{ c #957777", -"={ c #8E3737", -"-{ c #8B1F1F", -";{ c #978686", -">{ c #8F4646", -",{ c #8C2626", -"'{ c #C22F2F", -"){ c #B94747", -"!{ c #947070", -"~{ c #989494", -"{{ c #915555", -"]{ c #8C2D2D", -"^{ c #BF3939", -"/{ c #B55050", -"({ c #870B0B", -"_{ c #926464", -":{ c #8C3434", -"<{ c #B25A5A", -"[{ c #957E7E", -"}{ c #881A1A", -"|{ c #947373", -"1{ c #8D3B3B", -"2{ c #B84C4C", -"3{ c #AF6464", -"4{ c #8A2929", -"5{ c #968181", -"6{ c #840101", -"7{ c #8D4242", -"8{ c #B45656", -"9{ c #AB6D6D", -"0{ c #978C8C", -"a{ c #8B3838", -"b{ c #840808", -"c{ c #8E4949", -"d{ c #B15F5F", -"e{ c #978F8F", -"f{ c #830404", -"g{ c #8D4747", -"h{ c #841010", -"i{ c #8E5050", -"j{ c #A38181", -"k{ c #830A0A", -"l{ c #8F5757", -"m{ c #851818", -"n{ c #8F5858", -"o{ c #A97373", -"p{ c #916666", -"q{ c #862626", -"r{ c #8F5E5E", -"s{ c #A67B7B", -"t{ c #D70505", -"u{ c #821414", -"v{ c #937575", -"w{ c #883535", -"x{ c #906565", -"y{ c #A38282", -"z{ c #D50C0C", -"A{ c #821919", -"B{ c #958484", -"C{ c #8A4444", -"D{ c #916C6C", -"E{ c #D21414", -"F{ c #831F1F", -"G{ c #7F0505", -"H{ c #8C5353", -"I{ c #927373", -"J{ c #D70909", -"K{ c #CF1B1B", -"L{ c #842424", -"M{ c #8F6262", -"N{ c #937A7A", -"O{ c #D70C0C", -"P{ c #CD2222", -"Q{ c #842B2B", -"R{ c #811B1B", -"S{ c #917171", -"T{ c #948181", -"U{ c #D31414", -"V{ c #C92B2B", -"W{ c #853232", -"X{ c #832828", -"Y{ c #947E7E", -"Z{ c #7C0303", -"`{ c #968888", -" ] c #D01D1D", -".] c #C53535", -"+] c #863939", -"@] c #853737", -"#] c #968989", -"$] c #7B0707", -"%] c #CC2727", -"&] c #C13F3F", -"*] c #864040", -"=] c #884646", -"-] c #7B0A0A", -";] c #C83131", -">] c #BD4949", -",] c #874747", -"'] c #8A5555", -")] c #7C1414", -"!] c #790404", -"~] c #C43A3A", -"{] c #B95252", -"]] c #884E4E", -"^] c #8D6464", -"/] c #7F2424", -"(] c #7A0B0B", -"_] c #C04444", -":] c #B55C5C", -"<] c #895555", -"[] c #907373", -"}] c #823333", -"|] c #7A1313", -"1] c #BC4E4E", -"2] c #B16565", -"3] c #8B5C5C", -"4] c #750101", -"5] c #938181", -"6] c #854242", -"7] c #7B1919", -"8] c #B85757", -"9] c #AC6F6F", -"0] c #8C6363", -"a] c #760808", -"b] c #885151", -"c] c #7C2020", -"d] c #B46161", -"e] c #8D6A6A", -"f] c #771010", -"g] c #8B6161", -"h] c #7D2828", -"i] c #E00101", -"j] c #A48282", -"k] c #8F7171", -"l] c #791818", -"m] c #8E7070", -"n] c #7E2E2E", -"o] c #DF0505", -"p] c #A28787", -"q] c #917878", -"r] c #7C2626", -"s] c #927F7F", -"t] c #7F3535", -"u] c #A67E7E", -"v] c #DE0A0A", -"w] c #803C3C", -"x] c #A18888", -"y] c #DC0F0F", -"z] c #938484", -"A] c #710202", -"B] c #824444", -"C] c #710505", -"D] c #824343", -"E] c #DA1414", -"F] c #948787", -"G] c #710606", -"H] c #865353", -"I] c #741313", -"J] c #834A4A", -"K] c #E30202", -"L] c #D71A1A", -"M] c #958B8B", -"N] c #710A0A", -"O] c #8A6262", -"P] c #782222", -"Q] c #855252", -"R] c #DF0B0B", -"S] c #D32323", -"T] c #710D0D", -"U] c #8E7171", -"V] c #7B3131", -"W] c #865858", -"X] c #DB1515", -"Y] c #CF2D2D", -"Z] c #711010", -"`] c #6D0303", -" ^ c #917E7E", -".^ c #7F4141", -"+^ c #885F5F", -"@^ c #D71F1F", -"#^ c #CA3737", -"$^ c #711414", -"%^ c #6D0707", -"&^ c #948989", -"*^ c #835050", -"=^ c #8A6767", -"-^ c #D32828", -";^ c #C64141", -">^ c #711717", -",^ c #6D0B0B", -"'^ c #875F5F", -")^ c #C14A4A", -"!^ c #721E1E", -"~^ c #701515", -"{^ c #8B6E6E", -"]^ c #8E7474", -"^^ c #C93B3B", -"/^ c #BD5454", -"(^ c #742525", -"_^ c #742424", -":^ c #907D7D", -"<^ c #907C7C", -"[^ c #C44646", -"}^ c #B85E5E", -"|^ c #762C2C", -"1^ c #793434", -"2^ c #670101", -"3^ c #928282", -"4^ c #C04F4F", -"5^ c #B36767", -"6^ c #783333", -"7^ c #7D4343", -"8^ c #969191", -"9^ c #690A0A", -"0^ c #BB5959", -"a^ c #AE7171", -"b^ c #793A3A", -"c^ c #6C1616", -"d^ c #660202", -"e^ c #958E8E", -"f^ c #B66262", -"g^ c #E90101", -"h^ c #AA7979", -"i^ c #7B4141", -"j^ c #866161", -"k^ c #702222", -"l^ c #680808", -"m^ c #B16C6C", -"n^ c #A68080", -"o^ c #7D4848", -"p^ c #8B7070", -"q^ c #680D0D", -"r^ c #AC7676", -"s^ c #E80606", -"t^ c #A28888", -"u^ c #7F4F4F", -"v^ c #793F3F", -"w^ c #691212", -"x^ c #979393", -"y^ c #A77F7F", -"z^ c #E70808", -"A^ c #9F8F8F", -"B^ c #815656", -"C^ c #7E4E4E", -"D^ c #6A1717", -"E^ c #E60B0B", -"F^ c #835D5D", -"G^ c #630505", -"H^ c #6C1D1D", -"I^ c #EB0404", -"J^ c #E31212", -"K^ c #856464", -"L^ c #886C6C", -"M^ c #6D2222", -"N^ c #E70B0B", -"O^ c #DE1C1C", -"P^ c #886B6B", -"Q^ c #6C2222", -"R^ c #8E7B7B", -"S^ c #6E2828", -"T^ c #E41313", -"U^ c #D92525", -"V^ c #8A7272", -"W^ c #713232", -"X^ c #723434", -"Y^ c #E01A1A", -"Z^ c #D52F2F", -"`^ c #8C7878", -" / c #774141", -"./ c #774343", -"+/ c #DC2121", -"@/ c #CF3939", -"#/ c #8E7D7D", -"$/ c #7C5151", -"%/ c #D82A2A", -"&/ c #CA4242", -"*/ c #908383", -"=/ c #846464", -"-/ c #836363", -";/ c #D33434", -">/ c #C54C4C", -",/ c #928888", -"'/ c #8A7474", -")/ c #8C7979", -"!/ c #C05656", -"~/ c #948D8D", -"{/ c #918585", -"]/ c #C84747", -"^/ c #BA5F5F", -"// c #C35050", -"(/ c #B56969", -"_/ c #BE5A5A", -":/ c #B07373", -" ", -" , ' ", -" ) ! ", -" ~ { ", -" ] ^ ", -" / ( ", -" _ : ", -" + < [ ", -" } | 1 ", -" 2 3 4 ", -" 5 6 7 ", -" 8 9 0 ", -" a b c + ", -" d e e f ", -" g h h i ", -" j h h k ", -" l m m n ", -" o m m p ", -" q r r s ", -" t u u v ", -" w u u x ", -" y z z A ", -" + B z z C ", -" D E F F G ", -" # H I I J ", -" K L I I M ", -" N O P P Q ", -" R P P P S + ", -" T U U U V K ", -" W U U U X Y ", -" Z ` ` ` ... ", -" +.` ` ` @.#. ", -" $.%.%.%.%.&. ", -" *.=.=.=.=.-. ", -" ;.=.=.=.=.>. ", -" ,.'.'.'.'.). ", -" !.'.'.'.'.~. ", -" {.].].].].^. ", -" /.].].].].(. ", -" _.:.:.:.:.<. ", -" [.}.}.}.}.|. ", -" 1.}.}.}.}.2. ", -" 3.4.4.4.4.4.5.6. ", -" 7.4.4.4.4.4.8.3. ", -" 9.0.0.0.0.0.a.b. ", -" c.0.0.0.0.0.d.7. ", -" e.f.f.f.f.f.g.h. ", -" i.j.j.j.j.j.j.k. ", -" l.j.j.j.j.j.j.m. ", -" n.o.o.o.o.o.o.p. ", -" q.o.o.o.o.o.o.r. ", -" s.t.t.t.t.t.t.u. ", -" v.w.w.w.w.w.w.x. ", -" y.w.w.w.w.w.w.z. ", -" A.B.B.B.B.B.B.C. ", -" D.B.B.B.B.B.B.E. ", -" + F.G.G.G.G.G.G.H. ", -" I.J.G.G.G.G.G.G.K.6. ", -" L.M.N.N.N.N.N.N.O.P. ", -" Q.R.N.N.N.N.N.N.S.T. ", -" U.V.W.W.W.W.W.W.X.Y. ", -" Z.`.`.`.`.`.`.`. +.+ ", -" ++`.`.`.`.`.`.`.`.@+ ", -" #+$+$+$+$+$+$+$+$+U. ", -" %+$+$+$+$+$+$+$+$+&+ ", -" *+=+=+=+=+=+=+=+=+-+ ", -" ;+=+=+=+=+=+=+=+=+>+ ", -" ,+'+'+'+'+'+'+'+'+)+ ", -" !+~+~+~+~+~+~+~+~+{+ ", -" ]+~+~+~+~+~+~+~+~+^+ ", -" /+(+(+(+(+(+(+(+(+_+ ", -" 6.:+(+(+(+(+(+(+(+(+<+ ", -" T.[+}+}+}+}+}+}+}+}+|+ ", -" 1+2+}+}+}+}+}+}+}+}+3+ ", -" 4+5+6+6+6+6+6+6+6+6+7+ ", -" 8+9+0+0+0+0+0+0+0+0+a+ ", -" b+0+0+0+0+0+0+0+0+0+c+6. ", -" d+e+e+e+e+e+e+e+e+e+e+1+ ", -" f+e+e+e+e+e+e+e+e+e+e+g+ ", -" h+i+i+i+i+i+i+i+i+i+i+j+ ", -" k+l+l+l+l+l+l+l+l+l+l+m+ ", -" n+l+l+l+l+l+l+l+l+l+l+o+ ", -" + p+q+r+s+t+u+v+w+x+y+z+ A+B+B+B+B+B+B+B+B+B+B+C+ + D+E+F+G+H+I+J+K+L+M+N+ ", -" O+P+Q+R+S+T+U+V+W+X+M+ Y+B+B+B+B+B+B+B+B+B+B+Z+ `+ @.@+@@@#@$@%@&@*@=@+ ", -" N+-@;@>@,@#@,@'@)@!@N+ ~@{@{@{@{@{@{@{@{@{@{@]@ ^@/@(@_@:@:@<@[@}@|@ ", -" |@1@2@3@:@:@3@4@5@6@ 7@{@{@{@{@{@{@{@{@{@{@8@ + M+9@0@a@a@a@<@4@b@+ ", -" c@d@e@f@a@a@a@g@h@i@ 6.j@k@k@k@k@k@k@k@k@k@k@l@ m@n@o@p@p@p@p@q@r@z+ ", -" s@t@u@p@p@p@v@w@d@ x@y@k@k@k@k@k@k@k@k@k@k@z@ A@B@C@D@D@D@D@E@F@m@ ", -" G@H@I@D@D@D@D@J@K@+ L@M@N@N@N@N@N@N@N@N@N@N@O@ M+P@Q@R@R@R@R@S@T@ ", -" T@U@R@R@R@R@R@V@M+ W@X@Y@Y@Y@Y@Y@Y@Y@Y@Y@Y@Z@ `@ #.#+#+#+#+#@###O+ ", -" 6@$#%#R@R@R@R@%#&#c@ *#=#Y@Y@Y@Y@Y@Y@Y@Y@Y@Y@-# ;#>#,#,#,#,#,#'#)# ", -" !#~#+#+#+#+#+#{#]# ^#/#/#/#/#/#/#/#/#/#/#/#(#_# :#<#[#[#[#[#[#}#|#c@ ", -" 1#2#,#,#,#,#,#3#4#+ 5#/#/#/#/#/#/#/#/#/#/#/#X@6# 7#8#9#9#9#9#9#0#a#c@ ", -" ;#b#[#[#[#[#[#c#d#+ e#f#f#f#f#f#f#f#f#f#f#f#g#h# i#j#9#9#9#9#9#k#a# ", -" l#m#9#9#9#9#9#9#n#o# p#f#f#f#f#f#f#f#f#f#f#f#q#r# s#t#u#u#u#u#u#u#v#+ ", -" O+w#u#u#u#u#u#u#x#y# z#A#A#A#A#A#A#A#A#A#A#A#B#C# + D#E#E#E#E#E#E#F#G# ", -" c@H#E#E#E#E#E#E#E#I# J#K#K#K#K#K#K#K#K#K#K#K#K#e# L#M#N#N#N#N#N#N#M#O# ", -" P#Q#N#N#N#N#N#N#R#S# T#K#K#K#K#K#K#K#K#K#K#K#K#U# V#W#W#W#W#W#W#W#X#N+ ", -" z+Y#W#W#W#W#W#W#W#Z# `# $ $ $ $ $ $ $ $ $ $ $ $.$ +$@$#$#$#$#$#$#$#$$$ ", -" %$#$#$#$#$#$#$#$&$*$ =$ $ $ $ $ $ $ $ $ $ $ $ $-$ ;$>$>$>$>$>$>$>$,$z+ ", -" '$,$>$>$>$>$>$>$>$)$O+ !$~$~$~$~$~$~$~$~$~$~$~$~${$ ]$^$^$^$^$^$^$^$^$]$ ", -" /$^$^$^$^$^$^$^$^$($ _$~$~$~$~$~$~$~$~$~$~$~$~$:$ <$[$[$[$[$[$[$[$[$}$`@ ", -" |$^$^$^$^$^$^$^$^$1$ 2$3$3$3$3$3$3$3$3$3$3$3$3$4$ 6@5$6$6$6$6$6$6$6$5$7$ ", -" O+8$[$[$[$[$[$[$[$[$9$ 0$a$a$a$a$a$a$a$a$a$a$a$a$b$ c$d$d$d$d$d$d$d$d$e$ ", -" f$6$6$6$6$6$6$6$6$6$g$ h$a$a$a$a$a$a$a$a$a$a$a$a$i$ j$k$k$k$k$k$k$k$k$l$ ", -" m$d$d$d$d$d$d$d$d$d$n$ 6.o$p$p$p$p$p$p$p$p$p$p$p$p$q$ r$k$k$k$k$k$k$k$k$s$6@ ", -" t$k$k$k$k$k$k$k$k$k$u$ v$p$p$p$p$p$p$p$p$p$p$p$p$p$w$x@ x$y$y$y$y$y$y$y$y$z$A$ ", -" B$y$y$y$y$y$y$y$y$y$C$ D$E$E$E$E$E$E$E$E$E$E$E$E$E$F$G$ H$I$J$J$J$J$J$J$J$J$K$L$ ", -" M$J$J$J$J$J$J$J$J$J$N$L$ O$P$P$P$P$P$P$P$P$P$P$P$P$P$Q$R$ S$T$T$T$T$T$T$T$T$T$T$U$ ", -" V$T$T$T$T$T$T$T$T$T$T$W$N+ X$P$P$P$P$P$P$P$P$P$P$P$P$P$Y$Z$ `$ %.%.%.%.%.%.%.%.%.%+%L$ ", -" @%.%.%.%.%.%.%.%.%.%.%#%$%%%&%*%=% -%;%;%;%;%;%;%;%;%;%;%;%;%;%>%,% '%)%!%!%!%!%!%!%!%!%!%!%~%{% ", -" ]%!%!%!%!%!%!%!%!%!%^%/%(%_%_%_%:%<%[% }%;%;%;%;%;%;%;%;%;%;%;%;%;%;%|% c@1%2%#%#%#%#%#%#%#%#%#%#%#%3%`@ ", -" 4%5%#%#%#%#%#%#%#%6%7%_%_%_%_%_%_%_%8%=% 9%0%0%0%0%0%0%0%0%0%0%0%0%0%0%a% {%b%c%d%d%d%d%d%d%d%d%d%d%d%d%e% ", -" f%d%d%d%d%d%d%g%h%_%_%_%_%_%_%_%_%_%i%j% k%0%0%0%0%0%0%0%0%0%0%0%0%0%0%l% m%n%n%n%n%n%o% =%n%n%n%n%n%n%n%n%n%p%q%r%s%s%s%s%s%s%s%s%s%s%s%s%s%t%u% ", -" v%w%d%d%d%d%d%~+_%_%_%_%_%_%_%_%_%_%x%y% z%A%A%A%A%A%A%A%A%A%A%A%A%A%A%B% C%_%_%_%_%_%D% j%E%F%G%_%_%_%_%_%_%_%_%_%_%_%_%H%I%}.J%K%K%K%K%K%K%K%K%K%K%L% ", -" + M%s%s%s%s%s%N%_%_%_%_%_%_%_%_%_%_%_%O%P%`@ Q%A%A%A%A%A%A%A%A%A%A%A%A%A%A%R% C%_%_%_%_%_%D% S%T%U%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%V%A%W%W%W%W%W%W%W%W%X%Y% ", -" 4%Z%K%K%K%K%`%_%_%_%_%_%_%_%_%_%_%_%f. &.&+&@& #&$&$&$&$&$&$&$&$&$&$&$&$&$&$&%& C%_%_%_%_%_%D% &&*&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%=&P$-&-&-&-&-&-&;&>& ", -" ,&'&W%W%W%)&_%_%_%_%_%_%_%_%_%_%_%B+W%W%W%!&~&{&N+ ]&^&^&^&^&^&^&^&^&^&^&^&^&^&^&/& C%_%_%_%_%_%D% (&_&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%:&<&-&-&-&-&-&[&`@ ", -" }&|&-&-&l+_%_%_%_%_%_%_%_%_%_%1&2&-&-&-&-&-&-&3&4&5&6&+ 7&^&^&^&^&^&^&^&^&^&^&^&^&^&^&8& C%_%_%_%_%_%D% 9&0&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%a&b&b&b&b&c&N+ ", -" d&e&b&f&I%_%_%_%_%_%_%_%_%_%r g&b&b&b&b&b&b&b&b&b&h&i&j&Y%k& l&m&m&m&m&m&m&m&m&m&m&m&m&m&m&n& C%_%_%_%_%_%D% *%_%_%_%_%_%_%o&V%p&p&p&p&p&p&p&p&p&q&H%_%_%_%_%_%r&s&g&g&t&u& ", -" P%v&g&w&x&_%_%_%_%_%_%H%)&y&g&g&g&g&g&g&g&g&g&g&g&g&g&z&A&B&C&D& x@E&m&m&m&m&m&m&m&m&m&m&m&m&m&m&]&+ C%_%_%_%_%_%D% F&G&H&I&_%_%_%_%_%r&J&K&L&L&L&L&L&L&L&L&s&M&}.H%_%_%_%_%(%N&O&P&k& ", -" Q&R&S&2&T&1&_%_%_%U&'+f&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&S&V&A&W&X&Y&+ Z&`& * * * * * * * * * * * * * *.*6. C%_%_%_%_%_%D% +*@*#*$*%*&***=*_%_%_%_%_%z ************************s&q&_%_%_%_%H%-*;*`@ ", -" `@>*,***'*)* *N&g%**************************************************!*~*H&{*@&c@ ]*^* * * * * * * * * * * * * * */*(* C%_%_%_%_%_%D% N+_*:*<*[*}*g%g%g%g%g%g%|*_%_%_%_%_%N.g%g%g%g%g%g%g%g%g%g%g%g%g%I%_%_%_%_%_%1* ", -" 2*3*g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%4*5*6*;*{*4%c@ 7*8*9*9*9*9*9*9*9*9*9*9*9*9*9*9*0*L@ C%_%_%_%_%_%D% a*Y&b*c*d*e*f*g*g*g*g*g*g*g*g*g*g*h*i*i*i*i*i*`.g*g*g*g*g*g*g*g*g*g*g*g*g*j*_%_%_%_%_%k* ", -" l*m*n*o*(+(+(+(+(+(+p*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*g*L&y&y&y&y&y&y&y&y&y&y&f&g*q*r*3*s*t*2*u*+ v*w*x*x*x*x*x*x*x*x*x*x*x*x*x*x*y*z* C%_%_%_%_%_%D% a*A*B*C*D*E*F*f&f&f&f&f&f&f&f&f&f&f&f&f&f&f&G*H*H*H*H*H*M&f&f&f&f&f&f&f&f&f&f&f&f&f&j*_%_%_%_%_%k* ", -" I*_%_%_%_%_%_%_%_%_%=+f&f&f&f&f&f&f&f&f&f&f&f&f&J*j.K*L*M*:&:&:&:&:&:&:&:&:&:&q&N*O*B+P*f&f&Q*R*S*T*U*V*W*6& X*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*w*Y* C%_%_%_%_%_%D% `@Z*`* =.=+=@=#=L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&I%_%_%_%_%_%k* ", -" I*_%_%_%_%_%_%_%_%_%$+f&f&f&f&f&f&f&f&f&f&f&$=%=&=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%r&i+'*f&f&f&f&f&f&f&Q**=D*==-=;=>=+*`@j%=%,='=)=)=)=)=)=)=)=)=)=)=!=~={= 9&]=)=)=)=)=)= o%)=)=)=)=)=^= /=(=(=(=(=(=(=(=(=(=(=(=;%w.0.0.0._=)=)=)=)=)=)=)='=,=o%j% C%_%_%_%_%_%D% m%'=)=)=)=)=)=:= N+6&<=[=}=|=.*1=p$p$p$p$p$p$p$p$p$p$2=3=y&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&s&4= =5=_%_%_%_%_%k* ", -" I*_%_%_%_%_%_%_%_%_%$+L&L&L&L&L&L&L&L&L&L&6=7=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%8=9=0=L&L&L&L&L&L&L&s&s&s&s&s&a=b=c=d=:%_%_%_%_%_%_%_%_%_%_%_%_%_%e=f=g=9& h=G%_%_%_%_%_& i=_%_%_%_%_%j= k=(=(=(=(=(=(=(=(=(=(=$&I%_%_%_%_%_%_%_%_%_%_%_%_%_%_%l=m=n= C%_%_%_%_%_%D% S%o=_%_%_%_%_%_&E% p=q=r=s=t=u=v=w=x='*x*y=z=_%_%_%_%_%_%_%_%_%_%_%_%_%(%A=A#K&'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*b=B=q= C=_%_%_%_%_%k* ", -" D=_%_%_%_%_%_%_%_%_%E=F=G=s&s&s&s&s&s&s&2&H=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%I=K&s&s&s&s&s&s&s&'*'*'*'*'*j.&=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%J=K= h=G%_%_%_%_%_& i=_%_%_%_%_%j= L=M=M=M=M=M=M=M=M=M=M==+H%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%x%N=&& C%_%_%_%_%_%D% j%O=_&_%_%_%_%_%P=Q=R=S=T=U=V=W='*'*'*'*'*X=u (%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%8=O*<&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&y&Y=Z=`= C=_%_%_%_%_%k* ", -" D=_%_%_%_%_%_%_%_%_% -+ .-+-x='*'*'*'*'*@-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%H%4.'*'*'*'*'*'*y&y&y&y&y&`.8=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%#-$-+ h=G%_%_%_%_%_& i=_%_%_%_%_%j= %-M=M=M=M=M=M=M=M=M=M='._%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_&N= C%_%_%_%_%_%D% F&&-*-_&_%_%_%_%_%_%=---y&y&y&y&y&y&y&y&y&y&;-u H%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%>-P*;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-,-'-)- C=_%_%_%_%_%k* ", -" i%_%_%_%_%_%_%_%_%_% - !-~-{-]-y&2=H%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%z=3=y&y&y&y&y&y&y&y&y&^-1&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%/-(-_-:-<-[-}-|-1-2-3-4-G%_%_%_%_%_& i=_%_%_%_%_%j= 5-6-6-6-6-6-6-6-6-6-6-t._%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%x%7- C%_%_%_%_%_%8-9-0-a-b-c-d-e-A#f-_%_%_%_%_%_%p&g-;-;-;-;-;-;-;-;-;-;-;-m&8=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%o.;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-h-i-j-+ C=_%_%_%_%_%k* ", -" i%_%_%_%_%_%_%_%_%_% - p=k-l-m-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%G.;-;-;-;-;-;-;-;-;-T&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%=&n-;-;-;-;-;-;-;-;-h-o-p-_%_%_%_%_&q-r-2-6&p= i=_%_%_%_%_%j= s-2=2=2=2=2=2=2=2=2=2=a$t-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%u-j%+ +*q=v-w-x-y-z-A-B-_%_%_%_%_%/-P*P*P*P*P*P*M=C-_%_%_%_%_%_%7%D-P*P*P*P*P*P*P*P*P*P*P*P*K*_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%r&--P*P*P*P*P*P*P*P*P*P*P*P*P*P*P*E-F-G-u* H-_%_%_%_%_%l* ", -" i%_%_%_%_%_%_%_%_%_% - I-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%J-P*P*P*P*P*P*P*P*K-L-_%_%_%_%_%(%M-N-N%N%N%N%N%N%N%N%O-1&_%_%_%_%_%_%N.P*P*P*P*P*P*P*P*P*J*M*_%_%_%_%H%P*P-Q-R-S-F-T-U-V-W-X-Y-Z-`-_%_%_%_%_%j= ;2=2=2=2=2=2=2=2=2=2=2=B.y=.;.;.;+;@;@;@;@;@;#;$;%;&;_%_%_%_%_%*;=;-;;;>;,;K&K&K&K&K&f._%_%_%_%_%';K&K&K&K&K&^-h%_%_%_%_%_%_%);p$K&K&K&K&K&K&K&K&K&K&K&K&!;(%_%_%_%_%_%H%~;N-N-N-N-N-N-N-N-N-y=q&_%_%_%_%_%H%E$K&K&K&K&K&K&K&K&K&K&K&K&K&;;{;];k& ^;/;_%_%_%_%e=(; ", -" _;_%_%_%_%_%_%_%_%_% - [%:%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%=-K&K&K&K&K&K&K&K&n-);_%_%_%_%_%N@X=K&K&K&K&K&K&K&K&K&X=x*t-_%_%_%_%_%:;K&K&K&K&K&K&K&K&K&J*M*_%_%_%_%H%K&K&K&K&K&K&K&K&K&K&K&K&<;[;_%_%_%_%_%j= };J&J&J&J&J&J&J&J&J&J&J&J&J&J&J&J&|; p=1;2;3;4;o&_%_%_%_%_%(=X=X=X=X=X=X=X=X=X=f._%_%_%_%_%';X=X=X=X=5;H=_%_%_%_%_%_%f-~+X=X=X=X=X=X=X=X=X=X=X=X=X=6-_%_%_%_%_%H%].M&X=X=X=X=X=X=X=X=X=X=6;7;_%_%_%_%_%4.X=X=X=X=X=X=X=X=X=X=2;8;Y-+* n%9;9;9;9;9;9;9;0;a;_%_%_%_%_%l==% ", -" _;_%_%_%_%_%_%_%_%_% - K=b;_%_%_%_%_%_%_%_%i*m %.%.%.%.%.%.%.%.c;_%_%_%_%_%_%_%_%_%x&X=X=X=X=X=X=X=X=d;H%_%_%_%_%M*X=X=X=X=X=X=X=X=X=X=X=X=X=e;_%_%_%_%_%/%X=X=X=X=X=X=X=X=X=^%M*_%_%_%_%H%X=X=X=X=X=X=X=X=X=X=X=X=X=P$_%_%_%_%_%j= + f;J&J&J&J&J&J&J&J&J&J&J&J&J&J&J&J&g; `@h;J%J%$=N*_%_%_%_%_%A#J%J%J%J%J%J%J%J%J%0._%_%_%_%_%';J%J%J%K-K*_%_%_%_%_%_%H%` J%J%J%J%J%J%J%J%J%J%J%J%J%J% $_%_%_%_%_%i;K-J%J%J%J%J%J%J%J%J%J%J%J%@-_%_%_%_%_%%=J%J%J%J%J%J%j;k;l;m;a* *%_%_%_%_%_%_%_%_%_%_%_%_%_%_%m= ", -" _;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%o;p;q;r;J%J%J%J%J%J%^&_%_%_%_%_%_%_%_%_%p&J%J%J%J%J%J%J%J%6%H%_%_%_%_%s;J%J%J%J%J%J%J%J%J%J%J%J%J%B._%_%_%_%_%t;J%J%J%J%J%J%J%J%J%g-:&_%_%_%_%H%J%J%J%J%J%J%J%J%J%J%J%J%J%E$_%_%_%_%_%j= u;v;w;w;w;w;w;w;w;w;w;w;w;w;w;w;w;w;x; + y;0=0=0=7=_%_%_%_%_%/#0=0=0=0=0=0=0=0=0=0._%_%_%_%_%z;0=0=$=T&_%_%_%_%_%_%_%A;M&0=0=0=0=0=0=0=0=0=0=0=0=0=0=A#_%_%_%_%_%B;0=0=0=0=0=0=0=0=0=0=0=0=0=a&_%_%_%_%_%C;0=0=0=D;E;F;G;)- *%_%_%_%_%_%_%_%_%_%_%_%_%_%e=n= ", -" _;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S%+ H;I;J;K;0=0=0=$&_%_%_%_%_%_%_%_%_%p&0=0=0=0=0=0=0=0=L;H%_%_%_%_%s;0=0=0=0=0=0=0=0=0=0=0=0=0=B._%_%_%_%_%t;0=0=0=0=0=0=0=0=0=M;:&_%_%_%_%H%0=0=0=0=0=0=0=0=0=0=0=0=0=E$_%_%_%_%_%j= z*N;O;O;O;O;O;O;O;O;O;O;O;O;O;O;O;O;P; Q;M&M&M&7=_%_%_%_%_%Y@M&M&M&M&M&M&M&M&M&4._%_%_%_%_%z;M&M&].8=_%_%_%_%_%_%y=R;M&M&M&M&M&M&M&M&M&M&M&M&M&M&M&A#_%_%_%_%_%S;M&M&M&M&M&M&M&M&M&M&M&M&M&a&_%_%_%_%_%C;T;U;V;W;X; *%_%_%_%_%_%_%_%_%_%_%_%_%_%Y; ", -" Z;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% )-`; >.>+>_%_%_%_%_%_%_%_%_%p&M&M&M&M&M&M&M&M&)*H%_%_%_%_%L-M&M&M&M&M&M&M&M&M&M&M&M&M&B._%_%_%_%_%t;M&M&M&M&M&M&M&M&M&H*:&_%_%_%_%H%M&M&M&M&M&M&M&M&M&M&M&M&M&p$_%_%_%_%_%j= @>#>O;O;O;O;O;O;O;O;O;O;O;O;O;O;O;O;$> %>$=$=$=7=_%_%_%_%_%N@$=$=$=$=$=$=$=$=$=4._%_%_%_%_%T&$=l+i*_%_%_%_%_%_%H=M;$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=f#_%_%_%_%_%S;$=$=$=$=$=$=$=$=$=$=$=$=$=e;_%_%_%_%_%&>*>`@ *%_%_%_%_%_%_%_%_%_%_%_%_%_%e=n= ", -" 0;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% =>_%_%_%_%_%_%_%_%_%p&M&M&M&M&M&$=$=$=)*H%_%_%_%_%L-$=$=$=$=$=$=$=$=$=$=$=$=$=w._%_%_%_%_%t;$=$=$=$=$=$=$=$=$=6=:&_%_%_%_%H%$=$=$=$=$=$=$=$=$=$=$=$=$=a$_%_%_%_%_%j= ->;>D-D-D-D-D-D-D-D-D-D-D-D-D-D-D-D->> ,>$=$=$=7=_%_%_%_%_%N@$=$=$=$=$=$=$=$=$=}._%_%_%_%_%T&$&z=_%_%_%_%_%_%p&^-$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=/#_%_%_%_%_%S;K-K-K-K-K-K-K-K-K-K-K-K-'>)>_%_%_%_%_%!> *%_%_%_%_%_%_%_%_%_%_%_%_%_%_%u- ", -" 0;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%p&$=$=$=$=$=K-K-K-~>H%_%_%_%_%L-K-K-K-K-K-K-K-K-K-K-K-K-K-w._%_%_%_%_%>-K-K-K-K-K-K-K-K-K-n-:&_%_%_%_%H%K-K-K-K-K-K-K-K-K-K-K-K-K-a$_%_%_%_%_%j= {>]>D-D-D-D-D-D-D-D-D-D-D-0%4.|*^>^>/>!>!>!>!>!>(>C;=*'.p&_%_%_%_%_%k@K-K-K-K-K-K-K-K-K-:._%_%_%_%_%y=_>_%_%_%_%_%_%:&6-K-K-K-K-K-K-K-K-K-K-K-K-K-K-K-K-K-K-Y@_%_%_%_%_%S;<&<&<&<&<&<&<&<&<&:><>[>}>|>_%_%_%_%_%!> n%N=N=N=N=N=N=9;0;1>_%_%_%_%_%l=o% ", -" 0;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%2>3>4>K-K-K-K-<&<&D-H%_%_%_%_%L-<&<&<&<&<&<&<&<&<&<&<&<&<&t._%_%_%_%_%>-<&<&<&<&<&<&<&<&<&n-:&_%_%_%_%H%<&<&<&<&<&<&<&<&<&<&<&<&<&3$_%_%_%_%_%j= 5>~>~>~>~>~>~>~>~>~>~>$&6>7>_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%{@<&<&<&<&<&<&<&<&<&:._%_%_%_%_%H%_%_%_%_%_%_%=&A#<&<&<&<&<&<&<&<&<&<&<&<&<&<&<&<&<&<&<&Y@_%_%_%_%_%B;----------8>9>0>a>q= b>_%_%_%_%_%!> ,=/;_%_%_%_%e=,= ", -" 0;_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c>p=d>e>f>g>h>----O;H%_%_%_%_%L---------------------------t._%_%_%_%_%>-------------------6;:&_%_%_%_%H%--------------------------~$_%_%_%_%_%j= i>~>~>~>~>~>~>~>~>~> $h%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%{@------------------]._%_%_%_%_%_%_%_%_%_%_%f-N.G*--------------------------------------N@_%_%_%_%_%B;G*j>k>l>m>n>o>p>p>p>p>p>p>0&_%_%_%_%_%!> H-_%_%_%_%_%l* ", -" q>_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> a*r>s>t>_%_%_%_%_%L---------------------------o._%_%_%_%_%u>------------------N&:&_%_%_%_%H%--------------------------~$_%_%_%_%_%j= v>w>)*)*)*)*)*)*)*^&h%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%B+G*G*G*G*G*G*G*G*G*]._%_%_%_%_%_%_%_%_%_%_%z;G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*G*k@_%_%_%_%_%x>y>z>_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%!> C=_%_%_%_%_%k* ", -" q>_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_%B>C>G*G*G*G*G*G*G*G*G*G*G*G*o._%_%_%_%_%u>G*G*G*G*G*G*G*G*G*w&:&_%_%_%_%H%G*G*G*G*G*G*G*G*G*G*G*G*G* $_%_%_%_%_%j= D>E>)*)*)*)*)*)*)*6>_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%l+2&2&2&2&2&2&2&2&2&'._%_%_%_%_%_%_%_%_%_%_%F>x*2&2&2&2&2&2&2&2&2&2&2&2&2&2&2&2&2&G>H>I>J>_%_%_%_%_%K> I*_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%!> C=_%_%_%_%_%k* ", -" q>_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_%L>M>N>O>P>Q>R>2&2&2&2&2&2&2&j._%_%_%_%_%u>2&2&2&2&2&2&2&2&2&p*:&_%_%_%_%H%2&2&2&2&2&2&2&2&2&2&2&2&2&K#_%_%_%_%_%j= z*S>L;L;L;L;L;L;$&7>_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%l+R;R;R;R;R;R;R;R;R;'._%_%_%_%_%_%_%_%_%_%_%_%V%9*R;R;R;R;R;R;R;R;R;R;R;R;T>U>V>W>X>Y>+ )=_%_%_%_%_%K> Z>_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%!> C=_%_%_%_%_%k* ", -" `>_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , u;.,+,@,#,$,%,R;R;f._%_%_%_%_%u>R;R;R;R;R;R;R;R;R;^-:&_%_%_%_%H%R;R;R;R;R;R;R;R;R;R;R;R;R;K#_%_%_%_%_%j= u;&,6%6%6%6%6%6%o._%_%_%_%_%_%*,|*r =,-,-,-,-,-,;,:.|*7>_%_%_%_%_%_%i+!;!;!;!;!;!;!;!;!;=._%_%_%_%_%_%_%_%_%_%_%_%_%>,x*!;!;!;!;!;!;,,',),!,~,{,+ )=_%_%_%_%_%K> ],_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%!> C=_%_%_%_%_%k* ", -" `>_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , p=^,!,/,_%_%_%_%_%(,!;!;!;!;!;!;!;!;!;_,:&_%_%_%_%H%!;!;!;!;!;!;!;!;!;!;!;!;!;A#_%_%_%_%_%j= + :,6%6%6%6%6%6%C;_%_%_%_%_%~;6%6%6%<, [,5;5;p$o&_%_%_%_%_%i+5;5;5;5;5;5;5;5;5;=._%_%_%_%_%},'.f-_%_%_%_%_%_%q&|,1,2,3,4,Y> )=_%_%_%_%_%K> n%5,U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%<% C=_%_%_%_%_%k* ", -" D%_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , 6,_%_%_%_%_%7,8,9,j>0,5;5;5;5;5;_,:&_%_%_%_%H%5;5;5;5;5;5;5;5;5;5;5;5;5;f#_%_%_%_%_%j= a,b,b,b,b,b,b,},_%_%_%_%_%9=b,b,b,c, d,e,e,^%f,_%_%_%_%_%e+e,e,e,e,e,e,e,e,e,%._%_%_%_%_%A;3=g,h,_%_%_%_%_%_%1>n= )=_%_%_%_%_%K> m%i,j,j,j,j,j,j,j,j,j,j,j,j,j,j,j,K= C=_%_%_%_%_%k* ", -" D%_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , 6,_%_%_%_%_%o= + k,l,m,n,o,p,q,r,C-_%_%_%_%H%e,e,e,e,e,e,e,e,e,e,e,e,e,f#_%_%_%_%_%j= s,b,b,b,b,b,b,},_%_%_%_%_%|*b,b,b,t, u,3=3=3==-_%_%_%_%_%0+3=3=3=3=3=3=3=3=3=%._%_%_%_%_%v,w,x,y,U%_%_%_%_%_%_%a;n= )=_%_%_%_%_%K> C=_%_%_%_%_%k* ", -" D%_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , 6,_%_%_%_%_%o= p=z,A,_%_%_%_%H%3=3=3=3=3=3=3=3=3=3=3=3=3=/#_%_%_%_%_%j= B,d;d;d;d;d;d;},_%_%_%_%_%|*d;d;d;C, D,E,J*J*=-_%_%_%_%_%0+J*J*J*J*J*J*F,G,H,I,_%_%_%_%_%D% j% -_&_%_%_%_%_%_%J,E% )=_%_%_%_%_%K> K,&%L,M,=% C=_%_%_%_%_%k* ", -" O=_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , 6,_%_%_%_%_%o= h=G%_%_%_%_%H%J*J*J*J*J*J*J*J*J*J*J*J*J*Y@_%_%_%_%_%j= N,d;d;d;d;d;d;},_%_%_%_%_%e;d;d;d;O, P,Q,J*J*=-_%_%_%_%_%6+J*J*J*J*J*E,R, C%_%_%_%_%_%D% 6,x%_%_%_%_%_%_%G%!= )=_%_%_%_%_%K> l*x%_%_%_%G%S, C=_%_%_%_%_%k* ", -" O=_%_%_%_%_%_%_%_%_% - n;b;_%_%_%_%_%_%_%_%:%S% !=_%_%_%_%_%_%_%_%_%c> A>_&_%_%_%_% , 6,_%_%_%_%_%o= h=G%_%_%_%_%H%^%^%^%^%^%^%^%^%^%^%^%^%^%N@_%_%_%_%_%j= T,U,U,U,U,U,U,9=_%_%_%_%_%e;U,U,U,V, W,X,^%g-=-_%_%_%_%_%}+^%^%^%^%^%X,W, C%_%_%_%_%_%D% j%6,x%_%_%_%_%_%_%J,l* )=_%_%_%_%_%K> T%_%_%_%_%_%6, C=_%_%_%_%_%k* ", -" O=_%_%_%_%_%_%_%_%_%m=Y, K=b;_%_%_%_%_%_%_%_%e=D=b>b>b>b>b>b>b>b>m=_%_%_%_%_%_%_%_%_%Z, A>_&_%_%_%_% , 6,_%_%_%_%_%o= h=G%_%_%_%_%H%g-g-g-g-g-g-g-g-g-g-g-g-g-N@_%_%_%_%_%j= `, ' ' ' ' ' '9=_%_%_%_%_%e; ' ' '.' +'@'g-g-=-_%_%_%_%_%}+g-g-g-g-g-#'k, C%_%_%_%_%_%D% j%(&x%_%_%_%_%_%_%G%k* )=_%_%_%_%_%K> q>_%_%_%_%_%L, C=_%_%_%_%_%k* ", -" T%_%_%_%_%_%_%_%_%_%_%$'Y, S%:%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%%' A>_&_%_%_%_%H- &'_%_%_%_%_%o= h=G%_%_%_%_%H%n-M;M;M;M;M;M;M;M;M;M;M;M;k@_%_%_%_%_%j= *' ' ' ' ' ' '9=_%_%_%_%_%T& ' ' '=' -';'M;6;L*_%_%_%_%_%(+M;M;M;M;M;>'6. C%_%_%_%_%_%D% j%,'e=_%_%_%_%_%_%l=l* )=_%_%_%_%_%Y; q>_%_%_%_%_%&' H-_%_%_%_%_%k* ", -" T%_%_%_%_%_%_%_%_%_%_%_%''=% ,_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%)' n%/;_%_%_%_%e=n; 9&!'_%_%_%_%_%o= m%1>_%_%_%_%_%A#M;M;M;M;M;M;M;M;M;M;M;M;k@_%_%_%_%_%j= ~'_,_,_,_,_,_,C;_%_%_%_%_%{' '_,_,]' ^'/'H*l+8=_%_%_%_%_%N@H*H*H*H*H*(' C%_%_%_%_%_%D% _'x%_%_%_%_%_%_%:']= ^=_%_%_%_%_%1>=% <%_%_%_%_%_%@;j% n=x%_%_%_%_%e=E% ", -" b>_%_%_%_%_%_%_%_%_%_%_%_%_; `>_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%g= =%a;_%_%_%_%_%<'6,)='='='='='='='='=['}'_&_%_%_%_%_%o= j%j=_%_%_%_%_%F>P }+6+6+6+6+6+6+6+6+6+6+h _%_%_%_%_%j= |'_,_,_,_,_,_,f._%_%_%_%_%_%N%t.=+1''='='='='=2'3'm t-_%_%_%_%_%8=x*6=6=6=6=6=4' C%_%_%_%_%_%D% j%_'/;_%_%_%_%_%_%:%5' 6'_%_%_%_%_%_%!'&%'='='='='='='='='='='='='='='='=5'S% 6,_%_%_%_%_%U%_;7''='='='='='='='=)=-,8'_%_%_%_%_%b;K, ", -" k*:'_%_%_%_%_%_%_%_%_%_%_%9'[% n=_&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%G%o% u-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%o= T%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%j= 0'a'^-^-^-^-^-^&=&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%b'p*n-n-n-n-n-c' C%_%_%_%_%_%D% j%&%/;_%_%_%_%_%_%J= ,_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%/;n% n%_&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%d'j% ", -" %%/;_%_%_%_%_%_%_%_%_%_%9'Y, @;_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%L, '=e=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%o= e'/;_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%j= f'g'^-^-^-^-^-_,h'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%%.6;6;6;6;6;6;i' C%_%_%_%_%_%D% j'e=_%_%_%_%_%!' k'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%/;n% u-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%j' ", -" l'/;_%_%_%_%_%_%_%_%_%m= o%C=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_&I*&& j%F%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%o= m'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%j= n'o'p*p*p*p*p*p*0%M*_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%p'U,N&N&N&N&N&N&q' C%_%_%_%_%_%D% M,/;_%_%_%_%!' Y,%'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%:'r' A>s'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%$'j% ", -" ,'U%_%_%_%_%_%_%_%b;t' y%d'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%e=0;S% [%J=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%o= &&I*_&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%j= u'v'w&w&w&w&w&w&w&6+t-_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%w'M=w&w&w&w&w&w&w&x' C%_%_%_%_%_%D% M,b;_%_%_%!' y%y'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%<'j% 5's'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%''o% ", -" M,:%_%_%_%_%_%x%,' m%z'G%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%y'7'j% S%A'G%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%o= && -9'_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%j= u;B'w&w&w&w&w&w&w&w&3$C'8=_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%1&D')*p*p*p*p*p*p*p*E'F' C%_%_%_%_%_%D% M,G'_%_%!' r'i%x%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%:%k* i,K>_&_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%l=<%m% ", -" H'I'_&_%_%J'*% K=,'F%K'Z,8'8'8'8'8'8'8'8'8'8'J'''`>'=S% r'L'O=@;)')')')')')')')')')'I*M'_%_%_%_%_%o= :=N'O'>-P'P'P'P'P'P'P'P'P'P'P'P'h'Q')')')'b> R'N&N&N&N&N&N&N&N&N&^-3$e )&P'S')')')')')')')'7,y=I=].x*^-^-^-^-^-^-^-^-^-T'U' )=)')')')')',' V')')'A' j%n%-,q>@;)')')')')')')')')')'F%I*0;m'_'K, &&^;W'i%)')')')')')')')')')'Z>D%g=K= ", -" ~='=,=j% 6,_%_%_%_%_%o= X'^-^-^-^-^-^-^-^-^-^-^-^-^-Y'-' Z'N&N&N&N&N&N&N&N&N&N&N&N&N&N&`' )^-^-^-^-^-^-^-^-^-^-^-^-^-.)u; ", -" 6,_%_%_%_%_%o= +)_,_,_,_,_,_,_,_,_,_,_,_,_,@)#) $)6;6;6;6;6;6;6;6;6;6;6;6;6;6;%) &)_,_,_,_,_,_,_,_,_,_,_,_,_,*) ", -" 6,_%_%_%_%_%o= =) ' ' ' ' ' ' ' ' ' ' ' ' '-);) >)n-n-n-n-n-n-n-n-n-n-n-n-n-n-,) ') ' ' ' ' ' ' ' ' ' ' ' ' ')) ", -" 6,_%_%_%_%_%o= !)U,U,U,U,U,U,U,U,U,U,U,U,U,~)u; {)n-n-n-n-n-n-n-n-n-n-n-n-n-n-]) ^)U,U,U,U,U,U,U,U,U,U,U,U,U,/) ", -" 6,_%_%_%_%_%o= D>()U,U,U,U,U,U,U,U,U,U,U,U,_)_# :)6=6=6=6=6=6=6=6=6=6=6=6=6=6=<) [)d;d;d;d;d;d;d;d;d;d;d;d;d;}) ", -" 6,_%_%_%_%_%o= #)|)d;d;d;d;d;d;d;d;d;d;d;d;1)6. 2)6=6=6=6=6=6=6=6=6=6=6=6=6=6=3) 4)b,b,b,b,b,b,b,b,b,b,b,b,b,5) ", -" 6,_%_%_%_%_%o= u;6)b,b,b,b,b,b,b,b,b,b,b,b,7) 8)H*H*H*H*H*H*H*H*H*H*H*H*H*H*9) 0)6%6%6%6%6%6%6%6%6%6%6%6%6%a) ", -" 6,_%_%_%_%_%o= + b)6%6%6%6%6%6%6%6%6%6%6%6%c) d)H*H*H*H*H*H*H*H*H*H*H*H*H*H*e) f)L;L;L;L;L;L;L;L;L;L;L;L;L;0) ", -" 6,_%_%_%_%_%o= g)L;L;L;L;L;L;L;L;L;L;L;L;h) i)M;M;M;M;M;M;M;M;M;M;M;M;M;M;x, j)k))*)*)*)*)*)*)*)*)*)*)*)*l) ", -" 6,_%_%_%_%_%o= m))*)*)*)*)*)*)*)*)*)*)*)*n) o)M;M;M;M;M;M;M;M;M;M;M;M;M;p)q) {>r)~>~>~>~>~>~>~>~>~>~>~>~>u' ", -" 6,_%_%_%_%_%o= s)~>~>~>~>~>~>~>~>~>~>~>~>t) u)g-g-g-g-g-g-g-g-g-g-g-g-g-v)w) x)y)D-D-D-D-D-D-D-D-D-D-D-;>+ ", -" 6,_%_%_%_%_%o= z)D-D-D-D-D-D-D-D-D-D-D-D-A) B)^%^%^%^%^%^%^%^%^%^%^%^%^%C)D) D>E)O;O;O;O;O;O;O;O;O;O;O;F) ", -" i,L,L,L,L,L,)= G)O;O;O;O;O;O;O;O;O;O;O;O;H) +'^%^%^%^%^%^%^%^%^%^%^%^%^%I)X; z*J)O;O;O;O;O;O;O;O;O;O;O;K) ", -" L)w;w;w;w;w;w;w;w;w;w;w;w;M) p=J*J*J*J*J*J*J*J*J*J*J*J*J*N)`@ x@O)w;w;w;w;w;w;w;w;w;w;w;P) ", -" x)Q)J&J&J&J&J&J&J&J&J&J&J&R) S)J*J*J*J*J*J*J*J*J*J*J*J*T) + U)J&J&J&J&J&J&J&J&J&J&J&V) ", -" W)X)2=2=2=2=2=2=2=2=2=2=2=Y) Z)3=3=3=3=3=3=3=3=3=3=3=3=`) !2=2=2=2=2=2=2=2=2=2=2=.! ", -" (*+!2=2=2=2=2=2=2=2=2=2=2=@! #!3=3=3=3=3=3=3=3=3=3=3=3=$! %!6-6-6-6-6-6-6-6-6-6-6-&! ", -" *!6-6-6-6-6-6-6-6-6-6-6-=! 1,e,e,e,e,e,e,e,e,e,e,e,e,-! ;!M=M=M=M=M=M=M=M=M=M=M=>! ", -" ,!M=M=M=M=M=M=M=M=M=M=M='! )!5;5;5;5;5;5;5;5;5;5;5;5;!! ~!(=(=(=(=(=(=(=(=(=(=(={! ", -" ]!(=(=(=(=(=(=(=(=(=(=(=7* ^!5;5;5;5;5;5;5;5;5;5;5;5;/! (!x*x*x*x*x*x*x*x*x*x*w*_! ", -" :!x*x*x*x*x*x*x*x*x*x*x! y!$&$&$&$&$&$&$&$&$&$&z! ", -" + A!A%A%A%A%A%A%A%A%A%B!+ C!G*G*G*G*G*G*G*G*G*G*G*D!E! F!A%A%A%A%A%A%A%A%A%A%B% ", -" G!0%0%0%0%0%0%0%0%0%H! x!----------------------I!{, J!0%0%0%0%0%0%0%0%0%0%K! ", -" L!0%0%0%0%0%0%0%0%0%M! Y>N!--------------------O!+ P!;%;%;%;%;%;%;%;%;%;%O$ ", -" Q!;%;%;%;%;%;%;%;%;%R! S!T!<&<&<&<&<&<&<&<&<&<&U! V!P$P$P$P$P$P$P$P$P$W!X! ", -" Y!P$P$P$P$P$P$P$P$P$Z! X;`!K-K-K-K-K-K-K-K-K-K- ~ .~E$E$E$E$E$E$E$E$E$+~v$ ", -" @~E$E$E$E$E$E$E$E$E$#~ F&$~K-K-K-K-K-K-K-K-K-K-%~ &~p$p$p$p$p$p$p$p$p$*~(* ", -" =~p$p$p$p$p$p$p$p$p$-~ `@;~$=$=$=$=$=$=$=$=$=$=>~ ,~a$a$a$a$a$a$a$a$a$'~ ", -" V!a$a$a$a$a$a$a$a$a$)~ !~$=$=$=$=$=$=$=$=$=$=~~ L@3$3$3$3$3$3$3$3$3${~ ", -" X!3$3$3$3$3$3$3$3$3$]~ ^~M&M&M&M&M&M&M&M&M&M&/~ + (~~$~$~$~$~$~$~$~$_~ ", -" (*(~~$~$~$~$~$~$~$~$:~ <~M&M&M&M&M&M&M&M&M&M&[~ }~ $ $ $ $ $ $ $ $T# ", -" |~ $ $ $ $ $ $ $ $.$ 1~0=0=0=0=0=0=0=0=0=0=2~ 3~ $ $ $ $ $ $ $ $4~ ", -" 5~K#K#K#K#K#K#K#K#6~ 7~0=0=0=0=0=0=0=0=0=0=8~ 9~K#K#K#K#K#K#K#K#0~ ", -" a~A#A#A#A#A#A#A#A#b~ c~J%J%J%J%J%J%J%J%J%J%d~ e~A#A#A#A#A#A#A#B#f~ ", -" g~f#f#f#f#f#f#f#f#h~ i~X=X=X=X=X=X=X=X=X=X=j~ k~f#f#f#f#f#f#f#q#l~ ", -" m~f#f#f#f#f#f#f#n~o~ p~X=X=X=X=X=X=X=X=X=X=q~ r~/#/#/#/#/#/#/#X@1+ ", -" s~/#/#/#/#/#/#/#t~u~ v~K&K&K&K&K&K&K&K&K&K&u* w~Y@Y@Y@Y@Y@Y@Y@x~+ ", -" y~Y@Y@Y@Y@Y@Y@Y@z~l~ A~K&K&K&K&K&K&K&K&K&K&X; B~N@N@N@N@N@N@N@C~ ", -" D~N@N@N@N@N@N@N@E~h# &-E-P*P*P*P*P*P*P*P*F~ G~k@k@k@k@k@k@k@H~ ", -" I~k@k@k@k@k@k@k@J~1+ 2-Q-P*P*P*P*P*P*P*P*R- K~{@{@{@{@{@{@{@L~ ", -" 6#M~{@{@{@{@{@{@N~T. O~P~;-;-;-;-;-;-;-;-Q~ R~B+B+B+B+B+B+B+S~ ", -" T.T~B+B+B+B+B+B+U~+ +*V~y&y&y&y&y&y&y&y&W~ X~l+l+l+l+l+l+l+Y~ ", -" _#Z~l+l+l+l+l+l+`~ `@_-y&y&y&y&y&y&y&y& { .{i+i+i+i+i+i+i++{ ", -" @{i+i+i+i+i+i+#{ ${'*'*'*'*'*'*'*'*%{ &{i+i+i+i+i+i+i+*{ ", -" ={e+e+e+e+e+e+-{ T='*'*'*'*'*'*'*'*+- f+e+e+e+e+e+e+e+;{ ", -" >{0+0+0+0+0+0+,{ '{s&s&s&s&s&s&s&s&){ !{0+0+0+0+0+0+c+~{ ", -" {{6+6+6+6+6+6+]{ ^{s&s&s&s&s&s&s&s&/{ *{6+6+6+6+6+6+({ ", -" _{6+6+6+6+6+6+:{ ==L&L&L&L&L&L&L&L&<{ [{}+}+}+}+}+}+}{ ", -" |{}+}+}+}+}+}+1{ 2{f&f&f&f&f&f&f&f&3{ @+(+(+(+(+(+(+4{ ", -" 5{6{(+(+(+(+(+7{ 8{f&f&f&f&f&f&f&f&9{ 0{~+~+~+~+~+~+a{ ", -" 4+b{~+~+~+~+~+c{ d{g*g*g*g*g*g*g*g*W* e{f{'+'+'+'+'+g{ ", -" I.h{'+'+'+'+'+i{ b*g*g*g*g*g*g*g*g*j{ I.k{=+=+=+=+=+l{ ", -" + m{=+=+=+=+=+n{ o{g%g%g%g%g%g%g%g%>= T.3'$+$+$+$+$+p{ ", -" q{$+$+$+$+$+r{ s{&*************t{6& ~{u{`.`.`.`.`.v{ ", -" w{`.`.`.`.`.x{ y{,*************z{)- P.A{W.W.W.W.W.B{ ", -" C{W.W.W.W.W.D{ D&V&S&S&S&S&S&S&E{F& 6.F{W.W.W.W.G{e{ ", -" H{N.N.N.N.N.I{ @&J{S&S&S&S&S&S&K{k& L{N.N.N.N.S.T. ", -" M{G.G.G.G.G.N{ `@O{g&g&g&g&g&g&P{+ Q{G.G.G.G.R{D ", -" S{B.B.B.B.B.T{ U{g&g&g&g&g&g&V{ W{B.B.B.B.X{ ", -" Y{Z{B.B.B.B.`{ ]b&b&b&b&b&b&.] +]w.w.w.w.@] ", -" #]$]w.w.w.w.e{ %]b&b&b&b&b&b&&] *]t.t.t.t.=] ", -" ~{-]t.t.t.t.D ;]-&-&-&-&-&-&>] ,]o.o.o.o.'] ", -" )]o.o.o.!] ~]W%W%W%W%W%W%{] ]]j.j.j.j.^] ", -" /]j.j.j.(] _]W%W%W%W%W%W%:] <]f.f.f.f.[] ", -" }]f.f.f.|] 1]K%K%K%K%K%K%2] 3]0.0.0.4]5] ", -" 6]0.0.0.7] 8]K%K%K%K%K%K%9] 0]4.4.4.a]7. ", -" b]4.4.4.c] d]s%s%s%s%s%s%v% e]}.}.}.f]K ", -" g]}.}.}.h] `$s%s%s%s%s%i]j] k]}.}.}.l]+ ", -" m]:.:.:.n] }&d%d%d%d%d%o]p] q]:.:.:.r] ", -" s]].].].t] u]#%#%#%#%#%v]4% s]].].].t] ", -" b.'.'.'.w] x]#%#%#%#%#%y]@& z]A]'.'.B] ", -" + C]'.'.D] @&!%!%!%!%!%E]N+ F]G]=.=.H] ", -" I]=.=.J] + K]!%!%!%!%L] M]N]%.%.O] ", -" P]%.%.Q] R].%.%.%.%S] b.T]` ` U] ", -" V]` ` W] X]T$T$T$T$Y] 3.Z]U `] ^ ", -" .^U U +^ @^T$T$T$T$#^ P.$^P %^&^ ", -" *^P P =^ -^J$J$J$J$;^ + >^I ,^~{ ", -" '^I I Z M$J$J$J$J$)^ !^F ~^ ", -" {^F F ]^ ^^y$y$y$y$/^ (^z _^ ", -" :^z z <^ [^y$y$y$y$}^ |^z 1^ ", -" 5 2^u 3^ 4^k$k$k$k$5^ 6^u 7^ ", -" 8^9^r &^ 0^d$d$d$d$a^ b^r o ", -" # c^d^e^ f^d$d$d$g^h^ i^m j^ ", -" + k^l^2 m^6$6$6$8$n^ o^h p^ ", -" O%q^3. r^6$6$6$s^t^ u^e k ", -" v^w^x^ y^[$[$[$z^A^ B^%=e^ ", -" C^D^} L#[$[$[$E^o# F^G^+ ", -" F^H^. A^I^^$^$J^ K^| ", -" L^M^+ @&N^^$^$O^ P^Q^ ", -" R^S^ 6@T^>$>$U^ V^W^ ", -" 8 X^ o#Y^#$#$Z^ `^ / ", -" e^./ + +/#$#$@/ #/, ", -" } $/ %/W#W#&/ */=/ ", -" -/ ;/W#W#>/ ,/'/ ", -" )/ H#N#N#!/ ~/{/ ", -" % ]/N#N#^/ # } ", -" //E#E#(/ ", -" _/u#u#:/ ", -"