mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b7fc0b6a3 | ||
|
|
2e4bef0d09 | ||
|
|
172952cb0f | ||
|
|
72c27bdbe8 | ||
|
|
bd4de16007 | ||
|
|
2e560f2ddb | ||
|
|
d35d3d25f8 | ||
|
|
2d5111f14b | ||
|
|
d95754d6b4 | ||
|
|
5e3d4c6cfd | ||
|
|
deca820c9e | ||
|
|
21c298271b |
No files matched your search
+4
-5
@@ -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
@@ -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/.*$'
|
||||
|
||||
@@ -9,7 +9,3 @@ indent_style = tab
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.sh]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
cmake/ @asarium
|
||||
|
||||
code/executor/ @asarium
|
||||
|
||||
code/scpui/ @asarium
|
||||
|
||||
code/scripting/ @asarium
|
||||
@@ -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
|
||||
@@ -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 }}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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}")
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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 ..
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 -*--===#
|
||||
#
|
||||
Executable
+24
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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}")
|
||||
@@ -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,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()
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)) {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+40
-65
@@ -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
@@ -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 );
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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() )
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
+5
-8
@@ -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)));
|
||||
+7
-11
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,2 @@
|
||||
|
||||
@ARRAY_ELEMENTS@
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in new issue
Block a user