Compare commits

..
Author SHA1 Message Date
SirKnightly cf5f207ca6 Automated build commit 2022-04-01 21:30:46 +00:00
403 changed files with 10117 additions and 25141 deletions

No files matched your search

-2
View File
@@ -1,8 +1,6 @@
cmake/ @asarium
ci/ @asarium @z64555
code/executor/ @asarium
code/scpui/ @asarium
+1 -94
View File
@@ -15,7 +15,7 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-11e553c
steps:
- name: Cache Qt
id: cache-qt-lin
@@ -210,96 +210,3 @@ jobs:
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh nightly
build_mac:
strategy:
matrix:
configuration: [FastDebug, Release]
compiler: [clang]
arch: [x86_64]
name: Mac
runs-on: macos-latest
steps:
- name: Cache Qt
id: cache-qt-mac
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-mac.outputs.cache-hit }}
setup-python: 'false'
aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
- name: Set up test version
shell: bash
run: |
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"]
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build
run: cd bin && tar -cvzf macos-build.tar *.app
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build.tar
mac_zip:
name: Build Mac distribution zip
needs: build_mac
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
steps:
- uses: actions/checkout@v2
name: Checkout
with:
submodules: true
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v2
with:
name: mac-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: mac-FastDebug
path: builds
- name: Create Distribution package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
- name: Upload result package
working-directory: ./builds
env:
INDIEGAMES_USER: ${{ secrets.INDIEGAMES_USER }}
INDIEGAMES_SSHPASS: ${{ secrets.INDIEGAMES_PASSWORD }}
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh nightly
+45 -12
View File
@@ -34,6 +34,23 @@ jobs:
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Store upload URL
run: |
echo -n "${{ steps.create_release.outputs.upload_url }}" > upload_url
- name: Persist upload URL
uses: actions/upload-artifact@v2
# 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.
# warn Display a warning but do not fail the action
# error Display an error and fail the action
# ignore No display, No fail
# retention-days=0 Days to keep the artifact.
# 0 Use default retention policy of the repo
# 1~90 Min 1, Max 90 days to keep the artifact unless changed by repo settings page
with:
name: upload_url # name of artifact
path: ${{ github.workspace }}/upload_url # source location of artifact to upload
build_linux:
strategy:
@@ -44,7 +61,7 @@ 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-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-11e553c
steps:
- name: Cache Qt
id: cache-qt-lin
@@ -117,15 +134,6 @@ jobs:
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
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.
# warn Display a warning but do not fail the action
# error Display an error and fail the action
# ignore No display, No fail
# retention-days=0 Days to keep the artifact.
# 0 Use default retention policy of the repo
# 1~90 Min 1, Max 90 days to keep the artifact unless changed by repo settings page
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
@@ -140,6 +148,21 @@ jobs:
with:
submodules: true
fetch-depth: '0' # value 0 to fetch all history and tags for all branches
- name: Download upload URL
uses: actions/download-artifact@v1
# Downloads and extracts uploaded artifact by name
# github_token default ${{secrets.GITHUB_TOKEN}}
# name name of artifact to download
# latest Download latest artifact (default true)
# path Where to save the artifact, (default extract_here)
# repo Source repo of artifact (default ${{github.repository}})
with:
name: upload_url
path: .
- name: Extract upload URL
# Extract the URL from file and stuff it into a shell variable
id: extractUploadUrl
run: echo "::set-output name=upload_url::$(cat upload_url)"
- name: Download Release builds
# Grab the release builds
uses: actions/download-artifact@v2
@@ -268,6 +291,16 @@ jobs:
submodules: true
fetch-depth: '0'
- name: Download upload URL
uses: actions/download-artifact@v1
with:
name: upload_url
path: .
- name: Extract upload URL
id: extractUploadUrl
run: echo "::set-output name=upload_url::$(cat upload_url)"
- name: Download Release builds
uses: actions/download-artifact@v2
with:
@@ -315,6 +348,6 @@ jobs:
needs: [linux_zip, windows_zip]
uses: ./.github/workflows/post-build-release.yaml
with:
linux_result: ${{ needs.linux_zip.result }}
windows_result: ${{ needs.windows_zip.result }}
linux_result: ${{ needs.build_linux.result }}
windows_result: ${{ needs.build_windows.result }}
releaseTag: ${{ github.ref_name }}
+1 -93
View File
@@ -15,7 +15,7 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-11e553c
steps:
- name: Cache Qt
id: cache-qt-lin
@@ -224,95 +224,3 @@ jobs:
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh test
build_mac:
strategy:
matrix:
configuration: [FastDebug, Release]
compiler: [clang]
arch: [x86_64]
name: Mac
runs-on: macos-latest
steps:
- name: Cache Qt
id: cache-qt-mac
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-mac.outputs.cache-hit }}
setup-python: 'false'
aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
- name: Set up test version
shell: bash
run: |
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build
run: cd bin && tar -cvzf macos-build.tar *.app
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build.tar
mac_zip:
name: Build Mac distribution zip
needs: build_mac
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
steps:
- uses: actions/checkout@v2
name: Checkout
with:
submodules: true
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v2
with:
name: mac-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v2
with:
name: mac-FastDebug
path: builds
- name: Create Distribution package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
- name: Upload result package
working-directory: ./builds
env:
INDIEGAMES_USER: ${{ secrets.INDIEGAMES_USER }}
INDIEGAMES_SSHPASS: ${{ secrets.INDIEGAMES_PASSWORD }}
DATACORDER_USER: ${{ secrets.DATACORDER_USER }}
DATACORDER_SSHPASS: ${{ secrets.DATACORDER_PASSWORD }}
run: $GITHUB_WORKSPACE/ci/linux/upload_dist_package.sh test
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
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-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-11e553c
steps:
- name: Cache Qt
id: cache-qt-lin
+7 -12
View File
@@ -6,10 +6,10 @@ on:
inputs:
linux_result: # job.result; either success, failure, canceled or skipped
required: true
type: string
type: boolean
windows_result: # job.result
required: true
type: string
type: boolean
releaseTag:
required: true
type: string
@@ -30,31 +30,26 @@ env:
NEBULA_PASSWORD: ${{ secrets.NEBULA_PASSWORD }}
HLP_API: ${{ secrets.HLP_API }}
HLP_KEY: ${{ secrets.HLP_KEY }}
RELEASE_TAG: ${{ inputs.releaseTag }}
RELEASE_TAG: ${{ github.event.inputs.releaseTag }}
jobs:
post_builds:
name: Post builds on Nebula and the forums
runs-on: ubuntu-latest
steps:
- name: Caller
# Name of what called this yaml. Used to debug auto/manual step being triggered
run: echo "github.event_name= ${{ github.event_name }}"
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: '0'
ref: ${{ env.RELEASE_TAG }}
- name: Install Python dependencies
run: pip install -r ci/post/requirements.txt
- name: Post Builds (Auto trigger)
if: ${{ (github.event_name == 'workflow_call') || (github.event_name == 'push') }}
if: ${{ github.event_name == 'workflow_call' }}
env:
LINUX_RESULT: ${{ inputs.linux_result }}
WINDOWS_RESULT: ${{ inputs.windows_result }}
LINUX_RESULT: ${{ github.event.inputs.linux_result }}
WINDOWS_RESULT: ${{ github.event.inputs.windows_result }}
run: python ci/post/main.py release
- name: Post Builds (Manual trigger)
@@ -64,6 +59,6 @@ jobs:
LINUX_RESULT: success
WINDOWS_RESULT: success
run: |
echo "releaseTag= ${{ env.RELEASE_TAG }}"
echo "releaseTag= ${{ github.event.inputs.releaseTag }}"
echo "repository= ${{ github.repository }}"
python ci/post/main.py release
+1 -62
View File
@@ -22,7 +22,7 @@ jobs:
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-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-11e553c
steps:
- name: Cache Qt
id: cache-qt-lin
@@ -156,64 +156,3 @@ jobs:
else
"./bin/$CONFIGURATION/unittests" --gtest_shuffle
fi
build_mac:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [clang]
arch: [x86_64]
cmake_options: [""]
name: Mac
runs-on: macos-latest
steps:
- name: Cache Qt
id: cache-qt-mac
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-mac.outputs.cache-hit }}
setup-python: 'false'
aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
- name: ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
working-directory: ./build
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Run Clang Tidy
# Clang-tidy reuses the precompiled headers so this only makes sense for the clang compilers
if: startsWith(matrix.compiler, 'clang-')
run: $GITHUB_WORKSPACE/ci/linux/clang_tidy.sh ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
- name: Process clang-tidy warnings
if: startsWith(matrix.compiler, 'clang-')
uses: asarium/clang-tidy-action@v1
with:
fixesFile: clang-fixes.yaml
+1 -2
View File
@@ -43,8 +43,7 @@ PROJECT(FS2_Open)
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(CCACHE_PROGRAM AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(NOT CMAKE_C_COMPILER_LAUNCHER)
message(STATUS "Using ccache for C compilation: ${CCACHE_PROGRAM}")
SET(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
-51
View File
@@ -3,52 +3,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [22.0.0] - 2022-04-01 ([Thread](https://www.hard-light.net/forums/index.php?topic=98125.0))
### Changed
- Controls5 PR (aka multi-joy)
- Timing system upgrade
- Model animation code upgrades
## [21.4.0] - 2021-09-27 ([Thread](https://www.hard-light.net/forums/index.php?topic=97802.0))
### Changed
- Multiple features; see thread
- Multiple bugfixes; see thread
### Deprecations
- `script-eval` has been deprecated in favor of `script-eval-block`
- renamed `hud-set-retail-gauge-active` to `hud-set-builtin-gauge-active`
## [21.2.0] - 2021-05-02 ([Thread](https://www.hard-light.net/forums/index.php?topic=97561.0))
### Changed
- Added a dynamic action system for more modder control of effects
- Removed fireball limit
- Fixed bomb intercept in multiplayer
- Changed nebula fog distance from a linear to exponential model
- Turrets on moving subobjects enabled
- LZ4 Compression added for game files
## [21.0.0] - 2021-01-27 ([Thread](https://www.hard-light.net/forums/index.php?topic=97293.0))
### Changed
- More OpenGL optimizations
- Full type information output for Lua documentation. Very useful for writing Lua scripts.
- A new -weaponspew command-line option for printing MediaVP-style statistics, plus a weapon comparison spreadsheet, to the debug log.
- Improved ship lookup behavior in SEXPs for improved performance.
- BPTC/BC7 texture compression support
- Refactoring and new features for the ship lab.
- Missile multi-lock. It's finally in an official build!
- Enhancements to the model code in preparation for cool features in 21.2.
- IPv6 support for multiplayer
- A lot of general fixes for multiplayer.
### Deprecated
- Dropped support for Windows XP
- Scripting:
- `ba.getFrametime()`: The parameter value was used incorrectly inside the implementation. To avoid breaking existing scripts and to improve readability this has been split into `ba.getMissionFrametime()` and `ba.getRealFrametime()`.
- `gr.drawMonochromeImage()`: `gr.drawImage()` got a new parameter for drawing monochrome images and is more flexible in general so the monochrome variant is no longer needed.
## [19.0.0] - 2020-01-25 ([Thread](https://www.hard-light.net/forums/index.php?topic=96226.0))
### Meta
- With this release we decided to drop the "`3.Major_revision.Minor_revision`" versioning scheme in favor of a year based scheme since the Major and Minor versions did not have much meaning anymore. Instead the scheme will now be "`<year>.<number that is incremented every release>.0`". The last 0 is still there because some of our systems expect that. It will be gone at some point.
@@ -71,7 +25,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
- Refactored bitmap slot handling and removed the fixed upper limit on the number of bitmaps. No more bmpman corruption!
## [3.8.0] - 2017-08-22 ([Release Thread](https://www.hard-light.net/forums/index.php?topic=93812.0))
### Added
- Support for APNG animations: [APNG](https://en.wikipedia.org/wiki/APNG) is a variant of the established PNG format which allows to store animations instead of single frames in a PNG file. This change allows to use these animation files in FSO which significantly improves usability for modders since they no longer have to store all individual frames as separate images.
@@ -96,7 +49,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
- "Tons" of bugfixes
## [3.7.2] - 2015-04-23 ([Release thread](http://www.hard-light.net/forums/index.php?topic=89597.0))
### Added
- MediaVPS 2014 Support
@@ -127,19 +79,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Raised the per-model debris limit to 48 (previously 32).
- Increased the per-frame debris limit to 96 (previously 64)
## [3.6.18] - 2013-03-01 ([Release thread](http://www.hard-light.net/forums/index.php?topic=83889.0))
### Fixed
- Critical damage bug which caused heavy balance issues in the game
## [3.6.16] - 2013-01-31 ([Release thread](http://www.hard-light.net/forums/index.php?topic=83577.0))
### Added
- Diaspora TC support
### Changed
- Performance Improvements
## [3.6.14] - 2012-10-23 - ([Release thread](https://www.hard-light.net/forums/index.php?topic=82648.0))
### Added
- Objecttype tables support for deciding how enemies respond to ship classes when disabled
+1 -1
View File
@@ -19,5 +19,5 @@ BASE_COMMIT=$(git merge-base $1 $2)
echo "Running clang-tidy on changed files"
git diff -U0 --no-color "$BASE_COMMIT..$2" | \
$HERE/clang-tidy-diff.py -path "$(pwd)/build" -p1 \
-regex '(code(?!((\/graphics\/shaders\/compiled)|(\/globalincs\/windebug)))|freespace2|qtfred|test|build|tools)\/.*\.(cpp|h)' \
-regex '(code(?!\/graphics\/shaders\/compiled)|freespace2|qtfred|test|build|tools)\/.*\.(cpp|h)' \
-clang-tidy-binary /usr/bin/clang-tidy-9 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
+4 -15
View File
@@ -15,16 +15,8 @@ if [ "$COMPILER" = "clang-9" ]; then
fi
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH
if [ "$RUNNER_OS" = "macOS" ]; then
CXXFLAGS="-mtune=generic -pipe -Wno-unknown-pragmas"
CFLAGS="-mtune=generic -pipe -Wno-unknown-pragmas"
PLATFORM_CMAKE_OPTIONS=""
export CMAKE_OSX_ARCHITECTURES="$ARCHITECTURE"
else
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
PLATFORM_CMAKE_OPTIONS="-DFSO_BUILD_APPIMAGE=ON"
fi
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CMAKE_OPTIONS="$JOB_CMAKE_OPTIONS"
if [[ "$COMPILER" =~ ^clang.*$ ]]; then
@@ -38,10 +30,7 @@ export CXXFLAGS
export CFLAGS
export LD_LIBRARY_PATH
if [ "$RUNNER_OS" = "macOS" ]; then
brew install ninja
fi
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 \
cmake -G Ninja -DFSO_FATAL_WARNINGS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON $CMAKE_OPTIONS \
-DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_BUILD_APPIMAGE=ON -DCMAKE_BUILD_TYPE=$CONFIGURATION \
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON \
-DSHADERS_ENABLE_COMPILATION=ON ..
-6
View File
@@ -25,12 +25,6 @@ elif [ "$OS" = "Windows" ]; then
echo "::set-output name=debug_path::$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z"
echo "::set-output name=debug_name::$(get_package_name)-debug-$ARCH-$SIMD.7z"
echo "::set-output name=debug_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")"
elif [ "$OS" = "Mac" ]; then
tar -cvzf "$(get_package_name)-builds-Mac.tar.gz" *
echo "::set-output name=package_path::$(pwd)/$(get_package_name)-builds-Mac.tar.gz"
echo "::set-output name=package_name::$(get_package_name)-builds-Mac.tar.gz"
echo "::set-output name=package_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac.tar.gz")"
else
echo "Invalid OS: $OS"
fi
+1 -1
View File
@@ -5,7 +5,7 @@ HERE=$(dirname "$SCRIPT")
export LD_LIBRARY_PATH=$(pwd)/bin/lib:$LD_LIBRARY_PATH
if [ "$CONFIGURATION" = "Debug"] && [[ "$RUNNER_OS" != "macOS" ]] ; then
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$HERE/valgrind.supp" ./bin/unittests --gtest_shuffle
else
-169
View File
@@ -1,169 +0,0 @@
# Retrives a log of commit messages and attempts to pretty them into a human-readbile format
import argparse
import os
import re
import requests
import sys
from datetime import datetime
from subprocess import check_output
MAX_PAGES = 100 # maximum number of PR pages to go through
warnings = 0
def get_last_page(response: requests.Response) -> int:
"""
@brief Extract the last page number from the response header
@param[in] response The response from a GET call
@returns The page number of the last page, or MAX_PAGES
"""
# The link header is a dictionary in string form, and for that matter the
# value is in front of the key. It is of the form '<<url1>>; rel=<key1>, <url2>, <key2>'
link = response.headers['link']
link = link.split(',')
for x in link:
y = x.split(';') # <url>; rel=<key>
if "last" not in y[1]: # look for rel='last'
continue
# grab the page number from the URL
# group(0) is `page=123`, group(1) is `123`
last_page = int( re.search(r'page=(\d+)', y[0]).group(1) )
if not last_page:
print("Error: Could not find page number in url! URL: %s", y[0])
sys.exit(1)
if last_page > MAX_PAGES:
return MAX_PAGES
else:
return last_page
def main():
parser = argparse.ArgumentParser(description="Retrieves a log of commit messages and attempts to pretty them into a human-readable format")
parser.add_argument("start_date",
help="Day of the earliest commit to add to the log.")
parser.add_argument("-u", "--user", nargs=2, metavar=("NAME", "TOKEN"), default=["", ""],
help="Github username and token/password")
args = parser.parse_args()
os.chdir(os.path.dirname(__file__)) # Change working directory to this file's directory
start_date = datetime.strptime(args.start_date, "%Y-%m-%d")
print("start_date: {}".format(start_date))
# Retrive the git log for master, since start date, order by date, in ascending order, use YYYY-MM-DD date format,
# each line is of the form "<author short date> | <message>", only grab commits from master,
# output to `fsofordigest.txt`,
# check_output(("git log master", "--after=2021-09-15", "--date-order", "--reverse", "--date=short",
# "--pretty=\"%as | %s\"", "--first-parent",
# "--output fsofordigest.txt"), text=True)
# The commit messages are either of the form "<body> (#<PR_number>)" or "Merge pull request #<PR_number> from <source_repo>"
# For our purposes, we want them be all of the form "<body> (#<PR_number>)"
# Typically, the second form does not have a usable body, so we'll have to pull the PR title from github
# Github's REST API allows us to retrieve PR's, but due to it being HTTP requests it has to page in the data.
# We can loop over the GET request and check for a merge date.
# The GET request doesn't have sorting by merge date, but does have sorting by the last time it was updated... which is usually
# also the merge date but not always.
# Key attributes within the PR JSON objects:
# "merged_at: <date>" # Date the PR was merged in
# "merged: <bool>" # If the PR was merged yet
# "html_url: <string>" # URL of the PR's HEAD commit, used by some clients to pull in the PR branch
# "number: <int>" # The PR id number
# "title: <string>" # Title of the PR
# "body: <string>" # The body paragraph detailing the PR
# "labels: [label_object]" # All labels attached to this PR
changelog = {}
url = "https://api.github.com/repos/scp-fs2open/fs2open.github.com/pulls"
page = 1
last_page = MAX_PAGES
while page <= last_page:
# GET <url>?base=master&sort=updated&direction=desc&state=closed&page=1
response = requests.get(url,
auth=(args.user[0], args.user[1]),
params={
"base": "master",
"direction": "desc",
"page": page,
"state": "closed",
"sort": "updated"
})
# Check if good response
if (response.status_code != 200) :
print("Error: ", response.status_code)
print(response.json()['message'])
sys.exit(1)
else:
print("Request successful: 200")
print("page={}".format(page))
# Update the last_page index at first iteration and possibly last iteration
# This should cover the edge case of a new PR being added to the database before this script is finished
if (page == 1) or (page == last_page):
last_page = get_last_page(response)
print("last_page={}".format(last_page))
# assume pulls are organized from newest to oldest
for pull in response.json():
if (pull['state'] != 'closed'):
# This pull is not merged, so ignore
print("Found irrelevant pull, skipping...")
print("state: {}; number: {}".format(pull['state'], pull['number']))
continue
if (pull['merged_at'] == None):
# This pull wasn't merged, skip
print("Found closed pull #{} ({}), skipping...".format(pull['number'], pull['closed_at']))
continue
merge_date = datetime.strptime(pull['merged_at'], "%Y-%m-%dT%H:%M:%SZ")
updated_date = datetime.strptime(pull['updated_at'], "%Y-%m-%dT%H:%M:%SZ")
if (merge_date < start_date) and (updated_date >= start_date):
# This pull is too old, but was updated within our timeframe. skip
print("Found old pull #{} ({}), skipping...".format(pull['number'], pull['merged_at']))
continue
if (updated_date < start_date):
# This pull is too old
print("Found old pull #{} ({}), stopping loop...".format(pull['number'], pull['updated_at']))
page = last_page + 1
break
# Add the pull to the changelog, indexed by its pull.number
if pull['number'] not in changelog:
# only add if the key isn't there already
changelog[pull['number']] = {
"date": merge_date,
"title": pull['title'],
"labels": pull['labels'],
"url": pull['html_url']
}
print("Added pull #{} ({})".format(pull['number'], merge_date))
# Else, silently ignore duplicate (for now...)
page += 1 # iterate to next page
# Write the changelog to file
# 2021-09-28 | (#3661) Fix homing child weapons in niche circumstances
print("Writing to change.log...")
str = ''
for key, value in changelog.items():
str += "{} | (#{}) {} \n".format(value['date'].strftime("%Y-%m-%d"), key, value['title'])
with open("change.log", "w") as file:
file.write(str)
print("Done!")
main()
+3 -41
View File
@@ -8,27 +8,12 @@ from file_list import ReleaseFile
class ForumAPI:
POST_SIZE_MAX = 50000
"""!
Maximum number of characters allowed in a post, including BBCode (03/17/2022)
Check with HLP admins occasionally to verify this limit, they can set it in the forum's admin panel
"""
def __init__(self, config):
self.config = config
def create_post(self, title, content, board):
"""!
@brief Create a post on the forums
@param[in] title Title of the post
@param[in] content Body of the post
@param[in] board Which board/forum to post to
@returns { "thread_url": <url_of_created_thread> }
"""
print(self.config["hlp"]["api"])
print(self.config["hlp"]["key"])
if (self.config["hlp"]["api"] == "") or (self.config["hlp"]["key"] == ""):
print("Post failed! No API or API_KEY given!")
return
@@ -42,19 +27,8 @@ class ForumAPI:
if resp.text != "OK":
print("Post failed! Response: %s" %resp.text)
return resp.json()
def post_nightly(self, date, revision, files, log, success):
"""!
@brief Post a new Nightly topic on the forums using nightly.mako
@param[in] date The date to use
@param[in] version The build's version
@param[in] groups dict[Any, file_list.FileGroup]; FileGroups of SSE2, AVX, etc.
@param[in] sources URL's of builds on github or fs2net
"""
print("Posting nightly thread...")
title = "Nightly: {} - Revision {}".format(date, revision)
@@ -72,17 +46,6 @@ class ForumAPI:
self.create_post(title, rendered, self.config["nightly"]["hlp_board"])
def post_release(self, date, version: semantic_version.Version, groups, sources):
"""!
@brief Post a new Release topic on the forums using release.mako.
@param[in] date The date to use
@param[in] version The build's version
@param[in] groups dict[Any, file_list.FileGroup]; FileGroups of SSE2, AVX, etc.
@param[in] sources URL's of builds on github or fs2net
@returns If Successful, the URL of the created post
"""
print("Posting release thread...")
title = "Release: {}".format(version)
@@ -99,5 +62,4 @@ class ForumAPI:
print("Creating post...")
json = self.create_post(title, rendered, self.config["release"]["hlp_board"])
return json["thread_url"]
self.create_post(title, rendered, self.config["release"]["hlp_board"])
-85
View File
@@ -1,85 +0,0 @@
# Class for use with interfacing with github via HTTP requests
import requests
from util import retry_multi, GLOBAL_TIMEOUT
class GithubAPI:
headers = {
"Accept": "application/vnd.github.v3+json"
}
url_root = "https://api.github.com"
def __init__(self, config):
self.config = config
@retry_multi(5)
def get(self, path):
"""!
@brief Performs a GET request with the given path. To be used with Github's REST API.
@returns If successful, returns a .JSON object
"""
url = self.url_root + path
# GET https://api.github.com/<path> Accept: "application/vnd.github.v3+json"
response = requests.get(url, headers=self.headers, timeout=GLOBAL_TIMEOUT)
response.raise_for_status() # Raise a RequestException if we failed, and trigger retry
return response.json()
def get_release(self, tag_name):
"""!
@brief Retrieves the Github Release metadata as a JSON object
@see https://docs.github.com/en/rest/reference/releases#get-a-release-by-tag-name
"""
return self.get("/repos/{}/releases/tags/{}".format(self.config["github"]["repo"], tag_name))
def patch(self, path, data):
"""!
@brief Performs a PATCH request with the given path and body data (as dictionary)
@returns If successful, returns a .JSON object
"""
url = self.url_root + path
response = requests.patch(url, headers=self.headers, timeout=GLOBAL_TIMEOUT, data=data)
response.raise_for_status()
return response.json()
def update_release(self, release_id, tag_name="", name="", body="", draft=None, prerelease=None):
"""!
@brief Updates a Github Release
@param[in] release_id The id of the release, as obtained by get_release()
@param[in] tag_name (optional) The git tag this release is associated with
@param[in] name (optional) The name of the release
@param[in] body (optional) Body text describing the release
@param[in] draft (optional) If true, the release is marked as a "draft"
@param[in] prerelease (optional) If true, the release is marked as a "prerelease"
@note If an optional argument is not provided, then its associated data is not changed
"""
path = "/repos/{}/releases/{}".format(self.config["github"]["repo"], release_id)
# Add to the data JSON if options are specified
data = {}
if tag_name != "":
data["tag_name"] = tag_name
if name != "":
data["name"] = name
if body != "":
data["body"] = body
if draft != None:
data["draft"] = data
if prerelease != None:
data["prerelease"] = prerelease
self.patch(path, data)
+41 -86
View File
@@ -38,11 +38,9 @@ import nebula
import forum
# Compile regexes for extracting version components
MAJOR_VERSION_PATTERN = re.compile("(?:set_if_not_defined|set)\(FSO_VERSION_MAJOR (\d+)\)")
MINOR_VERSION_PATTERN = re.compile("(?:set_if_not_defined|set)\(FSO_VERSION_MINOR (\d+)\)")
BUILD_VERSION_PATTERN = re.compile("(?:set_if_not_defined|set)\(FSO_VERSION_BUILD (\d+)\)")
REVISION_VERSION_PATTERN = re.compile("(?:set_if_not_defined|set)\(FSO_VERSION_REVISION (\d+)\)")
REVISION_STR_VERSION_PATTERN = re.compile("(?:set_if_not_defined|set)\(FSO_VERSION_REVISION_STR (\w+)\)")
MAJOR_VERSION_PATTERN = re.compile("set_if_not_defined\(FSO_VERSION_MAJOR (\d+)\)")
MINOR_VERSION_PATTERN = re.compile("set_if_not_defined\(FSO_VERSION_MINOR (\d+)\)")
BUILD_VERSION_PATTERN = re.compile("set_if_not_defined\(FSO_VERSION_BUILD (\d+)\)")
LOG_FORMAT = """
------------------------------------------------------------------------%n
@@ -62,64 +60,45 @@ def _match_version_number(text, regex):
"""
match = regex.search(text)
return int(match.group(1))
def _match_version_str(text, regex):
"""! Extracts the version component represented by `regex` from `text`
@param [in] `text` Filename with version string 'MAJOR.MINOR.BUILD'
@param [in] `regex` Regex pattern of component to look for
@return The version component as integer
"""
match = regex.search(text)
return match.group(1)
def get_source_version(date_version: datetime, tag_name: str) -> semantic_version.Version:
"""! Retrieves the version string from version_override.cmake (and version.cmake)
"""! Retrieves the build's version from `version.cmake`, forms it as a string, and appends the date
@param[in] `date_version` Date this build is published for release
@param[in] `tag_name` Tag of this release, used to determine if release, rc, or nightly
@return If release: `FSO_VERSION_MAJOR.FSO_VERSION_MINOR.FSO_VERSION_BUILD`
@return If rc: `FSO_VERSION_MAJOR.FSO_VERSION_MINOR.FSO_VERSION_BUILD-FSO_VERSION_REVISION_STR`
@return If nightly: `FSO_VERSION_MAJOR.FSO_VERSION_MINOR.FSO_VERSION_BUILD-FSO_VERSION_REVISION_STR` (uses both version_override.cmake and version.cmake)
@note This is the version used to identify in Nebula and the forums. version_override.cmake is used for the builds
made by CI tools and version.cmake is used for builds made by devs.
@return If release: `MAJOR_VERSION.MINOR_VERSION.BUILD_VERSION` from version.cmake, or
@return If rc: `MAJOR_VERSION.MINOR_VERSION.BUILD_VERSION` from tag_name, or
@return If nightly: `MAJOR_VERSION.MINOR_VERSION.BUILD_VERSION-date` from version.cmake
"""
with open(os.path.join("..", "..", "version_override.cmake"), "r") as f:
major = minor = build = version = 0
with open(os.path.join("..", "..", "cmake", "version.cmake"), "r") as f:
filetext = f.read()
major = _match_version_number(filetext, MAJOR_VERSION_PATTERN)
minor = _match_version_number(filetext, MINOR_VERSION_PATTERN)
build = _match_version_number(filetext, BUILD_VERSION_PATTERN)
# revision = _match_version_number(filetext, REVISION_VERSION_PATTERN)
revision_str = _match_version_str(filetext, REVISION_STR_VERSION_PATTERN)
print("Parsing version_override.cmake...")
if "rc" in tag_name.lower():
version = semantic_version.Version("{}.{}.{}-{}".format(major, minor, build, revision_str))
# Release candidates idenfity with their unstable version (ex: 21.5.0-03052022) within the game and the logs, but
# the builds are named with the target release version (ex: 22.0.0). Since this script works on the builds we
# need to grab the target release version from tag_name
x = tag_name.upper().split("_")
# "release" = x[0], year = x[1], major = x[2], minor = x[3], build = x[4],
version = semantic_version.Version("{}.{}.{}-{}".format(x[1], x[2], x[3], x[4]))
elif "release" in tag_name.lower():
version = semantic_version.Version("{}.{}.{}".format(major, minor, build))
elif "nightly" in tag_name.lower():
# Nightly's version_override.cmake only has FSO_VERSION_REVISION and FSO_VERSION_REVISION_STR set
# So, we have to pull the rest of the version string from version.cmake
print("Parsing version.cmake...")
with open(os.path.join("..", "..", "cmake", "version.cmake"), "r") as f:
major = _match_version_number(filetext, MAJOR_VERSION_PATTERN)
minor = _match_version_number(filetext, MINOR_VERSION_PATTERN)
build = _match_version_number(filetext, BUILD_VERSION_PATTERN)
version = semantic_version.Version("{}.{}.{}-{}".format(major, minor, build, revision_str))
version = semantic_version.Version("{}.{}.{}-{}".format(major, minor, build, date_version))
else:
print(" ERROR: malformed tag_name %s" % tag_name)
print("ERROR: malformed tag_name %s" % tag_name)
sys.exit(1)
print(" version: {}".format(version))
print(" version.prerelease: {}".format(version.prerelease))
print("version: {}".format(version))
print("version.prerelease: {}".format(version.prerelease))
return version
@@ -166,43 +145,17 @@ def main():
print("ERROR: Invalid release mode %s passed. Expected release or nightly!" % sys.argv[1])
sys.exit(1)
linux_success = os.environ["LINUX_RESULT"] == "success"
windows_success = os.environ["WINDOWS_RESULT"] == "success"
if (sys.argv[1] == "release"):
if not (linux_success and windows_success):
# bail if this is a release and either build workflow failed
print("ERROR: One or more builds failed to publish! Cannot post release.")
sys.exit(1)
else:
if not (linux_success or windows_success):
# bail if this is a nightly build and both build workflows failed
print("ERROR: All builds failed to publish! Cannot post nightly.")
sys.exit(1)
# bail if tag_name doesn't match with sys.argv[1]
tag_name = os.environ["RELEASE_TAG"] ##!< commit tag string
if (sys.argv[1] == "release") and (not tag_name.startswith("release_")):
print("ERROR: Invalid tag name detected. Expected release_ prefix for release builds but found %s (full ref = %s)" % tag_name, os.environ["GITHUB_REF"])
sys.exit(1)
if (sys.argv[1] == "nightly") and (not tag_name.startswith("nightly_")):
print("ERROR: Invalid tag name detected. Expected nightly_ prefix for nightly builds but found %s (full ref = %s)" % tag_name, os.environ["GITHUB_REF"])
sys.exit(1)
# bail if tag_name does not exist in the repo
if not check_output(("git", "show-ref", "--tags", "refs/tags/%s" % tag_name), text=True):
print("ERROR: Couldn't find tag %s in repo (git show-ref)!" % tag_name)
sys.exit(1)
# Populate version and date
date = datetime.now() ##!< current date
version = get_source_version(date.strftime(DATEFORMAT_VERSION), tag_name) ##!< form full version string
# find the previous tag release (used by nightly)
success = os.environ["LINUX_RESULT"] == "success" and os.environ["WINDOWS_RESULT"] == "success" ##!< true if both linux and windows builds successful
# check that tag_name is actually in the git repo and find the previous tag release
tags = check_output(("git", "for-each-ref", "--sort=-taggerdate", "--format='%(tag)'", "refs/tags"), text=True).splitlines() # retrieve all tags in the repo by using git on the shell
# NOTE: check_output returns canonical string representation. use repr() on strings its being compared to
previous_tag = None
found = False
for tag in tags:
if found:
# Look for the "previous" tag with the same configuration ('release_' or 'nightly_')
@@ -216,20 +169,24 @@ def main():
if not found:
# couldn't find tag, bail
print("ERROR: Couldn't find tag %s in repo! (git for-each-ref)" % tag_name)
print("ERROR: Couldn't find tag %s in repo!" % tag_name)
sys.exit(1)
if (sys.argv[1] == "nightly") and (not previous_tag):
if not previous_tag:
# couldn't find previous tag, bail
print("ERROR: Could not find a previous tag for %s!" % tag_name)
sys.exit(1)
if sys.argv[1] == "release":
# Release specific action
print("Retrieving file list...")
if not tag_name.startswith("release_"):
# Safety check tag is from a release
print("ERROR: Invalid tag name detected. Expected release_ prefix for release builds but found %s (full ref = %s)" % tag_name, os.environ["GITHUB_REF"])
sys.exit(1)
files, sources = file_list.get_release_files(tag_name, config)
print("Hashing files...")
print("Hashing files")
for file in files:
installer.get_hashed_file_list(file)
@@ -265,27 +222,30 @@ def main():
# print(installer.render_installer_config(version, groups, config))
# Publish release builds to Nebula
print("Publishing to Nebula...")
nebula.submit_release(
nebula.render_nebula_release(version, "rc" if version.prerelease else "stable", files, config),
config)
# Publish forum post, using the release.mako template
print("Publishing to Hard-light.net...")
fapi = forum.ForumAPI(config)
fapi.post_release(date.strftime(DATEFORMAT_FORUM), version, groups, sources)
else:
# Dead for now, nightly publish is done elsewhere
# Nightly specific action
print("Retrieving file list...")
if not tag_name.startswith("nightly_"):
# safety check tag is from a nightly
print("ERROR: Invalid tag name detected. Expected nightly_ prefix for nightly builds but found %s (full ref = %s)" % tag_name, os.environ["GITHUB_REF"])
sys.exit(1)
print("Retrieving file list")
files = file_list.get_ftp_files("nightly", tag_name, config)
print("Hashing files...")
print("Hashing files")
for file in files:
installer.get_hashed_file_list(file)
print("Publishing to Nebula...")
# Publish nightly builds to Nebula
nebula.submit_release(
nebula.render_nebula_release(version, "nightly", files, config),
config)
@@ -294,12 +254,7 @@ def main():
log = check_output(("git", "log", "%s^..%s^" % (previous_tag, tag_name), "--no-merges", "--stat", "--pretty=format:\"%s\"" % LOG_FORMAT.strip()))
# Publish forum post, using the nighty.mako template
print("Publishing to Hard-light.net...")
fapi = forum.ForumAPI(config)
fapi.post_nightly(date.strftime(DATEFORMAT_FORUM), os.environ["GITHUB_SHA"], files, log, (linux_success and windows_success))
fapi.post_nightly(date.strftime(DATEFORMAT_FORUM), os.environ["GITHUB_SHA"], files, log, success)
print("Done!")
if __name__ == "__main__":
main()
main()
+1 -1
View File
@@ -8,7 +8,7 @@ if(DOXYGEN_FOUND)
FILE(TO_NATIVE_PATH ${OUTPUT_DIR} OUTPUT_DIR)
SET(OUTPUT_DIR \"${OUTPUT_DIR}\")
SET(INPUTS "${CMAKE_CURRENT_SOURCE_DIR}/code" "${CMAKE_CURRENT_SOURCE_DIR}/freespace2" "${CMAKE_CURRENT_SOURCE_DIR}/fred2" "${CMAKE_CURRENT_SOURCE_DIR}/wxfred2" "${CMAKE_CURRENT_SOURCE_DIR}/qtfred")
SET(INPUTS "${CMAKE_CURRENT_SOURCE_DIR}/code" "${CMAKE_CURRENT_SOURCE_DIR}/freespace2" "${CMAKE_CURRENT_SOURCE_DIR}/fred2" "${CMAKE_CURRENT_SOURCE_DIR}/wxfred2")
SET(INPUT_DIRS)
FOREACH(DIR IN LISTS INPUTS)
+1 -1
View File
@@ -7,7 +7,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 22)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_MINOR 0)
set_if_not_defined(FSO_VERSION_BUILD 0)
# A numeric revision e.g. the CI build number
-3
View File
@@ -106,6 +106,3 @@ set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYM
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[variant=Debug] "NO")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN[variant=Debug] "NO")
# Prevent GCC warnings in third-party BitOp... see GitHub #4366
suppress_file_warnings(scripting/lua/bitop/bit.c)
+2 -2
View File
@@ -1,11 +1,11 @@
#pragma once
#include "actions/expression/nodes/AbstractExpression.h"
#include "globalincs/pstypes.h"
#include "ParseContext.h"
#include "actions/expression/nodes/AbstractExpression.h"
namespace actions {
namespace expression {
@@ -1,11 +1,11 @@
#pragma once
#include <Parser.h>
#include <Token.h>
#include "actions/expression/ParseContext.h"
#include "actions/expression/Value.h"
#include <Parser.h>
#include <Token.h>
namespace actions {
namespace expression {
namespace nodes {
+2 -20
View File
@@ -17,7 +17,6 @@
#include "globalincs/pstypes.h"
#include "globalincs/systemvars.h"
#include "object/waypoint.h"
#include "parse/sexp.h"
#include "physics/physics.h"
#include "ship/ship_flags.h"
@@ -72,7 +71,6 @@ extern ai_flag_name Ai_flag_names[];
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
#define AITTV_IGNORE_BANK (1<<2) // Goober5000 - ignore bank when turning
#define AITTV_SLOW_BANK_ACCEL (1<<3) // Asteroth - used by formation flying
#define AITTV_FORCE_DELTA_BANK (1<<4) // Lafiel - Always use the provided delta bank and override calculated values
#define KAMIKAZE_HULL_ON_DEATH -1000.0f // Hull strength ship gets set to if it crash-dies.
@@ -105,13 +103,11 @@ typedef struct ai_goal {
int index;
} dockee;
object_ship_wing_point_team lua_ai_target;
} ai_goal;
#define AIM_CHASE 0
#define AIM_EVADE 1
#define AIM_GET_BEHIND 2 // This mode is not actually implemented.
#define AIM_GET_BEHIND 2
#define AIM_STAY_NEAR 3 // Stay near another ship.
#define AIM_STILL 4 // Sit still. Don't move. Hold your breath. Don't blink.
#define AIM_GUARD 5 // Guard an object
@@ -131,9 +127,8 @@ typedef struct ai_goal {
#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 // [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
#define MAX_AI_BEHAVIORS 22 // Number of AIM_xxxx types
#define MAX_WAYPOINTS_PER_LIST 20
#define MAX_ENEMY_DISTANCE 2500.0f // Maximum distance from which a ship will pursue an enemy.
@@ -272,8 +267,6 @@ extern pnode *Ppfp; // Free pointer in path points.
// Goober5000 (based on the "you can only remember 7 things in short-term memory" assumption)
#define MAX_IGNORE_NEW_OBJECTS 7
#define AI_DYNAMIC_PATH_RECHECK_DELAY 1*1000
typedef struct ai_info {
flagset<AI::AI_Flags> ai_flags; // Special flags for AI behavior.
int shipnum; // Ship using this slot, -1 means none.
@@ -350,9 +343,6 @@ typedef struct ai_info {
int submode_parm1; // SUSHI: Another optional 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
vec3d last_dynamic_path_goal; //ETP: Remebers last target location in ai_new_maybe_reposition_attack_subsys
//SUSHI: like last_predicted_enemy_pos, but for aiming (which currently ignores predicted position)
//Unlike the predicted position stuff, also takes into account velocity
//Only used against small ships
@@ -503,8 +493,6 @@ typedef struct ai_info {
int multilock_check_timestamp; // when to check for multilock next
SCP_vector<std::pair<int, ship_subsys*>> ai_missile_locks_firing; // a list of missile locks (locked objnum, locked subsys) the ai is currently firing
object_ship_wing_point_team lua_ai_target;
} ai_info;
// Goober5000
@@ -548,8 +536,6 @@ extern int Ai_firing_enabled;
extern const char *Skill_level_names(int skill_level, int translate = 1);
extern int Ai_goal_signature;
extern control_info AI_ci;
// need access to following data in AiBig.cpp
extern object *Pl_objp;
extern object *En_objp;
@@ -587,7 +573,6 @@ extern void ai_do_default_behavior(object *obj);
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
extern vec3d ai_get_acc_limit(vec3d* vel_limit, const object* objp);
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.
@@ -686,7 +671,4 @@ void do_random_sidethrust(ai_info *aip, ship_info *sip);
void ai_formation_object_recalculate_slotnums(int form_objnum, int exiting_objnum = -1);
bool test_line_of_sight(vec3d* from, vec3d* to, std::unordered_set<const object*>&& excluded_objects = {}, float threshold = 10.0f, bool test_for_shields = false, bool test_for_hull = true, float* first_intersect_dist = nullptr);
#endif
-1
View File
@@ -144,7 +144,6 @@ namespace AI {
Fighterbay_departures_use_carrier_orient,
Prevent_negative_turret_ammo,
Fix_keep_safe_distance,
Ignore_aspect_when_leading,
NUM_VALUES
};
-2
View File
@@ -598,8 +598,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$fix keep-safe-distance:", AI::Profile_Flags::Fix_keep_safe_distance);
set_flag(profile, "$AI ignores aspect lock for leading:", AI::Profile_Flags::Ignore_aspect_when_leading);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
+50 -58
View File
@@ -560,69 +560,61 @@ bool ai_new_maybe_reposition_attack_subsys() {
return false;
// not in sight, gotta get there
vec3d tgt2pl = Pl_objp->pos - target_objp->pos;
vec3d tgt2subsys = gsubpos - target_objp->pos;
float pl_dist = vm_vec_mag(&tgt2pl);
float subsys_dist = vm_vec_mag(&tgt2subsys) * 1.3f; // add a bit to this, we don't want to go directly at the subsys, we want to go above it
float angle2subsys = vm_vec_delta_ang(&tgt2pl, &tgt2subsys, nullptr);
float angle2goal = angle2subsys;
if (angle2goal > 1.2f) // let's not try to go more than about 70 degrees around the ship
angle2goal = 1.2f;
// we'll start by travelling along the sphere at our current distance around the ship
// remember that goal_pos will be relative to our target_ship (so we can scale in and out easily)
vec3d goal_pos, cross;
vm_vec_cross(&cross, &tgt2pl, &tgt2subsys);
vm_vec_normalize(&cross);
vm_vec_negate(&cross);
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;
vec3d* good_pos = nullptr;
// 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;
vec3d tgt2subsys = gsubpos - target_objp->pos;
float pl_dist = vm_vec_mag(&tgt2pl);
float subsys_dist = vm_vec_mag(&tgt2subsys) * 1.3f; // add a bit to this, we don't want to go directly at the subsys, we want to go above it
float angle2subsys = vm_vec_delta_ang(&tgt2pl, &tgt2subsys, nullptr);
float angle2goal = angle2subsys;
if (angle2goal > 1.2f) // let's not try to go more than about 70 degrees around the ship
angle2goal = 1.2f;
// we'll start by travelling along the sphere at our current distance around the ship
// remember that goal_pos will be relative to our target_ship (so we can scale in and out easily)
vec3d goal_pos, cross;
vm_vec_cross(&cross, &tgt2pl, &tgt2subsys);
vm_vec_normalize(&cross);
vm_vec_negate(&cross);
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;
if (pp_collide(&Pl_objp->pos, &world_goal_pos, target_objp, Pl_objp->radius * 4.0f)) {
// ok best case won't work
if (pl_dist > subsys_dist) {
//we're farther away than the subsys, let's try at our current distance
world_goal_pos = goal_pos + target_objp->pos;
if (!pp_collide(&Pl_objp->pos, &world_goal_pos, target_objp, Pl_objp->radius * 4.0f))
good_pos = &world_goal_pos;
}
// ok, let's start moving it away and see if that's better
for (float i = 1.0f; i < 4.0f; i += 1.0f) {
if (good_pos)
break;
vm_vec_copy_scale(&world_goal_pos, &goal_pos, (new_radius / pl_dist) * powf(1.3f,i));
world_goal_pos += target_objp->pos;
if (!pp_collide(&Pl_objp->pos, &world_goal_pos, target_objp, Pl_objp->radius * 4.0f))
good_pos = &world_goal_pos;
}
// welp this sucks, just run away i guess
if (!good_pos) {
vm_vec_copy_normalize(&world_goal_pos, &tgt2pl);
world_goal_pos *= target_objp->radius + pl_dist;
world_goal_pos += target_objp->pos;
if (pp_collide(&Pl_objp->pos, &world_goal_pos, target_objp, Pl_objp->radius * 4.0f)) {
// ok best case won't work
if (pl_dist > subsys_dist) {
//we're farther away than the subsys, let's try at our current distance
world_goal_pos = goal_pos + target_objp->pos;
if (!pp_collide(&Pl_objp->pos, &world_goal_pos, target_objp, Pl_objp->radius * 4.0f))
good_pos = &world_goal_pos;
}
}
else
good_pos = &world_goal_pos;
aip->next_dynamic_path_check_time = timestamp( AI_DYNAMIC_PATH_RECHECK_DELAY );
// ok, let's start moving it away and see if that's better
for (float i = 1.0f; i < 4.0f; i += 1.0f) {
if (good_pos)
break;
vm_vec_copy_scale(&world_goal_pos, &goal_pos, (new_radius / pl_dist) * powf(1.3f,i));
world_goal_pos += target_objp->pos;
if (!pp_collide(&Pl_objp->pos, &world_goal_pos, target_objp, Pl_objp->radius * 4.0f))
good_pos = &world_goal_pos;
}
// welp this sucks, just run away i guess
if (!good_pos) {
vm_vec_copy_normalize(&world_goal_pos, &tgt2pl);
world_goal_pos *= target_objp->radius + pl_dist;
world_goal_pos += target_objp->pos;
good_pos = &world_goal_pos;
}
}
else{ //Not enough time has passed till recheck.
good_pos = &aip->last_dynamic_path_goal;
}
else
good_pos = &world_goal_pos;
ai_turn_towards_vector(good_pos, Pl_objp, nullptr, nullptr, 0.0f, 0);
float subsys_distance = vm_vec_dist(&Pl_objp->pos, &gsubpos);
+302 -403
View File
File diff suppressed because it is too large. Load diff
+81 -123
View File
@@ -11,7 +11,6 @@
#include "ai/aigoals.h"
#include "ai/ailua.h"
#include "globalincs/linklist.h"
#include "mission/missionlog.h"
#include "mission/missionparse.h"
@@ -54,6 +53,12 @@ struct ship_registry_entry;
// goals given from the player to other ships in the game are also handled in this
// code
#define AI_GOAL_ACHIEVABLE 1
#define AI_GOAL_NOT_ACHIEVABLE 2
#define AI_GOAL_NOT_KNOWN 3
#define AI_GOAL_SATISFIED 4
int Ai_goal_signature;
int Num_ai_dock_names = 0;
char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
@@ -95,7 +100,7 @@ int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
// HUD what a ship's current orders are. If the AI goal doesn't correspond to something that
// ought to be printable, then NULL is used.
// JAS: Converted to a function in order to externalize the strings
const char *Ai_goal_text(int goal, int submode)
const char *Ai_goal_text(int goal)
{
switch(goal) {
case AI_GOAL_CHASE:
@@ -126,15 +131,10 @@ const char *Ai_goal_text(int goal, int submode)
return XSTR( "rearm ", 484);
case AI_GOAL_FLY_TO_SHIP:
return XSTR( "rendezvous with ", 1597);
case AI_GOAL_LUA:
auto mode = ai_lua_find_mode(submode);
if (mode == nullptr)
return nullptr;
return mode->hudText;
}
// Avoid compiler warning
return nullptr;
return NULL;
}
void ai_maybe_add_form_goal(wing* wingp)
@@ -240,8 +240,8 @@ int ai_query_goal_valid( int ship, int ai_goal_type )
{
int accepted;
if (ai_goal_type == AI_GOAL_NONE || ai_goal_type == AI_GOAL_LUA)
return 1; // anything can have no orders or Lua'd orders.
if (ai_goal_type == AI_GOAL_NONE)
return 1; // anything can have no orders.
accepted = 0;
@@ -306,7 +306,7 @@ void ai_clear_ship_goals( ai_info *aip )
// add scripting hook for 'On Goals Cleared' --wookieejedi
if (Script_system.IsActiveAction(CHA_ONGOALSCLEARED)) {
Script_system.SetHookObject("Ship", &Objects[Ships[aip->shipnum].objnum]);
Script_system.RunCondition(CHA_ONGOALSCLEARED, &Objects[Ships[aip->shipnum].objnum]);
Script_system.RunCondition(CHA_ONGOALSCLEARED);
Script_system.RemHookVars({"Ship"});
}
}
@@ -659,7 +659,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, char *target_name, ai_goal *aigp, const object_ship_wing_point_team& lua_target )
void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name, ai_goal *aigp )
{
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
@@ -667,7 +667,6 @@ void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name,
aigp->type = type; // from player for sure -- could be to ship or to wing
aigp->ai_mode = mode; // major mode for this goal
aigp->ai_submode = submode; // could mean different things depending on mode
aigp->lua_ai_target = lua_target;
if ( mode == AI_GOAL_WARP ) {
if (submode >= 0) {
@@ -813,7 +812,7 @@ void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipn
// 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, char *shipname, ai_info *aip, const object_ship_wing_point_team& lua_target)
void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip )
{
int empty_index;
ai_goal *aigp;
@@ -822,7 +821,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, a
// get a pointer to the goal structure
aigp = &aip->goals[empty_index];
ai_add_goal_sub_player( type, mode, submode, shipname, aigp, lua_target );
ai_add_goal_sub_player( type, mode, submode, shipname, aigp );
// if the goal is to dock, then we must determine which dock points on the two ships to use.
// If the target of the dock is a cargo type container, then we should use DOCK_TYPE_CARGO
@@ -839,7 +838,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, a
// 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, char *shipname, int wingnum, const object_ship_wing_point_team& lua_target)
void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum )
{
int i, empty_index;
wing *wingp = &Wings[wingnum];
@@ -850,7 +849,7 @@ void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, i
int num = wingp->ship_index[i];
if ( num == -1 ) // ship must have been destroyed or departed
continue;
ai_add_ship_goal_player( type, mode, submode, shipname, &Ai_info[Ships[num].ai_index], lua_target );
ai_add_ship_goal_player( type, mode, submode, shipname, &Ai_info[Ships[num].ai_index] );
}
}
@@ -858,7 +857,7 @@ void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, i
// there are more waves to come. We use the same method here as when adding a goal to
// a ship -- find the first empty entry. If none exists, take the oldest entry and replace it.
empty_index = ai_goal_find_empty_slot( wingp->ai_goals, -1 );
ai_add_goal_sub_player( type, mode, submode, shipname, &wingp->ai_goals[empty_index], lua_target );
ai_add_goal_sub_player( type, mode, submode, shipname, &wingp->ai_goals[empty_index] );
}
@@ -1042,24 +1041,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
break;
default:
const ai_mode_lua* luaAIMode = ai_lua_find_mode(op);
if(luaAIMode != nullptr){
//Found a LuaAI mode sexp for this
int localnode = CDR(node);
aigp->ai_mode = AI_GOAL_LUA;
aigp->ai_submode = op;
if(luaAIMode->needsTarget) {
eval_object_ship_wing_point_team(&aigp->lua_ai_target, localnode);
localnode = CDR(localnode);
}
aigp->priority = atoi( CTEXT(localnode) );
}
else {
UNREACHABLE("Invalid SEXP-OP number %d for an AI goal!", op);
}
Int3(); // get ALLENDER -- invalid ai-goal specified for ai object!!!!
}
if ( aigp->priority > MAX_GOAL_PRIORITY ) {
@@ -1235,28 +1217,8 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_IGNORE_NEW;
break;
case OP_AI_FORM_ON_WING:
priority = 99;
goalmode = AI_GOAL_FORM_ON_WING;
break;
default:
const ai_mode_lua* luaAIMode = ai_lua_find_mode(op);
if(luaAIMode != nullptr){
//Found a LuaAI mode sexp for this
int localnode = CDR(node);
goalmode = AI_GOAL_LUA;
goalsubmode = op;
if(luaAIMode->needsTarget) {
localnode = CDR(localnode);
}
priority = localnode >= 0 ? atoi( CTEXT(localnode) ) : -1;
}
else {
UNREACHABLE("Invalid SEXP-OP %s (number %d) for an AI goal!", Sexp_nodes[node].text, op);
}
Int3( );
break;
};
@@ -1276,13 +1238,13 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
return goalindex;
}
// code to remove ai goals from wings.
// code to add ai goals to wings.
void ai_remove_wing_goal_sexp(int sexp, wing *wingp)
{
int i;
int goalindex = -1;
// remove the ai goal for any ship that is currently arrived in the game (only if fred isn't running)
// add the ai goal for any ship that is currently arrived in the game (only if fred isn't running)
if ( !Fred_running ) {
for (i = 0; i < wingp->current_count; i++) {
int num = wingp->ship_index[i];
@@ -1294,8 +1256,6 @@ void ai_remove_wing_goal_sexp(int sexp, wing *wingp)
}
}
// remove the sexpression index from the wing's list of goal sexpressions if
// there are more waves to come
if ((wingp->num_waves - wingp->current_wave > 0) || Fred_running)
{
ai_remove_goal_sexp_sub( sexp, wingp->ai_goals );
@@ -1449,10 +1409,10 @@ void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
// function to determine if an ai goal is achieveable or not. Will return
// one of the AI_GOAL_* values. Also determines is a goal was successful.
ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
int status;
ai_achievability return_val;
int return_val;
object *objp;
ai_info *aip;
int index = -1, sindex = -1;
@@ -1465,11 +1425,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// these orders are always achievable.
if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE)
|| (aigp->ai_mode == AI_GOAL_CHASE_ANY) || (aigp->ai_mode == AI_GOAL_STAY_STILL)
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) || (aigp->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT))
return ai_achievability::ACHIEVABLE;
if (aigp->ai_mode == AI_GOAL_LUA)
return ai_lua_is_achievable(aigp, objnum);
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) || (aigp->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT) )
return AI_GOAL_ACHIEVABLE;
// warp (depart) only achievable if there's somewhere to depart to
if (aigp->ai_mode == AI_GOAL_WARP)
@@ -1478,14 +1435,14 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// 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;
return AI_GOAL_ACHIEVABLE;
// if we can't warp, we can only depart if the ship (or its wing) departs to a fighter bay and the mothership is present
if (ship_can_bay_depart(shipp)) {
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
else {
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
}
}
@@ -1497,10 +1454,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
sindex = ship_name_lookup( aigp->target_name );
if (sindex < 0)
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
aigp->flags.set(AI::Goal_Flags::Goal_override);
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
// check to see if we have a valid list. If not, then try to set one up. If that
@@ -1511,10 +1468,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if ( aigp->wp_list == NULL ) {
Warning(LOCATION, "Unknown waypoint list %s - not found in mission file. Killing ai goal", aigp->target_name );
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
}
}
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
// chasing all ships of a certain ship class is achievable if there are ships of that class present;
@@ -1523,14 +1480,14 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if ( aigp->ai_mode == AI_GOAL_CHASE_SHIP_CLASS ) {
for (objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp)) {
if ((objp->type == OBJ_SHIP) && !strcmp(aigp->target_name, Ship_info[Ships[objp->instance].ship_info_index].name)) {
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
}
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
}
return_val = ai_achievability::SATISFIED;
return_val = AI_GOAL_SATISFIED;
// next, determine if the goal has been completed successfully
switch ( aigp->ai_mode )
@@ -1632,7 +1589,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
if ( status )
return_val = ai_achievability::NOT_ACHIEVABLE;
return_val = AI_GOAL_NOT_ACHIEVABLE;
} else {
status = 0;
}
@@ -1647,7 +1604,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if ( !status ) {
status = mission_log_get_time( LOG_WING_DESTROYED, aigp->target_name, NULL, NULL);
if ( status )
return_val = ai_achievability::NOT_ACHIEVABLE;
return_val = AI_GOAL_NOT_ACHIEVABLE;
}
break;
@@ -1661,14 +1618,14 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
Assert( aigp->target_instance >= 0 );
if ( Weapons[aigp->target_instance].objnum == -1 )
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
// if the signatures don't match, then goal isn't achievable.
if ( Objects[Weapons[aigp->target_instance].objnum].signature != aigp->target_signature )
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
// otherwise, we should be good to go
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
break;
}
@@ -1692,22 +1649,22 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
sindex = wing_name_lookup( aigp->target_name );
if (sindex < 0)
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
wing *wingp = &Wings[sindex];
if ( wingp->flags[Ship::Wing_Flags::Gone] )
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
else if ( wingp->total_arrived_count == 0 )
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
else
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
// Goober5000 - undocking from an unspecified object is always achievable;
// undocking from a specified object is handled below
else if ( (aigp->ai_mode == AI_GOAL_UNDOCK) && (aigp->target_name == NULL) )
{
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
else
{
@@ -1748,7 +1705,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
// if the ship has no turrets, we can't disarm it!
if (Ships[ship_name_lookup(aigp->target_name)].subsys_info[SUBSYSTEM_TURRET].type_count == 0)
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
}
// if the goal is an ignore/disable/disarm goal, then
@@ -1790,12 +1747,12 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if ( (aigp->dockee.index == -1) || (aigp->docker.index == -1) ) {
Int3(); // for now, allender wants to know about these things!!!!
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
}
// if ship is disabled, don't know if it can dock or not
if ( Ships[objp->instance].flags[Ship::Ship_Flags::Disabled] )
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
// we must also determine if we're prevented from docking for any reason
sindex = ship_name_lookup(aigp->target_name);
@@ -1817,7 +1774,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
else if (obstacle_objp != objp)
{
// return NOT_KNOWN which will place the goal on hold until the dockpoint is clear
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
}
}
@@ -1837,7 +1794,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
ai_add_goal_ship_internal( aip, AI_GOAL_UNDOCK, Ships[obstacle_objp->instance].ship_name, -1, -1, 0 );
// return NOT_KNOWN which will place the goal on hold until the undocking is complete.
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
}
}
@@ -1851,7 +1808,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
// only put it on hold if it's someone other than the guy we're undocking from right now!!
if (aip->goal_objnum != Ships[ship_name_lookup(aigp->target_name)].objnum)
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
}
} else if ( (aigp->ai_mode == AI_GOAL_DESTROY_SUBSYSTEM) && (status == SHIP_STATUS_ARRIVED) ) {
@@ -1862,11 +1819,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
sindex = ship_name_lookup( aigp->target_name );
if ( sindex != -1 ) {
aigp->ai_submode = ship_find_subsys( &Ships[sindex], aigp->docker.name );
aigp->ai_submode = ship_get_subsys_index( &Ships[sindex], aigp->docker.name );
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
} else {
Int3();
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
return AI_GOAL_NOT_ACHIEVABLE; // force this goal to be invalid
}
}
} else if ( ((aigp->ai_mode == AI_GOAL_IGNORE) || (aigp->ai_mode == AI_GOAL_IGNORE_NEW)) && (status == SHIP_STATUS_ARRIVED) ) {
@@ -1879,7 +1836,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
ai_ignore_object(objp, ignored, (aigp->ai_mode == AI_GOAL_IGNORE_NEW));
return ai_achievability::SATISFIED;
return AI_GOAL_SATISFIED;
}
switch ( aigp->ai_mode )
@@ -1900,13 +1857,13 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
case AI_GOAL_FLY_TO_SHIP:
{
if ( status == SHIP_STATUS_ARRIVED )
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
else if ( status == SHIP_STATUS_NOT_ARRIVED )
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
else if ( status == SHIP_STATUS_GONE )
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
else if ( status == SHIP_STATUS_UNKNOWN )
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
Int3(); // get allender -- bad logic
break;
@@ -1921,61 +1878,66 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// we mark the goal as not achievable.
if ( status == SHIP_STATUS_NOT_ARRIVED ) {
Int3(); // get Allender. this shouldn't happen!!!
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
}
if ( status == SHIP_STATUS_GONE )
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
Int3();
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
}
// 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;
return AI_GOAL_ACHIEVABLE;
// if the destination ship is dying or departing (but not completed yet), the mark goal as
// not achievable.
if ( Ships[sindex].is_dying_or_departing())
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
// if the destination object is no longer awaiting repair, then remove the item
if ( !(Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
return ai_achievability::NOT_ACHIEVABLE;
return AI_GOAL_NOT_ACHIEVABLE;
// not repairing anything means that he can do this goal!!!
if ( !(aip->ai_flags[AI::AI_Flags::Repairing]) )
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
// test code!!!
if ( aip->goal_objnum == -1 ) {
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
// 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 != Ships[sindex].objnum )
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
return ai_achievability::ACHIEVABLE;
return AI_GOAL_ACHIEVABLE;
}
default:
Int3(); // invalid case in switch:
}
return ai_achievability::NOT_KNOWN;
return AI_GOAL_NOT_KNOWN;
}
// Compare function for sorting ai_goals based on priority.
// Return values set to sort array in _decreasing_ order.
int ai_goal_priority_compare(const ai_goal *ga, const ai_goal *gb)
int ai_goal_priority_compare(const void *a, const void *b)
{
ai_goal *ga, *gb;
ga = (ai_goal *) a;
gb = (ai_goal *) b;
// first, sort based on whether or not the ON_HOLD flag is set for the goal.
// If the flag is set, don't push the goal higher in the list even if priority
// is higher since goal cannot currently be achieved.
@@ -2023,7 +1985,7 @@ int ai_goal_priority_compare(const ai_goal *ga, const ai_goal *gb)
void prioritize_goals(ai_info *aip)
{
// First sort based on priority field.
insertion_sort(aip->goals, MAX_AI_GOALS, ai_goal_priority_compare);
insertion_sort(aip->goals, MAX_AI_GOALS, sizeof(ai_goal), ai_goal_priority_compare);
}
// Scan the list of goals at aip->goals.
@@ -2037,7 +1999,7 @@ void validate_mission_goals(int objnum, ai_info *aip)
// loop through all of the goals to determine which goal should be followed.
// This determination will be based on priority, and the time at which it was issued.
for ( i = 0; i < MAX_AI_GOALS; i++ ) {
ai_achievability state;
int state;
ai_goal *aigp;
aigp = &aip->goals[i];
@@ -2056,18 +2018,18 @@ void validate_mission_goals(int objnum, ai_info *aip)
state = ai_mission_goal_achievable( objnum, aigp );
// if this order is no longer a valid one, remove it
if ( (state == ai_achievability::NOT_ACHIEVABLE) || (state == ai_achievability::SATISFIED) ) {
if ( (state == AI_GOAL_NOT_ACHIEVABLE) || (state == AI_GOAL_SATISFIED) ) {
ai_remove_ship_goal( aip, i );
continue;
}
// if the status is achievable, and the on_hold flag is set, clear the flagb
if ( (state == ai_achievability::ACHIEVABLE) && (aigp->flags[AI::Goal_Flags::Goal_on_hold]) )
if ( (state == AI_GOAL_ACHIEVABLE) && (aigp->flags[AI::Goal_Flags::Goal_on_hold]) )
aigp->flags.remove(AI::Goal_Flags::Goal_on_hold);
// if the goal is not known, then set the ON_HOLD flag so that it doesn't get counted as
// a goal to be pursued
if (state == ai_achievability::NOT_KNOWN)
if (state == AI_GOAL_NOT_KNOWN)
aigp->flags.set(AI::Goal_Flags::Goal_on_hold); // put this goal on hold until it becomes true
}
@@ -2435,17 +2397,13 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
other_obj = &Objects[Ships[shipnum].objnum];
ai_rearm_repair( objp, current_goal->docker.index, other_obj, current_goal->dockee.index );
break;
case AI_GOAL_LUA:
ai_lua_start(current_goal, objp);
break;
default:
Int3();
break;
}
if (old_form_objnum >= 0)
if (old_form_objnum != -1)
ai_formation_object_recalculate_slotnums(old_form_objnum);
}
+4 -8
View File
@@ -14,7 +14,6 @@
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
#include "parse/sexp.h"
struct wing;
struct ai_info;
@@ -60,7 +59,6 @@ struct ai_goal;
#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) // 0x03000000
#define AI_GOAL_LUA (1<<27) // 0x04000000
// now the masks for ship types
@@ -84,8 +82,6 @@ struct ai_goal;
#define MAX_AI_DOCK_NAMES 25
enum class ai_achievability { ACHIEVABLE, NOT_ACHIEVABLE, NOT_KNOWN, SATISFIED };
typedef flag_def_list ai_goal_list;
extern ai_goal_list Ai_goal_names[];
@@ -94,7 +90,7 @@ extern int Num_ai_goals;
extern int Num_ai_dock_names;
extern char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
extern const char *Ai_goal_text(int goal, int submode);
extern const char *Ai_goal_text(int goal);
// extern function definitions
extern void ai_post_process_mission();
@@ -107,14 +103,14 @@ extern int ai_goal_num(ai_goal *goals);
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_goal *aigp, char *actor_name);
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name );
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
extern void ai_remove_wing_goal_sexp( int sexp, wing *wingp );
// adds goals to ships/sings through player orders
extern void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip, const object_ship_wing_point_team& lua_target = object_ship_wing_point_team());
extern void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum, const object_ship_wing_point_team& lua_target = object_ship_wing_point_team());
extern void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip );
extern void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum );
extern void ai_remove_ship_goal( ai_info *aip, int index );
extern void ai_clear_ship_goals( ai_info *aip );
-239
View File
@@ -1,239 +0,0 @@
#include "ai/ailua.h"
#include "hud/hudsquadmsg.h"
#include "iff_defs/iff_defs.h"
#include "parse/sexp/sexp_lookup.h"
#include "parse/sexp/LuaAISEXP.h"
#include "scripting/api/objs/ai_helper.h"
#include "scripting/api/objs/enums.h"
#include "scripting/api/objs/oswpt.h"
#include "scripting/api/objs/ship.h"
#include "scripting/scripting.h"
static std::unordered_map<int, ai_mode_lua> Lua_ai_modes;
static std::unordered_map<int, player_order_lua> Lua_player_orders;
void ai_lua_add_mode(int sexp_op, const ai_mode_lua& mode) {
Lua_ai_modes.emplace(sexp_op, mode);
}
bool ai_lua_add_order(int sexp_op, player_order_lua order) {
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;
}
bool ai_lua_has_mode(int sexp_op){
return Lua_ai_modes.count(sexp_op) > 0;
}
const ai_mode_lua* ai_lua_find_mode(int sexp_op){
auto aiLuaMode = Lua_ai_modes.find(sexp_op);
if(aiLuaMode == Lua_ai_modes.end())
return nullptr;
else
return &aiLuaMode->second;
}
const player_order_lua* ai_lua_find_player_order(int sexp_op) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return nullptr;
else
return &aiLuaOrder->second;
}
void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua_ai, ai_info* aip) {
if (!action.isValid()) {
Error(LOCATION,
"Lua AI SEXP called without a valid action function! A script probably failed to set the action for some reason.");
return;
}
luacpp::LuaValueList luaParameters;
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)));
}
auto retVals = action.call(Script_system.GetLuaSession(), luaParameters);
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::BOOLEAN) {
if (retVals[0].getValue<bool>())
ai_mission_goal_complete(aip);
}
}
void ai_lua(ai_info* aip){
Assertion(aip->mode == AIM_LUA, "Tried to invoke LuaAI on a ship not in LuaAI-Mode");
const auto& lua_ai = Lua_ai_modes.at(aip->submode);
auto dynamicSEXP = sexp::get_dynamic_sexp(aip->submode);
if (dynamicSEXP != nullptr && typeid(*dynamicSEXP) == typeid(sexp::LuaAISEXP)) {
auto lua_ai_sexp = static_cast<sexp::LuaAISEXP*>(dynamicSEXP);
const auto& action = lua_ai_sexp->getActionFrame();
run_ai_lua_action(action, lua_ai, aip);
}
}
void ai_lua_start(ai_goal* aigp, object* objp){
Assert(objp->type == OBJ_SHIP);
Assert((objp->instance >= 0) && (objp->instance < MAX_SHIPS));
ai_info *aip = &Ai_info[Ships[objp->instance].ai_index];
aip->mode = AIM_LUA;
aip->submode = aigp->ai_submode;
aip->lua_ai_target = aigp->lua_ai_target;
aip->submode_start_time = Missiontime;
const auto& lua_ai = Lua_ai_modes.at(aigp->ai_submode);
auto dynamicSEXP = sexp::get_dynamic_sexp(aigp->ai_submode);
if (dynamicSEXP != nullptr && typeid(*dynamicSEXP) == typeid(sexp::LuaAISEXP)) {
auto lua_ai_sexp = static_cast<sexp::LuaAISEXP*>(dynamicSEXP);
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];
const player_order_lua& order = *ai_lua_find_player_order(sexp_op);
switch (order.targetRestrictions) {
case player_order_lua::target_restrictions::TARGET_ALL:
return true;
case player_order_lua::target_restrictions::TARGET_OWN:
return target->team == self->team;
case player_order_lua::target_restrictions::TARGET_ALLIES:
return !iff_x_attacks_y(self->team, target->team);
case player_order_lua::target_restrictions::TARGET_ENEMIES:
return iff_x_attacks_y(self->team, target->team);
case player_order_lua::target_restrictions::TARGET_SAME_WING:
return target->wingnum != -1 && self->wingnum == target->wingnum;
case player_order_lua::target_restrictions::TARGET_PLAYER_WING:
return target->wingnum != -1 && Ships[Player_obj->instance].wingnum == target->wingnum;
case player_order_lua::target_restrictions::TARGET_ALL_CAPS:
return Ship_info[target->ship_info_index].is_big_ship();
case player_order_lua::target_restrictions::TARGET_ALLIED_CAPS:
return !iff_x_attacks_y(self->team, target->team) && Ship_info[target->ship_info_index].is_big_ship();
case player_order_lua::target_restrictions::TARGET_ENEMY_CAPS:
return iff_x_attacks_y(self->team, target->team) && Ship_info[target->ship_info_index].is_big_ship();
case player_order_lua::target_restrictions::TARGET_NOT_SELF:
return self->objnum != target_objnum;
}
return false;
}
bool ai_lua_is_valid_target_lua(const ai_mode_lua& mode, int sexp_op, int target_objnum, ship* self) {
auto dynamicSEXP = sexp::get_dynamic_sexp(sexp_op);
if (dynamicSEXP != nullptr && typeid(*dynamicSEXP) == typeid(sexp::LuaAISEXP)) {
auto lua_ai_sexp = static_cast<sexp::LuaAISEXP*>(dynamicSEXP);
const auto& action = lua_ai_sexp->getTargetRestrict();
if (!action.isValid())
return true;
luacpp::LuaValueList luaParameters;
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_Ship.Set(object_h(&Objects[self->objnum]))));
if (mode.needsTarget) {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_OSWPT.Set(object_ship_wing_point_team(&Ships[Objects[target_objnum].instance]))));
}
auto retVals = action.call(Script_system.GetLuaSession(), luaParameters);
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::BOOLEAN) {
return retVals[0].getValue<bool>();
}
else {
Error(LOCATION, "LuaAI target restriction function did not return a valid boolean!");
}
}
return true;
}
bool ai_lua_is_valid_target(int sexp_op, int target_objnum, ship* self) {
const ai_mode_lua& mode = *ai_lua_find_mode(sexp_op);
//All targetless AI modes are fine
if (mode.needsTarget) {
//No target is then not valid
if (target_objnum == -1)
return false;
//As of now, only accept ships
if (Objects[target_objnum].type != OBJ_SHIP)
return false;
if (!ai_lua_is_valid_target_intrinsic(sexp_op, target_objnum, self))
return false;
}
//If we haven't bailed yet, query the custom callback
return ai_lua_is_valid_target_lua(mode, sexp_op, target_objnum, self);
}
ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum){
const auto& lua_ai = Lua_ai_modes.at(aigp->ai_submode);
auto dynamicSEXP = sexp::get_dynamic_sexp(aigp->ai_submode);
if (dynamicSEXP != nullptr && typeid(*dynamicSEXP) == typeid(sexp::LuaAISEXP)) {
auto lua_ai_sexp = static_cast<sexp::LuaAISEXP*>(dynamicSEXP);
const auto& action = lua_ai_sexp->getAchievable();
if (!action.isValid())
return ai_achievability::ACHIEVABLE;
luacpp::LuaValueList luaParameters;
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_Ship.Set(object_h(&Objects[objnum]))));
if (lua_ai.needsTarget) {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_OSWPT.Set(aigp->lua_ai_target)));
}
auto retVals = action.call(Script_system.GetLuaSession(), luaParameters);
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()) {
Error(LOCATION, "LuaAI SEXP achievability hook returned an invalid avilability enum.");
return ai_achievability::ACHIEVABLE;
}
switch (enumData.index) {
case scripting::api::LE_LUAAI_ACHIEVABLE:
return ai_achievability::ACHIEVABLE;
case scripting::api::LE_LUAAI_NOT_YET_ACHIEVABLE:
return ai_achievability::NOT_KNOWN;
case scripting::api::LE_LUAAI_UNACHIEVABLE:
return ai_achievability::NOT_ACHIEVABLE;
default:
Error(LOCATION, "LuaAI SEXP achievability hook returned an invalid avilability enum.");
return ai_achievability::ACHIEVABLE;
}
}
else {
Error(LOCATION, "LuaAI SEXP achievability hook did not return any avilability enum!");
}
}
return ai_achievability::ACHIEVABLE;
}
-29
View File
@@ -1,29 +0,0 @@
#pragma once
#include "ai/ai.h"
#include "ai/aigoals.h"
#include "mission/missionmessage.h"
#include "ship/ship.h"
#include "globalincs/globals.h"
struct ai_mode_lua {
bool needsTarget;
const char* hudText;
};
struct player_order_lua {
int ai_message = MESSAGE_YESSIR;
SCP_string parseText = "";
SCP_string displayText = "";
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;
};
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);
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);
void ai_lua(ai_info* aip);
void ai_lua_start(ai_goal* aigp, object* objp);
bool ai_lua_is_valid_target(int sexp_op, int target_objnum, ship* self);
ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum);
+13 -15
View File
@@ -434,7 +434,7 @@ int valid_turret_enemy(object *objp, object *turret_parent)
}
// don't shoot at ships without collision check
if (!(objp->flags[Object::Object_Flags::Collides]) && !(objp->flags[Object::Object_Flags::Attackable_if_no_collide])) {
if (!(objp->flags[Object::Object_Flags::Collides])) {
return 0;
}
@@ -1782,8 +1782,6 @@ 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, 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 = *firing_vec;
@@ -1820,13 +1818,13 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
memset(&fire_info, 0, sizeof(beam_fire_info));
fire_info.accuracy = 1.0f;
fire_info.beam_info_index = turret_weapon_class;
fire_info.beam_info_override = nullptr;
fire_info.beam_info_override = NULL;
fire_info.shooter = &Objects[parent_objnum];
fire_info.target = turret_enemy_objp;
fire_info.target = &Objects[turret->turret_enemy_objnum];
if (wip->wi_flags[Weapon::Info_Flags::Antisubsysbeam])
fire_info.target_subsys = turret->targeted_subsys;
else
fire_info.target_subsys = nullptr;
fire_info.target_subsys = NULL;
fire_info.turret = turret;
fire_info.burst_seed = old_burst_seed;
fire_info.fire_method = BFM_TURRET_FIRED;
@@ -1843,8 +1841,8 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
turret->last_fired_weapon_info_index = turret_weapon_class;
if (Script_system.IsActiveAction(CHA_ONTURRETFIRED)) {
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", nullptr, "Beam", objp, "Target", turret_enemy_objp);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum], objp);
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", nullptr, "Beam", objp, "Target", &Objects[turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum]);
Script_system.RemHookVars({"Ship", "Weapon", "Beam", "Target"});
}
}
@@ -1986,8 +1984,8 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
wp->turret_subsys = turret;
if (Script_system.IsActiveAction(CHA_ONTURRETFIRED)) {
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", objp, "Beam", nullptr, "Target", turret_enemy_objp);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum], objp);
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", objp, "Beam", nullptr, "Target", &Objects[turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum]);
Script_system.RemHookVars({"Ship", "Weapon", "Beam", "Target"});
}
@@ -2017,7 +2015,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if ( MULTIPLAYER_MASTER && (weapon_objnum != -1) ) {
int subsys_index;
subsys_index = ship_get_subsys_index(turret);
subsys_index = ship_get_index_from_subsys(turret, parent_objnum );
Assert( subsys_index != -1 );
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
send_flak_fired_packet( parent_objnum, subsys_index, weapon_objnum, flak_range );
@@ -2105,7 +2103,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
if (Script_system.IsActiveAction(CHA_ONTURRETFIRED)) {
Script_system.SetHookObjects(4, "Ship", &Objects[tsi->parent_objnum], "Weapon", &Objects[weapon_objnum], "Beam", nullptr, "Target", &Objects[tsi->turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[tsi->parent_objnum], &Objects[weapon_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[tsi->parent_objnum]);
Script_system.RemHookVars({"Ship", "Weapon", "Beam", "Target"});
}
@@ -2126,7 +2124,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
if ( MULTIPLAYER_MASTER && (weapon_objnum != -1) ) {
int subsys_index;
subsys_index = ship_get_subsys_index(tsi->turret);
subsys_index = ship_get_index_from_subsys(tsi->turret, tsi->parent_objnum );
Assert( subsys_index != -1 );
send_turret_fired_packet( tsi->parent_objnum, subsys_index, weapon_objnum );
}
@@ -2742,7 +2740,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
{
//something did fire, get the lowest valid timestamp
// don't do this if we already set a turret timestamp previously in the function
if (timestamp_since(ss->turret_next_fire_stamp) > 0)
if (timestamp_until(ss->turret_next_fire_stamp) <= 0)
{
int minimum_stamp = -1;
@@ -2751,7 +2749,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
int stamp = (i < MAX_SHIP_PRIMARY_BANKS) ? swp->next_primary_fire_stamp[i] : swp->next_secondary_fire_stamp[i - MAX_SHIP_PRIMARY_BANKS];
// valid timestamps start at 2; stamp must be in the future
if (stamp < 2 || timestamp_since(stamp) > 0)
if (stamp < 2 || timestamp_until(stamp) <= 0)
continue;
// find minimum
+6 -8
View File
@@ -32,7 +32,7 @@
#include "object/objcollide.h"
#include "object/object.h"
#include "parse/parselo.h"
#include "scripting/global_hooks.h"
#include "scripting/scripting.h"
#include "particle/particle.h"
#include "render/3d.h"
#include "ship/ship.h"
@@ -1511,12 +1511,11 @@ static void asteroid_maybe_break_up(object *pasteroid_obj)
if ( timestamp_elapsed(asp->final_death_time) ) {
vec3d relvec, vfh, tvec;
bool skip = false;
bool hooked = scripting::hooks::OnDeath->isActive();
bool hooked = Script_system.IsActiveAction(CHA_DEATH);
if (hooked) {
skip = scripting::hooks::OnDeath->isOverride(
scripting::hook_param_list(scripting::hook_param("Self", 'o', pasteroid_obj)),
pasteroid_obj);
Script_system.SetHookObject("Self", pasteroid_obj);
skip = Script_system.IsConditionOverride(CHA_DEATH, pasteroid_obj);
}
if (!skip)
{
@@ -1624,9 +1623,8 @@ static void asteroid_maybe_break_up(object *pasteroid_obj)
asp->final_death_time = timestamp(-1);
}
if (hooked) {
scripting::hooks::OnDeath->run(
scripting::hook_param_list(scripting::hook_param("Self", 'o', pasteroid_obj)),
pasteroid_obj);
Script_system.RunCondition(CHA_DEATH, pasteroid_obj);
Script_system.RemHookVar("Self");
}
}
}
-15
View File
@@ -1581,18 +1581,3 @@ bool IsVisited(int nav)
return 1;
return 0;
}
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
void Nav_SetColor(const char *nav, bool visited, ubyte r, ubyte g, ubyte b)
{
int n = FindNav(nav);
if (n >= 0 && n < MAX_NAVPOINTS)
{
auto rgb = visited ? Navs[n].visited_color : Navs[n].normal_color;
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
}
-12
View File
@@ -31,8 +31,6 @@ class NavPoint
public:
char m_NavName[32];
int flags;
ubyte normal_color[3];
ubyte visited_color[3];
const void *target_obj;
int waypoint_num; //only used when flags & NP_WAYPOINT
@@ -44,14 +42,6 @@ public:
m_NavName[0] = 0;
flags = 0;
normal_color[0] = 0x80;
normal_color[1] = 0x80;
normal_color[2] = 0xFF;
visited_color[0] = 0xFF;
visited_color[1] = 0xFF;
visited_color[2] = 0x00;
target_obj = nullptr;
waypoint_num = -1;
}
@@ -165,8 +155,6 @@ unsigned int DistanceTo(int nav);
bool IsVisited(const char *nav);
bool IsVisited(int nav);
void Nav_SetColor(const char *nav, bool visited, ubyte r, ubyte g, ubyte b);
void send_autopilot_msg(const char *msg, const char *snd=nullptr);
void send_autopilot_msgID(int msgid);
#endif
+9 -2
View File
@@ -592,9 +592,12 @@ void bm_convert_format(bitmap *bmp, ushort flags) {
return;
if (Is_standalone) {
Assert(bmp->bpp == 8);
return;
} else {
if(!(flags & BMP_AABITMAP))
if (flags & BMP_AABITMAP)
Assert(bmp->bpp == 8);
else
Assert((bmp->bpp == 16) || (bmp->bpp == 32));
}
@@ -1872,7 +1875,9 @@ bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
}
// otherwise do it as normal
else {
if ((flags & BMP_TEX_NONCOMP) && (!(flags & BMP_TEX_COMP))) {
if (flags & BMP_AABITMAP) {
Assert(bpp == 8);
} else if ((flags & BMP_TEX_NONCOMP) && (!(flags & BMP_TEX_COMP))) {
Assert(bpp >= 16); // cheating but bpp passed isn't what we normally end up with
} else if ((flags & BMP_TEX_DXT1) || (flags & BMP_TEX_DXT3) || (flags & BMP_TEX_DXT5) || (flags & BMP_TEX_BC7)) {
Assert(bpp >= 16); // cheating but bpp passed isn't what we normally end up with
@@ -1882,6 +1887,8 @@ bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
(be->type == BM_TYPE_CUBEMAP_DXT3) ||
(be->type == BM_TYPE_CUBEMAP_DXT5));
Assert(bpp >= 16);
} else {
Assert(0); //?
}
}
+27 -97
View File
@@ -9,13 +9,11 @@
#include "model/model.h" //polymodel, model_get
#include "options/Option.h"
#include "parse/parselo.h"
#include "parse/sexp_container.h"
#include "playerman/player.h" //player_get_padlock_orient
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
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;
@@ -243,16 +241,7 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
{
vec3d position;
matrix orient_buf;
matrix *orient = nullptr;
if (Use_host_orientation_for_set_camera_facing)
{
// we want to retrieve the camera's orientation, so provide a buffer for it
orient = &orient_buf;
// reset the camera's orientation state because if we have no host object, that is what the camera will default to
c_ori = vmd_identity_matrix;
}
auto orient = Use_host_orientation_for_set_camera_facing ? &orient_buf : nullptr;
this->get_info(&position, orient, false);
@@ -608,46 +597,11 @@ void warp_camera::get_info(vec3d *position, matrix *orientation)
#define MAX_SUBTITLE_LINES 64
subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char* in_imageanim, float in_display_time,
float in_fade_time, const color* in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width,
int in_height, bool in_post_shaded, int in_line_height_modifier, bool in_adjust_wh)
: display_time(-1.0f), fade_time(-1.0f), text_fontnum(-1), line_height_modifier(0),
image_id(-1), time_displayed(-1.0f), time_displayed_end(-1.0f), post_shaded(false), do_screen_scaling(false)
float in_fade_time, const color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width,
int in_height, bool in_post_shaded, float in_line_height_factor)
: display_time(-1.0f), fade_time(-1.0f), text_fontnum(-1), line_height_factor(1.0f),
image_id(-1), time_displayed(-1.0f), time_displayed_end(-1.0f), post_shaded(false)
{
if ((in_text == nullptr || *in_text == '\0') && (in_imageanim == nullptr || *in_imageanim == '\0'))
return;
auto screen_w = gr_screen.center_w;
auto screen_h = gr_screen.center_h;
// we might be doing screen scaling
if (Show_subtitle_screen_base_res[0] > 0 && Show_subtitle_screen_base_res[1] > 0)
{
// The way this works is we specify our subtitle coordinates relative to a base resolution, e.g. 1024x768.
// The base resolution is adjusted behind the scenes to match the aspect ratio of the current resolution
// (and the subtitle coordinates are adjusted as well). Then the adjusted subtitles are resized by the
// graphics code when they are drawn to the screen.
do_screen_scaling = true;
// we might need to adjust the coordinates for aspect ratio
if (in_adjust_wh)
{
if (Show_subtitle_screen_base_res[0] != Show_subtitle_screen_adjusted_res[0])
{
in_x_pos = in_x_pos * Show_subtitle_screen_adjusted_res[0] / Show_subtitle_screen_base_res[0];
in_width = in_width * Show_subtitle_screen_adjusted_res[0] / Show_subtitle_screen_base_res[0];
}
if (Show_subtitle_screen_base_res[1] != Show_subtitle_screen_adjusted_res[1])
{
in_y_pos = in_y_pos * Show_subtitle_screen_adjusted_res[1] / Show_subtitle_screen_base_res[1];
in_height = in_height * Show_subtitle_screen_adjusted_res[1] / Show_subtitle_screen_base_res[1];
}
}
// use these because we will be scaling the subtitle when it is displayed
screen_w = Show_subtitle_screen_adjusted_res[0];
screen_h = Show_subtitle_screen_adjusted_res[1];
}
// Initialize color
gr_init_color(&text_color, 0, 0, 0);
@@ -658,11 +612,13 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
memset( &text_pos, 0, 2*sizeof(int) );
memset( &image_pos, 0, 4*sizeof(int) );
if ( ((in_text != NULL) && (strlen(in_text) <= 0)) && ((in_imageanim != NULL) && (strlen(in_imageanim) <= 0)) )
return;
if (in_text != NULL && in_text[0] != '\0')
{
text_buf = in_text;
sexp_replace_variable_names_with_values(text_buf);
sexp_container_replace_refs_with_values(text_buf);
in_text = text_buf.c_str();
}
@@ -688,7 +644,7 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
else
gr_init_alphacolor(&text_color, 255, 255, 255, 255);
text_fontnum = in_text_fontnum;
line_height_modifier = in_line_height_modifier;
line_height_factor = in_line_height_factor;
//Setup display and fade time
display_time = fl_abs(in_display_time);
@@ -727,15 +683,7 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
if(w > tw)
tw = w;
if (line_height_modifier != 0.0f)
{
if (Show_subtitle_uses_pixels)
h = line_height_modifier;
else
h = fl2i(h * line_height_modifier / 100.0f);
}
th += h;
th += fl2i(line_height_factor * h);
}
// restore old font
@@ -760,20 +708,20 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
//Center it?
if(center_x)
image_pos.x = (screen_w - tw)/2;
image_pos.x = (gr_screen.center_w - tw)/2 + gr_screen.center_offset_x;
if(center_y)
image_pos.y = (screen_h - th)/2;
image_pos.y = (gr_screen.center_h - th)/2 + gr_screen.center_offset_y;
}
if(in_x_pos < 0 && !center_x)
image_pos.x += screen_w + in_x_pos;
image_pos.x += gr_screen.center_offset_x + gr_screen.center_w + in_x_pos;
else if(!center_x)
image_pos.x += in_x_pos;
image_pos.x += gr_screen.center_offset_x + in_x_pos;
if(in_y_pos < 0 && !center_y)
image_pos.y += screen_h + in_y_pos;
image_pos.y += gr_screen.center_offset_y + gr_screen.center_h + in_y_pos;
else if(!center_y)
image_pos.y += in_y_pos;
image_pos.y += gr_screen.center_offset_y + in_y_pos;
image_pos.w = in_width;
image_pos.h = in_height;
@@ -829,32 +777,24 @@ void subtitle::do_frame(float frametime)
int x = text_pos.x;
int y = text_pos.y;
auto sizing_mode = do_screen_scaling ? GR_RESIZE_FULL : GR_RESIZE_NONE;
if (do_screen_scaling)
gr_set_screen_scale(Show_subtitle_screen_adjusted_res[0], Show_subtitle_screen_adjusted_res[1]);
// do the actual drawing ---------------------
for(SCP_vector<SCP_string>::iterator line = text_lines.begin(); line != text_lines.end(); ++line)
{
gr_string(x, y, (char*)line->c_str(), sizing_mode);
gr_string(x, y, (char*)line->c_str(), GR_RESIZE_NONE);
y += fl2i(line_height_factor * font_height);
}
if (line_height_modifier != 0.0f)
{
if (Show_subtitle_uses_pixels)
font_height = line_height_modifier;
else
font_height = fl2i(font_height * line_height_modifier / 100.0f);
}
y += font_height;
// restore old font
if (old_fontnum >= 0)
{
font::set_font(old_fontnum);
}
if(image_id >= 0)
{
gr_set_bitmap(image_id, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, text_color.alpha/255.0f);
// image scaling?
// scaling?
if (image_pos.w > 0 || image_pos.h > 0)
{
int orig_w, orig_h;
@@ -866,25 +806,16 @@ void subtitle::do_frame(float frametime)
scale.xyz.z = 1.0f;
gr_push_scale_matrix(&scale);
gr_bitmap(fl2i(image_pos.x / scale.xyz.x), fl2i(image_pos.y / scale.xyz.y), sizing_mode);
gr_bitmap(fl2i(image_pos.x / scale.xyz.x), fl2i(image_pos.y / scale.xyz.y), GR_RESIZE_NONE);
gr_pop_scale_matrix();
}
// no scaling
else
{
gr_bitmap(image_pos.x, image_pos.y, sizing_mode);
gr_bitmap(image_pos.x, image_pos.y, GR_RESIZE_NONE);
}
}
// finished the actual drawing ---------------
if (do_screen_scaling)
gr_reset_screen_scale();
// restore old font
if (old_fontnum >= 0)
font::set_font(old_fontnum);
time_displayed += frametime;
}
@@ -901,7 +832,7 @@ void subtitle::clone(const subtitle &sub)
{
text_lines = sub.text_lines;
text_fontnum = sub.text_fontnum;
line_height_modifier = sub.line_height_modifier;
line_height_factor = sub.line_height_factor;
// copy the structs
text_pos = sub.text_pos;
@@ -924,7 +855,6 @@ void subtitle::clone(const subtitle &sub)
time_displayed_end = sub.time_displayed_end;
post_shaded = sub.post_shaded;
do_screen_scaling = sub.do_screen_scaling;
}
subtitle& subtitle::operator=(const subtitle &sub)
+2 -5
View File
@@ -123,7 +123,7 @@ private:
float fade_time;
color text_color;
int text_fontnum;
int line_height_modifier;
float line_height_factor;
//Done with set
char imageanim[MAX_FILENAME_LEN];
@@ -137,13 +137,11 @@ private:
float time_displayed_end;
bool post_shaded;
bool do_screen_scaling;
public:
subtitle(int in_x_pos, int in_y_pos, const char* in_text = NULL, const char* in_imageanim = NULL,
float in_display_time = 0, float in_fade_time = 0.0f, const color *in_text_color = NULL, int in_text_fontnum = -1,
bool center_x = false, bool center_y = false, int in_width = 0, int in_height = 0, bool post_shaded = false,
int in_line_height_modifier = 0, bool in_adjust_wh = true);
float in_line_height_factor = 1.0f);
~subtitle();
subtitle(const subtitle &sub) { clone(sub); }
@@ -156,7 +154,6 @@ public:
//Some global stuff
extern SCP_vector<subtitle> Subtitles;
extern float VIEWER_ZOOM_DEFAULT;
extern float COCKPIT_ZOOM_DEFAULT;
extern float Sexp_fov;
//Helpful functions
+4 -4
View File
@@ -74,7 +74,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf .otf", CF_TYPE_DATA },
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", /* DON'T add pilot files here!! */ CF_TYPE_DATA },
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
{ CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css .json", CF_TYPE_PLAYERS },
@@ -86,7 +86,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc .fnl", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
{ CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA },
{ CF_TYPE_INTERFACE_MARKUP, "data" DIR_SEPARATOR_STR "interface" DIR_SEPARATOR_STR "markup", ".rml", CF_TYPE_INTERFACE },
@@ -635,7 +635,7 @@ void cf_create_directory(int dir_type, uint32_t location_flags)
//
// parameters: *filepath ==> name of file to open (may be path+name)
// *mode ==> specifies how file should be opened (eg "rb" for read binary)
// passing NULL to mode triggers an assert and returns NULL
// passing NULL to mode deletes the file if it exists and returns NULL
// type ==> one of: CFILE_NORMAL
// CFILE_MEMORY_MAPPED
// dir_type => override extension check, value is one of CF_TYPE* #defines
@@ -782,7 +782,7 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
//
// parameters: *filepath ==> name of file to open (may be path+name)
// *mode ==> specifies how file should be opened (eg "rb" for read binary)
// passing NULL to mode triggers an assert and returns NULL
// passing NULL to mode deletes the file if it exists and returns NULL
// dir_type => override extension check, value is one of CF_TYPE* #defines
//
+4 -16
View File
@@ -1551,7 +1551,7 @@ int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* fil
}
bool skip_packfiles = false;
if ( (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
skip_packfiles = true;
} else if (Get_file_list_child != NULL) {
skip_packfiles = true;
@@ -1708,7 +1708,7 @@ int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int
}
bool skip_packfiles = false;
if ((pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS)) {
if ((pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS)) {
skip_packfiles = true;
}
else if (Get_file_list_child != NULL) {
@@ -1887,7 +1887,7 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
}
bool skip_packfiles = false;
if ((pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS)) {
if ((pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS)) {
skip_packfiles = true;
}
else if (Get_file_list_child != NULL) {
@@ -1981,10 +1981,8 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
// Output: path - Fully qualified pathname.
//Returns 0 if the result would be too long (invalid result)
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename, bool localize,
uint32_t _location_flags)
uint32_t location_flags)
{
uint32_t location_flags = _location_flags;
if ( filename && strchr(filename, DIR_SEPARATOR_CHAR) ) {
// Already has full path
strncpy( path, filename, path_max );
@@ -1992,16 +1990,6 @@ int cf_create_default_path_string(char* path, uint path_max, int pathtype, const
} else {
cf_root* root = nullptr;
// override location flags for path types which should always come from the root (NOT mod directories)
// NOTE: cache directories should NOT be added here to avoid possible mod breakage
switch(pathtype) {
case CF_TYPE_PLAYERS:
case CF_TYPE_MULTI_PLAYERS:
case CF_TYPE_SINGLE_PLAYERS:
location_flags = CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
break;
}
for (auto i = 0; i < Num_roots; ++i) {
auto current_root = cf_get_root(i);
+116 -66
View File
@@ -19,7 +19,6 @@
#include "hud/hudconfig.h"
#include "io/joy.h"
#include "network/multi.h"
#include "network/multi_log.h"
#include "options/OptionsManager.h"
#include "osapi/osapi.h"
#include "parse/sexp.h"
@@ -43,7 +42,6 @@
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <sstream>
#include <jansson.h>
@@ -197,7 +195,6 @@ Flag exe_params[] =
{ "-no_enhanced_sound", "Disable enhanced sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_enhanced_sound", },
{ "-portable_mode", "Store config in portable location", false, 0, EASY_DEFAULT, "Launcher", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-portable_mode", },
{ "-joy_info", "Outputs SDL joystick info", true, 0, EASY_DEFAULT, "Launcher", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-joy_info",},
{ "-standalone", "Run as standalone server", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-standalone", },
{ "-startgame", "Skip mainhall and start hosting", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-startgame", },
@@ -225,7 +222,6 @@ Flag exe_params[] =
{ "-noshadercache", "Disables the shader cache", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noshadercache", },
{ "-prefer_ipv4", "Prefer IPv4 DNS lookups", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-prefer_ipv4", },
{ "-prefer_ipv6", "Prefer IPv6 DNS lookups", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-prefer_ipv6", },
{ "-log_multi_packet", "Log multi packet types ", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-log_multi_packet",},
#ifdef WIN32
{ "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fix_registry", },
#endif
@@ -246,7 +242,6 @@ Flag exe_params[] =
{ "-output_sexps", "Output SEXPs to sexps.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_sexps", },
{ "-output_scripting", "Output scripting to scripting.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_scripting", },
{ "-output_script_json", "Output scripting doc to scripting.json", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_script_json", },
{ "-controlconfig_tbl", "Save control presets to table", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-controlconfig_tbl", },
{ "-save_render_target", "Save render targets to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-save_render_target", },
{ "-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", },
@@ -315,7 +310,6 @@ int Cmdline_use_last_pilot = 0;
// Graphics related
cmdline_parm fov_arg("-fov", "Vertical field-of-view factor", AT_FLOAT); // Cmdline_fov -- comand line FOV -Bobboau
cmdline_parm fov_cockpit_arg("-fov_cockpit", "Vertical field-of-view factor for Cockpits", AT_FLOAT);
cmdline_parm clip_dist_arg("-clipdist", "Changes the distance from the viewpoint for the near-clipping plane", AT_FLOAT); // Cmdline_clip_dist
cmdline_parm spec_static_arg("-spec_static", "Adjusts suns contribution to specular highlights", AT_FLOAT);
cmdline_parm spec_point_arg("-spec_point", "Adjusts laser weapons contribution to specular highlights", AT_FLOAT);
@@ -429,7 +423,6 @@ char *Cmdline_gateway_ip = nullptr;
// Launcher related options
cmdline_parm portable_mode("-portable_mode", NULL, AT_NONE);
cmdline_parm joy_info("-joy_info", "Outputs SDL joystick info", AT_NONE);
bool Cmdline_portable_mode = false;
@@ -451,7 +444,6 @@ cmdline_parm nograb_arg("-nograb", NULL, AT_NONE);
cmdline_parm noshadercache_arg("-noshadercache", NULL, AT_NONE);
cmdline_parm prefer_ipv4_arg("-prefer_ipv4", nullptr, AT_NONE);
cmdline_parm prefer_ipv6_arg("-prefer_ipv6", nullptr, AT_NONE);
cmdline_parm log_multi_packet_arg("-log_multi_packet", nullptr, AT_NONE);
#ifdef WIN32
cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
#endif
@@ -472,7 +464,6 @@ bool Cmdline_nograb = false;
bool Cmdline_noshadercache = false;
bool Cmdline_prefer_ipv4 = false;
bool Cmdline_prefer_ipv6 = false;
bool Cmdline_dump_packet_type = false;
#ifdef WIN32
bool Cmdline_alternate_registry_path = false;
#endif
@@ -546,7 +537,6 @@ cmdline_parm get_flags_arg(GET_FLAGS_STRING, "Output the launcher flags file", A
cmdline_parm output_sexp_arg("-output_sexps", NULL, AT_NONE); //WMC - outputs all SEXPs to sexps.html
cmdline_parm output_scripting_arg("-output_scripting", NULL, AT_NONE); //WMC
cmdline_parm output_script_json_arg("-output_script_json", nullptr, AT_NONE); // m!m
cmdline_parm generate_controlconfig_arg("-controlconfig_tbl", nullptr, AT_NONE);
// Deprecated flags - CommanderDJ
cmdline_parm deprecated_spec_arg("-spec", "Deprecated", AT_NONE);
@@ -563,6 +553,18 @@ cmdline_parm deprecated_cache_bitmaps_arg("-cache_bitmaps", "Deprecated", AT_NON
cmdline_parm deprecated_no_emissive_arg("-no_emissive_light", "Deprecated", AT_NONE);
cmdline_parm deprecated_postprocess_arg("-post_process", "Deprecated", AT_NONE);
int Cmdline_deprecated_spec = 0;
int Cmdline_deprecated_glow = 0;
int Cmdline_deprecated_normal = 0;
int Cmdline_deprecated_env = 0;
int Cmdline_deprecated_tbp = 0;
int Cmdline_deprecated_jpgtga = 0;
int Cmdline_deprecated_nohtl = 0;
bool Cmdline_deprecated_brief_lighting = 0;
bool Cmdline_deprecated_missile_lighting = false;
bool Cmdline_deprecated_cache_bitmaps = false;
bool Cmdline_deprecated_postprocess = false;
#ifndef NDEBUG
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
void cmdline_debug_print_cmdline()
@@ -588,41 +590,61 @@ void cmdline_debug_print_cmdline()
mprintf(("\n"));
//Print log messages about any deprecated flags we found - CommanderDJ
//Do it programmatically, rather than enumerating them by hand - MageKing17
for (parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (parmp->name_found && !stricmp("deprecated", parmp->help)) {
mprintf(("Deprecated flag '%s' found. Please remove from your cmdline.\n", parmp->name));
}
if(Cmdline_deprecated_spec == 1)
{
mprintf(("Deprecated flag '-spec' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_glow == 1)
{
mprintf(("Deprecated flag '-glow' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_normal == 1)
{
mprintf(("Deprecated flag '-normal' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_env == 1)
{
mprintf(("Deprecated flag '-env' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_tbp == 1)
{
mprintf(("Deprecated flag '-tbp' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_jpgtga == 1)
{
mprintf(("Deprecated flag '-jpgtga' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_nohtl == 1)
{
mprintf(("Deprecated flag '-nohtl' found. Please remove from your cmdline.\n"));
}
if(Cmdline_deprecated_brief_lighting == 1)
{
mprintf(("Deprecated flag '-brief_lighting' found. Please remove from your cmdline.\n"));
}
if (Cmdline_deprecated_missile_lighting)
{
mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
}
if (Cmdline_deprecated_cache_bitmaps) {
mprintf(("Deprecated flag '-cache_bitmaps' found. Please remove from your cmdline.\n"));
}
if (Cmdline_deprecated_postprocess) {
mprintf(("Deprecated flag '-post_process' found. Please remove from your cmdline.\n"));
}
}
#endif
// prints simple cmdline to multi.log
void cmdline_print_cmdline_multi()
{
cmdline_parm *parmp;
int found = 0;
std::ostringstream cmdline;
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
if ( parmp->name_found ) {
cmdline << " " << parmp->name;
if (parmp->args) {
cmdline << " " << parmp->args;
}
found++;
}
}
if ( !found ) {
cmdline << " <none>";
}
ml_printf("Command line:%s", cmdline.str().c_str());
}
// Return true if this character is an extra char (white space and quotes)
int is_extra_space(char ch)
{
@@ -1504,11 +1526,6 @@ bool SetCmdlineParams()
return false;
}
if (joy_info.found()) {
io::joystick::printJoyJSON();
return false;
}
if (no_fpscap.found())
{
Cmdline_NoFPSCap = 1;
@@ -1540,9 +1557,6 @@ bool SetCmdlineParams()
// is this a standalone server??
if (standalone_arg.found()) {
Is_standalone = 1;
// also enable non-interactive by default here
Cmdline_noninteractive = true;
}
}
@@ -1799,16 +1813,6 @@ bool SetCmdlineParams()
}
}
if ( fov_cockpit_arg.found() ) {
auto val = fov_cockpit_arg.get_float();
if (val > 0.1) {
COCKPIT_ZOOM_DEFAULT = val;
}
else {
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
}
}
if( clip_dist_arg.found() ) {
Min_draw_distance = Cmdline_clip_dist = clip_dist_arg.get_float();
}
@@ -1937,9 +1941,6 @@ bool SetCmdlineParams()
Cmdline_output_sexp_info = true;
}
if (generate_controlconfig_arg.found())
Generate_controlconfig_table = true;
if ( no_pbo_arg.found() )
{
Cmdline_no_pbo = 1;
@@ -2167,10 +2168,63 @@ bool SetCmdlineParams()
}
//Deprecated flags - CommanderDJ
if( deprecated_spec_arg.found() )
{
Cmdline_deprecated_spec = 1;
}
if( deprecated_glow_arg.found() )
{
Cmdline_deprecated_glow = 1;
}
if( deprecated_normal_arg.found() )
{
Cmdline_deprecated_normal = 1;
}
if( deprecated_env_arg.found() )
{
Cmdline_deprecated_env = 1;
}
if( deprecated_tbp_arg.found() )
{
Cmdline_deprecated_tbp = 1;
}
if( deprecated_jpgtga_arg.found() )
{
Cmdline_deprecated_jpgtga = 1;
}
if ( deprecated_htl_arg.found() )
{
Cmdline_deprecated_nohtl = 1;
}
if ( deprecated_brieflighting_arg.found() )
{
Cmdline_deprecated_brief_lighting = 1;
}
if (deprecated_missile_lighting_arg.found())
{
Cmdline_deprecated_missile_lighting = true;
}
if (deprecated_cache_bitmaps_arg.found()) {
Cmdline_deprecated_cache_bitmaps = true;
}
if (deprecated_no_emissive_arg.found()) {
Cmdline_emissive = 0;
}
if (deprecated_postprocess_arg.found()) {
Cmdline_deprecated_postprocess = true;
}
if (deprecated_fxaa_arg.found() ) {
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
@@ -2226,10 +2280,6 @@ bool SetCmdlineParams()
}
}
if (log_multi_packet_arg.found()) {
Cmdline_dump_packet_type = true;
}
return true;
}
-1
View File
@@ -125,7 +125,6 @@ extern bool Cmdline_nograb;
extern bool Cmdline_noshadercache;
extern bool Cmdline_prefer_ipv4;
extern bool Cmdline_prefer_ipv6;
extern bool Cmdline_dump_packet_type;
#ifdef WIN32
extern bool Cmdline_alternate_registry_path;
#endif
+20 -63
View File
@@ -190,8 +190,8 @@ static unsigned int Defaults_cycle_pos = 0; // the controls preset that was last
int Control_config_overlay_id;
struct conflict {
int first = -1; // index of other control in conflict with this one
int second = -1; // index of other control in conflict with this one
int first = -1; // index of other control in conflict with this one
int second = -1; // index of other control in conflict with this one
};
SCP_vector<conflict> Conflicts;
@@ -1137,7 +1137,8 @@ void control_config_toggle_invert()
item.second.invert_toggle();
break;
default:
UNREACHABLE("Unhandled selItem in control_config_toggle_invert(): %i\n", static_cast<int>(Selected_item));
// unhandled
mprintf(("Unhandled selItem in control_config_toggle_invert(): %i", static_cast<int>(Selected_item)));
}
}
@@ -1286,15 +1287,6 @@ int control_config_accept()
}
SCP_string str = cstr;
// Check if a hardcoded preset with name already exists. If so, complain to user and force retry
auto it = std::find_if(Control_config_presets.begin(), Control_config_presets.end(),
[str](CC_preset& p) { return (p.name == str) && ((p.type == Preset_t::tbl) || (p.type == Preset_t::hardcode)); });
if (it != Control_config_presets.end()) {
popup(flags, 1, POPUP_OK, "You may not overwrite a default preset. Please choose another name.");
goto retry;
}
// Check if a preset file with name already exists. If so, prompt the user
CFILE* fp = cfopen((str + ".json").c_str(), "r", CFILE_NORMAL, CF_TYPE_PLAYER_BINDS, false,
@@ -1665,7 +1657,8 @@ void control_config_draw_selected_preset() {
auto preset_it = control_config_get_current_preset();
if (preset_it != Control_config_presets.end()) {
sprintf(preset_str, XSTR("Preset: %s", 1659), preset_it->name.c_str());
sprintf(preset_str, XSTR("Preset: %s", 1659), preset_it->name.c_str());
} else {
sprintf(preset_str, XSTR("Preset: custom", 1660), "");
}
@@ -2539,7 +2532,7 @@ int check_control_used(int id, int key)
return 0;
}
if (item.disabled || item.locked)
if (item.disabled)
return 0;
short z = item.get_btn(CID_KEYBOARD); // Get the key that's bound to this control
@@ -2608,43 +2601,30 @@ int check_control_used(int id, int key)
int check_control(int id, int key)
{
const bool is_control_used = check_control_used(id, key) != 0;
const bool is_ignored = Ignored_keys[id] != 0;
//Decrement Ignored_keys if key was pressed and is ignored
if (is_control_used && Ignored_keys[id] > 0) {
Ignored_keys[id]--;
if (check_control_used(id, key)) {
if (Ignored_keys[id]) {
if (Ignored_keys[id] > 0) {
Ignored_keys[id]--;
}
return 0;
}
return 1;
}
int control_triggered = 0; // boolean as int (0 = false, 1 = true); Weirdness for compatibility with control_run_lua();
if (is_control_used && !is_ignored) {
control_triggered = 1;
}
if (Control_config[id].type == CC_TYPE_CONTINUOUS) {
// Only call lua in here when it's a continuous button
if (control_run_lua(static_cast<IoActionId>(id), control_triggered)) {
// lua has taken care of the control already. Mark as not triggered to prevent hardcode from executing.
control_triggered = 0;
} // Else, let hardcode process the control
}
if (!is_control_used && Control_config[id].continuous_ongoing) {
if (Control_config[id].continuous_ongoing) {
// If we reach this point, then it means this is a continuous control
// which has just been released
if (Script_system.IsActiveAction(CHA_ONACTIONSTOPPED)) {
Script_system.SetHookVar("Action", 's', Control_config[id].text);
Script_system.RunCondition(CHA_ONACTIONSTOPPED, nullptr, nullptr, id);
Script_system.RunCondition(CHA_ONACTIONSTOPPED, nullptr, id);
Script_system.RemHookVar("Action");
}
Control_config[id].continuous_ongoing = false;
}
return control_triggered;
return 0;
}
/**
@@ -2773,8 +2753,7 @@ void control_get_axes_readings(int *axis_v, float frame_time)
mouse_get_delta(&axe[MOUSE_ID][MOUSE_X_AXIS], &axe[MOUSE_ID][MOUSE_Y_AXIS], &axe[MOUSE_ID][MOUSE_Z_AXIS]);
for (int action = 0; action < Action::NUM_VALUES; ++action) {
const auto action_id = static_cast<IoActionId>(action + JOY_AXIS_BEGIN);
CCI & item = Control_config[action_id];
CCI & item = Control_config[action + JOY_AXIS_BEGIN];
// Assume actions are all axis actions, no need to check
// Assumes all axes are uniquely bound to an action
@@ -2787,28 +2766,6 @@ void control_get_axes_readings(int *axis_v, float frame_time)
if (!item.second.empty()) {
scale_invert(item.second, action, item.type, frame_time, axe, axis_v);
}
//Call Lua hooks
if (control_run_lua(action_id, axis_v[action])) {
Assert(item.type == CC_TYPE_AXIS_ABS || item.type == CC_TYPE_AXIS_REL);
switch (item.type) {
case CC_TYPE_AXIS_ABS:
axis_v[action] = item.used;
break;
case CC_TYPE_AXIS_REL:
axis_v[action] = 0;
break;
case CC_TYPE_AXIS_BTN_NEG:
case CC_TYPE_AXIS_BTN_POS:
default:
//This should never happen, especially with the above Assertion. This is required as incomplete switches on an enum generate warnings
break;
}
}
//Store values for possible lua override
item.used = axis_v[action];
}
}
@@ -2824,7 +2781,7 @@ void control_used(int id)
if (Control_config[id].used < Last_frame_timestamp) {
if (!Control_config[id].continuous_ongoing) {
Script_system.SetHookVar("Action", 's', Control_config[id].text);
Script_system.RunCondition(CHA_ONACTION, nullptr, nullptr, id);
Script_system.RunCondition(CHA_ONACTION, nullptr, id);
Script_system.RemHookVar("Action");
if (Control_config[id].type == CC_TYPE_CONTINUOUS)
+35 -136
View File
@@ -12,7 +12,6 @@
#define CONTROLS_CONFIG_H
#include "globalincs/pstypes.h"
#include "scripting/scripting.h"
#define CONTROL_CONFIG_XSTR 507
@@ -22,7 +21,6 @@
#define CCF_AXIS 0x08 //!< btn is an axis
#define CCF_HAT 0x04 //!< btn is a hat
#define CCF_BALL 0x02 //!< btn is a ball
#define CCF_BUTTON 0x01 //!< btn is actually a button
/*!
* These are used to index a corresponding axis value from an array.
@@ -322,15 +320,6 @@ enum {
};
}
/*!
* Where the preset is located in memory
*/
enum class Preset_t {
hardcode, // Preset is defined hardcode
tbl, // Preset is defined in controlconfigdefaults.tbl
pst // Preset is defined in a .json
};
class CCB;
/*!
@@ -372,16 +361,6 @@ public:
*/
bool empty() const;
/**
* Takes the given binding.
*/
void take(CID _cid, short _btn, char _flags = 0);
/**
* Validates the binding, clearing it if necassary
*/
void validate();
/*!
* Returns a copy of ::btn
*/
@@ -397,6 +376,16 @@ public:
*/
char get_flags() const;
/**
* Takes the given binding.
*/
void take(CID _cid, short _btn, char _flags = 0);
/**
* Validates the binding, clearing it if necassary
*/
void validate();
/*!
* Returns a human-readable string of this binding
*/
@@ -479,12 +468,12 @@ public:
/*!
* Checks if the given CCB is exactly equal to this
*/
bool operator==(const CCB&) const;
bool operator==(const CCB&);
/*!
* Checks if the given CCB differs from this
*/
bool operator!=(const CCB&) const;
bool operator!=(const CCB&);
/*!
* Returns True if this CCB's first isn't empty and the given CCB has a binding that can conflict with it
@@ -510,21 +499,6 @@ public:
* Returns a pointer to first, or second, whichever has *all* flags in the given mask
*/
CC_bind* find_flags(const char);
/*!
* Sets the inversion state of both bindings
*/
void invert(bool);
/*!
* Toggles the inversion state of Primary and copies it to Secondary
*/
void invert_toggle();
/*!
* Is true if both bindings are inverted, false otherwise
*/
bool is_inverted() const;
};
/*!
@@ -534,13 +508,8 @@ class CC_preset {
public:
SCP_vector<CCB> bindings;
SCP_string name;
Preset_t type;
public:
CC_preset() = default;
CC_preset(const CC_preset& A) = default;
CC_preset& operator=(const CC_preset&);
/*!
* Checks if the given preset is a duplicate of this one
*/
@@ -565,10 +534,8 @@ public:
CC_type type; //!< manner control should be checked in
// Items used during gameplay
int used; //!< has control been used yet in mission? If so, this is the timestamp. For axes, this denotes the last frame's value
int used; //!< has control been used yet in mission? If so, this is the timestamp
bool disabled = true; //!< whether this action should be available at all
bool locked = false; //!< whether this action will be triggered by the respectively bound key
bool scriptEnabledByDefault = false; //!< whether this binding will execute it's registered hooks if triggered. Resets each mission
bool continuous_ongoing; //!< whether this action is a continuous one and is currently ongoing
public:
@@ -646,10 +613,9 @@ extern int Control_config_overlay_id;
extern SCP_vector<CCI> Control_config; //!< Stores the keyboard configuration
extern SCP_vector<CC_preset> Control_config_presets; // tabled control presets; pointers to config_item arrays
extern const char **Scan_code_text;
extern const char **Joy_button_text; // String table of button labels. XSTR'd on init.
extern bool Generate_controlconfig_table;
// string table constants for labels and stuff.
#define NUM_AXIS_TEXT JOY_NUM_AXES
#define NUM_MOUSE_TEXT MOUSE_NUM_BUTTONS
@@ -724,10 +690,7 @@ bool control_config_use_preset_by_name(const SCP_string &name);
*
* @returns an iterator to the current preset, or
* @returns ::iterator Control_config_presets.end() if current bindings are not in a preset
*
* @note Similar to preset_find_duplicate, this function has additional logic in its search to ignore disabled controls
*/
SCP_vector<CC_preset>::iterator control_config_get_current_preset(bool invert_agnostic = false);
/*!
@@ -763,9 +726,10 @@ int translate_key_to_index(const char *key, bool find_override=true);
const char *translate_key(char *key);
/**
* @brief Converts the specified key code to a human readable string, according to the selected locale and keyboard layout
* @brief Converts the specified key code to a human readable string, according to the selected locale
*
* @param[in] code The key scancode to convert
* @param[in] code The key code to convert
* @param[in] use_default_locale If true, return the default locale (English) translation of the key
*
* @return The text representation of the code.
*
@@ -773,18 +737,7 @@ const char *translate_key(char *key);
*
* @note The return value is translated according to localization settings
*/
const char *textify_scancode(int code);
/**
* @brief Converts the specified key code to a human readable string. Uses the English locale and QWERTY layout.
*
* @param[in] code The key scancode to convert
*
* @return The text representation of the code
*
* @note Not thread safe. Has an internal buffer for the return value which is overwritten on each call.
*/
const char *textify_scancode_universal(int code);
const char *textify_scancode(int code, bool use_default_locale = false);
/*!
* @brief Checks how long a control has been active
@@ -831,35 +784,6 @@ void control_get_axes_readings(int *axis_v, float frame_time);
*/
void control_used(int id);
/**
* @brief Runs a given controlbindings lua hook added in ccd.tbl
*
* @return Whether the control should be overridden
*/
bool control_run_lua(IoActionId id, int value);
/**
* @brief Resets the cache for script evaluations for continuous buttons. Should be called once per frame.
*
*/
void control_reset_lua_cache();
/**
* @brief Registers a new hook for the keybinding action system.
* Parameters set if it is a normal or an override function, as well as if it is enabled by default or needs to be enabled manually each mission
*/
void control_register_hook(IoActionId id, const luacpp::LuaFunction& hook, bool is_override, bool enabledByDefault);
/**
* @brief Enables or disables the respective Lua hook
*/
void control_enable_hook(IoActionId id, bool enable);
/**
* @brief Resets every hooks enable state to the tabled value. Call on Mission start
*/
void control_reset_hook();
/**
* @brief Clears the bindings of all controls
*/
@@ -912,17 +836,18 @@ CID CIDToVal(const char * str);
/**
* Reverse lookups the CID to get its stringified name
* @return The stringified name of the CID, or
* @return "NONE" if not found
* @return Pointer to the stringified name of the CID, or
* @return nullptr if not found
*/
SCP_string ValToCID(CID id);
const char * ValToCID(CID id);
/**
* Reverse lookups the CID to get its stringified name
* @return The stringified name of the CID, or
* @return "NONE" if not found, or invalid id
* @return Pointer to the stringified name of the CID, or
* @return nullptr if not found, or invalid id
*/
SCP_string ValToCID(int id);
const char * ValToCID(int id);
/**
* Lookups the given stringified enum to find its value
*/
@@ -930,8 +855,8 @@ char CCFToVal(const char * str);
/**
* Constructs a enum string from the CCF_FLAGS
* @return The stringified name of the CCF, or
* @return "NONE" if not found, or invalid id
* @return Pointer to the stringified name of the CCF, or
* @return nullptr if not found, or invalid id
*/
SCP_string ValToCCF(char id);
@@ -943,8 +868,8 @@ short InputToVal(CID cid, const char * str);
/**
* Constructs a enumstring from the input binding, depending on the CID
*
* @return The stringified name of the input, or
* @return "NONE" if not found, or invalid CC_bind
* @return Pointer to the stringified name of the input, or
* @return nullptr if not found, or invalid CC_bind
*
* @note This requires a CCB due to the way things are encoded
*/
@@ -958,8 +883,8 @@ short MouseToVal(const char * str);
/**
* Constructs a enum string from the mouse input
*
* @return The stringified name of the input, or
* @return "NONE" if not found, or invalid CC_bind
* @return Pointer to the stringified name of the input, or
* @return nullptr if not found, or invalid CC_bind
* TODO XSTR
*
* @note This requires a CCB due to the way things are encoded
@@ -974,8 +899,8 @@ short KeyboardToVal(const char * str);
/**
* Constructs an enum string from the key binding
*
* @return The stringified name of the input, or
* @return "NONE" f not found, or invalid CC_bind
* @return Pointer to the stringified name of the input, or
* @return nullptr if not found, or invalid CC_bind
*
* @note This requires a CCB due to the way things are encoded
* TODO XSTR
@@ -990,37 +915,11 @@ short JoyToVal(const char * str);
/**
* Constructs a enum string from the Joystick input
*
* @return The stringified name of the input, or
* @return "NONE" if not found, or invalid CC_bind
* @return Pointer to the stringified name of the input, or
* @return nullptr if not found, or invalid CC_bind
*
* @note This requires a CCB due to the way things are encoded
* TODO XSTR
*/
SCP_string ValToJoy(const CC_bind &bind);
/**
* Lookups the given string to find its tab value
*/
char CCTabToVal(const char *str);
/**
* Reverse lookups the given tab in mCCTabToVal to retrieve the string name
*
* @return The stringified name of the input, or
* @return nullptr if not found, or invalid tab
*
*/
SCP_string ValToCCTab(char tab);
/**
* Lookups the given string to find its CC_type value. =
*/
CC_type CCTypeToVal(const char *str);
/**
* Reverse lookups the given CC_type to retrieve the string name
*/
SCP_string ValToCCType(CC_type type);
#endif
File diff suppressed because it is too large. Load diff
+14 -32
View File
@@ -47,7 +47,7 @@ void load_preset_files() {
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!fp) {
mprintf(("PST => Unable to open '%s' for loading!\n", file.c_str()));
mprintf(("PLR => Unable to open '%s' for loading!\n", file.c_str()));
// try next
continue;
}
@@ -55,7 +55,7 @@ void load_preset_files() {
try {
handler.reset(new PresetFileHandler(fp, true));
} catch (const std::exception& e) {
mprintf(("PST => Failed to open JSON: `%s`\n", e.what()));
mprintf(("PLR => Failed to open JSON: `%s`\n", e.what()));
continue;
}
@@ -74,7 +74,6 @@ void load_preset_files() {
// Start reading in data
CC_preset preset;
preset.name = file;
preset.type = Preset_t::pst;
preset.bindings.resize(Control_config.size());
size_t size;
@@ -105,7 +104,6 @@ void load_preset_files() {
str = handler->readString("input");
auto btn = InputToVal(cid, str.c_str());
item.first.take(cid, btn, flags);
handler->endSectionRead(); // Primary
@@ -126,16 +124,21 @@ void load_preset_files() {
handler->endArrayRead(); // Actions
// Done with the file
auto it = preset_find_duplicate(preset);
bool unique = true;
auto it = Control_config_presets.begin();
for (; it != Control_config_presets.end(); ++it) {
if (preset.is_duplicate_of(*it)) {
unique = false;
break;
}
}
if (it == Control_config_presets.end()) {
if (unique) {
Control_config_presets.push_back(preset);
} else if ((it->name != preset.name) || (it->type != Preset_t::pst)) {
// Complain and ignore if the preset names or the type differs
Warning(LOCATION, "PST => Preset '%s' is a duplicate of an existing preset, ignoring", preset.name.c_str());
} else {
Warning(LOCATION, "Preset '%s' is a duplicate of '%s', ignoring", preset.name.c_str(), it->name.c_str());
}
} // else, silent ignore
}
}
@@ -217,27 +220,6 @@ bool save_preset_file(CC_preset preset, bool overwrite) {
return true;
}
SCP_vector<CC_preset>::iterator preset_find_duplicate(const CC_preset& new_preset) {
SCP_vector<CC_preset>::iterator it = Control_config_presets.begin(); // NOLINT(modernize-use-auto)
for (; it != Control_config_presets.end(); ++it) {
size_t i;
for (i = 0; i < it->bindings.size(); ++i) {
if (new_preset.bindings[i] != it->bindings[i]) {
// These two differ, check the next in the vector
break;
}
}
if (i == it->bindings.size()) {
// These two are equal
break;
}
}
return it;
}
PresetFileHandler::PresetFileHandler(CFILE* cfp, bool reading) : _cfp(cfp) {
Assertion(cfp != nullptr, "File pointer must be valid!");
-8
View File
@@ -216,14 +216,6 @@ bool save_preset_file(CC_preset preset, bool overwrite);
*/
void load_preset_files();
/**
* @brief Checks if the given preset is a duplicate within Control_config_presets vector
* @returns iterator to the duplicate if found, or
* @returns iterator to Control_config_presets.end() otherwise
*/
SCP_vector<CC_preset>::iterator preset_find_duplicate(const CC_preset& new_preset);
/**
* @brief Returns true if a preset file with the given name exists.
*/
-1
View File
@@ -51,7 +51,6 @@ void processEvents()
{
io::mouse::CursorManager::get()->showCursor(false);
os_remove_deferred_cutscene_key_events();
os_poll();
}
+3 -5
View File
@@ -668,11 +668,9 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
// ensure vel is valid
Assert( !vm_is_vec_nan(&obj->phys_info.vel) );
if (OnDebrisCreatedHook->isActive()) {
OnDebrisCreatedHook->run(scripting::hook_param_list(
scripting::hook_param("Debris", 'o', obj),
scripting::hook_param("Source", 'o', source_obj)));
}
OnDebrisCreatedHook->run(scripting::hook_param_list(
scripting::hook_param("Debris", 'o', obj),
scripting::hook_param("Source", 'o', source_obj)));
if (db->is_hull) {
MONITOR_INC(NumHullDebris,1);
+5 -24
View File
@@ -488,21 +488,6 @@ void dc_putc(char c)
line_str->push_back(c);
}
bool handle_textInputEvent(const SDL_Event& event) {
if (event.text.text[0] != '\0' && event.text.text[0] != '\1') {
for (char c : event.text.text) {
if (c < 32)
break;
if (dc_command_buf.size() < MAX_CLI_LEN) {
dc_command_buf.push_back(c);
}
}
}
return true;
}
void debug_console(void (*_func)(void))
{
int done = 0;
@@ -515,9 +500,6 @@ void debug_console(void (*_func)(void))
dc_init();
}
auto textListener = os::events::addEventListener(SDL_TEXTINPUT, 10000, &handle_textInputEvent);
SDL_StartTextInput();
dc_draw(TRUE);
while (!done) {
@@ -604,9 +586,11 @@ void debug_console(void (*_func)(void))
break;
default:
// Leave handling of key input to SDL
break;
// Not any of the control key codes, so it's probably a letter or number.
ubyte c = (ubyte)key_to_ascii(k);
if ((c != 255) && (dc_command_buf.size() < MAX_CLI_LEN)) {
dc_command_buf.push_back(c);
}
}
// Do the passed function
@@ -618,9 +602,6 @@ void debug_console(void (*_func)(void))
dc_draw(TRUE);
}
SDL_StopTextInput();
os::events::removeEventListener(textListener);
while( key_inkey() ) {
os_poll();
}
+211 -181
View File
@@ -9,158 +9,179 @@
#include "tracing/tracing.h"
#include "ship/ship.h"
namespace decals {
namespace {
DecalDefinition::DecalDefinition(SCP_string name) : _name(std::move(name)) {
}
class DecalDefinition {
SCP_string _name;
DecalDefinition::~DecalDefinition() {
if (_diffuseBitmap >= 0) {
bm_release(_diffuseBitmap);
SCP_string _diffuseFilename;
bool _loopDiffuse = true;
SCP_string _glowFilename;
bool _loopGlow = true;
SCP_string _normalMapFilename;
bool _loopNormal = true;
int _diffuseBitmap = -1;
int _glowBitmap = -1;
int _normalBitmap = -1;
public:
explicit DecalDefinition(SCP_string name) : _name(std::move(name)) {
}
if (_glowBitmap >= 0) {
bm_release(_glowBitmap);
}
if (_normalBitmap >= 0) {
bm_release(_normalBitmap);
}
}
DecalDefinition::DecalDefinition(DecalDefinition&& other) noexcept {
*this = std::move(other); // Use operator implementation
}
DecalDefinition& DecalDefinition::operator=(DecalDefinition&& other) noexcept {
std::swap(_name, other._name);
std::swap(_diffuseFilename, other._diffuseFilename);
std::swap(_glowFilename, other._glowFilename);
std::swap(_normalMapFilename, other._normalMapFilename);
std::swap(_diffuseBitmap, other._diffuseBitmap);
std::swap(_glowBitmap, other._glowBitmap);
std::swap(_normalBitmap, other._normalBitmap);
std::swap(_loopDiffuse, other._loopDiffuse);
std::swap(_loopGlow, other._loopGlow);
std::swap(_loopNormal, other._loopNormal);
return *this;
}
void DecalDefinition::parse() {
if (optional_string("+Diffuse:")) {
stuff_string(_diffuseFilename, F_FILESPEC);
if (!bm_validate_filename(_diffuseFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _diffuseFilename.c_str());
_diffuseFilename = "";
~DecalDefinition() {
if (_diffuseBitmap >= 0) {
bm_release(_diffuseBitmap);
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopDiffuse);
if (_glowBitmap >= 0) {
bm_release(_glowBitmap);
}
if (_normalBitmap >= 0) {
bm_release(_normalBitmap);
}
}
if (optional_string("+Glow:")) {
stuff_string(_glowFilename, F_FILESPEC);
if (!bm_validate_filename(_glowFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _glowFilename.c_str());
_glowFilename = "";
// Disallow copying
DecalDefinition(const DecalDefinition&) = delete;
DecalDefinition& operator=(const DecalDefinition&) = delete;
// Move constructor and operator
DecalDefinition(DecalDefinition&& other) noexcept {
*this = std::move(other); // Use operator implementation
}
DecalDefinition& operator=(DecalDefinition&& other) noexcept {
std::swap(_name, other._name);
std::swap(_diffuseFilename, other._diffuseFilename);
std::swap(_glowFilename, other._glowFilename);
std::swap(_normalMapFilename, other._normalMapFilename);
std::swap(_diffuseBitmap, other._diffuseBitmap);
std::swap(_glowBitmap, other._glowBitmap);
std::swap(_normalBitmap, other._normalBitmap);
std::swap(_loopDiffuse, other._loopDiffuse);
std::swap(_loopGlow, other._loopGlow);
std::swap(_loopNormal, other._loopNormal);
return *this;
}
void parse() {
if (optional_string("+Diffuse:")) {
stuff_string(_diffuseFilename, F_FILESPEC);
if (!bm_validate_filename(_diffuseFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _diffuseFilename.c_str());
_diffuseFilename = "";
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopDiffuse);
}
}
if (optional_string("+Glow:")) {
stuff_string(_glowFilename, F_FILESPEC);
if (optional_string("+Loop:")) {
stuff_boolean(&_loopGlow);
if (!bm_validate_filename(_glowFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _glowFilename.c_str());
_glowFilename = "";
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopGlow);
}
}
if (optional_string("+Normal:")) {
stuff_string(_normalMapFilename, F_FILESPEC);
if (!bm_validate_filename(_normalMapFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _normalMapFilename.c_str());
_normalMapFilename = "";
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopNormal);
}
}
}
if (optional_string("+Normal:")) {
stuff_string(_normalMapFilename, F_FILESPEC);
if (!bm_validate_filename(_normalMapFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _normalMapFilename.c_str());
_normalMapFilename = "";
void loadBitmaps() {
if (_diffuseBitmap == -1 && VALID_FNAME(_diffuseFilename)) {
_diffuseBitmap = bm_load_either(_diffuseFilename.c_str());
if (_diffuseBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_diffuseFilename.c_str(),
_name.c_str());
}
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopNormal);
if (_glowBitmap == -1 && VALID_FNAME(_glowFilename)) {
_glowBitmap = bm_load_either(_glowFilename.c_str());
if (_glowBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_glowFilename.c_str(),
_name.c_str());
}
}
if (_normalBitmap == -1 && VALID_FNAME(_normalMapFilename)) {
_normalBitmap = bm_load_either(_normalMapFilename.c_str());
if (_normalBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_normalMapFilename.c_str(),
_name.c_str());
}
}
}
}
void DecalDefinition::loadBitmaps() {
if (_diffuseBitmap == -1 && VALID_FNAME(_diffuseFilename)) {
_diffuseBitmap = bm_load_either(_diffuseFilename.c_str());
if (_diffuseBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_diffuseFilename.c_str(),
_name.c_str());
void pageIn() {
if (_diffuseBitmap >= 0) {
bm_page_in_texture(_diffuseBitmap);
}
if (_glowBitmap >= 0) {
bm_page_in_texture(_glowBitmap);
}
if (_normalBitmap >= 0) {
bm_page_in_texture(_normalBitmap);
}
}
if (_glowBitmap == -1 && VALID_FNAME(_glowFilename)) {
_glowBitmap = bm_load_either(_glowFilename.c_str());
if (_glowBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_glowFilename.c_str(),
_name.c_str());
}
}
if (_normalBitmap == -1 && VALID_FNAME(_normalMapFilename)) {
_normalBitmap = bm_load_either(_normalMapFilename.c_str());
if (_normalBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_normalMapFilename.c_str(),
_name.c_str());
}
}
}
void DecalDefinition::pageIn() {
if (_diffuseBitmap >= 0) {
bm_page_in_texture(_diffuseBitmap);
bool bitmapsLoaded() {
// Since both bitmap types are optional we need to check if either is loaded to determine if any bitmap is loaded
return _diffuseBitmap >= 0 || _glowBitmap >= 0 || _normalBitmap >= 0;
}
if (_glowBitmap >= 0) {
bm_page_in_texture(_glowBitmap);
const SCP_string& getName() const {
return _name;
}
if (_normalBitmap >= 0) {
bm_page_in_texture(_normalBitmap);
int getDiffuseBitmap() const {
return _diffuseBitmap;
}
}
int getGlowBitmap() const {
return _glowBitmap;
}
int getNormalBitmap() const {
return _normalBitmap;
}
bool isDiffuseLooping() const {
return _loopDiffuse;
}
bool isGlowLooping() const {
return _loopGlow;
}
bool isNormalLooping() const {
return _loopNormal;
}
};
bool DecalDefinition::bitmapsLoaded() {
// Since both bitmap types are optional we need to check if either is loaded to determine if any bitmap is loaded
return _diffuseBitmap >= 0 || _glowBitmap >= 0 || _normalBitmap >= 0;
}
const SCP_string& DecalDefinition::getName() const {
return _name;
}
int DecalDefinition::getDiffuseBitmap() const {
return _diffuseBitmap;
}
int DecalDefinition::getGlowBitmap() const {
return _glowBitmap;
}
int DecalDefinition::getNormalBitmap() const {
return _normalBitmap;
}
bool DecalDefinition::isDiffuseLooping() const {
return _loopDiffuse;
}
bool DecalDefinition::isGlowLooping() const {
return _loopGlow;
}
bool DecalDefinition::isNormalLooping() const {
return _loopNormal;
}
SCP_vector<DecalDefinition> DecalDefinitions;
SCP_vector<DecalDefinition> decalDefinitions;
// Variable to indicate if the system is able to work correctly on the current system
bool Decal_system_active = true;
bool decal_system_active = true;
void parse_decals_table(const char* filename) {
try {
@@ -176,7 +197,7 @@ void parse_decals_table(const char* filename) {
DecalDefinition def(name);
def.parse();
DecalDefinitions.push_back(std::move(def));
decalDefinitions.push_back(std::move(def));
}
required_string("#End");
@@ -187,17 +208,17 @@ void parse_decals_table(const char* filename) {
if (!gr_is_capable(CAPABILITY_DEFERRED_LIGHTING)) {
// we need deferred lighting
Decal_system_active = false;
decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of deferred lighting.\n"));
}
if (!gr_is_capable(CAPABILITY_NORMAL_MAP)) {
// We need normal mapping for the full feature range
Decal_system_active = false;
decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of normal mapping.\n"));
}
if (!gr_is_capable(CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
// WWe need separate blending functions for different color buffers
Decal_system_active = false;
decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of separate color buffer blend functions.\n"));
}
}
@@ -293,41 +314,35 @@ float smoothstep(float edge0, float edge1, float x) {
namespace decals {
void initialize() {
if (gr_screen.mode == GR_STUB) {
Decal_system_active = false;
return;
}
DecalDefinitions.clear();
decalDefinitions.clear();
graphics::decal_draw_list::globalInit();
parse_modular_table(NOX("*-dcl.tbm"), parse_decals_table);
}
void shutdown() {
graphics::decal_draw_list::globalShutdown();
// Free allocated resources
DecalDefinitions.clear();
decalDefinitions.clear();
}
int findDecalDefinition(const SCP_string& name) {
auto ii = std::find_if(DecalDefinitions.begin(), DecalDefinitions.end(), [&](const DecalDefinition& def)
{
return def.getName() == name;
});
int getDecalConfig(const SCP_string& name) {
int index = 0;
for (auto& def : decalDefinitions) {
if (!stricmp(def.getName().c_str(), name.c_str())) {
return index;
}
++index;
}
if (ii == DecalDefinitions.end())
return -1;
return static_cast<int>(std::distance(DecalDefinitions.begin(), ii));
return -1;
}
void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
SCP_string name;
stuff_string(name, F_NAME);
auto decalRef = findDecalDefinition(name);
auto decalRef = getDecalConfig(name);
if (decalRef < 0) {
error_display(0, "Decal definition '%s' is unknown!", name.c_str());
@@ -352,9 +367,8 @@ void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
}
}
}
void loadBitmaps(const creation_info& info) {
if (!Decal_system_active) {
if (!decal_system_active) {
return;
}
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
@@ -362,16 +376,15 @@ void loadBitmaps(const creation_info& info) {
return;
}
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) DecalDefinitions.size(),
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
auto& def = DecalDefinitions[info.definition_handle];
auto& def = decalDefinitions[info.definition_handle];
def.loadBitmaps();
}
void pageInDecal(const creation_info& info) {
if (!Decal_system_active) {
if (!decal_system_active) {
return;
}
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
@@ -379,10 +392,10 @@ void pageInDecal(const creation_info& info) {
return;
}
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) DecalDefinitions.size(),
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
DecalDefinitions[info.definition_handle].pageIn();
decalDefinitions[info.definition_handle].pageIn();
}
void initializeMission() {
@@ -398,25 +411,48 @@ matrix4 getDecalTransform(Decal& decal) {
auto pm = model_get(pmi->model_num);
vec3d worldPos;
matrix worldOrient;
model_instance_local_to_global_point_orient(&worldPos,
&worldOrient,
model_instance_local_to_global_point(&worldPos,
&decal.position,
&decal.orientation,
pm,
pmi,
decal.submodel,
&objp->orient,
&objp->pos);
vec3d worldDir;
model_instance_local_to_global_dir(&worldDir,
&decal.orientation.vec.fvec,
pm,
pmi,
decal.submodel,
&objp->orient);
// The decal API sees the "direction" of a decal to be along the normal of the surface it is attached to. However,
// this will lead to a situation where we would look at the decal texture "from behind" causing the texture to
// appear flipped. We fix that here for the graphics transform by inverting the Z scaling.
// appear flipped. We fix that here for the graphics transform.
vm_vec_scale(&worldDir, -1.0f);
vec3d worldUp;
model_instance_local_to_global_dir(&worldUp,
&decal.orientation.vec.uvec,
pm,
pmi,
decal.submodel,
&objp->orient);
matrix worldOrient;
vm_vector_2_matrix(&worldOrient, &worldDir, &worldUp);
// Apply scaling
vm_vec_scale(&worldOrient.vec.rvec, decal.scale.xyz.x);
vm_vec_scale(&worldOrient.vec.uvec, decal.scale.xyz.y);
vm_vec_scale(&worldOrient.vec.fvec, -decal.scale.xyz.z);
worldOrient.a2d[0][0] *= decal.scale.xyz.x;
worldOrient.a2d[0][1] *= decal.scale.xyz.x;
worldOrient.a2d[0][2] *= decal.scale.xyz.x;
worldOrient.a2d[1][0] *= decal.scale.xyz.y;
worldOrient.a2d[1][1] *= decal.scale.xyz.y;
worldOrient.a2d[1][2] *= decal.scale.xyz.y;
worldOrient.a2d[2][0] *= decal.scale.xyz.z;
worldOrient.a2d[2][1] *= decal.scale.xyz.z;
worldOrient.a2d[2][2] *= decal.scale.xyz.z;
matrix4 mat4;
vm_matrix4_set_transform(&mat4, &worldOrient, &worldPos);
@@ -425,7 +461,7 @@ matrix4 getDecalTransform(Decal& decal) {
}
void renderAll() {
if (!Decal_system_active) {
if (!decal_system_active) {
return;
}
@@ -456,9 +492,9 @@ void renderAll() {
int glow_bm = -1;
int normal_bm = -1;
Assertion(decal.definition_handle >= 0 && decal.definition_handle < (int) DecalDefinitions.size(),
Assertion(decal.definition_handle >= 0 && decal.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
auto& decalDef = DecalDefinitions[decal.definition_handle];
auto& decalDef = decalDefinitions[decal.definition_handle];
auto decal_time = mission_time - decal.creation_time;
auto progress = decal_time / decal.lifetime;
@@ -489,9 +525,9 @@ void renderAll() {
draw_list.render();
}
void addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
if (!Decal_system_active) {
void
addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
if (!decal_system_active) {
return;
}
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
@@ -499,9 +535,9 @@ void addDecal(creation_info& info, object* host, int submodel, const vec3d& loca
return;
}
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) DecalDefinitions.size(),
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
auto& def = DecalDefinitions[info.definition_handle];
auto& def = decalDefinitions[info.definition_handle];
if (!def.bitmapsLoaded()) {
// If this decal was never used before then the bitmaps are not loaded so we need to do that here.
@@ -518,15 +554,9 @@ void addDecal(creation_info& info, object* host, int submodel, const vec3d& loca
newDecal.position = local_pos;
newDecal.orientation = local_orient;
if (info.width < 0.0f || info.height < 0.0f) {
newDecal.scale.xyz.x = info.radius;
newDecal.scale.xyz.y = info.radius;
newDecal.scale.xyz.z = info.radius;
} else {
newDecal.scale.xyz.x = info.width;
newDecal.scale.xyz.y = info.height;
newDecal.scale.xyz.z = MIN(info.width, info.height);
}
newDecal.scale.xyz.x = info.radius;
newDecal.scale.xyz.y = info.radius;
newDecal.scale.xyz.z = info.radius;
active_decals.push_back(newDecal);
}
-53
View File
@@ -8,52 +8,6 @@
namespace decals {
class DecalDefinition {
SCP_string _name;
SCP_string _diffuseFilename;
bool _loopDiffuse = true;
SCP_string _glowFilename;
bool _loopGlow = true;
SCP_string _normalMapFilename;
bool _loopNormal = true;
int _diffuseBitmap = -1;
int _glowBitmap = -1;
int _normalBitmap = -1;
public:
explicit DecalDefinition(SCP_string name);
~DecalDefinition();
// Disallow copying
DecalDefinition(const DecalDefinition&) = delete;
DecalDefinition& operator=(const DecalDefinition&) = delete;
// Move constructor and operator
DecalDefinition(DecalDefinition&& other) noexcept;
DecalDefinition& operator=(DecalDefinition&& other) noexcept;
void parse();
void loadBitmaps();
void pageIn();
bool bitmapsLoaded();
const SCP_string& getName() const;
int getDiffuseBitmap() const;
int getGlowBitmap() const;
int getNormalBitmap() const;
bool isDiffuseLooping() const;
bool isGlowLooping() const;
bool isNormalLooping() const;
};
extern SCP_vector<DecalDefinition> DecalDefinitions;
extern bool Decal_system_active;
/**
* @brief A reference to a decal definition
*/
@@ -65,8 +19,6 @@ typedef int DecalReference;
struct creation_info {
DecalReference definition_handle = -1;
float radius = -1.0f;
float width = -1.0f;
float height = -1.0f;
util::UniformFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
};
@@ -76,11 +28,6 @@ struct creation_info {
void initialize();
/**
* Returns the index of this decal, or -1 if not found
*/
int findDecalDefinition(const SCP_string& name);
/**
* @brief Parses the information for a decal reference
*
+3 -3
View File
@@ -56,7 +56,7 @@ void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
// Positional light source
lightDir = lightPosition - position.xyz;
float dist = length(lightDir);
attenuation = 1.0 - clamp(sqrt(dist / lightRadius), 0.0, 1.0);
attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
if(dist > lightRadius && lightType != LT_TUBE) {
discard;
@@ -81,7 +81,7 @@ void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
if(dist > lightRadius) {
discard;
}
attenuation = 1.0 - clamp(sqrt(dist / lightRadius), 0.0, 1.0);
attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
} else if (lightType == LT_CONE) {
float coneDot = dot(normalize(-lightDir), coneDir);
if(dualCone) {
@@ -98,7 +98,7 @@ void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
}
}
}
attenuation *= attenuation;
lightDir = normalize(lightDir);
}
}
@@ -1,20 +0,0 @@
#define M_PI 3.1415926535897932384626433832795
uniform samplerCube envmap;
in vec4 fragTexCoord;
out vec4 fragOut0;
layout (location = 0) out vec4 outColor;
void main() {
const float theta = -fragTexCoord.x * (2.0 * M_PI);
const float phi = fragTexCoord.y * (M_PI) - (0.5 * M_PI);
const float st = sin(theta);
const float ct = cos(theta);
const float sp = sin(phi);
const float cp = cos(phi);
const vec3 sampVec = vec3(cp * ct, sp, cp * st);
fragOut0 = vec4(texture(envmap, sampVec).rgb, 1.0);
}
+1 -12
View File
@@ -407,21 +407,10 @@ void fireball_parse_tbl()
{
if (fi.lod_count > 1)
{
Assertion(fi.lod_count <= MAX_FIREBALL_LOD, "Fireball LOD (%d) greater than MAX_FIREBALL_LOD %d.", fi.lod_count, MAX_FIREBALL_LOD);
static_assert(MAX_FIREBALL_LOD < 10, "The fireball LOD naming scheme needs to be changed for LODs > 9");
auto lod0 = fi.lod[0].filename;
constexpr int MAX_BASENAME_LEN = MAX_FILENAME_LEN - 3; // ensure base file name + _*lod* fits in filename field
if (strlen(lod0) > MAX_BASENAME_LEN)
{
Warning(LOCATION, "A fireball base file name may not be longer than %d characters due to the LOD naming scheme.\nLODs other than LOD0 will be skipped for fireball %s", MAX_BASENAME_LEN, lod0);
fi.lod_count = 1;
continue;
}
for (int j = 1; j < fi.lod_count; ++j)
sprintf(fi.lod[j].filename, "%.*s_%d", MAX_BASENAME_LEN, lod0, j % MAX_FIREBALL_LOD /*to show gcc12 format string is safe*/);
sprintf(fi.lod[j].filename, "%s_%d", lod0, j);
}
}
+68 -51
View File
@@ -68,8 +68,8 @@ typedef struct tagSNDPATTERN {
SNDPATTERN Patterns[MAX_PATTERNS]; // holds data on sections of a SoundTrack
// Holds filenames for the different sections of a soundtrack
SCP_vector<SOUNDTRACK_INFO> Soundtracks;
SOUNDTRACK_INFO Soundtracks[MAX_SOUNDTRACKS];
int Num_soundtracks;
int Current_soundtrack_num; // Active soundtrack for the current mission.. index into Soundtracks[]
int Current_pattern = -1; // currently playing part of track
@@ -87,6 +87,12 @@ static int Victory2_music_played;
static int Next_arrival_timestamp;
static int Check_for_battle_music;
// stores the number of measures for the different patterns (data from music.tbl)
float Pattern_num_measures[MAX_SOUNDTRACKS][MAX_PATTERNS];
// stores the number of bytes per measure (data from music.tbl)
int Pattern_samples_per_measure[MAX_SOUNDTRACKS][MAX_PATTERNS];
typedef struct pattern_info
{
const char *pattern_name;
@@ -250,10 +256,11 @@ extern int hud_target_invalid_awacs(object *objp);
// Holds file names of spooled music that is played at menus, briefings, credits etc.
// Indexed into by a #define enumeration of the different kinds of spooled music
SCP_vector<menu_music> Spooled_music;
menu_music Spooled_music[MAX_SPOOLED_MUSIC];
int Num_music_files; // Number of spooled music files
// Array that holds indicies into Spooled_music[], these specify which music is played in briefing/debriefing
int Mission_music[NUM_SCORES];
int Mission_music[NUM_SCORES];
// -------------------------------------------------------------------------------------------------
@@ -278,11 +285,23 @@ void event_music_init()
return;
}
int i, j;
//MUST be called before parsing stuffzors.
Soundtracks.clear();
Spooled_music.clear();
Num_music_files = 0;
Num_soundtracks = 0; // Global
event_music_reset_choices();
// Goober5000
// set all the filenames to "none" so we're compatible with the extra NRMLs in FS1 music
memset(Soundtracks, 0, MAX_SOUNDTRACKS * sizeof(SOUNDTRACK_INFO));
for (i = 0; i < MAX_SOUNDTRACKS; i++)
for (j = 0; j < MAX_PATTERNS; j++)
strcpy_s(Soundtracks[i].pattern_fnames[j], NOX("none.wav"));
// Goober5000
memset(Spooled_music, 0, MAX_SPOOLED_MUSIC * sizeof(menu_music));
//Do teh parsing
event_music_parse_musictbl("music.tbl");
@@ -548,9 +567,9 @@ void event_music_level_start(int force_soundtrack)
return;
}
Assert(Current_soundtrack_num >= 0 && Current_soundtrack_num < (int)Soundtracks.size());
Assert(Current_soundtrack_num >= 0 && Current_soundtrack_num < Num_soundtracks);
if (Current_soundtrack_num < 0 || Current_soundtrack_num > (int)Soundtracks.size())
if (Current_soundtrack_num < 0 || Current_soundtrack_num > Num_soundtracks)
return;
strack = &Soundtracks[Current_soundtrack_num];
@@ -563,13 +582,13 @@ void event_music_level_start(int force_soundtrack)
// tracks because their patterns weren't -1
for (i = 0; i < MAX_PATTERNS; i++)
{
if (!strnicmp(strack->patterns[i].fname, NOX("none.wav"), 4))
if (!strnicmp(strack->pattern_fnames[i], NOX("none.wav"), 4))
{
Patterns[i].handle = -1;
continue;
}
Patterns[i].handle = audiostream_open( strack->patterns[i].fname, ASF_EVENTMUSIC );
Patterns[i].handle = audiostream_open( strack->pattern_fnames[i], ASF_EVENTMUSIC );
if (Patterns[i].handle >= 0)
{
@@ -590,8 +609,8 @@ void event_music_level_start(int force_soundtrack)
Patterns[i].loop_for = Patterns[i].default_loop_for;
Patterns[i].force_pattern = FALSE;
Patterns[i].can_force = pip->pattern_can_force;
Patterns[i].samples_per_measure = strack->patterns[i].samples_per_measure;
Patterns[i].num_measures = strack->patterns[i].num_measures;
Patterns[i].samples_per_measure = Pattern_samples_per_measure[Current_soundtrack_num][i];
Patterns[i].num_measures = Pattern_num_measures[Current_soundtrack_num][i];
}
Num_enemy_arrivals = 0;
@@ -660,18 +679,6 @@ void event_music_first_pattern()
// this yields a relative start time of 1 second. Mission start will now use relative rather than absolute delay.
void event_music_set_start_delay()
{
if (Event_music_inited == FALSE) {
return;
}
if (Event_music_enabled == FALSE) {
return;
}
if (Event_music_level_inited == FALSE) {
return;
}
Pattern_timer_id = timestamp(1000);
}
@@ -687,8 +694,11 @@ void event_music_level_close()
if ( Event_music_level_inited == FALSE )
return;
if ( Current_soundtrack_num >= 0 && Current_soundtrack_num < (int)Soundtracks.size() ) {
auto strack = &Soundtracks[Current_soundtrack_num];
if ( Current_soundtrack_num >= 0 && Current_soundtrack_num < MAX_SOUNDTRACKS ) {
SOUNDTRACK_INFO *strack;
Assert( Current_soundtrack_num >= 0 && Current_soundtrack_num < MAX_SOUNDTRACKS );
strack = &Soundtracks[Current_soundtrack_num];
// close the pattern files
for ( i = 0; i < strack->num_patterns; i++ ) {
@@ -1146,16 +1156,16 @@ bool parse_soundtrack_line(int strack_idx, int pattern_idx)
}
if (count == 0) {
Soundtracks[strack_idx].patterns[pattern_idx].num_measures = (float)atof(token); //Num_measures
} else if (count == 1) {
Soundtracks[strack_idx].patterns[pattern_idx].samples_per_measure = atoi(token); //Samples per measure
if ( count == 0 ) {
Pattern_num_measures[strack_idx][pattern_idx] = (float)atof(token); //Num_measures
} else if(count == 1) {
Pattern_samples_per_measure[strack_idx][pattern_idx] = atoi(token); //Samples per measure
}
count++;
} // end while
strcpy_s(Soundtracks[strack_idx].patterns[pattern_idx].fname, fname);
strcpy_s(Soundtracks[strack_idx].pattern_fnames[pattern_idx], fname);
return true;
}
@@ -1179,27 +1189,28 @@ void parse_soundtrack()
}
//Get a valid strack_idx
if (strack_idx < 0 && nocreate)
if(strack_idx < 0 && (nocreate || Num_soundtracks >= MAX_SOUNDTRACKS))
{
if(Num_soundtracks >= MAX_SOUNDTRACKS) {
Warning(LOCATION, "Maximum number of soundtracks reached after '%s'; max is '%d'", Soundtracks[MAX_SOUNDTRACKS-1].name, MAX_SOUNDTRACKS);
}
//Track doesn't exist and has nocreate, so don't create it
if ( !skip_to_start_of_string_either("#SoundTrack Start", "#Menu Music Start") && !skip_to_string("#SoundTrack End")) {
error_display(1, "Couldn't find #Soundtrack Start, #Menu Music Start or #Soundtrack End.");
}
return;
}
else if (strack_idx < 0)
else if(strack_idx < 0)
{
//If we don't have this soundtrack already, create it
strack_idx = (int)Soundtracks.size();
Soundtracks.emplace_back();
strack_idx = Num_soundtracks;
Soundtracks[strack_idx].flags = 0;
Soundtracks[strack_idx].num_patterns = 0;
strcpy_s(Soundtracks[strack_idx].name, namebuf);
Soundtracks[strack_idx].num_patterns = 0;
// set all the filenames to "none" so we're compatible with the extra NRMLs in FS1 music
for (auto &pattern : Soundtracks[strack_idx].patterns)
strcpy_s(pattern.fname, NOX("none.wav"));
Num_soundtracks++;
}
// Goober5000
@@ -1290,11 +1301,11 @@ void parse_soundtrack()
for (i = 0; i < Soundtracks[strack_idx].num_patterns; i++)
{
// check for "none"
if (!strlen(Soundtracks[strack_idx].patterns[i].fname) || !strnicmp(Soundtracks[strack_idx].patterns[i].fname, "none", 4))
if (!strlen(Soundtracks[strack_idx].pattern_fnames[i]) || !strnicmp(Soundtracks[strack_idx].pattern_fnames[i], "none", 4))
continue;
// check for file
if (!cf_exists_full_ext(Soundtracks[strack_idx].patterns[i].fname, CF_TYPE_MUSIC, NUM_AUDIO_EXT, audio_ext_list))
if (!cf_exists_full(Soundtracks[strack_idx].pattern_fnames[i], CF_TYPE_MUSIC))
return;
}
@@ -1317,19 +1328,22 @@ void parse_menumusic()
int idx = event_music_get_spooled_music_index(spoolname);
if (idx < 0 && nocreate)
if(idx < 0 && (nocreate || Num_music_files >= MAX_SPOOLED_MUSIC))
{
if(Num_music_files >= MAX_SPOOLED_MUSIC) {
Warning(LOCATION, "Could not load spooled music file after '%s' as maximum number of spooled music was reached (Max is %d)", Spooled_music[Num_music_files - 1].name, MAX_SPOOLED_MUSIC);
}
if (!skip_to_start_of_string_either("$Name:", "#Menu Music End")) {
Error(LOCATION, "Couldn't find $Name or #Menu Music End. Music.tbl or -mus.tbm is invalid.\n");
}
return;
}
else if (idx < 0)
else if(idx < 0)
{
idx = (int)Spooled_music.size();
Spooled_music.emplace_back();
idx = Num_music_files;
Spooled_music[idx].flags = 0;
strcpy_s( Spooled_music[idx].name, spoolname );
strcpy_s( Spooled_music[idx].filename, "");
}
@@ -1352,6 +1366,9 @@ void parse_menumusic()
// chief1983 - use type list defined in ffmpeg.h
if ( cf_exists_full_ext(Spooled_music[idx].filename, CF_TYPE_MUSIC, NUM_AUDIO_EXT, audio_ext_list) )
Spooled_music[idx].flags |= SMF_VALID;
if (!nocreate)
Num_music_files++;
}
// -------------------------------------------------------------------------------------------------
@@ -1600,7 +1617,7 @@ int event_music_next_soundtrack(int delta)
}
new_soundtrack = Current_soundtrack_num + delta;
if ( new_soundtrack >= (int)Soundtracks.size() )
if ( new_soundtrack >= Num_soundtracks )
new_soundtrack = 0;
event_music_level_close();
@@ -1616,7 +1633,7 @@ void event_sexp_change_soundtrack(const char *name)
int i, new_soundtrack = -1;
for (i = 0; i < (int)Soundtracks.size(); i++) {
for (i = 0; i < Num_soundtracks; i++) {
if ( !stricmp(name, Soundtracks[i].name) ) {
new_soundtrack = i;
}
@@ -1660,7 +1677,7 @@ void event_music_set_soundtrack(const char *name)
int event_music_get_soundtrack_index(const char *name)
{
// find the correct index for the event music
for ( int i = 0; i < (int)Soundtracks.size(); i++ ) {
for ( int i = 0; i < Num_soundtracks; i++ ) {
if ( !stricmp(name, Soundtracks[i].name) ) {
return i;
}
@@ -1672,7 +1689,7 @@ int event_music_get_soundtrack_index(const char *name)
int event_music_get_spooled_music_index(const char *name)
{
// find the correct index for the event music
for ( int i = 0; i < (int)Spooled_music.size(); i++ ) {
for ( int i = 0; i < Num_music_files; i++ ) {
if ( !stricmp(name, Spooled_music[i].name) ) {
return i;
}
+10 -8
View File
@@ -67,30 +67,32 @@ typedef struct menu_music {
char filename[MAX_FILENAME_LEN]; // name music is stored on disk as
} menu_music;
#define MAX_SPOOLED_MUSIC 50 // max number of briefing/mainhall/credits tracks
// Goober5000 - spooled music flags
#define SMF_VALID (1 << 0)
extern SCP_vector<menu_music> Spooled_music;
extern menu_music Spooled_music[MAX_SPOOLED_MUSIC];
extern int Num_music_files;
// event music soundtrack storage
typedef struct tagSOUNDTRACK_INFO {
int flags;
int num_patterns;
char name[NAME_LENGTH];
struct {
char fname[MAX_FILENAME_LEN];
float num_measures;
int samples_per_measure;
} patterns[MAX_PATTERNS];
char name[NAME_LENGTH];
char pattern_fnames[MAX_PATTERNS][MAX_FILENAME_LEN];
} SOUNDTRACK_INFO;
#define MAX_SOUNDTRACKS 30 // max number of battle tracks
// Goober5000 - event music flags
#define EMF_VALID (1 << 0)
#define EMF_ALLIED_ARRIVAL_OVERLAY (1 << 1)
#define EMF_CYCLE_FS1 (1 << 2)
extern SCP_vector<SOUNDTRACK_INFO> Soundtracks;
extern SOUNDTRACK_INFO Soundtracks[MAX_SOUNDTRACKS];
extern int Num_soundtracks;
void event_music_init();
+2 -2
View File
@@ -823,7 +823,7 @@ void parse_gamesnd_soundset(game_snd* gs, bool no_create) {
int temp_limit;
stuff_int(&temp_limit);
if (temp_limit > 0)
if ((temp_limit > 0) && (static_cast<uint>(temp_limit) <= SND_ENHANCED_MAX_LIMIT))
{
gs->enhanced_sound_data.limit = (unsigned int)temp_limit;
}
@@ -927,7 +927,7 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
int temp_limit;
stuff_int(&temp_limit);
if (temp_limit > 0)
if ((temp_limit > 0) && (static_cast<uint>(temp_limit) <= SND_ENHANCED_MAX_LIMIT))
{
gs->enhanced_sound_data.limit = (unsigned int)temp_limit;
}
+1 -161
View File
@@ -7,7 +7,7 @@
*
*/
#include <utility> // for std::move
#ifndef _LINKLIST_H
#define _LINKLIST_H
@@ -83,164 +83,4 @@ do { \
#define NOT_EMPTY(head) ((head)->next != (head))
#define EMPTY(head) ((head) == nullptr || (head)->next == (head))
// Note that since these iterators operate on pointer collections, the dereference of an iterator using operator* returns a pointer.
template <class T>
class volition_linked_list
{
T* head;
public:
class iterator
{
T* ptr;
public:
iterator(T* x)
: ptr(x)
{}
iterator(const iterator& it)
: ptr(it.ptr)
{}
iterator& operator++()
{
ptr = GET_NEXT(ptr);
return *this;
}
iterator operator++(int)
{
iterator tmp(*this);
operator++();
return tmp;
}
iterator& operator--()
{
ptr = GET_PREV(ptr);
return *this;
}
iterator operator--(int)
{
iterator tmp(*this);
operator--();
return tmp;
}
bool operator==(const iterator& rhs) const
{
return ptr == rhs.ptr;
}
bool operator!=(const iterator& rhs) const
{
return ptr != rhs.ptr;
}
T*& operator*()
{
return ptr;
}
T* operator->()
{
return ptr;
}
};
class const_iterator
{
const T* ptr;
public:
const_iterator(const T* x)
: ptr(x)
{}
const_iterator(const const_iterator& it)
: ptr(it.ptr)
{}
const_iterator& operator++()
{
ptr = GET_NEXT(ptr);
return *this;
}
const_iterator operator++(int)
{
const_iterator tmp(*this);
operator++();
return tmp;
}
const_iterator& operator--()
{
ptr = GET_PREV(ptr);
return *this;
}
const_iterator operator--(int)
{
const_iterator tmp(*this);
operator--();
return tmp;
}
bool operator==(const const_iterator& rhs) const
{
return ptr == rhs.ptr;
}
bool operator!=(const const_iterator& rhs) const
{
return ptr != rhs.ptr;
}
const T*& operator*()
{
return ptr;
}
const T* operator->()
{
return ptr;
}
};
iterator begin() const
{
return iterator(GET_FIRST(head));
}
iterator end() const
{
return iterator(END_OF_LIST(head));
}
const_iterator cbegin() const
{
return const_iterator(GET_FIRST(head));
}
const_iterator cend() const
{
return const_iterator(END_OF_LIST(head));
}
volition_linked_list(T* ptr)
: head(ptr)
{}
};
template <class T>
volition_linked_list<T> list_range(T* head)
{
return volition_linked_list<T>(head);
}
#endif
+1 -2
View File
@@ -114,8 +114,7 @@ typedef struct vec2d {
} vec2d;
// Euler angles for a rotation: h=heading, b=bank and p=pitch; angles are around the y, z and x axes
// respectively and are performed in that order. (Strictly speaking these are Tait-Bryan angles,
// not classic Euler angles.)
// respectively and are performed in that order.
typedef struct angles {
float p, b, h;
} angles_t;
-5
View File
@@ -6,11 +6,6 @@
#define SCP_TOKEN_CONCAT1(x, y) x ## y
#define SCP_TOKEN_CONCAT(x, y) SCP_TOKEN_CONCAT1(x, y)
// these are useful for embedding numbers in strings
// see https://stackoverflow.com/questions/5459868/concatenate-int-to-string-using-c-preprocessor
#define SCP_TOKEN_TO_STR1(x) #x
#define SCP_TOKEN_TO_STR(x) SCP_TOKEN_TO_STR1(x)
#define SCP_UNUSED(x) (void)(x)
#endif // SCP_DEFINES_H
+40
View File
@@ -427,6 +427,46 @@ DCF(detail, "Turns on/off parts of the game for speed testing" )
}
#endif
// Goober5000
// (Taylor says that for optimization purposes malloc/free should be used rather than vm_malloc/vm_free here)
// NOTE: Because this uses memcpy, it should only be used to sort POD elements!
void insertion_sort(void *array_base, size_t array_size, size_t element_size, int (*fncompare)(const void *, const void *))
{
int i, j;
void *current;
char *array_byte_base;
// this is used to avoid having to cast array_base to (char *) all the time
array_byte_base = (char *) array_base;
// allocate space for the element being moved
current = malloc(element_size);
if (current == NULL)
{
Int3();
return;
}
// loop
for (i = 1; (unsigned) i < array_size; i++)
{
// grab the current element
memcpy(current, array_byte_base + (i * element_size), element_size);
// bump other elements toward the end of the array
for (j = i - 1; (j >= 0) && (fncompare(array_byte_base + (j * element_size), current) > 0); j--)
{
memcpy(array_byte_base + ((j + 1) * element_size), array_byte_base + (j * element_size), element_size);
}
// insert the current element at the correct place
memcpy(array_byte_base + ((j + 1) * element_size), current, element_size);
}
// free the allocated space
free(current);
}
// Stuff that can't be included in vmallocator.h
std::locale SCP_default_locale("");
+17 -68
View File
@@ -31,23 +31,23 @@
#define GM_CAMPAIGN_MODE (1 << 10) // are we currently in a campaign.
#define GM_LAB (1 << 11) // We are currently in the F3 lab
#define VM_EXTERNAL (1 << 0) // Set if not viewing from player position.
#define VM_TRACK (1 << 1) // Set if viewer is tracking target.
#define VM_DEAD_VIEW (1 << 2) // Set if viewer is watching from dead view.
#define VM_CHASE (1 << 3) // Chase view.
#define VM_OTHER_SHIP (1 << 4) // View from another ship.
#define VM_CAMERA_LOCKED (1 << 5) // Set if player does not have control of the camera
#define VM_WARP_CHASE (1 << 6) // View while warping out (form normal view mode)
#define VM_PADLOCK_UP (1 << 7) // Set when player is looking up
#define VM_PADLOCK_REAR (1 << 8) // Set when player is looking behind
#define VM_PADLOCK_LEFT (1 << 9) // Set when player is looking left
#define VM_PADLOCK_RIGHT (1 << 10) // Set when player is looking right
#define VM_WARPIN_ANCHOR (1 << 11) // special warpin camera mode
#define VM_TOPDOWN (1 << 12) // Camera is looking down on ship
#define VM_FREECAMERA (1 << 13) // Camera is not attached to any particular object, probably under SEXP control
#define VM_CENTERING (1 << 14) // View is springing to center
#define VM_EXTERNAL (1 << 0) // Set if not viewing from player position.
#define VM_TRACK (1 << 1) // Set if viewer is tracking target.
#define VM_DEAD_VIEW (1 << 2) // Set if viewer is watching from dead view.
#define VM_CHASE (1 << 3) // Chase view.
#define VM_OTHER_SHIP (1 << 4) // View from another ship.
#define VM_CAMERA_LOCKED (1 << 5) // Set if player does not have control of the camera
#define VM_WARP_CHASE (1 << 6) // View while warping out (form normal view mode)
#define VM_PADLOCK_UP (1 << 7)
#define VM_PADLOCK_REAR (1 << 8)
#define VM_PADLOCK_LEFT (1 << 9)
#define VM_PADLOCK_RIGHT (1 << 10)
#define VM_WARPIN_ANCHOR (1 << 11) // special warpin camera mode
#define VM_TOPDOWN (1 << 12) //Camera is looking down on ship
#define VM_FREECAMERA (1 << 13) //Camera is not attached to any particular object, probably under SEXP control
#define VM_CENTERING (1 << 14) // View is springing to center
#define VM_PADLOCK_ANY (VM_PADLOCK_UP | VM_PADLOCK_REAR | VM_PADLOCK_LEFT | VM_PADLOCK_RIGHT)
#define VM_PADLOCK_ANY (VM_PADLOCK_UP|VM_PADLOCK_REAR|VM_PADLOCK_LEFT|VM_PADLOCK_RIGHT)
//-----Cutscene stuff
//No bars
@@ -213,58 +213,7 @@ int current_detail_level();
// Goober5000
// A sort for use with small or almost-sorted lists. Iteration time is O(n) for a fully-sorted list.
// This uses a type-safe version of the function prototype for stdlib's qsort, although the size is an int rather than a size_t (for the reasons that j is an int).
// The fncompare function should return <0, 0, or >0 as the left item is less than, equal to, or greater than the right item.
template <typename T>
void insertion_sort(T* array_base, int array_size, int (*fncompare)(const T*, const T*))
{
// NOTE: j *must* be a signed type because j reaches -1 and j+1 must be 0.
int i, j;
T *current, *current_buf;
void insertion_sort(void *array, size_t array_size, size_t element_size, int (*fncompare)(const void *, const void *));
// allocate space for the element being moved
// (Taylor says that for optimization purposes malloc/free should be used rather than vm_malloc/vm_free here)
current_buf = (T*)malloc(sizeof(T));
if (current_buf == nullptr)
{
UNREACHABLE("Malloc failed!");
return;
}
// loop
for (i = 1; i < array_size; i++)
{
// grab the current element
// this does a lazy move/copy because if the array is mostly sorted,
// there's no sense copying sorted items to their own places
bool lazily_copied = false;
current = &array_base[i];
// bump other elements toward the end of the array
for (j = i - 1; (j >= 0) && (fncompare(&array_base[j], current) > 0); j--)
{
if (!lazily_copied)
{
// this may look strange but it is just copying the data
// into the buffer, then pointing to the buffer
*current_buf = std::move(*current);
current = current_buf;
lazily_copied = true;
}
array_base[j + 1] = std::move(array_base[j]);
}
if (lazily_copied)
{
// insert the current element at the correct place
array_base[j + 1] = std::move(*current);
}
}
// free the allocated space
free(current_buf);
}
#endif
+10 -4
View File
@@ -313,8 +313,11 @@ void Add_Symbol( int section, int offset, const char *name, char *module )
}
int Sym_compare( const MemSymbol *sym1, const MemSymbol *sym2 )
int Sym_compare( const void *arg1, const void *arg2 )
{
MemSymbol * sym1 = (MemSymbol *)arg1;
MemSymbol * sym2 = (MemSymbol *)arg2;
if ( sym1->section < sym2->section ) {
return -1;
} else if ( sym1->section > sym2->section ) {
@@ -328,8 +331,11 @@ int Sym_compare( const MemSymbol *sym1, const MemSymbol *sym2 )
}
}
int Sym_compare1( const MemSymbol *sym1, const MemSymbol *sym2 )
int Sym_compare1( const void *arg1, const void *arg2 )
{
MemSymbol * sym1 = (MemSymbol *)arg1;
MemSymbol * sym2 = (MemSymbol *)arg2;
if ( sym1->size < sym2->size ) {
return 1;
} else if ( sym1->size > sym2->size ) {
@@ -343,7 +349,7 @@ void DumpSymbols()
{
int i;
insertion_sort( Symbols, Num_symbols, Sym_compare );
insertion_sort( Symbols, Num_symbols, sizeof(MemSymbol), Sym_compare );
for (i=0;i<Num_symbols; i++ ) {
MemSymbol * sym1 = &Symbols[i];
@@ -355,7 +361,7 @@ void DumpSymbols()
}
}
insertion_sort( Symbols, Num_symbols, Sym_compare1 );
insertion_sort( Symbols, Num_symbols, sizeof(MemSymbol), Sym_compare1 );
FILE *fp = fopen( "dump", "wt" );
+20 -56
View File
@@ -1435,7 +1435,7 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
auto res = ResolutionOption->getValue();
width = res.width;
height = res.height;
} else if ( !Is_standalone ) {
} else {
// We cannot continue without this, quit, but try to help the user out first
ptr = os_config_read_string(nullptr, NOX("VideocardFs2open"), nullptr);
@@ -1540,15 +1540,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
depth = d_depth;
}
// if we are in standalone mode then just use special defaults
if (Is_standalone) {
mode = GR_STUB;
width = 640;
height = 480;
depth = 16;
center_aspect_ratio = -1.0f;
}
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
@@ -1565,6 +1556,15 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
}
}
// if we are in standalone mode then just use special defaults
if (Is_standalone) {
mode = GR_STUB;
width = 640;
height = 480;
depth = 16;
center_aspect_ratio = -1.0f;
}
// 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
@@ -1616,12 +1616,14 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
mprintf(("Initializing path renderer...\n"));
graphics::paths::PathRenderer::init();
gr_light_init();
if ( !Is_standalone ) {
gr_light_init();
// Initialize uniform buffer managers
uniform_buffer_managers_init();
// Initialize uniform buffer managers
uniform_buffer_managers_init();
gpu_heap_init();
gpu_heap_init();
}
mprintf(("Checking graphics capabilities:\n"));
mprintf((" Persistent buffer mapping: %s\n",
@@ -2532,10 +2534,6 @@ void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float a
static void output_uniform_debug_data()
{
if (gr_screen.mode == GR_STUB) {
return;
}
int line_height = gr_get_font_height() + 1;
gr_set_color_fast(&Color_bright_white);
@@ -2557,9 +2555,7 @@ void gr_flip(bool execute_scripting)
TRACE_SCOPE(tracing::LuaOnFrame);
// WMC - Do conditional hooks. Yippee!
if (OnFrameHook->isActive()) {
OnFrameHook->run();
}
OnFrameHook->run();
// WMC - Do scripting reset stuff
Script_system.EndFrame();
}
@@ -2594,33 +2590,9 @@ void gr_print_timestamp(int x, int y, fix timestamp, int resize_mode)
gr_string(x, y, time.c_str(), resize_mode);
}
static void uniform_buffer_managers_init()
{
if (gr_screen.mode == GR_STUB) {
return;
}
UniformBufferManager.reset(new graphics::util::UniformBufferManager());
}
static void uniform_buffer_managers_deinit()
{
if (gr_screen.mode == GR_STUB) {
return;
}
UniformBufferManager.reset();
}
static void uniform_buffer_managers_retire_buffers()
{
if (gr_screen.mode == GR_STUB) {
return;
}
UniformBufferManager->onFrameEnd();
}
static void uniform_buffer_managers_init() { UniformBufferManager.reset(new graphics::util::UniformBufferManager()); }
static void uniform_buffer_managers_deinit() { UniformBufferManager.reset(); }
static void uniform_buffer_managers_retire_buffers() { UniformBufferManager->onFrameEnd(); }
graphics::util::UniformBuffer gr_get_uniform_buffer(uniform_block_type type, size_t num_elements, size_t element_size_override)
{
@@ -2755,10 +2727,6 @@ size_t vertex_layout::hash() const {
static std::unique_ptr<graphics::util::GPUMemoryHeap> gpu_heaps [static_cast<size_t>(GpuHeap::NUM_VALUES)];
static void gpu_heap_init() {
if (gr_screen.mode == GR_STUB) {
return;
}
for (size_t i = 0; i < static_cast<size_t>(GpuHeap::NUM_VALUES); ++i) {
auto enumVal = static_cast<GpuHeap>(i);
@@ -2854,10 +2822,6 @@ static void make_gamma_ramp(float gamma, ushort* ramp)
void gr_set_gamma(float gamma)
{
if (gr_screen.mode == GR_STUB) {
return;
}
Gr_gamma = gamma;
// new way - but not while running FRED
-6
View File
@@ -204,8 +204,6 @@ enum shader_type {
SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT,
SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING,
SDR_TYPE_ENVMAP_SPHERE_WARP,
NUM_SHADER_TYPES
};
@@ -715,9 +713,6 @@ typedef struct screen {
// dumps the current screen to a file
std::function<void(const char* filename)> gf_print_screen;
// transforms and dumps the current environment map to a file
std::function<void(const char* filename)> gf_dump_envmap;
// Retrieves the zbuffer mode.
std::function<int()> gf_zbuffer_get;
@@ -1002,7 +997,6 @@ extern void gr_activate(int active);
// old Descent-style gr_xxx calls.
#define gr_print_screen GR_CALL(gr_screen.gf_print_screen)
#define gr_dump_envmap GR_CALL(gr_screen.gf_dump_envmap)
//#define gr_flip GR_CALL(gr_screen.gf_flip)
void gr_flip(bool execute_scripting = true);
-225
View File
@@ -1,225 +0,0 @@
#include "graphics/color.h"
#include "graphics/2d.h"
#include "globalincs/pstypes.h"
#include "globalincs/vmallocator.h"
#include "math/floating.h"
void hdr_color::set_vecf(const SCP_vector<float>& input)
{
size_t l = input.size();
Assertion(l >= 3, "attempted to set color values invalid component count");
this->red = input.at(0);
this->green = input.at(1);
this->blue = input.at(2);
if (l > 3)
this->alpha = input.at(3);
if (l > 4)
this->intensity = input.at(4);
}
/*
* @brief Fills a vector with the raw float color components of the color, in the order red, green, blue, alpha,
* intensity
*
* @param to_fill: The fector that will be filled with the color compoents
*/
void hdr_color::get_v5f(SCP_vector<float>& to_fill) const
{
to_fill.clear();
to_fill.push_back(this->red);
to_fill.push_back(this->green);
to_fill.push_back(this->blue);
to_fill.push_back(this->alpha);
to_fill.push_back(this->intensity);
}
hdr_color::hdr_color()
{
this->red = 1.0f;
this->green = 1.0f;
this->blue = 1.0f;
this->alpha = 1.0f;
this->intensity = 1.0f;
}
hdr_color::hdr_color(float new_r, float new_g, float new_b, float new_a, float new_i)
{
this->red = new_r;
this->green = new_g;
this->blue = new_b;
this->alpha = new_a;
this->intensity = new_i;
}
hdr_color::hdr_color(const hdr_color* const source_color)
{
this->red = source_color->red;
this->green = source_color->green;
this->blue = source_color->blue;
this->alpha = source_color->alpha;
this->intensity = source_color->intensity;
}
/**
* @brief Sets RGB values from three 0-255 ints
*/
void hdr_color::set_rgb(int new_r, int new_g, int new_b)
{
this->red = i2fl(new_r) / 255.0f;
this->green = i2fl(new_g) / 255.0f;
this->blue = i2fl(new_b) / 255.0f;
}
/**
* @brief Sets RGBA values from an old style color object
*/
void hdr_color::set_rgb(const color* const new_color)
{
this->set_rgb(new_color->red, new_color->green, new_color->blue);
this->alpha = i2fl(new_color->alpha);
}
/**
* @brief Sets RGB values from an array of three 0-255 ints
*/
void hdr_color::set_rgb(const int* const new_rgb)
{
this->set_rgb(new_rgb[0], new_rgb[1], new_rgb[2]);
}
/**
* @brief retreives unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::r() const
{
return red;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::r(float in)
{
red = in;
return red;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component from 0-255 int.
*/
float hdr_color::r(int in)
{
red = i2fl(in) / 255.0f;
return red;
}
/**
* @brief retreives unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::g() const
{
return green;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::g(float in)
{
green = in;
return green;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component from 0-255 int.
*/
float hdr_color::g(int in)
{
green = i2fl(in) / 255.0f;
return green;
}
/**
* @brief retreives unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::b() const
{
return blue;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::b(float in)
{
blue = in;
return blue;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component from 0-255 int.
*/
float hdr_color::b(int in)
{
blue = i2fl(in) / 255.0f;
return blue;
}
/**
* @brief retreives unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::a() const
{
return alpha;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::a(float in)
{
alpha = in;
return alpha;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component from 0-255 int.
*/
float hdr_color::a(int in)
{
alpha = i2fl(in) / 255.0f;
return alpha;
}
/**
* @brief retreives unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::i() const
{
return intensity;
}
/**
* @brief sets and returns unmultiplied 0.0f-1.0f color component.
*/
float hdr_color::i(float in)
{
intensity = in;
return intensity;
}
/**
* @brief Resets to a full alpha, 100% white.
*/
void hdr_color::reset()
{
this->red = 1.0f;
this->green = 1.0f;
this->blue = 1.0f;
this->alpha = 1.0f;
this->intensity = 1.0f;
}
-42
View File
@@ -1,42 +0,0 @@
#pragma once
#include "graphics/2d.h"
#include "graphics/color.h"
#include "globalincs/pstypes.h"
#include "globalincs/vmallocator.h"
class hdr_color{
private:
float red,green,blue,alpha,intensity;
public:
hdr_color();
hdr_color(const float new_r, const float new_g, const float new_b, const float new_a = 1.0f, const float new_i =1.0f);
hdr_color(const hdr_color* const source_color);
void reset();
void get_v5f(SCP_vector<float>& outvec) const;
void set_vecf(const SCP_vector<float>& input);
void set_rgb(const int new_r,const int new_g,const int new_b);
void set_rgb(const color* const new_rgb);
void set_rgb(const int* const new_rgb);
float r() const;
float r(const float in);
float r(const int in);
float g() const;
float g(const float in);
float g(const int in);
float b() const;
float b(const float in);
float b(const int in);
float a() const;
float a(const float in);
float a(const int in);
float i() const;
float i(const float in);
};
-38
View File
@@ -1,38 +0,0 @@
#include "debug_sphere.h"
#include "globalincs/vmallocator.h"
#include "render/3d.h"
SCP_vector<debug_sphere> debug_sphere::Spheres;
debug_sphere::debug_sphere(const vec3d& pos_in, float rad_in)
{
pos = pos_in;
radius = rad_in;
}
void debug_sphere::add(const vec3d& pos, float rad)
{
Spheres.emplace_back(pos, rad);
}
void debug_sphere::clear()
{
Spheres.clear();
}
void debug_sphere::render()
{
color uicolor = gr_screen.current_color;
color render_color;
render_color.red = 255;
render_color.green = 255;
render_color.blue = 255;
render_color.alpha = 64;
gr_set_color_fast(&render_color);
for (auto& s : Spheres) {
g3_draw_sphere_ez(&(s.pos), s.radius);
}
gr_set_color_fast(&uicolor);
clear();
}
-16
View File
@@ -1,16 +0,0 @@
#pragma once
#include "globalincs/pstypes.h"
#include "globalincs/vmallocator.h"
class debug_sphere {
public:
static void add(const vec3d& pos, float radius);
static void render();
debug_sphere(const vec3d& pos, float radius);
private:
static SCP_vector<debug_sphere> Spheres;
static void clear();
vec3d pos;
float radius;
};
-31
View File
@@ -205,10 +205,6 @@ static void pre_render_init_lights() {
}
void gr_set_light(light* fs_light) {
if (gr_screen.mode == GR_STUB) {
return;
}
// init the light
gr_light grl;
FSLight2GLLight(fs_light, &grl);
@@ -217,10 +213,6 @@ void gr_set_light(light* fs_light) {
}
void gr_set_center_alpha(int type) {
if (gr_screen.mode == GR_STUB) {
return;
}
if (!type) {
return;
}
@@ -283,19 +275,11 @@ void gr_set_center_alpha(int type) {
}
void gr_reset_lighting() {
if (gr_screen.mode == GR_STUB) {
return;
}
gr_lights.clear();
Num_active_gr_lights = 0;
}
void gr_calculate_ambient_factor(int ambient_factor) {
if (gr_screen.mode == GR_STUB) {
return;
}
gr_user_ambient = (float) ((ambient_factor * 2) - 255) / 255.0f;
}
@@ -304,10 +288,6 @@ void gr_light_shutdown() {
}
void gr_light_init() {
if (gr_screen.mode == GR_STUB) {
return;
}
gr_calculate_ambient_factor();
// allocate memory for enabled lights
@@ -315,9 +295,6 @@ void gr_light_init() {
}
void gr_set_lighting() {
if (gr_screen.mode == GR_STUB) {
return;
}
//Valathil: Sort lights by priority
extern bool Deferred_lighting;
@@ -349,10 +326,6 @@ void gr_set_lighting() {
}
void gr_set_ambient_light(int red, int green, int blue) {
if (gr_screen.mode == GR_STUB) {
return;
}
gr_light_ambient[0] = i2fl(red) / 255.0f;
gr_light_ambient[1] = i2fl(green) / 255.0f;
gr_light_ambient[2] = i2fl(blue) / 255.0f;
@@ -362,10 +335,6 @@ void gr_set_ambient_light(int red, int green, int blue) {
}
void gr_lighting_fill_uniforms(void* data_out, size_t buffer_size) {
if (gr_screen.mode == GR_STUB) {
return;
}
Assertion(sizeof(gr_light_uniforms) <= buffer_size, "Insufficient buffer supplied.");
memcpy(reinterpret_cast<graphics::model_light*>(data_out), gr_light_uniforms, sizeof(gr_light_uniforms));
-27
View File
@@ -53,26 +53,6 @@ void material_set_unlit(material* mat_info, int texture, float alpha, bool blend
}
}
void material_set_unlit_opaque(material* mat_info, int texture, bool depth_testing)
{
mat_info->set_texture_map(TM_BASE_TYPE, texture);
gr_alpha_blend blend_mode = ALPHA_BLEND_NONE;
gr_zbuffer_type depth_mode = material_determine_depth_mode(depth_testing, false);
mat_info->set_blend_mode(blend_mode);
mat_info->set_depth_mode(depth_mode);
mat_info->set_cull_mode(false);
mat_info->set_color(1.0f, 1.0f, 1.0f, 1.0f);
if ( texture >= 0 && bm_has_alpha_channel(texture) ) {
mat_info->set_texture_type(material::TEX_TYPE_XPARENT);
}
}
void material_set_unlit_emissive(material* mat_info, int texture, float alpha, float color_scale)
{
material_set_unlit(mat_info, texture, alpha, true, true);
@@ -181,13 +161,6 @@ void material_set_batched_bitmap(batched_bitmap_material* mat_info, int base_tex
mat_info->set_color_scale(color_scale);
}
void material_set_batched_opaque_bitmap(batched_bitmap_material* mat_info, int base_tex, float color_scale) {
material_set_unlit_opaque(mat_info, base_tex, true);
mat_info->set_color_scale(color_scale);
}
void material_set_nanovg(nanovg_material* mat_info, int base_tex) {
material_set_unlit(mat_info, base_tex, 1.0f, true, false);
-1
View File
@@ -373,7 +373,6 @@ void material_set_unlit_volume(particle_material* mat_info, int texture, bool po
void material_set_distortion(distortion_material *mat_info, int texture, bool thruster);
void material_set_movie(movie_material *mat_info, int y_bm, int u_bm, int v_bm);
void material_set_batched_bitmap(batched_bitmap_material* mat_info, int base_tex, float alpha, float color_scale);
void material_set_batched_opaque_bitmap(batched_bitmap_material* mat_info, int base_tex, float color_scale);
void material_set_nanovg(nanovg_material* mat_info, int base_tex);
void material_set_decal(material* mat_info, int diffuse_tex, int glow_tex, int normal_tex);
+1 -54
View File
@@ -7,7 +7,7 @@
#endif
#include "gropengl.h"
#include "ShaderProgram.h"
#include "gropenglbmpman.h"
#include "gropengldeferred.h"
#include "gropengldraw.h"
@@ -290,58 +290,6 @@ void gr_opengl_print_screen(const char *filename)
}
}
void gr_opengl_dump_envmap(const char* filename)
{
char tmp[MAX_PATH_LEN];
GLubyte* pixels = nullptr;
_mkdir(os_get_config_path("envmaps").c_str());
auto width = 512; // These are the hardcoded envmap dimensions
auto height = 512; // in future envmap resolution should be dynamic, or at least extracted from envmap_render_target
auto sphere_width = 4 * width;
auto sphere_height = 2 * height;
auto env_tex = bm_get_gr_info<tcache_slot_opengl>(gr_screen.envmap_render_target);
glBindTexture(env_tex->texture_target, env_tex->texture_id);
// Save the previous render target so we can reset it once we are done here
auto previous_target = gr_screen.rendering_to_texture;
// New render target
int sm_flags = (BMP_FLAG_RENDER_TARGET_STATIC);
int spheremap_render_target = bm_make_render_target(sphere_width, sphere_height, sm_flags);
bm_set_render_target(spheremap_render_target);
// Set up cubemap to spherical shader and draw
int env_shader = gr_opengl_maybe_create_shader(SDR_TYPE_ENVMAP_SPHERE_WARP, 0);
opengl_shader_set_current(env_shader);
GL_state.Texture.Enable(0, GL_TEXTURE_CUBE_MAP, env_tex->texture_id);
Current_shader->program->Uniforms.setTextureUniform("envmap", 0);
gr_clear();
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_v_scale);
bm_set_render_target(previous_target);
// load texture info and write to file
auto sphere_tex = bm_get_gr_info<tcache_slot_opengl>(spheremap_render_target);
glBindTexture(sphere_tex->texture_target, sphere_tex->texture_id);
pixels = (GLubyte*)vm_malloc(sphere_width * sphere_height * 4, memory::quiet_alloc);
glGetTexImage(sphere_tex->texture_target, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
snprintf(tmp, MAX_PATH_LEN - 1, "envmaps/%s.png", filename);
if (!png_write_bitmap(os_get_config_path(tmp).c_str(), 4 * width, 2 * height, true, pixels)) {
ReleaseWarning(LOCATION, "Failed to write envmap to \"%s\".", os_get_config_path(tmp).c_str());
}
// cleanup
if (!bm_release(spheremap_render_target, 1)) {
Warning(LOCATION, "Unable to release environment map render target.");
}
if (pixels != nullptr) {
vm_free(pixels);
}
}
void gr_opengl_shutdown()
{
opengl_tcache_shutdown();
@@ -859,7 +807,6 @@ void opengl_setup_function_pointers()
// gr_screen.gf_rect = gr_opengl_rect;
gr_screen.gf_print_screen = gr_opengl_print_screen;
gr_screen.gf_dump_envmap = gr_opengl_dump_envmap;
gr_screen.gf_zbuffer_get = gr_opengl_zbuffer_get;
gr_screen.gf_zbuffer_set = gr_opengl_zbuffer_set;
+9 -10
View File
@@ -211,14 +211,13 @@ void gr_opengl_deferred_lighting_finish()
case Light_Type::Point:
vm_vec_scale(&light_data->specLightColor, static_point_factor);
light_data->lightRadius = MAX(l.rada, l.radb);
//A small padding factor is added to guard against potentially clipping the edges of the light with facets of the volume mesh.
light_data->scale.xyz.x = MAX(l.rada, l.radb) * 1.05f;
light_data->scale.xyz.y = MAX(l.rada, l.radb) * 1.05f;
light_data->scale.xyz.z = MAX(l.rada, l.radb) * 1.05f;
light_data->lightRadius = MAX(l.rada, l.radb) * 1.25f;
light_data->scale.xyz.x = MAX(l.rada, l.radb) * 1.28f;
light_data->scale.xyz.y = MAX(l.rada, l.radb) * 1.28f;
light_data->scale.xyz.z = MAX(l.rada, l.radb) * 1.28f;
break;
case Light_Type::Tube: {
light_data->lightRadius = l.radb;
light_data->lightRadius = l.radb * 1.5f;
light_data->lightType = LT_TUBE;
vec3d a;
@@ -229,9 +228,8 @@ void gr_opengl_deferred_lighting_finish()
//origin we must extend it here. Later the position will be adjusted as well.
length += light_data->lightRadius * 2.0f;
//A small padding factor is added to guard against potentially clipping the edges of the light with facets of the volume mesh.
light_data->scale.xyz.x = l.radb * 1.05f;
light_data->scale.xyz.y = l.radb * 1.05f;
light_data->scale.xyz.x = l.radb * 1.53f;
light_data->scale.xyz.y = l.radb * 1.53f;
light_data->scale.xyz.z = length;
vm_vec_scale(&light_data->specLightColor, static_tube_factor);
@@ -278,7 +276,8 @@ void gr_opengl_deferred_lighting_finish()
//to allow smooth fall-off from all angles. Since the light volume starts at the mesh
//origin we must extend it, which has been done above, and then move it backwards one radius.
vm_vec_normalize(&dir);
vm_vec_scale_sub(&newPos, &l.vec2, &dir, l.radb);
//1.5 multiplier matches scaling used earlier to scale light radius for all tubes
vm_vec_scale_sub(&newPos, &l.vec2, &dir, l.radb * 1.5f);
gr_opengl_draw_deferred_light_cylinder(&newPos, &orient);
++element_index;
break;
+82 -82
View File
@@ -1,82 +1,82 @@
#include "graphics/opengl/gropenglquery.h"
#include "graphics/opengl/gropengl.h"
namespace {
struct query_object_slot {
bool used = false;
GLuint name = 0;
};
SCP_vector<query_object_slot> query_objects;
int get_new_query_slot() {
auto end = query_objects.end();
for (auto iter = query_objects.begin(); iter != end; ++iter) {
if (!iter->used) {
return (int) std::distance(query_objects.begin(), iter);
}
}
query_objects.emplace_back();
return (int) (query_objects.size() - 1);
}
query_object_slot& get_query_slot(int handle) {
Assertion(handle >= 0 && handle < (int)query_objects.size(), "Query object index %d is invalid!", handle);
return query_objects[handle];
}
}
int gr_opengl_create_query_object() {
auto idx = get_new_query_slot();
auto& slot = query_objects[idx];
slot.used = true;
glGenQueries(1, &slot.name);
return idx;
}
void gr_opengl_query_value(int obj, QueryType type) {
auto& slot = get_query_slot(obj);
switch(type) {
case QueryType::Timestamp:
Assertion(GLAD_GL_ARB_timer_query, "Timestamp queries are not available! Availability must be checked before calling this function!");
glQueryCounter(slot.name, GL_TIMESTAMP);
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
}
bool gr_opengl_query_value_available(int obj) {
auto& slot = get_query_slot(obj);
GLuint available;
glGetQueryObjectuiv(slot.name, GL_QUERY_RESULT_AVAILABLE, &available);
return available == GL_TRUE;
}
std::uint64_t gr_opengl_get_query_value(int obj) {
auto& slot = get_query_slot(obj);
GLuint64 available;
glGetQueryObjectui64v(slot.name, GL_QUERY_RESULT, &available);
return available;
}
void gr_opengl_delete_query_object(int obj) {
auto& slot = get_query_slot(obj);
glDeleteQueries(1, &slot.name);
slot.name = 0;
slot.used = false;
}
#include "graphics/opengl/gropenglquery.h"
#include "graphics/opengl/gropengl.h"
namespace {
struct query_object_slot {
bool used = false;
GLuint name = 0;
};
SCP_vector<query_object_slot> query_objects;
int get_new_query_slot() {
auto end = query_objects.end();
for (auto iter = query_objects.begin(); iter != end; ++iter) {
if (!iter->used) {
return (int) std::distance(query_objects.begin(), iter);
}
}
query_objects.emplace_back();
return (int) (query_objects.size() - 1);
}
query_object_slot& get_query_slot(int handle) {
Assertion(handle >= 0 && handle < (int)query_objects.size(), "Query object index %d is invalid!", handle);
return query_objects[handle];
}
}
int gr_opengl_create_query_object() {
auto idx = get_new_query_slot();
auto& slot = query_objects[idx];
slot.used = true;
glGenQueries(1, &slot.name);
return idx;
}
void gr_opengl_query_value(int obj, QueryType type) {
auto& slot = get_query_slot(obj);
switch(type) {
case QueryType::Timestamp:
Assertion(GLAD_GL_ARB_timer_query, "Timestamp queries are not available! Availability must be checked before calling this function!");
glQueryCounter(slot.name, GL_TIMESTAMP);
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
}
bool gr_opengl_query_value_available(int obj) {
auto& slot = get_query_slot(obj);
GLuint available;
glGetQueryObjectuiv(slot.name, GL_QUERY_RESULT_AVAILABLE, &available);
return available == GL_TRUE;
}
std::uint64_t gr_opengl_get_query_value(int obj) {
auto& slot = get_query_slot(obj);
GLuint64 available;
glGetQueryObjectui64v(slot.name, GL_QUERY_RESULT, &available);
return available;
}
void gr_opengl_delete_query_object(int obj) {
auto& slot = get_query_slot(obj);
glDeleteQueries(1, &slot.name);
slot.name = 0;
slot.used = false;
}
+9 -9
View File
@@ -1,9 +1,9 @@
#ifndef _GROPENGLQUERY_H
#define _GROPENGLQUERY_H
#pragma once
#include "graphics/2d.h"
#ifndef _GROPENGLQUERY_H
#define _GROPENGLQUERY_H
#pragma once
#include "graphics/2d.h"
int gr_opengl_create_query_object();
@@ -13,6 +13,6 @@ bool gr_opengl_query_value_available(int obj);
std::uint64_t gr_opengl_get_query_value(int obj);
void gr_opengl_delete_query_object(int obj);
#endif // _GROPENGLQUERY_H
void gr_opengl_delete_query_object(int obj);
#endif // _GROPENGLQUERY_H
-3
View File
@@ -156,9 +156,6 @@ static opengl_shader_type_t GL_shader_types[] = {
{ SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING, "smaa-neighbour-v.sdr", "smaa-neighbour-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "SMAA Neighborhood Blending", false },
{ SDR_TYPE_ENVMAP_SPHERE_WARP, "post-v.sdr", "envmap-sphere-warp-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "Environment Map Generation", false },
};
// clang-format on
-17
View File
@@ -5,7 +5,6 @@
#include "options/Option.h"
#include "parse/parselo.h"
#include "ship/ship.h"
#include "starfield/supernova.h"
namespace graphics {
namespace {
@@ -209,14 +208,6 @@ void PostProcessingManager::setBloomShadersOk(bool ok)
bool gr_lightshafts_enabled()
{
if (gr_screen.mode == GR_STUB) {
return false;
}
// supernova glare should disable lightshafts
if (supernova_stage() >= SUPERNOVA_STAGE::CLOSE) {
return false;
}
if (!graphics::Post_processing_manager->getLightshaftParams().on) {
return false;
@@ -231,10 +222,6 @@ bool gr_lightshafts_enabled()
int gr_bloom_intensity()
{
if (gr_screen.mode == GR_STUB) {
return 0;
}
if (graphics::Post_processing_manager == nullptr || !graphics::Post_processing_manager->bloomShadersOk()) {
return 0;
}
@@ -248,10 +235,6 @@ int gr_bloom_intensity()
void gr_set_bloom_intensity(int intensity)
{
if (gr_screen.mode == GR_STUB) {
return;
}
if (Using_in_game_options) {
graphics::Post_processing_bloom_intensity = intensity;
} else {
-96
View File
@@ -46,10 +46,6 @@ static void gr_flash_internal(int r, int g, int b, int a, bool alpha_flash)
}
void gr_flash(int r, int g, int b) {
if (gr_screen.mode == GR_STUB) {
return;
}
if (!(r || g || b)) {
return;
}
@@ -58,10 +54,6 @@ void gr_flash(int r, int g, int b) {
}
void gr_flash_alpha(int r, int g, int b, int a) {
if (gr_screen.mode == GR_STUB) {
return;
}
if (!(r || g || b || a)) {
return;
}
@@ -160,10 +152,6 @@ static void bitmap_ex_internal(int x,
}
void gr_aabitmap(int x, int y, int resize_mode, bool mirror) {
if (gr_screen.mode == GR_STUB) {
return;
}
GR_DEBUG_SCOPE("Draw AA-bitmap");
int w, h, do_resize;
@@ -234,10 +222,6 @@ void gr_aabitmap(int x, int y, int resize_mode, bool mirror) {
&gr_screen.current_color);
}
void gr_aabitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode, bool mirror) {
if (gr_screen.mode == GR_STUB) {
return;
}
int reclip;
#ifndef NDEBUG
@@ -365,10 +349,6 @@ void gr_aabitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode,
}
//these are penguins bitmap functions
void gr_bitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
int reclip;
#ifndef NDEBUG
int count = 0;
@@ -768,10 +748,6 @@ void endDrawing(graphics::paths::PathRenderer* path) {
}
void gr_string(float sx, float sy, const char* s, int resize_mode, int in_length) {
if (gr_screen.mode == GR_STUB) {
return;
}
GR_DEBUG_SCOPE("Render string");
using namespace font;
@@ -941,18 +917,10 @@ static void gr_line(float x1, float y1, float x2, float y2, int resize_mode) {
}
void gr_line(int x1, int y1, int x2, int y2, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
gr_line(i2fl(x1), i2fl(y1), i2fl(x2), i2fl(y2), resize_mode);
}
void gr_aaline(vertex* v1, vertex* v2) {
if (gr_screen.mode == GR_STUB) {
return;
}
float x1 = v1->screen.xyw.x;
float y1 = v1->screen.xyw.y;
float x2 = v2->screen.xyw.x;
@@ -963,10 +931,6 @@ void gr_aaline(vertex* v1, vertex* v2) {
}
void gr_gradient(int x1, int y1, int x2, int y2, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
if (!gr_screen.current_color.is_alphacolor) {
gr_line(x1, y1, x2, y2, resize_mode);
return;
@@ -989,18 +953,10 @@ void gr_gradient(int x1, int y1, int x2, int y2, int resize_mode) {
endDrawing(path);
}
void gr_pixel(int x, int y, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
gr_line(x, y, x, y, resize_mode);
}
void gr_circle(int xc, int yc, int d, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
auto path = beginDrawing(resize_mode);
path->circle(i2fl(xc), i2fl(yc), d / 2.0f);
@@ -1010,10 +966,6 @@ void gr_circle(int xc, int yc, int d, int resize_mode) {
endDrawing(path);
}
void gr_unfilled_circle(int xc, int yc, int d, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
auto path = beginDrawing(resize_mode);
path->circle(i2fl(xc), i2fl(yc), d / 2.0f);
@@ -1023,10 +975,6 @@ void gr_unfilled_circle(int xc, int yc, int d, int resize_mode) {
endDrawing(path);
}
void gr_arc(int xc, int yc, float r, float angle_start, float angle_end, bool fill, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
// Ensure that angle_start < angle_end
if (angle_end < angle_start) {
float temp = angle_start;
@@ -1053,10 +1001,6 @@ void gr_arc(int xc, int yc, float r, float angle_start, float angle_end, bool fi
endDrawing(path);
}
void gr_curve(int xc, int yc, int r, int direction, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
using namespace graphics::paths;
auto path = beginDrawing(resize_mode);
@@ -1104,10 +1048,6 @@ void gr_curve(int xc, int yc, int r, int direction, int resize_mode) {
}
void gr_rect(int x, int y, int w, int h, int resize_mode, float angle) {
if (gr_screen.mode == GR_STUB) {
return;
}
auto path = beginDrawing(resize_mode);
if (angle != 0) {
// If we don't do this translation before and after rotating, the rotation will use 0,0 as the pivot, flinging the rectangle far away.
@@ -1125,10 +1065,6 @@ void gr_rect(int x, int y, int w, int h, int resize_mode, float angle) {
}
void gr_shade(int x, int y, int w, int h, int resize_mode) {
if (gr_screen.mode == GR_STUB) {
return;
}
auto r = (int) gr_screen.current_shader.r;
auto g = (int) gr_screen.current_shader.g;
auto b = (int) gr_screen.current_shader.b;
@@ -1147,10 +1083,6 @@ void gr_shade(int x, int y, int w, int h, int resize_mode) {
}
void gr_2d_start_buffer() {
if (gr_screen.mode == GR_STUB) {
return;
}
Assertion(!buffering_nanovg, "Tried to enable 2D buffering but it was already enabled!");
buffering_nanovg = true;
@@ -1160,10 +1092,6 @@ void gr_2d_start_buffer() {
}
void gr_2d_stop_buffer() {
if (gr_screen.mode == GR_STUB) {
return;
}
Assertion(buffering_nanovg, "Tried to stop 2D buffering but it was not enabled!");
buffering_nanovg = false;
@@ -1178,10 +1106,6 @@ static size_t immediate_buffer_size = 0;
static const int IMMEDIATE_BUFFER_RESIZE_BLOCK_SIZE = 2048;
size_t gr_add_to_immediate_buffer(size_t size, void* data) {
if (gr_screen.mode == GR_STUB) {
return 0;
}
GR_DEBUG_SCOPE("Add data to immediate buffer");
if (!gr_immediate_buffer_handle.isValid()) {
@@ -1208,10 +1132,6 @@ size_t gr_add_to_immediate_buffer(size_t size, void* data) {
return old_offset;
}
void gr_reset_immediate_buffer() {
if (gr_screen.mode == GR_STUB) {
return;
}
if (!gr_immediate_buffer_handle.isValid()) {
// we haven't used the immediate buffer yet
return;
@@ -1230,10 +1150,6 @@ void gr_render_primitives_immediate(material* material_info,
int n_verts,
void* data,
size_t size) {
if (gr_screen.mode == GR_STUB) {
return;
}
auto offset = gr_add_to_immediate_buffer(size, data);
gr_render_primitives(material_info, prim_type, layout, 0, n_verts, gr_immediate_buffer_handle, offset);
@@ -1246,10 +1162,6 @@ void gr_render_primitives_2d_immediate(material* material_info,
void* data,
size_t size)
{
if (gr_screen.mode == GR_STUB) {
return;
}
gr_set_2d_matrix();
gr_render_primitives_immediate(material_info, prim_type, layout, n_verts, data, size);
@@ -1403,10 +1315,6 @@ static void draw_bitmap_list(bitmap_rect_list* list, int n_bm, int resize_mode,
void gr_bitmap_list(bitmap_rect_list* list, int n_bm, int resize_mode, float angle)
{
if (gr_screen.mode == GR_STUB) {
return;
}
material mat_params;
material_set_interface(&mat_params,
gr_screen.current_bitmap,
@@ -1418,10 +1326,6 @@ void gr_bitmap_list(bitmap_rect_list* list, int n_bm, int resize_mode, float ang
void gr_aabitmap_list(bitmap_rect_list* list, int n_bm, int resize_mode, float angle)
{
if (gr_screen.mode == GR_STUB) {
return;
}
material render_mat;
render_mat.set_blend_mode(ALPHA_BLEND_ALPHA_BLEND_ALPHA);
render_mat.set_depth_mode(ZBUFFER_TYPE_NONE);
-4
View File
@@ -418,10 +418,6 @@ void shadows_end_render()
void shadows_render_all(float fov, matrix *eye_orient, vec3d *eye_pos)
{
if (gr_screen.mode == GR_STUB) {
return;
}
GR_DEBUG_SCOPE("Render shadows");
TRACE_SCOPE(tracing::BuildShadowMap);
+3 -3
View File
@@ -41,7 +41,7 @@ namespace font
int w, h;
w = 0;
h = text == nullptr ? 0 : fl2i(this->getHeight());
h = 0;
longest_width = 0;
// Maintain old behavior where textLen was an int
@@ -49,8 +49,8 @@ namespace font
bool checkLength = textLen >= 0;
if (text != nullptr && textLen != 0)
{
if (text != nullptr && textLen != 0) {
h += fl2i(this->getHeight());
while (*text)
{
// Process one or more
+2 -1
View File
@@ -688,7 +688,8 @@ void gr_get_string_size(int *w1, int *h1, const char *text, int len)
float w = 0.0f;
float h = 0.0f;
FontManager::getCurrentFont()->getStringSize(text, static_cast<size_t>(len), -1, &w, &h);
if (len != 0)
FontManager::getCurrentFont()->getStringSize(text, static_cast<size_t>(len), -1, &w, &h);
if (w1)
{
+33 -72
View File
@@ -57,7 +57,6 @@
#include "weapon/emp.h"
#include "weapon/weapon.h"
// This contains not only the retail HUD gauges but also any custom HUD gauges that are not specific to a ship.
SCP_vector<std::unique_ptr<HudGauge>> default_hud_gauges;
// new values for HUD alpha
@@ -370,13 +369,12 @@ void HudGauge::getPosition(int *x, int *y)
*y = position[1];
}
void HudGauge::initBaseResolution(int w, int h, float aq)
void HudGauge::initBaseResolution(int w, int h)
{
Assert(w >= 640 && h >= 480);
base_w = w;
base_h = h;
aspect_quotient = aq;
}
void HudGauge::initSlew(bool slew)
@@ -391,43 +389,6 @@ void HudGauge::initFont(int input_font_num)
}
}
int HudGauge::getFont()
{
return font_num;
}
void HudGauge::initOriginAndOffset(float originX, float originY, int offsetX, int offsetY)
{
tabled_origin[0] = originX;
tabled_origin[1] = originY;
tabled_offset[0] = offsetX;
tabled_offset[1] = offsetY;
}
void HudGauge::getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY)
{
*originX = tabled_origin[0];
*originY = tabled_origin[1];
*offsetX = tabled_offset[0];
*offsetY = tabled_offset[1];
}
void HudGauge::initCoords(bool use_coords, int coordsX, int coordsY)
{
tabled_use_coords = use_coords;
tabled_coords[0] = coordsX;
tabled_coords[1] = coordsY;
}
void HudGauge::getCoords(bool *use_coords, int *coordsX, int *coordsY)
{
*use_coords = tabled_use_coords;
*coordsX = tabled_coords[0];
*coordsY = tabled_coords[1];
}
const char* HudGauge::getCustomGaugeName()
{
return custom_name;
@@ -563,11 +524,6 @@ int HudGauge::getBaseHeight()
return base_h;
}
float HudGauge::getAspectQuotient()
{
return aspect_quotient;
}
int HudGauge::getConfigType()
{
//return gauge_type;
@@ -1421,6 +1377,7 @@ void hud_maybe_popup_weapons_gauge()
void hud_update_frame(float /*frametime*/)
{
object *targetp;
vec3d target_pos;
int can_target;
update_throttle_sound();
@@ -1506,6 +1463,8 @@ void hud_update_frame(float /*frametime*/)
hud_update_closest_turret();
}
hud_target_change_check();
// check to see if we are in messaging mode. If so, send the key to the code
// to deal with the message. hud_sqaudmsg_do_frame will return 0 if the key
// wasn't used in messaging mode, otherwise 1. In the event the key was used,
@@ -1515,15 +1474,15 @@ void hud_update_frame(float /*frametime*/)
}
if (Player_ai->target_objnum == -1) {
Player->target_is_dying = -1; // according to comments elsewhere in the code, set to -1 when no target
hud_target_change_check();
if (Target_static_looping.isValid()) {
snd_stop(Target_static_looping);
}
return;
}
targetp = &Objects[Player_ai->target_objnum];
if ( Player_ai->targeted_subsys != NULL ) {
vec3d target_pos;
get_subsystem_world_pos(targetp, Player_ai->targeted_subsys, &target_pos);
// get new distance of current target
@@ -1550,12 +1509,11 @@ void hud_update_frame(float /*frametime*/)
}
}
} else {
target_pos = targetp->pos;
Player_ai->current_target_distance = hud_find_target_distance(targetp,Player_obj);
}
// moved past the if() block so that the target tracker has the current frame's target distance
hud_target_change_check();
bool stop_targeting_this_thing = false;
// check to see if the target is still alive
@@ -1665,7 +1623,7 @@ void hud_render_preprocess(float frametime)
Player->subsys_in_view = -1;
hud_target_clear_display_list();
if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_stage() >= SUPERNOVA_STAGE::HIT) ) {
if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() >= 3) ) {
return;
}
@@ -1776,16 +1734,17 @@ void HudGaugeMissionTime::render(float /*frametime*/)
}
/**
* @brief Show supernova warning if there's a supernova coming
* @brief Show supernova warning it there's a supernova coming
*/
void hud_maybe_display_supernova()
{
if (!supernova_active()) {
float time_left;
time_left = supernova_time_left();
if(time_left < 0.0f){
return;
}
auto time_left = supernova_hud_time_left();
gr_set_color_fast(&Color_bright_red);
if (Lcl_pl) {
gr_printf(Supernova_coords[gr_screen.res][0], Supernova_coords[gr_screen.res][1], "Wybuch supernowej: %.2f s", time_left);
@@ -1835,7 +1794,7 @@ void hud_render_gauges(int cockpit_display_num)
return;
}
} else {
if( supernova_stage() >= SUPERNOVA_STAGE::HIT) {
if( supernova_active() >= 3 ) {
return;
}
}
@@ -1949,8 +1908,10 @@ void update_throttle_sound()
if ( object_get_gliding(Player_obj) ) { // Backslash
percent_throttle = Player_obj->phys_info.forward_thrust;
} else {
} else if ( Ships[Player_obj->instance].current_max_speed == 0 ) {
percent_throttle = Player_obj->phys_info.fspeed / Ship_info[Ships[Player_obj->instance].ship_info_index].max_speed;
} else {
percent_throttle = Player_obj->phys_info.fspeed / Ships[Player_obj->instance].current_max_speed;
}
if (percent_throttle != last_percent_throttle || !Player_engine_snd_loop.isValid()) {
@@ -3908,6 +3869,11 @@ HudGauge* hud_get_custom_gauge(const char* name, bool check_all_gauges)
}
}
}
for (auto &gauge : default_hud_gauges) {
if (!stricmp(name, gauge->getCustomGaugeName())) {
return gauge.get();
}
}
}
// if the player is flying a ship with a custom set of gauges, check those
else if (player_sip && !player_sip->hud_gauges.empty()) {
@@ -3918,19 +3884,12 @@ HudGauge* hud_get_custom_gauge(const char* name, bool check_all_gauges)
}
}
// fall back to checking the custom gauges in the default list
for (auto &gauge : default_hud_gauges) {
if (gauge->isCustom() && !stricmp(name, gauge->getCustomGaugeName())) {
return gauge.get();
}
}
return nullptr;
}
int hud_get_default_gauge_index(const char *name)
{
int config_type = -1, object_type = -1;
int config_type = -1;
// default gauges had two different lists
for (int i = 0; i < NUM_HUD_GAUGES; i++) {
@@ -3943,15 +3902,15 @@ int hud_get_default_gauge_index(const char *name)
if (config_type < 0) {
for (int i = 0; i < Num_hud_gauge_types; i++) {
if (!stricmp(name, Hud_gauge_types[i].name)) {
object_type = Hud_gauge_types[i].def;
config_type = Hud_gauge_types[i].def;
break;
}
}
}
if (config_type >= 0 || object_type >= 0) {
if (config_type >= 0) {
for (int i = 0; i < (int)default_hud_gauges.size(); i++) {
if (default_hud_gauges[i]->getConfigType() == config_type || default_hud_gauges[i]->getObjectType() == object_type) {
if (default_hud_gauges[i]->getConfigType() == config_type) {
return i;
}
}
@@ -4067,12 +4026,14 @@ HudGauge(HUD_OBJECT_SUPERNOVA, HUD_DIRECTIVES_VIEW, false, false, 0, 255, 255, 2
void HudGaugeSupernova::render(float /*frametime*/)
{
if (!supernova_active()) {
float time_left;
// if there's a supernova coming
time_left = supernova_time_left();
if(time_left < 0.0f){
return;
}
auto time_left = supernova_hud_time_left();
gr_set_color_fast(&Color_bright_red);
if (Lcl_pl) {
renderPrintf(position[0], position[1], "Wybuch supernowej: %.2f s", time_left);
+2 -17
View File
@@ -220,13 +220,6 @@ protected:
int font_num;
// useful information to keep around for scripts
float tabled_origin[2];
int tabled_offset[2];
bool tabled_use_coords;
int tabled_coords[2];
float aspect_quotient;
bool lock_color;
bool sexp_lock_color;
bool reticle_follow;
@@ -269,29 +262,21 @@ public:
virtual ~HudGauge();
void initPosition(int x, int y);
void initBaseResolution(int w, int h, float aq);
void initFont(int input_font_num);
void initOriginAndOffset(float originX, float originY, int offsetX, int offsetY);
void initCoords(bool use_coords, int coordsX, int coordsY);
void initBaseResolution(int w, int h);
void initSlew(bool slew);
void initFont(int input_font_num);
void initCockpitTarget(const char* display_name, int _target_x, int _target_y, int _target_w, int _target_h, int _canvas_w, int _canvas_h);
void initRenderStatus(bool render);
bool isCustom();
int getBaseWidth();
int getBaseHeight();
float getAspectQuotient();
int getConfigType();
int getObjectType();
void getPosition(int *x, int *y);
bool isOffbyDefault();
bool isActive();
int getFont();
void getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY);
void getCoords(bool* use_coords, int* coordsX, int* coordsY);
void updateColor(int r, int g, int b, int a = 255);
const color& getColor();
+4 -15
View File
@@ -57,9 +57,9 @@ void draw_brackets_square(graphics::line_draw_list* draw_list, int x1, int y1, i
}
width = x2 - x1;
Assert( width > 0);
height = y2 - y1;
if (width < 1 || height < 1)
return;
Assert( height > 0);
// make the brackets extend 25% of the way along the width or height
int bracket_width = width/4;
@@ -395,12 +395,7 @@ void HudGaugeBrackets::renderObjectBrackets(object *targetp, color *clr, int w_c
int bound_rc;
SCP_list<CJumpNode>::iterator jnp;
bool not_player_target = (Player_ai->target_objnum < 0 || targetp != &Objects[Player_ai->target_objnum]);
// target_is_dying is set to zero when the target is not dying, -1 when no target. Only 1, aka "TRUE", is invalid.
if ( not_player_target || Player->target_is_dying <= 0) {
if ( Player->target_is_dying <= 0 || (Player_ai->target_objnum >= 0 && targetp != &Objects[Player_ai->target_objnum])) {
int modelnum;
switch ( targetp->type ) {
@@ -480,13 +475,7 @@ void HudGaugeBrackets::renderObjectBrackets(object *targetp, color *clr, int w_c
int target_objnum = -1;
if(flags & TARGET_DISPLAY_DIST) {
// since we can have either the target, or rogue asteroids bracketed,
// check which case we are in, and then do the correct distance.
if (not_player_target) {
distance = hud_find_target_distance(targetp, &Player_obj->pos);
} else {
distance = Player_ai->current_target_distance;
}
distance = hud_find_target_distance(targetp, Player_obj);
}
if(flags & TARGET_DISPLAY_DOTS) {
-3
View File
@@ -16,10 +16,7 @@
#include "graphics/line_draw_list.h"
void hud_init_brackets();
// requires that x2 > x1 and y2 > y1
void draw_brackets_square(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2, int resize_mode = GR_RESIZE_FULL);
void draw_brackets_square_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2, int thick=0);
void draw_brackets_diamond_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2);
+6 -12
View File
@@ -1613,7 +1613,6 @@ void hud_config_color_load(const char *name)
int idx;
char str[1024];
char *fname;
ubyte r, g, b, a;
fname = cf_add_ext(name, ".hcf");
@@ -1631,18 +1630,13 @@ void hud_config_color_load(const char *name)
while (optional_string("+Gauge:")) {
stuff_string(str, F_NAME, sizeof(str));
required_string("+RGBA:");
stuff_ubyte(&r);
stuff_ubyte(&g);
stuff_ubyte(&b);
stuff_ubyte(&a);
for (idx = 0; idx < NUM_HUD_GAUGES; idx++) {
if (!stricmp(str, HC_gauge_descriptions(idx))) {
HUD_config.clr[idx].red = r;
HUD_config.clr[idx].green = g;
HUD_config.clr[idx].blue = b;
HUD_config.clr[idx].alpha = a;
if (!stricmp(str, Hud_Gauge_Names[idx])) {
required_string("+RGBA:");
stuff_ubyte(&HUD_config.clr[idx].red);
stuff_ubyte(&HUD_config.clr[idx].green);
stuff_ubyte(&HUD_config.clr[idx].blue);
stuff_ubyte(&HUD_config.clr[idx].alpha);
break;
}
}
+1 -2
View File
@@ -194,8 +194,7 @@ void HudGaugeLock::renderOld(float frametime)
return;
}
// 1 is the only value for which your target is actually dying
if (Player->target_is_dying == 1) {
if (Player->target_is_dying) {
return;
}
+2 -4
View File
@@ -603,10 +603,8 @@ void hud_sourced_print(int source, const char *msg)
HUD_msg_buffer.push_back(new_msg);
// Invoke the scripting hook
if (OnHudMessageReceivedHook->isActive()) {
OnHudMessageReceivedHook->run(scripting::hook_param_list(scripting::hook_param("Text", 's', msg),
scripting::hook_param("SourceType", 'i', source)));
}
OnHudMessageReceivedHook->run(scripting::hook_param_list(scripting::hook_param("Text", 's', msg),
scripting::hook_param("SourceType", 'i', source)));
}
int hud_query_scrollback_size()
+4 -2
View File
@@ -40,8 +40,10 @@ void hud_draw_navigation()
unsigned int alpha = HUD_COLOR_ALPHA_MAX * 16;
auto rgb = (Navs[CurrentNav].flags & NP_VISITED) ? Navs[CurrentNav].visited_color : Navs[CurrentNav].normal_color;
gr_init_alphacolor( &NavColor, rgb[0], rgb[1], rgb[2], alpha );
if (Navs[CurrentNav].flags & NP_VISITED)
gr_init_alphacolor( &NavColor, 0xFF, 0xFF, 0x00, alpha);
else
gr_init_alphacolor( &NavColor, 0x80, 0x80, 0xff, alpha);
g3_rotate_vertex(&target_point, target_pos);
g3_project_vertex(&target_point);
+15 -26
View File
@@ -1168,7 +1168,7 @@ void check_color(int *colorp)
}
}
void adjust_base_res(int *base_res, const int *force_scaling_above_res, float *aspect_quotient, bool scaling = true)
void adjust_base_res(int *base_res, int *force_scaling_above_res, bool scaling = true)
{
// Don't scale gauge if:
// no scaling is set and current res is between base res and "force scaling above res"
@@ -1178,7 +1178,6 @@ void adjust_base_res(int *base_res, const int *force_scaling_above_res, float *a
gr_screen.center_w <= force_scaling_above_res[0] || gr_screen.center_h <= force_scaling_above_res[1])) ||
(gr_screen.center_w >= base_res[0] && gr_screen.center_h == base_res[1]) ||
(gr_screen.center_w == base_res[0] && gr_screen.center_h >= base_res[1])) {
*aspect_quotient = 1.0f;
base_res[0] = gr_screen.center_w;
base_res[1] = gr_screen.center_h;
return;
@@ -1190,11 +1189,11 @@ void adjust_base_res(int *base_res, const int *force_scaling_above_res, float *a
base_res[1] = force_scaling_above_res[1];
}
*aspect_quotient = ((float)gr_screen.center_w / (float)gr_screen.center_h) / ((float)base_res[0] / (float)base_res[1]);
if (*aspect_quotient >= 1.0f) {
base_res[0] = (int)(base_res[0] * *aspect_quotient);
float aspect_quotient = ((float)gr_screen.center_w / (float)gr_screen.center_h) / ((float)base_res[0] / (float)base_res[1]);
if (aspect_quotient >= 1.0) {
base_res[0] = (int)(base_res[0] * aspect_quotient);
} else {
base_res[1] = (int)(base_res[1] / *aspect_quotient);
base_res[1] = (int)(base_res[1] / aspect_quotient);
}
}
@@ -1238,7 +1237,7 @@ std::unique_ptr<T> gauge_load_common(gauge_settings* settings, T* preAllocated =
stuff_int_list(settings->force_scaling_above_res, 2);
}
adjust_base_res(settings->base_res, settings->force_scaling_above_res, &settings->aspect_quotient, settings->scale_gauge);
adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
// If no positioning information is specified, use the default position
bool use_default_pos = true;
@@ -1262,7 +1261,7 @@ std::unique_ptr<T> gauge_load_common(gauge_settings* settings, T* preAllocated =
}
}
} else {
adjust_base_res(settings->base_res, settings->force_scaling_above_res, &settings->aspect_quotient, settings->scale_gauge);
adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
}
} else {
if(gr_screen.res == GR_640) {
@@ -1273,7 +1272,7 @@ std::unique_ptr<T> gauge_load_common(gauge_settings* settings, T* preAllocated =
settings->base_res[1] = 768;
}
adjust_base_res(settings->base_res, settings->force_scaling_above_res, &settings->aspect_quotient, settings->scale_gauge);
adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
if (settings->set_position && !settings->use_coords) {
settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
@@ -1345,11 +1344,8 @@ std::unique_ptr<T> gauge_load_common(gauge_settings* settings, T* preAllocated =
instance.reset(new T());
}
instance->initBaseResolution(settings->base_res[0], settings->base_res[1], settings->aspect_quotient);
instance->initBaseResolution(settings->base_res[0], settings->base_res[1]);
instance->initFont(settings->font_num);
instance->initOriginAndOffset(settings->origin[0], settings->origin[1], settings->offset[0], settings->offset[1]);
instance->initCoords(settings->use_coords, settings->coords[0], settings->coords[1]);
instance->initChase_view_only(settings->chase_view_only);
if (settings->set_position) {
instance->initPosition(settings->coords[0], settings->coords[1]);
@@ -1411,7 +1407,7 @@ void load_gauge_custom(gauge_settings* settings)
stuff_int_list(settings->force_scaling_above_res, 2);
}
adjust_base_res(settings->base_res, settings->force_scaling_above_res, &settings->aspect_quotient, settings->scale_gauge);
adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
// If no positioning information is specified, use the default position
bool use_default_pos = true;
@@ -1523,13 +1519,9 @@ void load_gauge_custom(gauge_settings* settings)
}
std::unique_ptr<HudGauge> hud_gauge(new HudGauge(gauge_type, settings->slew, r, g, b, name, text, filename, txtoffset_x, txtoffset_y));
hud_gauge->initBaseResolution(settings->base_res[0], settings->base_res[1], settings->aspect_quotient);
hud_gauge->initBaseResolution(settings->base_res[0], settings->base_res[1]);
hud_gauge->initPosition(settings->coords[0], settings->coords[1]);
hud_gauge->initFont(settings->font_num);
hud_gauge->initOriginAndOffset(settings->origin[0], settings->origin[1], settings->offset[0], settings->offset[1]);
hud_gauge->initCoords(settings->use_coords, settings->coords[0], settings->coords[1]);
hud_gauge->initRenderStatus(active_by_default);
hud_gauge->updateColor(colors[0], colors[1], colors[2]);
hud_gauge->lockConfigColor(lock_color);
@@ -2949,7 +2941,7 @@ void load_gauge_radar_dradis(gauge_settings* settings)
stuff_int_list(settings->force_scaling_above_res, 2);
}
adjust_base_res(settings->base_res, settings->force_scaling_above_res, &settings->aspect_quotient, settings->scale_gauge);
adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
if(optional_string("Origin:")) {
stuff_float_list(settings->origin, 2);
@@ -2975,7 +2967,7 @@ void load_gauge_radar_dradis(gauge_settings* settings)
settings->base_res[1] = 768;
}
adjust_base_res(settings->base_res, settings->force_scaling_above_res, &settings->aspect_quotient, settings->scale_gauge);
adjust_base_res(settings->base_res, settings->force_scaling_above_res, settings->scale_gauge);
settings->coords[0] = (int)(settings->base_res[0] * settings->origin[0]) + settings->offset[0];
settings->coords[1] = (int)(settings->base_res[1] * settings->origin[1]) + settings->offset[1];
@@ -3068,15 +3060,12 @@ void load_gauge_radar_dradis(gauge_settings* settings)
}
std::unique_ptr<HudGaugeRadarDradis> hud_gauge(new HudGaugeRadarDradis());
hud_gauge->initBaseResolution(settings->base_res[0], settings->base_res[1], settings->aspect_quotient);
hud_gauge->initBaseResolution(settings->base_res[0], settings->base_res[1]);
hud_gauge->initPosition(settings->coords[0], settings->coords[1]);
hud_gauge->initFont(settings->font_num);
hud_gauge->initOriginAndOffset(settings->origin[0], settings->origin[1], settings->offset[0], settings->offset[1]);
hud_gauge->initCoords(settings->use_coords, settings->coords[0], settings->coords[1]);
hud_gauge->initRadius(Radar_radius[0], Radar_radius[1]);
hud_gauge->initBitmaps(xy_fname, xz_yz_fname, sweep_fname, target_fname, unknown_fname);
hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
hud_gauge->initFont(settings->font_num);
hud_gauge->initSound(loop_snd, loop_snd_volume, arrival_beep_snd, departure_beep_snd, stealth_arrival_snd, stealth_departure_snd, arrival_beep_delay, departure_beep_delay);
hud_gauge->initChase_view_only(settings->chase_view_only);
-2
View File
@@ -30,7 +30,6 @@ typedef struct gauge_settings {
int font_num;
bool scale_gauge;
int force_scaling_above_res[2];
float aspect_quotient;
SCP_vector<int>* ship_idx;
color *use_clr;
float origin[2];
@@ -46,7 +45,6 @@ typedef struct gauge_settings {
base_res[0] = -1;
base_res[1] = -1;
memcpy(force_scaling_above_res, Force_scaling_above_res_global, sizeof(force_scaling_above_res));
aspect_quotient = 1.0f;
origin[0] = 0.0f;
origin[1] = 0.0f;
offset[0] = 0;
+9 -20
View File
@@ -309,21 +309,12 @@ ship_info *sip = &Ship_info[Player_ship->ship_info_index];
}
void HudGaugeReticle::getFirepointStatus() {
// allow the firepoint status to be empty when a multiplayer observer
// this is not a bug, the observer will simply *not* have any firepoints.
if (Objects[Player->objnum].type == OBJ_OBSERVER) {
// only multiplayer instances should be getting here!
Assertion((Game_mode & GM_MULTIPLAYER), "Somehow FSO thinks its player object is an observer even though it's not in Multiplayer. Please report!");
return;
}
//First, get the player ship
ship_info* sip;
ship* shipp;
polymodel* pm;
Assertion(Objects[Player->objnum].type == OBJ_SHIP, "HudGaugeReticle::getFirepointStatus was passed an invalid object type of %d. Please report!", Objects[Player->objnum].type);
Assert(Objects[Player->objnum].type == OBJ_SHIP);
if (Objects[Player->objnum].type == OBJ_SHIP) {
shipp = &Ships[Objects[Player->objnum].instance];
@@ -468,9 +459,8 @@ void HudGaugeThrottle::initMatchSpeedOffsets(int x, int y, bool custom)
Match_speed_offsets[1] = y;
Use_custom_match_speed = custom;
auto match_speed_str = XSTR("m", 1667);
font::FSFont* fsFont = font::get_font(font_num);
if (fsFont->getType() == font::VFNT_FONT)
{
ubyte sc = lcl_get_font_index(font_num);
@@ -478,7 +468,7 @@ void HudGaugeThrottle::initMatchSpeedOffsets(int x, int y, bool custom)
// a) the german font has no special m (its an a)
// b) the font has no special characters
if (sc == 0 || Lcl_gr) {
Match_speed_icon = match_speed_str[0];
Match_speed_icon = 'm';
}
else {
Match_speed_icon = sc + 3;
@@ -488,12 +478,13 @@ void HudGaugeThrottle::initMatchSpeedOffsets(int x, int y, bool custom)
else
{
// Default version for other fonts, draw a black character on a rectangle
Match_speed_icon = match_speed_str[0];
Match_speed_icon = 'm';
Match_speed_draw_background = true;
}
SCP_stringstream stream;
stream << static_cast<char>(Match_speed_icon);
const SCP_string& iconStr = stream.str();
gr_get_string_size(&Match_speed_icon_width, nullptr, iconStr.c_str());
@@ -593,7 +584,7 @@ void HudGaugeThrottle::render(float /*frametime*/)
if ( Show_percent ) {
if ( Player_obj->phys_info.flags & PF_AFTERBURNER_ON ) {
strcpy_s(buf, XSTR( "A/B", 1669 ));
strcpy_s(buf, "A/B");
} else {
sprintf(buf, XSTR( "%d%%", 326), (int)std::lround( (desired_speed/max_speed)*100 ));
}
@@ -650,10 +641,8 @@ void HudGaugeThrottle::renderThrottleSpeed(float current_speed, int y_end)
renderPrintf(sx, sy, "%s", buf);
if ( object_get_gliding(Player_obj) ) {
auto glide_str = XSTR("GLIDE", 1668);
if ( Use_custom_glide ) {
renderString(position[0] + Glide_offsets[0], position[1] + Glide_offsets[1], glide_str);
renderString(position[0] + Glide_offsets[0], position[1] + Glide_offsets[1], "GLIDE");
} else {
int offset;
if ( current_speed <= 9.5 ) {
@@ -664,7 +653,7 @@ void HudGaugeThrottle::renderThrottleSpeed(float current_speed, int y_end)
offset = -13;
}
renderString(sx+offset, sy + h, glide_str);
renderString(sx+offset, sy + h, "GLIDE");
}
} else if ( Players[Player_num].flags & PLAYER_FLAGS_MATCH_TARGET ) {
if ( Use_custom_match_speed ) {
+119 -129
View File
@@ -12,7 +12,6 @@
#include "ai/aigoals.h"
#include "ai/ailua.h"
#include "gamesnd/gamesnd.h"
#include "globalincs/linklist.h"
#include "hud/hudmessage.h"
@@ -34,6 +33,7 @@
#include "weapon/emp.h"
#include "weapon/weapon.h"
// defines for different modes in the squad messaging system
#define DEFAULT_MSG_TIMEOUT (8 * 1000) // number of seconds * 1000 to get milliseconds
@@ -156,38 +156,25 @@ int keys_used[] = { KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_
SCP_string Comm_order_types[NUM_COMM_ORDER_TYPES];
int player_order::orderingCounter = 0;
std::vector<player_order> Player_orders = {
player_order("no order", "No Order", -1, -1, NO_ORDER_ITEM), //Required to keep defines in sync with array indices
player_order("attack ship", "Destroy my target", 299, -1, ATTACK_TARGET_ITEM),
player_order("disable ship", "Disable my target", 300, -1, DISABLE_TARGET_ITEM),
player_order("disarm ship", "Disarm my target", 301, -1, DISARM_TARGET_ITEM),
player_order("disable subsys","Destroy subsystem", 302, -1, DISABLE_SUBSYSTEM_ITEM),
player_order("guard ship", "Protect my target", 303, -1, PROTECT_TARGET_ITEM),
player_order("ignore ship", "Ignore my target", 304, -1, IGNORE_TARGET_ITEM),
player_order("form on wing","Form on my wing", 305, -1, FORMATION_ITEM),
player_order("cover me", "Cover me", 306, -1, COVER_ME_ITEM),
player_order("attack any", "Engage enemy", 307, -1, ENGAGE_ENEMY_ITEM),
player_order("dock", "Capture my target", 308, -1, CAPTURE_TARGET_ITEM),
player_order("rearm me", "Rearm me", 309, -1, REARM_REPAIR_ME_ITEM),
player_order("abort rearm", "Abort rearm", 310, -1, ABORT_REARM_REPAIR_ITEM),
player_order("depart", "Depart", 311, -1, DEPART_ITEM),
player_order("stay near me", "Stay near me", -1, -1, STAY_NEAR_ME_ITEM),
player_order("stay near ship", "Stay near my target",-1, -1, STAY_NEAR_TARGET_ITEM),
player_order("keep safe dist", "Keep safe distance", -1, -1, KEEP_SAFE_DIST_ITEM)
player_order("attack ship", "Destroy my target", 299, ATTACK_TARGET_ITEM),
player_order("disable ship", "Disable my target", 300, DISABLE_TARGET_ITEM ),
player_order("disarm ship", "Disarm my target", 301, DISARM_TARGET_ITEM ),
player_order("disable subsys","Destroy subsystem", 302, DISABLE_SUBSYSTEM_ITEM ),
player_order("guard ship", "Protect my target", 303, PROTECT_TARGET_ITEM ),
player_order("ignore ship", "Ignore my target", 304, IGNORE_TARGET_ITEM ),
player_order("form on wing","Form on my wing", 305, FORMATION_ITEM ),
player_order("cover me", "Cover me", 306, COVER_ME_ITEM ),
player_order("attack any", "Engage enemy", 307, ENGAGE_ENEMY_ITEM ),
player_order("dock", "Capture my target", 308, CAPTURE_TARGET_ITEM),
player_order("rearm me", "Rearm me", 309, REARM_REPAIR_ME_ITEM),
player_order("abort rearm", "Abort rearm", 310, ABORT_REARM_REPAIR_ITEM),
player_order("depart", "Depart", 311, DEPART_ITEM),
player_order("stay near me", "Stay near me", -1, STAY_NEAR_ME_ITEM),
player_order("stay near ship", "Stay near my target",-1, STAY_NEAR_TARGET_ITEM),
player_order("keep safe dist", "Keep safe distance", -1, KEEP_SAFE_DIST_ITEM)
};
const std::set<size_t> default_messages{ ATTACK_TARGET_ITEM , DISABLE_TARGET_ITEM , DISARM_TARGET_ITEM , PROTECT_TARGET_ITEM , IGNORE_TARGET_ITEM , FORMATION_ITEM , COVER_ME_ITEM , ENGAGE_ENEMY_ITEM , DEPART_ITEM , DISABLE_SUBSYSTEM_ITEM };
const std::set<size_t> enemy_target_messages{ ATTACK_TARGET_ITEM , DISABLE_TARGET_ITEM , DISARM_TARGET_ITEM , IGNORE_TARGET_ITEM , STAY_NEAR_TARGET_ITEM , CAPTURE_TARGET_ITEM , DISABLE_SUBSYSTEM_ITEM };
const std::set<size_t> friendly_target_messages{ PROTECT_TARGET_ITEM };
const std::set<size_t> target_messages = []() {
std::set<size_t> setunion;
std::set_union(enemy_target_messages.cbegin(), enemy_target_messages.cend(), friendly_target_messages.cbegin(), friendly_target_messages.cend(), std::inserter(setunion, setunion.end()));
return setunion;
}();
void hud_init_comm_orders()
{
int i;
@@ -207,21 +194,22 @@ void hud_init_comm_orders()
Comm_order_types[i] = temp_comm_order_types[i];
}
for (auto& order : Player_orders)
order.localize();
std::sort(Player_orders.begin(), Player_orders.end(), [](const player_order& o1, const player_order& o2) {
return o1.legacy_id < o2.legacy_id;
});
for(auto& order : Player_orders) {
order.localized_name = XSTR(order.hud_name.c_str(), order.hud_xstr);
}
}
// Text to display on the messaging menu when using the shortcut keys
const char *comm_order_get_text(int item)
{
Assertion(item < (int)Player_orders.size(), "Did not find order with index %d!", item);
for(const auto& order : Player_orders){
if(order.id == item)
return order.localized_name.c_str();
}
return Player_orders[item].localized_name.c_str();
UNREACHABLE("Did not find order with id %d!", item);
return nullptr;
}
SCP_vector<squadmsg_history> Squadmsg_history;
@@ -229,7 +217,7 @@ SCP_vector<squadmsg_history> Squadmsg_history;
// forward declarations
void hud_add_issued_order(const char *name, int order);
void hud_update_last_order(const char *target, int order_source, int special_index);
bool hud_squadmsg_is_target_order_valid(size_t order, ai_info *aip = nullptr);
bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip = nullptr);
bool hud_squadmsg_ship_valid(ship *shipp, object *objp = nullptr);
bool hud_squadmsg_ship_order_valid( int shipnum, int order );
@@ -344,7 +332,10 @@ bool hud_squadmsg_ship_valid(ship *shipp, object *objp)
// if a messaging shortcut, be sure this ship can process the order
if ( Msg_shortcut_command != -1 ) {
if (shipp->orders_accepted.count((size_t) Msg_shortcut_command) == 0)
bool accepts_any = false;
for(size_t order : shipp->orders_accepted)
accepts_any |= (bool)(Player_orders[order].id & Msg_shortcut_command);
if ( !accepts_any )
return false;
else if ( !hud_squadmsg_ship_order_valid(objp->instance, Msg_shortcut_command) )
@@ -595,13 +586,11 @@ int hud_squadmsg_get_key()
return i;
// play general fail sound if inactive item hit.
else if ((i + First_menu_item < Num_menu_items) && !(MsgItems[i + First_menu_item].active)) {
else if ( (i < Num_menu_items) && !(MsgItems[i].active) )
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
else if ((i + First_menu_item < Num_menu_items) && (MsgItems[i + First_menu_item].active)) { // only return keys that are associated with menu items
return i + First_menu_item;
}
else if ( (i < Num_menu_items) && (MsgItems[i].active) ) // only return keys that are associated with menu items
return i;
else {
Msg_key_used = 0; // if no #-key pressed for visible item, break and allow timer to
@@ -734,7 +723,7 @@ bool hud_squadmsg_ship_order_valid( int shipnum, int order )
Assert( shipnum >= 0 && shipnum < MAX_SHIPS );
ship *shipp = &Ships[shipnum];
switch ( order )
switch ( order )
{
case DEPART_ITEM:
// disabled ships can't depart.
@@ -756,27 +745,31 @@ bool hud_squadmsg_ship_order_valid( int shipnum, int order )
// returns true or false if the Players target is valid for the given order
// find_order is true when we need to search the comm_orders array for the order entry. We have
// to do this action in some cases since all we know is the actual "value" of the order
bool hud_squadmsg_is_target_order_valid(size_t order, ai_info *aip )
bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
{
int target_objnum;
size_t i;
ship *shipp, *ordering_shipp;
object *objp;
if ( aip == NULL )
aip = Player_ai;
target_objnum = aip->target_objnum;
ordering_shipp = &Ships[aip->shipnum];
//If it's a lua order, defer to luaai
if (Player_orders[order].lua_id != -1) {
return ai_lua_is_valid_target(Player_orders[order].lua_id, target_objnum, ordering_shipp);
// find the comm_menu item for this command
if ( find_order ) {
for (i = 0; i < Player_orders.size(); i++ ) {
if ( Player_orders[i].id == order )
break;
}
Assert( i < Player_orders.size() );
order = (int)i;
}
// orders which don't operate on targets are always valid
if ( target_messages.count(order) == 0 )
if ( !(Player_orders[order].id & TARGET_MESSAGES) )
return true;
target_objnum = aip->target_objnum;
// order isn't valid if there is no player target
if ( target_objnum == -1 ) {
@@ -785,6 +778,7 @@ bool hud_squadmsg_is_target_order_valid(size_t order, ai_info *aip )
objp = &Objects[target_objnum];
ordering_shipp = &Ships[aip->shipnum];
// target isn't a ship, then return false
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_WEAPON) )
@@ -799,7 +793,7 @@ bool hud_squadmsg_is_target_order_valid(size_t order, ai_info *aip )
return false;
}
if ( order == ATTACK_TARGET_ITEM
if ( (Player_orders[order].id == ATTACK_TARGET_ITEM )
&& ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Fighter_Interceptable]))
&& (Weapons[objp->instance].team != ordering_shipp->team) ) {
return true;
@@ -823,24 +817,24 @@ bool hud_squadmsg_is_target_order_valid(size_t order, ai_info *aip )
}
// if the order is a disable order or depart, and the ship is disabled, order isn't active
if ( (order == DISABLE_TARGET_ITEM) && (shipp->flags[Ship::Ship_Flags::Disabled]) ){
if ( (Player_orders[order].id == DISABLE_TARGET_ITEM) && (shipp->flags[Ship::Ship_Flags::Disabled]) ){
return false;
}
// same as above except for disarmed.
if ( (order == DISARM_TARGET_ITEM) && ((shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0) || (shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f)) ){
if ( (Player_orders[order].id == DISARM_TARGET_ITEM) && ((shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0) || (shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f)) ){
return false;
}
// if order is disable subsystem, and no subsystem targeted or no hits, then order not valid
if ( (order == DISABLE_SUBSYSTEM_ITEM) && ((aip->targeted_subsys == nullptr) || (aip->targeted_subsys->current_hits <= 0.0f)) ){
if ( (Player_orders[order].id == DISABLE_SUBSYSTEM_ITEM) && ((aip->targeted_subsys == nullptr) || (aip->targeted_subsys->current_hits <= 0.0f)) ){
return false;
}
// check based on target's and player's team
if ( (shipp->team == ordering_shipp->team) && (friendly_target_messages.count(order) > 0) ){
if ( (shipp->team == ordering_shipp->team) && (FRIENDLY_TARGET_MESSAGES & Player_orders[order].id) ){
return true;
} else if ( (shipp->team != ordering_shipp->team) && (enemy_target_messages.count(order) > 0) ){
} else if ( (shipp->team != ordering_shipp->team) && (ENEMY_TARGET_MESSAGES & Player_orders[order].id) ){
return true;
} else {
return false;
@@ -917,7 +911,11 @@ void hud_squadmsg_send_to_all_fighters( int command, int player_num )
// don't send the command if the "wing" won't accept the command. We do this by looking at
// the set of orders accepted for the wing leader
if (shipp->orders_accepted.count((size_t)command) == 0)
bool accepts_current = false;
for(size_t order : shipp->orders_accepted)
accepts_current |= (bool)(Player_orders[order].id & command);
if ( !accepts_current )
continue;
// send the command to the wing
@@ -953,7 +951,11 @@ void hud_squadmsg_send_to_all_fighters( int command, int player_num )
continue;
// don't send command if ship won't accept if
if (shipp->orders_accepted.count((size_t)command) == 0)
bool accepts_current = false;
for(size_t order : shipp->orders_accepted)
accepts_current |= (bool)(Player_orders[order].id & command);
if ( !accepts_current )
continue;
if (send_message) {
@@ -1007,7 +1009,6 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message,
ai_info *ainfo;
int ai_mode, ai_submode; // ai mode and submode needed for ship commands
char *target_shipname; // ship number of possible targets
object_ship_wing_point_team lua_target;
int message;
int target_team, ship_team; // team id's for the ship getting message and any target the player has
ship *ordering_shipp;
@@ -1044,10 +1045,10 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message,
// a shortcut to save on repetitive coding. If the order is a 'target' order, make the default
// mesage be "no target"
message = MESSAGE_NOSIR;
if ( target_messages.count((size_t)command) > 0 && (ainfo->target_objnum == -1) )
if ( (command & TARGET_MESSAGES) && (ainfo->target_objnum == -1) )
message = MESSAGE_NO_TARGET;
if ( hud_squadmsg_is_target_order_valid((size_t) command, ainfo) ) {
if ( hud_squadmsg_is_target_order_valid(command, 1, ainfo) ) {
target_shipname = NULL;
target_team = -1;
@@ -1125,7 +1126,7 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message,
}
ai_mode = AI_GOAL_DESTROY_SUBSYSTEM;
ai_submode = ship_find_subsys( &Ships[Objects[ainfo->target_objnum].instance], ainfo->targeted_subsys->system_info->subobj_name );
ai_submode = ship_get_subsys_index( &Ships[Objects[ainfo->target_objnum].instance], ainfo->targeted_subsys->system_info->subobj_name );
special_index = ai_submode;
message = MESSAGE_ATTACK_TARGET;
break;
@@ -1243,24 +1244,16 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message,
message = MESSAGE_YESSIR;
break;
default: {
Assert(command < (int) Player_orders.size()); // get Allender -- illegal message
ai_mode = AI_GOAL_LUA;
ai_submode = Player_orders[command].lua_id;
auto lua_porder = ai_lua_find_player_order(Player_orders[command].lua_id);
message = lua_porder->ai_message;
if (ainfo->target_objnum != -1)
lua_target = object_ship_wing_point_team(&Ships[Objects[ainfo->target_objnum].instance]);
default:
Int3(); // get Allender -- illegal message
break;
}
}
// handle case of messaging one ship. Deal with messaging all fighters next.
if ( ai_mode != AI_GOAL_NONE ) {
Assert(ai_submode != -1234567);
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, ai_mode, ai_submode, target_shipname, &Ai_info[Ships[shipnum].ai_index], lua_target );
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, ai_mode, ai_submode, target_shipname, &Ai_info[Ships[shipnum].ai_index] );
if( update_history == SQUADMSG_HISTORY_ADD_ENTRY ) {
hud_add_issued_order(Ships[shipnum].ship_name, command);
hud_update_last_order(target_shipname, player_num, special_index);
@@ -1300,7 +1293,6 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
ai_info *ainfo;
int ai_mode, ai_submode; // ai mode and submode needed for ship commands
char *target_shipname; // ship number of possible targets
object_ship_wing_point_team lua_target;
int message_sent, message;
int target_team, wing_team; // team for the wing and the player's target
ship *ordering_shipp;
@@ -1339,10 +1331,10 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
// a shortcut to save on repetative coding
message = MESSAGE_NOSIR;
if ( (target_messages.count((size_t)command) > 0) && (ainfo->target_objnum == -1) )
if ( (command & TARGET_MESSAGES) && (ainfo->target_objnum == -1) )
message = MESSAGE_NO_TARGET;
if ( hud_squadmsg_is_target_order_valid((size_t)command, ainfo) ) {
if ( hud_squadmsg_is_target_order_valid(command, 1, ainfo) ) {
target_shipname = NULL;
target_team = -1;
@@ -1407,7 +1399,7 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
Assert( ainfo->targeted_subsys->current_hits > 0.0f);
ai_mode = AI_GOAL_DESTROY_SUBSYSTEM;
ai_submode = ship_find_subsys( &Ships[Objects[ainfo->target_objnum].instance], ainfo->targeted_subsys->system_info->subobj_name );
ai_submode = ship_get_subsys_index( &Ships[Objects[ainfo->target_objnum].instance], ainfo->targeted_subsys->system_info->subobj_name );
special_index = ai_submode;
message = MESSAGE_ATTACK_TARGET;
break;
@@ -1470,23 +1462,15 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
case KEEP_SAFE_DIST_ITEM:
return 0;
default: {
Assert(command < (int) Player_orders.size()); // get Allender -- illegal message
ai_mode = AI_GOAL_LUA;
ai_submode = Player_orders[command].lua_id;
auto lua_porder = ai_lua_find_player_order(Player_orders[command].lua_id);
message = lua_porder->ai_message;
if(ainfo->target_objnum != -1)
lua_target = object_ship_wing_point_team(&Ships[Objects[ainfo->target_objnum].instance]);
default:
Int3(); // get Allender -- illegal message
break;
}
}
if ( ai_mode != AI_GOAL_NONE ) {
Assert(ai_submode != -1234567);
ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, ai_mode, ai_submode, target_shipname, wingnum, lua_target );
ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, ai_mode, ai_submode, target_shipname, wingnum );
if( update_history == SQUADMSG_HISTORY_ADD_ENTRY ) {
hud_add_issued_order(Wings[wingnum].name, command);
@@ -1588,6 +1572,8 @@ void hud_squadmsg_type_select( )
{
int k, i;
First_menu_item = 0;
// Add the items
for (i = 0; i < NUM_COMM_ORDER_TYPES; i++)
{
@@ -1711,13 +1697,13 @@ void hud_squadmsg_ship_select()
k = hud_squadmsg_get_key();
if ( k != -1 ) { // if true, we have selected a ship.
if ( Msg_shortcut_command == -1 ) {
Msg_instance = MsgItems[k].instance; // store the instance id in a global
Msg_instance = MsgItems[First_menu_item + k].instance; // store the instance id in a global
hud_squadmsg_do_mode( SM_MODE_SHIP_COMMAND ); // and move to a new mode
} else {
// we must convert the Msg_shortcut_command value to a value that the message
// system normally uses to select a command. Since the menu
//Assert( Msg_shortcut_command != IGNORE_TARGET_ITEM );
hud_squadmsg_send_ship_command( MsgItems[k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY);
hud_squadmsg_send_ship_command( MsgItems[First_menu_item+k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY);
hud_squadmsg_toggle();
}
}
@@ -1738,11 +1724,11 @@ void hud_squadmsg_wing_select()
k = hud_squadmsg_get_key();
if ( k != -1 ) { // if true, we have selected a ship.
if ( Msg_shortcut_command == -1 ) { // do normal menu stuff when no hoykey active
Msg_instance = MsgItems[k].instance; // store the instance id in a global
Msg_instance = MsgItems[First_menu_item + k].instance; // store the instance id in a global
hud_squadmsg_do_mode( SM_MODE_WING_COMMAND ); // and move to a new mode
} else {
//Assert( Msg_shortcut_command != IGNORE_TARGET_ITEM );
hud_squadmsg_send_wing_command( MsgItems[k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY );
hud_squadmsg_send_wing_command( MsgItems[First_menu_item+k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY );
hud_squadmsg_toggle();
}
}
@@ -1907,11 +1893,11 @@ void hud_squadmsg_reinforcement_select()
hud_squadmsg_toggle(); // take us out of message mode
rnum = MsgItems[k].instance;
rnum = MsgItems[First_menu_item + k].instance;
// check to see if trying to call a reinforcement not yet available. If so, maybe play message, but
// definately bail
if ( MsgItems[k].active == 0 ) {
if ( MsgItems[First_menu_item + k].active == 0 ) {
return;
}
@@ -1926,17 +1912,12 @@ void hud_squadmsg_reinforcement_select()
}
}
bool hud_order_comparator(size_t a, size_t b) {
return Player_orders[a].ordering < Player_orders[b].ordering;
}
// function to display list of commands for a ship
void hud_squadmsg_ship_command()
{
int k;
std::set<size_t> orders;
std::set<size_t, decltype(&hud_order_comparator)> default_orders(&hud_order_comparator);
std::set<size_t> orders, default_orders;
// when adding ship commands, we must look at the type of ship, and what messages that
// ship allows. First, place all messages that are possible onto the menu, then
@@ -1945,31 +1926,33 @@ void hud_squadmsg_ship_command()
// show on comm menu.
if ( Msg_instance != MESSAGE_ALL_FIGHTERS ) {
orders = Ships[Msg_instance].orders_accepted;
const auto& default_orders_accepted = ship_get_default_orders_accepted(&Ship_info[Ships[Msg_instance].ship_info_index]);
default_orders.insert(default_orders_accepted.cbegin(), default_orders_accepted.cend());
default_orders = ship_get_default_orders_accepted( &Ship_info[Ships[Msg_instance].ship_info_index] );
} else {
orders = default_messages;
default_orders.insert(default_messages.cbegin(), default_messages.cend());
for(size_t i = 0; i < Player_orders.size(); i++){
if(Player_orders[i].id & DEFAULT_MESSAGES)
default_orders.insert(i);
}
orders = default_orders;
}
First_menu_item = 0;
Num_menu_items = 0;
for(size_t order_id : default_orders) {
Assert (Num_menu_items < MAX_MENU_ITEMS);
MsgItems[Num_menu_items].text = Player_orders[order_id].localized_name;
MsgItems[Num_menu_items].instance = (int)order_id;
MsgItems[Num_menu_items].instance = Player_orders[order_id].id;
MsgItems[Num_menu_items].active = 0;
// check the bit to see if the command is active
if (orders.find(order_id) != orders.end())
MsgItems[Num_menu_items].active = 1;
// if the order cannot be carried out by the ship, then item should be inactive
if ((Msg_instance != MESSAGE_ALL_FIGHTERS) && !hud_squadmsg_ship_order_valid(Msg_instance, (int)order_id))
if ((Msg_instance != MESSAGE_ALL_FIGHTERS) && !hud_squadmsg_ship_order_valid(Msg_instance, Player_orders[order_id].id))
MsgItems[Num_menu_items].active = 0;
// do some other checks to possibly gray out other items.
// if no target, remove any items which are associated with the players target
if (!hud_squadmsg_is_target_order_valid(order_id, nullptr))
if (!hud_squadmsg_is_target_order_valid((int)order_id, 0))
MsgItems[Num_menu_items].active = 0;
// if messaging all fighters, see if we should gray out the order if no one will accept it,
@@ -1977,10 +1960,10 @@ void hud_squadmsg_ship_command()
if (Msg_instance == MESSAGE_ALL_FIGHTERS) {
ship_obj* so;
ship* shipp;
bool partial_accept, all_accept; // value which tells us what to do with menu item
int partial_accept, all_accept; // value which tells us what to do with menu item
all_accept = true;
partial_accept = false;
all_accept = Player_orders[order_id].id;
partial_accept = 0;
for (so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so)) {
// don't send messge to ships not on player's team, or that are in a wing.
@@ -1992,9 +1975,11 @@ void hud_squadmsg_ship_command()
if (!(Ship_info[shipp->ship_info_index].is_fighter_bomber()))
continue;
bool local_accepted = shipp->orders_accepted.count(order_id) > 0;
int local_accepted = 0;
for(size_t accepted_order : shipp->orders_accepted)
local_accepted |= Player_orders[accepted_order].id;
all_accept &= local_accepted; // 'and'ing will either keep this bit set or zero it properly
partial_accept |= local_accepted; // 'or'ing will tell us if at least one accepts
partial_accept |= (local_accepted & Player_orders[order_id].id); // 'or'ing will tell us if at least one accepts
}
if (!all_accept) {
@@ -2036,8 +2021,7 @@ void hud_squadmsg_wing_command()
wing *wingp;
int shipnum;
std::set<size_t> orders;
std::set<size_t, decltype(&hud_order_comparator)> default_orders(&hud_order_comparator);
std::set<size_t> default_orders, orders;
// when adding commands for wings, we will look at all of the ships in the wing, and create
// the order list from that set of ships. In the future, we may want to do something else....
@@ -2050,7 +2034,10 @@ void hud_squadmsg_wing_command()
default_orders.insert(setAdd.begin(), setAdd.end());
}
default_orders.erase(CAPTURE_TARGET_ITEM); // we cannot capture any target with a wing.
for(size_t i = 0; i < Player_orders.size(); i++){
if (Player_orders[i].id & CAPTURE_TARGET_ITEM) // we cannot capture any target with a wing.
default_orders.erase(i);
}
Num_menu_items = 0;
shipnum = wingp->ship_index[wingp->special_ship];
@@ -2062,7 +2049,7 @@ void hud_squadmsg_wing_command()
// to be available in the wing.
Assert ( Num_menu_items < MAX_MENU_ITEMS );
MsgItems[Num_menu_items].text = Player_orders[order_id].localized_name;
MsgItems[Num_menu_items].instance = (int)order_id;
MsgItems[Num_menu_items].instance = Player_orders[order_id].id;
MsgItems[Num_menu_items].active = 0;
// possibly grey out the menu item depending on whether or not the "wing" will accept this order
@@ -2255,7 +2242,11 @@ int hud_squadmsg_hotkey_select( int k )
continue;
// be sure that this ship can accept this command
if ( Ships[objp->instance].orders_accepted.count(Msg_shortcut_command) == 0)
bool accepts_current = false;
for(size_t order : Ships[objp->instance].orders_accepted)
accepts_current |= (bool)(Player_orders[order].id & Msg_shortcut_command);
if ( !accepts_current )
continue;
hud_squadmsg_send_ship_command( objp->instance, Msg_shortcut_command, send_message, SQUADMSG_HISTORY_ADD_ENTRY );
@@ -2421,17 +2412,16 @@ int hud_query_order_issued(const char *to, const char *order_name, const char *t
for (i = 0; i < (int) Player_orders.size(); i++)
if (!stricmp(order_name, Player_orders[i].hud_name.c_str())) {
order = i;
break;
}
if (!stricmp(order_name, Player_orders[i].hud_name.c_str()))
order = Player_orders[i].id;
// Goober5000 - if not found, check compatibility
if (order == -1)
{
if (!stricmp(order_name, "Attack my target"))
{
order = ATTACK_TARGET_ITEM;
i = 0; // it maps to option 0, "Destroy my target"
order = Player_orders[i].id;
}
}
@@ -2460,7 +2450,7 @@ int hud_query_order_issued(const char *to, const char *order_name, const char *t
continue;
}
int subsys_index = ship_find_subsys(&Ships[target_ship], special_argument);
int subsys_index = ship_get_subsys_index(&Ships[target_ship], special_argument);
// if the order is for s different subsystem
if (Squadmsg_history[i].special_index != subsys_index) {
continue;
+25 -30
View File
@@ -30,52 +30,42 @@
class object;
// defines for messages that can be sent from the player. Indexes into Player_orders
// defines for messages that can be sent from the player. Defined at bitfields so that we can enable
// and disable messages on a message by message basis
#define NO_ORDER_ITEM 0
#define ATTACK_TARGET_ITEM 1
#define DISABLE_TARGET_ITEM 2
#define DISARM_TARGET_ITEM 3
#define PROTECT_TARGET_ITEM 4
#define IGNORE_TARGET_ITEM 5
#define FORMATION_ITEM 6
#define COVER_ME_ITEM 7
#define ENGAGE_ENEMY_ITEM 8
#define CAPTURE_TARGET_ITEM 9
#define ATTACK_TARGET_ITEM (1<<0)
#define DISABLE_TARGET_ITEM (1<<1)
#define DISARM_TARGET_ITEM (1<<2)
#define PROTECT_TARGET_ITEM (1<<3)
#define IGNORE_TARGET_ITEM (1<<4)
#define FORMATION_ITEM (1<<5)
#define COVER_ME_ITEM (1<<6)
#define ENGAGE_ENEMY_ITEM (1<<7)
#define CAPTURE_TARGET_ITEM (1<<8)
// the next are for the support ship only
#define REARM_REPAIR_ME_ITEM 10
#define ABORT_REARM_REPAIR_ITEM 11
#define STAY_NEAR_ME_ITEM 12
#define STAY_NEAR_TARGET_ITEM 13
#define KEEP_SAFE_DIST_ITEM 14
#define REARM_REPAIR_ME_ITEM (1<<9)
#define ABORT_REARM_REPAIR_ITEM (1<<10)
#define STAY_NEAR_ME_ITEM (1<<11)
#define STAY_NEAR_TARGET_ITEM (1<<12)
#define KEEP_SAFE_DIST_ITEM (1<<13)
// next item for all ships again -- to try to preserve relative order within the message menu
#define DEPART_ITEM 15
#define DEPART_ITEM (1<<14)
// out of order, but it was this way in the original source
#define DISABLE_SUBSYSTEM_ITEM 16
#define DISABLE_SUBSYSTEM_ITEM (1<<15)
// used for Message box gauge
#define NUM_MBOX_FRAMES 3
typedef struct player_order {
private:
//Needed, because legacy order-id's were not assigned in order
static int orderingCounter;
//Used to ensure that built-in order indexing is always correct
int legacy_id;
friend void hud_init_comm_orders();
public:
SCP_string parse_name;
SCP_string hud_name;
int hud_xstr;
int id;
SCP_string localized_name;
int lua_id;
int ordering;
player_order(SCP_string parsename, SCP_string hudname, int hudxstr, int luaid = -1, int legacyid = 999999) : legacy_id(legacyid), parse_name(std::move(parsename)), hud_name(std::move(hudname)), hud_xstr(hudxstr), localized_name(""), lua_id(luaid), ordering(orderingCounter++) { }
inline void localize() { localized_name = XSTR(hud_name.c_str(), hud_xstr); }
player_order(SCP_string parsename, SCP_string hudname, int hudxstr, int orderid = 0) : parse_name(std::move(parsename)), hud_name(std::move(hudname)), hud_xstr(hudxstr), id(orderid), localized_name("") { }
} player_order;
extern std::vector<player_order> Player_orders;
@@ -84,6 +74,7 @@ extern std::vector<player_order> Player_orders;
// might not allow some messages
//WMC - Formerly FIGHTER_MESSAGES
#define DEFAULT_MESSAGES (ATTACK_TARGET_ITEM | DISABLE_TARGET_ITEM | DISARM_TARGET_ITEM | PROTECT_TARGET_ITEM | IGNORE_TARGET_ITEM | FORMATION_ITEM | COVER_ME_ITEM | ENGAGE_ENEMY_ITEM | DEPART_ITEM | DISABLE_SUBSYSTEM_ITEM)
/*
#define BOMBER_MESSAGES FIGHTER_MESSAGES // bombers can do the same things as fighters
@@ -101,6 +92,10 @@ extern std::vector<player_order> Player_orders;
// these messages require an active target. They are also the set of messages
// which cannot be given to a ship when the target is on the same team, or the target
// is not a ship.
#define ENEMY_TARGET_MESSAGES (ATTACK_TARGET_ITEM | DISABLE_TARGET_ITEM | DISARM_TARGET_ITEM | IGNORE_TARGET_ITEM | STAY_NEAR_TARGET_ITEM | CAPTURE_TARGET_ITEM | DISABLE_SUBSYSTEM_ITEM )
#define FRIENDLY_TARGET_MESSAGES (PROTECT_TARGET_ITEM)
#define TARGET_MESSAGES (ENEMY_TARGET_MESSAGES | FRIENDLY_TARGET_MESSAGES)
+6 -19
View File
@@ -1530,8 +1530,6 @@ void hud_target_missile(object *source_obj, int next_flag)
continue;
}
Assertion(Objects[so->objnum].type == OBJ_SHIP, "hud_target_missile was about to call obj_team with a non-ship obejct with type %d. Please report!", Objects[so->objnum].type);
// only allow targeting of hostile bombs
if (!iff_x_attacks_y(Player_ship->team, obj_team(A))) {
continue;
@@ -1718,8 +1716,11 @@ typedef struct eval_next_turret {
float dist;
} eval_next_turret;
int turret_compare_func(const eval_next_turret *p1, const eval_next_turret *p2)
int turret_compare_func(const void *e1, const void *e2)
{
eval_next_turret *p1 = (eval_next_turret*)e1;
eval_next_turret *p2 = (eval_next_turret*)e2;
Assert(p1->type != TYPE_NONE);
Assert(p2->type != TYPE_NONE);
@@ -1849,7 +1850,7 @@ void hud_target_live_turret(int next_flag, int auto_advance, int only_player_tar
// sort the list if we're not using turret straight ahead of us
if (!use_straight_ahead_turret) {
insertion_sort(ent, num_live_turrets, turret_compare_func);
insertion_sort(ent, num_live_turrets, sizeof(eval_next_turret), turret_compare_func);
}
if (use_straight_ahead_turret) {
@@ -2123,8 +2124,6 @@ bool evaluate_ship_as_closest_target(esct *esct_p)
// consider the ship alone if there are no attacking turrets
if ( !turret_is_attacking ) {
// Volition switched distance evaluation methods here... presumably this is to prioritize small fighters when dogfighting next to large ships...
// Since this is used specifically for finding an ordering of targets and does not involve any visual displays, distance-to-center is reasonable.
//new_distance = hud_find_target_distance(objp, Player_obj);
new_distance = vm_vec_dist_quick(&objp->pos, &Player_obj->pos);
@@ -4408,16 +4407,9 @@ void hud_target_change_check()
// check if the main target has changed
if (Player_ai->last_target != Player_ai->target_objnum) {
// acquired target
if ( Player_ai->target_objnum != -1){
snd_play( gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::TARGET_ACQUIRE)), 0.0f );
}
// cleared target
else {
if (Target_static_looping.isValid()) {
snd_stop(Target_static_looping);
}
}
// if we have a hotkey set active, see if new target is in set. If not in
// set, deselect the current hotkey set.
@@ -4525,7 +4517,6 @@ void HudGaugeTargetTriangle::render(float /*frametime*/)
object *targetp = &Objects[Player_ai->target_objnum];
// draw the targeting triangle that orbits the outside of the outer circle of the reticle
// checking !target_is_dying is correct here, since you do not want -1 (no target) or 1(is actually dying)
if (!Player->target_is_dying && maybeFlashSexp() != 1) {
hud_set_iff_color(targetp, 1);
@@ -6320,11 +6311,7 @@ void HudGaugeOffscreen::render(float /*frametime*/)
int dir;
if(target_display_list[i].objp) {
if (OBJ_INDEX(target_display_list[i].objp) == Player_ai->target_objnum) {
dist = Player_ai->current_target_distance;
} else {
dist = hud_find_target_distance( target_display_list[i].objp, Player_obj );
}
dist = hud_find_target_distance( target_display_list[i].objp, Player_obj );
} else {
// if we don't have a corresponding object, use given position to figure out distance
dist = vm_vec_dist_quick(&Player_obj->pos, &target_display_list[i].target_pos);
+7 -20
View File
@@ -1566,23 +1566,6 @@ void get_turret_subsys_name(ship_weapon *swp, char *outstr)
//WMC - find the first weapon, if there is one
if (swp->num_primary_banks || swp->num_secondary_banks) {
// allow the first weapon on the turret to specify the name
for (int i = 0; i < swp->num_primary_banks; ++i) {
auto wip = &Weapon_info[swp->primary_bank_weapons[i]];
if (*(wip->altSubsysName) != '\0') {
sprintf(outstr, "%s", wip->altSubsysName);
return;
}
}
for (int i = 0; i < swp->num_secondary_banks; ++i) {
auto wip = &Weapon_info[swp->secondary_bank_weapons[i]];
if (*(wip->altSubsysName) != '\0') {
sprintf(outstr, "%s", wip->altSubsysName);
return;
}
}
// otherwise use a general name based on the type of weapon(s) on the turret
auto flags = turret_weapon_aggregate_flags(swp);
// check if beam or flak using weapon flags
@@ -1595,13 +1578,17 @@ void get_turret_subsys_name(ship_weapon *swp, char *outstr)
sprintf(outstr, "%s", XSTR("Missile lnchr", 1569));
} else if (turret_weapon_has_subtype(swp, WP_LASER)) {
// ballistic too! - Goober5000
if (flags[Weapon::Info_Flags::Ballistic]) {
if (flags[Weapon::Info_Flags::Ballistic])
{
sprintf(outstr, "%s", XSTR("Turret", 1487));
}
// the TVWP has some primaries flagged as bombs
else if (flags[Weapon::Info_Flags::Bomb]) {
else if (flags[Weapon::Info_Flags::Bomb])
{
sprintf(outstr, "%s", XSTR("Missile lnchr", 1569));
} else {
}
else
{
sprintf(outstr, "%s", XSTR("Laser turret", 1568));
}
} else {
+2 -2
View File
@@ -372,7 +372,7 @@ bool CFtpGet::IssuePasv()
return false;
}
if ( connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&dataaddr), psnet_get_sockaddr_len(&dataaddr)) == SOCKET_ERROR ) {
if ( connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&dataaddr), sizeof(dataaddr)) == SOCKET_ERROR ) {
return false;
}
@@ -392,7 +392,7 @@ int CFtpGet::ConnectControlSocket()
}
// Now we will connect to the host
if ( connect(m_ControlSock, reinterpret_cast<LPSOCKADDR>(&m_ServerAddr), psnet_get_sockaddr_len(&m_ServerAddr)) ) {
if ( connect(m_ControlSock, reinterpret_cast<LPSOCKADDR>(&m_ServerAddr), sizeof(m_ServerAddr)) ) {
m_State = FTP_STATE_CANT_CONNECT;
return 0;
}
+2 -2
View File
@@ -331,7 +331,7 @@ int ChttpGet::ConnectSocket()
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), psnet_get_sockaddr_len(&hostaddr));
int serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), sizeof(hostaddr));
int cerr = WSAGetLastError();
if (serr) {
// fail after 20 seconds
@@ -360,7 +360,7 @@ int ChttpGet::ConnectSocket()
if (m_Aborting)
return 0;
serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), psnet_get_sockaddr_len(&hostaddr));
serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), sizeof(hostaddr));
if (serr == 0)
break;
Loaded 100 of 403 files, more files were not shown because too many files have changed in this diff. Show more