Compare commits

..
Author SHA1 Message Date
SirKnightly 504108603d Automated build commit 2023-10-14 02:16:58 +00:00
939 changed files with 10945 additions and 85181 deletions

No files matched your search

+40 -40
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-1ff82e8
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-9
ENABLE_QTFRED: OFF
COMPILER: gcc-5
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,39 +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: Sign builds
working-directory: ./build/bin
run: |
# make sure OpenAL framework is signed
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
# make sure dylibs are signed
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
# sign binaries
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
# sign apps
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
- 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
@@ -307,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
+72 -49
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,64 @@ 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-1ff82e8
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-9
ENABLE_QTFRED: OFF
COMPILER: gcc-5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
@@ -76,7 +121,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.
@@ -100,16 +145,15 @@ jobs:
with:
submodules: true
fetch-depth: '0' # value 0 to fetch all history and tags for all branches
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 +164,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 }}
@@ -147,7 +191,6 @@ jobs:
name: Checkout
with:
submodules: true
ref: '${{ github.ref }}'
# - name: Cache Qt
# # Cache Qt
# id: cache-qt-win
@@ -220,7 +263,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/*
@@ -242,15 +285,15 @@ jobs:
with:
submodules: true
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 +308,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 +333,7 @@ jobs:
matrix:
configuration: [FastDebug, Release]
compiler: [clang]
arch: [x86_64, arm64]
arch: [x86_64]
name: Mac
needs: create_release
runs-on: macos-latest
@@ -314,7 +357,6 @@ jobs:
with:
submodules: true
fetch-depth: 0
ref: '${{ github.ref }}'
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
@@ -327,7 +369,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,39 +377,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: Sign builds
working-directory: ./build/bin
run: |
# make sure OpenAL framework is signed
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
# make sure dylibs are signed
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
# sign binaries
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
# sign apps
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
- 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
@@ -377,28 +402,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 }}
+59
View File
@@ -0,0 +1,59 @@
name: Publish Standalone docker image
on:
push:
tags:
- 'nightly_*'
- 'release_*'
jobs:
build_images:
if: github.repository == 'scp-fs2open/fs2open.github.com'
strategy:
matrix:
configuration: [FastDebug, Release]
include:
- configuration: FastDebug
tag_suffix: -debug
- configuration: Release
tag_suffix: ""
fail-fast: false
runs-on: ubuntu-latest
steps:
- 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: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
with:
images: ghcr.io/scp-fs2open/standalone_server
tag-latest: false
- name: Login to GitHub Docker Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./docker/standalone/Dockerfile
push: true
tags: ${{ steps.docker_meta.outputs.tags }}${{ matrix.tag_suffix }}
labels: ${{ steps.docker_meta.outputs.labels }}
build-args: |
build_type=${{ matrix.configuration }}
+40 -40
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-1ff82e8
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-9
ENABLE_QTFRED: OFF
COMPILER: gcc-5
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,39 +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: Sign builds
working-directory: ./build/bin
run: |
# make sure OpenAL framework is signed
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
# make sure dylibs are signed
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
# sign binaries
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
# sign apps
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
- 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
@@ -320,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-9, 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-1ff82e8
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-9, 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-1ff82e8
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,69 +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!
# keep this from running on everyone's fork
# if: github.ref == 'refs/heads/master'
#This mode is for testing
#on: [push, pull_request]
# In production, push on a specific schedule
on:
schedule:
- cron: "57 18 * * *" # Run once per a week on Friday morning (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: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v1
with:
submodules: true # `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: FastDebug
COMPILER: gcc-9
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)
+12 -20
View File
@@ -1,16 +1,17 @@
#!/usr/bin/env bash
if [ "$COMPILER" = "gcc-9" ]; then
export CC=gcc-9
export CXX=g++-9
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,
+7 -8
View File
@@ -7,15 +7,15 @@ PLACEHOLDER
[b]Deprecations:[/b]
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. Any features listed under Deprecations will be removed or changed when the target version of a mod is at least the version released in this post.
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=99015.0]23.2.1 Release Thread[/url][/size]
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98682.0]23.0.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://knossosnet.github.io/Knossos-Release-Page/]Knossos.NET[/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=94068.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] (legacy project for a unified launcher)
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)
[b]Important:[/b] For best compatibility with FSO 3.8 and later you should use at least wxLauncher 0.12.
Windows: [url=http://scp.fsmods.net/builds/Launcher55g.zip]Launcher 5.5g[/url] ([url=https://scp.indiegames.us/builds/Launcher55g.zip]Mirror[/url]) ([url=https://www.mediafire.com/?wdvzn7hhhzh418m]Mirror[/url]) Not compatible with Windows 8+, use wxLauncher above
@@ -41,7 +41,7 @@ Linux: [url=https://www.hard-light.net/forums/index.php/topic,53206.0.html]YAL[
[b]What are those SSE, SSE2 and AVX builds I keep seeing everywhere?[/b]
[url=https://www.hard-light.net/forums/index.php?topic=65628.0]Your answer is in this topic.[/url]
Don't want to deal with that? Use [url=https://knossosnet.github.io/Knossos-Release-Page/]Knossos.NET[/url] and it will download the best build specifically for your PC!
Don't want to deal with that? Use [url=https://www.hard-light.net/forums/index.php?topic=94068.0]Knossos[/url] and it will download the best build specifically for your PC!
[/hidden]
[img]https://scp.indiegames.us/img/linux-icon.png[/img] [color=green][size=12pt]Linux 64-bit[/size][/color]
@@ -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
@@ -6,7 +6,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
include("${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 24)
set_if_not_defined(FSO_VERSION_MAJOR 23)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_BUILD 0)
@@ -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})
+1 -1
View File
@@ -47,7 +47,7 @@ ProgramInstance::ProgramInstance(const actions::Program* program) : _program(pro
ProgramState ProgramInstance::step()
{
if (!_locals.host.isValid()) {
if (!_locals.host.IsValid()) {
return ProgramState::Done;
}
+23 -14
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 );
@@ -597,8 +602,8 @@ extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, v
extern int is_instructor(object *objp);
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1);
float ai_get_weapon_speed(const ship_weapon *swp);
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, const vec3d *gun_pos, const object *pobjp, const vec3d *enemy_pos, const vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
float ai_get_weapon_speed(ship_weapon *swp);
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, vec3d *gun_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
// function to change rearm status for ai ships (called from sexpression code)
extern void ai_set_rearm_status( int team, int new_status );
@@ -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);
-4
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,9 +156,6 @@ namespace AI {
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
Player_orders_afterburn_hard,
Hudsquadmsg_tactical_disarm_disable,
Align_to_target_when_guarding_still,
NUM_VALUES
};
+5 -16
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,12 +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, "$player orders afterburn hard:", AI::Profile_Flags::Player_orders_afterburn_hard);
set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
set_flag(profile, "$align to target when guarding stationary ship:", AI::Profile_Flags::Align_to_target_when_guarding_still);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
{
@@ -820,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);
}
}
+12 -11
View File
@@ -76,7 +76,7 @@ extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d
// If truly_random flag set (haha), then generate a pretty random number. Otherwise, generate a static rand which
// tends to not change from frame to frame.
// Try four times and choose nearest point to increase chance of getting a good point.
void ai_bpap(const object *objp, const vec3d *attacker_objp_pos, const vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal, const ship_subsys *ss)
void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal, ship_subsys *ss)
{
float nearest_dist;
vec3d result_point, best_point;
@@ -193,7 +193,7 @@ done_1:
//
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const vec3d *gpos, const vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
{
if (!timestamp_elapsed(ssp->turret_pick_big_attack_point_timestamp)) {
vec3d result_point;
@@ -213,7 +213,7 @@ void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
// Note, attacker_objp can be a ship or a weapon.
void ai_big_pick_attack_point(const object *objp, const object *attacker_objp, vec3d *attack_point, float fov)
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov)
{
Assert(objp->instance > -1);
Assert(objp->type == OBJ_SHIP);
@@ -411,7 +411,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
}
}
if ( ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, true) ) {
if ( ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 1) ) {
subsys_in_sight = 1;
}
}
@@ -538,15 +538,15 @@ 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, false))
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 0))
return false;
// 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]) {
@@ -1034,7 +1035,7 @@ void ai_big_chase()
ai_big_pick_attack_point(En_objp, Pl_objp, &enemy_pos, 0.8f);
weapon_info* wip = ai_get_weapon(&shipp->weapons);
bool ballistic_aiming = !IS_VEC_NULL(&The_mission.gravity) && wip && wip->gravity_const != 0.0f;
bool ballistic_aiming = !IS_VEC_NULL(&The_mission.gravity) && wip->gravity_const != 0.0f;
bool valid_ballistic_trajectory = true;
if (!ballistic_aiming) {
@@ -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;
}
+2 -2
View File
@@ -24,8 +24,8 @@ void ai_big_subsys_path_cleanup(ai_info *aip);
void ai_big_strafe();
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
void ai_big_pick_attack_point(const object *objp, const object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const vec3d *gpos, const vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
// default distance for following subsystem path points --wookieejedi
// the value is 5 because that was the original value specified in ai_big_maybe_follow_subsys_path()
+285 -382
View File
File diff suppressed because it is too large. Load diff
+156 -172
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) );
@@ -751,9 +737,6 @@ void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_
if ( target_name != NULL )
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
if (The_mission.ai_profile->flags[AI::Profile_Flags::Player_orders_afterburn_hard])
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
// special case certain orders from player so that ships continue to do the right thing
@@ -818,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) );
@@ -835,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;
@@ -859,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;
@@ -880,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];
@@ -904,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;
@@ -918,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;
}
@@ -956,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))) );
@@ -1003,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 );
@@ -1049,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;
}
@@ -1090,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))) );
@@ -1116,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!");
@@ -1156,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);
}
@@ -1174,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);
}
@@ -1182,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);
}
@@ -1261,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:
@@ -1297,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:
@@ -1340,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;
@@ -1465,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 );
@@ -1517,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;
}
@@ -1557,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)
@@ -1572,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;
@@ -1595,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);
@@ -1652,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;
}
@@ -1664,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;
}
@@ -1722,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;
}
@@ -1791,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;
@@ -1813,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;
}
@@ -1839,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);
@@ -1875,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.
@@ -1953,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);
@@ -1968,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);
@@ -1977,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));
@@ -1998,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:
@@ -2017,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;
}
@@ -2029,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!!!
@@ -2066,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;
@@ -2340,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!!!!
@@ -2422,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.
@@ -2520,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
@@ -2551,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;
}
@@ -2578,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:
@@ -2654,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 );
+7 -7
View File
@@ -14,24 +14,24 @@
#include "weapon/weapon.h"
//Returns true if the specified object is a stealth ship, false if not
bool is_object_stealth_ship(const object* objp);
bool is_object_stealth_ship(object* objp);
//Number of live turrets on the object attacking
int num_turrets_attacking(const object *turret_parent, int target_objnum);
int num_turrets_attacking(object *turret_parent, int target_objnum);
//Determine whether an object is targetable within a nebula (checks for stealth)
bool object_is_targetable(const object *target, const ship *viewer);
int object_is_targetable(object *target, ship *viewer);
//Returns the number of enemy fighters within threshold of pos.
int num_nearby_fighters(int enemy_team_mask, const vec3d *pos, float threshold);
int num_nearby_fighters(int enemy_team_mask, vec3d *pos, float threshold);
//Returns true if OK for *aip to fire its current weapon at its current target.
bool check_ok_to_fire(int objnum, int target_objnum, const weapon_info *wip, int secondary_bank, const vec3d *firing_pos_global);
int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int secondary_bank, ship_subsys* turret);
//Returns true if *aip has a line of sight to its current target.
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, const vec3d *firing_pos_global);
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, ship_subsys* turret);
//Does all the stuff needed to aim and fire a turret.
void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss);
void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss);
#endif
+6 -169
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];
@@ -389,7 +226,7 @@ ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum){
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::USERDATA) {
scripting::api::enum_h enumData;
retVals[0].getValue(scripting::api::l_Enum.Get(&enumData));
if (!enumData.isValid()) {
if (!enumData.IsValid()) {
Error(LOCATION, "LuaAI SEXP achievability hook returned an invalid avilability enum.");
return ai_achievability::ACHIEVABLE;
}
-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);
+244 -179
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
@@ -118,9 +118,9 @@ void turret_instance_find_world_orient(matrix* out_mat, int model_instance_num,
* @param tpos Turret initial position
* @param dist Distance from turret to center point of object
*
* @return true if objp is in fov of the specified turret. Otherwise return false.
* @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;
@@ -175,9 +175,9 @@ bool object_in_turret_fov(const object *objp, const ship_subsys *ss, const vec3d
* @param bomb_objp Bomb specified
* @param ship_objp Ship specified
*
* @return true if bomb_objp is headed towards ship_objp
* @return 1 if bomb_objp is headed towards ship_objp
*/
bool bomb_headed_towards_ship(const object *bomb_objp, const object *ship_objp)
int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
{
float dot;
vec3d bomb_to_ship_vector;
@@ -185,7 +185,11 @@ bool bomb_headed_towards_ship(const object *bomb_objp, const object *ship_objp)
vm_vec_normalized_dir(&bomb_to_ship_vector, &ship_objp->pos, &bomb_objp->pos);
dot = vm_vec_dot(&bomb_objp->orient.vec.fvec, &bomb_to_ship_vector);
return ( dot > 0 );
if ( dot > 0 ) {
return 1;
}
return 0;
}
// Set active weapon for turret
@@ -197,7 +201,7 @@ bool bomb_headed_towards_ship(const object *bomb_objp, const object *ship_objp)
* @note All non-negative return values are expressed in what I like to call "widx"s.
* @return -1 if unable to find a weapon for the target at all.
*/
int turret_select_best_weapon(const ship_subsys *turret, const object * /*target*/)
int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
{
//TODO: Fill this out with extraodinary gun-picking algorithms
if(turret->weapons.num_primary_banks > 0)
@@ -211,7 +215,7 @@ int turret_select_best_weapon(const ship_subsys *turret, const 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++)
@@ -228,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++)
@@ -249,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);
@@ -275,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);
@@ -303,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);
@@ -331,7 +335,7 @@ bool turret_weapon_has_subtype(const ship_weapon *swp, int subtype)
*
* @return a pointer to the Weapon_info for weapon_num
*/
const weapon_info *get_turret_weapon_wip(const ship_weapon *swp, int weapon_num)
weapon_info *get_turret_weapon_wip(ship_weapon *swp, int weapon_num)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
Assert(weapon_num >= 0);
@@ -348,7 +352,7 @@ const weapon_info *get_turret_weapon_wip(const ship_weapon *swp, int weapon_num)
return &Weapon_info[wi_index];
}
int get_turret_weapon_next_fire_stamp(const ship_weapon *swp, int weapon_num)
int get_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
Assert(weapon_num >= 0);
@@ -375,7 +379,7 @@ void set_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num, int del
*
* @todo This function is kinda slow
*/
float longest_turret_weapon_range(const ship_weapon *swp)
float longest_turret_weapon_range(ship_weapon *swp)
{
float longest_range_so_far = 0.0f;
float weapon_range;
@@ -488,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;
@@ -766,10 +770,12 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
* @param laser_flag
* @param missile_flag
*/
int get_nearest_turret_objnum(int turret_parent_objnum, const ship_subsys *turret_subsys, int enemy_team_mask, const vec3d *tpos, const 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)
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;
auto swp = &turret_subsys->weapons;
ship_weapon *swp = &turret_subsys->weapons;
// list of stuff to go thru
ship_obj *so;
@@ -782,7 +788,10 @@ int get_nearest_turret_objnum(int turret_parent_objnum, const ship_subsys *turre
// 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;
@@ -814,6 +823,18 @@ int get_nearest_turret_objnum(int turret_parent_objnum, const ship_subsys *turre
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;
@@ -1043,7 +1064,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, const ship_subsys *turre
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.
}
}
}
@@ -1063,7 +1084,7 @@ DCF_BOOL(use_parent_target, Use_parent_target)
* @param tvec Forward vector of turret (world coords)
* @param current_enemy Objnum of current turret target
*/
int find_turret_enemy(const ship_subsys *turret_subsys, int objnum, const vec3d *tpos, const vec3d *tvec, int current_enemy)
int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d *tvec, int current_enemy)
{
int enemy_team_mask, enemy_objnum;
ship_info *sip;
@@ -1083,7 +1104,7 @@ int find_turret_enemy(const ship_subsys *turret_subsys, int objnum, const 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) {
@@ -1150,9 +1171,9 @@ int find_turret_enemy(const ship_subsys *turret_subsys, int objnum, const 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;
}
}
@@ -1184,6 +1205,8 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
model_instance_local_to_global_dir(gvec, &tp->turret_norm, model_instance_num, tp->subobj_num, &objp->orient, true);
}
void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss);
/**
* Given an object and a turret on that object, return the actual firing point of the gun and its normal.
*
@@ -1194,44 +1217,86 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
* @param objp Pointer to object
* @param ssp Pointer to turret subsystem
* @param gpos Absolute position of gun firing point
* @param avg_origin Use virtual gun pos corresponding to the average of the firing points
* @param gvec Vector from *gpos to *targetp
* @param use_angles Use current angles
* @param targetp Absolute position of target object
* @param targetp Pointer to target object
*/
void ship_get_global_turret_gun_info(const object *objp, const ship_subsys *ssp, vec3d *gpos, bool avg_origin, vec3d *gvec, bool use_angles, const vec3d *targetp)
void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, int use_angles, vec3d *targetp)
{
vec3d *gun_pos;
vec3d * gun_pos;
model_subsystem *tp = ssp->system_info;
polymodel_instance *pmi = model_get_instance(Ships[objp->instance].model_instance_num);
polymodel *pm = model_get(pmi->model_num);
vec3d avg_gun_pos;
if (avg_origin) {
vm_vec_avg_n(&avg_gun_pos, tp->turret_num_firing_points, tp->turret_firing_point);
gun_pos = &avg_gun_pos;
} else {
gun_pos = &tp->turret_firing_point[ssp->turret_next_fire_pos % tp->turret_num_firing_points];
}
gun_pos = &tp->turret_firing_point[ssp->turret_next_fire_pos % tp->turret_num_firing_points];
model_instance_local_to_global_point(gpos, gun_pos, pm, pmi, tp->turret_gun_sobj, &objp->orient, &objp->pos);
// we might not need to calculate this
if (!gvec)
return;
if (use_angles) {
model_instance_local_to_global_dir(gvec, &tp->turret_norm, pm, pmi, tp->turret_gun_sobj, &objp->orient);
} else if (tp->flags[Model::Subsystem_Flags::Share_fire_direction]) {
vec3d avg, tmp_pos, tmp_target, enemy_point, turret_norm;
vm_vec_avg_n(&avg, tp->turret_num_firing_points, tp->turret_firing_point);
model_instance_local_to_global_point(&tmp_pos, &avg, pm, pmi, tp->turret_gun_sobj, &objp->orient, &objp->pos);
if (targetp == nullptr) {
ship* shipp = &Ships[Objects[ssp->parent_objnum].instance];
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name, shipp->ship_name);
object *lep = &Objects[ssp->turret_enemy_objnum];
int best_weapon_tidx = turret_select_best_weapon(ssp, lep);
//This turret doesn't have any good weapons
if (best_weapon_tidx < 0)
return;
weapon_info *wip = get_turret_weapon_wip(&ssp->weapons, best_weapon_tidx);
float weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
if ((ssp->targeted_subsys != nullptr) && !(ssp->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
vm_vec_unrotate(&enemy_point, &ssp->targeted_subsys->system_info->pnt, &Objects[ssp->turret_enemy_objnum].orient);
vm_vec_add2(&enemy_point, &ssp->last_aim_enemy_pos);
} else {
if ((lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge())) {
// the turret norm here is from the perspective of the base submodel, not the gun submodel
model_instance_local_to_global_dir(&turret_norm, &tp->turret_norm, pm, pmi, pm->submodel[tp->subobj_num].parent, &objp->orient);
ai_big_pick_attack_point_turret(lep, ssp, &tmp_pos, &turret_norm, &enemy_point, MIN(wip->max_speed * wip->lifetime, wip->weapon_range), tp->turret_fov);
}
else {
enemy_point = ssp->last_aim_enemy_pos;
}
}
vec3d target_moving_direction = ssp->last_aim_enemy_vel;
//Try to guess where the enemy will be, and store that spot in predicted_enemy_pos
if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) {
vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount);
}
set_predicted_enemy_pos_turret(&tmp_target, &tmp_pos, objp, &enemy_point, &target_moving_direction, wip->max_speed, ssp->turret_time_enemy_in_range * (weapon_system_strength + 1.0f) / 2.0f);
} else {
tmp_target = *targetp;
}
vm_vec_normalized_dir(gvec, &tmp_target, &tmp_pos);
} else {
Assertion(targetp != nullptr, "The targetp parameter must not be null here!");
//vector gun_pos2;
//vm_vec_add(&gun_pos2, gpos, gun_pos);
vm_vec_normalized_dir(gvec, targetp, gpos);
}
// per firingpoint based changes go here for turrets
}
/**
* Update turret aiming data based on max turret aim update delay
*/
void turret_ai_update_aim(const ai_info *aip, const object *En_Objp, ship_subsys *ss)
void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss)
{
if (Missiontime >= ss->next_aim_pos_time)
{
@@ -1246,15 +1311,26 @@ void turret_ai_update_aim(const ai_info *aip, const object *En_Objp, ship_subsys
}
}
/**
* Sets predicted enemy position. Previously done at the beginning of aifft_rotate_turret.
* Rotate a turret towards an enemy.
*
* Some obscure model thing only John Slagel knows about.
* Sets predicted enemy position.
* If the turret (*ss) has a subsystem targeted, the subsystem is used as the predicted point.
*
* @return TRUE if caller should use angles in subsequent rotations.
*/
void aifft_update_predicted_enemy_pos(const object *objp, const ship *shipp, ship_subsys *ss, const vec3d *global_gun_pos, const vec3d *global_gun_vec, const object *lep, vec3d *predicted_enemy_pos)
int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep, vec3d *predicted_enemy_pos, vec3d *gvec)
{
int ret_val __UNUSED = 0; // to be used in future, see comment @ end of function
auto pmi = model_get_instance(shipp->model_instance_num);
auto pm = model_get(pmi->model_num);
if (ss->turret_enemy_objnum != -1) {
model_subsystem *tp = ss->system_info;
vec3d target_vel;
vec3d gun_pos, gun_vec, target_vel;
//float weapon_speed;
float weapon_system_strength;
//HACK HACK HACK -WMC
//This should use the best weapon variable
@@ -1263,13 +1339,15 @@ void aifft_update_predicted_enemy_pos(const object *objp, const ship *shipp, shi
//This turret doesn't have any good weapons
if (best_weapon_tidx < 0)
return;
return 0;
auto wip = get_turret_weapon_wip(&ss->weapons, best_weapon_tidx);
weapon_info *wip = get_turret_weapon_wip(&ss->weapons, best_weapon_tidx);
// weapon_system_strength scales time enemy in range in 0..1. So, the lower this is, the worse the aiming will be.
weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
ship_get_global_turret_info(objp, tp, &gun_pos, &gun_vec);
//Update "known" position and velocity of target. Only matters if max_aim_update_delay is set.
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ss->turret_enemy_objnum], ss);
@@ -1283,7 +1361,7 @@ void aifft_update_predicted_enemy_pos(const object *objp, const ship *shipp, shi
}
} else {
if ((lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge())) {
ai_big_pick_attack_point_turret(lep, ss, global_gun_pos, global_gun_vec, &enemy_point, tp->turret_fov, MIN(wip->max_speed * wip->lifetime, wip->weapon_range));
ai_big_pick_attack_point_turret(lep, ss, &gun_pos, &gun_vec, &enemy_point, tp->turret_fov, MIN(wip->max_speed * wip->lifetime, wip->weapon_range));
} else {
enemy_point = ss->last_aim_enemy_pos;
}
@@ -1296,13 +1374,24 @@ void aifft_update_predicted_enemy_pos(const object *objp, const ship *shipp, shi
vm_vec_scale_sub2(&target_vel, &objp->phys_info.vel, wip->vel_inherit_amount);
}
if (tp->flags[Model::Subsystem_Flags::Turret_distant_firepoint] || Always_use_distant_firepoints) {
//The firing point of this turret is so far away from the its center that we should consider this for firing calculations
//This will do the enemy position prediction based on their relative position and speed to the firing point, not the turret center.
vec3d temp;
ship_get_global_turret_gun_info(objp, ss, &gun_pos, &temp, 1, nullptr);
}
if (IS_VEC_NULL(&The_mission.gravity) || wip->gravity_const == 0.0f)
set_predicted_enemy_pos_turret(predicted_enemy_pos, global_gun_pos, objp, &enemy_point, &target_vel, wip->max_speed, ss->turret_time_enemy_in_range * (weapon_system_strength + 1.0f)/2.0f);
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(global_gun_pos, &enemy_point, &target_vel, wip->max_speed, &gravity_vec, &shoot_vec)) {
*predicted_enemy_pos = *global_gun_pos + shoot_vec * 1000.0f;
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))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
}
return ret_val;
}
}
@@ -1314,54 +1403,36 @@ void aifft_update_predicted_enemy_pos(const object *objp, const ship *shipp, shi
// Add to predicted_enemy_pos value in .45 to 1.5x radius of enemy ship, so will often miss, but not by a huge amount.
vm_vec_scale_add2(predicted_enemy_pos, &rand_vec, (1.0f - weapon_system_strength)*1.5f * lep->radius);
}
}
}
/**
* Rotate a turret towards an enemy.
*
* Some obscure model thing only John Slagel knows about.
*
* @return TRUE if caller should use angles in subsequent rotations.
*/
bool aifft_rotate_turret(const object *objp, const ship *shipp, ship_subsys *ss, const vec3d *global_gun_pos, const vec3d *global_gun_vec, const vec3d *predicted_enemy_pos)
{
bool ret_val __UNUSED = false; // to be used in future, see comment @ end of function
auto pmi = model_get_instance(shipp->model_instance_num);
auto pm = model_get(pmi->model_num);
if (ss->turret_enemy_objnum != -1) {
model_subsystem *tp = ss->system_info;
//Get the normalized dir between the turret and the predicted enemy position.
//If the dot product is smaller than or equal to the turret's FOV, try and point the gun at it.
vec3d v2e;
vm_vec_normalized_dir(&v2e, predicted_enemy_pos, global_gun_pos);
vm_vec_normalized_dir(&v2e, predicted_enemy_pos, &gun_pos);
bool in_fov;
in_fov = turret_fov_test(ss, global_gun_vec, &v2e);
in_fov = turret_fov_test(ss, gvec, &v2e);
if (in_fov) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos);
} else if ((tp->flags[Model::Subsystem_Flags::Turret_reset_idle]) &&(timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, nullptr);
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
}
} else if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, nullptr);
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
}
// by default "ret_val" should be set to true for multi-part turrets, and false for single-part turrets
// but we need to keep retail behavior by default, which means always returning false unless a special
// by default "ret_val" should be set to 1 for multi-part turrets, and 0 for single-part turrets
// but we need to keep retail behavior by default, which means always returning 0 unless a special
// flag is used. the "ret_val" stuff is here is needed/wanted at a later date however.
//return ret_val;
// return false by default (to preserve retail behavior) but allow for a per-subsystem option
// return 0 by default (to preserve retail behavior) but allow for a per-subsystem option
// for using the turret normals for firing
if (ss->system_info->flags[Model::Subsystem_Flags::Fire_on_normal])
return true;
return 1;
return false;
return 0;
}
/**
@@ -1369,7 +1440,7 @@ bool aifft_rotate_turret(const object *objp, const ship *shipp, ship_subsys *ss,
*
* @return Dot product of vector from point abs_gunposp to *enemy_subsysp, if hittable
*/
float aifft_compute_turret_dot(const object *objp, const object *enemy_objp, const vec3d *abs_gunposp, const ship_subsys *turret_subsysp, const ship_subsys *enemy_subsysp)
float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunposp, ship_subsys *turret_subsysp, ship_subsys *enemy_subsysp)
{
float dot_out;
vec3d subobj_pos, vector_out;
@@ -1377,7 +1448,7 @@ float aifft_compute_turret_dot(const object *objp, const object *enemy_objp, con
vm_vec_unrotate(&subobj_pos, &enemy_subsysp->system_info->pnt, &enemy_objp->orient);
vm_vec_add2(&subobj_pos, &enemy_objp->pos);
if (ship_subsystem_in_sight(enemy_objp, enemy_subsysp, abs_gunposp, &subobj_pos, true, &dot_out, &vector_out)) {
if (ship_subsystem_in_sight(enemy_objp, enemy_subsysp, abs_gunposp, &subobj_pos, 1, &dot_out, &vector_out)) {
vec3d turret_norm;
model_instance_local_to_global_dir(&turret_norm, &turret_subsysp->system_info->turret_norm, Ships[objp->instance].model_instance_num, turret_subsysp->system_info->subobj_num, &objp->orient, true);
@@ -1431,7 +1502,7 @@ DCF(mf, "Adjusts the maximum number of tries an AI may do when trying to pick a
*
* @return Dot product from turret to subsystem in *dot_out
*/
ship_subsys *aifft_find_turret_subsys(const object *objp, const ship_subsys *ssp, const vec3d *global_gun_pos, const object *enemy_objp, float *dot_out)
ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *enemy_objp, float *dot_out)
{
ship *eshipp, *shipp;
ship_info *esip;
@@ -1448,6 +1519,10 @@ ship_subsys *aifft_find_turret_subsys(const object *objp, const ship_subsys *ssp
float best_dot = 0.0f;
*dot_out = best_dot;
// Compute absolute gun position.
vec3d abs_gun_pos;
ship_get_global_turret_info(objp, ssp->system_info, &abs_gun_pos, nullptr);
// Only pick a turret to attack on large ships.
if (!esip->is_big_or_huge())
return best_subsysp;
@@ -1503,7 +1578,7 @@ ship_subsys *aifft_find_turret_subsys(const object *objp, const ship_subsys *ssp
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;
@@ -1513,7 +1588,7 @@ ship_subsys *aifft_find_turret_subsys(const object *objp, const ship_subsys *ssp
}
for(idx=offset; idx<aifft_list_size; idx+=stride){
dot = aifft_compute_turret_dot(objp, enemy_objp, global_gun_pos, ssp, aifft_list[idx]);
dot = aifft_compute_turret_dot(objp, enemy_objp, &abs_gun_pos, ssp, aifft_list[idx]);
if ((dot - dot_fov_modifier)* aifft_rank[idx] > best_dot) {
best_dot = (dot - dot_fov_modifier)*aifft_rank[idx];
@@ -1528,17 +1603,34 @@ ship_subsys *aifft_find_turret_subsys(const object *objp, const ship_subsys *ssp
}
/**
* @return true if the specified target should scan for a new target, otherwise return false
* @return !0 if the specified target should scan for a new target, otherwise return 0
*/
bool turret_should_pick_new_target(ship_subsys *turret)
int turret_should_pick_new_target(ship_subsys *turret)
{
return timestamp_elapsed(turret->turret_next_enemy_check_stamp);
// int target_type;
if ( timestamp_elapsed(turret->turret_next_enemy_check_stamp) ) {
return 1;
}
/*
if ( turret->turret_enemy_objnum == -1 ) {
return 1;
}
target_type = Objects[turret->turret_enemy_objnum].type;
if ( (target_type != OBJ_SHIP) && (target_type != OBJ_ASTEROID) ) {
return 1;
}
*/
return 0;
}
/**
* Set the next fire timestamp for a turret, based on weapon type and ai class
*/
void turret_set_next_fire_timestamp(int weapon_num, const weapon_info *wip, ship_subsys *turret, const ai_info *aip)
void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsys *turret, ai_info *aip)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
float wait = 1000.0f;
@@ -1651,13 +1743,13 @@ void turret_set_next_fire_timestamp(int weapon_num, const weapon_info *wip, ship
/**
* Decide if a turret should launch an aspect seeking missile
*/
bool turret_should_fire_aspect(const ship_subsys *turret, const weapon_info *wip, bool in_sight)
int turret_should_fire_aspect(ship_subsys *turret, weapon_info *wip, bool in_sight)
{
if ( in_sight && (turret->turret_time_enemy_in_range >= MIN(wip->min_lock_time,AICODE_TURRET_MAX_TIME_IN_RANGE)) ) {
return true;
return 1;
}
return false;
return 0;
}
/**
@@ -1679,9 +1771,9 @@ void turret_update_enemy_in_range(ship_subsys *turret, float seconds)
/**
* Fire a weapon from a turret
*/
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, const vec3d *orig_firing_pos, const vec3d *orig_firing_vec, const vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true)
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *firing_vec, vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true)
{
matrix firing_orient;
matrix turret_orient;
int weapon_objnum;
ai_info *parent_aip;
ship *parent_ship;
@@ -1743,21 +1835,16 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
#endif
if (check_ok_to_fire(parent_objnum, turret->turret_enemy_objnum, wip, -1, orig_firing_pos)) {
if (check_ok_to_fire(parent_objnum, turret->turret_enemy_objnum, wip, -1, turret)) {
auto turret_enemy_objp = (turret->turret_enemy_objnum >= 0) ? &Objects[turret->turret_enemy_objnum] : nullptr;
ship_weapon* swp = &turret->weapons;
turret->turret_last_fire_direction = *orig_firing_vec;
turret->turret_last_fire_direction = *firing_vec;
const vec3d *firing_vec = orig_firing_vec;
vec3d firing_vec_buf;
if (turret->turret_inaccuracy > 0.0f)
vm_vec_random_cone(firing_vec, firing_vec, turret->turret_inaccuracy);
if (turret->turret_inaccuracy > 0.0f) {
vm_vec_random_cone(&firing_vec_buf, firing_vec, turret->turret_inaccuracy);
firing_vec = &firing_vec_buf;
}
vm_vector_2_matrix(&firing_orient, firing_vec, nullptr, nullptr);
vm_vector_2_matrix(&turret_orient, firing_vec, nullptr, nullptr);
// grab and set some burst data before turret_set_next_fire_timestamp wipes it
int old_burst_seed = swp->burst_seed[weapon_num];
@@ -1936,15 +2023,11 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
}
vec3d firing_pos_buf;
const vec3d *firing_pos = &firing_pos_buf;
// zookeeper - Firepoints should cycle normally between shots,
// so we need to get the position info separately for each shot
ship_get_global_turret_gun_info(&Objects[parent_objnum], turret, &firing_pos_buf, false, nullptr, true, nullptr);
ship_get_global_turret_gun_info(&Objects[parent_objnum], turret, turret_pos, firing_vec, 1, nullptr);
weapon_objnum = weapon_create(firing_pos, &firing_orient, turret_weapon_class, parent_objnum, -1, 1, 0, 0.0f, turret);
weapon_objnum = weapon_create( turret_pos, &turret_orient, turret_weapon_class, parent_objnum, -1, 1, 0,0.0f, turret);
weapon_set_tracking_info(weapon_objnum, parent_objnum, turret->turret_enemy_objnum, 1, turret->targeted_subsys);
//nprintf(("AI", "Turret_time_enemy_in_range = %7.3f\n", ss->turret_time_enemy_in_range));
@@ -1976,7 +2059,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if(predicted_pos != NULL)
{
// pick a firing range so that it detonates properly
flak_pick_range(objp, firing_pos, predicted_pos, ship_get_subsystem_strength(parent_ship, SUBSYSTEM_WEAPONS));
flak_pick_range(objp, turret_pos, predicted_pos, ship_get_subsystem_strength(parent_ship, SUBSYSTEM_WEAPONS));
// determine what that range was
flak_range = flak_get_range(objp);
@@ -1989,7 +2072,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
// do mflash if the weapon has it
if (wip->muzzle_flash >= 0) {
mflash_create(firing_pos, firing_vec, &Objects[parent_ship->objnum].phys_info, wip->muzzle_flash);
mflash_create(turret_pos, firing_vec, &Objects[parent_ship->objnum].phys_info, wip->muzzle_flash);
}
// in multiplayer (and the master), then send a turret fired packet.
@@ -2008,7 +2091,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if ( play_sound && wip->launch_snd.isValid() ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( parent_objnum != OBJ_INDEX(Player_obj) || (turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), firing_pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), turret_pos, &View_position );
}
}
}
@@ -2040,7 +2123,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
{
int weapon_objnum;
matrix firing_orient;
matrix turret_orient;
vec3d turret_pos, turret_fvec;
// parent not alive, quick out.
@@ -2053,7 +2136,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
tsi->turret->turret_next_fire_pos = tsi->weapon_num;
// change firing point
ship_get_global_turret_gun_info(&Objects[tsi->parent_objnum], tsi->turret, &turret_pos, false, &turret_fvec, true, nullptr);
ship_get_global_turret_gun_info(&Objects[tsi->parent_objnum], tsi->turret, &turret_pos, &turret_fvec, 1, NULL);
tsi->turret->turret_next_fire_pos++;
//check if this really is a swarm. If not, how the hell did it get here?
@@ -2068,11 +2151,11 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
turret_fvec = tsi->turret->turret_last_fire_direction;
}
// make firing_orient from turret_fvec -- turret->turret_last_fire_direction
vm_vector_2_matrix(&firing_orient, &turret_fvec, NULL, NULL);
// make turret_orient from turret_fvec -- turret->turret_last_fire_direction
vm_vector_2_matrix(&turret_orient, &turret_fvec, NULL, NULL);
// create weapon and homing info
weapon_objnum = weapon_create(&turret_pos, &firing_orient, tsi->weapon_class, tsi->parent_objnum, -1, 1, 0, 0.0f, tsi->turret);
weapon_objnum = weapon_create(&turret_pos, &turret_orient, tsi->weapon_class, tsi->parent_objnum, -1, 1, 0, 0.0f, tsi->turret);
weapon_set_tracking_info(weapon_objnum, tsi->parent_objnum, tsi->target_objnum, 1, tsi->target_subsys);
// do other cool stuff if weapon is created.
@@ -2131,7 +2214,7 @@ int Num_turrets_fired = 0;
* all turret movement and resetting when idle
*/
extern int Nebula_sec_range;
void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
{
float weapon_firing_range;
float weapon_min_range; // *Weapon minimum firing range -Et1
@@ -2215,21 +2298,12 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
objp = &Objects[shipp->objnum];
Assert(objp->type == OBJ_SHIP);
vec3d global_gun_pos, global_gun_vec;
if (tp->flags[Model::Subsystem_Flags::Turret_distant_firepoint] || Always_use_distant_firepoints) {
//The firing point of this turret is so far away from the its center that we should consider this for firing calculations
//This will do the enemy position prediction based on their relative position and speed to the firing point, not the turret center.
ship_get_global_turret_gun_info(objp, ss, &global_gun_pos, false, &global_gun_vec, true, nullptr);
} else {
// Use the turret info for all guns, not one gun in particular.
ship_get_global_turret_info(objp, tp, &global_gun_pos, &global_gun_vec);
}
// Update predicted enemy position. This used to be done in aifft_rotate_turret
aifft_update_predicted_enemy_pos(objp, shipp, ss, &global_gun_pos, &global_gun_vec, lep, &predicted_enemy_pos);
// Use the turret info for all guns, not one gun in particular.
vec3d gvec, gpos;
ship_get_global_turret_info(objp, tp, &gpos, &gvec);
// Rotate the turret even if time hasn't elapsed, since it needs to turn to face its target.
bool use_angles = aifft_rotate_turret(objp, shipp, ss, &global_gun_pos, &global_gun_vec, &predicted_enemy_pos);
int use_angles = aifft_rotate_turret(objp, shipp, ss, lep, &predicted_enemy_pos, &gvec);
// Multiplayer clients are now able to try to track their targets and also reset to their idle positions.
// But everything after this point is turret firing, so we need to bail here.
@@ -2253,20 +2327,18 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
float dist_to_enemy = 0.0f;
if (lep) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Turrets_ignore_target_radius])
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &global_gun_pos));
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos));
else
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &global_gun_pos) - lep->radius);
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius);
}
// count the number of enemies, in case we have a spawning weapon
int num_ships_nearby = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &global_gun_pos, 1500.0f);
int num_ships_nearby = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &gpos, 1500.0f);
// some flags considering there may be different weapon types on this turret
bool we_did_non_spawning_logic = false;
bool tentative_return = false;
float turret_barrel_length = -1.0f;
//WMC - go through all valid weapons. Fire spawns if there are any.
int valid_weapons[MAX_SHIP_WEAPONS];
int num_valid = 0;
@@ -2298,7 +2370,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
if ( (wip->wi_flags[Weapon::Info_Flags::Spawn]) && !(wip->wi_flags[Weapon::Info_Flags::Smart_spawn]) )
{
if (( num_ships_nearby >= 3 ) || ((num_ships_nearby >= 2) && (frand() < 0.1f))) {
turret_fire_weapon(i, ss, parent_objnum, &global_gun_pos, &ss->turret_last_fire_direction);
turret_fire_weapon(i, ss, parent_objnum, &gpos, &ss->turret_last_fire_direction);
} else {
// Regardless of firing rate, don't check whether should fire for awhile.
if (tp->flags[Model::Subsystem_Flags::Use_multiple_guns])
@@ -2346,16 +2418,10 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
// If the barrel of this turret is long, we shouldn't try to fire if the enemy is under the gun.
// Note that this isn't the same thing as min_range, which is unrelated to barrel length.
if (tp->flags[Model::Subsystem_Flags::Turret_distant_firepoint] || Always_use_distant_firepoints) {
if (turret_barrel_length < 0.0f) {
if (tp->turret_gun_sobj >= 0) {
auto pm = model_get(tp->model_num);
auto submodel = &pm->submodel[tp->turret_gun_sobj];
turret_barrel_length = 2 * submodel->rad;
} else {
turret_barrel_length = 0.0f;
}
}
if (dist_to_enemy < turret_barrel_length) continue;
vec3d fpoint, fvec;
ship_get_global_turret_gun_info(objp, ss, &fpoint, &fvec, use_angles, &predicted_enemy_pos);
auto barrel_length = vm_vec_dist(&fpoint, &gpos);
if (dist_to_enemy < barrel_length) continue;
}
// Don't try to fire beyond weapon_limit_range (or within min range)
@@ -2473,7 +2539,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
// Maybe pick a new enemy, unless targeting has been taken over by scripting
if ( turret_should_pick_new_target(ss) && !ss->scripting_target_override && !(ss->flags[Ship::Subsystem_Flags::Forced_target])) {
Num_find_turret_enemy++;
int objnum = find_turret_enemy(ss, parent_objnum, &global_gun_pos, &global_gun_vec, ss->turret_enemy_objnum);
int objnum = find_turret_enemy(ss, parent_objnum, &gpos, &gvec, ss->turret_enemy_objnum);
if (objnum >= 0) {
if (ss->turret_enemy_objnum == -1) {
@@ -2495,7 +2561,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
float dot = 1.0f;
lep = &Objects[ss->turret_enemy_objnum];
if (( lep->type == OBJ_SHIP ) && !(ss->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
ss->targeted_subsys = aifft_find_turret_subsys(objp, ss, &global_gun_pos, lep, &dot);
ss->targeted_subsys = aifft_find_turret_subsys(objp, ss, lep, &dot);
}
// recheck in 2-3 seconds
ss->turret_next_enemy_check_stamp = timestamp((int)((MAX(dot, 0.5f) * The_mission.ai_profile->turret_target_recheck_time) + (The_mission.ai_profile->turret_target_recheck_time / 2.0f)));
@@ -2536,15 +2602,14 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
return;
}
//This can't happen. See above code
//if ( lep == nullptr ){
// return;
//}
if ( lep == nullptr ){
return;
}
//This can't happen. See above code
//Assert(ss->turret_enemy_objnum != -1);
bool in_fov = turret_fov_test(ss, &global_gun_vec, &v2e);
bool in_fov = turret_fov_test(ss, &gvec, &v2e);
bool something_was_ok_to_fire = false;
// the only reason predicted_enemy_pos might be zero, while everything else is valid is if
@@ -2599,13 +2664,13 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
ship_get_global_turret_gun_info(objp, ss, &global_gun_pos, false, &global_gun_vec, use_angles, &predicted_enemy_pos);
ship_get_global_turret_gun_info(objp, ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
// Fire in the direction the turret is facing, not right at the target regardless of turret dir.
// [Yet this retail comment precedes the calculation of vector-to-enemy...]
vm_vec_sub(&v2e, &predicted_enemy_pos, &global_gun_pos);
vm_vec_sub(&v2e, &predicted_enemy_pos, &gpos);
dist_to_enemy = vm_vec_normalize(&v2e);
float dot = vm_vec_dot(&v2e, &global_gun_vec);
float dot = vm_vec_dot(&v2e, &gvec);
// (flak jitter moved to after we obtain shoot_vector below)
@@ -2670,7 +2735,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
// Check if turret should fire and enemy's engines are
// in line of sight
if (turret_should_fire_aspect(ss, wip, in_sight) &&
ship_get_closest_subsys_in_sight(&Ships[lep->signature], SUBSYSTEM_ENGINE, &global_gun_pos))
ship_get_closest_subsys_in_sight(&Ships[lep->signature], SUBSYSTEM_ENGINE, &gpos))
{
ok_to_fire = true;
}
@@ -2680,14 +2745,14 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
if ( ok_to_fire && (tp->flags[Model::Subsystem_Flags::Turret_hull_check]) ) {
int model_num = Ship_info[shipp->ship_info_index].model_num;
vec3d end;
vm_vec_scale_add(&end, &global_gun_pos, &global_gun_vec, model_get_radius(model_num));
vm_vec_scale_add(&end, &gpos, &gvec, model_get_radius(model_num));
mc_info hull_check;
hull_check.model_instance_num = shipp->model_instance_num;
hull_check.model_num = model_num;
hull_check.orient = &objp->orient;
hull_check.pos = &objp->pos;
hull_check.p0 = &global_gun_pos;
hull_check.p0 = &gpos;
hull_check.p1 = &end;
hull_check.flags = MC_CHECK_MODEL | MC_CHECK_RAY;
@@ -2727,7 +2792,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
// (Despite the retail comment above, retail actually fired toward the enemy; v2e = vector-to-enemy)
vec3d shoot_vector = v2e;
if (tp->flags[Model::Subsystem_Flags::Fire_on_normal])
shoot_vector = global_gun_vec;
shoot_vector = gvec;
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
@@ -2735,7 +2800,7 @@ void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
flak_jitter_aim(&shoot_vector, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &global_gun_pos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &gpos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
}
else
{
@@ -2804,7 +2869,7 @@ void ai_turret_execute_behavior(const 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);
@@ -2814,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);
@@ -2840,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 -20
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 {
@@ -1049,7 +1049,6 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
*/
static void maybe_throw_asteroid()
{
Assertion(Asteroid_field.num_used_field_debris_types > 0, "maybe_throw_asteroid() called while num_used_field_debris_types was 0; this should never happen, get a coder!");
for (asteroid_target& target : Asteroid_targets) {
if (!timestamp_elapsed(target.throw_stamp))
@@ -1333,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;
@@ -1361,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) {
@@ -1406,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
@@ -2239,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);
@@ -2585,11 +2581,6 @@ void asteroid_frame()
return;
}
// If no asteroid types are defined for the field, abort.
if (Asteroid_field.num_used_field_debris_types <= 0) {
return;
}
// If there are no explicit targets, fall back to default retail targeting behavior
if (Asteroid_field.target_names.empty()) {
int objnum = set_asteroid_throw_objnum();
+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;
}
+34 -106
View File
@@ -14,8 +14,8 @@
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
fov_t VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
fov_t COCKPIT_ZOOM_DEFAULT = DEFAULT_FOV;
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,36 +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)
// Used to set the default value for in-game options
static constexpr float fov_default = DEFAULT_FOV;
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
@@ -64,57 +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(std::make_pair("Graphics", 1825))
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
VIEWER_ZOOM_DEFAULT = val;
return true;
})
.display(fov_display)
.default_val(fov_default)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
bool Use_cockpit_fov = false;
auto CockpitFOVToggleOption = options::OptionBuilder<bool>("Graphics.CockpitFOVToggle",
std::pair<const char*, int>{"Cockpit FOV Toggle", 1838},
std::pair<const char*, int>{"Whether or not to use a different FOV for cockpit rendering from normal rendering", 1839})
.category(std::make_pair("Graphics", 1825))
.default_val(false)
.change_listener([](bool val, bool) {
if (!val) {
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
}
return true; // This option will always persist so we never return false
})
.level(options::ExpertLevel::Advanced)
.bind_to(&Use_cockpit_fov)
.importance(61)
.finish();
auto CockpitFovOption = options::OptionBuilder<float>("Graphics.CockpitFOV",
std::pair<const char*, int>{"Cockpit Field Of View", 1840},
std::pair<const char*, int>{"The vertical field of view for cockpit rendering. Only works if cockpits are active and cockpit FOV toggle is turned on.", 1841})
.category(std::make_pair("Graphics", 1825))
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
if (Use_cockpit_fov){
COCKPIT_ZOOM_DEFAULT = val;
} else {
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
}
return true;
})
.display(fov_display)
.default_val(fov_default)
.level(options::ExpertLevel::Advanced)
.importance(62)
.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
@@ -157,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();
@@ -176,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)
{
@@ -186,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 ) )
@@ -341,7 +272,7 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
// if we have a host, we need the difference between the camera's current orient and the orient we want
// if not, we will later set the absolute orientation, rather than the orientation relative to the host
if (object_host.isValid())
if (object_host.IsValid())
{
vm_transpose(orient);
temp_matrix = temp_matrix * *orient;
@@ -364,7 +295,7 @@ void camera::do_frame(float /*in_frametime*/)
object *camera::get_object_host()
{
if(object_host.isValid())
if(object_host.IsValid())
return object_host.objp;
else
return NULL;
@@ -377,7 +308,7 @@ int camera::get_object_host_submodel()
object *camera::get_object_target()
{
if(object_target.isValid())
if(object_target.IsValid())
return object_target.objp;
else
return NULL;
@@ -388,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;
@@ -413,7 +341,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
bool use_host_orient = false;
//POSITION
if(!(flags & CAM_STATIONARY_POS) || object_host.isValid())
if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
{
c_pos = vmd_zero_vector;
@@ -422,7 +350,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
pos_y.get(&pt.xyz.y, NULL);
pos_z.get(&pt.xyz.z, NULL);
if(object_host.isValid())
if(object_host.IsValid())
{
object *objp = object_host.objp;
int model_num = object_get_model(objp);
@@ -484,9 +412,9 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
if(orientation != NULL)
{
bool target_set = false;
if(!(flags & CAM_STATIONARY_ORI) || object_target.isValid() || object_host.isValid())
if(!(flags & CAM_STATIONARY_ORI) || object_target.IsValid() || object_host.IsValid())
{
if(object_target.isValid())
if(object_target.IsValid())
{
object *target_objp = object_target.objp;
int model_num = object_get_model(target_objp);
@@ -521,7 +449,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
target_set = true;
}
else if(object_host.isValid())
else if(object_host.IsValid())
{
if(eyep)
{
@@ -794,7 +722,7 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
//Get text size
for(int i = 0; i < num_text_lines; i++)
{
gr_get_string_size(&w, &h, text_line_ptrs[i], static_cast<size_t>(text_line_lens[i]));
gr_get_string_size(&w, &h, text_line_ptrs[i], text_line_lens[i]);
if(w > tw)
tw = w;
@@ -1051,7 +979,7 @@ int camid::getSignature()
return sig;
}
bool camid::isValid() const
bool camid::isValid()
{
if(idx >= Cameras.size())
return false;
@@ -1243,7 +1171,7 @@ vec3d normal_cache;
void get_turret_cam_pos(camera *cam, vec3d *pos)
{
object_h obj(cam->get_object_host());
if(!obj.isValid())
if(!obj.IsValid())
return;
ship* shipp = &Ships[cam->get_object_host()->instance];
ship_subsys* ssp = GET_FIRST(&shipp->subsys_list);
@@ -1251,7 +1179,7 @@ void get_turret_cam_pos(camera *cam, vec3d *pos)
{
if(ssp->system_info->subobj_num == cam->get_object_host_submodel())
{
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, true, &normal_cache, true, nullptr);
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, &normal_cache, 1, NULL);
vec3d offset = vmd_zero_vector;
offset.xyz.x = 0.0001f;
vm_vec_add2(pos, &offset); // prevent beam turrets from crashing with a nullvec
@@ -1264,7 +1192,7 @@ void get_turret_cam_pos(camera *cam, vec3d *pos)
void get_turret_cam_orient(camera *cam, matrix *ori)
{
object_h obj(cam->get_object_host());
if(!obj.isValid())
if(!obj.IsValid())
return;
vm_vector_2_matrix(ori, &normal_cache, vm_vec_same(&normal_cache, &cam->get_object_host()->orient.vec.uvec)?NULL:&cam->get_object_host()->orient.vec.uvec, NULL);
}
+5 -20
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,19 +18,6 @@
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
#define DEFAULT_FOV 0.75f;
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:
@@ -56,7 +41,7 @@ protected:
avd_movement ori[9];
//Cache stuff
fov_t c_fov;
float c_fov;
vec3d c_pos;
matrix c_ori;
public:
@@ -74,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);
@@ -89,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
@@ -170,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
+17 -19
View File
@@ -91,10 +91,12 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
};
// clang-format on
#define CFILE_STACK_MAX 8
int cfile_inited = 0;
static int Cfile_stack_pos = 0;
static SCP_vector<SCP_string> Cfile_stack;
static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
@@ -328,16 +330,17 @@ int cfile_push_chdir(int type)
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
cf_create_default_path_string(dir, type, NULL);
Assert(Cfile_stack_pos < CFILE_STACK_MAX);
int rc = _cfile_chdir(dir.c_str(), OriginalDirectory);
// if success then push the original directory on to the stack
if (rc == 0) {
Cfile_stack.push_back(OriginalDirectory);
if (Cfile_stack_pos >= CFILE_STACK_MAX) {
return -1;
}
return rc;
strcpy_s(Cfile_stack[Cfile_stack_pos++], OriginalDirectory);
cf_create_default_path_string(dir, type, NULL);
return _cfile_chdir(dir.c_str(), OriginalDirectory);
}
/**
@@ -360,16 +363,13 @@ int cfile_chdir(const char *dir)
int cfile_pop_dir()
{
if (Cfile_stack.empty())
Assert(Cfile_stack_pos);
if ( !Cfile_stack_pos )
return -1;
int rc = cfile_chdir(Cfile_stack.back().c_str());
Assertion(rc == 0, "Failed to chdir() to previous directory (%s)!", Cfile_stack.back().c_str());
Cfile_stack.pop_back();
return rc;
Cfile_stack_pos--;
return cfile_chdir(Cfile_stack[Cfile_stack_pos]);
}
// flush (delete all files in) the passed directory (by type), return the # of files deleted
@@ -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));
}
}
+72 -159
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"
@@ -40,7 +39,6 @@
#ifdef SCP_UNIX
#include "osapi/osapi.h"
#include <dirent.h>
#include <sys/stat.h>
#endif
#include <cstring>
@@ -190,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",},
@@ -198,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", },
@@ -223,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", },
@@ -269,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", },
@@ -411,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
@@ -421,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
@@ -462,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
@@ -486,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;
@@ -521,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);
@@ -561,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;
@@ -1209,133 +1195,93 @@ bool cmdline_parm::has_param() {
}
#ifdef SCP_UNIX
extern void normalize_directory_separators(SCP_string &str);
static SCP_string get_real_mod_path(const char *mod)
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// dir must not contain a slash.
static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
{
DIR *dirp;
SCP_string fullpath;
SCP_string mod_path = mod;
SCP_vector<SCP_string> ret;
normalize_directory_separators(mod_path);
fullpath = SCP_string(".") + DIR_SEPARATOR_STR;
fullpath += mod_path;
// check if path already exists
dirp = opendir(fullpath.c_str());
if (dirp) {
// found it, return unchanged
closedir(dirp);
return mod_path;
DIR *dp;
if ((dp = opendir(parent.c_str())) == NULL) {
Warning(LOCATION, "Can't open directory '%s' when searching mod paths. Ignoring. errno=%d", parent.c_str(), errno);
return ret;
}
// not found, check for a difference in case
SCP_string new_mod_path;
SCP_string part;
struct dirent *dir;
SCP_string::size_type separator;
SCP_string::size_type offset = 0;
fullpath = SCP_string(".") + DIR_SEPARATOR_STR;
do {
separator = mod_path.find(DIR_SEPARATOR_CHAR, offset);
if (separator != SCP_string::npos) {
part = mod_path.substr(offset, separator-offset);
offset += separator-offset + 1;
} else {
part = mod_path.substr(offset);
offset += part.length();
dirent *dirp;
while ((dirp = readdir(dp)) != NULL) {
if (!stricmp(dirp->d_name, dir.c_str())) {
ret.push_back(dirp->d_name);
}
}
(void)closedir(dp);
dirp = opendir(fullpath.c_str());
return ret;
}
if ( !dirp ) {
break;
}
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// Recurses to deal with slashes in dir.
static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
{
size_t slash = dir.find_first_of("/\\");
while ((dir = readdir(dirp)) != nullptr) {
if (stricmp(dir->d_name, part.c_str())) {
continue;
}
SCP_string fn = fullpath + dir->d_name;
// make sure it accessible and a directory
struct stat buf;
if (stat(fn.c_str(), &buf) == -1) {
continue;
}
if ( !S_ISDIR(buf.st_mode) ) {
continue;
}
if ( !new_mod_path.empty() ) {
new_mod_path += DIR_SEPARATOR_STR;
}
new_mod_path += dir->d_name;
fullpath += dir->d_name;
fullpath += DIR_SEPARATOR_STR;
break;
}
if (dirp) {
closedir(dirp);
}
} while (offset < mod_path.length());
// Append anything left from mod_path onto the new path. This will catch trailing separators
// as well as mod folders which don't exist so that the mod string remains unchanged except
// for the directory name case.
if (new_mod_path.length() != mod_path.length()) {
new_mod_path += mod_path.substr(new_mod_path.length());
// no subdirectories, no need to recurse
if (slash == std::string::npos) {
return unix_get_single_dir_names(parent, dir);
}
return new_mod_path;
// get the names of the first component of dir
SCP_vector<SCP_string> this_dir_names = unix_get_single_dir_names(parent, dir.substr(0, slash));
SCP_string rest = dir.substr(slash + 1);
SCP_vector<SCP_string> ret;
// search for the rest of dir in each of these
SCP_vector<SCP_string>::iterator ii, end = this_dir_names.end();
for (ii = this_dir_names.begin(); ii != end; ++ii) {
SCP_string this_dir_path = parent + "/" + *ii;
SCP_vector<SCP_string> mod_path = unix_get_dir_names(this_dir_path, rest);
// add all found paths relative to parent
SCP_vector<SCP_string>::iterator ii2, end2 = mod_path.end();
for (ii2 = mod_path.begin(); ii2 != end2; ++ii2) {
ret.push_back(*ii + "/" + *ii2);
}
}
return ret;
}
// For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
//
// NOTE: Aside from change in case no alterations should be made to the modlist. Missing
// mod folders should be left in place and no errors or warnings should be generated.
// There should be no difference between Windows and non-Windows modlist handling.
static void handle_unix_modlist(char **modlist, size_t *len)
{
// search filesystem for given paths
SCP_vector<SCP_string> mod_paths;
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ",")) {
SCP_string path = get_real_mod_path(cur_mod);
mod_paths.push_back(path);
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
{
SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
// Ignore non-existing mods for unit tests
if (!running_unittests && this_mod_paths.empty()) {
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
}
mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
}
// create new char[] to replace modlist
size_t total_len = 0;
for (auto &path : mod_paths) {
total_len += path.length() + 1;
SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
total_len += ii->length() + 1;
}
char *new_modlist = new char[total_len + 1];
memset(new_modlist, 0, total_len + 1);
for (auto &path : mod_paths) {
strcat_s(new_modlist, total_len + 1, path.c_str());
strcat_s(new_modlist, total_len + 1, ",");
end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
strcat_s(new_modlist, total_len + 1, ii->c_str());
strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
}
// remove trailing comma
new_modlist[total_len-1] = '\0';
// make the rest of the modlist manipulation unaware that anything happened here
delete [] *modlist;
*modlist = new_modlist;
@@ -1700,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';
}
}
@@ -1764,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();
}
@@ -1840,7 +1769,7 @@ bool SetCmdlineParams()
if(mod_arg.found() ) {
Cmdline_mod = mod_arg.str();
// strip off blank space if it's there
// strip off blank space it it's there
if ( Cmdline_mod[strlen(Cmdline_mod)-1] == ' ' ) {
Cmdline_mod[strlen(Cmdline_mod)-1] = '\0';
}
@@ -1900,7 +1829,7 @@ bool SetCmdlineParams()
if (val > 0.1) {
VIEWER_ZOOM_DEFAULT = val;
} else {
VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
VIEWER_ZOOM_DEFAULT = 0.75f;
}
}
@@ -1914,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;
@@ -1950,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();
@@ -1977,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;
+6 -7
View File
@@ -923,8 +923,8 @@ bool control_config_do_reset(bool cycle, bool API_Access)
// first, determine how many bindings need to be changed
for (size_t e = 0; e < Control_config.size(); ++e) {
const auto& item = Control_config[e];
const auto& default_item = default_bindings[e];
auto item = Control_config[e];
auto default_item = default_bindings[e];
if (item.disabled) {
// skip
@@ -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);
+1 -1
View File
@@ -947,7 +947,7 @@ int check_control(int id, int key = -1);
void control_get_axes_readings(int *axis_v, float frame_time);
/**
* @brief Marks the given control (by IoActionId) as used
* @brief Markes the given control (by IoActionId) as used
*
* @details Updates the ::used timestamp, triggers a script hook, and marks ::continous_ongoing as true
*/
+33 -37
View File
@@ -45,31 +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(std::make_pair("Input", 1827))
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Input", 1827))
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.flags({options::OptionFlags::RetailBuiltinOption})
.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
@@ -162,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)
@@ -177,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)
@@ -213,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)
@@ -239,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)
@@ -262,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
@@ -453,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[] = {
@@ -462,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 -14
View File
@@ -25,8 +25,6 @@
extern int Cmdline_nomovies;
bool Movie_active = false;
const char* Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
"ViewFootage",
@@ -62,18 +60,6 @@ static cutscene_info *get_cutscene_pointer(char *cutscene_filename)
return NULL;
}
int get_cutscene_index_by_name(const char* name)
{
for (int i = 0; i < static_cast<int>(Cutscenes.size()); i++) {
if (!stricmp(name, Cutscenes[i].name)) {
return i;
}
}
// Didn't find anything.
return -1;
}
static void cutscene_info_init(cutscene_info *csni)
{
csni->filename[0] = '\0';
@@ -236,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
@@ -248,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);
-4
View File
@@ -37,8 +37,6 @@ typedef struct cutscene_info
extern SCP_vector<cutscene_info> Cutscenes;
extern bool Movie_active;
// initializa table data
void cutscene_init();
@@ -50,6 +48,4 @@ void cutscenes_screen_do_frame();
void cutscene_mark_viewable(const char* filename);
int get_cutscene_index_by_name(const char* name);
#endif
-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));
-3
View File
@@ -278,7 +278,6 @@ bool play(const char* name) {
// clear the screen and hide the mouse cursor
io::mouse::CursorManager::get()->pushStatus();
io::mouse::CursorManager::get()->showCursor(false);
Movie_active = true;
gr_reset_clip();
gr_set_color(255, 255, 255);
gr_set_clear_color(0, 0, 0);
@@ -305,8 +304,6 @@ bool play(const char* name) {
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
}
Movie_active = false;
// show the mouse cursor again
io::mouse::CursorManager::get()->popStatus();
+11 -10
View File
@@ -501,11 +501,11 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
}
else if (vaporize) {
db->model_num = Debris_vaporize_model;
db->submodel_num = (Debris_num_submodels <= 0 ? 0 : Random::next(Debris_num_submodels));
db->submodel_num = Random::next(Debris_num_submodels);
}
else {
db->model_num = Debris_model;
db->submodel_num = (Debris_num_submodels <= 0 ? 0 : Random::next(Debris_num_submodels));
db->submodel_num = Random::next(Debris_num_submodels);
}
}
else {
@@ -644,7 +644,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
if (spark_timeout >= 0) {
db->fire_timeout = _timestamp(spark_timeout);
} else if (parent_objnum >= 0) {
float t = 1000*Objects[parent_objnum].radius/3 + (fl2i(1000*3*Objects[parent_objnum].radius) == 0 ? 0 : Random::next(fl2i(1000*3*Objects[parent_objnum].radius)));
float t = 1000*Objects[parent_objnum].radius/3 + Random::next(fl2i(1000*3*Objects[parent_objnum].radius));
db->fire_timeout = _timestamp(fl2i(t)); // fireballs last from 5 - 30 seconds
} else {
db->fire_timeout = TIMESTAMP::immediate();
@@ -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
+2 -2
View File
@@ -220,8 +220,8 @@ struct Decal {
vm_vec_make(&scale, 1.f, 1.f, 1.f);
}
bool isValid() const {
if (!object.isValid()) {
bool isValid() {
if (!object.IsValid()) {
return false;
}
if (object.objp->flags[Object::Object_Flags::Should_be_dead]) {
+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;
+4 -15
View File
@@ -118,13 +118,10 @@ uniform sampler2DArray sMiscmap;
uniform sampler2DArray shadow_map;
out vec4 fragOut0;
#ifndef FLAG_SHADOW_MAP
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
#endif
vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
{
@@ -188,9 +185,10 @@ void main()
#ifdef FLAG_SHADOW_MAP
// need depth and depth squared for variance shadow maps
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
return;
#else
if (true) {
return;
}
#endif
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
vec2 texCoord = vertIn.texCoord.xy;
@@ -265,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'.
@@ -402,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)) {
@@ -463,5 +453,4 @@ void main()
fragOut3 = vec4(specColor.rgb, fresnelFactor);
fragOut4 = emissiveColor;
}
#endif
}
+1
View File
@@ -5,6 +5,7 @@ out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
out float gl_FragDepth;
uniform sampler2DMS texColor;
uniform sampler2DMS texPos;
@@ -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
+28 -35
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(std::make_pair("Graphics", 1825))
.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){
@@ -1052,7 +1045,7 @@ float fireball_wormhole_intensity(fireball *fb)
rad = (float)pow((fb->total_time - t) / fb->warp_close_duration, 0.4f);
}
return rad;
}
}
extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id);
-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(std::make_pair("Graphics", 1825))
.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 )
{
+1 -1
View File
@@ -499,7 +499,7 @@ void help_overlay_blit(int overlay_id, int resolution_index)
font::set_font(help_overlaylist[overlay_id].fontlist.at(resolution_index));
for (idx = 0; idx < textcount; idx++) {
gr_set_color_fast(&Color_black);
gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, (int)strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
gr_rect(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord-2*HELP_PADDING, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord-3*HELP_PADDING, width+4*HELP_PADDING, height+4*HELP_PADDING, GR_RESIZE_MENU);
gr_set_color_fast(&Color_bright_white);
gr_printf_menu(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord,
-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 -6
View File
@@ -113,9 +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_INGAME_OPTIONS"
"GS_EVENT_SCRIPTING"
};
//XSTR:ON
@@ -178,9 +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_INGAME_OPTIONS"
"GS_STATE_SCRIPTING"
};
//XSTR:ON
-4
View File
@@ -89,8 +89,6 @@ enum GS_EVENT {
GS_EVENT_PXO_HELP,
GS_EVENT_FICTION_VIEWER,
GS_EVENT_SCRIPTING,
GS_EVENT_SCRIPTING_MISSION,
GS_EVENT_INGAME_OPTIONS,
GS_NUM_EVENTS // Last one++
};
@@ -161,8 +159,6 @@ enum GS_STATE {
GS_STATE_START_GAME,
GS_STATE_FICTION_VIEWER,
GS_STATE_SCRIPTING,
GS_STATE_SCRIPTING_MISSION,
GS_STATE_INGAME_OPTIONS,
GS_NUM_STATES // Last one++
};
+12 -20
View File
@@ -45,16 +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(std::make_pair("Audio", 1826))
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.flags({options::OptionFlags::RetailBuiltinOption})
.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
@@ -341,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;
}
@@ -607,10 +604,7 @@ void event_music_level_start(int force_soundtrack)
// Check that soundtrack index is in range, except that < 0 means no soundtrack
if (Current_soundtrack_num < 0)
{
Pattern_timer_id = TIMESTAMP::never(); // update the timestamp as if a soundtrack did start
return;
}
Assert(Current_soundtrack_num < (int)Soundtracks.size());
if (Current_soundtrack_num >= (int)Soundtracks.size())
return;
@@ -971,13 +965,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
+1 -1
View File
@@ -319,7 +319,7 @@ enum class InterfaceSounds {
MIN_INTERFACE_SOUNDS =70 //!< MIN_INTERFACE_SOUNDS
};
// These two id types are defined as subclasses so that type safe implicit conversions are possible from the predefined
// These two id types are defined as sublcasses so that type safe implicit conversions are possible from the predefined
// sound enum values
struct gamesnd_id_tag{};
+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
View File
@@ -72,7 +72,6 @@
#define MAX_POLYGON_MODELS 300
// object.h
//If this value exceeds 2^16-1, this will break collision pair caching as is. Proceed with caution.
#define MAX_OBJECTS 5000 //Increased from 3500 to 5000 in 2022
// from weapon.h (and beam.h)
+3 -3
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)) {\
@@ -442,7 +442,7 @@ public:
class camera *getCamera();
size_t getIndex();
int getSignature();
bool isValid() const;
bool isValid();
};
#include "globalincs/vmallocator.h"
@@ -453,7 +453,7 @@ public:
// - is not "none"
// - is not "<none>"
inline bool VALID_FNAME(const char* x) {
return (x[0] != '\0') && stricmp(x, "none") != 0 && stricmp(x, "<none>") != 0;
return strlen((x)) && stricmp((x), "none") != 0 && stricmp((x), "<none>") != 0;
}
/**
* @brief Checks if the specified string may be a valid file name
+49 -80
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,95 +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(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.detail_distance = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.hardware_textures = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_particles = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.importance(4)
.change_listener([](int val,bool) {
Detail.num_small_debris = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.shield_effects = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_stars = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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;
+1 -11
View File
@@ -21,20 +21,10 @@ template <typename T>
using SCP_vector = std::vector<T, std::allocator<T>>;
template <typename T>
bool SCP_vector_contains(const SCP_vector<T>& vector, const T& item) {
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(const SCP_vector<T>& vector, int idx) {
return ((idx >= 0) && (idx < static_cast<int>(vector.size())));
}
template <typename T>
inline bool SCP_vector_inbounds(const SCP_vector<T>& vector, size_t idx) {
return idx < vector.size();
}
template <typename T>
using SCP_list = std::list<T, std::allocator<T>>;
+148 -221
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,40 +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(std::make_pair("Graphics", 1825))
.default_val(1.0f)
.enumerator(gamma_value_enumerator)
.display(gamma_display)
.change_listener(gamma_change_listener)
.flags({options::OptionFlags::RetailBuiltinOption})
.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(std::make_pair("Graphics", 1825))
.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;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.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;
@@ -168,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(std::make_pair("Graphics", 1825))
.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);
@@ -195,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;
@@ -259,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(std::make_pair("Graphics", 1825))
.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;
@@ -369,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(std::make_pair("Graphics", 1825))
.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(std::make_pair("Graphics", 1825))
.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(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.values({{{}, {"None", 211}},
{{FramebufferEffects::Shockwaves}, {"Shockwaves", 1688}},
{{FramebufferEffects::Thrusters}, {"Thrusters", 1689}},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, {"All", 1690}}})
.default_val({})
.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(std::make_pair("Graphics", 1825))
.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(std::make_pair("Graphics", 1825))
.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)
{
@@ -457,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(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.default_val(true)
.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(std::make_pair("Graphics", 1825))
.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;
@@ -708,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;
}
@@ -1029,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));
@@ -1263,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) ) {
@@ -1593,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;
@@ -1602,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
@@ -1621,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
@@ -1750,12 +1699,20 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
Shadow_quality = ShadowQuality::Disabled;
}
if(Cmdline_enable_vr)
openxr_init();
return true;
}
void gr_force_windowed()
{
if ( !Gr_inited ) {
return;
}
if ( Os_debugger_running ) {
os_sleep(1000);
}
}
int gr_activated = 0;
void gr_activate(int active)
{
@@ -1770,7 +1727,7 @@ void gr_activate(int active)
}
if (active) {
if (gr_is_viewport_window()) {
if (Cmdline_fullscreen_window || Cmdline_window) {
os::getMainViewport()->restore();
} else {
os::getMainViewport()->setState(os::ViewportState::Fullscreen);
@@ -1780,7 +1737,7 @@ void gr_activate(int active)
}
if (active) {
if (!gr_is_viewport_window()) {
if (!Cmdline_fullscreen_window && !Cmdline_window) {
gr_set_gamma(Gr_gamma);
}
}
@@ -2630,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)
@@ -2959,28 +2911,3 @@ void gr_get_post_process_effect_names(SCP_vector<SCP_string>& names)
names.push_back(eff.name);
}
}
bool gr_is_viewport_window()
{
if (Fred_running) {
return true;
}
if (Using_in_game_options) {
switch (Gr_configured_window_state)
{
case os::ViewportState::Windowed:
case os::ViewportState::Borderless:
return true;
break;
default:
break;
}
} else {
if (Cmdline_window || Cmdline_fullscreen_window) {
return true;
}
}
return false;
}
+4 -35
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();
@@ -1002,7 +985,7 @@ extern void gr_printf_menu_zoomed( int x, int y, const char * format, SCP_FORMAT
extern void gr_printf_no_resize( int x, int y, const char * format, SCP_FORMAT_STRING ... ) SCP_FORMAT_STRING_ARGS(3, 4);
// Returns the size of the string in pixels in w and h
extern void gr_get_string_size( int *w, int *h, const char * text, size_t len = std::string::npos );
extern void gr_get_string_size( int *w, int *h, const char * text, int len = 9999 );
// Returns the height of the current font
extern int gr_get_font_height();
@@ -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 );
@@ -1428,8 +1399,6 @@ void gr_set_gamma(float gamma);
void gr_get_post_process_effect_names(SCP_vector<SCP_string> &names);
bool gr_is_viewport_window();
// Include this last to make the 2D rendering function available everywhere
#include "graphics/render.h"
-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();
+2 -9
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];
@@ -339,8 +332,8 @@ void gr_set_ambient_light(int red, int green, int blue) {
gr_light_ambient[3] = 1.0f;
}
void gr_get_ambient_light(vec3d* light_vector) {
const auto& abv = ltp::current()->ambient_light_brightness;
const auto& over = ltp::current()->overall_brightness;
auto abv = ltp::current()->ambient_light_brightness;
auto over = ltp::current()->overall_brightness;
light_vector->xyz.x = over.handle(abv.handle(gr_light_ambient[0]));
light_vector->xyz.y = over.handle(abv.handle(gr_light_ambient[1]));
light_vector->xyz.z = over.handle(abv.handle(gr_light_ambient[2]));
-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;
Loaded 100 of 939 files, more files were not shown because too many files have changed in this diff. Show more