Compare commits

..
Author SHA1 Message Date
John Fernandez 456ee79ab4 Update Release.mako 2023-10-26 23:43:06 -04:00
Goober5000 5238f65d7c fix incorrect setting of disabled/disarmed flags when cheating
Normally the disabled/disarmed flags are only set if the destroyed subsystem is actually an engine or turret.  This should be done for cheats as well, otherwise, for example, destroying any subsystem on a non-engined ship will cause it to become disabled.
2023-10-26 23:43:06 -04:00
Goober5000 47cd2a06a6 fix a crash in the apply-loadout-to-wing routine
If a wing has fewer than four ships, clicking the apply-to-all button will cause a vector subscript out of range error.  This fixes it.
2023-10-26 23:43:06 -04:00
Goober5000 9ac617dd1a fix change-soundtrack after <No Music>
The fix in #5578 assumed that a previously playing soundtrack would properly set the timestamp, but if no soundtrack was previously played at all, this wouldn't happen.  So if we deliberately don't play a soundtrack, be sure to set the timestamp as if `event_music_do_frame()` had been called.

Fixes #5705.
2023-10-26 23:43:06 -04:00
wookieejedi 365ec2a14d Fix glare shining through cockpits in freelook (#5690)
Fixes #3098. The `shipfx_eye_in_shadow` function did a collision check for cockpits, bit did not previously take into account of the viewpoint had a non-forward orientation (ie the player was using free look). This PR sets the collide check to take that into account with a 1 line fix. Tested with multiple FotG cockpits and fixes the issue.
2023-10-26 23:43:05 -04:00
John Fernandez 1373a42719 Fix workflow by adding reference branch 2023-10-26 23:43:05 -04:00
782 changed files with 6712 additions and 78277 deletions

No files matched your search

+39 -27
View File
@@ -6,7 +6,7 @@ on:
- 'nightly_*'
env:
QT_VERSION: 5.12.12
QT_VERSION: 5.12.9
jobs:
build_linux:
@@ -15,17 +15,36 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
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'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -45,7 +64,7 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
@@ -61,12 +80,12 @@ jobs:
submodules: true
fetch-depth: '0'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v1
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: linux-FastDebug
path: builds
@@ -164,7 +183,7 @@ jobs:
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
@@ -184,12 +203,12 @@ jobs:
submodules: true
fetch-depth: '0'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v1
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
@@ -215,7 +234,7 @@ jobs:
matrix:
configuration: [FastDebug, Release]
compiler: [clang]
arch: [x86_64, arm64]
arch: [x86_64]
name: Mac
runs-on: macos-latest
steps:
@@ -257,7 +276,6 @@ jobs:
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -266,27 +284,23 @@ jobs:
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
mac_zip:
name: Build Mac distribution zip
needs: build_mac
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [x86_64, arm64]
steps:
- uses: actions/checkout@v2
name: Checkout
@@ -295,24 +309,22 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: mac-Release-${{ matrix.arch }}
name: mac-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: mac-FastDebug-${{ matrix.arch }}
name: mac-FastDebug
path: builds
- name: Unpack builds
working-directory: ./builds
run: |
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
tar -xvzf macos-build-Release.tgz
tar -xvzf macos-build-FastDebug.tgz
- name: Create Distribution package
working-directory: ./builds
env:
ARCH: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
- name: Upload result package
working-directory: ./builds
+70 -31
View File
@@ -6,7 +6,7 @@ on:
- 'release_*'
env:
QT_VERSION: 5.12.12
QT_VERSION: 5.12.9
jobs:
create_release:
@@ -44,19 +44,65 @@ jobs:
name: Linux
needs: create_release # Don't run this job until create_release is done and successful
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
steps:
# - name: Cache Qt
# id: cache-qt-lin
# uses: actions/cache@v1
# cache the Qt directory so we don't have to reinstall it every time
# cache.inputs:
# path - A list of files, directories, and wildcard patterns to cache and restore. See @actions/glob for supported patterns.
# key - An explicit key for restoring and saving the cache
# restore-keys - An ordered list of keys to use for restoring the cache if no cache hit occurred for key
# cache.outputs:
# cache-hit true when an exact match was found for the key, false otherwise.
# with:
# path: ${{ github.workspace }}/../Qt
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
# - name: Install Qt
# uses: jurplel/install-qt-action@v2
# installs Qt in the action workflow
# install-qt-action.inputs:
# version desired qt version to install
# host Host platform of Qt, default to platform used by runs-on
# target target platform of Qt, default to desktop
# arch target architecture of Qt, only used for windows or android builds
# dir root dir Qt will be installed to
# install-deps if true, auto-install dependencies on linux. Default true
# modules whitespace delimited list string of additional addon modules to install
# archives whitespace delimited list string of Qt archives to install
# cached if true, Don't download Qt but set ENVARs; use with cache.outputs.cache-hit
# setup-python Set to false to skip using setup-python to find/download a valid python version
# set-env if true, set ENVARs; default = false
# aqtversion version of aqtinstall to use; default = 2.0.0
# py7zrversion version of py7zr to use; default = 0.16.1
# extra additional arguments to pass to aqinstall
# ENVARS set:
# Qt5_DIR / Qt6_DIR
# Qt bin dir appended to PATH
# QT_PLUGIN_PATH, QML2_IMPORT_PATH, PKG_CONFIG_PATH, LD_LIBRARY_PATH
# with:
# version: ${{ env.QT_VERSION }}
# dir: ${{ github.workspace }}/..
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
# setup-python: 'false'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
# checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
name: Checkout
with:
submodules: true # `true` to checkout submodules, `recursive` to recursively checkout submodules
ref: '${{ github.ref }}'
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -76,7 +122,7 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
# Upload the url file for use with other runners
# upload-artifact.inputs:
# if-no-files-found=warn What to do if path fails to find any files.
@@ -103,13 +149,13 @@ jobs:
ref: '${{ github.ref }}'
- name: Download Release builds
# Grab the release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
# Grab the debug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: linux-FastDebug
path: builds
@@ -120,7 +166,7 @@ jobs:
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
- name: Upload result package
# Stash the result to artifact filespace
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: ${{ steps.generate_package.outputs.package_name }}
path: ${{ steps.generate_package.outputs.package_path }}
@@ -220,7 +266,7 @@ jobs:
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
@@ -244,13 +290,13 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
@@ -265,13 +311,13 @@ jobs:
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
- name: Upload result package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: ${{ steps.generate_package.outputs.package_name }}
path: ${{ steps.generate_package.outputs.package_path }}
- name: Upload debug package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: ${{ steps.generate_package.outputs.debug_name }}
path: ${{ steps.generate_package.outputs.debug_path }}
@@ -290,7 +336,7 @@ jobs:
matrix:
configuration: [FastDebug, Release]
compiler: [clang]
arch: [x86_64, arm64]
arch: [x86_64]
name: Mac
needs: create_release
runs-on: macos-latest
@@ -327,7 +373,6 @@ jobs:
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -336,27 +381,23 @@ jobs:
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
mac_zip:
name: Build Mac distribution zip
needs: build_mac
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [x86_64, arm64]
steps:
- uses: actions/checkout@v2
name: Checkout
@@ -365,28 +406,26 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: mac-Release-${{ matrix.arch }}
name: mac-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: mac-FastDebug-${{ matrix.arch }}
name: mac-FastDebug
path: builds
- name: Unpack builds
working-directory: ./builds
run: |
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
tar -xvzf macos-build-Release.tgz
tar -xvzf macos-build-FastDebug.tgz
- name: Create Distribution package
id: generate_package
working-directory: ./builds
env:
ARCH: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
- name: Upload result package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: ${{ steps.generate_package.outputs.package_name }}
path: ${{ steps.generate_package.outputs.package_path }}
+6
View File
@@ -24,6 +24,12 @@ jobs:
name: Checkout
with:
submodules: true
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
+39 -27
View File
@@ -6,7 +6,7 @@ on:
- 'test/*'
env:
QT_VERSION: 5.12.12
QT_VERSION: 5.12.9
jobs:
build_linux:
@@ -15,8 +15,22 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
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'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
@@ -27,11 +41,16 @@ jobs:
[[ "${{ 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: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -51,7 +70,7 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
@@ -68,12 +87,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v1
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: linux-FastDebug
path: builds
@@ -177,7 +196,7 @@ jobs:
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
@@ -198,12 +217,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v1
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
@@ -229,7 +248,7 @@ jobs:
matrix:
configuration: [FastDebug, Release]
compiler: [clang]
arch: [x86_64, arm64]
arch: [x86_64]
name: Mac
runs-on: macos-latest
steps:
@@ -270,7 +289,6 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -279,27 +297,23 @@ jobs:
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
mac_zip:
name: Build Mac distribution zip
needs: build_mac
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [x86_64, arm64]
steps:
- uses: actions/checkout@v2
name: Checkout
@@ -308,24 +322,22 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: mac-Release-${{ matrix.arch }}
name: mac-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v2
with:
name: mac-FastDebug-${{ matrix.arch }}
name: mac-FastDebug
path: builds
- name: Unpack builds
working-directory: ./builds
run: |
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
tar -xvzf macos-build-Release.tgz
tar -xvzf macos-build-FastDebug.tgz
- name: Create Distribution package
working-directory: ./builds
env:
ARCH: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
- name: Upload result package
working-directory: ./builds
+20 -14
View File
@@ -6,27 +6,42 @@ on:
- master
env:
QT_VERSION: 5.12.12
QT_VERSION: 5.12.9
jobs:
build_linux:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [gcc-5, gcc-13, clang-16]
compiler: [gcc-5, gcc-10]
cmake_options: [""]
include:
# Also include configurations that check if the code compiles without the graphics backends
- configuration: Debug
compiler: gcc-13
compiler: gcc-10
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
- configuration: Release
compiler: gcc-13
compiler: gcc-10
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
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'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
@@ -35,22 +50,13 @@ jobs:
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
- name: Configure ccache
run: |
ccache --set-config=sloppiness=pch_defines,time_macros
ccache -p
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
CCACHE_PATH: /usr/local/bin/ccache
ENABLE_QTFRED: ON
Qt5_DIR: /qt/${{ env.QT_VERSION }}/gcc_64/lib/cmake/Qt5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
- name: Show CCache statistics
run: ccache --show-stats
+27 -19
View File
@@ -3,27 +3,41 @@ name: Check a pull request
on: [pull_request]
env:
QT_VERSION: 5.12.12
QT_VERSION: 5.12.9
jobs:
build_linux:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [gcc-5, gcc-13, clang-16]
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-13
compiler: gcc-10
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
- configuration: Release
compiler: gcc-13
compiler: gcc-10
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
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'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
@@ -33,18 +47,17 @@ jobs:
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
save: false # Caches are created by a separate job and only restored for PRs
verbose: 1
- name: Configure ccache
run: ccache --set-config=sloppiness=pch_defines,time_macros
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
CCACHE_PATH: /usr/local/bin/ccache
ENABLE_QTFRED: ON
Qt5_DIR: /qt/${{ env.QT_VERSION }}/gcc_64/lib/cmake/Qt5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -55,8 +68,6 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Show CCache statistics
run: ccache --show-stats
- name: Run Clang Tidy
# Clang-tidy reuses the precompiled headers so this only makes sense for the clang compilers
if: startsWith(matrix.compiler, 'clang-')
@@ -171,7 +182,7 @@ jobs:
matrix:
configuration: [Debug, Release]
compiler: [clang]
arch: [x86_64, arm64]
arch: [x86_64]
cmake_options: [""]
name: Mac
runs-on: macos-latest
@@ -199,8 +210,7 @@ jobs:
- name: ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}-${{ matrix.arch }}
save: false # Caches are created by a separate job and only restored for PRs
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
@@ -213,7 +223,6 @@ jobs:
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -222,7 +231,6 @@ jobs:
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Run Clang Tidy
@@ -1,68 +0,0 @@
name: Weekly Coverity Scan for Freespace Open
# adapted from code by "albert-github" on the doxygen repository
# many thanks for figuring this out first so it could be less painful for us!
#This mode is for testing
on: [push, pull_request]
# In production, push on a specific schedule
#on:
# schedule:
# - cron: "5 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
env:
QT_VERSION: 5.12.12
coverity_email: [email protected]
coverity_token: ${{ secrets.COVERITY_TOKEN }}
jobs:
build:
name: Build FSO With Coverity Wrapper
runs-on: ${{ matrix.config.os }}
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
strategy:
fail-fast: false
matrix:
config:
- { name: "GCC on ubuntu", os: ubuntu-latest, build_type: "Release" }
steps:
- name: Checkout
uses: actions/checkout@v1
with:
submodules: recursive # `true` to checkout submodules, `recursive` to recursively checkout submodules
# pipe results of wget to a log file because it's very verbose and rarely fails
- name: Install Coverity
run: |
wget -o wgetlog.txt -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=${{ env.coverity_token }}&project=scp-fs2open/fs2open.github.com" -O coverity_tool.tgz
mkdir cov-scan
tar ax -f coverity_tool.tgz --strip-components=1 -C cov-scan
- name: Setup Environment
run: |
echo "$(pwd)/cov-scan/bin" >> $GITHUB_PATH
echo "NPROC=$(getconf _NPROCESSORS_ONLN)" >> $GITHUB_ENV
- name: Configure CMake for FSO
env:
CONFIGURATION: Release
compiler: gcc-5
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Build FSO with Coverity Wrapper
working-directory: ./build
env:
CONFIGURATION: Release
run: cov-build --dir cov-int ninja -k 20 all
- name: Compress Results
working-directory: ./build
run: tar zcf cov-scan.tgz cov-int
#Comment this out when testing to keep from running into upload limits
- name: Upload to Coverity
run: |
cd build
curl --form token=${{ env.coverity_token }} --form email=${{ env.coverity_email }} --form [email protected] --form version="$(git rev-parse HEAD)" --form description="Automatic GHA scan" 'https://scan.coverity.com/builds?project=scp-fs2open/fs2open.github.com'
-1
View File
@@ -250,7 +250,6 @@ documentation/doxygen/*
projects/*
/.vs
CMakeSettings.json
CMakePresets.json
# Weird files created by Linux
.fuse_hidden*
+14 -3
View File
@@ -47,6 +47,20 @@ endif()
PROJECT(FS2_Open LANGUAGES ${FSO_LANGUAGES})
find_program(CCACHE_PROGRAM ccache)
# Currently only GCC support ccache properly without generating additional warnings
# Enable ccache on Mac even for clang
if(CCACHE_PROGRAM AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR APPLE))
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()
endif()
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
@@ -127,8 +141,6 @@ OPTION(FSO_BUILD_WITH_OPENGL_DEBUG "Enables debug option for OpenGL" OFF)
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" OFF)
OPTION(FSO_BUILD_WITH_OPENXR_DEBUG "Enables debug option for OpenXR" OFF)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
@@ -142,7 +154,6 @@ mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL_DEBUG)
mark_as_advanced(FORCE FSO_BUILD_WITH_VULKAN)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENXR_DEBUG)
# Include cotire file from https://github.com/sakra/cotire/
include(cotire)
+9 -17
View File
@@ -4,13 +4,14 @@ if [ "$COMPILER" = "gcc-5" ]; then
export CC=gcc-5
export CXX=g++-5
fi
if [ "$COMPILER" = "gcc-13" ]; then
export CC=gcc-13
export CXX=g++-13
if [ "$COMPILER" = "gcc-10" ]; then
export CC=gcc-10
export CXX=g++-10
fi
if [ "$COMPILER" = "clang-16" ]; then
export CC=clang-16
export CXX=clang++-16
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
@@ -33,11 +34,6 @@ if [[ "$COMPILER" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -Qunused-arguments"
fi
if [ ! "$CCACHE_PATH" = "" ]; then
echo "Using ccache at $CCACHE_PATH"
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCMAKE_C_COMPILER_LAUNCHER=$CCACHE_PATH -DCMAKE_CXX_COMPILER_LAUNCHER=$CCACHE_PATH"
fi
mkdir build
cd build
@@ -48,11 +44,7 @@ export LD_LIBRARY_PATH
if [ "$RUNNER_OS" = "macOS" ]; then
brew install ninja
fi
# CMAKE_JOB_POOLS and CMAKE_JOB_POOL_LINK ensure that when using ninja, link operations are done sequentially
# we have some build rules that do not play nice with parallel invocation and that fixes these issues
cmake -G Ninja -DFSO_FATAL_WARNINGS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON $CMAKE_OPTIONS $PLATFORM_CMAKE_OPTIONS \
-DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DCMAKE_BUILD_TYPE=$CONFIGURATION \
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=${ENABLE_QTFRED:-OFF} \
-DSHADERS_ENABLE_COMPILATION=ON -DCMAKE_JOB_POOLS=link=1 -DCMAKE_JOB_POOL_LINK=link ..
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=OFF \
-DSHADERS_ENABLE_COMPILATION=ON ..
+4 -4
View File
@@ -26,11 +26,11 @@ elif [ "$OS" = "Windows" ]; then
echo "debug_name=$(get_package_name)-debug-$ARCH-$SIMD.7z" >> $GITHUB_OUTPUT
echo "debug_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")" >> $GITHUB_OUTPUT
elif [ "$OS" = "Mac" ]; then
tar -cvzf "$(get_package_name)-builds-Mac-$ARCH.tar.gz" *.app
tar -cvzf "$(get_package_name)-builds-Mac.tar.gz" *.app
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac-$ARCH.tar.gz" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-Mac-$ARCH.tar.gz" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac-$ARCH.tar.gz")" >> $GITHUB_OUTPUT
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac.tar.gz")" >> $GITHUB_OUTPUT
else
echo "Invalid OS: $OS"
fi
-7
View File
@@ -5,13 +5,6 @@ HERE=$(dirname "$SCRIPT")
export LD_LIBRARY_PATH=$(pwd)/bin/lib:$LD_LIBRARY_PATH
# if on mac and building for architecture that doesn't match host
# then unittests will fail so we just need to skip it (for now)
if [ "$RUNNER_OS" = "macOS" ] && [ "$ARCH" != "$(uname -m)" ]; then
echo "Skipping tests due to architecture mismatch!"
exit 0
fi
if [ "$CONFIGURATION" = "Debug"] && [[ "$RUNNER_OS" != "macOS" ]] ; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$HERE/valgrind.supp" ./bin/unittests --gtest_shuffle
+1 -1
View File
@@ -19,7 +19,7 @@
# HLP_API:
# HLP_KEY:
# LINUX_RESULT: bool, if the linux builds were successfully uploaded
# LINUX_RESULT: bool, if the linux builds were sucessfully uploaded
# WINDOWS_RESULT: bool, if the windows builds were successfully uploaded
import sys
+5 -9
View File
@@ -8,8 +8,7 @@ from file_list import ReleaseFile
from util import retry_multi, GLOBAL_TIMEOUT
LINUX_KEY = "Linux"
MACOSX_X64_KEY = "Mac-x86_64"
MACOSX_ARM64_KEY = "Mac-arm64"
MACOSX_KEY = "Mac"
WIN32_SSE2_KEY = "Win32-SSE2"
WIN64_SSE2_KEY = "Win64-SSE2"
WIN32_AVX_KEY = "Win32-AVX"
@@ -35,8 +34,7 @@ metadata = {
platforms = {
LINUX_KEY: 'linux',
MACOSX_X64_KEY: 'macosx',
MACOSX_ARM64_KEY: 'macosx',
MACOSX_KEY: 'macosx',
WIN32_SSE2_KEY: 'windows',
WIN64_SSE2_KEY: 'windows',
WIN32_AVX_KEY: 'windows',
@@ -45,8 +43,7 @@ platforms = {
envs = {
LINUX_KEY: 'linux && x86_64', # Linux only has 64bit builds
MACOSX_X64_KEY: 'macosx && x86_64',
MACOSX_ARM64_KEY: 'macosx && arm64',
MACOSX_KEY: 'macosx',
WIN32_SSE2_KEY: 'windows',
WIN64_SSE2_KEY: 'windows && x86_64',
WIN32_AVX_KEY: 'windows && avx',
@@ -138,7 +135,7 @@ def render_nebula_release(version, stability, files, config):
'label': label,
'properties': props,
})
elif group.startswith('Mac') and fn.startswith(os.path.basename(fn) + '.app/'):
elif group == MACOSX_KEY and fn.startswith(os.path.basename(fn) + '.app/'):
if 'qtfred' in fn:
if '-FASTDBG' in fn:
label = 'QtFRED Debug'
@@ -151,8 +148,7 @@ def render_nebula_release(version, stability, files, config):
label = None
props = {
"arm64": "arm64" in fn,
"x64": "x64" in fn,
"x64": True, # All Mac builds are 64-bit
"sse2": True, # There are no forced options on mac but 64-bit always implies SSE2 so we set that here
"avx": False,
"avx2": False,
+4 -5
View File
@@ -9,10 +9,10 @@ PLACEHOLDER
Deprecations are a mechanism in FSO where a certain feature or aspect of the engine has changed or is no longer supported. Since this would normally break existing mods we have the mod table feature "[tt]$Target Version:[/tt]" with which a mod can specify what version of FSO it was developed with. The features listed above will be removed or changed when the target version of a mod is at least the version released in this post.
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98682.0]23.0.0 Release Thread[/url][/size]
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98682.0]23.2.0 Release Thread[/url][/size]
Launchers, if you don't have one already:
[b]All platforms: [/b] For every day use, we recommend [url=https://www.hard-light.net/forums/index.php?topic=94068.0]Knossos[/url], an integrated solution for downloading and launching mods.
[b]All platforms: [/b] For every day use, we recommend [url=https://www.hard-light.net/forums/index.php?topic=98984.0]Knossos[/url], an integrated solution for downloading and launching mods.
[hidden=Alternative Launchers]
Cross-platform: [url=https://www.hard-light.net/forums/index.php?topic=89162]wxLauncher 0.12.x Test Build[/url] (ongoing project for a unified launcher, you should upgrade to the latest RC/test build if you have not yet)
@@ -53,9 +53,8 @@ Alternatively, if there is a package in your software repository then you should
[img]https://scp.indiegames.us/img/mac-icon.png[/img] [color=green][size=12pt]macOS[/size][/color]
[size=8pt]macOS 10.9+[/size]
[b]Intel (64-bit):[/b] ${build(groups["Mac"].subFiles["x86_64"])}
[b]Apple Silicon:[/b] ${build(groups["Mac"].subFiles["arm64"])}
[size=8pt]macOS 10.9+, 64-bit (Intel)[/size]
${build(groups["Mac"].mainFile)}
These builds are not signed and so by default will fail to launch. To run them simply right-click on the app, click open, then click open again on the security confirmation dialog. You should only have to do this once for each app.
If running the game through Knossos or Knossos.NET this step should not be necessary.
-6
View File
@@ -7,9 +7,3 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
else()
set(IS_64BIT FALSE)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)")
set(IS_ARM64 TRUE)
else()
set(IS_ARM64 FALSE)
endif()
-8
View File
@@ -22,14 +22,6 @@ SET(LIBRAY_DESTINATION "../Frameworks")
set(PLATFORM_MAC TRUE CACHE INTERNAL "" FORCE)
# Maybe override arm64 setting if we are compiling for different architecture
# If not specified, or if it's a universal build, then this should do nothing
if(CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
set(IS_ARM64 TRUE)
elseif(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
set(IS_ARM64 FALSE)
endif()
# Generate and don't strip debug symbols
# These settings don't seem to generate debug symbols for code and Freespace2
# so those settings are set manually in code and Freespace2's CMakeLists.txt files
-1
View File
@@ -9,7 +9,6 @@
#cmakedefine SCP_HAVE_STD_MAX_ALIGN_T
#cmakedefine01 IS_64BIT
#cmakedefine01 IS_ARM64
#cmakedefine01 SCP_HAVE_STRCASECMP
#cmakedefine01 SCP_HAVE_STRNCASECMP
+8 -29
View File
@@ -83,41 +83,20 @@ if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
endif()
# Check if there is a user-set optimisation flag
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
# If no user-set opt flag, set -O2 and -Og
if ("${CXX_OPT_FLAG}" STREQUAL "")
set(CXX_OPT_FLAG_RELEASE "-O2")
set(CXX_OPT_FLAG_DEBUG "-Og")
else()
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
endif()
if ("${C_OPT_FLAG}" STREQUAL "")
set(C_OPT_FLAG_RELEASE "-O2")
set(C_OPT_FLAG_DEBUG "-Og")
else()
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
set(C_OPT_FLAG_DEBUG "${C_OPT_FLAG}")
endif()
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
set(CXX_FLAGS_RELEASE "${CXX_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-parameter")
set(C_FLAGS_RELEASE "${C_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-parameter")
set(CXX_FLAGS_DEBUG "${CXX_OPT_FLAG_DEBUG} -g -Wshadow")
set(C_FLAGS_DEBUG "${C_OPT_FLAG_DEBUG} -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}")
set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS_RELEASE})
set(CMAKE_C_FLAGS_RELEASE ${C_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
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_CXX_FLAGS_DEBUG ${CXX_FLAGS_DEBUG})
set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS_DEBUG})
set(CMAKE_EXE_LINKER_FLAGS "")
+6 -28
View File
@@ -113,41 +113,19 @@ if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
endif()
# Check if there is a user-set optimisation flag
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
# If no user-set opt flag, set -O2 and -Og
if ("${CXX_OPT_FLAG}" STREQUAL "")
set(CXX_OPT_FLAG_RELEASE "-O2")
set(CXX_OPT_FLAG_DEBUG "-Og")
else()
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
endif()
if ("${C_OPT_FLAG}" STREQUAL "")
set(C_OPT_FLAG_RELEASE "-O2")
set(C_OPT_FLAG_DEBUG "-Og")
else()
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
set(C_OPT_FLAG_DEBUG "${C_OPT_FLAG}")
endif()
set(CXX_FLAGS_RELEASE "${CXX_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(C_FLAGS_RELEASE "${C_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(CXX_FLAGS_DEBUG "${CXX_OPT_FLAG_DEBUG} -g -Wshadow")
set(C_FLAGS_DEBUG "${C_OPT_FLAG_DEBUG} -g -Wshadow")
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
# Always use the base flags and add our compiler flags at the back
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS_RELEASE})
set(CMAKE_C_FLAGS_RELEASE ${C_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS_DEBUG})
set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS_DEBUG})
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_EXE_LINKER_FLAGS "${LINKER_FLAGS}")
+2 -4
View File
@@ -7,7 +7,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 23)
set_if_not_defined(FSO_VERSION_MINOR 3)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_BUILD 0)
# A numeric revision e.g. the CI build number
@@ -35,9 +35,7 @@ ELSE()
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}_${FSO_VERSION_REVISION_STR}")
ENDIF()
IF(IS_ARM64)
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_arm64")
ELSEIF(IS_64BIT)
IF(IS_64BIT)
# This is a 64-bit builds
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_x64")
ENDIF()
-15
View File
@@ -25,10 +25,6 @@ if (FSO_BUILD_WITH_OPENGL)
endif()
endif()
if(FSO_BUILD_WITH_OPENXR_DEBUG)
add_definitions(-DFS_OPENXR_DEBUG)
endif()
TARGET_LINK_LIBRARIES(code PUBLIC openal)
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
@@ -79,17 +75,6 @@ target_link_libraries(code PUBLIC hidapi::hidapi)
target_link_libraries(code PUBLIC imgui)
IF(NOT APPLE)
target_link_libraries(code PUBLIC OpenXR::openxr_loader)
target_include_directories(code PUBLIC OpenXR::Headers)
ENDIF()
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
# On Linux, we need to access X11 window data.
# On Windows, SDL already provides everything, so no need to do anything
find_package(X11)
target_link_libraries(code PUBLIC ${X11_LIBRARIES})
ENDIF()
# Headers for standalone "gui" on UNIX
IF(UNIX)
TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS})
+21 -12
View File
@@ -56,6 +56,12 @@ extern const int Num_ai_flag_names;
#define AIDO_DOCK_NOW 2 // Immediately move into dock position. For ships that start mission docked.
#define AIDO_UNDOCK 3 // Set goal of undocking with object.
// Submodes for seeking safety.
#define AISS_1 41 // Pick a spot to fly to.
#define AISS_2 42 // Flying to spot.
#define AISS_3 43 // Gotten near spot, fly about there.
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2
// Flags to ai_turn_towards_vector().
#define AITTV_FAST (1<<0) // Turn fast, not slowed down based on skill level.
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
@@ -87,7 +93,7 @@ extern const int Num_ai_flag_names;
#define AIM_BAY_DEPART 18 // Departing to a fighter bay, following path to do so
#define AIM_SENTRYGUN 19 // AI mode for sentry guns only (floating turrets)
#define AIM_WARP_OUT 20 // Commence warp out sequence. Point in legal direction. Then call John's code.
#define AIM_FLY_TO_SHIP 21 // Rendezvous with a ship. Like stay-near, but non-perpetual.
#define AIM_FLY_TO_SHIP 21 // [Kazan] Fly to a ship, doesn't matter if it's hostile or friendly -- for Autopilot usage
#define AIM_LUA 22 // Generic Lua-based AI mode
#define MAX_AI_BEHAVIORS 23 // Number of AIM_xxxx types
@@ -180,12 +186,6 @@ typedef struct ai_class {
#define AIS_UNDOCK_3 33
#define AIS_UNDOCK_4 34
// Submodes for seeking safety.
#define AISS_1 41 // Pick a spot to fly to.
#define AISS_2 42 // Flying to spot.
#define AISS_3 43 // Gotten near spot, fly about there.
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2. (Not implemented.)
// Submodes for Guard behavior
#define AIS_GUARD_PATROL 101
#define AIS_GUARD_ATTACK 102
@@ -240,6 +240,7 @@ typedef struct ai_info {
flagset<AI::AI_Flags> ai_flags; // Special flags for AI behavior.
int shipnum; // Ship using this slot, -1 means none.
int behavior; // AI behavior; vestigial field from early development of FS1
int mode;
int previous_mode;
int mode_time; // timestamp at which current mode elapses.
@@ -277,7 +278,7 @@ typedef struct ai_info {
// Probably become obsolete, to be replaced by path_start, path_cur, etc.
waypoint_list *wp_list; // waypoint list being followed
int wp_index; // waypoint index in list
size_t wp_index; // waypoint index in list
int wp_flags; // waypoint flags, see WPF_xxxx
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
@@ -307,7 +308,6 @@ typedef struct ai_info {
fix submode_start_time; // time at which we entered the current submode
int submode_parm0; // parameter specific to current submode
int submode_parm1; // SUSHI: Another optional parameter
float submode_float0; // Goober5000: a float parameter
fix next_predict_pos_time; // Next time to predict position.
int next_dynamic_path_check_time; //ETP: Time of next path check in ai_new_maybe_reposition_attack_subsys
@@ -373,6 +373,11 @@ typedef struct ai_info {
float ai_turret_max_aim_update_delay;
flagset<AI::Profile_Flags> ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI
union {
float stay_near_distance; // Distance to stay within for AIM_STAY_NEAR mode.
};
ship_subsys* targeted_subsys; // Targeted subobject on current target. NULL if none;
ship_subsys* last_subsys_target; // last known subsystem target
int targeted_subsys_parent; // Parent objnum of subobject, not necessarily targeted
@@ -533,11 +538,11 @@ extern void ai_ignore_wing(object *ignorer, int wingnum);
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
extern void ai_do_default_behavior(object *obj);
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int start_index);
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 vec3d ai_get_acc_limit(vec3d* vel_limit, const object* objp);
extern void ai_turn_towards_vector(const vec3d *dest, object *objp, const vec3d *slide_vec, const vec3d *rel_pos, float bank_override, int flags, const vec3d *rvec = nullptr, const vec3d* turnrate_mod = nullptr);
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 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
@@ -560,7 +565,7 @@ extern void ai_attack_wing(object *attacker, int wingnum);
extern void ai_deathroll_start(object *ship_obj);
extern int set_target_objnum(ai_info *aip, int objnum);
extern void ai_form_on_wing(object *objp, object *goal_objp);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist, int additional_data);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
extern ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int parent_objnum);
extern void ai_rearm_repair( object *objp, int docker_index, object *goal_objp, int dockee_index );
extern void ai_add_rearm_goal( object *requester_objp, object *support_objp );
@@ -620,6 +625,10 @@ int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float ra
// moved to header file by Goober5000
void ai_announce_ship_dying(object *dying_objp);
// added by kazan
void ai_start_fly_to_ship(object *objp, int shipnum);
void ai_fly_to_ship();
//Moved declaration here for player ship -WMC
void ai_process_subobjects(int objnum);
-2
View File
@@ -47,7 +47,6 @@ namespace AI {
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
Target_own_team, // this attack goal is allowed to target friendlies
Afterburn_hard, // afterburn as hard as possible to the goal
Waypoints_in_reverse, // decrement instead of increment
NUM_VALUES
};
@@ -157,7 +156,6 @@ namespace AI {
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
Hudsquadmsg_tactical_disarm_disable,
NUM_VALUES
};
+5 -12
View File
@@ -258,7 +258,7 @@ void parse_ai_profiles_tbl(const char *filename)
if (optional_string("$Glide Attack Percent:")) {
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
//While we're at it, verify the range
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
@@ -271,7 +271,7 @@ void parse_ai_profiles_tbl(const char *filename)
if (optional_string("$Circle Strafe Percent:")) {
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
//While we're at it, verify the range
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
@@ -284,7 +284,7 @@ void parse_ai_profiles_tbl(const char *filename)
if (optional_string("$Glide Strafe Percent:")) {
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
//While we're at it, verify the range
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
@@ -297,7 +297,7 @@ void parse_ai_profiles_tbl(const char *filename)
if (optional_string("$Random Sidethrust Percent:")) {
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
//While we're at it, verify the range
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
@@ -552,9 +552,7 @@ void parse_ai_profiles_tbl(const char *filename)
profile->flags.set(AI::Profile_Flags::All_nonshielded_ships_can_manage_ets, temp);
}
// ----------
set_flag(profile, "$no directional bias for missile and ship turning:", AI::Profile_Flags::No_turning_directional_bias);
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);
@@ -625,8 +623,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$dynamic goals afterburn hard:", AI::Profile_Flags::Dynamic_goals_afterburn_hard);
set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
{
@@ -816,7 +812,4 @@ void ai_profile_t::reset()
if (mod_supports_version(23, 2, 0)) {
flags.set(AI::Profile_Flags::Ships_playing_dead_dont_manage_ets);
}
if (mod_supports_version(23, 4, 0)) {
flags.set(AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
}
}
+6 -5
View File
@@ -538,7 +538,8 @@ bool ai_new_maybe_reposition_attack_subsys() {
model_local_to_global_point(&geye, &ep->pnt, pm, 0, &Pl_objp->orient, &Pl_objp->pos);
// get world pos of subsystem
get_subsystem_pos(&gsubpos, target_objp, aip->targeted_subsys);
polymodel* tgt_pm = model_get(Ship_info[Ships[target_objp->instance].ship_info_index].model_num);
model_local_to_global_point(&gsubpos, &vmd_zero_vector, tgt_pm, aip->targeted_subsys->system_info->subobj_num, &En_objp->orient, &En_objp->pos);
// you're in sight! shoot it!
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 0))
@@ -546,7 +547,6 @@ bool ai_new_maybe_reposition_attack_subsys() {
// not in sight, gotta get there
vec3d* good_pos = nullptr;
vec3d world_goal_pos;
// For performance reasons we only recheck once a second, otherwise we reuse the last found target.
if (timestamp_elapsed(aip->next_dynamic_path_check_time)) {
vec3d tgt2pl = Pl_objp->pos - target_objp->pos;
@@ -568,6 +568,7 @@ bool ai_new_maybe_reposition_attack_subsys() {
vm_rot_point_around_line(&goal_pos, &tgt2pl, angle2goal, &vmd_zero_vector, &cross);
// then scale in (or out) towards our subsys
vec3d world_goal_pos;
float new_radius = ((subsys_dist - pl_dist) * (angle2goal / angle2subsys)) + pl_dist;
vm_vec_copy_scale(&world_goal_pos, &goal_pos, new_radius / pl_dist);
world_goal_pos += target_objp->pos;
@@ -913,13 +914,13 @@ static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
}
if (tswp->num_secondary_banks > 0) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL))) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP))) {
bool valid_secondary = ai_choose_secondary_weapon(Pl_objp, aip, En_objp);
int current_bank = tswp->current_secondary_bank;
if (current_bank > -1 && valid_secondary) {
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
// If ship is protected and very low on hits, don't fire missiles.
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (En_objp->hull_strength > 10*swip->damage)) {
if (aip->ai_flags[AI::AI_Flags::Unload_secondaries]) {
@@ -1841,7 +1842,7 @@ void ai_big_strafe()
/*
if ( aip->goal_objnum != aip->target_objnum ) {
UNREACHABLE("The goal objnum does not match the target objnum in ai_big_strafe(), please report to the SCP!"); // what is going on here? - Get Alan
Int3(); // what is going on here? - Get Alan
aip->mode = AIM_NONE;
return;
}
+249 -341
View File
File diff suppressed because it is too large. Load diff
+156 -169
View File
@@ -51,8 +51,6 @@ struct ship_registry_entry;
// Goober5000 - okay, this seems really stupid. If any ship in the mission is assigned a goal
// in PURGE_GOALS_ALL_SHIPS, *every* other ship will have certain goals purged. So I added
// PURGE_GOALS_ONE_SHIP for goals which should only purge other goals in the one ship.
// Goober5000 - note that the new disable and disarm goals (AI_GOAL_DISABLE_SHIP_TACTICAL and
// AI_GOAL_DISARM_SHIP_TACTICAL) do not purge ANY goals, not even the ones in the one ship
#define PURGE_GOALS_ALL_SHIPS (AI_GOAL_IGNORE | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)
#define PURGE_GOALS_ONE_SHIP (AI_GOAL_IGNORE_NEW)
@@ -77,9 +75,7 @@ ai_goal_list Ai_goal_names[] =
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disable ship (tactical)",AI_GOAL_DISABLE_SHIP_TACTICAL, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Disarm ship (tactical)", AI_GOAL_DISARM_SHIP_TACTICAL, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
@@ -124,10 +120,8 @@ const char *Ai_goal_text(int goal, int submode)
case AI_GOAL_GUARD_WING:
return XSTR( "guard ", 480);
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
return XSTR( "disable ", 481);
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
return XSTR( "disarm ", 482);
case AI_GOAL_EVADE_SHIP:
return XSTR( "evade ", 483);
@@ -214,7 +208,7 @@ void ai_maybe_add_form_goal(wing* wingp)
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];
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];
@@ -487,12 +481,10 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// these goals cannot be associated to wings, but can to a ship in a wing. So, we should find out
// if the ship is in a wing so we can purge goals which might operate on that wing
ship_index = ship_name_lookup(name);
Assertion(ship_index > -1, "Found a bad ship_index of %d in ai_goal_purge_invalid_goals, please report to the SCP!", ship_index); // get allender -- this is sort of odd
if ( ship_index < 0 ) {
return;
if ( ship_index == -1 ) {
Int3(); // get allender -- this is sort of odd
return;
}
wingnum = Ships[ship_index].wingnum;
purge_goal = goal_list;
@@ -536,12 +528,11 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// ignore goals should get rid of any kind of attack goal
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
purge_goal->flags.set(AI::Goal_Flags::Purge);
break;
// disarm/disable goals should remove attacks from certain ships types
// (but not tactical disarm/disable)
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISABLE_SHIP:
if ( purge_ai_mode & (AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS) ) {
@@ -558,17 +549,12 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
}
// grab the ship type of the ship that is being disarmed/disabled
int crippled_ship_type = Ship_info[Ships[ship_index].ship_info_index].class_type;
ship_type_info *crippled_ships_type = &Ship_types[Ship_info[Ships[ship_index].ship_info_index].class_type];
if (ai_ship_type < 0 || crippled_ship_type < 0)
break;
ship_type_info *crippled_ship_type_info = &Ship_types[crippled_ship_type];
// work through all the ship types to see if the class matching our ai ship must ignore the ship
// work through all the ship types which to see if the class matching our ai ship must ignore the ship
// being disarmed/disabled
for ( j=0 ; j < (int)crippled_ship_type_info->ai_cripple_ignores.size(); j++) {
if (crippled_ship_type_info->ai_cripple_ignores[j] == ai_ship_type) {
for ( j=0 ; j < (int)crippled_ships_type->ai_cripple_ignores.size(); j++) {
if (crippled_ships_type->ai_cripple_ignores[j] == ai_ship_type) {
purge_goal->flags.set(AI::Goal_Flags::Purge);
}
}
@@ -728,7 +714,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
// from the mission goals (i.e. those goals which come from events) in that we don't
// use sexpressions for goals from the player...so we enumerate all the parameters
void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
{
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
@@ -815,7 +801,7 @@ int ai_goal_num(ai_goal *goals)
}
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, const char *target_name, ai_goal *aigp )
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, char *target_name, ai_goal *aigp )
{
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
@@ -832,7 +818,7 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, co
aigp->priority = priority;
}
void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char *shipname, ai_info *aip)
void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip)
{
int empty_index;
ai_goal *aigp;
@@ -856,7 +842,7 @@ void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char
// is issued to ship or wing (from player), mode is AI_GOAL_*. submode is the submode the
// ship should go into. shipname is the object of the action. aip is the ai_info pointer
// of the ship receiving the order
void ai_add_ship_goal_player( int type, int mode, int submode, const char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
{
int empty_index;
ai_goal *aigp;
@@ -877,7 +863,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, const char *shipn
// adds a goal from the player to the given wing (which in turn will add it to the proper
// ships in the wing
void ai_add_wing_goal_player( int type, int mode, int submode, const char *shipname, int wingnum, const ai_lua_parameters& lua_target)
void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum, const ai_lua_parameters& lua_target)
{
int i, empty_index;
wing *wingp = &Wings[wingnum];
@@ -901,7 +887,7 @@ void ai_add_wing_goal_player( int type, int mode, int submode, const char *shipn
// common routine to add a sexpression mission goal to the appropriate goal structure.
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name )
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char *actor_name )
{
int node, dummy, op;
@@ -915,30 +901,22 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
switch (op) {
case OP_AI_WAYPOINTS_ONCE:
case OP_AI_WAYPOINTS:
{
case OP_AI_WAYPOINTS: {
int ref_type;
bool is_nan, is_nan_forever;
ref_type = Sexp_nodes[CDR(node)].subtype;
Assertion(ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA, "Found a bad ref_type in ai_add_goal_sub_sexp of %d. Please report to the SCP!", ref_type);
// referenced by name
// save the waypoint path name -- the list will get resolved when the goal is checked
// for achievability.
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
if (ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA) { // referenced by name
// save the waypoint path name -- the list will get resolved when the goal is checked
// for achievability.
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
} else
Int3();
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->ai_mode = AI_GOAL_WAYPOINTS;
if ( op == OP_AI_WAYPOINTS_ONCE )
aigp->ai_mode = AI_GOAL_WAYPOINTS_ONCE;
if (CDDDDR(node) < 0)
aigp->int_data = 0; // handle optional node separately because we don't subtract 1 here
else
aigp->int_data = eval_num(CDDDDR(node), is_nan, is_nan_forever) - 1;
if (is_sexp_true(CDDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Waypoints_in_reverse);
break;
}
@@ -953,16 +931,14 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
break;
case OP_AI_DISABLE_SHIP:
case OP_AI_DISABLE_SHIP_TACTICAL:
aigp->ai_mode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
aigp->ai_mode = AI_GOAL_DISABLE_SHIP;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_ENGINE;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
break;
case OP_AI_DISARM_SHIP:
case OP_AI_DISARM_SHIP_TACTICAL:
aigp->ai_mode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
aigp->ai_mode = AI_GOAL_DISARM_SHIP;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_TURRET;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
@@ -1000,9 +976,9 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
// this goal needs some extra setup
// if this doesn't work, the goal will be immediately removed
auto ship_entry = ship_registry_get(aigp->target_name);
if (ship_entry && ship_entry->has_shipp())
if (ship_entry && ship_entry->shipp)
{
auto target_aip = &Ai_info[ship_entry->shipp()->ai_index];
auto target_aip = &Ai_info[ship_entry->shipp->ai_index];
target_aip->ai_flags.set(AI::AI_Flags::Awaiting_repair);
Assertion(aip != nullptr, "Must provide aip if assigning a rearm goal!");
ai_goal_fixup_dockpoints( aip, aigp );
@@ -1046,30 +1022,17 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
break;
case OP_AI_FLY_TO_SHIP:
case OP_AI_STAY_NEAR_SHIP:
{
bool is_nan, is_nan_forever;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDDR(node)) );
// distance from ship
if ( CDDDR(node) < 0 )
aigp->float_data = 300.0f;
else
aigp->float_data = i2fl(eval_num(CDDDR(node), is_nan, is_nan_forever));
// (the CDDDDR argument is whether to afterburn, and is handled at the end of the function, so don't handle it here)
// whether to "escort" the ship
if ( CDDDDDR(node) >= 0 )
aigp->int_data = is_sexp_true(CDDDDDR(node)) ? 1 : 0;
if (op == OP_AI_FLY_TO_SHIP)
aigp->ai_mode = AI_GOAL_FLY_TO_SHIP;
else
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
break;
}
@@ -1087,6 +1050,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
case OP_AI_EVADE_SHIP:
case OP_AI_IGNORE:
case OP_AI_IGNORE_NEW:
case OP_AI_FLY_TO_SHIP:
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
@@ -1113,10 +1077,14 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
aigp->ai_mode = AI_GOAL_CHASE_WING;
} else if (op == OP_AI_CHASE_SHIP_CLASS) {
aigp->ai_mode = AI_GOAL_CHASE_SHIP_CLASS;
} else if ( op == OP_AI_STAY_NEAR_SHIP ) {
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
} else if ( op == OP_AI_IGNORE ) {
aigp->ai_mode = AI_GOAL_IGNORE;
} else if ( op == OP_AI_IGNORE_NEW ) {
aigp->ai_mode = AI_GOAL_IGNORE_NEW;
} else if ( op == OP_AI_FLY_TO_SHIP ) {
aigp->ai_mode = AI_GOAL_FLY_TO_SHIP;
} else
UNREACHABLE("Coding error: unhandled AI goal in ai_add_goal_sub_sexp!");
@@ -1153,8 +1121,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
}
// Goober5000 - we now have an extra optional chase argument to allow chasing our own team
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS
|| op == OP_AI_DISABLE_SHIP || op == OP_AI_DISABLE_SHIP_TACTICAL || op == OP_AI_DISARM_SHIP || op == OP_AI_DISARM_SHIP_TACTICAL ) {
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS || op == OP_AI_DISABLE_SHIP || op == OP_AI_DISARM_SHIP ) {
if (is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
@@ -1171,7 +1138,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
if (op == OP_AI_GUARD ||
op == OP_AI_GUARD_WING ||
op == OP_AI_WAYPOINTS ||
op == OP_AI_WAYPOINTS_ONCE) {
op == OP_AI_WAYPOINTS_ONCE ||
op == OP_AI_FLY_TO_SHIP) {
if (is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
@@ -1179,11 +1147,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
op == OP_AI_CHASE_WING ||
op == OP_AI_CHASE_SHIP_CLASS ||
op == OP_AI_DISABLE_SHIP ||
op == OP_AI_DISABLE_SHIP_TACTICAL ||
op == OP_AI_DISARM_SHIP ||
op == OP_AI_DISARM_SHIP_TACTICAL ||
op == OP_AI_STAY_NEAR_SHIP ||
op == OP_AI_FLY_TO_SHIP) {
op == OP_AI_STAY_NEAR_SHIP) {
if (is_sexp_true(CDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
@@ -1258,13 +1223,11 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR( CDR( CDR(node) ) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( CDR( node ) ) ) ) ) : -1;
break;
case OP_AI_DISABLE_SHIP:
case OP_AI_DISABLE_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
goalmode = AI_GOAL_DISABLE_SHIP;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
break;
case OP_AI_DISARM_SHIP:
case OP_AI_DISARM_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
goalmode = AI_GOAL_DISABLE_SHIP;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
break;
case OP_AI_WARP_OUT:
@@ -1294,8 +1257,11 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD:
goalmode = AI_GOAL_PLAY_DEAD;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
goalmode = (op == OP_AI_PLAY_DEAD) ? AI_GOAL_PLAY_DEAD : AI_GOAL_PLAY_DEAD_PERSISTENT;
goalmode = AI_GOAL_PLAY_DEAD_PERSISTENT;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
@@ -1337,9 +1303,12 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
goalmode = AI_GOAL_STAY_NEAR_SHIP;
break;
case OP_AI_IGNORE:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_IGNORE;
break;
case OP_AI_IGNORE_NEW:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = (op == OP_AI_IGNORE) ? AI_GOAL_IGNORE : AI_GOAL_IGNORE_NEW;
goalmode = AI_GOAL_IGNORE_NEW;
break;
case OP_AI_FORM_ON_WING:
priority = 99;
@@ -1462,8 +1431,15 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
int gindex;
ai_goal *aigp;
#ifndef NDEBUG
// Goober5000 - none of the goals act on the actor, as in ai_add_goal_sub_sexp
Assertion(strcmp(name, Ships[aip->shipnum].ship_name) != 0, "The goals apply to the actor in ai_add_goal_ship_internal for ship %s, please report to the SCP!", name);
if (!strcmp(name, Ships[aip->shipnum].ship_name))
{
// not good
Int3();
return;
}
#endif
// find an empty slot to put this goal in.
gindex = ai_goal_find_empty_slot( aip->goals, aip->active_goal );
@@ -1514,7 +1490,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
break;
default:
UNREACHABLE("unsupported internal goal of %d found in ai_add_goal_ship_internal. Please report to the SCP", goal_type); // see Mike K or Mark A.
Int3(); // unsupported internal goal -- see Mike K or Mark A.
return;
}
@@ -1554,11 +1530,13 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
int status;
ai_achievability return_val;
ai_info *aip;
int index = -1, sindex = -1;
int modelnum = -1;
auto objp = &Objects[objnum];
Assert( objp->instance != -1 );
auto shipp = &Ships[objp->instance];
auto aip = &Ai_info[shipp->ai_index];
aip = &Ai_info[Ships[objp->instance].ai_index];
// these orders are always achievable.
if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE)
@@ -1569,11 +1547,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if (aigp->ai_mode == AI_GOAL_LUA)
return ai_lua_is_achievable(aigp, objnum);
auto target_ship_entry = aigp->target_name == nullptr ? nullptr : ship_registry_get(aigp->target_name);
// warp (depart) only achievable if there's somewhere to depart to
if (aigp->ai_mode == AI_GOAL_WARP)
{
ship *shipp = &Ships[objp->instance];
// always valid if has working subspace drive, not disabled, and not limited by subsystem strength
if ( ship_can_warp_full_check(shipp) )
return ai_achievability::ACHIEVABLE;
@@ -1592,7 +1570,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if the wing target is valid then be sure to set the override bit so that it always
// gets executed next
if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) {
if (!target_ship_entry || !target_ship_entry->has_shipp())
sindex = ship_name_lookup( aigp->target_name );
if (sindex < 0)
return ai_achievability::NOT_ACHIEVABLE;
aigp->flags.set(AI::Goal_Flags::Goal_override);
@@ -1649,10 +1629,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup( aigp->target_name );
// can't determine the status of this goal if ship not valid
// or we haven't found a valid subsystem index yet
if ( !target_ship_entry || !target_ship_entry->has_shipp() || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
if ( (sindex == -1) || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
status = 0;
break;
}
@@ -1661,46 +1642,46 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// as 0 so we can continue. (The subsystem name must be turned into an index into the ship's subsystems
// for this goal to be valid).
Assert ( aigp->ai_submode >= 0 );
ssp = ship_get_indexed_subsys( target_ship_entry->shipp(), aigp->ai_submode );
ssp = ship_get_indexed_subsys( &Ships[sindex], aigp->ai_submode );
if (ssp != NULL) {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (ssp->current_hits <= 0.0f) ? 1 : 0;
} else {
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp()->ship_name));
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, Ships[sindex].ship_name));
status = 0;
}
break;
}
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
if (sindex < 0) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
status = (Ships[sindex].subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
break;
}
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
if (sindex < 0) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
status = (Ships[sindex].subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
break;
}
@@ -1719,23 +1700,22 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// MWA -- 4/22/98. Check for the ship actually being in the mission before
// checking departure and destroyed. In multiplayer, since ships can respawn,
// they get log entries for being destroyed even though they have respawned.
// Goober5000 - update this to use ship registry status with similar logic
if (target_ship_entry && target_ship_entry->status == ShipStatus::EXITED) {
status = 1;
return_val = ai_achievability::NOT_ACHIEVABLE;
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
status = mission_log_get_time( LOG_SHIP_DEPARTED, aigp->target_name, NULL, NULL);
if ( !status ) {
status = mission_log_get_time( LOG_SHIP_DESTROYED, aigp->target_name, NULL, NULL);
if ( !status ) {
status = mission_log_get_time( LOG_SELF_DESTRUCTED, aigp->target_name, NULL, NULL);
}
}
if ( status )
return_val = ai_achievability::NOT_ACHIEVABLE;
} else {
status = 0;
}
// fly-to-ship can potentially be determined
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->has_objp()) {
auto dist = vm_vec_dist(&target_ship_entry->objp()->pos, &objp->pos);
if (dist < aigp->float_data) {
return_val = ai_achievability::SATISFIED;
status = 1;
}
}
break;
}
@@ -1788,12 +1768,12 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// the if statement.
if ( (aigp->ai_mode == AI_GOAL_CHASE_WING) || (aigp->ai_mode == AI_GOAL_GUARD_WING) )
{
int wingnum = wing_name_lookup( aigp->target_name );
sindex = wing_name_lookup( aigp->target_name );
if (wingnum < 0)
if (sindex < 0)
return ai_achievability::NOT_KNOWN;
wing *wingp = &Wings[wingnum];
wing *wingp = &Wings[sindex];
if ( wingp->flags[Ship::Wing_Flags::Gone] )
return ai_achievability::NOT_ACHIEVABLE;
@@ -1810,22 +1790,24 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
else
{
if (!target_ship_entry)
auto ship_entry = ship_registry_get(aigp->target_name);
if (!ship_entry)
{
status = SHIP_STATUS_UNKNOWN;
}
// goal ship is currently in mission
else if (target_ship_entry->status == ShipStatus::PRESENT || target_ship_entry->status == ShipStatus::DEATH_ROLL)
else if (ship_entry->status == ShipStatus::PRESENT || ship_entry->status == ShipStatus::DEATH_ROLL)
{
status = SHIP_STATUS_ARRIVED;
}
// goal ship is still on the arrival list
else if (target_ship_entry->status == ShipStatus::NOT_YET_PRESENT)
else if (ship_entry->status == ShipStatus::NOT_YET_PRESENT)
{
status = SHIP_STATUS_NOT_ARRIVED;
}
// goal ship has left the area
else if (target_ship_entry->status == ShipStatus::EXITED)
else if (ship_entry->status == ShipStatus::EXITED)
{
status = SHIP_STATUS_GONE;
}
@@ -1836,16 +1818,18 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
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", shipp->ship_name, aigp->target_name));
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));
}
}
// Goober5000 - before doing anything else, check if this is a disarm goal for an arrived ship...
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP || aigp->ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL))
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP))
{
if (target_ship_entry && target_ship_entry->has_shipp()) {
sindex = ship_name_lookup(aigp->target_name);
if ( sindex >= 0 ) {
// if the ship has no turrets, we can't disarm it!
if (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
if (Ships[sindex].subsys_info[SUBSYSTEM_TURRET].type_count == 0)
return ai_achievability::NOT_ACHIEVABLE;
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
@@ -1872,36 +1856,40 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// this goal will get removed.
if ( (aigp->ai_mode == AI_GOAL_DOCK) && (status == SHIP_STATUS_ARRIVED) ) {
if (!(aigp->flags[AI::Goal_Flags::Docker_index_valid])) {
int modelnum = Ship_info[shipp->ship_info_index].model_num;
modelnum = Ship_info[Ships[objp->instance].ship_info_index].model_num;
Assert( modelnum >= 0 );
aigp->docker.index = model_find_dock_name_index(modelnum, aigp->docker.name);
index = model_find_dock_name_index(modelnum, aigp->docker.name);
aigp->docker.index = index;
aigp->flags.set(AI::Goal_Flags::Docker_index_valid);
}
if (!(aigp->flags[AI::Goal_Flags::Dockee_index_valid])) {
if (target_ship_entry && target_ship_entry->has_shipp()) {
int modelnum = Ship_info[target_ship_entry->shipp()->ship_info_index].model_num;
aigp->dockee.index = model_find_dock_name_index(modelnum, aigp->dockee.name);
sindex = ship_name_lookup(aigp->target_name);
if ( sindex != -1 ) {
modelnum = Ship_info[Ships[sindex].ship_info_index].model_num;
index = model_find_dock_name_index(modelnum, aigp->dockee.name);
aigp->dockee.index = index;
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
} else
aigp->dockee.index = -1; // this will force code into if statement below making goal not achievable.
}
if ( (aigp->dockee.index == -1) || (aigp->docker.index == -1) ) {
Warning(LOCATION, "Cannot determine docking information for %s!", shipp->ship_name); // for now, allender wants to know about these things!!!!
Warning(LOCATION, "Cannot determine docking information for %s!", Ships[objp->instance].ship_name); // for now, allender wants to know about these things!!!!
return ai_achievability::NOT_ACHIEVABLE;
}
// if ship is disabled, don't know if it can dock or not
if ( shipp->flags[Ship::Ship_Flags::Disabled] )
if ( Ships[objp->instance].flags[Ship::Ship_Flags::Disabled] )
return ai_achievability::NOT_KNOWN;
// we must also determine if we're prevented from docking for any reason
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
sindex = ship_name_lookup(aigp->target_name);
if (sindex < 0) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
auto goal_objp = target_ship_entry->objp();
object *goal_objp = &Objects[Ships[sindex].objnum];
// if the ship that I am supposed to dock with is docked with something else, then I need to put my goal on hold
// [MK, 4/23/98: With Mark, we believe this fixes the problem of Comet refusing to warp out after docking with Omega.
@@ -1950,9 +1938,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// might happen too, so err on the safe side. (Yay for emergent paragraph justification!)
if ((aip->mode == AIM_DOCK) && (aip->submode >= AIS_UNDOCK_0))
{
if ( target_ship_entry && target_ship_entry->has_objp() ) {
sindex = ship_name_lookup(aigp->target_name);
if ( sindex >= 0 ) {
// only put it on hold if it's someone other than the guy we're undocking from right now!!
if (aip->goal_objnum != target_ship_entry->objnum)
if (aip->goal_objnum != Ships[sindex].objnum)
return ai_achievability::NOT_KNOWN;
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
@@ -1965,8 +1955,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
// the ship's subsystem list
if ( aigp->flags[AI::Goal_Flags::Subsys_needs_fixup] ) {
if ( target_ship_entry && target_ship_entry->has_shipp() ) {
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp(), aigp->docker.name );
sindex = ship_name_lookup( aigp->target_name );
if ( sindex != -1 ) {
aigp->ai_submode = ship_find_subsys( &Ships[sindex], aigp->docker.name );
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
@@ -1974,12 +1966,15 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
}
} else if ( ((aigp->ai_mode == AI_GOAL_IGNORE) || (aigp->ai_mode == AI_GOAL_IGNORE_NEW)) && (status == SHIP_STATUS_ARRIVED) ) {
object *ignored;
// for ignoring a ship, call the ai_ignore object function, then declare the goal satisfied
if (!target_ship_entry || !target_ship_entry->has_objp()) {
sindex = ship_name_lookup( aigp->target_name );
if (sindex < 0) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
auto ignored = target_ship_entry->objp();
ignored = &Objects[Ships[sindex].objnum];
ai_ignore_object(objp, ignored, (aigp->ai_mode == AI_GOAL_IGNORE_NEW));
@@ -1995,9 +1990,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
case AI_GOAL_GUARD:
case AI_GOAL_GUARD_WING:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
@@ -2014,7 +2007,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
else if ( status == SHIP_STATUS_UNKNOWN )
return ai_achievability::NOT_KNOWN;
UNREACHABLE("Invalid status variable %d for ship %s; get Allender or a SCP member", status, shipp->ship_name); // get allender -- bad logic
UNREACHABLE("Invalid status variable %d for ship %s; get Allender or a SCP member", status, Ships[objp->instance].ship_name); // get allender -- bad logic
break;
}
@@ -2026,29 +2019,30 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// short circuit a couple of cases. Ship not arrived shouldn't happen. Ship gone means
// we mark the goal as not achievable.
if ( status == SHIP_STATUS_NOT_ARRIVED ) {
UNREACHABLE("Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", shipp->ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
UNREACHABLE("Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", Ships[objp->instance].ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
return ai_achievability::NOT_ACHIEVABLE;
}
if ( status == SHIP_STATUS_GONE )
return ai_achievability::NOT_ACHIEVABLE;
if ( !target_ship_entry || !target_ship_entry->has_shipp() ) {
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE;
}
// if destination currently being repaired, then goal is still active
if ( Ai_info[target_ship_entry->shipp()->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
// if desitnation currently being repaired, then goal is stil active
if ( Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
return ai_achievability::ACHIEVABLE;
// if the destination ship is dying or departing (but not completed yet), the mark goal as
// not achievable.
if ( target_ship_entry->shipp()->is_dying_or_departing())
if ( Ships[sindex].is_dying_or_departing())
return ai_achievability::NOT_ACHIEVABLE;
// if the destination object is no longer awaiting repair, then remove the item
if ( !(Ai_info[target_ship_entry->shipp()->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
if ( !(Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
return ai_achievability::NOT_ACHIEVABLE;
// not repairing anything means that he can do this goal!!!
@@ -2063,7 +2057,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if he is repairing something, he can satisfy his repair goal (his goal_objnum)
// return GOAL_NOT_KNOWN which is kind of a hack which puts the goal on hold until it can be
// satisfied.
if ( aip->goal_objnum != target_ship_entry->objnum )
if ( aip->goal_objnum != Ships[sindex].objnum )
return ai_achievability::NOT_KNOWN;
return ai_achievability::ACHIEVABLE;
@@ -2337,14 +2331,19 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
case AI_GOAL_WAYPOINTS: // do nothing for waypoints
case AI_GOAL_WAYPOINTS_ONCE: {
int flags = 0;
if (current_goal->ai_mode == AI_GOAL_WAYPOINTS)
if ( current_goal->ai_mode == AI_GOAL_WAYPOINTS)
flags |= WPF_REPEAT;
if (current_goal->flags[AI::Goal_Flags::Waypoints_in_reverse])
flags |= WPF_BACKTRACK;
ai_start_waypoints(objp, current_goal->wp_list, flags, current_goal->int_data);
ai_start_waypoints(objp, current_goal->wp_list, flags);
break;
}
case AI_GOAL_FLY_TO_SHIP:
shipnum = ship_name_lookup( current_goal->target_name );
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
ai_start_fly_to_ship(objp, shipnum);
break;
case AI_GOAL_DOCK: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
@@ -2419,27 +2418,22 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
// when destroying a subsystem, we can destroy a specific instance of a subsystem
// or all instances of a type of subsystem (i.e. a specific engine or all engines).
// the ai_submode value is > 0 for a specific instance of subsystem and < 0 for all
// instances of a specific type
// when destroying a subsystem, we can destroy a specific instance of a subsystem
// or all instances of a type of subsystem (i.e. a specific engine or all engines).
// the ai_submode value is > 0 for a specific instance of subsystem and < 0 for all
// instances of a specific type
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL: {
case AI_GOAL_DISARM_SHIP: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert( shipnum >= 0 );
other_obj = &Objects[Ships[shipnum].objnum];
ai_attack_object( objp, other_obj);
ai_set_attack_subsystem( objp, current_goal->ai_submode ); // submode stored the subsystem type
// don't protect-ship for tactical goals
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM && current_goal->ai_mode != AI_GOAL_DISABLE_SHIP_TACTICAL && current_goal->ai_mode != AI_GOAL_DISARM_SHIP_TACTICAL) {
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM) {
if (aip->target_objnum != -1) {
int class_type = Ship_info[Ships[shipnum].ship_info_index].class_type;
// Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected.
if (class_type >= 0 && Ship_types[class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
Objects[aip->target_objnum].flags.set(Object::Object_Flags::Protected);
}
} else // Just in case this ship had been protected, unprotect it.
@@ -2517,17 +2511,14 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// labels for support ship commands
case AI_GOAL_STAY_NEAR_SHIP:
case AI_GOAL_FLY_TO_SHIP:
{
case AI_GOAL_STAY_NEAR_SHIP: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert( shipnum >= 0 );
other_obj = &Objects[Ships[shipnum].objnum];
float dist = current_goal->float_data; // How far away to stay from ship. Should be set in SEXP?
int additional_data = current_goal->int_data; // Whether to target a particular point as if escorting
ai_do_stay_near(objp, other_obj, dist, additional_data);
ai_do_stay_near(objp, other_obj, dist);
break;
}
}
case AI_GOAL_KEEP_SAFE_DISTANCE:
// todo MK: hook to keep support ship at a safe distance
@@ -2548,7 +2539,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
default:
UNREACHABLE("unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP", current_goal->ai_mode);
Int3();
break;
}
@@ -2575,9 +2566,7 @@ void ai_update_goal_references(ai_goal *goals, sexp_ref_type type, const char *o
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_GUARD:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
case AI_GOAL_EVADE_SHIP:
@@ -2651,9 +2640,7 @@ bool query_referenced_in_ai_goals(ai_goal *goals, sexp_ref_type type, const char
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_GUARD:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
case AI_GOAL_EVADE_SHIP:
+7 -9
View File
@@ -73,17 +73,15 @@ struct ai_info;
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x04000000
#define AI_GOAL_LUA (1<<27) // 0x08000000
#define AI_GOAL_DISARM_SHIP_TACTICAL (1<<28) // 0x10000000
#define AI_GOAL_DISABLE_SHIP_TACTICAL (1<<29) // 0x20000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
#define AI_GOAL_LUA (1<<27) // 0x04000000
// now the masks for ship types
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
//WMC - Don't need these anymore. Whee!
/*
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
@@ -168,17 +166,17 @@ extern void ai_process_mission_orders( int objnum, ai_info *aip );
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, const char *shipname, ai_info *aip);
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_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name);
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, 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 );
// adds goals to ships/sings through player orders
extern void ai_add_ship_goal_player(int type, int mode, int submode, const char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_add_wing_goal_player(int type, int mode, int submode, const char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_add_ship_goal_player(int type, int mode, int submode, char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_add_wing_goal_player(int type, int mode, int submode, char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_remove_ship_goal( ai_info *aip, int index );
extern void ai_clear_ship_goals( ai_info *aip );
+5 -168
View File
@@ -18,9 +18,9 @@ void ai_lua_add_mode(int sexp_op, const ai_mode_lua& mode) {
}
bool ai_lua_add_order(int sexp_op, player_order_lua order) {
Player_orders.emplace_back(order.parseText, order.displayText, -1, sexp_op);
Player_orders.emplace_back(vm_strdup(order.parseText.c_str()), vm_strdup(order.displayText.c_str()), -1, sexp_op);
Player_orders.back().localize();
Lua_player_orders.emplace(sexp_op, std::move(order));
return true;
@@ -48,140 +48,6 @@ const player_order_lua* ai_lua_find_player_order(int sexp_op) {
return &aiLuaOrder->second;
}
int ai_lua_get_num_general_orders() {
int count = 0;
for (const auto& order : Lua_player_orders) {
if (order.second.generalOrder) {
count++;
}
}
return count;
}
SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only)
{
SCP_vector<SCP_string> list;
for (const auto& order : Lua_player_orders) {
const SCP_string &cat = order.second.category;
// If it's not a general order then move on
if (!order.second.generalOrder) {
continue;
}
// If the order is not enabled then move on
if (enabled_only && !order.second.cur_enabled) {
continue;
}
Assertion((cat.length() > 0), "Lua general orders category name must be longer than 0 characters!");
for (size_t i = 0; i <= list.size(); i++) {
// reached the end of the list, so add it
if (i == list.size()) {
list.push_back(cat);
break;
}
// if it's already in the list then don't add it
if (cat == list[i]) {
break;
}
}
}
return list;
}
// Provides a list of general orders for mission saving. You can only get one kind
// of list at a time. If onlyEnabled and onlyValid are both true, for example, you will get
// a list of onlyEnabled orders. If you need a list of enabled orders that are also valid, you'll
// need to get both lists separately and compare.
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled, bool onlyValid, const SCP_string& category)
{
SCP_vector<SCP_string> list;
for (const auto& order : Lua_player_orders) {
if (order.second.generalOrder) {
bool add = false;
// All general orders
if (!onlyEnabled && !onlyValid && category.empty()) {
add = true;
} else {
// Only enabled orders
if (onlyEnabled && order.second.cur_enabled) {
add = true;
// Only valid orders
} else if (onlyValid && order.second.cur_valid) {
add = true;
// Only orders that match the category requested
} else if ((!category.empty()) && (order.second.category == category)) {
add = true;
}
}
if (add) {
list.push_back(order.second.parseText);
}
}
}
return list;
}
int ai_lua_find_general_order_id(const SCP_string& name) {
for (const auto& order : Lua_player_orders) {
if (order.second.parseText == name) {
return order.first;
}
}
return -1;
}
void ai_lua_enable_general_order(int sexp_op, bool enable) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return;
else
aiLuaOrder->second.cur_enabled = enable;
}
void ai_lua_validate_general_order(int sexp_op, bool validity)
{
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return;
else
aiLuaOrder->second.cur_valid = validity;
}
void ai_lua_reset_general_orders() {
for (const auto& order : Lua_player_orders) {
ai_lua_enable_general_order(order.first, false);
ai_lua_validate_general_order(order.first, false);
}
}
bool ai_lua_is_general_order(int sexp_op) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return false;
return aiLuaOrder->second.generalOrder;
}
void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua_ai, ai_info* aip) {
if (!action.isValid()) {
Error(LOCATION,
@@ -190,11 +56,7 @@ void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua
}
luacpp::LuaValueList luaParameters;
if (aip->shipnum >= 0){
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h(&Objects[Ships[aip->shipnum].objnum]))));
} else {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h())));
}
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h(&Objects[Ships[aip->shipnum].objnum]))));
if (lua_ai.needsTarget) {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_OSWPT.Set(aip->lua_ai_target.target)));
}
@@ -205,13 +67,8 @@ void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua
auto retVals = action.call(Script_system.GetLuaSession(), luaParameters);
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::BOOLEAN) {
if (retVals[0].getValue<bool>()) {
// If we don't have a ship then it's a general order and we have nothing else to do
if (aip->shipnum >= 0) {
ai_mission_goal_complete(aip);
}
}
if (retVals[0].getValue<bool>())
ai_mission_goal_complete(aip);
}
}
@@ -246,26 +103,6 @@ void ai_lua_start(ai_goal* aigp, object* objp){
run_ai_lua_action(action, lua_ai, aip);
}
// For sending general orders that don't run on a ship.
// Essentially just runs arbitrary lua script when the command is called
void ai_lua_start_general(int lua_sexp_id, int target_objnum)
{
//Create a dummy aip to pass the target data
ai_info aip;
aip.shipnum = -1;
if (target_objnum >= 0 && Objects[target_objnum].type == OBJ_SHIP) {
aip.lua_ai_target = {object_ship_wing_point_team(&Ships[Objects[target_objnum].instance]), {}};
}
const auto& lua_ai = ai_lua_find_mode(lua_sexp_id);
const auto& lua_ai_sexp = lua_ai->sexp;
const auto& action = lua_ai_sexp.getActionEnter();
run_ai_lua_action(action, *lua_ai, &aip);
}
bool ai_lua_is_valid_target_intrinsic(int sexp_op, int target_objnum, ship* self) {
ship* target = &Ships[Objects[target_objnum].instance];
-13
View File
@@ -19,10 +19,6 @@ struct player_order_lua {
int ai_message = MESSAGE_YESSIR;
SCP_string parseText = "";
SCP_string displayText = "";
bool generalOrder = false;
SCP_string category = "";
bool cur_enabled = false;
bool cur_valid = false;
enum class target_restrictions : int { TARGET_ALLIES, TARGET_ALL, TARGET_OWN, TARGET_ENEMIES, TARGET_SAME_WING, TARGET_PLAYER_WING, TARGET_ALL_CAPS, TARGET_ALLIED_CAPS, TARGET_ENEMY_CAPS, TARGET_NOT_SELF } targetRestrictions = target_restrictions::TARGET_ALL;
enum class ship_restrictions : int { ANY, WING, IN_PLAYER_WING, PLAYER_WING } shipRestrictions = ship_restrictions::ANY;
};
@@ -33,17 +29,8 @@ bool ai_lua_add_order(int sexp_op, player_order_lua order);
bool ai_lua_has_mode(int sexp_op);
const ai_mode_lua* ai_lua_find_mode(int sexp_op);
const player_order_lua* ai_lua_find_player_order(int sexp_op);
SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only = true);
int ai_lua_get_num_general_orders();
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled = false, bool onlyValid = false, const SCP_string& category = "");
int ai_lua_find_general_order_id(const SCP_string& name);
void ai_lua_enable_general_order(int sexp_op, bool enable);
void ai_lua_validate_general_order(int sexp_op, bool validity);
void ai_lua_reset_general_orders();
bool ai_lua_is_general_order(int sexp_op);
void ai_lua(ai_info* aip);
void ai_lua_start(ai_goal* aigp, object* objp);
void ai_lua_start_general(int lua_sexp_id, int target_objnum);
bool ai_lua_is_valid_target(int sexp_op, int target_objnum, ship* self, size_t order);
bool ai_lua_is_valid_ship(int sexp_op, bool isWing, ship* self);
ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum);
+50 -34
View File
@@ -72,29 +72,29 @@ const char* Turret_valid_types[NUM_TURRET_TYPES] = {
};
typedef struct eval_enemy_obj_struct {
int turret_parent_objnum = -1; // parent of turret
float weapon_travel_dist = 0.0f; // max targeting range of turret weapon
int enemy_team_mask = 0;
bool weapon_system_ok = false; // is the weapon subsystem of turret ship ok
int eeo_flags = 0;
int turret_parent_objnum; // parent of turret
float weapon_travel_dist; // max targeting range of turret weapon
int enemy_team_mask;
int weapon_system_ok; // is the weapon subsystem of turret ship ok
int eeo_flags;
const vec3d *tpos = nullptr;
const vec3d *tvec = nullptr;
const ship_subsys *turret_subsys = nullptr;
int current_enemy = -1;
vec3d *tpos;
vec3d *tvec;
ship_subsys *turret_subsys;
int current_enemy;
float nearest_attacker_dist = 99999.0f; // nearest ship
int nearest_attacker_objnum = -1;
float nearest_attacker_dist; // nearest ship
int nearest_attacker_objnum;
float nearest_homing_bomb_dist = 99999.0f; // nearest homing bomb
int nearest_homing_bomb_objnum = -1;
float nearest_homing_bomb_dist; // nearest homing bomb
int nearest_homing_bomb_objnum;
float nearest_bomb_dist = 99999.0f; // nearest non-homing bomb
int nearest_bomb_objnum = -1;
float nearest_bomb_dist; // nearest non-homing bomb
int nearest_bomb_objnum;
float nearest_dist = 99999.0f; // nearest ship attacking this turret
int nearest_objnum = -1;
float nearest_dist; // nearest ship attacking this turret
int nearest_objnum;
} eval_enemy_obj_struct;
// the current world orientation of the turret matrix, corresponding to its fvec and uvec defined in the model
@@ -120,7 +120,7 @@ void turret_instance_find_world_orient(matrix* out_mat, int model_instance_num,
*
* @return 1 if objp is in fov of the specified turret. Otherwise return 0.
*/
bool object_in_turret_fov(const object *objp, const ship_subsys *ss, const vec3d *tvec, const vec3d *tpos, float dist)
bool object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
{
vec3d v2e;
float size_mod;
@@ -215,7 +215,7 @@ int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
/**
* Returns true if all weapons in swp have the specified flag
*/
bool all_turret_weapons_have_flags(const ship_weapon *swp, flagset<Weapon::Info_Flags> flags)
bool all_turret_weapons_have_flags(ship_weapon *swp, flagset<Weapon::Info_Flags> flags)
{
int i;
for(i = 0; i < swp->num_primary_banks; i++)
@@ -232,7 +232,7 @@ bool all_turret_weapons_have_flags(const ship_weapon *swp, flagset<Weapon::Info_
return true;
}
bool all_turret_weapons_have_flags(const ship_weapon *swp, Weapon::Info_Flags flags)
bool all_turret_weapons_have_flags(ship_weapon *swp, Weapon::Info_Flags flags)
{
int i;
for (i = 0; i < swp->num_primary_banks; i++)
@@ -253,7 +253,7 @@ bool all_turret_weapons_have_flags(const ship_weapon *swp, Weapon::Info_Flags fl
* Returns true if any of the weapons in swp have flags
*
*/
bool turret_weapon_has_flags(const ship_weapon *swp, Weapon::Info_Flags flags)
bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags)
{
Assert(swp != NULL);
@@ -279,7 +279,7 @@ bool turret_weapon_has_flags(const ship_weapon *swp, Weapon::Info_Flags flags)
/**
* Just gloms all the flags from all the weapons into one variable. More efficient if all you need to do is test for the existence of a flag.
*/
flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(const ship_weapon *swp)
flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(ship_weapon *swp)
{
Assert(swp != NULL);
@@ -307,7 +307,7 @@ flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(const ship_weapon *swp
* @note It might be a little faster to optimize based on WP_LASER should only appear in primaries
* and WP_MISSILE in secondaries. but in the interest of future coding I leave it like this.
*/
bool turret_weapon_has_subtype(const ship_weapon *swp, int subtype)
bool turret_weapon_has_subtype(ship_weapon *swp, int subtype)
{
Assert(swp != NULL);
@@ -492,7 +492,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
{
object *turret_parent_obj = &Objects[eeo->turret_parent_objnum];
ship *shipp;
auto ss = eeo->turret_subsys;
ship_subsys *ss = eeo->turret_subsys;
float dist, dist_comp;
bool turret_has_no_target = false;
@@ -772,6 +772,8 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
*/
int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag, bool flak_flag, bool laser_flag, bool missile_flag)
{
//float weapon_travel_dist;
int weapon_system_ok;
eval_enemy_obj_struct eeo;
ship_weapon *swp = &turret_subsys->weapons;
@@ -786,7 +788,10 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
// weapon_travel_dist=wip->lssm_lock_range;
// Set flag based on strength of weapons subsystem. If weapons subsystem is destroyed, don't let turrets fire at bombs
bool weapon_system_ok = !ship_subsystems_blown(&Ships[Objects[turret_parent_objnum].instance], SUBSYSTEM_WEAPONS);
weapon_system_ok = 0;
if ( ship_get_subsystem_strength( &Ships[Objects[turret_parent_objnum].instance], SUBSYSTEM_WEAPONS ) > 0 ) {
weapon_system_ok = 1;
}
// Initialize eeo struct.
eeo.turret_parent_objnum = turret_parent_objnum;
@@ -818,6 +823,18 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
eeo.tvec = tvec;
eeo.turret_subsys = turret_subsys;
eeo.nearest_attacker_dist = 99999.0f;
eeo.nearest_attacker_objnum = -1;
eeo.nearest_homing_bomb_dist = 99999.0f;
eeo.nearest_homing_bomb_objnum = -1;
eeo.nearest_bomb_dist = 99999.0f;
eeo.nearest_bomb_objnum = -1;
eeo.nearest_dist = 99999.0f;
eeo.nearest_objnum = -1;
// here goes the new targeting priority setting
int n_tgt_priorities;
int priority_weapon_idx = -1;
@@ -1047,7 +1064,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
break;
default:
UNREACHABLE("Invalid target type of %d sent to get_nearest_turret_objnum. Please report to the SCP!", turret_subsys->turret_targeting_order[i]);
Int3(); //Means invalid number passed.
}
}
}
@@ -1087,7 +1104,7 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
ai_info *aip = &Ai_info[Ships[Objects[objnum].instance].ai_index];
sip = &Ship_info[Ships[Objects[objnum].instance].ship_info_index];
if ((sip->class_type >= 0) && (Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
if ((Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
int target_objnum = aip->target_objnum;
if (Objects[target_objnum].signature == aip->target_signature) {
@@ -1154,9 +1171,9 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
Assert( !((Objects[enemy_objnum].flags[Object::Object_Flags::Flak_protected]) && flak_flag) );
Assert( !((Objects[enemy_objnum].flags[Object::Object_Flags::Laser_protected]) && laser_flag) );
Assert( !((Objects[enemy_objnum].flags[Object::Object_Flags::Missile_protected]) && missile_flag) );
Assertion(!Objects[enemy_objnum].flags[Object::Object_Flags::Protected], "find_turret_enemy selected an object of type %d %s that is protected, please report to the SCP!", Objects[enemy_objnum].type, Objects[enemy_objnum].type == OBJ_SHIP ? Ships[Objects[enemy_objnum].instance].ship_name : "");
if ( Objects[enemy_objnum].flags[Object::Object_Flags::Protected] ) {
Int3();
enemy_objnum = aip->target_objnum;
}
}
@@ -1368,8 +1385,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_vel, wip->max_speed, ss->turret_time_enemy_in_range * (weapon_system_strength + 1.0f)/2.0f);
else {
vec3d shoot_vec;
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
if (physics_lead_ballistic_trajectory(&gun_pos, &enemy_point, &target_vel, wip->max_speed, &gravity_vec, &shoot_vec)) {
if (physics_lead_ballistic_trajectory(&gun_pos, &enemy_point, &target_vel, wip->max_speed, &The_mission.gravity, &shoot_vec)) {
*predicted_enemy_pos = gun_pos + shoot_vec * 1000.0f;
} else {
if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
@@ -1562,7 +1578,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
if(stride <= 0){
stride = 1;
}
int offset = Random::next((aifft_list_size % stride) + 1); // returns an offset in [0, size % stride] inclusive
int offset = (int)frand_range(0.0f, (float)(aifft_list_size % stride));
int idx;
float dot_fov_modifier = 0.0f;
@@ -2853,7 +2869,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
}
}
bool turret_std_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod)
bool turret_std_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
{
model_subsystem *tp = ss->system_info;
float dot = vm_vec_dot(v2e, gvec);
@@ -2863,7 +2879,7 @@ bool turret_std_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *
return false;
}
bool turret_adv_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod)
bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
{
model_subsystem *tp = ss->system_info;
float dot = vm_vec_dot(v2e, gvec);
@@ -2889,7 +2905,7 @@ bool turret_adv_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *
return false;
}
bool turret_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod)
bool turret_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
{
bool in_fov = false;
if (ss->system_info->turret_base_fov > -1.0f)
+1 -1
View File
@@ -670,7 +670,7 @@ void anim_read_header(anim *ptr, CFILE *fp)
* @param file_mapped Whether to use memory-mapped file or not.
*
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
* @return Pointer to anim that is loaded if success, NULL if failure.
* @return Pointer to anim that is loaded if sucess, NULL if failure.
*/
anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
{
+3 -3
View File
@@ -22,19 +22,19 @@ anim_instance *init_anim_instance(anim *ptr, int bpp)
{
anim_instance *inst;
Assertion(ptr, "Bad pointer in init_anim_instance(), please report to the SCP!");
if (!ptr) {
Int3();
return NULL;
}
if ( ptr->flags & ANF_STREAMED ) {
Assertion(ptr->file_offset > -1, "Bad file offset of %d in init_anim_instance(), please report to the SCP!", ptr->file_offset);
if ( ptr->file_offset < 0 ) {
Int3();
return NULL;
}
} else {
Assertion(ptr->data, "Bad data in init_anim_instance(), please report to the SCP!");
if ( !ptr->data ) {
Int3();
return NULL;
}
}
+11 -14
View File
@@ -401,12 +401,12 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
vec3d rotvel;
if ( Game_mode & GM_NORMAL ) {
vm_vec_rand_vec_quick(&rotvel);
vm_vec_scale(&rotvel, asip->rotational_vel_multiplier * (frand()/4.0f + 0.1f));
vm_vec_scale(&rotvel, frand()/4.0f + 0.1f);
objp->phys_info.rotvel = rotvel;
vm_vec_rand_vec_quick(&objp->phys_info.vel);
} else {
static_randvec( rand_base++, &rotvel );
vm_vec_scale(&rotvel, asip->rotational_vel_multiplier * (static_randf(rand_base++)/4.0f + 0.1f));
vm_vec_scale(&rotvel, static_randf(rand_base++)/4.0f + 0.1f);
objp->phys_info.rotvel = rotvel;
static_randvec( rand_base++, &objp->phys_info.vel );
}
@@ -1030,7 +1030,7 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
float dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
// if asteroid is within view or far enough away then wrap
if (dot > cos(g3_get_hfov(Proj_fov))) {
if (dot > cos(Proj_fov)) {
if (range_override) {
return true;
} else {
@@ -1332,9 +1332,10 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
// copy important data
int orig_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
vec3d orig_p0 = *mc.p0;
vec3d orig_p1 = *mc.p1;
int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
vec3d copy_p0, copy_p1;
copy_p0 = *mc.p0;
copy_p1 = *mc.p1;
// first test against the sphere - if this fails then don't do any submodel tests
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
@@ -1360,7 +1361,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
}
// Only check single submodel now, since children of moving submodels are handled as moving as well
mc.flags = orig_flags | MC_SUBMODEL;
mc.flags = copy_flags | MC_SUBMODEL;
// check each submodel in turn
for (auto submodel: submodel_vector) {
@@ -1405,9 +1406,9 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
}
// Now complete base model collision checks that do not take into account rotating submodels.
mc.flags = orig_flags;
mc.p0 = &orig_p0;
mc.p1 = &orig_p1;
mc.flags = copy_flags;
*mc.p0 = copy_p0;
*mc.p1 = copy_p1;
mc.orient = &heavy_obj->orient;
// usual ship_ship collision test
@@ -2238,10 +2239,6 @@ static void asteroid_parse_section()
stuff_float(&asteroid_p->max_speed);
}
if (optional_string("$Rotational Velocity Multiplier:")) {
stuff_float(&asteroid_p->rotational_vel_multiplier);
}
if(optional_string("$Damage Type:")) {
char buf[NAME_LENGTH];
stuff_string(buf, F_NAME, NAME_LENGTH);
+1 -3
View File
@@ -63,7 +63,6 @@ public:
int num_detail_levels; // number of detail levels for this ship
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
float max_speed; // cap on speed for asteroid
float rotational_vel_multiplier; // rotational velocity multiplier for asteroid --wookieejedi
int damage_type_idx; //Damage type of the asteroid
int damage_type_idx_sav; // stored value from table used to reset damage_type_idx
float inner_rad; // radius within which maximum area effect damage is applied
@@ -81,8 +80,7 @@ public:
float gravity_const; // multiplier for mission gravity
asteroid_info( )
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0),
rotational_vel_multiplier(1), damage_type_idx(0),
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0), damage_type_idx(0),
damage_type_idx_sav( -1 ), inner_rad( 0 ), outer_rad( 0 ),
damage( 0 ), blast( 0 ), initial_asteroid_strength( 0 ),
fireball_radius_multiplier( -1 ), spawn_weight( 1 ), gravity_const( 0 )
+1 -1
View File
@@ -869,7 +869,7 @@ void EndAutoPilot()
Assert( CurrentNav >= 0 );
int goal = 0;
const char *goal_name = NULL;
char *goal_name = NULL;
if (Navs[CurrentNav].flags & NP_WAYPOINT)
{
+1 -2
View File
@@ -425,7 +425,6 @@ DCF(bm_used, "Shows BmpMan Slot Usage") {
SCP_stringstream text;
text << "BmpMan Used Slots\n";
text << " " << std::dec << std::setw(4) << std::setfill('0') << none << ", NONE\n";
text << " " << std::dec << std::setw(4) << std::setfill('0') << pcx << ", PCX\n";
text << " " << std::dec << std::setw(4) << std::setfill('0') << user << ", User\n";
text << " " << std::dec << std::setw(4) << std::setfill('0') << tga << ", TGA\n";
@@ -599,7 +598,7 @@ int bm_create_3d(int bpp, int w, int h, int d, void* data) {
// make sure that we have valid data
if (data == nullptr) {
UNREACHABLE("No valid data received for 3D Bitmap creation!");
UNREACHABLE("No valid data recieved for 3D Bitmap creation!");
return -1;
}
+21 -53
View File
@@ -14,8 +14,8 @@
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
fov_t VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
fov_t COCKPIT_ZOOM_DEFAULT = 0.75f;
float VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
float COCKPIT_ZOOM_DEFAULT = 0.75f;
float Sexp_fov = 0.0f;
warp_camera Warp_camera;
@@ -27,33 +27,6 @@ SCP_vector<camera*> Cameras;
camid Current_camera;
camid Main_camera;
asymmetric_fov operator* (const asymmetric_fov& left, const float& right) {
return asymmetric_fov{ left.left * right, left.right * right, left.up * right, left.down * right };
}
asymmetric_fov operator+ (const asymmetric_fov& left, const float& right) {
float ar = (left.up - left.down) / (left.right - left.left);
return asymmetric_fov{ left.left - right * 0.5f, left.right + right * 0.5f, left.up + right * 0.5f * ar, left.down - right * 0.5f * ar };
}
asymmetric_fov operator- (const asymmetric_fov& left, const float& right) {
float ar = (left.up - left.down) / (left.right - left.left);
return asymmetric_fov{ left.left + right * 0.5f, left.right - right * 0.5f, left.up - right * 0.5f * ar, left.down + right * 0.5f * ar };
}
#define APPLY_TO_FOV_T(op, name) \
struct apply_##name##_to_fov { \
float r; \
template<typename T> \
fov_t operator()(const T& l) { \
return fov_t(l op r); \
} \
}; \
fov_t operator op (const fov_t& zoom, const float& scale) { \
return mpark::visit(apply_##name##_to_fov{scale}, zoom); \
}
APPLY_TO_FOV_T(*, mul)
APPLY_TO_FOV_T(+, add)
APPLY_TO_FOV_T(-, sub)
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
@@ -61,20 +34,15 @@ static SCP_string fov_display(float val)
sprintf(out, u8"%.1f\u00B0", degrees);
return out;
}
auto FovOption = options::OptionBuilder<float>("Graphics.FOV",
std::pair<const char*, int>{"Field Of View", 1703},
std::pair<const char*, int>{"The vertical field of view", 1704})
.category("Graphics")
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
VIEWER_ZOOM_DEFAULT = val;
return true;
})
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
auto FovOption = options::OptionBuilder<float>("Graphics.FOV", "Field Of View", "The vertical field of view.")
.category("Graphics")
.range(0.436332f, 1.5708f)
.bind_to(&VIEWER_ZOOM_DEFAULT)
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
//*************************CLASS: camera*************************
//This is where the camera class begins! :D
@@ -117,7 +85,7 @@ void camera::reset()
func_custom_orientation = NULL;
fov.clear();
fov.set(g3_get_hfov(VIEWER_ZOOM_DEFAULT));
fov.set(VIEWER_ZOOM_DEFAULT);
pos_x.clear();
pos_y.clear();
@@ -136,7 +104,7 @@ void camera::set_name(const char *in_name)
strncpy(name, in_name, NAME_LENGTH-1);
}
void camera::set_fov(fov_t in_fov, float in_fov_time, float in_fov_acceleration_time, float in_fov_deceleration_time)
void camera::set_fov(float in_fov, float in_fov_time, float in_fov_acceleration_time, float in_fov_deceleration_time)
{
if(in_fov_time == 0.0f && in_fov_acceleration_time == 0.0f && in_fov_deceleration_time == 0.0f)
{
@@ -146,23 +114,26 @@ void camera::set_fov(fov_t in_fov, float in_fov_time, float in_fov_acceleration_
}
flags &= ~CAM_STATIONARY_FOV;
if(g3_get_hfov(in_fov) <= 0.0f)
if(in_fov <= 0.0f)
{
fov.setVD(in_fov_time, in_fov_acceleration_time, 0.0f);
}
fov.setAVD(g3_get_hfov(in_fov), in_fov_time, in_fov_acceleration_time, in_fov_deceleration_time, 0.0f);
fov.setAVD(in_fov, in_fov_time, in_fov_acceleration_time, in_fov_deceleration_time, 0.0f);
}
void camera::set_object_host(object *objp, int n_object_host_submodel)
{
if(objp == NULL)
object_host = object_h();
object_host = object_h(objp);
object_host_submodel = n_object_host_submodel;
set_custom_position_function(NULL);
set_custom_orientation_function(NULL);
if(n_object_host_submodel > 0)
{
if(objp != nullptr && objp->type == OBJ_SHIP)
if(objp->type == OBJ_SHIP)
{
ship_subsys* ssp = GET_FIRST(&Ships[objp->instance].subsys_list);
while ( ssp != END_OF_LIST( &Ships[objp->instance].subsys_list ) )
@@ -348,14 +319,11 @@ int camera::get_object_target_submodel()
return object_target_submodel;
}
fov_t camera::get_fov()
float camera::get_fov()
{
if(!(flags & CAM_STATIONARY_FOV))
{
float fov_now;
fov.get(&fov_now, nullptr);
return fov_now;
//TODO enable moving asymmetric fov
fov.get(&c_fov, NULL);
}
return c_fov;
+5 -18
View File
@@ -10,8 +10,6 @@
#include <string>
#include <mpark/variant.hpp>
#define CAM_STATIONARY_FOV (1<<0)
#define CAM_STATIONARY_ORI (1<<1)
#define CAM_STATIONARY_POS (1<<2)
@@ -20,17 +18,6 @@
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
struct asymmetric_fov {
float left, right, up, down;
friend asymmetric_fov operator* (const asymmetric_fov&, const float&);
friend asymmetric_fov operator+ (const asymmetric_fov&, const float&);
friend asymmetric_fov operator- (const asymmetric_fov&, const float&);
};
using fov_t = mpark::variant<float, asymmetric_fov>;
fov_t operator* (const fov_t&, const float&);
fov_t operator+ (const fov_t&, const float&);
fov_t operator- (const fov_t&, const float&);
class camera
{
protected:
@@ -54,7 +41,7 @@ protected:
avd_movement ori[9];
//Cache stuff
fov_t c_fov;
float c_fov;
vec3d c_pos;
matrix c_ori;
public:
@@ -72,7 +59,7 @@ public:
void set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *pos));
void set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *ori));
void set_fov(fov_t in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
@@ -87,7 +74,7 @@ public:
int get_object_host_submodel();
object *get_object_target();
int get_object_target_submodel();
fov_t get_fov();
float get_fov();
void get_info(vec3d *position, matrix *orientation, bool apply_camera_orientation = true);
//Is
@@ -168,8 +155,8 @@ public:
//Some global stuff
extern SCP_vector<subtitle> Subtitles;
extern fov_t VIEWER_ZOOM_DEFAULT;
extern fov_t COCKPIT_ZOOM_DEFAULT;
extern float VIEWER_ZOOM_DEFAULT;
extern float COCKPIT_ZOOM_DEFAULT;
extern float Sexp_fov;
//Helpful functions
+1 -3
View File
@@ -438,7 +438,7 @@ int cfile_flush_dir(int dir_type)
// filename = name of filename or filepath to process
// ext = extension to add. Must start with the period
// Returns: new filename or filepath with extension.
const char *cf_add_ext(const char *filename, const char *ext)
char *cf_add_ext(const char *filename, const char *ext)
{
static char path[MAX_PATH_LEN];
@@ -681,8 +681,6 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
} else {
// Path type given?
Assert( dir_type != CF_TYPE_ANY );
if (dir_type == CF_TYPE_ANY)
return NULL;
// Create the directory if necessary
cf_create_directory(dir_type, location_flags);
+1 -1
View File
@@ -171,7 +171,7 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
void cfile_close();
// add an extension to a filename if it doesn't already have it
const char *cf_add_ext(const char *filename, const char *ext);
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);
+1 -1
View File
@@ -1172,7 +1172,7 @@ void cf_build_file_list()
}
Warning(LOCATION, "Some critical files might be shadowed! Please check the debug log for details.\n\n"
SIZE_T_ARG " file(s) detected, including:\n%s", count, shadowed.c_str());
"%lu file(s) detected, including:\n%s", count, shadowed.c_str());
}
critical_shadowed.clear();
+1 -1
View File
@@ -82,7 +82,7 @@ void SpawnShipCheat::runCheat() {
if (ptr->system_info->type == SUBSYSTEM_TURRET)
{
ptr->weapons.flags.set(Ship::Weapon_Flags::Beam_Free);
ptr->turret_next_fire_stamp = timestamp(Random::next(50, 4000));
ptr->turret_next_fire_stamp = timestamp((int)frand_range(50.0f, 4000.0f));
}
}
+10 -56
View File
@@ -15,7 +15,6 @@
#include "globalincs/pstypes.h"
#include "globalincs/systemvars.h"
#include "globalincs/version.h"
#include "graphics/openxr.h"
#include "graphics/shadows.h"
#include "hud/hudconfig.h"
#include "io/joy.h"
@@ -189,7 +188,6 @@ Flag exe_params[] =
//flag launcher text FSO on_flags off_flags category reference URL
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
{ "-capture_mouse", "Capture the mouse within the window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-capture_mouse", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
@@ -197,8 +195,6 @@ Flag exe_params[] =
{ "-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", },
{ "-vr", "Enable Virtual Reality Mode", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-vr", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
//flag launcher text FSO on_flags off_flags category reference URL
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
@@ -222,7 +218,6 @@ Flag exe_params[] =
//flag launcher text FSO on_flags off_flags category reference URL
{ "-no_set_gamma", "Disable setting of gamma", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_set_gamma", },
{ "-no_ingame_options", "Disable using ingame options", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ingame_options", },
{ "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
{ "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
{ "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
@@ -268,6 +263,7 @@ Flag exe_params[] =
{ "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", },
{ "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", },
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
{ "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
@@ -410,9 +406,7 @@ cmdline_parm use_3dwarp("-3dwarp", nullptr, AT_NONE); // Is now Fireball_use_3
cmdline_parm use_warp_flash("-warp_flash", nullptr, AT_NONE); // Cmdline_warp_flash
cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", nullptr, AT_NONE);
cmdline_parm stretch_menu("-stretch_menu", nullptr, AT_NONE); // Cmdline_stretch_menu
cmdline_parm capture_mouse("-capture_mouse", nullptr, AT_NONE); // Cmdline_capture_mouse
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
cmdline_parm vr("-vr", nullptr, AT_NONE);
cmdline_parm deadzone("-deadzone",
"Sets the joystick deadzone. Integer value from 0 to 100 as a percentage of the joystick's range (100% would make the stick do nothing). Disables deadzone slider in the in-game Options menu.", AT_INT); //Cmdline_deadzone
@@ -420,10 +414,8 @@ int Cmdline_ship_choice_3d = 0;
int Cmdline_weapon_choice_3d = 0;
int Cmdline_autopilot_interruptable = 1;
int Cmdline_stretch_menu = 0;
bool Cmdline_capture_mouse = false;
int Cmdline_no_screenshake = 0;
int Cmdline_deadzone = -1;
bool Cmdline_enable_vr = false;
// Audio related
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
@@ -461,7 +453,6 @@ SCP_string Cmdline_lang;
cmdline_parm loadallweapons_arg("-loadallweps", NULL, AT_NONE); // Cmdline_load_all_weapons
cmdline_parm nomovies_arg("-nomovies", NULL, AT_NONE); // Cmdline_nomovies -- Allows video streaming
cmdline_parm no_set_gamma_arg("-no_set_gamma", NULL, AT_NONE); // Cmdline_no_set_gamma
cmdline_parm no_ingame_options_arg("-no_ingame_options", NULL, AT_NONE); // Cmdline_no_ingame_options
cmdline_parm no_fbo_arg("-disable_fbo", NULL, AT_NONE); // Cmdline_no_fbo
cmdline_parm no_pbo_arg("-disable_pbo", NULL, AT_NONE); // Cmdline_no_pbo
cmdline_parm mipmap_arg("-mipmap", NULL, AT_NONE); // Cmdline_mipmap
@@ -485,7 +476,6 @@ cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
int Cmdline_load_all_weapons = 0;
int Cmdline_nomovies = 0;
int Cmdline_no_set_gamma = 0;
bool Cmdline_no_ingame_options = false;
int Cmdline_no_fbo = 0;
int Cmdline_no_pbo = 0;
int Cmdline_ati_color_swap = 0;
@@ -520,9 +510,7 @@ cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
cmdline_parm window_arg("-window", NULL, AT_NONE); // Cmdline_window
cmdline_parm fullscreen_window_arg("-fullscreen_window", "Fullscreen/borderless window (Windows only)", AT_NONE);
cmdline_parm deprecated_res_arg("-res", "Deprecated, resolution, formatted like 1600x900", AT_STRING);
cmdline_parm render_res_arg("-render_res", "Resolution, formatted like 1600x900", AT_STRING);
cmdline_parm window_res_arg("-window_res", "Window resolution, formatted like 1600x900.", AT_STRING);
cmdline_parm res_arg("-res", "Resolution, formatted like 1600x900", AT_STRING);
cmdline_parm center_res_arg("-center_res", "Resolution of center monitor, formatted like 1600x900", AT_STRING);
cmdline_parm verify_vps_arg("-verify_vps", NULL, AT_NONE); // Cmdline_verify_vps -- spew VP crcs to vp_crcs.txt
cmdline_parm parse_cmdline_only(PARSE_COMMAND_LINE_STRING, "Ignore any cmdline_fso.cfg files", AT_NONE);
@@ -560,7 +548,6 @@ int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
int Cmdline_window = 0;
int Cmdline_fullscreen_window = 0;
tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res = tl::nullopt;
char *Cmdline_res = 0;
char *Cmdline_center_res = 0;
int Cmdline_verify_vps = 0;
@@ -1659,7 +1646,7 @@ bool SetCmdlineParams()
// be sure that this string fits in our limits
if ( strlen(Cmdline_game_password) >= MAX_PASSWD_LEN ) {
ReleaseWarning(LOCATION, "Multi game password is longer than max of %d characters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
ReleaseWarning(LOCATION, "Multi game password is longer than max of %d charaters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
Cmdline_game_password[MAX_PASSWD_LEN-1] = '\0';
}
}
@@ -1723,48 +1710,31 @@ bool SetCmdlineParams()
// d3d windowed
if(window_arg.found()) {
// We need to set both values since we don't know if we are going to use the new config system
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
Cmdline_window = 1;
}
if ( fullscreen_window_arg.found( ) )
{
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
Cmdline_fullscreen_window = 1;
Cmdline_window = 0; /* Make sure no-one sets both */
}
if(render_res_arg.found() || deprecated_res_arg.found()){
if (render_res_arg.found()) {
Cmdline_res = render_res_arg.str();
}
else {
Cmdline_res = deprecated_res_arg.str();
mprintf(("Deprecated -res argument. Use -render_res instead...\n"));
}
if(res_arg.found()){
Cmdline_res = res_arg.str();
/*int width = 0;
int width = 0;
int height = 0;
if (sscanf(Cmdline_res, "%dx%d", &width, &height) == 2) {
if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
SCP_string override;
sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
} else {
Warning(LOCATION, "Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res);
}*/
}
if(window_res_arg.found()){
int width = 0;
int height = 0;
if ( sscanf(window_res_arg.str(), "%dx%d", &width, &height) == 2 ) {
Cmdline_window_res.emplace(static_cast<uint16_t>(width), static_cast<uint16_t>(height));
} else {
Warning(LOCATION, "Failed to parse -window_res parameter \"%s\". Must be in format \"<width>x<height>\".\n", window_res_arg.str());
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res));
}
}
if(center_res_arg.found()){
Cmdline_center_res = center_res_arg.str();
}
@@ -1873,14 +1843,6 @@ bool SetCmdlineParams()
}
}
if (vr.found()) {
Cmdline_enable_vr = true;
if (fov_arg.found() || fov_cockpit_arg.found()) {
Warning(LOCATION, "FoV Command line settings found. VR-Mode will override these with the HMD's native FoV...");
}
openxr_prepare();
}
if (orb_radar.found())
{
Cmdline_orb_radar = 1;
@@ -1909,10 +1871,6 @@ bool SetCmdlineParams()
if ( stretch_menu.found() ) {
Cmdline_stretch_menu = 1;
}
if ( capture_mouse.found() ) {
Cmdline_capture_mouse = true;
}
// new lighting lines
if ( ambient_power_arg.found() )
Cmdline_ambient_power = ambient_power_arg.get_float();
@@ -1936,10 +1894,6 @@ bool SetCmdlineParams()
Cmdline_no_set_gamma = 1;
}
if (no_ingame_options_arg.found()) {
Cmdline_no_ingame_options = true;
}
if(no_vsync_arg.found() )
{
Gr_enable_vsync = false;
+1 -6
View File
@@ -6,13 +6,12 @@
* source.
*
*/
*/
#ifndef FS_CMDLINE_HEADER_FILE
#define FS_CMDLINE_HEADER_FILE
#include <tl/optional.hpp>
int parse_cmdline(int argc, char *argv[]);
@@ -47,7 +46,6 @@ extern int Cmdline_use_last_pilot;
extern int Cmdline_window;
extern int Cmdline_fullscreen_window;
extern char *Cmdline_res;
extern tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res;
extern char *Cmdline_center_res;
@@ -88,10 +86,8 @@ extern int Cmdline_ship_choice_3d;
extern int Cmdline_weapon_choice_3d;
extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
extern bool Cmdline_capture_mouse;
extern int Cmdline_no_screenshake;
extern int Cmdline_deadzone;
extern bool Cmdline_enable_vr;
// Audio related
extern int Cmdline_voice_recognition;
@@ -114,7 +110,6 @@ extern SCP_string Cmdline_lang;
extern int Cmdline_load_all_weapons;
extern int Cmdline_nomovies; // WMC Toggles movie playing support
extern int Cmdline_no_set_gamma;
extern bool Cmdline_no_ingame_options;
extern int Cmdline_no_fbo;
extern int Cmdline_no_pbo;
extern int Cmdline_mipmap;
+4 -5
View File
@@ -1359,6 +1359,9 @@ bool control_config_accept(bool API_Access)
}
}
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
if (!API_Access) {
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
@@ -1627,7 +1630,7 @@ void control_config_close(bool API_Access)
Ui_window.destroy();
common_free_interface_palette(); // restore game palette
}
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
game_flush();
if (Game_mode & GM_MULTIPLAYER) {
@@ -2533,10 +2536,6 @@ void control_config_do_frame(float frametime)
if (List_buttons[i].pressed()) {
// Select the pressed line
Selected_line = i + Scroll_offset;
// Cyborg - Quick assertion for Coverity 1093701. Not likely to happen, but we check for a negative Selected Line later.
Assertion(Selected_line > -1, "control_config_do_frame() has somehow managed to get a negative Selected_line index of %d. Please get an SCP member.", Selected_line);
Selected_item = selItem::None;
List_buttons[i].get_mouse_pos(&x, &y);
+33 -35
View File
@@ -45,29 +45,27 @@ int Failed_key_index;
// Joystick configuration
int Joy_dead_zone_size = 10;
auto DeadZoneOption = options::OptionBuilder<int>("Input.JoystickDeadZone",
std::pair<const char*, int>{"Deadzone", 1377},
std::pair<const char*, int>{"The deadzone used for all joysticks", 1744})
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
auto DeadZoneOption =
options::OptionBuilder<int>("Input.JoystickDeadZone", "Deadzone", "The deadzone of the selected joystick.")
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
int Joy_sensitivity = 9;
auto SensitivityOption = options::OptionBuilder<int>("Input.JoystickSensitivity",
std::pair<const char*, int>{"Sensitivity", 1745},
std::pair<const char*, int>{"The sensitivity used for all joysticks", 1746})
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
auto SensitivityOption =
options::OptionBuilder<int>("Input.JoystickSensitivity", "Sensitivity", "The sentitivity of the selected joystick.")
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
//! arrays which hold the key mappings. The array index represents a key-independent action.
//! please use SPACES for aligning the fields of this array
@@ -160,8 +158,8 @@ void control_config_common_init_bindings() {
// flight controls (flight modes)
(BANK_WHEN_PRESSED, -1, -1, SHIP_TAB, 1, "Bank When Pressed", CC_TYPE_CONTINUOUS)
(AFTERBURNER, KEY_TAB, 5, SHIP_TAB, 1, "Afterburner", CC_TYPE_CONTINUOUS)
(GLIDE_WHEN_PRESSED, -1, -1, SHIP_TAB, 1774, "Glide When Pressed", CC_TYPE_CONTINUOUS)
(TOGGLE_GLIDING, KEY_ALTED | KEY_G, -1, SHIP_TAB, 1775, "Toggle Gliding", CC_TYPE_TRIGGER)
(GLIDE_WHEN_PRESSED, -1, -1, SHIP_TAB, 0, "Glide When Pressed", CC_TYPE_CONTINUOUS)
(TOGGLE_GLIDING, KEY_ALTED | KEY_G, -1, SHIP_TAB, 0, "Toggle Gliding", CC_TYPE_TRIGGER)
// flight controls (axes)
(JOY_HEADING_AXIS, JOY_X_AXIS, MOUSE_X_AXIS, SHIP_TAB, 1016, "Turn (Yaw) Axis", CC_TYPE_AXIS_REL)
@@ -175,7 +173,7 @@ void control_config_common_init_bindings() {
(FIRE_SECONDARY, KEY_SPACEBAR, 1, WEAPON_TAB, 1, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS)
(CYCLE_NEXT_PRIMARY, KEY_PERIOD, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_PREV_PRIMARY, KEY_COMMA, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Backward", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 1776, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 0, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_SECONDARY, KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_NUM_MISSLES, KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER)
(LAUNCH_COUNTERMEASURE, KEY_X, 3, WEAPON_TAB, 1, "Launch Countermeasure", CC_TYPE_TRIGGER)
@@ -211,8 +209,8 @@ void control_config_common_init_bindings() {
(PADLOCK_DOWN, -1, 32, COMPUTER_TAB, 1, "View Rear", CC_TYPE_CONTINUOUS)
(PADLOCK_LEFT, -1, 34, COMPUTER_TAB, 1, "View Left", CC_TYPE_CONTINUOUS)
(PADLOCK_RIGHT, -1, 35, COMPUTER_TAB, 1, "View Right", CC_TYPE_CONTINUOUS)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 1777, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 1778, "Target Padlock View", CC_TYPE_TRIGGER)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 0, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 0, "Target Padlock View", CC_TYPE_TRIGGER)
(RADAR_RANGE_CYCLE, KEY_RAPOSTRO, -1, COMPUTER_TAB, 1, "Cycle Radar Range", CC_TYPE_TRIGGER)
(SQUADMSG_MENU, KEY_C, -1, COMPUTER_TAB, 1, "Communications Menu", CC_TYPE_TRIGGER)
@@ -237,8 +235,8 @@ void control_config_common_init_bindings() {
// Navigation and Autopilot
(SHOW_NAVMAP, -1, -1, NO_TAB, 1, "Show Nav Map", CC_TYPE_TRIGGER, true)
(AUTO_PILOT_TOGGLE, KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 1779, "Toggle Auto Pilot", CC_TYPE_TRIGGER)
(NAV_CYCLE, KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 1780, "Cycle Nav Points", CC_TYPE_TRIGGER)
(AUTO_PILOT_TOGGLE, KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 0, "Toggle Auto Pilot", CC_TYPE_TRIGGER)
(NAV_CYCLE, KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 0, "Cycle Nav Points", CC_TYPE_TRIGGER)
// Escort
(ADD_REMOVE_ESCORT, KEY_ALTED | KEY_E, -1, COMPUTER_TAB, 1, "Add or Remove Escort", CC_TYPE_TRIGGER)
@@ -260,15 +258,15 @@ void control_config_common_init_bindings() {
// HUD
(TOGGLE_HUD, KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, 1, "Toggle HUD", CC_TYPE_TRIGGER)
(TOGGLE_HUD_CONTRAST, KEY_L, -1, COMPUTER_TAB, 1, "Toggle High HUD Contrast", CC_TYPE_TRIGGER)
(TOGGLE_HUD_SHADOWS, KEY_ALTED | KEY_L, -1, COMPUTER_TAB, 1781, "Toggle HUD Drop Shadows", CC_TYPE_TRIGGER)
(TOGGLE_HUD_SHADOWS, KEY_ALTED | KEY_L, -1, COMPUTER_TAB, 0, "Toggle HUD Drop Shadows", CC_TYPE_TRIGGER)
(HUD_TARGETBOX_TOGGLE_WIREFRAME, KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, 1, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER)
// Custom Controls
(CUSTOM_CONTROL_1, KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 1784, "Custom Control 1", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_2, KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 1785, "Custom Control 2", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_3, KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 1786, "Custom Control 3", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_4, KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 1787, "Custom Control 4", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_5, KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 1788, "Custom Control 5", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_1, KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 0, "Custom Control 1", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_2, KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 0, "Custom Control 2", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_3, KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 0, "Custom Control 3", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_4, KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 0, "Custom Control 4", CC_TYPE_TRIGGER, true)
(CUSTOM_CONTROL_5, KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 0, "Custom Control 5", CC_TYPE_TRIGGER, true)
.end(); // Builder
// init default preset
@@ -451,7 +449,7 @@ const char* Joy_button_text_french_u[] = {
"Bouton 13", "Bouton 14", "Bouton 15", "Bouton 16", "Bouton 17", "Bouton 18",
"Bouton 19", "Bouton 20", "Bouton 21", "Bouton 22", "Bouton 23", "Bouton 24",
"Bouton 25", "Bouton 26", "Bouton 27", "Bouton 28", "Bouton 29", "Bouton 30",
"Bouton 31", "Bouton 32", ("Chapeau Arri\xc3\xa8""re"), "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
"Bouton 31", "Bouton 32", "Chapeau Arri\xc3\xa8""re", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
};
const char* Joy_button_text_polish_u[] = {
@@ -460,7 +458,7 @@ const char* Joy_button_text_polish_u[] = {
"Przyc.13", "Przyc.14", "Przyc.15", "Przyc.16", "Przyc.17", "Przyc.18",
"Przyc.19", "Przyc.20", "Przyc.21", "Przyc.22", "Przyc.23", "Przyc.24",
"Przyc.25", "Przyc.26", "Przyc.27", "Przyc.28", "Przyc.29", "Przyc.30",
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", ("Hat Prz\xc3\xb3""d"), "Hat Lewo", "Hat Prawo"
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", "Hat Prz\xc3\xb3""d", "Hat Lewo", "Hat Prawo"
};
const char* Joy_button_text_english_u[] = {
+1 -2
View File
@@ -52,7 +52,6 @@ struct MovieProperties {
FrameSize size;
float fps = -1.0f;
float duration = 0.0f;
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
};
@@ -109,7 +108,7 @@ class Decoder {
* @note A implementation should initialize the datastructures required for decoding here.
*
* @param fileName The name of the file that should be opened
* @return @c true if the initialization was successful, @c false otherwise
* @return @c true if the initialization was successfull, @c false otherwise
*/
virtual bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) = 0;
+2
View File
@@ -222,6 +222,7 @@ void cutscene_mark_viewable(const char* filename)
// change to lower case
strlwr(file);
int i = 0;
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
{
// change the cutscene file name to lower case
@@ -234,6 +235,7 @@ void cutscene_mark_viewable(const char* filename)
cut->flags.set(Cutscene::Cutscene_Flags::Viewable);
return;
}
i++;
}
Warning(LOCATION, "Could not find cutscene '%s' in listing; cannot mark it viewable...", filename);
-1
View File
@@ -503,7 +503,6 @@ MovieProperties FFMPEGDecoder::getProperties() const
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
props.duration = static_cast<float>(m_status->videoStream->duration * av_q2d(m_status->videoStream->time_base));
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
+8 -7
View File
@@ -926,9 +926,10 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
// copy important data
int orig_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
vec3d orig_p0 = *mc.p0;
vec3d orig_p1 = *mc.p1;
int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
vec3d copy_p0, copy_p1;
copy_p0 = *mc.p0;
copy_p1 = *mc.p1;
// first test against the sphere - if this fails then don't do any submodel tests
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
@@ -954,7 +955,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
}
// Only check single submodel now, since children of moving submodels are handled as moving as well
mc.flags = orig_flags | MC_SUBMODEL;
mc.flags = copy_flags | MC_SUBMODEL;
if (Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod > -1) {
mc.lod = Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod;
@@ -1004,9 +1005,9 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
}
// Now complete base model collision checks that do not take into account rotating submodels.
mc.flags = orig_flags;
mc.p0 = &orig_p0;
mc.p1 = &orig_p1;
mc.flags = copy_flags;
*mc.p0 = copy_p0;
*mc.p1 = copy_p1;
mc.orient = &heavy_obj->orient;
// usual ship_ship collision test
+1 -1
View File
@@ -119,7 +119,7 @@
* half-rate linear filtering on GCN.
*
* If SMAA is applied to 64-bit color buffers, switching to point filtering
* when accessing them will increase the performance. Search for
* when accesing them will increase the performance. Search for
* 'SMAASamplePoint' to see which textures may benefit from point
* filtering, and where (which is basically the color input in the edge
* detection and resolve passes).
-8
View File
@@ -1,17 +1,9 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
#ifdef COPY_ARRAY
uniform sampler2DArray tex;
#else
uniform sampler2D tex;
#endif
void main()
{
#ifdef COPY_ARRAY
fragOut0 = texture(tex, vec3(fragTexCoord.xy, 0));
#else
fragOut0 = texture(tex, fragTexCoord.xy);
#endif
}
+3 -5
View File
@@ -24,8 +24,6 @@ layout (std140) uniform globalDeferredData {
float invScreenWidth;
float invScreenHeight;
float nearPlane;
};
layout (std140) uniform matrixData {
@@ -81,7 +79,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
lightDirOut = lightPosition - position.xyz;
float dist = length(lightDirOut);
// this chunk is unnecessary if sourceRadius= 0.0, but let's avoid a branch.
// this chunk is unneccessary if sourceRadius= 0.0, but let's avoid a branch.
// given a sphere of radius sourceRadius centered at lightDirOut,
// move lightDirOut towards the ray defined by reflectDir
lightDirOut = ExpandLightSize(lightDirOut, reflectDir);
@@ -124,7 +122,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
// should figure out how to optimise these calcs - qaz
// this chunk is unnecessary if sourceRadius = 0.0, but let's avoid a branch.
// this chunk is unneccessary if sourceRadius = 0.0, but let's avoid a branch.
// Same principle as in LT_POINT, treat chosen location as a spherelight.
lightDirOut = ExpandLightSize(lightDirOut, reflectDir);
float dist = length(lightDirOut);
@@ -170,7 +168,7 @@ void main()
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
vec3 position = texture(PositionBuffer, screenPos).xyz;
if(abs(dot(position, position)) < nearPlane * nearPlane)
if(abs(dot(position, position)) < 0.1)
discard;
vec3 diffColor = texture(ColorBuffer, screenPos).rgb;
+1 -1
View File
@@ -11,7 +11,7 @@ in vec4 fragTexCoord;
out vec4 fragOut0;
// Iteratively optimised points to give low discrepancy distribution on arbitrary hemisphere.
// Iteratively optimised points to give low discrepancy distribution on arbritrary hemisphere.
const vec3 points[128] = vec3[128](
vec3(-0.2268, 0.6185, 0.7523),
vec3( 0.9958, -0.0871, -0.0277),
+2 -2
View File
@@ -33,7 +33,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
// NOTE - we're intentionally using UE4's reflectance model as modellers are using tools designed for common engines.
// Cook-Torrance BRDF Model (Specular Reflection) = Distribution * Fresnel * Geometry / (4*dotNV*dotNL)
// Cook-Torrance BRDF Model (Specular Reflection) = Distibution * Fresnel * Geometry / (4*dotNV*dotNL)
// Distribution Term - Trowbridge-Reitz GGX
@@ -49,7 +49,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
// Smith's method:
// Microsurfaces block light rays coming in from the light
// AND block light rays reflecting to the camera.
// Hence, model both separately and multiply.
// Hence, model both seperately and multiply.
float g1vNL = GeometrySchlickGGX(dotNL, k);
float g1vNV = GeometrySchlickGGX(dotNV, k);
float geometry = g1vNL * g1vNV;
-8
View File
@@ -263,9 +263,6 @@ void main()
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
specColor *= alphaMult;
}
if(alphaGloss) glossData = specColor.a;
if(gammaSpec) {
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
@@ -400,11 +397,6 @@ void main()
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
//Since this is emissive, we need to premultiply it for intensity, and apply alpha to not replace existing emissive
emissiveColor *= alphaMult;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
vec3 finalFogColor = fogColor.rgb;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
@@ -37,6 +37,7 @@ vec3 Uncharted2ToneMapping(vec3 hdr_color) // John Hable's filmic
hdr_color = ((hdr_color * (A * hdr_color + C * B) + D * E) / (hdr_color * (A * hdr_color + B) + D * F)) - E / F;
float white = ((W * (A * W + C * B) + D * E) / (W * (A * W + B) + D * F)) - E / F;
hdr_color /= white;
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
return hdr_color;
}
@@ -64,6 +65,7 @@ vec3 aces(vec3 hdr_color)
hdr_color = aces_input * hdr_color;
hdr_color = rtt_and_odt_fit(hdr_color);
hdr_color = aces_output * hdr_color;
hdr_color = linear_to_srgb(hdr_color);
return hdr_color;
}
@@ -77,6 +79,7 @@ vec3 aces_approx(vec3 hdr_color) // also filmic, higher contrast then Uncharted2
hdr_color *= 0.6f;
hdr_color = clamp((hdr_color*(a*hdr_color+b))/(hdr_color*(c*hdr_color+d)+e), 0.0f, 1.0f);
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
return hdr_color;
}
@@ -93,6 +96,7 @@ vec3 rhj_lumaToneMapping(vec3 hdr_color) // reinhard_jodie
float luma = dot(hdr_color, vec3(0.2126, 0.7152, 0.0722)); //dot products are a bit more expensive
float toneMappedLuma = luma / (1.0 + luma);
hdr_color *= toneMappedLuma / luma;
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
return hdr_color;
}
@@ -101,12 +105,14 @@ vec3 reinhard_extended(vec3 hdr_color)
float max_white = 1.0;
vec3 numerator = hdr_color * (1.0f + (hdr_color / vec3(max_white * max_white)));
hdr_color = numerator / (1.0f + hdr_color);
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
return hdr_color;
}
vec3 linearToneMapping(vec3 hdr_color)
{
hdr_color = clamp(hdr_color, 0., 1.);
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
return hdr_color;
}
@@ -149,7 +155,7 @@ vec3 PPC_RGB( vec3 color ) {
funswitch(color.g),
funswitch(color.b));
return color;
return linear_to_srgb(color);
}
@@ -168,7 +174,7 @@ vec3 PPC( vec3 color ) {
else {
luma_tone = sh_offsetY;
}
return color * luma_tone / luma;
return linear_to_srgb(color * luma_tone / luma);
}
@@ -207,9 +213,5 @@ void main()
break;
}
#ifdef LINEAR_OUT
fragOut0 = vec4(color.rgb, 1.0);
#else
fragOut0 = vec4(linear_to_srgb(color.rgb), 1.0);
#endif
}
-714
View File
@@ -1,714 +0,0 @@
-- Module options:
local always_try_using_lpeg = true
local register_global_module_table = false
local global_module_name = 'json'
--[==[
David Kolf's JSON module for Lua 5.1/5.2
Version 2.5
For the documentation see the corresponding readme.txt or visit
<http://dkolf.de/src/dkjson-lua.fsl/>.
You can contact the author by sending an e-mail to 'david' at the
domain 'dkolf.de'.
Copyright (C) 2010-2014 David Heiko Kolf
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
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 OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]==]
-- global dependencies:
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
local error, require, pcall, select = error, require, pcall, select
local floor, huge = math.floor, math.huge
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
string.rep, string.gsub, string.sub, string.byte, string.char,
string.find, string.len, string.format
local strmatch = string.match
local concat = table.concat
local json = { version = "dkjson 2.5" }
if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.
-- Don't worry, this module doesn't change anything in them.
local debmeta = require "debug".getmetatable
if debmeta then getmetatable = debmeta end
end)
json.null = setmetatable ({}, {
__tojson = function () return "null" end
})
local function isarray (tbl)
local max, n, arraylen = 0, 0, 0
for k,v in pairs (tbl) do
if k == 'n' and type(v) == 'number' then
arraylen = v
if v > max then
max = v
end
else
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
return false
end
if k > max then
max = k
end
n = n + 1
end
end
if max > 10 and max > arraylen and max > n * 2 then
return false -- don't create an array with too many holes
end
return true, max
end
local escapecodes = {
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
}
local function escapeutf8 (uchar)
local value = escapecodes[uchar]
if value then
return value
end
local a, b, c, d = strbyte (uchar, 1, 4)
a, b, c, d = a or 0, b or 0, c or 0, d or 0
if a <= 0x7f then
value = a
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
value = (a - 0xc0) * 0x40 + b - 0x80
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
else
return ""
end
if value <= 0xffff then
return strformat ("\\u%.4x", value)
elseif value <= 0x10ffff then
-- encode as UTF-16 surrogate pair
value = value - 0x10000
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
else
return ""
end
end
local function fsub (str, pattern, repl)
-- gsub always builds a new string in a buffer, even when no match
-- exists. First using find should be more efficient when most strings
-- don't contain the pattern.
if strfind (str, pattern) then
return gsub (str, pattern, repl)
else
return str
end
end
local function quotestring (value)
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
if strfind (value, "[\194\216\220\225\226\239]") then
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
value = fsub (value, "\216[\128-\132]", escapeutf8)
value = fsub (value, "\220\143", escapeutf8)
value = fsub (value, "\225\158[\180\181]", escapeutf8)
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
value = fsub (value, "\239\187\191", escapeutf8)
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
end
return "\"" .. value .. "\""
end
json.quotestring = quotestring
local function replace(str, o, n)
local i, j = strfind (str, o, 1, true)
if i then
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
else
return str
end
end
-- locale independent num2str and str2num functions
local decpoint, numfilter
local function updatedecpoint ()
decpoint = strmatch(tostring(0.5), "([^05+])")
-- build a filter that can be used to remove group separators
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
end
updatedecpoint()
local function num2str (num)
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
end
local function str2num (str)
local num = tonumber(replace(str, ".", decpoint))
if not num then
updatedecpoint()
num = tonumber(replace(str, ".", decpoint))
end
return num
end
local function addnewline2 (level, buffer, buflen)
buffer[buflen+1] = "\n"
buffer[buflen+2] = strrep (" ", level)
buflen = buflen + 2
return buflen
end
function json.addnewline (state)
if state.indent then
state.bufferlen = addnewline2 (state.level or 0,
state.buffer, state.bufferlen or #(state.buffer))
end
end
local encode2 -- forward declaration
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
local kt = type (key)
if kt ~= 'string' and kt ~= 'number' then
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
end
if prev then
buflen = buflen + 1
buffer[buflen] = ","
end
if indent then
buflen = addnewline2 (level, buffer, buflen)
end
buffer[buflen+1] = quotestring (key)
buffer[buflen+2] = ":"
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
end
local function appendcustom(res, buffer, state)
local buflen = state.bufferlen
if type (res) == 'string' then
buflen = buflen + 1
buffer[buflen] = res
end
return buflen
end
local function exception(reason, value, state, buffer, buflen, defaultmessage)
defaultmessage = defaultmessage or reason
local handler = state.exception
if not handler then
return nil, defaultmessage
else
state.bufferlen = buflen
local ret, msg = handler (reason, value, state, defaultmessage)
if not ret then return nil, msg or defaultmessage end
return appendcustom(ret, buffer, state)
end
end
function json.encodeexception(reason, value, state, defaultmessage)
return quotestring("<" .. defaultmessage .. ">")
end
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
local valtype = type (value)
local valmeta = getmetatable (value)
valmeta = type (valmeta) == 'table' and valmeta -- only tables
local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
state.bufferlen = buflen
local ret, msg = valtojson (value, state)
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
tables[value] = nil
buflen = appendcustom(ret, buffer, state)
elseif value == nil then
buflen = buflen + 1
buffer[buflen] = "null"
elseif valtype == 'number' then
local s
if value ~= value or value >= huge or -value >= huge then
-- This is the behaviour of the original JSON implementation.
s = "null"
else
s = num2str (value)
end
buflen = buflen + 1
buffer[buflen] = s
elseif valtype == 'boolean' then
buflen = buflen + 1
buffer[buflen] = value and "true" or "false"
elseif valtype == 'string' then
buflen = buflen + 1
buffer[buflen] = quotestring (value)
elseif valtype == 'table' then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
level = level + 1
local isa, n = isarray (value)
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
isa = false
end
local msg
if isa then -- JSON array
buflen = buflen + 1
buffer[buflen] = "["
for i = 1, n do
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
if i < n then
buflen = buflen + 1
buffer[buflen] = ","
end
end
buflen = buflen + 1
buffer[buflen] = "]"
else -- JSON object
local prev = false
buflen = buflen + 1
buffer[buflen] = "{"
local order = valmeta and valmeta.__jsonorder or globalorder
if order then
local used = {}
n = #order
for i = 1, n do
local k = order[i]
local v = value[k]
if v then
used[k] = true
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
prev = true -- add a seperator before the next element
end
end
for k,v in pairs (value) do
if not used[k] then
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
else -- unordered
for k,v in pairs (value) do
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
if indent then
buflen = addnewline2 (level - 1, buffer, buflen)
end
buflen = buflen + 1
buffer[buflen] = "}"
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end
function json.encode (value, state)
state = state or {}
local oldbuffer = state.buffer
local buffer = oldbuffer or {}
state.buffer = buffer
updatedecpoint()
local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if not ret then
error (msg, 2)
elseif oldbuffer == buffer then
state.bufferlen = ret
return true
else
state.bufferlen = nil
state.buffer = nil
return concat (buffer)
end
end
local function loc (str, where)
local line, pos, linepos = 1, 1, 0
while true do
pos = strfind (str, "\n", pos, true)
if pos and pos < where then
line = line + 1
linepos = pos
pos = pos + 1
else
break
end
end
return "line " .. line .. ", column " .. (where - linepos)
end
local function unterminated (str, what, where)
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
end
local function scanwhite (str, pos)
while true do
pos = strfind (str, "%S", pos)
if not pos then return nil end
local sub2 = strsub (str, pos, pos + 1)
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
-- UTF-8 Byte Order Mark
pos = pos + 3
elseif sub2 == "//" then
pos = strfind (str, "[\n\r]", pos + 2)
if not pos then return nil end
elseif sub2 == "/*" then
pos = strfind (str, "*/", pos + 2)
if not pos then return nil end
pos = pos + 2
else
return pos
end
end
end
local escapechars = {
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
}
local function unichar (value)
if value < 0 then
return nil
elseif value <= 0x007f then
return strchar (value)
elseif value <= 0x07ff then
return strchar (0xc0 + floor(value/0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return strchar (0xe0 + floor(value/0x1000),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return strchar (0xf0 + floor(value/0x40000),
0x80 + (floor(value/0x1000) % 0x40),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function scanstring (str, pos)
local lastpos = pos + 1
local buffer, n = {}, 0
while true do
local nextpos = strfind (str, "[\"\\]", lastpos)
if not nextpos then
return unterminated (str, "string", pos)
end
if nextpos > lastpos then
n = n + 1
buffer[n] = strsub (str, lastpos, nextpos - 1)
end
if strsub (str, nextpos, nextpos) == "\"" then
lastpos = nextpos + 1
break
else
local escchar = strsub (str, nextpos + 1, nextpos + 1)
local value
if escchar == "u" then
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
if value then
local value2
if 0xD800 <= value and value <= 0xDBff then
-- we have the high surrogate of UTF-16. Check if there is a
-- low surrogate escaped nearby to combine them.
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
else
value2 = nil -- in case it was out of range for a low surrogate
end
end
end
value = value and unichar (value)
if value then
if value2 then
lastpos = nextpos + 12
else
lastpos = nextpos + 6
end
end
end
end
if not value then
value = escapechars[escchar] or escchar
lastpos = nextpos + 2
end
n = n + 1
buffer[n] = value
end
end
if n == 1 then
return buffer[1], lastpos
elseif n > 1 then
return concat (buffer), lastpos
else
return "", lastpos
end
end
local scanvalue -- forward declaration
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
local len = strlen (str)
local tbl, n = {}, 0
local pos = startpos + 1
if what == 'object' then
setmetatable (tbl, objectmeta)
else
setmetatable (tbl, arraymeta)
end
while true do
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
local char = strsub (str, pos, pos)
if char == closechar then
return tbl, pos + 1
end
local val1, err
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
if char == ":" then
if val1 == nil then
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
end
pos = scanwhite (str, pos + 1)
if not pos then return unterminated (str, what, startpos) end
local val2
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
tbl[val1] = val2
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
else
n = n + 1
tbl[n] = val1
end
if char == "," then
pos = pos + 1
end
end
end
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
pos = pos or 1
pos = scanwhite (str, pos)
if not pos then
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
end
local char = strsub (str, pos, pos)
if char == "{" then
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
elseif char == "[" then
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
elseif char == "\"" then
return scanstring (str, pos)
else
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
if pstart then
local number = str2num (strsub (str, pstart, pend))
if number then
return number, pend + 1
end
end
pstart, pend = strfind (str, "^%a%w*", pos)
if pstart then
local name = strsub (str, pstart, pend)
if name == "true" then
return true, pend + 1
elseif name == "false" then
return false, pend + 1
elseif name == "null" then
return nullval, pend + 1
end
end
return nil, pos, "no valid JSON value at " .. loc (str, pos)
end
end
local function optionalmetatables(...)
if select("#", ...) > 0 then
return ...
else
return {__jsontype = 'object'}, {__jsontype = 'array'}
end
end
function json.decode (str, pos, nullval, ...)
local objectmeta, arraymeta = optionalmetatables(...)
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
end
function json.use_lpeg ()
local g = require ("lpeg")
if g.version() == "0.11" then
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
end
local pegmatch = g.match
local P, S, R = g.P, g.S, g.R
local function ErrorCall (str, pos, msg, state)
if not state.msg then
state.msg = msg .. " at " .. loc (str, pos)
state.pos = pos
end
return false
end
local function Err (msg)
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
end
local SingleLineComment = P"//" * (1 - S"\n\r")^0
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
local PlainChar = 1 - S"\"\\\n\r"
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
local HexDigit = R("09", "af", "AF")
local function UTF16Surrogate (match, pos, high, low)
high, low = tonumber (high, 16), tonumber (low, 16)
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
else
return false
end
end
local function UTF16BMP (hex)
return unichar (tonumber (hex, 16))
end
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
local Char = UnicodeEscape + EscapeSequence + PlainChar
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
local Fractal = P"." * R"09"^0
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
local SimpleValue = Number + String + Constant
local ArrayContent, ObjectContent
-- The functions parsearray and parseobject parse only a single value/pair
-- at a time and store them directly to avoid hitting the LPeg limits.
local function parsearray (str, pos, nullval, state)
local obj, cont
local npos
local t, nt = {}, 0
repeat
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
if not npos then break end
pos = npos
nt = nt + 1
t[nt] = obj
until cont == 'last'
return pos, setmetatable (t, state.arraymeta)
end
local function parseobject (str, pos, nullval, state)
local obj, key, cont
local npos
local t = {}
repeat
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
if not npos then break end
pos = npos
t[key] = obj
until cont == 'last'
return pos, setmetatable (t, state.objectmeta)
end
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
local Value = Space * (Array + Object + SimpleValue)
local ExpectedValue = Value + Space * Err "value expected"
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local DecodeValue = ExpectedValue * g.Cp ()
function json.decode (str, pos, nullval, ...)
local state = {}
state.objectmeta, state.arraymeta = optionalmetatables(...)
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
if state.msg then
return nil, state.pos, state.msg
else
return obj, retpos
end
end
-- use this function only once:
json.use_lpeg = function () return json end
json.using_lpeg = true
return json -- so you can get the module using json = require "dkjson".use_lpeg()
end
if always_try_using_lpeg then
pcall (json.use_lpeg)
end
return json
+23 -48
View File
@@ -1,5 +1,5 @@
#Ship types
#Ship types
$Name: Navbuoy
$Max Debris Speed: 200
$FF Multiplier: 1.0
@@ -11,8 +11,7 @@ $AI:
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Sentry Gun
$Counts for Alone: YES
$On Hotkey List: YES
@@ -32,8 +31,7 @@ $AI:
+Guards attack this: YES
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Escape Pod
$Praise Destruction: YES
$On Hotkey List: YES
@@ -51,8 +49,7 @@ $AI:
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Cargo
$Scannable: YES
$Max Debris Speed: 200
@@ -65,8 +62,7 @@ $Fog:
+Compl dist: 500.0
$AI:
+Passive docks: ( "cargo" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Support
$Counts for Alone: YES
$Praise Destruction: YES
@@ -92,8 +88,7 @@ $AI:
+Turrets attack this: YES
+Active docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
;;WMC - Stealth ships always have another type, so this isn't used
$Name: Stealth
$Counts for Alone: YES
@@ -118,8 +113,7 @@ $AI:
+Turrets attack this: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Fighter
$Counts for Alone: YES
$Praise Destruction: YES
@@ -146,8 +140,7 @@ $AI:
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Bomber
$Counts for Alone: YES
$Praise Destruction: YES
@@ -174,9 +167,8 @@ $AI:
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
$Vaporize Percent Chance: 0.0
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
$Name: Fighter/bomber
$Counts for Alone: YES
$Praise Destruction: YES
@@ -202,8 +194,7 @@ $AI:
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Transport
$Counts for Alone: YES
$Praise Destruction: YES
@@ -213,7 +204,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 2.0
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -232,8 +222,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Freighter
$Counts for Alone: YES
$Praise Destruction: YES
@@ -244,7 +233,6 @@ $Scannable: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 1.75
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -264,8 +252,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: AWACS
$Counts for Alone: YES
$Praise Destruction: YES
@@ -275,7 +262,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.8
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -294,8 +280,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Gas Miner
$Counts for Alone: YES
$Praise Destruction: YES
@@ -305,7 +290,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 1.0
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -324,8 +308,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Cruiser
$Counts for Alone: YES
$Praise Destruction: YES
@@ -335,7 +318,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.9
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -354,8 +336,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Corvette
$Counts for Alone: YES
$Praise Destruction: YES
@@ -365,7 +346,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.3333
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -384,8 +364,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Capital
$Counts for Alone: YES
$Praise Destruction: YES
@@ -414,8 +393,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Super Cap
$Counts for Alone: YES
$Praise Destruction: YES
@@ -442,8 +420,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Drydock
$Counts for Alone: YES
$Praise Destruction: YES
@@ -468,8 +445,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
$Vaporize Percent Chance: 0.0
$Name: Knossos Device
$Counts for Alone: YES
$Praise Destruction: YES
@@ -492,6 +468,5 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
#End
$Vaporize Percent Chance: 0.0
#End
+1 -1
View File
@@ -311,7 +311,7 @@ static char* GetFilePart(char *source)
SCP_string safe_string;
// Entry point into the main exception handling routine. This routine is put into an except()
// statement at the beginning of a thread and is called anytime that there is a program exception
// statment at the beginning of a thread and is called anytime that there is a program exception
// The data is stored in a file called ErrorLog.txt in the data directory.
//
// data: pointer to the exception data
+27 -34
View File
@@ -48,51 +48,44 @@ bool fireballs_parsed = false;
bool Fireball_use_3d_warp = false;
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp",
std::pair<const char*, int>{"3D Warp", 1770},
std::pair<const char*, int>{"Use a 3D model for warp effects", 1771})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp", "3D Warp", "Use a 3D model for warp effects")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
/**
* Play warp in sound for warp effect
*/
void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
{
gamesnd_id sound_index;
float range_multiplier = 1.0f;
object *fireball_objp;
Assert((fb != NULL) && (fb->objnum >= 0));
if((fb == NULL) || (fb->objnum < 0)){
return;
}
auto fireball_objp = &Objects[fb->objnum];
auto sound_index = gamesnd_id(GameSounds::WARP_IN);
fireball_objp = &Objects[fb->objnum];
if (fb->warp_open_sound_index.isValid()) {
sound_index = gamesnd_id(GameSounds::WARP_IN);
if(fb->warp_open_sound_index.isValid()) {
sound_index = fb->warp_open_sound_index;
} else if ((ship_class >= 0) && (ship_class < ship_info_size())) {
if ( Ship_info[ship_class].is_huge_ship() ) {
sound_index = gamesnd_id(GameSounds::CAPITAL_WARP_IN);
}
}
if (ship_class >= 0 && ship_class < ship_info_size()) {
if (Ship_info[ship_class].is_huge_ship()) {
fb->flags |= FBF_WARP_CAPITAL_SIZE;
} else if (Ship_info[ship_class].is_big_ship()) {
} else if ( Ship_info[ship_class].is_big_ship() ) {
range_multiplier = 6.0f;
fb->flags |= FBF_WARP_CRUISER_SIZE;
}
// originally 6.0 for SIF_BIG_SHIP and 1.0 for everything else
if (Ship_info[ship_class].class_type >= 0)
fb->warp_sound_range_multiplier = Ship_types[Ship_info[ship_class].class_type].warp_sound_range_multiplier;
else
fb->warp_sound_range_multiplier = 1.0f;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, fb->warp_sound_range_multiplier); // play warp sound effect
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
}
/**
@@ -100,14 +93,15 @@ void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
*/
void fireball_play_warphole_close_sound(fireball *fb)
{
Assert((fb != NULL) && (fb->objnum >= 0));
if((fb == NULL) || (fb->objnum < 0)){
return;
}
auto fireball_objp = &Objects[fb->objnum];
auto sound_index = gamesnd_id(GameSounds::WARP_OUT);
gamesnd_id sound_index;
if (fb->warp_close_sound_index.isValid()) {
object *fireball_objp;
fireball_objp = &Objects[fb->objnum];
sound_index = gamesnd_id(GameSounds::WARP_OUT);
if ( fb->warp_close_sound_index.isValid() ) {
sound_index = fb->warp_close_sound_index;
} else if ( fb->flags & FBF_WARP_CAPITAL_SIZE ) {
sound_index = gamesnd_id(GameSounds::CAPITAL_WARP_OUT);
@@ -115,7 +109,7 @@ void fireball_play_warphole_close_sound(fireball *fb)
return;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0F, SND_PRIORITY_SINGLE_INSTANCE, NULL, fb->warp_sound_range_multiplier); // play warp sound effect
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
}
static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index)
@@ -851,7 +845,6 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
new_fireball->warp_close_sound_index = warp_close_sound;
new_fireball->warp_open_duration = (warp_open_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_open_duration;
new_fireball->warp_close_duration = (warp_close_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_close_duration;
new_fireball->warp_sound_range_multiplier = 1.0f;
matrix orient;
if(orient_override != NULL){
-3
View File
@@ -92,9 +92,6 @@ typedef struct fireball {
gamesnd_id warp_close_sound_index;
float warp_open_duration;
float warp_close_duration;
// the sound multiplier is based on the ship class, but we lose that while the warp is closing
float warp_sound_range_multiplier;
} fireball;
// end move
+7 -9
View File
@@ -24,15 +24,13 @@
bool Fireball_warp_flash = false;
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash",
std::pair<const char*, int>{"Warp Flash", 1768},
std::pair<const char*, int>{"Show flash upon warp open or close", 1769})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash", "Warp Flash", "Show flash upon warp open or close")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
{
-3
View File
@@ -16,7 +16,6 @@
#include "gamesnd/gamesnd.h"
#include "globalincs/alphacolors.h"
#include "io/key.h"
#include "mission/missionmessage.h"
#include "missionui/missionscreencommon.h"
#include "sound/audiostr.h"
#include "ui/ui.h"
@@ -517,7 +516,6 @@ void gameplay_help_leave()
// unpause all game sounds
weapon_unpause_sounds();
audiostream_unpause_all();
message_resume_all();
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
game_flush();
@@ -633,7 +631,6 @@ void gameplay_help_do_frame(float /*frametime*/)
// make sure game sounds are paused
weapon_pause_sounds();
audiostream_pause_all();
message_pause_all();
k = Ui_window.process() & ~KEY_DEBUGGED;
gameplay_help_process_key(k);
+2 -4
View File
@@ -113,8 +113,7 @@ const char *GS_event_text[] =
"GS_EVENT_LAB",
"GS_EVENT_PXO_HELP",
"GS_EVENT_FICTION_VIEWER", // 65
"GS_EVENT_SCRIPTING",
"GS_EVENT_SCRIPTING_MISSION"
"GS_EVENT_SCRIPTING"
};
//XSTR:ON
@@ -177,8 +176,7 @@ const char *GS_state_text[] =
"GS_STATE_PXO_HELP", // 50
"GS_STATE_START_GAME",
"GS_STATE_FICTION_VIEWER",
"GS_STATE_SCRIPTING",
"GS_STATE_SCRIPTING_MISSION"
"GS_STATE_SCRIPTING"
};
//XSTR:ON
-2
View File
@@ -89,7 +89,6 @@ enum GS_EVENT {
GS_EVENT_PXO_HELP,
GS_EVENT_FICTION_VIEWER,
GS_EVENT_SCRIPTING,
GS_EVENT_SCRIPTING_MISSION,
GS_NUM_EVENTS // Last one++
};
@@ -160,7 +159,6 @@ enum GS_STATE {
GS_STATE_START_GAME,
GS_STATE_FICTION_VIEWER,
GS_STATE_SCRIPTING,
GS_STATE_SCRIPTING_MISSION,
GS_NUM_STATES // Last one++
};
+12 -16
View File
@@ -45,15 +45,13 @@ static bool music_volume_change_listener(float new_val, bool /*initial*/)
return true;
}
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music",
std::pair<const char*, int>{"Music", 1371},
std::pair<const char*, int>{"Volume used for playing music", 1760})
.category("Audio")
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.finish();
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music", "Music", "Volume used for playing music")
.category("Audio")
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.finish();
typedef struct tagSNDPATTERN {
int default_next_pattern; // Needed so the next_pattern member can be reset
@@ -340,7 +338,7 @@ void event_music_init()
Warning(LOCATION, "Soundtrack file %s was not found with its specified extension, but another file %s exists in the modpack. Please update the extension and adjust audio specifications if necessary.", filename, res.name_ext.c_str());
#endif
Warning(LOCATION, "Soundtrack file %s was not found. The soundtrack '%s' will not be used.", filename, soundtrack.name);
Warning(LOCATION, "One or more files in '%s' could not be loaded. The soundtrack will not be used.", soundtrack.name);
all_patterns_valid = false;
break;
}
@@ -970,13 +968,11 @@ int event_music_friendly_arrival()
// overlay
if (Soundtracks[Current_soundtrack_num].flags & EMF_ALLIED_ARRIVAL_OVERLAY)
{
// Goober5000 - This is how retail did it. For some reason, FS2 only has one
// Goober5000 - I didn't touch this part... for some reason, FS2 only has one
// arrival music pattern, and this is it
if (Patterns[SONG_AARV_1].handle >= 0)
{
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure));
}
Assert(Patterns[SONG_AARV_1].handle >= 0 );
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure) );
}
// don't overlay
else
+2 -2
View File
@@ -191,8 +191,8 @@ class flagset {
return *this;
}
bool any_set() const { return values.any(); }
bool none_set() const { return values.none(); }
bool any_set() { return values.any(); }
bool none_set() { return values.none(); }
void from_u64(std::uint64_t num) { values = (unsigned long) num; }
+1 -1
View File
@@ -288,7 +288,7 @@ constexpr bool LoggingEnabled = false;
// Disabling this functionality is dangerous, crazy values can run rampant unchecked, and the longer it's disabled
// the more likely you are to have problems getting it working again.
#if defined(NDEBUG)
# define Assert(expr) do { ASSUME(expr); (void)sizeof(expr); } while (false)
# define Assert(expr) do { ASSUME(expr); } while (false)
#else
# define Assert(expr) do {\
if (!(expr)) {\
+49 -74
View File
@@ -12,6 +12,7 @@
#include "debugconsole/console.h"
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "io/timer.h"
#include "nebula/neb.h"
#include "options/Option.h"
@@ -33,6 +34,12 @@ float Cutscene_delta_time = 1.0f;
//How far along a change is (0 to 1)
float Cutscene_bars_progress = 1.0f;
//FADEIN STUFF
shader Viewer_shader;
FadeType Fade_type = FI_NONE;
int Fade_start_timestamp = 0;
int Fade_end_timestamp = 0;
// The detail level. Anything below zero draws simple models earlier than it
// should. Anything above zero draws higher detail models longer than it should.
// -2=lowest
@@ -238,89 +245,57 @@ detail_levels Detail_defaults[NUM_DEFAULT_DETAIL_LEVELS] = {
// Global used to access detail levels in game and libs
detail_levels Detail = Detail_defaults[NUM_DEFAULT_DETAIL_LEVELS - 1];
const SCP_vector<std::pair<int, std::pair<const char*, int>>> DetailLevelValues = {{ 0, {"Minimum", 1680}},
{ 1, {"Low", 1161}},
{ 2, {"Medium", 1162}},
{ 3, {"High", 1163}},
{ 4, {"Ultra", 1721}}};
const SCP_vector<std::pair<int, SCP_string>> DetailLevelValues = {{ 0, "Minimum" },
{ 1, "Low" },
{ 2, "Medium" },
{ 3, "High" },
{ 4, "Ultra" }, };
const auto ModelDetailOption __UNUSED = options::OptionBuilder<int>("Graphics.Detail",
std::pair<const char*, int>{"Model Detail", 1739},
std::pair<const char*, int>{"Detail level of models", 1740})
.importance(8)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.detail_distance = val;
return true;
})
.finish();
const auto ModelDetailOption __UNUSED =
options::OptionBuilder<int>("Graphics.Detail", "Model Detail", "Detail level of models").importance(8).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.detail_distance = val;
return true;
}).finish();
const auto TexturesOption __UNUSED = options::OptionBuilder<int>("Graphics.Texture",
std::pair<const char*, int>{"3D Hardware Textures", 1362},
std::pair<const char*, int>{"Level of detail of textures", 1720})
.importance(6)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.hardware_textures = val;
return true;
})
.finish();
"3D Hardware Textures",
"Level of detail of textures").importance(6).category("Graphics").values(
DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.hardware_textures = val;
return true;
}).finish();
const auto ParticlesOption __UNUSED = options::OptionBuilder<int>("Graphics.Particles",
std::pair<const char*, int>{"Particles", 1363},
std::pair<const char*, int>{"Level of detail for particles", 1717})
.importance(5)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_particles = val;
return true;
})
.finish();
"Particles",
"Level of detail for particles").importance(5).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.num_particles = val;
return true;
}).finish();
const auto SmallDebrisOption __UNUSED = options::OptionBuilder<int>("Graphics.SmallDebris",
std::pair<const char*, int>{"Impact Effects", 1364},
std::pair<const char*, int>{"Level of detail of impact effects", 1743})
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.importance(4)
.change_listener([](int val,bool) {
Detail.num_small_debris = val;
return true;
})
.finish();
const auto SmallDebrisOption __UNUSED =
options::OptionBuilder<int>("Graphics.SmallDebris", "Impact Effects", "Level of detail of impact effects").category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).importance(4).change_listener([](int val,
bool) {
Detail.num_small_debris = val;
return true;
}).finish();
const auto ShieldEffectsOption __UNUSED = options::OptionBuilder<int>("Graphics.ShieldEffects",
std::pair<const char*, int>{"Shield Hit Effects", 1718},
std::pair<const char*, int>{"Level of detail of shield impacts", 1719})
.importance(3)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.shield_effects = val;
return true;
})
.finish();
"Shield Hit Effects",
"Level of detail of shield impacts").importance(3).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.shield_effects = val;
return true;
}).finish();
const auto StarsOption __UNUSED = options::OptionBuilder<int>("Graphics.Stars",
std::pair<const char*, int>{"Stars", 1366},
std::pair<const char*, int>{"Number of stars in the mission", 1698})
.importance(2)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_stars = val;
return true;
})
.finish();
const auto StarsOption __UNUSED =
options::OptionBuilder<int>("Graphics.Stars", "Stars", "Number of stars in the mission").importance(2).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.num_stars = val;
return true;
}).finish();
// Call this with:
// 0 - lowest
+13
View File
@@ -59,6 +59,19 @@
extern float Cutscene_bars_progress, Cutscene_delta_time;
extern int Cutscene_bar_flags;
//-----Fadein stuff
struct shader;
extern shader Viewer_shader;
enum FadeType {
FI_NONE,
FI_FADEIN,
FI_FADEOUT
};
extern FadeType Fade_type;
extern int Fade_start_timestamp;
extern int Fade_end_timestamp;
typedef struct vei {
angles_t angles; // Angles defining viewer location.
+1 -1
View File
@@ -34,7 +34,7 @@
#define ASSUME(x)
#if defined(NDEBUG)
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
# define Assertion(expr, msg, ...) do { } while (false)
#else
/*
* NOTE: Assertion() can only use its proper functionality in compilers
+1 -1
View File
@@ -34,7 +34,7 @@
#define ASSUME(x)
#if defined(NDEBUG)
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
# define Assertion(expr, msg, ...) do {} while (false)
#else
/*
* NOTE: Assertion() can only use its proper functionality in compilers
+1 -1
View File
@@ -36,7 +36,7 @@
#define ASSUME(x)
#if defined(NDEBUG)
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
# define Assertion(expr, msg, ...) do {} while (false)
#else
/*
* NOTE: Assertion() can only use its proper functionality in compilers
+1 -1
View File
@@ -39,7 +39,7 @@
#define ASSUME(x)
#if defined(NDEBUG)
# define Assertion(expr, msg, ...) do { ASSUME(expr); (void)sizeof(expr); } while (false)
# define Assertion(expr, msg, ...) do { ASSUME(expr); } while (false)
#else
# define Assertion(expr, msg, ...) \
do { \
+32 -48
View File
@@ -53,10 +53,41 @@ version parse_version() {
return v;
}
version parse_version_inline() {
version v;
SCP_string input;
stuff_string(input, F_RAW);
return version(std::move(input), 0);
size_t start_pos = 0;
size_t end_pos = input.find('.');
v.major = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
if (end_pos == SCP_string::npos)
return v;
start_pos = end_pos + 1;
end_pos = input.find('.', start_pos);
v.minor = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
if (end_pos == SCP_string::npos)
return v;
start_pos = end_pos + 1;
end_pos = input.find('.', start_pos);
v.build = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
if (end_pos == SCP_string::npos)
return v;
start_pos = end_pos + 1;
end_pos = input.find('.', start_pos);
v.revision = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
return v;
}
version get_executable_version() {
version v;
@@ -71,53 +102,6 @@ version get_executable_version() {
version::version(int major_in, int minor_in, int build_in, int revision_in) :
major(major_in), minor(minor_in), build(build_in), revision(revision_in) {
}
version::version(const SCP_string& semver, int missing) : major(missing), minor(missing), build(missing), revision(missing) {
int i = 0;
auto str = semver;
int has_fields = 0;
while (i <= 4) {
size_t pos = str.find_first_of('.');
SCP_string ver;
if (pos != SCP_string::npos) {
ver = str.substr(0, pos);
str.erase(0, pos + 1);
}
else {
ver = str;
str.clear();
}
if (!ver.empty() && std::find_if(ver.begin(), ver.end(), [](char c) { return !std::isdigit(c, SCP_default_locale); }) == ver.end()) {
switch (has_fields) {
case 0:
major = std::stoi(ver.c_str());
++has_fields;
break;
case 1:
minor = std::stoi(ver.c_str());
++has_fields;
break;
case 2:
build = std::stoi(ver.c_str());
++has_fields;
break;
case 3:
revision = std::stoi(ver.c_str());
++has_fields;
break;
default:
UNREACHABLE("Version parsing broken, get a coder!");
break;
}
}
else
break; //Break out of the loop if the first string is not a digit.
i++;
}
}
bool version::isValid() const { return major != 0 || minor != 0 || build != 0 || revision != 0; }
bool version::operator<(const version& v) const {
-2
View File
@@ -57,8 +57,6 @@ struct version {
version(int major, int minor = 0, int build = 0, int revision = 0);
version(const SCP_string& semver, int missing = -1);
bool isValid() const;
bool operator<(const version& other) const;
-10
View File
@@ -25,16 +25,6 @@ bool SCP_vector_contains(SCP_vector<T>& vector, T item) {
return std::find(vector.begin(), vector.end(), item) != vector.end();
}
template <typename T>
inline bool SCP_vector_inbounds(SCP_vector<T>& vector, int idx) {
return ((idx >= 0) && (idx < static_cast<int>(vector.size())));
}
template <typename T>
inline bool SCP_vector_inbounds(SCP_vector<T>& vector, size_t idx) {
return idx < vector.size();
}
template <typename T>
using SCP_list = std::list<T, std::allocator<T>>;
+135 -192
View File
@@ -25,7 +25,6 @@
#include "cmdline/cmdline.h"
#include "debugconsole/console.h"
#include "executor/global_executors.h"
#include "graphics/openxr.h"
#include "graphics/paths/PathRenderer.h"
#include "graphics/post_processing.h"
#include "graphics/util/GPUMemoryHeap.h"
@@ -113,38 +112,35 @@ static bool gamma_change_listener(float new_val, bool initial)
return true;
}
static auto GammaOption __UNUSED = options::OptionBuilder<float>("Graphics.Gamma",
std::pair<const char*, int>{"Brightness", 1375},
std::pair<const char*, int>{"The brightness value used for the game window", 1738})
.category("Graphics")
.default_val(1.0f)
.enumerator(gamma_value_enumerator)
.display(gamma_display)
.change_listener(gamma_change_listener)
.finish();
static auto GammaOption __UNUSED =
options::OptionBuilder<float>("Graphics.Gamma", "Brightness", "The brighness value used for the game window")
.category("Graphics")
.default_val(1.0f)
.enumerator(gamma_value_enumerator)
.display(gamma_display)
.change_listener(gamma_change_listener)
.finish();
const SCP_vector<std::pair<int, std::pair<const char*, int>>> DetailLevelValues = {{ 0, {"Minimum", 1680}},
{ 1, {"Low", 1161}},
{ 2, {"Medium", 1162}},
{ 3, {"High", 1163}},
{ 4, {"Ultra", 1721}}};
const SCP_vector<std::pair<int, SCP_string>> DetailLevelValues = {{ 0, "Minimum" },
{ 1, "Low" },
{ 2, "Medium" },
{ 3, "High" },
{ 4, "Ultra" }, };
const auto LightingOption __UNUSED = options::OptionBuilder<int>("Graphics.Lighting",
std::pair<const char*, int>{"Lighting", 1367},
std::pair<const char*, int>{"Level of detail of the lighting", 1715})
.importance(1)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool initial) {
Detail.lighting = val;
if (!initial) {
gr_recompile_all_shaders(nullptr);
}
return true;
})
.finish();
const auto LightingOption __UNUSED = options::OptionBuilder<int>("Graphics.Lighting", "Lighting", "Level of detail of the lighting")
.importance(1)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool initial) {
Detail.lighting = val;
if (!initial) {
gr_recompile_all_shaders(nullptr);
}
return true;
})
.finish();
os::ViewportState Gr_configured_window_state = os::ViewportState::Windowed;
@@ -166,18 +162,17 @@ static bool mode_change_func(os::ViewportState state, bool initial)
return true;
}
static auto WindowModeOption __UNUSED = options::OptionBuilder<os::ViewportState>("Graphics.WindowMode",
std::pair<const char*, int>{"Window Mode", 1772},
std::pair<const char*, int>{"Controls how the game window is created", 1773})
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.values({{os::ViewportState::Fullscreen, {"Fullscreen", 1679}},
{os::ViewportState::Borderless, {"Borderless", 1675}},
{os::ViewportState::Windowed, {"Windowed", 1676}}})
.importance(98)
.default_val(os::ViewportState::Fullscreen)
.change_listener(mode_change_func)
.finish();
static auto WindowModeOption __UNUSED = options::OptionBuilder<os::ViewportState>("Graphics.WindowMode", "Window Mode",
"Controls how the game window is created.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.values({{os::ViewportState::Fullscreen, "Fullscreen"},
{os::ViewportState::Borderless, "Borderless"},
{os::ViewportState::Windowed, "Windowed"}})
.importance(98)
.default_val(os::ViewportState::Fullscreen)
.change_listener(mode_change_func)
.finish();
const std::shared_ptr<scripting::OverridableHook<>> OnFrameHook = scripting::OverridableHook<>::Factory(
"On Frame", "Called every frame as the last action before showing the frame result to the user.", {}, tl::nullopt, CHA_ONFRAME);
@@ -193,7 +188,6 @@ int gr_stencil_mode = 0;
// Default clipping distances
const float Default_min_draw_distance = 1.0f;
const float Default_max_draw_distance = 1e10;
float Min_draw_distance_cockpit = 0.02f;
float Min_draw_distance = Default_min_draw_distance;
float Max_draw_distance = Default_max_draw_distance;
@@ -257,20 +251,18 @@ static bool videodisplay_change(int display, bool initial)
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display), SDL_WINDOWPOS_CENTERED_DISPLAY(display));
return true;
}
static auto VideoDisplayOption = options::OptionBuilder<int>("Graphics.Display",
std::pair<const char*, int>{"Primary display", 1741},
std::pair<const char*, int>{"The display used for rendering", 1742})
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(videodisplay_deserializer)
.serializer(videodisplay_serializer)
.enumerator(videodisplay_enumerator)
.display(videodisplay_display)
.flags({options::OptionFlags::ForceMultiValueSelection})
.default_val(0)
.change_listener(videodisplay_change)
.importance(99)
.finish();
static auto VideoDisplayOption =
options::OptionBuilder<int>("Graphics.Display", "Primary display", "The display used for rendering.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(videodisplay_deserializer)
.serializer(videodisplay_serializer)
.enumerator(videodisplay_enumerator)
.display(videodisplay_display)
.default_val(0)
.change_listener(videodisplay_change)
.importance(99)
.finish();
struct ResolutionInfo {
uint32_t width = 0;
@@ -367,83 +359,80 @@ static bool resolution_change(const ResolutionInfo& /*info*/, bool initial)
}
*/
}
static auto ResolutionOption = options::OptionBuilder<ResolutionInfo>("Graphics.Resolution",
std::pair<const char*, int>{"Resolution", 1748},
std::pair<const char*, int>{"The rendering resolution", 1749})
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(resolution_deserializer)
.serializer(resolution_serializer)
.enumerator(resolution_enumerator)
.display(resolution_display)
.default_func(resolution_default)
.change_listener(resolution_change)
.importance(100)
.finish();
static auto ResolutionOption =
options::OptionBuilder<ResolutionInfo>("Graphics.Resolution", "Resolution", "The rendering resolution.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(resolution_deserializer)
.serializer(resolution_serializer)
.enumerator(resolution_enumerator)
.display(resolution_display)
.default_func(resolution_default)
.change_listener(resolution_change)
.importance(100)
.finish();
bool Gr_enable_soft_particles = false;
static auto SoftParticlesOption __UNUSED = options::OptionBuilder<bool>("Graphics.SoftParticles",
std::pair<const char*, int>{"Soft Particles", 1761},
std::pair<const char*, int>{"Enable or disable soft particle rendering", 1762})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_soft_particles)
.importance(68)
.finish();
static auto SoftParticlesOption __UNUSED = options::OptionBuilder<bool>("Graphics.SoftParticles", "Soft Particles",
"Enable or disable soft particle rendering.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_soft_particles)
.importance(68)
.finish();
flagset<FramebufferEffects> Gr_framebuffer_effects;
static auto FramebufferEffectsOption __UNUSED = options::OptionBuilder<flagset<FramebufferEffects>>("Graphics.FramebufferEffects",
std::pair<const char*, int>{"Framebuffer effects", 1732},
std::pair<const char*, int>{"Controls which framebuffer effects will be applied to the scene", 1733})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{{}, {"None", 211}},
{{FramebufferEffects::Shockwaves}, {"Shockwaves", 1688}},
{{FramebufferEffects::Thrusters}, {"Thrusters", 1689}},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, {"All", 1690}}})
.default_val({FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters})
.bind_to_once(&Gr_framebuffer_effects)
.importance(77)
.finish();
static auto FramebufferEffectsOption __UNUSED =
options::OptionBuilder<flagset<FramebufferEffects>>(
"Graphics.FramebufferEffects", "Framebuffer effects",
"Controls which framebuffer effects will be applied to the scene.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{{}, "None"},
{{FramebufferEffects::Shockwaves}, "Shockwaves"},
{{FramebufferEffects::Thrusters}, "Thrusters"},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, "All"}})
.default_val({FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters})
.bind_to_once(&Gr_framebuffer_effects)
.importance(77)
.finish();
AntiAliasMode Gr_aa_mode = AntiAliasMode::None;
AntiAliasMode Gr_aa_mode_last_frame = AntiAliasMode::None;
static auto AAOption __UNUSED = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode",
std::pair<const char*, int>{"Anti Aliasing", 1752},
std::pair<const char*, int>{"Controls the anti aliasing mode of the engine.", 1753})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{AntiAliasMode::None, {"None", 211}},
{AntiAliasMode::FXAA_Low, {"FXAA Low", 1681}},
{AntiAliasMode::FXAA_Medium, {"FXAA Medium", 1682}},
{AntiAliasMode::FXAA_High, {"FXAA High", 1683}},
{AntiAliasMode::SMAA_Low, {"SMAA Low", 1684}},
{AntiAliasMode::SMAA_Medium, {"SMAA Medium", 1685}},
{AntiAliasMode::SMAA_High, {"SMAA High", 1686}},
{AntiAliasMode::SMAA_Ultra, {"SMAA Ultra", 1687}}})
.default_val(AntiAliasMode::None)
.bind_to(&Gr_aa_mode)
.importance(79)
.finish();
static auto AAOption __UNUSED = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode", "Anti Aliasing",
"Controls the anti aliasing mode of the engine.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{AntiAliasMode::None, "None"},
{AntiAliasMode::FXAA_Low, "FXAA Low"},
{AntiAliasMode::FXAA_Medium, "FXAA Medium"},
{AntiAliasMode::FXAA_High, "FXAA High"},
{AntiAliasMode::SMAA_Low, "SMAA Low"},
{AntiAliasMode::SMAA_Medium, "SMAA Medium"},
{AntiAliasMode::SMAA_High, "SMAA High"},
{AntiAliasMode::SMAA_Ultra, "SMAA Ultra"}})
.default_val(AntiAliasMode::None)
.bind_to(&Gr_aa_mode)
.importance(79)
.finish();
extern int Cmdline_msaa_enabled;
static auto MSAAOption __UNUSED = options::OptionBuilder<int>("Graphics.MSAASamples",
std::pair<const char*, int>{"Multisample Anti Aliasing", 1758},
std::pair<const char*, int>{"Controls whether multisample anti asliasing is enabled, and with how many samples", 1759})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{0, {"Off", 1693}},
{4, {"4 Samples", 1694}},
{8, {"8 Samples", 1695}},
{16, {"16 Samples", 1696}}})
.default_val(0)
.bind_to_once(&Cmdline_msaa_enabled)
.importance(78)
.finish();
static auto MSAAOption __UNUSED = options::OptionBuilder<int>("Graphics.MSAASamples", "Multisample Anti Aliasing",
"Controls whether multisample anti aliasing is enabled, and with how many samples.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{0, "Off"},
{4, "4 Samples"},
{8, "8 Samples"},
{16, "16 Samples"}})
.default_val(0)
.bind_to(&Cmdline_msaa_enabled)
.importance(78)
.finish();
bool gr_is_fxaa_mode(AntiAliasMode mode)
{
@@ -455,27 +444,26 @@ bool gr_is_smaa_mode(AntiAliasMode mode) {
bool Gr_post_processing_enabled = true;
static auto PostProcessOption __UNUSED = options::OptionBuilder<bool>("Graphics.PostProcessing",
std::pair<const char*, int>{"Post processing", 1726},
std::pair<const char*, int>{"Controls whether post processing is enabled in the engine.", 1727})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(false)
.bind_to_once(&Gr_post_processing_enabled)
.importance(69)
.finish();
static auto PostProcessOption __UNUSED =
options::OptionBuilder<bool>("Graphics.PostProcessing", "Post processing",
"Controls whether post processing is enabled in the engine")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(false)
.bind_to_once(&Gr_post_processing_enabled)
.importance(69)
.finish();
bool Gr_enable_vsync = true;
static auto VSyncOption __UNUSED = options::OptionBuilder<bool>("Graphics.VSync",
std::pair<const char*, int>{"Vertical Sync", 1766},
std::pair<const char*, int>{"Controls how the engine does vertical synchronization", 1767})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_vsync)
.importance(70)
.finish();
static auto VSyncOption __UNUSED = options::OptionBuilder<bool>("Graphics.VSync", "Vertical Sync",
"Controls how the engine does vertical synchronization")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_vsync)
.importance(70)
.finish();
static std::unique_ptr<graphics::util::UniformBufferManager> UniformBufferManager;
@@ -706,7 +694,7 @@ bool gr_resize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
*/
bool gr_unsize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
{
if ( resize_mode == GR_RESIZE_NONE || resize_mode == GR_RESIZE_REPLACE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
if ( resize_mode == GR_RESIZE_NONE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
return false;
}
@@ -1027,9 +1015,6 @@ void gr_close()
return;
}
if(Cmdline_enable_vr)
openxr_close();
if (Gr_original_gamma_ramp != nullptr && os::getSDLMainWindow() != nullptr) {
SDL_SetWindowGammaRamp(os::getSDLMainWindow(), Gr_original_gamma_ramp, (Gr_original_gamma_ramp + 256),
(Gr_original_gamma_ramp + 512));
@@ -1261,38 +1246,14 @@ static void init_colors()
Gr_ta_alpha.scale = 17;
}
static void gr_init_function_pointers(int mode) {
gr_screen = {};
switch (mode) {
case GR_OPENGL:
#ifdef WITH_OPENGL
gr_opengl_init_function_pointers();
#else
Error(LOCATION, "OpenGL renderer was requested but that was not compiled into this build.");
#endif
break;
case GR_VULKAN:
#ifdef WITH_VULKAN
graphics::vulkan::initialize_function_pointers();
#else
Error(LOCATION, "Vulkan renderer was requested but that was not compiled into this build.");
#endif
break;
case GR_STUB:
gr_stub_init_function_pointers();
break;
default:
UNREACHABLE("Invalid graphics mode requested"); // Invalid graphics mode
}
}
static bool gr_init_sub(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int mode, int width, int height,
int depth, float center_aspect_ratio)
{
int res = GR_1024;
bool rc = false;
gr_screen = {};
float aspect_ratio = (float)width / (float)height;
if ( (((width == 640) && (height == 480)) || ((width == 1024) && (height == 768))) && (aspect_ratio == center_aspect_ratio) ) {
@@ -1591,6 +1552,9 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
depth = d_depth;
}
if (Cmdline_vulkan)
mode = GR_VULKAN;
// if we are in standalone mode then just use special defaults
if (Is_standalone) {
mode = GR_STUB;
@@ -1600,8 +1564,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
center_aspect_ratio = -1.0f;
}
gr_init_function_pointers(mode);
if (gr_get_resolution_class(width, height) != GR_640) {
// check for hi-res interface files so that we can verify our width/height is correct
// if we don't have it then fall back to 640x480 mode instead
@@ -1619,17 +1581,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
}
}
if (Cmdline_enable_vr) {
float user_ar = i2fl(width) / i2fl(height);
float xr_ar = openxr_preinit(user_ar);
if (MAX(user_ar, xr_ar) / MIN(user_ar, xr_ar) > 1.05f) {
int newWidth = fl2i(i2fl(height) * xr_ar);
mprintf(("User specified resolution does not match OpenXR HMD aspect ratio. Adjusting width from %dpx to %dpx.", width, newWidth));
width = newWidth;
}
}
// These compiler macros will force windowed mode at the specified resolution if
// built in debug mode. This helps if you run with the debugger active as the
// game won't be switching from fullscreen to minimized every time you hit a breakpoint or
@@ -1748,9 +1699,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
Shadow_quality = ShadowQuality::Disabled;
}
if(Cmdline_enable_vr)
openxr_init();
return true;
}
@@ -2639,12 +2587,7 @@ void gr_flip(bool execute_scripting)
uniform_buffer_managers_retire_buffers();
TRACE_SCOPE(tracing::PageFlip);
//Prevent a real page flip if OpenXR is on and claims that that wasn't the full image yet
if (!gr_openxr_flip()) {
gr_screen.gf_flip();
gr_setup_frame();
}
gr_screen.gf_flip();
}
void gr_print_timestamp(int x, int y, fix timestamp, int resize_mode)
+3 -32
View File
@@ -36,7 +36,6 @@ class OverridableHook;
extern const float Default_min_draw_distance;
extern const float Default_max_draw_distance;
extern float Min_draw_distance_cockpit;
extern float Min_draw_distance;
extern float Max_draw_distance;
extern int Gr_inited;
@@ -103,7 +102,7 @@ public:
Stack.push_back(Current_transform);
}
const matrix4 &get_transform() const
matrix4 &get_transform()
{
return Current_transform;
}
@@ -116,7 +115,7 @@ public:
Stack.push_back(Current_transform);
}
void push_and_replace(const matrix4 &new_transform)
void push_and_replace(matrix4 new_transform)
{
Current_transform = new_transform;
Stack.push_back(Current_transform);
@@ -203,7 +202,6 @@ enum shader_type {
SDR_TYPE_VOLUMETRIC_FOG,
SDR_TYPE_ROCKET_UI,
SDR_TYPE_COPY,
SDR_TYPE_COPY_WORLD,
SDR_TYPE_MSAA_RESOLVE,
SDR_TYPE_POST_PROCESS_SMAA_EDGE,
@@ -238,10 +236,6 @@ enum shader_type {
#define SDR_FLAG_VOLUMETRICS_DO_EDGE_SMOOTHING (1<<0)
#define SDR_FLAG_VOLUMETRICS_NOISE (1<<1)
#define SDR_FLAG_COPY_FROM_ARRAY (1 << 0)
#define SDR_FLAG_TONEMAPPING_LINEAR_OUT (1 << 0)
enum class uniform_block_type {
Lights = 0,
@@ -306,7 +300,7 @@ public:
void add_vertex_component(vertex_format_data::vertex_format format_type, size_t stride, size_t offset);
size_t get_vertex_stride() const { return Vertex_stride; }
size_t get_vertex_stride() { return Vertex_stride; }
bool operator==(const vertex_layout& other) const;
@@ -702,8 +696,6 @@ typedef struct screen {
// switch onscreen, offscreen
std::function<void()> gf_flip;
std::function<void()> gf_setup_frame;
// sets the clipping region
std::function<void(int x, int y, int w, int h, int resize_mode)> gf_set_clip;
@@ -919,14 +911,6 @@ typedef struct screen {
std::function<void(int x, int y, int width, int height)> gf_set_viewport;
std::function<void(bool set_override)> gf_override_fog;
//OpenXR functions
std::function<SCP_vector<const char*>()> gf_openxr_get_extensions;
std::function<bool()> gf_openxr_test_capabilities;
std::function<bool()> gf_openxr_create_session;
std::function<int64_t(const SCP_vector<int64_t>&)> gf_openxr_get_swapchain_format;
std::function<bool()> gf_openxr_acquire_swapchain_buffers;
std::function<bool()> gf_openxr_flip;
} screen;
// handy macro
@@ -981,7 +965,6 @@ extern screen gr_screen;
#define GR_RESIZE_MENU 3
#define GR_RESIZE_MENU_ZOOMED 4
#define GR_RESIZE_MENU_NO_OFFSET 5
#define GR_RESIZE_REPLACE 6
void gr_set_screen_scale(int x, int y, int zoom_x = -1, int zoom_y = -1, int max_x = gr_screen.max_w, int max_y = gr_screen.max_h, int center_x = gr_screen.center_w, int center_y = gr_screen.center_h, bool force_stretch = false);
void gr_reset_screen_scale();
@@ -1027,10 +1010,6 @@ extern void gr_activate(int active);
//#define gr_flip GR_CALL(gr_screen.gf_flip)
void gr_flip(bool execute_scripting = true);
inline void gr_setup_frame() {
gr_screen.gf_setup_frame();
}
//#define gr_set_clip GR_CALL(gr_screen.gf_set_clip)
inline void gr_set_clip(int x, int y, int w, int h, int resize_mode=GR_RESIZE_FULL)
{
@@ -1292,14 +1271,6 @@ inline void gr_sync_delete(gr_sync sync)
gr_screen.gf_sync_delete(sync);
}
//OpenXR
#define gr_openxr_get_extensions GR_CALL(gr_screen.gf_openxr_get_extensions)
#define gr_openxr_test_capabilities GR_CALL(gr_screen.gf_openxr_test_capabilities)
#define gr_openxr_create_session GR_CALL(gr_screen.gf_openxr_create_session)
#define gr_openxr_get_swapchain_format GR_CALL(gr_screen.gf_openxr_get_swapchain_format)
#define gr_openxr_acquire_swapchain_buffers GR_CALL(gr_screen.gf_openxr_acquire_swapchain_buffers)
#define gr_openxr_flip GR_CALL(gr_screen.gf_openxr_flip)
// color functions
void gr_init_color(color *c, int r, int g, int b);
void gr_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type = AC_TYPE_HUD );
-22
View File
@@ -734,28 +734,6 @@ void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool m
}
}
void generic_anim_bitmap_set(generic_anim* ga, float frametime, const generic_extras* ge)
{
if ((ge != nullptr) && (ga->use_hud_color == true)) {
Warning(LOCATION, "Monochrome generic anims can't use extra info (yet)");
return;
}
float a = 1.0f;
if (ge != nullptr) {
a = ge->alpha;
}
if (ga->type == BM_TYPE_PNG) {
generic_anim_render_variable_frame_delay(ga, frametime, a);
}
else {
generic_anim_render_fixed_frame_delay(ga, frametime, a);
}
if (ga->num_frames > 0)
ga->previous_frame = ga->current_frame;
}
/*
* @brief reset an animation back to the start
*
-1
View File
@@ -91,6 +91,5 @@ int generic_anim_stream(generic_anim *ga, const bool cache = true);
int generic_bitmap_load(generic_bitmap *gb);
void generic_anim_unload(generic_anim *ga);
void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool menu = false, const generic_extras *ge = nullptr);
void generic_anim_bitmap_set(generic_anim* ga, float frametime, const generic_extras* ge = nullptr);
void generic_anim_reset(generic_anim *ga);
#endif
+2 -47
View File
@@ -18,11 +18,6 @@
#include "bmpman/bm_internal.h"
void gr_stub_setup_frame()
{
}
uint gr_stub_lock()
{
return 1;
@@ -426,37 +421,7 @@ void gr_stub_delete_query_object(int /*obj*/)
{
}
SCP_vector<const char*> gr_stub_openxr_get_extensions()
{
return {};
}
bool gr_stub_openxr_test_capabilities()
{
return false;
}
bool gr_stub_openxr_create_session()
{
return false;
}
int64_t gr_stub_openxr_get_swapchain_format(const SCP_vector<int64_t>& /*allowed*/)
{
return 0;
}
bool gr_stub_openxr_acquire_swapchain_buffers()
{
return false;
}
bool gr_stub_openxr_flip()
{
return false;
}
bool gr_stub_init()
bool gr_stub_init()
{
if (gr_screen.res != GR_640) {
gr_screen.res = GR_640;
@@ -482,13 +447,8 @@ bool gr_stub_init()
Gr_blue.mask = 0xff;
Gr_t_blue = Gr_blue;
return true;
}
void gr_stub_init_function_pointers() {
// function pointers...
gr_screen.gf_flip = gr_stub_flip;
gr_screen.gf_setup_frame = gr_stub_setup_frame;
gr_screen.gf_set_clip = gr_stub_set_clip;
gr_screen.gf_reset_clip = gr_stub_reset_clip;
@@ -612,10 +572,5 @@ void gr_stub_init_function_pointers() {
gr_screen.gf_override_fog = [](bool /*b*/) {};
gr_screen.gf_openxr_get_extensions = gr_stub_openxr_get_extensions;
gr_screen.gf_openxr_test_capabilities = gr_stub_openxr_test_capabilities;
gr_screen.gf_openxr_create_session = gr_stub_openxr_create_session;
gr_screen.gf_openxr_get_swapchain_format = gr_stub_openxr_get_swapchain_format;
gr_screen.gf_openxr_acquire_swapchain_buffers = gr_stub_openxr_acquire_swapchain_buffers;
gr_screen.gf_openxr_flip = gr_stub_openxr_flip;
return true;
}
+1 -1
View File
@@ -1,3 +1,3 @@
void gr_stub_init_function_pointers();
bool gr_stub_init();
-7
View File
@@ -15,7 +15,6 @@
#include "cmdline/cmdline.h"
#include "graphics/2d.h"
#include "io/timer.h"
#include "lighting/lighting.h"
#include "lighting/lighting_profiles.h"
#include "math/bitarray.h"
@@ -44,12 +43,6 @@ struct gr_light
int type;
};
//FADEIN STUFF
shader Viewer_shader;
FadeType Fade_type = FadeType::FI_NONE;
TIMESTAMP Fade_start_timestamp = TIMESTAMP::invalid();
TIMESTAMP Fade_end_timestamp = TIMESTAMP::invalid();
// Variables
SCP_vector<gr_light> gr_lights;
graphics::model_light gr_light_uniforms[graphics::MAX_UNIFORM_LIGHTS];
-15
View File
@@ -5,20 +5,6 @@
#include "lighting/lighting.h"
#include "cmdline/cmdline.h"
//-----Fadein stuff
struct shader;
extern shader Viewer_shader;
enum class FadeType {
FI_NONE = 0,
FI_FADEIN,
FI_FADEOUT
};
extern FadeType Fade_type;
extern TIMESTAMP Fade_start_timestamp;
extern TIMESTAMP Fade_end_timestamp;
//Variables
extern int Num_active_gr_lights;
@@ -27,7 +13,6 @@ extern const float gr_light_zero[4];
extern const float gr_light_emission[4];
extern float gr_light_ambient[4];
//Functions
void gr_set_light(light *fs_light);
void gr_reset_lighting();
+1 -1
View File
@@ -441,7 +441,7 @@ void material::set_color(int r, int g, int b, int a)
Clr.xyzw.w = i2fl(a) / 255.0f;
}
void material::set_color(const color &clr_in)
void material::set_color(color &clr_in)
{
if ( clr_in.is_alphacolor ) {
Clr.xyzw.x = i2fl(clr_in.red) / 255.0f;
+1 -1
View File
@@ -133,7 +133,7 @@ public:
void set_color(float red, float green, float blue, float alpha);
void set_color(int r, int g, int b, int a);
void set_color(const color &clr_in);
void set_color(color &clr_in);
const vec4& get_color() const;
void set_color_scale(float scale);
+10 -27
View File
@@ -16,8 +16,6 @@ matrix4 gr_texture_matrix;
matrix4 gr_env_texture_matrix;
float gr_near_plane;
bool gr_htl_projection_matrix_set = false;
static int modelview_matrix_depth = 1;
@@ -118,43 +116,28 @@ void gr_end_instance_matrix()
}
// the projection matrix; fov, aspect ratio, near, far
void gr_set_proj_matrix(fov_t fov, float aspect, float z_near, float z_far) {
void gr_set_proj_matrix(float fov, float aspect, float z_near, float z_far) {
if (gr_screen.rendering_to_texture != -1) {
gr_set_viewport(gr_screen.offset_x, gr_screen.offset_y, gr_screen.clip_width, gr_screen.clip_height);
} else {
gr_set_viewport(gr_screen.offset_x, (gr_screen.max_h - gr_screen.offset_y - gr_screen.clip_height), gr_screen.clip_width, gr_screen.clip_height);
}
gr_last_projection_matrix = gr_projection_matrix;
float clip_width, clip_height;
if (mpark::holds_alternative<float>(fov)) {
float clip_width, clip_height;
clip_height = tan(mpark::get<float>(fov) * 0.5f) * z_near;
clip_width = clip_height * aspect;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, clip_height, -clip_height, z_near, z_far);
} else {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, -clip_height, clip_height, z_near, z_far);
}
}
else {
const auto& afov = mpark::get<asymmetric_fov>(fov);
float clip_l = tanf(afov.left) * z_near;
float clip_r = tanf(afov.right) * z_near;
float clip_u = tanf(afov.up) * z_near;
float clip_d = tanf(afov.down) * z_near;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, clip_l, clip_r, clip_u, clip_d, z_near, z_far);
}
else {
create_perspective_projection_matrix(&gr_projection_matrix, clip_l, clip_r, clip_d, clip_u, z_near, z_far);
}
clip_height = tan( fov * 0.5f ) * z_near;
clip_width = clip_height * aspect;
gr_last_projection_matrix = gr_projection_matrix;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, clip_height, -clip_height, z_near, z_far);
} else {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, -clip_height, clip_height, z_near, z_far);
}
gr_htl_projection_matrix_set = true;
matrix_uniform_up_to_date = false;
gr_near_plane = z_near;
}
void gr_end_proj_matrix() {
+1 -3
View File
@@ -1,7 +1,6 @@
#pragma once
#include "graphics/2d.h"
#include "render/3d.h"
extern transform_stack gr_model_matrix_stack;
extern matrix4 gr_view_matrix;
@@ -9,7 +8,6 @@ extern matrix4 gr_model_view_matrix;
extern matrix4 gr_projection_matrix;
extern matrix4 gr_last_projection_matrix;
extern matrix4 gr_env_texture_matrix;
extern float gr_near_plane;
void gr_matrix_on_frame();
@@ -17,7 +15,7 @@ void gr_start_instance_matrix(const vec3d* offset, const matrix* rotation);
void gr_start_angles_instance_matrix(const vec3d* pos, const angles* rotation);
void gr_end_instance_matrix();
void gr_set_proj_matrix(fov_t fov, float aspect, float z_near, float z_far);
void gr_set_proj_matrix(float fov, float aspect, float z_near, float z_far);
void gr_end_proj_matrix();
void gr_set_view_matrix(const vec3d* pos, const matrix* orient);
+26 -76
View File
@@ -6,19 +6,11 @@
#include <direct.h>
#endif
#if !defined __APPLE_CC__ && defined SCP_UNIX
#include<glad/glad_glx.h>
//Required because X defines none and always, which is used later
#undef None
#undef Always
#endif
#include "gropengl.h"
#include "ShaderProgram.h"
#include "gropenglbmpman.h"
#include "gropengldeferred.h"
#include "gropengldraw.h"
#include "gropenglopenxr.h"
#include "gropenglpostprocessing.h"
#include "gropenglquery.h"
#include "gropenglshader.h"
@@ -35,7 +27,6 @@
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "libs/renderdoc/renderdoc.h"
#include "lighting/lighting.h"
#include "math/floating.h"
#include "model/model.h"
#include "options/Option.h"
@@ -115,18 +106,6 @@ void gr_opengl_flip()
if (!GL_initted)
return;
if (Cmdline_window_res) {
GL_state.BindFrameBuffer(0, GL_DRAW_FRAMEBUFFER);
GL_state.BindFrameBuffer(Back_framebuffer, GL_READ_FRAMEBUFFER);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_BACK);
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, Cmdline_window_res->first, Cmdline_window_res->second, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glDrawBuffer(GL_NONE);
GL_state.PopFramebufferState();
}
if (Cmdline_gl_finish)
glFinish();
@@ -143,17 +122,6 @@ void gr_opengl_flip()
#endif
}
void gr_opengl_setup_frame() {
if (!GL_initted)
return;
if (Cmdline_window_res) {
GL_state.PushFramebufferState();
GL_state.BindFrameBuffer(Back_framebuffer);
glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
}
}
void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
{
// check for sanity of parameters
@@ -165,7 +133,7 @@ void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
y = 0;
}
int to_resize = (resize_mode != GR_RESIZE_NONE && resize_mode != GR_RESIZE_REPLACE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)));
int to_resize = (resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)));
int max_w = ((to_resize) ? gr_screen.max_w_unscaled : gr_screen.max_w);
int max_h = ((to_resize) ? gr_screen.max_h_unscaled : gr_screen.max_h);
@@ -174,30 +142,28 @@ void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
gr_unsize_screen_pos(&max_w, &max_h);
}
if (resize_mode != GR_RESIZE_REPLACE) {
if (x >= max_w) {
x = max_w - 1;
}
if (x >= max_w) {
x = max_w - 1;
}
if (y >= max_h) {
y = max_h - 1;
}
if (y >= max_h) {
y = max_h - 1;
}
if (x + w > max_w) {
w = max_w - x;
}
if (x + w > max_w) {
w = max_w - x;
}
if (y + h > max_h) {
h = max_h - y;
}
if (y + h > max_h) {
h = max_h - y;
}
if (w > max_w) {
w = max_w;
}
if (w > max_w) {
w = max_w;
}
if (h > max_h) {
h = max_h;
}
if (h > max_h) {
h = max_h;
}
gr_screen.offset_x_unscaled = x;
@@ -895,9 +861,6 @@ int opengl_init_display_device()
}
}
if (Cmdline_capture_mouse)
attrs.flags.set(os::ViewPortFlags::Capture_Mouse);
auto viewport = gr_opengl_create_viewport(attrs);
if (!viewport) {
return 1;
@@ -934,10 +897,9 @@ int opengl_init_display_device()
return 0;
}
void gr_opengl_init_function_pointers()
void opengl_setup_function_pointers()
{
gr_screen.gf_flip = gr_opengl_flip;
gr_screen.gf_setup_frame = gr_opengl_setup_frame;
gr_screen.gf_set_clip = gr_opengl_set_clip;
gr_screen.gf_reset_clip = gr_opengl_reset_clip;
@@ -1066,13 +1028,6 @@ void gr_opengl_init_function_pointers()
gr_screen.gf_override_fog = gr_opengl_override_fog;
gr_screen.gf_openxr_get_extensions = gr_opengl_openxr_get_extensions;
gr_screen.gf_openxr_test_capabilities = gr_opengl_openxr_test_capabilities;
gr_screen.gf_openxr_create_session = gr_opengl_openxr_create_session;
gr_screen.gf_openxr_get_swapchain_format = gr_opengl_openxr_get_swapchain_format;
gr_screen.gf_openxr_acquire_swapchain_buffers = gr_opengl_openxr_acquire_swapchain_buffers;
gr_screen.gf_openxr_flip = gr_opengl_openxr_flip;
// NOTE: All function pointers here should have a Cmdline_nohtl check at the top
// if they shouldn't be run in non-HTL mode, Don't keep separate entries.
// *****************************************************************************
@@ -1222,7 +1177,7 @@ static void init_extensions() {
// we require a minimum GLSL version
if (GLSL_version < MIN_REQUIRED_GLSL_VERSION) {
Error(LOCATION, "Current GL Shading Language Version of %d is less than the required version of %d. Switch video modes or update your drivers.", GLSL_version, MIN_REQUIRED_GLSL_VERSION);
Error(LOCATION, "Current GL Shading Langauge Version of %d is less than the required version of %d. Switch video modes or update your drivers.", GLSL_version, MIN_REQUIRED_GLSL_VERSION);
}
GLint max_texture_units;
@@ -1271,12 +1226,6 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
Error(LOCATION, "Failed to load OpenGL!");
}
#if !defined __APPLE_CC__ && defined SCP_UNIX
if (!gladLoadGLXLoader(GL_context->getLoaderFunction(), nullptr, 0)) {
Error(LOCATION, "Failed to load GLX!");
}
#endif
// version check
GL_version = (GLVersion.major * 10) + GLVersion.minor;
@@ -1309,6 +1258,11 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
}
#endif
// this MUST be done before any other gr_opengl_* or
// opengl_* function calls!!
opengl_setup_function_pointers();
mprintf(( " OpenGL Vendor : %s\n", glGetString(GL_VENDOR) ));
mprintf(( " OpenGL Renderer : %s\n", glGetString(GL_RENDERER) ));
mprintf(( " OpenGL Version : %s\n", glGetString(GL_VERSION) ));
@@ -1388,15 +1342,11 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
Gr_current_green = &Gr_green;
Gr_current_alpha = &Gr_alpha;
gr_setup_frame();
gr_opengl_reset_clip();
gr_opengl_clear();
gr_opengl_flip();
gr_setup_frame();
gr_opengl_clear();
gr_opengl_flip();
gr_setup_frame();
gr_opengl_clear();
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &GL_max_elements_vertices);
@@ -1449,7 +1399,7 @@ bool gr_opengl_is_capable(gr_capability capability)
case CAPABILITY_POST_PROCESSING:
return Gr_post_processing_enabled && !Cmdline_no_fbo;
case CAPABILITY_DEFERRED_LIGHTING:
return !Cmdline_no_fbo && light_deferred_enabled();
return !Cmdline_no_fbo && !Cmdline_no_deferred_lighting;
case CAPABILITY_SHADOWS:
case CAPABILITY_THICK_OUTLINE:
return !Cmdline_no_geo_sdr_effects;
-1
View File
@@ -16,7 +16,6 @@
#include "globalincs/pstypes.h"
#include "graphics/grinternal.h"
void gr_opengl_init_function_pointers();
bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps);
void gr_opengl_cleanup(bool closing, int minimize=1);
int opengl_check_for_errors(const char *err_at = NULL);
+125 -217
View File
@@ -1,7 +1,6 @@
#include "gropengldeferred.h"
#include "globalincs/vmallocator.h"
#include "ShaderProgram.h"
#include "gropengldraw.h"
@@ -58,7 +57,7 @@ void opengl_clear_deferred_buffers()
void gr_opengl_deferred_lighting_begin(bool clearNonColorBufs)
{
if (!light_deferred_enabled())
if ( Cmdline_no_deferred_lighting)
return;
static const float black[] = {0, 0, 0, 1.0f};
@@ -150,7 +149,7 @@ void gr_opengl_deferred_lighting_msaa()
opengl_set_generic_uniform_data<graphics::generic_data::msaa_data>(
[&](graphics::generic_data::msaa_data* data) {
data->samples = Cmdline_msaa_enabled;
data->fov = g3_get_hfov(Proj_fov);
data->fov = Proj_fov;
});
GL_state.SetAlphaBlendMode(gr_alpha_blend::ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_WRITE);
@@ -171,57 +170,26 @@ void gr_opengl_deferred_lighting_end()
GL_state.ColorMask(true, true, true, false);
}
static GLuint deferred_light_cylinder_vbo = 0;
static GLuint deferred_light_cylinder_ibo = 0;
static GLushort deferred_light_cylinder_vcount = 0;
static GLuint deferred_light_cylinder_icount = 0;
static GLuint deferred_light_sphere_vbo = 0;
static GLuint deferred_light_sphere_ibo = 0;
static GLushort deferred_light_sphere_vcount = 0;
static GLuint deferred_light_sphere_icount = 0;
extern SCP_vector<light> Lights;
extern int Num_lights;
namespace ltp = lighting_profiles;
using namespace ltp;
static bool override_fog = false;
graphics::deferred_light_data*
// common conversion operations to translate a game light data structure into a render-ready light uniform.
prepare_light_uniforms(light& l, graphics::util::UniformAligner& uniformAligner)
{
graphics::deferred_light_data* light_data = uniformAligner.addTypedElement<graphics::deferred_light_data>();
light_data->lightType = static_cast<int>(l.type);
vec3d diffuse;
diffuse.xyz.x = l.r * l.intensity;
diffuse.xyz.y = l.g * l.intensity;
diffuse.xyz.z = l.b * l.intensity;
light_data->diffuseLightColor = diffuse;
// Set a default value for all lights. Only the first directional light will change this.
light_data->enable_shadows = false;
light_data->sourceRadius = l.source_radius;
return light_data;
}
void gr_opengl_deferred_lighting_finish()
{
GR_DEBUG_SCOPE("Deferred lighting finish");
TRACE_SCOPE(tracing::ApplyLights);
if (!light_deferred_enabled()) {
if (Cmdline_no_deferred_lighting) {
return;
}
GL_state.SetAlphaBlendMode(ALPHA_BLEND_ADDITIVE);
gr_zbuffer_set(GR_ZBUFF_NONE);
// GL_state.DepthFunc(GL_GREATER);
// GL_state.DepthMask(GL_FALSE);
//GL_state.DepthFunc(GL_GREATER);
//GL_state.DepthMask(GL_FALSE);
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_DEFERRED_LIGHTING, 0));
@@ -246,7 +214,7 @@ void gr_opengl_deferred_lighting_finish()
if (Shadow_quality != ShadowQuality::Disabled) {
GL_state.Texture.Enable(4, GL_TEXTURE_2D_ARRAY, Shadow_map_texture);
}
// We need to use stable sorting here to make sure that the relative ordering of the same light types is the same as
// the rest of the code. Otherwise the shadow mapping would be applied while rendering the wrong light which would
// lead to flickering lights in some circumstances
@@ -257,43 +225,19 @@ void gr_opengl_deferred_lighting_finish()
size_t num_data_elements = Lights.size();
// Get a uniform buffer for our data
auto light_buffer = gr_get_uniform_buffer(uniform_block_type::Lights, num_data_elements);
auto& light_uniform_aligner = light_buffer.aligner();
auto matrix_buffer = gr_get_uniform_buffer(uniform_block_type::Matrices, num_data_elements);
auto& matrix_uniform_aligner = matrix_buffer.aligner();
auto buffer = gr_get_uniform_buffer(uniform_block_type::Lights, num_data_elements);
auto& uniformAligner = buffer.aligner();
// This is the light which is responsible for shadows and volumetric nebula lighting
const light* global_light = nullptr;
vec3d global_light_diffuse;
// To allow reduced bind calls, we sort lights into subsets based on rendering methods.
// It might seem optimal to create these subsets as lights are added, or some other method,
// but this keeps the graphics implementation methods better contained and profiling currently
// (dec 2023) shows negligable cost of doing it this way.
SCP_vector<light> full_frame_lights = SCP_vector<light>();
SCP_vector<light> sphere_lights = SCP_vector<light>();
SCP_vector<light> cylinder_lights = SCP_vector<light>();
for (auto& l : Lights) {
switch (l.type) {
case Light_Type::Directional:
full_frame_lights.push_back(l);
break;
case Light_Type::Cone:
FALLTHROUGH;
case Light_Type::Point:
sphere_lights.push_back(l);
break;
case Light_Type::Tube:
cylinder_lights.push_back(l);
break;
}
}
{
GR_DEBUG_SCOPE("Build buffer data");
auto lp = ltp::current();
auto header = light_uniform_aligner.getHeader<deferred_global_data>();
auto header = uniformAligner.getHeader<deferred_global_data>();
if (Shadow_quality != ShadowQuality::Disabled) {
// Avoid this overhead when we are not going to use these values
header->shadow_mv_matrix = Shadow_view_matrix_light;
@@ -310,182 +254,136 @@ void gr_opengl_deferred_lighting_finish()
header->invScreenWidth = 1.0f / gr_screen.max_w;
header->invScreenHeight = 1.0f / gr_screen.max_h;
header->nearPlane = gr_near_plane;
// Only the first directional light uses shaders so we need to know when we already saw that light
bool first_directional = true;
for (auto& l : Lights) {
auto light_data = uniformAligner.addTypedElement<deferred_light_data>();
for (auto& l : full_frame_lights) {
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
if (Shadow_quality != ShadowQuality::Disabled) {
light_data->enable_shadows = first_directional ? 1 : 0;
}
light_data->lightType = static_cast<int>(l.type);
// Global light direction should match shadow light direction
if (first_directional) {
global_light = &l;
global_light_diffuse = light_data->diffuseLightColor;
}
vec3d diffuse;
diffuse.xyz.x = l.r * l.intensity;
diffuse.xyz.y = l.g * l.intensity;
diffuse.xyz.z = l.b * l.intensity;
vec4 light_dir;
light_dir.xyzw.x = -l.vec.xyz.x;
light_dir.xyzw.y = -l.vec.xyz.y;
light_dir.xyzw.z = -l.vec.xyz.z;
light_dir.xyzw.w = 0.0f;
vec4 view_dir;
light_data->diffuseLightColor = diffuse;
vm_vec_transform(&view_dir, &light_dir, &gr_view_matrix);
// Set a default value for all lights. Only the first directional light will change this.
light_data->enable_shadows = false;
light_data->sourceRadius = l.source_radius;
light_data->lightDir.xyz.x = view_dir.xyzw.x;
light_data->lightDir.xyz.y = view_dir.xyzw.y;
light_data->lightDir.xyz.z = view_dir.xyzw.z;
switch (l.type) {
case Light_Type::Directional:
if (Shadow_quality != ShadowQuality::Disabled) {
light_data->enable_shadows = first_directional ? 1 : 0;
}
first_directional = false;
}
for (auto& l : sphere_lights) {
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
// Global light direction should match shadow light direction
if (first_directional) {
global_light = &l;
global_light_diffuse = diffuse;
}
vec4 light_dir;
light_dir.xyzw.x = -l.vec.xyz.x;
light_dir.xyzw.y = -l.vec.xyz.y;
light_dir.xyzw.z = -l.vec.xyz.z;
light_dir.xyzw.w = 0.0f;
vec4 view_dir;
if (l.type == Light_Type::Cone) {
vm_vec_transform(&view_dir, &light_dir, &gr_view_matrix);
light_data->lightDir.xyz.x = view_dir.xyzw.x;
light_data->lightDir.xyz.y = view_dir.xyzw.y;
light_data->lightDir.xyz.z = view_dir.xyzw.z;
first_directional = false;
break;
case Light_Type::Cone:
light_data->dualCone = l.dual_cone ? 1.0f : 0.0f;
light_data->coneAngle = l.cone_angle;
light_data->coneInnerAngle = l.cone_inner_angle;
light_data->coneDir = l.vec2;
FALLTHROUGH;
case Light_Type::Point: {
float rad = (Lighting_mode == lighting_mode::COCKPIT) ? lp->cockpit_light_radius_modifier.handle(MAX(l.rada, l.radb)) : MAX(l.rada, l.radb);
light_data->lightRadius = rad;
//A small padding factor is added to guard against potentially clipping the edges of the light with facets of the volume mesh.
light_data->scale.xyz.x = rad * 1.05f;
light_data->scale.xyz.y = rad * 1.05f;
light_data->scale.xyz.z = rad * 1.05f;
break;
}
case Light_Type::Tube: {
float rad = (Lighting_mode == lighting_mode::COCKPIT) ? lp->cockpit_light_radius_modifier.handle(l.radb) : l.radb;
light_data->lightRadius = rad;
light_data->lightType = LT_TUBE;
vec3d a;
vm_vec_sub(&a, &l.vec, &l.vec2);
auto length = vm_vec_mag(&a);
//Tube light volumes must be extended past the length of their requested light vector
//to allow smooth fall-off from all angles. Since the light volume starts at the mesh
//origin we must extend it here. Later the position will be adjusted as well.
length += light_data->lightRadius * 2.0f;
//A small padding factor is added to guard against potentially clipping the edges of the light with facets of the volume mesh.
light_data->scale.xyz.x = rad * 1.05f;
light_data->scale.xyz.y = rad * 1.05f;
light_data->scale.xyz.z = length;
break;
}
}
float rad = (Lighting_mode == lighting_mode::COCKPIT)
? lp->cockpit_light_radius_modifier.handle(MAX(l.rada, l.radb))
: MAX(l.rada, l.radb);
light_data->lightRadius = rad;
// A small padding factor is added to guard against potentially clipping the edges of the light with facets
// of the volume mesh.
light_data->scale.xyz.x = rad * 1.05f;
light_data->scale.xyz.y = rad * 1.05f;
light_data->scale.xyz.z = rad * 1.05f;
}
for (auto& l : cylinder_lights) {
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
float rad =
(Lighting_mode == lighting_mode::COCKPIT) ? lp->cockpit_light_radius_modifier.handle(l.radb) : l.radb;
light_data->lightRadius = rad;
light_data->lightType = LT_TUBE;
vec3d a;
vm_vec_sub(&a, &l.vec, &l.vec2);
auto length = vm_vec_mag(&a);
// Tube light volumes must be extended past the length of their requested light vector
// to allow smooth fall-off from all angles. Since the light volume starts at the mesh
// origin we must extend it here. Later the position will be adjusted as well.
length += light_data->lightRadius * 2.0f;
// A small padding factor is added to guard against potentially clipping the edges of the light with facets
// of the volume mesh.
light_data->scale.xyz.x = rad * 1.05f;
light_data->scale.xyz.y = rad * 1.05f;
light_data->scale.xyz.z = length;
}
// Uniform data has been assembled, upload it to the GPU and issue the draw calls
light_buffer.submitData();
}
{
for (size_t i = 0; i<full_frame_lights.size(); i++) {
// just keeping things aligned really.
matrix_uniform_aligner.addTypedElement<graphics::matrix_uniforms>();
}
for (auto& l : sphere_lights) {
auto matrix_data = matrix_uniform_aligner.addTypedElement<graphics::matrix_uniforms>();
g3_start_instance_matrix(&l.vec, &vmd_identity_matrix, true);
matrix_data->modelViewMatrix = gr_model_view_matrix;
matrix_data->projMatrix = gr_projection_matrix;
g3_done_instance(true);
}
for (auto& l : cylinder_lights ) {
auto matrix_data = matrix_uniform_aligner.addTypedElement<graphics::matrix_uniforms>();
vec3d dir, newPos;
matrix orient;
vm_vec_sub(&dir, &l.vec, &l.vec2);
vm_vector_2_matrix(&orient, &dir, nullptr, nullptr);
// Tube light volumes must be extended past the length of their requested light vector
// to allow smooth fall-off from all angles. Since the light volume starts at the mesh
// origin we must extend it, which has been done above, and then move it backwards one radius.
vm_vec_normalize(&dir);
vm_vec_scale_sub(&newPos, &l.vec2, &dir, l.radb);
g3_start_instance_matrix(&newPos, &orient, true);
matrix_data->modelViewMatrix = gr_model_view_matrix;
matrix_data->projMatrix = gr_projection_matrix;
g3_done_instance(true);
}
matrix_buffer.submitData();
buffer.submitData();
}
{
GR_DEBUG_SCOPE("Render light geometry");
gr_bind_uniform_buffer(uniform_block_type::DeferredGlobals,
light_buffer.getBufferOffset(0),
sizeof(graphics::deferred_global_data),
light_buffer.bufferHandle());
gr_bind_uniform_buffer(uniform_block_type::Matrices,
matrix_buffer.getBufferOffset(0),
sizeof(graphics::matrix_uniforms),
matrix_buffer.bufferHandle());
gr_bind_uniform_buffer(uniform_block_type::DeferredGlobals, buffer.getBufferOffset(0),
sizeof(graphics::deferred_global_data), buffer.bufferHandle());
size_t element_index = 0;
vertex_layout vertex_declare;
vertex_declare.add_vertex_component(vertex_format_data::POSITION3, sizeof(float) * 3, 0);
for (auto& l : Lights) {
GR_DEBUG_SCOPE("Deferred apply single light");
for (size_t i = 0; i<full_frame_lights.size(); i++) {
GR_DEBUG_SCOPE("Deferred apply single dir light");
switch (l.type) {
case Light_Type::Directional:
gr_bind_uniform_buffer(uniform_block_type::Lights, buffer.getAlignerElementOffset(element_index),
sizeof(graphics::deferred_light_data), buffer.bufferHandle());
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
++element_index;
break;
case Light_Type::Cone:
case Light_Type::Point:
gr_bind_uniform_buffer(uniform_block_type::Lights, buffer.getAlignerElementOffset(element_index),
sizeof(graphics::deferred_light_data), buffer.bufferHandle());
gr_opengl_draw_deferred_light_sphere(&l.vec);
++element_index;
break;
case Light_Type::Tube:
gr_bind_uniform_buffer(uniform_block_type::Lights, buffer.getAlignerElementOffset(element_index),
sizeof(graphics::deferred_light_data), buffer.bufferHandle());
gr_bind_uniform_buffer(uniform_block_type::Lights,
light_buffer.getAlignerElementOffset(element_index),
sizeof(graphics::deferred_light_data),
light_buffer.bufferHandle());
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
++element_index;
}
if (!sphere_lights.empty()) {
opengl_bind_vertex_layout(vertex_declare, deferred_light_sphere_vbo, deferred_light_sphere_ibo);
}
for (size_t i = 0; i<sphere_lights.size(); i++) {
gr_bind_uniform_buffer(uniform_block_type::Lights,
light_buffer.getAlignerElementOffset(element_index),
sizeof(graphics::deferred_light_data),
light_buffer.bufferHandle());
gr_bind_uniform_buffer(uniform_block_type::Matrices,
matrix_buffer.getAlignerElementOffset(element_index),
sizeof(graphics::matrix_uniforms),
matrix_buffer.bufferHandle());
glDrawRangeElements(GL_TRIANGLES,
0,
deferred_light_sphere_vcount,
deferred_light_sphere_icount,
GL_UNSIGNED_SHORT,
0);
opengl_draw_sphere();
++element_index;
}
if (!cylinder_lights.empty()) {
opengl_bind_vertex_layout(vertex_declare, deferred_light_cylinder_vbo, deferred_light_cylinder_ibo);
}
for (size_t i = 0; i<cylinder_lights.size(); i++) {
gr_bind_uniform_buffer(uniform_block_type::Lights,
light_buffer.getAlignerElementOffset(element_index),
sizeof(graphics::deferred_light_data),
light_buffer.bufferHandle());
gr_bind_uniform_buffer(uniform_block_type::Matrices,
matrix_buffer.getAlignerElementOffset(element_index),
sizeof(graphics::matrix_uniforms),
matrix_buffer.bufferHandle());
glDrawRangeElements(GL_TRIANGLES,
0,
deferred_light_cylinder_vcount,
deferred_light_cylinder_icount,
GL_UNSIGNED_SHORT,
0);
++element_index;
vec3d dir, newPos;
matrix orient;
vm_vec_sub(&dir, &l.vec, &l.vec2);
vm_vector_2_matrix(&orient, &dir, nullptr, nullptr);
//Tube light volumes must be extended past the length of their requested light vector
//to allow smooth fall-off from all angles. Since the light volume starts at the mesh
//origin we must extend it, which has been done above, and then move it backwards one radius.
vm_vec_normalize(&dir);
vm_vec_scale_sub(&newPos, &l.vec2, &dir, l.radb);
gr_opengl_draw_deferred_light_cylinder(&newPos, &orient);
++element_index;
break;
default:
continue;
}
}
}
@@ -582,7 +480,7 @@ void gr_opengl_deferred_lighting_finish()
data->noiseColorScale2 = std::get<1>(neb.getNoiseColorScale());
data->noiseColorIntensity = neb.getNoiseColorIntensity();
data->aspect = gr_screen.clip_aspect;
data->fov = g3_get_hfov(Proj_fov);
data->fov = Proj_fov;
});
{
@@ -636,6 +534,11 @@ void gr_opengl_draw_deferred_light_sphere(const vec3d *position)
}
static GLuint deferred_light_cylinder_vbo = 0;
static GLuint deferred_light_cylinder_ibo = 0;
static GLushort deferred_light_cylinder_vcount = 0;
static GLuint deferred_light_cylinder_icount = 0;
void gr_opengl_deferred_light_cylinder_init(int segments) // Generate a VBO of a cylinder of radius and height 1.0f, based on code at http://www.ogre3d.org/tikiwiki/ManualSphereMeshes
{
unsigned int nVertex = (segments + 1) * 2 * 3 + 6; // Can someone verify this?
@@ -752,6 +655,11 @@ void gr_opengl_deferred_light_cylinder_init(int segments) // Generate a VBO of a
Vertices = nullptr;
}
static GLuint deferred_light_sphere_vbo = 0;
static GLuint deferred_light_sphere_ibo = 0;
static GLushort deferred_light_sphere_vcount = 0;
static GLuint deferred_light_sphere_icount = 0;
void gr_opengl_deferred_light_sphere_init(int rings, int segments) // Generate a VBO of a sphere of radius 1.0f, based on code at http://www.ogre3d.org/tikiwiki/ManualSphereMeshes
{
unsigned int nVertex = (rings + 1) * (segments+1) * 3;
-4
View File
@@ -1,9 +1,6 @@
#pragma once
#include "globalincs/pstypes.h"
#include "graphics/util/UniformAligner.h"
#include "graphics/util/uniform_structs.h"
#include "lighting/lighting.h"
void gr_opengl_deferred_init();
@@ -12,7 +9,6 @@ void gr_opengl_deferred_lighting_begin(bool clearNonColorBufs = false);
void gr_opengl_deferred_lighting_msaa();
void gr_opengl_deferred_lighting_end();
void gr_opengl_deferred_lighting_finish();
graphics::deferred_light_data* prepare_light_uniforms(light& l, graphics::util::UniformAligner& uniformAligner);
void gr_opengl_deferred_light_sphere_init(int rings, int segments);
void gr_opengl_deferred_light_cylinder_init(int segments);
+1 -53
View File
@@ -25,7 +25,6 @@
#include "graphics/matrix.h"
#include "graphics/paths/PathRenderer.h"
#include "graphics/util/uniform_structs.h"
#include "lighting/lighting.h"
#include "render/3d.h"
#include "tracing/tracing.h"
@@ -50,10 +49,6 @@ GLuint Scene_depth_texture_ms;
GLuint Cockpit_depth_texture;
GLuint Scene_stencil_buffer;
GLuint Back_framebuffer;
GLuint Back_texture;
GLuint Back_depth_texture;
GLuint Distortion_framebuffer = 0;
GLuint Distortion_texture[2];
int Distortion_switch = 0;
@@ -529,53 +524,6 @@ void opengl_setup_scene_textures()
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
}
if (Cmdline_window_res) {
//Gen Framebuffer
glGenFramebuffers(1, &Back_framebuffer);
GL_state.BindFrameBuffer(Back_framebuffer);
opengl_set_object_label(GL_FRAMEBUFFER, Back_framebuffer, "Backbuffer");
// setup main render texture
// setup high dynamic range color texture
glGenTextures(1, &Back_texture);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(Back_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gr_screen.max_w, gr_screen.max_h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Back_texture, 0);
opengl_set_object_label(GL_TEXTURE, Back_texture, "Backbuffer texture");
glGenTextures(1, &Back_depth_texture);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(Back_depth_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, gr_screen.max_w, gr_screen.max_h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
opengl_set_object_label(GL_TEXTURE, Back_depth_texture, "Backbuffer depth texture");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, Back_depth_texture, 0);
gr_zbuffer_set(GR_ZBUFF_FULL);
glClear(GL_DEPTH_BUFFER_BIT);
}
//Setup thruster distortion framebuffer
if (Gr_framebuffer_effects.any_set())
{
@@ -725,7 +673,7 @@ void gr_opengl_scene_texture_begin()
Scene_texture_v_scale = 1.0f;
}
if (!light_deferred_enabled()) {
if ( Cmdline_no_deferred_lighting ) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} else {
-3
View File
@@ -38,9 +38,6 @@ extern GLuint Scene_depth_texture_ms;
extern GLuint Cockpit_depth_texture;
extern GLuint Scene_stencil_buffer;
extern GLuint Back_framebuffer;
extern GLuint Back_texture;
void gr_opengl_update_distortion();
void gr_opengl_sphere(material *material_def, float rad);
-471
View File
@@ -1,471 +0,0 @@
#include "gropenglopenxr.h"
#include "io/cursor.h"
#include "io/mouse.h"
#include "graphics/matrix.h"
#include "graphics/opengl/gropengl.h"
#include "graphics/opengl/gropengldraw.h"
#include "graphics/opengl/gropenglshader.h"
#include "graphics/opengl/gropenglstate.h"
#include "graphics/opengl/ShaderProgram.h"
#include "osapi/osapi.h"
#ifdef WIN32
#define XR_USE_PLATFORM_WIN32
#include <unknwn.h>
#elif defined __APPLE_CC__
//Not supported
#elif defined SCP_UNIX
#define XR_USE_PLATFORM_XLIB
#include<X11/Xlib.h>
#include<glad/glad_glx.h>
#endif
#define XR_USE_GRAPHICS_API_OPENGL
#include "graphics/openxr_internal.h"
#include <SDL_syswm.h>
#ifndef __APPLE_CC__
//SETUP FUNCTIONS OGL
SCP_vector<const char*> gr_opengl_openxr_get_extensions() {
return { XR_KHR_OPENGL_ENABLE_EXTENSION_NAME };
}
bool gr_opengl_openxr_test_capabilities() {
XrGraphicsRequirementsOpenGLKHR requirements{
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR,
nullptr,
0,
0
};
if (openxr_callExtensionFunction<PFN_xrGetOpenGLGraphicsRequirementsKHR>("xrGetOpenGLGraphicsRequirementsKHR", xr_instance, xr_system, &requirements) != XR_SUCCESS) {
mprintf(("Failed to query OpenXR graphics requirements!\n"));
return false;
}
if (requirements.minApiVersionSupported > XR_MAKE_VERSION(GLVersion.major, GLVersion.minor, 0)) {
mprintf(("System doesn't meet OpenXR graphics requirements (min %" PRIu64 ", available %" PRIu64 ")!\n", requirements.minApiVersionSupported, static_cast<XrVersion>(XR_MAKE_VERSION(GLVersion.major, GLVersion.minor, 0))));
return false;
}
return true;
}
#ifdef WIN32
bool gr_opengl_openxr_create_session() {
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(os::getSDLMainWindow(), &wmInfo);
XrGraphicsBindingOpenGLWin32KHR graphicsBinding{
XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
nullptr,
wmInfo.info.win.hdc,
(HGLRC) SDL_GL_GetCurrentContext() //uuuuuugly, and not technically allowed by the standard, but this "opaque" SDL_GLContext type is just the hGLRC on Win32
};
XrSessionCreateInfo sessionCreateInfo{
XR_TYPE_SESSION_CREATE_INFO,
&graphicsBinding,
0,
xr_system
};
XrResult sessionInit = xrCreateSession(xr_instance, &sessionCreateInfo, &xr_session);
if (sessionInit != XR_SUCCESS) {
mprintf(("Failed to create OpenXR session with code %d\n", static_cast<int>(sessionInit)));
return false;
}
return true;
}
#elif defined SCP_UNIX
bool gr_opengl_openxr_create_session() {
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(os::getSDLMainWindow(), &wmInfo);
XWindowAttributes wa;
XGetWindowAttributes(wmInfo.info.x11.display, wmInfo.info.x11.window, &wa);
GLXContext glxcontext = (GLXContext) SDL_GL_GetCurrentContext(); //uuuuuugly, and not technically allowed by the standard, but this "opaque" SDL_GLContext type is just the GLXContext on X11
int glxfbconfigid, glxscreenid, nfbconfigs;
glXQueryContext(wmInfo.info.x11.display, glxcontext, GLX_FBCONFIG_ID, &glxfbconfigid);
glXQueryContext(wmInfo.info.x11.display, glxcontext, GLX_SCREEN, &glxscreenid);
const int fbconfigattrs[] = {GLX_FBCONFIG_ID, glxfbconfigid, None};
GLXFBConfig* fbconfigs = glXChooseFBConfig(wmInfo.info.x11.display, glxscreenid, fbconfigattrs, &nfbconfigs);
if (nfbconfigs < 1) {
mprintf(("Unable to find Linux FBConfig for OpenXR!\n"));
return false;
}
XrGraphicsBindingOpenGLXlibKHR graphicsBinding {
XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR,
nullptr,
wmInfo.info.x11.display,
static_cast<uint32_t>(XVisualIDFromVisual(wa.visual)),
fbconfigs[0],
glXGetCurrentDrawable(),
glxcontext
};
XrSessionCreateInfo sessionCreateInfo {
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO,
sessionCreateInfo.next = &graphicsBinding,
sessionCreateInfo.createFlags = 0,
sessionCreateInfo.systemId = xr_system
};
XrResult sessionInit = xrCreateSession(xr_instance, &sessionCreateInfo, &xr_session);
if (sessionInit != XR_SUCCESS) {
mprintf(("Failed to create OpenXR session with code %d\n", static_cast<int>(sessionInit)));
return false;
}
return true;
}
#endif
int64_t gr_opengl_openxr_get_swapchain_format(const SCP_vector<int64_t>& allowed) {
//We prefer whatever our backbuffer is
if (std::find(allowed.cbegin(), allowed.cend(), GL_RGBA16F) != allowed.cend())
return GL_RGBA16F;
//Otherwise, Fallback
return allowed.front();
}
//PIPELINE FUNCTIONS OGL
std::array<SCP_vector<XrSwapchainImageOpenGLKHR>, 2> swapchainImages;
GLuint xr_fbo;
GLuint xr_swap_tex;
bool gr_opengl_openxr_acquire_swapchain_buffers() {
// create framebuffer
glGenFramebuffers(1, &xr_fbo);
GL_state.BindFrameBuffer(xr_fbo);
opengl_set_object_label(GL_FRAMEBUFFER, xr_fbo, "XR Swapchain");
//While blitting from the backbuffer is fine for the 3d-scenes, when we render a flat scene, we need to bind the backbuffer as a texture.
//Since that doesn't work, we need an intermediary. Not pretty, but it doesn't need to be for the flat scenes
glGenTextures(1, &xr_swap_tex);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(xr_swap_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gr_screen.max_w, gr_screen.max_h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, xr_swap_tex, 0);
opengl_set_object_label(GL_TEXTURE, xr_swap_tex, "XR Swap Texture");
for (uint32_t i = 0; i < 2; i++) {
uint32_t imageCount = 0;
XrResult swapchainAcq = xrEnumerateSwapchainImages(xr_swapchains[i]->swapchain, 0, &imageCount, nullptr);
if (swapchainAcq != XR_SUCCESS) {
mprintf(("Failed to acquire OpenXR swapchain %d with code %d\n", i, static_cast<int>(swapchainAcq)));
return false;
}
swapchainImages[i] = SCP_vector<XrSwapchainImageOpenGLKHR>(imageCount, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR, nullptr, 0 });
swapchainAcq = xrEnumerateSwapchainImages(xr_swapchains[i]->swapchain, imageCount, &imageCount, (XrSwapchainImageBaseHeader*)swapchainImages[i].data());
if (swapchainAcq != XR_SUCCESS) {
mprintf(("Failed to acquire OpenXR swapchain %d with code %d\n", i, static_cast<int>(swapchainAcq)));
return false;
}
}
return true;
}
bool gr_opengl_openxr_flip() {
if (!openxr_enabled())
return false;
static bool was_multiframe = false;
//If a stereoscopic frame has started, we're good. Otherwise, this is a normal frame that still needs to be OpenXR-Initialized
//In addition, since we don't actually blit one backbuffer per eye in monoframe mode, we need to make a copy of it to a readable texture now.
if (xr_stage == OpenXRFBStage::NONE) {
openxr_start_frame();
GR_DEBUG_SCOPE("XR Blit");
GL_state.PushFramebufferState();
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_READ_FRAMEBUFFER);
GL_state.BindFrameBuffer(xr_fbo, GL_DRAW_FRAMEBUFFER);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, xr_swap_tex, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_BACK);
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, gr_screen.max_w, gr_screen.max_h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glDrawBuffer(GL_NONE);
GL_state.PopFramebufferState();
if (was_multiframe) {
openxr_reset_offset();
was_multiframe = false;
}
}
else
was_multiframe = true;
uint32_t startFrame = xr_stage == OpenXRFBStage::SECOND ? 1 : 0;
uint32_t endFrame = xr_stage == OpenXRFBStage::FIRST ? 1 : 2;
for (uint32_t i = startFrame; i < endFrame; i++) {
XrSwapchain swapchain = xr_swapchains[i]->swapchain;
XrSwapchainImageAcquireInfo acquireImageInfo {
XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO,
nullptr
};
uint32_t activeIndex;
xrAcquireSwapchainImage(swapchain, &acquireImageInfo, &activeIndex);
XrSwapchainImageWaitInfo waitImageInfo{
waitImageInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO,
nullptr,
waitImageInfo.timeout = std::numeric_limits<int64_t>::max()
};
xrWaitSwapchainImage(swapchain, &waitImageInfo);
const XrSwapchainImageOpenGLKHR& image = swapchainImages[i][activeIndex];
//Monoframe mode: We only have one image that FSO just tried to flip. We have it in a readable texture which we'll now render as a flat plane in a fake 3D scene directly to the swapchain
if (xr_stage == OpenXRFBStage::NONE) {
GR_DEBUG_SCOPE("XR Plane");
GL_state.PushFramebufferState();
GL_state.BindFrameBuffer(xr_fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, image.image, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
GL_state.Texture.Enable(0, GL_TEXTURE_2D, xr_swap_tex);
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_COPY_WORLD, 0));
Current_shader->program->Uniforms.setTextureUniform("tex", 0);
const auto& pos = xr_views[i].pose.position;
const auto& ori = xr_views[i].pose.orientation;
vec3d position{{ { pos.x, pos.y, -pos.z } }};
position -= xr_offset;
matrix orientation;
vm_quaternion_to_matrix(&orientation, ori.x, ori.y, -ori.z, -ori.w);
gr_set_clip(0, 0, xr_swapchains[i]->width, xr_swapchains[i]->height, GR_RESIZE_REPLACE);
gr_set_proj_matrix(asymmetric_fov {
xr_views[i].fov.angleLeft,
xr_views[i].fov.angleRight,
xr_views[i].fov.angleUp,
xr_views[i].fov.angleDown
}, i2fl(xr_swapchains[i]->width) / i2fl(xr_swapchains[i]->height), 0.01f, 1000);
gr_set_view_matrix(&position, &orientation);
glViewport(0, 0, xr_swapchains[i]->width, xr_swapchains[i]->height);
GL_state.ScissorTest(GL_FALSE);
GL_state.SetZbufferType(gr_zbuffer_type::ZBUFFER_TYPE_NONE);
GLfloat v[4][5] = {
{
-2.0f * gr_screen.clip_aspect, -2.0f, 4, 0, 0
},
{
2.0f * gr_screen.clip_aspect, -2.0f, 4, 1, 0
},
{
2.0f * gr_screen.clip_aspect, 2.0f, 4, 1, 1
},
{
-2.0f * gr_screen.clip_aspect, 2.0f, 4, 0, 1
}
};
vertex_layout vert_def;
vert_def.add_vertex_component(vertex_format_data::POSITION3, sizeof(GLfloat) * 5, 0);
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 5, sizeof(GLfloat) * 3);
gr_matrix_set_uniforms();
gr_set_clear_color(20, 20, 20);
gr_clear();
gr_set_clear_color(0, 0, 0);
opengl_render_primitives_immediate(PRIM_TYPE_TRIFAN, &vert_def, 4, v, sizeof(v));
//And if we have a curser, it also needs to be put onscreen manually
if (io::mouse::CursorManager::get()->isCursorShown()) {
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_COPY_WORLD, SDR_FLAG_COPY_FROM_ARRAY));
Current_shader->program->Uniforms.setTextureUniform("tex", 0);
float u_scale, v_scale;
uint32_t array_index;
int mouse_bm = io::mouse::CursorManager::get()->getCurrentCursor()->getBitmapHandle();
int mousex, mousey, mousew, mouseh;
bm_get_info(mouse_bm, &mousew, &mouseh);
gr_opengl_tcache_set(mouse_bm, TCACHE_TYPE_INTERFACE, &u_scale, &v_scale, &array_index);
mouse_get_pos(&mousex, &mousey);
float mouse_unscaled_x = i2fl(mousex) / i2fl(gr_screen.max_w) * 2.0f - 1.0f;
float mouse_unscaled_y = i2fl(mousey) / i2fl(gr_screen.max_h) * -2.0f + 1.0f;
float mouse_unscaled_w = i2fl(mousew) / i2fl(gr_screen.max_w);
float mouse_unscaled_h = i2fl(mouseh) / i2fl(gr_screen.max_h);
float left = 2.0f * gr_screen.clip_aspect * mouse_unscaled_x;
float right = left + 4.0f * gr_screen.clip_aspect * mouse_unscaled_w;
float top = 2.0f * mouse_unscaled_y;
float bottom = top - 4.0f * mouse_unscaled_h;
GLfloat vmouse[4][5] = {
{
left, bottom, 4, 0, 1
},
{
right, bottom, 4, 1, 1
},
{
right, top, 4, 1, 0
},
{
left, top, 4, 0, 0
}
};
opengl_render_primitives_immediate(PRIM_TYPE_TRIFAN, &vert_def, 4, vmouse, sizeof(vmouse));
}
gr_end_proj_matrix();
gr_end_view_matrix();
gr_reset_clip();
glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
GL_state.Texture.Enable(0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0);
glDrawBuffer(GL_NONE);
GL_state.PopFramebufferState();
}
//If we are in stereo mode, we just need to take the current backbuffer and blit it to the proper swapchain target
else {
GR_DEBUG_SCOPE("XR Blit");
GL_state.PushFramebufferState();
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_READ_FRAMEBUFFER);
GL_state.BindFrameBuffer(xr_fbo, GL_DRAW_FRAMEBUFFER);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, image.image, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_BACK);
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, xr_swapchains[i]->width, xr_swapchains[i]->height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0);
glDrawBuffer(GL_NONE);
GL_state.PopFramebufferState();
}
XrSwapchainImageReleaseInfo releaseImageInfo {
XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO,
nullptr
};
xrReleaseSwapchainImage(swapchain, &releaseImageInfo);
}
switch (xr_stage) {
case OpenXRFBStage::FIRST:
//We just rendered the first part of a stereo image. We now need to follow up with another one for the other eye
xr_stage = OpenXRFBStage::SECOND;
return true;
case OpenXRFBStage::SECOND:
case OpenXRFBStage::NONE:
//We just rendered the second part of a stereo image or a mono image. Barring further instruction, the next image may be mono again.
//Also, since that means we're done with whatever we just rendered, finish this frame
xr_stage = OpenXRFBStage::NONE;
break;
}
XrCompositionLayerProjectionView projectedViews[2];
for (uint32_t i = 0; i < 2; i++)
{
projectedViews[i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
projectedViews[i].next = nullptr;
projectedViews[i].pose = xr_views[i].pose;
projectedViews[i].fov = xr_views[i].fov;
projectedViews[i].subImage = {
xr_swapchains[i]->swapchain,
{
{ 0, 0 },
{ (int32_t)xr_swapchains[i]->width, (int32_t)xr_swapchains[i]->height }
},
0
};
}
XrCompositionLayerProjection layer {
XR_TYPE_COMPOSITION_LAYER_PROJECTION,
nullptr,
0,
xr_space,
2,
projectedViews
};
auto pLayer = (const XrCompositionLayerBaseHeader*)&layer;
XrFrameEndInfo frameEndInfo {
XR_TYPE_FRAME_END_INFO,
nullptr,
xr_state.predictedDisplayTime,
XR_ENVIRONMENT_BLEND_MODE_OPAQUE,
0,
nullptr
};
if (xr_state.shouldRender) {
frameEndInfo.layerCount = 1;
frameEndInfo.layers = &pLayer;
}
xrEndFrame(xr_session, &frameEndInfo);
return false;
}
#else
//Stubs for Mac, as linking with OpenXR causes issues there.
SCP_vector<const char*> gr_opengl_openxr_get_extensions() { return SCP_vector<const char*>{}; }
bool gr_opengl_openxr_test_capabilities() { return false; }
bool gr_opengl_openxr_create_session() { return false; }
int64_t gr_opengl_openxr_get_swapchain_format(const SCP_vector<int64_t>& allowed) { return 0; }
bool gr_opengl_openxr_acquire_swapchain_buffers() { return false; }
bool gr_opengl_openxr_flip() { return false; }
#endif
-8
View File
@@ -1,8 +0,0 @@
#pragma once
SCP_vector<const char*> gr_opengl_openxr_get_extensions();
bool gr_opengl_openxr_test_capabilities();
bool gr_opengl_openxr_create_session();
int64_t gr_opengl_openxr_get_swapchain_format(const SCP_vector<int64_t>& allowed);
bool gr_opengl_openxr_acquire_swapchain_buffers();
bool gr_opengl_openxr_flip();
Loaded 100 of 782 files, more files were not shown because too many files have changed in this diff. Show more