mirror of
https://github.com/OpenMW/openmw.git
synced 2026-01-05 18:43:06 +00:00
Merge branch 'master' of https://gitlab.com/OpenMW/openmw
This commit is contained in:
commit
e2e8a02a26
177 changed files with 1711 additions and 763 deletions
8
.github/workflows/push.yml
vendored
8
.github/workflows/push.yml
vendored
|
|
@ -73,7 +73,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Building Dependencies
|
||||
run: CI/before_install.osx.sh
|
||||
run: CI/before_install.macos.sh
|
||||
|
||||
- name: Prime ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
|
|
@ -82,11 +82,9 @@ jobs:
|
|||
max-size: 1000M
|
||||
|
||||
- name: Configure
|
||||
run: CI/before_script.osx.sh
|
||||
run: CI/before_script.macos.sh
|
||||
- name: Build
|
||||
run: |
|
||||
cd build
|
||||
make -j $(sysctl -n hw.logicalcpu) package
|
||||
run: CI/macos/build.sh
|
||||
|
||||
Output-Envs:
|
||||
name: Read .env file and expose it as output
|
||||
|
|
|
|||
|
|
@ -507,14 +507,15 @@ Ubuntu_GCC_integration_tests_asan:
|
|||
paths:
|
||||
- ccache/
|
||||
script:
|
||||
- CI/before_install.osx.sh
|
||||
- CI/before_install.macos.sh
|
||||
- export CCACHE_BASEDIR="$(pwd)"
|
||||
- export CCACHE_DIR="$(pwd)/ccache"
|
||||
- mkdir -pv "${CCACHE_DIR}"
|
||||
- ccache -z -M "${CCACHE_SIZE}"
|
||||
- CI/before_script.osx.sh
|
||||
- cd build; make -j $(sysctl -n hw.logicalcpu) package
|
||||
- for dmg in *.dmg; do mv "$dmg" "${dmg%.dmg}_${CI_COMMIT_REF_NAME##*/}.dmg"; done
|
||||
- CI/macos/ccache_prep.sh
|
||||
- CI/before_script.macos.sh
|
||||
- CI/macos/build.sh
|
||||
- cd build
|
||||
- for dmg in *.dmg; do mv "$dmg" "${dmg%.dmg}_${DMG_IDENTIFIER}_${CI_COMMIT_REF_NAME##*/}.dmg"; done
|
||||
- |
|
||||
if [[ -n "${AWS_ACCESS_KEY_ID}" ]]; then
|
||||
echo "[default]" > ~/.s3cfg
|
||||
|
|
@ -529,11 +530,23 @@ Ubuntu_GCC_integration_tests_asan:
|
|||
s3cmd put "${dmg}" s3://openmw-artifacts/${artifactDirectory}
|
||||
done
|
||||
fi
|
||||
- ccache -s
|
||||
- ../CI/macos/ccache_save.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- build/OpenMW-*.dmg
|
||||
|
||||
macOS14_Xcode15_amd64:
|
||||
extends: .MacOS
|
||||
image: macos-14-xcode-15
|
||||
tags:
|
||||
- saas-macos-medium-m1
|
||||
cache:
|
||||
key: macOS14_Xcode15_amd64.v2
|
||||
variables:
|
||||
CCACHE_SIZE: 3G
|
||||
DMG_IDENTIFIER: amd64
|
||||
MACOS_AMD64: true
|
||||
|
||||
macOS14_Xcode15_arm64:
|
||||
extends: .MacOS
|
||||
image: macos-14-xcode-15
|
||||
|
|
@ -542,6 +555,7 @@ macOS14_Xcode15_arm64:
|
|||
cache:
|
||||
key: macOS14_Xcode15_arm64.v1
|
||||
variables:
|
||||
DMG_IDENTIFIER: arm64
|
||||
CCACHE_SIZE: 3G
|
||||
|
||||
.Compress_And_Upload_Symbols_Base:
|
||||
|
|
@ -968,7 +982,7 @@ Windows_MSBuild_CacheInit:
|
|||
- flatpak build-bundle ./repo openmw.flatpak org.openmw.OpenMW.devel
|
||||
cache:
|
||||
key: flatpak
|
||||
paths:
|
||||
paths:
|
||||
- ".flatpak-builder"
|
||||
artifacts:
|
||||
untracked: false
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
0.50.0
|
||||
------
|
||||
|
||||
|
||||
0.49.0
|
||||
------
|
||||
|
||||
|
|
@ -236,6 +240,8 @@
|
|||
Bug #8465: Blue screen w/ antialiasing and post-processing on macOS
|
||||
Bug #8503: Camera does not handle NaN gracefully
|
||||
Bug #8541: Lua: util.color:asHex produces wrong output for some colors
|
||||
Bug #8567: Token replacement does not work via CLI and relative paths passed via the command line are not relative to the CWD
|
||||
Bug #8576: Crash on exit when unresolving containers with scripted items
|
||||
Feature #1415: Infinite fall failsafe
|
||||
Feature #2566: Handle NAM9 records for manual cell references
|
||||
Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking
|
||||
|
|
|
|||
11
CI/before_install.macos.sh
Executable file
11
CI/before_install.macos.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
export HOMEBREW_NO_EMOJI=1
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
export HOMEBREW_AUTOREMOVE=1
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
./CI/macos/before_install.amd64.sh
|
||||
else
|
||||
./CI/macos/before_install.arm64.sh
|
||||
fi
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
export HOMEBREW_NO_EMOJI=1
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
export HOMEBREW_AUTOREMOVE=1
|
||||
|
||||
brew tap --repair
|
||||
brew update --quiet
|
||||
|
||||
brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd
|
||||
|
||||
command -v ccache >/dev/null 2>&1 || brew install ccache
|
||||
command -v cmake >/dev/null 2>&1 || brew install cmake
|
||||
command -v qmake >/dev/null 2>&1 || brew install qt@6
|
||||
|
||||
# Install deps
|
||||
brew install openal-soft icu4c yaml-cpp sqlite
|
||||
|
||||
ccache --version
|
||||
cmake --version
|
||||
qmake --version
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240802.zip -o ~/openmw-deps.zip
|
||||
unzip -o ~/openmw-deps.zip -d /tmp > /dev/null
|
||||
else
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240818-arm64.tar.xz -o ~/openmw-deps.tar.xz
|
||||
tar xf ~/openmw-deps.tar.xz -C /tmp > /dev/null
|
||||
fi
|
||||
77
CI/before_script.macos.sh
Executable file
77
CI/before_script.macos.sh
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Silence a git warning
|
||||
git config --global advice.detachedHead false
|
||||
|
||||
rm -fr build
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
DEPENDENCIES_ROOT="/tmp/openmw-deps"
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
QT_PATH=$(arch -x86_64 /usr/local/bin/brew --prefix qt@6)
|
||||
ICU_PATH=$(arch -x86_64 /usr/local/bin/brew --prefix icu4c)
|
||||
OPENAL_PATH=$(arch -x86_64 /usr/local/bin/brew --prefix openal-soft)
|
||||
CCACHE_EXECUTABLE=$(arch -x86_64 /usr/local/bin/brew --prefix ccache)/bin/ccache
|
||||
else
|
||||
QT_PATH=$(brew --prefix qt@6)
|
||||
ICU_PATH=$(brew --prefix icu4c)
|
||||
OPENAL_PATH=$(brew --prefix openal-soft)
|
||||
CCACHE_EXECUTABLE=$(brew --prefix ccache)/bin/ccache
|
||||
fi
|
||||
|
||||
declare -a CMAKE_CONF_OPTS=(
|
||||
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH;$OPENAL_PATH"
|
||||
-D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE"
|
||||
-D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE"
|
||||
-D CMAKE_CXX_FLAGS="-stdlib=libc++"
|
||||
-D CMAKE_C_COMPILER="clang"
|
||||
-D CMAKE_CXX_COMPILER="clang++"
|
||||
-D CMAKE_OSX_DEPLOYMENT_TARGET="13.6"
|
||||
-D OPENMW_USE_SYSTEM_RECASTNAVIGATION=TRUE
|
||||
-D Boost_INCLUDE_DIR="$DEPENDENCIES_ROOT/include"
|
||||
-D OSGPlugins_LIB_DIR="$DEPENDENCIES_ROOT/lib/osgPlugins-3.6.5"
|
||||
-D ICU_ROOT="$ICU_PATH"
|
||||
-D OPENMW_OSX_DEPLOYMENT=TRUE
|
||||
)
|
||||
|
||||
declare -a BUILD_OPTS=(
|
||||
-D BUILD_OPENMW=TRUE
|
||||
-D BUILD_OPENCS=TRUE
|
||||
-D BUILD_ESMTOOL=TRUE
|
||||
-D BUILD_BSATOOL=TRUE
|
||||
-D BUILD_ESSIMPORTER=TRUE
|
||||
-D BUILD_NIFTEST=TRUE
|
||||
-D BUILD_NAVMESHTOOL=TRUE
|
||||
-D BUILD_BULLETOBJECTTOOL=TRUE
|
||||
-G"Unix Makefiles"
|
||||
)
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-D CMAKE_OSX_ARCHITECTURES="x86_64"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "${CMAKE_BUILD_TYPE}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
else
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
arch -x86_64 cmake \
|
||||
"${CMAKE_CONF_OPTS[@]}" \
|
||||
"${BUILD_OPTS[@]}" \
|
||||
..
|
||||
else
|
||||
cmake \
|
||||
"${CMAKE_CONF_OPTS[@]}" \
|
||||
"${BUILD_OPTS[@]}" \
|
||||
..
|
||||
fi
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Silence a git warning
|
||||
git config --global advice.detachedHead false
|
||||
|
||||
rm -fr build
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
DEPENDENCIES_ROOT="/tmp/openmw-deps"
|
||||
|
||||
QT_PATH=$(brew --prefix qt@6)
|
||||
ICU_PATH=$(brew --prefix icu4c)
|
||||
OPENAL_PATH=$(brew --prefix openal-soft)
|
||||
CCACHE_EXECUTABLE=$(brew --prefix ccache)/bin/ccache
|
||||
|
||||
declare -a CMAKE_CONF_OPTS=(
|
||||
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH;$OPENAL_PATH"
|
||||
-D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE"
|
||||
-D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE"
|
||||
-D CMAKE_CXX_FLAGS="-stdlib=libc++"
|
||||
-D CMAKE_C_COMPILER="clang"
|
||||
-D CMAKE_CXX_COMPILER="clang++"
|
||||
-D CMAKE_OSX_DEPLOYMENT_TARGET="13.6"
|
||||
-D OPENMW_USE_SYSTEM_RECASTNAVIGATION=TRUE
|
||||
-D Boost_INCLUDE_DIR="$DEPENDENCIES_ROOT/include"
|
||||
-D OSGPlugins_LIB_DIR="$DEPENDENCIES_ROOT/lib/osgPlugins-3.6.5"
|
||||
-D ICU_ROOT="$ICU_PATH"
|
||||
-D OPENMW_OSX_DEPLOYMENT=TRUE
|
||||
)
|
||||
|
||||
if [[ "${CMAKE_BUILD_TYPE}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
else
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
)
|
||||
fi
|
||||
|
||||
cmake \
|
||||
"${CMAKE_CONF_OPTS[@]}" \
|
||||
-D BUILD_OPENMW=TRUE \
|
||||
-D BUILD_OPENCS=TRUE \
|
||||
-D BUILD_ESMTOOL=TRUE \
|
||||
-D BUILD_BSATOOL=TRUE \
|
||||
-D BUILD_ESSIMPORTER=TRUE \
|
||||
-D BUILD_NIFTEST=TRUE \
|
||||
-D BUILD_NAVMESHTOOL=TRUE \
|
||||
-D BUILD_BULLETOBJECTTOOL=TRUE \
|
||||
-G"Unix Makefiles" \
|
||||
..
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
git ls-files -- ':(exclude)extern/' '*.cpp' '*.hpp' '*.h' |
|
||||
grep -vP '/[a-z0-9]+\.(cpp|hpp|h)$' |
|
||||
grep -vFf CI/file_name_exceptions.txt &&
|
||||
grep -vP '/[a-z0-9]+\.(cpp|hpp|h)$' &&
|
||||
( echo 'File names do not follow the naming convention, see https://wiki.openmw.org/index.php?title=Naming_Conventions#Files'; exit -1 )
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
apps/openmw/android_main.cpp
|
||||
apps/openmw/mwsound/efx-presets.h
|
||||
apps/openmw/mwsound/ffmpeg_decoder.cpp
|
||||
apps/openmw/mwsound/ffmpeg_decoder.hpp
|
||||
apps/openmw/mwsound/openal_output.cpp
|
||||
apps/openmw/mwsound/openal_output.hpp
|
||||
apps/openmw/mwsound/sound_buffer.cpp
|
||||
apps/openmw/mwsound/sound_buffer.hpp
|
||||
apps/openmw/mwsound/sound_decoder.hpp
|
||||
apps/openmw/mwsound/sound_output.hpp
|
||||
apps/components_tests/esm/test_fixed_string.cpp
|
||||
apps/components_tests/files/conversion_tests.cpp
|
||||
apps/components_tests/lua/test_async.cpp
|
||||
apps/components_tests/lua/test_configuration.cpp
|
||||
apps/components_tests/lua/test_l10n.cpp
|
||||
apps/components_tests/lua/test_lua.cpp
|
||||
apps/components_tests/lua/test_scriptscontainer.cpp
|
||||
apps/components_tests/lua/test_serialization.cpp
|
||||
apps/components_tests/lua/test_storage.cpp
|
||||
apps/components_tests/lua/test_ui_content.cpp
|
||||
apps/components_tests/lua/test_utilpackage.cpp
|
||||
apps/components_tests/lua/test_inputactions.cpp
|
||||
apps/components_tests/lua/test_yaml.cpp
|
||||
apps/components_tests/misc/test_endianness.cpp
|
||||
apps/components_tests/misc/test_resourcehelpers.cpp
|
||||
apps/components_tests/misc/test_stringops.cpp
|
||||
apps/openmw_tests/mwdialogue/test_keywordsearch.cpp
|
||||
apps/openmw_tests/mwscript/test_scripts.cpp
|
||||
apps/openmw_tests/mwscript/test_utils.hpp
|
||||
apps/openmw_tests/mwworld/test_store.cpp
|
||||
components/bsa/bsa_file.cpp
|
||||
components/bsa/bsa_file.hpp
|
||||
components/crashcatcher/windows_crashcatcher.cpp
|
||||
components/crashcatcher/windows_crashcatcher.hpp
|
||||
components/crashcatcher/windows_crashmonitor.cpp
|
||||
components/crashcatcher/windows_crashmonitor.hpp
|
||||
components/crashcatcher/windows_crashshm.hpp
|
||||
components/fx/lexer_types.hpp
|
||||
components/fx/parse_constants.hpp
|
||||
components/platform/file.posix.cpp
|
||||
components/platform/file.stdio.cpp
|
||||
components/platform/file.win32.cpp
|
||||
components/sdlutil/gl4es_init.cpp
|
||||
components/sdlutil/gl4es_init.h
|
||||
components/to_utf8/gen_iconv.cpp
|
||||
components/to_utf8/tables_gen.hpp
|
||||
components/to_utf8/to_utf8.cpp
|
||||
components/to_utf8/to_utf8.hpp
|
||||
8
CI/macos/before_install.amd64.sh
Executable file
8
CI/macos/before_install.amd64.sh
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
arch -x86_64 /usr/local/bin/brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd ccache cmake qt@6 openal-soft icu4c yaml-cpp sqlite
|
||||
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240802.zip -o ~/openmw-deps.zip
|
||||
unzip -o ~/openmw-deps.zip -d /tmp > /dev/null
|
||||
16
CI/macos/before_install.arm64.sh
Executable file
16
CI/macos/before_install.arm64.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
brew tap --repair
|
||||
brew update --quiet
|
||||
|
||||
brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd
|
||||
|
||||
command -v ccache >/dev/null 2>&1 || brew install ccache
|
||||
command -v cmake >/dev/null 2>&1 || brew install cmake
|
||||
command -v qmake >/dev/null 2>&1 || brew install qt@6
|
||||
|
||||
# Install deps
|
||||
brew install openal-soft icu4c yaml-cpp sqlite
|
||||
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240818-arm64.tar.xz -o ~/openmw-deps.tar.xz
|
||||
tar xf ~/openmw-deps.tar.xz -C /tmp > /dev/null
|
||||
9
CI/macos/build.sh
Executable file
9
CI/macos/build.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
cd build
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
arch -x86_64 make -j $(sysctl -n hw.logicalcpu) package
|
||||
else
|
||||
make -j $(sysctl -n hw.logicalcpu) package
|
||||
fi
|
||||
7
CI/macos/ccache_prep.sh
Executable file
7
CI/macos/ccache_prep.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
arch -x86_64 ccache -z -M "${CCACHE_SIZE}"
|
||||
else
|
||||
ccache -z -M "${CCACHE_SIZE}"
|
||||
fi
|
||||
7
CI/macos/ccache_save.sh
Executable file
7
CI/macos/ccache_save.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
arch -x86_64 ccache -s
|
||||
else
|
||||
ccache -s
|
||||
fi
|
||||
|
|
@ -80,7 +80,7 @@ endif()
|
|||
message(STATUS "Configuring OpenMW...")
|
||||
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 49)
|
||||
set(OPENMW_VERSION_MINOR 50)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
set(OPENMW_LUA_API_REVISION 76)
|
||||
set(OPENMW_POSTPROCESSING_API_REVISION 2)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ OpenMW is an open-source open-world RPG game engine that supports playing Morrow
|
|||
|
||||
OpenMW also comes with OpenMW-CS, a replacement for Bethesda's Construction Set.
|
||||
|
||||
* Version: 0.49.0
|
||||
* Version: 0.50.0
|
||||
* License: GPLv3 (see [LICENSE](https://gitlab.com/OpenMW/openmw/-/raw/master/LICENSE) for more information)
|
||||
* Website: https://www.openmw.org
|
||||
* IRC: #openmw on irc.libera.chat
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <components/resource/niffilemanager.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
#include <components/version/version.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/registerarchives.hpp>
|
||||
|
|
@ -125,6 +125,7 @@ namespace
|
|||
}
|
||||
|
||||
Files::ConfigurationManager config;
|
||||
config.processPaths(variables, std::filesystem::current_path());
|
||||
config.readConfiguration(variables, desc);
|
||||
|
||||
Debug::setupLogging(config.getLogPath(), applicationName);
|
||||
|
|
|
|||
|
|
@ -4,29 +4,28 @@ include_directories(SYSTEM ${GMOCK_INCLUDE_DIRS})
|
|||
file(GLOB UNITTEST_SRC_FILES
|
||||
main.cpp
|
||||
|
||||
esm/test_fixed_string.cpp
|
||||
esm/variant.cpp
|
||||
esm/testfixedstring.cpp
|
||||
esm/testrefid.cpp
|
||||
esm/variant.cpp
|
||||
|
||||
lua/test_lua.cpp
|
||||
lua/test_scriptscontainer.cpp
|
||||
lua/test_utilpackage.cpp
|
||||
lua/test_serialization.cpp
|
||||
lua/test_configuration.cpp
|
||||
lua/test_l10n.cpp
|
||||
lua/test_storage.cpp
|
||||
lua/test_async.cpp
|
||||
lua/test_inputactions.cpp
|
||||
lua/test_yaml.cpp
|
||||
|
||||
lua/test_ui_content.cpp
|
||||
lua/testasync.cpp
|
||||
lua/testconfiguration.cpp
|
||||
lua/testinputactions.cpp
|
||||
lua/testl10n.cpp
|
||||
lua/testlua.cpp
|
||||
lua/testscriptscontainer.cpp
|
||||
lua/testserialization.cpp
|
||||
lua/teststorage.cpp
|
||||
lua/testuicontent.cpp
|
||||
lua/testutilpackage.cpp
|
||||
lua/testyaml.cpp
|
||||
|
||||
misc/compression.cpp
|
||||
misc/progressreporter.cpp
|
||||
misc/test_endianness.cpp
|
||||
misc/test_resourcehelpers.cpp
|
||||
misc/test_stringops.cpp
|
||||
misc/testendianness.cpp
|
||||
misc/testmathutil.cpp
|
||||
misc/testresourcehelpers.cpp
|
||||
misc/teststringops.cpp
|
||||
|
||||
nifloader/testbulletnifloader.cpp
|
||||
|
||||
|
|
@ -64,8 +63,8 @@ file(GLOB UNITTEST_SRC_FILES
|
|||
esmloader/esmdata.cpp
|
||||
esmloader/record.cpp
|
||||
|
||||
files/conversiontests.cpp
|
||||
files/hash.cpp
|
||||
files/conversion_tests.cpp
|
||||
|
||||
toutf8/toutf8.cpp
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <components/esmloader/load.hpp>
|
||||
#include <components/files/collections.hpp>
|
||||
#include <components/files/multidircollection.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <components/misc/strings/conversion.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <components/esm4/readerutils.hpp>
|
||||
#include <components/esm4/records.hpp>
|
||||
#include <components/esm4/typetraits.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
namespace EsmTool
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "importercontext.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ Allowed options)");
|
|||
bpo::notify(variables);
|
||||
|
||||
Files::ConfigurationManager cfgManager(true);
|
||||
cfgManager.processPaths(variables, std::filesystem::current_path());
|
||||
cfgManager.readConfiguration(variables, desc);
|
||||
|
||||
const auto& essFile = variables["mwsave"].as<Files::MaybeQuotedPath>();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
class MwIniImporter
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <components/resource/niffilemanager.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
#include <components/version/version.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/registerarchives.hpp>
|
||||
|
|
@ -143,6 +143,7 @@ namespace NavMeshTool
|
|||
}
|
||||
|
||||
Files::ConfigurationManager config;
|
||||
config.processPaths(variables, std::filesystem::current_path());
|
||||
config.readConfiguration(variables, desc);
|
||||
|
||||
Debug::setupLogging(config.getLogPath(), applicationName);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <components/misc/rng.hpp>
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "view/doc/viewmanager.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#include <apps/opencs/model/world/universalid.hpp>
|
||||
|
||||
#include <components/files/multidircollection.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "../world/data.hpp"
|
||||
#include "../world/idcompletionmanager.hpp"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <components/files/multidircollection.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "loader.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#endif
|
||||
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
|
@ -55,16 +52,17 @@ void CSMDoc::Runner::start(bool delayed)
|
|||
|
||||
QString path = "openmw";
|
||||
#ifdef Q_OS_WIN
|
||||
path.append(QString(".exe"));
|
||||
#elif defined(Q_OS_MAC)
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
dir.cdUp();
|
||||
dir.cdUp();
|
||||
dir.cdUp();
|
||||
path = dir.absoluteFilePath(path.prepend("OpenMW.app/Contents/MacOS/"));
|
||||
#else
|
||||
path.prepend(QString("./"));
|
||||
path.append(QLatin1String(".exe"));
|
||||
#endif
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
#ifdef Q_OS_MAC
|
||||
// the CS and engine are in separate .app directories
|
||||
dir.cdUp();
|
||||
dir.cdUp();
|
||||
dir.cdUp();
|
||||
path.prepend("OpenMW.app/Contents/MacOS/");
|
||||
#endif
|
||||
path = dir.absoluteFilePath(path);
|
||||
|
||||
mStartup = new QTemporaryFile(this);
|
||||
mStartup->open();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "operation.hpp"
|
||||
#include "savingstate.hpp"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
#include <components/misc/algorithm.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace CSMPrefs
|
|||
}
|
||||
}
|
||||
|
||||
bool ShortcutManager::getModifier(const std::string& name, int& modifier) const
|
||||
bool ShortcutManager::getModifier(std::string_view name, int& modifier) const
|
||||
{
|
||||
ModifierMap::const_iterator item = mModifiers.find(name);
|
||||
if (item != mModifiers.end())
|
||||
|
|
@ -175,14 +175,14 @@ namespace CSMPrefs
|
|||
return concat;
|
||||
}
|
||||
|
||||
void ShortcutManager::convertFromString(const std::string& data, QKeySequence& sequence) const
|
||||
void ShortcutManager::convertFromString(std::string_view data, QKeySequence& sequence) const
|
||||
{
|
||||
const int MaxKeys = 4; // A limitation of QKeySequence
|
||||
|
||||
size_t end = data.find(';');
|
||||
size_t size = std::min(end, data.size());
|
||||
|
||||
std::string value = data.substr(0, size);
|
||||
std::string_view value = data.substr(0, size);
|
||||
size_t start = 0;
|
||||
|
||||
int keyPos = 0;
|
||||
|
|
@ -195,7 +195,7 @@ namespace CSMPrefs
|
|||
end = data.find('+', start);
|
||||
end = std::min(end, value.size());
|
||||
|
||||
std::string name = value.substr(start, end - start);
|
||||
std::string_view name = value.substr(start, end - start);
|
||||
|
||||
if (name == "Ctrl")
|
||||
{
|
||||
|
|
@ -242,12 +242,12 @@ namespace CSMPrefs
|
|||
sequence = QKeySequence(keys[0], keys[1], keys[2], keys[3]);
|
||||
}
|
||||
|
||||
void ShortcutManager::convertFromString(const std::string& data, int& modifier) const
|
||||
void ShortcutManager::convertFromString(std::string_view data, int& modifier) const
|
||||
{
|
||||
size_t start = data.find(';') + 1;
|
||||
start = std::min(start, data.size());
|
||||
|
||||
std::string name = data.substr(start);
|
||||
std::string_view name = data.substr(start);
|
||||
KeyMap::const_iterator searchResult = mKeys.find(name);
|
||||
if (searchResult != mKeys.end())
|
||||
{
|
||||
|
|
@ -259,7 +259,7 @@ namespace CSMPrefs
|
|||
}
|
||||
}
|
||||
|
||||
void ShortcutManager::convertFromString(const std::string& data, QKeySequence& sequence, int& modifier) const
|
||||
void ShortcutManager::convertFromString(std::string_view data, QKeySequence& sequence, int& modifier) const
|
||||
{
|
||||
convertFromString(data, sequence);
|
||||
convertFromString(data, modifier);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace CSMPrefs
|
|||
bool getSequence(std::string_view name, QKeySequence& sequence) const;
|
||||
void setSequence(std::string_view name, const QKeySequence& sequence);
|
||||
|
||||
bool getModifier(const std::string& name, int& modifier) const;
|
||||
bool getModifier(std::string_view name, int& modifier) const;
|
||||
void setModifier(std::string_view name, int modifier);
|
||||
|
||||
std::string convertToString(const QKeySequence& sequence) const;
|
||||
|
|
@ -39,10 +39,10 @@ namespace CSMPrefs
|
|||
|
||||
std::string convertToString(const QKeySequence& sequence, int modifier) const;
|
||||
|
||||
void convertFromString(const std::string& data, QKeySequence& sequence) const;
|
||||
void convertFromString(const std::string& data, int& modifier) const;
|
||||
void convertFromString(std::string_view data, QKeySequence& sequence) const;
|
||||
void convertFromString(std::string_view data, int& modifier) const;
|
||||
|
||||
void convertFromString(const std::string& data, QKeySequence& sequence, int& modifier) const;
|
||||
void convertFromString(std::string_view data, QKeySequence& sequence, int& modifier) const;
|
||||
|
||||
/// Replaces "{sequence-name}" or "{modifier-name}" with the appropriate text
|
||||
QString processToolTip(const QString& toolTip) const;
|
||||
|
|
@ -53,7 +53,7 @@ namespace CSMPrefs
|
|||
typedef std::map<std::string, QKeySequence, std::less<>> SequenceMap;
|
||||
typedef std::map<std::string, int, std::less<>> ModifierMap;
|
||||
typedef std::map<int, std::string> NameMap;
|
||||
typedef std::map<std::string, int> KeyMap;
|
||||
typedef std::map<std::string, int, std::less<>> KeyMap;
|
||||
|
||||
ShortcutMap mShortcuts;
|
||||
SequenceMap mSequences;
|
||||
|
|
|
|||
|
|
@ -498,7 +498,7 @@ CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut(
|
|||
// Setup with actual data
|
||||
QKeySequence sequence;
|
||||
|
||||
getShortcutManager().convertFromString(value, sequence);
|
||||
getShortcutManager().convertFromString(value.get(), sequence);
|
||||
getShortcutManager().setSequence(value.mName, sequence);
|
||||
|
||||
CSMPrefs::ShortcutSetting* setting
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "../doc/operation.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <apps/opencs/model/world/idcollection.hpp>
|
||||
#include <apps/opencs/model/world/record.hpp>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <apps/opencs/model/world/universalid.hpp>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include <components/esm3/selectiongroup.hpp>
|
||||
#include <components/files/multidircollection.hpp>
|
||||
#include <components/misc/algorithm.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "cell.hpp"
|
||||
#include "idcollection.hpp"
|
||||
|
|
|
|||
|
|
@ -171,16 +171,18 @@ osg::Vec3f CSVRender::InstanceMode::getProjectionSpaceCoords(const osg::Vec3f& p
|
|||
|
||||
osg::Vec3f CSVRender::InstanceMode::getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart)
|
||||
{
|
||||
osg::Matrix viewMatrix;
|
||||
viewMatrix.invert(getWorldspaceWidget().getCamera()->getViewMatrix());
|
||||
osg::Matrix projMatrix;
|
||||
projMatrix.invert(getWorldspaceWidget().getCamera()->getProjectionMatrix());
|
||||
osg::Matrix combined = projMatrix * viewMatrix;
|
||||
const osg::Matrix viewMatrix = getWorldspaceWidget().getCamera()->getViewMatrix();
|
||||
const osg::Matrix projMatrix = getWorldspaceWidget().getCamera()->getProjectionMatrix();
|
||||
const osg::Matrix combined = osg::Matrix::inverse(viewMatrix * projMatrix);
|
||||
|
||||
/* calculate viewport normalized coordinates
|
||||
note: is there a reason to use getCamera()->getViewport()->computeWindowMatrix() instead? */
|
||||
float x = (point.x() * 2) / getWorldspaceWidget().getCamera()->getViewport()->width() - 1.0f;
|
||||
float y = 1.0f - (point.y() * 2) / getWorldspaceWidget().getCamera()->getViewport()->height();
|
||||
const float scale = getWorldspaceWidget().devicePixelRatioF();
|
||||
const osg::Viewport* viewport = getWorldspaceWidget().getCamera()->getViewport();
|
||||
float x = point.x() * scale / viewport->width();
|
||||
float y = point.y() * scale / viewport->height();
|
||||
x = x * 2.0f - 1.0f;
|
||||
y = 1.0f - y * 2.0f;
|
||||
|
||||
osg::Vec3f mousePlanePoint = osg::Vec3f(x, y, dragStart.z()) * combined;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ set(OPENMW_HEADERS
|
|||
profile.hpp
|
||||
)
|
||||
|
||||
source_group(apps/openmw FILES main.cpp android_main.cpp ${OPENMW_SOURCES} ${OPENMW_HEADERS} ${OPENMW_RESOURCES})
|
||||
source_group(apps/openmw FILES main.cpp androidmain.cpp ${OPENMW_SOURCES} ${OPENMW_HEADERS} ${OPENMW_RESOURCES})
|
||||
|
||||
add_openmw_dir (mwrender
|
||||
actors objects renderingmanager animation rotatecontroller sky skyutil npcanimation esm4npcanimation vismask
|
||||
|
|
@ -71,8 +71,8 @@ add_openmw_dir (mwlua
|
|||
)
|
||||
|
||||
add_openmw_dir (mwsound
|
||||
soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output
|
||||
loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater
|
||||
soundmanagerimp openaloutput ffmpegdecoder sound soundbuffer sounddecoder soundoutput
|
||||
loudness movieaudiofactory alext efx efxpresets regionsoundselector watersoundupdater
|
||||
)
|
||||
|
||||
add_openmw_dir (mwworld
|
||||
|
|
@ -127,7 +127,7 @@ if(BUILD_OPENMW)
|
|||
if (ANDROID)
|
||||
add_library(openmw SHARED
|
||||
main.cpp
|
||||
android_main.cpp
|
||||
androidmain.cpp
|
||||
)
|
||||
else()
|
||||
openmw_add_executable(openmw
|
||||
|
|
@ -138,6 +138,12 @@ if(BUILD_OPENMW)
|
|||
endif()
|
||||
|
||||
target_link_libraries(openmw openmw-lib)
|
||||
|
||||
# Workaround necessary to ensure osgAnimation::MatrixLinearSampler dynamic casts work under Clang
|
||||
# NOTE: it's unclear whether the broken behavior is spec-compliant
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set_target_properties(openmw PROPERTIES ENABLE_EXPORTS ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING
|
||||
|
|
|
|||
|
|
@ -404,8 +404,8 @@ OMW::Engine::~Engine()
|
|||
mMechanicsManager = nullptr;
|
||||
mDialogueManager = nullptr;
|
||||
mJournal = nullptr;
|
||||
mScriptManager = nullptr;
|
||||
mWindowManager = nullptr;
|
||||
mScriptManager = nullptr;
|
||||
mWorld = nullptr;
|
||||
mStereoManager = nullptr;
|
||||
mSoundManager = nullptr;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ bool parseOptions(int argc, char** argv, OMW::Engine& engine, Files::Configurati
|
|||
return false;
|
||||
}
|
||||
|
||||
cfgMgr.processPaths(variables, std::filesystem::current_path());
|
||||
|
||||
cfgMgr.readConfiguration(variables, desc);
|
||||
|
||||
Debug::setupLogging(cfgMgr.getLogPath(), "OpenMW");
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ namespace MWSound
|
|||
|
||||
class Sound;
|
||||
class Stream;
|
||||
struct Sound_Decoder;
|
||||
typedef std::shared_ptr<Sound_Decoder> DecoderPtr;
|
||||
struct SoundDecoder;
|
||||
typedef std::shared_ptr<SoundDecoder> DecoderPtr;
|
||||
|
||||
/* These must all fit together */
|
||||
enum class PlayMode
|
||||
|
|
|
|||
|
|
@ -265,10 +265,6 @@ bool MWDialogue::Filter::testFunctionLocal(const MWDialogue::SelectWrapper& sele
|
|||
|
||||
bool MWDialogue::Filter::testSelectStruct(const SelectWrapper& select) const
|
||||
{
|
||||
if (select.isNpcOnly() && (mActor.getType() != ESM::NPC::sRecordId))
|
||||
// If the actor is a creature, we pass all conditions only applicable to NPCs.
|
||||
return true;
|
||||
|
||||
if (select.getFunction() == ESM::DialogueCondition::Function_Choice && mChoice == -1)
|
||||
// If not currently in a choice, we reject all conditions that test against choices.
|
||||
return false;
|
||||
|
|
@ -305,9 +301,13 @@ bool MWDialogue::Filter::testSelectStructNumeric(const SelectWrapper& select) co
|
|||
switch (select.getFunction())
|
||||
{
|
||||
case ESM::DialogueCondition::Function_Global:
|
||||
|
||||
{
|
||||
const auto& world = MWBase::Environment::get().getWorld();
|
||||
if (world->getGlobalVariableType(select.getName()) == ' ')
|
||||
return true; // ignore this filter if the global doesn't exist
|
||||
// internally all globals are float :(
|
||||
return select.selectCompare(MWBase::Environment::get().getWorld()->getGlobalFloat(select.getName()));
|
||||
return select.selectCompare(world->getGlobalFloat(select.getName()));
|
||||
}
|
||||
|
||||
case ESM::DialogueCondition::Function_Local:
|
||||
{
|
||||
|
|
@ -504,7 +504,8 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
|||
return MWBase::Environment::get().getWorld()->getCurrentWeather();
|
||||
|
||||
case ESM::DialogueCondition::Function_Reputation:
|
||||
|
||||
if (!mActor.getClass().isNpc())
|
||||
return 0;
|
||||
return mActor.getClass().getNpcStats(mActor).getReputation();
|
||||
|
||||
case ESM::DialogueCondition::Function_FactionRankDifference:
|
||||
|
|
@ -586,11 +587,11 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
|||
|
||||
case ESM::DialogueCondition::Function_NotClass:
|
||||
|
||||
return mActor.get<ESM::NPC>()->mBase->mClass != select.getId();
|
||||
return !mActor.getClass().isNpc() || mActor.get<ESM::NPC>()->mBase->mClass != select.getId();
|
||||
|
||||
case ESM::DialogueCondition::Function_NotRace:
|
||||
|
||||
return mActor.get<ESM::NPC>()->mBase->mRace != select.getId();
|
||||
return !mActor.getClass().isNpc() || mActor.get<ESM::NPC>()->mBase->mRace != select.getId();
|
||||
|
||||
case ESM::DialogueCondition::Function_NotCell:
|
||||
{
|
||||
|
|
@ -598,12 +599,14 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
|||
return !Misc::StringUtils::ciStartsWith(actorCell, select.getCellName());
|
||||
}
|
||||
case ESM::DialogueCondition::Function_SameSex:
|
||||
|
||||
if (!mActor.getClass().isNpc())
|
||||
return false;
|
||||
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)
|
||||
== (mActor.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female);
|
||||
|
||||
case ESM::DialogueCondition::Function_SameRace:
|
||||
|
||||
if (!mActor.getClass().isNpc())
|
||||
return false;
|
||||
return mActor.get<ESM::NPC>()->mBase->mRace == player.get<ESM::NPC>()->mBase->mRace;
|
||||
|
||||
case ESM::DialogueCondition::Function_SameFaction:
|
||||
|
|
@ -668,7 +671,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
|||
|
||||
case ESM::DialogueCondition::Function_Werewolf:
|
||||
|
||||
return mActor.getClass().getNpcStats(mActor).isWerewolf();
|
||||
return mActor.getClass().isNpc() && mActor.getClass().getNpcStats(mActor).isWerewolf();
|
||||
|
||||
default:
|
||||
|
||||
|
|
|
|||
|
|
@ -247,29 +247,6 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
|
|||
};
|
||||
}
|
||||
|
||||
bool MWDialogue::SelectWrapper::isNpcOnly() const
|
||||
{
|
||||
switch (mSelect.mFunction)
|
||||
{
|
||||
case ESM::DialogueCondition::Function_NotFaction:
|
||||
case ESM::DialogueCondition::Function_NotClass:
|
||||
case ESM::DialogueCondition::Function_NotRace:
|
||||
case ESM::DialogueCondition::Function_SameSex:
|
||||
case ESM::DialogueCondition::Function_SameRace:
|
||||
case ESM::DialogueCondition::Function_SameFaction:
|
||||
case ESM::DialogueCondition::Function_RankRequirement:
|
||||
case ESM::DialogueCondition::Function_Reputation:
|
||||
case ESM::DialogueCondition::Function_FactionRankDifference:
|
||||
case ESM::DialogueCondition::Function_Werewolf:
|
||||
case ESM::DialogueCondition::Function_PcWerewolfKills:
|
||||
case ESM::DialogueCondition::Function_FacReactionLowest:
|
||||
case ESM::DialogueCondition::Function_FacReactionHighest:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MWDialogue::SelectWrapper::selectCompare(int value) const
|
||||
{
|
||||
return selectCompareImp(mSelect, value);
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ namespace MWDialogue
|
|||
|
||||
Type getType() const;
|
||||
|
||||
bool isNpcOnly() const;
|
||||
///< \attention Do not call any of the select functions for this select struct!
|
||||
|
||||
bool selectCompare(int value) const;
|
||||
|
||||
bool selectCompare(float value) const;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "bookpage.hpp"
|
||||
#include "journalviewmodel.hpp"
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "windowbase.hpp"
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ namespace MWGui
|
|||
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true);
|
||||
|
||||
std::string name{ iter->getClass().getName(*iter) };
|
||||
name += " - " + MyGUI::utility::toString(price)
|
||||
name += " - " + MyGUI::utility::toString(price)
|
||||
+ MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>().find("sgp")->mValue.getString();
|
||||
|
||||
items.emplace_back(name, price, *iter);
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ namespace MWGui
|
|||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
||||
player, mActor, MWBase::MechanicsManager::OT_Pickpocket, ESM::RefId(), 0, true);
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||
mPickpocketDetected = true;
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,8 +129,8 @@ namespace MWGui
|
|||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
||||
player, mActor, MWBase::MechanicsManager::OT_Pickpocket, ESM::RefId(), 0, true);
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||
mPickpocketDetected = true;
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -434,6 +434,9 @@ namespace MWGui
|
|||
}
|
||||
|
||||
store.setSelectedEnchantItem(it);
|
||||
// to reset WindowManager::mSelectedSpell immediately
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(*it);
|
||||
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState::Spell);
|
||||
}
|
||||
}
|
||||
|
|
@ -461,6 +464,9 @@ namespace MWGui
|
|||
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState::Weapon);
|
||||
}
|
||||
|
||||
// Updates the state of equipped/not equipped (skin) in spellwindow
|
||||
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
||||
}
|
||||
|
||||
bool QuickKeysMenu::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ namespace MWGui
|
|||
{
|
||||
getWidget(mScreenshot, "Screenshot");
|
||||
getWidget(mCharacterSelection, "SelectCharacter");
|
||||
getWidget(mCellName, "CellName");
|
||||
getWidget(mInfoText, "InfoText");
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
|
|
@ -230,7 +231,8 @@ namespace MWGui
|
|||
title << " (#{OMWEngine:Level} " << signature.mPlayerLevel << " "
|
||||
<< MyGUI::TextIterator::toTagsString(MyGUI::UString(className)) << ")";
|
||||
|
||||
mCharacterSelection->addItem(MyGUI::LanguageManager::getInstance().replaceTags(title.str()));
|
||||
const MyGUI::UString playerDesc = MyGUI::LanguageManager::getInstance().replaceTags(title.str());
|
||||
mCharacterSelection->addItem(playerDesc, signature.mPlayerName);
|
||||
|
||||
if (mCurrentCharacter == &*it
|
||||
|| (!mCurrentCharacter && !mSaving
|
||||
|
|
@ -424,6 +426,7 @@ namespace MWGui
|
|||
if (pos == MyGUI::ITEM_NONE || !mCurrentCharacter)
|
||||
{
|
||||
mCurrentSlot = nullptr;
|
||||
mCellName->setCaption({});
|
||||
mInfoText->setCaption({});
|
||||
mScreenshot->setImageTexture({});
|
||||
return;
|
||||
|
|
@ -445,15 +448,21 @@ namespace MWGui
|
|||
|
||||
std::stringstream text;
|
||||
|
||||
text << Misc::fileTimeToString(mCurrentSlot->mTimeStamp, "%Y.%m.%d %T") << "\n";
|
||||
const size_t profileIndex = mCharacterSelection->getIndexSelected();
|
||||
const std::string& slotPlayerName = mCurrentSlot->mProfile.mPlayerName;
|
||||
const std::string& profilePlayerName = *mCharacterSelection->getItemDataAt<std::string>(profileIndex);
|
||||
if (slotPlayerName != profilePlayerName)
|
||||
text << slotPlayerName << "\n";
|
||||
|
||||
text << "#{OMWEngine:Level} " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
|
||||
|
||||
if (mCurrentSlot->mProfile.mCurrentDay > 0)
|
||||
text << "#{Calendar:day} " << mCurrentSlot->mProfile.mCurrentDay << "\n";
|
||||
|
||||
if (mCurrentSlot->mProfile.mMaximumHealth > 0)
|
||||
text << "#{OMWEngine:Health} " << static_cast<int>(mCurrentSlot->mProfile.mCurrentHealth) << "/"
|
||||
<< static_cast<int>(mCurrentSlot->mProfile.mMaximumHealth) << "\n";
|
||||
|
||||
text << "#{OMWEngine:Level} " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
|
||||
text << "#{sCell=" << mCurrentSlot->mProfile.mPlayerCellName << "}\n";
|
||||
|
||||
int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour);
|
||||
bool pm = hour >= 12;
|
||||
if (hour >= 13)
|
||||
|
|
@ -461,20 +470,19 @@ namespace MWGui
|
|||
if (hour == 0)
|
||||
hour = 12;
|
||||
|
||||
if (mCurrentSlot->mProfile.mCurrentDay > 0)
|
||||
text << "#{Calendar:day} " << mCurrentSlot->mProfile.mCurrentDay << "\n";
|
||||
|
||||
text << mCurrentSlot->mProfile.mInGameTime.mDay << " "
|
||||
<< MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName(
|
||||
mCurrentSlot->mProfile.mInGameTime.mMonth)
|
||||
<< " " << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}");
|
||||
<< " " << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}") << "\n";
|
||||
|
||||
if (mCurrentSlot->mProfile.mTimePlayed > 0)
|
||||
{
|
||||
text << "\n"
|
||||
<< "#{OMWEngine:TimePlayed}: " << formatTimeplayed(mCurrentSlot->mProfile.mTimePlayed);
|
||||
text << "#{OMWEngine:TimePlayed}: " << formatTimeplayed(mCurrentSlot->mProfile.mTimePlayed) << "\n";
|
||||
}
|
||||
|
||||
text << Misc::fileTimeToString(mCurrentSlot->mTimeStamp, "%Y.%m.%d %T") << "\n";
|
||||
|
||||
mCellName->setCaptionWithReplacing("#{sCell=" + mCurrentSlot->mProfile.mPlayerCellName + "}");
|
||||
mInfoText->setCaptionWithReplacing(text.str());
|
||||
|
||||
// Reset the image for the case we're unable to recover a screenshot
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ namespace MWGui
|
|||
bool mSaving;
|
||||
|
||||
MyGUI::ComboBox* mCharacterSelection;
|
||||
MyGUI::EditBox* mCellName;
|
||||
MyGUI::EditBox* mInfoText;
|
||||
MyGUI::Button* mOkButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "../mwmechanics/actorutil.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/spells.hpp"
|
||||
#include "../mwmechanics/spellutil.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
|
@ -52,8 +53,8 @@ namespace MWGui
|
|||
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
||||
|
||||
int price = std::max(1,
|
||||
static_cast<int>(
|
||||
spell.mData.mCost * store.get<ESM::GameSetting>().find("fSpellValueMult")->mValue.getFloat()));
|
||||
static_cast<int>(MWMechanics::calcSpellCost(spell)
|
||||
* store.get<ESM::GameSetting>().find("fSpellValueMult")->mValue.getFloat()));
|
||||
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true);
|
||||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
|
|
@ -71,7 +72,7 @@ namespace MWGui
|
|||
mCurrentY += lineHeight;
|
||||
|
||||
toAdd->setUserData(price);
|
||||
toAdd->setCaptionWithReplacing(spell.mName + " - " + MyGUI::utility::toString(price) + "#{sgp}");
|
||||
toAdd->setCaptionWithReplacing(spell.mName + " - " + MyGUI::utility::toString(price) + "#{sgp}");
|
||||
toAdd->setSize(mSpellsView->getWidth(), lineHeight);
|
||||
toAdd->eventMouseWheel += MyGUI::newDelegate(this, &SpellBuyingWindow::onMouseWheel);
|
||||
toAdd->setUserString("ToolTipType", "Spell");
|
||||
|
|
|
|||
|
|
@ -252,22 +252,51 @@ namespace MWGui
|
|||
return;
|
||||
|
||||
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer()));
|
||||
|
||||
SpellModel::ModelIndex selected = mSpellView->getModel()->getSelectedIndex();
|
||||
if (selected < 0)
|
||||
selected = 0;
|
||||
|
||||
selected += next ? 1 : -1;
|
||||
int itemcount = mSpellView->getModel()->getItemCount();
|
||||
if (itemcount == 0)
|
||||
int itemCount = mSpellView->getModel()->getItemCount();
|
||||
if (itemCount == 0)
|
||||
return;
|
||||
selected = (selected + itemcount) % itemcount;
|
||||
|
||||
const Spell& spell = mSpellView->getModel()->getItem(selected);
|
||||
if (spell.mType == Spell::Type_EnchantedItem)
|
||||
onEnchantedItemSelected(spell.mItem, spell.mActive);
|
||||
SpellModel::ModelIndex nextIndex;
|
||||
SpellModel::ModelIndex currentIndex = mSpellView->getModel()->getSelectedIndex();
|
||||
|
||||
// If we have a selected index, search for a valid selection in the target direction
|
||||
if (currentIndex >= 0)
|
||||
{
|
||||
MWWorld::ContainerStore store;
|
||||
const Spell& currentSpell = mSpellView->getModel()->getItem(currentIndex);
|
||||
|
||||
nextIndex = currentIndex;
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
nextIndex += next ? 1 : -1;
|
||||
nextIndex = (nextIndex + itemCount) % itemCount;
|
||||
|
||||
// We can keep this selection if:
|
||||
// * we're not switching off of an enchanted item
|
||||
// * we're not switching to an enchanted item
|
||||
// * the next item wouldn't stack with the current item
|
||||
if (currentSpell.mType != Spell::Type_EnchantedItem)
|
||||
break;
|
||||
|
||||
const Spell& nextSpell = mSpellView->getModel()->getItem(nextIndex);
|
||||
if (nextSpell.mType != Spell::Type_EnchantedItem || !store.stacks(currentSpell.mItem, nextSpell.mItem))
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Otherwise, the first selection is always index 0
|
||||
else
|
||||
onSpellSelected(spell.mId);
|
||||
nextIndex = 0;
|
||||
|
||||
// Only trigger the selection event if the selection is actually changing.
|
||||
// The itemCount check earlier ensures we have at least one spell to select.
|
||||
if (nextIndex != currentIndex)
|
||||
{
|
||||
const Spell& selectedSpell = mSpellView->getModel()->getItem(nextIndex);
|
||||
if (selectedSpell.mType == Spell::Type_EnchantedItem)
|
||||
onEnchantedItemSelected(selectedSpell.mItem, selectedSpell.mActive);
|
||||
else
|
||||
onSpellSelected(selectedSpell.mId);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
|
||||
|
|
|
|||
|
|
@ -33,16 +33,10 @@ namespace MWGui
|
|||
{
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
getWidget(mPlayerGold, "PlayerGold");
|
||||
getWidget(mSelect, "Select");
|
||||
getWidget(mDestinations, "Travel");
|
||||
getWidget(mDestinationsView, "DestinationsView");
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TravelWindow::onCancelButtonClicked);
|
||||
|
||||
mDestinations->setCoord(450 / 2 - mDestinations->getTextSize().width / 2, mDestinations->getTop(),
|
||||
mDestinations->getTextSize().width, mDestinations->getHeight());
|
||||
mSelect->setCoord(8, mSelect->getTop(), mSelect->getTextSize().width, mSelect->getHeight());
|
||||
|
||||
if (Settings::gui().mControllerMenus)
|
||||
{
|
||||
mDisableGamepadCursor = true;
|
||||
|
|
@ -100,8 +94,7 @@ namespace MWGui
|
|||
|
||||
const std::string& nameString = name.getRefIdString();
|
||||
toAdd->setUserString("price", std::to_string(price));
|
||||
toAdd->setCaptionWithReplacing(
|
||||
"#{sCell=" + nameString + "} - " + MyGUI::utility::toString(price) + "#{sgp}");
|
||||
toAdd->setCaptionWithReplacing("#{sCell=" + nameString + "} - " + MyGUI::utility::toString(price) + "#{sgp}");
|
||||
toAdd->setSize(mDestinationsView->getWidth(), lineHeight);
|
||||
toAdd->eventMouseWheel += MyGUI::newDelegate(this, &TravelWindow::onMouseWheel);
|
||||
toAdd->setUserString("Destination", nameString);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ namespace MWGui
|
|||
protected:
|
||||
MyGUI::Button* mCancelButton;
|
||||
MyGUI::TextBox* mPlayerGold;
|
||||
MyGUI::TextBox* mDestinations;
|
||||
MyGUI::TextBox* mSelect;
|
||||
|
||||
std::vector<MyGUI::Button*> mDestinationButtons;
|
||||
|
||||
MyGUI::ScrollView* mDestinationsView;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <components/sdlutil/sdlcursormanager.hpp>
|
||||
#include <components/sdlutil/sdlvideowrapper.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
#include "charactercreation.hpp"
|
||||
#include "controllerbuttonsoverlay.hpp"
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ namespace MWMechanics
|
|||
if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power
|
||||
&& !isSpellActive(spell->mId))
|
||||
{
|
||||
mSpells.emplace_back(ActiveSpellParams{ spell, ptr });
|
||||
mSpells.emplace_back(ActiveSpellParams{ spell, ptr, true });
|
||||
mSpells.back().setActiveSpellId(MWBase::Environment::get().getESMStore()->generateId());
|
||||
}
|
||||
}
|
||||
|
|
@ -506,9 +506,9 @@ namespace MWMechanics
|
|||
mQueue.emplace_back(params);
|
||||
}
|
||||
|
||||
void ActiveSpells::addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor)
|
||||
void ActiveSpells::addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor, bool ignoreResistances)
|
||||
{
|
||||
mQueue.emplace_back(ActiveSpellParams{ spell, actor, true });
|
||||
mQueue.emplace_back(ActiveSpellParams{ spell, actor, ignoreResistances });
|
||||
}
|
||||
|
||||
void ActiveSpells::purge(ParamsPredicate predicate, const MWWorld::Ptr& ptr)
|
||||
|
|
|
|||
|
|
@ -137,8 +137,8 @@ namespace MWMechanics
|
|||
///
|
||||
void addSpell(const ActiveSpellParams& params);
|
||||
|
||||
/// Bypasses resistances
|
||||
void addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor);
|
||||
/// Force resistances
|
||||
void addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor, bool ignoreResistances = true);
|
||||
|
||||
/// Removes the active effects from this spell/potion/.. with \a id
|
||||
void removeEffectsBySourceSpellId(const MWWorld::Ptr& ptr, const ESM::RefId& id);
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ namespace MWMechanics
|
|||
|
||||
/// Reset pathfinding state
|
||||
void reset();
|
||||
virtual void resetInitialPosition() {}
|
||||
|
||||
/// Return if actor's rotation speed is sufficient to rotate to the destination pathpoint on the run. Otherwise
|
||||
/// actor should rotate while standing.
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ namespace MWMechanics
|
|||
const auto newTypeId = package.getTypeId();
|
||||
if (currentTypeId <= MWMechanics::AiPackageTypeId::Wander
|
||||
&& !hasPackage(MWMechanics::AiPackageTypeId::InternalTravel)
|
||||
&& (newTypeId <= MWMechanics::AiPackageTypeId::Combat || newTypeId == MWMechanics::AiPackageTypeId::Pursue
|
||||
&& (newTypeId == MWMechanics::AiPackageTypeId::Combat || newTypeId == MWMechanics::AiPackageTypeId::Pursue
|
||||
|| newTypeId == MWMechanics::AiPackageTypeId::Cast))
|
||||
{
|
||||
osg::Vec3f dest;
|
||||
|
|
@ -444,8 +444,15 @@ namespace MWMechanics
|
|||
|
||||
if ((*it)->getPriority() <= package.getPriority())
|
||||
{
|
||||
if (cancelOther && isActualAiPackage((*it)->getTypeId()))
|
||||
mAiState.reset();
|
||||
onPackageAdded(package);
|
||||
mPackages.insert(it, package.clone());
|
||||
it = mPackages.insert(it, package.clone());
|
||||
if (newTypeId == MWMechanics::AiPackageTypeId::Follow)
|
||||
{
|
||||
for (++it; it != mPackages.end(); ++it)
|
||||
(*it)->resetInitialPosition();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -455,11 +462,7 @@ namespace MWMechanics
|
|||
|
||||
// Make sure that temporary storage is empty
|
||||
if (cancelOther)
|
||||
{
|
||||
mAiState.moveIn(std::make_unique<AiCombatStorage>());
|
||||
mAiState.moveIn(std::make_unique<AiFollowStorage>());
|
||||
mAiState.moveIn(std::make_unique<AiWanderStorage>());
|
||||
}
|
||||
mAiState.reset();
|
||||
}
|
||||
|
||||
bool MWMechanics::AiSequence::isEmpty() const
|
||||
|
|
|
|||
|
|
@ -59,12 +59,7 @@ namespace MWMechanics
|
|||
mStorage = std::make_unique<Derived>(payload);
|
||||
}
|
||||
|
||||
/// \brief takes ownership of the passed object
|
||||
template <class Derived>
|
||||
void moveIn(std::unique_ptr<Derived>&& storage)
|
||||
{
|
||||
mStorage = std::move(storage);
|
||||
}
|
||||
void reset() { mStorage.reset(); }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -676,6 +676,13 @@ namespace MWMechanics
|
|||
stopMovement(actor);
|
||||
}
|
||||
|
||||
void AiWander::resetInitialPosition()
|
||||
{
|
||||
mStoredInitialActorPosition = false;
|
||||
mPathFinder.clearPath();
|
||||
mHasDestination = false;
|
||||
}
|
||||
|
||||
bool AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||
{
|
||||
if ((GroupIndex_MinIdle <= idleSelect) && (idleSelect <= GroupIndex_MaxIdle))
|
||||
|
|
@ -804,7 +811,7 @@ namespace MWMechanics
|
|||
|
||||
converter.toWorld(dest);
|
||||
|
||||
state.moveIn(std::make_unique<AiWanderStorage>());
|
||||
state.reset();
|
||||
|
||||
osg::Vec3f pos(static_cast<float>(dest.mX), static_cast<float>(dest.mY), static_cast<float>(dest.mZ));
|
||||
MWBase::Environment::get().getWorld()->moveObject(actor, pos);
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ namespace MWMechanics
|
|||
|
||||
static std::string_view getIdleGroupName(size_t index) { return sIdleSelectToGroupName[index]; }
|
||||
|
||||
void resetInitialPosition() override;
|
||||
|
||||
private:
|
||||
void stopWalking(const MWWorld::Ptr& actor);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,9 @@ namespace MWMechanics
|
|||
if (Misc::Rng::rollDice(10000, prng) < x)
|
||||
{
|
||||
// Contracted disease!
|
||||
actor.getClass().getCreatureStats(actor).getSpells().add(spell);
|
||||
MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor);
|
||||
creatureStats.getSpells().add(spell);
|
||||
creatureStats.getActiveSpells().addSpell(spell, actor, false);
|
||||
MWBase::Environment::get().getWorld()->applyLoopingParticles(actor);
|
||||
|
||||
std::string msg = MWBase::Environment::get()
|
||||
|
|
|
|||
|
|
@ -185,18 +185,18 @@ namespace MWMechanics
|
|||
*
|
||||
* Formula on UESPWiki is not entirely correct.
|
||||
*/
|
||||
float Enchanting::getEnchantPoints(bool precise) const
|
||||
std::vector<float> Enchanting::getEffectCosts() const
|
||||
{
|
||||
std::vector<float> costs;
|
||||
if (mEffectList.mList.empty())
|
||||
// No effects added, cost = 0
|
||||
return 0;
|
||||
return costs;
|
||||
|
||||
costs.reserve(mEffectList.mList.size());
|
||||
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
||||
const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
|
||||
const float fEnchantmentConstantDurationMult
|
||||
= store.get<ESM::GameSetting>().find("fEnchantmentConstantDurationMult")->mValue.getFloat();
|
||||
|
||||
float enchantmentCost = 0.f;
|
||||
float cost = 0.f;
|
||||
for (const ESM::IndexedENAMstruct& effect : mEffectList.mList)
|
||||
{
|
||||
|
|
@ -215,9 +215,18 @@ namespace MWMechanics
|
|||
if (effect.mData.mRange == ESM::RT_Target)
|
||||
cost *= 1.5f;
|
||||
|
||||
enchantmentCost += precise ? cost : std::floor(cost);
|
||||
costs.push_back(cost);
|
||||
}
|
||||
|
||||
return costs;
|
||||
}
|
||||
|
||||
float Enchanting::getEnchantPoints(bool precise) const
|
||||
{
|
||||
float enchantmentCost = 0.f;
|
||||
for (float cost : getEffectCosts())
|
||||
enchantmentCost += precise ? cost : std::floor(cost);
|
||||
|
||||
return enchantmentCost;
|
||||
}
|
||||
|
||||
|
|
@ -278,13 +287,19 @@ namespace MWMechanics
|
|||
if (mEnchanter.isEmpty())
|
||||
return 0;
|
||||
|
||||
// Use the final effect's accumulated cost
|
||||
float finalEffectCost = 0.f;
|
||||
std::vector<float> effectCosts = getEffectCosts();
|
||||
if (!effectCosts.empty())
|
||||
finalEffectCost = effectCosts.back();
|
||||
|
||||
float priceMultipler = MWBase::Environment::get()
|
||||
.getESMStore()
|
||||
->get<ESM::GameSetting>()
|
||||
.find("fEnchantmentValueMult")
|
||||
->mValue.getFloat();
|
||||
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(
|
||||
mEnchanter, static_cast<int>(getEnchantPoints() * priceMultipler), true);
|
||||
mEnchanter, static_cast<int>(finalEffectCost * priceMultipler), true);
|
||||
price *= count * getTypeMultiplier();
|
||||
return std::max(1, price);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define GAME_MWMECHANICS_ENCHANTING_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm3/effectlist.hpp>
|
||||
#include <components/esm3/loadench.hpp>
|
||||
|
|
@ -32,6 +33,7 @@ namespace MWMechanics
|
|||
float getTypeMultiplier() const;
|
||||
void payForEnchantment(int count) const;
|
||||
int getEnchantPrice(int count) const;
|
||||
std::vector<float> getEffectCosts() const;
|
||||
|
||||
public:
|
||||
Enchanting();
|
||||
|
|
|
|||
|
|
@ -1232,33 +1232,39 @@ namespace MWMechanics
|
|||
victim.getClass().getCreatureStats(victim).notifyMurder();
|
||||
|
||||
// Bounty and disposition penalty for each type of crime
|
||||
float disp = 0.f, dispVictim = 0.f;
|
||||
int bounty;
|
||||
float disp, dispVictim;
|
||||
if (type == OT_Trespassing || type == OT_SleepingInOwnedBed)
|
||||
{
|
||||
arg = store.find("iCrimeTresspass")->mValue.getInteger();
|
||||
bounty = store.find("iCrimeTresspass")->mValue.getInteger();
|
||||
disp = dispVictim = store.find("iDispTresspass")->mValue.getFloat();
|
||||
}
|
||||
else if (type == OT_Pickpocket)
|
||||
{
|
||||
arg = store.find("iCrimePickPocket")->mValue.getInteger();
|
||||
bounty = store.find("iCrimePickPocket")->mValue.getInteger();
|
||||
disp = dispVictim = store.find("fDispPickPocketMod")->mValue.getFloat();
|
||||
}
|
||||
else if (type == OT_Assault)
|
||||
{
|
||||
arg = store.find("iCrimeAttack")->mValue.getInteger();
|
||||
bounty = store.find("iCrimeAttack")->mValue.getInteger();
|
||||
disp = store.find("iDispAttackMod")->mValue.getFloat();
|
||||
dispVictim = store.find("fDispAttacking")->mValue.getFloat();
|
||||
}
|
||||
else if (type == OT_Murder)
|
||||
{
|
||||
arg = store.find("iCrimeKilling")->mValue.getInteger();
|
||||
bounty = store.find("iCrimeKilling")->mValue.getInteger();
|
||||
disp = dispVictim = store.find("iDispKilling")->mValue.getFloat();
|
||||
}
|
||||
else if (type == OT_Theft)
|
||||
{
|
||||
bounty = static_cast<int>(arg * store.find("fCrimeStealing")->mValue.getFloat());
|
||||
bounty = std::max(1, bounty); // Minimum bounty of 1, in case items with zero value are stolen
|
||||
disp = dispVictim = store.find("fDispStealing")->mValue.getFloat() * arg;
|
||||
arg = static_cast<int>(arg * store.find("fCrimeStealing")->mValue.getFloat());
|
||||
arg = std::max(1, arg); // Minimum bounty of 1, in case items with zero value are stolen
|
||||
}
|
||||
else
|
||||
{
|
||||
bounty = arg;
|
||||
disp = dispVictim = 0.f;
|
||||
}
|
||||
|
||||
// Make surrounding actors within alarm distance respond to the crime
|
||||
|
|
@ -1296,7 +1302,7 @@ namespace MWMechanics
|
|||
else if (type == OT_Murder)
|
||||
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("iFightKilling")->mValue.getInteger();
|
||||
else if (type == OT_Theft)
|
||||
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("fFightStealing")->mValue.getInteger();
|
||||
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("fFightStealing")->mValue.getInteger() * arg;
|
||||
|
||||
bool reported = false;
|
||||
|
||||
|
|
@ -1457,7 +1463,7 @@ namespace MWMechanics
|
|||
if (reported)
|
||||
{
|
||||
player.getClass().getNpcStats(player).setBounty(
|
||||
std::max(0, player.getClass().getNpcStats(player).getBounty() + arg));
|
||||
std::max(0, player.getClass().getNpcStats(player).getBounty() + bounty));
|
||||
|
||||
// If committing a crime against a faction member, expell from the faction
|
||||
if (!victim.isEmpty() && victim.getClass().isNpc())
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ namespace MWScript
|
|||
std::string_view cell = runtime.getStringLiteral(runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
// In Morrowind, using an empty string either errors out (e.g. console) or kills the game
|
||||
// so it should be reasonable to interrupt the script
|
||||
if (cell.empty())
|
||||
throw std::runtime_error("ShowMap substring must not be empty");
|
||||
|
||||
// "Will match complete or partial cells, so ShowMap, "Vivec" will show cells Vivec and Vivec, Fred's
|
||||
// House as well." http://www.uesp.net/wiki/Tes3Mod:ShowMap
|
||||
|
||||
|
|
|
|||
|
|
@ -884,8 +884,8 @@ namespace MWScript
|
|||
return;
|
||||
}
|
||||
|
||||
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
runtime.push(stats.getActiveSpells().isSpellActive(id));
|
||||
const auto& activeSpells = ptr.getClass().getCreatureStats(ptr).getActiveSpells();
|
||||
runtime.push(activeSpells.isSpellActive(id) || activeSpells.isEnchantmentActive(id));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* Reverb presets for EFX */
|
||||
|
||||
#ifndef EFX_PRESETS_H
|
||||
#define EFX_PRESETS_H
|
||||
#ifndef GAME_SOUND_EFXPRESETS_H
|
||||
#define GAME_SOUND_EFXPRESETS_H
|
||||
|
||||
#ifndef EFXEAXREVERBPROPERTIES_DEFINED
|
||||
#define EFXEAXREVERBPROPERTIES_DEFINED
|
||||
|
|
@ -852,4 +852,4 @@ typedef struct
|
|||
0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 \
|
||||
}
|
||||
|
||||
#endif /* EFX_PRESETS_H */
|
||||
#endif
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "ffmpeg_decoder.hpp"
|
||||
#include "ffmpegdecoder.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
|
@ -44,11 +44,11 @@ namespace MWSound
|
|||
av_frame_free(&ptr);
|
||||
}
|
||||
|
||||
int FFmpeg_Decoder::readPacket(void* user_data, uint8_t* buf, int buf_size)
|
||||
int FFmpegDecoder::readPacket(void* user_data, uint8_t* buf, int buf_size)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::istream& stream = *static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
||||
std::istream& stream = *static_cast<FFmpegDecoder*>(user_data)->mDataStream;
|
||||
stream.clear();
|
||||
stream.read((char*)buf, buf_size);
|
||||
std::streamsize count = stream.gcount();
|
||||
|
|
@ -65,18 +65,18 @@ namespace MWSound
|
|||
}
|
||||
|
||||
#if OPENMW_FFMPEG_CONST_WRITEPACKET
|
||||
int FFmpeg_Decoder::writePacket(void*, const uint8_t*, int)
|
||||
int FFmpegDecoder::writePacket(void*, const uint8_t*, int)
|
||||
#else
|
||||
int FFmpeg_Decoder::writePacket(void*, uint8_t*, int)
|
||||
int FFmpegDecoder::writePacket(void*, uint8_t*, int)
|
||||
#endif
|
||||
{
|
||||
Log(Debug::Error) << "can't write to read-only stream";
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t FFmpeg_Decoder::seek(void* user_data, int64_t offset, int whence)
|
||||
int64_t FFmpegDecoder::seek(void* user_data, int64_t offset, int whence)
|
||||
{
|
||||
std::istream& stream = *static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
||||
std::istream& stream = *static_cast<FFmpegDecoder*>(user_data)->mDataStream;
|
||||
|
||||
whence &= ~AVSEEK_FORCE;
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ namespace MWSound
|
|||
/* Used by getAV*Data to search for more compressed data, and buffer it in the
|
||||
* correct stream. It won't buffer data for streams that the app doesn't have a
|
||||
* handle for. */
|
||||
bool FFmpeg_Decoder::getNextPacket()
|
||||
bool FFmpegDecoder::getNextPacket()
|
||||
{
|
||||
if (!mStream)
|
||||
return false;
|
||||
|
|
@ -129,7 +129,7 @@ namespace MWSound
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FFmpeg_Decoder::getAVAudioData()
|
||||
bool FFmpegDecoder::getAVAudioData()
|
||||
{
|
||||
bool got_frame = false;
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ namespace MWSound
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t FFmpeg_Decoder::readAVAudioData(void* data, size_t length)
|
||||
size_t FFmpegDecoder::readAVAudioData(void* data, size_t length)
|
||||
{
|
||||
size_t dec = 0;
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ namespace MWSound
|
|||
return dec;
|
||||
}
|
||||
|
||||
void FFmpeg_Decoder::open(VFS::Path::NormalizedView fname)
|
||||
void FFmpegDecoder::open(VFS::Path::NormalizedView fname)
|
||||
{
|
||||
close();
|
||||
mDataStream = mResourceMgr->get(fname);
|
||||
|
|
@ -317,7 +317,7 @@ namespace MWSound
|
|||
mStream = stream;
|
||||
}
|
||||
|
||||
void FFmpeg_Decoder::close()
|
||||
void FFmpegDecoder::close()
|
||||
{
|
||||
mStream = nullptr;
|
||||
mCodecCtx.reset();
|
||||
|
|
@ -332,7 +332,7 @@ namespace MWSound
|
|||
mDataStream.reset();
|
||||
}
|
||||
|
||||
std::string FFmpeg_Decoder::getName()
|
||||
std::string FFmpegDecoder::getName()
|
||||
{
|
||||
// In the FFMpeg 4.0 a "filename" field was replaced by "url"
|
||||
#if LIBAVCODEC_VERSION_INT < 3805796
|
||||
|
|
@ -342,7 +342,7 @@ namespace MWSound
|
|||
#endif
|
||||
}
|
||||
|
||||
void FFmpeg_Decoder::getInfo(int* samplerate, ChannelConfig* chans, SampleType* type)
|
||||
void FFmpegDecoder::getInfo(int* samplerate, ChannelConfig* chans, SampleType* type)
|
||||
{
|
||||
if (!mStream)
|
||||
throw std::runtime_error("No audio stream info");
|
||||
|
|
@ -459,7 +459,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
size_t FFmpeg_Decoder::read(char* buffer, size_t bytes)
|
||||
size_t FFmpegDecoder::read(char* buffer, size_t bytes)
|
||||
{
|
||||
if (!mStream)
|
||||
{
|
||||
|
|
@ -469,7 +469,7 @@ namespace MWSound
|
|||
return readAVAudioData(buffer, bytes);
|
||||
}
|
||||
|
||||
void FFmpeg_Decoder::readAll(std::vector<char>& output)
|
||||
void FFmpegDecoder::readAll(std::vector<char>& output)
|
||||
{
|
||||
if (!mStream)
|
||||
{
|
||||
|
|
@ -490,7 +490,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
size_t FFmpeg_Decoder::getSampleOffset()
|
||||
size_t FFmpegDecoder::getSampleOffset()
|
||||
{
|
||||
#if OPENMW_FFMPEG_5_OR_GREATER
|
||||
std::size_t delay = (mFrameSize - mFramePos) / mOutputChannelLayout.nb_channels
|
||||
|
|
@ -501,8 +501,8 @@ namespace MWSound
|
|||
return static_cast<std::size_t>(mNextPts * mCodecCtx->sample_rate) - delay;
|
||||
}
|
||||
|
||||
FFmpeg_Decoder::FFmpeg_Decoder(const VFS::Manager* vfs)
|
||||
: Sound_Decoder(vfs)
|
||||
FFmpegDecoder::FFmpegDecoder(const VFS::Manager* vfs)
|
||||
: SoundDecoder(vfs)
|
||||
, mStream(nullptr)
|
||||
, mFrameSize(0)
|
||||
, mFramePos(0)
|
||||
|
|
@ -534,7 +534,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
FFmpeg_Decoder::~FFmpeg_Decoder()
|
||||
FFmpegDecoder::~FFmpegDecoder()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef GAME_SOUND_FFMPEG_DECODER_H
|
||||
#define GAME_SOUND_FFMPEG_DECODER_H
|
||||
#ifndef GAME_SOUND_FFMPEGDECODER_H
|
||||
#define GAME_SOUND_FFMPEGDECODER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ extern "C"
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "sound_decoder.hpp"
|
||||
#include "sounddecoder.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
|
@ -63,7 +63,7 @@ namespace MWSound
|
|||
|
||||
using AVFramePtr = std::unique_ptr<AVFrame, AVFrameDeleter>;
|
||||
|
||||
class FFmpeg_Decoder final : public Sound_Decoder
|
||||
class FFmpegDecoder final : public SoundDecoder
|
||||
{
|
||||
AVIOContextPtr mIoCtx;
|
||||
AVFormatContextPtr mFormatCtx;
|
||||
|
|
@ -114,13 +114,13 @@ namespace MWSound
|
|||
void readAll(std::vector<char>& output) override;
|
||||
size_t getSampleOffset() override;
|
||||
|
||||
FFmpeg_Decoder& operator=(const FFmpeg_Decoder& rhs);
|
||||
FFmpeg_Decoder(const FFmpeg_Decoder& rhs);
|
||||
FFmpegDecoder& operator=(const FFmpegDecoder& rhs);
|
||||
FFmpegDecoder(const FFmpegDecoder& rhs);
|
||||
|
||||
public:
|
||||
explicit FFmpeg_Decoder(const VFS::Manager* vfs);
|
||||
explicit FFmpegDecoder(const VFS::Manager* vfs);
|
||||
|
||||
virtual ~FFmpeg_Decoder();
|
||||
virtual ~FFmpegDecoder();
|
||||
|
||||
friend class SoundManager;
|
||||
};
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include "sound_decoder.hpp"
|
||||
#include "sounddecoder.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
||||
#include "sound_decoder.hpp"
|
||||
#include "sounddecoder.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
||||
class MovieAudioDecoder;
|
||||
class MWSoundDecoderBridge final : public Sound_Decoder
|
||||
class MWSoundDecoderBridge final : public SoundDecoder
|
||||
{
|
||||
public:
|
||||
MWSoundDecoderBridge(MWSound::MovieAudioDecoder* decoder)
|
||||
: Sound_Decoder(nullptr)
|
||||
: SoundDecoder(nullptr)
|
||||
, mDecoder(decoder)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,14 +17,13 @@
|
|||
#include <components/misc/thread.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
#include "efxpresets.h"
|
||||
#include "loudness.hpp"
|
||||
#include "openal_output.hpp"
|
||||
#include "openaloutput.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "sound_decoder.hpp"
|
||||
#include "sounddecoder.hpp"
|
||||
#include "soundmanagerimp.hpp"
|
||||
|
||||
#include "efx-presets.h"
|
||||
|
||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
#endif
|
||||
|
|
@ -301,7 +300,7 @@ namespace MWSound
|
|||
OpenAL_SoundStream(const OpenAL_SoundStream& rhs);
|
||||
OpenAL_SoundStream& operator=(const OpenAL_SoundStream& rhs);
|
||||
|
||||
friend class OpenAL_Output;
|
||||
friend class OpenALOutput;
|
||||
|
||||
public:
|
||||
OpenAL_SoundStream(ALuint src, DecoderPtr decoder);
|
||||
|
|
@ -323,7 +322,7 @@ namespace MWSound
|
|||
//
|
||||
// A background streaming thread (keeps active streams processed)
|
||||
//
|
||||
struct OpenAL_Output::StreamThread
|
||||
struct OpenALOutput::StreamThread
|
||||
{
|
||||
std::vector<OpenAL_SoundStream*> mStreams;
|
||||
|
||||
|
|
@ -393,13 +392,13 @@ namespace MWSound
|
|||
StreamThread& operator=(const StreamThread& rhs) = delete;
|
||||
};
|
||||
|
||||
class OpenAL_Output::DefaultDeviceThread
|
||||
class OpenALOutput::DefaultDeviceThread
|
||||
{
|
||||
public:
|
||||
std::basic_string<ALCchar> mCurrentName;
|
||||
|
||||
private:
|
||||
OpenAL_Output& mOutput;
|
||||
OpenALOutput& mOutput;
|
||||
|
||||
std::atomic<bool> mQuitNow;
|
||||
std::mutex mMutex;
|
||||
|
|
@ -433,7 +432,7 @@ namespace MWSound
|
|||
}
|
||||
|
||||
public:
|
||||
DefaultDeviceThread(OpenAL_Output& output, std::basic_string_view<ALCchar> name = {})
|
||||
DefaultDeviceThread(OpenALOutput& output, std::basic_string_view<ALCchar> name = {})
|
||||
: mCurrentName(name)
|
||||
, mOutput(output)
|
||||
, mQuitNow(false)
|
||||
|
|
@ -655,7 +654,7 @@ namespace MWSound
|
|||
//
|
||||
// An OpenAL output device
|
||||
//
|
||||
std::vector<std::string> OpenAL_Output::enumerate()
|
||||
std::vector<std::string> OpenALOutput::enumerate()
|
||||
{
|
||||
std::vector<std::string> devlist;
|
||||
const ALCchar* devnames;
|
||||
|
|
@ -672,14 +671,14 @@ namespace MWSound
|
|||
return devlist;
|
||||
}
|
||||
|
||||
void OpenAL_Output::eventCallback(
|
||||
void OpenALOutput::eventCallback(
|
||||
ALenum eventType, ALuint object, ALuint param, ALsizei length, const ALchar* message, void* userParam)
|
||||
{
|
||||
if (eventType == AL_EVENT_TYPE_DISCONNECTED_SOFT)
|
||||
static_cast<OpenAL_Output*>(userParam)->onDisconnect();
|
||||
static_cast<OpenALOutput*>(userParam)->onDisconnect();
|
||||
}
|
||||
|
||||
void OpenAL_Output::onDisconnect()
|
||||
void OpenALOutput::onDisconnect()
|
||||
{
|
||||
if (!mInitialized || !alcReopenDeviceSOFT)
|
||||
return;
|
||||
|
|
@ -702,7 +701,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
bool OpenAL_Output::init(const std::string& devname, const std::string& hrtfname, HrtfMode hrtfmode)
|
||||
bool OpenALOutput::init(const std::string& devname, const std::string& hrtfname, HrtfMode hrtfmode)
|
||||
{
|
||||
deinit();
|
||||
std::lock_guard<std::mutex> lock(mReopenMutex);
|
||||
|
|
@ -802,7 +801,7 @@ namespace MWSound
|
|||
{
|
||||
static const std::array<ALenum, 1> events{ { AL_EVENT_TYPE_DISCONNECTED_SOFT } };
|
||||
alEventControlSOFT(events.size(), events.data(), AL_TRUE);
|
||||
alEventCallbackSOFT(&OpenAL_Output::eventCallback, this);
|
||||
alEventCallbackSOFT(&OpenALOutput::eventCallback, this);
|
||||
}
|
||||
else
|
||||
Log(Debug::Warning) << "Cannot detect audio device changes";
|
||||
|
|
@ -970,7 +969,7 @@ namespace MWSound
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenAL_Output::deinit()
|
||||
void OpenALOutput::deinit()
|
||||
{
|
||||
mStreamThread->removeAll();
|
||||
mDefaultDeviceThread.reset();
|
||||
|
|
@ -1006,7 +1005,7 @@ namespace MWSound
|
|||
mInitialized = false;
|
||||
}
|
||||
|
||||
std::vector<std::string> OpenAL_Output::enumerateHrtf()
|
||||
std::vector<std::string> OpenALOutput::enumerateHrtf()
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
|
|
@ -1028,7 +1027,7 @@ namespace MWSound
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::pair<Sound_Handle, size_t> OpenAL_Output::loadSound(VFS::Path::NormalizedView fname)
|
||||
std::pair<Sound_Handle, size_t> OpenALOutput::loadSound(VFS::Path::NormalizedView fname)
|
||||
{
|
||||
getALError();
|
||||
|
||||
|
|
@ -1076,7 +1075,7 @@ namespace MWSound
|
|||
return std::make_pair(MAKE_PTRID(buf), size);
|
||||
}
|
||||
|
||||
size_t OpenAL_Output::unloadSound(Sound_Handle data)
|
||||
size_t OpenALOutput::unloadSound(Sound_Handle data)
|
||||
{
|
||||
ALuint buffer = GET_PTRID(data);
|
||||
if (!buffer)
|
||||
|
|
@ -1105,7 +1104,7 @@ namespace MWSound
|
|||
return size;
|
||||
}
|
||||
|
||||
void OpenAL_Output::initCommon2D(
|
||||
void OpenALOutput::initCommon2D(
|
||||
ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv)
|
||||
{
|
||||
alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f);
|
||||
|
|
@ -1143,7 +1142,7 @@ namespace MWSound
|
|||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void OpenAL_Output::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist,
|
||||
void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist,
|
||||
ALfloat gain, ALfloat pitch, bool loop, bool useenv)
|
||||
{
|
||||
alSourcef(source, AL_REFERENCE_DISTANCE, mindist);
|
||||
|
|
@ -1183,7 +1182,7 @@ namespace MWSound
|
|||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void OpenAL_Output::updateCommon(
|
||||
void OpenALOutput::updateCommon(
|
||||
ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv)
|
||||
{
|
||||
if (useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
|
||||
|
|
@ -1199,7 +1198,7 @@ namespace MWSound
|
|||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
bool OpenAL_Output::playSound(Sound* sound, Sound_Handle data, float offset)
|
||||
bool OpenALOutput::playSound(Sound* sound, Sound_Handle data, float offset)
|
||||
{
|
||||
ALuint source;
|
||||
|
||||
|
|
@ -1238,7 +1237,7 @@ namespace MWSound
|
|||
return true;
|
||||
}
|
||||
|
||||
bool OpenAL_Output::playSound3D(Sound* sound, Sound_Handle data, float offset)
|
||||
bool OpenALOutput::playSound3D(Sound* sound, Sound_Handle data, float offset)
|
||||
{
|
||||
ALuint source;
|
||||
|
||||
|
|
@ -1277,7 +1276,7 @@ namespace MWSound
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenAL_Output::finishSound(Sound* sound)
|
||||
void OpenALOutput::finishSound(Sound* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return;
|
||||
|
|
@ -1294,7 +1293,7 @@ namespace MWSound
|
|||
mActiveSounds.erase(std::find(mActiveSounds.begin(), mActiveSounds.end(), sound));
|
||||
}
|
||||
|
||||
bool OpenAL_Output::isSoundPlaying(Sound* sound)
|
||||
bool OpenALOutput::isSoundPlaying(Sound* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return false;
|
||||
|
|
@ -1307,7 +1306,7 @@ namespace MWSound
|
|||
return state == AL_PLAYING || state == AL_PAUSED;
|
||||
}
|
||||
|
||||
void OpenAL_Output::updateSound(Sound* sound)
|
||||
void OpenALOutput::updateSound(Sound* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return;
|
||||
|
|
@ -1318,7 +1317,7 @@ namespace MWSound
|
|||
getALError();
|
||||
}
|
||||
|
||||
bool OpenAL_Output::streamSound(DecoderPtr decoder, Stream* sound, bool getLoudnessData)
|
||||
bool OpenALOutput::streamSound(DecoderPtr decoder, Stream* sound, bool getLoudnessData)
|
||||
{
|
||||
if (mFreeSources.empty())
|
||||
{
|
||||
|
|
@ -1349,7 +1348,7 @@ namespace MWSound
|
|||
return true;
|
||||
}
|
||||
|
||||
bool OpenAL_Output::streamSound3D(DecoderPtr decoder, Stream* sound, bool getLoudnessData)
|
||||
bool OpenALOutput::streamSound3D(DecoderPtr decoder, Stream* sound, bool getLoudnessData)
|
||||
{
|
||||
if (mFreeSources.empty())
|
||||
{
|
||||
|
|
@ -1380,7 +1379,7 @@ namespace MWSound
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenAL_Output::finishStream(Stream* sound)
|
||||
void OpenALOutput::finishStream(Stream* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return;
|
||||
|
|
@ -1402,7 +1401,7 @@ namespace MWSound
|
|||
delete stream;
|
||||
}
|
||||
|
||||
double OpenAL_Output::getStreamDelay(Stream* sound)
|
||||
double OpenALOutput::getStreamDelay(Stream* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return 0.0;
|
||||
|
|
@ -1410,7 +1409,7 @@ namespace MWSound
|
|||
return stream->getStreamDelay();
|
||||
}
|
||||
|
||||
double OpenAL_Output::getStreamOffset(Stream* sound)
|
||||
double OpenALOutput::getStreamOffset(Stream* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return 0.0;
|
||||
|
|
@ -1419,7 +1418,7 @@ namespace MWSound
|
|||
return stream->getStreamOffset();
|
||||
}
|
||||
|
||||
float OpenAL_Output::getStreamLoudness(Stream* sound)
|
||||
float OpenALOutput::getStreamLoudness(Stream* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return 0.0;
|
||||
|
|
@ -1428,7 +1427,7 @@ namespace MWSound
|
|||
return stream->getCurrentLoudness();
|
||||
}
|
||||
|
||||
bool OpenAL_Output::isStreamPlaying(Stream* sound)
|
||||
bool OpenALOutput::isStreamPlaying(Stream* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return false;
|
||||
|
|
@ -1437,7 +1436,7 @@ namespace MWSound
|
|||
return stream->isPlaying();
|
||||
}
|
||||
|
||||
void OpenAL_Output::updateStream(Stream* sound)
|
||||
void OpenALOutput::updateStream(Stream* sound)
|
||||
{
|
||||
if (!sound->mHandle)
|
||||
return;
|
||||
|
|
@ -1449,17 +1448,17 @@ namespace MWSound
|
|||
getALError();
|
||||
}
|
||||
|
||||
void OpenAL_Output::startUpdate()
|
||||
void OpenALOutput::startUpdate()
|
||||
{
|
||||
alcSuspendContext(alcGetCurrentContext());
|
||||
}
|
||||
|
||||
void OpenAL_Output::finishUpdate()
|
||||
void OpenALOutput::finishUpdate()
|
||||
{
|
||||
alcProcessContext(alcGetCurrentContext());
|
||||
}
|
||||
|
||||
void OpenAL_Output::updateListener(
|
||||
void OpenALOutput::updateListener(
|
||||
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env)
|
||||
{
|
||||
if (mContext)
|
||||
|
|
@ -1501,7 +1500,7 @@ namespace MWSound
|
|||
mListenerEnv = env;
|
||||
}
|
||||
|
||||
void OpenAL_Output::pauseSounds(int types)
|
||||
void OpenALOutput::pauseSounds(int types)
|
||||
{
|
||||
std::vector<ALuint> sources;
|
||||
for (Sound* sound : mActiveSounds)
|
||||
|
|
@ -1524,7 +1523,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
void OpenAL_Output::pauseActiveDevice()
|
||||
void OpenALOutput::pauseActiveDevice()
|
||||
{
|
||||
if (mDevice == nullptr)
|
||||
return;
|
||||
|
|
@ -1540,7 +1539,7 @@ namespace MWSound
|
|||
alListenerf(AL_GAIN, 0.0f);
|
||||
}
|
||||
|
||||
void OpenAL_Output::resumeActiveDevice()
|
||||
void OpenALOutput::resumeActiveDevice()
|
||||
{
|
||||
if (mDevice == nullptr)
|
||||
return;
|
||||
|
|
@ -1556,7 +1555,7 @@ namespace MWSound
|
|||
alListenerf(AL_GAIN, 1.0f);
|
||||
}
|
||||
|
||||
void OpenAL_Output::resumeSounds(int types)
|
||||
void OpenALOutput::resumeSounds(int types)
|
||||
{
|
||||
std::vector<ALuint> sources;
|
||||
for (Sound* sound : mActiveSounds)
|
||||
|
|
@ -1579,8 +1578,8 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
OpenAL_Output::OpenAL_Output(SoundManager& mgr)
|
||||
: Sound_Output(mgr)
|
||||
OpenALOutput::OpenALOutput(SoundManager& mgr)
|
||||
: SoundOutput(mgr)
|
||||
, mDevice(nullptr)
|
||||
, mContext(nullptr)
|
||||
, mListenerPos(0.0f, 0.0f, 0.0f)
|
||||
|
|
@ -1593,12 +1592,12 @@ namespace MWSound
|
|||
{
|
||||
}
|
||||
|
||||
OpenAL_Output::~OpenAL_Output()
|
||||
OpenALOutput::~OpenALOutput()
|
||||
{
|
||||
OpenAL_Output::deinit();
|
||||
OpenALOutput::deinit();
|
||||
}
|
||||
|
||||
float OpenAL_Output::getTimeScaledPitch(SoundBase* sound)
|
||||
float OpenALOutput::getTimeScaledPitch(SoundBase* sound)
|
||||
{
|
||||
const bool shouldScale = !(sound->mParams.mFlags & PlayMode::NoScaling);
|
||||
return shouldScale ? sound->getPitch() * mManager.getSimulationTimeScale() : sound->getPitch();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef GAME_SOUND_OPENAL_OUTPUT_H
|
||||
#define GAME_SOUND_OPENAL_OUTPUT_H
|
||||
#ifndef GAME_SOUND_OPENALOUTPUT_H
|
||||
#define GAME_SOUND_OPENALOUTPUT_H
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#include "alc.h"
|
||||
#include "alext.h"
|
||||
|
||||
#include "sound_output.hpp"
|
||||
#include "soundoutput.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
|
@ -22,7 +22,7 @@ namespace MWSound
|
|||
class Sound;
|
||||
class Stream;
|
||||
|
||||
class OpenAL_Output : public Sound_Output
|
||||
class OpenALOutput : public SoundOutput
|
||||
{
|
||||
ALCdevice* mDevice;
|
||||
ALCcontext* mContext;
|
||||
|
|
@ -72,8 +72,8 @@ namespace MWSound
|
|||
|
||||
float getTimeScaledPitch(SoundBase* sound);
|
||||
|
||||
OpenAL_Output& operator=(const OpenAL_Output& rhs);
|
||||
OpenAL_Output(const OpenAL_Output& rhs);
|
||||
OpenALOutput& operator=(const OpenALOutput& rhs);
|
||||
OpenALOutput(const OpenALOutput& rhs);
|
||||
|
||||
static void eventCallback(
|
||||
ALenum eventType, ALuint object, ALuint param, ALsizei length, const ALchar* message, void* userParam);
|
||||
|
|
@ -117,8 +117,8 @@ namespace MWSound
|
|||
void pauseActiveDevice() override;
|
||||
void resumeActiveDevice() override;
|
||||
|
||||
OpenAL_Output(SoundManager& mgr);
|
||||
virtual ~OpenAL_Output();
|
||||
OpenALOutput(SoundManager& mgr);
|
||||
virtual ~OpenALOutput();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "sound_output.hpp"
|
||||
#include "soundoutput.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
|
@ -53,7 +53,7 @@ namespace MWSound
|
|||
protected:
|
||||
Sound_Instance mHandle = nullptr;
|
||||
|
||||
friend class OpenAL_Output;
|
||||
friend class OpenALOutput;
|
||||
|
||||
public:
|
||||
void setPosition(const osg::Vec3f& pos) { mParams.mPos = pos; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "sound_buffer.hpp"
|
||||
#include "soundbuffer.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
|
@ -35,7 +35,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
SoundBufferPool::SoundBufferPool(Sound_Output& output)
|
||||
SoundBufferPool::SoundBufferPool(SoundOutput& output)
|
||||
: mOutput(&output)
|
||||
, mBufferCacheMax(Settings::sound().mBufferCacheMax * 1024 * 1024)
|
||||
, mBufferCacheMin(
|
||||
|
|
@ -48,31 +48,31 @@ namespace MWSound
|
|||
clear();
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::lookup(const ESM::RefId& soundId) const
|
||||
SoundBuffer* SoundBufferPool::lookup(const ESM::RefId& soundId) const
|
||||
{
|
||||
const auto it = mBufferNameMap.find(soundId);
|
||||
if (it != mBufferNameMap.end())
|
||||
{
|
||||
Sound_Buffer* sfx = it->second;
|
||||
SoundBuffer* sfx = it->second;
|
||||
if (sfx->getHandle() != nullptr)
|
||||
return sfx;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::lookup(std::string_view fileName) const
|
||||
SoundBuffer* SoundBufferPool::lookup(std::string_view fileName) const
|
||||
{
|
||||
const auto it = mBufferFileNameMap.find(std::string(fileName));
|
||||
if (it != mBufferFileNameMap.end())
|
||||
{
|
||||
Sound_Buffer* sfx = it->second;
|
||||
SoundBuffer* sfx = it->second;
|
||||
if (sfx->getHandle() != nullptr)
|
||||
return sfx;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::loadSfx(Sound_Buffer* sfx)
|
||||
SoundBuffer* SoundBufferPool::loadSfx(SoundBuffer* sfx)
|
||||
{
|
||||
if (sfx->getHandle() != nullptr)
|
||||
return sfx;
|
||||
|
|
@ -95,7 +95,7 @@ namespace MWSound
|
|||
return sfx;
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::load(const ESM::RefId& soundId)
|
||||
SoundBuffer* SoundBufferPool::load(const ESM::RefId& soundId)
|
||||
{
|
||||
if (mBufferNameMap.empty())
|
||||
{
|
||||
|
|
@ -103,7 +103,7 @@ namespace MWSound
|
|||
insertSound(sound.mId, sound);
|
||||
}
|
||||
|
||||
Sound_Buffer* sfx;
|
||||
SoundBuffer* sfx;
|
||||
const auto it = mBufferNameMap.find(soundId);
|
||||
if (it != mBufferNameMap.end())
|
||||
sfx = it->second;
|
||||
|
|
@ -118,9 +118,9 @@ namespace MWSound
|
|||
return loadSfx(sfx);
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::load(std::string_view fileName)
|
||||
SoundBuffer* SoundBufferPool::load(std::string_view fileName)
|
||||
{
|
||||
Sound_Buffer* sfx;
|
||||
SoundBuffer* sfx;
|
||||
const auto it = mBufferFileNameMap.find(std::string(fileName));
|
||||
if (it != mBufferFileNameMap.end())
|
||||
sfx = it->second;
|
||||
|
|
@ -146,7 +146,7 @@ namespace MWSound
|
|||
mUnusedBuffers.clear();
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::insertSound(std::string_view fileName)
|
||||
SoundBuffer* SoundBufferPool::insertSound(std::string_view fileName)
|
||||
{
|
||||
static const AudioParams audioParams
|
||||
= makeAudioParams(MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>());
|
||||
|
|
@ -158,13 +158,13 @@ namespace MWSound
|
|||
min = std::max(min, 1.0f);
|
||||
max = std::max(min, max);
|
||||
|
||||
Sound_Buffer& sfx = mSoundBuffers.emplace_back(fileName, volume, min, max);
|
||||
SoundBuffer& sfx = mSoundBuffers.emplace_back(fileName, volume, min, max);
|
||||
|
||||
mBufferFileNameMap.emplace(fileName, &sfx);
|
||||
return &sfx;
|
||||
}
|
||||
|
||||
Sound_Buffer* SoundBufferPool::insertSound(const ESM::RefId& soundId, const ESM::Sound& sound)
|
||||
SoundBuffer* SoundBufferPool::insertSound(const ESM::RefId& soundId, const ESM::Sound& sound)
|
||||
{
|
||||
static const AudioParams audioParams
|
||||
= makeAudioParams(MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>());
|
||||
|
|
@ -183,7 +183,7 @@ namespace MWSound
|
|||
min = std::max(min, 1.0f);
|
||||
max = std::max(min, max);
|
||||
|
||||
Sound_Buffer& sfx = mSoundBuffers.emplace_back(
|
||||
SoundBuffer& sfx = mSoundBuffers.emplace_back(
|
||||
Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normalized(sound.mSound)), volume, min, max);
|
||||
|
||||
mBufferNameMap.emplace(soundId, &sfx);
|
||||
|
|
@ -194,7 +194,7 @@ namespace MWSound
|
|||
{
|
||||
while (!mUnusedBuffers.empty() && mBufferCacheSize > mBufferCacheMin)
|
||||
{
|
||||
Sound_Buffer* const unused = mUnusedBuffers.back();
|
||||
SoundBuffer* const unused = mUnusedBuffers.back();
|
||||
|
||||
mBufferCacheSize -= mOutput->unloadSound(unused->getHandle());
|
||||
unused->mHandle = nullptr;
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
#ifndef GAME_SOUND_SOUND_BUFFER_H
|
||||
#define GAME_SOUND_SOUND_BUFFER_H
|
||||
#ifndef GAME_SOUND_SOUNDBUFFER_H
|
||||
#define GAME_SOUND_SOUNDBUFFER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "sound_output.hpp"
|
||||
#include <components/esm/refid.hpp>
|
||||
|
||||
#include "soundoutput.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Sound;
|
||||
|
|
@ -23,11 +24,11 @@ namespace MWSound
|
|||
{
|
||||
class SoundBufferPool;
|
||||
|
||||
class Sound_Buffer
|
||||
class SoundBuffer
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
Sound_Buffer(T&& resname, float volume, float mindist, float maxdist)
|
||||
SoundBuffer(T&& resname, float volume, float mindist, float maxdist)
|
||||
: mResourceName(std::forward<T>(resname))
|
||||
, mVolume(volume)
|
||||
, mMinDist(mindist)
|
||||
|
|
@ -59,7 +60,7 @@ namespace MWSound
|
|||
class SoundBufferPool
|
||||
{
|
||||
public:
|
||||
SoundBufferPool(Sound_Output& output);
|
||||
SoundBufferPool(SoundOutput& output);
|
||||
|
||||
SoundBufferPool(const SoundBufferPool&) = delete;
|
||||
|
||||
|
|
@ -67,20 +68,20 @@ namespace MWSound
|
|||
|
||||
/// Lookup a soundId for its sound data (resource name, local volume,
|
||||
/// minRange, and maxRange)
|
||||
Sound_Buffer* lookup(const ESM::RefId& soundId) const;
|
||||
SoundBuffer* lookup(const ESM::RefId& soundId) const;
|
||||
|
||||
/// Lookup a sound by file name for its sound data (resource name, local volume,
|
||||
/// minRange, and maxRange)
|
||||
Sound_Buffer* lookup(std::string_view fileName) const;
|
||||
SoundBuffer* lookup(std::string_view fileName) const;
|
||||
|
||||
/// Lookup a soundId for its sound data (resource name, local volume,
|
||||
/// minRange, and maxRange), and ensure it's ready for use.
|
||||
Sound_Buffer* load(const ESM::RefId& soundId);
|
||||
SoundBuffer* load(const ESM::RefId& soundId);
|
||||
|
||||
// Lookup for a sound by file name, and ensure it's ready for use.
|
||||
Sound_Buffer* load(std::string_view fileName);
|
||||
SoundBuffer* load(std::string_view fileName);
|
||||
|
||||
void use(Sound_Buffer& sfx)
|
||||
void use(SoundBuffer& sfx)
|
||||
{
|
||||
if (sfx.mUses++ == 0)
|
||||
{
|
||||
|
|
@ -90,7 +91,7 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
void release(Sound_Buffer& sfx)
|
||||
void release(SoundBuffer& sfx)
|
||||
{
|
||||
if (--sfx.mUses == 0)
|
||||
mUnusedBuffers.push_front(&sfx);
|
||||
|
|
@ -99,23 +100,23 @@ namespace MWSound
|
|||
void clear();
|
||||
|
||||
private:
|
||||
Sound_Buffer* loadSfx(Sound_Buffer* sfx);
|
||||
SoundBuffer* loadSfx(SoundBuffer* sfx);
|
||||
|
||||
Sound_Output* mOutput;
|
||||
std::deque<Sound_Buffer> mSoundBuffers;
|
||||
std::unordered_map<ESM::RefId, Sound_Buffer*> mBufferNameMap;
|
||||
std::unordered_map<std::string, Sound_Buffer*> mBufferFileNameMap;
|
||||
SoundOutput* mOutput;
|
||||
std::deque<SoundBuffer> mSoundBuffers;
|
||||
std::unordered_map<ESM::RefId, SoundBuffer*> mBufferNameMap;
|
||||
std::unordered_map<std::string, SoundBuffer*> mBufferFileNameMap;
|
||||
std::size_t mBufferCacheMax;
|
||||
std::size_t mBufferCacheMin;
|
||||
std::size_t mBufferCacheSize = 0;
|
||||
// NOTE: unused buffers are stored in front-newest order.
|
||||
std::deque<Sound_Buffer*> mUnusedBuffers;
|
||||
std::deque<SoundBuffer*> mUnusedBuffers;
|
||||
|
||||
inline Sound_Buffer* insertSound(const ESM::RefId& soundId, const ESM::Sound& sound);
|
||||
inline Sound_Buffer* insertSound(std::string_view fileName);
|
||||
inline SoundBuffer* insertSound(const ESM::RefId& soundId, const ESM::Sound& sound);
|
||||
inline SoundBuffer* insertSound(std::string_view fileName);
|
||||
|
||||
inline void unloadUnused();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* GAME_SOUND_SOUND_BUFFER_H */
|
||||
#endif /* GAME_SOUND_SOUNDBUFFER_H */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef GAME_SOUND_SOUND_DECODER_H
|
||||
#define GAME_SOUND_SOUND_DECODER_H
|
||||
#ifndef GAME_SOUND_SOUNDDECODER_H
|
||||
#define GAME_SOUND_SOUNDDECODER_H
|
||||
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ namespace MWSound
|
|||
size_t framesToBytes(size_t frames, ChannelConfig config, SampleType type);
|
||||
size_t bytesToFrames(size_t bytes, ChannelConfig config, SampleType type);
|
||||
|
||||
struct Sound_Decoder
|
||||
struct SoundDecoder
|
||||
{
|
||||
const VFS::Manager* mResourceMgr;
|
||||
|
||||
|
|
@ -48,15 +48,15 @@ namespace MWSound
|
|||
virtual void readAll(std::vector<char>& output);
|
||||
virtual size_t getSampleOffset() = 0;
|
||||
|
||||
Sound_Decoder(const VFS::Manager* resourceMgr)
|
||||
SoundDecoder(const VFS::Manager* resourceMgr)
|
||||
: mResourceMgr(resourceMgr)
|
||||
{
|
||||
}
|
||||
virtual ~Sound_Decoder() {}
|
||||
virtual ~SoundDecoder() {}
|
||||
|
||||
private:
|
||||
Sound_Decoder(const Sound_Decoder& rhs);
|
||||
Sound_Decoder& operator=(const Sound_Decoder& rhs);
|
||||
SoundDecoder(const SoundDecoder& rhs);
|
||||
SoundDecoder& operator=(const SoundDecoder& rhs);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -26,12 +26,12 @@
|
|||
#include "../mwmechanics/actorutil.hpp"
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "ffmpeg_decoder.hpp"
|
||||
#include "openal_output.hpp"
|
||||
#include "ffmpegdecoder.hpp"
|
||||
#include "openaloutput.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "sound_buffer.hpp"
|
||||
#include "sound_decoder.hpp"
|
||||
#include "sound_output.hpp"
|
||||
#include "soundbuffer.hpp"
|
||||
#include "sounddecoder.hpp"
|
||||
#include "soundoutput.hpp"
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
|
|
@ -57,7 +57,7 @@ namespace MWSound
|
|||
return settings;
|
||||
}
|
||||
|
||||
float initialFadeVolume(float squaredDist, Sound_Buffer* sfx, Type type, PlayMode mode)
|
||||
float initialFadeVolume(float squaredDist, SoundBuffer* sfx, Type type, PlayMode mode)
|
||||
{
|
||||
// If a sound is farther away than its maximum distance, start playing it with a zero fade volume.
|
||||
// It can still become audible once the player moves closer.
|
||||
|
|
@ -111,7 +111,7 @@ namespace MWSound
|
|||
|
||||
SoundManager::SoundManager(const VFS::Manager* vfs, bool useSound)
|
||||
: mVFS(vfs)
|
||||
, mOutput(std::make_unique<OpenAL_Output>(*this))
|
||||
, mOutput(std::make_unique<OpenALOutput>(*this))
|
||||
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
|
||||
, mSoundBuffers(*mOutput)
|
||||
, mMusicType(MWSound::MusicType::Normal)
|
||||
|
|
@ -169,7 +169,7 @@ namespace MWSound
|
|||
// Return a new decoder instance, used as needed by the output implementations
|
||||
DecoderPtr SoundManager::getDecoder()
|
||||
{
|
||||
return std::make_shared<FFmpeg_Decoder>(mVFS);
|
||||
return std::make_shared<FFmpegDecoder>(mVFS);
|
||||
}
|
||||
|
||||
DecoderPtr SoundManager::loadVoice(VFS::Path::NormalizedView voicefile)
|
||||
|
|
@ -459,7 +459,7 @@ namespace MWSound
|
|||
return false;
|
||||
}
|
||||
|
||||
Sound* SoundManager::playSound(Sound_Buffer* sfx, float volume, float pitch, Type type, PlayMode mode, float offset)
|
||||
Sound* SoundManager::playSound(SoundBuffer* sfx, float volume, float pitch, Type type, PlayMode mode, float offset)
|
||||
{
|
||||
if (!mOutput->isInitialized())
|
||||
return nullptr;
|
||||
|
|
@ -495,7 +495,7 @@ namespace MWSound
|
|||
if (!mVFS->exists(normalizedName))
|
||||
return nullptr;
|
||||
|
||||
Sound_Buffer* sfx = mSoundBuffers.load(normalizedName);
|
||||
SoundBuffer* sfx = mSoundBuffers.load(normalizedName);
|
||||
if (!sfx)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -508,14 +508,14 @@ namespace MWSound
|
|||
if (!mOutput->isInitialized())
|
||||
return nullptr;
|
||||
|
||||
Sound_Buffer* sfx = mSoundBuffers.load(soundId);
|
||||
SoundBuffer* sfx = mSoundBuffers.load(soundId);
|
||||
if (!sfx)
|
||||
return nullptr;
|
||||
|
||||
return playSound(sfx, volume, pitch, type, mode, offset);
|
||||
}
|
||||
|
||||
Sound* SoundManager::playSound3D(const MWWorld::ConstPtr& ptr, Sound_Buffer* sfx, float volume, float pitch,
|
||||
Sound* SoundManager::playSound3D(const MWWorld::ConstPtr& ptr, SoundBuffer* sfx, float volume, float pitch,
|
||||
Type type, PlayMode mode, float offset)
|
||||
{
|
||||
if (!mOutput->isInitialized())
|
||||
|
|
@ -576,7 +576,7 @@ namespace MWSound
|
|||
return nullptr;
|
||||
|
||||
// Look up the sound in the ESM data
|
||||
Sound_Buffer* sfx = mSoundBuffers.load(soundId);
|
||||
SoundBuffer* sfx = mSoundBuffers.load(soundId);
|
||||
if (!sfx)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -594,7 +594,7 @@ namespace MWSound
|
|||
if (!mVFS->exists(normalizedName))
|
||||
return nullptr;
|
||||
|
||||
Sound_Buffer* sfx = mSoundBuffers.load(normalizedName);
|
||||
SoundBuffer* sfx = mSoundBuffers.load(normalizedName);
|
||||
if (!sfx)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -608,7 +608,7 @@ namespace MWSound
|
|||
return nullptr;
|
||||
|
||||
// Look up the sound in the ESM data
|
||||
Sound_Buffer* sfx = mSoundBuffers.load(soundId);
|
||||
SoundBuffer* sfx = mSoundBuffers.load(soundId);
|
||||
if (!sfx)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -642,7 +642,7 @@ namespace MWSound
|
|||
mOutput->finishSound(sound);
|
||||
}
|
||||
|
||||
void SoundManager::stopSound(Sound_Buffer* sfx, const MWWorld::ConstPtr& ptr)
|
||||
void SoundManager::stopSound(SoundBuffer* sfx, const MWWorld::ConstPtr& ptr)
|
||||
{
|
||||
SoundMap::iterator snditer = mActiveSounds.find(ptr.mRef);
|
||||
if (snditer != mActiveSounds.end())
|
||||
|
|
@ -660,7 +660,7 @@ namespace MWSound
|
|||
if (!mOutput->isInitialized())
|
||||
return;
|
||||
|
||||
Sound_Buffer* sfx = mSoundBuffers.lookup(soundId);
|
||||
SoundBuffer* sfx = mSoundBuffers.lookup(soundId);
|
||||
if (!sfx)
|
||||
return;
|
||||
|
||||
|
|
@ -673,7 +673,7 @@ namespace MWSound
|
|||
return;
|
||||
|
||||
std::string normalizedName = VFS::Path::normalizeFilename(fileName);
|
||||
Sound_Buffer* sfx = mSoundBuffers.lookup(normalizedName);
|
||||
SoundBuffer* sfx = mSoundBuffers.lookup(normalizedName);
|
||||
if (!sfx)
|
||||
return;
|
||||
|
||||
|
|
@ -725,7 +725,7 @@ namespace MWSound
|
|||
SoundMap::iterator snditer = mActiveSounds.find(ptr.mRef);
|
||||
if (snditer != mActiveSounds.end())
|
||||
{
|
||||
Sound_Buffer* sfx = mSoundBuffers.lookup(soundId);
|
||||
SoundBuffer* sfx = mSoundBuffers.lookup(soundId);
|
||||
if (sfx == nullptr)
|
||||
return;
|
||||
for (SoundBufferRefPair& sndbuf : snditer->second.mList)
|
||||
|
|
@ -743,7 +743,7 @@ namespace MWSound
|
|||
SoundMap::const_iterator snditer = mActiveSounds.find(ptr.mRef);
|
||||
if (snditer != mActiveSounds.end())
|
||||
{
|
||||
Sound_Buffer* sfx = mSoundBuffers.lookup(normalizedName);
|
||||
SoundBuffer* sfx = mSoundBuffers.lookup(normalizedName);
|
||||
if (!sfx)
|
||||
return false;
|
||||
|
||||
|
|
@ -761,7 +761,7 @@ namespace MWSound
|
|||
SoundMap::const_iterator snditer = mActiveSounds.find(ptr.mRef);
|
||||
if (snditer != mActiveSounds.end())
|
||||
{
|
||||
Sound_Buffer* sfx = mSoundBuffers.lookup(soundId);
|
||||
SoundBuffer* sfx = mSoundBuffers.lookup(soundId);
|
||||
if (!sfx)
|
||||
return false;
|
||||
|
||||
|
|
@ -846,7 +846,7 @@ namespace MWSound
|
|||
const auto update = mWaterSoundUpdater.update(player, *world);
|
||||
|
||||
WaterSoundAction action;
|
||||
Sound_Buffer* sfx;
|
||||
SoundBuffer* sfx;
|
||||
std::tie(action, sfx) = getWaterSoundAction(update, curcell);
|
||||
|
||||
switch (action)
|
||||
|
|
@ -870,7 +870,7 @@ namespace MWSound
|
|||
mLastCell = curcell;
|
||||
}
|
||||
|
||||
std::pair<SoundManager::WaterSoundAction, Sound_Buffer*> SoundManager::getWaterSoundAction(
|
||||
std::pair<SoundManager::WaterSoundAction, SoundBuffer*> SoundManager::getWaterSoundAction(
|
||||
const WaterSoundUpdate& update, const MWWorld::Cell* cell) const
|
||||
{
|
||||
if (mNearWaterSound)
|
||||
|
|
@ -880,7 +880,7 @@ namespace MWSound
|
|||
|
||||
bool soundIdChanged = false;
|
||||
|
||||
Sound_Buffer* sfx = mSoundBuffers.lookup(update.mId);
|
||||
SoundBuffer* sfx = mSoundBuffers.lookup(update.mId);
|
||||
if (mLastCell != cell)
|
||||
{
|
||||
const auto snditer = mActiveSounds.find(nullptr);
|
||||
|
|
@ -1168,7 +1168,7 @@ namespace MWSound
|
|||
|
||||
// Default readAll implementation, for decoders that can't do anything
|
||||
// better
|
||||
void Sound_Decoder::readAll(std::vector<char>& output)
|
||||
void SoundDecoder::readAll(std::vector<char>& output)
|
||||
{
|
||||
size_t total = output.size();
|
||||
size_t got;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue