Compare commits

..
Author SHA1 Message Date
Tyler Blount 6b7fc0b6a3 Don't reset target restrictions during table load
Prevents an issue with load order causing target restrictions to be reset.
2020-05-20 14:45:24 -06:00
Tyler Blount 2e4bef0d09 Remove unneeded code and some style changes 2020-05-20 12:25:13 -06:00
Tyler Blount 172952cb0f Correctly implement fixes from #73 2020-05-20 12:25:13 -06:00
Tyler Blount 72c27bdbe8 CI and Lock fixes 2020-05-20 12:25:13 -06:00
Tyler Blount bd4de16007 Use correct comparison 2020-05-20 12:25:13 -06:00
Tyler Blount 2e560f2ddb Fix some CI errors 2020-05-20 12:25:12 -06:00
Tyler Blount d35d3d25f8 Finally fix no dumbfire
also some miscellaneous changes
2020-05-20 12:25:12 -06:00
Tyler Blount 2d5111f14b Perhaps this works? 2020-05-20 12:25:12 -06:00
Tyler Blount d95754d6b4 No Dumbfire fix
Another fix for MLMs associated with the No Dumbfire flag.
2020-05-20 12:25:12 -06:00
Tyler Blount 5e3d4c6cfd More fixes
Contains changes related to failed CI builds and feedback.
2020-05-20 12:25:12 -06:00
Tyler Blount deca820c9e Lost fixes
These were lost during a rebase at one point. Will leave this commit as separate to avoid issues in the future.
2020-05-20 12:25:12 -06:00
Swifty 21c298271b Initial commit of multilock missile features. 2020-05-20 12:25:11 -06:00
1038 changed files with 26806 additions and 83455 deletions

No files matched your search

