Compare commits

..
Author SHA1 Message Date
asarium 34bcb03ef8 Add text rendering using signed distance fonts
Signed distance fonts have the advantage that they can be used to apply
complicated effects at runtime without having to rerender the text on
the CPU. This would make it possible to add support for rendering the
outline of the text using a different color but this currently only
renders the text like before.
2017-12-19 13:22:50 +01:00
1357 changed files with 50133 additions and 230512 deletions

No files matched your search

-182
View File
@@ -1,182 +0,0 @@
version: 2
references:
container_config: &container_config
docker:
- image: "debian:stretch"
working_directory: /root/build
restore_repo: &restore_repo
restore_cache:
keys:
- source-repo-{{ .Branch }}-{{ .Revision }}
- source-repo-{{ .Branch }}
- source-repo
cmake_configure: &cmake_configure
run:
name: Creating Build Files
command: |
mkdir build
cd build
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
if [[ "$CC" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
fi
eval $CC --version
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
compile: &compile
run:
name: Compiling Source code
command: |
cd build
ninja -k 20 all
run_tests: &run_tests
run:
name: Run unit tests
command: |
./build/bin/unittests --gtest_shuffle
compile_steps: &compile_steps
steps:
- *restore_repo
- *cmake_configure
- *compile
- *run_tests
jobs:
checkout_code:
<<: *container_config
steps:
- run:
name: Installing Git
command: 'apt-get update && apt-get -yq install git'
- *restore_repo
- checkout
- run:
name: Updating submodules
command: 'git submodule update --init --recursive'
- save_cache:
key: source-repo-{{ .Branch }}-{{ .Revision }}
paths:
- .
build_gcc_lowest_debug:
docker:
- image: asarium/fso_compile:gcc-lowest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Debug
<<: *compile_steps
build_gcc_lowest_release:
docker:
- image: asarium/fso_compile:gcc-lowest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Release
<<: *compile_steps
build_gcc_latest_debug:
docker:
- image: asarium/fso_compile:gcc-latest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Debug
<<: *compile_steps
build_gcc_latest_release:
docker:
- image: asarium/fso_compile:gcc-latest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Release
<<: *compile_steps
build_clang_latest_debug:
docker:
- image: asarium/fso_compile:clang-latest
working_directory: /root/build
environment:
CC: clang-8
CXX: clang++-8
CONFIGURATION: Debug
<<: *compile_steps
build_clang_latest_release:
docker:
- image: asarium/fso_compile:clang-latest
working_directory: /root/build
environment:
CC: clang-8
CXX: clang++-8
CONFIGURATION: Release
<<: *compile_steps
build_clang_lowest_debug:
docker:
- image: asarium/fso_compile:clang-lowest
working_directory: /root/build
environment:
CC: clang
CXX: clang++
CONFIGURATION: Debug
<<: *compile_steps
build_clang_lowest_release:
docker:
- image: asarium/fso_compile:clang-lowest
working_directory: /root/build
environment:
CC: clang
CXX: clang++
CONFIGURATION: Release
<<: *compile_steps
workflows:
version: 2
build_test:
jobs:
- checkout_code
- build_gcc_lowest_debug:
requires:
- checkout_code
- build_gcc_lowest_release:
requires:
- checkout_code
- build_gcc_latest_debug:
requires:
- checkout_code
- build_gcc_latest_release:
requires:
- checkout_code
- build_clang_latest_debug:
requires:
- checkout_code
- build_clang_latest_release:
requires:
- checkout_code
- build_clang_lowest_debug:
requires:
- checkout_code
- build_clang_lowest_release:
requires:
- checkout_code
-103
View File
@@ -1,103 +0,0 @@
---
Language: Cpp
Standard: Cpp11
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowAllArgumentsOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^(<.*\.(h|hh|hpp)>)$' # Includes of external libraries
Priority: 5
- Regex: '^(<.*>)$' # standard library includes (won't match deprecated C headers)
Priority: 6
- Regex: '^"globalincs\/.*\.h"$' # globalincs always come first
Priority: 1
- Regex: '^"[^/]*\.(h)"$' # Local includes
Priority: 2
- Regex: '^".*\.(h)"$' # standard engine includes
Priority: 3
- Regex: '.*' # Catch all in case something is unhandled above
Priority: 4
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: ForContinuationAndIndentation
...
-40
View File
@@ -1,40 +0,0 @@
---
Checks: "-*,\
modernize-*,\
-modernize-raw-string-literal,\
-modernize-use-using,\
-modernize-make-unique,\
-modernize-use-trailing-return-type,\
-modernize-avoid-c-arrays,\
performance-*,\
-performance-type-promotion-in-math-fn,\
misc-*,\
-misc-macro-parentheses,\
-misc-misplaced-widening-cast,\
-misc-static-assert,\
-misc-unused-parameters,\
-misc-non-private-member-variables-in-classes,\
readability-*,\
-readability-function-size,\
-readability-identifier-naming,\
-readability-implicit-bool-conversion,\
-readability-inconsistent-declaration-parameter-name,\
-readability-isolate-declaration,\
-readability-magic-numbers,\
-readability-named-parameter,\
-readability-qualified-auto,\
-readability-uppercase-literal-suffix,\
-readability-else-after-return,\
"
WarningsAsErrors: ''
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
AnalyzeTemporaryDtors: false
CheckOptions:
- key: 'misc-assert-side-effect.AssertMacros'
value: 'assert,Assert,Assertion'
- key: 'modernize-use-emplace.ContainersWithPushBack'
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
- key: 'readability-braces-around-statements.ShortStatementLines'
value: '4' # Avoid flagging simple if (...) return false; statements
...
-2
View File
@@ -1,2 +0,0 @@
/build
/.git
-21
View File
@@ -1,21 +0,0 @@
build:
image: teaci/msys$$arch
pull: true
shell: mingw$$arch
commands:
- git submodule update --init --recursive
- if [ $$arch = 32 ]; then target=i686; fi
- if [ $$arch = 64 ]; then target=x86_64; fi
- pacman -S --needed --noconfirm --noprogressbar mingw-w64-${target}-pkg-config mingw-w64-${target}-cmake
- mkdir build && cd build
- cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=$$CONFIGURATION -DFSO_USE_SPEECH=OFF -DFSO_USE_VOICEREC=OFF -DFSO_FATAL_WARNINGS=ON -DFSO_BUILD_FRED2=OFF ..
- make -j$(nproc) all
matrix:
arch:
- 64
- 32
CONFIGURATION:
- Debug
- Release
-4
View File
@@ -5,7 +5,3 @@ indent_style = tab
[*.sdr]
indent_style = tab
[*.{yml,yaml}]
indent_style = space
indent_size = 2
-7
View File
@@ -1,7 +0,0 @@
# Default for everything
# * text=auto
# For the test data and built-in files to make them consistent on all platforms
*.tbl text eol=lf
*.tbm text eol=lf
*.sdr text eol=lf
-130
View File
@@ -1,130 +0,0 @@
name: Check a pull request
on: [pull_request]
jobs:
build_linux:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [gcc-5, gcc-9, clang-4.0]
name: Linux
runs-on: ubuntu-16.04
steps:
- name: Prepare Environment
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo add-apt-repository ppa:beineri/opt-qt571-xenial
sudo add-apt-repository ppa:msulikowski/valgrind # For fixing a bug with valgrind 3.11 which does not recognize the rdrand instruction
sudo apt-get -yq update
sudo apt-get -yq install cmake ninja-build libopenal-dev libreadline6-dev libpng12-dev libjpeg62-dev liblua5.1-0-dev libjansson-dev libsdl2-dev libfreetype6-dev valgrind qt57base g++-5 g++-9 clang-4.0 clang-tidy-4.0 libc++-dev libc++abi-dev
# Fix a header bug present in ubuntu...
sudo ln -s /usr/include/libcxxabi/__cxxabi_config.h /usr/include/c++/v1/__cxxabi_config.h
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
run: |
if [ "$COMPILER" = "gcc-5" ]; then
export CC=gcc-5
export CXX=g++-5
fi
if [ "$COMPILER" = "gcc-9" ]; then
export CC=gcc-9
export CXX=g++-9
fi
if [ "$COMPILER" = "clang-4.0" ]; then
export CC=clang-4.0
export CXX=clang++-4.0
fi
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
if [[ "$CC" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
fi
mkdir build
cd build
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON ..
- name: Compile
working-directory: ./build
run: ninja -k 20 all
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
run: |
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$GITHUB_WORKSPACE/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
build_windows:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [MSVC]
arch: [Win32, x64]
name: Windows
runs-on: windows-2019
steps:
- name: Prepare Environment
run: choco install ninja
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
ARCHITECTURE: ${{ matrix.arch }}
shell: bash
run: |
mkdir build
cd build
if [ "$COMPILER" = "MinGW" ]; then
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DFSO_BUILD_FRED2="OFF" -DCMAKE_BUILD_TYPE=$CONFIGURATION -G "Ninja" ..
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" -T "v142" -A "$ARCHITECTURE" ..
fi
- name: Compile
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
shell: bash
run: |
if [ "$COMPILER" = "MinGW" ]; then
cmake --build . --config "$CONFIGURATION"
else
cmake --build . --config "$CONFIGURATION" -- /verbosity:minimal
fi
- name: Run Tests
working-directory: ./build
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: ${{ matrix.compiler }}
shell: bash
run: |
if [ "$COMPILER" = "MinGW" ]; then
./bin/unittests --gtest_shuffle
else
"./bin/$CONFIGURATION/unittests" --gtest_shuffle
fi
@@ -1,48 +0,0 @@
name: Publish Standalone docker image
on:
push:
tags:
- '*'
jobs:
build_images:
strategy:
matrix:
configuration: [FastDebug, Release]
include:
- configuration: FastDebug
latest_tag: latest_debug
nightly_tag: nightly_debug
release_tag: release_debug
- configuration: Release
latest_tag: latest
nightly_tag: nightly
release_tag: release
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Docker login
run: echo ${{ secrets.DOCKER_ACCESSTOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Docker build
run: docker build --build-arg build_type=${{ matrix.configuration }} -f docker/standalone/Dockerfile -t ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.latest_tag }} .
- name: Push latest tag
run: |
docker push ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.latest_tag }}
- name: Push nightly tag
if: contains(github.ref, 'refs/tags/nightly_')
run: |
docker tag ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.latest_tag }} ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.nightly_tag }}
docker push ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.nightly_tag }}
- name: Push release tag
if: contains(github.ref, 'refs/tags/release_')
run: |
docker tag ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.latest_tag }} ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.release_tag }}
docker push ${{ secrets.DOCKER_REPOSITORY }}:${{ matrix.release_tag }}
+3 -5
View File
@@ -26,6 +26,9 @@
*.unsuccessfulbuild
ipch/
[Oo]bj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
*.VC.db
*.VC.VC.opendb
@@ -253,8 +256,3 @@ CMakeSettings.json
# Weird files created by Linux
.fuse_hidden*
# This gets ignored by one of the rules above for some reason...
!/code/scripting/lua/LuaConvert.h
!/code/debugconsole/
!/docker/build
-3
View File
@@ -1,6 +1,3 @@
[submodule "cmake/external/rpavlik-cmake-modules"]
path = cmake/external/rpavlik-cmake-modules
url = https://github.com/asarium/cmake-modules.git
[submodule "lib/libRocket"]
path = lib/libRocket
url = https://github.com/asarium/libRocket.git
+110 -187
View File
@@ -1,201 +1,124 @@
language: bash
language: generic
sudo: required
dist: xenial
dist: trusty
cache:
directories:
- $HOME/cmake-3.8
- $HOME/.ccache
- $HOME/curl_cache
directories:
- $HOME/cmake
addons:
apt:
packages: &global_deps
- ninja-build
- libopenal-dev
- libreadline6-dev
- libpng12-dev
- libjpeg62-dev
- liblua5.1-0-dev
- libjansson-dev
- libsdl2-dev
- libfreetype6-dev
- qt57base
coverity_scan:
project:
name: "scp-fs2open/fs2open.github.com"
notification_email: [email protected]
build_command: "ci/travis/script.sh"
# must match TRAVIS_BRANCH check below
branch_pattern: coverity_scan
apt:
packages: &global_deps
- ninja-build
- libopenal-dev
- libreadline6-dev
- libpng12-dev
- libjpeg62-dev
- liblua5.1-0-dev
- libjansson-dev
- libsdl2-dev
- valgrind
coverity_scan:
project:
name: "scp-fs2open/fs2open.github.com"
notification_email: niffiwan.scp@gmail.com
build_command: "ci/travis/script.sh"
# must match TRAVIS_BRANCH check below
branch_pattern: coverity_scan
env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
# also note that fork's don't get access to secure keys
# you have to test using a branch in the main repo
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
# These declarations set INDIEGAMES_USER and INDIEGAMES_PASSWORD for uploading nightly builds to the indiegames server
- secure: "lUuRu8XIi8MKNf1ebOfyC4iVEpPyASojJIDWXRo2bNqEF4ILAljXdkVeXeN6H5yKCHD52cxCNTtyePIG/o3p3QEuGSVud9bDS3D7LaQicLETGGrsw3l07U49gF2OKHXGopg0MzBbZUU9QmhoFTAe8t6PV9NDuEayYCheqvTqjZg="
- secure: "E/DHLYcPK/hBUqxBYYlUqp5sjgvIqY5A0qRHyQ4bmjsB+WB/Xx71bGCSiF7hk6lTxar1ZI1i5RAXXh9AIvNVaYAIdEOlCP+q3gvwCYuc5naZEKmkxlUCf0oEL4O9Fye93A/3VkFHuBdC1TGPYYf69m4W5r4367wWO9dPRIdWpJA="
# These declarations set DATACORDER_USER and DATACORDER_PASSWORD
- secure: "dpBH/dDN3bmU/NFlh+2v9isNx9wX0ocoRy+W+kBXRH32sosUGp26REhMqgVRpBNP5oxPBU8ic5bEogxAYWCB+0xUygBbkxAwyMPgoA34s0OXdTCY/ofw14ni8qqV2Ffy7fQJbP/jkMURyiMHx3kBTxNv3YjxKJqLnOuOMlQLpT8="
- secure: "tLMRBD1Ufp5iKNwlqPDVbbuczgusaXNoBJyAnPATpJq2YwlkW4j3PqP9rW5vd85+52xam2EOP20w9PoBR5J6FLdiXRu4Lf7yCEhSHFAgowVqQj8QcJpPlyXr90bM4emFGrGqpdxVwxyQ5AFhKwLuEZKsI14GYLN+UMEwpNCMing="
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
# also note that fork's don't get access to secure keys
# you have to test using a branch in the main repo
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
# These declarations set INDIEGAMES_USER and INDIEGAMES_PASSWORD for uploading nightly builds to the indiegames server
- secure: "lUuRu8XIi8MKNf1ebOfyC4iVEpPyASojJIDWXRo2bNqEF4ILAljXdkVeXeN6H5yKCHD52cxCNTtyePIG/o3p3QEuGSVud9bDS3D7LaQicLETGGrsw3l07U49gF2OKHXGopg0MzBbZUU9QmhoFTAe8t6PV9NDuEayYCheqvTqjZg="
- secure: "E/DHLYcPK/hBUqxBYYlUqp5sjgvIqY5A0qRHyQ4bmjsB+WB/Xx71bGCSiF7hk6lTxar1ZI1i5RAXXh9AIvNVaYAIdEOlCP+q3gvwCYuc5naZEKmkxlUCf0oEL4O9Fye93A/3VkFHuBdC1TGPYYf69m4W5r4367wWO9dPRIdWpJA="
# These declarations set FS2DOWNLOADS_USER and FS2DOWNLOADS_PASSWORD
- secure: "h6GbMX2jLsW1bS9fCM9fthOSJ1nfQQIRWi6EUH2p8u4NFLD5Bfi/C8JhQPKHUzyo3wvKkSHl+PsW7bgr1oXLusRwAur/dtv2N3imqvtbfIz305b00hZlsvbcYmQmUzQFSAdOGShK57JJ5aKQKccaUBP25KqB7Q+JaqBRdaMBS54="
- secure: "fUDAPAUUaaYZy8I4zU3SJ0JcK7aw4eb6eTdaEr7LyNyTMSfPgwY6P1MrbSQC0lJNQIUQ5ffjdxE5g7D7OYpoJF9L14ni4UY8t2QASt7kmpgcYihmjeuYy8FQXgmFG8CTxiWBPKTybZJ7voQcvIvRaNG7b2wM9PMfc5lRIondB6c="
deploy:
- provider: releases
api_key:
secure: "q619+eQTe7lv8UVphK4OIzU8Jw84KBbVkuprN2sWIubRcV3IbZr2+WahJoUMt+nyhiy3YjDYtstO2ZgkxupwnZgwGUBVIiD1c4SPuyy+HTjNMOtiVsEUHT2hf+xPAemWpTlK5HcwhMmHAOh6rt6dEj57QOg0gcmGiwD/tCbEriA="
skip_cleanup: true
file_glob: true
file: "/tmp/builds/*"
on:
condition: '"$RELEASE_BUILD" == true'
tags: true
- provider: releases
api_key:
secure: "Wdt4Ccefo7a0ZDjEJQJgpghh7n72FtNJuKSAPUvoz4gtEX6Ct9J8yJI1t9V3jE3CTbbLJ21/Q6eZRDfT7UfNJe5DdepoJsP9DeFhKMWqQCq+AChqQWlm0KeZAffJoJreL8vXYhnRYcLT9ceZHEH6AqwN9TPV+xJziGPISAkYNZ8="
skip_cleanup: true
file_glob: true
file: "/tmp/builds/*"
on:
condition: '"$RELEASE_BUILD" == true'
tags: true
- provider: script
script: bash ci/travis/ftp_deploy.sh
on:
condition: '"$NIGHTLY_BUILD" == true'
tags: true
- provider: script
script: bash ci/travis/ftp_deploy.sh
on:
condition: '"$NIGHTLY_BUILD" == true'
tags: true
- provider: script
skip_cleanup: true
script: bash ci/travis/ftp_deploy.sh
on:
condition: $TEST_BUILD = true
all_branches: true
- provider: script
skip_cleanup: true
script: bash ci/travis/ftp_deploy.sh
on:
condition: $TEST_BUILD = true
all_branches: true
matrix:
include:
# note that gcc Debug MUST be 1st for Coverity
- os: linux
env: CONFIGURATION="Debug" CC=gcc-5 CXX=g++-5
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Debug" CC=gcc-9 CXX=g++-9
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- g++-9
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCLANG_USE_LIBCXX=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- clang-4.0
- libc++-dev
- libc++abi-dev
- os: linux
env: CONFIGURATION="Debug" CC=clang-9 CXX=clang++-9 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-9
script:
- ./ci/travis/script.sh
- ./ci/travis/clang_tidy.sh
- os: osx
env: CONFIGURATION="Debug"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
- os: linux
env: CONFIGURATION="Release" CC=gcc-5 CXX=g++-5
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Release" CC=gcc-9 CXX=g++-9
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- g++-9
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCLANG_USE_LIBCXX=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- clang-4.0
- libc++-dev
- libc++abi-dev
- os: linux
env: CONFIGURATION="Release" CC=clang-9 CXX=clang++-9 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-9
script:
- ./ci/travis/script.sh
- ./ci/travis/clang_tidy.sh
- os: osx
env: CONFIGURATION="Release"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
# There is a GCC compiler bug with MinGW that causes compilation failures on Windows at the moment
allow_failures:
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
fast_finish: true
include:
# note that gcc Debug MUST be 1st for Coverity
- os: linux
env: CONFIGURATION="Debug" CC=gcc-5 CXX=g++-5
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-3.6 CXX=clang++-3.6
addons:
apt:
sources:
- llvm-toolchain-precise
packages:
- clang-3.6
- libc++-dev
- *global_deps
- os: osx
env: CONFIGURATION="Debug"
- os: linux
env: CONFIGURATION="Release" CC=gcc-5 CXX=g++-5
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-3.6 CXX=clang++-3.6
addons:
apt:
sources:
- llvm-toolchain-precise
packages:
- clang-3.6
- libc++-dev
- *global_deps
- os: osx
env: CONFIGURATION="Release"
before_install:
# ugly hack; if running a coverity scan abort all except the 1st build
# see note re gcc compiler above needing to be 1st
# also note that branch_pattern & the TRAVIS_BRANCH check must match
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
# build process
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
- source "./ci/travis/check_release.sh"
- "./ci/travis/before_install.sh"
# ugly hack; if running a coverity scan abort all except the 1st build
# see note re gcc compiler above needing to be 1st
# also note that branch_pattern & the TRAVIS_BRANCH check must match
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
# build process
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
- source "./ci/travis/check_release.sh"
- "./ci/travis/before_install.sh"
install:
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then export PATH="/c/Program Files/CMake/bin":$PATH; fi
- "./ci/travis/install.sh"
- export PATH=$HOME/cmake-3.6/bin:$PATH
- "./ci/travis/install.sh"
- export PATH=$HOME/cmake/bin:$PATH
before_script:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
- "./ci/travis/before_script.sh"
- "./ci/travis/before_script.sh"
script:
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
+29
View File
@@ -0,0 +1,29 @@
Original source (Freespace 2) by Volition, Inc.; see "credits.tbl"
Modifications by the FreeSpace Source Code Project (FSSCP)
http://fs2source.warpcore.org
FS2_OPEN STAFF:
Project leader:
Edward "Inquisitor" Gardner
Programmers:
"Bobboau"
Dennis "DTP" Pedersen
Ian "Goober5000" Warfield
Joe "Righteous1" Dowd
Mike "penguin" Harris
"Mysterial"
"PhReAk"
Thomas "Random Tiger" Whittaker
Will "Unknown PLayer" Rousnel
"WMCoolmon"
Web support:
Icefire and the staff at Volitionwatch.com
Alex "Thunder" Avery and the staff at Hard Light Productions
Special thanks to:
Volition for making FS2 such a great game
Dave Baranec for giving us the code and keeping us sanity checked
-41
View File
@@ -1,41 +0,0 @@
## FreeSpace
FreeSpace: The Great War (Released 1998) and FreeSpace 2 (1999) are mission-based space combat simulators, like X-Wing/TIE Fighter and Wing Commander. Among the greatest games of the genre, they were also effectively the last.
The FreeSpace series follows humanity and their Vasudan allies as they fight to withstand the xenocidal, enigmatic Shivans, a species of unknown origin, vast technological capability, and seemingly limitless malice.
## FreeSpace Open
Thanks to Volition's generosity, we've continued development of FreeSpace 2 as FreeSpace Open, building graphical enhancements to bring the original games up to modern standards, telling new stories set in the FreeSpace universe and original worlds, and creating spectacular total conversions that let players fly in the beloved universes of Babylon 5, Battlestar Galactica, Wing Commander, and Star Wars.
## Hard-Light Productions
HLP is a fan community built on love and open-source code. We're dedicated to bringing modders together and giving them a place to share their own hard work and draw inspiration from the work of others. Thanks to Volition's generosity, we've continued development of FreeSpace 2 as FreeSpace Open, building graphical enhancements to bring the original games up to modern standards, telling new stories set in the FreeSpace universe and original worlds, and creating spectacular total conversions that let players fly in the beloved universes of Babylon 5, Battlestar Galactica, Wing Commander, and Star Wars.
Find us at:
- Our [website](http://www.hard-light.net/) and [forums](http://www.hard-light.net/forums/)
- [Discord](https://discord.gg/YNVP3WR)
- [Facebook](https://www.facebook.com/groups/Hardlightproductions/)
- [Youtube](https://www.youtube.com/channel/UCxKkd609hDtY6yNetR1iT4w)
- [Reddit](https://www.reddit.com/r/freespace/)
- [Twitter](https://twitter.com/hardlightpro)
- [IRC](irc://irc.esper.net/hard-light)
## How to get the game
FreeSpace Open requires a retail installation of FreeSpace 2, which is available at the following stores:
- [GOG.com](https://www.gog.com/game/freespace_2)
- [Steam](https://store.steampowered.com/app/273620/Freespace_2/)
After installing retail FS2, use [Knossos](https://fsnebula.org/knossos/) to upgrade to the most recent release of FSO. Knossos is an advanced mod manager and launcher for FSO.
## Improvements
The new open source game engine has several distingushing features including:
- Linux and Mac OS X support
- OpenGL support
- OpenAL audio support
- Easy mod installation
- OGG support
- Hardware transform, clipping, and lighting
## The FreeSpace Upgrade Project
While the SCP improves the code of the game engine to enable new and exciting features, the FreeSpace Upgrade Project (FSU) creates material that takes advantage of the improved game engine.
The FSU improves the ships, effects, and background elements of FreeSpace 2. Every now and then these improvements are released as a pack called MediaVPs. These assorted improvements enhance the graphics of the game.
While the best way to experience the FSU is by playing the game with it, you can watch this [comparison video](https://www.youtube.com/watch?v=RM1YC_gK-qo) between 1999 and 2019 to have an idea of how much more beautiful FSU makes the game.
^(Much of this content was pulled from existing sources, such as InsaneBaron's "What Is Hard Light Productions" [thread](https://www.hard-light.net/forums/index.php?topic=86650.0), the Wiki's [Getting Started article](https://wiki.hard-light.net/index.php/Getting_started) and more.)
-8
View File
@@ -1,8 +0,0 @@
Original source (Freespace 2) by Volition, Inc.; see "`credits.tbl`"
Modifications by the FreeSpace 2 Source Code Project [(FSO SCP)](https://www.hard-light.net/forums/index.php?board=50.0)
[Project Contributors](https://github.com/scp-fs2open/fs2open.github.com/graphs/contributors)
Special thanks to:
Volition for making FS2 such a great game
Dave Baranec for giving us the code and keeping us sanity checked
+8 -28
View File
@@ -10,7 +10,7 @@ endif()
include(cmake/util.cmake)
# Set a few policies
set_policy(CMP0051 NEW)
set_policy(CMP0051 OLD)
set_policy(CMP0053 NEW)
set_policy(CMP0054 NEW)
@@ -40,14 +40,6 @@ set(CMAKE_CONFIGURATION_TYPES Debug Release FastDebug CACHE STRING "Available co
PROJECT(FS2_Open)
find_program(CCACHE_PROGRAM ccache)
# Currently only GCC support ccache properly without generating additional warnings
if(CCACHE_PROGRAM AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
message(STATUS "Using ccache for compilation: ${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_PROGRAM}")
endif()
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
@@ -84,6 +76,7 @@ IF (WIN32)
OPTION(FSO_BUILD_FRED2 "Build FRED2 binary" ON)
elseif(UNIX)
option(FSO_BUILD_APPIMAGE "Build an AppImage package" OFF)
set(APPIMAGE_ASSISTANT "" CACHE STRING "The root directory of an AppImage clone.")
ENDIF(WIN32)
OPTION(FSO_BUILD_TOOLS "Build tools related to FSO" OFF)
@@ -92,7 +85,7 @@ OPTION(FSO_BUILD_TESTS "Build unit tests" OFF)
OPTION(FSO_DEVELOPMENT_MODE "Generate binaries in development mode, only use if you know what you're doing!" OFF)
OPTION(FSO_BUILD_QTFRED "Build qtFRED2 binary" OFF)
OPTION(FSO_BUILD_WXFRED2 "Build wxFRED2 binary" OFF)
IF(WIN32 OR APPLE)
# On windows and mac the default should be to always build the included libraries
@@ -115,12 +108,6 @@ SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generate
option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF)
option(ENABLE_COTIRE "Enable cotire for faster compilation. Enabled by default." ON)
option(FSO_RELEASE_LOGGING "Enable logging output for release builds" OFF)
OPTION(FSO_BUILD_WITH_FFMPEG "Enable the usage of FFmpeg for sound and custscenes" ON)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
@@ -128,9 +115,6 @@ MARK_AS_ADVANCED(FORCE FSO_USE_LUAJIT)
MARK_AS_ADVANCED(FORCE FSO_DEVELOPMENT_MODE)
MARK_AS_ADVANCED(FORCE FSO_FATAL_WARNINGS)
mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
mark_as_advanced(FORCE ENABLE_COTIRE)
mark_as_advanced(FORCE FSO_RELEASE_LOGGING)
mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
# Include cotire file from https://github.com/sakra/cotire/
include(cotire)
@@ -150,8 +134,6 @@ if(FSO_BUILD_APPIMAGE)
include(appimage)
endif()
include(clang-tidy)
# This includes source code for some tools, either used in the build or also for something else
ADD_SUBDIRECTORY(tools)
@@ -165,9 +147,9 @@ IF(FSO_BUILD_FRED2)
ADD_SUBDIRECTORY(fred2)
ENDIF(FSO_BUILD_FRED2)
IF(FSO_BUILD_QTFRED)
ADD_SUBDIRECTORY(qtfred)
ENDIF()
IF(FSO_BUILD_WXFRED2)
ADD_SUBDIRECTORY(wxfred2)
ENDIF(FSO_BUILD_WXFRED2)
if(FSO_BUILD_TESTS)
add_subdirectory(test)
@@ -194,14 +176,12 @@ include(doxygen)
# Print used options to log
IF (WIN32)
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
message(STATUS "Using text to speech: ${FSO_USE_SPEECH}")
message(STATUS "Using voice recogition: ${FSO_USE_VOICEREC}")
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
elseif(UNIX)
message(STATUS "Building AppImage: ${FSO_BUILD_APPIMAGE}")
ENDIF()
message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}")
message(STATUS "Building qtFRED: ${FSO_BUILD_QTFRED}")
message(STATUS "Building wxFRED: ${FSO_BUILD_WXFRED2}")
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
message(STATUS "Release logging: ${FSO_RELEASE_LOGGING}")
message(STATUS "With FFmpeg: ${FSO_BUILD_WITH_FFMPEG}")
+4 -5
View File
@@ -1,15 +1,14 @@
Volition Copyright (applies to original FreeSpace2 source code
developed and released by Volition):
>Copyright (C) Volition, Inc. 1999. All rights reserved.
>
>All source code herein is the property of Volition, Inc. You may not
"Copyright (C) Volition, Inc. 1999. All rights reserved.
All source code herein is the property of Volition, Inc. You may not
sell or otherwise commercially exploit the source or things you
created based on the source.
created based on the source."
Modifications by members of the FreeSpace Source Code Project are
released under whatever terms the individual authors choose, but the
above notice continues to apply to all fs2_open code.
See [**Licensing**](https://github.com/scp-fs2open/fs2open.github.com/wiki/Licensing) for more information.
+19 -128
View File
@@ -1,131 +1,23 @@
# Changelog
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/).
## [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.
### Added
- Full Unicode text support: You can now use non-ASCII characters without having to worry about special fonts and special characters. This is an opt-in mod flag.
- Translation features for making it easier to only distribute one version of a mod which includes all languages.
- OpenAL Soft is included by default in binary distributions of FSO now.
- System for dynamically adding new SEXPs. With this a Lua script can expose functionality to the mission which can be used exactly the same as a standard SEXP with all the usual editing features in FRED.
- Support for displaying decals on the surface of an object.
- Integrated support for the [Discord Rich Presence API](https://discordapp.com/rich-presence).
- New markup based user interface system using [libRocket](https://github.com/libRocket/libRocket).
### Changed
- Exposed the movie player to the scripting API for advanced display features
- Various OpenGL optimizations for better graphics performance:
- Animations now use texture arrays
- Model uniforms get sent to the GPU using uniform buffers for less overhead
- Various other minor changes
- Converted pilot files from custom binary format to JSON
- Replaced Blinn-Phong BRDF with GGX BRDF
### 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.
- Physically-Based Rendering (PBR): This upgrade of our rendering engine allows to use [PBR](https://en.wikipedia.org/wiki/Physically_based_rendering) assets to make models look more realistic and allow more artistic freedom for modders since they have more control over how a model looks. This also added support for HDR lighting which should improve the overall graphics experience.
- Native particle systems: Particles have always been supported by FSO but the effects that could be created by them were very limited. There were some attempts to fix this by using Lua scripting for more advanced features but that suffered from performance issues. With these new particle systems that feature has been integrated directly into the engine which should improve performance and allow for better effects in the future.
- TrueType Font support: [TrueType](https://en.wikipedia.org/wiki/TrueType) fonts improve the text rendering capabilities of FSO by allowing to use freely scaleable font faces instead of the previous bitmap fonts.
### Changed
- We now use SDL2 on all platforms: SDL is a library for abstracting away the differences between different platforms. We now use SDL2 for all platforms which reduces the amount of platform-specific code tremendously and should result in better usability on all platforms. This was a major change that has been in development for several years. Here are a few key features that were added:
- Pilot and configuration data is now stored in the correct location across all platforms (this allows to run FSO on Windows from the Program Files directory without administrator rights)
- All platforms now use the ini files for storing settings. This fixes a lot of issues with the registry on Windows.
- Better support for input devices. Since SDL handles keyboard, mouse and joystick input we now have better support on newer OS versions. Note: This does not mean that we support multiple joysticks (yet). There is ongoing development effort to support this but this release does not have that yet.
- CMake build system generation: This isn't relevant for players but we are now using [CMake](https://en.wikipedia.org/wiki/CMake) for handling compiling our builds. This improves cross-platform support and allows to implement advanced compilation features across multiple platforms. Modders will like the new "FastDebug" builds which are like the previous "Debug" builds but are compiled with all the optimizations of normal Release builds. That should make modding a lot easier since you can now debug your mod with almost the same performance as a Release build.
- Improved shield effects: Rendering of the shields is now handled by special shaders which improves the overall quality of the effects and allows more freedom for future effects.
- Use OpenGL Core Profile for rendering: This is another major graphical upgrade which adds support for the OpenGL Core profile across all platforms (this was also made possible by the SDL2 integration). This upgrade allows us to use more modern rendering techniques and is especially useful for our Linux users who use the open-source Mesa drivers since our shaders failed to compile with those drivers. Now everyone will be able to enjoy the new graphical features added in this and previous releases. This also made some internal changes to how we handle rendering which improves the usability of our rendering engine within our code.
- Use FFmpeg for video & audio decoding: [FFmpeg](https://www.ffmpeg.org/) is a multi-media library which exposes functionality for decoding video and audio files to their raw form so that we can use that data. Thanks to this library we can now play 1080p cutscenes without any stuttering or frame-timing issues. It also allows to use more advanced audio and video codecs such as H.264 for video or Opus for audio.
## [3.7.4] - 2016-07-04 ([Release thread](http://www.hard-light.net/forums/index.php?topic=92181.0))
### Changed
- Major graphics update including deferred lighting and shadows
- Enhanced sound (up to 128 channels)
### 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
- Autospread on model point shields
- WebUI based multiplayer standalone server (for non-Windows platforms)
- Toggle subsytem scanning, scannable, cargo revealed, hidden from sensors, stealth and friendly stealth added to the `alter-ship-flag` SEXP
- Support added to add more languages besides English, French, German and Polish, leading the way to better localization!
- `player-is-cheating` SEXP
- New ship flag to enable smarter AI use of afterburners. Now it can use them while flying waypoints or attacking capital ships (use the `free-afterburner-use` flag with `alter-ship-flag`)
- Experimental configurations to make AVX builds (see [this post](http://www.hard-light.net/forums/index.php?topic=85566.0) for more explanations)
- Frame profiling code, see what exactly is slowing down FreeSpace. (Mostly for devs or coders)
### Changed
- Unstretched interface screens
- Automatically non stretched HUD gauges and simpler modder options for placing HUD gauges
- `show-subtitle-text` can now display messages as well as raw text
- Allow a user-specified number of credit images
- event.log can now snapshot events checked in a frame and record the status of an event the previous time it was checked as well as the current state
- Allow the specification of the positions of medals, callsigns and labels on the medal screen.
- The number of medals is now dynamic!
- `is-facing` now works for things that aren't ships (like waypoints!)
- allowing `fade-in` and `fade-out` sexps to use any color, not just black, white and red.
## [3.7.0] - 2013-08-31 ([Release thread](http://www.hard-light.net/forums/index.php?topic=85435.0))
### Major Change
- New Flexible Pilot Save File Code (combines single/multi pilots & allows safe switching between unfinished campaigns)
### Changed
- 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
- Allow modders to set a [mood](http://www.hard-light.net/forums/index.php?topic=81991.msg1639770#msg1639770) for builtin messages and then switch the mood for the mission on the fly using a SEXP
- Allow modders to set the chance of builtin messages being sent, how many will be sent per mission and how long is the delay between two messages
- Allow campaigns to be hidden in the campaign and tech rooms ([Game settings.tbl](https://wiki.hard-light.net/index.php/Game_settings.tbl#.23Ignored_Campaign_File_Names))
- Allow mods to set a default campaign ([Game settings.tbl](https://wiki.hard-light.net/index.php/Game_settings.tbl#.24Default_Campaign_File_Name:))
- New SEXPs
- `set-player-orders`
- `is-event\goal-true\false-msecs-delay`
- `get\set-num-countermeasures`
- `directive-value`
- `invalidate-all-arguments`
- `validate-all-arguments`
- `has-primary-weapon`
- `has-secondary-weapon`
- [`hud-display-gauge`](http://www.hard-light.net/forums/index.php?topic=68837.msg1361711#msg1361711)
- `get-object-speed-x`
- `get-object-speed-y`
- `get-object-speed-z`
### Changed
- Major HUD gauges overhaul
- Split the Locked flag so that you can lock Ships or Weapons on the game loadout screen independently
- Mixed ammo for primary and secondary weapons - [`$Substitute`](http://www.hard-light.net/wiki/index.php/Weapons.tbl#.24Substitute:) - Allows you to have a weapon that fires other weapon ammo in a specific pattern (say a Gatling gun with tracers).
- [`show-subtitle`](https://wiki.hard-light.net/index.php/SCP_SEXPs#show-subtitle) SEXP supports custom fonts
- The active support ship limit per side is now dynamic. See [`set-support-ship`](https://wiki.hard-light.net/index.php/SCP_SEXPs#set-support-ship) for more info.
### Fixed
- Various multiplayer SEXP fixes
- `rotating-subsys-set-time` now accelerates properly
- [Fixed a whole heap of memory, logic and coding errors](http://www.hard-light.net/forums/index.php?topic=78044.0) -- using PVS-Studio: C/C++ source code analysis and checking tool
----
## [Older Changes] - Unformatted
```
ChangeLog for fs2_open. All times are UTC.
Features: September 2013
http://www.hard-light.net/forums/index.php?topic=85700.0
- show-subtitle-text can now display messages as well as raw text - Goober5000
- toggle subsytem scanning, scannable, cargo revealed, hidden from sensors, stealth and friendly stealth added to the alter-ship-flag sexp - karajorma
- Support added to add more languages besides English, French, German and Polish, leading the way to better localization! - karajorma
- event.log can now snapshot events checked in a frame and record the status of an event the previous time it was checked as well as the current state - karajorma
- added a player-is-cheating sexp - The E
- allow a user-specified number of credit images - Goober5000
- allow the specification of the positions of medals, callsigns and labels on the medal screen. - Goober5000
- lua function to check if a ship is warp capable, and access to a ship's auto-aim FOV - zookeeper
- is-facing now works for things that aren't ships (like waypoints!) - zookeeper
- experimental configurations to make AVX builds (see this post for more explainations) - The E
- new ship flag to enable smarter AI use of afterburners. Now it can use them while flying waypoints or attacking capital ships (use the free-afterburner-use flag with alter-ship-flag) - Admiral MS
- the number of medals is now dynamic! - Goober5000
- frame profiling code, see what exactly is slowing down FreeSpace. (Mostly for devs or coders) - Swifty + The E
- allowing fade-in and fade-out sexps to use any color, not just black, white and red. - Goober5000
==================================================================
( massive gap in updates, maybe this will be filled in someday...)
==================================================================
@@ -459,7 +351,7 @@ ChangeLog for fs2_open. All times are UTC.
(2.1.2.4), weapon/weapons.cpp (2.1.2.2):
Sorted out some bits and pieces. The background nebula blends now
which is nice. – RT
which is nice. – RT
2002-09-28 12:20 randomtiger
@@ -1994,4 +1886,3 @@ NOTE:
# generated by cvs2cl.pl
# cvs2cl.pl -r -S --utc -f ChangeLog2
```
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
This is still in pretty rough form.
=== for people building fs2_open:
Win32-MSVC:
Use the Freespace2.dsw workspace and build within the IDE.
Win32-MinGW:
make
Linux and other unix variants (NOT YET COMPLETE)
./configure [options]
make
=== for the project maintainers (people who need to
=== keep the makefiles up to date) and those building
=== from CVS:
./autogen.sh (should only has to be done once)
./configure [options]
make
automake v1.6.1+ and
autoconf v2.54+ are required
+32 -1
View File
@@ -7,5 +7,36 @@ FreeSpace2 *S*ource *C*ode *P*roject
Building
--
Before you do anything, make sure you have updated your git submodules, either by running `git submodule update --init --recursive` or by cloning the repository with the `--recursive` flag.<br/>
<br/>
For building you will need [CMake](http://www.cmake.org/cmake/resources/software.html). Version 3.4 is required. Once you have installed CMake you should create a build directory where the project/make files should be created, **do not create them inside the source tree!**<br>
<br>
On Windows you can use the `cmake-gui` executable to get a nice GUI, on Unix just use `cmake`. Use the newly created directory as build directory (change to this directory on Unix) and run cmake. On Windows this can be done by clicking the `Configure` button. Choose your compiler version and hit `Generate` when configuring is done. <br>
Depending on the makefile generator used build the `all` or `ALL_BUILD` target to compile the project.<br>
The main instructions for building can be found at our github wiki, on the [Building](https://github.com/scp-fs2open/fs2open.github.com/wiki/Building) page.
### Available variables to control the build
* `FSO_BUILD_WXFRED2`: Build the wxfred2 project, requires wxWidgets
* `FSO_FREESPACE_PATH`: Sets the path of your FreeSpace install, can be used to automatically run the generated executables with the correct working directory, this is an optional variable. By default this will use the value of the `FS2PATH` environment variable.
* `FSO_BUILD_TOOLS`: Build some tools related to FSO
* `CMAKE_BUILD_TYPE`: Sets the binary build type between `Debug` and `Release` (default)
#### Windows only variables
* `FSO_BUILD_FRED2`: Build FRED2, requires a Visual Studio version that ships with MFC
* `FSO_USE_SPEECH`: Build a binary with text-to-speech support
* `FSO_USE_VOICEREC`: Build a binary with voice recognition support
#### Advanced variables
You should only use these variables if you know what you're doing
* `FSO_CMAKE_DEBUG`: Print CMake debugging informations
* `FSO_BUILD_INCLUDED_LIBS`: Build libraries from the included source
* `FSO_USE_OPENALSOFT`: Use [OpenALSoft](http://kcat.strangesoft.net/openal.html) for OpenAL support
* `FSO_USE_LUAJIT`: Use [luajit](http://luajit.org/) as a replacement for lua
* `FSO_DEVELOPMENT_MODE`: Toggles some development behavior, only use if you really need it.
* `FSO_RUN_ARGUMENTS`: If you run an executable from within the project, these arguments will also be passed to the executable
* `FSO_BUILD_POSTFIX`: Sets a postfix to be added to the executable name, may be useful for release candidates.
#### Visual Studio specific variables
* `MSVC_USE_RUNTIME_DLL`: Use the DLL version of the runtime, experimental and not well tested.
* `MSVC_SIMD_INSTRUCTIONS`: The instruction set the executables will be optimized for.
### Generating an installation package
CMake can automatically generate installation packages of the project. To do this you will just need to run the `package` target of the build system and the package will be placed inside your build directory. On Windows you will have to install [NSIS](http://nsis.sourceforge.net/Main_Page) to use this.
-18
View File
@@ -1,18 +0,0 @@
#Updating Documentation
####The goal of this file is simply to offer a comprehensive checklist of things we must check when updating the documentation.
1. Changelog:
- Is [Changelog.md](https://github.com/scp-fs2open/fs2open.github.com/blob/master/Changelog.md) up-to-date with the latest release?
- Is it in the proper [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format?
2. Build instructions:
- If a programmer who never built FSO before read the build instruction at [Readme.md](https://github.com/scp-fs2open/fs2open.github.com/blob/master/Readme.md), would they manage to build FSO?
- Is the information in the file up-to-date regarding other matters (such as versions of tools mentioned, links to other guides, etc.)?
- Is the information in the [Building](https://github.com/scp-fs2open/fs2open.github.com/wiki/Building) article, and its sub-articles, still up-to-date?
3. Forums:
- Does the [Forum](https://www.hard-light.net/forums/index.php?board=50.0) contain enough clear information to help a new developer find their way into the up-to-date instructions?
- Is there anything that might mislead a new developer to stumble onto old tools, dead links and/or old versions of the project?
4. General documentation files:
- Is the information in the following files up-to-date?
- [About.md](https://github.com/scp-fs2open/fs2open.github.com/blob/master/About.md) (Should contain general information about FS, FS2, HLP, FSO and FSU)
- [Authors.md](https://github.com/scp-fs2open/fs2open.github.com/blob/master/Authors.md) (Should contain information about the original developers, a way to see FSO's contributors, and special thanks to Volition and Dave Baranec)
- [Copying.md](https://github.com/scp-fs2open/fs2open.github.com/blob/master/Copying.md) (Should contain Volition's Copyright terms and a way to check FSO's Licensing info)
+17 -18
View File
@@ -1,5 +1,4 @@
version: 1.0.0.{build}
image: Visual Studio 2015
configuration:
- Debug
- Release
@@ -7,13 +6,11 @@ clone_depth: 10
environment:
matrix:
- BuildID: 0
CMAKE_GENERATOR: Visual Studio 14 2015
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9\msvc2015
CMAKE_GENERATOR: Visual Studio 12 2013
PlatformToolset: v120_xp
- BuildID: 1
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9\msvc2015_64
before_build:
- git submodule update --init --recursive
build_script:
@@ -24,7 +21,7 @@ test_script:
deploy:
- provider: GitHub
auth_token:
secure: h55Scpy+3vmo1Yb7WlSIGA4d9DRnsbzUYc2LYsQdByQHZHbqrqjBpicH0D2FFLEO
secure: 3kV4efHXwRnfXzmJPRAOs8D7+MhwXUXYeayI/P5y114L09kJa6b6L70beXdW7yYr
on:
ReleaseBuild: true # deploy on release push only
@@ -40,23 +37,25 @@ deploy:
NightlyBuild: true # deploy on nightly push only
- provider: FTP
protocol: sftp
host: porphyrion.feralhosting.com
username:
secure: 36+bVD8eJgI0BVbi7TZ4zQ==
protocol: ftp
host: swc.fs2downloads.com
username:
secure: EXg2ADoKzMduZF90ip2Q0g==
password:
secure: CrzmDVca8AGG08iWPA1gOD4Ge06+wJ3rcBagBGclwYQ=
folder: www/datacorder.porphyrion.feralhosting.com/public_html/builds/nightly/$(VersionName)
secure: x0LL0uY9yBAQ7JTARhQ6AA==
folder: swc.fs2downloads.com/builds/nightly/$(VersionName)
beta: true
on:
NightlyBuild: true # deploy on nightly push only
- provider: FTP
protocol: sftp
host: porphyrion.feralhosting.com
username:
secure: 36+bVD8eJgI0BVbi7TZ4zQ==
protocol: ftp
host: swc.fs2downloads.com
username:
secure: EXg2ADoKzMduZF90ip2Q0g==
password:
secure: CrzmDVca8AGG08iWPA1gOD4Ge06+wJ3rcBagBGclwYQ=
folder: www/datacorder.porphyrion.feralhosting.com/public_html/builds/test/$(VersionName)
secure: x0LL0uY9yBAQ7JTARhQ6AA==
folder: swc.fs2downloads.com/builds/test/$(VersionName)
beta: true
on:
TestBuild: true # deploy on test build push only
+1 -14
View File
@@ -4,7 +4,6 @@ class BuildConfig {
[string]$PackageType
[string]$Toolset
[string]$SimdType
[string]$QtDir
[Bool]$SourcePackage
}
@@ -14,7 +13,6 @@ $NightlyConfigurations = @(
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
},
[BuildConfig]@{
@@ -22,7 +20,6 @@ $NightlyConfigurations = @(
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$false;
}
)
@@ -32,7 +29,6 @@ $ReleaseConfigurations = @(
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$true;
}
[BuildConfig]@{
@@ -40,7 +36,6 @@ $ReleaseConfigurations = @(
PackageType="Win32-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$false;
}
[BuildConfig]@{
@@ -48,7 +43,6 @@ $ReleaseConfigurations = @(
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
}
[BuildConfig]@{
@@ -56,7 +50,6 @@ $ReleaseConfigurations = @(
PackageType="Win64-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
}
)
@@ -133,8 +126,6 @@ if ($DeployBuild) {
cmake -DCMAKE_INSTALL_PREFIX="$env:APPVEYOR_BUILD_FOLDER/../install" -DFSO_USE_SPEECH="ON" `
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$($buildConfig.SimdType)" `
-DQT5_INSTALL_ROOT="$($buildConfig.QtDir)" -DFSO_BUILD_QTFRED=ON `
-DFSO_INSTALL_DEBUG_FILES="ON" `
-G "$($buildConfig.Generator)" -T "$($buildConfig.Toolset)" ..
$Configs = @("Release", "FastDebug")
@@ -146,14 +137,10 @@ if ($DeployBuild) {
}
}
7z a -xr'!*.pdb' "$($PackageName)-builds-$($buildConfig.PackageType).zip" "$env:APPVEYOR_BUILD_FOLDER/../install/*"
7z a "$($PackageName)-builds-$($buildConfig.PackageType).zip" "$env:APPVEYOR_BUILD_FOLDER/../install/*"
Push-AppveyorArtifact "$($PackageName)-builds-$($buildConfig.PackageType).zip"
7z a "$($PackageName)-debug-$($buildConfig.PackageType).7z" "$env:APPVEYOR_BUILD_FOLDER/../install/*.pdb"
Push-AppveyorArtifact "$($PackageName)-debug-$($buildConfig.PackageType).7z"
} else {
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="ON" -DFSO_BUILD_TESTS="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 `
-DFSO_BUILD_QTFRED=ON -DQT5_INSTALL_ROOT="$env:QT_DIR" -DFSO_BUILD_FRED2="ON" `
-G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
cmake --build . --config "$Env:CONFIGURATION" -- /verbosity:minimal
+2 -11
View File
@@ -3,18 +3,9 @@
set -ex
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
export DEBIAN_FRONTEND=noninteractive
sudo add-apt-repository -y "ppa:msulikowski/valgrind" # For fixing a bug with valgrind 3.11 which does not recognize the rdrand instruction
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository -y 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
sudo apt-get -yq update
# Nothing to do here
:
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
# Nothing to do here
:
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
# Nothing to do here
:
fi
+14 -21
View File
@@ -2,49 +2,42 @@
set -ex
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
mkdir -p /tmp/builds
if [ "$RELEASE_BUILD" = true ]; then
# Package the source code in release builds
PARENT_DIR="$(basename "$PWD")"
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
fi
mkdir -p build
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ "$RELEASE_BUILD" = true ]; then
PARENT_DIR="$(basename $PWD)"
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
if [[ "$CC" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
fi
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON"
if [ "$BUILD_DEPLOYMENT" = true ]; then
for config in $BUILD_CONFIGS
do
mkdir -p $config
cd $config
eval $CMAKE -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_BUILD_TYPE=$config -DCMAKE_INSTALL_PREFIX="/tmp/release/$config" \
-DFSO_BUILD_APPIMAGE=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_QTFRED=OFF ../..
-DFSO_BUILD_APPIMAGE=ON -DAPPIMAGE_ASSISTANT="$HOME/AppImageAssistant" \
-DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON ../..
cd ..
done
else
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON ..
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
if [ "$BUILD_DEPLOYMENT" = true ]; then
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
else
cmake -G "Xcode" $CMAKE_OPTIONS ..
fi
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DFSO_BUILD_FRED2="OFF" -G "$CMAKE_GENERATOR" ..
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "$CMAKE_GENERATOR" -T "$CMAKE_TOOLSET" ..
cmake -G "Xcode" ..
fi
fi
+1 -6
View File
@@ -49,7 +49,7 @@ if ([ "$RELEASE_BUILD" = true ] || [ "$NIGHTLY_BUILD" = true ] || [ "$TEST_BUILD
fi
if [ "$BUILD_DEPLOYMENT" = true ]; then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc-5.*$ ]])); then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc.*$ ]])); then
echo "Skipping non-release compiler";
exit 0;
fi
@@ -58,11 +58,6 @@ if [ "$BUILD_DEPLOYMENT" = true ]; then
echo "Skipping non-release configuration";
exit 0;
fi
if [ "$TRAVIS_OS_NAME" = "windows" ]; then
echo "Skipping non-release platform"
exit 0
fi
fi
export RELEASE_BUILD
-268
View File
@@ -1,268 +0,0 @@
#!/usr/bin/env python
#
#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===------------------------------------------------------------------------===#
r"""
ClangTidy Diff Checker
======================
This script reads input from a unified diff, runs clang-tidy on all changed
files and outputs clang-tidy warnings in changed lines only. This is useful to
detect clang-tidy regressions in the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 HEAD^ | clang-tidy-diff.py -p1
svn diff --diff-cmd=diff -x-U0 | \
clang-tidy-diff.py -fix -checks=-*,modernize-use-override
"""
import argparse
import glob
import json
import multiprocessing
import os
import re
import shutil
import subprocess
import sys
import tempfile
import threading
import traceback
try:
import yaml
except ImportError:
yaml = None
is_py2 = sys.version[0] == '2'
if is_py2:
import Queue as queue
else:
import queue as queue
def run_tidy(task_queue, lock, timeout):
watchdog = None
while True:
command = task_queue.get()
try:
proc = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if timeout is not None:
watchdog = threading.Timer(timeout, proc.kill)
watchdog.start()
stdout, stderr = proc.communicate()
with lock:
sys.stdout.write(stdout.decode('utf-8'))
sys.stdout.flush()
if stderr:
sys.stderr.write(stderr.decode('utf-8'))
sys.stderr.flush()
except Exception as e:
with lock:
sys.stderr.write('Failed: ' + str(e) + ': '.join(command) + '\n')
finally:
with lock:
if (not timeout is None) and (not watchdog is None):
if not watchdog.is_alive():
sys.stderr.write('Terminated by timeout: ' +
' '.join(command) + '\n')
watchdog.cancel()
task_queue.task_done()
def start_workers(max_tasks, tidy_caller, task_queue, lock, timeout):
for _ in range(max_tasks):
t = threading.Thread(target=tidy_caller, args=(task_queue, lock, timeout))
t.daemon = True
t.start()
def merge_replacement_files(tmpdir, mergefile):
"""Merge all replacement files in a directory into a single file"""
# The fixes suggested by clang-tidy >= 4.0.0 are given under
# the top level key 'Diagnostics' in the output yaml files
mergekey = "Diagnostics"
merged = []
for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')):
content = yaml.safe_load(open(replacefile, 'r'))
if not content:
continue # Skip empty files.
merged.extend(content.get(mergekey, []))
if merged:
# MainSourceFile: The key is required by the definition inside
# include/clang/Tooling/ReplacementsYaml.h, but the value
# is actually never used inside clang-apply-replacements,
# so we set it to '' here.
output = { 'MainSourceFile': '', mergekey: merged }
with open(mergefile, 'w') as out:
yaml.safe_dump(output, out)
else:
# Empty the file:
open(mergefile, 'w').close()
def main():
parser = argparse.ArgumentParser(description=
'Run clang-tidy against changed files, and '
'output diagnostics only for modified '
'lines.')
parser.add_argument('-clang-tidy-binary', metavar='PATH',
default='clang-tidy',
help='path to clang-tidy binary')
parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
parser.add_argument('-regex', metavar='PATTERN', default=None,
help='custom pattern selecting file paths to check '
'(case sensitive, overrides -iregex)')
parser.add_argument('-iregex', metavar='PATTERN', default=
r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
help='custom pattern selecting file paths to check '
'(case insensitive, overridden by -regex)')
parser.add_argument('-j', type=int, default=1,
help='number of tidy instances to be run in parallel.')
parser.add_argument('-timeout', type=int, default=None,
help='timeout per each file in seconds.')
parser.add_argument('-fix', action='store_true', default=False,
help='apply suggested fixes')
parser.add_argument('-checks',
help='checks filter, when not specified, use clang-tidy '
'default',
default='')
parser.add_argument('-path', dest='build_path',
help='Path used to read a compile command database.')
if yaml:
parser.add_argument('-export-fixes', metavar='FILE', dest='export_fixes',
help='Create a yaml file to store suggested fixes in, '
'which can be applied with clang-apply-replacements.')
parser.add_argument('-extra-arg', dest='extra_arg',
action='append', default=[],
help='Additional argument to append to the compiler '
'command line.')
parser.add_argument('-extra-arg-before', dest='extra_arg_before',
action='append', default=[],
help='Additional argument to prepend to the compiler '
'command line.')
parser.add_argument('-quiet', action='store_true', default=False,
help='Run clang-tidy in quiet mode')
clang_tidy_args = []
argv = sys.argv[1:]
if '--' in argv:
clang_tidy_args.extend(argv[argv.index('--'):])
argv = argv[:argv.index('--')]
args = parser.parse_args(argv)
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line)
if match:
filename = match.group(2)
if filename is None:
continue
if args.regex is not None:
if not re.match('^%s$' % args.regex, filename):
continue
else:
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
continue
match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).append([start_line, end_line])
if not any(lines_by_file):
print("No relevant changes found.")
sys.exit(0)
max_task_count = args.j
if max_task_count == 0:
max_task_count = multiprocessing.cpu_count()
max_task_count = min(len(lines_by_file), max_task_count)
tmpdir = None
if yaml and args.export_fixes:
tmpdir = tempfile.mkdtemp()
# Tasks for clang-tidy.
task_queue = queue.Queue(max_task_count)
# A lock for console output.
lock = threading.Lock()
# Run a pool of clang-tidy workers.
start_workers(max_task_count, run_tidy, task_queue, lock, args.timeout)
# Form the common args list.
common_clang_tidy_args = []
if args.fix:
common_clang_tidy_args.append('-fix')
if args.checks != '':
common_clang_tidy_args.append('-checks=' + args.checks)
if args.quiet:
common_clang_tidy_args.append('-quiet')
if args.build_path is not None:
common_clang_tidy_args.append('-p=%s' % args.build_path)
for arg in args.extra_arg:
common_clang_tidy_args.append('-extra-arg=%s' % arg)
for arg in args.extra_arg_before:
common_clang_tidy_args.append('-extra-arg-before=%s' % arg)
for name in lines_by_file:
line_filter_json = json.dumps(
[{"name": name, "lines": lines_by_file[name]}],
separators=(',', ':'))
# Run clang-tidy on files containing changes.
command = [args.clang_tidy_binary]
command.append('-line-filter=' + line_filter_json)
if yaml and args.export_fixes:
# Get a temporary file. We immediately close the handle so clang-tidy can
# overwrite it.
(handle, tmp_name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir)
os.close(handle)
command.append('-export-fixes=' + tmp_name)
command.extend(common_clang_tidy_args)
command.append(name)
command.extend(clang_tidy_args)
task_queue.put(command)
# Wait for all threads to be done.
task_queue.join()
if yaml and args.export_fixes:
print('Writing fixes to ' + args.export_fixes + ' ...')
try:
merge_replacement_files(tmpdir, args.export_fixes)
except:
sys.stderr.write('Error exporting fixes.\n')
traceback.print_exc()
if tmpdir:
shutil.rmtree(tmpdir)
if __name__ == '__main__':
main()
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env bash
set -e
if ! git rev-list $TRAVIS_COMMIT_RANGE 2>1 >/dev/null; then
echo "\$TRAVIS_COMMIT_RANGE ($TRAVIS_COMMIT_RANGE) is not valid for this build (probably caused by a rebase)."
exit 0
fi
cd "$TRAVIS_BUILD_DIR"
echo "Running clang-tidy on changed files"
git diff -U0 --no-color $TRAVIS_COMMIT_RANGE | \
$TRAVIS_BUILD_DIR/ci/travis/clang-tidy-diff.py -path "$TRAVIS_BUILD_DIR/build" -p1 \
-regex '(code|freespace2|qtfred|testsrc|build|tools)\/.*\.(cpp|h)' \
-clang-tidy-binary /usr/bin/clang-tidy-9 -j$(nproc) -quiet 2>/dev/null | \
tee clang-tidy-output.txt
if [[ -n $(grep "warning: " clang-tidy-output.txt) ]] || [[ -n $(grep "error: " clang-tidy-output.txt) ]]; then
echo "Errors or warnings were detected in the clang-tidy output!"
exit 1
else
echo -e "\033[1;32m\xE2\x9C\x93 passed:\033[0m clang-tidy test succeeded";
fi
+22 -57
View File
@@ -10,62 +10,27 @@ if [[ ! "$(curl -V)" == *"sftp"* ]]; then
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ -f ~/curl_cache/curl*.deb ]; then
cd ~/curl_cache
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
else
# Since the Travis CI people are not capable of enabling SSH/SCP support for their libcurl we need to build that manually...
# These commands are based on the tutorial from here: http://zeroset.mnim.org/2013/03/14/sftp-support-for-curl-in-ubuntu-12-10-quantal-quetzal-and-later/
mkdir /tmp/curl
cd /tmp/curl
sudo apt-get update
sudo apt-get install build-essential debhelper libssh2-1-dev libgnutls-dev libidn11-dev libkrb5-dev libldap2-dev libnss3-dev librtmp-dev libtool openssh-server quilt
apt-get source curl
sudo apt-get build-dep curl
# Since the Travis CI people are not capable of enabling SSH/SCP support for their libcurl we need to build that manually...
# These commands are based on the tutorial from here: http://zeroset.mnim.org/2013/03/14/sftp-support-for-curl-in-ubuntu-12-10-quantal-quetzal-and-later/
mkdir /tmp/curl
cd /tmp/curl
sudo apt-get update
sudo apt-get install build-essential debhelper libssh2-1-dev libgnutls-dev libidn11-dev libkrb5-dev libldap2-dev libnss3-dev librtmp-dev libtool openssh-server quilt
apt-get source curl
sudo apt-get build-dep curl
cd curl-*
export DEB_BUILD_OPTIONS="nocheck"
sudo dpkg-buildpackage -uc -us -j"$(grep -c ^processor /proc/cpuinfo)"
cd curl-*
export DEB_BUILD_OPTIONS="nocheck"
sudo dpkg-buildpackage -uc -us -j"$(grep -c ^processor /proc/cpuinfo)"
cd ..
dpkg -l | grep curl
ls -al
if [ ! -d ~/curl_cache ]; then
mkdir ~/curl_cache
fi
cp libcurl3*.deb curl*.deb ~/curl_cache
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
fi
cd ..
dpkg -l | grep curl
ls -al
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install libssh2
if [ -d ~/curl_cache/curl ]; then
cd ~/curl_cache/curl
sudo make install
else
mkdir /tmp/curl
cd /tmp/curl
curl -LO "https://curl.haxx.se/download/curl-7.64.0.tar.bz2"
tar -xjf curl-7.64.0.tar.bz2
cd curl-7.64.0
./configure --disable-debug --disable-dependency-tracking --disable-silent-rules --with-libssh2 --with-darwinssl --without-ca-bundle --without-ca-path
make -j"$(sysctl hw.logicalcpu | cut -d " " -f 2)"
if [ ! -d ~/curl_cache ]; then
mkdir ~/curl_cache
fi
cp -a . ~/curl_cache/curl
sudo make install
fi
export PATH=/usr/local/bin:$PATH
brew install curl --with-libssh2
export PATH="/usr/local/opt/curl/bin:$PATH"
fi
# After
@@ -77,13 +42,13 @@ cd /tmp/builds
for file in *; do
if [ "$TEST_BUILD" = true ]; then
# Upload to datacorder
curl -k "sftp://porphyrion.feralhosting.com/www/datacorder.porphyrion.feralhosting.com/public_html/builds/test/$VERSION_NAME/" --user "$DATACORDER_USER:$DATACORDER_PASSWORD" -T "$file" --ftp-create-dirs
# Upload to fs2downloads
curl -k "ftp://swc.fs2downloads.com/swc.fs2downloads.com/builds/test/$VERSION_NAME/" --user "$FS2DOWNLOADS_USER:$FS2DOWNLOADS_PASSWORD" -T "$file" --ftp-create-dirs
else
# Upload to indiegames
curl -k "sftp://scp.indiegames.us/~/public_html/builds/nightly/$VERSION_NAME/" --user "$INDIEGAMES_USER:$INDIEGAMES_PASSWORD" -T "$file" --ftp-create-dirs
# Upload to datacorder
curl -k "sftp://porphyrion.feralhosting.com/~/www/datacorder.porphyrion.feralhosting.com/public_html/builds/nightly/$VERSION_NAME/" --user "$DATACORDER_USER:$DATACORDER_PASSWORD" -T "$file" --ftp-create-dirs
# Upload to fs2downloads
curl -k "ftp://swc.fs2downloads.com/swc.fs2downloads.com/builds/nightly/$VERSION_NAME/" --user "$FS2DOWNLOADS_USER:$FS2DOWNLOADS_PASSWORD" -T "$file" --ftp-create-dirs
fi
done
+10 -26
View File
@@ -1,47 +1,31 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -ex
FILENAME=
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
export DEBIAN_FRONTEND=noninteractive
if [ ! -d "$HOME/cmake-3.8/bin" ]; then
if [ ! -d "$HOME/cmake/bin" ]; then
# If the cache does not currently contain CMake then download and install it
mkdir -p $HOME/cmake-3.8/
FILENAME=cmake-3.4.3-Linux-x86_64
wget -O /tmp/cmake.tar.gz --no-check-certificate https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake-3.8/ --strip-components=1
mkdir -p $HOME/cmake/
wget -O /tmp/cmake.tar.gz --no-check-certificate https://www.cmake.org/files/v3.4/$FILENAME.tar.gz
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake/ --strip-components=1
fi
export PATH=$HOME/cmake-3.8/bin:$PATH
export PATH=$HOME/cmake/bin:$PATH
cd $HOME
if [ "${BUILD_DEPLOYMENT}" = true ]; then
wget -O appimagetool -c "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" # (64-bit)
chmod a+x ./appimagetool
wget -O linuxdeployqt -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" # (64-bit)
chmod a+x ./linuxdeployqt
fi
sudo apt-get -yq install valgrind
if [[ "$CC" = "clang-9" ]]; then
sudo apt-get -yq install clang-9 clang-tidy-9
fi
if [[ "$CC" = "clang-4.0" ]]; then
# Fix a header bug present in ubuntu...
sudo ln -s /usr/include/libcxxabi/__cxxabi_config.h /usr/include/c++/v1/__cxxabi_config.h
wget -c "https://github.com/probonopd/AppImageKit/releases/download/5/AppImageAssistant" # (64-bit)
chmod a+x ./AppImageAssistant
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
gem install xcpretty
brew update
brew outdated cmake || brew upgrade cmake
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
choco install mingw ninja
fi
cmake --version
+1 -34
View File
@@ -8,40 +8,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
for config in $BUILD_CONFIGS
do
cd "$config"
# Compile all targets
ninja all
# Install Freespace2 targets
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Unspecified -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Freespace2 -P cmake_install.cmake
# We need to be a bit creative for determining the AppImage name since we don't want to hard-code the name
FILENAME="$(find /tmp/release/$config/fso/bin -name 'fs2_open_*' -type f -printf "%f\n").AppImage"
$HOME/appimagetool -n /tmp/release/$config/fso "/tmp/release/$config/fso/$FILENAME"
: <<'END'
# Install qtFRED targets
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=Unspecified -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=qtFRED -P cmake_install.cmake
PREV="$(pwd)"
cd /tmp/release/$config/qtfred
unset QTDIR; unset QT_PLUGIN_PATH; unset LD_LIBRARY_PATH
$HOME/linuxdeployqt usr/qtfred.desktop -bundle-non-qt-libs
# Move our AppRun script to the right location
mv usr/AppRun AppRun
echo "Embed newer libstdc++ for distros that don't come with it (ubuntu 14.04)";
mkdir -p usr/optional/; mkdir -p usr/optional/libstdc++/;
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/;
$HOME/appimagetool -n . "$(find /tmp/release/$config/qtfred/usr/bin -name 'qtfred_*' -type f -printf "%f\n").AppImage"
cd "$PREV"
END
ninja appimage
cd ..
done
+3 -13
View File
@@ -5,14 +5,10 @@ set -e
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ninja -k 20 all
ninja all
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
XCODE_RET=${PIPESTATUS[0]}
@@ -21,10 +17,4 @@ elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
exit $XCODE_RET
fi
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
cmake --build . --config "$CONFIGURATION"
else
cmake --build . --config "$CONFIGURATION" -- /verbosity:minimal
fi
fi
+1 -137
View File
@@ -25,140 +25,4 @@
fun:_dl_init
fun:dl_open_worker
fun:_dl_catch_error
}
{
CLang Lua unitialized value error
Memcheck:Cond
...
fun:luaH_get
fun:lua_rawget
fun:_ZN12_GLOBAL__N_117ade_index_handlerEP9lua_State
}
{
False-positive uninitialized variable warning
Memcheck:Cond
fun:_Z23cf_check_location_flagsjj
fun:_Z29cf_create_default_path_stringPcjiPKcbj
...
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:_Znwm
obj:*
obj:*
obj:*
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
fun:_Z7gr_initOSt10unique_ptrIN2os18GraphicsOperationsESt14default_deleteIS1_EEiiii
fun:_ZN4test13FSTestFixture5SetUpEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing4Test3RunEv
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:_Znwm
obj:*
obj:*
obj:*
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
fun:_Z7gr_initOSt10unique_ptrIN2os18GraphicsOperationsESt14default_deleteIS1_EEiiii
fun:_ZN4test13FSTestFixture5SetUpEv
fun:_ZN8FontTest5SetUpEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_Znwm
obj:*
obj:*
obj:*
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
fun:_Z7gr_initONSt3__110unique_ptrIN2os18GraphicsOperationsENS_14default_deleteIS2_EEEEiiii
fun:_ZN4test13FSTestFixture5SetUpEv
fun:_ZN8FontTest5SetUpEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_Znwm
obj:*
obj:*
obj:*
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
fun:_Z7gr_initONSt3__110unique_ptrIN2os18GraphicsOperationsENS_14default_deleteIS2_EEEEiiii
fun:_ZN4test13FSTestFixture5SetUpEv
fun:_ZN8FontTest5SetUpEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_Znwm
obj:*
obj:*
obj:*
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
obj:/usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0
fun:_Z7gr_initONSt3__110unique_ptrIN2os18GraphicsOperationsENS_14default_deleteIS2_EEEEiiii
fun:_ZN4test13FSTestFixture5SetUpEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_dl_signal_error
fun:_dl_open
fun:dlopen_doit
fun:_dl_catch_error
fun:_dlerror_run
fun:dlopen@@GLIBC_2.2.5
obj:*
obj:*
fun:call_init.part.0
fun:call_init
fun:_dl_init
fun:dl_open_worker
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_dl_signal_error
fun:_dl_open
fun:dlopen_doit
fun:_dl_catch_error
fun:_dlerror_run
fun:dlopen@@GLIBC_2.2.5
obj:*
obj:*
fun:call_init.part.0
fun:call_init
fun:_dl_init
fun:dl_open_worker
}
}
+1 -3
View File
@@ -1,6 +1,4 @@
[Desktop Entry]
Type=Application
Name=FreeSpace Open
Exec=$<TARGET_FILE_NAME:Freespace2>
Icon=app_icon
Categories=Game;
Icon=app_icon.png
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/sh
HERE=$(dirname $(readlink -f "${0}"))
export LD_LIBRARY_PATH="${HERE}"/lib:"$LD_LIBRARY_PATH"
exec "${HERE}"/bin/$<TARGET_FILE_NAME:Freespace2> $@
"${HERE}"/bin/$<TARGET_FILE_NAME:Freespace2> $@
+8 -6
View File
@@ -6,16 +6,18 @@ configure_file("${CMAKE_CURRENT_LIST_DIR}/AppRun.in" "${CMAKE_CURRENT_BINARY_DIR
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>"
INPUT "${CMAKE_CURRENT_BINARY_DIR}/AppRun.gen")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>" DESTINATION "." RENAME "AppRun"
COMPONENT "Freespace2")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>" DESTINATION "." RENAME "AppRun")
configure_file("${CMAKE_CURRENT_LIST_DIR}/AppImage.desktop.in" "${CMAKE_CURRENT_BINARY_DIR}/AppImage.desktop.gen" @ONLY)
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop"
INPUT "${CMAKE_CURRENT_BINARY_DIR}/AppImage.desktop.gen")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop" DESTINATION "." RENAME "fso.desktop"
COMPONENT "Freespace2")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop" DESTINATION "." RENAME "fso.desktop")
install(FILES "${CMAKE_SOURCE_DIR}/freespace2/resources/app_icon.png" DESTINATION "."
COMPONENT "Freespace2")
install(FILES "${CMAKE_SOURCE_DIR}/freespace2/resources/app_icon.png" DESTINATION ".")
add_custom_target(appimage
COMMAND "${APPIMAGE_ASSISTANT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/fs2_open_${FSO_BINARY_SUFFIX}.AppImage")
add_dependencies(appimage install)
-37
View File
@@ -1,37 +0,0 @@
option(ENABLE_CLANG_TIDY "Enable source code checking using clang-tidy" OFF)
find_program(
CLANG_TIDY_EXE
NAMES "clang-tidy"
DOC "Path to clang-tidy executable"
)
function(enable_clang_tidy target)
# Not enabled in this configuration
endfunction()
if(NOT ENABLE_CLANG_TIDY)
return()
endif()
if(NOT EXISTS "${CLANG_TIDY_EXE}")
message(SEND_ERROR "clang-tidy: Could not find clang-tidy executable (value of variable is \"${CLANG_TIDY_EXE}\".")
return()
endif()
if(CMAKE_VERSION VERSION_LESS "3.6.0")
message(SEND_ERROR "Clang-tidy support requires CMake 3.6")
return()
endif()
message(STATUS "clang-tidy: Using \"${CLANG_TIDY_EXE}\"")
function(enable_clang_tidy target)
SET(TIDY_OPTIONS "${CLANG_TIDY_EXE}")
if(FSO_FATAL_WARNINGS)
set(TIDY_OPTIONS "${TIDY_OPTIONS};-warnings-as-errors=*")
endif()
set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "${TIDY_OPTIONS}")
endfunction()
+1 -1
View File
@@ -3,7 +3,7 @@ INCLUDE(util)
MESSAGE(STATUS "Configuring UNIX specific things and stuff...")
target_compile_definitions(platform INTERFACE SCP_UNIX USE_OPENAL _REENTRANT)
target_compile_definitions(platform INTERFACE SCP_UNIX USE_OPENAL)
# Set RPATH
set(CMAKE_SKIP_BUILD_RPATH TRUE)
+1 -1
View File
@@ -8,7 +8,7 @@ SET(WIN32_LIBS
odbccp32
vfw32
winmm
ws2_32
wsock32
psapi
)
+8 -11
View File
@@ -10,8 +10,8 @@ include(CheckSymbolExists)
include(CheckCXXSymbolExists)
include(CheckTypeSize)
CHECK_INCLUDE_FILE("execinfo.h" SCP_HAVE_EXECINFO_H)
CHECK_INCLUDE_FILE_CXX("cxxabi.h" SCP_HAVE_CXXAPI_H)
CHECK_INCLUDE_FILE("execinfo.h" HAVE_EXECINFO_H)
CHECK_INCLUDE_FILE_CXX("cxxabi.h" HAVE_CXXAPI_H)
CHECK_TYPE_SIZE("max_align_t" MAX_ALIGN_T)
@@ -31,18 +31,15 @@ CHECK_TYPE_SIZE("U'b'" UNICODE_CHAR_LITERAL LANGUAGE CXX)
set(CMAKE_REQUIRED_FLAGS)
CHECK_FUNCTION_EXISTS(strcasecmp SCP_HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strncasecmp SCP_HAVE_STRNCASECMP)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP)
CHECK_FUNCTION_EXISTS(_stricmp SCP_HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strnicmp SCP_HAVE__STRNICMP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP)
CHECK_FUNCTION_EXISTS(strlwr SCP_HAVE_STRLWR)
CHECK_FUNCTION_EXISTS(strlwr HAVE_STRLWR)
CHECK_INCLUDE_FILE("strings.h" SCP_HAVE_STRINGS_H)
check_symbol_exists(snprintf "stdio.h" SCP_HAVE_SNPRINTF)
check_symbol_exists(_snprintf "stdio.h" SCP_HAVE__SNPRINTF)
CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
+12 -14
View File
@@ -3,28 +3,26 @@
#define __PLATFORM_CHECKS_H__
#pragma once
#cmakedefine SCP_HAVE_EXECINFO_H
#cmakedefine SCP_HAVE_CXXAPI_H
#cmakedefine SCP_HAVE_MAX_ALIGN_T
#cmakedefine SCP_HAVE_STD_MAX_ALIGN_T
#cmakedefine HAVE_EXECINFO_H
#cmakedefine HAVE_CXXAPI_H
#cmakedefine HAVE_MAX_ALIGN_T
#cmakedefine HAVE_STD_MAX_ALIGN_T
#cmakedefine01 HAVE_STD_IS_TRIVIALLY_COPYABLE
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE_ARRAY
#cmakedefine01 IS_64BIT
#cmakedefine01 SCP_HAVE_STRCASECMP
#cmakedefine01 SCP_HAVE_STRNCASECMP
#cmakedefine01 SCP_HAVE__STRICMP
#cmakedefine01 SCP_HAVE__STRNICMP
#cmakedefine01 HAVE_STRCASECMP
#cmakedefine01 HAVE_STRNCASECMP
#cmakedefine01 HAVE__STRICMP
#cmakedefine01 HAVE__STRNICMP
#cmakedefine01 SCP_HAVE_STRLWR
#cmakedefine01 HAVE_STRLWR
#cmakedefine01 SCP_HAVE_STRINGS_H
#cmakedefine01 HAVE_STRINGS_H
#cmakedefine01 HAVE_CHAR32_T
#cmakedefine01 HAVE_UNICODE_CHAR_LITERAL
#cmakedefine01 SCP_HAVE_SNPRINTF
#cmakedefine01 SCP_HAVE__SNPRINTF
#endif // __PLATFORM_CHECKS_H__
+2
View File
@@ -9,6 +9,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -funroll-loops -fsigned-char -Wno-
# Omit "conversion from string literal to 'char *' is deprecated" warnings.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-char-subscripts")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
+5 -11
View File
@@ -7,8 +7,6 @@ MESSAGE(STATUS "Doing configuration specific to clang...")
option(CLANG_ENABLE_LEAK_CHECK "Enable -fsanitize=leak" OFF)
option(CLANG_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
option(CLANG_USE_LIBCXX "Use libc++" OFF)
# These are the default values
set(C_BASE_FLAGS "-march=native -pipe")
set(CXX_BASE_FLAGS "-march=native -pipe")
@@ -21,10 +19,6 @@ if(DEFINED ENV{CFLAGS})
set(C_BASE_FLAGS $ENV{CFLAGS})
endif()
if (CLANG_USE_LIBCXX)
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -stdlib=libc++")
endif()
# Initialize with an empty string to make sure we always get a clean start
set(COMPILER_FLAGS "")
@@ -72,17 +66,21 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
# Dear Clang, please tell us if a function does not return a value since that part of the standard is stupid!
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-char-subscripts")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
check_cxx_compiler_flag(-Wshift-negative-value SUPPORTS_SHIFT_NEGATIVE_VALUE)
if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
@@ -99,10 +97,6 @@ set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_EXE_LINKER_FLAGS "")
if (CLANG_USE_LIBCXX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
endif()
if (SANITIZE_FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
endif()
+5 -13
View File
@@ -78,23 +78,16 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
# Dear GCC, please tell us if a function does not return a value since that part of the standard is stupid!
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
# These two warnings cause a lot of false-positives in the FSO code base
check_cxx_compiler_flag(-Wstringop-truncation SUPPORTS_STRINGOP_TRUNCATION)
if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-truncation")
endif()
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
check_cxx_compiler_flag(-Wstringop-overflow SUPPORTS_STRINGOP_OVERFLOW)
if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
@@ -112,7 +105,6 @@ set(CMAKE_EXE_LINKER_FLAGS "")
IF (MINGW)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
target_compile_definitions(compiler INTERFACE __USE_MINGW_ANSI_STDIO=1)
ENDIF(MINGW)
if (SANITIZE_FLAGS)
@@ -139,4 +131,4 @@ if (FSO_FATAL_WARNINGS)
endif()
# Always define this to make sure that the fixed width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS=1)
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
+10 -11
View File
@@ -36,24 +36,21 @@ set(WARNING_FLAGS
/wd4592 # "symbol will be dynamically initialized" is being generated by a compiler bug, see https://stackoverflow.com/a/34027257 for an explanation - m!m
$<$<CONFIG:Release>:/wd4101> # In release mode there are unreferenced variables because debug needs them
/wd4995 # "'vsprintf': name was marked as #pragma deprecated" is being caused by our custom definition of vsprintf. I have no idea what causes this or how to fix it - m!m
/wd4723 # "potential divide by 0" is caused by some code that definitely will not divide by zero - m!m
/wd4121 # "alignment of a member was sensitive to packing" happens in a Windows header - m!m
)
target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
# Base
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /DYNAMICBASE:NO /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
set(CMAKE_STATIC_LINKER_FLAGS "")
# Release
set(CMAKE_C_FLAGS_RELEASE "/GL /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
set(CMAKE_CXX_FLAGS_RELEASE "/GL /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
# /DEBUG:FULL so that we get PDBs which is needed for debugging crashdumps
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/OPT:REF /LTCG /INCREMENTAL:NO /DEBUG:FULL")
set(CMAKE_C_FLAGS_RELEASE "/GL /W2 /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
set(CMAKE_CXX_FLAGS_RELEASE "/GL /W2 /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/OPT:REF /LTCG /INCREMENTAL:NO")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
globally_enable_extra_compiler_warnings()
@@ -65,6 +62,8 @@ if (MSVC_RELEASE_DEBUGGING)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zo")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zo")
endif()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
endif()
IF(MSVC_USE_RUNTIME_DLL)
@@ -136,9 +135,9 @@ else()
ENDIF()
endif()
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX
"$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>" _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX "$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
target_compile_options(compiler INTERFACE "/WX")
+4 -44
View File
@@ -10,7 +10,7 @@ FUNCTION(ADD_IMPORTED_LIB NAME INCLUDES LIBS)
target_link_libraries(${NAME} INTERFACE "${LIBS}")
target_include_directories(${NAME} SYSTEM INTERFACE "${INCLUDES}")
target_include_directories(${NAME} INTERFACE "${INCLUDES}")
ENDFUNCTION(ADD_IMPORTED_LIB)
MACRO(PKG_CONFIG_LIB_RESOLVE NAME OUTVAR)
@@ -141,12 +141,10 @@ macro(set_if_not_defined VAR VALUE)
endmacro(set_if_not_defined)
macro(configure_cotire target)
if(ENABLE_COTIRE)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
cotire(${target})
endif()
cotire(${target})
endmacro(configure_cotire)
macro(add_target_copy_files)
@@ -197,41 +195,3 @@ function(suppress_warnings _target)
target_compile_options(${_target} PRIVATE "-w")
endif()
endfunction(suppress_warnings)
function(list_target_dependencies _target _out_var)
set(out_list)
set(work_libs ${_target})
list(LENGTH work_libs libs_length)
while(libs_length GREATER 0)
list(GET work_libs 0 current)
list(REMOVE_AT work_libs 0)
list(APPEND out_list ${current})
get_target_property(current_libs ${current} INTERFACE_LINK_LIBRARIES)
if(current_libs)
foreach(lib ${current_libs})
if (TARGET ${lib})
list(APPEND work_libs ${lib})
endif (TARGET ${lib})
endforeach(lib)
endif(current_libs)
list(LENGTH work_libs libs_length)
endwhile(libs_length GREATER 0)
list(REMOVE_DUPLICATES out_list)
set(${_out_var} ${out_list} PARENT_SCOPE)
endfunction(list_target_dependencies)
macro(add_file_folder FOLDER_NAME)
string(MAKE_C_IDENTIFIER "${FOLDER_NAME}" VARIABLE_NAME)
set(files_${VARIABLE_NAME} ${files_${VARIABLE_NAME}} ${ARGN})
string(REPLACE "/" "\\" FIXED_FOLDER_FILE "${FOLDER_NAME}")
source_group("${FIXED_FOLDER_FILE}" FILES ${ARGN})
set(source_files ${source_files} ${ARGN})
endmacro(add_file_folder)
+4 -4
View File
@@ -6,9 +6,9 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
include("${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 20)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_BUILD 0)
set_if_not_defined(FSO_VERSION_MAJOR 3)
set_if_not_defined(FSO_VERSION_MINOR 8)
set_if_not_defined(FSO_VERSION_BUILD 1)
# A numeric revision e.g. the CI build number
set_if_not_defined(FSO_VERSION_REVISION 0)
@@ -49,4 +49,4 @@ IF (NOT "${FSO_BUILD_POSTFIX}" STREQUAL "")
ENDIF()
set(CONFIG_POSTFIX "$<$<CONFIG:Release>:>$<$<CONFIG:Debug>:-DEBUG>$<$<CONFIG:FastDebug>:-FASTDBG>")
set(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}${CONFIG_POSTFIX}")
set(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}${CONFIG_POSTFIX}")
+3 -37
View File
@@ -3,7 +3,7 @@ INCLUDE(source_groups.cmake)
INCLUDE(voice_rec.cmake)
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
ADD_LIBRARY(code STATIC ${file_root} ${VOICE_REC_FILES})
target_compile_features(code PUBLIC ${REQUIRED_CXX_FEATURES})
@@ -28,9 +28,7 @@ TARGET_LINK_LIBRARIES(code PUBLIC ${JPEG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC sdl2)
if (FSO_BUILD_WITH_FFMPEG)
TARGET_LINK_LIBRARIES(code PUBLIC ffmpeg)
endif()
TARGET_LINK_LIBRARIES(code PUBLIC ffmpeg)
TARGET_LINK_LIBRARIES(code PUBLIC utfcpp)
@@ -39,16 +37,6 @@ TARGET_LINK_LIBRARIES(code PUBLIC compiler)
target_link_libraries(code PUBLIC md5)
target_link_libraries(code PUBLIC discord-rpc)
target_link_libraries(code PUBLIC libRocket)
target_link_libraries(code PUBLIC pcp)
target_link_libraries(code PUBLIC vulkan-hpp)
enable_clang_tidy(code)
IF (FSO_USE_SPEECH)
find_package(Speech REQUIRED)
target_link_libraries(code PUBLIC speech)
@@ -67,29 +55,7 @@ IF(FSO_BUILD_TOOLS)
ADD_SUBDIRECTORY(cfileextractor)
ENDIF(FSO_BUILD_TOOLS)
if (ENABLE_COTIRE)
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h")
else()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/FI ${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
ELSE()
MESSAGE("Unknown compiler for global includes. This will probably break the build.")
ENDIF()
endif()
if (FSO_RELEASE_LOGGING)
target_compile_definitions(code PUBLIC SCP_RELEASE_LOGGING)
endif()
if (FSO_BUILD_WITH_FFMPEG)
target_compile_definitions(code PUBLIC WITH_FFMPEG)
endif()
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "prefix_header.h")
include(util)
configure_cotire(code)
+13 -15
View File
@@ -18,7 +18,8 @@
#include "ship/ship.h"
SCP_vector<char *> Goal_target_names;
int Total_goal_target_names = 0;
char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
ai_info Ai_info[MAX_AI_INFO];
ai_info *Player_ai;
@@ -81,25 +82,22 @@ void set_wingnum(int objnum, int wingnum)
Ai_info[ai_index].wing = wingnum;
}
const char *ai_get_goal_target_name(const char *name, int *index)
char *ai_get_goal_target_name(const char *name, int *index)
{
Assertion(name != nullptr && index != nullptr, "Arguments cannot be null!");
Assert(name != NULL);
Assert(index != NULL);
int i;
for (int i = 0; i < static_cast<int>(Goal_target_names.size()); ++i) {
for (i=0; i < Total_goal_target_names; i++)
if (!stricmp(name, Goal_target_names[i])) {
*index = i;
return Goal_target_names[i];
}
}
*index = static_cast<int>(Goal_target_names.size());
Goal_target_names.push_back(vm_strdup(name));
return Goal_target_names[*index];
}
void ai_clear_goal_target_names()
{
for (auto ptr : Goal_target_names)
vm_free(ptr);
Goal_target_names.clear();
Assert(Total_goal_target_names < MAX_GOAL_TARGET_NAMES);
Assertion(strlen(name) <= NAME_LENGTH - 1, "Goal target name %s is too long. Needs to be 31 characters or less.", name);
i = Total_goal_target_names++;
strcpy_s(Goal_target_names[i], name);
*index = i;
return Goal_target_names[i];
}
+17 -9
View File
@@ -83,7 +83,7 @@ typedef struct ai_goal {
fix time; // time at which this goal was issued.
int priority; // how important is this goal -- number 0 - 100
const char *target_name; // name of the thing that this goal acts upon
char *target_name; // name of the thing that this goal acts upon
int target_name_index; // index of goal_target_name in Goal_target_names[][]
waypoint_list *wp_list; // waypoints that this ship might fly.
int target_instance; // instance of thing this ship might be chasing (currently only used for weapons; note, not the same as objnum!)
@@ -93,17 +93,19 @@ typedef struct ai_goal {
// (AIGF_DOCKER_INDEX_VALID and AIGF_DOCKEE_INDEX_VALID tell us to use indexes; otherwise we use names)
// these are the dockpoints used on the docker and dockee ships, not the ships themselves
union {
const char *name;
char *name;
int index;
} docker;
union {
const char *name;
char *name;
int index;
} dockee;
} ai_goal;
#define MAX_GOAL_TARGET_NAMES 100
#define AIM_CHASE 0
#define AIM_EVADE 1
#define AIM_GET_BEHIND 2
@@ -511,6 +513,8 @@ typedef struct {
#define BURST_DURATION 500 // decay time over which Player->damage_this_burst falls from MAX_BURST_DAMAGE to 0
extern int Mission_all_attack; // !0 means all teams attack all teams.
extern int Total_goal_target_names;
extern char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
extern void update_ai_info_for_hit(int hitter_obj, int hit_obj);
extern void ai_frame_all(void);
@@ -552,8 +556,7 @@ void ai_process( object * obj, int ai_index, float frametime );
int get_wingnum(int objnum);
void set_wingnum(int objnum, int wingnum);
const char *ai_get_goal_target_name(const char *name, int *index);
void ai_clear_goal_target_names();
char *ai_get_goal_target_name(const char *name, int *index);
extern void init_ai_system(void);
extern void ai_attack_object(object *attacker, object *attacked, ship_subsys *ssp, int ship_info_index = -1);
@@ -564,9 +567,9 @@ extern void ai_dock_with_object(object *docker, int docker_index, object *dockee
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
extern void ai_do_default_behavior(object *obj);
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, int sexp_flags = 0);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum, Ship::Exit_Flags method);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = NULL, int sexp_flags = 0);
extern void init_ai_object(int objnum);
extern void ai_init(void); // Call this one to parse ai.tbl.
extern void ai_level_init(void); // Call before each level to reset AI
@@ -584,10 +587,13 @@ extern void get_absolute_wing_pos_autopilot( vec3d *result_pos, object *leader_o
// Interface from goals code to AI. Set ship to guard. *objp guards *other_objp
extern void ai_set_guard_object(object *objp, object *other_objp);
extern void ai_set_evade_object(object *objp, object *other_objp);
extern void ai_set_guard_wing(object *objp, int wingnum);
extern void ai_warp_out(object *objp, vec3d *vp);
extern void ai_attack_wing(object *attacker, int wingnum);
extern void ai_deathroll_start(object *ship_obj);
extern void ai_fly_in_formation(int wing_num); // Force wing to fly in formation.
extern void ai_disband_formation(int wing_num); // Force wing to disband formation flying.
extern int set_target_objnum(ai_info *aip, int objnum);
extern void ai_form_on_wing(object *objp, object *goal_objp);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
@@ -616,7 +622,7 @@ extern float ai_path();
extern void evade_weapon();
extern int might_collide_with_ship(object *obj1, object *obj2, float dot_to_enemy, float dist_to_enemy, float duration);
extern int ai_fire_primary_weapon(object *objp); //changed to return weather it fired-Bobboau
extern int ai_fire_secondary_weapon(object *objp);
extern int ai_fire_secondary_weapon(object *objp, int priority1 = -1, int priority2 = -1);
extern float ai_get_weapon_dist(ship_weapon *swp);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
@@ -640,6 +646,8 @@ extern void ai_do_objects_repairing_stuff( object *repaired_obj, object *repair_
// Move to a position relative to a dock bay using thrusters.
extern float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo = NULL);
extern int find_danger_weapon(object *sobjp, float dtime, float *atime, float dot_threshhold);
void ai_set_mode_warp_out(object *objp, ai_info *aip);
// prototyped by Goober5000
+4 -16
View File
@@ -51,19 +51,14 @@ namespace AI {
};
FLAG_LIST(Maneuver_Override_Flags) {
Full_rot, // full sexp control over pitch/bank/heading rotation
Full, // Full sexp control
Roll, // Sexp forced roll maneuver
Pitch, // Sexp forced pitch change
Heading, // Sexp forced heading change
Full_lat, // full control over up/side/forward movement
Up, // Sexp forced vertical movement
Sideways, // Sexp forced horizontal movement
Forward, // Sexp forced forward movement
Dont_bank_when_turning, // maps to CIF_DONT_BANK_WHEN_TURNING
Dont_clamp_max_velocity, // maps to CIF_DONT_CLAMP_MAX_VELOCITY
Instantaneous_acceleration, // maps to CIF_INSTANTANEOUS_ACCELERATION
Never_expire, // don't clear the maneuver when the timestamp is up
Up, // vertical movement
Sideways, // horizontal movement
Forward, // forward movement
NUM_VALUES
};
@@ -84,19 +79,14 @@ namespace AI {
Assist_scoring_scales_with_damage,
Beams_damage_weapons,
Big_ships_can_attack_beam_turrets_on_untargeted_ships,
Check_comms_for_non_player_ships,
Disable_linked_fire_penalty,
Disable_player_secondary_doublefire,
Disable_ai_secondary_doublefire,
Disable_weapon_damage_scaling,
Dont_insert_random_turret_fire_delay,
Fix_ai_class_bug,
Fix_ai_path_order_bug,
Fix_heat_seeker_stealth_bug,
Fix_linked_primary_bug,
Fix_ramming_stationary_targets_bug,
Force_beam_turret_fov,
Free_afterburner_use,
Glide_decay_requires_thrust,
Hack_improve_non_homing_swarm_turret_fire_accuracy,
Huge_turret_weapons_ignore_bombs,
@@ -119,9 +109,7 @@ namespace AI {
Smart_shield_management,
Smart_subsystem_targeting_for_turrets,
Strict_turred_tagged_only_targeting,
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in http://scp.indiegames.us/mantis/view.php?id=3198
Turrets_ignore_target_radius,
Use_actual_primary_range,
Use_additive_weapon_velocity,
Use_newtonian_dampening,
Use_only_single_fov_for_turrets,
+7 -36
View File
@@ -7,11 +7,11 @@
#include "ai/ai_profiles.h"
#include "globalincs/pstypes.h"
#include "def_files/def_files.h"
#include "ai/ai_profiles.h"
#include "globalincs/pstypes.h"
#include "localization/localize.h"
#include "mod_table/mod_table.h"
#include "parse/parselo.h"
#include "ship/ship.h"
#include "weapon/weapon.h"
@@ -357,8 +357,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management);
set_flag(profile, "$free afterburner use:", AI::Profile_Flags::Free_afterburner_use);
set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire);
set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
@@ -371,16 +369,10 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp);
set_flag(profile, "$check communications for non-player ships:", AI::Profile_Flags::Check_comms_for_non_player_ships);
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap);
set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);
set_flag(profile, "$disable player secondary doublefire:", AI::Profile_Flags::Disable_player_secondary_doublefire);
set_flag(profile, "$disable ai secondary doublefire:", AI::Profile_Flags::Disable_ai_secondary_doublefire);
set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling);
set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity);
@@ -397,8 +389,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug);
set_flag(profile, "$fix ramming stationary targets bug:", AI::Profile_Flags::Fix_ramming_stationary_targets_bug);
set_flag(profile, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);
set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets);
@@ -443,8 +433,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
set_flag(profile, "$support don't add primaries:", AI::Profile_Flags::Support_dont_add_primaries);
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
if (optional_string("$ai path mode:"))
{
@@ -470,8 +458,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
if (optional_string("$bay arrive speed multiplier:")) {
@@ -512,8 +498,7 @@ void parse_ai_profiles_tbl(const char *filename)
}
// find next valid option
if (!skip_to_start_of_string_either("$", "#"))
break;
skip_to_start_of_string_either("$", "#");
saved_Mp = Mp;
}
}
@@ -525,6 +510,10 @@ void parse_ai_profiles_tbl(const char *filename)
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default ai_profiles.tbl>", e.what()));
return;
}
// add tbl/tbm to multiplayer validation list
extern void fs2netd_add_table_validation(const char *tblname);
fs2netd_add_table_validation(filename);
}
void ai_profiles_init()
@@ -632,22 +621,4 @@ void ai_profile_t::reset()
for (int i = 0; i <= MAX_DETAIL_LEVEL; ++i) {
detail_distance_mult[i] = 0;
}
// via Github #2332, enable bugfixes if we are targeting version 20 and up
if (mod_supports_version(20, 0, 0)) {
flags.set(AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
flags.set(AI::Profile_Flags::Fix_linked_primary_bug);
flags.set(AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);
flags.set(AI::Profile_Flags::Fix_heat_seeker_stealth_bug);
flags.set(AI::Profile_Flags::Allow_vertical_dodge);
flags.set(AI::Profile_Flags::Fix_ai_class_bug);
flags.set(AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
flags.set(AI::Profile_Flags::Fix_ai_path_order_bug);
flags.set(AI::Profile_Flags::Aspect_invulnerability_fix);
flags.set(AI::Profile_Flags::Use_actual_primary_range);
}
// this flag has been enabled ever since 3.7.2
if (mod_supports_version(3, 7, 2)) {
flags.set(AI::Profile_Flags::Fix_ramming_stationary_targets_bug);
}
}
+26 -20
View File
@@ -64,11 +64,10 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
void ai_big_avoid_ship();
int ai_big_maybe_follow_subsys_path(int do_dot_check=1);
void ai_big_strafe_position();
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos);
extern int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, polymodel **pm, int *octs);
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal);
// Called by ai_big_pick_attack_point.
@@ -632,7 +631,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
else
rvec = NULL;
ai_turn_towards_vector(enemy_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, 0.0f, 0, rvec);
ai_turn_towards_vector(enemy_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, 0.0f, 0, rvec);
// calc range of primary weapon
weapon_travel_dist = ai_get_weapon_dist(&Ships[Pl_objp->instance].weapons);
@@ -642,7 +641,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
accelerate_ship(aip, 1.0f);
ship *shipp = &Ships[Pl_objp->instance];
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (dot_to_enemy > 0.75f)) {
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (dot_to_enemy > 0.75f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
@@ -684,7 +683,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
accelerate_ship(aip, accel);
ship *shipp = &Ships[Pl_objp->instance];
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
@@ -708,14 +707,14 @@ extern float set_secondary_fire_delay(ai_info *aip, ship *shipp, weapon_info *sw
extern void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp);
extern int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time);
extern void maybe_cheat_fire_synaptic(object *objp);
extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
// Determine if Pl_objp should fire weapons at current target, based on input parameters
//
// dist_to_enemy => distance (in m) to attack point on current target
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
//
static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel)
{
ai_info *aip;
ship_weapon *swp;
@@ -846,6 +845,8 @@ void ai_big_switch_to_chase_mode(ai_info *aip)
aip->submode_start_time = Missiontime;
}
extern int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos);
// Make object Pl_objp chase object En_objp, which is a big ship, not a small ship.
void ai_big_chase()
{
@@ -858,7 +859,7 @@ void ai_big_chase()
Assert(aip->mode == AIM_CHASE);
maybe_cheat_fire_synaptic(Pl_objp);
maybe_cheat_fire_synaptic(Pl_objp, aip);
ai_set_positions(Pl_objp, En_objp, aip, &player_pos, &enemy_pos);
@@ -881,7 +882,7 @@ void ai_big_chase()
dot_to_enemy = vm_vec_dot(&vec_to_enemy, &Pl_objp->orient.vec.fvec);
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
if ( ai_big_strafe_maybe_retreat(&enemy_pos) ) {
if ( ai_big_strafe_maybe_retreat(dist_to_enemy, &enemy_pos) ) {
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
aip->submode = AIS_STRAFE_AVOID;
@@ -1044,7 +1045,7 @@ void ai_big_chase()
if ((dist_normal_to_enemy < ATTACK_COLLIDE_AVOID_DIST + speed_dist) || (time_to_enemy < ATTACK_COLLIDE_AVOID_TIME) ) {
// get away, simulate crsh recovery (don't use avoid)
// accelerate_ship(aip, -1.0f);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
// aip->submode = SM_AVOID;
// aip->submode_start_time = Missiontime;
} else if ((dist_normal_to_enemy < ATTACK_COLLIDE_SLOW_DIST) || (time_to_enemy < ATTACK_COLLIDE_SLOW_TIME) ) {
@@ -1143,7 +1144,7 @@ void ai_big_chase()
// TODO: investigate why ships fire (and aren't close to hitting ship) when following a path near
// a big ship
if (aip->mode != AIM_EVADE && aip->path_start == -1 ) {
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy);
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy, &player_pos, &predicted_enemy_pos, &En_objp->phys_info.vel);
} else {
if (flFrametime < 1.0f)
aip->time_enemy_in_range *= (1.0f - flFrametime);
@@ -1152,6 +1153,11 @@ void ai_big_chase()
}
}
void ai_big_ship(object *objp)
{
// do nothing
}
// all three parms are output parameters
// Enemy object is En_objp
// pos => world pos of attack point
@@ -1222,7 +1228,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
// AIS_STRAFE_RETREAT
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
{
ai_info *aip;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
@@ -1252,7 +1258,7 @@ static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
// use standard collision resolution
aip->ai_flags.remove(AI::AI_Flags::Target_collision);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
} else {
// too close for comfort so fly to box point + 300
aip->submode = AIS_STRAFE_RETREAT1;
@@ -1292,12 +1298,12 @@ void ai_big_strafe_attack()
}
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(&target_pos) )
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
return;
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
if (target_dist < 1200.0f) {
ai_turn_towards_vector(&target_pos, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&target_pos, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((target_dist < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
@@ -1341,7 +1347,7 @@ void ai_big_strafe_attack()
}
// maybe fire weapons at target
ai_big_maybe_fire_weapons(target_dist, target_dot);
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
fix last_hit = Missiontime - aip->last_hit_time;
@@ -1487,7 +1493,7 @@ void ai_big_strafe_glide_attack()
vm_vec_sub2(&target_pos, &En_objp->pos);
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
ai_big_maybe_fire_weapons(target_dist, target_dot);
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
}
// if haven't been hit in quite a while, leave strafe mode
@@ -1511,7 +1517,7 @@ void ai_big_strafe_avoid()
mode_time = Missiontime - aip->submode_start_time;
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(&target_pos) )
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
return;
if ( mode_time > fl2f(0.5)) {
@@ -1698,7 +1704,7 @@ void ai_big_strafe()
//
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
// so, enter AIM_STRAFE
int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int consider_target_only)
{
ai_info *aip;
ship_info *sip;
@@ -1772,7 +1778,7 @@ int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
// Consider attacking a turret, if a turret actually fired the weapon
// input: ship_objp => ship that will attack the turret
// weapon_objp =>
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp)
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
{
ai_info *aip;
object *parent_objp;
+3 -2
View File
@@ -17,13 +17,14 @@ struct ai_info;
struct vec3d;
class ship_subsys;
void ai_big_ship(object *objp);
void ai_big_chase();
void ai_big_subsys_path_cleanup(ai_info *aip);
// strafe functions
void ai_big_strafe();
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
int ai_big_maybe_enter_strafe_mode(object *objp, int weapon_objnum, int consider_target_only=0);
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp);
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
+279 -239
View File
File diff suppressed because it is too large. Load diff
+70 -105
View File
@@ -21,7 +21,6 @@
#include "object/waypoint.h"
#include "parse/sexp.h"
#include "playerman/player.h"
#include "scripting/scripting.h"
#include "ship/ship.h"
#include "weapon/weapon.h"
@@ -63,32 +62,31 @@ char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
// Used in objecttypes.tbl to define custom ship types
ai_goal_list Ai_goal_names[] =
{
{ "Attack ship", AI_GOAL_CHASE, 0 },
{ "Dock", AI_GOAL_DOCK, 0 },
{ "Waypoints", AI_GOAL_WAYPOINTS, 0 },
{ "Waypoints once", AI_GOAL_WAYPOINTS_ONCE, 0 },
{ "Depart", AI_GOAL_WARP, 0 },
{ "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 },
{ "Form on wing", AI_GOAL_FORM_ON_WING, 0 },
{ "Undock", AI_GOAL_UNDOCK, 0 },
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
{ "Play dead (persistent)", AI_GOAL_PLAY_DEAD_PERSISTENT, 0 },
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
{ "Attack ship", AI_GOAL_CHASE, 0 },
{ "Dock", AI_GOAL_DOCK, 0 },
{ "Waypoints", AI_GOAL_WAYPOINTS, 0 },
{ "Waypoints once", AI_GOAL_WAYPOINTS_ONCE, 0 },
{ "Depart", AI_GOAL_WARP, 0 },
{ "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 },
{ "Form on wing", AI_GOAL_FORM_ON_WING, 0 },
{ "Undock", AI_GOAL_UNDOCK, 0 },
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
};
int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
@@ -127,7 +125,7 @@ const char *Ai_goal_text(int goal)
case AI_GOAL_REARM_REPAIR:
return XSTR( "rearm ", 484);
case AI_GOAL_FLY_TO_SHIP:
return XSTR( "rendezvous with ", 1597);
return XSTR( "rendezvous with ", -1);
}
// Avoid compiler warning
@@ -269,12 +267,6 @@ void ai_clear_ship_goals( ai_info *aip )
{
ai_do_default_behavior( &Objects[Ships[aip->shipnum].objnum] );
}
// add scripting hook for 'On Goals Cleared' --wookieejedi
Script_system.SetHookObject("Ship", &Objects[Ships[aip->shipnum].objnum]);
Script_system.RunCondition(CHA_ONGOALSCLEARED);
Script_system.RemHookVars(1, "Ship");
}
void ai_clear_wing_goals( int wingnum )
@@ -310,7 +302,7 @@ void ai_clear_wing_goals( int wingnum )
void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
{
int mode, submode, priority, i;
const char *name;
char *name;
ai_goal *aigp;
wing *wingp;
@@ -388,7 +380,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
{
int i, j;
ai_goal *purge_goal;
const char *name;
char *name;
int mode, ship_index, wingnum;
// get locals for easer access
@@ -422,7 +414,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
if ( purge_ai_mode == AI_GOAL_CHASE_SHIP_CLASS ) {
// if the target of the purge goal is the same class of ship we are concerned about, then we have a match;
// if it is not, then we can continue (see standard ship check below)
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) != 0 )
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) )
continue;
}
// standard goals operating on either wings or ships
@@ -434,7 +426,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// don't match, we can continue; if the wing is valid, don't process if the wing numbers
// are different.
if ( purge_wing == -1 ) {
if ( stricmp(purge_goal->target_name, name ) != 0 )
if ( stricmp(purge_goal->target_name, name ) )
continue;
} else if ( purge_wing != wingnum )
continue;
@@ -740,12 +732,6 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, ch
aigp->target_signature = Objects[Weapons[submode].objnum].signature;
}
if ( mode == AI_GOAL_WAYPOINTS_ONCE || mode == AI_GOAL_WAYPOINTS ) {
// should be the same as setting via sexp, see ai_add_goal_sub_sexp
// set to null so the AI code can setup the new waypoint list, see ai_mission_goal_achievable
aigp->wp_list = nullptr;
}
if ( target_name != NULL )
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
else
@@ -951,11 +937,6 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->ai_mode = AI_GOAL_PLAY_DEAD;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->ai_mode = AI_GOAL_PLAY_DEAD_PERSISTENT;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
@@ -1145,10 +1126,6 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
goalmode = AI_GOAL_PLAY_DEAD;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
goalmode = AI_GOAL_PLAY_DEAD_PERSISTENT;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
goalmode = AI_GOAL_KEEP_SAFE_DISTANCE;
@@ -1286,7 +1263,7 @@ void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
// this name can be a shipname or a wingname)
// docker_point and dockee_point are used for the AI_GOAL_DOCK command to tell two ships where to dock
// immediate means to process this order right away
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*docker_point*/, int /*dockee_point*/, int immediate )
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate )
{
int gindex;
ai_goal *aigp;
@@ -1363,6 +1340,25 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
ai_process_mission_orders( Ships[aip->shipnum].objnum, aip );
}
// function to add an internal goal to a wing. Mike K says that the goal doesn't need to persist
// across waves of the wing so we merely need to add the goal to each ship in the wing. Certain
// goal are simply not valid for wings (like dock, undock). Immediate parameter gets passed to add_ship_goal
// to say whether or not we should process this goal right away
void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate )
{
int i;
// be sure we are not trying to issue dock or undock goals to wings
Assert ( (goal_type != AI_GOAL_DOCK) && (goal_type != AI_GOAL_UNDOCK) );
for (i = 0; i < wingp->current_count; i++) {
int num = wingp->ship_index[i];
if ( num == -1 ) // ship must have been destroyed or departed
continue;
ai_add_goal_ship_internal( &Ai_info[Ships[num].ai_index], goal_type, name, -1, -1, immediate);
}
}
// this function copies goals from a wing to an ai_info * from a ship.
void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
{
@@ -1376,7 +1372,7 @@ void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
}
if (j >= MAX_AI_GOALS) {
mprintf(("Unable to assign wing goal to ship %s; the ship goals are already filled to capacity\n", Ships[aip->shipnum].ship_name));
mprintf(("Unable to assign wing goal to ship %s; the ship goals are already filled to capacity", Ships[aip->shipnum].ship_name));
}
}
@@ -1405,7 +1401,7 @@ int 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) )
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) )
return AI_GOAL_ACHIEVABLE;
// warp (depart) only achievable if there's somewhere to depart to
@@ -1413,17 +1409,21 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
ship *shipp = &Ships[objp->instance];
// always valid if has working subspace drive, not disabled, and not limited by subsystem strength
if ( ship_can_warp_full_check(shipp) )
// always valid if has subspace drive
if (!(shipp->flags[Ship::Ship_Flags::No_subspace_drive]))
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_GOAL_ACHIEVABLE;
}
else {
return AI_GOAL_NOT_KNOWN;
// if no subspace drive, only valid if our mothership is present
// check that we have a mothership and that we can depart to it
if (shipp->departure_location == DEPART_AT_DOCK_BAY)
{
int anchor_shipnum = ship_name_lookup(Parse_names[shipp->departure_anchor]);
if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, shipp->departure_path_mask))
return AI_GOAL_ACHIEVABLE;
}
return AI_GOAL_NOT_KNOWN;
}
@@ -1502,8 +1502,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
Assert ( aigp->ai_submode >= 0 );
ssp = ship_get_indexed_subsys( &Ships[sindex], aigp->ai_submode );
if (ssp != NULL) {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (ssp->current_hits <= 0.0f) ? 1 : 0;
status = mission_log_get_time( LOG_SHIP_SUBSYS_DESTROYED, aigp->target_name, ssp->system_info->subobj_name, NULL );
} else {
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, Ships[sindex].ship_name));
@@ -1513,36 +1512,12 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
case AI_GOAL_DISABLE_SHIP:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (sindex < 0) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (Ships[sindex].subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
status = mission_log_get_time( LOG_SHIP_DISABLED, aigp->target_name, NULL, NULL );
break;
}
case AI_GOAL_DISARM_SHIP:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (sindex < 0) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (Ships[sindex].subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
status = mission_log_get_time( LOG_SHIP_DISARMED, aigp->target_name, NULL, NULL );
break;
}
// to guard or ignore a ship, the goal cannot continue if the ship being guarded is either destroyed
// or has departed.
@@ -1654,7 +1629,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
status = SHIP_STATUS_ARRIVED;
}
// goal ship is still on the arrival list
else if ( mission_check_ship_yet_to_arrive(aigp->target_name) )
else if ( mission_parse_get_arrival_ship(aigp->target_name) )
{
status = SHIP_STATUS_NOT_ARRIVED;
}
@@ -1920,12 +1895,9 @@ int ai_goal_priority_compare(const void *a, const void *b)
// check whether or not the goal override flag is set. If it is set, then push this goal higher
// in the list
// Goober5000: the ONLY goals we do not override are play-dead and play-dead-persistent,
// because the override flag needs to work in any other situation
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) && !(gb->ai_mode == AI_GOAL_PLAY_DEAD) && !(gb->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT) )
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) )
return -1;
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) && !(ga->ai_mode == AI_GOAL_PLAY_DEAD) && !(ga->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT))
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) )
return 1;
// now normal priority processing
@@ -2318,13 +2290,6 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
aip->submode_start_time = Missiontime;
break;
case AI_GOAL_PLAY_DEAD_PERSISTENT:
// same as above, but we don't clear out ship goals
aip->mode = AIM_PLAY_DEAD;
aip->submode = -1;
aip->submode_start_time = Missiontime;
break;
case AI_GOAL_FORM_ON_WING:
// for form on wing, we need to clear out all goals for this ship, and then call the form
// on wing AI code
+5 -5
View File
@@ -58,17 +58,16 @@ struct ai_goal;
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
// now the masks for ship types
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
//WMC - Don't need these anymore. Whee!
/*
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD| AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_FREIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CRUISER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FREIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CORVETTE ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
@@ -76,7 +75,7 @@ struct ai_goal;
#define AI_GOAL_ACCEPT_AWACS ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CAPITAL ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER & ~(AI_GOAL_DOCK | AI_GOAL_UNDOCK) | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_SUPERCAP ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CAPITAL | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT )
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD)
#define AI_GOAL_ACCEPT_ESCAPEPOD ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT| AI_GOAL_STAY_NEAR_SHIP )
*/
@@ -103,7 +102,7 @@ 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, int wingnum );
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 );
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
extern void ai_remove_wing_goal_sexp(int sexp, int wingnum);
@@ -128,5 +127,6 @@ extern char *ai_add_dock_name(const char *str);
extern int ai_query_goal_valid( int ship, int ai_goal_type );
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
extern void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate = 1 );
#endif
+28 -28
View File
@@ -24,7 +24,7 @@
#include "weapon/swarm.h"
#include "weapon/weapon.h"
#include <climits>
#include <limits.h>
// How close a turret has to be point at its target before it
@@ -243,7 +243,7 @@ int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
* @note All non-negative return values are expressed in what I like to call "widx"s.
* @return -1 if unable to find a weapon for the target at all.
*/
int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
int turret_select_best_weapon(ship_subsys *turret, object *target)
{
//TODO: Fill this out with extraodinary gun-picking algorithms
if(turret->weapons.num_primary_banks > 0)
@@ -856,11 +856,11 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
// flags for weapon types
if (beam_flag)
eeo.eeo_flags |= EEOF_BEAM;
if (flak_flag)
else if (flak_flag)
eeo.eeo_flags |= EEOF_FLAK;
if (laser_flag)
else if (laser_flag)
eeo.eeo_flags |= EEOF_LASER;
if (missile_flag)
else if (missile_flag)
eeo.eeo_flags |= EEOF_MISSILE;
eeo.enemy_team_mask = enemy_team_mask;
@@ -1290,9 +1290,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
model_instance_find_world_point(&tmp_pos, &avg, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient, &objp->pos);
if (targetp == nullptr) {
ship* shipp = &Ships[Objects[ssp->parent_objnum].instance];
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name,
(shipp->has_display_name()) ? shipp->display_name.c_str() : shipp->ship_name);
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship number %d is invalid.", ssp->turret_enemy_objnum, ssp->sub_name, ssp->parent_objnum);
object *lep = &Objects[ssp->turret_enemy_objnum];
int best_weapon_tidx = turret_select_best_weapon(ssp, lep);
@@ -1303,9 +1301,9 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
weapon_info *wip = get_turret_weapon_wip(&ssp->weapons, best_weapon_tidx);
float weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
float weapon_system_strength = ship_get_subsystem_strength(&Ships[ssp->parent_objnum], SUBSYSTEM_WEAPONS);
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
turret_ai_update_aim(&Ai_info[Ships[ssp->parent_objnum].ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
if ((ssp->targeted_subsys != nullptr) && !(ssp->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
vm_vec_unrotate(&enemy_point, &ssp->targeted_subsys->system_info->pnt, &Objects[ssp->turret_enemy_objnum].orient);
@@ -1678,12 +1676,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
wait *= wip->burst_delay;
turret->weapons.burst_counter[weapon_num]++;
} else {
// Random fire delay (DahBlount) used in ship_fire_primary(), added here by wookieejedi to correct oversight
if (wip->max_delay != 0.0f && wip->min_delay != 0.0f) {
wait *= frand_range(wip->min_delay, wip->max_delay);
} else {
wait *= wip->fire_wait;
}
wait *= wip->fire_wait;
if ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Random_length])) {
turret->weapons.burst_counter[weapon_num] = (myrand() % wip->burst_shots);
} else {
@@ -1812,7 +1805,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
parent_aip = &Ai_info[Ships[Objects[parent_objnum].instance].ai_index];
parent_ship = &Ships[Objects[parent_objnum].instance];
wip = get_turret_weapon_wip(&turret->weapons, weapon_num);
int turret_weapon_class = weapon_info_get_index(wip);
int turret_weapon_class = WEAPON_INFO_INDEX(wip);
#ifndef NDEBUG
// moved here from check_ok_to_fire
@@ -1881,7 +1874,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
turret->last_fired_weapon_info_index = turret_weapon_class;
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.RunCondition(CHA_ONTURRETFIRED, 0, NULL, &Objects[parent_objnum]);
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
}
@@ -2016,7 +2009,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
wp->turret_subsys = turret;
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.RunCondition(CHA_ONTURRETFIRED, 0, NULL, &Objects[parent_objnum]);
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
// if the gun is a flak gun
@@ -2055,7 +2048,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
if ( wip->launch_snd.isValid() ) {
if ( wip->launch_snd != -1 ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( parent_objnum != OBJ_INDEX(Player_obj) || (turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), turret_pos, &View_position );
@@ -2133,7 +2126,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
tsi->turret->last_fired_weapon_info_index = tsi->weapon_class;
Script_system.SetHookObjects(4, "Ship", &Objects[tsi->parent_objnum], "Weapon", &Objects[weapon_objnum], "Beam", nullptr, "Target", &Objects[tsi->turret->turret_enemy_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[tsi->parent_objnum]);
Script_system.RunCondition(CHA_ONTURRETFIRED, 0, NULL, &Objects[tsi->parent_objnum]);
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
// muzzle flash?
@@ -2142,7 +2135,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
}
// maybe sound
if ( Weapon_info[tsi->weapon_class].launch_snd.isValid() ) {
if ( Weapon_info[tsi->weapon_class].launch_snd != -1 ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( tsi->parent_objnum != OBJ_INDEX(Player_obj) ) {
snd_play_3d( gamesnd_get_game_sound(Weapon_info[tsi->weapon_class].launch_snd), &turret_pos, &View_position );
@@ -2544,6 +2537,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// Ok, the turret is lined up... now line up a particular gun.
bool ok_to_fire = false;
bool something_was_ok_to_fire=false;
vec3d tv2e; //so flak can get their jitter without screwing up other guns
if (in_fov ) {
@@ -2580,9 +2574,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
ss->turret_next_fire_pos = ffp_pos;
}
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
ship_get_global_turret_gun_info(&Objects[parent_objnum], ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
ship_get_global_turret_gun_info(&Objects[parent_objnum], ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
// Fire in the direction the turret is facing, not right at the target regardless of turret dir.
vm_vec_sub(&v2e, &predicted_enemy_pos, &gpos);
@@ -2593,6 +2585,12 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[0]);
else
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[i]);
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
// moved here as if there are two weapons with indentical fire stamps
// they would have shared the fire point.
tv2e = gvec;
// make sure to reset this for current weapon
ok_to_fire = false;
@@ -2600,7 +2598,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
flak_jitter_aim(&v2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
flak_jitter_aim(&tv2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
// Fire if:
@@ -2711,9 +2709,9 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
//Pass along which gun we are using
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &v2e, &predicted_enemy_pos);
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
else
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &v2e, &predicted_enemy_pos);
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
} else {
// make sure salvo fire mode does not turn into autofire
if ((tp->flags[Model::Subsystem_Flags::Turret_salvo]) && ((i + 1) == number_of_firings)) {
@@ -2726,6 +2724,8 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
if(!something_was_ok_to_fire)
{
mprintf(("nothing ok to fire\n"));
if (ss->turret_best_weapon >= 0) {
//Impose a penalty on turret accuracy for losing site of its goal, or just not being able to fire.
turret_update_enemy_in_range(ss, -4*Weapon_info[ss->turret_best_weapon].fire_wait);
+171 -2
View File
@@ -274,9 +274,9 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
percent_through = instance->time_elapsed / time;
if(instance->direction == ANIM_DIRECT_FORWARD)
new_frame_num = instance->start_at - 1 + (int) lround(percent_through * n_frames);
new_frame_num = instance->start_at - 1 + fl2i(percent_through * n_frames + 0.5f);
else
new_frame_num = instance->start_at - 1 - (int) lround(percent_through * n_frames);
new_frame_num = instance->start_at - 1 - fl2i(percent_through * n_frames + 0.5f);
frame_save = instance->frame_num;
@@ -519,6 +519,19 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
return 0;
}
/**
* @brief Stop an anim instance that is on the anim_render_list from playing
*/
int anim_stop_playing(anim_instance* instance)
{
Assert(instance != NULL);
if ( anim_playing(instance) ) {
anim_release_render_instance(instance);
}
return 0;
}
/**
* @brief Free a particular animation instance that is on the anim_render_list.
* Do not call this function to free an animation instance in general (use
@@ -853,6 +866,20 @@ int anim_free(anim *ptr)
return 0;
}
/**
* @brief Return if an anim is playing or not.
*/
int anim_playing(anim_instance *ai)
{
Assert(ai != NULL);
if ( ai->frame == NULL )
return 0;
else
return 1;
}
/**
* @brief Called at the beginning of a mission to initialize any mission dependent anim data.
* @todo Redundant?
@@ -869,6 +896,138 @@ void anim_level_close()
anim_release_all_instances();
}
/**
* @brief Write the frames of a .ani file out to disk as .pcx files.
* @details Use naming convention: filename0000.pcx, filename0001.pcx etc.
*
* @return If success 0, or if failed -1
*/
int anim_write_frames_out(char *filename)
{
anim *source_anim;
anim_instance *ai;
char root_name[256], pcxname[256];
char buf[64];
int i,j;
ubyte **row_data;
strcpy_s(root_name, filename);
root_name[strlen(filename)-4] = 0;
source_anim = anim_load(filename);
if ( source_anim == NULL )
return -1;
ai = init_anim_instance(source_anim, 16);
row_data = (ubyte**)vm_malloc((source_anim->height+1) * 4);
for ( i = 0; i < source_anim->total_frames; i++ ) {
anim_get_next_raw_buffer(ai, 0, 0, 16);
strcpy_s(pcxname, root_name);
sprintf(buf,"%04d",i);
strcat_s(pcxname, buf);
for ( j = 0; j < source_anim->height; j++ ) {
row_data[j] = &ai->frame[j*source_anim->width];
}
pcx_write_bitmap( pcxname,
source_anim->width,
source_anim->height,
row_data,
source_anim->palette);
printf(".");
}
printf("\n");
vm_free(row_data);
return 0;
}
/**
* @brief Display information and statistics about a .ani file.
* @details This is called when -i switch is on when running ac.exe
*/
void anim_display_info(char *real_filename)
{
CFILE *fp;
anim A;
float percent;
int i, uncompressed, compressed, *key_frame_nums=NULL, tmp;
char filename[MAX_FILENAME_LEN];
strcpy_s( filename, real_filename );
char *p = strchr( filename, '.' );
if ( p ) {
*p = 0;
}
strcat_s( filename, ".ani" );
fp = cfopen(filename, "rb");
if ( !fp ) {
printf("Fatal error opening %s", filename);
return;
}
anim_read_header(&A, fp);
if (A.width < 0 || A.height < 0) {
Error(LOCATION, "Ani file %s has a faulty header and cannot be loaded.", filename);
}
// read the keyframe frame nums and offsets
key_frame_nums = (int*)vm_malloc(sizeof(int)*A.num_keys);
Assert(key_frame_nums != NULL);
if (key_frame_nums == NULL)
return;
for ( i = 0; i < A.num_keys; i++ ) {
key_frame_nums[i] = 0;
cfread(&key_frame_nums[i], 2, 1, fp);
cfread(&tmp, 4, 1, fp);
}
cfread(&compressed, 4, 1, fp);
uncompressed = A.width * A.height * A.total_frames; // 8 bits per pixel
percent = i2fl(compressed) / uncompressed * 100.0f;
printf("%% of uncompressed size: %.0f%%\n", percent);
printf("Width: %d\n", A.width);
printf("Height: %d\n", A.height);
printf("Total Frames: %d\n", A.total_frames);
#ifndef NDEBUG
printf("Key Frames: %d\n", A.num_keys);
if ( A.num_keys > 1 && (A.total_frames != A.num_keys) ) {
printf("key list: (");
for ( i = 0; i < A.num_keys; i++ ) {
if ( i < A.num_keys-1 )
printf("%d, ", key_frame_nums[i]);
else
printf("%d)\n", key_frame_nums[i]);
}
}
#endif
printf("FPS: %d\n", A.fps);
#ifndef NDEBUG
printf("Transparent RGB: (%u,%u,%u)\n", A.xparent_r, A.xparent_g, A.xparent_b);
#endif
printf("ac version: %d\n", A.version);
if ( key_frame_nums != NULL ) {
vm_free(key_frame_nums);
}
cfclose(fp);
}
void anim_reverse_direction(anim_instance *ai)
{
int temp;
@@ -902,6 +1061,16 @@ void anim_reverse_direction(anim_instance *ai)
}
}
void anim_pause(anim_instance *ai)
{
ai->paused = 1;
}
void anim_unpause(anim_instance *ai)
{
ai->paused = 0;
}
void anim_ignore_next_frametime()
{
Anim_ignore_frametime=1;
+6
View File
@@ -54,13 +54,19 @@ void anim_render_one(int screen_id, anim_instance *ani, float frametime);
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int max_x = -1, int max_y = -1);
anim_instance *anim_play(anim_play_struct *aps);
void anim_ignore_next_frametime();
int anim_stop_playing(anim_instance* anim_instance);
int anim_show_next_frame(anim_instance *instance, float frametime);
void anim_release_all_instances(int screen_id = 0);
void anim_release_render_instance(anim_instance* instance);
anim *anim_load(const char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_DISK);
int anim_free(anim *ptr);
int anim_playing(anim_instance *ai);
int anim_write_frames_out(char *filename);
void anim_display_info(char *filename);
void anim_read_header(anim *ptr, CFILE *fp);
void anim_reverse_direction(anim_instance *ai); // called automatically for ping-ponging, and can also be called externally
void anim_pause(anim_instance *ai);
void anim_unpause(anim_instance *ai);
int anim_instance_is_streamed(anim_instance *ai);
unsigned char anim_instance_get_byte(anim_instance *ai, int offset);
+361
View File
@@ -78,6 +78,52 @@ void free_anim_instance(anim_instance *inst)
vm_free(inst);
}
int anim_get_next_frame(anim_instance *inst)
{
int bm, bitmap_flags;
int aabitmap = 0;
int bpp = 16;
if ( anim_instance_is_streamed(inst) ) {
if ( inst->file_offset <= 0 ) {
return -1;
}
} else {
if (!inst->data)
return -1;
}
inst->frame_num++;
if (inst->frame_num >= inst->parent->total_frames) {
inst->data = NULL;
inst->file_offset = inst->parent->file_offset;
return -1;
}
bitmap_flags = 0;
bpp = 16;
if(inst->aa_color != NULL){
bitmap_flags |= BMP_AABITMAP;
aabitmap = 1;
bpp = 8;
}
anim_check_for_palette_change(inst);
BM_SELECT_TEX_FORMAT();
if ( anim_instance_is_streamed(inst) ) {
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
} else {
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
}
bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
bm_unload(bm);
return bm;
}
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
{
if ( anim_instance_is_streamed(inst) ) {
@@ -116,6 +162,321 @@ ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap
return inst->frame;
}
/**
* @brief Pack key frame
*
* @param frame Frame pixel data to pack
* @param save Memory to store packed data to
* @param size Number of bytes to pack
* @param max Maximum number of packed bytes (size of buffer)
* @param compress_type Compress type
* @return Actual number of bytes data packed to or -1 if error
*/
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
{
int last = -32768, count = 0;
long packed_size = 1;
switch ( compress_type ) {
case PACKING_METHOD_RLE_KEY:
*save++ = PACKING_METHOD_RLE_KEY;
while (size--) {
if (*frame != last || count > 255) {
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)last;
packed_size += 3;
}
count = 0;
last = *frame;
}
count++;
frame++;
}
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)last;
packed_size += 3;
}
break;
case PACKING_METHOD_STD_RLE_KEY: {
ubyte *dest_start;
int i;
dest_start = save;
count = 1;
last = *frame++;
*save++ = PACKING_METHOD_STD_RLE_KEY;
for (i=1; i < size; i++ ) {
if ( *frame != last ) {
if ( count ) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
last = *frame;
count = 0;
}
count++;
frame++;
if ( count == 127 ) {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
count = 0;
}
} // end for
if (count) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
Assert(packed_size == (save-dest_start) );
return packed_size;
}
default:
Assert(0);
return -1;
break;
} // end switch
return packed_size;
}
/**
* @brief Pack frame
*
* @param frame Frame pixel data to pack
* @param frame2 Previous frame's pixel data
* @param save Memory to store packed data to
* @param size Number of bytes to pack
* @param max Maximum number of packed bytes (size of buffer)
* @param compress_type Compress type
* @return Actual number of bytes data packed to or -1 if error
*/
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
{
int pixel, last = -32768, count = 0, i;
long packed_size = 1;
switch ( compress_type ) {
case PACKING_METHOD_RLE: // Hoffoss RLE regular frame
*save++ = PACKING_METHOD_RLE;
while (size--) {
if (*frame != *frame2++)
pixel = *frame;
else
pixel = transparent_code;
if (pixel != last || count > 255) {
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)last;
packed_size += 3;
}
count = 0;
last = pixel;
}
frame++;
count++;
}
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)(packer_code);
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)(last);
packed_size += 3;
}
break;
case PACKING_METHOD_STD_RLE: { // high bit count regular RLE frame
ubyte *dest_start;
dest_start = save;
count = 1;
if (*frame++ != *frame2++)
last = *frame;
else
last = transparent_code;
*save++ = PACKING_METHOD_STD_RLE;
for (i=1; i < size; i++ ) {
if (*frame != *frame2++)
pixel = *frame;
else
pixel = transparent_code;
if ( pixel != last ) {
if ( count ) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
last = pixel;
count = 0;
}
count++;
frame++;
if ( count == 127 ) {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
count = 0;
}
} // end for
if (count) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
Assert(packed_size == (save-dest_start) );
return packed_size;
}
default:
Assert(0);
return -1;
break;
} // end switch
return packed_size;
}
/**
* @brief Convert a 24 bit value to a 16 bit value
* @param bit_24 24 bit value
+4
View File
@@ -97,12 +97,16 @@ typedef struct anim_instance {
int loop_count; // starts at 0, and is incremented each time it loops
} anim_instance;
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type);
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type);
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
void anim_init();
anim_instance *init_anim_instance(anim *ptr, int bpp);
void free_anim_instance(anim_instance *inst);
int anim_get_next_frame(anim_instance *inst);
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp);
void anim_set_palette(anim *a);
void anim_check_for_palette_change(anim_instance *inst);
+109 -45
View File
@@ -76,7 +76,7 @@ float Asteroid_icon_closeup_zoom;
/**
* Force updating of pair stuff for asteroid *objp.
*/
static void asteroid_update_collide(object *objp)
void asteroid_update_collide(object *objp)
{
// Asteroid has wrapped, update collide objnum and flags
Asteroids[objp->instance].collide_objnum = -1;
@@ -87,7 +87,7 @@ static void asteroid_update_collide(object *objp)
/**
* Clear out the ::Asteroid_obj_list
*/
static void asteroid_obj_list_init()
void asteroid_obj_list_init()
{
int i;
@@ -101,7 +101,7 @@ static void asteroid_obj_list_init()
* Add a node from the Asteroid_obj_list.
* Only called from ::weapon_create()
*/
static int asteroid_obj_list_add(int objnum)
int asteroid_obj_list_add(int objnum)
{
int index;
@@ -123,7 +123,7 @@ static int asteroid_obj_list_add(int objnum)
* Remove a node from the Asteroid_obj_list.
* Only called from ::weapon_delete()
*/
static void asteroid_obj_list_remove(object * obj)
void asteroid_obj_list_remove(object * obj)
{
int index = obj->instance;
@@ -138,7 +138,7 @@ static void asteroid_obj_list_remove(object * obj)
/**
* Prevent speed from getting too huge so it's hard to catch up to an asteroid.
*/
static float asteroid_cap_speed(int asteroid_info_index, float speed)
float asteroid_cap_speed(int asteroid_info_index, float speed)
{
float max, double_max;
@@ -164,7 +164,7 @@ static float asteroid_cap_speed(int asteroid_info_index, float speed)
* Sum together the following: 1 inside x, 2 inside y, 4 inside z
* inside only when sum = 7
*/
static int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, float delta)
int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, float delta)
{
Assert(asfieldp->has_inner_bound);
@@ -188,7 +188,7 @@ static int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *po
* Check if asteroid is within inner bound
* @return 0 if not inside or no inner bound, 1 if inside inner bound
*/
static int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
if (!asfieldp->has_inner_bound) {
return 0;
@@ -202,7 +202,7 @@ static int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float d
*
* Moves to the other side of the inner box a distance delta from edge of box
*/
static void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
{
if (!asteroid_in_inner_bound(asfieldp, pos, 0)) {
return;
@@ -446,7 +446,7 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
/**
* Load in an asteroid model
*/
static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
void asteroid_load(int asteroid_info_index, int asteroid_subtype)
{
int i;
asteroid_info *asip;
@@ -478,7 +478,7 @@ static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
}
else
{
nprintf(("Warning", "For asteroid '%s', detail level mismatch (POF needs %d)\n", asip->name, pm->n_detail_levels));
nprintf(("Warning", "For asteroid '%s', detail level mismatch (POF needs %d)", asip->name, pm->n_detail_levels));
}
}
// Stuff detail level distances.
@@ -487,12 +487,26 @@ static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
}
}
/**
* Randomly choose a debris model within the current group
*/
int get_debris_from_same_group(int index) {
int group_base, group_offset;
group_base = (index / NUM_DEBRIS_SIZES) * NUM_DEBRIS_SIZES;
group_offset = index - group_base;
// group base + offset
// offset is formed by adding 1 or 2 (since 3 in model group) and mapping back in the 0-2 range
return group_base + ((group_offset + rand()%(NUM_DEBRIS_SIZES-1) + 1) % NUM_DEBRIS_SIZES);
}
/**
* Returns a weight that depends on asteroid size.
*
* The weight is then used to determine the frequencty of different sizes of ship debris
*/
static int get_debris_weight(int ship_debris_index)
int get_debris_weight(int ship_debris_index)
{
int size = ship_debris_index % NUM_DEBRIS_SIZES;
switch (size)
@@ -612,7 +626,7 @@ void asteroid_create_all()
}
/**
* Init asteroid system for the level, called from ::game_level_init()
* Init asteriod system for the level, called from ::game_level_init()
*/
void asteroid_level_init()
{
@@ -631,7 +645,7 @@ void asteroid_level_init()
*
* @return !0 if asteroid should be wrapped, 0 otherwise.
*/
static int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
{
if ( MULTIPLAYER_CLIENT )
return 0;
@@ -676,7 +690,7 @@ static int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
/**
* Wrap an asteroid from one end of the asteroid field to the other
*/
static void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
{
if (objp->pos.xyz.x < asfieldp->min_bound.xyz.x) {
objp->pos.xyz.x = asfieldp->max_bound.xyz.x + (objp->pos.xyz.x - asfieldp->min_bound.xyz.x);
@@ -713,7 +727,7 @@ static void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
*
* @return !0 if this asteroid is a target for any ship, otherwise return 0
*/
static int asteroid_is_targeted(object *objp)
int asteroid_is_targeted(object *objp)
{
ship_obj *so;
object *ship_objp;
@@ -734,7 +748,7 @@ static int asteroid_is_targeted(object *objp)
/**
* Create an asteroid that will hit object *objp in delta_time seconds
*/
static void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
{
vec3d predicted_center_pos;
vec3d rand_vec;
@@ -762,7 +776,7 @@ static void asteroid_aim_at_target(object *objp, object *asteroid_objp, float de
*
* @param count asteroids already targeted on
*/
static void maybe_throw_asteroid(int count)
void maybe_throw_asteroid(int count)
{
if (!timestamp_elapsed(Next_asteroid_throw)) {
return;
@@ -836,7 +850,7 @@ void asteroid_delete( object * obj )
* See if we should reposition the asteroid.
* Only reposition if oustide the bounding volume and the player isn't looking towards the asteroid.
*/
static void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
{
// passive field does not wrap
if (asfieldp->field_type == FT_PASSIVE) {
@@ -889,7 +903,7 @@ static void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
}
}
static void lerp(float *goal, float f1, float f2, float scale)
void lerp(float *goal, float f1, float f2, float scale)
{
*goal = (f2 - f1) * scale + f1;
}
@@ -1143,6 +1157,8 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// SET PHYSICS PARAMETERS
// already have (hitpos - heavy) and light_cm_pos
// get heavy cm pos - already have light_cm_pos
asteroid_hit_info->heavy_collision_cm_pos = zero;
// get r_heavy and r_light
asteroid_hit_info->r_heavy = asteroid_hit_info->hit_pos;
@@ -1191,7 +1207,7 @@ void asteroid_render(object * obj, model_draw_list *scene)
/**
* Create a normalized vector generally in the direction from *hitpos to other_obj->pos
*/
static void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
{
vec3d tvec, rand_vec;
int count = 0;
@@ -1213,7 +1229,7 @@ static void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
/**
* Return multiplier on asteroid radius for fireball
*/
static float asteroid_get_fireball_scale_multiplier(int num)
float asteroid_get_fireball_scale_multiplier(int num)
{
if (Asteroids[num].flags & AF_USED) {
asteroid_info *asip = &Asteroid_info[Asteroids[num].asteroid_type];
@@ -1242,7 +1258,7 @@ static float asteroid_get_fireball_scale_multiplier(int num)
* Create asteroid explosion
* @return expected time for explosion anim to last, in seconds
*/
static float asteroid_create_explosion(object *objp)
float asteroid_create_explosion(object *objp)
{
int fireball_objnum;
float explosion_life, fireball_scale_multiplier;
@@ -1261,7 +1277,7 @@ static float asteroid_create_explosion(object *objp)
fireball_scale_multiplier = asteroid_get_fireball_scale_multiplier(objp->instance);
fireball_objnum = fireball_create( &objp->pos, fireball_type, FIREBALL_LARGE_EXPLOSION, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, false, &objp->phys_info.vel );
fireball_objnum = fireball_create( &objp->pos, fireball_type, FIREBALL_LARGE_EXPLOSION, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, 0, &objp->phys_info.vel );
if ( fireball_objnum > -1 ) {
explosion_life = fireball_lifeleft(&Objects[fireball_objnum]);
} else {
@@ -1274,23 +1290,23 @@ static float asteroid_create_explosion(object *objp)
/**
* Play sound when asteroid explodes
*/
static void asteroid_explode_sound(object *objp, int type, int play_loud)
void asteriod_explode_sound(object *objp, int type, int play_loud)
{
gamesnd_id sound_index;
int sound_index = -1;
float range_factor = 1.0f; // how many times sound should traver farther than normal
if (type % NUM_DEBRIS_SIZES <= 1)
{
sound_index = gamesnd_id(GameSounds::ASTEROID_EXPLODE_SMALL);
sound_index = SND_ASTEROID_EXPLODE_SMALL;
range_factor = 5.0;
}
else
{
sound_index = gamesnd_id(GameSounds::ASTEROID_EXPLODE_LARGE);
sound_index = SND_ASTEROID_EXPLODE_LARGE;
range_factor = 10.0f;
}
Assert(sound_index.isValid());
Assert(sound_index != -1);
if ( !play_loud ) {
range_factor = 1.0f;
@@ -1302,9 +1318,9 @@ static void asteroid_explode_sound(object *objp, int type, int play_loud)
/**
* Do the area effect for an asteroid exploding
*
* @param asteroid_objp object pointer to asteroid causing explosion
* @param asteroid_objp object pointer to asteriod causing explosion
*/
static void asteroid_do_area_effect(object *asteroid_objp)
void asteroid_do_area_effect(object *asteroid_objp)
{
object *ship_objp;
float damage, blast;
@@ -1366,7 +1382,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
explosion_life = asteroid_create_explosion(pasteroid_obj);
asteroid_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
asteriod_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
asteroid_do_area_effect(pasteroid_obj);
asp->final_death_time = timestamp( fl2i(explosion_life*1000.0f)/5 ); // Wait till 30% of vclip time before breaking the asteroid up.
@@ -1385,7 +1401,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
weapon_info *wip;
wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
// If the weapon didn't play any impact animation, play custom asteroid impact animation
if (!wip->impact_weapon_expl_effect.isValid()) {
if ( wip->impact_weapon_expl_effect < 0 ) {
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, particle::PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
}
}
@@ -1416,6 +1432,35 @@ void asteroid_level_close()
DCF_BOOL2(asteroids, Asteroids_enabled, "enables or disables asteroids", "Usage: asteroids [bool]\nTurns asteroid system on/off. If nothing passed, then toggles it.\n");
void hud_target_asteroid()
{
int i;
int start_index = 0, end_index = MAX_ASTEROIDS;
if (Player_ai->target_objnum != -1) {
if (Objects[Player_ai->target_objnum].type == OBJ_ASTEROID) {
start_index = Objects[Player_ai->target_objnum].instance+1;
end_index = start_index-1;
if (end_index < 0)
end_index = MAX_ASTEROIDS;
}
}
i = start_index;
while (i != end_index) {
if (i == MAX_ASTEROIDS)
i = 0;
if (Asteroids[i].flags & AF_USED) {
Assert(Objects[Asteroids[i].objnum].type == OBJ_ASTEROID);
set_target_objnum( Player_ai, Asteroids[i].objnum);
break;
}
i++;
}
}
/**
* Return the number of active asteroids
*/
@@ -1428,7 +1473,7 @@ int asteroid_count()
* See if asteroid should split up.
* We delay splitting up to allow the explosion animation to play for a bit.
*/
static void asteroid_maybe_break_up(object *pasteroid_obj)
void asteroid_maybe_break_up(object *pasteroid_obj)
{
asteroid *asp;
asteroid_info *asip;
@@ -1545,12 +1590,31 @@ static void asteroid_maybe_break_up(object *pasteroid_obj)
}
asp->final_death_time = timestamp(-1);
}
Script_system.RunCondition(CHA_DEATH, pasteroid_obj);
Script_system.RunCondition(CHA_DEATH, '\0', NULL, pasteroid_obj);
Script_system.RemHookVar("Self");
}
}
static void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger)
{
int idx;
vec3d asteroid_dir;
// just pick the first asteroid which satisfies our condition
for(idx=0; idx<Num_asteroids; idx++){
vm_vec_sub(&asteroid_dir, &Objects[Asteroids[idx].objnum].pos, pos);
vm_vec_normalize_quick(&asteroid_dir);
// if it satisfies the condition
if(vm_vec_dot(dir, &asteroid_dir) >= ang){
return idx;
}
}
return -1;
}
void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
{
float asteroid_ray_dist;
vec3d asteroid_fvec, terminus;
@@ -1592,7 +1656,7 @@ static void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_i
*
* @return !0 if the asteroid will collide with the escort
*/
static int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
{
mc_info mc;
mc_info_init(&mc);
@@ -1610,7 +1674,7 @@ static int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
* Warn if asteroid on collision path with ship
* @return !0 if we should warn about asteroid hitting ship, otherwise return 0
*/
static int asteroid_valid_ship_to_warn_collide(ship *shipp)
int asteroid_valid_ship_to_warn_collide(ship *shipp)
{
if ( !(Ship_info[shipp->ship_info_index].is_big_or_huge()) ) {
return 0;
@@ -1632,7 +1696,7 @@ static int asteroid_valid_ship_to_warn_collide(ship *shipp)
* See if asteroid will collide with a large ship on the escort list in the next
* ASTEROID_MIN_COLLIDE_TIME seconds.
*/
static void asteroid_update_collide_flag(object *asteroid_objp)
void asteroid_update_collide_flag(object *asteroid_objp)
{
int i, num_escorts, escort_objnum, will_collide=0;
ship *escort_shipp;
@@ -1671,7 +1735,7 @@ static void asteroid_update_collide_flag(object *asteroid_objp)
/**
* Ensure that the collide objnum for the asteroid is still valid
*/
static void asteroid_verify_collide_objnum(asteroid *asp)
void asteroid_verify_collide_objnum(asteroid *asp)
{
if ( asp->collide_objnum >= 0 ) {
if ( Objects[asp->collide_objnum].signature != asp->collide_objsig ) {
@@ -1751,7 +1815,7 @@ float asteroid_time_to_impact(object *asteroid_objp)
/**
* Read in a single asteroid section from asteroid.tbl
*/
static void asteroid_parse_section(asteroid_info *asip)
void asteroid_parse_section(asteroid_info *asip)
{
required_string("$Name:");
stuff_string(asip->name, F_NAME, NAME_LENGTH);
@@ -1851,7 +1915,7 @@ to do with the debris of ships that explode, however these
are the same debris and asteroids that get flung at a ship
that is being protected.
*/
static void asteroid_parse_tbl()
void asteroid_parse_tbl()
{
char impact_ani_file[MAX_FILENAME_LEN];
@@ -1937,11 +2001,11 @@ static void asteroid_parse_tbl()
if (tally != max_asteroids)
{
#ifndef NDEBUG
mprintf(("Asteroid.tbl as parsed:\n"));
for (SCP_vector<SCP_string>::iterator iter = parsed_asteroids.begin();
iter != parsed_asteroids.end(); ++iter)
{
mprintf(("%s\n", iter->c_str()));
mprintf(("Asteroid.tbl as parsed:\n"));
mprintf(("%s", iter->c_str()));
}
#endif
Error(LOCATION,
@@ -2002,7 +2066,7 @@ static void asteroid_parse_tbl()
/**
* Return number of asteroids expected to collide with a ship.
*/
static int count_incident_asteroids()
int count_incident_asteroids()
{
object *asteroid_objp;
int count;
@@ -2026,7 +2090,7 @@ static int count_incident_asteroids()
* Pick object to throw asteroids at.
* Pick any capital or big ship inside the bounds of the asteroid field.
*/
static int set_asteroid_throw_objnum()
int set_asteroid_throw_objnum()
{
if (Asteroid_field.num_initial_asteroids < 1)
return -1;
+1
View File
@@ -163,6 +163,7 @@ int asteroid_collide_objnum(object *asteroid_objp);
float asteroid_time_to_impact(object *asteroid_objp);
void asteroid_show_brackets();
void asteroid_target_closest_danger();
int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger = 0);
// need to extern for multiplayer
void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec);
+51 -5
View File
@@ -122,6 +122,31 @@ vec3d *NavPoint::GetPosition()
}
}
char* NavPoint::GetInternalName()
{
char *NavName;
char strtmp[33];
if (flags & NP_WAYPOINT)
{
NavName = new char[strlen(((waypoint_list*)target_obj)->get_name())+5];
memset(NavName, 0, strlen(((waypoint_list*)target_obj)->get_name())+5);
strcpy(NavName, ((waypoint_list*)target_obj)->get_name());
strcat(NavName, ":");
sprintf(strtmp, "%d", waypoint_num);
strcat(NavName, strtmp);
}
else
{
NavName = new char[strlen(((ship*)target_obj)->ship_name)+1];
memset(NavName, 0, strlen(((ship*)target_obj)->ship_name)+1);
strcpy(NavName, ((ship*)target_obj)->ship_name);
}
return NavName;
}
// ********************************************************************************************
bool CanAutopilot(vec3d targetPos, bool send_msg)
{
@@ -218,9 +243,9 @@ bool StartAutopilot()
if (shipp->team != Player_ship->team)
continue;
Assertion((shipp->ship_info_index >= 0) && (shipp->ship_info_index < ship_info_size()),
Assertion((shipp->ship_info_index >= 0) && (shipp->ship_info_index < static_cast<int>(Ship_info.size())),
"Ship '%s' does not have a valid pointer to a ship class. Pointer is %d, which is smaller than 0 or bigger than %d",
shipp->ship_name, shipp->ship_info_index, ship_info_size());
shipp->ship_name, shipp->ship_info_index, static_cast<int>(Ship_info.size()));
ship_info *sip = &Ship_info[shipp->ship_info_index];
if ( !(sip->flags[Ship::Info_Flags::Support]) )
@@ -973,6 +998,7 @@ camera* nav_get_set_camera()
return nav_camera.getCamera();
}
extern int Cmdline_old_collision_sys;
void nav_warp(bool prewarp=false)
{
/* ok... find our end distance - norm1 is still a unit vector in the
@@ -1027,7 +1053,11 @@ void nav_warp(bool prewarp=false)
}
// retime all collision pairs
obj_collide_retime_cached_pairs();
if ( Cmdline_old_collision_sys ) {
obj_all_collisions_retime();
} else {
obj_collide_retime_cached_pairs();
}
}
// ********************************************************************************************
@@ -1201,7 +1231,7 @@ void send_autopilot_msg(char *msg, char *snd)
audio_handle = -1;
}
if (msg[0] != '\0' && strcmp(msg, "none") != 0)
if (msg[0] != '\0' && strcmp(msg, "none"))
change_message("autopilot builtin message", msg, -1, 0);
// load sound
@@ -1216,7 +1246,7 @@ void send_autopilot_msg(char *msg, char *snd)
audiostream_play(audio_handle, (Master_event_music_volume * aav_music_volume), 0);
}
if (msg[0] != '\0' && strcmp(msg, "none") != 0)
if (msg[0] != '\0' && strcmp(msg, "none"))
message_training_queue("autopilot builtin message", timestamp(0), 5); // display message for five seconds
}
@@ -1434,6 +1464,22 @@ bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags)
}
// ********************************************************************************************
//Change Flags
bool Nav_Alt_Flags(char *Nav, int flags)
{
flags &= ~NP_VALIDTYPE; //clear the NP_SHIP and NP_WAYPOINT bits, make sure they haven't been set
int nav = FindNav(Nav);
if (nav != -1)
{
Navs[nav].flags &= NP_VALIDTYPE; // Clear all bits BUT NP_SHIP or NO_WAYPOINT
Navs[nav].flags |= flags; // merge
}
return (nav != -1);
}
//Get Flags
int Nav_Get_Flags(char *Nav)
{
+7
View File
@@ -36,6 +36,7 @@ public:
int waypoint_num; //only used when flags & NP_WAYPOINT
vec3d *GetPosition();
char* GetInternalName();
void clear()
{
@@ -128,6 +129,9 @@ void SelectNav(char *Nav);
// Deselects any navpoint selected.
void DeselectNav();
// Set A Nav point to "ZERO"
void ZeroNav(int i);
// Removes a Nav
bool DelNavPoint(char *Nav);
bool DelNavPoint(int nav);
@@ -136,6 +140,9 @@ bool DelNavPoint(int nav);
bool AddNav_Ship(char *Nav, char *TargetName, int flags);
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags);
//Change Flags
bool Nav_Alt_Flags(char *Nav, int flags);
// Sexp Accessors
bool Nav_Set_Flag(char *Nav, int flag);
bool Nav_UnSet_Flag(char *Nav, int flag);
+11 -37
View File
@@ -23,16 +23,6 @@
#include "bmpman/bmpman.h"
#include <array>
/**
* @brief Container class for graphics API specific bitmap data
*/
class gr_bitmap_info {
public:
virtual ~gr_bitmap_info() = 0;
};
union bm_extra_info {
struct {
// Stuff needed for animations
@@ -67,7 +57,9 @@ struct bitmap_entry {
char filename[MAX_FILENAME_LEN]; //!< filename for this bitmap
uint signature; //!< a unique signature identifying the data
uint palette_checksum; //!< checksum used to be sure bitmap is in current palette
int handle; //!< Handle = id*MAX_BITMAPS + bitmapnum
int last_used; //!< When this bitmap was last used
BM_TYPE type; //!< PCX, USER, ANI, etc
BM_TYPE comp_type; //!< What sort of compressed type, BM_TYPE_NONE if not compressed
@@ -98,35 +90,17 @@ struct bitmap_entry {
#endif
};
struct bitmap_slot {
bitmap_entry entry;
gr_bitmap_info* gr_info = nullptr;
};
extern bitmap_entry* bm_bitmaps;
// image specific lock functions
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_dds( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_png( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_apng( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_jpg( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
const size_t BM_BLOCK_SIZE = 4096;
extern SCP_vector<std::array<bitmap_slot, BM_BLOCK_SIZE>> bm_blocks;
bitmap_slot* bm_get_slot(int handle, bool separate_ani_frames = true);
inline bitmap_entry* bm_get_entry(int handle, bool separate_ani_frames = true) {
return &bm_get_slot(handle, separate_ani_frames)->entry;
}
template<typename T>
T* bm_get_gr_info(int handle, bool separate_ani_frames = true) {
return static_cast<T*>(bm_get_slot(handle, separate_ani_frames)->gr_info);
}
#endif // __BM_INTERNAL_H__
+838 -777
View File
File diff suppressed because it is too large. Load diff
+102 -33
View File
@@ -32,6 +32,23 @@
* @{
*/
/**
* @brief How many bitmaps the game can handle by default
*
* @attention MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's proper use even the
* largest missions should stay under this number. With the largest retail missions and wasteful content we should
* still have about 20% of the slots free. If it still goes over then it's something the artists need to fix.
* For instance the Terran Mara fighter, with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.
* 111 of those is just for the glowmaps. This number can be greatly reduced if the number of ani frames for another
* LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little more than a waste of resources.
* Future reports of texture corruption should be initially approached with content as the cause and not code.
* If anything we could/should reduce MAX_BITMAPS in the future. Where it's at now should accomidate even the
* largest mods. -- Taylor
*/
#define DEFAULT_MAX_BITMAPS 4750
extern int MAX_BITMAPS;
// Flag positions for bitmap.flags
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
@@ -98,10 +115,6 @@ struct bitmap
*/
};
// Forward definition for the graphics API
struct bitmap_entry;
struct bitmap_slot;
extern size_t bm_texture_ram; //!< how many bytes of textures are used.
extern int Bm_paging; //!< Bool type that indicates if BMPMAN is currently paging.
@@ -113,7 +126,12 @@ extern const BM_TYPE bm_ani_type_list[]; //!< List of valid bitmap animation t
extern const char *bm_ani_ext_list[]; //!< List of extensions for those types
extern const int BM_ANI_NUM_TYPES; //!< Calculated number of bitmap animation types
extern int GLOWMAP; //!< References a map that is a fully lit version of its index -Bobboau
extern int SPECMAP; //!< References a map that is for specular mapping -Bobboau
extern int ENVMAP; //!< References a map that is for environment mapping -Bobboau
extern int NORMMAP; //!< Normal mapping
extern int HEIGHTMAP; //!< Height map for normal mapping
extern int MISCMAP; //!< Utility map, to be utilized for various things shader authors can come up with
/**
* @brief Initilizes the bitmap manager
@@ -125,6 +143,22 @@ void bm_init();
*/
void bm_close();
/**
* Gets the cache slot of the bitmap indexed by handle.
*
* @details if the bitmap is an ani, gets the first frame
*
* @returns The cache slot index of the bitmap if handle is valid
*
* @note If the handle is invalid, an Assert() fails
*/
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames);
/**
* @brief Gets the next available bitmap slot.
*/
int bm_get_next_handle();
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0)
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1)
#define BMP_FLAG_CUBEMAP (1<<2)
@@ -162,6 +196,9 @@ public:
bool valid();
float get_channel_red(float u, float v);
float get_channel_green(float u, float v);
float get_channel_blue(float u, float v);
float get_channel_alpha(float u, float v);
};
@@ -303,6 +340,13 @@ int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, i
*/
bitmap* bm_lock(int handle, int bpp, ubyte flags, bool nodebug = false);
/**
* @brief Returns a unique signiature for the bitmap indexed by handle
*
* @details A signature will change when the bitmap's data changes
*/
uint bm_get_signature(int handle);
/**
* @brief Returns the image type of the given bitmap handle
*/
@@ -368,6 +412,13 @@ void bm_get_filename(int bitmapnum, char *filename);
*/
const char *bm_get_filename(int handle);
/**
* @brief Loads all data for all bitmaps that have been requested to be loaded
*
* @note This function is not defined.
*/
void bm_gfx_load_all();
/**
* @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
*
@@ -386,6 +437,15 @@ void bm_unload_all();
*/
void bm_get_palette(int handle, ubyte *pal, char *name);
/**
* @brief Hack to get a pixel from a bitmap
*
* @details only works good in 8bpp mode
*
* @note This function is not defined.
*/
void bm_gfx_get_pixel(int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b);
/**
* @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
*
@@ -444,6 +504,15 @@ void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
*/
void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
/**
* @brief Unloads the bitmap indexed by handle that was previously paged-in
*
* @returns 0 If the bitmap had already been released, or
* @returns 0 If the handle is invalid, or
* @returns 1 If successful
*/
bool bm_page_out(int handle);
/**
* @brief Sets BMPMAN's memory mode
*
@@ -492,6 +561,16 @@ void BM_SELECT_ALPHA_TEX_FORMAT();
*/
extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Functional pointer that references any of the bm_set_components_32 functions.
*
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
*
* @see bm_set_components
*/
extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Sets the 16bpp screen pixel to the specified RGBA value
*
@@ -499,6 +578,13 @@ extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyt
*/
void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Sets the 32bpp screen pixel to the specified RGBA value
*
* @see bm_set_components
*/
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Sets the 16bpp texture pixel to the specified RGBA value
*
@@ -520,7 +606,15 @@ void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, u
*/
void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
extern int UNLITMAP; //this holds a reference to a map that is optional used instead of the base map for unlit rendering
extern int GLOWMAP; //this holds a reference to a map that is a fully lit version of its index -Bobboau
extern int SPECMAP; //this holds a reference to a map that is for specular mapping -Bobboau
extern int SPECGLOSSMAP; //this holds a reference to a map that is for specular mapping -Bobboau
extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
extern int NORMMAP; // normal mapping
extern int HEIGHTMAP; // height map for normal mapping
extern int AMBIENTMAP; // ambient occluion map. red channel affects ambient lighting, green channel affects diffuse and specular
extern int MISCMAP; // Utility map, to be utilized for various things shader authors can come up with
/**
* @brief Returns the compression type of the bitmap indexed by handle
@@ -532,6 +626,10 @@ int bm_is_compressed(int handle);
*/
int bm_get_tcache_type(int handle);
/**
* @brief Gets the size, in bytes, taken up by the bitmap indexed by handle
*/
size_t bm_get_size(int handle);
/**
* @brief Gets the number of mipmaps of the indexed texture
@@ -643,33 +741,4 @@ int bm_get_array_index(const int handle);
*/
int bmpman_count_bitmaps();
/**
* @brief Counts how many slots are available to the bmpman system
*
* Since the number of slots is dynamic now, this should be used for determining the total amount of available slots at
* the moment.
*
* @warning This is entirely for debugging and logging purposes. It should not be used in actual engine code.
*
* @return The number of available slots
*/
int bmpman_count_available_slots();
/**
* @brief Checks if the given filename is a valid effect or texture file name
*
* @note At least one of @c single_frame or @c animation must be true since the result would make no sense otherwise. It
* is also valid to set both parmeters to @c true.
*
* @todo This currently just tries to load the file but could be improved by not actually loading the file in the future.
*
* @param file The file name to check
* @param single_frame If set to @c true then single frames are valid files
* @param animation If set to @c true then animations are valid files
* @return @c true if the file name is valid, @c false otherwise
*/
bool bm_validate_filename(const SCP_string& file, bool single_frame, bool animation);
SDL_Surface* bm_to_sdl_surface(int handle);
#endif
+18 -24
View File
@@ -7,10 +7,9 @@
#include "math/vecmat.h"
#include "mod_table/mod_table.h"
#include "model/model.h" //polymodel, model_get
#include "options/Option.h"
#include "parse/parselo.h"
#include "playerman/player.h" //player_get_padlock_orient
#include "ship/ship.h" //compute_slew_matrix
#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
@@ -25,23 +24,6 @@ SCP_vector<camera*> Cameras;
camid Current_camera;
camid Main_camera;
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
SCP_string out;
sprintf(out, u8"%.1f\u00B0", degrees);
return out;
}
auto FovOption = options::OptionBuilder<float>("Graphics.FOV", "Field Of View", "The vertical field of view.")
.category("Graphics")
.range(0.436332f, 1.5708f)
.bind_to(&VIEWER_ZOOM_DEFAULT)
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
//*************************CLASS: camera*************************
//This is where the camera class beings! :D
camera::camera(const char *in_name, int in_signature)
@@ -163,7 +145,7 @@ void camera::set_object_target(object *objp, int n_object_target_submodel)
* Custom function receives the already-modified current position value.
* It should be replaced or added to as the custom function modifier sees fit.
*/
void camera::set_custom_position_function(void (*n_func_custom_position)(camera* /*cam*/, vec3d* /*camera_pos*/))
void camera::set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *camera_pos))
{
func_custom_position = n_func_custom_position;
}
@@ -172,7 +154,7 @@ void camera::set_custom_position_function(void (*n_func_custom_position)(camera*
* Custom function receives the already-modified current orientation value.
* It should be replaced or added to as the custom function modifier sees fit.
*/
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera* /*cam*/, matrix* /*camera_ori*/))
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *camera_ori))
{
func_custom_orientation = n_func_custom_orientation;
}
@@ -203,6 +185,13 @@ void camera::set_position(vec3d *in_position, float in_translation_time, float i
pos_z.setAVD(in_position->xyz.z, in_translation_time, in_translation_acceleration_time, in_translation_deceleration_time, in_end_velocity);
}
void camera::set_translation_velocity(vec3d *in_velocity, float in_acceleration_time)
{
pos_x.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.x);
pos_y.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.y);
pos_z.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.z);
}
void camera::set_rotation(matrix *in_orientation, float in_rotation_time, float in_rotation_acceleration_time, float in_rotation_deceleration_time)
{
if(in_orientation != NULL && in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f && in_rotation_deceleration_time == 0.0f)
@@ -256,7 +245,12 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
set_rotation(&temp_matrix, in_rotation_time, in_rotation_acceleration_time, in_rotation_deceleration_time);
}
void camera::do_frame(float /*in_frametime*/)
void camera::set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time)
{
Error(LOCATION, "This function is disabled until further notice.");
}
void camera::do_frame(float in_frametime)
{
}
@@ -808,7 +802,7 @@ void subtitle::clone(const subtitle &sub)
post_shaded = sub.post_shaded;
}
subtitle& subtitle::operator=(const subtitle &sub)
const subtitle &subtitle::operator=(const subtitle &sub)
{
if (this != &sub) {
if (image_id != -1) {
@@ -968,7 +962,7 @@ size_t cam_get_num()
/**
* Looks up camera by name, returns -1 on failure
*/
camid cam_lookup(const char* name)
camid cam_lookup(char *name)
{
size_t i, size=Cameras.size();
for(i = 0; i < size; i++)
+6 -3
View File
@@ -17,6 +17,7 @@
class camera
{
friend class avd_camera;
protected:
char name[NAME_LENGTH];
int sig;
@@ -59,13 +60,15 @@ public:
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
void set_translation_velocity(vec3d *in_velocity, float in_acceleration_time = 0.0f);
void set_rotation(matrix *in_orientation = NULL, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation(angles *in_angles, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation_facing(vec3d *in_target, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time = 0.0f);
//Get
const char* get_name() { return name; }
char *get_name() {return name;}
int get_signature() {return sig;}
object *get_object_host();
int get_object_host_submodel();
@@ -140,7 +143,7 @@ public:
~subtitle();
subtitle(const subtitle &sub) { clone(sub); }
subtitle& operator=(const subtitle &sub);
const subtitle &operator=(const subtitle &sub);
void do_frame(float frametime);
bool is_post_shaded( ) { return post_shaded; }
@@ -160,7 +163,7 @@ camid cam_create(const char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_obje
void cam_delete(camid cid);
bool cam_set_camera(camid cid);
void cam_reset_camera();
camid cam_lookup(const char* name);
camid cam_lookup(char *name);
camid cam_get_camera(uint index);
camid cam_get_current();
size_t cam_get_num();
+319 -246
View File
File diff suppressed because it is too large. Load diff
+57 -139
View File
@@ -13,11 +13,10 @@
#define __CFILE_H__
#include <time.h>
#include "globalincs/pstypes.h"
#include <ctime>
#include <stdexcept>
#include <memory>
#define CF_EOF (-1)
@@ -26,8 +25,10 @@
#define CF_SEEK_CUR (1)
#define CF_SEEK_END (2)
// Opaque file handle
struct CFILE;
typedef struct CFILE {
int id; // Index into cfile.cpp specific structure
int version; // version of this file
} CFILE;
// extra info that can be returned when getting a file listing
typedef struct {
@@ -78,11 +79,9 @@ typedef struct {
#define CF_TYPE_SCRIPTS 35
#define CF_TYPE_FICTION 36
#define CF_TYPE_FREDDOCS 37
#define CF_TYPE_INTERFACE_MARKUP 38
#define CF_TYPE_INTERFACE_CSS 39
#define CF_MAX_PATH_TYPES \
40 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
#define CF_MAX_PATH_TYPES 38 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
// TRUE if type is specified and valid
#define CF_TYPE_SPECIFIED(path_type) (((path_type)>CF_TYPE_INVALID) && ((path_type)<CF_MAX_PATH_TYPES))
@@ -96,63 +95,8 @@ typedef struct {
#define CF_SORT_TIME 2
#define CF_SORT_REVERSE 3
/**
* @brief Contains a collection of flags for specifying from where a CFILE should be opened
*
* There are two types of flags. CF_LOCATION_GAME_ROOT and CF_LOCATION_USER_ROOT specify in which basic root directory
* CFile should search for files.
*
* The remaining flags control what type of location may be used for the operation. It's possible to restrict the
* location to the primary mod, the remaining mods or the top-level root directory.
*/
enum CFileLocationFlags {
CF_LOCATION_ROOT_GAME = 1 << 0, //!< The game root location. This is the location of the game data (e.g. FS2 retail)
/**
* @brief The user directories.
*
* If the engine is in portable mode then using this flag exclusively will result in a failure to open files!
*/
CF_LOCATION_ROOT_USER = 1 << 1,
/**
* @brief The memory root
*
* This contains all the built-in files available to the engine.
*/
CF_LOCATION_ROOT_MEMORY = 1 << 2,
/**
* @brief Mask for extracting root type from a location bit field
*/
CF_LOCATION_ROOT_MASK = 0xFFFF,
CF_LOCATION_TYPE_ROOT = 1 << 16, //!< The basic, top-level root location
/**
* @brief The primary mod location.
*
* This is the mod that appears first on the command line. If there are no mods then the root location is considered
* to be the primary mod
*/
CF_LOCATION_TYPE_PRIMARY_MOD = 1 << 17,
/**
* @brief The remaining mods.
*
* If there are no mods on the command line then this might not include any valid location.
*/
CF_LOCATION_TYPE_SECONDARY_MODS = 1 << 18,
/**
* @brief Bitmask for extracting the type from a location bit field
*/
CF_LOCATION_TYPE_MASK = 0xFFFF0000,
/**
* @brief A combination of all flags
*
* This should be used when the default behavior without any location filtering is desired.
*/
CF_LOCATION_ALL = CF_LOCATION_ROOT_MASK | CF_LOCATION_TYPE_MASK
};
#define cfread_fix(file) (fix)cfread_int(file)
#define cfwrite_fix(i,file) cfwrite_int(i,file)
// callback function used for get_file_list() to filter files to be added to list. Return 1
// to add file to list, or 0 to not add it.
@@ -167,39 +111,52 @@ extern const char *Get_file_list_child;
#define CFILE_ROOT_DIRECTORY_LEN 256
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
#ifdef SCP_UNIX
extern char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN];
#endif
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
void cfile_close();
// Call this if pack files got added or removed or the
// cdrom changed. This will refresh the list of filenames
// stored in packfiles and on the cdrom.
void cfile_refresh();
// add an extension to a filename if it doesn't already have it
char *cf_add_ext(const char *filename, const char *ext);
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
int cf_get_dir_type(CFILE *cfile);
// Opens the file. If no path is given, use the extension to look into the
// default path. If mode is NULL, delete the file.
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode, int type = CFILE_NORMAL,
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
// default path. If mode is NULL, delete the file.
CFILE *_cfopen(const char* source_file, int line, const char *filename, const char *mode,
int type = CFILE_NORMAL, int dir_type = CF_TYPE_ANY, bool localize = false);
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
// NOTE: only supports reading files!!
CFILE *_cfopen_special(const char* source_file, int line, const char *file_path, const char *mode,
const size_t size, const size_t offset, const void* data, int dir_type = CF_TYPE_ANY);
const size_t size, const size_t offset, int dir_type = CF_TYPE_ANY);
#define cfopen_special(...) _cfopen_special(LOCATION, __VA_ARGS__) // Pass source location to the function
// Flush the open file buffer
int cflush(CFILE *cfile);
// version number of opened file. Will be 0 unless you put something else here after you
// open a file. Once set, you can use minimum version numbers with the read functions.
void cf_set_version( CFILE * cfile, int version );
// will throw an error if cfread*() functions read past this mark
// converted to raw offsets when used, but gets passed actual length from current position
// setting 'len' to zero will disable the check
void cf_set_max_read_len(CFILE *cfile, size_t len);
// Deletes a file. Returns 0 on error, 1 if successful
int cf_delete(const char *filename, int dir_type, uint32_t location_flags = CF_LOCATION_ALL);
int cf_delete(const char *filename, int dir_type);
// Same as _access function to read a file's access bits
int cf_access(const char *filename, int dir_type, int mode);
@@ -233,6 +190,10 @@ int cfread(void *buf, int elsize, int nelem, CFILE *fp);
// cfwrite() writes to the file
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile);
// Reads/writes RLE compressed data.
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile);
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile);
// Moves the file pointer
int cfseek(CFILE *fp, int offset, int where);
@@ -255,7 +216,7 @@ char *cfgets(char *buf, int n, CFILE *cfile);
int cfeof(CFILE *cfile);
// Return the data pointer associated with the CFILE structure (for memory mapped files)
const void *cf_returndata(CFILE *cfile);
void *cf_returndata(CFILE *cfile);
// get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
int cf_chksum_short(const char *filename, ushort *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
@@ -284,6 +245,7 @@ uint cf_add_chksum_long(uint seed, ubyte *buffer, size_t size);
// convenient for misc checksumming purposes ------------------------------------------
//================= HIGH LEVEL FUNCTIONS ==================
int cfexist(const char *filename); // Returns true if file exists on disk (1) or in hog (2).
// rename a file, utilizing the extension to determine where file is.
#define CF_RENAME_SUCCESS 0 // successfully renamed the file
@@ -291,10 +253,6 @@ uint cf_add_chksum_long(uint seed, ubyte *buffer, size_t size);
#define CF_RENAME_FAIL_EXIST 2 // old name does not exist
int cf_rename(const char *old_name, const char *name, int type = CF_TYPE_ANY );
// Creates the directory path if it doesn't exist. Even creates all its
// parent paths.
void cf_create_directory(int dir_type, uint32_t location_flags = CF_LOCATION_ALL);
// changes the attributes of a file
void cf_attrib(const char *name, int set, int clear, int type);
@@ -305,15 +263,17 @@ int cfile_flush_dir(int type);
// functions for reading from cfile
// These are all high level, built up from
// cfread.
int cfgetc(CFILE *fp);
char *cfgets(char *buf, size_t n, CFILE *fp);
char cfread_char(CFILE* file, char deflt = 0);
ubyte cfread_ubyte(CFILE* file, ubyte deflt = 0);
short cfread_short(CFILE* file, short deflt = 0);
ushort cfread_ushort(CFILE* file, ushort deflt = 0);
int cfread_int(CFILE* file, int deflt = 0);
uint cfread_uint(CFILE* file, uint deflt = 0);
float cfread_float(CFILE* file, float deflt = 0.0f);
void cfread_vector(vec3d* vec, CFILE* file, vec3d* deflt = nullptr);
char cfread_char(CFILE *file, int ver = 0, char deflt = 0);
ubyte cfread_ubyte(CFILE *file, int ver = 0, ubyte deflt = 0);
short cfread_short(CFILE *file, int ver = 0, short deflt = 0);
ushort cfread_ushort(CFILE *file, int ver = 0, ushort deflt = 0);
int cfread_int(CFILE *file, int ver = 0, int deflt = 0);
uint cfread_uint(CFILE *file, int ver = 0, uint deflt = 0);
float cfread_float(CFILE *file, int ver = 0, float deflt = 0.0f);
void cfread_vector(vec3d *vec, CFILE *file, int ver = 0, vec3d *deflt = NULL);
void cfread_angles(angles *ang, CFILE *file, int ver = 0, angles *deflt = NULL);
// Reads variable length, null-termined string. Will only read up
// to n characters.
@@ -329,13 +289,6 @@ void cfread_string(char *buf,int n, CFILE *file);
*/
void cfread_string_len(char *buf,int n, CFILE *file);
/**
* @brief Read a string from the file where the length is stored in the file
* @param file The file to read the string from
* @return The string that was read
*/
SCP_string cfread_string_len(CFILE *file);
// functions for writing cfiles
int cfwrite_char(char c, CFILE *file);
int cfwrite_float(float f, CFILE *file);
@@ -344,6 +297,8 @@ int cfwrite_uint(uint i, CFILE *file);
int cfwrite_short(short s, CFILE *file);
int cfwrite_ushort(ushort s, CFILE *file);
int cfwrite_ubyte(ubyte u, CFILE *file);
int cfwrite_vector(vec3d *vec, CFILE *file);
int cfwrite_angles(angles *ang, CFILE *file);
// writes variable length, null-termined string.
int cfwrite_string(const char *buf, CFILE *file);
@@ -356,26 +311,12 @@ int cfwrite_string(const char *buf, CFILE *file);
*/
int cfwrite_string_len(const char *buf, CFILE *file);
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort = CF_SORT_NONE,
SCP_vector<file_list_info>* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list(int max, char** list, int type, const char* filter, int sort = CF_SORT_NONE,
file_list_info* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int type, const char* filter,
int sort = CF_SORT_NONE, file_list_info* info = nullptr,
uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort = CF_SORT_NONE, SCP_vector<file_list_info> *info = NULL );
int cf_get_file_list( int max, char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info = NULL );
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info = NULL );
struct CFileLocation {
bool found = false;
SCP_string full_name;
size_t size = 0;
size_t offset = 0;
const void* data_ptr = nullptr;
explicit CFileLocation(bool found_in = false) : found(found_in) {}
};
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files.
// Input: filespace - Filename & extension
@@ -385,17 +326,7 @@ struct CFileLocation {
// size - File size
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns 0.
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize = false,
uint32_t location_flags = CF_LOCATION_ALL);
struct CFileLocationExt : public CFileLocation {
int extension_index = -1;
explicit CFileLocationExt(int extension_index_in = -1)
: CFileLocation(extension_index_in >= 0), extension_index(extension_index_in)
{
}
};
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false);
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
@@ -409,8 +340,7 @@ struct CFileLocationExt : public CFileLocation {
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns -1, else returns offset into ext_list.
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
CFileLocationExt cf_find_file_location_ext(const char* filename, const int ext_num, const char** ext_list, int pathtype,
bool localize = false);
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false);
// Functions to change directories
int cfile_chdir(const char *dir);
@@ -425,8 +355,6 @@ int cfile_push_chdir(int type);
// restore directory on top of the stack
int cfile_pop_dir();
int cfile_get_path_type(const SCP_string& dir);
namespace cfile
{
// exceptions and other errors
@@ -437,13 +365,16 @@ namespace cfile
{
}
explicit cfile_error(const std::string &excuse) : m_excuse(excuse)
cfile_error(const std::string &excuse) : m_excuse(excuse)
{
}
~cfile_error() SCP_NOEXCEPT override {}
~cfile_error() throw()
{
}
const char *what() const SCP_NOEXCEPT override {
virtual const char *what() const throw()
{
return m_excuse.c_str();
}
@@ -454,7 +385,7 @@ namespace cfile
class max_read_length : public cfile_error
{
public:
explicit max_read_length(const std::string &excuse) : cfile_error(excuse)
max_read_length(const std::string &excuse) : cfile_error(excuse)
{
}
@@ -465,17 +396,4 @@ namespace cfile
}
// This allows to use std::unique_ptr with CFILE
namespace std {
template <>
struct default_delete<CFILE> {
void operator()(CFILE* ptr)
{
if (cf_is_valid(ptr)) {
cfclose(ptr);
}
}
};
} // namespace std
#endif /* __CFILE_H__ */
+87 -86
View File
@@ -11,9 +11,9 @@
#define _CFILE_INTERNAL
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef _WIN32
#include <io.h>
@@ -36,20 +36,24 @@
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos )
{
Assert(cfile != nullptr);
Assert(cfile != NULL);
cfile->lib_offset = lib_offset;
cfile->raw_position = pos;
cfile->size = size;
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
if ( cfile->fp ) {
if ( cfile->lib_offset ) {
fseek( cfile->fp, (long)cfile->lib_offset, SEEK_SET );
cb->lib_offset = lib_offset;
cb->raw_position = pos;
cb->size = size;
if ( cb->fp ) {
if ( cb->lib_offset ) {
fseek( cb->fp, (long)cb->lib_offset, SEEK_SET );
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
Assert(raw_position == cfile->raw_position);
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
#endif
}
}
@@ -66,16 +70,25 @@ int cfeof(CFILE *cfile)
{
Assert(cfile != NULL);
int result = 0;
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
int result;
result = 0;
// cfeof() not supported for memory-mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
Assert(raw_position == cfile->raw_position);
}
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
#endif
if (cfile->raw_position >= cfile->size ) {
if (cb->raw_position >= cb->size ) {
result = 1;
} else {
result = 0;
@@ -92,18 +105,24 @@ int cfeof(CFILE *cfile)
int cftell( CFILE * cfile )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// Doesn't work for memory mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
Assert(raw_position == cfile->raw_position);
}
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
#endif
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
Assertion(cfile->raw_position <= static_cast<size_t>(std::numeric_limits<int>::max()),
Assertion(cb->raw_position <= static_cast<size_t>(std::numeric_limits<int>::max()),
"Integer overflow in cftell, a file is probably too large (but I don't know which one).");
return (int) cfile->raw_position;
return (int) cb->raw_position;
}
@@ -116,23 +135,28 @@ int cfseek( CFILE *cfile, int offset, int where )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// TODO: seek to offset in memory mapped file
Assert( !cfile->mem_mapped );
Assert( !cb->data );
Assert( cb->fp != NULL );
size_t goal_position;
switch( where ) {
case CF_SEEK_SET:
goal_position = offset+cfile->lib_offset;
goal_position = offset+cb->lib_offset;
break;
case CF_SEEK_CUR:
{
goal_position = cfile->raw_position+offset+cfile->lib_offset;
goal_position = cb->raw_position+offset+cb->lib_offset;
}
break;
case CF_SEEK_END:
goal_position = cfile->size+offset+cfile->lib_offset;
goal_position = cb->size+offset+cb->lib_offset;
break;
default:
Int3();
@@ -140,24 +164,16 @@ int cfseek( CFILE *cfile, int offset, int where )
}
// Make sure we don't seek beyond the end of the file
CAP(goal_position, cfile->lib_offset, cfile->lib_offset + cfile->size);
CAP(goal_position, cb->lib_offset, cb->lib_offset + cb->size);
int result = 0;
if (cfile->fp) {
// If we have a file pointer we can also seek in that file
result = fseek(cfile->fp, (long)goal_position, SEEK_SET );
Assertion(goal_position >= cfile->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cfile->lib_offset);
}
// If we only have a data pointer this will do all the work
cfile->raw_position = goal_position - cfile->lib_offset;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
int result = fseek(cb->fp, (long)goal_position, SEEK_SET );
Assertion(goal_position >= cb->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cb->lib_offset);
cb->raw_position = goal_position - cb->lib_offset;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset == cfile->raw_position);
}
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
#endif
return result;
@@ -179,17 +195,26 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
if(buf == NULL || size <= 0)
return 0;
if ( (cfile->raw_position+size) > cfile->size ) {
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
size = cfile->size - cfile->raw_position;
Cfile_block *cb = &Cfile_block_list[cfile->id];
// cfread() not supported for memory-mapped files
if(cb->data != NULL)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return 0;
}
if ( (cb->raw_position+size) > cb->size ) {
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
size = cb->size - cb->raw_position;
if ( size < 1 ) {
return 0;
}
//mprintf(( "CFILE: EOF encountered in file\n" ));
}
if (cfile->max_read_len) {
if ( cfile->raw_position+size > cfile->max_read_len ) {
if (cb->max_read_len) {
if ( cb->raw_position+size > cb->max_read_len ) {
std::ostringstream s_buf;
s_buf << "Attempted to read " << size << "-byte(s) beyond length limit";
@@ -197,24 +222,15 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
}
}
size_t bytes_read;
if (cfile->data != nullptr) {
// This is a file from memory
bytes_read = size;
memcpy(buf, reinterpret_cast<const char*>(cfile->data) + cfile->raw_position, size);
} else {
bytes_read = fread( buf, 1, size, cfile->fp );
}
size_t bytes_read = fread( buf, 1, size, cb->fp );
if ( bytes_read > 0 ) {
cfile->raw_position += bytes_read;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
cb->raw_position += bytes_read;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset==cfile->raw_position);
}
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
#endif
return (int)(bytes_read / elsize);
@@ -229,38 +245,23 @@ int cfread_lua_number(double *buf, CFILE *cfile)
if(buf == NULL)
return 0;
Cfile_block *cb = &Cfile_block_list[cfile->id];
// cfread() not supported for memory-mapped files
if(cfile->data != nullptr)
if(cb->data != NULL)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return 0;
}
size_t advance = 0;
int items_read;
if (cfile->fp) {
long orig_pos = ftell(cfile->fp);
items_read = fscanf(cfile->fp, LUA_NUMBER_SCAN, buf);
advance = (size_t) (ftell(cfile->fp)-orig_pos);
} else {
int read;
// %n returns the number of bytes currently read so we append that to the scan format at the end so it will return
// how many bytes we have consumed
items_read = sscanf(reinterpret_cast<const char*>(cfile->data), LUA_NUMBER_SCAN "%n", buf, &read);
if (items_read == 2) {
// We need to correct the items read counter since we read one additional item
items_read = 1;
}
advance = (size_t) read;
}
cfile->raw_position += advance;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
long orig_pos = ftell(cb->fp);
int items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
cb->raw_position += ftell(cb->fp)-orig_pos;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset==cfile->raw_position);
}
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
#endif
return items_read;
+14 -14
View File
@@ -22,30 +22,30 @@
#define CFILE_BLOCK_UNUSED 0
#define CFILE_BLOCK_USED 1
struct CFILE {
int type = CFILE_BLOCK_UNUSED; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
int dir_type; // directory location
FILE* fp; // File pointer if opening an individual file
const void* data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
bool mem_mapped; // Flag for memory mapped files (if data is not null and this is false it means that it's an embedded file)
typedef struct Cfile_block {
int type; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
int dir_type; // directory location
FILE *fp; // File pointer if opening an individual file
void *data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
#ifdef _WIN32
HANDLE hInFile; // Handle from CreateFile()
HANDLE hMapFile; // Handle from CreateFileMapping()
#else
size_t data_length; // length of data for mmap
// int fd; // file descriptor
size_t data_length; // length of data for mmap
#endif
size_t lib_offset;
size_t raw_position;
size_t size; // for packed files
size_t max_read_len; // max read offset, for special error handling
size_t lib_offset;
size_t raw_position;
size_t size; // for packed files
size_t max_read_len; // max read offset, for special error handling
const char* source_file;
int line_num;
};
} Cfile_block;
#define MAX_CFILE_BLOCKS 64
extern std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
extern Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS];
// Called once to setup the low-level reading code.
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos );
+353 -4
View File
@@ -9,9 +9,9 @@
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <string>
#include <algorithm>
@@ -200,4 +200,353 @@ void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
}
nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
}
}
#if (0) // these aren't used anywhere now
// cf_compress - Do Run Length Compression on a block of data. Targa format.
//
// Usage:
// out Buffer to write it out to
// in Buffer to compress
// bytecount Number of bytes input
int cf_compress(char *out, char *in, int bytecount )
{
int pixcount; // number of pixels in the current packet
char *inputpixel=NULL; // current input pixel position
char *matchpixel=NULL; // pixel value to match for a run
char *flagbyte=NULL; // location of last flag byte to set
int rlcount; // current count in r.l. string
int rlthresh; // minimum valid run length
char *copyloc; // location to begin copying at
// set the threshold -- the minimum valid run length
rlthresh = 2; // Require a 2 pixel span before rle'ing
// set the first pixel up
flagbyte = out; // place to put next flag if run
inputpixel = in;
pixcount = 1;
rlcount = 0;
copyloc = (char *)0;
// loop till data processing complete
do {
// if we have accumulated a 128-byte packet, process it
if ( pixcount == 129 ) {
*flagbyte = 127;
// set the run flag if this is a run
if ( rlcount >= rlthresh ) {
*flagbyte |= 0x80;
pixcount = 2;
}
// copy the data into place
++flagbyte;
memmove( flagbyte, copyloc, pixcount-1 );
flagbyte += pixcount-1;
pixcount = 1;
// set up for next packet
continue;
}
// if zeroth byte, handle as special case
if ( pixcount == 1 ) {
rlcount = 0;
copyloc = inputpixel; /* point to 1st guy in packet */
matchpixel = inputpixel; /* set pointer to pix to match */
pixcount = 2;
inputpixel += 1;
continue;
}
// assembling a packet -- look at next pixel
// current pixel == match pixel?
if ( *inputpixel == *matchpixel ) {
// establishing a run of enough length to
// save space by doing it
// -- write the non-run length packet
// -- start run-length packet
if ( ++rlcount == rlthresh ) {
// close a non-run packet
if ( pixcount > (rlcount+1) ) {
// write out length and do not set run flag
*flagbyte++ = (char)(pixcount - 2 - rlthresh);
memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
flagbyte += (pixcount-1-rlcount);
copyloc = inputpixel;
pixcount = rlcount + 1;
}
}
} else {
// no match -- either break a run or continue without one
// if a run exists break it:
// write the bytes in the string (1+1)
// start the next string
if ( rlcount >= rlthresh ) {
*flagbyte++ = (char)(0x80 | rlcount);
memmove(flagbyte, copyloc, 1 );
flagbyte += 1;
pixcount = 1;
continue;
} else {
// not a match and currently not a run
// - save the current pixel
// - reset the run-length flag
rlcount = 0;
matchpixel = inputpixel;
}
}
pixcount++;
inputpixel += 1;
} while ( inputpixel < (in + bytecount));
// quit this buffer without loosing any data
if ( --pixcount >= 1 ) {
*flagbyte = (char)(pixcount - 1);
if ( rlcount >= rlthresh ) {
*flagbyte |= 0x80;
pixcount = 1;
}
// copy the data into place
++flagbyte;
memmove(flagbyte, copyloc, pixcount );
flagbyte += pixcount;
}
return(flagbyte-out);
}
// cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
//
// Usage:
// out Buffer to write it out to
// in Buffer to compress
// bytecount Number of bytes input
int cf_decompress(char *out, char *in )
{
int count;
char *param_out = out;
while(1) {
count = int(*in++);
int run_span = count & 0x80;
count &= (~0x80);
if ( count > 0 ) {
if ( run_span ) {
// RLE'd data
ubyte c = *in++;
memset( out, c, count );
out += count;
} else {
memmove( out, in, count );
in += count;
out += count;
}
}
}
return out - param_out;
}
#endif // 0
// cfread() reads from a file and decompresses it
//
// returns: returns the number of full elements read
//
//
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
{
char *out = (char *)buf;
while(1) {
ubyte count;
if ( cfread( &count, 1, 1, cfile ) != 1 ) {
break;
}
int run_span = count & 0x80;
count &= (~0x80);
count++;
if ( count > 0 ) {
if ( run_span ) {
// RLE'd data
ubyte c;
if ( cfread( &c, 1, 1, cfile ) != 1 ) {
break;
}
memset( out, c, count );
} else {
if ( cfread( out, 1, count, cfile ) != count ) {
break;
}
}
out += count;
if ( out >= (char *)buf + (elsize*nelem)) {
break;
}
} else {
break;
}
}
return (int)((out - (char *)buf)/elsize);
}
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
{
char *in = (char *)param_buf;
int bytecount = (param_elsize * param_nelem );
int pixcount; // number of pixels in the current packet
char *inputpixel=NULL; // current input pixel position
char *matchpixel=NULL; // pixel value to match for a run
int rlcount; // current count in r.l. string
int rlthresh; // minimum valid run length
char *copyloc; // location to begin copying at
// set the threshold -- the minimum valid run length
rlthresh = 2; // Require a 2 pixel span before rle'ing
// set the first pixel up
inputpixel = in;
pixcount = 1;
rlcount = 0;
copyloc = (char *)0;
// loop till data processing complete
do {
// if we have accumulated a 128-byte packet, process it
if ( pixcount == 129 ) {
ubyte code = 127;
// set the run flag if this is a run
if ( rlcount >= rlthresh ) {
code |= 0x80;
pixcount = 2;
}
cfwrite( &code, 1, 1, cfile );
// copy the data into place
cfwrite( copyloc, 1, pixcount-1, cfile );
pixcount = 1;
// set up for next packet
continue;
}
// if zeroth byte, handle as special case
if ( pixcount == 1 ) {
rlcount = 0;
copyloc = inputpixel; /* point to 1st guy in packet */
matchpixel = inputpixel; /* set pointer to pix to match */
pixcount = 2;
inputpixel += 1;
continue;
}
// assembling a packet -- look at next pixel
// current pixel == match pixel?
if ( *inputpixel == *matchpixel ) {
// establishing a run of enough length to
// save space by doing it
// -- write the non-run length packet
// -- start run-length packet
if ( ++rlcount == rlthresh ) {
// close a non-run packet
if ( pixcount > (rlcount+1) ) {
// write out length and do not set run flag
ubyte code = (ubyte)(pixcount - 2 - rlthresh);
cfwrite( &code, 1, 1, cfile );
cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
copyloc = inputpixel;
pixcount = rlcount + 1;
}
}
} else {
// no match -- either break a run or continue without one
// if a run exists break it:
// write the bytes in the string (1+1)
// start the next string
if ( rlcount >= rlthresh ) {
ubyte code = (ubyte)(0x80 | rlcount);
cfwrite( &code, 1, 1, cfile );
cfwrite( copyloc, 1, 1, cfile );
pixcount = 1;
continue;
} else {
// not a match and currently not a run
// - save the current pixel
// - reset the run-length flag
rlcount = 0;
matchpixel = inputpixel;
}
}
pixcount++;
inputpixel += 1;
} while ( inputpixel < (in + bytecount));
// quit this buffer without loosing any data
if ( --pixcount >= 1 ) {
ubyte code = ubyte(pixcount - 1);
// set the run flag if this is a run
if ( rlcount >= rlthresh ) {
code |= 0x80;
pixcount = 1;
}
cfwrite( &code, 1, 1, cfile );
// copy the data into place
cfwrite( copyloc, 1, pixcount, cfile );
}
return param_nelem;
}
+189 -383
View File
File diff suppressed because it is too large. Load diff
+2 -6
View File
@@ -29,8 +29,6 @@ typedef struct cf_pathtype {
// During cfile_init, verify that Pathtypes[n].index == n for each item
extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
// Returns the default storage path for files given a
// particular pathtype. In other words, the path to
// the unpacked, non-cd'd, stored on hard drive path.
@@ -41,9 +39,7 @@ bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if result would be too long (invalid result)
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename = nullptr,
bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename = nullptr, bool localize = false,
uint32_t location_flags = CF_LOCATION_ALL);
int cf_create_default_path_string( char *path, uint path_max, int pathtype, const char *filename=NULL, bool localize = false);
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename=NULL, bool localize = false );
#endif //_CFILESYSTEM_H
+235 -341
View File
@@ -5,27 +5,27 @@
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
#include "cmdline/cmdline.h"
#include "camera/camera.h" //VIEWER_ZOOM_DEFAULT
#include "cfile/cfilesystem.h"
#include "fireball/fireballs.h"
#include "cmdline/cmdline.h"
#include "globalincs/linklist.h"
#include "globalincs/pstypes.h"
#include "globalincs/systemvars.h"
#include "globalincs/version.h"
#include "graphics/shadows.h"
#include "hud/hudconfig.h"
#include "io/joy.h"
#include "network/multi.h"
#include "options/OptionsManager.h"
#include "osapi/osapi.h"
#include "parse/sexp.h"
#include "scripting/scripting.h"
#include "sound/openal.h"
#include "parse/sexp.h"
#include "globalincs/version.h"
#include "globalincs/pstypes.h"
#include "osapi/osapi.h"
#include "cfile/cfilesystem.h"
#include "sound/speech.h"
#include "starfield/starfield.h"
#include "sound/openal.h"
#include "io/joy.h"
#ifdef _WIN32
#include <io.h>
@@ -39,8 +39,8 @@
#include <dirent.h>
#endif
#include <cstring>
#include <cstdlib>
#include <string.h>
#include <stdlib.h>
#include <cstdio>
#include <jansson.h>
@@ -82,8 +82,8 @@ public:
int name_found; // true if parameter on command line, otherwise false
const int arg_type; // from enum cmdline_arg_type; used for help
cmdline_parm(const char *name, const char *help, const int arg_type, const bool stacks = false) noexcept;
~cmdline_parm() noexcept;
cmdline_parm(const char *name, const char *help, const int arg_type, const bool stacks = false);
~cmdline_parm();
int found();
int get_int();
float get_float();
@@ -100,13 +100,17 @@ extern int Show_framerate; // from freespace.cpp
enum
{
// DO NOT CHANGE ANYTHING ABOUT THESE FIRST TWO OR WILL MESS UP THE LAUNCHER
EASY_DEFAULT = 1 << 1, // Default FS2 (All features off)
EASY_ALL_ON = 1 << 2, // All features on
EASY_DEFAULT = 1 << 1,
EASY_ALL_ON = 1 << 2,
EASY_HI_MEM_ON = 1 << 3, // High memory usage features on
EASY_HI_MEM_OFF = 1 << 4, // High memory usage features off
EASY_MEM_ON = 1 << 3,
EASY_MEM_OFF = 1 << 4,
// Add new flags here
// Combos
EASY_MEM_ALL_ON = EASY_ALL_ON | EASY_MEM_ON,
EASY_DEFAULT_MEM = EASY_DEFAULT | EASY_MEM_OFF
};
enum BuildCaps
@@ -118,7 +122,6 @@ enum BuildCaps
};
#define PARSE_COMMAND_LINE_STRING "-parse_cmdline_only"
#define GET_FLAGS_STRING "-get_flags"
typedef struct
{
@@ -142,116 +145,116 @@ typedef struct
char name[20]; // The actual flag
char desc[40]; // The text that will appear in the launcher (unless its blank, other name is shown)
bool fso_only; // true if this is a fs2_open only feature
int on_flags; // "Easy setting" which will turn this option on
int off_flags; // "Easy setting" which will turn this option off
int on_flags; // Easy flag which will turn this feature on
int off_flags; // Easy flag which will turn this feature off
char type[16]; // Launcher uses this to put flags under different headings
char web_url[256]; // Link to documentation of feature (please use wiki or somewhere constant)
} Flag;
// clang-format off
// Please group them by type, ie graphics, gameplay etc, maximum 20 different types
Flag exe_params[] =
{
{ "-nospec", "Disable specular", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nospec", },
{ "-noglow", "Disable glow maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noglow", },
{ "-noenv", "Disable environment maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noenv", },
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nonormal" },
{ "-emissive_light", "Enable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-emissive_light" },
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noheight" },
{ "-3dshockwave", "Enable 3D shockwaves", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
{ "-no_post_process", "Disable post-processing", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_post_process" },
{ "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
{ "-aa", "Enable Post-process anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-aa" },
{ "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nolightshafts"},
{ "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
{ "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
{ "-enable_shadows", "Enable Shadows", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-enable_shadows"},
{ "-nospec", "Disable specular", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-spec", },
{ "-noglow", "Disable glow maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-glow", },
{ "-noenv", "Disable environment maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-env", },
{ "-nomotiondebris", "Disable motion debris", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-missile_lighting", "Apply lighting to missiles" , true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missile_lighting", },
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-normal" },
{ "-no_emissive_light", "Disable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_emissive_light" },
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-height" },
{ "-3dshockwave", "Enable 3D shockwaves", true, EASY_MEM_ALL_ON, EASY_DEFAULT_MEM, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
{ "-post_process", "Enable post processing", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-post_process" },
{ "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
{ "-fxaa", "Enable FXAA anti-aliasing", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fxaa" },
{ "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-flightshaftsoff"},
{ "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
{ "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT_MEM, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
{ "-enable_shadows", "Enable Shadows", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_shadows"},
{ "-no_vsync", "Disable vertical sync", true, 0, EASY_DEFAULT, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_vsync", },
{ "-cache_bitmaps", "Cache bitmaps between missions", true, 0, EASY_DEFAULT_MEM, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-cache_bitmaps", },
{ "-no_vsync", "Disable vertical sync", true, 0, EASY_DEFAULT, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_vsync", },
{ "-dualscanlines", "Add another pair of scanning lines", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dualscanlines", },
{ "-targetinfo", "Enable info next to target", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-targetinfo", },
{ "-orbradar", "Enable 3D radar", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-orbradar", },
{ "-rearm_timer", "Enable rearm/repair completion timer", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-rearm_timer", },
{ "-ballistic_gauge", "Enable analog ballistic ammo gauge", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ballistic_gauge", },
{ "-fps", "Show frames per second on HUD", false, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fps", },
{ "-dualscanlines", "Add another pair of scanning lines", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dualscanlines", },
{ "-targetinfo", "Enable info next to target", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-targetinfo", },
{ "-orbradar", "Enable 3D radar", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-orbradar", },
{ "-rearm_timer", "Enable rearm/repair completion timer", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-rearm_timer", },
{ "-ballistic_gauge", "Enable analog ballistic ammo gauge", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ballistic_gauge", },
{ "-ship_choice_3d", "Use 3D models for ship selection", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ship_choice_3d", },
{ "-weapon_choice_3d", "Use 3D models for weapon selection", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-weapon_choice_3d", },
{ "-3dwarp", "Enable 3D warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
{ "-ship_choice_3d", "Use 3D models for ship selection", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ship_choice_3d", },
{ "-weapon_choice_3d", "Use 3D models for weapon selection", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-weapon_choice_3d", },
{ "-3dwarp", "Enable 3D warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
{ "-nomusic", "Disable music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomusic", },
{ "-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", },
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
{ "-nomusic", "Disable music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomusic", },
{ "-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", },
{ "-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", },
{ "-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", },
{ "-closed", "Start hosted server as closed", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-closed", },
{ "-restricted", "Host confirms join requests", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-restricted", },
{ "-multilog", "", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-multilog", },
{ "-clientdamage", "", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-clientdamage", },
{ "-mpnoreturn", "Disable flight deck option", true, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mpnoreturn", },
{ "-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", },
{ "-closed", "Start hosted server as closed", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-closed", },
{ "-restricted", "Host confirms join requests", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-restricted", },
{ "-multilog", "", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-multilog", },
{ "-clientdamage", "", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-clientdamage", },
{ "-mpnoreturn", "Disable flight deck option", true, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mpnoreturn", },
{ "-gateway_ip", "Set gateway IP address", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gateway_ip", },
{ "-no_set_gamma", "Disable setting of gamma", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_set_gamma", },
{ "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
{ "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
{ "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
{ "-disable_fbo", "Disable OpenGL RenderTargets", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_fbo", },
{ "-disable_pbo", "Disable OpenGL Pixel Buffer Objects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_pbo", },
{ "-ati_swap", "Fix colour issues on some ATI cards", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ati_swap", },
{ "-no_3d_sound", "Use only 2D/stereo for sound effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_3d_sound", },
{ "-mipmap", "Enable mipmapping", true, 0, EASY_DEFAULT | EASY_HI_MEM_OFF, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mipmap", },
{ "-use_gldrawelements","Don't use glDrawRangeElements", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-use_gldrawelements", },
{ "-gl_finish", "Fix input lag on some ATI+Linux systems", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gl_finish", },
{ "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_geo_effects", },
{ "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-set_cpu_affinity", },
{ "-nograb", "Disables mouse grabbing", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nograb", },
{ "-noshadercache", "Disables the shader cache", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noshadercache", },
{ "-no_set_gamma", "Disable setting of gamma", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_set_gamma", },
{ "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
{ "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
{ "-query_speech", "Check if this build has speech", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-query_speech", },
{ "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
{ "-disable_fbo", "Disable OpenGL RenderTargets", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_fbo", },
{ "-disable_pbo", "Disable OpenGL Pixel Buffer Objects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_pbo", },
{ "-ati_swap", "Fix colour issues on some ATI cards", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ati_swap", },
{ "-no_3d_sound", "Use only 2D/stereo for sound effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_3d_sound", },
{ "-mipmap", "Enable mipmapping", true, 0, EASY_DEFAULT_MEM, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mipmap", },
{ "-use_gldrawelements","Don't use glDrawRangeElements", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-use_gldrawelements", },
{ "-old_collision", "Use old collision detection system", true, EASY_DEFAULT, EASY_ALL_ON, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-old_collision", },
{ "-gl_finish", "Fix input lag on some ATI+Linux systems", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gl_finish", },
{ "-no_batching", "Disable batched model rendering", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-nograb", "Disables mouse grabbing", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nograb", },
{ "-noshadercache", "Disables the shader cache", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noshadercache", },
#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", },
{ "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
#endif
{ "-ingame_join", "Allow in-game joining", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ingame_join", },
{ "-voicer", "Enable voice recognition", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-voicer", },
{ "-ingame_join", "Allow in-game joining", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ingame_join", },
{ "-voicer", "Enable voice recognition", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-voicer", },
{ "-bmpmanusage", "Show how many BMPMAN slots are in use", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-bmpmanusage", },
{ "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
{ "-stats", "Show statistics", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stats", },
{ "-coords", "Show coordinates", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-coords", },
{ "-pofspew", "Dump model information to pofspew.txt", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pofspew", },
{ "-weaponspew", "Dump weapon stats and spreadsheets", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-weaponspew", },
{ "-tablecrcs", "Dump table CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-tablecrcs", },
{ "-missioncrcs", "Dump mission CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missioncrcs", },
{ "-dis_collisions", "Disable collisions", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_collisions", },
{ "-dis_weapons", "Disable weapon rendering", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_weapons", },
{ "-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", },
{ "-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", },
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
{ "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
{ "-json_profiling", "Generate JSON profiling output", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_profiling", },
{ "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
{ "-gr_debug", "Output graphics debug information", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gr_debug", },
{ "-fps", "Show frames per second on HUD", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fps", },
{ "-bmpmanusage", "Show how many BMPMAN slots are in use", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-bmpmanusage", },
{ "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
{ "-stats", "Show statistics", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stats", },
{ "-coords", "Show coordinates", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-coords", },
{ "-show_mem_usage", "Show memory usage", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-show_mem_usage", },
{ "-pofspew", "Generate all ibx files immediately", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pofspew", },
{ "-tablecrcs", "Dump table CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-tablecrcs", },
{ "-missioncrcs", "Dump mission CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missioncrcs", },
{ "-dis_collisions", "Disable collisions", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_collisions", },
{ "-dis_weapons", "Disable weapon rendering", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_weapons", },
{ "-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", },
{ "-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", },
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
{ "-json_pilot", "Dump pilot files in JSON format", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_pilot", },
{ "-json_profiling", "Generate JSON profiling output", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_profiling", },
{ "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", },
{ "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
};
// clang-format on
// forward declaration
const char * get_param_desc(const char *flag_name);
@@ -275,7 +278,6 @@ cmdline_parm port_arg("-port", "Multiplayer network port", AT_INT);
cmdline_parm multilog_arg("-multilog", NULL, AT_NONE); // Cmdline_multi_log
cmdline_parm client_dodamage("-clientdamage", NULL, AT_NONE); // Cmdline_client_dodamage
cmdline_parm pof_spew("-pofspew", NULL, AT_NONE); // Cmdline_spew_pof_info
cmdline_parm weapon_spew("-weaponspew", nullptr, AT_NONE); // Cmdline_spew_weapon_stats
cmdline_parm mouse_coords("-coords", NULL, AT_NONE); // Cmdline_mouse_coords
cmdline_parm timeout("-timeout", "Multiplayer network timeout (secs)", AT_INT); // Cmdline_timeout
cmdline_parm bit32_arg("-32bit", "Deprecated", AT_NONE); // (only here for retail compatibility reasons, doesn't actually do anything)
@@ -297,7 +299,6 @@ int Cmdline_multi_stream_chat_to_file = 0;
int Cmdline_network_port = -1;
int Cmdline_restricted_game = 0;
int Cmdline_spew_pof_info = 0;
bool Cmdline_spew_weapon_stats = false;
int Cmdline_start_netgame = 0;
int Cmdline_timeout = -1;
int Cmdline_use_last_pilot = 0;
@@ -308,57 +309,69 @@ 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 clip_dist_arg("-clipdist", "Changes the distance from the viewpoint for the near-clipping plane", AT_FLOAT); // Cmdline_clip_dist
cmdline_parm spec_exp_arg("-spec_exp", "Adjusts the size of shiny spots on ships", AT_FLOAT);
cmdline_parm ogl_spec_arg("-ogl_spec", "Shininess of specular light", AT_FLOAT); // Cmdline_ogl_spec
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);
cmdline_parm spec_tube_arg("-spec_tube", "Adjusts beam weapons contribution to specular highlights", AT_FLOAT);
cmdline_parm ambient_factor_arg("-ambient_factor", "Adjusts ambient light applied to all parts of a ship", AT_INT); // Cmdline_ambient_factor
cmdline_parm missile_lighting_arg("-missile_lighting", NULL, AT_NONE); // Cmdline_missile_lighting
cmdline_parm env("-noenv", NULL, AT_NONE); // Cmdline_env
cmdline_parm glow_arg("-noglow", NULL, AT_NONE); // Cmdline_glow -- use Bobs glow code
cmdline_parm nomotiondebris_arg("-nomotiondebris", NULL, AT_NONE); // Cmdline_nomotiondebris -- Removes those ugly floating rocks -C
cmdline_parm noscalevid_arg("-noscalevid", NULL, AT_NONE); // Cmdline_noscalevid -- disable video scaling that fits to window
cmdline_parm spec_arg("-nospec", NULL, AT_NONE); // Cmdline_spec --
cmdline_parm emissive_arg("-emissive_light", "Enable emissive light from ships", AT_NONE); // Cmdline_no_emissive -- don't use emissive light in OGL
cmdline_parm noemissive_arg("-no_emissive_light", "Disable emissive light from ships", AT_NONE); // Cmdline_no_emissive -- don't use emissive light in OGL
cmdline_parm normal_arg("-nonormal", NULL, AT_NONE); // Cmdline_normal -- disable normal mapping
cmdline_parm height_arg("-noheight", NULL, AT_NONE); // Cmdline_height -- enable support for parallax mapping
cmdline_parm enable_3d_shockwave_arg("-3dshockwave", NULL, AT_NONE);
cmdline_parm softparticles_arg("-soft_particles", NULL, AT_NONE);
cmdline_parm no_postprocess_arg("-no_post_process", "Disables post-processing", AT_NONE);
cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires post-processing", AT_INT);
cmdline_parm post_process_aa_arg("-aa", "Enables post-process antialiasing", AT_NONE);
cmdline_parm post_process_aa_preset_arg("-aa_preset", "Sets the AA effect to use. See the wiki for details", AT_INT);
cmdline_parm deprecated_fxaa_arg("-fxaa", nullptr, AT_NONE);
cmdline_parm deprecated_fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-2), requires post-processing and -fxaa", AT_INT);
cmdline_parm deprecated_smaa_arg("-smaa", nullptr, AT_NONE);
cmdline_parm deprecated_smaa_preset_arg("-smaa_preset", "SMAA quality (0-3), requires post-processing and -smaa", AT_INT);
cmdline_parm postprocess_arg("-post_process", NULL, AT_NONE);
cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires -post_process", AT_INT);
cmdline_parm fxaa_arg("-fxaa", NULL, AT_NONE);
cmdline_parm fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-9), requires -post_process and -fxaa", AT_INT);
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
cmdline_parm no_batching("-no_batching", NULL, AT_NONE);
cmdline_parm shadow_quality_arg("-shadow_quality", NULL, AT_INT);
cmdline_parm enable_shadows_arg("-enable_shadows", NULL, AT_NONE);
cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline_no_deferred
cmdline_parm anisotropy_level_arg("-anisotropic_filter", NULL, AT_INT);
float Cmdline_clip_dist = Default_min_draw_distance;
float Cmdline_fov = 0.75f;
float Cmdline_ogl_spec = 80.0f;
int Cmdline_ambient_factor = 128;
int Cmdline_env = 1;
int Cmdline_mipmap = 0;
int Cmdline_missile_lighting = 0;
int Cmdline_glow = 1;
int Cmdline_nomotiondebris = 0;
int Cmdline_noscalevid = 0;
int Cmdline_spec = 1;
int Cmdline_emissive = 0;
int Cmdline_no_emissive = 0;
int Cmdline_normal = 1;
int Cmdline_height = 1;
int Cmdline_enable_3d_shockwave = 0;
int Cmdline_softparticles = 0;
int Cmdline_bloom_intensity = 25;
int Cmdline_postprocess = 0;
int Cmdline_bloom_intensity = 75;
bool Cmdline_fxaa = false;
int Cmdline_fxaa_preset = 6;
extern int Fxaa_preset_last_frame;
bool Cmdline_fb_explosions = 0;
bool Cmdline_fb_thrusters = false;
bool Cmdline_no_batching = false;
extern bool ls_force_off;
int Cmdline_shadow_quality = 0;
int Cmdline_no_deferred_lighting = 0;
int Cmdline_aniso_level = 0;
// Game Speed related
cmdline_parm cache_bitmaps_arg("-cache_bitmaps", NULL, AT_NONE); // Cmdline_cache_bitmaps
cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NONE); // Cmdline_NoFPSCap
cmdline_parm no_vsync_arg("-no_vsync", NULL, AT_NONE); // Cmdline_no_vsync
int Cmdline_cache_bitmaps = 0; // caching of bitmaps between missions (faster loads, can hit swap on reload with <512 Meg RAM though) - taylor
int Cmdline_NoFPSCap = 0; // Disable FPS capping - kazan
int Cmdline_no_vsync = 0;
@@ -391,8 +404,10 @@ int Cmdline_autopilot_interruptable = 1;
int Cmdline_stretch_menu = 0;
// Audio related
cmdline_parm query_speech_arg("-query_speech", NULL, AT_NONE); // Cmdline_query_speech
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
int Cmdline_query_speech = 0;
int Cmdline_voice_recognition = 0;
int Cmdline_no_enhanced_sound = 0;
@@ -405,14 +420,16 @@ char *Cmdline_mod = NULL; //DTP for mod argument
cmdline_parm almission_arg("-almission", "Autoload multiplayer mission", AT_STRING); // Cmdline_almission -- DTP for autoload Multi mission
cmdline_parm ingamejoin_arg("-ingame_join", NULL, AT_NONE); // Cmdline_ingamejoin
cmdline_parm mpnoreturn_arg("-mpnoreturn", NULL, AT_NONE); // Cmdline_mpnoreturn -- Removes 'Return to Flight Deck' in respawn dialog -C
cmdline_parm missioncrcspew_arg("-missioncrcs", NULL, AT_STRING); // Cmdline_spew_mission_crcs
cmdline_parm tablecrcspew_arg("-tablecrcs", NULL, AT_STRING); // Cmdline_spew_table_crcs
cmdline_parm objupd_arg("-cap_object_update", "Multiplayer object update cap (0-3)", AT_INT);
cmdline_parm gateway_ip_arg("-gateway_ip", "Set gateway IP address", AT_STRING);
char *Cmdline_almission = NULL; //DTP for autoload multi mission.
int Cmdline_ingamejoin = 0;
int Cmdline_mpnoreturn = 0;
char *Cmdline_spew_mission_crcs = NULL;
char *Cmdline_spew_table_crcs = NULL;
int Cmdline_objupd = 3; // client object updates on LAN by default
char *Cmdline_gateway_ip = nullptr;
// Launcher related options
cmdline_parm portable_mode("-portable_mode", NULL, AT_NONE);
@@ -430,6 +447,7 @@ cmdline_parm atiswap_arg("-ati_swap", NULL, AT_NONE); // Cmdline_atiswap
cmdline_parm no3dsound_arg("-no_3d_sound", NULL, AT_NONE); // Cmdline_no_3d_sound - Disable use of full 3D sounds
cmdline_parm no_drawrangeelements("-use_gldrawelements", NULL, AT_NONE); // Cmdline_drawelements -- Uses glDrawElements instead of glDrawRangeElements
cmdline_parm keyboard_layout("-keyboard_layout", "Specify keyboard layout (qwertz or azerty)", AT_STRING);
cmdline_parm old_collision_system("-old_collision", NULL, AT_NONE); // Cmdline_old_collision_sys
cmdline_parm gl_finish ("-gl_finish", NULL, AT_NONE);
cmdline_parm no_geo_sdr_effects("-no_geo_effects", NULL, AT_NONE);
cmdline_parm set_cpu_affinity("-set_cpu_affinity", NULL, AT_NONE);
@@ -479,18 +497,17 @@ cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); //
cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause
cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
cmdline_parm json_pilot("-json_pilot", NULL, AT_NONE); //Cmdline_json_pilot
cmdline_parm json_profiling("-json_profiling", NULL, AT_NONE); //Cmdline_json_profiling
cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_video_info
cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
cmdline_parm debug_window_arg("-debug_window", NULL, AT_NONE); // Cmdline_debug_window
cmdline_parm graphics_debug_output_arg("-gr_debug", nullptr, AT_NONE); // Cmdline_graphics_debug_output
cmdline_parm log_to_stdout_arg("-stdout_log", nullptr, AT_NONE); // Cmdline_log_to_stdout
char *Cmdline_start_mission = NULL;
int Cmdline_old_collision_sys = 0;
int Cmdline_dis_collisions = 0;
int Cmdline_dis_weapons = 0;
bool Cmdline_output_sexp_info = false;
int Cmdline_noparseerrors = 0;
#ifdef Allow_NoWarn
int Cmdline_nowarn = 0; // turn warnings off in FRED
@@ -510,18 +527,16 @@ bool Cmdline_profile_write_file = false;
bool Cmdline_no_unfocus_pause = false;
bool Cmdline_benchmark_mode = false;
bool Cmdline_noninteractive = false;
bool Cmdline_json_pilot = false;
bool Cmdline_json_profiling = false;
bool Cmdline_frame_profile = false;
bool Cmdline_show_video_info = false;
bool Cmdline_debug_window = false;
bool Cmdline_graphics_debug_output = false;
bool Cmdline_log_to_stdout = false;
// Other
cmdline_parm get_flags_arg(GET_FLAGS_STRING, "Output the launcher flags file", AT_STRING);
cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_STRING);
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
// Deprecated flags - CommanderDJ
cmdline_parm deprecated_spec_arg("-spec", "Deprecated", AT_NONE);
@@ -533,10 +548,6 @@ cmdline_parm deprecated_jpgtga_arg("-jpgtga", "Deprecated", AT_NONE);
cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_cache_bitmaps_arg("-cache_bitmaps", "Deprecated", AT_NONE);
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;
@@ -546,9 +557,6 @@ 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
@@ -614,19 +622,6 @@ void cmdline_debug_print_cmdline()
{
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
@@ -819,7 +814,7 @@ void os_validate_parms(int argc, char *argv[])
size_t sp = 0;
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
// don't output deprecated flags
if (stricmp("deprecated", parmp->help) != 0) {
if (stricmp("deprecated", parmp->help)) {
sp = strlen(parmp->name);
if (parmp->arg_type != AT_NONE) {
atp = strlen(cmdline_arg_types[parmp->arg_type]);
@@ -931,11 +926,11 @@ void os_process_cmdline(char* cmdline)
delete[] argv;
}
bool has_cmdline_only_or_get_flags(int argc, char *argv[])
bool has_cmdline_only_flag(int argc, char *argv[])
{
for (int i = 0; i < argc; ++i)
{
if (!strcmp(argv[i], PARSE_COMMAND_LINE_STRING) || !strcmp(argv[i], GET_FLAGS_STRING))
if (!strcmp(argv[i], PARSE_COMMAND_LINE_STRING))
{
return true;
}
@@ -967,9 +962,7 @@ void os_init_cmdline(int argc, char *argv[])
FILE *fp;
// Don't parse any command-line config files if we specified PARSE_COMMAND_LINE_STRING (to explicitly prevent it),
// or GET_FLAGS_STRING (because the engine is going to do a quick exit and for GitHub issue #1221)
if (!has_cmdline_only_or_get_flags(argc, argv)) {
if (!has_cmdline_only_flag(argc, argv)) {
// Only parse the config file in the current directory if we are in legacy config mode
if (os_is_legacy_mode()) {
// read the cmdline_fso.cfg file from the data folder, and pass the command line arguments to
@@ -1034,7 +1027,7 @@ void os_init_cmdline(int argc, char *argv[])
fclose(fp);
}
}
} // If cmdline included PARSE_COMMAND_LINE_STRING or GET_FLAGS_STRING
} // If cmdline included PARSE_COMMAND_LINE_STRING
// By parsing cmdline last, anything actually on the command line will take precedence.
os_parse_parms(argc, argv);
@@ -1050,7 +1043,7 @@ void os_init_cmdline(int argc, char *argv[])
* @param arg_type_ parameters arguement type (if any)
* @param stacks_ can the parameter be stacked
*/
cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_type_, const bool stacks_) noexcept:
cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_type_, const bool stacks_):
name(name_), help(help_), stacks(stacks_), arg_type(arg_type_)
{
args = NULL;
@@ -1073,7 +1066,7 @@ cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_t
// destructor - frees any allocated memory
cmdline_parm::~cmdline_parm() noexcept
cmdline_parm::~cmdline_parm()
{
#ifndef FRED
if (args) {
@@ -1170,7 +1163,7 @@ bool cmdline_parm::has_param() {
#ifdef SCP_UNIX
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// dir must not contain a slash.
static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
static SCP_vector<SCP_string> unix_get_single_dir_names(SCP_string parent, SCP_string dir)
{
SCP_vector<SCP_string> ret;
@@ -1193,7 +1186,7 @@ static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// Recurses to deal with slashes in dir.
static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
static SCP_vector<SCP_string> unix_get_dir_names(SCP_string parent, SCP_string dir)
{
size_t slash = dir.find_first_of("/\\");
@@ -1394,15 +1387,6 @@ static json_t* json_get_v1() {
json_object_set_new(openal_obj, "capture_devices", capture_array);
}
{
auto efx_support_obj = json_object();
for (auto& pair : openal_info.efx_support) {
json_object_set_new(efx_support_obj, pair.first.c_str(), json_boolean(pair.second));
}
json_object_set_new(openal_obj, "efx_support", efx_support_obj);
}
json_object_set_new(root, "openal", openal_obj);
}
@@ -1479,7 +1463,7 @@ static void write_flags_file() {
}
static flag_output_type get_flags_output_type() {
Assertion(get_flags_arg.found(), "This function is only valid if " GET_FLAGS_STRING " is present!");
Assertion(get_flags_arg.found(), "This function is only valid if -get_flags is present!");
if (!get_flags_arg.has_param()) {
// Default to binary mode
@@ -1554,6 +1538,24 @@ bool SetCmdlineParams()
Cmdline_extra_warn = 1;
}
if ( missioncrcspew_arg.found() ) {
Cmdline_spew_mission_crcs = missioncrcspew_arg.str();
// strip off blank space at end if it's there
if ( Cmdline_spew_mission_crcs[strlen(Cmdline_spew_mission_crcs)-1] == ' ' ) {
Cmdline_spew_mission_crcs[strlen(Cmdline_spew_mission_crcs)-1] = '\0';
}
}
if ( tablecrcspew_arg.found() ) {
Cmdline_spew_table_crcs = tablecrcspew_arg.str();
// strip off blank space at end if it's there
if ( Cmdline_spew_table_crcs[strlen(Cmdline_spew_table_crcs)-1] == ' ' ) {
Cmdline_spew_table_crcs[strlen(Cmdline_spew_table_crcs)-1] = '\0';
}
}
if (!Fred_running) { //There is no standalone FRED
// is this a standalone server??
if (standalone_arg.found()) {
@@ -1644,11 +1646,6 @@ bool SetCmdlineParams()
Cmdline_network_port = port_arg.get_int();
}
// get IP address of gateway, for auto port forwarding
if ( gateway_ip_arg.found() ) {
Cmdline_gateway_ip = gateway_ip_arg.str();
}
// the connect argument specifies to join a game at this particular address
if ( connect_arg.found() ) {
Cmdline_use_last_pilot = 1;
@@ -1671,11 +1668,6 @@ bool SetCmdlineParams()
Cmdline_spew_pof_info = 1;
}
// spew weapon stats
if (weapon_spew.found()) {
Cmdline_spew_weapon_stats = true;
}
// mouse coords
if(mouse_coords.found()){
Cmdline_mouse_coords = 1;
@@ -1687,32 +1679,18 @@ bool SetCmdlineParams()
}
// d3d windowed
if(window_arg.found()) {
// We need to set both values since we don't know if we are going to use the new config system
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
if(window_arg.found()){
Cmdline_window = 1;
}
if ( fullscreen_window_arg.found( ) )
{
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
Cmdline_fullscreen_window = 1;
Cmdline_window = 0; /* Make sure no-one sets both */
}
if(res_arg.found()){
Cmdline_res = res_arg.str();
int width = 0;
int height = 0;
if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
SCP_string override;
sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
} else {
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".", Cmdline_res));
}
}
if(center_res_arg.found()){
Cmdline_center_res = center_res_arg.str();
@@ -1792,7 +1770,7 @@ bool SetCmdlineParams()
}
if ( nomotiondebris_arg.found() ) {
Motion_debris_enabled = false;
Cmdline_nomotiondebris = 1;
}
if( mipmap_arg.found() ) {
@@ -1804,11 +1782,11 @@ bool SetCmdlineParams()
}
if ( fov_arg.found() ) {
auto val = fov_arg.get_float();
if (val > 0.1) {
VIEWER_ZOOM_DEFAULT = val;
Cmdline_fov = fov_arg.get_float();
if (Cmdline_fov > 0.1) {
VIEWER_ZOOM_DEFAULT = Cmdline_fov;
} else {
VIEWER_ZOOM_DEFAULT = 0.75f;
VIEWER_ZOOM_DEFAULT = Cmdline_fov = 0.75f;
}
}
@@ -1822,7 +1800,7 @@ bool SetCmdlineParams()
}
if ( use_3dwarp.found() ) {
Fireball_use_3d_warp = true;
Cmdline_3dwarp = 1;
}
if ( use_warp_flash.found() ) {
@@ -1836,8 +1814,11 @@ bool SetCmdlineParams()
if ( stretch_menu.found() ) {
Cmdline_stretch_menu = 1;
}
// specular comand lines
if ( spec_exp_arg.found() ) {
specular_exponent_value = spec_exp_arg.get_float();
}
if ( spec_point_arg.found() ) {
static_point_factor = spec_point_arg.get_float();
}
@@ -1862,7 +1843,7 @@ bool SetCmdlineParams()
if(no_vsync_arg.found() )
{
Gr_enable_vsync = false;
Cmdline_no_vsync = 1;
}
if ( normal_arg.found() ) {
@@ -1872,44 +1853,23 @@ bool SetCmdlineParams()
if ( height_arg.found() ) {
Cmdline_height = 0;
}
if (fxaa_arg.found() ) {
Cmdline_fxaa = true;
if (post_process_aa_arg.found() || post_process_aa_preset_arg.found()) {
Gr_aa_mode = AntiAliasMode::SMAA_Low;
if (post_process_aa_preset_arg.found()) {
switch (post_process_aa_preset_arg.get_int()) {
case 0:
Gr_aa_mode = AntiAliasMode::FXAA_Low;
break;
case 1:
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
break;
case 2:
Gr_aa_mode = AntiAliasMode::FXAA_High;
break;
case 3:
Gr_aa_mode = AntiAliasMode::SMAA_Low;
break;
case 4:
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
break;
case 5:
Gr_aa_mode = AntiAliasMode::SMAA_High;
break;
case 6:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
}
if (fxaa_preset_arg.found()) {
Cmdline_fxaa_preset = fxaa_preset_arg.get_int();
}
}
// If any of the AA presets were chosen, update the _last_frame AA mode to avoid an unnecessary
// shader recompile.
Gr_aa_mode_last_frame = Gr_aa_mode;
Fxaa_preset_last_frame = Cmdline_fxaa_preset;
}
if ( glow_arg.found() )
Cmdline_glow = 0;
if ( query_speech_arg.found() )
Cmdline_query_speech = 1;
if ( ship_choice_3d_arg.found() )
Cmdline_ship_choice_3d = 1;
@@ -1929,11 +1889,8 @@ bool SetCmdlineParams()
if ( output_scripting_arg.found() )
Output_scripting_meta = true;
if (output_script_json_arg.found() )
Output_scripting_json = true;
if (output_sexp_arg.found() ) {
Cmdline_output_sexp_info = true;
output_sexps("sexps.html");
}
if ( no_pbo_arg.found() )
@@ -1995,6 +1952,13 @@ bool SetCmdlineParams()
Cmdline_ballistic_gauge = 1;
}
if ( cache_bitmaps_arg.found() ) {
Cmdline_cache_bitmaps = 1;
}
if(old_collision_system.found())
Cmdline_old_collision_sys = 1;
if(dis_collisions.found())
Cmdline_dis_collisions = 1;
@@ -2005,13 +1969,22 @@ bool SetCmdlineParams()
Cmdline_no_fbo = 1;
}
if ( emissive_arg.found() ) {
Cmdline_emissive = 1;
if ( noemissive_arg.found() ) {
Cmdline_no_emissive = 1;
}
if ( ogl_spec_arg.found() ) {
Cmdline_ogl_spec = ogl_spec_arg.get_float();
CLAMP(Cmdline_ogl_spec, 0.0f, 128.0f);
}
if ( rearm_timer_arg.found() )
Cmdline_rearm_timer = 1;
if ( missile_lighting_arg.found() )
Cmdline_missile_lighting = 1;
if ( save_render_targets_arg.found() )
Cmdline_save_render_targets = 1;
@@ -2038,17 +2011,22 @@ bool SetCmdlineParams()
if ( fb_explosions_arg.found() )
{
Gr_framebuffer_effects.set(FramebufferEffects::Shockwaves, true);
Cmdline_fb_explosions = 1;
}
if (fb_thrusters_arg.found())
{
Gr_framebuffer_effects.set(FramebufferEffects::Thrusters, true);
Cmdline_fb_thrusters = true;
}
if ( no_postprocess_arg.found() )
if ( no_batching.found() )
{
Gr_post_processing_enabled = false;
Cmdline_no_batching = true;
}
if ( postprocess_arg.found() )
{
Cmdline_postprocess = 1;
}
if ( bloom_intensity_arg.found() )
@@ -2068,32 +2046,12 @@ bool SetCmdlineParams()
if( enable_shadows_arg.found() )
{
Shadow_quality = ShadowQuality::Medium;
Cmdline_shadow_quality = 2;
}
if( shadow_quality_arg.found() )
{
switch (shadow_quality_arg.get_int()) {
case 0:
Shadow_quality = ShadowQuality::Disabled;
break;
case 1:
Shadow_quality = ShadowQuality::Low;
break;
case 2:
Shadow_quality = ShadowQuality::Medium;
break;
case 3:
Shadow_quality = ShadowQuality::High;
break;
case 4:
Shadow_quality = ShadowQuality::Ultra;
break;
default:
mprintf(("Invalid shadow quality %d. Disabling shadows...\n", shadow_quality_arg.get_int()));
Shadow_quality = ShadowQuality::Disabled;
break;
}
Cmdline_shadow_quality = shadow_quality_arg.get_int();
}
if( no_deferred_lighting_arg.found() )
@@ -2101,11 +2059,6 @@ bool SetCmdlineParams()
Cmdline_no_deferred_lighting = 1;
}
if (anisotropy_level_arg.found())
{
Cmdline_aniso_level = anisotropy_level_arg.get_int();
}
if (frame_profile_write_file.found())
{
Cmdline_profile_write_file = true;
@@ -2126,6 +2079,11 @@ bool SetCmdlineParams()
Cmdline_noninteractive = true;
}
if (json_pilot.found())
{
Cmdline_json_pilot = true;
}
if (json_profiling.found())
{
Cmdline_json_profiling = true;
@@ -2140,14 +2098,6 @@ bool SetCmdlineParams()
Cmdline_debug_window = true;
}
if (graphics_debug_output_arg.found()) {
Cmdline_graphics_debug_output = true;
}
if (log_to_stdout_arg.found()) {
Cmdline_log_to_stdout = true;
}
if (show_video_info.found())
{
Cmdline_show_video_info = true;
@@ -2194,62 +2144,6 @@ bool SetCmdlineParams()
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;
if (deprecated_fxaa_preset_arg.found()) {
auto val = deprecated_fxaa_preset_arg.get_int();
if (val > 6) {
Gr_aa_mode = AntiAliasMode::FXAA_High;
} else if (val > 3) {
Gr_aa_mode = AntiAliasMode::FXAA_Medium;
} else {
Gr_aa_mode = AntiAliasMode::FXAA_Low;
}
}
}
if (deprecated_smaa_arg.found()) {
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
if (deprecated_smaa_preset_arg.found()) {
switch (deprecated_smaa_preset_arg.get_int()) {
case 0:
Gr_aa_mode = AntiAliasMode::SMAA_Low;
break;
case 1:
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
break;
case 2:
Gr_aa_mode = AntiAliasMode::SMAA_High;
break;
case 3:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
default:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
}
}
}
return true;
}
+19 -8
View File
@@ -53,25 +53,37 @@ extern char *Cmdline_center_res;
// FSO OPTIONS -------------------------------------------------
// Graphics related
extern double specular_exponent_value;
extern float Cmdline_clip_dist;
extern float Cmdline_fov;
extern float Cmdline_ogl_spec;
extern float static_light_factor;
extern float static_point_factor;
extern float static_tube_factor;
extern int Cmdline_ambient_factor;
extern int Cmdline_env;
extern int Cmdline_missile_lighting;
extern int Cmdline_glow;
extern int Cmdline_nomotiondebris;
extern int Cmdline_noscalevid; // disables fit-to-window for movies - taylor
extern int Cmdline_spec;
extern int Cmdline_normal;
extern int Cmdline_height;
extern int Cmdline_enable_3d_shockwave;
extern int Cmdline_softparticles;
extern int Cmdline_postprocess;
extern int Cmdline_bloom_intensity;
extern bool Cmdline_fxaa;
extern int Cmdline_fxaa_preset;
extern bool Cmdline_fb_explosions;
extern bool Cmdline_fb_thrusters;
extern bool Cmdline_no_batching;
extern int Cmdline_shadow_quality;
extern int Cmdline_no_deferred_lighting;
extern int Cmdline_emissive;
extern int Cmdline_aniso_level;
extern int Cmdline_no_emissive;
// Game Speed related
extern int Cmdline_cache_bitmaps;
extern int Cmdline_NoFPSCap;
extern int Cmdline_no_vsync;
@@ -91,6 +103,7 @@ extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
// Audio related
extern int Cmdline_query_speech;
extern int Cmdline_voice_recognition;
extern int Cmdline_no_enhanced_sound;
@@ -100,8 +113,9 @@ extern char *Cmdline_mod; // DTP for mod support
extern char *Cmdline_almission; // DTP for autoload mission (for multi only)
extern int Cmdline_ingamejoin;
extern int Cmdline_mpnoreturn;
extern char *Cmdline_spew_mission_crcs;
extern char *Cmdline_spew_table_crcs;
extern int Cmdline_objupd;
extern char *Cmdline_gateway_ip;
// Launcher related options
extern bool Cmdline_portable_mode;
@@ -128,9 +142,9 @@ extern bool Cmdline_alternate_registry_path;
// Developer/Testing related
extern char *Cmdline_start_mission;
extern int Cmdline_old_collision_sys;
extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern bool Cmdline_output_sexp_info;
extern int Cmdline_noparseerrors;
extern int Cmdline_extra_warn;
extern int Cmdline_bmpman_usage;
@@ -143,13 +157,10 @@ extern bool Cmdline_profile_write_file;
extern bool Cmdline_no_unfocus_pause;
extern bool Cmdline_benchmark_mode;
extern bool Cmdline_noninteractive;
extern bool Cmdline_json_pilot;
extern bool Cmdline_json_profiling;
extern bool Cmdline_frame_profile;
extern bool Cmdline_show_video_info;
extern bool Cmdline_debug_window;
extern bool Cmdline_graphics_debug_output;
extern bool Cmdline_log_to_stdout;
extern bool Cmdline_spew_weapon_stats;
#endif
+21 -1
View File
@@ -53,6 +53,26 @@ void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand)
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z );
}
void cmeasure_select_next(ship *shipp)
{
Assert(shipp != NULL);
int i, new_index;
for (i = 1; i < Num_weapon_types; i++)
{
new_index = (shipp->current_cmeasure + i) % Num_weapon_types;
if(Weapon_info[new_index].wi_flags[Weapon::Info_Flags::Cmeasure])
{
shipp->current_cmeasure = new_index;
return;
}
}
mprintf(("Countermeasure type set to %i in frame %i\n", shipp->current_cmeasure, Framecount));
}
/**
* @brief If this is a player countermeasure, let the player know they evaded a missile.
* @param objp [description]
@@ -72,7 +92,7 @@ void cmeasure_maybe_alert_success(object *objp)
if ( objp->parent == OBJ_INDEX(Player_obj) ) {
hud_start_text_flash(XSTR("Evaded", 1430), 800);
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::MISSILE_EVADED_POPUP)));
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, SND_MISSILE_EVADED_POPUP)));
} else if ( Objects[objp->parent].flags[Object::Object_Flags::Player_ship] ) {
send_countermeasure_success_packet( objp->parent );
}
+1
View File
@@ -28,6 +28,7 @@ extern int Cmeasures_homing_check;
extern int Countermeasures_enabled;
extern void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand);
extern void cmeasure_select_next(object *objp);
extern void cmeasure_maybe_alert_success(object *objp);
#endif // _CMEASURE_H
+76 -58
View File
@@ -38,6 +38,7 @@
#define NUM_SYSTEM_KEYS 14
#define NUM_BUTTONS 19
#define NUM_TABS 4
@@ -156,6 +157,11 @@ char *Mouse_button_text[NUM_MOUSE_TEXT];
char *Mouse_axis_text[NUM_MOUSE_AXIS_TEXT];
char *Invert_text[NUM_INVERT_TEXT];
ubyte System_keys[NUM_SYSTEM_KEYS] = {
KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,
KEY_F11, KEY_F12, KEY_PRINT_SCRN
};
int Control_check_count = 0;
static int Tab; // which tab we are currently in
@@ -350,7 +356,7 @@ DCF_BOOL(show_controls_info, Show_controls_info);
static int Axes_origin[JOY_NUM_AXES];
static int joy_get_unscaled_reading(int raw)
static int joy_get_unscaled_reading(int raw, int axn)
{
int rng;
@@ -516,9 +522,7 @@ void control_config_list_prepare()
Num_cc_lines = y = z = 0;
while (z < CCFG_MAX) {
if (Control_config[z].tab == Tab && !Control_config[z].disabled) {
if (Control_config[z].indexXSTR > 1) {
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, Control_config[z].indexXSTR);
} else if (Control_config[z].indexXSTR == 1) {
if (Control_config[z].hasXSTR) {
Cc_lines[Num_cc_lines].label = XSTR(Control_config[z].text, CONTROL_CONFIG_XSTR + z);
} else {
Cc_lines[Num_cc_lines].label = Control_config[z].text;
@@ -611,7 +615,7 @@ int control_config_undo_last()
int i, z, tab;
if (!Config_item_undo) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -660,7 +664,7 @@ int control_config_undo_last()
free_undo_block();
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
return 0;
}
@@ -711,7 +715,7 @@ int control_config_remove_binding()
config_item_undo *ptr;
if (Selected_line < 0) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -719,7 +723,7 @@ int control_config_remove_binding()
if (z & JOY_AXIS) {
z &= ~JOY_AXIS;
if (Axis_map_to[z] < 0) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -727,13 +731,13 @@ int control_config_remove_binding()
Axis_map_to[z] = -1;
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
Selected_item = -1;
return 0;
}
if ((Control_config[z].joy_id < 0) && (Control_config[z].key_id < 0)) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -751,7 +755,7 @@ int control_config_remove_binding()
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
Selected_item = -1;
return 0;
}
@@ -762,7 +766,7 @@ int control_config_clear_other()
config_item_undo *ptr;
if (Selected_line < 0) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -772,7 +776,7 @@ int control_config_clear_other()
z &= ~JOY_AXIS;
if (Axis_map_to[z] < 0) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -783,7 +787,7 @@ int control_config_clear_other()
}
if (!total) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -804,7 +808,7 @@ int control_config_clear_other()
}
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
return 0;
}
@@ -816,12 +820,12 @@ int control_config_clear_other()
}
}
if (!total) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
if ((Control_config[z].joy_id < 0) && (Control_config[z].key_id < 0)) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -846,7 +850,7 @@ int control_config_clear_other()
}
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
return 0;
}
@@ -863,7 +867,7 @@ int control_config_clear_all()
}
if (!total) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -884,7 +888,7 @@ int control_config_clear_all()
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::RESET_PRESSED);
gamesnd_play_iface(SND_RESET_PRESSED);
return 0;
}
@@ -941,7 +945,7 @@ int control_config_do_reset()
}
if (!total && !cycling_presets) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
@@ -977,7 +981,7 @@ int control_config_do_reset()
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::RESET_PRESSED);
gamesnd_play_iface(SND_RESET_PRESSED);
return 0;
}
@@ -1001,7 +1005,7 @@ void control_config_reset_defaults(int presetnum)
Control_config[i].key_id = preset[i].key_default;
Control_config[i].joy_id = preset[i].joy_default;
Control_config[i].tab = preset[i].tab;
Control_config[i].indexXSTR = preset[i].indexXSTR;
Control_config[i].hasXSTR = preset[i].hasXSTR;
Control_config[i].type = preset[i].type;
Control_config[i].disabled = preset[i].disabled;
}
@@ -1022,10 +1026,10 @@ void control_config_scroll_screen_up()
}
Selected_item = -1;
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -1038,10 +1042,10 @@ void control_config_scroll_line_up()
}
Selected_item = -1;
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -1055,10 +1059,10 @@ void control_config_scroll_screen_down()
}
Selected_item = -1;
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -1072,10 +1076,10 @@ void control_config_scroll_line_down()
}
Selected_item = -1;
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -1087,13 +1091,13 @@ void control_config_toggle_modifier(int bit)
Assert(!(z & JOY_AXIS));
k = Control_config[z].key_id;
if (k < 0) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return;
}
control_config_bind_key(z, k ^ bit);
control_config_conflict_check();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
}
void control_config_toggle_invert()
@@ -1114,7 +1118,7 @@ void control_config_do_bind()
game_flush();
// if ((Selected_line < 0) || (Cc_lines[Selected_line].cc_index & JOY_AXIS)) {
if (Selected_line < 0) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return;
}
@@ -1138,7 +1142,7 @@ void control_config_do_bind()
Search_mode = 0;
Last_key = -1;
Axis_override = -1;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
}
void control_config_do_search()
@@ -1162,7 +1166,7 @@ void control_config_do_search()
Binding_mode = 0;
Search_mode = 1;
Last_key = -1;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
}
void control_config_do_cancel(int fail = 0)
@@ -1185,9 +1189,9 @@ void control_config_do_cancel(int fail = 0)
Binding_mode = Search_mode = 0;
if (fail){
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
} else {
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
}
}
@@ -1202,13 +1206,13 @@ int control_config_accept()
}
if (i < NUM_TABS) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
return -1;
}
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
gamesnd_play_iface(SND_COMMIT_PRESSED);
return 0;
}
@@ -1233,7 +1237,7 @@ void control_config_button_pressed(int n)
Tab = n;
Scroll_offset = Selected_line = 0;
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
break;
case BIND_BUTTON:
@@ -1246,17 +1250,17 @@ void control_config_button_pressed(int n)
case SHIFT_TOGGLE:
control_config_toggle_modifier(KEY_SHIFTED);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
break;
case ALT_TOGGLE:
control_config_toggle_modifier(KEY_ALTED);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
break;
case INVERT_AXIS:
control_config_toggle_invert();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
break;
case SCROLL_UP_BUTTON:
@@ -1277,7 +1281,7 @@ void control_config_button_pressed(int n)
case HELP_BUTTON:
launch_context_help();
gamesnd_play_iface(InterfaceSounds::HELP_PRESSED);
gamesnd_play_iface(SND_HELP_PRESSED);
break;
case RESET_BUTTON:
@@ -1795,7 +1799,7 @@ void control_config_do_frame(float frametime)
Scroll_offset = Selected_line = 0;
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
break;
case KEY_TAB: // activate next tab
@@ -1806,7 +1810,7 @@ void control_config_do_frame(float frametime)
Scroll_offset = Selected_line = 0;
control_config_list_prepare();
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
break;
case KEY_LEFT:
@@ -1821,7 +1825,7 @@ void control_config_do_frame(float frametime)
}
}
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
break;
case KEY_RIGHT:
@@ -1833,7 +1837,7 @@ void control_config_do_frame(float frametime)
} else if (Selected_item > 1) {
Selected_item = -1;
}
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
break;
case KEY_BACKSP: // undo
@@ -1869,7 +1873,7 @@ void control_config_do_frame(float frametime)
Selected_item = 1;
}
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
gamesnd_play_iface(SND_USER_SELECT);
}
if (List_buttons[i].double_clicked()) {
@@ -1984,9 +1988,7 @@ void control_config_do_frame(float frametime)
gr_get_string_size(&w, NULL, str);
gr_printf_menu(x - w / 2, y - font_height, "%s", str);
if (Control_config[i].indexXSTR > 1) {
strcpy_s(buf, XSTR(Control_config[i].text, Control_config[i].indexXSTR));
} else if (Control_config[i].indexXSTR == 1) {
if (Control_config[i].hasXSTR) {
strcpy_s(buf, XSTR(Control_config[i].text, CONTROL_CONFIG_XSTR + i));
} else {
strcpy_s(buf, Control_config[i].text);
@@ -2191,6 +2193,17 @@ void control_config_do_frame(float frametime)
gr_flip();
}
void clear_key_binding(short key)
{
int i;
for (i=0; i<CCFG_MAX; i++) {
if (Control_config[i].key_id == key) {
Control_config[i].key_id = -1;
}
}
}
float check_control_timef(int id)
{
float t1, t2;
@@ -2304,7 +2317,7 @@ int check_control_used(int id, int key)
if ((Control_config[id].key_id == key) || joy_down_count(Control_config[id].joy_id, 1) ||
((Control_config[id].joy_id >= 0) && (Control_config[id].joy_id < MOUSE_NUM_BUTTONS) && mouse_down_count(1 << Control_config[id].joy_id))) {
//mprintf(("Key used %d\n", key));
//mprintf(("Key used %d", key));
control_used(id);
return 1;
}
@@ -2332,7 +2345,7 @@ int check_control(int id, int key)
// which has just been released
Script_system.SetHookVar("Action", 's', Control_config[id].text);
Script_system.RunCondition(CHA_ONACTIONSTOPPED, nullptr, id);
Script_system.RunCondition(CHA_ONACTIONSTOPPED, '\0', NULL, NULL, id);
Script_system.RemHookVar("Action");
Control_config[id].continuous_ongoing = false;
@@ -2366,7 +2379,7 @@ void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr)
*ta = 0;
if (Axis_map_to[3] >= 0) {
*ta = joy_get_unscaled_reading(axes_values[Axis_map_to[3]]);
*ta = joy_get_unscaled_reading(axes_values[Axis_map_to[3]], Axis_map_to[3]);
}
*tr = 0;
@@ -2406,7 +2419,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, id);
Script_system.RunCondition(CHA_ONACTION, '\0', NULL, NULL, id);
Script_system.RemHookVar("Action");
if (Control_config[id].type == CC_TYPE_CONTINUOUS)
@@ -2434,4 +2447,9 @@ void control_config_clear()
for (i=0; i<CCFG_MAX; i++) {
Control_config[i].key_id = Control_config[i].joy_id = -1;
}
}
}
int control_config_handle_conflict()
{
return 0;
}
+8 -10
View File
@@ -62,7 +62,7 @@ typedef struct config_item {
short key_default; //!< default key bound to action
short joy_default; //!< default joystick button bound to action
char tab; //!< what tab (category) it belongs in
int indexXSTR; //!< what string index we should use to translate this with an XSTR
bool hasXSTR; //!< whether we should translate this with an XSTR
const char *text; //!< describes the action in the config screen
char type; //!< manner control should be checked in
short key_id; //!< actual key bound to action
@@ -270,15 +270,6 @@ enum IoActionId {
//!< ----------------------------
CYCLE_PRIMARY_WEAPON_SEQUENCE =118, //!< cycle num primaries to fire at once
//!< @n
//!< Custom control slots
//!< ----------------------------
CUSTOM_CONTROL_1 = 119,
CUSTOM_CONTROL_2 = 120,
CUSTOM_CONTROL_3 = 121,
CUSTOM_CONTROL_4 = 122,
CUSTOM_CONTROL_5 = 123,
/*!
* This must always be below the last defined item
*/
@@ -286,6 +277,12 @@ enum IoActionId {
};
extern int Failed_key_index;
extern int Invert_heading;
extern int Invert_pitch;
extern int Invert_roll;
extern int Invert_thrust;
extern int Disable_axis2;
extern int Disable_axis3;
extern int Axis_map_to[];
extern int Invert_axis[];
@@ -339,6 +336,7 @@ int check_control(int id, int key = -1);
void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr);
void control_used(int id);
void control_config_clear();
void clear_key_binding(short key);
void control_check_indicate();
void control_config_clear_used_status();
+160 -156
View File
@@ -7,8 +7,8 @@
*
*/
#include <cstdio>
#include <cstdarg>
#include <stdio.h>
#include <stdarg.h>
#include "cfile/cfile.h"
#include "controlconfig/controlsconfig.h"
@@ -17,7 +17,6 @@
#include "io/joy.h"
#include "io/key.h"
#include "localization/localize.h"
#include "options/Option.h"
#include "parse/parselo.h"
// z64: These enumerations MUST equal to those in controlsconfig.cpp...
@@ -33,29 +32,15 @@ int Failed_key_index;
// Joystick configuration
int Joy_dead_zone_size = 10;
auto DeadZoneOption =
options::OptionBuilder<int>("Input.JoystickDeadZone", "Deadzone", "The deadzone of the selected joystick.")
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
int Joy_sensitivity = 9;
auto SensitivityOption =
options::OptionBuilder<int>("Input.JoystickSensitivity", "Sensitivity", "The sentitivity of the selected joystick.")
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
// assume control keys are used as modifiers until we find out
int Shift_is_modifier;
int Ctrl_is_modifier;
int Alt_is_modifier;
int Axis_enabled[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
int Axis_enabled_defaults[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
int Invert_axis[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
@@ -64,164 +49,159 @@ int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
//XSTR:OFF
config_item Control_config[CCFG_MAX + 1] = {
// targeting a ship
{ KEY_T, -1, TARGET_TAB, 1, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, 1, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_H, 2, TARGET_TAB, 1, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, 1, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, 1, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_F, -1, TARGET_TAB, 1, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, 1, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_Y, 4, TARGET_TAB, 1, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_G, -1, TARGET_TAB, 1, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, 1, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, 1, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// targeting a ship's subsystem
{ KEY_V, -1, TARGET_TAB, 1, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_S, -1, TARGET_TAB, 1, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, 1, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, 1, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// matching speed
{ KEY_M, -1, COMPUTER_TAB, 1, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, 1, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// weapons
{ KEY_LCTRL, 0, WEAPON_TAB, 1, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SPACEBAR, 1, WEAPON_TAB, 1, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PERIOD, -1, WEAPON_TAB, 1, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_COMMA, -1, WEAPON_TAB, 1, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_X, 3, WEAPON_TAB, 1, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// controls
{ KEY_A, -1, SHIP_TAB, 1, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_Z, -1, SHIP_TAB, 1, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD7, -1, SHIP_TAB, 1, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD9, -1, SHIP_TAB, 1, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD8, -1, SHIP_TAB, 1, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD2, -1, SHIP_TAB, 1, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD4, -1, SHIP_TAB, 1, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD6, -1, SHIP_TAB, 1, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
// throttle controls
{ KEY_BACKSP, -1, SHIP_TAB, 1, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SLASH, -1, SHIP_TAB, 1, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LBRACKET, -1, SHIP_TAB, 1, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_RBRACKET, -1, SHIP_TAB, 1, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_EQUAL, -1, SHIP_TAB, 1, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_MINUS, -1, SHIP_TAB, 1, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// squadmate messaging
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, 1, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, 1, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, 1, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, 1, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, 1, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, 1, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, 1, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, 1, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, 1, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, 1, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, 1, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, 1, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_R, 6, TARGET_TAB, 1, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// Views
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, 1, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADPERIOD, -1, COMPUTER_TAB, 1, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADENTER, -1, COMPUTER_TAB, 1, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAD0, -1, COMPUTER_TAB, 1, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, 1, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADPLUS, -1, COMPUTER_TAB, 1, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PADMINUS, -1, COMPUTER_TAB, 1, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD5, -1, COMPUTER_TAB, 1, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 33, COMPUTER_TAB, 1, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 32, COMPUTER_TAB, 1, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 34, COMPUTER_TAB, 1, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 35, COMPUTER_TAB, 1, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false }, // Not in use anymore (Swifty)
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, 1, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_C, -1, COMPUTER_TAB, 1, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, -1, 1, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, 1, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_J, -1, TARGET_TAB, 1, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_TAB, 5, SHIP_TAB, 1, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, -1, true, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_INSERT, -1, COMPUTER_TAB, 1, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DELETE, -1, COMPUTER_TAB, 1, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_HOME, -1, COMPUTER_TAB, 1, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_END, -1, COMPUTER_TAB, 1, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAGEUP, -1, COMPUTER_TAB, 1, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, 1, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, 1, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_Q, 7, COMPUTER_TAB, 1, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_UP, -1, COMPUTER_TAB, 1, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DOWN, -1, COMPUTER_TAB, 1, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LEFT, -1, COMPUTER_TAB, 1, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_RIGHT, -1, COMPUTER_TAB, 1, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, 1, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, 1, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// { -1, -1, -1, true, "Show Damage Popup Window" },
{ -1, -1, SHIP_TAB, 0, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
//Backslash -- this was a convenient place for Glide When Pressed, as Show Damage Popup isn't used
{ -1, -1, SHIP_TAB, 1, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, -1, -1, 1, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, 1, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, 1, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_E, -1, TARGET_TAB, 1, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, 1, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, -1, -1, true, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_U, -1, TARGET_TAB, 1, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, 1, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_N, -1, TARGET_TAB, 1, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_K, -1, TARGET_TAB, 1, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, 1, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_B, -1, TARGET_TAB, 1, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, 1, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// multiplayer messaging keys
{ KEY_1, -1, COMPUTER_TAB, 1, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_2, -1, COMPUTER_TAB, 1, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_3, -1, COMPUTER_TAB, 1, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_4, -1, COMPUTER_TAB, 1, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, 1, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, 1, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, 1, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_L, -1, COMPUTER_TAB, 1, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, 1, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, 1, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
// Misc
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, 1, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, 1, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, 1, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, 1, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, 1, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, 1, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, COMPUTER_TAB, 0, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, COMPUTER_TAB, 0, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false }, // (Swifty) Toggle for VM_TRACK
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, COMPUTER_TAB, false, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false }, // (Swifty) Toggle for VM_TRACK
// Auto Navigation Systen
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 0, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 0, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, 0, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_O, -1, WEAPON_TAB, 0, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 0, "Custom Control 1", CC_TYPE_TRIGGER, -1, -1, 0, true, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 0, "Custom Control 2", CC_TYPE_TRIGGER, -1, -1, 0, true, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 0, "Custom Control 3", CC_TYPE_TRIGGER, -1, -1, 0, true, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 0, "Custom Control 4", CC_TYPE_TRIGGER, -1, -1, 0, true, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 0, "Custom Control 5", CC_TYPE_TRIGGER, -1, -1, 0, true, false },
{ -1, -1, -1, 0, "", CC_TYPE_TRIGGER, -1, -1, 0, false, false }
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, -1, false, "", CC_TYPE_TRIGGER, -1, -1, 0, false, false }
};
const char *Scan_code_text_german[] = {
"", "Esc", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab", // NOLINT
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab",
"Q", "W", "E", "R", "T", "Z", "U", "I",
"O", "P", "\x9A", "+", "Eingabe", "Strg Links", "A", "S",
@@ -271,8 +251,8 @@ const char *Joy_button_text_german[] = {
};
const char *Scan_code_text_french[] = {
"", "\x90""chap", "1", "2", "3", "4", "5", "6", // NOLINT
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab", // NOLINT
"", "\x90""chap", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab",
"Q", "W", "E", "R", "T", "Y", "U", "I",
"O", "P", "[", "]", "Entr\x82""e", "Ctrl Gauche", "A", "S",
@@ -430,6 +410,31 @@ const char **Joy_button_text = Joy_button_text_english;
SCP_vector<config_item*> Control_config_presets;
SCP_vector<SCP_string> Control_config_preset_names;
void set_modifier_status()
{
int i;
Alt_is_modifier = 0;
Shift_is_modifier = 0;
Ctrl_is_modifier = 0;
for (i=0; i<CCFG_MAX; i++) {
if (Control_config[i].key_id < 0)
continue;
if (Control_config[i].key_id & KEY_ALTED)
Alt_is_modifier = 1;
if (Control_config[i].key_id & KEY_SHIFTED)
Shift_is_modifier = 1;
if (Control_config[i].key_id & KEY_CTRLED) {
Assert(0); // get Alan
Ctrl_is_modifier = 1;
}
}
}
// If find_override is set to true, then this returns the index of the action
// which has been bound to the given key. Otherwise, the index of the action
// which has the given key as its default key will be returned.
@@ -531,9 +536,7 @@ char *translate_key(char *key)
// both key and joystick button are mapped to this control
if ((key_code >= 0 ) && (joy_code >= 0) ) {
strcpy_s(text, key_text);
strcat_s(text, " ");
strcat_s(text, XSTR("or", 1638));
strcat_s(text, " ");
strcat_s(text, " or ");
strcat_s(text, joy_text);
}
// if we only have one
@@ -613,6 +616,7 @@ void control_config_common_load_overrides();
void control_config_common_init()
{
for (int i=0; i<CCFG_MAX; i++) {
Control_config[i].disabled = false;
Control_config[i].continuous_ongoing = false;
}
@@ -869,7 +873,7 @@ void control_config_common_load_overrides()
* short key_default;
* short joy_default;
* char tab;
* int indexXSTR;
* bool hasXSTR;
* char type;
*/
@@ -911,7 +915,7 @@ void control_config_common_load_overrides()
if (optional_string("$Has XStr:")) {
stuff_int(&iTemp);
r_ccConfig.indexXSTR = iTemp;
r_ccConfig.hasXSTR = (iTemp == 1);
}
if (optional_string("$Type:")) {
+11 -6
View File
@@ -3,12 +3,6 @@
#include <memory>
namespace cutscene {
FrameSize::FrameSize(size_t in_width, size_t in_height, size_t in_stride)
: width(in_width), height(in_height), stride(in_stride)
{
}
FrameSize::FrameSize() = default;
Decoder::Decoder() : m_decoding(true) {
}
@@ -46,6 +40,10 @@ void Decoder::stopDecoder() {
m_subtitleQueue->close();
}
bool Decoder::canPushAudioData() {
return !isAudioQueueFull();
}
void Decoder::pushAudioData(AudioFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
@@ -57,6 +55,9 @@ void Decoder::pushAudioData(AudioFramePtr&& data) {
}
}
bool Decoder::canPushSubtitleData() {
return !isSubtitleQueueFull();
}
void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
@@ -68,6 +69,10 @@ void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
}
}
bool Decoder::canPushVideoData() {
return !isVideoQueueFull();
}
void Decoder::pushFrameData(VideoFramePtr&& frame) {
Assertion(frame, "Invalid video data passed!");
+25 -27
View File
@@ -10,26 +10,28 @@ struct FrameSize {
size_t width = 0;
size_t height = 0;
size_t stride = 0;
FrameSize();
FrameSize(size_t width, size_t in_height, size_t in_stride);
};
class VideoFrame {
protected:
VideoFrame() = default;
VideoFrame() {}
public:
virtual ~VideoFrame() = default;
public:
virtual ~VideoFrame() {}
double frameTime = -1.0;
int id = -1;
virtual size_t getPlaneNumber() = 0;
FrameSize ySize;
FrameSize uvSize;
virtual FrameSize getPlaneSize(size_t plane) = 0;
struct DataPointers {
ubyte* y;
ubyte* u;
ubyte* v;
};
virtual void* getPlaneData(size_t plane) = 0;
virtual DataPointers getDataPointers() = 0;
};
/**
@@ -41,19 +43,10 @@ using FramePtr = std::unique_ptr<T>;
typedef std::unique_ptr<VideoFrame> VideoFramePtr;
enum class FramePixelFormat {
Invalid,
YUV420,
BGR,
BGRA
};
struct MovieProperties {
FrameSize size;
float fps = -1.0f;
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
};
struct AudioFrame {
@@ -73,11 +66,6 @@ struct SubtitleFrame {
};
typedef std::unique_ptr<SubtitleFrame> SubtitleFramePtr;
struct PlaybackProperties {
bool with_audio = true;
bool looping = false;
};
/**
* @brief Abstract class for decoding a video or audio stream
*
@@ -111,13 +99,13 @@ class Decoder {
* @param fileName The name of the file that should be opened
* @return @c true if the initialization was successfull, @c false otherwise
*/
virtual bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) = 0;
virtual bool initialize(const SCP_string& fileName) = 0;
/**
* @brief Returns the properties of the video
* @return The properties
*/
virtual MovieProperties getProperties() const = 0;
virtual MovieProperties getProperties() = 0;
/**
* @brief Starts decoding the video
@@ -128,9 +116,9 @@ class Decoder {
* @brief Determines if the video has audio
* @return @c true if audio is included in the video
*/
virtual bool hasAudio() const = 0;
virtual bool hasAudio() = 0;
virtual bool hasSubtitles() const = 0;
virtual bool hasSubtitles() = 0;
/**
* @brief Ends decoding of the video file
@@ -147,6 +135,10 @@ class Decoder {
bool isSubtitleQueueFull() { return m_subtitleQueue->size() == m_queueSize; }
bool isSubtitleFrameAvailable() { return !m_subtitleQueue->empty(); }
size_t getSubtitleQueueSize() { return m_subtitleQueue->size(); }
bool tryPopSubtitleData(SubtitleFramePtr&);
bool isVideoQueueFull() { return m_videoQueue->size() == m_queueSize; }
@@ -164,10 +156,16 @@ class Decoder {
protected:
void initializeQueues(size_t queueSize);
bool canPushAudioData();
void pushAudioData(AudioFramePtr&& data);
bool canPushSubtitleData();
void pushSubtitleData(SubtitleFramePtr&& data);
bool canPushVideoData();
void pushFrameData(VideoFramePtr&& frame);
};
}
+24 -67
View File
@@ -14,85 +14,46 @@ struct movie_vertex {
namespace cutscene {
namespace player {
VideoPresenter::VideoPresenter(const MovieProperties& props) : _properties(props)
{
VideoPresenter::VideoPresenter(const MovieProperties& props) {
GR_DEBUG_SCOPE("Init video");
_planeTextureHandles.fill(-1);
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
switch (props.pixelFormat) {
case FramePixelFormat::YUV420:
_planeTextureBuffers[0].reset(new uint8_t[w * h]);
_planeTextureHandles[0] = bm_create(8, w, h, _planeTextureBuffers[0].get(), BMP_AABITMAP);
// Create buffer textures
_yTexBuffer.reset(new uint8_t[w * h]);
_ytex = bm_create(8, w, h, _yTexBuffer.get(), BMP_AABITMAP);
_planeTextureBuffers[1].reset(new uint8_t[w / 2 * h / 2]);
_planeTextureHandles[1] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[1].get(), BMP_AABITMAP);
_uTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_utex = bm_create(8, w / 2, h / 2, _uTexBuffer.get(), BMP_AABITMAP);
_planeTextureBuffers[2].reset(new uint8_t[w / 2 * h / 2]);
_planeTextureHandles[2] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[2].get(), BMP_AABITMAP);
_vTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_vtex = bm_create(8, w / 2, h / 2, _vTexBuffer.get(), BMP_AABITMAP);
material_set_movie(&_movie_material, _planeTextureHandles[0], _planeTextureHandles[1], _planeTextureHandles[2]);
break;
case FramePixelFormat::BGR:
_planeTextureBuffers[0].reset(new uint8_t[w * h * 3]);
_planeTextureHandles[0] = bm_create(24, w, h, _planeTextureBuffers[0].get(), 0);
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, false, false);
break;
case FramePixelFormat::BGRA:
_planeTextureBuffers[0].reset(new uint8_t[w * h * 4]);
_planeTextureHandles[0] = bm_create(32, w, h, _planeTextureBuffers[0].get(), 0);
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, true, false);
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
material_set_movie(&_render_material, _ytex, _utex, _vtex);
}
VideoPresenter::~VideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
for (auto& handle : _planeTextureHandles) {
if (handle > 0) {
bm_release(handle);
handle = -1;
}
}
bm_release(_ytex);
bm_release(_utex);
bm_release(_vtex);
_ytex = _utex = _vtex = -1;
}
void VideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
for (size_t i = 0; i < frame->getPlaneNumber(); ++i) {
auto size = frame->getPlaneSize(i);
auto data = frame->getPlaneData(i);
memcpy(_yTexBuffer.get(), ptrs.y, frame->ySize.stride * frame->ySize.height);
memcpy(_uTexBuffer.get(), ptrs.u, frame->uvSize.stride * frame->uvSize.height);
memcpy(_vTexBuffer.get(), ptrs.v, frame->uvSize.stride * frame->uvSize.height);
memcpy(_planeTextureBuffers[i].get(), data, size.stride * size.height);
int bpp = 0;
switch (_properties.pixelFormat) {
case FramePixelFormat::YUV420:
bpp = 8;
break;
case FramePixelFormat::BGR:
bpp = 24;
break;
case FramePixelFormat::BGRA:
bpp = 32;
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
gr_update_texture(_planeTextureHandles[i], bpp, _planeTextureBuffers[i].get(), static_cast<int>(size.width),
static_cast<int>(size.height));
}
gr_update_texture(_ytex, 8, _yTexBuffer.get(), (int) frame->ySize.width, (int) frame->ySize.height);
gr_update_texture(_utex, 8, _uTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
gr_update_texture(_vtex, 8, _vTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
}
void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
@@ -124,14 +85,10 @@ void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
auto offset = gr_add_to_immediate_buffer(sizeof(vertex_data), vertex_data);
vertex_layout layout;
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offsetof(movie_vertex, uv));
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, uv));
if (_properties.pixelFormat == FramePixelFormat::YUV420) {
gr_render_movie(&_movie_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle, offset);
} else {
gr_render_primitives(&_rgb_material, PRIM_TYPE_TRISTRIP, &layout, 0, 4, gr_immediate_buffer_handle, offset);
}
gr_render_movie(&_render_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle);
}
}
+8 -5
View File
@@ -12,13 +12,16 @@ namespace cutscene {
namespace player {
class VideoPresenter {
MovieProperties _properties;
int _ytex = -1;
std::unique_ptr<uint8_t[]> _yTexBuffer;
std::array<int, 3> _planeTextureHandles;
std::array<std::unique_ptr<uint8_t[]>, 3> _planeTextureBuffers;
int _utex = -1;
std::unique_ptr<uint8_t[]> _uTexBuffer;
movie_material _movie_material;
material _rgb_material; // Material used when a RGB/RGBA movie is played
int _vtex = -1;
std::unique_ptr<uint8_t[]> _vTexBuffer;
movie_material _render_material;
public:
explicit VideoPresenter(const MovieProperties& props);
+21 -30
View File
@@ -83,33 +83,24 @@ void cutscene_init()
if (optional_string("$cd:"))
{
// CD option isn't needed anymore. Consume the token and ignore it
// Option isn't needed anymore. Consume the token and ignore it
int junk;
stuff_int(&junk);
}
cutinfo.flags.reset();
cutinfo.viewable = false;
if (isFirstCutscene)
{
isFirstCutscene = false;
// The original code assumes the first movie is the intro, so make it viewable
cutinfo.flags.set(Cutscene::Cutscene_Flags::Viewable);
// The original code assumes the first movie is the intro, so always viewable
cutinfo.viewable = true;
}
if (optional_string("$Always Viewable:"))
{
bool flag;
stuff_boolean(&flag);
if (flag)
cutinfo.flags.set(Cutscene::Cutscene_Flags::Always_viewable);
}
if (optional_string("$Never Viewable:"))
{
bool flag;
stuff_boolean(&flag);
if (flag)
cutinfo.flags.set(Cutscene::Cutscene_Flags::Never_viewable);
stuff_boolean(&cutinfo.viewable);
}
Cutscenes.push_back(cutinfo);
@@ -152,7 +143,7 @@ void cutscene_mark_viewable(const char* filename)
// see if the stripped filename matches the cutscene filename
if (strstr(cut_file, file) != NULL)
{
cut->flags.set(Cutscene::Cutscene_Flags::Viewable);
cut->viewable = true;
return;
}
i++;
@@ -295,10 +286,10 @@ void cutscenes_screen_scroll_line_up()
if (Selected_line)
{
Selected_line--;
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
if (Selected_line < Scroll_offset)
Scroll_offset = Selected_line;
@@ -311,10 +302,10 @@ void cutscenes_screen_scroll_line_down()
if (Selected_line < (int) Cutscene_list.size() - 1)
{
Selected_line++;
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
if (Selected_line >= Scroll_offset + h)
@@ -337,11 +328,11 @@ void cutscenes_screen_scroll_screen_up()
Selected_line--;
}
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else
{
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -358,10 +349,10 @@ void cutscenes_screen_scroll_screen_down()
Selected_line = Scroll_offset;
}
gamesnd_play_iface(InterfaceSounds::SCROLL);
gamesnd_play_iface(SND_SCROLL);
} else
{
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -370,17 +361,17 @@ int cutscenes_screen_button_pressed(int n)
switch (n)
{
case TECH_DATABASE_BUTTON:
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
gamesnd_play_iface(SND_SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_TECH_MENU);
return 1;
case SIMULATOR_BUTTON:
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
gamesnd_play_iface(SND_SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
return 1;
case CREDITS_BUTTON:
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
gamesnd_play_iface(SND_SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_CREDITS);
return 1;
@@ -397,7 +388,7 @@ int cutscenes_screen_button_pressed(int n)
break;
case EXIT_BUTTON:
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
gamesnd_play_iface(SND_COMMIT_PRESSED);
gameseq_post_event(GS_EVENT_MAIN_MENU);
game_flush();
break;
@@ -450,9 +441,9 @@ void cutscenes_screen_init()
Cutscene_list.clear();
int u = 0;
for (auto cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, ++u)
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, u++)
{
if (cut->flags[Cutscene::Cutscene_Flags::Viewable, Cutscene::Cutscene_Flags::Always_viewable] && !cut->flags[Cutscene::Cutscene_Flags::Never_viewable])
if ((*cut).viewable)
{
Cutscene_list.push_back(u);
}
+9 -14
View File
@@ -10,31 +10,26 @@
#ifndef _FREESPACE_CUTSCENES_SCREEN_HEADER_FILE
#define _FREESPACE_CUTSCENES_SCREEN_HEADER_FILE
#include "globalincs/flagset.h"
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
namespace Cutscene
{
FLAG_LIST(Cutscene_Flags)
{
Viewable = 0,
Always_viewable,
Never_viewable,
NUM_VALUES
};
}
typedef struct cutscene_info
{
char filename[MAX_FILENAME_LEN];
char name[NAME_LENGTH];
char* description;
flagset<Cutscene::Cutscene_Flags> flags;
bool viewable;
} cutscene_info;
#if SCP_COMPILER_IS_GNU
#pragma GCC diagnostic push
// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable
#pragma GCC diagnostic ignored "-Wshadow"
#endif
extern SCP_vector<cutscene_info> Cutscenes;
#if SCP_COMPILER_IS_GNU
#pragma GCC diagnostic pop
#endif
// initializa table data
void cutscene_init();
+1 -7
View File
@@ -55,9 +55,6 @@ int resample_convert(SwrContext* ctx, uint8_t** output,
#ifdef WITH_LIBAV
return avresample_convert(ctx, output, out_plane_size, out_samples, input, in_plane_size, in_samples);
#else
(void)out_plane_size;
(void)in_plane_size;
return swr_convert(ctx, output, out_samples, (const uint8_t**) input, in_samples);
#endif
}
@@ -126,7 +123,7 @@ void AudioDecoder::handleDecodedFrame(AVFrame* frame) {
auto ret = av_samples_alloc(m_outData, &m_outLinesize, OUT_NUM_CHANNELS, m_outNumSamples,
OUT_SAMPLE_FORMAT, 1);
if (ret < 0) {
mprintf(("FFMPEG: Failed to allocate samples!!!\n"));
mprintf(("FFMPEG: Failed to allocate samples!!!"));
return;
}
@@ -223,8 +220,5 @@ void AudioDecoder::finishDecoding() {
// Push the last bits of audio data into the queue
flushAudioBuffer();
}
void AudioDecoder::flushBuffers() {
avcodec_flush_buffers(m_status->audioCodecCtx);
}
}
}
+3 -5
View File
@@ -25,13 +25,11 @@ class AudioDecoder: public FFMPEGStreamDecoder<AudioFrame> {
public:
explicit AudioDecoder(DecoderStatus* status);
~AudioDecoder() override;
virtual ~AudioDecoder();
void decodePacket(AVPacket* packet) override;
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
void finishDecoding() override;
void flushBuffers() override;
virtual void finishDecoding() SCP_OVERRIDE;
};
}
}
+145 -374
View File
@@ -11,7 +11,6 @@
#include "cutscene/ffmpeg/VideoDecoder.h"
#include "cutscene/ffmpeg/SubtitleDecoder.h"
#include "FFMPEGDecoder.h"
#include "localization/localize.h"
using namespace libs::ffmpeg;
@@ -28,26 +27,20 @@ class AVPacketScope
: _packet(av_packet) {
}
AVPacketScope(const AVPacketScope&) = delete;
AVPacketScope& operator=(const AVPacketScope&) = delete;
~AVPacketScope() {
av_packet_unref(_packet);
}
};
const char* CHECKED_EXTENSIONS[] = {"webm", "mp4", "ogg",
"png", // This is designed to be used with APNG animations
"mve"};
const char* CHECKED_SUBT_EXTENSIONS[] = {"srt"};
const char* CHECKED_EXTENSIONS[] = {
"webm",
"mp4",
"ogg",
"mve"
};
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
auto fps = av_q2d(stream->r_frame_rate);
#else
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
#endif
if (fps < 0.000001)
{
@@ -65,111 +58,45 @@ double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
CodecContextParameters getCodecParameters(AVStream* stream) {
CodecContextParameters paras;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
paras.width = stream->codecpar->width;
paras.height = stream->codecpar->height;
paras.width = stream->codecpar->width;
paras.height = stream->codecpar->height;
paras.pixel_format = (AVPixelFormat)stream->codecpar->format;
paras.channel_layout = stream->codecpar->channel_layout;
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
paras.codec_id = stream->codecpar->codec_id;
paras.codec_id = stream->codecpar->codec_id;
#else
paras.width = stream->codec->width;
paras.height = stream->codec->height;
paras.width = stream->codec->width;
paras.height = stream->codec->height;
paras.pixel_format = stream->codec->pix_fmt;
paras.channel_layout = stream->codec->channel_layout;
paras.sample_rate = stream->codec->sample_rate;
paras.audio_format = stream->codec->sample_fmt;
paras.sample_rate = stream->codec->sample_rate;
paras.audio_format = stream->codec->sample_fmt;
paras.codec_id = stream->codec->codec_id;
paras.codec_id = stream->codec->codec_id;
#endif
return paras;
return paras;
}
SCP_string normalizeLanguage(const char* langauge_name) {
if (!stricmp(langauge_name, "eng")) {
return "English";
}
if (!stricmp(langauge_name, "ger")) {
return "German";
}
if (!stricmp(langauge_name, "spa")) {
return "Spanish";
}
if (!stricmp(langauge_name, "eng")) {
return "English";
}
if (!stricmp(langauge_name, "ger")) {
return "German";
}
if (!stricmp(langauge_name, "spa")) {
return "Spanish";
}
// Print to log so that we can find the actual value more easily later
mprintf(("FFmpeg log: Found unknown language value '%s'!\n", langauge_name));
// Print to log so that we can find the actual value more easily later
mprintf(("FFmpeg log: Found unknown language value '%s'!\n", langauge_name));
// Default to english for everything else
return "English";
}
/**
* @brief Given a FFmpeg pixel format returns the format it should be converted to
* @param in_fmt The input format
* @return The output format
*/
AVPixelFormat getConversionFormat(AVPixelFormat in_fmt)
{
switch (in_fmt) {
case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_BGR24:
case AV_PIX_FMT_BGR8:
case AV_PIX_FMT_BGR4:
case AV_PIX_FMT_BGR4_BYTE:
case AV_PIX_FMT_RGB8:
case AV_PIX_FMT_RGB4:
case AV_PIX_FMT_RGB4_BYTE:
case AV_PIX_FMT_RGB48BE:
case AV_PIX_FMT_RGB48LE:
case AV_PIX_FMT_RGB565BE:
case AV_PIX_FMT_RGB565LE:
case AV_PIX_FMT_RGB555BE:
case AV_PIX_FMT_RGB555LE:
case AV_PIX_FMT_BGR565BE:
case AV_PIX_FMT_BGR565LE:
case AV_PIX_FMT_BGR555BE:
case AV_PIX_FMT_BGR555LE:
case AV_PIX_FMT_RGB444LE:
case AV_PIX_FMT_RGB444BE:
case AV_PIX_FMT_BGR444LE:
case AV_PIX_FMT_BGR444BE:
case AV_PIX_FMT_BGR48BE:
case AV_PIX_FMT_BGR48LE:
case AV_PIX_FMT_0RGB:
case AV_PIX_FMT_RGB0:
case AV_PIX_FMT_0BGR:
case AV_PIX_FMT_BGR0:
return AV_PIX_FMT_BGR24;
case AV_PIX_FMT_RGBA64BE:
case AV_PIX_FMT_RGBA64LE:
case AV_PIX_FMT_BGRA64BE:
case AV_PIX_FMT_BGRA64LE:
case AV_PIX_FMT_ARGB:
case AV_PIX_FMT_RGBA:
case AV_PIX_FMT_ABGR:
case AV_PIX_FMT_BGRA:
return AV_PIX_FMT_BGRA;
default:
// Assume that everything else is converted to YUV 420
return AV_PIX_FMT_YUV420P;
}
}
FramePixelFormat getPixelFormat(AVPixelFormat fmt)
{
switch (fmt) {
case AV_PIX_FMT_BGR24:
return FramePixelFormat::BGR;
case AV_PIX_FMT_BGRA:
return FramePixelFormat::BGRA;
default:
return FramePixelFormat::YUV420;
}
// Default to english for everything else
return "English";
}
}
@@ -216,15 +143,7 @@ std::unique_ptr<InputStream> openStream(const SCP_string& name) {
return input;
}
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream,
std::unique_ptr<InputStream>& subt,
const PlaybackProperties& properties)
{
if (subt && properties.looping) {
mprintf(("FFmpeg: External subtitles and looping movies are not supported!\n"));
return nullptr;
}
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream) {
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
auto ctx = stream->m_ctx->ctx();
@@ -242,18 +161,14 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
return nullptr;
}
int audioStream = -1;
if (properties.with_audio) {
audioStream = av_find_best_stream(ctx, AVMEDIA_TYPE_AUDIO, -1, videoStream, &status->audioCodec, 0);
if (audioStream < 0) {
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No audio stream found in file!\n"));
} else if (audioStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
}
auto audioStream = av_find_best_stream(ctx, AVMEDIA_TYPE_AUDIO, -1, videoStream, &status->audioCodec, 0);
if (audioStream < 0) {
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No audio stream found in file!\n"));
} else if (videoStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
}
}
@@ -265,60 +180,31 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
status->audioStream = ctx->streams[audioStream];
}
if (subt) {
auto subtCtx = subt->m_ctx->ctx();
auto& current_language = Lcl_languages[Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
auto subtStream = av_find_best_stream(subtCtx, AVMEDIA_TYPE_SUBTITLE, -1, -1, nullptr, 0);
if (subtStream < 0) {
if (subtStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No subtitle stream found in subtitle file!\n"));
} else if (subtStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for subtitle stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding subtitle stream!\n"));
}
} else {
status->subtitleStream = subtCtx->streams[subtStream];
status->externalSubtitles = true;
status->subtitleStreamIndex = subtStream;
auto& pars = test_stream->codecpar;
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
continue;
}
AVDictionaryEntry* tag = nullptr;
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
continue;
}
}
if (status->subtitleStream == nullptr) {
// We don't have an external subtitle stream or loading from that file has failed
auto& current_language = Lcl_languages[Lcl_current_lang == LCL_UNTRANSLATED ? LCL_DEFAULT : Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
auto normalized_language = normalizeLanguage(tag->value);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
auto& pars = test_stream->codecpar;
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
continue;
}
#endif
AVDictionaryEntry* tag = nullptr;
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
continue;
}
auto normalized_language = normalizeLanguage(tag->value);
if (!stricmp(normalized_language.c_str(), current_language.lang_name)) {
status->subtitleStreamIndex = i;
status->subtitleStream = test_stream;
break;
}
if (!stricmp(normalized_language.c_str(), current_language.lang_name)) {
status->subtitleStreamIndex = i;
status->subtitleStream = test_stream;
break;
}
}
status->videoCodecPars = getCodecParameters(status->videoStream);
if (properties.looping && status->videoCodecPars.codec_id == AV_CODEC_ID_INTERPLAY_VIDEO) {
mprintf(("FFmpeg: Looping is not supported for inteplay (MVE) movies!\n"));
return nullptr;
}
int err;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
status->videoCodecCtx = avcodec_alloc_context3(status->videoCodec);
@@ -375,37 +261,36 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
status->audioCodec->name ? status->audioCodec->name : "<Unknown>"));
}
if (status->subtitleStream != nullptr) {
// Not really sure if this makes sense for subtitles but it shouldn't break anything...
status->subtitleCodecPars = getCodecParameters(status->subtitleStream);
if (status->subtitleStreamIndex >= 0) {
// Not really sure if this makes sense for subtitles but it shouldn't break anything...
status->subtitleCodecPars = getCodecParameters(status->subtitleStream);
status->subtitleCodec = avcodec_find_decoder(status->subtitleCodecPars.codec_id);
status->subtitleCodec = avcodec_find_decoder(status->subtitleCodecPars.codec_id);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
status->subtitleCodecCtx = avcodec_alloc_context3(status->subtitleCodec);
status->subtitleCodecCtx = avcodec_alloc_context3(status->subtitleCodec);
err = avcodec_parameters_to_context(status->subtitleCodecCtx, status->subtitleStream->codecpar);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
return nullptr;
}
err = avcodec_parameters_to_context(status->subtitleCodecCtx, status->subtitleStream->codecpar);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
return nullptr;
}
#else
status->subtitleCodecCtx = status->subtitleStream->codec;
status->subtitleCodecCtx = status->subtitleStream->codec;
#endif
err = avcodec_open2(status->subtitleCodecCtx, status->subtitleCodec, nullptr);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to open subtitle codec! Error: %s\n", errorStr));
}
err = avcodec_open2(status->subtitleCodecCtx, status->subtitleCodec, nullptr);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to open subtitle codec! Error: %s\n", errorStr));
}
mprintf(("FFmpeg: Using subtitle codec %s (%s).\n",
status->subtitleCodec->long_name ? status->subtitleCodec->long_name : "<Unknown>",
status->subtitleCodec->name ? status->subtitleCodec->name : "<Unknown>"));
}
mprintf(("FFmpeg: Using subtitle codec %s (%s).\n", status->subtitleCodec->long_name ? status->subtitleCodec->long_name : "<Unknown>",
status->subtitleCodec->name ? status->subtitleCodec->name : "<Unknown>"));
}
return status;
}
@@ -425,35 +310,12 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
return nullptr;
}
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string& name)
{
auto& current_language = Lcl_languages[Lcl_current_lang == LCL_UNTRANSLATED ? LCL_DEFAULT : Lcl_current_lang];
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
SCP_string fileName;
if (strlen(current_language.lang_ext) == 0) {
fileName = name + "." + ext;
} else {
fileName = name + "-" + current_language.lang_ext + "." + ext;
}
auto input = openStream(fileName);
if (input) {
return input;
}
}
return nullptr;
}
}
bool FFMPEGDecoder::initialize(const SCP_string& fileName, const PlaybackProperties& properties)
{
bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
SCP_string movieName = fileName;
// First make the file name lower case
std::transform(movieName.begin(), movieName.end(), movieName.begin(), [](char c) { return (char)::tolower(c); });
std::transform(movieName.begin(), movieName.end(), movieName.begin(), ::tolower);
// Then remove the extension
size_t dotPos = movieName.find('.');
@@ -467,10 +329,8 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName, const PlaybackPropert
return false;
}
auto subt = openSubtitleStream(movieName);
// We now have a valid input stream, try to find the correct streams
auto status = initializeStatus(input, subt, properties);
auto status = initializeStatus(input);
if (!status) {
return false;
}
@@ -480,178 +340,46 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName, const PlaybackPropert
// We're done, now just put the pointer into this
std::swap(m_input, input);
std::swap(m_subtitleInput, subt);
std::swap(m_status, status);
m_properties = properties;
return true;
}
MovieProperties FFMPEGDecoder::getProperties() const
{
MovieProperties FFMPEGDecoder::getProperties() {
MovieProperties props;
props.size.width = static_cast<size_t>(m_status->videoCodecPars.width);
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
return props;
}
void FFMPEGDecoder::startDecoding() {
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get(), getConversionFormat(m_status->videoCodecPars.pixel_format)));
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
std::unique_ptr<AudioDecoder> audioDecoder;
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
if (hasAudio()) {
audioDecoder.reset(new AudioDecoder(m_status.get()));
}
if (hasSubtitles()) {
subtitleDecoder.reset(new SubtitleDecoder(m_status.get()));
}
std::unique_ptr<std::thread> subtitle_thread;
if (hasExternalSubtitle()) {
// Start a new thread for the subtitles since otherwise we would need to make sure that neither of the input
// streames starves while the other waits for more space in the queues
subtitle_thread.reset(
new std::thread([this, &subtitleDecoder]() { runSubtitleDecoder(subtitleDecoder.get()); }));
}
if (hasSubtitles()) {
subtitleDecoder.reset(new SubtitleDecoder(m_status.get()));
}
auto ctx = m_input->m_ctx->ctx();
AVPacket packet;
do {
if (m_properties.looping) {
// Only seek if we are looping the movie. The MVE code doesn't support seeking to this function may not be
// called there
auto seek_err = av_seek_frame(ctx, -1, 0, AVSEEK_FLAG_BACKWARD);
if (seek_err < 0) {
char errorStr[512];
av_strerror(seek_err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to seek to start of movie file! Error: %s\n", errorStr));
break;
}
}
videoDecoder->flushBuffers();
if (audioDecoder) {
audioDecoder->flushBuffers();
}
if (subtitleDecoder) {
subtitleDecoder->flushBuffers();
}
while (isDecoding()) {
auto read_err = av_read_frame(ctx, &packet);
AVPacketScope scope(&packet);
if (read_err < 0) {
if (read_err == AVERROR_EOF) {
// Finished reading -> break out of loop
break;
} else if (avio_feof(ctx->pb) != 0) {
// Also EOF!
break;
} else {
// Some kind of other error, try to continue reading
char errorStr[512];
av_strerror(read_err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to read frame! Error: %s\n", errorStr));
// Skip packet
continue;
}
}
if (packet.stream_index == m_status->videoStreamIndex) {
videoDecoder->decodePacket(&packet);
VideoFramePtr ptr;
while ((ptr = videoDecoder->getFrame()) != nullptr) {
pushFrameData(std::move(ptr));
}
} else if (audioDecoder && packet.stream_index == m_status->audioStreamIndex) {
audioDecoder->decodePacket(&packet);
AudioFramePtr ptr;
while ((ptr = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(ptr));
}
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
subtitleDecoder->decodePacket(&packet);
SubtitleFramePtr ptr;
while ((ptr = subtitleDecoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
}
}
if (isDecoding()) {
// If we are still alive then read the last frames from the decoders
videoDecoder->finishDecoding();
VideoFramePtr video_ptr;
while ((video_ptr = videoDecoder->getFrame()) != nullptr) {
pushFrameData(std::move(video_ptr));
}
if (audioDecoder) {
audioDecoder->finishDecoding();
AudioFramePtr audio_frame;
while ((audio_frame = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(audio_frame));
}
}
}
// If the video is being looped then we start again from the beginning
} while (m_properties.looping && isDecoding());
// Stop the decoder first to let the subtitle thread know that it shouldn't continue
stopDecoder();
if (subtitle_thread) {
subtitle_thread->join();
}
}
bool FFMPEGDecoder::hasAudio() const { return m_status->audioStreamIndex >= 0; }
bool FFMPEGDecoder::hasSubtitles() const { return m_status->subtitleStream != nullptr; }
bool FFMPEGDecoder::hasExternalSubtitle() const { return m_status->externalSubtitles; }
void FFMPEGDecoder::close() {
if (m_status) {
m_status = nullptr;
}
if (m_input) {
// This will delete the InputStream pointer and free all data
m_input = nullptr;
}
if (m_subtitleInput) {
m_subtitleInput = nullptr;
}
}
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder* decoder)
{
auto ctx = m_subtitleInput->m_ctx->ctx();
AVPacket packet;
while (isDecoding()) {
auto read_err = av_read_frame(ctx, &packet);
AVPacketScope scope(&packet);
if (read_err < 0) {
if (avio_feof(ctx->pb) != 0) {
// EOF!!
break;
} else if (read_err < 0) {
if (read_err == AVERROR_EOF) {
// Finished reading -> break out of loop
break;
} else if (avio_feof(ctx->pb) != 0) {
// Also EOF!
break;
} else {
// Some kind of other error, try to continue reading
char errorStr[512];
@@ -663,23 +391,66 @@ void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder* decoder)
}
}
if (packet.stream_index == m_status->subtitleStreamIndex) {
decoder->decodePacket(&packet);
if (packet.stream_index == m_status->videoStreamIndex) {
videoDecoder->decodePacket(&packet);
SubtitleFramePtr ptr;
while ((ptr = decoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
VideoFramePtr ptr;
while((ptr = videoDecoder->getFrame()) != nullptr) {
pushFrameData(std::move(ptr));
}
} else if (audioDecoder && packet.stream_index == m_status->audioStreamIndex) {
audioDecoder->decodePacket(&packet);
AudioFramePtr ptr;
while ((ptr = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(ptr));
}
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
subtitleDecoder->decodePacket(&packet);
SubtitleFramePtr ptr;
while((ptr = subtitleDecoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
}
}
if (isDecoding()) {
// If we are still alive then read the last frames from the decoders
videoDecoder->finishDecoding();
VideoFramePtr video_ptr;
while ((video_ptr = videoDecoder->getFrame()) != nullptr) {
pushFrameData(std::move(video_ptr));
}
if (audioDecoder) {
audioDecoder->finishDecoding();
AudioFramePtr audio_frame;
while ((audio_frame = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(audio_frame));
}
}
}
if (isDecoding()) {
// If we are still alive then read the last frames from the decoders
decoder->finishDecoding();
SubtitleFramePtr ptr;
while ((ptr = decoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
stopDecoder();
}
bool FFMPEGDecoder::hasAudio() {
return m_status->audioStreamIndex >= 0;
}
bool FFMPEGDecoder::hasSubtitles() {
return m_status->subtitleStreamIndex >= 0;
}
void FFMPEGDecoder::close() {
if (m_status) {
m_status = nullptr;
}
if (m_input) {
// This will delete the InputStream pointer and free all data
m_input = nullptr;
}
}
}
+8 -18
View File
@@ -8,38 +8,28 @@ struct InputStream;
struct DecoderStatus;
class SubtitleDecoder;
class FFMPEGDecoder: public Decoder {
private:
std::unique_ptr<InputStream> m_input;
std::unique_ptr<InputStream> m_subtitleInput;
std::unique_ptr<DecoderStatus> m_status;
PlaybackProperties m_properties;
bool hasExternalSubtitle() const;
void runSubtitleDecoder(SubtitleDecoder* decoder);
public:
public:
FFMPEGDecoder();
~FFMPEGDecoder() override;
virtual ~FFMPEGDecoder();
bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) override;
bool initialize(const SCP_string& fileName) SCP_OVERRIDE;
MovieProperties getProperties() const override;
MovieProperties getProperties() SCP_OVERRIDE;
void startDecoding() override;
void startDecoding() SCP_OVERRIDE;
bool hasAudio() const override;
bool hasAudio() SCP_OVERRIDE;
bool hasSubtitles() const override;
bool hasSubtitles() SCP_OVERRIDE;
void close() override;
void close() SCP_OVERRIDE;
};
}
}
-21
View File
@@ -31,25 +31,7 @@ void SubtitleDecoder::decodePacket(AVPacket* packet) {
}
}
void SubtitleDecoder::finishDecoding() {
// Handle those decoders that have a delay
AVPacket nullPacket;
memset(&nullPacket, 0, sizeof(nullPacket));
nullPacket.data = nullptr;
nullPacket.size = 0;
AVSubtitle subtitle;
while (true) {
int finishedFrame = 1;
auto err = avcodec_decode_subtitle2(m_status->subtitleCodecCtx, &subtitle, &finishedFrame, &nullPacket);
if (err < 0 || !finishedFrame) {
break;
}
pushSubtitleFrame(&nullPacket, &subtitle);
avsubtitle_free(&subtitle);
}
}
void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle) {
if (subtitle->format != 1) {
@@ -129,9 +111,6 @@ void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle)
pushFrame(std::move(frame));
}
void SubtitleDecoder::flushBuffers() {
avcodec_flush_buffers(m_status->subtitleCodecCtx);
}
}
}
+3 -4
View File
@@ -10,13 +10,12 @@ class SubtitleDecoder: public FFMPEGStreamDecoder<SubtitleFrame> {
public:
explicit SubtitleDecoder(DecoderStatus* status);
~SubtitleDecoder() override;
virtual ~SubtitleDecoder();
void decodePacket(AVPacket* packet) override;
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
void finishDecoding() override;
virtual void finishDecoding() SCP_OVERRIDE;
void pushSubtitleFrame(AVPacket* subtitle, AVSubtitle* pSubtitle);
void flushBuffers() override;
};
}
+63 -62
View File
@@ -3,9 +3,11 @@
#include "tracing/tracing.h"
namespace {
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt, AVPixelFormat destination_fmt)
{
return sws_getContext(width, height, fmt, width, height, destination_fmt, SWS_BILINEAR, nullptr, nullptr, nullptr);
const AVPixelFormat DESTINATION_FORMAT = AV_PIX_FMT_YUV420P;
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt) {
return sws_getContext(width, height, fmt, width, height, DESTINATION_FORMAT,
SWS_BILINEAR, nullptr, nullptr, nullptr);
}
double getFrameTime(int64_t pts, AVRational time_base) {
@@ -16,53 +18,34 @@ double getFrameTime(int64_t pts, AVRational time_base) {
namespace cutscene {
namespace ffmpeg {
class FFMPEGVideoFrame: public VideoFrame {
size_t _width;
size_t _height;
AVFrame* _frame;
public:
FFMPEGVideoFrame() : frame(nullptr) {
}
public:
FFMPEGVideoFrame(size_t width, size_t height, AVFrame* frame) : _width(width), _height(height), _frame(frame) {}
~FFMPEGVideoFrame() override {
if (_frame != nullptr) {
av_freep(&_frame->data[0]);
av_frame_free(&_frame);
virtual ~FFMPEGVideoFrame() {
if (frame != nullptr) {
av_freep(&frame->data[0]);
av_frame_free(&frame);
}
}
size_t getPlaneNumber() override
{
switch (_frame->format) {
case AV_PIX_FMT_YUV420P:
// YUV data is planar
return 3;
default:
// Everything else is packed
return 1;
}
}
FrameSize getPlaneSize(size_t plane) override
{
switch (_frame->format) {
case AV_PIX_FMT_YUV420P: {
// YUV data is planar
auto width = plane > 0 ? _width / 2 : _width;
auto height = plane > 0 ? _height / 2 : _height;
return {width, height, (size_t)_frame->linesize[plane]};
}
default:
// Everything else is packed
return {_width, _height, (size_t)_frame->linesize[plane]};
}
virtual DataPointers getDataPointers() {
DataPointers ptrs;
ptrs.y = frame->data[0];
ptrs.u = frame->data[1];
ptrs.v = frame->data[2];
return ptrs;
}
void* getPlaneData(size_t plane) override { return _frame->data[plane]; }
AVFrame* frame;
};
VideoDecoder::VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt)
: FFMPEGStreamDecoder(status), m_frameId(0), m_destinationFormat(destination_fmt)
{
VideoDecoder::VideoDecoder(DecoderStatus* status)
: FFMPEGStreamDecoder(status),
m_frameId(0) {
m_swsCtx = getSWSContext(m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_status->videoCodecPars.pixel_format, destination_fmt);
m_status->videoCodecPars.pixel_format);
}
VideoDecoder::~VideoDecoder() {
@@ -70,32 +53,53 @@ VideoDecoder::~VideoDecoder() {
}
void VideoDecoder::convertAndPushPicture(const AVFrame* frame) {
// Allocate a picture to hold the destination data
// Allocate a picture to hold the YUV data
AVFrame* yuvFrame = av_frame_alloc();
av_frame_copy(yuvFrame, frame);
yuvFrame->format = m_destinationFormat;
yuvFrame->format = DESTINATION_FORMAT;
av_image_alloc(yuvFrame->data, yuvFrame->linesize, m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_destinationFormat, 1);
av_image_alloc(yuvFrame->data,
yuvFrame->linesize,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height,
DESTINATION_FORMAT,
1);
if (m_status->videoCodecPars.pixel_format == m_destinationFormat) {
av_image_copy(yuvFrame->data, yuvFrame->linesize, (const uint8_t**)(frame->data), frame->linesize,
m_destinationFormat, m_status->videoCodecPars.width, m_status->videoCodecPars.height);
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(new FFMPEGVideoFrame());
if (m_status->videoCodecPars.pixel_format == DESTINATION_FORMAT) {
av_image_copy(yuvFrame->data,
yuvFrame->linesize,
(const uint8_t**) (frame->data),
frame->linesize,
DESTINATION_FORMAT,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height);
} else {
// Convert frame to destination format
sws_scale(m_swsCtx, (uint8_t const* const*)frame->data, frame->linesize, 0, m_status->videoCodecPars.height,
yuvFrame->data, yuvFrame->linesize);
// Convert frame to YUV
sws_scale(
m_swsCtx,
(uint8_t const* const*) frame->data,
frame->linesize,
0,
m_status->videoCodecPars.height,
yuvFrame->data,
yuvFrame->linesize
);
}
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(
new FFMPEGVideoFrame(static_cast<size_t>(m_status->videoCodecPars.width),
static_cast<size_t>(m_status->videoCodecPars.height), yuvFrame));
videoFramePtr->id = ++m_frameId;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
videoFramePtr->frameTime = getFrameTime(frame->best_effort_timestamp, m_status->videoStream->time_base);
#else
videoFramePtr->frameTime = getFrameTime(av_frame_get_best_effort_timestamp(frame), m_status->videoStream->time_base);
#endif
videoFramePtr->frame = yuvFrame;
videoFramePtr->ySize.height = static_cast<size_t>(m_status->videoCodecPars.height);
videoFramePtr->ySize.width = static_cast<size_t>(m_status->videoCodecPars.width);
videoFramePtr->ySize.stride = static_cast<size_t>(yuvFrame->linesize[0]);
// 420P means that the UV channels have half the width and height
videoFramePtr->uvSize.height = static_cast<size_t>(m_status->videoCodecPars.height / 2);
videoFramePtr->uvSize.width = static_cast<size_t>(m_status->videoCodecPars.width / 2);
videoFramePtr->uvSize.stride = static_cast<size_t>(yuvFrame->linesize[1]);
pushFrame(VideoFramePtr(videoFramePtr.release()));
}
@@ -158,8 +162,5 @@ void VideoDecoder::finishDecoding() {
}
#endif
}
void VideoDecoder::flushBuffers() {
avcodec_flush_buffers(m_status->videoCodecCtx);
}
}
}
+4 -7
View File
@@ -9,20 +9,17 @@ class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
private:
int m_frameId;
SwsContext* m_swsCtx;
AVPixelFormat m_destinationFormat;
void convertAndPushPicture(const AVFrame* frame);
public:
explicit VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt);
explicit VideoDecoder(DecoderStatus* status);
~VideoDecoder() override;
virtual ~VideoDecoder();
void decodePacket(AVPacket* packet) override;
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
void finishDecoding() override;
void flushBuffers() override;
virtual void finishDecoding() SCP_OVERRIDE;
};
}
}
Loaded 100 of 1357 files, more files were not shown because too many files have changed in this diff. Show more