+4 -5
View File
@@ -3,18 +3,17 @@ Language: Cpp
Standard: Cpp11
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowAllArgumentsOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
+5 -6
View File
@@ -1,22 +1,20 @@
---
Checks: "-*,\
modernize-*,\
-modernize-avoid-c-arrays,\
-modernize-make-unique,\
-modernize-raw-string-literal,\
-modernize-use-trailing-return-type,\
-modernize-use-using,\
-modernize-make-unique,\
-modernize-use-trailing-return-type,\
-modernize-avoid-c-arrays,\
performance-*,\
-performance-type-promotion-in-math-fn,\
misc-*,\
-misc-macro-parentheses,\
-misc-misplaced-widening-cast,\
-misc-non-private-member-variables-in-classes,\
-misc-static-assert,\
-misc-unused-parameters,\
-misc-non-private-member-variables-in-classes,\
readability-*,\
-readability-avoid-const-params-in-decls,\
-readability-else-after-return,\
-readability-function-size,\
-readability-identifier-naming,\
-readability-implicit-bool-conversion,\
@@ -26,6 +24,7 @@ readability-*,\
-readability-named-parameter,\
-readability-qualified-auto,\
-readability-uppercase-literal-suffix,\
-readability-else-after-return,\
"
WarningsAsErrors: ''
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
-4
View File
@@ -9,7 +9,3 @@ indent_style = tab
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.sh]
indent_style = space
indent_size = 4
-8
View File
@@ -1,8 +0,0 @@
cmake/ @asarium
code/executor/ @asarium
code/scpui/ @asarium
code/scripting/ @asarium
-210
View File
@@ -1,210 +0,0 @@
name: Build Nightly package
on:
push:
tags:
- 'nightly_*'
env:
QT_VERSION: 5.12.9
jobs:
build_linux:
strategy:
matrix:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-a8ca321
steps:
# - name: Cache Qt
# id: cache-qt-lin
# uses: actions/cache@v1
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt
# uses: jurplel/install-qt-action@v2
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: |
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Generate AppImage
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
linux_zip:
name: Build Linux distribution zip
needs: build_linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: '0'
- name: Download Release builds
uses: actions/download-artifact@v1
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: linux-FastDebug
path: builds
- name: Create Distribution package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
- name: Upload result package
working-directory: ./builds
env:
INDIEGAMES_USER: ${{ secrets.INDIEGAMES_USER }}
INDIEGAMES_SSHPASS: ${{ secrets.INDIEGAMES_PASSWORD }}
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh nightly
build_windows:
strategy:
matrix:
configuration: [FastDebug, Release]
arch: [Win32, x64]
simd: [SSE2]
name: Windows
runs-on: windows-2019
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
# - name: Cache Qt
# id: cache-qt-win
# uses: actions/cache@v1
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-${{ matrix.arch }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt (32 bit)
# uses: jurplel/install-qt-action@v2
# if: ${{ matrix.arch == 'Win32' }}
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# arch: win32_msvc2017
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
# - name: Install Qt (64 bit)
# uses: jurplel/install-qt-action@v2
# if: ${{ matrix.arch == 'x64' }}
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCHITECTURE: ${{ matrix.arch }}
SIMD: ${{ matrix.simd }}
shell: bash
run: |
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
shell: bash
run: |
cmake --build . --config "$CONFIGURATION" --target INSTALL -- /verbosity:minimal
ls -alR "$(pwd)/install"
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
windows_zip:
name: Build Windows distribution zip
needs: build_windows
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [Win32, x64]
simd: [SSE2]
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: '0'
- name: Download Release builds
uses: actions/download-artifact@v1
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Create Distribution package
working-directory: ./builds
shell: bash
env:
ARCH: ${{ matrix.arch }}
SIMD: ${{ matrix.simd }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
- name: Upload result package
working-directory: ./builds
shell: bash
env:
INDIEGAMES_USER: ${{ secrets.INDIEGAMES_USER }}
INDIEGAMES_SSHPASS: ${{ secrets.INDIEGAMES_PASSWORD }}
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh nightly
-263
View File
@@ -1,263 +0,0 @@
name: Build Release package
on:
push:
tags:
- 'release_*'
env:
QT_VERSION: 5.12.9
jobs:
create_release:
name: Create GitHub release
runs-on: ubuntu-latest
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Store upload URL
run: |
echo -n "${{ steps.create_release.outputs.upload_url }}" > upload_url
- name: Persist upload URL
uses: actions/upload-artifact@v2
with:
name: upload_url
path: ${{ github.workspace }}/upload_url
build_linux:
strategy:
matrix:
configuration: [FastDebug, Release]
name: Linux
needs: create_release
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-a8ca321
steps:
# - name: Cache Qt
# id: cache-qt-lin
# uses: actions/cache@v1
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt
# uses: jurplel/install-qt-action@v2
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: |
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Generate AppImage
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
linux_zip:
name: Build Linux distribution zip
needs: build_linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: '0'
- name: Download upload URL
uses: actions/download-artifact@v1
with:
name: upload_url
path: .
- name: Extract upload URL
id: extractUploadUrl
run: echo "::set-output name=upload_url::$(cat upload_url)"
- name: Download Release builds
uses: actions/download-artifact@v1
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: linux-FastDebug
path: builds
- name: Create Distribution package
id: generate_package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
- name: Upload result package
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.extractUploadUrl.outputs.upload_url }}
asset_path: ${{ steps.generate_package.outputs.package_path }}
asset_name: ${{ steps.generate_package.outputs.package_name }}
asset_content_type: ${{ steps.generate_package.outputs.package_mime }}
build_windows:
strategy:
matrix:
configuration: [FastDebug, Release]
arch: [Win32, x64]
simd: [SSE2, AVX]
needs: create_release
name: Windows
runs-on: windows-2019
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
# - name: Cache Qt
# id: cache-qt-win
# uses: actions/cache@v1
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-${{ matrix.arch }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt (32 bit)
# uses: jurplel/install-qt-action@v2
# if: ${{ matrix.arch == 'Win32' }}
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# arch: win32_msvc2017
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
# - name: Install Qt (64 bit)
# uses: jurplel/install-qt-action@v2
# if: ${{ matrix.arch == 'x64' }}
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCHITECTURE: ${{ matrix.arch }}
SIMD: ${{ matrix.simd }}
shell: bash
run: |
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
shell: bash
run: |
cmake --build . --config "$CONFIGURATION" --target INSTALL -- /verbosity:minimal
ls -alR "$(pwd)/install"
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
windows_zip:
name: Build Windows distribution zip
needs: build_windows
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [Win32, x64]
simd: [SSE2, AVX]
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: '0'
- name: Download upload URL
uses: actions/download-artifact@v1
with:
name: upload_url
path: .
- name: Extract upload URL
id: extractUploadUrl
run: echo "::set-output name=upload_url::$(cat upload_url)"
- name: Download Release builds
uses: actions/download-artifact@v1
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Create Distribution package
id: generate_package
working-directory: ./builds
shell: bash
env:
ARCH: ${{ matrix.arch }}
SIMD: ${{ matrix.simd }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
- name: Upload result package
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.extractUploadUrl.outputs.upload_url }}
asset_path: ${{ steps.generate_package.outputs.package_path }}
asset_name: ${{ steps.generate_package.outputs.package_name }}
asset_content_type: ${{ steps.generate_package.outputs.package_mime }}
- name: Upload debug symbols
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.extractUploadUrl.outputs.upload_url }}
asset_path: ${{ steps.generate_package.outputs.debug_path }}
asset_name: ${{ steps.generate_package.outputs.debug_name }}
asset_content_type: ${{ steps.generate_package.outputs.debug_mime }}
-224
View File
@@ -1,224 +0,0 @@
name: Build Test package
on:
push:
branches:
- 'test/*'
env:
QT_VERSION: 5.12.9
jobs:
build_linux:
strategy:
matrix:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-a8ca321
steps:
- name: Cache Qt
id: cache-qt-lin
uses: actions/cache@v1
with:
path: ${{ github.workspace }}/../Qt
key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: ${{ env.QT_VERSION }}
dir: ${{ github.workspace }}/..
cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Set up test version
shell: bash
run: |
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: |
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Generate AppImage
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
linux_zip:
name: Build Linux distribution zip
needs: build_linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
steps:
- uses: actions/checkout@v2
name: Checkout
with:
submodules: true
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v1
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: linux-FastDebug
path: builds
- name: Create Distribution package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
- name: Upload result package
working-directory: ./builds
env:
INDIEGAMES_USER: ${{ secrets.INDIEGAMES_USER }}
INDIEGAMES_SSHPASS: ${{ secrets.INDIEGAMES_PASSWORD }}
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh test
build_windows:
strategy:
matrix:
configuration: [FastDebug, Release]
arch: [Win32, x64]
simd: [SSE2]
name: Windows
runs-on: windows-2019
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Set up test version
shell: bash
run: |
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
- name: Cache Qt
id: cache-qt-win
uses: actions/cache@v1
with:
path: ${{ github.workspace }}/../Qt
key: ${{ runner.os }}-${{ matrix.arch }}-QtCache-${{ env.QT_VERSION }}
- name: Install Qt (32 bit)
uses: jurplel/install-qt-action@v2
if: ${{ matrix.arch == 'Win32' }}
with:
version: ${{ env.QT_VERSION }}
dir: ${{ github.workspace }}/..
arch: win32_msvc2017
cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
aqtversion: ==0.8
- name: Install Qt (64 bit)
uses: jurplel/install-qt-action@v2
if: ${{ matrix.arch == 'x64' }}
with:
version: ${{ env.QT_VERSION }}
dir: ${{ github.workspace }}/..
arch: win64_msvc2017_64
cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
aqtversion: ==0.8
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCHITECTURE: ${{ matrix.arch }}
SIMD: ${{ matrix.simd }}
shell: bash
run: |
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=ON -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
shell: bash
run: |
cmake --build . --config "$CONFIGURATION" --target INSTALL -- /verbosity:minimal
ls -alR "$(pwd)/install"
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
windows_zip:
name: Build Windows distribution zip
needs: build_windows
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [Win32, x64]
simd: [SSE2]
steps:
- uses: actions/checkout@v2
name: Checkout
with:
submodules: true
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v1
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Create Distribution package
working-directory: ./builds
shell: bash
env:
ARCH: ${{ matrix.arch }}
SIMD: ${{ matrix.simd }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
- name: Upload result package
working-directory: ./builds
shell: bash
env:
INDIEGAMES_USER: ${{ secrets.INDIEGAMES_USER }}
INDIEGAMES_SSHPASS: ${{ secrets.INDIEGAMES_PASSWORD }}
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh test
+50 -72
View File
@@ -2,72 +2,76 @@ name: Check a pull request
on: [pull_request]
env:
QT_VERSION: 5.12.9
jobs:
build_linux:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [gcc-5, gcc-10, clang-9]
cmake_options: [""]
include:
# Also include configurations that check if the code compiles without the graphics backends
- configuration: Debug
compiler: gcc-10
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
- configuration: Release
compiler: gcc-10
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
compiler: [gcc-5, gcc-9, clang-4.0]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-e977d36
runs-on: ubuntu-16.04
steps:
# - name: Cache Qt
# id: cache-qt-lin
# uses: actions/cache@v1
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt
# uses: jurplel/install-qt-action@v2
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
# setup-python: 'false'
- name: Prepare Environment
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo add-apt-repository ppa:beineri/opt-qt571-xenial
sudo add-apt-repository ppa:msulikowski/valgrind # For fixing a bug with valgrind 3.11 which does not recognize the rdrand instruction
sudo apt-get -yq update
sudo apt-get -yq install cmake ninja-build libopenal-dev libreadline6-dev libpng12-dev libjpeg62-dev liblua5.1-0-dev libjansson-dev libsdl2-dev libfreetype6-dev valgrind qt57base g++-5 g++-9 clang-4.0 clang-tidy-4.0 libc++-dev libc++abi-dev
# Fix a header bug present in ubuntu...
sudo ln -s /usr/include/libcxxabi/__cxxabi_config.h /usr/include/c++/v1/__cxxabi_config.h
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
run: |
if [ "$COMPILER" = "gcc-5" ]; then
export CC=gcc-5
export CXX=g++-5
fi
if [ "$COMPILER" = "gcc-9" ]; then
export CC=gcc-9
export CXX=g++-9
fi
if [ "$COMPILER" = "clang-4.0" ]; then
export CC=clang-4.0
export CXX=clang++-4.0
fi
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
if [[ "$CC" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
fi
mkdir build
cd build
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON ..
- name: Compile
working-directory: ./build
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
run: ninja -k 20 all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Run Clang Tidy
# Clang-tidy reuses the precompiled headers so this only makes sense for the clang compilers
if: startsWith(matrix.compiler, 'clang-')
run: $GITHUB_WORKSPACE/ci/linux/clang_tidy.sh ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
- name: Process clang-tidy warnings
if: startsWith(matrix.compiler, 'clang-')
uses: asarium/clang-tidy-action@v1
with:
fixesFile: clang-fixes.yaml
run: |
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$GITHUB_WORKSPACE/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
build_windows:
strategy:
matrix:
@@ -83,31 +87,6 @@ jobs:
name: Checkout
with:
submodules: true
# - name: Cache Qt
# id: cache-qt-win
# uses: actions/cache@v1
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-${{ matrix.arch }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt (32 bit)
# uses: jurplel/install-qt-action@v2
# if: ${{ matrix.compiler == 'MSVC' && matrix.arch == 'Win32' }}
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# arch: win32_msvc2017
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
# - name: Install Qt (64 bit)
# uses: jurplel/install-qt-action@v2
# if: ${{ matrix.compiler == 'MSVC' && matrix.arch == 'x64' }}
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -123,8 +102,7 @@ jobs:
-DFSO_BUILD_FRED2="OFF" -DCMAKE_BUILD_TYPE=$CONFIGURATION -G "Ninja" ..
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" \
-DFSO_BUILD_QTFRED=OFF -T "v142" -A "$ARCHITECTURE" ..
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" -T "v142" -A "$ARCHITECTURE" ..
fi
- name: Compile
working-directory: ./build
+28 -2
View File
@@ -86,6 +86,19 @@ matrix:
packages:
- g++-9
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCLANG_USE_LIBCXX=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- clang-4.0
- libc++-dev
- libc++abi-dev
- os: linux
env: CONFIGURATION="Debug" CC=clang-9 CXX=clang++-9 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
@@ -103,7 +116,7 @@ matrix:
env: CONFIGURATION="Debug"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141 CMAKE_GENERATOR="Visual Studio 15 2017"
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
@@ -127,6 +140,19 @@ matrix:
packages:
- g++-9
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCLANG_USE_LIBCXX=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- clang-4.0
- libc++-dev
- libc++abi-dev
- os: linux
env: CONFIGURATION="Release" CC=clang-9 CXX=clang++-9 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
@@ -144,7 +170,7 @@ matrix:
env: CONFIGURATION="Release"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141 CMAKE_GENERATOR="Visual Studio 15 2017"
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
# There is a GCC compiler bug with MinGW that causes compilation failures on Windows at the moment
+3 -19
View File
@@ -8,7 +8,6 @@ if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
endif()
include(cmake/util.cmake)
include(cmake/embed_file.cmake)
# Set a few policies
set_policy(CMP0051 NEW)
@@ -44,14 +43,9 @@ PROJECT(FS2_Open)
find_program(CCACHE_PROGRAM ccache)
# Currently only GCC support ccache properly without generating additional warnings
if(CCACHE_PROGRAM AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(NOT CMAKE_C_COMPILER_LAUNCHER)
message(STATUS "Using ccache for C compilation: ${CCACHE_PROGRAM}")
SET(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
endif()
if(NOT CMAKE_CXX_COMPILER_LAUNCHER)
message(STATUS "Using ccache for C++ compilation: ${CCACHE_PROGRAM}")
SET(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
endif()
message(STATUS "Using ccache for compilation: ${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_PROGRAM}")
endif()
IF(CMAKE_CROSSCOMPILING)
@@ -127,10 +121,6 @@ option(FSO_RELEASE_LOGGING "Enable logging output for release builds" OFF)
OPTION(FSO_BUILD_WITH_FFMPEG "Enable the usage of FFmpeg for sound and custscenes" ON)
OPTION(FSO_BUILD_WITH_OPENGL "Enable compilation of the OpenGL renderer" ON)
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" ON)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
@@ -141,8 +131,6 @@ mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
mark_as_advanced(FORCE ENABLE_COTIRE)
mark_as_advanced(FORCE FSO_RELEASE_LOGGING)
mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL)
mark_as_advanced(FORCE FSO_BUILD_WITH_VULKAN)
# Include cotire file from https://github.com/sakra/cotire/
include(cotire)
@@ -169,8 +157,6 @@ ADD_SUBDIRECTORY(tools)
ADD_SUBDIRECTORY(lib)
ADD_SUBDIRECTORY(parsers)
ADD_SUBDIRECTORY(code)
ADD_SUBDIRECTORY(freespace2)
@@ -219,5 +205,3 @@ message(STATUS "Building qtFRED: ${FSO_BUILD_QTFRED}")
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
message(STATUS "Release logging: ${FSO_RELEASE_LOGGING}")
message(STATUS "With FFmpeg: ${FSO_BUILD_WITH_FFMPEG}")
message(STATUS "With OpenGL: ${FSO_BUILD_WITH_OPENGL}")
message(STATUS "With Vulkan: ${FSO_BUILD_WITH_VULKAN}")
-7
View File
@@ -12,11 +12,4 @@ Modifications by members of the FreeSpace Source Code Project are
released under whatever terms the individual authors choose, but the
above notice continues to apply to all fs2_open code.
All modifications made on or after November 1, 2020, shall be released under
the terms within [Unlicense](Unlicense.md). Modifications made before said date are released
under the previous terms with the exception of modifications made by members
of the FreeSpace Source Code Project that opt-in to the terms of Unlicense. Additionally,
a list of contributors who have opted in to the Unlicense terms can be found
in [**Licensing**](https://github.com/scp-fs2open/fs2open.github.com/wiki/Licensing).
See [**Licensing**](https://github.com/scp-fs2open/fs2open.github.com/wiki/Licensing) for more information.
-24
View File
@@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to [**Unlicense**](https://unlicense.org).
+2 -2
View File
@@ -8,11 +8,11 @@ environment:
matrix:
- BuildID: 0
CMAKE_GENERATOR: Visual Studio 14 2015
PlatformToolset: v140
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9\msvc2015
- BuildID: 1
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
PlatformToolset: v140
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9\msvc2015_64
before_build:
- git submodule update --init --recursive
+48 -48
View File
@@ -9,56 +9,56 @@ class BuildConfig {
}
$NightlyConfigurations = @(
# [BuildConfig]@{
# Generator="Visual Studio 14 2015 Win64";
# PackageType="Win64";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015_64";
# SourcePackage=$false;
# },
# [BuildConfig]@{
# Generator="Visual Studio 14 2015";
# PackageType="Win32";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015";
# SourcePackage=$false;
# }
[BuildConfig]@{
Generator="Visual Studio 14 2015 Win64";
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
},
[BuildConfig]@{
Generator="Visual Studio 14 2015";
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$false;
}
)
$ReleaseConfigurations = @(
# [BuildConfig]@{
# Generator="Visual Studio 14 2015";
# PackageType="Win32";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015";
# SourcePackage=$true;
# }
# [BuildConfig]@{
# Generator="Visual Studio 14 2015";
# PackageType="Win32-AVX";
# Toolset="v140";
# SimdType="AVX";
# QtDir="C:\Qt\5.9\msvc2015";
# SourcePackage=$false;
# }
# [BuildConfig]@{
# Generator="Visual Studio 14 2015 Win64";
# PackageType="Win64";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015_64";
# SourcePackage=$false;
# }
# [BuildConfig]@{
# Generator="Visual Studio 14 2015 Win64";
# PackageType="Win64-AVX";
# Toolset="v140";
# SimdType="AVX";
# QtDir="C:\Qt\5.9\msvc2015_64";
# SourcePackage=$false;
# }
[BuildConfig]@{
Generator="Visual Studio 14 2015";
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$true;
}
[BuildConfig]@{
Generator="Visual Studio 14 2015";
PackageType="Win32-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$false;
}
[BuildConfig]@{
Generator="Visual Studio 14 2015 Win64";
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
}
[BuildConfig]@{
Generator="Visual Studio 14 2015 Win64";
PackageType="Win64-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
}
)
$BuildConfigurations = $null
-23
View File
@@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -e
SCRIPT=$(readlink -f "$0")
HERE=$(dirname "$SCRIPT")
COMMIT_RANGE=$1..$2
if ! git rev-list $COMMIT_RANGE 2>&1 >/dev/null; then
echo "\$COMMIT_RANGE ($COMMIT_RANGE) is not valid for this build (probably caused by a rebase)."
exit 0
fi
# In order to get a proper diff without irrelevant changes, we need to determine where we branched off from the base
# branch
BASE_COMMIT=$(git merge-base $1 $2)
echo "Running clang-tidy on changed files"
git diff -U0 --no-color "$BASE_COMMIT..$2" | \
$HERE/clang-tidy-diff.py -path "$(pwd)/build" -p1 \
-regex '(code(?!\/graphics\/shaders\/compiled)|freespace2|qtfred|test|build|tools)\/.*\.(cpp|h)' \
-clang-tidy-binary /usr/bin/clang-tidy-9 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/env bash
if [ "$COMPILER" = "gcc-5" ]; then
export CC=gcc-5
export CXX=g++-5
fi
if [ "$COMPILER" = "gcc-10" ]; then
export CC=gcc-10
export CXX=g++-10
fi
if [ "$COMPILER" = "clang-9" ]; then
# Work around bug in clang that uses the wrong installation directory: https://bugs.llvm.org/show_bug.cgi?id=47460
export CC=$(readlink -f $(which clang-9))
export CXX=$(readlink -f $(which clang++-9))
fi
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CMAKE_OPTIONS="$JOB_CMAKE_OPTIONS"
if [[ "$COMPILER" =~ ^clang.*$ ]]; then
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCLANG_USE_LIBCXX=ON"
fi
mkdir build
cd build
export CXXFLAGS
export CFLAGS
export LD_LIBRARY_PATH
cmake -G Ninja -DFSO_FATAL_WARNINGS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON $CMAKE_OPTIONS \
-DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_BUILD_APPIMAGE=ON -DCMAKE_BUILD_TYPE=$CONFIGURATION \
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=OFF ..
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env bash
SCRIPT=$(readlink -f "$0")
HERE=$(dirname "$SCRIPT")
OS="$1"
source $HERE/dist_functions.sh
if [ "$OS" = "Linux" ]; then
tar -cvzf "$(get_package_name)-builds-Linux.tar.gz" *
echo "::set-output name=package_path::$(pwd)/$(get_package_name)-builds-Linux.tar.gz"
echo "::set-output name=package_name::$(get_package_name)-builds-Linux.tar.gz"
echo "::set-output name=package_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Linux.tar.gz")"
elif [ "$OS" = "Windows" ]; then
7z a -xr'!*.pdb' "$(get_package_name)-builds-$ARCH-$SIMD.zip" "*"
echo "::set-output name=package_path::$(pwd)/$(get_package_name)-builds-$ARCH-$SIMD.zip"
echo "::set-output name=package_name::$(get_package_name)-builds-$ARCH-$SIMD.zip"
echo "::set-output name=package_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-$ARCH-$SIMD.zip")"
7z a "$(get_package_name)-debug-$ARCH-$SIMD.7z" "*.pdb"
echo "::set-output name=debug_path::$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z"
echo "::set-output name=debug_name::$(get_package_name)-debug-$ARCH-$SIMD.7z"
echo "::set-output name=debug_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")"
else
echo "Invalid OS: $OS"
fi
-70
View File
@@ -1,70 +0,0 @@
function get_package_name() {
if git describe --match 'nightly_*' --exact-match 2>/dev/null >/dev/null; then
echo -n "$(git describe --match "nightly_*" --exact-match)"
return
fi
if git describe --match 'release_*' --exact-match 2>/dev/null >/dev/null; then
echo -n "$(git describe --match "release_*" --exact-match | sed 's/release_/fs2_open_/i')"
return
fi
if [[ "$(git branch --show-current)" =~ ^test\/(.*)$ ]]; then
echo -n "test_${BASH_REMATCH[1]}"
return
fi
echo "unknown_config"
}
function get_version_name() {
if git describe --match 'nightly_*' --exact-match 2>/dev/null >/dev/null; then
local tag_name=$(git describe --match "nightly_*" --exact-match)
# Use the bash regex matching for getting the relevant part of the tag name
[[ $tag_name =~ ^nightly_(.*)$ ]]
echo -n "${BASH_REMATCH[1]}"
return
fi
if git describe --match 'release_*' --exact-match 2>/dev/null >/dev/null; then
local tag_name=$(git describe --match "release_*" --exact-match)
# Use the bash regex matching for getting the relevant part of the tag name
[[ $tag_name =~ ^release_(.*)$ ]]
echo -n "${BASH_REMATCH[1]}"
return
fi
if [[ "$(git branch --show-current)" =~ ^test\/(.*)$ ]]; then
echo -n "${BASH_REMATCH[1]}"
return
fi
echo "unknown_config"
}
function upload_files_to_sftp() {
# We need empty glob patterns to "disappear" in the for loop below since this will be run for different configurations
# where it may be possible that some of the file patterns will not be present
shopt -s nullglob
echo "cd $2/" > sftp_batch
echo "mkdir $(get_version_name)" >> sftp_batch
# Create directory but do not cause an error if it already exists
sshpass -e sftp -oBatchMode=no -o "StrictHostKeyChecking no" -b sftp_batch $1 || true
echo "cd $2/$(get_version_name)/" > sftp_batch
for file in *.tar.gz *.7z *.zip; do
echo "put $file" >> sftp_batch
done
echo "bye" >> sftp_batch
sshpass -e sftp -oBatchMode=no -o "StrictHostKeyChecking no" -b sftp_batch $1
rm sftp_batch
}
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
INSTALL_FOLDER=$1
# Install Freespace2 targets
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_FOLDER -DCOMPONENT=Unspecified -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_FOLDER -DCOMPONENT=Freespace2 -P cmake_install.cmake
# We need to be a bit creative for determining the AppImage name since we don't want to hard-code the name
FILENAME="$(find $INSTALL_FOLDER/bin -name 'fs2_open_*' -type f -printf "%f\n").AppImage"
appimagetool -n $INSTALL_FOLDER "$INSTALL_FOLDER/$FILENAME"
chmod +x "$INSTALL_FOLDER/$FILENAME"
ls -al $INSTALL_FOLDER
-13
View File
@@ -1,13 +0,0 @@
#!/usr/bin/env bash
SCRIPT=$(readlink -f "$0")
HERE=$(dirname "$SCRIPT")
export LD_LIBRARY_PATH=$(pwd)/bin/lib:$LD_LIBRARY_PATH
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$HERE/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
-21
View File
@@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -e
UPLOAD_TYPE=$1
SCRIPT=$(readlink -f "$0")
HERE=$(dirname "$SCRIPT")
source $HERE/dist_functions.sh
if [ "$UPLOAD_TYPE" = "nightly" ]; then
SSHPASS=$INDIEGAMES_SSHPASS upload_files_to_sftp "$INDIEGAMES_USER@scp.indiegames.us" "public_html/builds/nightly"
SSHPASS=$DATACORDER_SSHPASS upload_files_to_sftp "$DATACORDER_USER@porphyrion.feralhosting.com" "www/datacorder.porphyrion.feralhosting.com/public_html/builds/nightly"
elif [ "$UPLOAD_TYPE" = "test" ]; then
SSHPASS=$DATACORDER_SSHPASS upload_files_to_sftp "$DATACORDER_USER@porphyrion.feralhosting.com" "www/datacorder.porphyrion.feralhosting.com/public_html/builds/test"
else
echo "Unknown upload type $UPLOAD_TYPE"
exit 1
fi
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
#
#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
#
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -e
if ! git rev-list $TRAVIS_COMMIT_RANGE 2>1 >/dev/null; then
echo "\$TRAVIS_COMMIT_RANGE ($TRAVIS_COMMIT_RANGE) is not valid for this build (probably caused by a rebase)."
exit 0
fi
cd "$TRAVIS_BUILD_DIR"
echo "Running clang-tidy on changed files"
git diff -U0 --no-color $TRAVIS_COMMIT_RANGE | \
$TRAVIS_BUILD_DIR/ci/travis/clang-tidy-diff.py -path "$TRAVIS_BUILD_DIR/build" -p1 \
-regex '(code|freespace2|qtfred|testsrc|build|tools)\/.*\.(cpp|h)' \
-clang-tidy-binary /usr/bin/clang-tidy-9 -j$(nproc) -quiet 2>/dev/null | \
tee clang-tidy-output.txt
if [[ -n $(grep "warning: " clang-tidy-output.txt) ]] || [[ -n $(grep "error: " clang-tidy-output.txt) ]]; then
echo "Errors or warnings were detected in the clang-tidy output!"
exit 1
else
echo -e "\033[1;32m\xE2\x9C\x93 passed:\033[0m clang-tidy test succeeded";
fi
+1 -1
View File
@@ -18,7 +18,7 @@ elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
XCODE_RET=${PIPESTATUS[0]}
if [ "$XCODE_RET" -ne "0" ]; then
tar -cvzf build.log.tar.gz build.log
curl --upload-file build.log.tar.gz "https://keep.sh"
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
exit $XCODE_RET
fi
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
@@ -145,19 +145,20 @@
fun:dl_open_worker
}
{
dlopen leak
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_dl_exception_create
fun:_dl_signal_error
fun:_dl_map_object
fun:dl_open_worker
fun:_dl_catch_exception
fun:_dl_open
fun:dlopen_doit
fun:_dl_catch_exception
fun:_dl_catch_error
fun:_dlerror_run
fun:dlopen@@GLIBC_2.2.5
obj:*
obj:*
fun:call_init.part.0
fun:call_init
fun:_dl_init
fun:dl_open_worker
}
+2
View File
@@ -4,6 +4,8 @@ include(WriteCompilerDetectionHeader)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
set(CMAKE_CXX_STANDARD 11)
set(REQUIRED_CXX_FEATURES cxx_rvalue_references cxx_nullptr)
get_property(CMAKE_CXX_KNOWN_FEATURES GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
write_compiler_detection_header(
-114
View File
@@ -1,114 +0,0 @@
set(_EMBEDD_FILE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
function(target_embed_files _target)
set(options)
set(oneValueArgs RELATIVE_TO PATH_TYPE_PREFIX)
set(multiValueArgs FILES)
cmake_parse_arguments(EMBED "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT DEFINED EMBED_RELATIVE_TO)
set(EMBED_RELATIVE_TO "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
if (NOT IS_ABSOLUTE "${EMBED_RELATIVE_TO}")
get_filename_component(EMBED_RELATIVE_TO "${EMBED_RELATIVE_TO}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
foreach (file ${EMBED_FILES})
get_filename_component(_absoluteFile "${file}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
file(RELATIVE_PATH _pathType "${EMBED_RELATIVE_TO}" "${_absoluteFile}")
get_filename_component(_pathType ${_pathType} DIRECTORY)
if (DEFINED EMBED_PATH_TYPE_PREFIX)
if (_pathType)
set(_pathType "${EMBED_PATH_TYPE_PREFIX}/${_pathType}")
else()
# Avoid trailing / when we are in the same directory
set(_pathType "${EMBED_PATH_TYPE_PREFIX}")
endif()
endif()
if (NOT _pathType)
# If it is still empty then we need to work around yet another annoying CMake behavior where it ignores
# "empty" property strings
set(_pathType ".")
endif()
set_property(TARGET ${_target} APPEND PROPERTY EMBEDDED_FILES "${_absoluteFile}")
set_property(TARGET ${_target} APPEND PROPERTY EMBEDDED_FILES_BASE_DIR "${EMBED_RELATIVE_TO}")
set_property(TARGET ${_target} APPEND PROPERTY EMBEDDED_FILES_PATH_TYPE "${_pathType}")
endforeach()
endfunction()
function(handle_embedded_files _target)
get_target_property(_filesToEmbed ${_target} EMBEDDED_FILES)
get_target_property(_baseDirs ${_target} EMBEDDED_FILES_BASE_DIR)
get_target_property(_pathTypes ${_target} EMBEDDED_FILES_PATH_TYPE)
SET(DEF_OUT_FILES)
set(INCLUDE_LIST)
set(ARRAY_ELEMENTS)
list(LENGTH _filesToEmbed _numFiles)
FOREACH(i RANGE ${_numFiles})
# Why must CMake always do the unexpected thing? The foreach variant includes the last index as opposed to every
# other sensible language which does not include it...
if (i GREATER_EQUAL _numFiles)
break()
endif()
list(GET _filesToEmbed ${i} _filePath)
list(GET _baseDirs ${i} _baseDir)
list(GET _pathTypes ${i} _pathType)
if (_pathType STREQUAL ".")
# Handle the workaround we had to do for empty path types
set(_pathType "")
endif()
file(RELATIVE_PATH _relativeFilePath "${_baseDir}" "${_filePath}")
SET(_outputBasePath "${CMAKE_CURRENT_BINARY_DIR}/embedded_files/${_relativeFilePath}")
# For some reason this is needed...
get_filename_component(_outputDirectory ${_outputBasePath} DIRECTORY)
file(MAKE_DIRECTORY ${_outputDirectory})
# Retrieve the path type name from the relative path
file(TO_NATIVE_PATH "${_pathType}" _pathType)
if (MINGW)
# There is a bug in CMake where it thinks MinGW uses forward slashes for paths but we need backslashes for Windows builds
string(REPLACE "/" "\\" _pathType "${_pathType}")
endif()
# Properly escape back slashes in strings
string(REPLACE "\\" "\\\\" _pathType "${_pathType}")
get_filename_component(FILE_NAME "${_relativeFilePath}" NAME)
string(MAKE_C_IDENTIFIER "${_relativeFilePath}" FIELD_NAME)
set(HEADER_FILE "${_outputBasePath}.h")
set(SOURCE_FILE "${_outputBasePath}.cpp")
set(ALL_OUTPUTS "${HEADER_FILE}" "${SOURCE_FILE}")
set(FIELD_NAME "Embedded_${FIELD_NAME}")
set(INCLUDE_LIST "${INCLUDE_LIST}\n#include \"${HEADER_FILE}\"")
set(ARRAY_ELEMENTS "${ARRAY_ELEMENTS}\n\t{ \"${_pathType}\", \"${FILE_NAME}\" , ${FIELD_NAME} , ${FIELD_NAME}_size },")
add_custom_command(
OUTPUT ${ALL_OUTPUTS}
COMMAND embedfile "${_filePath}" "${_outputBasePath}" "${FIELD_NAME}"
MAIN_DEPENDENCY "${_filePath}"
COMMENT "Generating string file for ${_filePath}"
)
list(APPEND DEF_OUT_FILES ${ALL_OUTPUTS})
ENDFOREACH()
configure_file("${_EMBEDD_FILE_BASE_DIR}/embedded_files.inc.in" "${CMAKE_CURRENT_BINARY_DIR}/embedded_files/embedded_files.inc")
target_include_directories(${_target} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/embedded_files")
target_sources(${_target} PRIVATE ${DEF_OUT_FILES})
source_group("Generated Files\\Embedded Files" FILES ${DEF_OUT_FILES})
endfunction()
+2 -2
View File
@@ -20,8 +20,8 @@ target_link_libraries(platform INTERFACE ${WIN32_LIBS})
target_compile_definitions(platform INTERFACE WIN32 USE_OPENAL _WINDOWS)
# Specify minimum Windows version for the headers (currently this is Vista)
target_compile_definitions(platform INTERFACE NTDDI_VERSION=0x06000000 _WIN32_WINNT=0x0600)
# Specify minimum Windows version for the headers (currently this is XP)
target_compile_definitions(platform INTERFACE NTDDI_VERSION=0x05010000 _WIN32_WINNT=0x0501)
SET(EXE_GUI_TYPE WIN32)
set(PLATFORM_WINDOWS TRUE CACHE INTERNAL "" FORCE)
+1
View File
@@ -42,6 +42,7 @@ CHECK_FUNCTION_EXISTS(strlwr SCP_HAVE_STRLWR)
CHECK_INCLUDE_FILE("strings.h" SCP_HAVE_STRINGS_H)
check_symbol_exists(snprintf "stdio.h" SCP_HAVE_SNPRINTF)
check_symbol_exists(_snprintf "stdio.h" SCP_HAVE__SNPRINTF)
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
-12
View File
@@ -23,7 +23,6 @@ endif()
if (CLANG_USE_LIBCXX)
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -stdlib=libc++")
target_link_libraries(compiler INTERFACE "c++" "c++abi")
endif()
# Initialize with an empty string to make sure we always get a clean start
@@ -118,14 +117,3 @@ endif()
# Always define this to make sure that the fixed width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
# GNU ar: Create thin archive files.
# Requires binutils-2.19 or later.
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
endif()
target_link_libraries(compiler INTERFACE m)
+8 -39
View File
@@ -8,8 +8,6 @@ MESSAGE(STATUS "Doing configuration specific to gcc...")
option(GCC_ENABLE_LEAK_CHECK "Enable -fsanitize=leak" OFF)
option(GCC_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
option(GCC_ENABLE_SANITIZE_UNDEFINED "Enable -fsanitize=undefined" OFF)
option(GCC_USE_GOLD "Use the gold linker instead of the standard linker" OFF)
option(GCC_GENERATE_GDB_INDEX "Adds linker option to generate the gdb index for debug builds" OFF)
# These are the default values
set(C_BASE_FLAGS "-march=native -pipe")
@@ -25,16 +23,6 @@ endif()
# Initialize with an empty string to make sure we always get a clean start
set(COMPILER_FLAGS "")
set(LINKER_FLAGS "")
if (GCC_USE_GOLD)
OPTION(GCC_INCREMENTAL_LINKING "Use incremental linking" OFF)
set(LINKER_FLAGS "${LINKER_FLAGS} -fuse-ld=gold")
if (GCC_INCREMENTAL_LINKING)
set(LINKER_FLAGS "${LINKER_FLAGS} -fno-use-linker-plugin -Wl,-z,norelro -Wl,--incremental")
endif()
endif()
# This is a slight hack since our flag setup is a bit more complicated
_enable_extra_compiler_warnings_flags()
@@ -42,11 +30,9 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
if (NOT GCC_INCREMENTAL_LINKING)
# Place each function and data in its own section so the linker can
# perform dead code elimination
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdata-sections -ffunction-sections")
endif()
# Place each function and data in its own section so the linker can
# perform dead code elimination
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdata-sections -ffunction-sections")
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
# Force color diagnostics for Ninja generator
@@ -112,7 +98,7 @@ set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variabl
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
# Always use the base flags and add our compiler flags at the back
# Always use the base flags and add our compiler flags at the bacl
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
@@ -122,7 +108,7 @@ set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_EXE_LINKER_FLAGS "${LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "")
IF (MINGW)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
@@ -135,25 +121,17 @@ endif()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g")
if (GCC_GENERATE_GDB_INDEX)
# For pure debug binaries, generate a gdb index for better debugging
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -Wl,--gdb-index")
endif()
IF(NOT MINGW)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
# Allow the linker to perform dead code elimination; this is considered
# experimental for COFF and PE formats and thus disabled for Windows builds
# (https://sourceware.org/binutils/docs/ld/Options.html)
if (NOT GCC_INCREMENTAL_LINKING AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
endif()
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
ENDIF(NOT MINGW)
IF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-zignore")
ENDIF()
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-zignore")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
@@ -162,12 +140,3 @@ endif()
# Always define this to make sure that the fixed width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS=1)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
# GNU ar: Create thin archive files.
# Requires binutils-2.19 or later.
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
endif()
-3
View File
@@ -17,9 +17,6 @@ ELSE("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
MESSAGE(STATUS "No special handling for this compiler present, good luck!")
ENDIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
find_package(Threads REQUIRED)
target_link_libraries(compiler INTERFACE Threads::Threads)
# Copy release settings to FastDebug
set(CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_RELEASE}")
+7 -43
View File
@@ -140,34 +140,14 @@ macro(set_if_not_defined VAR VALUE)
endif()
endmacro(set_if_not_defined)
function(set_precompiled_header _target _headerPath)
if (COMMAND target_precompile_headers)
target_compile_definitions(${_target} PRIVATE CMAKE_PCH)
target_precompile_headers(${_target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${_headerPath}>")
else()
if (ENABLE_COTIRE)
message("${_headerPath}")
set_target_properties(${_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${_headerPath}")
macro(configure_cotire target)
if(ENABLE_COTIRE)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
# Disable unity build as it doesn't work well for us
set_target_properties(${_target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
cotire(${_target})
else()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_compile_options(${_target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${_headerPath}>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_options(${_target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/FI ${_headerPath}>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_compile_options(${_target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${_headerPath}>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
target_compile_options(${_target} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${_headerPath}>")
ELSE()
MESSAGE("Unknown compiler for global includes. This will probably break the build.")
ENDIF()
endif()
cotire(${target})
endif()
endfunction()
endmacro(configure_cotire)
macro(add_target_copy_files)
foreach(file ${ARGN})
@@ -204,7 +184,7 @@ function(detect_simd_instructions _out_var)
endfunction()
function (check_linker_flag _flag _out_var)
SET(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
SET(CMAKE_REQUIRED_FLAGS "${_flag}")
CHECK_C_COMPILER_FLAG("" ${_out_var})
endfunction(check_linker_flag)
@@ -218,22 +198,6 @@ function(suppress_warnings _target)
endif()
endfunction(suppress_warnings)
# Suppresses warnings for the specified files
function(suppress_file_warnings)
if (MSVC)
set_source_files_properties(
${ARGN}
PROPERTIES
COMPILE_FLAGS "/W0")
else()
# Assume everything else uses GCC style options
set_source_files_properties(
${ARGN}
PROPERTIES
COMPILE_FLAGS "-w")
endif()
endfunction(suppress_file_warnings)
function(list_target_dependencies _target _out_var)
set(out_list)
+24 -26
View File
@@ -1,12 +1,13 @@
include(util)
INCLUDE(source_groups.cmake)
INCLUDE(voice_rec.cmake)
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
target_compile_features(code PUBLIC cxx_std_11)
target_compile_features(code PUBLIC ${REQUIRED_CXX_FEATURES})
INCLUDE(default_files.cmake)
if (MSVC)
target_compile_definitions(code PUBLIC "PDB_DEBUGGING=1")
@@ -18,9 +19,7 @@ TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${FREESPACE_HEADERS})
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR})
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR}/code)
if (FSO_BUILD_WITH_OPENGL)
target_link_libraries(code PUBLIC OpenGL)
endif()
target_link_libraries(code PUBLIC OpenGL)
TARGET_LINK_LIBRARIES(code PUBLIC openal)
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
@@ -46,13 +45,7 @@ target_link_libraries(code PUBLIC libRocket)
target_link_libraries(code PUBLIC pcp)
if (FSO_BUILD_WITH_VULKAN)
target_link_libraries(code PUBLIC vulkan-hpp)
endif()
target_link_libraries(code PUBLIC parsers)
target_link_libraries(code PUBLIC mdns)
target_link_libraries(code PUBLIC vulkan-hpp)
enable_clang_tidy(code)
@@ -74,6 +67,22 @@ IF(FSO_BUILD_TOOLS)
ADD_SUBDIRECTORY(cfileextractor)
ENDIF(FSO_BUILD_TOOLS)
if (ENABLE_COTIRE)
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h")
else()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/FI ${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
ELSE()
MESSAGE("Unknown compiler for global includes. This will probably break the build.")
ENDIF()
endif()
if (FSO_RELEASE_LOGGING)
target_compile_definitions(code PUBLIC SCP_RELEASE_LOGGING)
endif()
@@ -81,20 +90,9 @@ endif()
if (FSO_BUILD_WITH_FFMPEG)
target_compile_definitions(code PUBLIC WITH_FFMPEG)
endif()
if (FSO_BUILD_WITH_OPENGL)
target_compile_definitions(code PUBLIC WITH_OPENGL)
endif()
if (FSO_BUILD_WITH_VULKAN)
target_compile_definitions(code PUBLIC WITH_VULKAN)
endif()
include(shaders.cmake)
target_embed_files(code FILES ${default_files_files} RELATIVE_TO "def_files")
handle_embedded_files(code)
set_precompiled_header(code "${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h")
include(util)
configure_cotire(code)
# Ensure that Xcode generates debug symbols on macOS for Debug builds
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
+2 -1
View File
@@ -36,7 +36,8 @@ int ai_get_slot(int shipnum)
return i;
}
Error( LOCATION, "Couldn't get AI slot, please tell a coder!");
Warning( LOCATION, "Couldn't get AI slot" );
Int3();
return -1;
}
+8 -14
View File
@@ -70,7 +70,6 @@ extern ai_flag_name Ai_flag_names[];
#define AITTV_FAST (1<<0) // Turn fast, not slowed down based on skill level.
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
#define AITTV_IGNORE_BANK (1<<2) // Goober5000 - ignore bank when turning
#define AITTV_SLOW_BANK_ACCEL (1<<3) // Asteroth - used by formation flying
#define KAMIKAZE_HULL_ON_DEATH -1000.0f // Hull strength ship gets set to if it crash-dies.
@@ -183,7 +182,6 @@ typedef struct ai_class {
// Submode definitions.
// Note: These need to be renamed to be of the form: AIS_mode_xxxx
// Cyborg17 -- If you add submodes for AI_CHASE, you *have to* add entries to Submode_text[] in aicode.cpp
#define SM_CONTINUOUS_TURN 1 // takes parm: vector_id {0..3 = right, -right, up, -up}
#define SM_ATTACK 2
#define SM_EVADE_SQUIGGLE 3
@@ -472,8 +470,8 @@ typedef struct ai_info {
fix avoid_check_timestamp; // timestamp at which to next check for having to avoid ship
vec3d big_collision_normal; // Global normal of collision with big ship. Helps find direction to fly away from big ship. Set for each collision.
vec3d big_recover_1_direction; // A relative direction to fly towards when recovering from collision with a big ship, stage 1.
vec3d big_recover_2_pos; // Global point to fly towards when recovering from collision with a big ship, stage 2.
vec3d big_recover_pos_1; // Global point to fly towards when recovering from collision with a big ship, stage 1.
vec3d big_recover_pos_2; // Global point to fly towards when recovering from collision with a big ship, stage 2.
int big_recover_timestamp; // timestamp at which it's OK to re-enter stage 1.
int abort_rearm_timestamp; // time at which this rearm should be aborted in a multiplayer game.
@@ -487,10 +485,7 @@ typedef struct ai_info {
flagset<AI::Maneuver_Override_Flags> ai_override_flags; // flags for marking ai overrides from sexp or lua systems
control_info ai_override_ci; // ai override control info
int ai_override_lat_timestamp; // mark for when to end the current lateral maneuver override
int ai_override_rot_timestamp; // mark for when to end the current rotational maneuver override
int form_obj_slotnum; // for flying in formation object mode, the position in the formation
int ai_override_timestamp; // mark for when to end the current override
} ai_info;
// Goober5000
@@ -571,7 +566,7 @@ extern void ai_do_default_behavior(object *obj);
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, vec3d* turnrate_mod = nullptr);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, int sexp_flags = 0);
extern void init_ai_object(int objnum);
extern void ai_init(void); // Call this one to parse ai.tbl.
extern void ai_level_init(void); // Call before each level to reset AI
@@ -584,7 +579,8 @@ extern void ai_update_danger_weapon(int objnum, int weapon_objnum);
// called externally from MissionParse.cpp to position ships in wings upon arrival into the
// mission.
extern void get_absolute_wing_pos(vec3d *result_pos, object *leader_objp, int wingnum, int wing_index, bool formation_object_flag, bool autopilot = false);
extern void get_absolute_wing_pos( vec3d *result_pos, object *leader_objp, int wing_index, int formation_object_flag);
extern void get_absolute_wing_pos_autopilot( vec3d *result_pos, object *leader_objp, int wing_index, int formation_object_flag);
// Interface from goals code to AI. Set ship to guard. *objp guards *other_objp
extern void ai_set_guard_object(object *objp, object *other_objp);
@@ -622,7 +618,7 @@ extern int might_collide_with_ship(object *obj1, object *obj2, float dot_to_enem
extern int ai_fire_primary_weapon(object *objp); //changed to return weather it fired-Bobboau
extern int ai_fire_secondary_weapon(object *objp);
extern float ai_get_weapon_dist(ship_weapon *swp);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override, matrix* target_orient = nullptr, int flags = 0);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, ai_info *aip);
@@ -634,7 +630,7 @@ void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, vec3d *gun_pos,
// function to change rearm status for ai ships (called from sexpression code)
extern void ai_set_rearm_status( int team, int new_status );
extern void ai_good_secondary_time( int team, int weapon_index, int num_weapons, const char *shipname );
extern void ai_good_secondary_time( int team, int weapon_index, int num_weapons, char *shipname );
extern void ai_do_objects_docked_stuff(object *docker, int docker_point, object *dockee, int dockee_point, bool update_clients = true);
extern void ai_do_objects_undocked_stuff( object *docker, object *dockee );
@@ -667,6 +663,4 @@ void ai_update_aim(ai_info *aip);
//SUSHI: Random evasive sidethrust
void do_random_sidethrust(ai_info *aip, ship_info *sip);
void ai_formation_object_recalculate_slotnums(int form_objnum, int exiting_objnum = -1);
#endif
+2 -10
View File
@@ -63,9 +63,7 @@ namespace AI {
Dont_bank_when_turning, // maps to CIF_DONT_BANK_WHEN_TURNING
Dont_clamp_max_velocity, // maps to CIF_DONT_CLAMP_MAX_VELOCITY
Instantaneous_acceleration, // maps to CIF_INSTANTANEOUS_ACCELERATION
Lateral_never_expire, // don't clear the lateral maneuver when the timestamp is up
Rotational_never_expire, // don't clear the rotational maneuver when the timestamp is up
Dont_override_old_maneuvers,// doesn't clear any previous maneuvers
Never_expire, // don't clear the maneuver when the timestamp is up
NUM_VALUES
};
@@ -120,19 +118,13 @@ namespace AI {
Smart_secondary_weapon_selection,
Smart_shield_management,
Smart_subsystem_targeting_for_turrets,
Strict_turret_tagged_only_targeting,
Strict_turred_tagged_only_targeting,
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in http://scp.indiegames.us/mantis/view.php?id=3198
Turrets_ignore_target_radius,
Use_actual_primary_range,
Use_subsystem_path_point_radii,
Use_additive_weapon_velocity,
Use_newtonian_dampening,
Use_only_single_fov_for_turrets,
No_turning_directional_bias,
Use_axial_turnrate_differences,
nonshielded_ships_can_manage_ets,
Better_collision_avoidance,
Require_exact_los,
NUM_VALUES
};
+1 -33
View File
@@ -8,7 +8,6 @@
#include "ai/ai_profiles.h"
#include "ai/aibig.h"
#include "def_files/def_files.h"
#include "globalincs/pstypes.h"
#include "localization/localize.h"
@@ -446,8 +445,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$support don't add primaries:", AI::Profile_Flags::Support_dont_add_primaries);
set_flag(profile, "$firing requires exact los:", AI::Profile_Flags::Require_exact_los);
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
if (optional_string("$ai path mode:"))
{
@@ -465,7 +462,7 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug);
set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turret_tagged_only_targeting);
set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turred_tagged_only_targeting);
set_flag(profile, "$aspect bomb invulnerability fix:", AI::Profile_Flags::Aspect_invulnerability_fix);
@@ -475,18 +472,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
if (optional_string("$override radius for subsystem path points:")) {
int path_radii;
stuff_int(&path_radii);
if (path_radii >= Minimum_subsystem_path_pt_dist) {
profile->subsystem_path_radii = path_radii;
} else {
mprintf(("Warning: \"$override radius for subsystem path points:\" should be >= %i (read %i). Value will not be used. ", Minimum_subsystem_path_pt_dist, path_radii));
}
}
set_flag(profile, "$use POF radius for subsystem path points:", AI::Profile_Flags::Use_subsystem_path_point_radii);
profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
if (optional_string("$bay arrive speed multiplier:")) {
@@ -513,21 +498,7 @@ void parse_ai_profiles_tbl(const char *filename)
stuff_boolean(&temp);
profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, !temp);
}
if (optional_string("$lead indicator second-order prediction factor:")) {
stuff_float(&profile->second_order_lead_predict_factor);
if (profile->second_order_lead_predict_factor > 1 || profile->second_order_lead_predict_factor < 0) {
mprintf(("Warning: \"$lead indicator second-order prediction factor\" must be 0 - 1, resetting to 0.\"\n"));
profile->second_order_lead_predict_factor = 0;
}
}
set_flag(profile, "$no directional bias for missile and ship turning:", AI::Profile_Flags::No_turning_directional_bias);
set_flag(profile, "$respect ship axial turnrate differences:", AI::Profile_Flags::Use_axial_turnrate_differences);
set_flag(profile, "$ships with no shields can manage ETS:", AI::Profile_Flags::nonshielded_ships_can_manage_ets);
set_flag(profile, "$better combat collision avoidance for fightercraft:", AI::Profile_Flags::Better_collision_avoidance);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
@@ -601,10 +572,8 @@ void ai_profile_t::reset()
flags.reset();
ai_path_mode = 0;
subsystem_path_radii = 0;
bay_arrive_speed_mult = 0;
bay_depart_speed_mult = 0;
second_order_lead_predict_factor = 0;
for (int i = 0; i < NUM_SKILL_LEVELS; ++i) {
max_incoming_asteroids[i] = 0;
@@ -676,7 +645,6 @@ void ai_profile_t::reset()
flags.set(AI::Profile_Flags::Fix_ai_path_order_bug);
flags.set(AI::Profile_Flags::Aspect_invulnerability_fix);
flags.set(AI::Profile_Flags::Use_actual_primary_range);
flags.set(AI::Profile_Flags::nonshielded_ships_can_manage_ets);
}
// this flag has been enabled ever since 3.7.2
if (mod_supports_version(3, 7, 2)) {
-6
View File
@@ -97,17 +97,11 @@ public:
int ai_path_mode;
// radii to use for the radius for subsystem path points and default value --wookieejedi
int subsystem_path_radii;
// Ships flying bay paths will gradually accelerate/decelerate instead of
// flying the whole path at max speed
float bay_arrive_speed_mult;
float bay_depart_speed_mult;
// How much 0-1 of a second-order lead prediction factor to add to lead indicators. Affects only the HUD indicator, and autoaim.
float second_order_lead_predict_factor;
void reset();
};
+11 -44
View File
@@ -370,8 +370,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
float dot = 1.0f, min_dot;
object *target_objp;
auto shipp = &Ships[Pl_objp->instance];
aip = &Ai_info[shipp->ai_index];
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
if ( aip->target_objnum < 0 )
return 0;
@@ -383,8 +382,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
float dist;
// Get models of both source and target
polymodel *pm = model_get( Ship_info[shipp->ship_info_index].model_num );
polymodel_instance *pmi = model_get_instance( shipp->model_instance_num );
polymodel *pm = model_get( Ship_info[Ships[Pl_objp->instance].ship_info_index].model_num );
polymodel *pm_t = model_get( Ship_info[Ships[target_objp->instance].ship_info_index].model_num );
// Necessary sanity check
@@ -405,8 +403,8 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
aip->path_subsystem_next_check = timestamp(1500);
// get world pos of eye (stored in geye)
ep = &(pm->view_positions[shipp->current_viewpoint]);
model_instance_find_world_point( &geye, &ep->pnt, pm, pmi, 0, &Pl_objp->orient, &Pl_objp->pos );
ep = &(pm->view_positions[Ships[Pl_objp->instance].current_viewpoint]);
model_find_world_point( &geye, &ep->pnt, pm->id, 0, &Pl_objp->orient, &Pl_objp->pos );
// get world pos of subsystem
vm_vec_unrotate(&gsubpos, &aip->targeted_subsys->system_info->pnt, &En_objp->orient);
@@ -433,6 +431,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
min_dot = (target_objp->phys_info.fspeed > 5.0f?MIN_DOT_TO_ATTACK_MOVING_SUBSYS:MIN_DOT_TO_ATTACK_SUBSYS);
if ( (checked_sight && ((!subsys_in_sight) || (dot < min_dot)) ) ) {
aip->path_goal_dist = 5;
subsys_path_num = aip->targeted_subsys->system_info->path_num;
if ( ((aip->path_start) == -1 || (aip->mp_index != subsys_path_num)) && subsys_path_num < pm_t->n_paths ) {
// maybe create a new path
@@ -462,41 +461,9 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
Assert(aip->path_length >= 2);
dist = vm_vec_dist_quick(&Path_points[aip->path_start+aip->path_length-2].pos, &Pl_objp->pos);
// distance setting --wookieejedi
if ( aip->path_cur >= (aip->path_start+aip->path_length-1) ) {
// register that path is done and reset goal distance to default
aip->path_goal_dist = Default_subsystem_path_pt_dist;
path_done=1;
}
// if not done then set path distances based on specified options
else {
bool found_point = false;
// 1. use radii of path points if specified
if (aip->ai_profile_flags[AI::Profile_Flags::Use_subsystem_path_point_radii]) {
// need a valid path and point in model to use pof specified radius
int path_num = aip->targeted_subsys->system_info->path_num;
if ((0 <= path_num) && (path_num < pm_t->n_paths)) {
// need a valid place in the path
if ((0 <= aip->path_cur) && (aip->path_cur < aip->path_length)) {
float path_point_radius = pm_t->paths[path_num].verts[aip->path_cur].radius;
int goal_dist = fl2i(path_point_radius);
// only set if >= Minimum path distance specified in aibig.h
if (goal_dist >= Minimum_subsystem_path_pt_dist) {
aip->path_goal_dist = goal_dist;
found_point = true;
}
}
}
}
// 2. use radii value in ai_profiles table if specified and no valid point found
if (!found_point && The_mission.ai_profile->subsystem_path_radii) {
aip->path_goal_dist = The_mission.ai_profile->subsystem_path_radii;
}
// 3. use default radii value if no valid point or specified radii
else {
aip->path_goal_dist = Default_subsystem_path_pt_dist;
}
}
min_dot = (target_objp->phys_info.fspeed > 5.0f?MIN_DOT_TO_ATTACK_MOVING_SUBSYS:MIN_DOT_TO_ATTACK_SUBSYS);
if ( (checked_sight && subsys_in_sight) && (dot > min_dot) ) {
@@ -664,8 +631,8 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
compute_desired_rvec(rvec, enemy_pos, &Pl_objp->pos);
else
rvec = NULL;
ai_turn_towards_vector(enemy_pos, Pl_objp, nullptr, rel_pos, 0.0f, 0, rvec);
ai_turn_towards_vector(enemy_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, 0.0f, 0, rvec);
// calc range of primary weapon
weapon_travel_dist = ai_get_weapon_dist(&Ships[Pl_objp->instance].weapons);
@@ -739,7 +706,7 @@ void ai_big_chase_ct()
extern void ai_select_secondary_weapon(object *objp, ship_weapon *swp, int priority1 = -1, int priority2 = -1);
extern float set_secondary_fire_delay(ai_info *aip, ship *shipp, weapon_info *swip, bool burst);
extern void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp);
extern int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time, float time_scale = 1.f);
extern int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time);
extern void maybe_cheat_fire_synaptic(object *objp);
@@ -1330,7 +1297,7 @@ void ai_big_strafe_attack()
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
if (target_dist < 1200.0f) {
ai_turn_towards_vector(&target_pos, Pl_objp, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&target_pos, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((target_dist < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
@@ -1455,7 +1422,7 @@ void ai_big_strafe_glide_attack()
vm_vec_sub(&targetToAttacker, &Pl_objp->pos, &target_objp->pos);
matrix orient;
vm_vector_2_matrix(&orient, &targetToAttacker, NULL, NULL);
vm_vec_random_in_circle(&tangentPoint, &target_objp->pos, &orient, target_objp->radius + GLIDE_STRAFE_DISTANCE, true);
vm_vec_random_in_circle(&tangentPoint, &target_objp->pos, &orient, target_objp->radius + GLIDE_STRAFE_DISTANCE, 1);
//Get tangent point in coords relative to ship, scale it up so the actual goal point is far away, then put back in world coords
vm_vec_sub2(&tangentPoint, &Pl_objp->pos);
vm_vec_scale(&tangentPoint, 1000.0f);
@@ -1707,7 +1674,7 @@ void ai_big_strafe()
break;
default:
Error(LOCATION, "Ai_big_strafe() just tried to use an illegal submode. Go tell a coder!");
Int3(); // Illegal submode for AIM_STRAFE
break;
}
-4
View File
@@ -27,10 +27,6 @@ void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *we
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
// default distance for following subsystem path points --wookieejedi
// the value is 5 because that was the original value specified in ai_big_maybe_follow_subsys_path()
const int Default_subsystem_path_pt_dist = 5;
const int Minimum_subsystem_path_pt_dist = 1;
#endif
+398 -714
View File
File diff suppressed because it is too large. Load diff
+40 -65
View File
@@ -25,8 +25,6 @@
#include "ship/ship.h"
#include "weapon/weapon.h"
// Just a reference to this struct being for looking up a ship's team in TVT
struct ship_registry_entry;
// all ai goals dealt with in this code are goals that are specified through
// sexpressions in the mission file. They are either specified as part of a
@@ -136,48 +134,28 @@ const char *Ai_goal_text(int goal)
return NULL;
}
void ai_maybe_add_form_goal(wing* wingp)
// function to maybe add the form on my wing goal for a player's starting wing. Called when a player wing arrives.
void ai_maybe_add_form_goal( wing *wingp )
{
// Cyborg17 - Changes from the client would just get overridden by the server anyway
// might as well keep them more closely in sync.
if (MULTIPLAYER_CLIENT) {
return;
}
int j;
// iterate through the ship_index list of this wing and check for orders. We will do
// this for all ships in the wing instead of on a wing only basis in case some ships
// in the wing actually have different orders than others
for (j = 0; j < wingp->current_count; j++) {
ai_info* aip;
for ( j = 0; j < wingp->current_count; j++ ) {
ai_info *aip;
Assert(wingp->ship_index[j] != -1); // get Allender
Assert( wingp->ship_index[j] != -1 ); // get Allender
aip = &Ai_info[Ships[wingp->ship_index[j]].ai_index];
// don't process a Player_ship
if (Objects[Ships[aip->shipnum].objnum].flags[Object::Object_Flags::Player_ship]) {
// don't process Player_ship
if ( aip == Player_ai )
continue;
}
// need to add a form on my wing goal here. Ships are always forming on the player's wing.
// it is sufficient enough to check the first goal entry to see if it has a valid goal
if (aip->goals[0].ai_mode == AI_GOAL_NONE) {
// Need to have a more specific target in multi, or they may end up trying to target standalone placeholder.
// So form on their team leader. In dogfight, all player-slot ai die, so just exclude.
if (MULTIPLAYER_MASTER && !(Netgame.type_flags & NG_TYPE_DOGFIGHT)) {
int wingnum;
if (Netgame.type_flags & NG_TYPE_TEAM) {
const ship_registry_entry* ship_regp = ship_registry_get(Ships[wingp->ship_index[j]].ship_name);
wingnum = TVT_wings[ship_regp->p_objp->team];
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
} else {
wingnum = Starting_wings[0];
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
}
} else if (!(Game_mode & GM_MULTIPLAYER)) {
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Player_ship->ship_name, aip);
}
if ( aip->goals[0].ai_mode == AI_GOAL_NONE ) {
// need to add a form on my wing goal here. Ships are always forming on the player's wing.
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Player_ship->ship_name, aip );
}
}
}
@@ -295,12 +273,15 @@ void ai_clear_ship_goals( ai_info *aip )
// add scripting hook for 'On Goals Cleared' --wookieejedi
Script_system.SetHookObject("Ship", &Objects[Ships[aip->shipnum].objnum]);
Script_system.RunCondition(CHA_ONGOALSCLEARED);
Script_system.RemHookVars({"Ship"});
Script_system.RemHookVars(1, "Ship");
}
void ai_clear_wing_goals( wing *wingp )
void ai_clear_wing_goals( int wingnum )
{
int i;
wing *wingp = &Wings[wingnum];
//p_object *objp;
// clear the goals for all ships in the wing
for (i = 0; i < wingp->current_count; i++) {
@@ -311,13 +292,15 @@ void ai_clear_wing_goals( wing *wingp )
}
// clear out the goals for the wing now
// clear out the goals for the wing now
for (i = 0; i < MAX_AI_GOALS; i++) {
wingp->ai_goals[i].ai_mode = AI_GOAL_NONE;
wingp->ai_goals[i].signature = -1;
wingp->ai_goals[i].priority = -1;
wingp->ai_goals[i].flags.reset();
}
}
// routine which marks a wing goal as being complete. We get the wingnum and a pointer to the goal
@@ -852,10 +835,11 @@ void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, i
void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
{
int node, dummy, op;
char *text;
Assert ( Sexp_nodes[sexp].first != -1 );
node = Sexp_nodes[sexp].first;
op = get_operator_const( node );
text = CTEXT(node);
aigp->signature = Ai_goal_signature++;
@@ -864,6 +848,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->type = type;
aigp->flags.reset();
op = get_operator_const( text );
switch (op) {
case OP_AI_WAYPOINTS_ONCE:
@@ -1032,7 +1018,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
}
if ( aigp->priority > MAX_GOAL_PRIORITY ) {
nprintf (("AI", "bashing sexpression priority of goal %s from %d to %d.\n", CTEXT(node), aigp->priority, MAX_GOAL_PRIORITY));
nprintf (("AI", "bashing sexpression priority of goal %s from %d to %d.\n", text, aigp->priority, MAX_GOAL_PRIORITY));
aigp->priority = MAX_GOAL_PRIORITY;
}
@@ -1097,9 +1083,14 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
int goalsubmode = -1;
/* Sexp node */
int node = Sexp_nodes[sexp].first;
int node = -1;
/* The operator to use */
int op = get_operator_const( node );
char* op_text = NULL;
int op = -1;
node = Sexp_nodes[ sexp ].first;
op_text = CTEXT( node );
op = get_operator_const( op_text );
/* We now need to determine what the mode and submode values are*/
switch( op )
@@ -1226,10 +1217,11 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
}
// code to add ai goals to wings.
void ai_remove_wing_goal_sexp(int sexp, wing *wingp)
void ai_remove_wing_goal_sexp(int sexp, int wingnum)
{
int i;
int goalindex = -1;
wing *wingp = &Wings[wingnum];
// add the ai goal for any ship that is currently arrived in the game (only if fred isn't running)
if ( !Fred_running ) {
@@ -1260,9 +1252,10 @@ void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip )
}
// code to add ai goals to wings.
void ai_add_wing_goal_sexp(int sexp, int type, wing *wingp)
void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
{
int i;
wing *wingp = &Wings[wingnum];
// add the ai goal for any ship that is currently arrived in the game (only if fred isn't running)
if ( !Fred_running ) {
@@ -1655,35 +1648,25 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
else
{
auto ship_entry = ship_registry_get(aigp->target_name);
if (!ship_entry)
{
status = SHIP_STATUS_UNKNOWN;
}
// goal ship is currently in mission
else if (ship_entry->status == ShipStatus::PRESENT)
if ( ship_name_lookup( aigp->target_name ) != -1 )
{
status = SHIP_STATUS_ARRIVED;
}
// goal ship is still on the arrival list
else if (ship_entry->status == ShipStatus::NOT_YET_PRESENT)
else if ( mission_check_ship_yet_to_arrive(aigp->target_name) )
{
status = SHIP_STATUS_NOT_ARRIVED;
}
// goal ship has left the area
else if (ship_entry->status == ShipStatus::EXITED)
else if ( ship_find_exited_ship_by_name(aigp->target_name) != -1 )
{
status = SHIP_STATUS_GONE;
}
else
{
status = SHIP_STATUS_UNKNOWN;
}
if (status == SHIP_STATUS_UNKNOWN)
{
mprintf(("Potentially incorrect behaviour in AI goal for ship %s: Ship %s could not be found among currently active, departed, or yet-to-arrive ships.\nPlease check the mission file.\n", Ships[objp->instance].ship_name, aigp->target_name));
status = SHIP_STATUS_UNKNOWN;
}
}
@@ -2118,13 +2101,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// if this object was flying in formation off of another object, remove the flag that tells him
// to do this. The form-on-my-wing command is removed from the goal list as soon as it is called, so
// we are safe removing this bit here.
int old_form_objnum = -1;
if (aip->ai_flags[AI::AI_Flags::Formation_object]) {
// save who he was following so we can tell any others
// who are following to re-organize
old_form_objnum = aip->goal_objnum;
aip->ai_flags.remove(AI::AI_Flags::Formation_object);
}
aip->ai_flags.remove(AI::AI_Flags::Formation_object);
// Goober5000 - we may want to use AI for the player
// AL 3-7-98: If this is a player ship, and the goal is not a formation goal, then do a quick out
@@ -2390,8 +2367,6 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
}
if (old_form_objnum != -1)
ai_formation_object_recalculate_slotnums(old_form_objnum);
}
void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, const char *new_name)
+3 -3
View File
@@ -102,11 +102,11 @@ extern int ai_goal_num(ai_goal *goals);
// adds goals to ships/wing through sexpressions
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip);
extern void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip );
extern void ai_add_wing_goal_sexp( int sexp, int type, wing *wingp );
extern void ai_add_wing_goal_sexp( int sexp, int type, int wingnum );
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name );
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
extern void ai_remove_wing_goal_sexp( int sexp, wing *wingp );
extern void ai_remove_wing_goal_sexp(int sexp, int wingnum);
// adds goals to ships/sings through player orders
extern void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip );
@@ -114,7 +114,7 @@ extern void ai_add_wing_goal_player( int type, int mode, int submode, char *ship
extern void ai_remove_ship_goal( ai_info *aip, int index );
extern void ai_clear_ship_goals( ai_info *aip );
extern void ai_clear_wing_goals( wing *wingp );
extern void ai_clear_wing_goals( int wingnum );
extern void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip );
+2 -5
View File
@@ -26,12 +26,9 @@ int object_is_targetable(object *target, ship *viewer);
int num_nearby_fighters(int enemy_team_mask, vec3d *pos, float threshold);
//Returns true if OK for *aip to fire its current weapon at its current target.
int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int secondary_bank, ship_subsys* turret);
//Returns true if *aip has a line of sight to its current target.
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, ship_subsys* turret);
int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip);
//Does all the stuff needed to aim and fire a turret.
void ai_fire_from_turret(ship *shipp, ship_subsys *ss);
void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum);
#endif
+297 -293
View File
@@ -382,16 +382,10 @@ weapon_info *get_turret_weapon_wip(ship_weapon *swp, int weapon_num)
Assert(weapon_num < MAX_SHIP_WEAPONS);
Assert(weapon_num >= 0);
int wi_index;
if(weapon_num >= MAX_SHIP_PRIMARY_BANKS)
wi_index = swp->secondary_bank_weapons[weapon_num - MAX_SHIP_PRIMARY_BANKS];
return &Weapon_info[swp->secondary_bank_weapons[weapon_num - MAX_SHIP_PRIMARY_BANKS]];
else
wi_index = swp->primary_bank_weapons[weapon_num];
if (wi_index < 0)
return nullptr;
else
return &Weapon_info[wi_index];
return &Weapon_info[swp->primary_bank_weapons[weapon_num]];
}
int get_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num)
@@ -405,17 +399,6 @@ int get_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num)
return swp->next_primary_fire_stamp[weapon_num];
}
void set_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num, int delta_ms)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
Assert(weapon_num >= 0);
if (weapon_num >= MAX_SHIP_PRIMARY_BANKS)
swp->next_secondary_fire_stamp[weapon_num - MAX_SHIP_PRIMARY_BANKS] = timestamp(delta_ms);
else
swp->next_primary_fire_stamp[weapon_num] = timestamp(delta_ms);
}
/**
* Returns the longest-ranged weapon on a turret
*
@@ -615,7 +598,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
// however if this is removed turrets still track targets but don't fire at them (which looks silly)
if (eeo->eeo_flags & EEOF_TAGGED_ONLY) {
if (!ship_is_tagged(objp) &&
( (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turret_tagged_only_targeting]) ||
( (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]) ||
( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, Weapon::Info_Flags::Spawn))) )) {
return;
}
@@ -792,6 +775,29 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
} // end asteroid selection
}
/**
* Is target beam valid?
*
* @return 0 only if objnum is beam protected and turret is beam turret
*/
int is_target_beam_valid(ship_weapon *swp, object *objp)
{
// check if turret has beam weapon
if (all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Beam)) {
if (objp->flags[Object::Object_Flags::Beam_protected]) {
return 0;
}
if (all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Huge)) {
if (objp->type == OBJ_SHIP && !(Ship_info[Ships[objp->instance].ship_info_index].is_big_or_huge()) ) {
return 0;
}
}
}
return 1;
}
/**
* Given an object and an enemy team, return the index of the nearest enemy object.
*
@@ -1067,7 +1073,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
evaluate_obj_as_target(objp, &eeo);
}
// next highest priority is attacking ship
Assert(eeo.nearest_attacker_objnum < 0 || is_target_beam_valid(swp, &Objects[eeo.nearest_attacker_objnum]));
// next highest priority is attacking ship
if ( eeo.nearest_attacker_objnum != -1 ) { // next highest priority is an attacking ship
return eeo.nearest_attacker_objnum;
}
@@ -1266,24 +1273,26 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
{
vec3d * gun_pos;
model_subsystem *tp = ssp->system_info;
polymodel_instance *pmi = model_get_instance(Ships[objp->instance].model_instance_num);
polymodel *pm = model_get(pmi->model_num);
//ship_model_start(objp);
gun_pos = &tp->turret_firing_point[ssp->turret_next_fire_pos % tp->turret_num_firing_points];
model_instance_find_world_point(gpos, gun_pos, pm, pmi, tp->turret_gun_sobj, &objp->orient, &objp->pos);
//model_find_world_point(gpos, gun_pos, tp->model_num, tp->turret_gun_sobj, &objp->orient, &objp->pos );
model_instance_find_world_point(gpos, gun_pos, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient, &objp->pos);
if (use_angles) {
model_instance_find_world_dir(gvec, &tp->turret_norm, pm, pmi, tp->turret_gun_sobj, &objp->orient);
model_instance_find_world_dir(gvec, &tp->turret_norm, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient);
} else if (tp->flags[Model::Subsystem_Flags::Share_fire_direction]) {
vec3d avg, tmp_pos, tmp_target, enemy_point, turret_norm;
vm_vec_avg_n(&avg, tp->turret_num_firing_points, tp->turret_firing_point);
model_instance_find_world_point(&tmp_pos, &avg, pm, pmi, tp->turret_gun_sobj, &objp->orient, &objp->pos);
model_instance_find_world_point(&tmp_pos, &avg, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient, &objp->pos);
if (targetp == nullptr) {
ship* shipp = &Ships[Objects[ssp->parent_objnum].instance];
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name, shipp->ship_name);
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name,
(shipp->has_display_name()) ? shipp->display_name.c_str() : shipp->ship_name);
object *lep = &Objects[ssp->turret_enemy_objnum];
int best_weapon_tidx = turret_select_best_weapon(ssp, lep);
@@ -1330,6 +1339,8 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
vm_vec_normalized_dir(gvec, targetp, gpos);
}
//ship_model_stop(objp);
// per firingpoint based changes go here for turrets
}
@@ -1361,11 +1372,9 @@ void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss)
*
* @return TRUE if caller should use angles in subsequent rotations.
*/
int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep, vec3d *predicted_enemy_pos, vec3d *gvec)
int aifft_rotate_turret(ship *shipp, int parent_objnum, ship_subsys *ss, object *objp, object *lep, vec3d *predicted_enemy_pos, vec3d *gvec)
{
int ret_val __UNUSED = 0; // to be used in future, see comment @ end of function
auto pmi = model_get_instance(shipp->model_instance_num);
auto pm = model_get(pmi->model_num);
if (ss->turret_enemy_objnum != -1) {
model_subsystem *tp = ss->system_info;
@@ -1386,7 +1395,7 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
// weapon_system_strength scales time enemy in range in 0..1. So, the lower this is, the worse the aiming will be.
weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
ship_get_global_turret_info(objp, tp, &gun_pos, &gun_vec);
ship_get_global_turret_info(&Objects[parent_objnum], tp, &gun_pos, &gun_vec);
//Update "known" position and velocity of target. Only matters if max_aim_update_delay is set.
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ss->turret_enemy_objnum], ss);
@@ -1417,7 +1426,7 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
set_predicted_enemy_pos_turret(predicted_enemy_pos, &gun_pos, objp, &enemy_point, &target_moving_direction, wip->max_speed, ss->turret_time_enemy_in_range * (weapon_system_strength + 1.0f)/2.0f);
//Mess with the turret's accuracy if the weapon system is damaged.
if (weapon_system_strength < Weapon_SS_Threshold_Turret_Inaccuracy) {
if (weapon_system_strength < 0.7f) {
vec3d rand_vec;
static_randvec(Missiontime >> 18, &rand_vec); // Return same random number for two seconds.
@@ -1440,12 +1449,15 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
}
if (in_fov) {
ret_val = model_rotate_gun(objp, pm, pmi, tp, predicted_enemy_pos);
ret_val = model_rotate_gun(Ship_info[shipp->ship_info_index].model_num,
tp, &Objects[parent_objnum].orient,
&ss->submodel_info_1.angs, &ss->submodel_info_2.angs,
&Objects[parent_objnum].pos, predicted_enemy_pos, shipp->objnum);
} else if ((tp->flags[Model::Subsystem_Flags::Turret_reset_idle]) &&(timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, tp, predicted_enemy_pos, true);
ret_val = model_rotate_gun(Ship_info[shipp->ship_info_index].model_num, tp, &Objects[parent_objnum].orient, &ss->submodel_info_1.angs, &ss->submodel_info_2.angs, &Objects[parent_objnum].pos, predicted_enemy_pos, shipp->objnum, true);
}
} else if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss->system_info, predicted_enemy_pos, true);
ret_val = model_rotate_gun(Ship_info[shipp->ship_info_index].model_num, ss->system_info, &Objects[parent_objnum].orient, &ss->submodel_info_1.angs, &ss->submodel_info_2.angs, &Objects[parent_objnum].pos, predicted_enemy_pos, shipp->objnum, true);
}
// by default "ret_val" should be set to 1 for multi-part turrets, and 0 for single-part turrets
@@ -1776,15 +1788,11 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
ai_info *parent_aip;
ship *parent_ship;
float flak_range = 0.0f;
weapon_info *wip;
weapon *wp;
object *objp;
// make sure we actually have a valid weapon
auto wip = get_turret_weapon_wip(&turret->weapons, weapon_num);
if (!wip)
return false;
bool last_shot_in_salvo = true;
if (turret->system_info->flags[Model::Subsystem_Flags::Turret_salvo])
{
if ((turret->turret_next_fire_pos + 1) == (turret->system_info->turret_num_firing_points))
@@ -1803,6 +1811,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
parent_aip = &Ai_info[Ships[Objects[parent_objnum].instance].ai_index];
parent_ship = &Ships[Objects[parent_objnum].instance];
wip = get_turret_weapon_wip(&turret->weapons, weapon_num);
int turret_weapon_class = weapon_info_get_index(wip);
#ifndef NDEBUG
@@ -1812,28 +1821,28 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
// should not get this far. check if ship is protected from beam and weapon is type beam
if ( (wip->wi_flags[Weapon::Info_Flags::Beam]) && (tobjp->flags[Object::Object_Flags::Beam_protected]) ) {
nprintf(("Warning","Ship %s is trying to fire beam turret at beam protected ship\n", parent_ship->ship_name));
return false;
Int3();
return 0;
}
// should not get this far. check if ship is protected from flak and weapon is type flak
else if ( (wip->wi_flags[Weapon::Info_Flags::Flak]) && (tobjp->flags[Object::Object_Flags::Flak_protected]) ) {
nprintf(("Warning","Ship %s is trying to fire flak turret at flak protected ship\n", parent_ship->ship_name));
return false;
Int3();
return 0;
}
// should not get this far. check if ship is protected from laser and weapon is type laser
else if ( (wip->subtype == WP_LASER) && (tobjp->flags[Object::Object_Flags::Laser_protected]) ) {
nprintf(("Warning","Ship %s is trying to fire laser turret at laser protected ship\n", parent_ship->ship_name));
return false;
Int3();
return 0;
}
// should not get this far. check if ship is protected from missile and weapon is type missile
else if ( (wip->subtype == WP_MISSILE) && (tobjp->flags[Object::Object_Flags::Missile_protected]) ) {
nprintf(("Warning","Ship %s is trying to fire missile turret at missile protected ship\n", parent_ship->ship_name));
return false;
Int3();
return 0;
}
}
#endif
if (check_ok_to_fire(parent_objnum, turret->turret_enemy_objnum, wip, -1, turret)) {
if (check_ok_to_fire(parent_objnum, turret->turret_enemy_objnum, wip)) {
vm_vector_2_matrix(&turret_orient, turret_fvec, NULL, NULL);
turret->turret_last_fire_direction = *turret_fvec;
@@ -1861,7 +1870,6 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
else
fire_info.target_subsys = NULL;
fire_info.turret = turret;
fire_info.fire_method = BFM_TURRET_FIRED;
// fire a beam weapon
weapon_objnum = beam_fire(&fire_info);
@@ -1874,7 +1882,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", nullptr, "Beam", objp, "Target", &Objects[turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum]);
Script_system.RemHookVars({"Ship", "Weapon", "Beam", "Target"});
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
}
turret->flags.set(Ship::Subsystem_Flags::Has_fired); //set fired flag for scripting -nike
@@ -2009,7 +2017,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", objp, "Beam", nullptr, "Target", &Objects[turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum]);
Script_system.RemHookVars({"Ship", "Weapon", "Beam", "Target"});
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
// if the gun is a flak gun
if (wip->wi_flags[Weapon::Info_Flags::Flak]) {
@@ -2073,7 +2081,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
turret->flags.set(Ship::Subsystem_Flags::Has_fired); //set has fired flag for scriptng - nuke
//Fire animation stuff
model_anim_start_type(turret, AnimationTriggerType::TurretFired, ANIMATION_SUBTYPE_ALL, 1);
model_anim_start_type(turret, TRIGGER_TYPE_TURRET_FIRED, ANIMATION_SUBTYPE_ALL, 1);
return true;
}
@@ -2126,7 +2134,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
Script_system.SetHookObjects(4, "Ship", &Objects[tsi->parent_objnum], "Weapon", &Objects[weapon_objnum], "Beam", nullptr, "Target", &Objects[tsi->turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[tsi->parent_objnum]);
Script_system.RemHookVars({"Ship", "Weapon", "Beam", "Target"});
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
// muzzle flash?
if (Weapon_info[tsi->weapon_class].muzzle_flash >= 0) {
@@ -2136,7 +2144,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
// maybe sound
if ( Weapon_info[tsi->weapon_class].launch_snd.isValid() ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( tsi->parent_objnum != OBJ_INDEX(Player_obj) || (tsi->turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
if ( tsi->parent_objnum != OBJ_INDEX(Player_obj) ) {
snd_play_3d( gamesnd_get_game_sound(Weapon_info[tsi->weapon_class].launch_snd), &turret_pos, &View_position );
}
}
@@ -2160,16 +2168,20 @@ int Num_turrets_fired = 0;
* Given a turret tp and its parent parent_objnum, fire from the turret at its enemy.
*/
extern int Nebula_sec_range;
void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
{
float weapon_firing_range;
float WeaponMinRange; // *Weapon minimum firing range -Et1
// *Weapon minimum firing range -Et1
float WeaponMinRange;
vec3d v2e;
object *lep; // Last enemy pointer
model_subsystem *tp = ss->system_info;
ship_weapon *swp = &ss->weapons;
vec3d predicted_enemy_pos = vmd_zero_vector;
object *objp;
//ai_info *aip;
// Reset the points to target value
ss->points_to_target = -1.0f;
@@ -2200,19 +2212,22 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
if (swp->primary_bank_weapons[weap_check] >= 0)
valid_weap = true;
}
if (!valid_weap) {
for (weap_check = 0; (weap_check < ss->weapons.num_secondary_banks) && !valid_weap; weap_check++) {
if (ss->weapons.secondary_bank_weapons[weap_check] >= 0)
valid_weap = true;
}
if (!valid_weap)
return;
}
// Monitor number of calls to ai_fire_from_turret
Num_ai_firing++;
// If beam weapon, check beam free
if ( all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Beam) && !(swp->flags[Ship::Weapon_Flags::Beam_Free]) ) {
return;
}
// Handle turret animation
if (ss->turret_animation_position == MA_POS_SET) {
if ( timestamp_elapsed(ss->turret_animation_done_time) ) {
ss->turret_animation_position = MA_POS_READY;
@@ -2226,43 +2241,45 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
}
}
// AL 09/14/97: ensure ss->turret_enemy_objnum != -1 before setting lep
if ( (ss->turret_enemy_objnum >= 0 && ss->turret_enemy_objnum < MAX_OBJECTS) && (ss->turret_enemy_sig == Objects[ss->turret_enemy_objnum].signature) )
Assert((parent_objnum >= 0) && (parent_objnum < MAX_OBJECTS));
objp = &Objects[parent_objnum];
Assert(objp->type == OBJ_SHIP);
Assert( shipp->objnum == parent_objnum );
// Monitor number of calls to ai_fire_from_turret
Num_ai_firing++;
if ( (ss->turret_enemy_objnum < 0 || ss->turret_enemy_objnum >= MAX_OBJECTS) || (ss->turret_enemy_sig != Objects[ss->turret_enemy_objnum].signature))
{
lep = &Objects[ss->turret_enemy_objnum];
ss->turret_enemy_objnum = -1;
lep = NULL;
}
else
{
ss->turret_enemy_objnum = -1;
lep = nullptr;
lep = &Objects[ss->turret_enemy_objnum];
}
Assert((shipp->objnum >= 0) && (shipp->objnum < MAX_OBJECTS));
int parent_objnum = shipp->objnum;
objp = &Objects[shipp->objnum];
Assert(objp->type == OBJ_SHIP);
//aip = &Ai_info[Ships[objp->instance].ai_index];
// Wanderer - make sure turrets already have all the data
if ( !(tp->flags[Model::Subsystem_Flags::Turret_matrix]) )
{
if (!(tp->turret_gun_sobj == tp->subobj_num))
{
auto pmi = model_get_instance(shipp->model_instance_num);
auto pm = model_get(pmi->model_num);
model_make_turret_matrix(pm, pmi, tp);
model_make_turret_matrix(Ship_info[shipp->ship_info_index].model_num, tp );
}
}
// Use the turret info for all guns, not one gun in particular.
vec3d gvec, gpos;
ship_get_global_turret_info(objp, tp, &gpos, &gvec);
ship_get_global_turret_info(&Objects[parent_objnum], tp, &gpos, &gvec);
if (tp->flags[Model::Subsystem_Flags::Turret_alt_math]) {
vm_matrix_x_matrix( &ss->world_to_turret_matrix, &objp->orient, &tp->turret_matrix );
vm_matrix_x_matrix( &ss->world_to_turret_matrix, &Objects[parent_objnum].orient, &tp->turret_matrix );
}
// Rotate the turret even if time hasn't elapsed, since it needs to turn to face its target.
int use_angles = aifft_rotate_turret(objp, shipp, ss, lep, &predicted_enemy_pos, &gvec);
int use_angles = aifft_rotate_turret(shipp, parent_objnum, ss, objp, lep, &predicted_enemy_pos, &gvec);
if ((tp->flags[Model::Subsystem_Flags::Fire_on_target]) && (ss->points_to_target >= 0.0f))
{
@@ -2276,81 +2293,76 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
}
// Don't try to fire beyond weapon_limit_range
// WMC moved the range check to within the loop, but we can still calculate the enemy distance here
//WMC - OTC
//weapon_firing_range = MIN(Weapon_info[tp->turret_weapon_type].lifetime * Weapon_info[tp->turret_weapon_type].max_speed, Weapon_info[tp->turret_weapon_type].weapon_range);
//WMC - build a list of valid weapons. Fire spawns if there are any.
float dist_to_enemy = 0.0f;
if (lep) {
if(lep != NULL) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Turrets_ignore_target_radius])
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos));
dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos));
else
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius);
dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius);
}
// count the number of enemies, in case we have a spawning weapon
int num_ships_nearby = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &gpos, 1500.0f);
// some flags considering there may be different weapon types on this turret
bool we_did_non_spawning_logic = false;
bool tentative_return = false;
//WMC - go through all valid weapons. Fire spawns if there are any.
int valid_weapons[MAX_SHIP_WEAPONS];
int valid_weapons[MAX_SHIP_PRIMARY_BANKS + MAX_SHIP_SECONDARY_BANKS];
int num_valid = 0;
for (int i = 0; i < MAX_SHIP_WEAPONS; ++i)
weapon_info *wip;
int num_ships_nearby = num_nearby_fighters(iff_get_attackee_mask(obj_team(&Objects[parent_objnum])), &gpos, 1500.0f);
int i;
int secnum = 0;
for(i = 0; i < (MAX_SHIP_WEAPONS); i++)
{
//WMC - Only fire more than once if we have multiple guns flag set.
if (num_valid > 0 && !(tp->flags[Model::Subsystem_Flags::Use_multiple_guns]))
if(num_valid > 0 && !(tp->flags[Model::Subsystem_Flags::Use_multiple_guns]))
break;
// figure out which weapon we are firing, if we even have a valid one
weapon_info *wip = nullptr;
if (i < MAX_SHIP_PRIMARY_BANKS)
if(i < MAX_SHIP_PRIMARY_BANKS)
{
if (i < swp->num_primary_banks && timestamp_elapsed(swp->next_primary_fire_stamp[i]))
wip = &Weapon_info[swp->primary_bank_weapons[i]];
if(i >= swp->num_primary_banks)
{
//set to MAX_SHIP_PRIMARY_BANKS - 1 since i is incremented at the top of the loop
//otherwise, we would pass over the first secondary weapon in the bank
i = MAX_SHIP_PRIMARY_BANKS - 1; //we are done with primaries
continue;
}
if ( !timestamp_elapsed(swp->next_primary_fire_stamp[i]))
{
continue;
}
wip = &Weapon_info[swp->primary_bank_weapons[i]];
}
else
{
int j = i - MAX_SHIP_PRIMARY_BANKS;
if (j < swp->num_secondary_banks && timestamp_elapsed(swp->next_secondary_fire_stamp[j]))
wip = &Weapon_info[swp->secondary_bank_weapons[j]];
secnum = i - MAX_SHIP_PRIMARY_BANKS;
if(secnum >= swp->num_secondary_banks)
break; //we are done.
if ( !timestamp_elapsed(swp->next_secondary_fire_stamp[secnum]))
{
continue;
}
wip = &Weapon_info[swp->secondary_bank_weapons[secnum]];
}
if (!wip)
continue;
// Turret spawn weapons are a special case. They fire if there are enough enemies in the
// immediate area (not necessarily in the turret fov).
// However, if this is a 'smart spawn', just use it like a normal weapon
//If this is a spawning type weapon, shoot it!
//If 'smart spawn' just use it like normal weapons
if ( (wip->wi_flags[Weapon::Info_Flags::Spawn]) && !(wip->wi_flags[Weapon::Info_Flags::Smart_spawn]) )
{
if (( num_ships_nearby >= 3 ) || ((num_ships_nearby >= 2) && (frand() < 0.1f))) {
turret_fire_weapon(i, ss, parent_objnum, &gpos, &ss->turret_last_fire_direction);
} else {
// Regardless of firing rate, don't check whether should fire for awhile.
if (tp->flags[Model::Subsystem_Flags::Use_multiple_guns])
set_turret_weapon_next_fire_stamp(swp, i, 1000);
else
ss->turret_next_fire_stamp = timestamp(1000);
ss->turret_next_fire_stamp = timestamp(1000); // Regardless of firing rate, don't check whether should fire for awhile.
}
//we're done with this weapon mount
continue;
}
we_did_non_spawning_logic = true; // for the post-loop check
// If beam weapon, check beam free
if (wip->wi_flags[Weapon::Info_Flags::Beam] && !(ss->weapons.flags[Ship::Weapon_Flags::Beam_Free])) {
tentative_return = true;
continue;
}
// the remaining checks in this loop all require a valid lep
if (!lep)
continue;
// Get weapon range
if (wip->wi_flags[Weapon::Info_Flags::Local_ssm])
if(wip->wi_flags[Weapon::Info_Flags::Local_ssm])
{
weapon_firing_range = wip->lssm_lock_range;
weapon_firing_range=wip->lssm_lock_range;
WeaponMinRange = 0.0f;
}
else
@@ -2359,115 +2371,105 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
WeaponMinRange = wip->WeaponMinRange;
}
// if beam weapon in nebula and target not tagged, decrease firing range
if (wip->wi_flags[Weapon::Info_Flags::Beam]) {
if ( !((shipp->tag_left > 0) || (shipp->level2_tag_left > 0)) ) {
if (Nebula_sec_range) {
if (Nebula_sec_range)
{
weapon_firing_range *= BEAM_NEBULA_RANGE_REDUCE_FACTOR;
// *Scale minimum weapon range in nebula -Et1
//Why? - WMC
//Commented this out, because it doesn't make sense - WMC
//WeaponMinRange *= BEAM_NEBULA_RANGE_REDUCE_FACTOR;
}
}
}
// Don't try to fire beyond weapon_limit_range (or within min range)
if (dist_to_enemy < WeaponMinRange || dist_to_enemy > weapon_firing_range) {
// it's possible another weapon is in range, but if not,
// we will end up selecting a new target
continue;
}
if(lep != NULL)
{
if( (dist_to_enemy <= weapon_firing_range) && (dist_to_enemy >= WeaponMinRange) )
{
if ( wip->wi_flags[Weapon::Info_Flags::Huge] ) {
if ( lep->type != OBJ_SHIP ) {
continue;
}
if ( !(Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge()) ) {
continue;
}
}
// If targeted a small ship and have a huge weapon, don't fire. But this shouldn't happen, as a small ship should not get selected.
if ( wip->wi_flags[Weapon::Info_Flags::Huge] ) {
if ( lep->type != OBJ_SHIP ) {
tentative_return = true;
continue;
}
if ( !(Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge()) ) {
tentative_return = true;
continue;
if ( wip->wi_flags[Weapon::Info_Flags::Small_only] ) {
if ( (lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge()) ) {
continue;
}
}
bool tagged_only = ((wip->wi_flags[Weapon::Info_Flags::Tagged_only]) || (ss->weapons.flags[Ship::Weapon_Flags::Tagged_Only]));
if (lep->type == OBJ_SHIP) {
// Check if we're targeting a protected ship
if (lep->flags[Object::Object_Flags::Protected]) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
}
// Check if we're targeting a beam protected ship with a beam weapon
if ( (lep->flags[Object::Object_Flags::Beam_protected]) && (wip->wi_flags[Weapon::Info_Flags::Beam]) ) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
}
// Check if we're targeting a flak protected ship with a flak weapon
else if ( (lep->flags[Object::Object_Flags::Flak_protected]) && (wip->wi_flags[Weapon::Info_Flags::Flak]) ) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
}
// Check if we're targeting a laser protected ship with a laser weapon
else if ( (lep->flags[Object::Object_Flags::Laser_protected]) && (wip->subtype == WP_LASER) ) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
}
// Check if we're targeting a missile protected ship with a missile weapon
else if ( (lep->flags[Object::Object_Flags::Missile_protected]) && (wip->subtype == WP_MISSILE) ) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
}
// Check if weapon or turret is set to tagged-only
// must check here in case turret has multiple weapons and not all are tagged-only
else if (!ship_is_tagged(lep) && tagged_only) {
continue;
}
}
else
{
// check tagged-only for non-ship targets
if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]))) {
continue;
}
}
//Add it to the list
valid_weapons[num_valid++] = i;
}
}
// Similar check for small weapons
if ( wip->wi_flags[Weapon::Info_Flags::Small_only] ) {
if ( (lep->type == OBJ_SHIP) && Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge() ) {
tentative_return = true;
continue;
}
}
bool tagged_only = ((wip->wi_flags[Weapon::Info_Flags::Tagged_only]) || (ss->weapons.flags[Ship::Weapon_Flags::Tagged_Only]));
// If targeting protected or beam protected ship, don't fire. Reset enemy objnum
// (note: due to the loop, we need to check all weapons on this turret. if none of them are valid, that's when the enemy objnum is reset)
if (lep->type == OBJ_SHIP) {
// Check if we're targeting a protected ship
if (lep->flags[Object::Object_Flags::Protected]) {
// *none* of the weapons will work on this ship, so just quit the loop
tentative_return = true;
break;
}
// Check if we're targeting a beam protected ship with a beam weapon
if ( (lep->flags[Object::Object_Flags::Beam_protected]) && (wip->wi_flags[Weapon::Info_Flags::Beam]) ) {
tentative_return = true;
continue;
}
// Check if we're targeting a flak protected ship with a flak weapon
else if ( (lep->flags[Object::Object_Flags::Flak_protected]) && (wip->wi_flags[Weapon::Info_Flags::Flak]) ) {
tentative_return = true;
continue;
}
// Check if we're targeting a laser protected ship with a laser weapon
else if ( (lep->flags[Object::Object_Flags::Laser_protected]) && (wip->subtype == WP_LASER) ) {
tentative_return = true;
continue;
}
// Check if we're targeting a missile protected ship with a missile weapon
else if ( (lep->flags[Object::Object_Flags::Missile_protected]) && (wip->subtype == WP_MISSILE) ) {
tentative_return = true;
continue;
}
// Check if weapon or turret is set to tagged-only
// must check here in case turret has multiple weapons and not all are tagged-only
else if (tagged_only && !ship_is_tagged(lep)) {
tentative_return = true;
continue;
}
}
else {
// check tagged-only for bombs only if the flag is set; see Mantis #3114
if (tagged_only && ((lep->type != OBJ_WEAPON) || The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turret_tagged_only_targeting])) {
tentative_return = true;
continue;
}
}
// If we made it this far, we have a valid weapon to fire
valid_weapons[num_valid++] = i;
}
// in the original code, spawning weapons immediately bailed after firing,
// so bail unless we have other weapons that need the rest of the function
if (!we_did_non_spawning_logic)
return;
//none of our guns can hit the enemy, so find a new enemy
if (num_valid == 0) {
//none of our guns can hit the enemy, so find a new one
if(num_valid < 1)
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
// in the original code, we returned where the "tentative return" variable was set,
// so return for real now, since we don't have a reason to remain in the function
if (tentative_return)
return;
}
// Maybe pick a new enemy, unless targeting has been taken over by scripting
if ( turret_should_pick_new_target(ss) && !ss->scripting_target_override ) {
Num_find_turret_enemy++;
int objnum = find_turret_enemy(ss, parent_objnum, &gpos, &gvec, ss->turret_enemy_objnum);
//Assert(objnum < 0 || is_target_beam_valid(tp, objnum));
if (objnum >= 0) {
if (objnum >= 0 && is_target_beam_valid(&ss->weapons, &Objects[objnum])) {
if (ss->turret_enemy_objnum == -1) {
ss->turret_enemy_objnum = objnum;
ss->targeted_subsys = NULL; // Turret has retargeted; reset subsystem - Valathil for Mantis #2652
@@ -2527,17 +2529,23 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
return;
}
if ( lep == nullptr ){
if ( lep == NULL ){
mprintf(("last enemy is null\n"));
return;
}
//This can't happen. See above code
//Assert(ss->turret_enemy_objnum != -1);
bool in_fov = turret_fov_test(ss, &gvec, &v2e);
bool something_was_ok_to_fire = false;
float dot;
bool in_fov;
in_fov = turret_fov_test(ss, &gvec, &v2e);
if (in_fov) {
// Ok, the turret is lined up... now line up a particular gun.
bool ok_to_fire = false;
bool something_was_ok_to_fire=false;
if (in_fov ) {
// Do salvo thing separately - to prevent messing up things
int number_of_firings;
@@ -2551,47 +2559,55 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
number_of_firings = num_valid;
}
for (int i = 0; i < number_of_firings; ++i)
for(i = 0; i < number_of_firings; i++)
{
int valid_index;
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
valid_index = 0;
else
valid_index = i;
auto wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[valid_index]);
// Forces the firing turret to retain the firingpoints of their weapons:
// if the turret has multiple banks, the first bank will only fire from the first firepoint,
// the second bank only from the second firepoint, and so on.
if (tp->flags[Model::Subsystem_Flags::Turret_fixed_fp])
{
int ffp_bank = valid_weapons[valid_index];
int ffp_pos = 0;
int ffp_bank;
ffp_bank = valid_weapons[i];
if (ffp_bank < MAX_SHIP_PRIMARY_BANKS)
ss->turret_next_fire_pos = ffp_bank;
{
ffp_pos = ffp_bank;
}
else
ss->turret_next_fire_pos = ffp_bank - MAX_SHIP_PRIMARY_BANKS + ss->weapons.num_primary_banks;
}
{
ffp_pos = ffp_bank - MAX_SHIP_PRIMARY_BANKS + ss->weapons.num_primary_banks;
}
// Ok, the turret is lined up... now line up a particular gun.
bool ok_to_fire = false;
ss->turret_next_fire_pos = ffp_pos;
}
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
ship_get_global_turret_gun_info(objp, ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
ship_get_global_turret_gun_info(&Objects[parent_objnum], ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
// Fire in the direction the turret is facing, not right at the target regardless of turret dir.
// [Yet this retail comment precedes the calculation of vector-to-enemy...]
vm_vec_sub(&v2e, &predicted_enemy_pos, &gpos);
dist_to_enemy = vm_vec_normalize(&v2e);
float dot = vm_vec_dot(&v2e, &gvec);
dot = vm_vec_dot(&v2e, &gvec);
// (flak jitter moved to after we obtain shoot_vector below)
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[0]);
else
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[i]);
// make sure to reset this for current weapon
ok_to_fire = false;
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
flak_jitter_aim(&v2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
// Fire if:
// dumbfire and nearly pointing at target.
// heat seeking and target in a fairly wide cone.
// aspect seeking and target is locked.
//turret_weapon_class = tp->turret_weapon_type;
bool in_sight = false;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_only_single_fov_for_turrets]) {
@@ -2609,7 +2625,6 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
}
}
// if dumbfire (lasers and non-homing missiles)
if ( !(wip->is_homing()) )
{
if ((dist_to_enemy < 75.0f) || in_sight)
@@ -2618,18 +2633,16 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
ok_to_fire = true;
}
}
// if heat seekers
else if ( wip->wi_flags[Weapon::Info_Flags::Homing_heat] )
{
{ // if heat seekers
if ((dist_to_enemy < 50.0f) || in_sight)
{
turret_update_enemy_in_range(ss, 2*wip->fire_wait);
ok_to_fire = true;
}
}
// if aspect seeker
else if ( wip->wi_flags[Weapon::Info_Flags::Homing_aspect] )
{
{ // if aspect seeker
if ((dist_to_enemy < 50.0f) || in_sight)
{
turret_update_enemy_in_range(ss, 2*wip->fire_wait);
@@ -2639,9 +2652,8 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
ok_to_fire = true;
}
}
// if javelin heat seeker
else if ( wip->wi_flags[Weapon::Info_Flags::Homing_javelin] )
{
{ // if javelin heat seeker
if ((dist_to_enemy < 50.0f) || in_sight)
{
turret_update_enemy_in_range(ss, 2*wip->fire_wait);
@@ -2655,7 +2667,6 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
}
}
// maybe check that the gun vector doesn't intersect with the hull
if ( ok_to_fire && (tp->flags[Model::Subsystem_Flags::Turret_hull_check]) ) {
int model_num = Ship_info[shipp->ship_info_index].model_num;
vec3d end;
@@ -2680,8 +2691,8 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
{
// starting animation checks
if (ss->turret_animation_position == MA_POS_NOT_SET) {
if ( model_anim_start_type(shipp, AnimationTriggerType::TurretFiring, ss->system_info->subobj_num, 1) ) {
ss->turret_animation_done_time = model_anim_get_time_type(shipp, AnimationTriggerType::TurretFiring, ss->system_info->subobj_num);
if ( model_anim_start_type(shipp, TRIGGER_TYPE_TURRET_FIRING, ss->system_info->subobj_num, 1) ) {
ss->turret_animation_done_time = model_anim_get_time_type(shipp, TRIGGER_TYPE_TURRET_FIRING, ss->system_info->subobj_num);
ss->turret_animation_position = MA_POS_SET;
}
}
@@ -2695,45 +2706,32 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
if ( ok_to_fire )
{
// finally!
something_was_ok_to_fire = true;
Num_turrets_fired++;
// (Despite the retail comment above, retail actually fired toward the enemy; v2e = vector-to-enemy)
vec3d shoot_vector = v2e;
if (tp->flags[Model::Subsystem_Flags::Fire_on_normal])
shoot_vector = gvec;
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
if (wip->wi_flags[Weapon::Info_Flags::Flak]) {
flak_jitter_aim(&shoot_vector, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &gpos, &shoot_vector, &predicted_enemy_pos);
}
else
{
turret_update_enemy_in_range(ss, -4*wip->fire_wait);
if (tp->flags[Model::Subsystem_Flags::Use_multiple_guns])
set_turret_weapon_next_fire_stamp(swp, valid_weapons[valid_index], 500);
//Pass along which gun we are using
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &v2e, &predicted_enemy_pos);
else
ss->turret_next_fire_stamp = timestamp(500);
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &v2e, &predicted_enemy_pos);
} else {
// make sure salvo fire mode does not turn into autofire
if ((tp->flags[Model::Subsystem_Flags::Turret_salvo]) && ((i + 1) == number_of_firings)) {
ai_info *parent_aip = &Ai_info[shipp->ai_index];
turret_set_next_fire_timestamp(valid_weapons[valid_index], wip, ss, parent_aip);
ai_info *parent_aip = &Ai_info[Ships[Objects[parent_objnum].instance].ai_index];
turret_set_next_fire_timestamp(valid_weapons[0], wip, ss, parent_aip);
}
}
// we are done firing, so fire the next weapon from the next firing point
// (This was originally done under the "We're ready to fire..." comment)
ss->turret_next_fire_pos++;
}
if (!something_was_ok_to_fire)
if(!something_was_ok_to_fire)
{
if (ss->turret_best_weapon >= 0) {
//Impose a penalty on turret accuracy for losing site of its goal, or just not being able to fire.
turret_update_enemy_in_range(ss, -4*Weapon_info[ss->turret_best_weapon].fire_wait);
}
ss->turret_next_fire_stamp = timestamp(500);
// If nothing is OK to fire (lost track of the target?)
// reset the target (so we don't continue to track what we can't hit)
if (tp->flags[Model::Subsystem_Flags::Turret_only_target_if_can_fire])
@@ -2744,31 +2742,37 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss)
}
else
{
//something did fire, get the lowest valid timestamp
// don't do this if we already set a turret timestamp previously in the function
if (timestamp_until(ss->turret_next_fire_stamp) <= 0)
ss->turret_next_fire_stamp = INT_MAX;
//something did fire, get the lowest valid timestamp
for (i = 0; i < MAX_SHIP_WEAPONS; i++)
{
int minimum_stamp = -1;
for (int i = 0; i < MAX_SHIP_WEAPONS; ++i)
if (i < MAX_SHIP_PRIMARY_BANKS)
{
int stamp = (i < MAX_SHIP_PRIMARY_BANKS) ? swp->next_primary_fire_stamp[i] : swp->next_secondary_fire_stamp[i - MAX_SHIP_PRIMARY_BANKS];
//timestamp range is 2 to INT_MAX/2
if (swp->next_primary_fire_stamp[i] < 2) continue;
if (swp->next_primary_fire_stamp[i] < ss->turret_next_fire_stamp)
{
ss->turret_next_fire_stamp = swp->next_primary_fire_stamp[i];
}
}
else
{
//timestamp range is 2 to INT_MAX/2
if (swp->next_secondary_fire_stamp[i - MAX_SHIP_PRIMARY_BANKS] < 2) continue;
// valid timestamps start at 2; stamp must be in the future
if (stamp < 2 || timestamp_until(stamp) <= 0)
continue;
if (swp->next_secondary_fire_stamp[i - MAX_SHIP_PRIMARY_BANKS] < ss->turret_next_fire_stamp)
{
ss->turret_next_fire_stamp = swp->next_secondary_fire_stamp[i - MAX_SHIP_PRIMARY_BANKS];
}
// find minimum
if (minimum_stamp < 0 || timestamp_until(stamp) < timestamp_until(minimum_stamp))
minimum_stamp = stamp;
}
// set turret timestamp, or 100ms for sanity's sake
if (minimum_stamp >= 0)
ss->turret_next_fire_stamp = minimum_stamp;
else
ss->turret_next_fire_stamp = timestamp(100);
}
// Wanderer -- sanity check
// if timestamp is still at int_max reset the wait to 100 ms instead of locking the turret for the rest of the game
if (ss->turret_next_fire_stamp == INT_MAX)
ss->turret_next_fire_stamp = timestamp(100);
}
}
else
+14 -28
View File
@@ -151,21 +151,14 @@ int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bp
bit_16 = (ushort)pix;
break;
case 8:
// 8 bit-per-pixel aa bitmaps are a bit special since they only use a palette index value in the range [0, 15]. These
// palette indexes must be remapped to alpha values between [0, 255] which is what graphics code expects. Palette
// range [0, 14] is a gradient from black to white, and palette index 15 is a special color which indicates the background
// area of a HUD gauge. Retail code uses the final alpha value for index 1 for this special index to give gauges a dark
// transparent background.
if (pix > 15) {
bit_8 = 255;
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
if (pix >= 15) {
bit_8 = 0;
} else {
bit_8 = (ubyte)(pix * 17);
}
else if (pix == 15) {
bit_8 = 18;
}
else {
bit_8 = (ubyte)(pix * 18);
}
break;
default:
Int3();
@@ -249,21 +242,14 @@ int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0,
bit_16 = (ushort)pix;
break;
case 8 :
// 8 bit-per-pixel aa bitmaps are a bit special since they only use a palette index value in the range [0, 15]. These
// palette indexes must be remapped to alpha values between [0, 255] which is what graphics code expects. Palette
// range [0, 14] is a gradient from black to white, and palette index 15 is a special color which indicates the background
// area of a HUD gauge. Retail code uses the final alpha value for index 1 for this special index to give gauges a dark
// transparent background.
if (pix > 15) {
bit_8 = 255;
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
if (pix >= 15) {
bit_8 = 0;
} else {
bit_8 = (ubyte)(pix * 17);
}
else if (pix == 15) {
bit_8 = 18;
}
else {
bit_8 = (ubyte)(pix * 18);
}
break;
default :
Int3();
+27 -47
View File
@@ -36,7 +36,6 @@
#include "particle/particle.h"
#include "render/3d.h"
#include "ship/ship.h"
#include "ship/shipfx.h"
#include "ship/shiphit.h"
#include "species_defs/species_defs.h"
#include "stats/scoring.h"
@@ -929,6 +928,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
Assert( other_obj->type == OBJ_WEAPON );
mc.model_instance_num = Asteroids[num].model_instance_num;
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
model_clear_instance( mc.model_num );
mc.orient = &pasteroid->orient; // The object's orient
mc.pos = &pasteroid->pos; // The object's position
mc.p0 = &other_obj->last_pos; // Point 1 of ray to check
@@ -942,11 +942,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
if (hitnormal)
{
vec3d normal;
if (mc.model_instance_num >= 0)
model_instance_find_world_dir(&normal, &mc.hit_normal, mc.model_instance_num, mc.hit_submodel, mc.orient);
else
model_find_world_dir(&normal, &mc.hit_normal, mc.model_num, mc.hit_submodel, mc.orient);
model_find_world_dir(&normal, &mc.hit_normal, mc.model_num, mc.hit_submodel, mc.orient);
*hitnormal = normal;
}
@@ -1014,51 +1010,51 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// first test against the sphere - if this fails then don't do any submodel tests
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
SCP_vector<int> submodel_vector;
polymodel_instance *pmi;
if (model_collide(&mc)) {
// Set earliest hit time
asteroid_hit_info->hit_time = FLT_MAX;
auto pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
auto pm = model_get(pmi->model_num);
// Do collision the cool new way
if ( asteroid_hit_info->collide_rotate ) {
// We collide with the sphere, find the list of rotating submodels and test one at a time
SCP_vector<int> submodel_vector;
model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
// turn off all rotating submodels, collide against only 1 at a time.
// turn off collision detection for all rotating submodels
for (auto submodel: submodel_vector) {
pmi->submodel[submodel].collision_checked = true;
// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
// turn off all rotating submodels and test for collision
for (size_t j=0; j<submodel_vector.size(); j++) {
pmi->submodel[submodel_vector[j]].collision_checked = true;
}
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
// check each submodel in turn
for (auto submodel: submodel_vector) {
auto smi = &pmi->submodel[submodel];
// turn on just one submodel for collision test
smi->collision_checked = false;
// check each submodel in turn
for (size_t i=0; i<submodel_vector.size(); i++) {
// turn on submodel for collision test
pmi->submodel[submodel_vector[i]].collision_checked = false;
// set angles for last frame (need to set to prev to get p0)
angles copy_angles = smi->angs;
angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
// find the start and end positions of the sphere in submodel RF
smi->angs = smi->prev_angs;
world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel, &heavy_obj->last_orient, &heavy_obj->last_pos);
pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
world_find_model_instance_point(&p0, &light_obj->last_pos, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
smi->angs = copy_angles;
world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel, &heavy_obj->orient, &heavy_obj->pos);
pmi->submodel[submodel_vector[i]].angs = copy_angles;
world_find_model_instance_point(&p1, &light_obj->pos, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
mc.p0 = &p0;
mc.p1 = &p1;
mc.orient = &vmd_identity_matrix;
mc.submodel_num = submodel;
mc.submodel_num = submodel_vector[i];
if ( model_collide(&mc) ) {
if ( mc.hit_dist < asteroid_hit_info->hit_time ) {
@@ -1069,23 +1065,23 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// set up asteroid_hit_info for rotating submodel
if (asteroid_hit_info->edge_hit == 0) {
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, pm, pmi, mc.hit_submodel, &heavy_obj->orient);
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, Ships[heavy_obj->instance].model_instance_num, mc.hit_submodel, &heavy_obj->orient);
}
// find position in submodel RF of light object at collison
vec3d int_light_pos, diff;
vm_vec_sub(&diff, mc.p1, mc.p0);
vm_vec_scale_add(&int_light_pos, mc.p0, &diff, mc.hit_dist);
model_instance_find_world_point(&asteroid_hit_info->light_collision_cm_pos, &int_light_pos, pm, pmi, mc.hit_submodel, &heavy_obj->orient, &zero);
model_instance_find_world_point(&asteroid_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
}
}
// Don't look at this submodel again
smi->collision_checked = true;
pmi->submodel[submodel_vector[i]].collision_checked = true;
}
}
// Now complete base model collision checks that do not take into account rotating submodels.
// Recover and do usual ship_ship collision, but without rotating submodels
mc.flags = copy_flags;
*mc.p0 = copy_p0;
*mc.p1 = copy_p1;
@@ -1101,7 +1097,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// get collision normal if not edge hit
if (asteroid_hit_info->edge_hit == 0) {
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, pm, pmi, mc.hit_submodel, &heavy_obj->orient);
model_instance_find_obj_dir(&asteroid_hit_info->collision_normal, &mc.hit_normal, Ships[heavy_obj->instance].model_instance_num, mc.hit_submodel, &heavy_obj->orient);
}
// find position in submodel RF of light object at collison
@@ -1117,6 +1113,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// Asteroid is heavier obj
mc.model_instance_num = Asteroids[num].model_instance_num;
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
model_clear_instance( mc.model_num );
mc.orient = &pasteroid->orient; // The object's orient
mc.radius = model_get_core_radius(Ship_info[Ships[pship_obj->instance].ship_info_index].model_num);
@@ -1140,23 +1137,6 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
}
}
// check if the hit point is beyond the clip plane if the ship is warping.
if (mc_ret_val) {
WarpEffect* warp_effect = nullptr;
ship* shipp = &Ships[pship_obj->instance];
// this is extremely confusing but mc.hit_point_world isn't actually in world coords
// everything above was calculated relative to the heavy's position
vec3d actual_world_hit_pos = mc.hit_point_world + heavy_obj->pos;
if ((shipp->is_arriving()) && (shipp->warpin_effect != nullptr))
warp_effect = shipp->warpin_effect;
else if ((shipp->flags[Ship::Ship_Flags::Depart_warp]) && (shipp->warpout_effect != nullptr))
warp_effect = shipp->warpout_effect;
if (warp_effect != nullptr && point_is_clipped_by_warp(&actual_world_hit_pos, warp_effect))
mc_ret_val = 0;
}
if ( mc_ret_val ) {
+26 -26
View File
@@ -108,7 +108,7 @@ bool Sel_NextNav()
// ********************************************************************************************
const vec3d *NavPoint::GetPosition()
vec3d *NavPoint::GetPosition()
{
if (flags & NP_WAYPOINT)
{
@@ -123,7 +123,7 @@ const vec3d *NavPoint::GetPosition()
}
// ********************************************************************************************
bool CanAutopilot(const vec3d *targetPos, bool send_msg)
bool CanAutopilot(vec3d targetPos, bool send_msg)
{
if (CurrentNav == -1)
{
@@ -140,7 +140,7 @@ bool CanAutopilot(const vec3d *targetPos, bool send_msg)
}
// You cannot autopilot if you're within 1000 meters of your destination nav point
if (vm_vec_dist_quick(targetPos, Navs[CurrentNav].GetPosition()) < 1000) {
if (vm_vec_dist_quick(&targetPos, Navs[CurrentNav].GetPosition()) < 1000) {
if (send_msg)
send_autopilot_msgID(NP_MSG_FAIL_TOCLOSE);
return false;
@@ -156,7 +156,7 @@ bool CanAutopilot(const vec3d *targetPos, bool send_msg)
&& !(Ship_info[Ships[other_objp->instance].ship_info_index].flags[Ship::Info_Flags::Cargo])) // ignore cargo
{
// Cannot autopilot if enemy within AutopilotMinEnemyDistance meters
if (vm_vec_dist_quick(targetPos, &other_objp->pos) < AutopilotMinEnemyDistance) {
if (vm_vec_dist_quick(&targetPos, &other_objp->pos) < AutopilotMinEnemyDistance) {
if (send_msg)
send_autopilot_msgID(NP_MSG_FAIL_HOSTILES);
return false;
@@ -173,7 +173,7 @@ bool CanAutopilot(const vec3d *targetPos, bool send_msg)
if (Asteroids[n].flags & AF_USED)
{
// Cannot autopilot if asteroid within AutopilotMinAsteroidDistance meters
if (vm_vec_dist_quick(targetPos, &Objects[Asteroids[n].objnum].pos) < AutopilotMinAsteroidDistance) {
if (vm_vec_dist_quick(&targetPos, &Objects[Asteroids[n].objnum].pos) < AutopilotMinAsteroidDistance) {
if (send_msg)
send_autopilot_msgID(NP_MSG_FAIL_HAZARD);
return false;
@@ -409,11 +409,11 @@ bool StartAutopilot()
if (leader_objp != &Objects[Ships[i].objnum])
{
// not leader.. get our position relative to leader
get_absolute_wing_pos(&goal_point, leader_objp, wingnum, wing_index, aip->ai_flags[AI::AI_Flags::Formation_object], true);
get_absolute_wing_pos_autopilot(&goal_point, leader_objp, wing_index, aip->ai_flags[AI::AI_Flags::Formation_object]);
}
else
{
ai_clear_wing_goals(&Wings[wingnum]);
ai_clear_wing_goals(wingnum);
j = 1+int( (float)floor(double(wcount-1)/2.0) );
switch (wcount % 2)
{
@@ -484,7 +484,7 @@ bool StartAutopilot()
//ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, target_shipname, wingnum );
//ai_clear_ship_goals( &(Ai_info[Ships[num].ai_index]) );
ai_clear_wing_goals( &Wings[i] );
ai_clear_wing_goals( i );
if (Navs[CurrentNav].flags & NP_WAYPOINT)
{
@@ -989,7 +989,7 @@ void nav_warp(bool prewarp=false)
/* using the vector of the flight leaders's path, simulate moving the
flight along this path by checking the autopilot conditions as specific
intervals along the path*/
while (CanAutopilot(&tpos))
while (CanAutopilot(tpos))
{
vm_vec_add(&tpos, &tpos, &pos);
}
@@ -1192,7 +1192,7 @@ void send_autopilot_msgID(int msgid)
}
// ********************************************************************************************
void send_autopilot_msg(const char *msg, const char *snd)
void send_autopilot_msg(char *msg, char *snd)
{
// setup
if (audio_handle != -1)
@@ -1312,7 +1312,7 @@ void parse_autopilot_table(const char *filename)
// ********************************************************************************************
// Finds a Nav point by name
int FindNav(const char *Nav)
int FindNav(char *Nav)
{
for (int i = 0; i < MAX_NAVPOINTS; i++)
{
@@ -1325,7 +1325,7 @@ int FindNav(const char *Nav)
// ********************************************************************************************
// Removes a Nav
bool DelNavPoint(const char *Nav)
bool DelNavPoint(char *Nav)
{
int n = FindNav(Nav);
@@ -1354,7 +1354,7 @@ bool DelNavPoint(int nav)
// ********************************************************************************************
// adds a Nav
bool AddNav_Ship(const char *Nav, const char *TargetName, int flags)
bool AddNav_Ship(char *Nav, char *TargetName, int flags)
{
// find an empty nav - should be the end
@@ -1397,7 +1397,7 @@ bool AddNav_Ship(const char *Nav, const char *TargetName, int flags)
}
bool AddNav_Waypoint(const char *Nav, const char *WP_Path, int node, int flags)
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags)
{
// find an empty nav - should be the end
@@ -1435,7 +1435,7 @@ bool AddNav_Waypoint(const char *Nav, const char *WP_Path, int node, int flags)
// ********************************************************************************************
//Get Flags
int Nav_Get_Flags(const char *Nav)
int Nav_Get_Flags(char *Nav)
{
int flags = 0;
@@ -1451,7 +1451,7 @@ int Nav_Get_Flags(const char *Nav)
// Sexp Accessors
//Generic
bool Nav_Set_Flag(const char *Nav, int flag)
bool Nav_Set_Flag(char *Nav, int flag)
{
Assert(!(flag & NP_VALIDTYPE));
int nav = FindNav(Nav);
@@ -1467,7 +1467,7 @@ bool Nav_Set_Flag(const char *Nav, int flag)
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool Nav_UnSet_Flag(const char *Nav, int flag)
bool Nav_UnSet_Flag(char *Nav, int flag)
{
Assert(!(flag & NP_VALIDTYPE));
@@ -1484,7 +1484,7 @@ bool Nav_UnSet_Flag(const char *Nav, int flag)
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//Named
bool Nav_Set_Hidden(const char *Nav)
bool Nav_Set_Hidden(char *Nav)
{
return Nav_Set_Flag(Nav, NP_HIDDEN);
@@ -1492,14 +1492,14 @@ bool Nav_Set_Hidden(const char *Nav)
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool Nav_Set_NoAccess(const char *Nav)
bool Nav_Set_NoAccess(char *Nav)
{
return Nav_Set_Flag(Nav, NP_NOACCESS);
}
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool Nav_Set_Visited(const char *Nav)
bool Nav_Set_Visited(char *Nav)
{
return Nav_Set_Flag(Nav, NP_VISITED);
@@ -1507,28 +1507,28 @@ bool Nav_Set_Visited(const char *Nav)
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool Nav_UnSet_Hidden(const char *Nav)
bool Nav_UnSet_Hidden(char *Nav)
{
return Nav_UnSet_Flag(Nav, NP_HIDDEN);
}
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool Nav_UnSet_NoAccess(const char *Nav)
bool Nav_UnSet_NoAccess(char *Nav)
{
return Nav_UnSet_Flag(Nav, NP_NOACCESS);
}
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool Nav_UnSet_Visited(const char *Nav)
bool Nav_UnSet_Visited(char *Nav)
{
return Nav_UnSet_Flag(Nav, NP_VISITED);
}
// ********************************************************************************************
// Selects a navpoint by name.
void SelectNav(const char *Nav)
void SelectNav(char *Nav)
{
for (int i = 0; i < MAX_NAVPOINTS; i++)
{
@@ -1547,7 +1547,7 @@ void DeselectNav()
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
unsigned int DistanceTo(const char *nav)
unsigned int DistanceTo(char *nav)
{
int n = FindNav(nav);
@@ -1564,7 +1564,7 @@ unsigned int DistanceTo(int nav)
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
bool IsVisited(const char *nav)
bool IsVisited(char *nav)
{
int n = FindNav(nav);
+21 -21
View File
@@ -32,17 +32,17 @@ public:
char m_NavName[32];
int flags;
const void *target_obj;
void *target_obj;
int waypoint_num; //only used when flags & NP_WAYPOINT
const vec3d *GetPosition();
vec3d *GetPosition();
void clear()
{
m_NavName[0] = 0;
flags = 0;
target_obj = nullptr;
target_obj = NULL;
waypoint_num = -1;
}
};
@@ -82,11 +82,11 @@ bool Sel_NextNav();
// * No asteroids within AutopilotMinAsteroidDistance meters
// * Destination > 1,000 meters away
// * Support ship not present or is actively leaving
bool CanAutopilot(const vec3d *targetPos, bool send_msg=false);
bool CanAutopilot(vec3d targetPos, bool send_msg=false);
// Check if autopilot is allowed at player's current position
// See CanAutopilot(vec3d, bool) for more information
inline bool CanAutopilot(bool send_msg=false) { return CanAutopilot(&Player_obj->pos, send_msg); }
inline bool CanAutopilot(bool send_msg=false) { return CanAutopilot(Player_obj->pos, send_msg); }
// Engages autopilot
// This does:
@@ -120,42 +120,42 @@ void NavSystem_Init();
void parse_autopilot_table(const char *filename);
// Finds a Nav point by name
int FindNav(const char *Nav);
int FindNav(char *Nav);
// Selects a Nav point by name
void SelectNav(const char *Nav);
void SelectNav(char *Nav);
// Deselects any navpoint selected.
void DeselectNav();
// Removes a Nav
bool DelNavPoint(const char *Nav);
bool DelNavPoint(char *Nav);
bool DelNavPoint(int nav);
// adds a Nav
bool AddNav_Ship(const char *Nav, const char *TargetName, int flags);
bool AddNav_Waypoint(const char *Nav, const char *WP_Path, int node, int flags);
bool AddNav_Ship(char *Nav, char *TargetName, int flags);
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags);
// Sexp Accessors
bool Nav_Set_Flag(const char *Nav, int flag);
bool Nav_UnSet_Flag(const char *Nav, int flag);
bool Nav_Set_Flag(char *Nav, int flag);
bool Nav_UnSet_Flag(char *Nav, int flag);
bool Nav_Set_Hidden(const char *Nav);
bool Nav_Set_NoAccess(const char *Nav);
bool Nav_Set_Visited(const char *Nav);
bool Nav_Set_Hidden(char *Nav);
bool Nav_Set_NoAccess(char *Nav);
bool Nav_Set_Visited(char *Nav);
bool Nav_UnSet_Hidden(const char *Nav);
bool Nav_UnSet_NoAccess(const char *Nav);
bool Nav_UnSet_Visited(const char *Nav);
bool Nav_UnSet_Hidden(char *Nav);
bool Nav_UnSet_NoAccess(char *Nav);
bool Nav_UnSet_Visited(char *Nav);
// Useful functions
unsigned int DistanceTo(const char *nav);
unsigned int DistanceTo(char *nav);
unsigned int DistanceTo(int nav);
bool IsVisited(const char *nav);
bool IsVisited(char *nav);
bool IsVisited(int nav);
void send_autopilot_msg(const char *msg, const char *snd=nullptr);
void send_autopilot_msg(char *msg, char *snd=NULL);
void send_autopilot_msgID(int msgid);
#endif
+22 -10
View File
@@ -9,6 +9,18 @@
*
*/
/**
* @file bm_internal.h
* These are functions and types used by bmpman and a few others.
*
* @details It is a "protected" header that requires BMPMAN_INTERNAL to be defined before it can be included. This is to
* provide a small measure of safety since this functions can cause problems if not used correctly
*/
#ifndef BMPMAN_INTERNAL
#error The file header "bmpman/bm_internal.h" is protected. Make sure you know what you are doing!
#endif
#include "bmpman/bmpman.h"
#include <array>
@@ -46,7 +58,7 @@ union bm_extra_info {
// Stuff needed for user bitmaps
void* data; //!< For user bitmaps, this is where the data comes from
ubyte bpp; //!< For user bitmaps, this is what format the data is
ushort flags; //!< For user bitmaps, Flags passed to bm_create
ubyte flags; //!< For user bitmaps, Flags passed to bm_create
} user;
};
@@ -70,7 +82,7 @@ struct bitmap_entry {
// Stuff to keep track of usage
ubyte preloaded; //!< If set, then this was loaded from the lst file
int preload_count; //!< how many times this gets used in game, for unlocking
ushort used_flags; //!< What flags it was accessed thru
ubyte used_flags; //!< What flags it was accessed thru
int load_count;
bitmap bm; //!< Bitmap info
@@ -93,14 +105,14 @@ struct bitmap_slot {
};
// image specific lock functions
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
const size_t BM_BLOCK_SIZE = 4096;
+21 -72
View File
@@ -81,8 +81,6 @@ static bool bm_inited = false;
static uint Bm_next_signature = 0x1234;
static int Bm_low_mem = 0;
SCP_map<int,ubyte*> bm_lookup_cache;
/**
* How much RAM bmpman can use for textures.
*
@@ -157,20 +155,16 @@ bitmap_lookup::bitmap_lookup(int bitmap_num):
Width = be->bm.w;
Height = be->bm.h;
Bitmap_data = (ubyte*)vm_malloc(Width * Height * Num_channels * sizeof(ubyte));
auto cache_search = bm_lookup_cache.find(bitmap_num);
if (cache_search == bm_lookup_cache.end()) {
Bitmap_data = (ubyte*)vm_malloc(Width * Height * Num_channels * sizeof(ubyte));
gr_get_bitmap_from_texture((void*)Bitmap_data, bitmap_num);
bm_lookup_cache.insert({bitmap_num, Bitmap_data});
} else {
Bitmap_data = cache_search->second;
}
gr_get_bitmap_from_texture((void*)Bitmap_data, bitmap_num);
}
bitmap_lookup::~bitmap_lookup()
{
if ( Bitmap_data != NULL ) {
vm_free(Bitmap_data);
}
}
bool bitmap_lookup::valid()
@@ -194,17 +188,10 @@ float bitmap_lookup::get_channel_alpha(float u, float v)
return i2fl(Bitmap_data[(y*Width + x)*Num_channels + 3]) / 255.0f;
}
void clear_bm_lookup_cache() {
for(auto &iter: bm_lookup_cache) {
free(iter.second);
}
bm_lookup_cache.clear();
}
/**
* Converts the bitmap referenced by bmp to the type specified by flags
*/
static void bm_convert_format(bitmap *bmp, ushort flags);
static void bm_convert_format(bitmap *bmp, ubyte flags);
/**
* Frees a bitmap's data if it can
@@ -584,7 +571,7 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
return n;
}
void bm_convert_format(bitmap *bmp, ushort flags) {
void bm_convert_format(bitmap *bmp, ubyte flags) {
int idx;
// no transparency for 24 bpp images
@@ -849,7 +836,7 @@ void bm_get_frame_usage(int *ntotal, int *nnew) {
#endif
}
int bm_get_info(int handle, int *w, int * h, ushort* flags, int *nframes, int *fps) {
int bm_get_info(int handle, int *w, int * h, ubyte * flags, int *nframes, int *fps) {
bitmap * bmp;
if (!bm_inited) return -1;
@@ -974,9 +961,6 @@ int bm_is_compressed(int num) {
case BM_TYPE_DXT5:
return DDS_DXT5;
case BM_TYPE_BC7:
return DDS_BC7;
case BM_TYPE_CUBEMAP_DXT1:
return DDS_CUBEMAP_DXT1;
@@ -1050,10 +1034,6 @@ static int bm_load_info(BM_TYPE type, const char *filename, CFILE *img_cfp, int
*c_type = BM_TYPE_DXT5;
break;
case DDS_BC7:
*c_type = BM_TYPE_BC7;
break;
case DDS_UNCOMPRESSED:
*c_type = BM_TYPE_DDS;
break;
@@ -1320,7 +1300,7 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
/**
* Lock an image files data into memory
*/
static int bm_load_image_data(int handle, int bpp, ushort flags, bool nodebug)
static int bm_load_image_data(int handle, int bpp, ubyte flags, bool nodebug)
{
BM_TYPE c_type = BM_TYPE_NONE;
int true_bpp;
@@ -1396,7 +1376,6 @@ static int bm_load_image_data(int handle, int bpp, ushort flags, bool nodebug)
case BM_TYPE_DXT1:
case BM_TYPE_DXT3:
case BM_TYPE_DXT5:
case BM_TYPE_BC7:
case BM_TYPE_CUBEMAP_DDS:
case BM_TYPE_CUBEMAP_DXT1:
case BM_TYPE_CUBEMAP_DXT3:
@@ -1836,7 +1815,7 @@ int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **
if (!res.found)
return -1;
CFILE *test = cfopen_special(res, "rb", dir_type);
CFILE *test = cfopen_special(res.full_name.c_str(), "rb", res.size, res.offset, res.data_ptr, dir_type);
if (test != NULL) {
if (img_cfp != NULL)
@@ -1846,11 +1825,11 @@ int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **
}
// umm, that's not good...
Warning(LOCATION, "Could not open file %s!", real_filename);
Warning(LOCATION, "Could not open file %s!", res.full_name.c_str());
return -1;
}
bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
bitmap * bm_lock(int handle, int bpp, ubyte flags, bool nodebug) {
bitmap *bmp;
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
@@ -1872,7 +1851,7 @@ bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
Assert(bpp == 8);
} else if ((flags & BMP_TEX_NONCOMP) && (!(flags & BMP_TEX_COMP))) {
Assert(bpp >= 16); // cheating but bpp passed isn't what we normally end up with
} else if ((flags & BMP_TEX_DXT1) || (flags & BMP_TEX_DXT3) || (flags & BMP_TEX_DXT5) || (flags & BMP_TEX_BC7)) {
} else if ((flags & BMP_TEX_DXT1) || (flags & BMP_TEX_DXT3) || (flags & BMP_TEX_DXT5)) {
Assert(bpp >= 16); // cheating but bpp passed isn't what we normally end up with
} else if (flags & BMP_TEX_CUBEMAP) {
Assert((be->type == BM_TYPE_CUBEMAP_DDS) ||
@@ -1951,7 +1930,7 @@ bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
return bmp;
}
void bm_lock_ani(int /*handle*/, bitmap_slot *bs, bitmap* /*bmp*/, int bpp, ushort flags) {
void bm_lock_ani(int /*handle*/, bitmap_slot *bs, bitmap* /*bmp*/, int bpp, ubyte flags) {
anim *the_anim;
anim_instance *the_anim_instance;
bitmap *bm;
@@ -2077,7 +2056,7 @@ void bm_lock_ani(int /*handle*/, bitmap_slot *bs, bitmap* /*bmp*/, int bpp, usho
}
void bm_lock_apng(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort /*flags*/) {
void bm_lock_apng(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte /*flags*/) {
auto be = &bs->entry;
int first_frame = be->info.ani.first_frame;
auto first_entry = bm_get_entry(first_frame);
@@ -2127,7 +2106,7 @@ void bm_lock_apng(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort
}
void bm_lock_dds(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /*flags*/) {
void bm_lock_dds(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ubyte /*flags*/) {
ubyte *data = NULL;
int error;
ubyte dds_bpp = 0;
@@ -2191,7 +2170,7 @@ void bm_lock_dds(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /
#endif
}
void bm_lock_jpg(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort /*flags*/) {
void bm_lock_jpg(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte /*flags*/) {
ubyte *data = NULL;
int d_size = 0;
int jpg_error = JPEG_ERROR_INVALID;
@@ -2238,7 +2217,7 @@ void bm_lock_jpg(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort /*fla
#endif
}
void bm_lock_pcx(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags) {
void bm_lock_pcx(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags) {
ubyte *data;
int pcx_error;
char filename[MAX_FILENAME_LEN];
@@ -2283,7 +2262,7 @@ void bm_lock_pcx(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags
bm_convert_format(bmp, flags);
}
void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /*flags*/) {
void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ubyte /*flags*/) {
ubyte *data = NULL;
//assume 32 bit - libpng should expand everything
int d_size;
@@ -2328,7 +2307,7 @@ void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /
#endif
}
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags) {
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags) {
ubyte *data = NULL;
int byte_size;
char filename[MAX_FILENAME_LEN];
@@ -2387,7 +2366,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags
bm_convert_format(bmp, flags);
}
void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags) {
void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags) {
auto be = &bs->entry;
// Unload any existing data
@@ -2669,10 +2648,6 @@ void bm_page_in_texture(int bitmapnum, int nframes) {
frame_entry->used_flags = BMP_TEX_DXT5;
continue;
case BM_TYPE_BC7:
frame_entry->used_flags = BMP_TEX_BC7;
continue;
case BM_TYPE_CUBEMAP_DXT1:
case BM_TYPE_CUBEMAP_DXT3:
case BM_TYPE_CUBEMAP_DXT5:
@@ -2714,10 +2689,6 @@ void bm_page_in_xparent_texture(int bitmapnum, int nframes) {
entry->used_flags = BMP_TEX_DXT5;
continue;
case BM_TYPE_BC7:
entry->used_flags = BMP_TEX_BC7;
continue;
case BM_TYPE_CUBEMAP_DXT1:
case BM_TYPE_CUBEMAP_DXT3:
case BM_TYPE_CUBEMAP_DXT5:
@@ -2854,28 +2825,6 @@ int bm_release(int handle, int clear_render_targets) {
return 1;
}
bool bm_release_rendertarget(int handle) {
Assert(handle >= 0);
bitmap_entry* be = bm_get_entry(handle);
if (be->type == BM_TYPE_NONE) {
return false; // Already been released?
}
Assertion(be->handle == handle, "Invalid bitmap handle number %d (expected %d) for %s passed to bm_release_rendertarget()\n", be->handle, handle, be->filename);
Assertion(!bm_is_anim(be), "Cannot release a render target of an animation (bitmap handle number %d for %s)!\n", be->handle, be->filename);
if (!((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
nprintf(("BmpMan", "Tried to release a render target of a non-rendered bitmap!\n"));
return false;
}
gr_bm_free_data(bm_get_slot(handle), false);
return true;
}
int bm_reload(int bitmap_handle, const char* filename) {
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
+6 -25
View File
@@ -40,12 +40,11 @@
#define BMP_TEX_DXT1 (1<<3) //!< dxt1 compressed 8r8g8b1a (24bit)
#define BMP_TEX_DXT3 (1<<4) //!< dxt3 compressed 8r8g8b4a (32bit)
#define BMP_TEX_DXT5 (1<<5) //!< dxt5 compressed 8r8g8b8a (32bit)
#define BMP_TEX_BC7 (1<<6) //!< BC7 compressed 8r8g8b8a (32bit)
#define BMP_TEX_CUBEMAP (1<<7) //!< a texture made for cubic environment map
#define BMP_MASK_BITMAP (1<<8) //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
#define BMP_TEX_CUBEMAP (1<<6) //!< a texture made for cubic environment map
#define BMP_MASK_BITMAP (1<<7) //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
// Combined flags
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 | BMP_TEX_BC7 ) //!< Compressed textures
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 ) //!< Compressed textures
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER ) //!< Non-compressed textures
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP ) //!< Any texture
@@ -75,7 +74,6 @@ enum BM_TYPE
BM_TYPE_DXT1, //!< 24 bit with switchable alpha
BM_TYPE_DXT3, //!< 32 bit with 4 bit alpha
BM_TYPE_DXT5, //!< 32 bit with 8 bit alpha
BM_TYPE_BC7, //!< 32-bit with variable alpha
BM_TYPE_CUBEMAP_DDS, //!< generic DDS cubemap (uncompressed cubemap surface)
BM_TYPE_CUBEMAP_DXT1, //!< 24-bit cubemap (compressed cubemap surface)
BM_TYPE_CUBEMAP_DXT3, //!< 32-bit cubemap (compressed cubemap surface)
@@ -93,7 +91,7 @@ struct bitmap
short rowsize; //!< What you need to add to go to next row
int bpp; //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
int true_bpp; //!< The image's actual bitdepth
ushort flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
ubyte flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
ptr_u data; //!< Pointer to data, or maybe offset into VRAM.
ubyte *palette; /**< @brief Pointer to this bitmap's palette (if it has one).
* @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
@@ -167,8 +165,6 @@ public:
float get_channel_alpha(float u, float v);
};
void clear_bm_lookup_cache();
/**
* @brief Loads a bitmap so we can draw with it later.
*
@@ -261,21 +257,6 @@ int bm_unload_fast(int handle, int clear_render_targets = 0);
*/
int bm_release(int handle, int clear_render_targets = 0);
/**
* @brief Detaches the render target of a bitmap if it exists
*
* @details Once called, this handle cannot be used as a target to switch the rendering context to
*
* @param handle The index number of the bitmap to release
*
* @returns 1 on success,
* @returns 0 otherwise
*
* @note If the passed handle is that of an ANI, it frees the render target of EVERY frame. Be sure to only pass the handle of the first frame!
*
*/
bool bm_release_rendertarget(int handle);
/**
* @brief Loads a bitmap sequance so we can draw with it.
*
@@ -320,7 +301,7 @@ int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, i
* @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
* @returns NULL if unsuccessful
*/
bitmap* bm_lock(int handle, int bpp, ushort flags, bool nodebug = false);
bitmap* bm_lock(int handle, int bpp, ubyte flags, bool nodebug = false);
/**
* @brief Returns the image type of the given bitmap handle
@@ -363,7 +344,7 @@ int bm_is_valid(int handle);
* @returns The handle to the first frame on success, or
* @returns -1 on failure
*/
int bm_get_info(int handle, int *w = nullptr, int * h = nullptr, ushort* flags = nullptr, int *nframes = nullptr, int *fps = nullptr);
int bm_get_info(int handle, int *w = NULL, int * h = NULL, ubyte * flags = NULL, int *nframes = NULL, int *fps = NULL);
/**
* @brief Gets the filename of the bitmap indexed by handle
+7 -51
View File
@@ -319,14 +319,11 @@ void camera::get_info(vec3d *position, matrix *orientation)
{
object *objp = object_host.objp;
int model_num = object_get_model(objp);
polymodel *pm = nullptr;
polymodel_instance *pmi = nullptr;
polymodel *pm = NULL;
if(model_num >= 0)
if(model_num > -1)
{
pm = model_get(model_num);
if (objp->type == OBJ_SHIP)
pmi = model_get_instance(Ships[objp->instance].model_instance_num);
}
if(object_host_submodel < 0 || pm == NULL)
@@ -342,16 +339,13 @@ void camera::get_info(vec3d *position, matrix *orientation)
Assertion(objp->type == OBJ_SHIP, "This part of the code expects the object to be a ship");
vec3d c_pos_in;
find_submodel_instance_point_normal(&c_pos_in, &host_normal, pm, pmi, eyep->parent, &eyep->pnt, &eyep->norm);
find_submodel_instance_point_normal(&c_pos_in, &host_normal, Ships[objp->instance].model_instance_num, eyep->parent, &eyep->pnt, &eyep->norm);
vm_vec_unrotate(&c_pos, &c_pos_in, &objp->orient);
vm_vec_add2(&c_pos, &objp->pos);
}
else
{
if (pmi != nullptr)
model_instance_find_world_point(&c_pos, &pt, pm, pmi, object_host_submodel, &objp->orient, &objp->pos);
else
model_find_world_point( &c_pos, &pt, pm, object_host_submodel, &objp->orient, &objp->pos );
model_find_world_point( &c_pos, &pt, pm->id, object_host_submodel, &objp->orient, &objp->pos );
}
}
}
@@ -380,16 +374,13 @@ void camera::get_info(vec3d *position, matrix *orientation)
{
object *objp = object_target.objp;
int model_num = object_get_model(objp);
polymodel *pm = nullptr;
polymodel_instance *pmi = nullptr;
polymodel *pm = NULL;
vec3d target_pos = vmd_zero_vector;
//See if we can get the model
if(model_num >= 0)
if(model_num > -1)
{
pm = model_get(model_num);
if (objp->type == OBJ_SHIP)
pmi = model_get_instance(Ships[objp->instance].model_instance_num);
}
//If we don't have a submodel or don't have the model use object pos
@@ -400,10 +391,7 @@ void camera::get_info(vec3d *position, matrix *orientation)
}
else
{
if (pmi != nullptr)
model_instance_find_world_point(&target_pos, &vmd_zero_vector, pm, pmi, object_target_submodel, &objp->orient, &objp->pos);
else
model_find_world_point( &target_pos, &vmd_zero_vector, pm, object_target_submodel, &objp->orient, &objp->pos );
model_find_world_point( &target_pos, &vmd_zero_vector, pm->id, object_target_submodel, &objp->orient, &objp->pos );
}
vec3d targetvec;
@@ -1107,35 +1095,3 @@ eye* get_submodel_eye(polymodel *pm, int submodel_num)
}
return NULL;
}
// maybe push the camera away from preferred dist if it would intersect the ship's bounding box
float cam_get_bbox_dist(const object* viewer_obj, float preferred_distance, const matrix* cam_orient) {
if (viewer_obj == nullptr)
return preferred_distance;
// radius is the maximal extent of the ship's bbox from the center, so if its at least that plus the padding its guaranteed to be good
// plus a little fudge factor at the end because shields count against the bounding box, but not the radius
if (preferred_distance > (viewer_obj->radius * EXTERN_CAM_BBOX_MULTIPLIER_PADDING + EXTERN_CAM_BBOX_CONSTANT_PADDING) * 1.5f)
return preferred_distance;
int modelnum = object_get_model(viewer_obj);
polymodel* pm = model_get(modelnum);
vec3d adjusted_bbox;
const vec3d* cam_vec = &cam_orient->vec.fvec;
// the bounding box is expanded by the padding and maybe use negative min instead of max, because they could differ significantly
// and we only care about the one thats on the side of the camera
adjusted_bbox.xyz.x = (cam_vec->xyz.x < 0 ? -pm->mins.xyz.x : pm->maxs.xyz.x) * EXTERN_CAM_BBOX_MULTIPLIER_PADDING + EXTERN_CAM_BBOX_CONSTANT_PADDING;
adjusted_bbox.xyz.y = (cam_vec->xyz.y < 0 ? -pm->mins.xyz.y : pm->maxs.xyz.y) * EXTERN_CAM_BBOX_MULTIPLIER_PADDING + EXTERN_CAM_BBOX_CONSTANT_PADDING;
adjusted_bbox.xyz.z = (cam_vec->xyz.z < 0 ? -pm->mins.xyz.z : pm->maxs.xyz.z) * EXTERN_CAM_BBOX_MULTIPLIER_PADDING + EXTERN_CAM_BBOX_CONSTANT_PADDING;
vec3d adjusted_dist;
// adjusted_dist is the vector (with an inverted magnitude) that contacts the surface of an
// ellipsoid which contacts the adjusted_bbox at each of its faces
adjusted_dist.xyz.x = cam_vec->xyz.x / adjusted_bbox.xyz.x;
adjusted_dist.xyz.y = cam_vec->xyz.y / adjusted_bbox.xyz.y;
adjusted_dist.xyz.z = cam_vec->xyz.z / adjusted_bbox.xyz.z;
float compensation = vm_vec_mag(&adjusted_dist);
return fmaxf(1 / compensation, preferred_distance);
}
-4
View File
@@ -15,9 +15,6 @@
#define CAM_STATIONARY_POS (1<<2)
#define CAM_DEFAULT_FLAGS 0
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
class camera
{
protected:
@@ -167,7 +164,6 @@ camid cam_lookup(const char* name);
camid cam_get_camera(uint index);
camid cam_get_current();
size_t cam_get_num();
float cam_get_bbox_dist(const object* viewer_obj, float preferred_distance, const matrix* cam_orient);
void get_turret_cam_pos(camera *cam, vec3d *pos);
void get_turret_cam_orient(camera *cam, matrix *ori);
+32 -37
View File
@@ -71,7 +71,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt .webm .png",CF_TYPE_DATA },
{ CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf .otf", CF_TYPE_DATA },
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
@@ -109,14 +109,14 @@ static const char *Cfile_cdrom_dir = NULL;
// Function prototypes for internally-called functions
//
static int cfget_cfile_block();
static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* original_filename, FILE * fp, int type);
static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type, size_t offset, size_t size);
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const char* original_filename, const void* data, size_t size, int dir_type);
static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE * fp, int type);
static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, size_t offset, size_t size);
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const void* data, size_t size, int dir_type);
#if defined _WIN32
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, HANDLE hFile, int type);
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type);
#elif defined SCP_UNIX
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type);
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp, int type);
#endif
static void cf_chksum_long_init();
@@ -675,10 +675,13 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
if ( strchr(mode,'w') || strchr(mode,'+') || strchr(mode,'a') ) {
char longname[_MAX_PATH];
auto last_separator = strrchr(file_path, DIR_SEPARATOR_CHAR);
// For write-only files, require a full path or a path type
if ( last_separator ) {
#ifdef SCP_UNIX
if ( strpbrk(file_path, "/") ) {
#else
if ( strpbrk(file_path,"/\\:") ) {
#endif
// Full path given?
strcpy_s(longname, file_path );
} else {
@@ -694,7 +697,7 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
// JOHN: TODO, you should create the path if it doesn't exist.
//WMC - For some reason, fread does not return the correct number of bytes read
//WMC - For some godawful reason, fread does not return the correct number of bytes read
//in text mode, which messes up FS2_Open's raw_position indicator in fgets. As a consequence, you
//_must_ open files that are gonna be read in binary mode.
@@ -729,7 +732,7 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
FILE *fp = fopen(longname, happy_mode);
if (fp) {
return cf_open_fill_cfblock(source, line, last_separator ? (last_separator + 1) : file_path, fp, dir_type);
return cf_open_fill_cfblock(source, line, fp, dir_type);
}
return NULL;
}
@@ -757,19 +760,20 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
hFile = CreateFile(find_res.full_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
return cf_open_mapped_fill_cfblock(source, line, file_path, hFile, dir_type);
return cf_open_mapped_fill_cfblock(source, line, hFile, dir_type);
}
#elif defined SCP_UNIX
FILE* fp = fopen(find_res.full_name.c_str(), "rb");
if (fp) {
return cf_open_mapped_fill_cfblock(source, line, file_path, fp, dir_type);
return cf_open_mapped_fill_cfblock(source, line, fp, dir_type);
}
#endif
}
} else {
// since cfopen_special already has all the code to handle the opening we can just use that here
return _cfopen_special(source, line, find_res, mode, dir_type);
return _cfopen_special(source, line, find_res.full_name.c_str(), mode, find_res.size, find_res.offset,
find_res.data_ptr, dir_type);
}
}
@@ -788,14 +792,14 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
// returns: success ==> address of CFILE structure
// error ==> NULL
//
CFILE *_cfopen_special(const char* source, int line, const CFileLocation &res, const char* mode, int dir_type)
CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const size_t size, const size_t offset, const void* data, int dir_type)
{
if ( !cfile_inited) {
Int3();
return NULL;
}
Assert( !res.full_name.empty() );
Assert( file_path && strlen(file_path) );
Assert( mode != NULL );
// cfopen_special() only supports reading files, not creating them
@@ -805,21 +809,21 @@ CFILE *_cfopen_special(const char* source, int line, const CFileLocation &res, c
}
// In-Memory files are a bit different from normal files so we need to handle them separately
if (res.data_ptr != nullptr) {
return cf_open_memory_fill_cfblock(source, line, res.name_ext.c_str(), res.data_ptr, res.size, dir_type);
if (data != nullptr) {
return cf_open_memory_fill_cfblock(source, line, data, size, dir_type);
}
else {
// "file_path" should already be a fully qualified path, so just try to open it
FILE *fp = fopen(res.full_name.c_str(), "rb");
FILE *fp = fopen(file_path, "rb");
if (fp) {
if (res.offset) {
if (offset) {
// Found it in a pack file
return cf_open_packed_cfblock(source, line, res.name_ext.c_str(), fp, dir_type, res.offset, res.size);
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
}
else {
// Found it in a normal file
return cf_open_fill_cfblock(source, line, res.name_ext.c_str(), fp, dir_type);
return cf_open_fill_cfblock(source, line, fp, dir_type);
}
}
}
@@ -842,7 +846,7 @@ CFILE *ctmpfile()
FILE *fp;
fp = tmpfile();
if ( fp )
return cf_open_fill_cfblock(LOCATION, "<temporary file>", fp, 0);
return cf_open_fill_cfblock(LOCATION, fp, 0);
else
return NULL;
}
@@ -949,7 +953,7 @@ int cf_is_valid(CFILE *cfile)
// returns: success ==> ptr to CFILE structure.
// error ==> NULL
//
static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type)
static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int type)
{
int cfile_block_index;
@@ -965,7 +969,6 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* ori
cfp->dir_type = type;
cfp->max_read_len = 0;
cfp->original_filename = original_filename;
cfp->source_file = source;
cfp->line_num = line;
@@ -985,7 +988,7 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* ori
// returns: success ==> ptr to CFILE structure.
// error ==> NULL
//
static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type, size_t offset, size_t size)
static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, size_t offset, size_t size)
{
// Found it in a pack file
int cfile_block_index;
@@ -1003,7 +1006,6 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* o
cfp->dir_type = type;
cfp->max_read_len = 0;
cfp->original_filename = original_filename;
cfp->source_file = source;
cfp->line_num = line;
@@ -1022,9 +1024,9 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* o
// returns: ptr CFILE structure.
//
#if defined _WIN32
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, HANDLE hFile, int type)
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type)
#elif defined SCP_UNIX
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type)
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp, int type)
#endif
{
int cfile_block_index;
@@ -1047,7 +1049,6 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const ch
#endif
cfp->dir_type = type;
cfp->original_filename = original_filename;
cfp->source_file = source;
cfp->line_num = line;
@@ -1077,7 +1078,7 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const ch
}
}
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const char* original_filename, const void* data, size_t size, int dir_type)
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const void* data, size_t size, int dir_type)
{
int cfile_block_index;
@@ -1093,7 +1094,6 @@ static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const ch
cfp->mem_mapped = false;
cfp->dir_type = dir_type;
cfp->original_filename = original_filename;
cfp->source_file = source;
cfp->line_num = line;
@@ -1104,12 +1104,7 @@ static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const ch
}
}
const char *cf_get_filename(const CFILE *cfile)
{
return cfile->original_filename.c_str();
}
int cf_get_dir_type(const CFILE *cfile)
int cf_get_dir_type(CFILE *cfile)
{
return cfile->dir_type;
}
+6 -13
View File
@@ -18,7 +18,6 @@
#include <ctime>
#include <stdexcept>
#include <memory>
#include <utility>
#define CF_EOF (-1)
@@ -176,11 +175,8 @@ void cfile_close();
// add an extension to a filename if it doesn't already have it
char *cf_add_ext(const char *filename, const char *ext);
// return filename of a CFILE you called cfopen() successfully on.
const char *cf_get_filename(const CFILE *cfile);
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
int cf_get_dir_type(const CFILE *cfile);
int cf_get_dir_type(CFILE *cfile);
// Opens the file. If no path is given, use the extension to look into the
// default path. If mode is NULL, delete the file.
@@ -188,12 +184,10 @@ CFILE* _cfopen(const char* source_file, int line, const char* filename, const ch
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
struct CFileLocation;
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
// NOTE: only supports reading files!!
CFILE *_cfopen_special(const char* source_file, int line, const CFileLocation &res, const char* mode,
int dir_type = CF_TYPE_ANY);
CFILE *_cfopen_special(const char* source_file, int line, const char *file_path, const char *mode,
const size_t size, const size_t offset, const void* data, int dir_type = CF_TYPE_ANY);
#define cfopen_special(...) _cfopen_special(LOCATION, __VA_ARGS__) // Pass source location to the function
// Flush the open file buffer
@@ -374,7 +368,6 @@ void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_
struct CFileLocation {
bool found = false;
SCP_string name_ext;
SCP_string full_name;
size_t size = 0;
size_t offset = 0;
@@ -444,13 +437,13 @@ namespace cfile
{
}
explicit cfile_error(std::string excuse) : m_excuse(std::move(excuse))
explicit cfile_error(const std::string &excuse) : m_excuse(excuse)
{
}
~cfile_error() noexcept override = default;
~cfile_error() SCP_NOEXCEPT override {}
const char *what() const noexcept override {
const char *what() const SCP_NOEXCEPT override {
return m_excuse.c_str();
}
+2 -4
View File
@@ -8,15 +8,14 @@
*/
#ifndef _CFILEARCHIVE_H
#define _CFILEARCHIVE_H
#ifndef _CFILE_INTERNAL
#pragma message("This file should only be included internally in CFILE!!")
#error This file should only be included internally in CFILE!!
#endif
#include "globalincs/pstypes.h"
// The following Cfile_block data is private to cfile.cpp
// DO NOT MOVE the Cfile_block* information to cfile.h / do not extern this data
//
@@ -41,7 +40,6 @@ struct CFILE {
size_t max_read_len; // max read offset, for special error handling
SCP_string original_filename;
const char* source_file;
int line_num;
};
+22 -20
View File
@@ -1034,21 +1034,18 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
// of the file
// NOTE: full path should also include localization, if so desired
auto last_separator = strrchr(filespec, DIR_SEPARATOR_CHAR);
// do we have a full path already?
if ( last_separator ) {
#ifdef SCP_UNIX
if ( strpbrk(filespec, "/") ) { // do we have a full path already?
#else
if ( strpbrk(filespec,"/\\:") ) { // do we have a full path already?
#endif
FILE *fp = fopen(filespec, "rb" );
if (fp) {
CFileLocation res(true);
res.size = static_cast<size_t>(filelength(fileno(fp)));
fclose(fp);
res.offset = 0;
res.full_name = filespec;
res.name_ext = last_separator + 1;
fclose(fp);
return res;
}
@@ -1107,7 +1104,6 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
res.offset = 0;
res.full_name = longname;
res.name_ext = filespec;
return res;
}
@@ -1123,7 +1119,6 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
res.offset = 0;
res.full_name = longname;
res.name_ext = filespec;
return res;
}
@@ -1159,7 +1154,6 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
res.name_ext = f->name_ext;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
@@ -1187,7 +1181,6 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
res.name_ext = f->name_ext;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
@@ -1242,8 +1235,13 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
Assert( (ext_list != NULL) && (ext_num > 1) ); // if we are searching for just one ext
// then this is the wrong function to use
// if we have a full path already then fail. this function if for searching via filter only!
if ( strchr(filename, DIR_SEPARATOR_CHAR) ) { // do we have a full path already?
#ifdef SCP_UNIX
if ( strpbrk(filename, "/") ) { // do we have a full path already?
#else
if ( strpbrk(filename,"/\\:") ) { // do we have a full path already?
#endif
Int3();
return CFileLocationExt();
}
@@ -1314,7 +1312,6 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
res.offset = 0;
res.full_name = longname;
res.name_ext = filespec;
return res;
}
@@ -1331,7 +1328,6 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
res.offset = 0;
res.full_name = longname;
res.name_ext = filespec;
return res;
}
@@ -1423,7 +1419,6 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
res.name_ext = f->name_ext;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
@@ -1455,7 +1450,6 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
res.name_ext = f->name_ext;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
@@ -2269,7 +2263,11 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename, bool localize,
uint32_t location_flags)
{
if ( filename && strchr(filename, DIR_SEPARATOR_CHAR) ) {
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
#else
if ( filename && strpbrk(filename,"/\\:") ) {
#endif
// Already has full path
strncpy( path, filename, path_max );
@@ -2348,7 +2346,11 @@ int cf_create_default_path_string(char* path, uint path_max, int pathtype, const
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename, bool /*localize*/,
uint32_t location_flags)
{
if ( filename && strchr(filename, DIR_SEPARATOR_CHAR) ) {
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
#else
if ( filename && strpbrk(filename,"/\\:") ) {
#endif
// Already has full path
path.assign(filename);
+18 -20
View File
@@ -188,7 +188,6 @@ Flag exe_params[] =
{ "-3dwarp", "Enable 3D warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
{ "-no_screenshake", "Disable screen shaking", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_screenshake", },
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
{ "-nomusic", "Disable music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomusic", },
@@ -274,8 +273,9 @@ cmdline_parm gameclosed_arg("-closed", NULL, AT_NONE); // Cmdline_closed_game
cmdline_parm gamerestricted_arg("-restricted", NULL, AT_NONE); // Cmdline_restricted_game
cmdline_parm port_arg("-port", "Multiplayer network port", AT_INT);
cmdline_parm multilog_arg("-multilog", NULL, AT_NONE); // Cmdline_multi_log
cmdline_parm client_dodamage("-clientdamage", NULL, AT_NONE); // Cmdline_client_dodamage
cmdline_parm pof_spew("-pofspew", NULL, AT_NONE); // Cmdline_spew_pof_info
cmdline_parm weapon_spew("-weaponspew", nullptr, AT_STRING); // Cmdline_spew_weapon_stats
cmdline_parm weapon_spew("-weaponspew", nullptr, AT_NONE); // Cmdline_spew_weapon_stats
cmdline_parm mouse_coords("-coords", NULL, AT_NONE); // Cmdline_mouse_coords
cmdline_parm timeout("-timeout", "Multiplayer network timeout (secs)", AT_INT); // Cmdline_timeout
cmdline_parm bit32_arg("-32bit", "Deprecated", AT_NONE); // (only here for retail compatibility reasons, doesn't actually do anything)
@@ -286,6 +286,7 @@ char *Cmdline_game_password = NULL;
char *Cmdline_rank_above = NULL;
char *Cmdline_rank_below = NULL;
int Cmdline_cd_check = 1;
int Cmdline_client_dodamage = 0;
int Cmdline_closed_game = 0;
int Cmdline_freespace_no_music = 0;
int Cmdline_freespace_no_sound = 0;
@@ -296,7 +297,7 @@ int Cmdline_multi_stream_chat_to_file = 0;
int Cmdline_network_port = -1;
int Cmdline_restricted_game = 0;
int Cmdline_spew_pof_info = 0;
WeaponSpewType Cmdline_spew_weapon_stats = WeaponSpewType::NONE;
bool Cmdline_spew_weapon_stats = false;
int Cmdline_start_netgame = 0;
int Cmdline_timeout = -1;
int Cmdline_use_last_pilot = 0;
@@ -350,7 +351,7 @@ int Cmdline_height = 1;
int Cmdline_enable_3d_shockwave = 0;
int Cmdline_softparticles = 0;
int Cmdline_bloom_intensity = 25;
bool Cmdline_force_lightshaft_off = false;
extern bool ls_force_off;
int Cmdline_no_deferred_lighting = 0;
int Cmdline_aniso_level = 0;
@@ -381,7 +382,6 @@ cmdline_parm weapon_choice_3d_arg("-weapon_choice_3d", NULL, AT_NONE); // Cmdlin
cmdline_parm use_warp_flash("-warp_flash", NULL, AT_NONE); // Cmdline_warp_flash
cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", NULL, AT_NONE);
cmdline_parm stretch_menu("-stretch_menu", NULL, AT_NONE); // Cmdline_stretch_menu
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
int Cmdline_3dwarp = 0;
int Cmdline_ship_choice_3d = 0;
@@ -389,7 +389,6 @@ int Cmdline_weapon_choice_3d = 0;
int Cmdline_warp_flash = 0;
int Cmdline_autopilot_interruptable = 1;
int Cmdline_stretch_menu = 0;
int Cmdline_no_screenshake = 0;
// Audio related
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
@@ -810,7 +809,7 @@ void os_validate_parms(int argc, char *argv[])
if (!stricmp(token, "-help") || !stricmp(token, "--help") || !stricmp(token, "-h") || !stricmp(token, "-?")) {
printf("FreeSpace 2 Open, version %s\n", FS_VERSION_FULL);
printf("Website: http://scp.indiegames.us\n");
printf("Github (bug reporting): https://github.com/scp-fs2open/fs2open.github.com/issues\n\n");
printf("Mantis (bug reporting): http://scp.indiegames.us/mantis/\n\n");
printf("Usage: fs2_open [options]\n");
// not the prettiest thing but the job gets done
@@ -1661,6 +1660,12 @@ bool SetCmdlineParams()
Cmdline_multi_log = 1;
}
// maybe use old-school client damage
if(client_dodamage.found()){
Cmdline_client_dodamage = 1;
}
// spew pof info
if(pof_spew.found()){
Cmdline_spew_pof_info = 1;
@@ -1668,14 +1673,7 @@ bool SetCmdlineParams()
// spew weapon stats
if (weapon_spew.found()) {
Cmdline_spew_weapon_stats = WeaponSpewType::STANDARD;
// currently just one argument
if (weapon_spew.has_param()) {
if (!stricmp(weapon_spew.str(), "all")) {
Cmdline_spew_weapon_stats = WeaponSpewType::ALL;
}
}
Cmdline_spew_weapon_stats = true;
}
// mouse coords
@@ -1835,10 +1833,6 @@ bool SetCmdlineParams()
Cmdline_autopilot_interruptable = 0;
}
if ( no_screenshake.found() ) {
Cmdline_no_screenshake = 1;
}
if ( stretch_menu.found() ) {
Cmdline_stretch_menu = 1;
}
@@ -1909,6 +1903,10 @@ bool SetCmdlineParams()
}
}
// If any of the AA presets were chosen, update the _last_frame AA mode to avoid an unnecessary
// shader recompile.
Gr_aa_mode_last_frame = Gr_aa_mode;
if ( glow_arg.found() )
Cmdline_glow = 0;
@@ -2060,7 +2058,7 @@ bool SetCmdlineParams()
if ( flightshaftsoff_arg.found() )
{
Cmdline_force_lightshaft_off = true;
ls_force_off = true;
}
if( reparse_mainhall_arg.found() )
+2 -5
View File
@@ -30,6 +30,7 @@ extern char *Cmdline_game_password;
extern char *Cmdline_rank_above;
extern char *Cmdline_rank_below;
extern int Cmdline_cd_check;
extern int Cmdline_client_dodamage;
extern int Cmdline_closed_game;
extern int Cmdline_freespace_no_music;
extern int Cmdline_freespace_no_sound;
@@ -66,7 +67,6 @@ extern int Cmdline_height;
extern int Cmdline_enable_3d_shockwave;
extern int Cmdline_softparticles;
extern int Cmdline_bloom_intensity;
extern bool Cmdline_force_lightshaft_off;
extern int Cmdline_no_deferred_lighting;
extern int Cmdline_emissive;
extern int Cmdline_aniso_level;
@@ -89,7 +89,6 @@ extern int Cmdline_weapon_choice_3d;
extern int Cmdline_warp_flash;
extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
extern int Cmdline_no_screenshake;
// Audio related
extern int Cmdline_voice_recognition;
@@ -150,9 +149,7 @@ extern bool Cmdline_show_video_info;
extern bool Cmdline_debug_window;
extern bool Cmdline_graphics_debug_output;
extern bool Cmdline_log_to_stdout;
enum class WeaponSpewType { NONE = 0, STANDARD, ALL };
extern WeaponSpewType Cmdline_spew_weapon_stats;
extern bool Cmdline_spew_weapon_stats;
#endif
+4 -4
View File
@@ -517,9 +517,9 @@ void control_config_list_prepare()
while (z < CCFG_MAX) {
if (Control_config[z].tab == Tab && !Control_config[z].disabled) {
if (Control_config[z].indexXSTR > 1) {
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, Control_config[z].indexXSTR, true);
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, Control_config[z].indexXSTR);
} else if (Control_config[z].indexXSTR == 1) {
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, CONTROL_CONFIG_XSTR + z, true);
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, CONTROL_CONFIG_XSTR + z);
} else {
Cc_lines[Num_cc_lines].label = Control_config[z].text;
}
@@ -1985,9 +1985,9 @@ void control_config_do_frame(float frametime)
gr_printf_menu(x - w / 2, y - font_height, "%s", str);
if (Control_config[i].indexXSTR > 1) {
strcpy_s(buf, XSTR(Control_config[i].text, Control_config[i].indexXSTR, true));
strcpy_s(buf, XSTR(Control_config[i].text, Control_config[i].indexXSTR));
} else if (Control_config[i].indexXSTR == 1) {
strcpy_s(buf, XSTR(Control_config[i].text, CONTROL_CONFIG_XSTR + i, true));
strcpy_s(buf, XSTR(Control_config[i].text, CONTROL_CONFIG_XSTR + i));
} else {
strcpy_s(buf, Control_config[i].text);
}
-27
View File
@@ -10,11 +10,9 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "freespace.h"
#include "globalincs/pstypes.h"
#include "globalincs/alphacolors.h"
#include "globalincs/systemvars.h"
@@ -29,7 +27,6 @@
#include "io/timer.h"
#include "io/key.h"
#include "mod_table/mod_table.h"
#include "network/multi.h"
extern int Game_mode;
extern int Is_standalone;
@@ -201,10 +198,6 @@ void movie_display_loop(Player* player, PlaybackState* state) {
// Use a dedicated listener here since we want to listen for the KEYUP event
auto key_handle = os::events::addEventListener(SDL_KEYUP, os::events::DEFAULT_LISTENER_WEIGHT - 10, listener);
// slight hack to make sure that game_set_frametime() doesn't also try to cap the framerate
auto fpsCapSave = Cmdline_NoFPSCap;
Cmdline_NoFPSCap = 1;
auto lastDisplayTimestamp = timer_get_microseconds();
while (state->playing) {
TRACE_SCOPE(tracing::CutsceneStep);
@@ -223,16 +216,6 @@ void movie_display_loop(Player* player, PlaybackState* state) {
processEvents();
// NOTE: This does not update mission time! If movies get enabled in places
// other than through cutscenes then some refactoring should be done
// to account for normal time progression rather than just timestamps
game_set_frametime(-1);
// maybe do multi processing
if ( (Game_mode & GM_MULTIPLAYER) && Net_player && (Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ) {
multi_do_frame();
}
if (passed < sleepTime) {
auto sleep = sleepTime - passed;
@@ -240,12 +223,7 @@ void movie_display_loop(Player* player, PlaybackState* state) {
}
}
Cmdline_NoFPSCap = fpsCapSave;
os::events::removeEventListener(key_handle);
// flush keys so we don't pass anything to the current state
key_flush();
}
}
@@ -264,11 +242,6 @@ bool play(const char* name) {
return false;
}
// for multiplayer, change the state in my netplayer structure
if ( (Game_mode & GM_MULTIPLAYER) && Net_player ) {
Net_player->state = NETPLAYER_STATE_CUTSCENE;
}
// clear the screen and hide the mouse cursor
io::mouse::CursorManager::get()->pushStatus();
io::mouse::CursorManager::get()->showCursor(false);
+40 -77
View File
@@ -26,30 +26,10 @@ static inline int is_power_of_two(int w, int h)
return ( (w && !(w & (w-1))) && (h && !(h & (h-1))) );
}
// This function is used to verify that the file format specified in the DX10 Header
// is supported by the OpenGL extensions
bool dds_read_dx10_header(CFILE* dds_file, DDS_HEADER_DXT10* header)
{
header->dxgiFormat = static_cast<DXGI_FORMAT>(cfread_uint(dds_file));
header->resourceDimension = static_cast<D3D10_RESOURCE_DIMENSION>(cfread_uint(dds_file));
header->miscFlag = cfread_uint(dds_file);
header->arraySize = cfread_uint(dds_file);
header->miscFlags2 = cfread_uint(dds_file);
switch (header->dxgiFormat) {
case DXGI_FORMAT::DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM_SRGB:
return true;
default:
return false;
}
}
int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, size_t *size, ubyte *palette)
{
DDS_HEADER dds_header;
DDS_HEADER_DXT10 dds_header_dx10;
DDSURFACEDESC2 dds_header;
int code = 0;
CFILE *ddsfile;
char real_name[MAX_FILENAME_LEN];
@@ -103,22 +83,17 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
for (i = 0; i < 11; i++)
cfread_uint(ddsfile);
dds_header.ddspf.dwSize = cfread_uint(ddsfile);
dds_header.ddspf.dwFlags = cfread_uint(ddsfile);
dds_header.ddspf.dwFourCC = cfread_uint(ddsfile);
dds_header.ddspf.dwRGBBitCount = cfread_uint(ddsfile);
dds_header.ddspf.dwRBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwGBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwBBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwABitMask = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwSize = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwFlags = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwFourCC = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwRGBBitCount = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwRBitMask = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwGBitMask = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwBBitMask = cfread_uint(ddsfile);
dds_header.ddpfPixelFormat.dwRGBAlphaBitMask = cfread_uint(ddsfile);
dds_header.dwCaps = cfread_uint(ddsfile);
dds_header.dwCaps2 = cfread_uint(ddsfile);
// Unused but need them checked for later
dds_header.dwCaps3 = cfread_uint(ddsfile);
dds_header.dwCaps4 = cfread_uint(ddsfile);
dds_header.dwReserved2 = cfread_uint(ddsfile);
dds_header.ddsCaps.dwCaps1 = cfread_uint(ddsfile);
dds_header.ddsCaps.dwCaps2 = cfread_uint(ddsfile);
// sanity
if (dds_header.dwDepth == 0)
@@ -132,12 +107,12 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
d_depth = dds_header.dwDepth;
// calculate the type and size of the data
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
if (dds_header.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
// did I mention lately that I hate Microsoft?
// this is here to fix the situation where Microsoft doesn't follow their own docs
if ( !(dds_header.dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH) ) || dds_header.dwPitchOrLinearSize <= 0 ) {
if ( dds_header.dwPitchOrLinearSize <= 0 ) {
// calculate the block size, mult by 8 for DXT1, 16 for DXT3 & 5
d_size = ((dds_header.dwWidth + 3)/4) * ((dds_header.dwHeight + 3)/4) * ((dds_header.dwDepth + 3)/4) * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
d_size = ((dds_header.dwWidth + 3)/4) * ((dds_header.dwHeight + 3)/4) * ((dds_header.dwDepth + 3)/4) * ((dds_header.ddpfPixelFormat.dwFourCC == FOURCC_DXT1) ? 8 : 16);
} else {
d_size = dds_header.dwPitchOrLinearSize;
}
@@ -155,11 +130,11 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
d_height = 1;
// size of data block (4x4)
d_size += ((d_width + 3) / 4) * ((d_height + 3) / 4) * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
d_size += ((d_width + 3) / 4) * ((d_height + 3) / 4) * ((dds_header.ddpfPixelFormat.dwFourCC == FOURCC_DXT1) ? 8 : 16);
}
if ( dds_header.dwCaps2 & DDSCAPS2_CUBEMAP ) {
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
if ( dds_header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ) {
if ( !(dds_header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
retval = DDS_ERROR_CUBEMAP_FACES;
ct = DDS_DXT_INVALID;
goto Done;
@@ -175,7 +150,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
Assert( d_size > 0 );
*size = d_size;
switch (dds_header.ddspf.dwFourCC) {
switch (dds_header.ddpfPixelFormat.dwFourCC) {
case FOURCC_DXT1:
bits = 24;
ct = (is_cubemap) ? DDS_CUBEMAP_DXT1 : DDS_DXT1;
@@ -199,18 +174,6 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
goto Done;
break;
case FOURCC_DX10:
if (dds_read_dx10_header(ddsfile, &dds_header_dx10)) {
// Currently only BC7 is supported
bits = 32;
ct = DDS_BC7;
} else {
retval = DDS_ERROR_UNSUPPORTED;
ct = DDS_DXT_INVALID;
goto Done;
}
break;
// none of the above
default:
retval = DDS_ERROR_INVALID_FORMAT;
@@ -218,8 +181,8 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
goto Done;
break;
}
} else if ( dds_header.ddspf.dwFlags & (DDPF_RGB | DDPF_PALETTEINDEXED8) ) {
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
} else if ( dds_header.ddpfPixelFormat.dwFlags & (DDPF_RGB | DDPF_PALETTEINDEXED8) ) {
d_size += d_width * d_height * d_depth * (dds_header.ddpfPixelFormat.dwRGBBitCount / 8);
// calculate full data size for all mipmap levels
for (i = 1; i < (int)dds_header.dwMipMapCount; i++) {
@@ -236,13 +199,13 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
if (d_depth < 1)
d_depth = 1;
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
d_size += d_width * d_height * d_depth * (dds_header.ddpfPixelFormat.dwRGBBitCount / 8);
}
Assert( d_size > 0 );
if ( dds_header.dwCaps2 & DDSCAPS2_CUBEMAP ) {
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
if ( dds_header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ) {
if ( !(dds_header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
retval = DDS_ERROR_CUBEMAP_FACES;
ct = DDS_DXT_INVALID;
goto Done;
@@ -257,7 +220,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
*size = d_size;
bits = dds_header.ddspf.dwRGBBitCount;
bits = dds_header.ddpfPixelFormat.dwRGBBitCount;
ct = (is_cubemap) ? DDS_CUBEMAP_UNCOMPRESSED : DDS_UNCOMPRESSED;
} else {
// it's not a readable format
@@ -294,7 +257,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
*levels = dds_header.dwMipMapCount;
if (palette && (bits == 8)) {
cfseek(ddsfile, (ct == DDS_BC7) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
cfseek(ddsfile, DDS_OFFSET, CF_SEEK_SET);
cfread(palette, 1, 1024, ddsfile);
}
@@ -344,7 +307,7 @@ int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
return retval;
}
cfseek(cfp, (ct == DDS_BC7) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
cfseek(cfp, DDS_OFFSET, CF_SEEK_SET);
// read in the data
cfread(data, 1, (int)size, cfp);
@@ -362,7 +325,7 @@ int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
// NOTE: we only support, uncompressed, 24-bit RGB and 32-bit RGBA images here!!
void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data, int cubemap, const char *filename)
{
DDS_HEADER dds_header;
DDSURFACEDESC2 dds_header;
char real_filename[MAX_FILENAME_LEN];
if (data == NULL) {
@@ -371,7 +334,7 @@ void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data
}
// header size check
if (sizeof(DDS_HEADER) != 124) {
if (sizeof(DDSURFACEDESC2) != 124) {
Int3();
return;
}
@@ -414,7 +377,7 @@ void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data
num_mipmaps = 1;
// we have a filename and file handle, so now lets create our DDS header...
memset( &dds_header, 0, sizeof(DDS_HEADER) );
memset( &dds_header, 0, sizeof(DDSURFACEDESC2) );
uint flags = (DDSD_CAPS | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT);
uint pixel_flags = DDPF_RGB;
@@ -443,22 +406,22 @@ void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data
dds_header.dwDepth = 0;
dds_header.dwMipMapCount = num_mipmaps;
dds_header.ddspf.dwSize = 32;
dds_header.ddspf.dwFlags = pixel_flags;
dds_header.ddspf.dwFourCC = 0;
dds_header.ddspf.dwRGBBitCount = bpp;
dds_header.ddspf.dwRBitMask = 0x00ff0000;
dds_header.ddspf.dwGBitMask = 0x0000ff00;
dds_header.ddspf.dwBBitMask = 0x000000ff;
dds_header.ddspf.dwABitMask = (bpp == 32) ? 0xff000000 : 0x00000000;
dds_header.ddpfPixelFormat.dwSize = 32;
dds_header.ddpfPixelFormat.dwFlags = pixel_flags;
dds_header.ddpfPixelFormat.dwFourCC = 0;
dds_header.ddpfPixelFormat.dwRGBBitCount = bpp;
dds_header.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
dds_header.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
dds_header.ddpfPixelFormat.dwBBitMask = 0x000000ff;
dds_header.ddpfPixelFormat.dwRGBAlphaBitMask = (bpp == 32) ? 0xff000000 : 0x00000000;
dds_header.dwCaps = caps1;
dds_header.dwCaps2 = caps2;
dds_header.ddsCaps.dwCaps1 = caps1;
dds_header.ddsCaps.dwCaps2 = caps2;
// now save it all...
uint dds_id = DDS_FILECODE;
cfwrite(&dds_id, 1, 4, image);
cfwrite(&dds_header, 1, sizeof(DDS_HEADER), image);
cfwrite(&dds_header, 1, sizeof(DDSURFACEDESC2), image);
int faces = (cubemap) ? 6 : 1;
int f_width = width;
+50 -190
View File
@@ -18,21 +18,20 @@
#define DDS_ERROR_CUBEMAP_FACES 7 // file is a cubemap, but doesn't have all six faces
#define DDS_DXT_INVALID -1
#define DDS_DXT_INVALID -1
#define DDS_UNCOMPRESSED 0
#define DDS_DXT1 1
#define DDS_DXT3 3
#define DDS_DXT5 5
#define DDS_BC7 7
#define DDS_CUBEMAP_UNCOMPRESSED 10
#define DDS_CUBEMAP_DXT1 11
#define DDS_CUBEMAP_DXT3 13
#define DDS_CUBEMAP_DXT5 15
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint)(ubyte)(ch0) | ((uint)(ubyte)(ch1) << 8) | \
((uint)(ubyte)(ch2) << 16) | ((uint)(ubyte)(ch3) << 24 ))
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint)(ubyte)(ch0) | ((uint)(ubyte)(ch1) << 8) | \
((uint)(ubyte)(ch2) << 16) | ((uint)(ubyte)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)
// FOURCC codes for DX compressed-texture pixel formats
@@ -41,7 +40,6 @@
#define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4'))
#define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5'))
#define FOURCC_DX10 (MAKEFOURCC('D','X','1','0'))
#define DDS_FILECODE 0x20534444 // "DDS " in file
@@ -82,198 +80,60 @@
DDSCAPS2_CUBEMAP_NEGATIVEZ )
#pragma pack(1)
enum class DXGI_FORMAT : uint {
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_R32G32B32A32_TYPELESS,
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32A32_UINT,
DXGI_FORMAT_R32G32B32A32_SINT,
DXGI_FORMAT_R32G32B32_TYPELESS,
DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT_R32G32B32_UINT,
DXGI_FORMAT_R32G32B32_SINT,
DXGI_FORMAT_R16G16B16A16_TYPELESS,
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_R16G16B16A16_UINT,
DXGI_FORMAT_R16G16B16A16_SNORM,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R32G32_TYPELESS,
DXGI_FORMAT_R32G32_FLOAT,
DXGI_FORMAT_R32G32_UINT,
DXGI_FORMAT_R32G32_SINT,
DXGI_FORMAT_R32G8X24_TYPELESS,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT,
DXGI_FORMAT_R10G10B10A2_TYPELESS,
DXGI_FORMAT_R10G10B10A2_UNORM,
DXGI_FORMAT_R10G10B10A2_UINT,
DXGI_FORMAT_R11G11B10_FLOAT,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_SNORM,
DXGI_FORMAT_R8G8B8A8_SINT,
DXGI_FORMAT_R16G16_TYPELESS,
DXGI_FORMAT_R16G16_FLOAT,
DXGI_FORMAT_R16G16_UNORM,
DXGI_FORMAT_R16G16_UINT,
DXGI_FORMAT_R16G16_SNORM,
DXGI_FORMAT_R16G16_SINT,
DXGI_FORMAT_R32_TYPELESS,
DXGI_FORMAT_D32_FLOAT,
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_UINT,
DXGI_FORMAT_R32_SINT,
DXGI_FORMAT_R24G8_TYPELESS,
DXGI_FORMAT_D24_UNORM_S8_UINT,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
DXGI_FORMAT_X24_TYPELESS_G8_UINT,
DXGI_FORMAT_R8G8_TYPELESS,
DXGI_FORMAT_R8G8_UNORM,
DXGI_FORMAT_R8G8_UINT,
DXGI_FORMAT_R8G8_SNORM,
DXGI_FORMAT_R8G8_SINT,
DXGI_FORMAT_R16_TYPELESS,
DXGI_FORMAT_R16_FLOAT,
DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_R16_UNORM,
DXGI_FORMAT_R16_UINT,
DXGI_FORMAT_R16_SNORM,
DXGI_FORMAT_R16_SINT,
DXGI_FORMAT_R8_TYPELESS,
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_R8_UINT,
DXGI_FORMAT_R8_SNORM,
DXGI_FORMAT_R8_SINT,
DXGI_FORMAT_A8_UNORM,
DXGI_FORMAT_R1_UNORM,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
DXGI_FORMAT_R8G8_B8G8_UNORM,
DXGI_FORMAT_G8R8_G8B8_UNORM,
DXGI_FORMAT_BC1_TYPELESS,
DXGI_FORMAT_BC1_UNORM,
DXGI_FORMAT_BC1_UNORM_SRGB,
DXGI_FORMAT_BC2_TYPELESS,
DXGI_FORMAT_BC2_UNORM,
DXGI_FORMAT_BC2_UNORM_SRGB,
DXGI_FORMAT_BC3_TYPELESS,
DXGI_FORMAT_BC3_UNORM,
DXGI_FORMAT_BC3_UNORM_SRGB,
DXGI_FORMAT_BC4_TYPELESS,
DXGI_FORMAT_BC4_UNORM,
DXGI_FORMAT_BC4_SNORM,
DXGI_FORMAT_BC5_TYPELESS,
DXGI_FORMAT_BC5_UNORM,
DXGI_FORMAT_BC5_SNORM,
DXGI_FORMAT_B5G6R5_UNORM,
DXGI_FORMAT_B5G5R5A1_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_B8G8R8X8_UNORM,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,
DXGI_FORMAT_B8G8R8A8_TYPELESS,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
DXGI_FORMAT_B8G8R8X8_TYPELESS,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB,
DXGI_FORMAT_BC6H_TYPELESS,
DXGI_FORMAT_BC6H_UF16,
DXGI_FORMAT_BC6H_SF16,
DXGI_FORMAT_BC7_TYPELESS,
DXGI_FORMAT_BC7_UNORM,
DXGI_FORMAT_BC7_UNORM_SRGB,
DXGI_FORMAT_AYUV,
DXGI_FORMAT_Y410,
DXGI_FORMAT_Y416,
DXGI_FORMAT_NV12,
DXGI_FORMAT_P010,
DXGI_FORMAT_P016,
DXGI_FORMAT_420_OPAQUE,
DXGI_FORMAT_YUY2,
DXGI_FORMAT_Y210,
DXGI_FORMAT_Y216,
DXGI_FORMAT_NV11,
DXGI_FORMAT_AI44,
DXGI_FORMAT_IA44,
DXGI_FORMAT_P8,
DXGI_FORMAT_A8P8,
DXGI_FORMAT_B4G4R4A4_UNORM,
DXGI_FORMAT_P208,
DXGI_FORMAT_V208,
DXGI_FORMAT_V408,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE,
DXGI_FORMAT_FORCE_UINT
};
// these structures are the headers for a dds file
/*typedef struct _DDPIXELFORMAT {
uint dwSize;
uint dwFlags;
uint dwFourCC;
uint dwRGBBitCount;
uint dwRBitMask;
uint dwGBitMask;
uint dwBBitMask;
uint dwRGBAlphaBitMask;
} DDPIXELFORMAT;
/* Potentially useful for later stuff - (DahBlount)
typedef enum D3D10_RESOURCE_MISC_FLAG : uint {
D3D10_RESOURCE_MISC_GENERATE_MIPS,
D3D10_RESOURCE_MISC_SHARED,
D3D10_RESOURCE_MISC_TEXTURECUBE,
D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX,
D3D10_RESOURCE_MISC_GDI_COMPATIBLE
};
*/
typedef struct _DDSCAPS2
{
uint dwCaps1;
uint dwCaps2;
uint Reserved[2];
} DDSCAPS2;*/
enum class D3D10_RESOURCE_DIMENSION : uint {
D3D10_RESOURCE_DIMENSION_UNKNOWN,
D3D10_RESOURCE_DIMENSION_BUFFER,
D3D10_RESOURCE_DIMENSION_TEXTURE1D,
D3D10_RESOURCE_DIMENSION_TEXTURE2D,
D3D10_RESOURCE_DIMENSION_TEXTURE3D
};
/* This is set in shaders for the most part - (DahBlount)
typedef enum DDS_ALPHA_MODE : uint {
DDS_ALPHA_MODE_UNKNOWN,
DDS_ALPHA_MODE_STRAIGHT,
DDS_ALPHA_MODE_PREMULTIPLIED,
DDS_ALPHA_MODE_OPAQUE,
DDS_ALPHA_MODE_CUSTOM
};
*/
typedef struct {
uint dwSize;
uint dwFlags;
uint dwHeight;
uint dwWidth;
uint dwPitchOrLinearSize;
uint dwDepth;
uint dwMipMapCount;
uint dwReserved1[11];
typedef struct _DDSURFACEDESC2
{
uint dwSize; // size of the DDSURFACEDESC structure
uint dwFlags; // determines what fields are valid
uint dwHeight; // height of surface to be created
uint dwWidth; // width of input surface
uint dwPitchOrLinearSize;
uint dwDepth;
uint dwMipMapCount;
uint dwReserved1[11];
struct {
uint dwSize;
uint dwFlags;
uint dwFourCC;
uint dwRGBBitCount;
uint dwRBitMask;
uint dwGBitMask;
uint dwBBitMask;
uint dwABitMask;
} ddspf;
uint dwSize;
uint dwFlags;
uint dwFourCC;
uint dwRGBBitCount;
uint dwRBitMask;
uint dwGBitMask;
uint dwBBitMask;
uint dwRGBAlphaBitMask;
} ddpfPixelFormat;
uint dwCaps;
uint dwCaps2;
uint dwCaps3;
uint dwCaps4;
uint dwReserved2;
} DDS_HEADER;
struct {
uint dwCaps1;
uint dwCaps2;
uint Reserved[2];
} ddsCaps;
typedef struct {
DXGI_FORMAT dxgiFormat;
D3D10_RESOURCE_DIMENSION resourceDimension;
uint miscFlag;
uint arraySize;
uint miscFlags2;
} DDS_HEADER_DXT10;
// DDPIXELFORMAT ddpfPixelFormat;
// DDSCAPS2 ddsCaps; // direct draw surface capabilities
uint dwReserved2;
} DDSURFACEDESC2;
#pragma pack()
#define DDS_OFFSET 4+sizeof(DDS_HEADER) //place where the data starts -- should be 128
#define DX10_OFFSET DDS_OFFSET+sizeof(DDS_HEADER_DXT10) // Unless a DX10 header is present
#define DDS_OFFSET 4+sizeof(DDSURFACEDESC2) //place where the data starts -- should be 128
//reads a dds header
//returns one of the error values
+126 -179
View File
@@ -25,8 +25,6 @@
#include "radar/radar.h"
#include "radar/radarsetup.h"
#include "render/3d.h"
#include "scripting/hook_api.h"
#include "scripting/scripting.h"
#include "ship/ship.h"
#include "ship/shipfx.h"
#include "species_defs/species_defs.h"
@@ -35,16 +33,14 @@
#define MIN_RADIUS_FOR_PERSISTANT_DEBRIS 50 // ship radius at which debris from it becomes persistant
#define DEBRIS_SOUND_DELAY 2000 // time to start debris sound after created
#define MAX_HULL_PIECES MAX_DEBRIS_PIECES // limit the number of hull debris chunks that can exist.
int Num_hull_pieces; // number of hull pieces in existence
// we now maintain a kind of "virtual" Hull_debris_list,
// but all we really need to know is how many hull pieces there are and whether a debris piece is on it
int Num_hull_pieces; // number of hull pieces in existance
debris Hull_debris_list; // head of linked list for hull debris chunks, for quick search
// This list holds debris pieces that are set to expire when their lifetime runs out;
// pieces that were placed by FREDers (i.e. that have the DoNotExpire flag) should not be on it.
SCP_vector<debris> Debris;
debris Debris[MAX_DEBRIS_PIECES];
int Num_debris_pieces = 0;
int Debris_inited = 0;
int Debris_model = -1;
@@ -53,15 +49,7 @@ int Debris_num_submodels = 0;
#define MAX_DEBRIS_DIST 10000.0f // Debris goes away if it's this far away.
#define DEBRIS_DISTANCE_CHECK_TIME (10*1000) // Check every 10 seconds.
#define DEBRIS_INDEX(dp) (int)(dp-Debris.data())
const auto OnDebrisCreatedHook = scripting::Hook::Factory(
"On Debris Created",
"Invoked when a piece of debris is created.",
{
{"Debris", "debris", "The newly created debris object"},
{"Source", "object", "The object (probably a ship) from which this debris piece was spawned."},
});
#define DEBRIS_INDEX(dp) (int)(dp-Debris)
/**
* Start the sequence of a piece of debris writhing in unholy agony!!!
@@ -81,10 +69,8 @@ static void debris_start_death_roll(object *debris_obj, debris *debris_p)
// only play debris destroy sound if hull piece and it has been around for at least 2 seconds
if ( Missiontime > debris_p->time_started + 2*F1_0 ) {
auto snd_id = Ship_info[debris_p->ship_info_index].debris_explosion_sound;
if (snd_id.isValid()) {
snd_play_3d( gamesnd_get_game_sound(snd_id), &debris_obj->pos, &View_position, debris_obj->radius );
}
snd_play_3d( gamesnd_get_game_sound(gamesnd_id(GameSounds::MISSILE_IMPACT1)), &debris_obj->pos, &View_position, debris_obj->radius );
}
}
@@ -96,6 +82,8 @@ static void debris_start_death_roll(object *debris_obj, debris *debris_p)
*/
void debris_init()
{
int i;
if ( !Debris_inited ) {
Debris_inited = 1;
}
@@ -105,10 +93,15 @@ void debris_init()
Debris_num_submodels = 0;
// Reset everything between levels
Debris.clear();
Debris.reserve(SOFT_LIMIT_DEBRIS_PIECES);
Num_debris_pieces = 0;
for (i=0; i<MAX_DEBRIS_PIECES; i++ ) {
Debris[i].flags = 0;
Debris[i].sound_delay = 0;
Debris[i].objnum = -1;
}
Num_hull_pieces = 0;
list_init(&Hull_debris_list);
}
/**
@@ -148,24 +141,17 @@ MONITOR(NumSmallDebrisRend)
MONITOR(NumHullDebrisRend)
/**
* Add item to [virtual] Hull_debris_list
* Removed the ::DEBRIS_EXPIRE flag, and remove item from ::Hull_debris_list
*/
void debris_add_to_hull_list(debris *db)
void debris_clear_expired_flag(debris *db)
{
if ( db->is_hull && !db->flags[Debris_Flags::OnHullDebrisList] ) {
Num_hull_pieces++;
db->flags.set(Debris_Flags::OnHullDebrisList);
}
}
/**
* Remove item from [virtual] Hull_debris_list
*/
void debris_remove_from_hull_list(debris *db)
{
if ( db->is_hull && db->flags[Debris_Flags::OnHullDebrisList] ) {
Num_hull_pieces--;
db->flags.remove(Debris_Flags::OnHullDebrisList);
if ( db->flags & DEBRIS_EXPIRE ) {
db->flags &= ~DEBRIS_EXPIRE;
if ( db->is_hull ) {
Num_hull_pieces--;
list_remove(Hull_debris_list, db);
Assert( Num_hull_pieces >= 0 );
}
}
}
@@ -180,20 +166,18 @@ void debris_delete( object * obj )
debris *db;
num = obj->instance;
Assert(num >= 0 && num < (int)Debris.size());
Assert(Debris[num].objnum == OBJ_INDEX(obj));
Assert( Debris[num].objnum == OBJ_INDEX(obj));
db = &Debris[num];
model_delete_instance(db->model_instance_num);
if ( db->is_hull ) {
debris_remove_from_hull_list(db);
Assert( Num_debris_pieces >= 0 );
if ( db->is_hull && (db->flags & DEBRIS_EXPIRE) ) {
debris_clear_expired_flag(db);
}
db->flags.reset();
db->flags = 0;
db->objnum = -1;
Num_debris_pieces--;
}
/**
@@ -205,7 +189,7 @@ void maybe_delete_debris(debris *db)
{
object *objp;
if (Player_obj != nullptr && timestamp_elapsed(db->next_distance_check) && timestamp_elapsed(db->must_survive_until)) {
if (timestamp_elapsed(db->next_distance_check) && timestamp_elapsed(db->must_survive_until)) {
if (!(Game_mode & GM_MULTIPLAYER)) { // In single player game, just check against player.
if (vm_vec_dist_quick(&Player_obj->pos, &Objects[db->objnum].pos) > MAX_DEBRIS_DIST)
db->lifeleft = 0.1f;
@@ -225,6 +209,9 @@ void maybe_delete_debris(debris *db)
}
}
MONITOR(NumSmallDebris)
MONITOR(NumHullDebris)
/**
* Do various updates to debris: check if time to die, start fireballs
* Maybe delete debris if it's very far away from player.
@@ -234,30 +221,31 @@ void maybe_delete_debris(debris *db)
*/
void debris_process_post(object * obj, float frame_time)
{
int num = obj->instance;
int i, num;
num = obj->instance;
int objnum = OBJ_INDEX(obj);
Assert(num >= 0 && num < (int)Debris.size());
Assert(Debris[num].objnum == objnum);
Assert( Debris[num].objnum == objnum );
debris *db = &Debris[num];
if ( db->is_hull ) {
MONITOR_INC(NumHullDebris,1);
radar_plot_object( obj );
if ( timestamp_elapsed(db->sound_delay) ) {
obj_snd_assign(objnum, db->ambient_sound, &vmd_zero_vector, 0);
obj_snd_assign(objnum, GameSounds::DEBRIS, &vmd_zero_vector, 0);
db->sound_delay = 0;
}
} else {
MONITOR_INC(NumSmallDebris,1);
}
if (!db->flags[Debris_Flags::DoNotExpire]) {
Assertion(db->lifeleft >= 0.0f, "A ship with a negative lifeleft should also have the DoNotExpire flag!");
if (db->lifeleft >= 0.0f) {
db->lifeleft -= frame_time;
if (db->lifeleft < 0.0f) {
debris_start_death_roll(obj, db);
}
}
if ( db->lifeleft < 0.0f ) {
debris_start_death_roll(obj, db);
}
maybe_delete_debris(db); // Make this debris go away if it's very far away.
@@ -287,7 +275,7 @@ void debris_process_post(object * obj, float frame_time)
int lifetime = (myrand()%((b)-(a)+1))+(a);
// Create the spark effects
for (int i=0; i<MAX_DEBRIS_ARCS; ++i) {
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
if ( !timestamp_valid( db->arc_timestamp[i] ) ) {
db->arc_timestamp[i] = timestamp(lifetime); // live up to a second
@@ -344,7 +332,7 @@ void debris_process_post(object * obj, float frame_time)
}
}
for (int i=0; i<MAX_DEBRIS_ARCS; ++i) {
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
if ( timestamp_valid( db->arc_timestamp[i] ) ) {
if ( timestamp_elapsed( db->arc_timestamp[i] ) ) {
// Kill off the spark
@@ -365,23 +353,22 @@ void debris_process_post(object * obj, float frame_time)
}
/**
* Locate the oldest hull debris chunk. Search through the Hull_debris_list, which is a list
* Locate the oldest hull debris chunk. Search through the ::Hull_debris_list, which is a list
* of all the hull debris chunks.
*/
int debris_find_oldest()
{
int oldest_index;
fix oldest_time;
debris *db;
oldest_index = -1;
oldest_time = 0x7fffffff;
for (auto &db: Debris) {
if (db.flags[Debris_Flags::OnHullDebrisList]) {
if ((db.time_started < oldest_time) && !(Objects[db.objnum].flags[Object::Object_Flags::Should_be_dead])) {
oldest_index = DEBRIS_INDEX(&db);
oldest_time = db.time_started;
}
for ( db = GET_FIRST(&Hull_debris_list); db != END_OF_LIST(&Hull_debris_list); db = GET_NEXT(db) ) {
if ( (db->time_started < oldest_time) && !(Objects[db->objnum].flags[Object::Object_Flags::Should_be_dead]) ) {
oldest_index = DEBRIS_INDEX(db);
oldest_time = db->time_started;
}
}
@@ -391,9 +378,6 @@ int debris_find_oldest()
#define DEBRIS_ROTVEL_SCALE 5.0f
void calc_debris_physics_properties( physics_info *pi, vec3d *min, vec3d *max );
MONITOR(NumSmallDebris)
MONITOR(NumHullDebris)
/**
* Create debris from an object
*
@@ -407,7 +391,7 @@ MONITOR(NumHullDebris)
*/
object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, int hull_flag, float exp_force)
{
int objnum, parent_objnum;
int i, n, objnum, parent_objnum;
object *obj;
ship *shipp;
debris *db;
@@ -435,24 +419,27 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
}
}
// try to maintain our soft limit
if (hull_flag && (Num_hull_pieces >= SOFT_LIMIT_DEBRIS_PIECES)) {
if ( hull_flag && (Num_hull_pieces >= MAX_HULL_PIECES ) ) {
// cause oldest hull debris chunk to blow up
int oldest_n = debris_find_oldest();
if (oldest_n >= 0)
debris_start_death_roll(&Objects[Debris[oldest_n].objnum], &Debris[oldest_n]);
n = debris_find_oldest();
if ( n >= 0 ) {
debris_start_death_roll(&Objects[Debris[n].objnum], &Debris[n] );
}
}
int n = 0;
for (auto &db_temp: Debris) {
if ( !(db_temp.flags[Debris_Flags::Used]) )
for (n=0; n<MAX_DEBRIS_PIECES; n++ ) {
if ( !(Debris[n].flags & DEBRIS_USED) )
break;
++n;
}
// we might have to create a new slot
if (n == (int)Debris.size()) {
Debris.emplace_back();
if (n == MAX_DEBRIS_PIECES) {
n = debris_find_oldest();
if (n >= 0)
debris_start_death_roll(&Objects[Debris[n].objnum], &Debris[n]);
nprintf(("Warning","Frame %i: Could not create debris, no more slots left\n", Framecount));
return NULL;
}
db = &Debris[n];
@@ -470,10 +457,8 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
if ( hull_flag ) {
if (rand() < RAND_MAX/6) // Make some pieces blow up shortly after explosion.
db->lifeleft = 2.0f * (myrand() * RAND_MAX_1f) + 0.5f;
else {
db->flags.set(Debris_Flags::DoNotExpire);
else
db->lifeleft = -1.0f; // large hull pieces stay around forever
}
} else {
db->lifeleft = (myrand() * RAND_MAX_1f) * 2.0f + 0.1f;
}
@@ -504,13 +489,12 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
if (vaporize) {
db->lifeleft *= 3.0f;
}
db->flags.set(Debris_Flags::Used);
db->flags |= DEBRIS_USED;
db->is_hull = hull_flag;
db->source_objnum = parent_objnum;
db->damage_type_idx = shipp->debris_damage_type_idx;
db->ship_info_index = shipp->ship_info_index;
db->team = shipp->team;
db->ambient_sound = sip->debris_ambient_sound;
db->fire_timeout = 0; // if not changed, timestamp_elapsed() will return false
db->time_started = Missiontime;
db->species = Ship_info[shipp->ship_info_index].species;
@@ -518,7 +502,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
db->parent_alt_name = shipp->alt_type_index;
db->damage_mult = 1.0f;
for (int i=0; i<MAX_DEBRIS_ARCS; ++i) { // NOLINT
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
db->arc_timestamp[i] = timestamp(-1);
}
@@ -544,9 +528,6 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
db->model_num = model_num;
db->submodel_num = submodel_num;
}
db->model_instance_num = model_create_instance(false, db->model_num);
float radius = submodel_get_radius( db->model_num, db->submodel_num );
db->next_fireball = timestamp_rand(500,2000); //start one 1/2 - 2 secs later
@@ -601,6 +582,8 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
db->damage_mult = sip->debris_damage_mult;
}
Num_debris_pieces++;
vec3d rotvel, radial_vel, to_center;
if ( exp_center )
@@ -628,9 +611,10 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
db->fire_timeout = timestamp(fl2i(t)); // fireballs last from 5 - 30 seconds
if ( Objects[db->source_objnum].radius < MIN_RADIUS_FOR_PERSISTANT_DEBRIS ) {
debris_add_to_hull_list(db);
db->flags |= DEBRIS_EXPIRE; // debris can expire
Num_hull_pieces++;
list_append(&Hull_debris_list, db);
} else {
db->flags.set(Debris_Flags::DoNotExpire);
nprintf(("Alan","A forever chunk of debris was created from ship with radius %f\n",Objects[db->source_objnum].radius));
}
}
@@ -688,16 +672,6 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
// ensure vel is valid
Assert( !vm_is_vec_nan(&obj->phys_info.vel) );
OnDebrisCreatedHook->run(scripting::hook_param_list(
scripting::hook_param("Debris", 'o', obj),
scripting::hook_param("Source", 'o', source_obj)));
if (db->is_hull) {
MONITOR_INC(NumHullDebris,1);
} else {
MONITOR_INC(NumSmallDebris,1);
}
return obj;
}
@@ -766,12 +740,13 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
{
mc_info mc;
mc_info_init(&mc);
int num;
Assert( pdebris->type == OBJ_DEBRIS );
int num = pdebris->instance;
num = pdebris->instance;
Assert( num >= 0 );
Assert( num >= 0 && num < (int)Debris.size() );
Assert( Debris[num].objnum == OBJ_INDEX(pdebris));
// debris_hit_info NULL - so debris-weapon collision
@@ -781,6 +756,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
mc.model_instance_num = -1;
mc.model_num = Debris[num].model_num; // Fill in the model to check
mc.submodel_num = Debris[num].submodel_num;
model_clear_instance( mc.model_num );
mc.orient = &pdebris->orient; // The object's orient
mc.pos = &pdebris->pos; // The object's position
mc.p0 = &other_obj->last_pos; // Point 1 of ray to check
@@ -793,11 +769,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
if (hitNormal)
{
vec3d normal;
if (mc.model_instance_num >= 0)
model_instance_find_world_dir(&normal, &mc.hit_normal, mc.model_instance_num, mc.hit_submodel, mc.orient);
else
model_find_world_dir(&normal, &mc.hit_normal, mc.model_num, mc.hit_submodel, mc.orient);
model_find_world_dir(&normal, &mc.hit_normal, mc.model_num, mc.hit_submodel, mc.orient);
*hitNormal = normal;
}
@@ -864,24 +836,27 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
// first test against the sphere - if this fails then don't do any submodel tests
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
SCP_vector<int> submodel_vector;
polymodel_instance *pmi;
if (model_collide(&mc)) {
// Set earliest hit time
debris_hit_info->hit_time = FLT_MAX;
auto pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
auto pm = model_get(pmi->model_num);
// Do collision the cool new way
if ( debris_hit_info->collide_rotate ) {
SCP_vector<int>::iterator smv;
// We collide with the sphere, find the list of rotating submodels and test one at a time
SCP_vector<int> submodel_vector;
model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
// turn off all rotating submodels, collide against only 1 at a time.
// turn off collision detection for all rotating submodels
for (auto submodel : submodel_vector) {
pmi->submodel[submodel].collision_checked = true;
// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
// turn off all rotating submodels and test for collision
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
pmi->submodel[*smv].collision_checked = true;
}
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
@@ -892,27 +867,25 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
}
// check each submodel in turn
for (auto submodel: submodel_vector) {
auto smi = &pmi->submodel[submodel];
// turn on just one submodel for collision test
smi->collision_checked = false;
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
// turn on submodel for collision test
pmi->submodel[*smv].collision_checked = false;
// set angles for last frame (need to set to prev to get p0)
angles copy_angles = smi->angs;
angles copy_angles = pmi->submodel[*smv].angs;
// find the start and end positions of the sphere in submodel RF
smi->angs = smi->prev_angs;
world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel, &heavy_obj->last_orient, &heavy_obj->last_pos);
pmi->submodel[*smv].angs = pmi->submodel[*smv].prev_angs;
world_find_model_instance_point(&p0, &light_obj->last_pos, pmi, *smv, &heavy_obj->last_orient, &heavy_obj->last_pos);
smi->angs = copy_angles;
world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel, &heavy_obj->orient, &heavy_obj->pos);
pmi->submodel[*smv].angs = copy_angles;
world_find_model_instance_point(&p1, &light_obj->pos, pmi, *smv, &heavy_obj->orient, &heavy_obj->pos);
mc.p0 = &p0;
mc.p1 = &p1;
mc.orient = &vmd_identity_matrix;
mc.submodel_num = submodel;
mc.submodel_num = *smv;
if ( model_collide(&mc) ) {
if ( mc.hit_dist < debris_hit_info->hit_time ) {
@@ -920,27 +893,26 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
// set up debris_hit_info common
set_hit_struct_info(debris_hit_info, &mc, SUBMODEL_ROT_HIT);
model_instance_find_world_point(&debris_hit_info->hit_pos, &mc.hit_point, pm, pmi, mc.hit_submodel, &heavy_obj->orient, &zero);
model_instance_find_world_point(&debris_hit_info->hit_pos, &mc.hit_point, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
// set up debris_hit_info for rotating submodel
if (debris_hit_info->edge_hit == 0) {
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, pm, pmi, mc.hit_submodel, &heavy_obj->orient);
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient);
}
// find position in submodel RF of light object at collison
vec3d int_light_pos, diff;
vm_vec_sub(&diff, mc.p1, mc.p0);
vm_vec_scale_add(&int_light_pos, mc.p0, &diff, mc.hit_dist);
model_instance_find_world_point(&debris_hit_info->light_collision_cm_pos, &int_light_pos, pm, pmi, mc.hit_submodel, &heavy_obj->orient, &zero);
model_instance_find_world_point(&debris_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_instance_num, mc.hit_submodel, &heavy_obj->orient, &zero);
}
}
// Don't look at this submodel again
smi->collision_checked = true;
pmi->submodel[*smv].collision_checked = true;
}
}
// Now complete base model collision checks that do not take into account rotating submodels.
// Recover and do usual ship_ship collision, but without rotating submodels
mc.flags = copy_flags;
*mc.p0 = copy_p0;
*mc.p1 = copy_p1;
@@ -956,7 +928,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
// get collision normal if not edge hit
if (debris_hit_info->edge_hit == 0) {
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, pm, pmi, mc.hit_submodel, &heavy_obj->orient);
model_instance_find_obj_dir(&debris_hit_info->collision_normal, &mc.hit_normal, Ships[heavy_obj->instance].model_instance_num, mc.hit_submodel, &heavy_obj->orient);
}
// find position in submodel RF of light object at collison
@@ -973,6 +945,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
mc.model_instance_num = -1;
mc.model_num = Debris[num].model_num; // Fill in the model to check
mc.submodel_num = Debris[num].submodel_num;
model_clear_instance( mc.model_num );
mc.orient = &pdebris->orient; // The object's orient
mc.radius = model_get_core_radius(Ship_info[Ships[pship_obj->instance].ship_info_index].model_num);
@@ -997,22 +970,6 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
}
}
if (mc_ret_val) {
WarpEffect* warp_effect = nullptr;
ship* shipp = &Ships[pship_obj->instance];
// this is extremely confusing but mc.hit_point_world isn't actually in world coords
// everything above was calculated relative to the heavy's position
vec3d actual_world_hit_pos = mc.hit_point_world + heavy_obj->pos;
if ((shipp->is_arriving()) && (shipp->warpin_effect != nullptr))
warp_effect = shipp->warpin_effect;
else if ((shipp->flags[Ship::Ship_Flags::Depart_warp]) && (shipp->warpout_effect != nullptr))
warp_effect = shipp->warpout_effect;
if (warp_effect != nullptr && point_is_clipped_by_warp(&actual_world_hit_pos, warp_effect))
mc_ret_val = 0;
}
if ( mc_ret_val ) {
@@ -1045,8 +1002,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
int debris_get_team(object *objp)
{
Assert( objp->type == OBJ_DEBRIS );
Assert( objp->instance >= 0 && objp->instance < (int)Debris.size() );
Assert( objp->instance >= 0 && objp->instance < MAX_DEBRIS_PIECES );
return Debris[objp->instance].team;
}
@@ -1083,29 +1039,30 @@ void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs
void debris_render(object * obj, model_draw_list *scene)
{
int i, num, swapped;
polymodel *pm;
debris *db;
swapped = -1;
pm = NULL;
num = obj->instance;
Assert(num >= 0 && num < (int)Debris.size());
Assert(num >= 0 && num < MAX_DEBRIS_PIECES);
db = &Debris[num];
Assert(db->flags[Debris_Flags::Used]);
Assert(db->flags & DEBRIS_USED);
texture_info *tbase = nullptr;
auto pmi = model_get_instance(db->model_instance_num);
auto pm = model_get(pmi->model_num);
texture_info *tbase = NULL;
model_clear_instance( db->model_num );
model_instance_clear_arcs(pm, pmi);
// Swap in a different texture depending on the species
if (db->species >= 0)
{
pm = model_get( db->model_num );
//WMC - Someday, we should have glowing debris.
if ( pm->n_textures == 1 ) {
if ( pm != NULL && (pm->n_textures == 1) ) {
tbase = &pm->maps[0].textures[TM_BASE_TYPE];
swapped = tbase->GetTexture();
tbase->SetTexture(Species_info[db->species].debris_texture.bitmap_id);
@@ -1116,7 +1073,7 @@ void debris_render(object * obj, model_draw_list *scene)
if ( vm_vec_dist_quick( &obj->pos, &Eye_position ) < obj->radius*50.0f ) {
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
if ( timestamp_valid( db->arc_timestamp[i] ) ) {
model_instance_add_arc( pm, pmi, db->submodel_num, &db->arc_pts[i][0], &db->arc_pts[i][1], MARC_TYPE_NORMAL );
model_add_arc( db->model_num, db->submodel_num, &db->arc_pts[i][0], &db->arc_pts[i][1], MARC_TYPE_NORMAL );
}
}
}
@@ -1130,19 +1087,9 @@ void debris_render(object * obj, model_draw_list *scene)
render_info.set_flags(MR_NO_LIGHTING);
}
submodel_render_queue( &render_info, scene, pm, pmi, db->submodel_num, &obj->orient, &obj->pos );
submodel_render_queue( &render_info, scene, db->model_num, db->submodel_num, &obj->orient, &obj->pos );
if (tbase != NULL && (swapped!=-1) && pm) {
tbase->SetTexture(swapped);
}
}
bool debris_is_generic(debris *db)
{
return db->model_num == Debris_model;
}
bool debris_is_vaporized(debris *db)
{
return db->model_num == Debris_vaporize_model;
}
+27 -38
View File
@@ -13,8 +13,6 @@
#define _DEBRIS_H
#include "globalincs/pstypes.h"
#include "globalincs/flagset.h"
#include "gamesnd/gamesnd.h"
class object;
struct CFILE;
@@ -22,48 +20,44 @@ class model_draw_list;
#define MAX_DEBRIS_ARCS 8 // Must be less than MAX_ARC_EFFECTS in model.h
FLAG_LIST(Debris_Flags) {
Used,
OnHullDebrisList,
DoNotExpire, // This debris piece has been placed in FRED and should not expire automatically
NUM_VALUES
};
typedef struct debris {
flagset<Debris_Flags> flags; // See DEBRIS_??? defines
int source_objnum; // What object this came from
int damage_type_idx; // Damage type of this debris
int ship_info_index; // Ship info index of the ship type debris came from
debris *next, *prev; // used for a linked list of the hull debris chunks
int flags; // See DEBRIS_??? defines
int source_objnum; // What object this came from
int damage_type_idx; // Damage type of this debris
int ship_info_index; // Ship info index of the ship type debris came from
int team; // Team of the ship where the debris came from
gamesnd_id ambient_sound; // Ambient looping sound
int objnum = -1; // What object this is linked to
int objnum; // What object this is linked to
float lifeleft; // When 0 or less object dies
int must_survive_until; //WMC - timestamp of earliest point that it can be murthered.
int model_num; // What model this uses
int model_instance_num; // What model instance this uses - needed for arcs
int submodel_num; // What submodel this uses
int next_fireball; // When to start a fireball
int must_survive_until; //WMC - timestamp of earliest point that it can be murthered.
int model_num; // What model this uses
int submodel_num; // What submodel this uses
int next_fireball; // When to start a fireball
int is_hull; // indicates a large hull chunk of debris
int species; // What species this is from. -1 if don't care.
int fire_timeout; // timestamp that holds time for fireballs to stop appearing
int sound_delay; // timestamp to signal when sound should start
fix time_started; // time when debris was created
int fire_timeout; // timestamp that holds time for fireballs to stop appearing
int sound_delay; // timestamp to signal when sound should start
fix time_started; // time when debris was created
int next_distance_check; // timestamp to determine whether to delete this piece of debris.
vec3d arc_pts[MAX_DEBRIS_ARCS][2]; // The endpoints of each arc
vec3d arc_pts[MAX_DEBRIS_ARCS][2]; // The endpoints of each arc
int arc_timestamp[MAX_DEBRIS_ARCS]; // When this times out, the spark goes away. -1 is not used
int arc_frequency; // Starts at 1000, gets bigger
int arc_frequency; // Starts at 0, gets bigger
int parent_alt_name;
float damage_mult;
// flags and objnum are the only things that are cleared when debris is deleted, so they are the only values initialized here (plus next and prev)
} debris;
#define SOFT_LIMIT_DEBRIS_PIECES 64
extern SCP_vector<debris> Debris;
// flags for debris pieces
#define DEBRIS_USED (1<<0)
#define DEBRIS_EXPIRE (1<<1) // debris can expire (ie hull chunks from small ships)
#define MAX_DEBRIS_PIECES 64
extern debris Debris[MAX_DEBRIS_PIECES];
extern int Num_debris_pieces;
struct collision_info_struct;
@@ -75,11 +69,6 @@ object *debris_create( object * source_obj, int model_num, int submodel_num, vec
int debris_check_collision( object * obj, object * other_obj, vec3d * hitpos, collision_info_struct *debris_hit_info=NULL, vec3d* hitnormal = NULL );
void debris_hit( object * debris_obj, object * other_obj, vec3d * hitpos, float damage );
int debris_get_team(object *objp);
void debris_add_to_hull_list(debris *db);
void debris_remove_from_hull_list(debris *db);
bool debris_is_generic(debris *db);
bool debris_is_vaporized(debris *db);
void debris_clear_expired_flag(debris *db);
#endif // _DEBRIS_H
+5 -10
View File
@@ -48,10 +48,10 @@ class DecalDefinition {
DecalDefinition& operator=(const DecalDefinition&) = delete;
// Move constructor and operator
DecalDefinition(DecalDefinition&& other) noexcept {
DecalDefinition(DecalDefinition&& other) SCP_NOEXCEPT {
*this = std::move(other); // Use operator implementation
}
DecalDefinition& operator=(DecalDefinition&& other) noexcept {
DecalDefinition& operator=(DecalDefinition&& other) SCP_NOEXCEPT {
std::swap(_name, other._name);
std::swap(_diffuseFilename, other._diffuseFilename);
@@ -401,14 +401,11 @@ matrix4 getDecalTransform(Decal& decal) {
auto objp = decal.object.objp;
auto ship = &Ships[objp->instance];
auto pmi = model_get_instance(ship->model_instance_num);
auto pm = model_get(pmi->model_num);
vec3d worldPos;
model_instance_find_world_point(&worldPos,
&decal.position,
pm,
pmi,
ship->model_instance_num,
decal.submodel,
&objp->orient,
&objp->pos);
@@ -416,16 +413,14 @@ matrix4 getDecalTransform(Decal& decal) {
vec3d worldDir;
model_instance_find_world_dir(&worldDir,
&decal.orientation.vec.fvec,
pm,
pmi,
ship->model_instance_num,
decal.submodel,
&objp->orient);
vec3d worldUp;
model_instance_find_world_dir(&worldUp,
&decal.orientation.vec.fvec,
pm,
pmi,
ship->model_instance_num,
decal.submodel,
&objp->orient);
@@ -1,14 +1,13 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#include "gamma.sdr"
layout (location = 0) in vec4 fragTexCoord;
layout (location = 1) in vec4 fragColor;
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
layout (location = 0) out vec4 fragOut0;
uniform sampler2DArray baseMap;
layout (binding = 1, std140) uniform genericData {
layout (std140) uniform genericData {
mat4 modelMatrix;
vec4 color;
@@ -25,8 +24,6 @@ layout (binding = 1, std140) uniform genericData {
bool clipEnabled;
};
layout(binding = 2) uniform sampler2DArray baseMap;
void main()
{
vec4 baseColor = texture(baseMap, vec3(fragTexCoord.xy, float(baseMapIndex)));
@@ -1,19 +1,15 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
in vec4 vertPosition;
in vec4 vertTexCoord;
in vec4 vertColor;
out vec4 fragTexCoord;
out vec4 fragColor;
layout (location = 0) in vec4 vertPosition;
layout (location = 1) in vec4 vertColor;
layout (location = 2) in vec4 vertTexCoord;
layout (location = 0) out vec4 fragTexCoord;
layout (location = 1) out vec4 fragColor;
layout (binding = 0, std140) uniform matrixData {
layout (std140) uniform matrixData {
mat4 modelViewMatrix;
mat4 projMatrix;
};
layout (binding = 1, std140) uniform genericData {
layout (std140) uniform genericData {
mat4 modelMatrix;
vec4 color;
@@ -74,7 +74,6 @@ void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
if(dist > lightRadius) {
discard;
}
attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
} else if (lightType == LT_CONE) {
float coneDot = dot(normalize(-lightDir), coneDir);
if(dualCone) {
+6 -24
View File
@@ -1,41 +1,23 @@
in vec2 fragTexCoord;
in vec4 fragColor;
in vec2 fragScreenPosition;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
layout (std140) uniform genericData {
mat4 modelViewMatrix;
mat4 projMatrix;
vec2 offset;
bool textured;
int baseMapIndex;
float horizontalSwipeOffset;
};
void main() {
if (fragScreenPosition.x > horizontalSwipeOffset) {
discard;
}
float distance = horizontalSwipeOffset - fragScreenPosition.x;
vec4 color;
if (textured) {
color = texture(baseMap, vec3(fragTexCoord, float(baseMapIndex))) * fragColor;
} else {
color = fragColor;
}
// Hard-coded for now but can be easily made configurable should that be needed at some point
if (distance < 10.f) {
// Only change the colors but not the alpha channel to preserve the transparent part of text
color.xyz = vec3(1.0);
}
fragOut0 = color;
if (textured) {
fragOut0 = texture(baseMap, vec3(fragTexCoord, float(baseMapIndex))) * fragColor;
} else {
fragOut0 = fragColor;
}
}
+2 -8
View File
@@ -5,16 +5,13 @@ in vec2 vertTexCoord;
out vec2 fragTexCoord;
out vec4 fragColor;
out vec2 fragScreenPosition;
layout (std140) uniform genericData {
mat4 modelViewMatrix;
mat4 projMatrix;
vec2 offset;
bool textured;
int baseMapIndex;
float horizontalSwipeOffset;
};
void main()
@@ -22,8 +19,5 @@ void main()
fragTexCoord = vertTexCoord;
fragColor = vertColor;
vec4 position = vec4(vertPosition + offset, 0.0, 1.0);
fragScreenPosition = position.xy;
gl_Position = projMatrix * position;
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition, 0.0, 1.0);
}
@@ -16,11 +16,11 @@ struct def_file
const size_t size;
};
#include "embedded_files.inc"
#include "def_files/generated_def_files-generic.inc"
default_file defaults_get_file(const char *filename)
{
default_file def{};
default_file def;
auto endIter = std::end(Default_files);
for (auto iter = std::begin(Default_files); iter != endIter; ++iter)
@@ -44,7 +44,7 @@ default_file defaults_get_file(const char *filename)
SCP_vector<default_file> defaults_get_all() {
SCP_vector<default_file> files;
for (const auto& file : Default_files) {
for (auto& file : Default_files) {
default_file def;
def.path_type = file.path_type;
def.filename = file.filename;
+96
View File
@@ -0,0 +1,96 @@
/*
* You may not sell or otherwise commercially exploit the source or things you
* create based on the source.
*/
#include "globalincs/pstypes.h"
#include "def_files/def_files.h"
#include <iterator>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
struct def_file
{
const char* path_type;
const char* filename;
const TCHAR* resource_name;
};
def_file Default_files[] =
{
#include "def_files/generated_def_files-win32.inc"
};
default_file defaults_get_file(const char *filename)
{
default_file def;
auto endIter = std::end(Default_files);
for (auto iter = std::begin(Default_files); iter != endIter; ++iter)
{
if (!stricmp(iter->filename, filename))
{
HRSRC resource = FindResource(nullptr, iter->resource_name, RT_RCDATA);
if (resource == nullptr)
{
continue;
}
HGLOBAL resHandle = LoadResource(nullptr, resource);
if (resHandle == nullptr)
{
continue;
}
def.path_type = iter->path_type;
def.filename = iter->filename;
def.data = LockResource(resHandle);
def.size = SizeofResource(nullptr, resource);
return def;
}
}
//WMC - This is really bad, because it means we have a default table missing.
Error(LOCATION, "Default table '%s' missing from executable - contact a coder.", filename);
def.data = nullptr;
def.data = 0;
return def;
}
SCP_vector<default_file> defaults_get_all() {
SCP_vector<default_file> files;
for (auto& file : Default_files) {
default_file def;
HRSRC resource = FindResource(nullptr, file.resource_name, RT_RCDATA);
if (resource == nullptr)
{
continue;
}
HGLOBAL resHandle = LoadResource(nullptr, resource);
if (resHandle == nullptr)
{
continue;
}
def.path_type = file.path_type;
def.filename = file.filename;
def.data = LockResource(resHandle);
def.size = SizeofResource(nullptr, resource);
files.push_back(def);
}
return files;
}
+4 -4
View File
@@ -15,10 +15,10 @@
struct default_file
{
const char* path_type = nullptr;
const char* filename = nullptr;
const void* data = nullptr;
size_t size = 0;
const char* path_type;
const char* filename;
const void* data;
size_t size;
};
//Used to retrieve pointer to file data from def_files.cpp
@@ -0,0 +1,2 @@
@ARRAY_ELEMENTS@
+91
View File
@@ -0,0 +1,91 @@
IF(MSVC)
# Windows specific version using resource files
set(RES_CONTENT)
set(ARRAY_ELEMENTS)
FOREACH(file ${default_files_files})
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
# Retrieve the path type name from the relative path
GET_FILENAME_COMPONENT(PATH_TYPE "${RELATIVE_FILE_PATH}" DIRECTORY)
file(TO_NATIVE_PATH "${PATH_TYPE}" PATH_TYPE)
string(REPLACE "\\" "\\\\" PATH_TYPE "${PATH_TYPE}")
GET_FILENAME_COMPONENT(FILE_NAME "${RELATIVE_FILE_PATH}" NAME)
string(MAKE_C_IDENTIFIER "${RELATIVE_FILE_PATH}" FIELD_NAME)
set(FIELD_NAME "Default_${FIELD_NAME}")
string(TOUPPER "${FIELD_NAME}" FIELD_NAME)
set(ARRAY_ELEMENTS "${ARRAY_ELEMENTS}\n\t{ \"${PATH_TYPE}\", \"${FILE_NAME}\" , TEXT(\"${FIELD_NAME}\") },")
set(RES_CONTENT "${RES_CONTENT}\n${FIELD_NAME} RCDATA \"${INPUT_NAME}\"")
ENDFOREACH(file)
file(WRITE "${GENERATED_SOURCE_DIR}/code/default_files.rc" "${RES_CONTENT}")
configure_file("def_files/generated_def_files-win32.inc.in" "${GENERATED_SOURCE_DIR}/code/def_files/generated_def_files-win32.inc")
target_sources(code INTERFACE "${GENERATED_SOURCE_DIR}/code/default_files.rc")
else()
# Generic version using embedfile
SET(DEF_OUT_FILES)
set(INCLUDE_LIST)
set(ARRAY_ELEMENTS)
FOREACH(file ${default_files_files})
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
# For some reason this is needed...
GET_FILENAME_COMPONENT(DIRECTORY_PATH ${OUTPUT} DIRECTORY)
FILE(MAKE_DIRECTORY ${DIRECTORY_PATH})
# Retrieve the path type name from the relative path
GET_FILENAME_COMPONENT(PATH_TYPE "${RELATIVE_FILE_PATH}" DIRECTORY)
file(TO_NATIVE_PATH "${PATH_TYPE}" PATH_TYPE)
if (MINGW)
# There is a bug in CMake where it thinks MinGW uses forward slashes for paths but we need backslashes for Windows builds
string(REPLACE "/" "\\" PATH_TYPE "${PATH_TYPE}")
endif()
# Properly escape back slashes in strings
string(REPLACE "\\" "\\\\" PATH_TYPE "${PATH_TYPE}")
GET_FILENAME_COMPONENT(FILE_NAME "${RELATIVE_FILE_PATH}" NAME)
string(MAKE_C_IDENTIFIER "${RELATIVE_FILE_PATH}" FIELD_NAME)
set(HEADER_FILE "${OUTPUT}.h")
set(SOURCE_FILE "${OUTPUT}.cpp")
set_source_files_properties("${HEADER_FILE}" "${SOURCE_FILE}" PROPERTIES GENERATED TRUE)
set(ALL_OUTPUTS "${HEADER_FILE}" "${SOURCE_FILE}")
set(FIELD_NAME "Default_${FIELD_NAME}")
set(INCLUDE_LIST "${INCLUDE_LIST}\n#include \"${file}.h\"")
set(ARRAY_ELEMENTS "${ARRAY_ELEMENTS}\n\t{ \"${PATH_TYPE}\", \"${FILE_NAME}\" , ${FIELD_NAME} , ${FIELD_NAME}_size },")
ADD_CUSTOM_COMMAND(
OUTPUT ${ALL_OUTPUTS}
COMMAND embedfile "${INPUT_NAME}" "${OUTPUT}" "${FIELD_NAME}"
MAIN_DEPENDENCY "${INPUT_NAME}"
DEPENDS embedfile
COMMENT "Generating string file for ${INPUT_NAME}"
)
LIST(APPEND DEF_OUT_FILES ${ALL_OUTPUTS})
ENDFOREACH(file)
configure_file("def_files/generated_def_files-generic.inc.in" "${GENERATED_SOURCE_DIR}/code/def_files/generated_def_files-generic.inc")
target_sources(code PRIVATE ${DEF_OUT_FILES})
SOURCE_GROUP("Generated Files\\Default Files" FILES ${DEF_OUT_FILES})
endif()
@@ -1,34 +0,0 @@
#include "CombinedExecutionContext.h"
namespace executor {
CombinedExecutionContext::CombinedExecutionContext(SCP_vector<std::shared_ptr<IExecutionContext>> contexts)
: m_contexts(std::move(contexts))
{
}
IExecutionContext::State CombinedExecutionContext::determineContextState() const
{
bool suspended_context = false;
bool invalid_context = false;
for (const auto& context : m_contexts) {
const auto state = context->determineContextState();
if (state == IExecutionContext::State::Suspended) {
suspended_context = true;
} else if (state == IExecutionContext::State::Invalid) {
invalid_context = true;
}
}
// If there is an invalid context then the combined state is invalid
// If there is not but there is a suspended one, then the state is suspended
if (invalid_context) {
return IExecutionContext::State::Invalid;
} else if (suspended_context) {
return IExecutionContext::State::Suspended;
} else {
return IExecutionContext::State::Valid;
}
}
CombinedExecutionContext::~CombinedExecutionContext() = default;
} // namespace executor
-21
View File
@@ -1,21 +0,0 @@
#pragma once
#include "IExecutionContext.h"
#include "gamesequence/gamesequence.h"
#include "utils/event.h"
namespace executor {
class CombinedExecutionContext : public IExecutionContext {
public:
CombinedExecutionContext(SCP_vector<std::shared_ptr<IExecutionContext>> contexts);
~CombinedExecutionContext() override;
State determineContextState() const override;
private:
SCP_vector<std::shared_ptr<IExecutionContext>> m_contexts;
};
} // namespace executor
-63
View File
@@ -1,63 +0,0 @@
#include "Executor.h"
#include "utils/finally.h"
namespace executor {
namespace {
thread_local Executor* currentExecutorRef = nullptr;
}
Executor* currentExecutor() { return currentExecutorRef; }
void Executor::post(Executor::Callback cb)
{
// To avoid deadlocks or recusive mutexes we have a temporary list which contains work items not added to the queue
// yet. Those items will be transferred to the main queue in the next process call.
std::unique_lock<std::mutex> lock(m_pendingWorkItemsMutex);
m_pendingWorkItems.push_back(std::move(cb));
}
void Executor::process()
{
// Ensure that no deadlocks happen when this is called from multiple threads
std::lock(m_mainMutex, m_pendingWorkItemsMutex);
Assertion(currentExecutorRef == nullptr, "Executor is already processing! Only one is allowed at a time.");
currentExecutorRef = this;
// Clean up ref after this function
auto _ = util::finally([]() { currentExecutorRef = nullptr; });
std::lock_guard<std::mutex> lk1(m_mainMutex, std::adopt_lock);
{
// Only need this for a limited time so we do this in a separate scope
std::lock_guard<std::mutex> lk2(m_pendingWorkItemsMutex, std::adopt_lock);
// Now move the pending items over to the actual work list
std::move(m_pendingWorkItems.begin(), m_pendingWorkItems.end(), std::back_inserter(m_workItems));
m_pendingWorkItems.clear();
}
for (auto iter = m_workItems.begin(); iter != m_workItems.end();) {
auto& cb = *iter;
if (cb() == CallbackResult::Done) {
// This callback does not want to be called again
// if we're sitting on the very last work item, popping-back will invalidate the iterator!
if (iter + 1 == m_workItems.end()) {
m_workItems.pop_back();
break;
}
// Remove entry without copying it since the current iterator value is not needed anymore
std::iter_swap(iter, std::prev(m_workItems.end()));
m_workItems.pop_back();
continue;
}
// next particle
++iter;
}
}
} // namespace executor
-54
View File
@@ -1,54 +0,0 @@
#pragma once
#include "globalincs/pstypes.h"
#include <mutex>
namespace executor {
/**
* @brief A class that collects work that should be executed repeatedly.
*
* The intention behind this is that the engine code creates executor objects and then calls process() on them at
* specific points of the engine code. External code can then post() work items to be executed when that point of the
* code is reached without introducing a hard dependency between the two code modules.
*
* Work items have the option of specifying that they should be rescheduled for the next execution round.
*
* @note This class is thread safe and work items can be posted to the executor from different threads without risking
* data corruption.
*/
class Executor {
public:
enum class CallbackResult {
Done, //! The work item is finished
Reschedule, //! The work item should be executed again in the next round
};
using Callback = std::function<CallbackResult()>;
/**
* @brief Adds a work item to this executor
*
* This work item will be executed every time process() is called until it returns CallbackResult::Done.
*
* @param cb The work item
*/
void post(Callback cb);
/**
* @brief Executes one round of work items
*/
void process();
private:
std::mutex m_mainMutex;
SCP_vector<Callback> m_workItems;
std::mutex m_pendingWorkItemsMutex;
SCP_vector<Callback> m_pendingWorkItems;
};
Executor* currentExecutor();
} // namespace executor
@@ -1,42 +0,0 @@
#include "GameStateExecutionContext.h"
#include "events/events.h"
namespace executor {
GameStateExecutionContext::GameStateExecutionContext(GS_STATE contextState, int stateInstance)
: m_contextState(contextState), m_stateInstanceId(stateInstance)
{
}
GameStateExecutionContext::~GameStateExecutionContext() = default;
IExecutionContext::State GameStateExecutionContext::determineContextState() const
{
const auto depth = gameseq_get_state_idx(m_contextState);
if (depth < 0) {
// Our game state is not present anymore
return IExecutionContext::State::Invalid;
}
if (gameseq_get_state() == m_contextState) {
// Check if this is still the same instance
if (gameseq_get_state_instance_id() != m_stateInstanceId) {
return IExecutionContext::State::Invalid;
}
// This is still the same state and it is active
return State::Valid;
}
// We are not in the correct state but it is still in the stack so we might return to it at some point
return State::Suspended;
}
std::shared_ptr<IExecutionContext> GameStateExecutionContext::captureContext()
{
return std::make_shared<GameStateExecutionContext>(static_cast<GS_STATE>(gameseq_get_state()),
gameseq_get_state_instance_id());
}
} // namespace executor
-31
View File
@@ -1,31 +0,0 @@
#pragma once
#include "IExecutionContext.h"
#include "gamesequence/gamesequence.h"
#include "utils/event.h"
namespace executor {
/**
* @brief An execution context that captures the game state
*
* This will only execute if the game state is the same as at the time when captureContext() was called. If a game state
* is pushed onto the stack then this context will only suspend. Should the game state change completely then this
* context will be invalid. Will also become invalid if the same game state is active but with a different instance id.
*/
class GameStateExecutionContext : public IExecutionContext, public std::enable_shared_from_this<GameStateExecutionContext> {
public:
GameStateExecutionContext(GS_STATE contextState, int stateInstance);
~GameStateExecutionContext() override;
State determineContextState() const override;
static std::shared_ptr<IExecutionContext> captureContext();
private:
GS_STATE m_contextState = GS_STATE_INVALID;
int m_stateInstanceId = -1;
};
} // namespace executor
-30
View File
@@ -1,30 +0,0 @@
#include "IExecutionContext.h"
namespace executor {
Executor::Callback runInContext(const std::shared_ptr<IExecutionContext>& context,
const IExecutionContext::Callback& func)
{
return [context, func]() {
const auto ctxState = context->determineContextState();
switch (ctxState) {
case IExecutionContext::State::Valid:
// We are in a valid state so execute our wrapped function
return func(IExecutionContext::State::Valid);
case IExecutionContext::State::Suspended:
// The state is not valid but my return so keep this function alive
return Executor::CallbackResult::Reschedule;
case IExecutionContext::State::Invalid:
// Call the function once more to let it know that the state became invalid
func(IExecutionContext::State::Invalid);
// This state will not become valid again so we do not need to be rescheduled
return Executor::CallbackResult::Done;
default:
UNREACHABLE("Unhandled context state %d", static_cast<int>(ctxState));
return Executor::CallbackResult::Done;
}
};
}
} // namespace executor
-47
View File
@@ -1,47 +0,0 @@
#pragma once
#include "Executor.h"
namespace executor {
/**
* @brief Abstract class representing the context of an execution.
*
* This is intended to be used with executors to ensure that work items are only executed in the same context as they
* were started. See runInContext() for how to use this with executors.
*/
class IExecutionContext {
public:
enum class State {
Valid, //! We are currently in the state captured in this context
Suspended, //! We are in a state that is not valid but may return to the captured state
Invalid, //! We are in an unrelated state
};
using Callback = std::function<Executor::CallbackResult(State contextState)>;
virtual ~IExecutionContext() = default;
/**
* @brief Determines the state of the context
* @return The context state
*/
virtual State determineContextState() const = 0;
};
/**
* @brief Wraps the specified callback in an execution context
*
* The return value is a work item for an executor that will only call the passed function when the context is valid.
* The function will not be called when the context is suspended. Should the context become invalid, the function will
* be called one last time with State::Invalid to indicate to the function that the context became invalid. This is
* useful to do cleanup work (e.g. setting an error state in created Lua Promises).
*
* @param context The execution context
* @param func The function to wrap
* @return An executor work item
*/
Executor::Callback runInContext(const std::shared_ptr<IExecutionContext>& context,
const IExecutionContext::Callback& func);
} // namespace executor
-10
View File
@@ -1,10 +0,0 @@
#include "global_executors.h"
namespace executor {
const std::shared_ptr<Executor> OnSimulationExecutor = std::make_shared<Executor>();
const std::shared_ptr<Executor> OnFrameExecutor = std::make_shared<Executor>();
} // namespace executor
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#include "Executor.h"
namespace executor
{
/**
* @brief Executor that will be called at the end of every simulation frame.
*/
extern const std::shared_ptr<Executor> OnSimulationExecutor;
/**
* @brief Executor that will be called just before the game triggers the presentation of the current frame.
*/
extern const std::shared_ptr<Executor> OnFrameExecutor;
}
+5 -8
View File
@@ -29,6 +29,8 @@ int Knossos_warp_ani_used;
#define WARPHOLE_GROW_TIME (2.35f) // time for warphole to reach max size (also time to shrink to nothing once it begins to shrink)
#define MAX_FIREBALLS 200
#define MAX_WARP_LOD 0
fireball Fireballs[MAX_FIREBALLS];
@@ -383,15 +385,10 @@ void fireball_parse_tbl()
parse_modular_table(NOX("*-fbl.tbm"), parse_fireball_tbl);
// fill in extra LOD filenames
for (auto &fi: Fireball_info)
for (int i = 0; i < Num_fireball_types; i++)
{
if (fi.lod_count > 1)
{
auto lod0 = fi.lod[0].filename;
for (int j = 1; j < fi.lod_count; ++j)
sprintf(fi.lod[j].filename, "%s_%d", lod0, j);
}
for (int j = 1; j < Fireball_info[i].lod_count; j++)
sprintf( Fireball_info[i].lod[j].filename, "%s_%d", Fireball_info[i].lod[0].filename, j);
}
fireballs_parsed = true;
-7
View File
@@ -40,8 +40,6 @@ class asteroid_info;
#define FIREBALL_NUM_LARGE_EXPLOSIONS 2
#define MAX_FIREBALLS 200
extern int fireball_used[MAX_FIREBALL_TYPES];
// all this moved here by Goober5000 because it makes more sense in the H file
@@ -95,11 +93,6 @@ typedef struct fireball {
} fireball;
// end move
extern fireball Fireballs[MAX_FIREBALLS];
extern int Num_fireballs;
extern bool fireballs_inited;
void fireball_init();
void fireball_render(object* obj, model_draw_list *scene);
void fireball_delete( object * obj );
+32 -17
View File
@@ -88,7 +88,8 @@ shader Grey_shader;
////////////////////////////////////////////////////////////////////
static int help_left_bracket_bitmap;
static int help_right_bracket_bitmap;
static SCP_vector<help_overlay> help_overlaylist;
static help_overlay help_overlaylist[MAX_HELP_OVERLAYS];
int num_help_overlays;
static int current_helpid = -1; // the currently active overlay_id, only really used for the debug console funxions
static int current_resolution = -1;
@@ -102,7 +103,7 @@ static int Source_game_state; // state from where F1 was pressed
int help_overlay_get_index(const char* overlay_name)
{
for (int i = 0; i < static_cast<int>(help_overlaylist.size()); i++) {
for (int i = 0; i < num_help_overlays; i++) {
if (!stricmp(overlay_name, help_overlaylist[i].name)) {
return i;
}
@@ -114,7 +115,7 @@ int help_overlay_get_index(const char* overlay_name)
// query whether a help overlay is active (ie being displayed)
int help_overlay_active(int overlay_id)
{
Assert(overlay_id < static_cast<int>(help_overlaylist.size()));
Assert(overlay_id < MAX_HELP_OVERLAYS);
if (overlay_id < 0) {
return 0;
@@ -126,7 +127,9 @@ int help_overlay_active(int overlay_id)
// stop displaying a help overlay
void help_overlay_set_state(int overlay_id, int resolution_index, int state)
{
if ( (overlay_id >= 0) && (overlay_id < static_cast<int>(help_overlaylist.size())) &&
Assert(overlay_id < MAX_HELP_OVERLAYS);
if ( (overlay_id >= 0) && (overlay_id < num_help_overlays) &&
(resolution_index >= 0) && (resolution_index < help_overlaylist[overlay_id].num_resolutions) ) {
if ( state > 0 ) {
Help_overlay_flags |= (1<<overlay_id);
@@ -143,6 +146,8 @@ void help_overlay_set_state(int overlay_id, int resolution_index, int state)
// maybe blit a bitmap of a help overlay to the screen
void help_overlay_maybe_blit(int overlay_id, int resolution_index)
{
Assert(overlay_id < MAX_HELP_OVERLAYS);
if ( (overlay_id >= 0) && (Help_overlay_flags & (1<<overlay_id)) &&
(resolution_index >= 0) && (resolution_index < help_overlaylist[overlay_id].num_resolutions) ) {
context_help_grey_screen();
@@ -278,16 +283,14 @@ void launch_context_help()
}
}
void close_help()
{
for (auto &ho : help_overlaylist) {
if (!ho.textlist.empty()) {
for (auto &text : ho.textlist.at(0)) {
safe_kill(text.string);
void close_help(){
for (int overlay_id=0; overlay_id<MAX_HELP_OVERLAYS; overlay_id++){
if (!help_overlaylist[overlay_id].textlist.empty()) {
for(SCP_vector<help_text>::iterator ii = help_overlaylist[overlay_id].textlist.at(0).begin(); ii != help_overlaylist[overlay_id].textlist.at(0).end(); ++ii) {
safe_kill(ii->string);
}
}
}
help_overlaylist.clear();
}
// Called once at the beginning of the game to load help bitmaps & data
@@ -305,8 +308,7 @@ void help_overlay_init()
atexit(close_help);
// clear the list if it's not empty for whatever reason
close_help();
num_help_overlays = 0;
// parse help.tbl
parse_helptbl(HELP_OVERLAY_FILENAME);
@@ -346,9 +348,20 @@ void parse_helptbl(const char *filename)
overlay_id = help_overlay_get_index(name);
if (overlay_id < 0) {
overlay_id = static_cast<int>(help_overlaylist.size());
help_overlaylist.emplace_back();
strcpy_s(help_overlaylist[overlay_id].name, name);
if (num_help_overlays >= MAX_HELP_OVERLAYS) {
Warning(LOCATION, "Could not load help overlay '%s' as maximum number of help overlays was reached (Max is %d)", name, MAX_HELP_OVERLAYS);
if (!skip_to_string("$end")) {
Error(LOCATION, "Couldn't find $end. Help.tbl or -hlp.tbm is invalid.\n");
}
continue;
}
else {
overlay_id = num_help_overlays;
strcpy_s(help_overlaylist[overlay_id].name, name);
num_help_overlays++;
}
}
// clear out counters in the overlay struct
@@ -495,6 +508,8 @@ void help_overlay_blit(int overlay_id, int resolution_index)
int rbracketcount = help_overlaylist[overlay_id].rbracketcount;
int lbracketcount = help_overlaylist[overlay_id].lbracketcount;
Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
// this draws each line of help text with white on black text (use the first resolution index for the string)
font::set_font(help_overlaylist[overlay_id].fontlist.at(resolution_index));
for (idx = 0; idx < textcount; idx++) {
@@ -538,7 +553,7 @@ DCF(help_reload, "Reloads help overlay data from help.tbl")
dc_printf( "Usage: sample\nCrashes your machine.\n" );
}
close_help();
num_help_overlays = 0;
parse_helptbl(HELP_OVERLAY_FILENAME);
parse_modular_table(NOX("*-hlp.tbm"), parse_helptbl);
}
+2
View File
@@ -16,6 +16,8 @@
// Help overlays
//
#define MAX_HELP_OVERLAYS 30
#define SS_OVERLAY "ship" // ship selection help
#define WL_OVERLAY "weapon" // weapons loadout help
#define BR_OVERLAY "briefing" // briefing help
+4 -16
View File
@@ -29,9 +29,7 @@ typedef struct state_stack {
int current_state;
int previous_state;
int event_queue[MAX_GAMESEQ_EVENTS];
int queue_tail;
int queue_head;
int instance_id;
int queue_tail, queue_head;
} state_stack;
// DO NOT MAKE THIS NON-STATIC!!!!
@@ -41,7 +39,6 @@ LOCAL int gs_current_stack = -1; // index of top state on stack.
static int state_reentry = 0; // set if we are already in state processing
static int state_processing_event_post = 0; // set if we are already processing an event to switch states
static int state_in_event_processer = 0;
static int next_instance_id = 1;
// Text of state, corresponding to enum values for GS_STATE_*
//XSTR:OFF
@@ -188,11 +185,10 @@ void gameseq_init()
for (i=0; i<GS_STACK_SIZE; i++ ) {
// gs[i].current_state = GS_STATE_MAIN_MENU;
gs[i].current_state = 0;
gs[i].current_state = 0;
gs[i].previous_state = 0;
gs[i].queue_tail = 0;
gs[i].queue_head = 0;
gs[i].instance_id = 0;
gs[i].queue_tail=0;
gs[i].queue_head=0;
}
gs_current_stack = 0;
@@ -278,7 +274,6 @@ void gameseq_set_state(int new_state, int override)
gs[gs_current_stack].current_state = new_state;
gs[gs_current_stack].previous_state = old_state;
gs[gs_current_stack].instance_id = ++next_instance_id;
game_enter_state(old_state,gs[gs_current_stack].current_state);
state_reentry--;
@@ -313,7 +308,6 @@ void gameseq_push_state( int new_state )
gs[gs_current_stack].previous_state = old_state;
gs[gs_current_stack].queue_tail = 0;
gs[gs_current_stack].queue_head = 0;
gs[gs_current_stack].instance_id = ++next_instance_id;
game_enter_state(old_state,gs[gs_current_stack].current_state);
state_reentry--;
@@ -425,9 +419,3 @@ int gameseq_get_state_idx(int state)
return -1;
}
int gameseq_get_state_instance_id(int depth) {
Assert(depth <= gs_current_stack);
return gs[gs_current_stack - depth].instance_id;
}
+2 -14
View File
@@ -193,23 +193,11 @@ void game_do_state(int current_state);
// Kazan
bool GameState_Stack_Valid();
// WMC
//WMC
int gameseq_get_event_idx(const char* s);
int gameseq_get_state_idx(const char* s);
// zookeeper
//zookeeper
int gameseq_get_state_idx(int state);
/**
* @brief Gets a state instance id of the specified depth.
*
* The instance ID is an integer associated with a specific instance of a state. Should the same state be entered later
* it will have a different instance id. This is meant to be used for keeping track of state changes without registering
* for the state change events.
*
* @param depth The depth in the stack to query the instance id
* @return The instance id
*/
int gameseq_get_state_instance_id(int depth = 0);
#endif /* __GAMESEQUENCE_H__ */
+2 -2
View File
@@ -1615,7 +1615,7 @@ int event_music_next_soundtrack(int delta)
}
// Goober5000 - along the same lines; this is for the sexp
void event_sexp_change_soundtrack(const char *name)
void event_sexp_change_soundtrack(char *name)
{
Assert(name);
@@ -1653,7 +1653,7 @@ void event_music_get_soundtrack_name(char *outbuf)
}
// set the current soundtrack based on name
void event_music_set_soundtrack(const char *name)
void event_music_set_soundtrack(char *name)
{
Current_soundtrack_num = event_music_get_soundtrack_index(name);
+2 -2
View File
@@ -118,8 +118,8 @@ void event_music_start_default();
void event_music_get_info(char *outbuf);
void event_music_get_soundtrack_name(char *outbuf);
int event_music_next_soundtrack(int delta);
void event_sexp_change_soundtrack(const char *name);
void event_music_set_soundtrack(const char *name);
void event_sexp_change_soundtrack(char *name);
void event_music_set_soundtrack(char *name);
void event_music_set_score(int score_index, const char *name);
int event_music_get_soundtrack_index(const char *name);
int event_music_get_spooled_music_index(const char *name);
+6 -10
View File
@@ -288,7 +288,7 @@ int gamesnd_lookup_name(const char* name, const SCP_vector<game_snd>& sounds)
for(SCP_vector<game_snd>::const_iterator snd = sounds.begin(); snd != sounds.end(); ++snd)
{
if (!stricmp(snd->name.c_str(), name))
if (snd->name == name)
{
return i;
}
@@ -417,9 +417,8 @@ interface_snd_id gamesnd_get_by_iface_tbl_index(int index)
* @param flags See the parse_sound_flags enum
*
*/
bool parse_game_sound(const char* tag, gamesnd_id* idx_dest)
{
if (optional_string(tag))
void parse_game_sound(const char* tag, gamesnd_id* idx_dest) {
if(optional_string(tag))
{
SCP_string buf;
stuff_string(buf, F_NAME);
@@ -427,13 +426,10 @@ bool parse_game_sound(const char* tag, gamesnd_id* idx_dest)
*idx_dest = gamesnd_get_by_name(buf.c_str());
// The special case "-1" is needed to silence warnings where sounds are intentionally removed
if (idx_dest->isValid() || buf == "-1")
return true;
error_display(0, "Could not find game sound with name '%s'!", buf.c_str());
if (!idx_dest->isValid() && buf != "-1") {
error_display(0, "Could not find game sound with name '%s'!", buf.c_str());
}
}
return false;
}
/**
+3 -3
View File
@@ -368,9 +368,9 @@ interface_snd_id gamesnd_get_by_iface_name(const char* name);
gamesnd_id gamesnd_get_by_tbl_index(int index);
interface_snd_id gamesnd_get_by_iface_tbl_index(int index);
// This should handle NO_SOUND just fine since it doesn't directly access lowlevel code
// Does all parsing for a sound. Returns true if a sound was successfully parsed.
bool parse_game_sound(const char* tag, gamesnd_id* idx_dest);
//This should handle NO_SOUND just fine since it doesn't directly access lowlevel code
//Does all parsing for a sound
void parse_game_sound(const char* tag, gamesnd_id* idx_dest);
void parse_iface_sound(const char* tag, interface_snd_id* idx_dest);
void parse_iface_sound_list(const char* tag, SCP_vector<interface_snd_id>& destination, const char* object_name, bool scp_list = false);
+1 -1
View File
@@ -132,7 +132,7 @@ class flagset {
namespace std {
template <typename T, size_t N>
struct hash<::flagset<T, N>> {
size_t operator()(const ::flagset<T, N>& val) const { return val.hash(); }
size_t operator()(const ::flagset<T, N>& val) { return val.hash(); }
};
} // namespace std
Loaded 100 of 1038 files, more files were not shown because too many files have changed in this diff. Show more