mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-12 19:21:42 +00:00
Merge progress, still lots to do and to continue up the change
This commit is contained in:
parent
37a4b2a103
commit
17a2c81b28
3350 changed files with 308020 additions and 159908 deletions
105
.clang-format
Normal file
105
.clang-format
Normal file
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: true
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: All
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: CaseSensitive
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++20
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
StatementMacros:
|
||||
- META_Object
|
||||
- META_StateAttribute
|
||||
- META_Node
|
18
.clang-tidy
Normal file
18
.clang-tidy
Normal file
|
@ -0,0 +1,18 @@
|
|||
Checks: >
|
||||
-*,
|
||||
boost-*,
|
||||
portability-*,
|
||||
clang-analyzer-*,
|
||||
-clang-analyzer-optin*,
|
||||
-clang-analyzer-cplusplus.NewDeleteLeaks,
|
||||
-clang-analyzer-core.CallAndMessage,
|
||||
-modernize-avoid-bind
|
||||
WarningsAsErrors: >
|
||||
-*,
|
||||
boost-*,
|
||||
portability-*,
|
||||
clang-analyzer-*,
|
||||
-clang-analyzer-optin*,
|
||||
-clang-analyzer-cplusplus.NewDeleteLeaks,
|
||||
-clang-analyzer-core.CallAndMessage
|
||||
HeaderFilterRegex: '^(apps|components)'
|
|
@ -10,7 +10,12 @@ indent_style = space
|
|||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
|
||||
[*.glsl]
|
||||
[*.{glsl,vert,tesc,tese,geom,frag,comp}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = false
|
||||
insert_final_newline = true
|
||||
|
||||
[{CMakeLists.txt,*.cmake}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
|
|
19
.git-blame-ignore-revs
Normal file
19
.git-blame-ignore-revs
Normal file
|
@ -0,0 +1,19 @@
|
|||
# This file lists revisions meant to be ignored by `git blame`.
|
||||
# Pass `--ignore-revs-file .git-blame-ignore-revs` to `git blame` to make your life easier.
|
||||
|
||||
# Author: Alexei Kotov <alexdobrohotov@yandex.ru>
|
||||
# Date: Fri Sep 2 02:52:49 2022 +0000
|
||||
# Reformat NIF record type mapping
|
||||
8df0587793a07ec556dc9cb575cd2af4204c456b
|
||||
|
||||
# Author: AnyOldName3 <krizdjali@gmail.com>
|
||||
# Date: Fri Sep 16 00:53:24 2022 +0100
|
||||
# Renormalise line endings
|
||||
84f8a6848a8b05502d7618ca7af8cca74f2c3bae
|
||||
|
||||
# Author: clang-format-bot <bot@clang-format>
|
||||
# Date: 9/22/2022 9:26:05 PM
|
||||
# Apply clang-format to code base
|
||||
ddb0522bbf2aa8aa7c9e139ff7395fb8ed6a841f
|
||||
|
||||
88ec8a95231341e7962b85716510d414e9f0c424
|
80
.github/workflows/openmw.yml
vendored
Normal file
80
.github/workflows/openmw.yml
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
name: CMake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
|
||||
jobs:
|
||||
Ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Add OpenMW PPA Dependencies
|
||||
run: sudo add-apt-repository ppa:openmw/openmw; sudo apt-get update
|
||||
|
||||
- name: Install Building Dependencies
|
||||
run: sudo CI/install_debian_deps.sh gcc openmw-deps openmw-deps-dynamic
|
||||
|
||||
- name: Prime ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ matrix.os }}-${{ env.BUILD_TYPE }}
|
||||
max-size: 1000M
|
||||
|
||||
- name: Configure
|
||||
run: cmake . -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DOPENMW_USE_SYSTEM_RECASTNAVIGATION=1 -DUSE_SYSTEM_TINYXML=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=install
|
||||
|
||||
- name: Build
|
||||
run: make -j3
|
||||
|
||||
- name: Test
|
||||
run: ./openmw_test_suite
|
||||
|
||||
# - name: Install
|
||||
# shell: bash
|
||||
# run: cmake --install .
|
||||
|
||||
# - name: Create Artifact
|
||||
# shell: bash
|
||||
# working-directory: install
|
||||
# run: |
|
||||
# ls -laR
|
||||
# 7z a ../build_artifact.7z .
|
||||
|
||||
# - name: Upload Artifact
|
||||
# uses: actions/upload-artifact@v1
|
||||
# with:
|
||||
# path: ./build_artifact.7z
|
||||
# name: build_artifact.7z
|
||||
|
||||
MacOS:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Building Dependencies
|
||||
run: CI/before_install.osx.sh
|
||||
|
||||
- name: Prime ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ matrix.os }}-${{ env.BUILD_TYPE }}
|
||||
max-size: 1000M
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
rm -fr build # remove the build directory
|
||||
CI/before_script.osx.sh
|
||||
- name: Build
|
||||
run: |
|
||||
cd build
|
||||
make -j $(sysctl -n hw.logicalcpu) package
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -35,7 +35,6 @@ CMakeLists.txt.user*
|
|||
.vscode
|
||||
|
||||
## resources
|
||||
data
|
||||
resources
|
||||
/*.cfg
|
||||
/*.desktop
|
||||
|
@ -73,6 +72,7 @@ components/ui_contentselector.h
|
|||
docs/mainpage.hpp
|
||||
docs/Doxyfile
|
||||
docs/DoxyfilePages
|
||||
docs/source/reference/lua-scripting/generated_html
|
||||
moc_*.cxx
|
||||
*.cxx_parameters
|
||||
*qrc_launcher.cxx
|
||||
|
@ -85,3 +85,7 @@ moc_*.cxx
|
|||
*.[ao]
|
||||
*.so
|
||||
venv/
|
||||
|
||||
## operating system files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
|
706
.gitlab-ci.yml
706
.gitlab-ci.yml
|
@ -1,131 +1,483 @@
|
|||
default:
|
||||
interruptible: true
|
||||
|
||||
# Note: We set `needs` on each job to control the job DAG.
|
||||
# See https://docs.gitlab.com/ee/ci/yaml/#needs
|
||||
stages:
|
||||
- checks
|
||||
- build
|
||||
- test
|
||||
|
||||
.Debian_Image:
|
||||
workflow:
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
||||
# https://blog.nimbleways.com/let-s-make-faster-gitlab-ci-cd-pipelines/
|
||||
variables:
|
||||
FF_USE_NEW_SHELL_ESCAPE: "true"
|
||||
FF_USE_FASTZIP: "true"
|
||||
# These can be specified per job or per pipeline
|
||||
ARTIFACT_COMPRESSION_LEVEL: "fast"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
|
||||
.Ubuntu_Image:
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
image: debian:bullseye
|
||||
image: ubuntu:22.04
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
|
||||
.Debian:
|
||||
extends: .Debian_Image
|
||||
Ubuntu_GCC_preprocess:
|
||||
extends: .Ubuntu_Image
|
||||
cache:
|
||||
key: Ubuntu_GCC_preprocess.ubuntu_22.04.v1
|
||||
paths:
|
||||
- apt-cache/
|
||||
- .cache/pip/
|
||||
stage: build
|
||||
variables:
|
||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh openmw-deps openmw-deps-dynamic gcc_preprocess
|
||||
- pip3 install --user click termtables
|
||||
script:
|
||||
- CI/ubuntu_gcc_preprocess.sh
|
||||
|
||||
.Ubuntu:
|
||||
extends: .Ubuntu_Image
|
||||
cache:
|
||||
paths:
|
||||
- apt-cache/
|
||||
- ccache/
|
||||
stage: build
|
||||
variables:
|
||||
CMAKE_EXE_LINKER_FLAGS: -fuse-ld=mold
|
||||
script:
|
||||
- df -h
|
||||
- export CCACHE_BASEDIR="`pwd`"
|
||||
- export CCACHE_DIR="`pwd`/ccache" && mkdir -pv "$CCACHE_DIR"
|
||||
- ccache -z -M "${CCACHE_SIZE}"
|
||||
- CI/before_script.linux.sh
|
||||
- cd build
|
||||
- cmake --build . -- -j $(nproc)
|
||||
- df -h
|
||||
- du -sh .
|
||||
- find . | grep '\.o$' | xargs rm -f
|
||||
- df -h
|
||||
- du -sh .
|
||||
- cmake --install .
|
||||
- if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw_test_suite; fi
|
||||
- if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw_detournavigator_navmeshtilescache_benchmark; fi
|
||||
- if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw_test_suite --gtest_output="xml:openmw_tests.xml"; fi
|
||||
- if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw-cs-tests --gtest_output="xml:openmw_cs_tests.xml"; fi
|
||||
- if [[ "${BUILD_TESTS_ONLY}" && ! "${BUILD_WITH_CODE_COVERAGE}" ]]; then ./openmw_detournavigator_navmeshtilescache_benchmark; fi
|
||||
- if [[ "${BUILD_TESTS_ONLY}" && ! "${BUILD_WITH_CODE_COVERAGE}" ]]; then ./openmw_esm_refid_benchmark; fi
|
||||
- if [[ "${BUILD_TESTS_ONLY}" && ! "${BUILD_WITH_CODE_COVERAGE}" ]]; then ./openmw_settings_access_benchmark; fi
|
||||
- ccache -s
|
||||
- df -h
|
||||
- if [[ "${BUILD_WITH_CODE_COVERAGE}" ]]; then gcovr --xml-pretty --exclude-unreachable-branches --print-summary --root "${CI_PROJECT_DIR}" -j $(nproc) -o ../coverage.xml; fi
|
||||
- ls | grep -v -e '^extern$' -e '^install$' -e '^openmw_tests.xml$' -e '^openmw_cs_tests.xml$' | xargs -I '{}' rm -rf './{}'
|
||||
- cd ..
|
||||
- df -h
|
||||
- du -sh build/
|
||||
- du -sh build/install/
|
||||
- du -sh apt-cache/
|
||||
- du -sh ccache/
|
||||
artifacts:
|
||||
paths:
|
||||
- build/install/
|
||||
|
||||
Coverity:
|
||||
extends: .Debian_Image
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
image: ubuntu:20.04
|
||||
stage: build
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
cache:
|
||||
key: Coverity.ubuntu_20.04.v1
|
||||
paths:
|
||||
- apt-cache/
|
||||
- ccache/
|
||||
variables:
|
||||
CCACHE_SIZE: 2G
|
||||
CC: clang-11
|
||||
CXX: clang++-11
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -O0
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh gcc openmw-deps openmw-deps-dynamic coverity
|
||||
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 --form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
|
||||
- CI/install_debian_deps.sh coverity openmw-deps openmw-deps-dynamic
|
||||
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
|
||||
- tar xfz /tmp/cov-analysis-linux64.tgz
|
||||
script:
|
||||
- export CCACHE_BASEDIR="$(pwd)"
|
||||
- export CCACHE_DIR="$(pwd)/ccache"
|
||||
- mkdir -pv "${CCACHE_DIR}"
|
||||
- ccache -z -M "${CCACHE_SIZE}"
|
||||
- CI/before_script.linux.sh
|
||||
# Add more than just `openmw` once we can build everything under 3h
|
||||
- cov-analysis-linux64-*/bin/cov-build --dir cov-int cmake --build build -- -j $(nproc) openmw
|
||||
- cov-analysis-linux64-*/bin/cov-configure --template --comptype prefix --compiler ccache
|
||||
# Remove the specific targets and build everything once we can do it under 3h
|
||||
- cov-analysis-linux64-*/bin/cov-build --dir cov-int cmake --build build -- -j $(nproc)
|
||||
- ccache -s
|
||||
after_script:
|
||||
- tar cfz cov-int.tar.gz cov-int
|
||||
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
||||
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
||||
--form file=@cov-int.tar.gz --form version="`git describe --tags`"
|
||||
--form description="`git describe --tags` / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
||||
variables:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
timeout: 8h
|
||||
--form file=@cov-int.tar.gz --form version="$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA"
|
||||
--form description="CI_COMMIT_SHORT_SHA / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
||||
artifacts:
|
||||
paths:
|
||||
- /builds/OpenMW/openmw/cov-int/build-log.txt
|
||||
|
||||
Debian_GCC:
|
||||
extends: .Debian
|
||||
Ubuntu_GCC:
|
||||
extends: .Ubuntu
|
||||
cache:
|
||||
key: Debian_GCC.v2
|
||||
key: Ubuntu_GCC.ubuntu_22.04.v1
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh gcc openmw-deps openmw-deps-dynamic
|
||||
variables:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CCACHE_SIZE: 3G
|
||||
CCACHE_SIZE: 4G
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
timeout: 2h
|
||||
|
||||
Debian_GCC_tests:
|
||||
extends: Debian_GCC
|
||||
Ubuntu_GCC_asan:
|
||||
extends: Ubuntu_GCC
|
||||
cache:
|
||||
key: Debian_GCC_tests.v2
|
||||
key: Ubuntu_GCC_asan.ubuntu_22.04.v1
|
||||
variables:
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -g -O1 -fno-omit-frame-pointer -fsanitize=address -fsanitize=pointer-subtract -fsanitize=leak
|
||||
CMAKE_EXE_LINKER_FLAGS: -fsanitize=address -fsanitize=pointer-subtract -fsanitize=leak -fuse-ld=mold
|
||||
BUILD_OPENMW_ONLY: 1
|
||||
|
||||
Clang_Format:
|
||||
extends: .Ubuntu_Image
|
||||
stage: checks
|
||||
cache:
|
||||
key: Ubuntu_Clang_Format.ubuntu_22.04.v1
|
||||
paths:
|
||||
- apt-cache/
|
||||
variables:
|
||||
CLANG_FORMAT: clang-format-14
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh openmw-clang-format
|
||||
script:
|
||||
- CI/check_cmake_format.sh
|
||||
- CI/check_file_names.sh
|
||||
- CI/check_clang_format.sh
|
||||
|
||||
Teal:
|
||||
stage: checks
|
||||
extends: .Ubuntu_Image
|
||||
before_script:
|
||||
- apt-get update
|
||||
- apt-get -y install curl wget make build-essential libreadline-dev git-core zip unzip
|
||||
script:
|
||||
- CI/teal_ci.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- teal_declarations.zip
|
||||
|
||||
Ubuntu_GCC_Debug:
|
||||
extends: .Ubuntu
|
||||
cache:
|
||||
key: Ubuntu_GCC_Debug.ubuntu_22.04.v1
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh gcc openmw-deps openmw-deps-dynamic
|
||||
variables:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CCACHE_SIZE: 4G
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -O0
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
timeout: 2h
|
||||
|
||||
Ubuntu_GCC_tests:
|
||||
extends: Ubuntu_GCC
|
||||
cache:
|
||||
key: Ubuntu_GCC_tests.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
Debian_GCC_Static_Deps:
|
||||
extends: Debian_GCC
|
||||
.Ubuntu_GCC_tests_Debug:
|
||||
extends: Ubuntu_GCC
|
||||
cache:
|
||||
key: Debian_GCC_Static_Deps
|
||||
paths:
|
||||
- apt-cache/
|
||||
- ccache/
|
||||
- build/extern/fetched/
|
||||
key: Ubuntu_GCC_tests_Debug.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -g -O0 -D_GLIBCXX_ASSERTIONS
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
Ubuntu_GCC_tests_asan:
|
||||
extends: Ubuntu_GCC
|
||||
cache:
|
||||
key: Ubuntu_GCC_tests_asan.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -g -O1 -fno-omit-frame-pointer -fsanitize=address -fsanitize=pointer-subtract -fsanitize=leak
|
||||
CMAKE_EXE_LINKER_FLAGS: -fsanitize=address -fsanitize=pointer-subtract -fsanitize=leak -fuse-ld=mold
|
||||
ASAN_OPTIONS: halt_on_error=1:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
Ubuntu_GCC_tests_ubsan:
|
||||
extends: Ubuntu_GCC
|
||||
cache:
|
||||
key: Ubuntu_GCC_tests_ubsan.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -g -O0 -fsanitize=undefined
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
.Ubuntu_GCC_tests_tsan:
|
||||
extends: Ubuntu_GCC
|
||||
cache:
|
||||
key: Ubuntu_GCC_tests_tsan.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -g -O2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=thread -fPIE
|
||||
CMAKE_EXE_LINKER_FLAGS: -pthread -pie -fsanitize=thread -fuse-ld=mold
|
||||
TSAN_OPTIONS: second_deadlock_stack=1:halt_on_error=1
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
Ubuntu_GCC_tests_coverage:
|
||||
extends: .Ubuntu_GCC_tests_Debug
|
||||
cache:
|
||||
key: Ubuntu_GCC_tests_coverage.ubuntu_22.04.v1
|
||||
variables:
|
||||
BUILD_WITH_CODE_COVERAGE: 1
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh gcc openmw-deps openmw-deps-static
|
||||
- CI/install_debian_deps.sh gcc openmw-deps openmw-deps-dynamic openmw-coverage
|
||||
coverage: /^\s*lines:\s*\d+.\d+\%/
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
junit: build/*_tests.xml
|
||||
|
||||
.Ubuntu_Static_Deps:
|
||||
extends: Ubuntu_Clang
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
changes:
|
||||
- "**/CMakeLists.txt"
|
||||
- "cmake/**/*"
|
||||
- "CI/**/*"
|
||||
- ".gitlab-ci.yml"
|
||||
cache:
|
||||
key: Ubuntu_Static_Deps.ubuntu_22.04.v1
|
||||
paths:
|
||||
- apt-cache/
|
||||
- ccache/
|
||||
- build/extern/fetched/
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh clang openmw-deps openmw-deps-static
|
||||
variables:
|
||||
CI_OPENMW_USE_STATIC_DEPS: 1
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CXXFLAGS: -O0
|
||||
timeout: 3h
|
||||
|
||||
Debian_GCC_Static_Deps_tests:
|
||||
extends: Debian_GCC_Static_Deps
|
||||
.Ubuntu_Static_Deps_tests:
|
||||
extends: .Ubuntu_Static_Deps
|
||||
cache:
|
||||
key: Debian_GCC_Static_Deps_tests
|
||||
key: Ubuntu_Static_Deps_tests.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CXXFLAGS: -O0
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
Debian_Clang:
|
||||
extends: .Debian
|
||||
Ubuntu_Clang:
|
||||
extends: .Ubuntu
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh clang openmw-deps openmw-deps-dynamic
|
||||
cache:
|
||||
key: Debian_Clang.v2
|
||||
key: Ubuntu_Clang.ubuntu_22.04.v2
|
||||
variables:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CCACHE_SIZE: 2G
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
timeout: 2h
|
||||
timeout: 3h
|
||||
|
||||
Debian_Clang_tests:
|
||||
extends: Debian_Clang
|
||||
.Ubuntu_Clang_Tidy_Base:
|
||||
extends: Ubuntu_Clang
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh clang clang-tidy openmw-deps openmw-deps-dynamic
|
||||
cache:
|
||||
key: Debian_Clang_tests.v2
|
||||
key: Ubuntu_Clang_Tidy.ubuntu_22.04.v1
|
||||
variables:
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -O0
|
||||
CI_CLANG_TIDY: 1
|
||||
CCACHE_BASEDIR: $CI_PROJECT_DIR
|
||||
CCACHE_DIR: $CI_PROJECT_DIR/ccache
|
||||
script:
|
||||
- mkdir -pv "${CCACHE_DIR}"
|
||||
- ccache -z -M "${CCACHE_SIZE}"
|
||||
- CI/before_script.linux.sh
|
||||
- cd build
|
||||
- find . -name *.o -exec touch {} \;
|
||||
- cmake --build . -- -j $(nproc) ${BUILD_TARGETS}
|
||||
- ccache -s
|
||||
artifacts:
|
||||
paths:
|
||||
- build/
|
||||
expire_in: 12h
|
||||
timeout: 3h
|
||||
|
||||
Ubuntu_Clang_Tidy_components:
|
||||
extends: .Ubuntu_Clang_Tidy_Base
|
||||
variables:
|
||||
BUILD_TARGETS: components components_qt oics osg-ffmpeg-videoplayer osgQt
|
||||
timeout: 3h
|
||||
|
||||
Ubuntu_Clang_Tidy_openmw:
|
||||
extends: .Ubuntu_Clang_Tidy_Base
|
||||
needs:
|
||||
- Ubuntu_Clang_Tidy_components
|
||||
variables:
|
||||
BUILD_TARGETS: openmw
|
||||
timeout: 3h
|
||||
|
||||
Ubuntu_Clang_Tidy_openmw-cs:
|
||||
extends: .Ubuntu_Clang_Tidy_Base
|
||||
needs:
|
||||
- Ubuntu_Clang_Tidy_components
|
||||
variables:
|
||||
BUILD_TARGETS: openmw-cs openmw-cs-tests
|
||||
timeout: 3h
|
||||
|
||||
Ubuntu_Clang_Tidy_other:
|
||||
extends: .Ubuntu_Clang_Tidy_Base
|
||||
needs:
|
||||
- Ubuntu_Clang_Tidy_components
|
||||
variables:
|
||||
BUILD_TARGETS: bsatool esmtool openmw-launcher openmw-iniimporter openmw-essimporter openmw-wizard niftest openmw_test_suite openmw-navmeshtool openmw-bulletobjecttool
|
||||
timeout: 3h
|
||||
|
||||
.Ubuntu_Clang_tests:
|
||||
extends: Ubuntu_Clang
|
||||
cache:
|
||||
key: Ubuntu_Clang_tests.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
Ubuntu_Clang_tests_Debug:
|
||||
extends: Ubuntu_Clang
|
||||
cache:
|
||||
key: Ubuntu_Clang_tests_Debug.ubuntu_22.04.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 1G
|
||||
BUILD_TESTS_ONLY: 1
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
artifacts:
|
||||
paths: []
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
when: always
|
||||
reports:
|
||||
junit: build/*_tests.xml
|
||||
|
||||
.Ubuntu_integration_tests_base:
|
||||
extends: .Ubuntu_Image
|
||||
stage: test
|
||||
variables:
|
||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||
cache:
|
||||
paths:
|
||||
- .cache/pip
|
||||
- apt-cache/
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh $OPENMW_DEPS
|
||||
- pip3 install --user numpy matplotlib termtables click
|
||||
script:
|
||||
- CI/run_integration_tests.sh
|
||||
after_script:
|
||||
- if [[ -f /tmp/openmw-crash.log ]]; then cat /tmp/openmw-crash.log; fi
|
||||
|
||||
Ubuntu_Clang_integration_tests:
|
||||
extends: .Ubuntu_integration_tests_base
|
||||
needs:
|
||||
- Ubuntu_Clang
|
||||
cache:
|
||||
key: Ubuntu_Clang_integration_tests.ubuntu_22.04.v2
|
||||
variables:
|
||||
OPENMW_DEPS: openmw-integration-tests
|
||||
|
||||
Ubuntu_GCC_integration_tests_asan:
|
||||
extends: .Ubuntu_integration_tests_base
|
||||
needs:
|
||||
- Ubuntu_GCC_asan
|
||||
cache:
|
||||
key: Ubuntu_GCC_integration_tests_asan.ubuntu_22.04.v1
|
||||
variables:
|
||||
OPENMW_DEPS: openmw-integration-tests libasan6
|
||||
ASAN_OPTIONS: halt_on_error=1:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:detect_leaks=0
|
||||
|
||||
.MacOS:
|
||||
image: macos-11-xcode-12
|
||||
tags:
|
||||
- shared-macos-amd64
|
||||
stage: build
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ID == "7107382"
|
||||
cache:
|
||||
paths:
|
||||
- ccache/
|
||||
|
@ -138,78 +490,89 @@ Debian_Clang_tests:
|
|||
- 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}_${CI_JOB_ID}.dmg"; done
|
||||
- for dmg in *.dmg; do mv "$dmg" "${dmg%.dmg}_${CI_COMMIT_REF_NAME##*/}_${CI_JOB_ID}.dmg"; done
|
||||
- ccache -s
|
||||
artifacts:
|
||||
paths:
|
||||
- build/OpenMW-*.dmg
|
||||
- "build/**/*.log"
|
||||
|
||||
macOS11_Xcode12:
|
||||
macOS13_Xcode14_arm64:
|
||||
extends: .MacOS
|
||||
image: macos-11-xcode-12
|
||||
allow_failure: true
|
||||
image: macos-12-xcode-14
|
||||
tags:
|
||||
- saas-macos-medium-m1
|
||||
cache:
|
||||
key: macOS11_Xcode12.v1
|
||||
key: macOS12_Xcode14_arm64.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 3G
|
||||
|
||||
macOS10.15_Xcode11:
|
||||
extends: .MacOS
|
||||
image: macos-10.15-xcode-11
|
||||
cache:
|
||||
key: macOS10.15_Xcode11.v1
|
||||
variables:
|
||||
CCACHE_SIZE: 3G
|
||||
|
||||
variables: &engine-targets
|
||||
targets: "openmw,openmw-essimporter,openmw-iniimporter,openmw-launcher,openmw-wizard"
|
||||
package: "Engine"
|
||||
|
||||
variables: &cs-targets
|
||||
targets: "openmw-cs,bsatool,esmtool,niftest"
|
||||
package: "CS"
|
||||
|
||||
variables: &tests-targets
|
||||
targets: "openmw_test_suite,openmw_detournavigator_navmeshtilescache_benchmark"
|
||||
package: "Tests"
|
||||
|
||||
.Windows_Ninja_Base:
|
||||
tags:
|
||||
- windows
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
before_script:
|
||||
- Get-Volume
|
||||
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
||||
- choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolatey/" --priority=1
|
||||
- choco source disable -n=chocolatey
|
||||
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
||||
- choco install 7zip -y
|
||||
- choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y
|
||||
- choco install ccache -y
|
||||
- choco install vswhere -y
|
||||
- choco install ninja -y
|
||||
- choco install python -y
|
||||
- refreshenv
|
||||
- |
|
||||
function Make-SafeFileName {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[String]
|
||||
$FileName
|
||||
)
|
||||
[IO.Path]::GetInvalidFileNameChars() | ForEach-Object {
|
||||
$FileName = $FileName.Replace($_, '_')
|
||||
}
|
||||
return $FileName
|
||||
}
|
||||
stage: build
|
||||
script:
|
||||
- Get-Volume
|
||||
- $time = (Get-Date -Format "HH:mm:ss")
|
||||
- echo ${time}
|
||||
- echo "started by ${GITLAB_USER_NAME}"
|
||||
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N -b -t
|
||||
- $env:CCACHE_BASEDIR = Get-Location
|
||||
- $env:CCACHE_DIR = "$(Get-Location)\ccache"
|
||||
- New-Item -Type Directory -Force -Path $env:CCACHE_DIR
|
||||
- New-Item -Type File -Force -Path MSVC2019_64_Ninja\.cmake\api\v1\query\codemodel-v2
|
||||
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N -b -t -C $multiview -E
|
||||
- Get-Volume
|
||||
- cd MSVC2019_64_Ninja
|
||||
- .\ActivateMSVC.ps1
|
||||
- cmake --build . --config $config --target ($targets.Split(','))
|
||||
- cmake --build . --config $config
|
||||
- ccache --show-stats
|
||||
- cd $config
|
||||
- echo "CI_COMMIT_REF_NAME ${CI_COMMIT_REF_NAME}`nCI_JOB_ID ${CI_JOB_ID}`nCI_COMMIT_SHA ${CI_COMMIT_SHA}" | Out-File -Encoding UTF8 CI-ID.txt
|
||||
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
||||
- |
|
||||
if (Get-ChildItem -Recurse *.pdb) {
|
||||
7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' CI-ID.txt
|
||||
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
||||
Push-Location ..
|
||||
..\CI\Store-Symbols.ps1
|
||||
7z a -tzip "..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_sym_store.zip"))" '.\SymStore\*' $config\CI-ID.txt
|
||||
Pop-Location
|
||||
Get-ChildItem -Recurse *.pdb | Remove-Item
|
||||
}
|
||||
- 7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}.zip '*'
|
||||
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
||||
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
||||
after_script:
|
||||
- Get-Volume
|
||||
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
||||
cache:
|
||||
key: ninja-v2
|
||||
key: ninja-v7
|
||||
paths:
|
||||
- ccache
|
||||
- deps
|
||||
- MSVC2019_64_Ninja/deps/Qt
|
||||
artifacts:
|
||||
|
@ -225,54 +588,32 @@ variables: &tests-targets
|
|||
- MSVC2019_64_Ninja/*/*/*/*/*/*.log
|
||||
- MSVC2019_64_Ninja/*/*/*/*/*/*/*.log
|
||||
- MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
timeout: 2h
|
||||
|
||||
Windows_Ninja_Engine_Release:
|
||||
.Windows_Ninja_Release:
|
||||
extends:
|
||||
- .Windows_Ninja_Base
|
||||
variables:
|
||||
<<: *engine-targets
|
||||
config: "Release"
|
||||
|
||||
Windows_Ninja_Engine_Debug:
|
||||
.Windows_Ninja_Release_MultiView:
|
||||
extends:
|
||||
- .Windows_Ninja_Base
|
||||
variables:
|
||||
<<: *engine-targets
|
||||
config: "Debug"
|
||||
|
||||
Windows_Ninja_Engine_RelWithDebInfo:
|
||||
extends:
|
||||
- .Windows_Ninja_Base
|
||||
variables:
|
||||
<<: *engine-targets
|
||||
config: "RelWithDebInfo"
|
||||
|
||||
Windows_Ninja_CS_Release:
|
||||
extends:
|
||||
- .Windows_Ninja_Base
|
||||
variables:
|
||||
<<: *cs-targets
|
||||
multiview: "-M"
|
||||
config: "Release"
|
||||
|
||||
Windows_Ninja_CS_Debug:
|
||||
.Windows_Ninja_Debug:
|
||||
extends:
|
||||
- .Windows_Ninja_Base
|
||||
variables:
|
||||
<<: *cs-targets
|
||||
config: "Debug"
|
||||
|
||||
Windows_Ninja_CS_RelWithDebInfo:
|
||||
.Windows_Ninja_RelWithDebInfo:
|
||||
extends:
|
||||
- .Windows_Ninja_Base
|
||||
variables:
|
||||
<<: *cs-targets
|
||||
config: "RelWithDebInfo"
|
||||
|
||||
Windows_Ninja_Tests_RelWithDebInfo:
|
||||
extends: .Windows_Ninja_Base
|
||||
stage: build
|
||||
variables:
|
||||
<<: *tests-targets
|
||||
config: "RelWithDebInfo"
|
||||
# Gitlab can't successfully execute following binaries due to unknown reason
|
||||
# executables: "openmw_test_suite.exe,openmw_detournavigator_navmeshtilescache_benchmark.exe"
|
||||
|
@ -280,37 +621,67 @@ Windows_Ninja_Tests_RelWithDebInfo:
|
|||
.Windows_MSBuild_Base:
|
||||
tags:
|
||||
- windows
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
before_script:
|
||||
- Get-Volume
|
||||
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
|
||||
- choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolatey/" --priority=1
|
||||
- choco source disable -n=chocolatey
|
||||
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
||||
- choco install 7zip -y
|
||||
- choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y
|
||||
- choco install ccache -y
|
||||
- choco install vswhere -y
|
||||
- choco install python -y
|
||||
- refreshenv
|
||||
- |
|
||||
function Make-SafeFileName {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[String]
|
||||
$FileName
|
||||
)
|
||||
[IO.Path]::GetInvalidFileNameChars() | ForEach-Object {
|
||||
$FileName = $FileName.Replace($_, '_')
|
||||
}
|
||||
return $FileName
|
||||
}
|
||||
stage: build
|
||||
script:
|
||||
- Get-Volume
|
||||
- $time = (Get-Date -Format "HH:mm:ss")
|
||||
- echo ${time}
|
||||
- echo "started by ${GITLAB_USER_NAME}"
|
||||
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -b -t
|
||||
- $env:CCACHE_BASEDIR = Get-Location
|
||||
- $env:CCACHE_DIR = "$(Get-Location)\ccache"
|
||||
- New-Item -Type Directory -Force -Path $env:CCACHE_DIR
|
||||
- New-Item -Type File -Force -Path MSVC2019_64\.cmake\api\v1\query\codemodel-v2
|
||||
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -b -t -C $multiview -E
|
||||
- cd MSVC2019_64
|
||||
- cmake --build . --config $config --target ($targets.Split(','))
|
||||
- Get-Volume
|
||||
- cmake --build . --config $config
|
||||
- ccache --show-stats
|
||||
- cd $config
|
||||
- echo "CI_COMMIT_REF_NAME ${CI_COMMIT_REF_NAME}`nCI_JOB_ID ${CI_JOB_ID}`nCI_COMMIT_SHA ${CI_COMMIT_SHA}" | Out-File -Encoding UTF8 CI-ID.txt
|
||||
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
||||
- |
|
||||
if (Get-ChildItem -Recurse *.pdb) {
|
||||
7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' CI-ID.txt
|
||||
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
||||
Push-Location ..
|
||||
..\CI\Store-Symbols.ps1
|
||||
7z a -tzip "..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_sym_store.zip"))" '.\SymStore\*' $config\CI-ID.txt
|
||||
Pop-Location
|
||||
Get-ChildItem -Recurse *.pdb | Remove-Item
|
||||
}
|
||||
- 7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}.zip '*'
|
||||
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
||||
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
||||
after_script:
|
||||
- Get-Volume
|
||||
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
||||
cache:
|
||||
key: msbuild-v2
|
||||
key: msbuild-v7
|
||||
paths:
|
||||
- ccache
|
||||
- deps
|
||||
- MSVC2019_64/deps/Qt
|
||||
artifacts:
|
||||
|
@ -326,78 +697,52 @@ Windows_Ninja_Tests_RelWithDebInfo:
|
|||
- MSVC2019_64/*/*/*/*/*/*.log
|
||||
- MSVC2019_64/*/*/*/*/*/*/*.log
|
||||
- MSVC2019_64/*/*/*/*/*/*/*/*.log
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
timeout: 2h
|
||||
|
||||
Windows_MSBuild_Engine_Release:
|
||||
.Windows_MSBuild_Release:
|
||||
extends:
|
||||
- .Windows_MSBuild_Base
|
||||
variables:
|
||||
<<: *engine-targets
|
||||
config: "Release"
|
||||
|
||||
Windows_MSBuild_Engine_Debug:
|
||||
.Windows_MSBuild_Debug:
|
||||
extends:
|
||||
- .Windows_MSBuild_Base
|
||||
variables:
|
||||
<<: *engine-targets
|
||||
config: "Debug"
|
||||
|
||||
Windows_MSBuild_Engine_RelWithDebInfo:
|
||||
Windows_MSBuild_RelWithDebInfo:
|
||||
extends:
|
||||
- .Windows_MSBuild_Base
|
||||
variables:
|
||||
<<: *engine-targets
|
||||
config: "RelWithDebInfo"
|
||||
|
||||
Windows_MSBuild_CS_Release:
|
||||
extends:
|
||||
- .Windows_MSBuild_Base
|
||||
variables:
|
||||
<<: *cs-targets
|
||||
config: "Release"
|
||||
|
||||
Windows_MSBuild_CS_Debug:
|
||||
extends:
|
||||
- .Windows_MSBuild_Base
|
||||
variables:
|
||||
<<: *cs-targets
|
||||
config: "Debug"
|
||||
|
||||
Windows_MSBuild_CS_RelWithDebInfo:
|
||||
extends:
|
||||
- .Windows_MSBuild_Base
|
||||
variables:
|
||||
<<: *cs-targets
|
||||
config: "RelWithDebInfo"
|
||||
|
||||
Windows_MSBuild_Tests_RelWithDebInfo:
|
||||
extends: .Windows_MSBuild_Base
|
||||
stage: build
|
||||
variables:
|
||||
<<: *tests-targets
|
||||
config: "RelWithDebInfo"
|
||||
# Gitlab can't successfully execute following binaries due to unknown reason
|
||||
# executables: "openmw_test_suite.exe,openmw_detournavigator_navmeshtilescache_benchmark.exe"
|
||||
# temporarily enabled while we're linking these on the downloads page
|
||||
rules:
|
||||
# run this for both pushes and schedules so 'latest successful pipeline for branch' always includes it
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "schedule"
|
||||
|
||||
Debian_AndroidNDK_arm64-v8a:
|
||||
.Ubuntu_AndroidNDK_arm64-v8a:
|
||||
tags:
|
||||
- linux
|
||||
image: debian:bullseye
|
||||
image: psi29a/android-ndk:focal-ndk22
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
variables:
|
||||
CCACHE_SIZE: 3G
|
||||
cache:
|
||||
key: Debian_AndroidNDK_arm64-v8a.v3
|
||||
key: Ubuntu__Focal_AndroidNDK_r22b_arm64-v8a.v2
|
||||
paths:
|
||||
- apt-cache/
|
||||
- ccache/
|
||||
- build/extern/fetched/
|
||||
before_script:
|
||||
- export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR
|
||||
- echo "deb http://deb.debian.org/debian unstable main contrib" > /etc/apt/sources.list
|
||||
- echo "google-android-ndk-installer google-android-installers/mirror select https://dl.google.com" | debconf-set-selections
|
||||
- apt-get update -yq
|
||||
- apt-get -q -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake ccache curl unzip git build-essential google-android-ndk-installer
|
||||
- CI/install_debian_deps.sh android
|
||||
stage: build
|
||||
script:
|
||||
- df -h
|
||||
- export CCACHE_BASEDIR="`pwd`"
|
||||
- export CCACHE_DIR="`pwd`/ccache" && mkdir -pv "$CCACHE_DIR"
|
||||
- ccache -z -M "${CCACHE_SIZE}"
|
||||
|
@ -405,10 +750,55 @@ Debian_AndroidNDK_arm64-v8a:
|
|||
- CI/before_script.android.sh
|
||||
- cd build
|
||||
- cmake --build . -- -j $(nproc)
|
||||
- cmake --install .
|
||||
# - cmake --install . # no one uses builds anyway, disable until 'no space left' is resolved
|
||||
- ccache -s
|
||||
- df -h
|
||||
- ls | grep -v -e '^extern$' -e '^install$' | xargs -I '{}' rm -rf './{}'
|
||||
- cd ..
|
||||
- df -h
|
||||
- du -sh build/
|
||||
# - du -sh build/install/ # no install dir because it's commented out above
|
||||
- du -sh apt-cache/
|
||||
- du -sh ccache/
|
||||
- du -sh build/extern/fetched/
|
||||
artifacts:
|
||||
paths:
|
||||
- build/install/
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
timeout: 1h30m
|
||||
|
||||
.FindMissingMergeRequests:
|
||||
image: python:latest
|
||||
stage: build
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
variables:
|
||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||
cache:
|
||||
key: FindMissingMergeRequests.v1
|
||||
paths:
|
||||
- .cache/pip
|
||||
before_script:
|
||||
- pip3 install --user requests click discord_webhook
|
||||
script:
|
||||
- scripts/find_missing_merge_requests.py --project_id=$CI_PROJECT_ID --ignored_mrs_path=$CI_PROJECT_DIR/.resubmitted_merge_requests.txt
|
||||
|
||||
.flatpak:
|
||||
image: 'docker.io/bilelmoussaoui/flatpak-github-actions'
|
||||
stage: build
|
||||
script:
|
||||
- flatpak install -y flathub org.kde.Platform/x86_64/5.15-21.08
|
||||
- flatpak install -y flathub org.kde.Sdk/x86_64/5.15-21.08
|
||||
- flatpak-builder --ccache --force-clean --repo=repo build CI/org.openmw.OpenMW.devel.yaml
|
||||
- flatpak build-bundle ./repo openmw.flatpak org.openmw.OpenMW.devel
|
||||
cache:
|
||||
key: flatpak
|
||||
paths:
|
||||
- ".flatpak-builder"
|
||||
artifacts:
|
||||
untracked: false
|
||||
paths:
|
||||
- "openmw.flatpak"
|
||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||
# Flatpak Builds compile all dependencies aswell so need more time. Build results of libraries are cached
|
||||
timeout: 4h
|
||||
|
|
8
.resubmitted_merge_requests.txt
Normal file
8
.resubmitted_merge_requests.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
1471
|
||||
1450
|
||||
1420
|
||||
1314
|
||||
1216
|
||||
1172
|
||||
1160
|
||||
1051
|
100
.travis.yml
100
.travis.yml
|
@ -1,100 +0,0 @@
|
|||
language: cpp
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- coverity_scan
|
||||
- /openmw-.*$/
|
||||
- /^[0-9]+\.[0-9]+\.[0-9]+.*$/
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "1QK0yVyoOB+gf2I7XzvhXu9w/5lq4stBXIwJbVCTjz4Q4XVHCosURaW1MAgKzMrPnbFEwjyn5uQ8BwsvvfkuN1AZD0YXITgc7gyI+J1wQ/p/ljxRxglakU6WEgsTs2J5z9UmGac4YTXg+quK7YP3rv+zuGim2I2rhzImejyzp0Ym3kRCnNcy+SGBsiRaevRJMe00Ch8zGAbEhduQGeSoS6W0rcu02DNlQKiq5NktWsXR+TWWWVfIeIlQR/lbPsCd0pdxMaMv2QCY0rVbwrYxWJwr/Qe45dAdWp+8/C3PbXpeMSGxlLa33nJNX4Lf/djxbjm8KWk6edaXPajrjR/0iwcpwq0jg2Jt6XfEdnJt35F1gpXlc04sxStjG45uloOKCFYT0wdhIO1Lq+hDP54wypQl+JInd5qC001O7pwhVxO36EgKWqo8HD+BqGDBwsNj2engy9Qcp3wO6G0rLBPB3CrZsk9wrHVv5cSiQSLMhId3Xviu3ZI2qEDA+kgTvxrKrsnMj4bILVCyG5Ka2Mj22wIDW9e8oIab9oTdujax3DTN1GkD6QuOAGzwDsNwGASsgfoeZ+FUhgM75RlBWGMilgkmnF7EJ0oAXLEpjtABnEr2d4qHv+y08kOuTDBLB9ExzCIj024dYYYNLZrqPKx0ncHuCMG2QNj2aJAJEZtj1rQ="
|
||||
cache: ccache
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'ppa:openmw/openmw'
|
||||
- ubuntu-toolchain-r-test
|
||||
packages: [
|
||||
# Dev
|
||||
cmake, clang-tools-7, gcc-8, g++-8, ccache,
|
||||
# Boost
|
||||
libboost-filesystem-dev, libboost-iostreams-dev, libboost-program-options-dev, libboost-system-dev,
|
||||
# FFmpeg
|
||||
libavcodec-dev, libavformat-dev, libavutil-dev, libswresample-dev, libswscale-dev,
|
||||
# Audio, Video and Misc. deps
|
||||
libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev, liblz4-dev,
|
||||
# The other ones from OpenMW ppa
|
||||
libbullet-dev, libopenscenegraph-3.4-dev, libmygui-dev,
|
||||
# tes3mp stuff
|
||||
libboost-dev, libqt5opengl5-dev, libluajit-5.1-dev
|
||||
]
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "TES3MP/openmw-tes3mp"
|
||||
description: "<Your project description here>"
|
||||
branch_pattern: coverity_scan
|
||||
notification_email: koncord@tes3mp.com
|
||||
build_command_prepend: "cov-configure --comptype gcc --compiler gcc-8 --template; cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE"
|
||||
build_command: "make VERBOSE=1 -j3"
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env:
|
||||
- ANALYZE="scan-build-7 --use-cc clang-7 --use-c++ clang++-7 "
|
||||
- MATRIX_CC="CC=clang-7 && CXX=clang++-7"
|
||||
compiler: clang
|
||||
sudo: required
|
||||
dist: bionic
|
||||
- os: linux
|
||||
env:
|
||||
- MATRIX_CC="CC=gcc-8 && CXX=g++-8"
|
||||
sudo: required
|
||||
dist: bionic
|
||||
- os: linux
|
||||
env:
|
||||
- MATRIX_CC="CC=clang-7 && CXX=clang++-7"
|
||||
sudo: required
|
||||
dist: bionic
|
||||
allow_failures:
|
||||
- env:
|
||||
- MATRIX_CC="CC=clang-7 && CXX=clang++-7"
|
||||
- env:
|
||||
- ANALYZE="scan-build-7 --use-cc clang-7 --use-c++ clang++-7 "
|
||||
- MATRIX_CC="CC=clang-7 && CXX=clang++-7"
|
||||
|
||||
before_install:
|
||||
- ./CI/before_install.${TRAVIS_OS_NAME}.sh
|
||||
before_script:
|
||||
- ccache -z
|
||||
- ./CI/before_script.${TRAVIS_OS_NAME}.sh
|
||||
script:
|
||||
- cd ./build
|
||||
- ${ANALYZE} make -j3; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ] && [ "${BUILD_TESTS_ONLY}" ]; then ./openmw_test_suite; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||
- cd "${TRAVIS_BUILD_DIR}"
|
||||
- ccache -s
|
||||
#deploy:
|
||||
# provider: script
|
||||
# script: ./CI/deploy.osx.sh
|
||||
# skip_cleanup: true
|
||||
# on:
|
||||
# branch: master
|
||||
# condition: "$TRAVIS_EVENT_TYPE = cron && $TRAVIS_OS_NAME = osx"
|
||||
# repo: TES3MP/openmw-tes3mp
|
||||
#notifications:
|
||||
# email:
|
||||
# recipients:
|
||||
# - corrmage+travis-ci@gmail.com
|
||||
# on_success: change
|
||||
# on_failure: always
|
||||
# irc:
|
||||
# channels:
|
||||
# - "chat.freenode.net#openmw"
|
||||
# on_success: change
|
||||
# on_failure: always
|
||||
# use_notice: true
|
28
AUTHORS.md
28
AUTHORS.md
|
@ -27,8 +27,12 @@ Programmers
|
|||
Alexander Olofsson (Ananace)
|
||||
Alex Rice
|
||||
Alex S (docwest)
|
||||
Alexey Yaryshev (skeevert)
|
||||
Allofich
|
||||
Andreas Stöckel
|
||||
Andrei Kortunov (akortunov)
|
||||
Andrew Appuhamy (andrew-app)
|
||||
Andrzej Głuszak (agluszak)
|
||||
AnyOldName3
|
||||
Ardekantur
|
||||
Armin Preiml
|
||||
|
@ -42,6 +46,7 @@ Programmers
|
|||
Austin Salgat (Salgat)
|
||||
Ben Shealy (bentsherman)
|
||||
Berulacks
|
||||
Bo Svensson
|
||||
Britt Mathis (galdor557)
|
||||
Capostrophic
|
||||
Carl Maxwell
|
||||
|
@ -54,8 +59,9 @@ Programmers
|
|||
Cory F. Cohen (cfcohen)
|
||||
Cris Mihalache (Mirceam)
|
||||
crussell187
|
||||
DanielVukelich
|
||||
Dan Vukelich (sanchezman)
|
||||
darkf
|
||||
Dave Corley (S3ctor)
|
||||
David Cernat (davidcernat)
|
||||
Declan Millar (declan-millar)
|
||||
devnexen
|
||||
|
@ -67,16 +73,19 @@ Programmers
|
|||
David Teviotdale (dteviot)
|
||||
Diggory Hardy
|
||||
Dmitry Marakasov (AMDmi3)
|
||||
Duncan Frost (duncans_pumpkin)
|
||||
Edmondo Tommasina (edmondo)
|
||||
Eduard Cot (trombonecot)
|
||||
Eli2
|
||||
Emanuel Guével (potatoesmaster)
|
||||
Eris Caffee (eris)
|
||||
eroen
|
||||
escondida
|
||||
Evgeniy Mineev (sandstranger)
|
||||
Federico Guerra (FedeWar)
|
||||
Fil Krynicki (filkry)
|
||||
Finbar Crago (finbar-crago)
|
||||
Florent Teppe (Tetramir)
|
||||
Florian Weber (Florianjw)
|
||||
Frédéric Chardon (fr3dz10)
|
||||
Gaëtan Dezeiraud (Brouilles)
|
||||
|
@ -88,15 +97,18 @@ Programmers
|
|||
Haoda Wang (h313)
|
||||
hristoast
|
||||
Internecine
|
||||
Ivan Beloborodov (myrix)
|
||||
Jackerty
|
||||
Jacob Essex (Yacoby)
|
||||
Jacob Turnbull (Tankinfrank)
|
||||
Jake Westrip (16bitint)
|
||||
James Carty (MrTopCat)
|
||||
James Deciutiis (JamesDeciutiis)
|
||||
James Moore (moore.work)
|
||||
James Stephens (james-h-stephens)
|
||||
Jan-Peter Nilsson (peppe)
|
||||
Jan Borsodi (am0s)
|
||||
JanuarySnow
|
||||
Jason Hooks (jhooks)
|
||||
jeaye
|
||||
jefetienne
|
||||
|
@ -108,6 +120,7 @@ Programmers
|
|||
John Blomberg (fstp)
|
||||
Jordan Ayers
|
||||
Jordan Milne
|
||||
Josquin Frei
|
||||
Josua Grawitter
|
||||
Jules Blok (Armada651)
|
||||
julianko
|
||||
|
@ -118,6 +131,7 @@ Programmers
|
|||
Kurnevsky Evgeny (kurnevsky)
|
||||
Lars Söderberg (Lazaroth)
|
||||
lazydev
|
||||
Léo Peltier
|
||||
Leon Krieg (lkrieg)
|
||||
Leon Saunders (emoose)
|
||||
logzero
|
||||
|
@ -146,6 +160,7 @@ Programmers
|
|||
Miroslav Puda (pakanek)
|
||||
MiroslavR
|
||||
Mitchell Schwitzer (schwitzerm)
|
||||
Mitten.O
|
||||
naclander
|
||||
Narmo
|
||||
Nat Meo (Utopium)
|
||||
|
@ -154,8 +169,10 @@ Programmers
|
|||
Nialsy
|
||||
Nick Crawford (nighthawk469)
|
||||
Nikolay Kasyanov (corristo)
|
||||
Noah Gooder
|
||||
nobrakal
|
||||
Nolan Poe (nopoe)
|
||||
Nurivan Gomez (Nuri-G)
|
||||
Oleg Chkan (mrcheko)
|
||||
Paul Cercueil (pcercuei)
|
||||
Paul McElroy (Greendogo)
|
||||
|
@ -170,6 +187,7 @@ Programmers
|
|||
PlutonicOverkill
|
||||
Radu-Marius Popovici (rpopovici)
|
||||
Rafael Moura (dhustkoder)
|
||||
Randy Davin (Kindi)
|
||||
rdimesio
|
||||
rexelion
|
||||
riothamus
|
||||
|
@ -186,6 +204,7 @@ Programmers
|
|||
Sergey Shambir (sergey-shambir)
|
||||
sergoz
|
||||
ShadowRadiance
|
||||
Shihan42
|
||||
Siimacore
|
||||
Simon Meulenbeek (simonmb)
|
||||
sir_herrbatka
|
||||
|
@ -207,16 +226,20 @@ Programmers
|
|||
tlmullis
|
||||
tri4ng1e
|
||||
Thoronador
|
||||
Tobias Tribble (zackhasacat)
|
||||
Tom Lowe (Vulpen)
|
||||
Tom Mason (wheybags)
|
||||
Torben Leif Carrington (TorbenC)
|
||||
unelsson
|
||||
uramer
|
||||
viadanna
|
||||
Vidi_Aquam
|
||||
Vincent Heuken
|
||||
Vladimir Panteleev (CyberShadow)
|
||||
vocollapse
|
||||
Wang Ryu (bzzt)
|
||||
Will Herrmann (Thunderforge)
|
||||
vocollapse
|
||||
Wolfgang Lieff
|
||||
xyzz
|
||||
Yohaulticetl
|
||||
Yuri Krupenin
|
||||
|
@ -237,6 +260,7 @@ Documentation
|
|||
Joakim Berg (lysol90)
|
||||
Ryan Tucker (Ravenwing)
|
||||
sir_herrbatka
|
||||
David Nagy (zuzaman)
|
||||
|
||||
Packagers
|
||||
---------
|
||||
|
|
312
CHANGELOG.md
312
CHANGELOG.md
|
@ -1,3 +1,313 @@
|
|||
0.49.0
|
||||
------
|
||||
|
||||
Bug #2623: Snowy Granius doesn't prioritize conjuration spells
|
||||
Bug #3842: Body part skeletons override the main skeleton
|
||||
Bug #4127: Weapon animation looks choppy
|
||||
Bug #4204: Dead slaughterfish doesn't float to water surface after loading saved game
|
||||
Bug #4382: Sound output device does not change when it should
|
||||
Bug #4610: Casting a Bound Weapon spell cancels the casting animation by equipping the weapon prematurely
|
||||
Bug #4754: Stack of ammunition cannot be equipped partially
|
||||
Bug #4816: GetWeaponDrawn returns 1 before weapon is attached
|
||||
Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses
|
||||
Bug #5129: Stuttering animation on Centurion Archer
|
||||
Bug #5371: Keyframe animation tracks are used for any file that begins with an X
|
||||
Bug #5714: Touch spells cast using ExplodeSpell don't always explode
|
||||
Bug #5849: Paralysis breaks landing
|
||||
Bug #5870: Disposing of actors who were selected in the console doesn't deselect them like vanilla
|
||||
Bug #5883: Immobile creatures don't cause water ripples
|
||||
Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load
|
||||
Bug #6027: Collisionshape becomes spiderweb-like when the mesh is too complex
|
||||
Bug #6313: Followers with high Fight can turn hostile
|
||||
Bug #6427: Enemy health bar disappears before damaging effect ends
|
||||
Bug #6550: Cloned body parts don't inherit texture effects
|
||||
Bug #6645: Enemy block sounds align with animation instead of blocked hits
|
||||
Bug #6657: Distant terrain tiles become black when using FWIW mod
|
||||
Bug #6661: Saved games that have no preview screenshot cause issues or crashes
|
||||
Bug #6716: mwscript comparison operator handling is too restrictive
|
||||
Bug #6807: Ultimate Galleon is not working properly
|
||||
Bug #6893: Lua: Inconsistent behavior with actors affected by Disable and SetDelete commands
|
||||
Bug #6894: Added item combines with equipped stack instead of creating a new unequipped stack
|
||||
Bug #6939: OpenMW-CS: ID columns are too short
|
||||
Bug #6949: Sun Damage effect doesn't work in quasi exteriors
|
||||
Bug #6964: Nerasa Dralor Won't Follow
|
||||
Bug #6973: Fade in happens after the scene load and is shown
|
||||
Bug #6974: Only harmful effects are reflected
|
||||
Bug #6977: Sun damage implementation does not match research
|
||||
Bug #6986: Sound magic effect does not make noise
|
||||
Bug #6987: Set/Mod Blindness should not darken the screen
|
||||
Bug #6992: Crossbow reloading doesn't look the same as in Morrowind
|
||||
Bug #6993: Shooting your last round of ammunition causes the attack animation to cancel
|
||||
Bug #7009: Falling actors teleport to the ground without receiving any damage on cell loading
|
||||
Bug #7034: Misc items defined in one content file are not treated as keys if another content file uses them as such
|
||||
Bug #7042: Weapon follow animations that immediately follow the hit animations cause multiple hits
|
||||
Bug #7044: Changing a class' services does not affect autocalculated NPCs
|
||||
Bug #7054: Quests aren't sorted by name
|
||||
Bug #7064: NPCs don't report crime if the player is casting offensive spells on them while sneaking
|
||||
Bug #7077: OpenMW fails to load certain particle effects in .osgt format
|
||||
Bug #7084: Resurrecting an actor doesn't take into account base record changes
|
||||
Bug #7088: Deleting last save game of last character doesn't clear character name/details
|
||||
Bug #7092: BSA archives from higher priority directories don't take priority
|
||||
Bug #7122: Teleportation to underwater should cancel active water walking effect
|
||||
Bug #7131: MyGUI log spam when post processing HUD is open
|
||||
Bug #7163: Myar Aranath: Wheat breaks the GUI
|
||||
Bug #7172: Current music playlist continues playing indefinitely if next playlist is empty
|
||||
Bug #7229: Error marker loading failure is not handled
|
||||
Bug #7243: Supporting loading external files from VFS from esm files
|
||||
Bug #7298: Water ripples from projectiles sometimes are not spawned
|
||||
Bug #7307: Alchemy "Magic Effect" search string does not match on tool tip for effects related to attributes
|
||||
Bug #7413: Generated wilderness cells don't spawn fish
|
||||
Bug #7415: Unbreakable lock discrepancies
|
||||
Bug #7428: AutoCalc flag is not used to calculate enchantment costs
|
||||
Feature #3537: Shader-based water ripples
|
||||
Feature #5492: Let rain and snow collide with statics
|
||||
Feature #6447: Add LOD support to Object Paging
|
||||
Feature #6491: Add support for Qt6
|
||||
Feature #6726: Lua API for creating new objects
|
||||
Feature #6922: Improve launcher appearance
|
||||
Feature #6933: Support high-resolution cursor textures
|
||||
Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData
|
||||
Feature #6979: Add support of loading and displaying LOD assets purely based on their filename extension
|
||||
Feature #6983: PCVisionBonus script functions
|
||||
Feature #6995: Localize the "show effect duration" option
|
||||
Feature #7058: Implement TestModels (T3D) console command
|
||||
Feature #7087: Block resolution change in the Windowed Fullscreen mode
|
||||
Feature #7125: Remembering console commands between sessions
|
||||
Feature #7129: Add support for non-adaptive VSync
|
||||
Feature #7130: Ability to set MyGUI logging verbosity
|
||||
Feature #7148: Optimize string literal lookup in mwscript
|
||||
Feature #7194: Ori to show texture paths
|
||||
Feature #7214: Searching in the in-game console
|
||||
Task #7113: Move from std::atoi to std::from_char
|
||||
Task #7117: Replace boost::scoped_array with std::vector
|
||||
Task #7151: Do not use std::strerror to get errno error message
|
||||
Task #7394: Drop support for --fs-strict
|
||||
|
||||
0.48.0
|
||||
------
|
||||
|
||||
Bug #1751: Birthsign abilities increase modified attribute values instead of base ones
|
||||
Bug #1930: Followers are still fighting if a target stops combat with a leader
|
||||
Bug #2036: SetStat and ModStat instructions aren't implemented the same way as in Morrowind
|
||||
Bug #3246: ESSImporter: Most NPCs are dead on save load
|
||||
Bug #3488: AI combat aiming is too slow
|
||||
Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear
|
||||
Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions)
|
||||
Bug #3792: 1 frame late magicka recalc breaks early scripted magicka reactions to Intelligence change
|
||||
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
|
||||
Bug #3855: AI sometimes spams defensive spells
|
||||
Bug #3867: All followers attack player when one follower enters combat with player
|
||||
Bug #3905: Great House Dagoth issues
|
||||
Bug #4175: Objects "vibrate" when extremely far from (0,0)
|
||||
Bug #4203: Resurrecting an actor doesn't close the loot GUI
|
||||
Bug #4227: Spellcasting restrictions are checked before spellcasting animations are played
|
||||
Bug #4310: Spell description is centered
|
||||
Bug #4374: Player rotation reset when nearing area that hasn't been loaded yet
|
||||
Bug #4376: Moved actors don't respawn in their original cells
|
||||
Bug #4389: NPC's lips do not move if his head model has the NiBSAnimationNode root node
|
||||
Bug #4526: Crash when additional maps are applied over a model with out of bounds UV
|
||||
Bug #4602: Robert's Bodies: crash inside createInstance()
|
||||
Bug #4700: OpenMW-CS: Incorrect command implementation
|
||||
Bug #4744: Invisible particles aren't always processed
|
||||
Bug #4949: Incorrect particle lighting
|
||||
Bug #5054: Non-biped creatures don't use spellcast equip/unequip animations
|
||||
Bug #5088: Sky abruptly changes direction during certain weather transitions
|
||||
Bug #5100: Persuasion doesn't always clamp the resulting disposition
|
||||
Bug #5120: Scripted object spawning updates physics system
|
||||
Bug #5192: Actor turn rate is too slow
|
||||
Bug #5207: Loose summons can be present in scene
|
||||
Bug #5279: Ingame console stops auto-scrolling after clicking output
|
||||
Bug #5318: Aiescort behaves differently from vanilla
|
||||
Bug #5377: Console does not appear after using menutest in inventory
|
||||
Bug #5379: Wandering NPCs falling through cantons
|
||||
Bug #5394: Windows snapping no longer works
|
||||
Bug #5434: Pinned windows shouldn't cover breath progress bar
|
||||
Bug #5453: Magic effect VFX are offset for creatures
|
||||
Bug #5483: AutoCalc flag is not used to calculate spells cost
|
||||
Bug #5508: Engine binary links to Qt without using it
|
||||
Bug #5592: Weapon idle animations do not work properly
|
||||
Bug #5596: Effects in constant spells should not be merged
|
||||
Bug #5621: Drained stats cannot be restored
|
||||
Bug #5766: Active grid object paging - disappearing textures
|
||||
Bug #5788: Texture editing parses the selected indexes wrongly
|
||||
Bug #5801: A multi-effect spell with the intervention effects and recall always favors Almsivi intervention
|
||||
Bug #5842: GetDisposition adds temporary disposition change from different actors
|
||||
Bug #5858: Visible modal windows and dropdowns crashing game on exit
|
||||
Bug #5863: GetEffect should return true after the player has teleported
|
||||
Bug #5913: Failed assertion during Ritual of Trees quest
|
||||
Bug #5937: Lights always need to be rotated by 90 degrees
|
||||
Bug #5976: Invisibility is broken when the attack starts instead of when it ends
|
||||
Bug #5978: NPCs and Creatures talk to and headtrack a player character with a 75% chameleon effect or more
|
||||
Bug #5989: Simple water isn't affected by texture filter settings
|
||||
Bug #6037: Launcher: Morrowind content language cannot be set to English
|
||||
Bug #6049: Main Theme on OpenMW should begin on the second video like Vanilla.
|
||||
Bug #6051: NaN water height in ESM file is not handled gracefully
|
||||
Bug #6054: Hotkey items can be equipped while in ready to attack stance
|
||||
Bug #6066: Addtopic "return" does not work from within script. No errors thrown
|
||||
Bug #6067: ESP loader fails for certain subrecord orders
|
||||
Bug #6087: Bound items added directly to the inventory disappear if their corresponding spell effect ends
|
||||
Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime
|
||||
Bug #6107: Fatigue is incorrectly recalculated when fortify effect is applied or removed
|
||||
Bug #6109: Crash when playing a custom made menu_background file
|
||||
Bug #6115: Showmap overzealous matching
|
||||
Bug #6118: Creature landing sound counts as a footstep
|
||||
Bug #6123: NPC with broken script freezes the game on hello
|
||||
Bug #6129: Player avatar not displayed correctly for large window sizes when GUI scaling active
|
||||
Bug #6131: Item selection in the avatar window not working correctly for large window sizes
|
||||
Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player
|
||||
Bug #6142: Groundcover plugins change cells flags
|
||||
Bug #6143: Capturing a screenshot renders the engine temporarily unresponsive
|
||||
Bug #6154: Levitating player character is floating rather than on the floor when teleported back from Magas Volar
|
||||
Bug #6165: Paralyzed player character can pickup items when the inventory is open
|
||||
Bug #6168: Weather particles flicker for a frame at start of storms
|
||||
Bug #6172: Some creatures can't open doors
|
||||
Bug #6174: Spellmaking and Enchanting sliders differences from vanilla
|
||||
Bug #6177: Followers of player follower stop following after waiting for a day
|
||||
Bug #6184: Command and Calm and Demoralize and Frenzy and Rally magic effects inconsistencies with vanilla
|
||||
Bug #6191: Encumbrance messagebox timer works incorrectly
|
||||
Bug #6197: Infinite Casting Loop
|
||||
Bug #6253: Multiple instances of Reflect stack additively
|
||||
Bug #6255: Reflect is different from vanilla
|
||||
Bug #6256: Crash on exit with enabled shadows and statically linked OpenSceneGraph
|
||||
Bug #6258: Barter menu glitches out when modifying prices
|
||||
Bug #6273: Respawning NPCs rotation is inconsistent
|
||||
Bug #6276: Deleted groundcover instances are not deleted in game
|
||||
Bug #6282: Laura craft doesn't follow the player character
|
||||
Bug #6283: Avis Dorsey follows you after her death
|
||||
Bug #6285: OpenMW-CS: Brush template drawing and terrain selection drawing performance is very bad
|
||||
Bug #6289: Keyword search in dialogues expected the text to be all ASCII characters
|
||||
Bug #6291: Can't pickup the dead mage's journal from the mysterious hunter mod
|
||||
Bug #6302: Teleporting disabled actor breaks its disabled state
|
||||
Bug #6303: After "go to jail" weapon can be stuck in the ready to attack state
|
||||
Bug #6307: Pathfinding in Infidelities quest from Tribunal addon is broken
|
||||
Bug #6321: Arrow enchantments should always be applied to the target
|
||||
Bug #6322: Total sold/cost should reset to 0 when there are no items offered
|
||||
Bug #6323: Wyrmhaven: Alboin doesn't follower the player character out of his house
|
||||
Bug #6324: Special Slave Companions: Can't buy the slave companions
|
||||
Bug #6326: Detect Enchantment/Key should detect items in unresolved containers
|
||||
Bug #6327: Blocking roots the character in place
|
||||
Bug #6333: Werewolf stat changes should be implemented as damage/fortifications
|
||||
Bug #6343: Magic projectile speed doesn't take race weight into account
|
||||
Bug #6347: PlaceItem/PlaceItemCell/PlaceAt should work with levelled creatures
|
||||
Bug #6354: SFX abruptly cut off after crossing max distance
|
||||
Bug #6358: Changeweather command does not report an error when entering non-existent region
|
||||
Bug #6363: Some scripts in Morrowland fail to work
|
||||
Bug #6376: Creatures should be able to use torches
|
||||
Bug #6386: Artifacts in water reflection due to imprecise screen-space coordinate computation
|
||||
Bug #6389: Maximum light distance setting doesn't affect water reflections
|
||||
Bug #6395: Translations with longer tab titles may cause tabs to disappear from the options menu
|
||||
Bug #6396: Inputting certain Unicode characters triggers an assertion
|
||||
Bug #6416: Morphs are applied to the wrong target
|
||||
Bug #6417: OpenMW doesn't always use the right node to accumulate movement
|
||||
Bug #6429: Wyrmhaven: Can't add AI packages to player
|
||||
Bug #6433: Items bound to Quick Keys sometimes do not appear until the Quick Key menu is opened
|
||||
Bug #6451: Weapon summoned from Cast When Used item will have the name "None"
|
||||
Bug #6473: Strings from NIF should be parsed only to first null terminator
|
||||
Bug #6493: Unlocking owned but not locked or unlocked containers is considered a crime
|
||||
Bug #6517: Rotations for KeyframeData in NIFs should be optional
|
||||
Bug #6519: Effects tooltips for ingredients work incorrectly
|
||||
Bug #6523: Disintegrate Weapon is resisted by Resist Magicka instead of Sanctuary
|
||||
Bug #6544: Far from world origin objects jitter when camera is still
|
||||
Bug #6545: Player character momentum is preserved when going to a different cell
|
||||
Bug #6559: Weapon condition inconsistency between melee and ranged critical / sneak / KO attacks
|
||||
Bug #6579: OpenMW compilation error when using OSG doubles for BoundingSphere
|
||||
Bug #6606: Quests with multiple IDs cannot always be restarted
|
||||
Bug #6653: With default settings the in-game console doesn't fit into screen
|
||||
Bug #6655: Constant effect absorb attribute causes the game to break
|
||||
Bug #6667: Pressing the Esc key while resting or waiting causes black screen.
|
||||
Bug #6670: Dialogue order is incorrect
|
||||
Bug #6680: object.cpp handles nodetree unsafely, memory access with dangling pointer
|
||||
Bug #6682: HitOnMe doesn't fire as intended
|
||||
Bug #6697: Shaders vertex lighting incorrectly clamped
|
||||
Bug #6705: OpenMW CS: A typo in the Creature levelled list
|
||||
Bug #6711: Log time differs from real time
|
||||
Bug #6717: Broken script causes interpreter stack corruption
|
||||
Bug #6718: Throwable weapons cause arrow enchantment effect to be applied to the whole body
|
||||
Bug #6730: LoopGroup stalls animation after playing :Stop frame until another animation is played
|
||||
Bug #6753: Info records without a DATA subrecords are loaded incorrectly
|
||||
Bug #6794: Light sources are attached to mesh bounds centers instead of mesh origins when AttachLight NiNode is missing
|
||||
Bug #6799: Game crashes if an NPC has no Class attached
|
||||
Bug #6849: ImageButton texture is not scaled properly
|
||||
Bug #6860: Sinnammu randomly strafes while running on water
|
||||
Bug #6869: Hits queue stagger during swing animation
|
||||
Bug #6890: SDL_PeepEvents errors are not handled
|
||||
Bug #6895: Removing a negative number of items from a script, makes the script terminate with an error
|
||||
Bug #6896: Sounds played using PlaySound3D are cut off as the emitter leaves the cell
|
||||
Bug #6898: Accessing the Quick Inventory menu does not work while in menu mode
|
||||
Bug #6901: Morrowind.exe soul gem usage discrepancy
|
||||
Bug #6909: Using enchanted items has no animation
|
||||
Bug #6910: Torches should not be extinguished when not being held
|
||||
Bug #6913: Constant effect enchanted items don't break invisibility
|
||||
Bug #6923: Dispose of corpse prevents respawning after load
|
||||
Bug #6937: Divided by Nix Hounds quest is broken
|
||||
Bug #7008: Race condition on initializing a vector of reserved node names
|
||||
Bug #7121: Crash on TimeStamp construction with invalid hour value
|
||||
Bug #7251: Force shaders setting still renders some drawables with FFP
|
||||
Feature #890: OpenMW-CS: Column filtering
|
||||
Feature #1465: "Reset" argument for AI functions
|
||||
Feature #2491: Ability to make OpenMW "portable"
|
||||
Feature #2554: OpenMW-CS: Modifying an object in the cell view should trigger the instances table to scroll to the corresponding record
|
||||
Feature #2766: Warn user if their version of Morrowind is not the latest.
|
||||
Feature #2780: A way to see current OpenMW version in the console
|
||||
Feature #2858: Add a tab to the launcher for handling datafolders
|
||||
Feature #3180: Support uncompressed colour-mapped TGA files
|
||||
Feature #3245: OpenMW-CS: Instance editing grid
|
||||
Feature #3616: Allow Zoom levels on the World Map
|
||||
Feature #3668: Support palettized DDS files
|
||||
Feature #4067: Post Processing
|
||||
Feature #4297: Implement APPLIED_ONCE flag for magic effects
|
||||
Feature #4414: Handle duration of EXTRA SPELL magic effect
|
||||
Feature #4595: Unique object identifier
|
||||
Feature #4974: Overridable MyGUI layout
|
||||
Feature #4975: Built-in TrueType fonts
|
||||
Feature #5198: Implement "Magic effect expired" event
|
||||
Feature #5454: Clear active spells from actor when he disappears from scene
|
||||
Feature #5489: MCP: Telekinesis fix for activators
|
||||
Feature #5701: Convert osgAnimation::RigGeometry to double-buffered custom version
|
||||
Feature #5737: OpenMW-CS: Handle instance move from one cell to another
|
||||
Feature #5928: Allow Glow in the Dahrk to be disabled
|
||||
Feature #5996: Support Lua scripts in OpenMW
|
||||
Feature #6017: Separate persistent and temporary cell references when saving
|
||||
Feature #6019: Add antialias alpha test to the launcher or enable by default if possible
|
||||
Feature #6032: Reverse-z depth buffer
|
||||
Feature #6078: Do not clear depth buffer for first-person meshes
|
||||
Feature #6128: Soft Particles
|
||||
Feature #6171: In-game log viewer
|
||||
Feature #6189: Navigation mesh disk cache
|
||||
Feature #6199: Support FBO Rendering
|
||||
Feature #6248: Embedded error marker mesh
|
||||
Feature #6249: Alpha testing support for Collada
|
||||
Feature #6251: OpenMW-CS: Set instance movement based on camera zoom
|
||||
Feature #6288: OpenMW-CS: Preserve "blocked" record flags when saving
|
||||
Feature #6360: More realistic raindrop ripples
|
||||
Feature #6380: Treat commas as whitespace in scripts
|
||||
Feature #6419: Don't grey out topics if they can produce another topic reference
|
||||
Feature #6443: Support NiStencilProperty
|
||||
Feature #6496: Handle NCC flag in NIF files
|
||||
Feature #6534: Shader-based object texture blending
|
||||
Feature #6541: Gloss-mapping
|
||||
Feature #6557: Add support for controller gyroscope
|
||||
Feature #6592: Support for NiTriShape particle emitters
|
||||
Feature #6600: Support NiSortAdjustNode
|
||||
Feature #6631: Support FFMPEG 5
|
||||
Feature #6684: Support NiFltAnimationNode
|
||||
Feature #6699: Support Ignored flag
|
||||
Feature #6700: Support windowed fullscreen
|
||||
Feature #6706: Save the size of the Options window
|
||||
Feature #6721: OpenMW-CS: Add option to open records in new window
|
||||
Feature #6823: Animation layering for osgAnimation formats
|
||||
Feature #6867: Add a way to localize hardcoded strings in GUI
|
||||
Feature #6888: Add switch for armor degradation fix
|
||||
Feature #6925: Allow to use a mouse wheel to rotate a head in the race selection menu
|
||||
Feature #6941: Allow users to easily change font size and ttf resolution
|
||||
Feature #7434: Exponential fog
|
||||
Feature #7435: Sky blending
|
||||
Task #5534: Remove support for OSG 3.4
|
||||
Task #6161: Refactor Sky to use shaders and be GLES/GL3 friendly
|
||||
Task #6162: Refactor GUI to use shaders and to be GLES and GL3+ friendly
|
||||
Task #6435: Add support for MSVC 2022
|
||||
Task #6564: Remove predefined data paths `data="?global?data"`, `data=./data`
|
||||
|
||||
0.47.0
|
||||
------
|
||||
|
||||
|
@ -180,6 +490,7 @@
|
|||
Feature #6024: OpenMW-CS: Selecting terrain in "Terrain land editing" should support "Add to selection" and "Remove from selection" modes
|
||||
Feature #6033: Include pathgrid to navigation mesh
|
||||
Feature #6034: Find path based on area cost depending on NPC stats
|
||||
Feature #7161: OpenMW-CS: Make adding and filtering TopicInfos easier
|
||||
Task #5480: Drop Qt4 support
|
||||
Task #5520: Improve cell name autocompleter implementation
|
||||
|
||||
|
@ -1907,6 +2218,7 @@
|
|||
Bug #2025: Missing mouse-over text for non affordable items
|
||||
Bug #2028: [MOD: Tamriel Rebuilt] Crashing when trying to enter interior cell "Ruinous Keep, Great Hall"
|
||||
Bug #2029: Ienith Brothers Thiev's Guild quest journal entry not adding
|
||||
Bug #3066: Editor doesn't check if IDs and other strings are longer than their hardcoded field length
|
||||
Feature #471: Editor: Special case implementation for top-level window with single sub-window
|
||||
Feature #472: Editor: Sub-Window re-use settings
|
||||
Feature #704: Font colors import from fallback settings
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
*** PLEASE PUT YOUR ISSUE DESCRIPTION FOR DUMMIES HERE FOR REVIEW ***
|
||||
|
||||
- I'm just a placeholder description (#1337)
|
||||
- I'm also just a placeholder description, but I'm a more recent one (#42)
|
||||
|
||||
***
|
||||
|
||||
0.47.0
|
||||
------
|
||||
|
||||
The OpenMW team is proud to announce the release of version 0.47.0! Grab it from our Downloads Page for all operating systems. ***short summary: XXX ***
|
||||
|
||||
Check out the release video (***add link***) and the OpenMW-CS release video (***add link***) by the ***add flattering adjective*** Atahualpa, and see below for the full list of changes.
|
||||
|
||||
Known Issues:
|
||||
- To use generic Linux binaries, Qt4 and libpng12 must be installed on your system
|
||||
- On macOS, launching OpenMW from OpenMW-CS requires OpenMW.app and OpenMW-CS.app to be siblings
|
||||
|
||||
New Features:
|
||||
- Dialogue to split item stacks now displays the name of the trapped soul for stacks of soul gems (#5362)
|
||||
- Basics of Collada animations are now supported via osgAnimation plugin (#5456)
|
||||
|
||||
New Editor Features:
|
||||
- Instance selection modes are now implemented (centred cube, corner-dragged cube, sphere) with four user-configurable actions (select only, add to selection, remove from selection, invert selection) (#3171)
|
||||
|
||||
Bug Fixes:
|
||||
- NiParticleColorModifier in NIF files is now properly handled which solves issues regarding particle effects, e.g., smoke and fire (#1952, #3676)
|
||||
- Targetting non-unique actors in scripts is now supported (#2311)
|
||||
- Guards no longer ignore attacks of invisible players but rather initiate dialogue and flee if the player resists being arrested (#4774)
|
||||
- Changing the dialogue window without closing it no longer clears the dialogue history in order to allow, e.g., emulation of three-way dialogue via ForceGreeting (#5358)
|
||||
- Scripts which try to start a non-existent global script now skip that step and continue execution instead of breaking (#5364)
|
||||
- Selecting already equipped spells or magic items via hotkey no longer triggers the equip sound to play (#5367)
|
||||
- 'Scale' argument in levelled creature lists is now taken into account when spawning creatures from such lists (#5369)
|
||||
- Morrowind legacy madness: Using a key on a trapped door/container now only disarms the trap if the door/container is locked (#5370)
|
||||
|
||||
Editor Bug Fixes:
|
||||
- Deleted and moved objects within a cell are now saved properly (#832)
|
||||
- Disabled record sorting in Topic and Journal Info tables, implemented drag-move for records (#4357)
|
||||
- Topic and Journal Info records can now be cloned with a different parent Topic/Journal Id (#4363)
|
||||
- Verifier no longer checks for alleged 'race' entries in clothing body parts (#5400)
|
||||
- Cell borders are now properly redrawn when undoing/redoing terrain changes (#5473)
|
||||
- Loading mods now keeps the master index (#5675)
|
||||
- Flicker and crashing on XFCE4 fixed (#5703)
|
||||
- Collada models render properly in the Editor (#5713)
|
||||
- Terrain-selection grid is now properly updated when undoing/redoing terrain changes (#6022)
|
||||
- Tool outline and select/edit actions in "Terrain land editing" mode now ignore references (#6023)
|
||||
- Primary-select and secondary-select actions in "Terrain land editing" mode now behave like in "Instance editing" mode (#6024)
|
||||
- Using the circle brush to select terrain in the "Terrain land editing" mode no longer selects vertices outside the circle (#6035)
|
||||
- Vertices at the NW and SE corners of a cell can now also be selected in "Terrain land editing" mode if the adjacent cells aren't loaded yet (#6036)
|
||||
|
||||
Miscellaneous:
|
||||
- Prevent save-game bloating by using an appropriate fog texture format (#5108)
|
||||
- Ensure that 'Enchantment autocalc" flag is treated as flag in OpenMW-CS and in our esm tools (#5363)
|
52
CI/Store-Symbols.ps1
Normal file
52
CI/Store-Symbols.ps1
Normal file
|
@ -0,0 +1,52 @@
|
|||
if (-Not (Test-Path CMakeCache.txt))
|
||||
{
|
||||
Write-Error "This script must be run from the build directory."
|
||||
}
|
||||
|
||||
if (-Not (Test-Path .cmake\api\v1\reply))
|
||||
{
|
||||
New-Item -Type File -Force .cmake\api\v1\query\codemodel-v2
|
||||
cmake .
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Push-Location .cmake\api\v1\reply
|
||||
|
||||
$index = Get-Content -Raw index-*.json | ConvertFrom-Json
|
||||
|
||||
$codemodel = Get-Content -Raw $index.reply."codemodel-v2".jsonFile | ConvertFrom-Json
|
||||
|
||||
$targets = @()
|
||||
$codemodel.configurations | ForEach-Object {
|
||||
$_.targets | ForEach-Object {
|
||||
$target = Get-Content -Raw $_.jsonFile | ConvertFrom-Json
|
||||
if ($target.type -eq "EXECUTABLE" -or $target.type -eq "SHARED_LIBRARY")
|
||||
{
|
||||
$targets += $target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$artifacts = @()
|
||||
$targets | ForEach-Object {
|
||||
$_.artifacts | ForEach-Object {
|
||||
$artifacts += $_.path
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if (-not (Test-Path symstore-venv))
|
||||
{
|
||||
python -m venv symstore-venv
|
||||
}
|
||||
if (-not (Test-Path symstore-venv\Scripts\symstore.exe))
|
||||
{
|
||||
symstore-venv\Scripts\pip install symstore==0.3.3
|
||||
}
|
||||
$artifacts = $artifacts | Where-Object { Test-Path $_ }
|
||||
symstore-venv\Scripts\symstore --compress .\SymStore @artifacts
|
|
@ -23,11 +23,11 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|||
fi
|
||||
|
||||
command -v unixPathAsWindows >/dev/null 2>&1 || function unixPathAsWindows {
|
||||
if command -v cygpath >/dev/null 2>&1; then
|
||||
cygpath -w $1
|
||||
else
|
||||
echo "$1" | sed "s,^/\([^/]\)/,\\1:/," | sed "s,/,\\\\,g"
|
||||
fi
|
||||
if command -v cygpath >/dev/null 2>&1; then
|
||||
cygpath -w $1
|
||||
else
|
||||
echo "$1" | sed "s,^/\([^/]\)/,\\1:/," | sed "s,/,\\\\,g"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/android/openmw-android-deps-20201129.zip -o ~/openmw-android-deps.zip
|
||||
unzip -o ~/openmw-android-deps -d /usr/lib/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr > /dev/null
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/android/openmw-android-deps-20211114.zip -o ~/openmw-android-deps.zip
|
||||
unzip -o ~/openmw-android-deps -d /android-ndk-r22/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr > /dev/null
|
||||
|
|
|
@ -1,22 +1,39 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
# workaround python issue on travis
|
||||
[ -z "${TRAVIS}" ] && HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies python@3.8 || true
|
||||
[ -z "${TRAVIS}" ] && HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies python@3.9 || true
|
||||
[ -z "${TRAVIS}" ] && HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies qt@6 || true
|
||||
export HOMEBREW_NO_EMOJI=1
|
||||
|
||||
brew uninstall --ignore-dependencies python@3.8 || true
|
||||
brew uninstall --ignore-dependencies python@3.9 || true
|
||||
brew uninstall --ignore-dependencies qt@5 || true
|
||||
brew uninstall --ignore-dependencies jpeg || true
|
||||
|
||||
brew tap --repair
|
||||
brew update --quiet
|
||||
|
||||
# Some of these tools can come from places other than brew, so check before installing
|
||||
brew reinstall xquartz fontconfig freetype harfbuzz brotli
|
||||
|
||||
# Fix: can't open file: @loader_path/libbrotlicommon.1.dylib (No such file or directory)
|
||||
BREW_LIB_PATH="$(brew --prefix)/lib"
|
||||
install_name_tool -change "@loader_path/libbrotlicommon.1.dylib" "${BREW_LIB_PATH}/libbrotlicommon.1.dylib" ${BREW_LIB_PATH}/libbrotlidec.1.dylib
|
||||
install_name_tool -change "@loader_path/libbrotlicommon.1.dylib" "${BREW_LIB_PATH}/libbrotlicommon.1.dylib" ${BREW_LIB_PATH}/libbrotlienc.1.dylib
|
||||
|
||||
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@5
|
||||
export PATH="/usr/local/opt/qt@5/bin:$PATH" # needed to use qmake in none default path as qt now points to qt6
|
||||
command -v qmake >/dev/null 2>&1 || brew install qt@6
|
||||
|
||||
# Install deps
|
||||
brew install icu4c yaml-cpp sqlite
|
||||
|
||||
ccache --version
|
||||
cmake --version
|
||||
qmake --version
|
||||
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20210617.zip -o ~/openmw-deps.zip
|
||||
unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||
if [[ "${MACOS_AMD64}" ]]; then
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20221113.zip -o ~/openmw-deps.zip
|
||||
else
|
||||
curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20230223_arm64.zip -o ~/openmw-deps.zip
|
||||
fi
|
||||
|
||||
unzip -o ~/openmw-deps.zip -d /tmp > /dev/null
|
||||
|
||||
# additional libraries
|
||||
[ -z "${TRAVIS}" ] && HOMEBREW_NO_AUTO_UPDATE=1 brew install fontconfig
|
|
@ -3,13 +3,31 @@
|
|||
# hack to work around: FFmpeg version is too old, 3.2 is required
|
||||
sed -i s/"NOT FFVER_OK"/"FALSE"/ CMakeLists.txt
|
||||
|
||||
# Silence a git warning
|
||||
git config --global advice.detachedHead false
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
# Build a version of ICU for the host so that it can use the tools during the cross-compilation
|
||||
mkdir -p icu-host-build
|
||||
cd icu-host-build
|
||||
if [ -r ../extern/fetched/icu/icu4c/source/configure ]; then
|
||||
ICU_SOURCE_DIR=../extern/fetched/icu/icu4c/source
|
||||
else
|
||||
wget https://github.com/unicode-org/icu/archive/refs/tags/release-70-1.zip
|
||||
unzip release-70-1.zip
|
||||
ICU_SOURCE_DIR=./icu-release-70-1/icu4c/source
|
||||
fi
|
||||
${ICU_SOURCE_DIR}/configure --disable-tests --disable-samples --disable-icuio --disable-extras CC="ccache gcc" CXX="ccache g++"
|
||||
make -j $(nproc)
|
||||
cd ..
|
||||
|
||||
cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/usr/lib/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/android-ndk-r22/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_ABI=arm64-v8a \
|
||||
-DANDROID_PLATFORM=android-21 \
|
||||
-DANDROID_LD=deprecated \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_INSTALL_PREFIX=install \
|
||||
|
@ -21,7 +39,11 @@ cmake \
|
|||
-DBUILD_ESSIMPORTER=0 \
|
||||
-DBUILD_OPENCS=0 \
|
||||
-DBUILD_WIZARD=0 \
|
||||
-DBUILD_NAVMESHTOOL=OFF \
|
||||
-DBUILD_BULLETOBJECTTOOL=OFF \
|
||||
-DOPENMW_USE_SYSTEM_MYGUI=OFF \
|
||||
-DOPENMW_USE_SYSTEM_OSG=OFF \
|
||||
-DOPENMW_USE_SYSTEM_BULLET=OFF \
|
||||
-DOPENMW_USE_SYSTEM_SQLITE3=OFF \
|
||||
-DOPENMW_USE_SYSTEM_YAML_CPP=OFF \
|
||||
-DOPENMW_USE_SYSTEM_ICU=OFF \
|
||||
-DOPENMW_ICU_HOST_BUILD_DIR="$(pwd)/icu-host-build" \
|
||||
..
|
||||
|
|
|
@ -4,35 +4,81 @@ set -xeo pipefail
|
|||
|
||||
free -m
|
||||
|
||||
# Silence a git warning
|
||||
git config --global advice.detachedHead false
|
||||
|
||||
BUILD_UNITTESTS=OFF
|
||||
BUILD_BENCHMARKS=OFF
|
||||
|
||||
if [[ "${BUILD_TESTS_ONLY}" ]]; then
|
||||
export GOOGLETEST_DIR="${PWD}/googletest/build/install"
|
||||
env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_googletest.sh
|
||||
BUILD_UNITTESTS=ON
|
||||
BUILD_BENCHMARKS=ON
|
||||
fi
|
||||
|
||||
# setup our basic cmake build options
|
||||
declare -a CMAKE_CONF_OPTS=(
|
||||
-DCMAKE_C_COMPILER="${CC:-/usr/bin/cc}"
|
||||
-DCMAKE_CXX_COMPILER="${CXX:-/usr/bin/c++}"
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_INSTALL_PREFIX=install
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DUSE_SYSTEM_TINYXML=ON
|
||||
<<<<<<< HEAD
|
||||
-DCMAKE_INSTALL_PREFIX=install
|
||||
-DRakNet_LIBRARY_RELEASE=~/CrabNet/lib/libRakNetLibStatic.a
|
||||
-DRakNet_LIBRARY_DEBUG=~/CrabNet/lib/libRakNetLibStatic.a
|
||||
=======
|
||||
-DOPENMW_USE_SYSTEM_RECASTNAVIGATION=ON
|
||||
-DOPENMW_CXX_FLAGS="-Werror -Werror=implicit-fallthrough" # flags specific to OpenMW project
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
)
|
||||
|
||||
if [[ "${CMAKE_EXE_LINKER_FLAGS}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS}"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ $CI_OPENMW_USE_STATIC_DEPS ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DOPENMW_USE_SYSTEM_MYGUI=OFF
|
||||
-DOPENMW_USE_SYSTEM_OSG=OFF
|
||||
-DOPENMW_USE_SYSTEM_BULLET=OFF
|
||||
-DOPENMW_USE_SYSTEM_SQLITE3=OFF
|
||||
-DOPENMW_USE_SYSTEM_RECASTNAVIGATION=OFF
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ $CI_CLANG_TIDY ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DCMAKE_CXX_CLANG_TIDY="clang-tidy;--warnings-as-errors=*"
|
||||
-DBUILD_UNITTESTS=ON
|
||||
-DBUILD_OPENCS_TESTS=ON
|
||||
-DBUILD_BENCHMARKS=ON
|
||||
)
|
||||
fi
|
||||
|
||||
|
||||
if [[ "${CMAKE_BUILD_TYPE}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
else
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "${CMAKE_CXX_FLAGS_DEBUG}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DCMAKE_CXX_FLAGS_DEBUG="${CMAKE_CXX_FLAGS_DEBUG}"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "${BUILD_WITH_CODE_COVERAGE}" ]]; then
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DBUILD_WITH_CODE_COVERAGE="${BUILD_WITH_CODE_COVERAGE}"
|
||||
)
|
||||
fi
|
||||
|
||||
|
@ -47,6 +93,16 @@ fi
|
|||
export RAKNET_ROOT=~/CrabNet
|
||||
|
||||
if [[ "${BUILD_TESTS_ONLY}" ]]; then
|
||||
|
||||
# flags specific to our test suite
|
||||
CXX_FLAGS="-Wno-error=deprecated-declarations -Wno-error=nonnull -Wno-error=deprecated-copy"
|
||||
if [[ "${CXX}" == 'clang++' ]]; then
|
||||
CXX_FLAGS="${CXX_FLAGS} -Wno-error=unused-lambda-capture -Wno-error=gnu-zero-variadic-macro-arguments"
|
||||
fi
|
||||
CMAKE_CONF_OPTS+=(
|
||||
-DCMAKE_CXX_FLAGS="${CXX_FLAGS}"
|
||||
)
|
||||
|
||||
${ANALYZE} cmake \
|
||||
"${CMAKE_CONF_OPTS[@]}" \
|
||||
-DBUILD_OPENMW=OFF \
|
||||
|
@ -59,10 +115,27 @@ if [[ "${BUILD_TESTS_ONLY}" ]]; then
|
|||
-DBUILD_ESSIMPORTER=OFF \
|
||||
-DBUILD_OPENCS=OFF \
|
||||
-DBUILD_WIZARD=OFF \
|
||||
-DBUILD_NAVMESHTOOL=OFF \
|
||||
-DBUILD_BULLETOBJECTTOOL=OFF \
|
||||
-DBUILD_NIFTEST=OFF \
|
||||
-DBUILD_UNITTESTS=${BUILD_UNITTESTS} \
|
||||
-DBUILD_OPENCS_TESTS=${BUILD_UNITTESTS} \
|
||||
-DBUILD_BENCHMARKS=${BUILD_BENCHMARKS} \
|
||||
-DGTEST_ROOT="${GOOGLETEST_DIR}" \
|
||||
-DGMOCK_ROOT="${GOOGLETEST_DIR}" \
|
||||
..
|
||||
elif [[ "${BUILD_OPENMW_ONLY}" ]]; then
|
||||
${ANALYZE} cmake \
|
||||
"${CMAKE_CONF_OPTS[@]}" \
|
||||
-DBUILD_OPENMW=ON \
|
||||
-DBUILD_BSATOOL=OFF \
|
||||
-DBUILD_ESMTOOL=OFF \
|
||||
-DBUILD_LAUNCHER=OFF \
|
||||
-DBUILD_MWINIIMPORTER=OFF \
|
||||
-DBUILD_ESSIMPORTER=OFF \
|
||||
-DBUILD_OPENCS=OFF \
|
||||
-DBUILD_WIZARD=OFF \
|
||||
-DBUILD_NAVMESHTOOL=OFF \
|
||||
-DBUILD_BULLETOBJECTTOOL=OFF \
|
||||
-DBUILD_NIFTEST=OFF \
|
||||
..
|
||||
else
|
||||
${ANALYZE} cmake \
|
||||
|
|
|
@ -62,6 +62,7 @@ VERBOSE=""
|
|||
STRIP=""
|
||||
SKIP_DOWNLOAD=""
|
||||
SKIP_EXTRACT=""
|
||||
USE_CCACHE=""
|
||||
KEEP=""
|
||||
UNITY_BUILD=""
|
||||
VS_VERSION=""
|
||||
|
@ -74,6 +75,9 @@ TEST_FRAMEWORK=""
|
|||
GOOGLE_INSTALL_ROOT=""
|
||||
INSTALL_PREFIX="."
|
||||
BUILD_BENCHMARKS=""
|
||||
OSG_MULTIVIEW_BUILD=""
|
||||
USE_WERROR=""
|
||||
USE_CLANG_TIDY=""
|
||||
|
||||
ACTIVATE_MSVC=""
|
||||
SINGLE_CONFIG=""
|
||||
|
@ -100,6 +104,9 @@ while [ $# -gt 0 ]; do
|
|||
e )
|
||||
SKIP_EXTRACT=true ;;
|
||||
|
||||
C )
|
||||
USE_CCACHE=true ;;
|
||||
|
||||
k )
|
||||
KEEP=true ;;
|
||||
|
||||
|
@ -112,7 +119,7 @@ while [ $# -gt 0 ]; do
|
|||
|
||||
n )
|
||||
NMAKE=true ;;
|
||||
|
||||
|
||||
N )
|
||||
NINJA=true ;;
|
||||
|
||||
|
@ -137,6 +144,15 @@ while [ $# -gt 0 ]; do
|
|||
b )
|
||||
BUILD_BENCHMARKS=true ;;
|
||||
|
||||
M )
|
||||
OSG_MULTIVIEW_BUILD=true ;;
|
||||
|
||||
E )
|
||||
USE_WERROR=true ;;
|
||||
|
||||
T )
|
||||
USE_CLANG_TIDY=true ;;
|
||||
|
||||
h )
|
||||
cat <<EOF
|
||||
Usage: $0 [-cdehkpuvVi]
|
||||
|
@ -145,6 +161,8 @@ Options:
|
|||
Set the configuration, can also be set with environment variable CONFIGURATION.
|
||||
For mutli-config generators, this is ignored, and all configurations are set up.
|
||||
For single-config generators, several configurations can be set up at once by specifying -c multiple times.
|
||||
-C
|
||||
Use ccache.
|
||||
-d
|
||||
Skip checking the downloads.
|
||||
-e
|
||||
|
@ -159,7 +177,7 @@ Options:
|
|||
Build unit tests / Google test
|
||||
-u
|
||||
Configure for unity builds.
|
||||
-v <2017/2019>
|
||||
-v <2019/2022>
|
||||
Choose the Visual Studio version to use.
|
||||
-n
|
||||
Produce NMake makefiles instead of a Visual Studio solution. Cannot be used with -N.
|
||||
|
@ -173,6 +191,12 @@ Options:
|
|||
CMake install prefix
|
||||
-b
|
||||
Build benchmarks
|
||||
-M
|
||||
Use a multiview build of OSG
|
||||
-E
|
||||
Use warnings as errors (/WX)
|
||||
-T
|
||||
Run clang-tidy
|
||||
EOF
|
||||
wrappedExit 0
|
||||
;;
|
||||
|
@ -258,10 +282,10 @@ download() {
|
|||
|
||||
if [ -z $VERBOSE ]; then
|
||||
RET=0
|
||||
curl --silent --retry 10 -Ly 5 -o $FILE $URL || RET=$?
|
||||
curl --silent --fail --retry 10 -Ly 5 -o $FILE $URL || RET=$?
|
||||
else
|
||||
RET=0
|
||||
curl --retry 10 -Ly 5 -o $FILE $URL || RET=$?
|
||||
curl --fail --retry 10 -Ly 5 -o $FILE $URL || RET=$?
|
||||
fi
|
||||
|
||||
if [ $RET -ne 0 ]; then
|
||||
|
@ -338,34 +362,49 @@ if [ -z $PLATFORM ]; then
|
|||
fi
|
||||
|
||||
if [ -z $VS_VERSION ]; then
|
||||
VS_VERSION="2017"
|
||||
VS_VERSION="2019"
|
||||
fi
|
||||
|
||||
case $VS_VERSION in
|
||||
17|17.0|2022 )
|
||||
GENERATOR="Visual Studio 17 2022"
|
||||
TOOLSET="vc143"
|
||||
MSVC_REAL_VER="17"
|
||||
MSVC_VER="14.3"
|
||||
MSVC_DISPLAY_YEAR="2022"
|
||||
|
||||
OSG_MSVC_YEAR="2019"
|
||||
MYGUI_MSVC_YEAR="2019"
|
||||
LUA_MSVC_YEAR="2019"
|
||||
QT_MSVC_YEAR="2019"
|
||||
BULLET_MSVC_YEAR="2019"
|
||||
|
||||
BOOST_VER="1.80.0"
|
||||
BOOST_VER_URL="1_80_0"
|
||||
BOOST_VER_SDK="108000"
|
||||
;;
|
||||
|
||||
16|16.0|2019 )
|
||||
GENERATOR="Visual Studio 16 2019"
|
||||
TOOLSET="vc142"
|
||||
MSVC_REAL_VER="16"
|
||||
MSVC_VER="14.2"
|
||||
MSVC_YEAR="2015"
|
||||
MSVC_REAL_YEAR="2019"
|
||||
MSVC_DISPLAY_YEAR="2019"
|
||||
BOOST_VER="1.71.0"
|
||||
BOOST_VER_URL="1_71_0"
|
||||
BOOST_VER_SDK="107100"
|
||||
|
||||
OSG_MSVC_YEAR="2019"
|
||||
MYGUI_MSVC_YEAR="2019"
|
||||
LUA_MSVC_YEAR="2019"
|
||||
QT_MSVC_YEAR="2019"
|
||||
BULLET_MSVC_YEAR="2019"
|
||||
|
||||
BOOST_VER="1.80.0"
|
||||
BOOST_VER_URL="1_80_0"
|
||||
BOOST_VER_SDK="108000"
|
||||
;;
|
||||
|
||||
15|15.0|2017 )
|
||||
GENERATOR="Visual Studio 15 2017"
|
||||
TOOLSET="vc141"
|
||||
MSVC_REAL_VER="15"
|
||||
MSVC_VER="14.1"
|
||||
MSVC_YEAR="2015"
|
||||
MSVC_REAL_YEAR="2017"
|
||||
MSVC_DISPLAY_YEAR="2017"
|
||||
BOOST_VER="1.67.0"
|
||||
BOOST_VER_URL="1_67_0"
|
||||
BOOST_VER_SDK="106700"
|
||||
echo "Visual Studio 2017 is no longer supported"
|
||||
wrappedExit 1
|
||||
;;
|
||||
|
||||
14|14.0|2015 )
|
||||
|
@ -398,10 +437,6 @@ case $PLATFORM in
|
|||
;;
|
||||
esac
|
||||
|
||||
if [ $BITS -eq 64 ] && [ $MSVC_REAL_VER -lt 16 ]; then
|
||||
GENERATOR="${GENERATOR} Win64"
|
||||
fi
|
||||
|
||||
if [ -n "$NMAKE" ]; then
|
||||
GENERATOR="NMake Makefiles"
|
||||
SINGLE_CONFIG=true
|
||||
|
@ -485,7 +520,7 @@ for i in ${!CONFIGURATIONS[@]}; do
|
|||
esac
|
||||
done
|
||||
|
||||
if [ $MSVC_REAL_VER -ge 16 ] && [ -z "$NMAKE" ] && [ -z "$NINJA" ]; then
|
||||
if [ -z "$NMAKE" ] && [ -z "$NINJA" ]; then
|
||||
if [ $BITS -eq 64 ]; then
|
||||
add_cmake_opts "-G\"$GENERATOR\" -A x64"
|
||||
else
|
||||
|
@ -503,6 +538,39 @@ if ! [ -z $UNITY_BUILD ]; then
|
|||
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
|
||||
fi
|
||||
|
||||
if ! [ -z $USE_CCACHE ]; then
|
||||
add_cmake_opts "-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
|
||||
fi
|
||||
|
||||
# turn on LTO by default
|
||||
add_cmake_opts "-DOPENMW_LTO_BUILD=True"
|
||||
|
||||
if ! [ -z "$USE_WERROR" ]; then
|
||||
add_cmake_opts "-DOPENMW_MSVC_WERROR=ON"
|
||||
fi
|
||||
|
||||
if ! [ -z "$USE_CLANG_TIDY" ]; then
|
||||
add_cmake_opts "-DCMAKE_CXX_CLANG_TIDY=\"clang-tidy --warnings-as-errors=*\""
|
||||
fi
|
||||
|
||||
BULLET_VER="2.89"
|
||||
FFMPEG_VER="4.2.2"
|
||||
ICU_VER="70_1"
|
||||
LUAJIT_VER="v2.1.0-beta3-452-g7a0cf5fd"
|
||||
LZ4_VER="1.9.2"
|
||||
OPENAL_VER="1.23.0"
|
||||
QT_VER="5.15.2"
|
||||
|
||||
OSG_ARCHIVE_NAME="OSGoS 3.6.5"
|
||||
OSG_ARCHIVE="OSGoS-3.6.5-123-g68c5c573d-msvc${OSG_MSVC_YEAR}-win${BITS}"
|
||||
OSG_ARCHIVE_REPO_URL="https://gitlab.com/OpenMW/openmw-deps/-/raw/main"
|
||||
if ! [ -z $OSG_MULTIVIEW_BUILD ]; then
|
||||
OSG_ARCHIVE_NAME="OSG-3.6-multiview"
|
||||
OSG_ARCHIVE="OSG-3.6-multiview-d2ee5aa8-msvc${OSG_MSVC_YEAR}-win${BITS}"
|
||||
OSG_ARCHIVE_REPO_URL="https://gitlab.com/madsbuvi/openmw-deps/-/raw/openmw-vr-ovr_multiview"
|
||||
fi
|
||||
|
||||
|
||||
echo
|
||||
echo "==================================="
|
||||
echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}"
|
||||
|
@ -527,63 +595,67 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
|||
fi
|
||||
|
||||
# Bullet
|
||||
download "Bullet 2.89" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double.7z" \
|
||||
"Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double.7z"
|
||||
download "Bullet ${BULLET_VER}" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/Bullet-${BULLET_VER}-msvc${BULLET_MSVC_YEAR}-win${BITS}-double-mt.7z" \
|
||||
"Bullet-${BULLET_VER}-msvc${BULLET_MSVC_YEAR}-win${BITS}-double-mt.7z"
|
||||
|
||||
# FFmpeg
|
||||
download "FFmpeg 4.2.2" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/ffmpeg-4.2.2-win${BITS}.zip" \
|
||||
"ffmpeg-4.2.2-win${BITS}.zip" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/ffmpeg-4.2.2-dev-win${BITS}.zip" \
|
||||
"ffmpeg-4.2.2-dev-win${BITS}.zip"
|
||||
download "FFmpeg ${FFMPEG_VER}" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/ffmpeg-${FFMPEG_VER}-win${BITS}.zip" \
|
||||
"ffmpeg-${FFMPEG_VER}-win${BITS}.zip" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/ffmpeg-${FFMPEG_VER}-dev-win${BITS}.zip" \
|
||||
"ffmpeg-${FFMPEG_VER}-dev-win${BITS}.zip"
|
||||
|
||||
# MyGUI
|
||||
download "MyGUI 3.4.0" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \
|
||||
"MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z"
|
||||
download "MyGUI 3.4.1" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}.7z" \
|
||||
"MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}.7z"
|
||||
|
||||
if [ -n "$PDBS" ]; then
|
||||
download "MyGUI symbols" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \
|
||||
"MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z"
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}-sym.7z" \
|
||||
"MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}-sym.7z"
|
||||
fi
|
||||
|
||||
# OpenAL
|
||||
download "OpenAL-Soft 1.20.1" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OpenAL-Soft-1.20.1.zip" \
|
||||
"OpenAL-Soft-1.20.1.zip"
|
||||
download "OpenAL-Soft ${OPENAL_VER}" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OpenAL-Soft-${OPENAL_VER}.zip" \
|
||||
"OpenAL-Soft-${OPENAL_VER}.zip"
|
||||
|
||||
# OSG
|
||||
download "OpenSceneGraph 3.6.5" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \
|
||||
"OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z"
|
||||
# OSGoS
|
||||
download "${OSG_ARCHIVE_NAME}" \
|
||||
"${OSG_ARCHIVE_REPO_URL}/windows/${OSG_ARCHIVE}.7z" \
|
||||
"${OSG_ARCHIVE}.7z"
|
||||
|
||||
if [ -n "$PDBS" ]; then
|
||||
download "OpenSceneGraph symbols" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \
|
||||
"OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z"
|
||||
download "${OSG_ARCHIVE_NAME} symbols" \
|
||||
"${OSG_ARCHIVE_REPO_URL}/windows/${OSG_ARCHIVE}-sym.7z" \
|
||||
"${OSG_ARCHIVE}-sym.7z"
|
||||
fi
|
||||
|
||||
# SDL2
|
||||
download "SDL 2.0.12" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/SDL2-2.0.12.zip" \
|
||||
"SDL2-2.0.12.zip"
|
||||
download "SDL 2.24.0" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/SDL2-devel-2.24.0-VC.zip" \
|
||||
"SDL2-devel-2.24.0-VC.zip"
|
||||
|
||||
# LZ4
|
||||
download "LZ4 1.9.2" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/lz4_win${BITS}_v1_9_2.7z" \
|
||||
"lz4_win${BITS}_v1_9_2.7z"
|
||||
download "LZ4 ${LZ4_VER}" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/lz4_win${BITS}_v${LZ4_VER//./_}.7z" \
|
||||
"lz4_win${BITS}_v${LZ4_VER//./_}.7z"
|
||||
|
||||
# Google test and mock
|
||||
if [ ! -z $TEST_FRAMEWORK ]; then
|
||||
echo "Google test 1.10.0..."
|
||||
if [ -d googletest ]; then
|
||||
printf " Google test exists, skipping."
|
||||
else
|
||||
git clone -b release-1.10.0 https://github.com/google/googletest.git
|
||||
fi
|
||||
fi
|
||||
# LuaJIT
|
||||
download "LuaJIT ${LUAJIT_VER}" \
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/LuaJIT-${LUAJIT_VER}-msvc${LUA_MSVC_YEAR}-win${BITS}.7z" \
|
||||
"LuaJIT-${LUAJIT_VER}-msvc${LUA_MSVC_YEAR}-win${BITS}.7z"
|
||||
|
||||
# ICU
|
||||
download "ICU ${ICU_VER/_/.}"\
|
||||
"https://github.com/unicode-org/icu/releases/download/release-${ICU_VER/_/-}/icu4c-${ICU_VER}-Win${BITS}-MSVC2019.zip" \
|
||||
"icu4c-${ICU_VER}-Win${BITS}-MSVC2019.zip"
|
||||
|
||||
download "zlib 1.2.11"\
|
||||
"https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/zlib-1.2.11-msvc2017-win64.7z" \
|
||||
"zlib-1.2.11-msvc2017-win64.7z"
|
||||
fi
|
||||
|
||||
cd .. #/..
|
||||
|
@ -620,7 +692,6 @@ echo "---------------------------------------------------"
|
|||
echo
|
||||
|
||||
|
||||
# Boost
|
||||
if [ -z $APPVEYOR ]; then
|
||||
printf "Boost ${BOOST_VER}... "
|
||||
else
|
||||
|
@ -668,35 +739,33 @@ fi
|
|||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# Bullet
|
||||
printf "Bullet 2.89... "
|
||||
printf "Bullet ${BULLET_VER}... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
if [ -d Bullet ]; then
|
||||
printf -- "Exists. (No version checking) "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf Bullet
|
||||
eval 7z x -y "${DEPS}/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double.7z" $STRIP
|
||||
mv "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double" Bullet
|
||||
eval 7z x -y "${DEPS}/Bullet-${BULLET_VER}-msvc${BULLET_MSVC_YEAR}-win${BITS}-double-mt.7z" $STRIP
|
||||
mv "Bullet-${BULLET_VER}-msvc${BULLET_MSVC_YEAR}-win${BITS}-double-mt" Bullet
|
||||
fi
|
||||
add_cmake_opts -DBULLET_ROOT="$(real_pwd)/Bullet"
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# FFmpeg
|
||||
printf "FFmpeg 4.2.2... "
|
||||
printf "FFmpeg ${FFMPEG_VER}... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
if [ -d FFmpeg ] && grep "4.2.2" FFmpeg/README.txt > /dev/null; then
|
||||
if [ -d FFmpeg ] && grep "${FFMPEG_VER}" FFmpeg/README.txt > /dev/null; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf FFmpeg
|
||||
eval 7z x -y "${DEPS}/ffmpeg-4.2.2-win${BITS}.zip" $STRIP
|
||||
eval 7z x -y "${DEPS}/ffmpeg-4.2.2-dev-win${BITS}.zip" $STRIP
|
||||
mv "ffmpeg-4.2.2-win${BITS}-shared" FFmpeg
|
||||
cp -r "ffmpeg-4.2.2-win${BITS}-dev/"* FFmpeg/
|
||||
rm -rf "ffmpeg-4.2.2-win${BITS}-dev"
|
||||
eval 7z x -y "${DEPS}/ffmpeg-${FFMPEG_VER}-win${BITS}.zip" $STRIP
|
||||
eval 7z x -y "${DEPS}/ffmpeg-${FFMPEG_VER}-dev-win${BITS}.zip" $STRIP
|
||||
mv "ffmpeg-${FFMPEG_VER}-win${BITS}-shared" FFmpeg
|
||||
cp -r "ffmpeg-${FFMPEG_VER}-win${BITS}-dev/"* FFmpeg/
|
||||
rm -rf "ffmpeg-${FFMPEG_VER}-win${BITS}-dev"
|
||||
fi
|
||||
export FFMPEG_HOME="$(real_pwd)/FFmpeg"
|
||||
for config in ${CONFIGURATIONS[@]}; do
|
||||
|
@ -709,21 +778,20 @@ printf "FFmpeg 4.2.2... "
|
|||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# MyGUI
|
||||
printf "MyGUI 3.4.0... "
|
||||
printf "MyGUI 3.4.1... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
if [ -d MyGUI ] && \
|
||||
grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
||||
grep "MYGUI_VERSION_MINOR 4" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
||||
grep "MYGUI_VERSION_PATCH 0" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null
|
||||
grep "MYGUI_VERSION_PATCH 1" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null
|
||||
then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf MyGUI
|
||||
eval 7z x -y "${DEPS}/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" $STRIP
|
||||
[ -n "$PDBS" ] && eval 7z x -y "${DEPS}/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" $STRIP
|
||||
mv "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}" MyGUI
|
||||
eval 7z x -y "${DEPS}/MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}.7z" $STRIP
|
||||
[ -n "$PDBS" ] && eval 7z x -y "${DEPS}/MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}-sym.7z" $STRIP
|
||||
mv "MyGUI-3.4.1-msvc${MYGUI_MSVC_YEAR}-win${BITS}" MyGUI
|
||||
fi
|
||||
export MYGUI_HOME="$(real_pwd)/MyGUI"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
|
@ -740,27 +808,25 @@ printf "MyGUI 3.4.0... "
|
|||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# OpenAL
|
||||
printf "OpenAL-Soft 1.20.1... "
|
||||
printf "OpenAL-Soft ${OPENAL_VER}... "
|
||||
{
|
||||
if [ -d openal-soft-1.20.1-bin ]; then
|
||||
if [ -d openal-soft-${OPENAL_VER}-bin ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf openal-soft-1.20.1-bin
|
||||
eval 7z x -y OpenAL-Soft-1.20.1.zip $STRIP
|
||||
rm -rf openal-soft-${OPENAL_VER}-bin
|
||||
eval 7z x -y OpenAL-Soft-${OPENAL_VER}.zip $STRIP
|
||||
fi
|
||||
OPENAL_SDK="$(real_pwd)/openal-soft-1.20.1-bin"
|
||||
OPENAL_SDK="$(real_pwd)/openal-soft-${OPENAL_VER}-bin"
|
||||
add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \
|
||||
-DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib"
|
||||
for config in ${CONFIGURATIONS[@]}; do
|
||||
add_runtime_dlls $config "$(pwd)/openal-soft-1.20.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
|
||||
add_runtime_dlls $config "$(pwd)/openal-soft-${OPENAL_VER}-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# OSG
|
||||
printf "OSG 3.6.5... "
|
||||
printf "${OSG_ARCHIVE_NAME}... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
if [ -d OSG ] && \
|
||||
|
@ -768,157 +834,147 @@ printf "OSG 3.6.5... "
|
|||
grep "OPENSCENEGRAPH_MINOR_VERSION 6" OSG/include/osg/Version > /dev/null && \
|
||||
grep "OPENSCENEGRAPH_PATCH_VERSION 5" OSG/include/osg/Version > /dev/null
|
||||
then
|
||||
printf "Exists. "
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf OSG
|
||||
eval 7z x -y "${DEPS}/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" $STRIP
|
||||
[ -n "$PDBS" ] && eval 7z x -y "${DEPS}/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" $STRIP
|
||||
mv "OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}" OSG
|
||||
eval 7z x -y "${DEPS}/${OSG_ARCHIVE}.7z" $STRIP
|
||||
[ -n "$PDBS" ] && eval 7z x -y "${DEPS}/${OSG_ARCHIVE}-sym.7z" $STRIP
|
||||
mv "${OSG_ARCHIVE}" OSG
|
||||
fi
|
||||
OSG_SDK="$(real_pwd)/OSG"
|
||||
add_cmake_opts -DOSG_DIR="$OSG_SDK"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
SUFFIX="d"
|
||||
SUFFIX_UPCASE="D"
|
||||
else
|
||||
SUFFIX=""
|
||||
SUFFIX_UPCASE=""
|
||||
fi
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng}${SUFFIX}.dll \
|
||||
"$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll
|
||||
add_osg_dlls $CONFIGURATION "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll
|
||||
|
||||
if ! [ -z $OSG_MULTIVIEW_BUILD ]; then
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/"{ot21-OpenThreads,libpng16}${SUFFIX}.dll \
|
||||
"$(pwd)/OSG/bin/osg162-osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow,Sim}${SUFFIX}.dll
|
||||
else
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/"{OpenThreads,icuuc58,libpng16}${SUFFIX}.dll \
|
||||
"$(pwd)/OSG/bin/libxml2"${SUFFIX_UPCASE}.dll \
|
||||
"$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow,Sim}${SUFFIX}.dll
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/icudt58.dll"
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/"{boost_system-vc141-mt-gd-1_63,collada-dom2.4-dp-vc141-mt-d}.dll
|
||||
else
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/"{boost_system-vc141-mt-1_63,collada-dom2.4-dp-vc141-mt}.dll
|
||||
fi
|
||||
fi
|
||||
add_osg_dlls $CONFIGURATION "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_"{bmp,dae,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll
|
||||
add_osg_dlls $CONFIGURATION "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# Qt
|
||||
if [ -z $APPVEYOR ]; then
|
||||
printf "Qt 5.15.0... "
|
||||
else
|
||||
printf "Qt 5.13 AppVeyor... "
|
||||
fi
|
||||
printf "Qt ${QT_VER}... "
|
||||
{
|
||||
if [ $BITS -eq 64 ]; then
|
||||
SUFFIX="_64"
|
||||
else
|
||||
SUFFIX=""
|
||||
fi
|
||||
if [ -z $APPVEYOR ]; then
|
||||
cd $DEPS_INSTALL
|
||||
|
||||
qt_version="5.15.0"
|
||||
if [ "win${BITS}_msvc${MSVC_REAL_YEAR}${SUFFIX}" == "win64_msvc2017_64" ]; then
|
||||
echo "This combination of options is known not to work. Falling back to Qt 5.14.2."
|
||||
qt_version="5.14.2"
|
||||
fi
|
||||
cd $DEPS_INSTALL
|
||||
|
||||
QT_SDK="$(real_pwd)/Qt/${qt_version}/msvc${MSVC_REAL_YEAR}${SUFFIX}"
|
||||
|
||||
if [ -d "Qt/${qt_version}" ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
if [ $MISSINGPYTHON -ne 0 ]; then
|
||||
echo "Can't be automatically installed without Python."
|
||||
wrappedExit 1
|
||||
fi
|
||||
QT_SDK="$(real_pwd)/Qt/${QT_VER}/msvc${QT_MSVC_YEAR}${SUFFIX}"
|
||||
|
||||
pushd "$DEPS" > /dev/null
|
||||
if ! [ -d 'aqt-venv' ]; then
|
||||
echo " Creating Virtualenv for aqt..."
|
||||
run_cmd python -m venv aqt-venv
|
||||
fi
|
||||
if [ -d 'aqt-venv/bin' ]; then
|
||||
VENV_BIN_DIR='bin'
|
||||
elif [ -d 'aqt-venv/Scripts' ]; then
|
||||
VENV_BIN_DIR='Scripts'
|
||||
else
|
||||
echo "Error: Failed to create virtualenv in expected location."
|
||||
wrappedExit 1
|
||||
fi
|
||||
|
||||
# check version
|
||||
aqt-venv/${VENV_BIN_DIR}/pip list | grep 'aqtinstall\s*1.1.3' || [ $? -ne 0 ]
|
||||
if [ $? -eq 0 ]; then
|
||||
echo " Installing aqt wheel into virtualenv..."
|
||||
run_cmd "aqt-venv/${VENV_BIN_DIR}/pip" install aqtinstall==1.1.3
|
||||
fi
|
||||
popd > /dev/null
|
||||
|
||||
rm -rf Qt
|
||||
|
||||
mkdir Qt
|
||||
cd Qt
|
||||
|
||||
run_cmd "${DEPS}/aqt-venv/${VENV_BIN_DIR}/aqt" install $qt_version windows desktop "win${BITS}_msvc${MSVC_REAL_YEAR}${SUFFIX}"
|
||||
|
||||
printf " Cleaning up extraneous data... "
|
||||
rm -rf Qt/{aqtinstall.log,Tools}
|
||||
|
||||
echo Done.
|
||||
fi
|
||||
|
||||
cd $QT_SDK
|
||||
add_cmake_opts -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
||||
-DCMAKE_PREFIX_PATH="$QT_SDK"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
DLLSUFFIX="d"
|
||||
else
|
||||
DLLSUFFIX=""
|
||||
fi
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll
|
||||
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
||||
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
||||
done
|
||||
echo Done.
|
||||
else
|
||||
QT_SDK="C:/Qt/5.13/msvc2017${SUFFIX}"
|
||||
add_cmake_opts -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
||||
-DCMAKE_PREFIX_PATH="$QT_SDK"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
DLLSUFFIX="d"
|
||||
else
|
||||
DLLSUFFIX=""
|
||||
fi
|
||||
DIR=$(windowsPathAsUnix "${QT_SDK}")
|
||||
add_runtime_dlls $CONFIGURATION "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll
|
||||
add_qt_platform_dlls $CONFIGURATION "${DIR}/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
||||
add_qt_style_dlls $CONFIGURATION "${DIR}/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
||||
done
|
||||
echo Done.
|
||||
fi
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# SDL2
|
||||
printf "SDL 2.0.12... "
|
||||
{
|
||||
if [ -d SDL2-2.0.12 ]; then
|
||||
if [ -d "Qt/${QT_VER}" ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf SDL2-2.0.12
|
||||
eval 7z x -y SDL2-2.0.12.zip $STRIP
|
||||
if [ $MISSINGPYTHON -ne 0 ]; then
|
||||
echo "Can't be automatically installed without Python."
|
||||
wrappedExit 1
|
||||
fi
|
||||
|
||||
pushd "$DEPS" > /dev/null
|
||||
if ! [ -d 'aqt-venv' ]; then
|
||||
echo " Creating Virtualenv for aqt..."
|
||||
run_cmd python -m venv aqt-venv
|
||||
fi
|
||||
if [ -d 'aqt-venv/bin' ]; then
|
||||
VENV_BIN_DIR='bin'
|
||||
elif [ -d 'aqt-venv/Scripts' ]; then
|
||||
VENV_BIN_DIR='Scripts'
|
||||
else
|
||||
echo "Error: Failed to create virtualenv in expected location."
|
||||
wrappedExit 1
|
||||
fi
|
||||
|
||||
# check version
|
||||
aqt-venv/${VENV_BIN_DIR}/pip list | grep 'aqtinstall\s*1.1.3' || [ $? -ne 0 ]
|
||||
if [ $? -eq 0 ]; then
|
||||
echo " Installing aqt wheel into virtualenv..."
|
||||
run_cmd "aqt-venv/${VENV_BIN_DIR}/pip" install aqtinstall==1.1.3
|
||||
fi
|
||||
popd > /dev/null
|
||||
|
||||
rm -rf Qt
|
||||
|
||||
mkdir Qt
|
||||
cd Qt
|
||||
|
||||
run_cmd "${DEPS}/aqt-venv/${VENV_BIN_DIR}/aqt" install ${QT_VER} windows desktop "win${BITS}_msvc${QT_MSVC_YEAR}${SUFFIX}"
|
||||
|
||||
printf " Cleaning up extraneous data... "
|
||||
rm -rf Qt/{aqtinstall.log,Tools}
|
||||
|
||||
echo Done.
|
||||
fi
|
||||
export SDL2DIR="$(real_pwd)/SDL2-2.0.12"
|
||||
for config in ${CONFIGURATIONS[@]}; do
|
||||
add_runtime_dlls $config "$(pwd)/SDL2-2.0.12/lib/x${ARCHSUFFIX}/SDL2.dll"
|
||||
|
||||
cd $QT_SDK
|
||||
add_cmake_opts -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
||||
-DCMAKE_PREFIX_PATH="$QT_SDK"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
DLLSUFFIX="d"
|
||||
else
|
||||
DLLSUFFIX=""
|
||||
fi
|
||||
if [ "${QT_VER:0:1}" -eq "6" ]; then
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,OpenGLWidgets,Widgets}${DLLSUFFIX}.dll
|
||||
else
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll
|
||||
fi
|
||||
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
||||
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# LZ4
|
||||
printf "LZ4 1.9.2... "
|
||||
printf "SDL 2.24.0... "
|
||||
{
|
||||
if [ -d LZ4_1.9.2 ]; then
|
||||
if [ -d SDL2-2.24.0 ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf LZ4_1.9.2
|
||||
eval 7z x -y lz4_win${BITS}_v1_9_2.7z -o$(real_pwd)/LZ4_1.9.2 $STRIP
|
||||
rm -rf SDL2-2.24.0
|
||||
eval 7z x -y SDL2-devel-2.24.0-VC.zip $STRIP
|
||||
fi
|
||||
export LZ4DIR="$(real_pwd)/LZ4_1.9.2"
|
||||
export SDL2DIR="$(real_pwd)/SDL2-2.24.0"
|
||||
for config in ${CONFIGURATIONS[@]}; do
|
||||
add_runtime_dlls $config "$(pwd)/SDL2-2.24.0/lib/x${ARCHSUFFIX}/SDL2.dll"
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
printf "LZ4 ${LZ4_VER}... "
|
||||
{
|
||||
if [ -d LZ4_${LZ4_VER} ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf LZ4_${LZ4_VER}
|
||||
eval 7z x -y lz4_win${BITS}_v${LZ4_VER//./_}.7z -o$(real_pwd)/LZ4_${LZ4_VER} $STRIP
|
||||
fi
|
||||
export LZ4DIR="$(real_pwd)/LZ4_${LZ4_VER}"
|
||||
add_cmake_opts -DLZ4_INCLUDE_DIR="${LZ4DIR}/include" \
|
||||
-DLZ4_LIBRARY="${LZ4DIR}/lib/liblz4.lib"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
|
@ -928,65 +984,74 @@ printf "LZ4 1.9.2... "
|
|||
SUFFIX=""
|
||||
LZ4_CONFIGURATION="Release"
|
||||
fi
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/LZ4_1.9.2/bin/${LZ4_CONFIGURATION}/liblz4.dll"
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/LZ4_${LZ4_VER}/bin/${LZ4_CONFIGURATION}/liblz4.dll"
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
# Google Test and Google Mock
|
||||
if [ ! -z $TEST_FRAMEWORK ]; then
|
||||
printf "Google test 1.10.0 ..."
|
||||
|
||||
cd googletest
|
||||
mkdir -p build${MSVC_REAL_YEAR}
|
||||
|
||||
cd build${MSVC_REAL_YEAR}
|
||||
|
||||
GOOGLE_INSTALL_ROOT="${DEPS_INSTALL}/GoogleTest"
|
||||
|
||||
printf "LuaJIT ${LUAJIT_VER}... "
|
||||
{
|
||||
if [ -d LuaJIT ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf LuaJIT
|
||||
eval 7z x -y LuaJIT-${LUAJIT_VER}-msvc${LUA_MSVC_YEAR}-win${BITS}.7z -o$(real_pwd)/LuaJIT $STRIP
|
||||
fi
|
||||
export LUAJIT_DIR="$(real_pwd)/LuaJIT"
|
||||
add_cmake_opts -DLuaJit_INCLUDE_DIR="${LUAJIT_DIR}/include" \
|
||||
-DLuaJit_LIBRARY="${LUAJIT_DIR}/lib/lua51.lib"
|
||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||
# FindGMock.cmake mentions Release explicitly, but not RelWithDebInfo. Only one optimised library config can be used, so go for the safer one.
|
||||
GTEST_CONFIG=$([ $CONFIGURATION == "RelWithDebInfo" ] && echo "Release" || echo "$CONFIGURATION" )
|
||||
if [ $GTEST_CONFIG == "Debug" ]; then
|
||||
DEBUG_SUFFIX="d"
|
||||
else
|
||||
DEBUG_SUFFIX=""
|
||||
fi
|
||||
|
||||
if [ ! -f "$GOOGLE_INSTALL_ROOT/lib/gtest${DEBUG_SUFFIX}.lib" ]; then
|
||||
# Always use MSBuild solution files as they don't need the environment activating
|
||||
cmake .. -DCMAKE_USE_WIN32_THREADS_INIT=1 -G "Visual Studio $MSVC_REAL_VER $MSVC_REAL_YEAR$([ $BITS -eq 64 ] && [ $MSVC_REAL_VER -lt 16 ] && echo " Win64")" $([ $MSVC_REAL_VER -ge 16 ] && echo "-A $([ $BITS -eq 64 ] && echo "x64" || echo "Win32")") -DBUILD_SHARED_LIBS=1
|
||||
cmake --build . --config "${GTEST_CONFIG}"
|
||||
cmake --install . --config "${GTEST_CONFIG}" --prefix "${GOOGLE_INSTALL_ROOT}"
|
||||
fi
|
||||
|
||||
add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gtest_main${DEBUG_SUFFIX}.dll"
|
||||
add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gtest${DEBUG_SUFFIX}.dll"
|
||||
add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gmock_main${DEBUG_SUFFIX}.dll"
|
||||
add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gmock${DEBUG_SUFFIX}.dll"
|
||||
add_runtime_dlls $CONFIGURATION "$(pwd)/LuaJIT/bin/lua51.dll"
|
||||
done
|
||||
|
||||
add_cmake_opts -DBUILD_UNITTESTS=yes
|
||||
# FindGTest and FindGMock do not work perfectly on Windows
|
||||
# but we can help them by telling them everything we know about installation
|
||||
add_cmake_opts -DGMOCK_ROOT="$GOOGLE_INSTALL_ROOT"
|
||||
add_cmake_opts -DGTEST_ROOT="$GOOGLE_INSTALL_ROOT"
|
||||
add_cmake_opts -DGTEST_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gtest.lib"
|
||||
add_cmake_opts -DGTEST_MAIN_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gtest_main.lib"
|
||||
add_cmake_opts -DGMOCK_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gmock.lib"
|
||||
add_cmake_opts -DGMOCK_MAIN_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gmock_main.lib"
|
||||
add_cmake_opts -DGTEST_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gtestd.lib"
|
||||
add_cmake_opts -DGTEST_MAIN_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gtest_maind.lib"
|
||||
add_cmake_opts -DGMOCK_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gmockd.lib"
|
||||
add_cmake_opts -DGMOCK_MAIN_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gmock_maind.lib"
|
||||
add_cmake_opts -DGTEST_LINKED_AS_SHARED_LIBRARY=True
|
||||
add_cmake_opts -DGTEST_LIBRARY_TYPE=SHARED
|
||||
add_cmake_opts -DGTEST_MAIN_LIBRARY_TYPE=SHARED
|
||||
|
||||
echo Done.
|
||||
}
|
||||
|
||||
fi
|
||||
cd $DEPS
|
||||
echo
|
||||
printf "ICU ${ICU_VER/_/.}... "
|
||||
{
|
||||
if [ -d ICU-${ICU_VER} ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf ICU-${ICU_VER}
|
||||
eval 7z x -y icu4c-${ICU_VER}-Win${BITS}-MSVC2019.zip -o$(real_pwd)/ICU-${ICU_VER} $STRIP
|
||||
fi
|
||||
ICU_ROOT="$(real_pwd)/ICU-${ICU_VER}"
|
||||
add_cmake_opts -DICU_ROOT="${ICU_ROOT}" \
|
||||
-DICU_INCLUDE_DIR="${ICU_ROOT}/include" \
|
||||
-DICU_I18N_LIBRARY="${ICU_ROOT}/lib${BITS}/icuin.lib " \
|
||||
-DICU_UC_LIBRARY="${ICU_ROOT}/lib${BITS}/icuuc.lib " \
|
||||
-DICU_DEBUG=ON
|
||||
|
||||
for config in ${CONFIGURATIONS[@]}; do
|
||||
add_runtime_dlls $config "$(pwd)/ICU-${ICU_VER}/bin${BITS}/icudt${ICU_VER/_*/}.dll"
|
||||
add_runtime_dlls $config "$(pwd)/ICU-${ICU_VER}/bin${BITS}/icuin${ICU_VER/_*/}.dll"
|
||||
add_runtime_dlls $config "$(pwd)/ICU-${ICU_VER}/bin${BITS}/icuuc${ICU_VER/_*/}.dll"
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
|
||||
cd $DEPS
|
||||
echo
|
||||
printf "zlib 1.2.11... "
|
||||
{
|
||||
if [ -d zlib-1.2.11-msvc2017-win64 ]; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf zlib-1.2.11-msvc2017-win64
|
||||
eval 7z x -y zlib-1.2.11-msvc2017-win64.7z $STRIP
|
||||
fi
|
||||
add_cmake_opts -DZLIB_ROOT="$(real_pwd)/zlib-1.2.11-msvc2017-win64"
|
||||
for config in ${CONFIGURATIONS[@]}; do
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
add_runtime_dlls $config "$(pwd)/zlib-1.2.11-msvc2017-win64/bin/zlibd.dll"
|
||||
else
|
||||
add_runtime_dlls $config "$(pwd)/zlib-1.2.11-msvc2017-win64/bin/zlib.dll"
|
||||
fi
|
||||
done
|
||||
echo Done.
|
||||
}
|
||||
|
||||
echo
|
||||
cd $DEPS_INSTALL/..
|
||||
|
@ -994,6 +1059,8 @@ echo
|
|||
echo "Setting up OpenMW build..."
|
||||
add_cmake_opts -DOPENMW_MP_BUILD=on
|
||||
add_cmake_opts -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}"
|
||||
add_cmake_opts -DOPENMW_USE_SYSTEM_SQLITE3=OFF
|
||||
add_cmake_opts -DOPENMW_USE_SYSTEM_YAML_CPP=OFF
|
||||
if [ ! -z $CI ]; then
|
||||
case $STEP in
|
||||
components )
|
||||
|
@ -1077,6 +1144,11 @@ if [ "${BUILD_BENCHMARKS}" ]; then
|
|||
add_cmake_opts -DBUILD_BENCHMARKS=ON
|
||||
fi
|
||||
|
||||
if [ -n "${TEST_FRAMEWORK}" ]; then
|
||||
add_cmake_opts -DBUILD_UNITTESTS=ON
|
||||
add_cmake_opts -DBUILD_OPENCS_TESTS=ON
|
||||
fi
|
||||
|
||||
if [ -n "$ACTIVATE_MSVC" ]; then
|
||||
echo -n "- Activating MSVC in the current shell... "
|
||||
command -v vswhere >/dev/null 2>&1 || { echo "Error: vswhere is not on the path."; wrappedExit 1; }
|
||||
|
|
|
@ -3,8 +3,13 @@
|
|||
export CXX=clang++
|
||||
export CC=clang
|
||||
|
||||
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
|
||||
QT_PATH=$(brew --prefix qt@5)
|
||||
# Silence a git warning
|
||||
git config --global advice.detachedHead false
|
||||
|
||||
DEPENDENCIES_ROOT="/tmp/openmw-deps"
|
||||
|
||||
QT_PATH=$(brew --prefix qt@6)
|
||||
ICU_PATH=$(brew --prefix icu4c)
|
||||
CCACHE_EXECUTABLE=$(brew --prefix ccache)/bin/ccache
|
||||
mkdir build
|
||||
cd build
|
||||
|
@ -16,14 +21,18 @@ cmake \
|
|||
-D CMAKE_CXX_FLAGS="-stdlib=libc++" \
|
||||
-D CMAKE_C_FLAGS_RELEASE="-g -O0" \
|
||||
-D CMAKE_CXX_FLAGS_RELEASE="-g -O0" \
|
||||
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.14" \
|
||||
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.15" \
|
||||
-D CMAKE_BUILD_TYPE=RELEASE \
|
||||
-D OPENMW_OSX_DEPLOYMENT=TRUE \
|
||||
-D OPENMW_USE_SYSTEM_RECASTNAVIGATION=TRUE \
|
||||
-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 \
|
||||
-D ICU_ROOT="$ICU_PATH" \
|
||||
-G"Unix Makefiles" \
|
||||
..
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh -ex
|
||||
|
||||
git clone -b release-1.10.0 https://github.com/google/googletest.git
|
||||
cd googletest
|
||||
mkdir build
|
||||
cd build
|
||||
cmake \
|
||||
-D CMAKE_C_COMPILER="${CC}" \
|
||||
-D CMAKE_CXX_COMPILER="${CXX}" \
|
||||
-D CMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-D CMAKE_BUILD_TYPE="${CONFIGURATION}" \
|
||||
-D CMAKE_INSTALL_PREFIX="${GOOGLETEST_DIR}" \
|
||||
-G "${GENERATOR}" \
|
||||
..
|
||||
cmake --build . --config "${CONFIGURATION}" -- -j $(nproc)
|
||||
cmake --install . --config "${CONFIGURATION}"
|
8
CI/check_clang_format.sh
Executable file
8
CI/check_clang_format.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
set -o pipefail
|
||||
|
||||
CLANG_FORMAT="${CLANG_FORMAT:-clang-format}"
|
||||
git ls-files -- ':(exclude)extern/' '*.cpp' '*.hpp' '*.h' |
|
||||
xargs -I '{}' -P $(nproc) bash -ec "\"${CLANG_FORMAT:?}\" --dry-run -Werror \"\${0:?}\" &> /dev/null || \"${CLANG_FORMAT:?}\" \"\${0:?}\" | git diff --color=always --no-index \"\${0:?}\" -" '{}' ||
|
||||
( echo "clang-format differences detected"; exit -1 )
|
6
CI/check_cmake_format.sh
Executable file
6
CI/check_cmake_format.sh
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
git ls-files -- ':(exclude)extern/' 'CMakeLists.txt' '*.cmake' |
|
||||
xargs grep -P '^\s*\t' &&
|
||||
( echo 'CMake files contain leading tab character. Use only spaces for indentation'; exit -1 )
|
||||
exit 0
|
7
CI/check_file_names.sh
Executable file
7
CI/check_file_names.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/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 &&
|
||||
( echo 'File names do not follow the naming convention, see https://wiki.openmw.org/index.php?title=Naming_Conventions#Files'; exit -1 )
|
||||
exit 0
|
48
CI/file_name_exceptions.txt
Normal file
48
CI/file_name_exceptions.txt
Normal file
|
@ -0,0 +1,48 @@
|
|||
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/openmw_test_suite/esm/test_fixed_string.cpp
|
||||
apps/openmw_test_suite/files/conversion_tests.cpp
|
||||
apps/openmw_test_suite/lua/test_async.cpp
|
||||
apps/openmw_test_suite/lua/test_configuration.cpp
|
||||
apps/openmw_test_suite/lua/test_l10n.cpp
|
||||
apps/openmw_test_suite/lua/test_lua.cpp
|
||||
apps/openmw_test_suite/lua/test_scriptscontainer.cpp
|
||||
apps/openmw_test_suite/lua/test_serialization.cpp
|
||||
apps/openmw_test_suite/lua/test_storage.cpp
|
||||
apps/openmw_test_suite/lua/test_ui_content.cpp
|
||||
apps/openmw_test_suite/lua/test_utilpackage.cpp
|
||||
apps/openmw_test_suite/misc/test_endianness.cpp
|
||||
apps/openmw_test_suite/misc/test_resourcehelpers.cpp
|
||||
apps/openmw_test_suite/misc/test_stringops.cpp
|
||||
apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp
|
||||
apps/openmw_test_suite/mwscript/test_scripts.cpp
|
||||
apps/openmw_test_suite/mwscript/test_utils.hpp
|
||||
apps/openmw_test_suite/mwworld/test_store.cpp
|
||||
apps/openmw_test_suite/openmw_test_suite.cpp
|
||||
apps/openmw_test_suite/testing_util.hpp
|
||||
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
|
|
@ -9,26 +9,38 @@ print_help() {
|
|||
}
|
||||
|
||||
declare -rA GROUPED_DEPS=(
|
||||
[gcc]="binutils gcc g++ libc-dev"
|
||||
[clang]="binutils clang"
|
||||
[gcc]="binutils gcc build-essential cmake ccache curl unzip git pkg-config mold"
|
||||
[clang]="binutils clang make cmake ccache curl unzip git pkg-config mold"
|
||||
[coverity]="binutils clang-11 make cmake ccache curl unzip git pkg-config"
|
||||
[gcc_preprocess]="
|
||||
binutils
|
||||
build-essential
|
||||
clang
|
||||
cmake
|
||||
curl
|
||||
gcc
|
||||
git
|
||||
libclang-dev
|
||||
ninja-build
|
||||
python3-clang
|
||||
python3-pip
|
||||
unzip
|
||||
"
|
||||
|
||||
# Common dependencies for building OpenMW.
|
||||
[openmw-deps]="
|
||||
make cmake ccache git pkg-config
|
||||
|
||||
libboost-filesystem-dev libboost-program-options-dev
|
||||
libboost-program-options-dev
|
||||
libboost-system-dev libboost-iostreams-dev
|
||||
|
||||
|
||||
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev
|
||||
libsdl2-dev libqt5opengl5-dev libopenal-dev libunshield-dev libtinyxml-dev
|
||||
libbullet-dev liblz4-dev libpng-dev libjpeg-dev
|
||||
ca-certificates
|
||||
libbullet-dev liblz4-dev libpng-dev libjpeg-dev libluajit-5.1-dev
|
||||
librecast-dev libsqlite3-dev ca-certificates libicu-dev libyaml-cpp-dev
|
||||
"
|
||||
# TODO: add librecastnavigation-dev when debian is ready
|
||||
|
||||
# These dependencies can alternatively be built and linked statically.
|
||||
[openmw-deps-dynamic]="libmygui-dev libopenscenegraph-dev"
|
||||
[coverity]="curl"
|
||||
[openmw-deps-dynamic]="libmygui-dev libopenscenegraph-dev libsqlite3-dev libcollada-dom-dev"
|
||||
[clang-tidy]="clang-tidy"
|
||||
|
||||
# Pre-requisites for building MyGUI and OSG for static linking.
|
||||
#
|
||||
|
@ -40,10 +52,53 @@ declare -rA GROUPED_DEPS=(
|
|||
# * JPEG: libjpeg-dev
|
||||
# * PNG: libpng-dev
|
||||
[openmw-deps-static]="
|
||||
make cmake
|
||||
ccache curl unzip libcollada-dom-dev libfreetype6-dev libjpeg-dev libpng-dev
|
||||
libcollada-dom-dev libfreetype6-dev libjpeg-dev libpng-dev
|
||||
libsdl2-dev libboost-system-dev libboost-filesystem-dev libgl-dev
|
||||
"
|
||||
|
||||
[openmw-coverage]="gcovr"
|
||||
|
||||
[openmw-integration-tests]="
|
||||
ca-certificates
|
||||
gdb
|
||||
git
|
||||
git-lfs
|
||||
libavcodec58
|
||||
libavformat58
|
||||
libavutil56
|
||||
libboost-iostreams1.74.0
|
||||
libboost-program-options1.74.0
|
||||
libboost-system1.74.0
|
||||
libbullet3.24
|
||||
libcollada-dom2.5-dp0
|
||||
libicu70
|
||||
libjpeg8
|
||||
libluajit-5.1-2
|
||||
liblz4-1
|
||||
libmyguiengine3debian1v5
|
||||
libopenal1
|
||||
libopenscenegraph161
|
||||
libpng16-16
|
||||
libqt5opengl5
|
||||
librecast1
|
||||
libsdl2-2.0-0
|
||||
libsqlite3-0
|
||||
libswresample3
|
||||
libswscale5
|
||||
libtinyxml2.6.2v5
|
||||
libyaml-cpp0.7
|
||||
python3-pip
|
||||
xvfb
|
||||
"
|
||||
|
||||
[libasan6]="libasan6"
|
||||
|
||||
[android]="binutils build-essential cmake ccache curl unzip git pkg-config"
|
||||
|
||||
[openmw-clang-format]="
|
||||
clang-format-14
|
||||
git-core
|
||||
"
|
||||
)
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
|
@ -61,7 +116,10 @@ for group in "$@"; do
|
|||
done
|
||||
|
||||
export APT_CACHE_DIR="${PWD}/apt-cache"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
set -x
|
||||
mkdir -pv "$APT_CACHE_DIR"
|
||||
apt-get update -yq
|
||||
apt-get -q -o dir::cache::archives="$APT_CACHE_DIR" install -y --no-install-recommends "${deps[@]}"
|
||||
apt-get update -yqq
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y --no-install-recommends software-properties-common gnupg >/dev/null
|
||||
add-apt-repository -y ppa:openmw/openmw
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y --no-install-recommends "${deps[@]}" >/dev/null
|
||||
|
|
200
CI/org.openmw.OpenMW.devel.yaml
Normal file
200
CI/org.openmw.OpenMW.devel.yaml
Normal file
|
@ -0,0 +1,200 @@
|
|||
---
|
||||
app-id: org.openmw.OpenMW.devel
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: '5.15-21.08'
|
||||
sdk: org.kde.Sdk
|
||||
command: openmw-launcher
|
||||
rename-appdata-file: openmw.appdata.xml
|
||||
finish-args:
|
||||
- "--share=ipc"
|
||||
- "--socket=x11"
|
||||
- "--device=all"
|
||||
- "--filesystem=host"
|
||||
- "--socket=pulseaudio"
|
||||
build-options:
|
||||
cflags: "-O2 -g"
|
||||
cxxflags: "-O2 -g"
|
||||
cleanup:
|
||||
- "/include"
|
||||
- "/lib/pkgconfig"
|
||||
- "/lib/cmake"
|
||||
- "/share/pkgconfig"
|
||||
- "/share/aclocal"
|
||||
- "/share/doc"
|
||||
- "/man"
|
||||
- "/share/man"
|
||||
- "/share/gtk-doc"
|
||||
- "/share/vala"
|
||||
- "*.la"
|
||||
- "*.a"
|
||||
|
||||
modules:
|
||||
- name: boost
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- ./bootstrap.sh --prefix=/app --with-libraries=filesystem,iostreams,program_options,system
|
||||
- ./b2 headers
|
||||
- ./b2 install
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz
|
||||
sha256: aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a
|
||||
|
||||
- name: collada-dom
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- "-DOPT_COLLADA14=1"
|
||||
- "-DOPT_COLLADA15=0"
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/rdiankov/collada-dom/archive/c1e20b7d6ff806237030fe82f126cb86d661f063.zip
|
||||
sha256: 6c51cd068c7d6760b587391884942caaac8a515d138535041e42d00d3e5c9152
|
||||
|
||||
- name: ffmpeg
|
||||
config-opts:
|
||||
- "--disable-static"
|
||||
- "--enable-shared"
|
||||
- "--disable-programs"
|
||||
- "--disable-doc"
|
||||
- "--disable-avdevice"
|
||||
- "--disable-avfilter"
|
||||
- "--disable-postproc"
|
||||
|
||||
- "--disable-encoders"
|
||||
- "--disable-muxers"
|
||||
- "--disable-protocols"
|
||||
- "--disable-indevs"
|
||||
- "--disable-devices"
|
||||
- "--disable-filters"
|
||||
sources:
|
||||
- type: archive
|
||||
url: http://ffmpeg.org/releases/ffmpeg-4.3.2.tar.xz
|
||||
sha256: 46e4e64f1dd0233cbc0934b9f1c0da676008cad34725113fb7f802cfa84ccddb
|
||||
cleanup:
|
||||
- "/share/ffmpeg"
|
||||
|
||||
- name: openscenegraph
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- "-DBUILD_OSG_PLUGINS_BY_DEFAULT=0"
|
||||
- "-DBUILD_OSG_PLUGIN_OSG=1"
|
||||
- "-DBUILD_OSG_PLUGIN_DDS=1"
|
||||
- "-DBUILD_OSG_PLUGIN_DAE=1"
|
||||
- "-DBUILD_OSG_PLUGIN_TGA=1"
|
||||
- "-DBUILD_OSG_PLUGIN_BMP=1"
|
||||
- "-DBUILD_OSG_PLUGIN_JPEG=1"
|
||||
- "-DBUILD_OSG_PLUGIN_PNG=1"
|
||||
- "-DBUILD_OSG_DEPRECATED_SERIALIZERS=0"
|
||||
- "-DBUILD_OSG_APPLICATIONS=0"
|
||||
- "-DCMAKE_BUILD_TYPE=Release"
|
||||
build-options:
|
||||
env:
|
||||
COLLADA_DIR: /app/include/collada-dom2.5
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/openmw/osg/archive/76e061739610bc9a3420a59e7c9395e742ce2f97.zip
|
||||
sha256: fa1100362eae260192819d65d90b29ec0b88fdf80e30cee677730b7a0d68637e
|
||||
|
||||
- name: bullet
|
||||
# The cmake + ninja buildsystem doesn't install the required binaries correctly
|
||||
buildsystem: cmake
|
||||
config-opts:
|
||||
- "-DBUILD_BULLET2_DEMOS=0"
|
||||
- "-DBUILD_BULLET3=0"
|
||||
- "-DBUILD_CPU_DEMOS=0"
|
||||
- "-DBUILD_EXTRAS=0"
|
||||
- "-DBUILD_OPENGL3_DEMOS=0"
|
||||
- "-DBUILD_UNIT_TESTS=0"
|
||||
- "-DCMAKE_BUILD_TYPE=Release"
|
||||
- "-DUSE_GLUT=0"
|
||||
- "-DUSE_GRAPHICAL_BENCHMARK=0"
|
||||
- "-DUSE_DOUBLE_PRECISION=on"
|
||||
- "-DBULLET2_MULTITHREADING=on"
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/bulletphysics/bullet3/archive/93be7e644024e92df13b454a4a0b0fcd02b21b10.zip
|
||||
sha256: 82968fbf20a92c51bc71ac9ee8f6381ecf3420c7cbb881ffb7bb633fa13b27f9
|
||||
|
||||
- name: mygui
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- "-DCMAKE_BUILD_TYPE=Release"
|
||||
- "-DMYGUI_RENDERSYSTEM=1"
|
||||
- "-DMYGUI_BUILD_DEMOS=0"
|
||||
- "-DMYGUI_BUILD_TOOLS=0"
|
||||
- "-DMYGUI_BUILD_PLUGINS=0"
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/MyGUI/mygui/archive/refs/tags/MyGUI3.4.1.tar.gz
|
||||
sha256: bdf730bdeb4ad89e6b8223967db01aa5274d2b93adc2c0d6aa4842faeed4de1a
|
||||
|
||||
- name: libunshield
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- "-DCMAKE_BUILD_TYPE=Release"
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/twogood/unshield/archive/1.4.3.tar.gz
|
||||
sha256: aa8c978dc0eb1158d266eaddcd1852d6d71620ddfc82807fe4bf2e19022b7bab
|
||||
|
||||
- name: lz4
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- "make lib"
|
||||
- "PREFIX=/app make install"
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/lz4/lz4/archive/refs/tags/v1.9.3.tar.gz
|
||||
sha256: 030644df4611007ff7dc962d981f390361e6c97a34e5cbc393ddfbe019ffe2c1
|
||||
|
||||
- name: recastnavigation
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- "-DCMAKE_BUILD_TYPE=Release"
|
||||
- "-DRECASTNAVIGATION_DEMO=no"
|
||||
- "-DRECASTNAVIGATION_TESTS=no"
|
||||
- "-DRECASTNAVIGATION_EXAMPLES=no"
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/recastnavigation/recastnavigation/archive/c5cbd53024c8a9d8d097a4371215e3342d2fdc87.zip
|
||||
sha256: 53dacfd7bead4d3b0c9a04a648caed3e7c3900e0aba765c15dee26b50f6103c6
|
||||
|
||||
- name: yaml-cpp
|
||||
buildsystem: cmake-ninja
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/jbeder/yaml-cpp/archive/refs/tags/yaml-cpp-0.7.0.zip
|
||||
sha256: 4d5e664a7fb2d7445fc548cc8c0e1aa7b1a496540eb382d137e2cc263e6d3ef5
|
||||
|
||||
- name: LuaJIT
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- make install PREFIX=/app
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/LuaJIT/LuaJIT/archive/refs/tags/v2.0.5.zip
|
||||
sha256: 2adbe397a5b6b8ab22fa8396507ce852a2495db50e50734b3daa1ffcadd9eeb4
|
||||
|
||||
- name: openmw
|
||||
builddir: true
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- "-DBUILD_BSATOOL=no"
|
||||
- "-DBUILD_ESMTOOL=no"
|
||||
- "-DCMAKE_BUILD_TYPE=Release"
|
||||
- "-DICONDIR=/app/share/icons"
|
||||
- "-DOPENMW_USE_SYSTEM_RECASTNAVIGATION=yes"
|
||||
sources:
|
||||
- type: dir
|
||||
path: ..
|
||||
- type: shell
|
||||
commands:
|
||||
- "sed -i 's:/wiki:/old-wiki:' ./files/openmw.appdata.xml"
|
||||
- "sed -i 's:>org.openmw.launcher.desktop<:>org.openmw.OpenMW.devel.desktop<:' ./files/openmw.appdata.xml"
|
||||
- "sed -i 's:Icon=openmw:Icon=org.openmw.OpenMW.devel.png:' ./files/org.openmw.launcher.desktop"
|
||||
- "sed -i 's:Icon=openmw-cs:Icon=org.openmw.OpenMW.OpenCS.devel.png:' ./files/org.openmw.cs.desktop"
|
||||
post-install:
|
||||
- "mv /app/share/applications/org.openmw.launcher.desktop /app/share/applications/org.openmw.OpenMW.devel.desktop"
|
||||
- "mv /app/share/applications/org.openmw.cs.desktop /app/share/applications/org.openmw.OpenMW.OpenCS.devel.desktop"
|
||||
- "mv /app/share/icons/openmw.png /app/share/icons/org.openmw.OpenMW.devel.png"
|
||||
- "mv /app/share/icons/openmw-cs.png /app/share/icons/org.openmw.OpenMW.OpenCS.devel.png"
|
10
CI/run_integration_tests.sh
Executable file
10
CI/run_integration_tests.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
git clone --depth=1 https://gitlab.com/OpenMW/example-suite.git
|
||||
|
||||
xvfb-run --auto-servernum --server-args='-screen 0 640x480x24x60' \
|
||||
scripts/integration_tests.py --omw build/install/bin/openmw --workdir integration_tests_output example-suite/
|
||||
|
||||
ls integration_tests_output/*.osg_stats.log | while read v; do
|
||||
scripts/osg_stats.py --stats '.*' --regexp_match < "${v}"
|
||||
done
|
12
CI/teal_ci.sh
Executable file
12
CI/teal_ci.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
docs/source/install_luadocumentor_in_docker.sh
|
||||
PATH=$PATH:~/luarocks/bin
|
||||
|
||||
pushd .
|
||||
echo "Install Teal Cyan"
|
||||
git clone https://github.com/teal-language/cyan.git --depth 1
|
||||
cd cyan
|
||||
luarocks make cyan-dev-1.rockspec
|
||||
popd
|
||||
|
||||
scripts/generate_teal_declarations.sh ./teal_declarations
|
||||
zip teal_declarations.zip -r teal_declarations
|
74
CI/ubuntu_gcc_preprocess.sh
Executable file
74
CI/ubuntu_gcc_preprocess.sh
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -xeo pipefail
|
||||
|
||||
SRC="${PWD:?}"
|
||||
VERSION=$(git rev-parse HEAD)
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-D CMAKE_C_COMPILER=gcc \
|
||||
-D CMAKE_CXX_COMPILER=g++ \
|
||||
-D USE_SYSTEM_TINYXML=ON \
|
||||
-D OPENMW_USE_SYSTEM_RECASTNAVIGATION=ON \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
-D CMAKE_C_FLAGS_RELEASE='-DNDEBUG -E -w' \
|
||||
-D CMAKE_CXX_FLAGS_RELEASE='-DNDEBUG -E -w' \
|
||||
-D CMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-D BUILD_BENCHMARKS=ON \
|
||||
-D BUILD_BSATOOL=ON \
|
||||
-D BUILD_BULLETOBJECTTOOL=ON \
|
||||
-D BUILD_ESMTOOL=ON \
|
||||
-D BUILD_ESSIMPORTER=ON \
|
||||
-D BUILD_LAUNCHER=ON \
|
||||
-D BUILD_LAUNCHER_TESTS=ON \
|
||||
-D BUILD_MWINIIMPORTER=ON \
|
||||
-D BUILD_NAVMESHTOOL=ON \
|
||||
-D BUILD_NIFTEST=ON \
|
||||
-D BUILD_OPENCS=ON \
|
||||
-D BUILD_OPENCS_TESTS=ON \
|
||||
-D BUILD_OPENMW=ON \
|
||||
-D BUILD_UNITTESTS=ON \
|
||||
-D BUILD_WIZARD=ON \
|
||||
"${SRC}"
|
||||
cmake --build . --parallel
|
||||
|
||||
cd ..
|
||||
|
||||
scripts/preprocessed_file_size_stats.py --remove_prefix "${SRC}/" build > "${VERSION:?}.json"
|
||||
ls -al "${VERSION:?}.json"
|
||||
|
||||
if [[ "${GENERATE_ONLY}" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git remote add target "${CI_MERGE_REQUEST_PROJECT_URL:-https://gitlab.com/OpenMW/openmw.git}"
|
||||
|
||||
TARGET_BRANCH="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-master}"
|
||||
|
||||
git fetch target "${TARGET_BRANCH:?}"
|
||||
|
||||
if [[ "${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}" ]]; then
|
||||
git remote add source "${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}"
|
||||
git fetch --unshallow source "${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"
|
||||
elif [[ "${CI_COMMIT_BRANCH}" ]]; then
|
||||
git fetch origin "${CI_COMMIT_BRANCH:?}"
|
||||
else
|
||||
git fetch origin
|
||||
fi
|
||||
|
||||
BASE_VERSION=$(git merge-base "target/${TARGET_BRANCH:?}" "${VERSION:?}")
|
||||
|
||||
# Save and use scripts from this commit because they may be absent or different in the base version
|
||||
cp scripts/preprocessed_file_size_stats.py scripts/preprocessed_file_size_stats.bak.py
|
||||
cp CI/ubuntu_gcc_preprocess.sh CI/ubuntu_gcc_preprocess.bak.sh
|
||||
git checkout "${BASE_VERSION:?}"
|
||||
mv scripts/preprocessed_file_size_stats.bak.py scripts/preprocessed_file_size_stats.py
|
||||
mv CI/ubuntu_gcc_preprocess.bak.sh CI/ubuntu_gcc_preprocess.sh
|
||||
env GENERATE_ONLY=1 CI/ubuntu_gcc_preprocess.sh
|
||||
git checkout --force "${VERSION:?}"
|
||||
|
||||
scripts/preprocessed_file_size_stats_diff.py "${BASE_VERSION:?}.json" "${VERSION:?}.json"
|
410
CMakeLists.txt
410
CMakeLists.txt
|
@ -1,18 +1,38 @@
|
|||
project(OpenMW)
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# for link time optimization, remove if cmake version is >= 3.9
|
||||
if(POLICY CMP0069) # LTO
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
endif()
|
||||
|
||||
# for position-independent executable, remove if cmake version is >= 3.14
|
||||
if(POLICY CMP0083)
|
||||
cmake_policy(SET CMP0083 NEW)
|
||||
cmake_policy(SET CMP0083 NEW)
|
||||
endif()
|
||||
|
||||
# to link with freetype library
|
||||
if(POLICY CMP0079)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
endif()
|
||||
|
||||
# don't add /W3 flag by default for MSVC
|
||||
if(POLICY CMP0092)
|
||||
cmake_policy(SET CMP0092 NEW)
|
||||
endif()
|
||||
|
||||
# set the timestamps of extracted contents to the time of extraction
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
project(OpenMW)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(OPENMW_GL4ES_MANUAL_INIT "Manually initialize gl4es. This is more reliable on platforms without a windowing system. Requires gl4es to be configured with -DNOEGL=ON -DNO_LOADER=ON -DNO_INIT_CONSTRUCTOR=ON." OFF)
|
||||
if(OPENMW_GL4ES_MANUAL_INIT)
|
||||
add_definitions(-DOPENMW_GL4ES_MANUAL_INIT)
|
||||
|
@ -32,6 +52,7 @@ option(BUILD_DOCS "Build documentation." OFF )
|
|||
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
|
||||
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF)
|
||||
option(BUILD_BENCHMARKS "Build benchmarks with Google Benchmark" OFF)
|
||||
<<<<<<< HEAD
|
||||
option(BUILD_OPENMW_MP "Build OpenMW-MP" ON)
|
||||
option(BUILD_BROWSER "Build tes3mp Server Browser" ON)
|
||||
option(BUILD_MASTER "Build tes3mp Master Server" OFF)
|
||||
|
@ -40,8 +61,18 @@ set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 a
|
|||
|
||||
if (NOT BUILD_LAUNCHER AND NOT BUILD_BROWSER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
|
||||
set(USE_QT FALSE)
|
||||
=======
|
||||
option(BUILD_NAVMESHTOOL "Build navmesh tool" ON)
|
||||
option(BUILD_BULLETOBJECTTOOL "Build Bullet object tool" ON)
|
||||
option(BUILD_OPENCS_TESTS "Build OpenMW Construction Set tests" OFF)
|
||||
|
||||
set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up.
|
||||
|
||||
if (BUILD_LAUNCHER OR BUILD_OPENCS OR BUILD_WIZARD OR BUILD_OPENCS_TESTS)
|
||||
set(USE_QT TRUE)
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
else()
|
||||
set(USE_QT TRUE)
|
||||
set(USE_QT FALSE)
|
||||
endif()
|
||||
|
||||
# If the user doesn't supply a CMAKE_BUILD_TYPE via command line, choose one for them.
|
||||
|
@ -68,7 +99,7 @@ endif()
|
|||
message(STATUS "Configuring OpenMW...")
|
||||
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 47)
|
||||
set(OPENMW_VERSION_MINOR 49)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
@ -112,7 +143,7 @@ configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_
|
|||
|
||||
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
|
||||
option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE)
|
||||
option(QT_STATIC "Link static build of QT into the binaries" FALSE)
|
||||
option(QT_STATIC "Link static build of Qt into the binaries" FALSE)
|
||||
|
||||
option(OPENMW_USE_SYSTEM_BULLET "Use system provided bullet physics library" ON)
|
||||
if(OPENMW_USE_SYSTEM_BULLET)
|
||||
|
@ -147,6 +178,11 @@ else()
|
|||
endif()
|
||||
option(RECASTNAVIGATION_STATIC "Build recastnavigation static libraries" ${_recastnavigation_static_default})
|
||||
|
||||
option(OPENMW_USE_SYSTEM_SQLITE3 "Use system provided SQLite3 library" ON)
|
||||
|
||||
option(OPENMW_USE_SYSTEM_BENCHMARK "Use system Google Benchmark library." OFF)
|
||||
option(OPENMW_USE_SYSTEM_GOOGLETEST "Use system Google Test library." OFF)
|
||||
|
||||
option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE)
|
||||
option(OPENMW_LTO_BUILD "Build OpenMW with Link-Time Optimization (Needs ~2GB of RAM)" OFF)
|
||||
|
||||
|
@ -162,18 +198,27 @@ option(OPENMW_OSX_DEPLOYMENT OFF)
|
|||
|
||||
if (MSVC)
|
||||
option(OPENMW_MP_BUILD "Build OpenMW with /MP flag" OFF)
|
||||
if (OPENMW_MP_BUILD)
|
||||
add_compile_options(/MP)
|
||||
endif()
|
||||
|
||||
# \bigobj is required:
|
||||
# 1) for OPENMW_UNITY_BUILD;
|
||||
# 2) to compile lua bindings in components, openmw and tests, because sol3 is heavily templated.
|
||||
# there should be no relevant downsides to having it on:
|
||||
# https://docs.microsoft.com/en-us/cpp/build/reference/bigobj-increase-number-of-sections-in-dot-obj-file
|
||||
add_compile_options(/bigobj)
|
||||
endif()
|
||||
|
||||
# Set up common paths
|
||||
if (APPLE)
|
||||
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "../Resources/resources" CACHE PATH "location of OpenMW resources files")
|
||||
elseif(UNIX)
|
||||
# Paths
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "Where to install libraries")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(GLOBAL_DATA_PATH "${DATAROOTDIR}/games/" CACHE PATH "Set data path prefix")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_DATAROOTDIR}" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(GLOBAL_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/games/" CACHE PATH "Set data path prefix")
|
||||
SET(DATADIR "${GLOBAL_DATA_PATH}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
|
||||
|
@ -184,10 +229,8 @@ elseif(UNIX)
|
|||
ENDIF()
|
||||
SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir")
|
||||
|
||||
set(MORROWIND_DATA_FILES "${DATADIR}/data" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "${DATADIR}/resources" CACHE PATH "location of OpenMW resources files")
|
||||
else()
|
||||
set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files")
|
||||
set(OPENMW_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
|
||||
endif(APPLE)
|
||||
|
||||
|
@ -195,8 +238,14 @@ if (WIN32)
|
|||
option(USE_DEBUG_CONSOLE "whether a debug console should be enabled for debug builds, if false debug output is redirected to Visual Studio output" ON)
|
||||
endif()
|
||||
|
||||
<<<<<<< HEAD
|
||||
find_package(RakNet REQUIRED)
|
||||
include_directories(${RakNet_INCLUDES})
|
||||
=======
|
||||
if(MSVC)
|
||||
add_compile_options("/utf-8")
|
||||
endif()
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
|
||||
# Dependencies
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
@ -204,12 +253,22 @@ find_package(OpenGL REQUIRED)
|
|||
find_package(LZ4 REQUIRED)
|
||||
|
||||
if (USE_QT)
|
||||
<<<<<<< HEAD
|
||||
find_package(Qt5Core 5.9 REQUIRED) # Temporary adjustment for TES3MP CI
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5OpenGL REQUIRED)
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
=======
|
||||
find_package(QT REQUIRED COMPONENTS Core NAMES Qt6 Qt5)
|
||||
if (QT_VERSION_MAJOR VERSION_EQUAL 5)
|
||||
find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL REQUIRED)
|
||||
else()
|
||||
find_package(Qt6 COMPONENTS Core Widgets Network OpenGL OpenGLWidgets REQUIRED)
|
||||
endif()
|
||||
message(STATUS "Using Qt${QT_VERSION}")
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
endif()
|
||||
|
||||
# Start of tes3mp addition
|
||||
|
@ -218,17 +277,20 @@ endif()
|
|||
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
set(USED_OSG_COMPONENTS
|
||||
osgAnimation
|
||||
osgDB
|
||||
osgViewer
|
||||
osgText
|
||||
osgGA
|
||||
osgParticle
|
||||
osgUtil
|
||||
osgFX
|
||||
osgParticle
|
||||
osgText
|
||||
osgUtil
|
||||
osgShadow
|
||||
osgAnimation)
|
||||
osgSim
|
||||
osgViewer
|
||||
)
|
||||
set(USED_OSG_PLUGINS
|
||||
osgdb_bmp
|
||||
osgdb_dae
|
||||
osgdb_dds
|
||||
osgdb_freetype
|
||||
osgdb_jpeg
|
||||
|
@ -242,6 +304,37 @@ set(USED_OSG_PLUGINS
|
|||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
|
||||
if(NOT COLLADA_DOM_VERSION_MAJOR)
|
||||
set(COLLADA_DOM_VERSION_MAJOR 2)
|
||||
endif()
|
||||
|
||||
if(NOT COLLADA_DOM_VERSION_MINOR)
|
||||
set(COLLADA_DOM_VERSION_MINOR 5)
|
||||
endif()
|
||||
|
||||
find_package(collada_dom 2.5)
|
||||
|
||||
option(OPENMW_USE_SYSTEM_ICU "Use system ICU library instead of internal. If disabled, requires autotools" ON)
|
||||
if(OPENMW_USE_SYSTEM_ICU)
|
||||
find_package(ICU REQUIRED COMPONENTS uc i18n data)
|
||||
endif()
|
||||
|
||||
option(OPENMW_USE_SYSTEM_YAML_CPP "Use system yaml-cpp library instead of internal." ON)
|
||||
if(OPENMW_USE_SYSTEM_YAML_CPP)
|
||||
set(_yaml_cpp_static_default OFF)
|
||||
else()
|
||||
set(_yaml_cpp_static_default ON)
|
||||
endif()
|
||||
option(YAML_CPP_STATIC "Link static build of yaml-cpp into the binaries" ${_yaml_cpp_static_default})
|
||||
if (OPENMW_USE_SYSTEM_YAML_CPP)
|
||||
find_package(yaml-cpp REQUIRED)
|
||||
endif()
|
||||
|
||||
if ((BUILD_UNITTESTS OR BUILD_OPENCS_TESTS) AND OPENMW_USE_SYSTEM_GOOGLETEST)
|
||||
find_package(GTest 1.10 REQUIRED)
|
||||
find_package(GMock 1.10 REQUIRED)
|
||||
endif()
|
||||
|
||||
add_subdirectory(extern)
|
||||
|
||||
# Sound setup
|
||||
|
@ -326,7 +419,12 @@ if (WIN32)
|
|||
add_definitions(-DSDL_MAIN_HANDLED)
|
||||
|
||||
# Get rid of useless crud from windows.h
|
||||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(
|
||||
-DNOMINMAX # name conflict with std::min, std::max
|
||||
-DWIN32_LEAN_AND_MEAN
|
||||
-DNOMB # name conflict with MWGui::MessageBox
|
||||
-DNOGDI # name conflict with osgAnimation::MorphGeometry::RELATIVE
|
||||
)
|
||||
endif()
|
||||
|
||||
# Start of tes3mp addition
|
||||
|
@ -397,10 +495,7 @@ endif()
|
|||
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
find_package(OpenSceneGraph 3.4.0 REQUIRED ${USED_OSG_COMPONENTS})
|
||||
if (${OPENSCENEGRAPH_VERSION} VERSION_GREATER 3.6.2 AND ${OPENSCENEGRAPH_VERSION} VERSION_LESS 3.6.5)
|
||||
message(FATAL_ERROR "OpenSceneGraph version ${OPENSCENEGRAPH_VERSION} has critical regressions which cause crashes. Please upgrade to 3.6.5 or later. We strongly recommend using the tip of the official 'OpenSceneGraph-3.6' branch or the tip of '3.6' OpenMW/osg (OSGoS).")
|
||||
endif()
|
||||
find_package(OpenSceneGraph 3.6.5 REQUIRED ${USED_OSG_COMPONENTS}) # Bump to 3.6.6 when released
|
||||
|
||||
if(OSG_STATIC)
|
||||
find_package(OSGPlugins REQUIRED COMPONENTS ${USED_OSG_PLUGINS})
|
||||
|
@ -421,7 +516,12 @@ ELSE(BUILD_OPENMW OR BUILD_OPENCS)
|
|||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options iostreams)
|
||||
include(cmake/CheckOsgMultiview.cmake)
|
||||
if(HAVE_MULTIVIEW)
|
||||
add_definitions(-DOSG_HAS_MULTIVIEW)
|
||||
endif(HAVE_MULTIVIEW)
|
||||
|
||||
set(BOOST_COMPONENTS system program_options iostreams)
|
||||
if(WIN32)
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||
if(MSVC)
|
||||
|
@ -438,13 +538,21 @@ endif()
|
|||
set(Boost_NO_BOOST_CMAKE ON)
|
||||
|
||||
find_package(Boost 1.6.2 REQUIRED COMPONENTS ${BOOST_COMPONENTS} OPTIONAL_COMPONENTS ${BOOST_OPTIONAL_COMPONENTS})
|
||||
<<<<<<< HEAD
|
||||
# Start of tes3mp addition
|
||||
#
|
||||
# Don't require certain dependencies for the server
|
||||
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
=======
|
||||
|
||||
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0)
|
||||
find_package(Boost 1.77.0 REQUIRED COMPONENTS atomic)
|
||||
endif()
|
||||
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
if(OPENMW_USE_SYSTEM_MYGUI)
|
||||
find_package(MyGUI 3.2.2 REQUIRED)
|
||||
find_package(MyGUI 3.4.1 REQUIRED)
|
||||
endif()
|
||||
# End of tes3mp addition
|
||||
#
|
||||
|
@ -458,11 +566,32 @@ find_package(SDL2 2.0.9 REQUIRED)
|
|||
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
find_package(OpenAL REQUIRED)
|
||||
<<<<<<< HEAD
|
||||
# End of tes3mp addition
|
||||
#
|
||||
# Don't require certain dependencies for the server
|
||||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
=======
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
option(USE_LUAJIT "Switch Lua/LuaJit (TRUE is highly recommended)" TRUE)
|
||||
if(USE_LUAJIT)
|
||||
find_package(LuaJit REQUIRED)
|
||||
set(LUA_INCLUDE_DIR ${LuaJit_INCLUDE_DIR})
|
||||
set(LUA_LIBRARIES ${LuaJit_LIBRARIES})
|
||||
else(USE_LUAJIT)
|
||||
find_package(Lua REQUIRED)
|
||||
add_compile_definitions(NO_LUAJIT)
|
||||
endif(USE_LUAJIT)
|
||||
if (NOT WIN32)
|
||||
include(cmake/CheckLuaCustomAllocator.cmake)
|
||||
endif()
|
||||
|
||||
# C++ library binding to Lua
|
||||
set(SOL_INCLUDE_DIR ${OpenMW_SOURCE_DIR}/extern/sol3)
|
||||
set(SOL_CONFIG_DIR ${OpenMW_SOURCE_DIR}/extern/sol_config)
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
|
||||
include_directories(
|
||||
BEFORE SYSTEM
|
||||
|
@ -473,12 +602,16 @@ include_directories(
|
|||
${OPENAL_INCLUDE_DIR}
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
${BULLET_INCLUDE_DIRS}
|
||||
${LUA_INCLUDE_DIR}
|
||||
${SOL_INCLUDE_DIR}
|
||||
${SOL_CONFIG_DIR}
|
||||
${ICU_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS})
|
||||
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${COLLADA_DOM_LIBRARY_DIRS})
|
||||
|
||||
if(MYGUI_STATIC)
|
||||
add_definitions(-DMYGUI_STATIC)
|
||||
add_definitions(-DMYGUI_STATIC)
|
||||
endif (MYGUI_STATIC)
|
||||
|
||||
if (APPLE)
|
||||
|
@ -489,9 +622,8 @@ if (APPLE)
|
|||
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
|
||||
endif (APPLE)
|
||||
|
||||
if (NOT APPLE)
|
||||
set(OPENMW_MYGUI_FILES_ROOT ${OpenMW_BINARY_DIR})
|
||||
set(OPENMW_SHADERS_ROOT ${OpenMW_BINARY_DIR})
|
||||
if (NOT APPLE) # this is modified for macOS use later in "apps/open[mw|cs]/CMakeLists.txt"
|
||||
set(OPENMW_RESOURCES_ROOT ${OpenMW_BINARY_DIR})
|
||||
endif ()
|
||||
|
||||
add_subdirectory(files/)
|
||||
|
@ -575,7 +707,7 @@ endif()
|
|||
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -pedantic -Wno-long-long")
|
||||
set(OPENMW_CXX_FLAGS "-Wall -Wextra -Wundef -Wextra-semi -Wno-unused-parameter -pedantic -Wno-long-long -Wnon-virtual-dtor -Wunused ${OPENMW_CXX_FLAGS}")
|
||||
add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS=ON )
|
||||
|
||||
if (APPLE)
|
||||
|
@ -585,12 +717,12 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
|||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.6 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 3.6)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
|
||||
set(OPENMW_CXX_FLAGS "${OPENMW_CXX_FLAGS} -Wno-potentially-evaluated-expression")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.6)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
|
||||
set(OPENMW_CXX_FLAGS "${OPENMW_CXX_FLAGS} -Wno-unused-but-set-parameter -Wduplicated-branches -Wduplicated-cond -Wlogical-op")
|
||||
endif()
|
||||
endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
|
||||
|
@ -608,12 +740,16 @@ add_subdirectory (extern/oics)
|
|||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
add_subdirectory (extern/Base64)
|
||||
<<<<<<< HEAD
|
||||
# Start of tes3mp addition
|
||||
#
|
||||
# Don't require certain dependencies for the server
|
||||
IF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
if (BUILD_OPENCS)
|
||||
=======
|
||||
if (BUILD_OPENCS OR BUILD_OPENCS_TESTS)
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
add_subdirectory (extern/osgQt)
|
||||
endif()
|
||||
# Start of tes3mp addition
|
||||
|
@ -622,9 +758,12 @@ endif()
|
|||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
# End of tes3mp addition
|
||||
|
||||
if (OPENMW_CXX_FLAGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENMW_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
# Components
|
||||
add_subdirectory (components)
|
||||
target_compile_definitions(components PRIVATE OPENMW_DOC_BASEURL="${OPENMW_DOC_BASEURL}")
|
||||
|
||||
# Apps and tools
|
||||
if (BUILD_OPENMW_MP)
|
||||
|
@ -640,15 +779,15 @@ if (BUILD_OPENMW)
|
|||
endif()
|
||||
|
||||
if (BUILD_BSATOOL)
|
||||
add_subdirectory( apps/bsatool )
|
||||
add_subdirectory( apps/bsatool )
|
||||
endif()
|
||||
|
||||
if (BUILD_ESMTOOL)
|
||||
add_subdirectory( apps/esmtool )
|
||||
add_subdirectory( apps/esmtool )
|
||||
endif()
|
||||
|
||||
if (BUILD_LAUNCHER)
|
||||
add_subdirectory( apps/launcher )
|
||||
add_subdirectory( apps/launcher )
|
||||
endif()
|
||||
|
||||
if (BUILD_BROWSER)
|
||||
|
@ -656,19 +795,19 @@ if (BUILD_BROWSER)
|
|||
endif()
|
||||
|
||||
if (BUILD_MWINIIMPORTER)
|
||||
add_subdirectory( apps/mwiniimporter )
|
||||
add_subdirectory( apps/mwiniimporter )
|
||||
endif()
|
||||
|
||||
if (BUILD_ESSIMPORTER)
|
||||
add_subdirectory (apps/essimporter )
|
||||
add_subdirectory (apps/essimporter )
|
||||
endif()
|
||||
|
||||
if (BUILD_OPENCS)
|
||||
add_subdirectory (apps/opencs)
|
||||
if (BUILD_OPENCS OR BUILD_OPENCS_TESTS)
|
||||
add_subdirectory (apps/opencs)
|
||||
endif()
|
||||
|
||||
if (BUILD_WIZARD)
|
||||
add_subdirectory(apps/wizard)
|
||||
add_subdirectory(apps/wizard)
|
||||
endif()
|
||||
|
||||
if (BUILD_NIFTEST)
|
||||
|
@ -677,19 +816,34 @@ endif(BUILD_NIFTEST)
|
|||
|
||||
# UnitTests
|
||||
if (BUILD_UNITTESTS)
|
||||
add_subdirectory( apps/openmw_test_suite )
|
||||
add_subdirectory( apps/openmw_test_suite )
|
||||
endif()
|
||||
|
||||
if (BUILD_BENCHMARKS)
|
||||
add_subdirectory(apps/benchmarks)
|
||||
add_subdirectory(apps/benchmarks)
|
||||
endif()
|
||||
|
||||
if (BUILD_NAVMESHTOOL)
|
||||
add_subdirectory(apps/navmeshtool)
|
||||
endif()
|
||||
|
||||
if (BUILD_BULLETOBJECTTOOL)
|
||||
add_subdirectory( apps/bulletobjecttool )
|
||||
endif()
|
||||
|
||||
if (BUILD_OPENCS_TESTS)
|
||||
add_subdirectory(apps/opencs_tests)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
if (MSVC)
|
||||
if (OPENMW_MP_BUILD)
|
||||
set( MT_BUILD "/MP")
|
||||
endif()
|
||||
if (MSVC)
|
||||
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
|
||||
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)" )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)" )
|
||||
endforeach( OUTPUTCONFIG )
|
||||
|
||||
<<<<<<< HEAD
|
||||
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
|
||||
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)" )
|
||||
|
@ -781,41 +935,154 @@ if (WIN32)
|
|||
set_target_properties(tes3mp PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD} /bigobj")
|
||||
else()
|
||||
set_target_properties(tes3mp PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
=======
|
||||
if (USE_DEBUG_CONSOLE AND BUILD_OPENMW)
|
||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
||||
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_CONSOLE>)
|
||||
elseif (BUILD_OPENMW)
|
||||
# Turn off debug console, debug output will be written to visual studio output instead
|
||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS")
|
||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS")
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_WIZARD)
|
||||
set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif()
|
||||
if (BUILD_OPENMW)
|
||||
# Release builds don't use the debug console
|
||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||
endif()
|
||||
|
||||
if (BUILD_BENCHMARKS)
|
||||
set_target_properties(openmw_detournavigator_navmeshtilescache_benchmark PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif()
|
||||
endif(MSVC)
|
||||
# Play a bit with the warning levels
|
||||
|
||||
<<<<<<< HEAD
|
||||
# TODO: At some point release builds should not use the console but rather write to a log file
|
||||
#set_target_properties(tes3mp PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
||||
#set_target_properties(tes3mp PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||
=======
|
||||
set(WARNINGS "/W4")
|
||||
|
||||
set(WARNINGS_DISABLE
|
||||
4100 # Unreferenced formal parameter (-Wunused-parameter)
|
||||
4127 # Conditional expression is constant
|
||||
4996 # Function was declared deprecated
|
||||
5054 # Deprecated operations between enumerations of different types caused by Qt headers
|
||||
)
|
||||
|
||||
if( "${MyGUI_VERSION}" VERSION_LESS_EQUAL "3.4.0" )
|
||||
set(WARNINGS_DISABLE ${WARNINGS_DISABLE}
|
||||
4866 # compiler may not enforce left-to-right evaluation order for call
|
||||
)
|
||||
endif()
|
||||
|
||||
if( "${MyGUI_VERSION}" VERSION_LESS_EQUAL "3.4.1" )
|
||||
set(WARNINGS_DISABLE ${WARNINGS_DISABLE}
|
||||
4275 # non dll-interface class 'MyGUI::delegates::IDelegateUnlink' used as base for dll-interface class 'MyGUI::Widget'
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(d ${WARNINGS_DISABLE})
|
||||
set(WARNINGS "${WARNINGS} /wd${d}")
|
||||
endforeach(d)
|
||||
|
||||
if(OPENMW_MSVC_WERROR)
|
||||
set(WARNINGS "${WARNINGS} /WX")
|
||||
endif()
|
||||
|
||||
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
|
||||
if (MSVC_VERSION GREATER_EQUAL 1915 AND MSVC_VERSION LESS 1920)
|
||||
target_compile_definitions(components INTERFACE _ENABLE_EXTENDED_ALIGNED_STORAGE)
|
||||
endif()
|
||||
|
||||
if (BUILD_BSATOOL)
|
||||
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_ESMTOOL)
|
||||
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_ESSIMPORTER)
|
||||
set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_LAUNCHER)
|
||||
set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_MWINIIMPORTER)
|
||||
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_OPENCS)
|
||||
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_OPENMW)
|
||||
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_WIZARD)
|
||||
set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_UNITTESTS)
|
||||
set_target_properties(openmw_test_suite PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_BENCHMARKS)
|
||||
set_target_properties(openmw_detournavigator_navmeshtilescache_benchmark PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_NAVMESHTOOL)
|
||||
set_target_properties(openmw-navmeshtool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_BULLETOBJECTTOOL)
|
||||
set(WARNINGS "${WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(openmw-bulletobjecttool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
||||
endif()
|
||||
endif(MSVC)
|
||||
|
||||
# TODO: At some point release builds should not use the console but rather write to a log file
|
||||
#set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
||||
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||
endif()
|
||||
|
||||
if (BUILD_OPENMW AND APPLE)
|
||||
target_compile_definitions(components PRIVATE GL_SILENCE_DEPRECATION=1)
|
||||
target_compile_definitions(openmw PRIVATE GL_SILENCE_DEPRECATION=1)
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
endif()
|
||||
|
||||
# Apple bundling
|
||||
if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.13 AND CMAKE_VERSION VERSION_LESS 3.13.4)
|
||||
message(FATAL_ERROR "macOS packaging is broken in early CMake 3.13 releases, see https://gitlab.com/OpenMW/openmw/issues/4767. Please use at least 3.13.4 or an older version like 3.12.4")
|
||||
if (CMAKE_VERSION VERSION_LESS 3.19)
|
||||
message(FATAL_ERROR "macOS packaging requires CMake 3.19 or higher to sign macOS app bundles.")
|
||||
endif ()
|
||||
|
||||
get_property(QT_COCOA_PLUGIN_PATH TARGET Qt5::QCocoaIntegrationPlugin PROPERTY LOCATION_RELEASE)
|
||||
get_property(QT_COCOA_PLUGIN_PATH TARGET Qt${QT_VERSION_MAJOR}::QCocoaIntegrationPlugin PROPERTY LOCATION_RELEASE)
|
||||
get_filename_component(QT_COCOA_PLUGIN_DIR "${QT_COCOA_PLUGIN_PATH}" DIRECTORY)
|
||||
get_filename_component(QT_COCOA_PLUGIN_GROUP "${QT_COCOA_PLUGIN_DIR}" NAME)
|
||||
get_filename_component(QT_COCOA_PLUGIN_NAME "${QT_COCOA_PLUGIN_PATH}" NAME)
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
|
||||
get_property(QT_QMACSTYLE_PLUGIN_PATH TARGET Qt${QT_VERSION_MAJOR}::QMacStylePlugin PROPERTY LOCATION_RELEASE)
|
||||
get_filename_component(QT_QMACSTYLE_PLUGIN_DIR "${QT_QMACSTYLE_PLUGIN_PATH}" DIRECTORY)
|
||||
get_filename_component(QT_QMACSTYLE_PLUGIN_GROUP "${QT_QMACSTYLE_PLUGIN_DIR}" NAME)
|
||||
get_filename_component(QT_QMACSTYLE_PLUGIN_NAME "${QT_QMACSTYLE_PLUGIN_PATH}" NAME)
|
||||
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
||||
|
||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${APP_BUNDLE_DIR}/Contents/Resources/qt.conf" COPYONLY)
|
||||
|
||||
if (BUILD_OPENCS)
|
||||
get_property(OPENCS_BUNDLE_NAME_TMP TARGET openmw-cs PROPERTY OUTPUT_NAME)
|
||||
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY)
|
||||
get_property(OPENCS_BUNDLE_NAME_TMP TARGET openmw-cs PROPERTY OUTPUT_NAME)
|
||||
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY)
|
||||
endif ()
|
||||
|
||||
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime)
|
||||
|
@ -884,7 +1151,9 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
|||
install_plugins_for_bundle("${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
|
||||
|
||||
set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
|
||||
set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}")
|
||||
set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
|
||||
set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}")
|
||||
|
||||
install(CODE "
|
||||
function(gp_item_default_embedded_path_override item default_embedded_path_var)
|
||||
|
@ -897,6 +1166,9 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
|||
fixup_bundle(\"${INSTALLED_OPENMW_APP}\" \"${PLUGINS}\" \"\")
|
||||
fixup_bundle(\"${INSTALLED_OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
set(CPACK_PRE_BUILD_SCRIPTS ${CMAKE_SOURCE_DIR}/cmake/SignMacApplications.cmake)
|
||||
|
||||
include(CPack)
|
||||
elseif(NOT APPLE)
|
||||
get_generator_is_multi_config(multi_config)
|
||||
|
@ -929,7 +1201,6 @@ elseif(NOT APPLE)
|
|||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/CHANGELOG.md" DESTINATION "." RENAME "CHANGELOG.txt")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/README.md" DESTINATION "." RENAME "README.txt")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/LICENSE" DESTINATION "." RENAME "LICENSE.txt")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/mygui/DejaVuFontLicense.txt" DESTINATION ".")
|
||||
INSTALL(FILES "${INSTALL_SOURCE}/defaults.bin" DESTINATION ".")
|
||||
# Start of tes3mp addition
|
||||
INSTALL(FILES "${INSTALL_SOURCE}/tes3mp-client-default.cfg" DESTINATION ".")
|
||||
|
@ -1053,9 +1324,12 @@ elseif(NOT APPLE)
|
|||
IF(BUILD_WIZARD)
|
||||
INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-wizard" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_WIZARD)
|
||||
|
||||
# Install licenses
|
||||
INSTALL(FILES "files/mygui/DejaVuFontLicense.txt" DESTINATION "${LICDIR}" )
|
||||
if(BUILD_NAVMESHTOOL)
|
||||
install(PROGRAMS "${INSTALL_SOURCE}/openmw-navmeshtool" DESTINATION "${BINDIR}" )
|
||||
endif()
|
||||
IF(BUILD_BULLETOBJECTTOOL)
|
||||
INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-bulletobjecttool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_BULLETOBJECTTOOL)
|
||||
|
||||
# Install icon and desktop file
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.launcher.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
|
||||
|
|
|
@ -22,9 +22,9 @@ Pull Request Guidelines
|
|||
To facilitate the review process, your pull request description should include the following, if applicable:
|
||||
|
||||
* A link back to the bug report or forum discussion that prompted the change. Note: when linking bugs, use the syntax ```[Bug #xyz](https://gitlab.com/OpenMW/openmw/issues/#xyz)``` to create a clickable link. Writing only 'Bug #xyz' will unfortunately create a link to the Github pull request with that number instead.
|
||||
* Summary of the changes made
|
||||
* Reasoning / motivation behind the change
|
||||
* What testing you have carried out to verify the change
|
||||
* Summary of the changes made.
|
||||
* Reasoning / motivation behind the change.
|
||||
* What testing you have carried out to verify the change.
|
||||
|
||||
Furthermore, we advise to:
|
||||
|
||||
|
@ -51,9 +51,9 @@ OpenMW, in its default configuration, is meant to be a faithful reimplementation
|
|||
|
||||
That said, we may sometimes evaluate such issues on an individual basis. Common exceptions to the above would be:
|
||||
|
||||
* Issues so glaring that they would severely limit the capabilities of the engine in the future (for example, the scripting engine not being allowed to access objects in remote cells)
|
||||
* Bugs where the intent is very obvious, and that have little to no balancing impact (e.g. the bug were being tired made it easier to repair items, instead of harder)
|
||||
* Bugs that were fixed in an official patch for Morrowind
|
||||
* Issues so glaring that they would severely limit the capabilities of the engine in the future (for example, the scripting engine not being allowed to access objects in remote cells).
|
||||
* Bugs where the intent is very obvious, and that have little to no balancing impact (e.g. the bug were being tired made it easier to repair items, instead of harder).
|
||||
* Bugs that were fixed in an official patch for Morrowind.
|
||||
|
||||
Feature additions policy
|
||||
=====================
|
||||
|
@ -99,7 +99,7 @@ Code Review
|
|||
Merging
|
||||
=======
|
||||
|
||||
To be able to merge PRs, commit priviledges are required. If you do not have the priviledges, just ping someone that does have them with a short comment like "Looks good to me @user".
|
||||
To be able to merge PRs, commit privileges are required. If you do not have the privileges, just ping someone that does have them with a short comment like "Looks good to me @user".
|
||||
|
||||
The person to merge the PR may either use github's Merge button or if using the command line, use the ```--no-ff``` flag (so a merge commit is created, just like with Github's merge button) and include the pull request number in the commit description.
|
||||
|
||||
|
|
79
README.md
79
README.md
|
@ -1,6 +1,7 @@
|
|||
TES3MP
|
||||
======
|
||||
|
||||
<<<<<<< HEAD
|
||||
Copyright (c) 2008-2015, OpenMW Team
|
||||
Copyright (c) 2016-2022, David Cernat & Stanislav Zhukov
|
||||
|
||||
|
@ -12,11 +13,32 @@ TES3MP is a project adding multiplayer functionality to [OpenMW](https://github.
|
|||
|
||||
Font Licenses:
|
||||
* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVuFontLicense.txt](https://github.com/TES3MP/TES3MP/blob/master/files/mygui/DejaVuFontLicense.txt) for more information)
|
||||
=======
|
||||
OpenMW is an open-source open-world RPG game engine that supports playing Morrowind by Bethesda Softworks. You need to own the game for OpenMW to play Morrowind.
|
||||
|
||||
OpenMW also comes with OpenMW-CS, a replacement for Bethesda's Construction Set.
|
||||
|
||||
* Version: 0.49.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
|
||||
* Discord: https://discord.gg/bWuqq2e
|
||||
|
||||
|
||||
Font Licenses:
|
||||
* DejaVuLGCSansMono.ttf: custom (see [files/data/fonts/DejaVuFontLicense.txt](https://gitlab.com/OpenMW/openmw/-/raw/master/files/data/fonts/DejaVuFontLicense.txt) for more information)
|
||||
* DemonicLetters.ttf: SIL Open Font License (see [files/data/fonts/DemonicLettersFontLicense.txt](https://gitlab.com/OpenMW/openmw/-/raw/master/files/data/fonts/DemonicLettersFontLicense.txt) for more information)
|
||||
* MysticCards.ttf: SIL Open Font License (see [files/data/fonts/MysticCardsFontLicense.txt](https://gitlab.com/OpenMW/openmw/-/raw/master/files/data/fonts/MysticCardsFontLicense.txt) for more information)
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
|
||||
Project status
|
||||
--------------
|
||||
|
||||
<<<<<<< HEAD
|
||||
[Version changelog](https://github.com/TES3MP/TES3MP/blob/master/tes3mp-changelog.md)
|
||||
=======
|
||||
The main quests in Morrowind, Tribunal and Bloodmoon are all completable. Some issues with side quests are to be expected (but rare). Check the [bug tracker](https://gitlab.com/OpenMW/openmw/issues?label_name%5B%5D=1.0) for a list of issues we need to resolve before the "1.0" release. Even before the "1.0" release however, OpenMW boasts some new [features](https://wiki.openmw.org/index.php?title=Features), such as improved graphics and user interfaces.
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
|
||||
As of version 0.8.1, TES3MP is fully playable, providing very extensive player, NPC, world and quest synchronization, as well as state saving and loading, all of which are highly customizable via [serverside Lua scripts](https://github.com/TES3MP/CoreScripts).
|
||||
|
||||
|
@ -27,7 +49,17 @@ TES3MP now also has a [VR branch](https://github.com/TES3MP/TES3MP/tree/0.8.1-vr
|
|||
Donations
|
||||
---------------
|
||||
|
||||
<<<<<<< HEAD
|
||||
You can benefit the project by donating on Patreon to our two developers, [David Cernat](https://www.patreon.com/davidcernat) and [Koncord](https://www.patreon.com/Koncord), as well as by supporting [OpenMW](https://openmw.org).
|
||||
=======
|
||||
* [Official forums](https://forum.openmw.org/)
|
||||
* [Installation instructions](https://openmw.readthedocs.io/en/latest/manuals/installation/index.html)
|
||||
* [Build from source](https://wiki.openmw.org/index.php?title=Development_Environment_Setup)
|
||||
* [Testing the game](https://wiki.openmw.org/index.php?title=Testing)
|
||||
* [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted)
|
||||
* [Report a bug](https://gitlab.com/OpenMW/openmw/issues) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug!
|
||||
* [Known issues](https://gitlab.com/OpenMW/openmw/issues?label_name%5B%5D=Bug)
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
|
||||
Contributing
|
||||
---------------
|
||||
|
@ -36,7 +68,54 @@ Helping us with documentation, bug hunting and video showcases is always greatly
|
|||
|
||||
For code contributions, it's best to start out with modestly sized fixes and features and work your way up. There are so many different possible implementations of more major features – many of which would cause undesirable code or vision conflicts with OpenMW – that those should be talked over in advance with the existing developers before effort is spent on them.
|
||||
|
||||
<<<<<<< HEAD
|
||||
Feel free to contact the [team members](https://github.com/TES3MP/TES3MP/blob/master/tes3mp-credits.md) for any questions you might have.
|
||||
=======
|
||||
Syntax: openmw <options>
|
||||
Allowed options:
|
||||
--help print help message
|
||||
--version print version information and quit
|
||||
--data arg (=data) set data directories (later directories
|
||||
have higher priority)
|
||||
--data-local arg set local data directory (highest
|
||||
priority)
|
||||
--fallback-archive arg (=fallback-archive)
|
||||
set fallback BSA archives (later
|
||||
archives have higher priority)
|
||||
--resources arg (=resources) set resources directory
|
||||
--start arg set initial cell
|
||||
--content arg content file(s): esm/esp, or
|
||||
omwgame/omwaddon
|
||||
--no-sound [=arg(=1)] (=0) disable all sounds
|
||||
--script-verbose [=arg(=1)] (=0) verbose script output
|
||||
--script-all [=arg(=1)] (=0) compile all scripts (excluding dialogue
|
||||
scripts) at startup
|
||||
--script-all-dialogue [=arg(=1)] (=0) compile all dialogue scripts at startup
|
||||
--script-console [=arg(=1)] (=0) enable console-only script
|
||||
functionality
|
||||
--script-run arg select a file containing a list of
|
||||
console commands that is executed on
|
||||
startup
|
||||
--script-warn [=arg(=1)] (=1) handling of warnings when compiling
|
||||
scripts
|
||||
0 - ignore warning
|
||||
1 - show warning but consider script as
|
||||
correctly compiled anyway
|
||||
2 - treat warnings as errors
|
||||
--script-blacklist arg ignore the specified script (if the use
|
||||
of the blacklist is enabled)
|
||||
--script-blacklist-use [=arg(=1)] (=1)
|
||||
enable script blacklisting
|
||||
--load-savegame arg load a save game file on game startup
|
||||
(specify an absolute filename or a
|
||||
filename relative to the current
|
||||
working directory)
|
||||
--skip-menu [=arg(=1)] (=0) skip main menu on game startup
|
||||
--new-game [=arg(=1)] (=0) run new game sequence (ignored if
|
||||
skip-menu=0)
|
||||
--encoding arg (=win1252) Character encoding used in OpenMW game
|
||||
messages:
|
||||
>>>>>>> 8a33edd64a6f0e9fe3962c88618e8b27aad1b7a7
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
|
|
@ -1,27 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.11)
|
||||
|
||||
set(BENCHMARK_ENABLE_TESTING OFF)
|
||||
set(BENCHMARK_ENABLE_INSTALL OFF)
|
||||
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
|
||||
|
||||
set(SAVED_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
string(REPLACE "-Wsuggest-override" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "-Wundef" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(benchmark
|
||||
URL https://github.com/google/benchmark/archive/refs/tags/v1.5.2.zip
|
||||
URL_HASH MD5=49395b757a7c4656d70f1328d93efd00
|
||||
SOURCE_DIR fetched/benchmark
|
||||
)
|
||||
FetchContent_MakeAvailableExcludeFromAll(benchmark)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${SAVED_CMAKE_CXX_FLAGS}")
|
||||
|
||||
openmw_add_executable(openmw_detournavigator_navmeshtilescache_benchmark detournavigator/navmeshtilescache.cpp)
|
||||
target_compile_features(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE cxx_std_17)
|
||||
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark benchmark::benchmark components)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(OPENMW_USE_SYSTEM_BENCHMARK)
|
||||
find_package(benchmark REQUIRED)
|
||||
endif()
|
||||
|
||||
add_subdirectory(detournavigator)
|
||||
add_subdirectory(esm)
|
||||
add_subdirectory(settings)
|
||||
|
|
15
apps/benchmarks/detournavigator/CMakeLists.txt
Normal file
15
apps/benchmarks/detournavigator/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
openmw_add_executable(openmw_detournavigator_navmeshtilescache_benchmark navmeshtilescache.cpp)
|
||||
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark benchmark::benchmark components)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE <algorithm>)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
target_compile_options(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE --coverage)
|
||||
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark gcov)
|
||||
endif()
|
|
@ -1,10 +1,11 @@
|
|||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <components/detournavigator/navmeshtilescache.hpp>
|
||||
#include <components/detournavigator/stats.hpp>
|
||||
#include <components/esm3/loadland.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -12,23 +13,22 @@ namespace
|
|||
|
||||
struct Key
|
||||
{
|
||||
osg::Vec3f mAgentHalfExtents;
|
||||
AgentBounds mAgentBounds;
|
||||
TilePosition mTilePosition;
|
||||
RecastMesh mRecastMesh;
|
||||
std::vector<OffMeshConnection> mOffMeshConnections;
|
||||
};
|
||||
|
||||
struct Item
|
||||
{
|
||||
Key mKey;
|
||||
NavMeshData mValue;
|
||||
PreparedNavMeshData mValue;
|
||||
};
|
||||
|
||||
template <typename Random>
|
||||
TilePosition generateTilePosition(int max, Random& random)
|
||||
osg::Vec2i generateVec2i(int max, Random& random)
|
||||
{
|
||||
std::uniform_int_distribution<int> distribution(0, max);
|
||||
return TilePosition(distribution(random), distribution(random));
|
||||
return osg::Vec2i(distribution(random), distribution(random));
|
||||
}
|
||||
|
||||
template <typename Random>
|
||||
|
@ -56,11 +56,16 @@ namespace
|
|||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return AreaType_null;
|
||||
case 1: return AreaType_water;
|
||||
case 2: return AreaType_door;
|
||||
case 3: return AreaType_pathgrid;
|
||||
case 4: return AreaType_ground;
|
||||
case 0:
|
||||
return AreaType_null;
|
||||
case 1:
|
||||
return AreaType_water;
|
||||
case 2:
|
||||
return AreaType_door;
|
||||
case 3:
|
||||
return AreaType_pathgrid;
|
||||
case 4:
|
||||
return AreaType_ground;
|
||||
}
|
||||
return AreaType_null;
|
||||
}
|
||||
|
@ -69,7 +74,7 @@ namespace
|
|||
AreaType generateAreaType(Random& random)
|
||||
{
|
||||
std::uniform_int_distribution<int> distribution(0, 4);
|
||||
return toAreaType(distribution(random));;
|
||||
return toAreaType(distribution(random));
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Random>
|
||||
|
@ -81,47 +86,77 @@ namespace
|
|||
template <typename OutputIterator, typename Random>
|
||||
void generateWater(OutputIterator out, std::size_t count, Random& random)
|
||||
{
|
||||
std::uniform_real_distribution<btScalar> distribution(0.0, 1.0);
|
||||
std::uniform_real_distribution<float> distribution(0.0, 1.0);
|
||||
std::generate_n(out, count, [&] {
|
||||
const btVector3 shift(distribution(random), distribution(random), distribution(random));
|
||||
return RecastMesh::Water {1, btTransform(btMatrix3x3::getIdentity(), shift)};
|
||||
return CellWater{ generateVec2i(1000, random), Water{ ESM::Land::REAL_SIZE, distribution(random) } };
|
||||
});
|
||||
}
|
||||
|
||||
template <typename OutputIterator, typename Random>
|
||||
void generateOffMeshConnection(OutputIterator out, std::size_t count, Random& random)
|
||||
template <class Random>
|
||||
Mesh generateMesh(std::size_t triangles, Random& random)
|
||||
{
|
||||
std::uniform_real_distribution<btScalar> distribution(0.0, 1.0);
|
||||
std::generate_n(out, count, [&] {
|
||||
const osg::Vec3f start(distribution(random), distribution(random), distribution(random));
|
||||
const osg::Vec3f end(distribution(random), distribution(random), distribution(random));
|
||||
return OffMeshConnection {start, end, generateAreaType(random)};
|
||||
});
|
||||
std::uniform_real_distribution<float> distribution(0.0, 1.0);
|
||||
std::vector<float> vertices;
|
||||
std::vector<int> indices;
|
||||
std::vector<AreaType> areaTypes;
|
||||
if (distribution(random) < 0.939)
|
||||
{
|
||||
generateVertices(std::back_inserter(vertices), triangles * 2.467, random);
|
||||
generateIndices(std::back_inserter(indices), static_cast<int>(vertices.size() / 3) - 1,
|
||||
vertices.size() * 1.279, random);
|
||||
generateAreaTypes(std::back_inserter(areaTypes), indices.size() / 3, random);
|
||||
}
|
||||
return Mesh(std::move(indices), std::move(vertices), std::move(areaTypes));
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
Heightfield generateHeightfield(Random& random)
|
||||
{
|
||||
std::uniform_real_distribution<float> distribution(0.0, 1.0);
|
||||
Heightfield result;
|
||||
result.mCellPosition = generateVec2i(1000, random);
|
||||
result.mCellSize = ESM::Land::REAL_SIZE;
|
||||
result.mMinHeight = distribution(random);
|
||||
result.mMaxHeight = result.mMinHeight + 1.0;
|
||||
result.mLength = static_cast<std::uint8_t>(ESM::Land::LAND_SIZE);
|
||||
std::generate_n(
|
||||
std::back_inserter(result.mHeights), ESM::Land::LAND_NUM_VERTS, [&] { return distribution(random); });
|
||||
result.mOriginalSize = ESM::Land::LAND_SIZE;
|
||||
result.mMinX = 0;
|
||||
result.mMinY = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
FlatHeightfield generateFlatHeightfield(Random& random)
|
||||
{
|
||||
std::uniform_real_distribution<float> distribution(0.0, 1.0);
|
||||
FlatHeightfield result;
|
||||
result.mCellPosition = generateVec2i(1000, random);
|
||||
result.mCellSize = ESM::Land::REAL_SIZE;
|
||||
result.mHeight = distribution(random);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
Key generateKey(std::size_t triangles, Random& random)
|
||||
{
|
||||
const CollisionShapeType agentShapeType = CollisionShapeType::Aabb;
|
||||
const osg::Vec3f agentHalfExtents = generateAgentHalfExtents(0.5, 1.5, random);
|
||||
const TilePosition tilePosition = generateTilePosition(10000, random);
|
||||
const std::size_t generation = std::uniform_int_distribution<std::size_t>(0, 100)(random);
|
||||
const std::size_t revision = std::uniform_int_distribution<std::size_t>(0, 10000)(random);
|
||||
std::vector<float> vertices;
|
||||
generateVertices(std::back_inserter(vertices), triangles * 1.98, random);
|
||||
std::vector<int> indices;
|
||||
generateIndices(std::back_inserter(indices), static_cast<int>(vertices.size() / 3) - 1, vertices.size() * 1.53, random);
|
||||
std::vector<AreaType> areaTypes;
|
||||
generateAreaTypes(std::back_inserter(areaTypes), indices.size() / 3, random);
|
||||
std::vector<RecastMesh::Water> water;
|
||||
generateWater(std::back_inserter(water), 2, random);
|
||||
RecastMesh recastMesh(generation, revision, std::move(indices), std::move(vertices),
|
||||
std::move(areaTypes), std::move(water));
|
||||
std::vector<OffMeshConnection> offMeshConnections;
|
||||
generateOffMeshConnection(std::back_inserter(offMeshConnections), 300, random);
|
||||
return Key {agentHalfExtents, tilePosition, std::move(recastMesh), std::move(offMeshConnections)};
|
||||
const TilePosition tilePosition = generateVec2i(10000, random);
|
||||
const Version version{
|
||||
.mGeneration = std::uniform_int_distribution<std::size_t>(0, 100)(random),
|
||||
.mRevision = std::uniform_int_distribution<std::size_t>(0, 10000)(random),
|
||||
};
|
||||
Mesh mesh = generateMesh(triangles, random);
|
||||
std::vector<CellWater> water;
|
||||
generateWater(std::back_inserter(water), 1, random);
|
||||
RecastMesh recastMesh(version, std::move(mesh), std::move(water), { generateHeightfield(random) },
|
||||
{ generateFlatHeightfield(random) }, {});
|
||||
return Key{ AgentBounds{ agentShapeType, agentHalfExtents }, tilePosition, std::move(recastMesh) };
|
||||
}
|
||||
|
||||
constexpr std::size_t trianglesPerTile = 310;
|
||||
constexpr std::size_t trianglesPerTile = 239;
|
||||
|
||||
template <typename OutputIterator, typename Random>
|
||||
void generateKeys(OutputIterator out, std::size_t count, Random& random)
|
||||
|
@ -137,7 +172,7 @@ namespace
|
|||
while (true)
|
||||
{
|
||||
Key key = generateKey(trianglesPerTile, random);
|
||||
cache.set(key.mAgentHalfExtents, key.mTilePosition, key.mRecastMesh, key.mOffMeshConnections, NavMeshData());
|
||||
cache.set(key.mAgentBounds, key.mTilePosition, key.mRecastMesh, std::make_unique<PreparedNavMeshData>());
|
||||
*out++ = std::move(key);
|
||||
const std::size_t newSize = cache.getStats().mNavMeshCacheSize;
|
||||
if (size >= newSize)
|
||||
|
@ -156,22 +191,53 @@ namespace
|
|||
generateKeys(std::back_inserter(keys), keys.size() * (100 - hitPercentage) / 100, random);
|
||||
std::size_t n = 0;
|
||||
|
||||
while (state.KeepRunning())
|
||||
for (auto _ : state)
|
||||
{
|
||||
const auto& key = keys[n++ % keys.size()];
|
||||
const auto result = cache.get(key.mAgentHalfExtents, key.mTilePosition, key.mRecastMesh, key.mOffMeshConnections);
|
||||
const auto result = cache.get(key.mAgentBounds, key.mTilePosition, key.mRecastMesh);
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto getFromFilledCache_1m_100hit = getFromFilledCache<1 * 1024 * 1024, 100>;
|
||||
constexpr auto getFromFilledCache_4m_100hit = getFromFilledCache<4 * 1024 * 1024, 100>;
|
||||
constexpr auto getFromFilledCache_16m_100hit = getFromFilledCache<16 * 1024 * 1024, 100>;
|
||||
constexpr auto getFromFilledCache_64m_100hit = getFromFilledCache<64 * 1024 * 1024, 100>;
|
||||
constexpr auto getFromFilledCache_1m_70hit = getFromFilledCache<1 * 1024 * 1024, 70>;
|
||||
constexpr auto getFromFilledCache_4m_70hit = getFromFilledCache<4 * 1024 * 1024, 70>;
|
||||
constexpr auto getFromFilledCache_16m_70hit = getFromFilledCache<16 * 1024 * 1024, 70>;
|
||||
constexpr auto getFromFilledCache_64m_70hit = getFromFilledCache<64 * 1024 * 1024, 70>;
|
||||
void getFromFilledCache_1m_100hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<1 * 1024 * 1024, 100>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_4m_100hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<4 * 1024 * 1024, 100>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_16m_100hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<16 * 1024 * 1024, 100>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_64m_100hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<64 * 1024 * 1024, 100>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_1m_70hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<1 * 1024 * 1024, 70>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_4m_70hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<4 * 1024 * 1024, 70>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_16m_70hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<16 * 1024 * 1024, 70>(state);
|
||||
}
|
||||
|
||||
void getFromFilledCache_64m_70hit(benchmark::State& state)
|
||||
{
|
||||
getFromFilledCache<64 * 1024 * 1024, 70>(state);
|
||||
}
|
||||
|
||||
template <std::size_t maxCacheSize>
|
||||
void setToBoundedNonEmptyCache(benchmark::State& state)
|
||||
|
@ -187,15 +253,31 @@ namespace
|
|||
while (state.KeepRunning())
|
||||
{
|
||||
const auto& key = keys[n++ % keys.size()];
|
||||
const auto result = cache.set(key.mAgentHalfExtents, key.mTilePosition, key.mRecastMesh, key.mOffMeshConnections, NavMeshData());
|
||||
const auto result = cache.set(
|
||||
key.mAgentBounds, key.mTilePosition, key.mRecastMesh, std::make_unique<PreparedNavMeshData>());
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto setToBoundedNonEmptyCache_1m = setToBoundedNonEmptyCache<1 * 1024 * 1024>;
|
||||
constexpr auto setToBoundedNonEmptyCache_4m = setToBoundedNonEmptyCache<4 * 1024 * 1024>;
|
||||
constexpr auto setToBoundedNonEmptyCache_16m = setToBoundedNonEmptyCache<16 * 1024 * 1024>;
|
||||
constexpr auto setToBoundedNonEmptyCache_64m = setToBoundedNonEmptyCache<64 * 1024 * 1024>;
|
||||
void setToBoundedNonEmptyCache_1m(benchmark::State& state)
|
||||
{
|
||||
setToBoundedNonEmptyCache<1 * 1024 * 1024>(state);
|
||||
}
|
||||
|
||||
void setToBoundedNonEmptyCache_4m(benchmark::State& state)
|
||||
{
|
||||
setToBoundedNonEmptyCache<4 * 1024 * 1024>(state);
|
||||
}
|
||||
|
||||
void setToBoundedNonEmptyCache_16m(benchmark::State& state)
|
||||
{
|
||||
setToBoundedNonEmptyCache<16 * 1024 * 1024>(state);
|
||||
}
|
||||
|
||||
void setToBoundedNonEmptyCache_64m(benchmark::State& state)
|
||||
{
|
||||
setToBoundedNonEmptyCache<64 * 1024 * 1024>(state);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
BENCHMARK(getFromFilledCache_1m_100hit);
|
||||
|
|
15
apps/benchmarks/esm/CMakeLists.txt
Normal file
15
apps/benchmarks/esm/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
openmw_add_executable(openmw_esm_refid_benchmark benchrefid.cpp)
|
||||
target_link_libraries(openmw_esm_refid_benchmark benchmark::benchmark components)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(openmw_esm_refid_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(openmw_esm_refid_benchmark PRIVATE <algorithm>)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
target_compile_options(openmw_esm_refid_benchmark PRIVATE --coverage)
|
||||
target_link_libraries(openmw_esm_refid_benchmark gcov)
|
||||
endif()
|
249
apps/benchmarks/esm/benchrefid.cpp
Normal file
249
apps/benchmarks/esm/benchrefid.cpp
Normal file
|
@ -0,0 +1,249 @@
|
|||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "components/esm/refid.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr std::size_t refIdsCount = 64 * 1024;
|
||||
|
||||
template <class Random>
|
||||
std::string generateText(std::size_t size, Random& random)
|
||||
{
|
||||
std::uniform_int_distribution<int> distribution('A', 'z');
|
||||
std::string result;
|
||||
result.reserve(size);
|
||||
std::generate_n(std::back_inserter(result), size, [&] { return distribution(random); });
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
std::vector<ESM::RefId> generateStringRefIds(std::size_t size, Random& random)
|
||||
{
|
||||
std::vector<ESM::RefId> result;
|
||||
result.reserve(refIdsCount);
|
||||
std::generate_n(
|
||||
std::back_inserter(result), refIdsCount, [&] { return ESM::StringRefId(generateText(size, random)); });
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Serialize>
|
||||
std::vector<std::string> generateSerializedRefIds(const std::vector<ESM::RefId>& generated, Serialize&& serialize)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
result.reserve(generated.size());
|
||||
for (ESM::RefId refId : generated)
|
||||
result.push_back(serialize(refId));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random, class Serialize>
|
||||
std::vector<std::string> generateSerializedStringRefIds(std::size_t size, Random& random, Serialize&& serialize)
|
||||
{
|
||||
return generateSerializedRefIds(generateStringRefIds(size, random), serialize);
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
std::vector<ESM::RefId> generateIndexRefIds(Random& random)
|
||||
{
|
||||
std::vector<ESM::RefId> result;
|
||||
result.reserve(refIdsCount);
|
||||
std::uniform_int_distribution<std::uint32_t> distribution(0, std::numeric_limits<std::uint32_t>::max());
|
||||
std::generate_n(std::back_inserter(result), refIdsCount,
|
||||
[&] { return ESM::IndexRefId(ESM::REC_ARMO, distribution(random)); });
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random, class Serialize>
|
||||
std::vector<std::string> generateSerializedIndexRefIds(Random& random, Serialize&& serialize)
|
||||
{
|
||||
return generateSerializedRefIds(generateIndexRefIds(random), serialize);
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
std::vector<ESM::RefId> generateGeneratedRefIds(Random& random)
|
||||
{
|
||||
std::vector<ESM::RefId> result;
|
||||
result.reserve(refIdsCount);
|
||||
std::uniform_int_distribution<std::uint64_t> distribution(0, std::numeric_limits<std::uint64_t>::max());
|
||||
std::generate_n(
|
||||
std::back_inserter(result), refIdsCount, [&] { return ESM::GeneratedRefId(distribution(random)); });
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random, class Serialize>
|
||||
std::vector<std::string> generateSerializedGeneratedRefIds(Random& random, Serialize&& serialize)
|
||||
{
|
||||
return generateSerializedRefIds(generateGeneratedRefIds(random), serialize);
|
||||
}
|
||||
|
||||
template <class Random>
|
||||
std::vector<ESM::RefId> generateESM3ExteriorCellRefIds(Random& random)
|
||||
{
|
||||
std::vector<ESM::RefId> result;
|
||||
result.reserve(refIdsCount);
|
||||
std::uniform_int_distribution<std::int32_t> distribution(-100, 100);
|
||||
std::generate_n(std::back_inserter(result), refIdsCount,
|
||||
[&] { return ESM::ESM3ExteriorCellRefId(distribution(random), distribution(random)); });
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Random, class Serialize>
|
||||
std::vector<std::string> generateSerializedESM3ExteriorCellRefIds(Random& random, Serialize&& serialize)
|
||||
{
|
||||
return generateSerializedRefIds(generateESM3ExteriorCellRefIds(random), serialize);
|
||||
}
|
||||
|
||||
void serializeRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<ESM::RefId> refIds = generateStringRefIds(state.range(0), random);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(refIds[i].serialize());
|
||||
if (++i >= refIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<std::string> serializedRefIds
|
||||
= generateSerializedStringRefIds(state.range(0), random, [](ESM::RefId v) { return v.serialize(); });
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(ESM::RefId::deserialize(serializedRefIds[i]));
|
||||
if (++i >= serializedRefIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void serializeTextStringRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<ESM::RefId> refIds = generateStringRefIds(state.range(0), random);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(refIds[i].serializeText());
|
||||
if (++i >= refIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeTextStringRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<std::string> serializedRefIds
|
||||
= generateSerializedStringRefIds(state.range(0), random, [](ESM::RefId v) { return v.serializeText(); });
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(ESM::RefId::deserializeText(serializedRefIds[i]));
|
||||
if (++i >= serializedRefIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void serializeTextGeneratedRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<ESM::RefId> refIds = generateGeneratedRefIds(random);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(refIds[i].serializeText());
|
||||
if (++i >= refIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeTextGeneratedRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<std::string> serializedRefIds
|
||||
= generateSerializedGeneratedRefIds(random, [](ESM::RefId v) { return v.serializeText(); });
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(ESM::RefId::deserializeText(serializedRefIds[i]));
|
||||
if (++i >= serializedRefIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void serializeTextIndexRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<ESM::RefId> refIds = generateIndexRefIds(random);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(refIds[i].serializeText());
|
||||
if (++i >= refIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeTextIndexRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<std::string> serializedRefIds
|
||||
= generateSerializedIndexRefIds(random, [](ESM::RefId v) { return v.serializeText(); });
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(ESM::RefId::deserializeText(serializedRefIds[i]));
|
||||
if (++i >= serializedRefIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void serializeTextESM3ExteriorCellRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<ESM::RefId> refIds = generateESM3ExteriorCellRefIds(random);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(refIds[i].serializeText());
|
||||
if (++i >= refIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeTextESM3ExteriorCellRefId(benchmark::State& state)
|
||||
{
|
||||
std::minstd_rand random;
|
||||
std::vector<std::string> serializedRefIds
|
||||
= generateSerializedESM3ExteriorCellRefIds(random, [](ESM::RefId v) { return v.serializeText(); });
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(ESM::RefId::deserializeText(serializedRefIds[i]));
|
||||
if (++i >= serializedRefIds.size())
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(serializeRefId)->RangeMultiplier(4)->Range(8, 64);
|
||||
BENCHMARK(deserializeRefId)->RangeMultiplier(4)->Range(8, 64);
|
||||
BENCHMARK(serializeTextStringRefId)->RangeMultiplier(4)->Range(8, 64);
|
||||
BENCHMARK(deserializeTextStringRefId)->RangeMultiplier(4)->Range(8, 64);
|
||||
BENCHMARK(serializeTextGeneratedRefId);
|
||||
BENCHMARK(deserializeTextGeneratedRefId);
|
||||
BENCHMARK(serializeTextIndexRefId);
|
||||
BENCHMARK(deserializeTextIndexRefId);
|
||||
BENCHMARK(serializeTextESM3ExteriorCellRefId);
|
||||
BENCHMARK(deserializeTextESM3ExteriorCellRefId);
|
||||
|
||||
BENCHMARK_MAIN();
|
18
apps/benchmarks/settings/CMakeLists.txt
Normal file
18
apps/benchmarks/settings/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
openmw_add_executable(openmw_settings_access_benchmark access.cpp)
|
||||
target_link_libraries(openmw_settings_access_benchmark benchmark::benchmark components)
|
||||
|
||||
target_compile_definitions(openmw_settings_access_benchmark
|
||||
PRIVATE OPENMW_PROJECT_SOURCE_DIR=u8"${PROJECT_SOURCE_DIR}")
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(openmw_settings_access_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(openmw_settings_access_benchmark PRIVATE <algorithm>)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
target_compile_options(openmw_settings_access_benchmark PRIVATE --coverage)
|
||||
target_link_libraries(openmw_settings_access_benchmark gcov)
|
||||
endif()
|
162
apps/benchmarks/settings/access.cpp
Normal file
162
apps/benchmarks/settings/access.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "components/misc/strings/conversion.hpp"
|
||||
#include "components/settings/parser.hpp"
|
||||
#include "components/settings/settings.hpp"
|
||||
#include "components/settings/values.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
void settingsManager(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::Manager::getFloat("sky blending start", "Fog"));
|
||||
}
|
||||
}
|
||||
|
||||
void settingsManager2(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::Manager::getFloat("near clip", "Camera"));
|
||||
benchmark::DoNotOptimize(Settings::Manager::getBool("transparent postpass", "Post Processing"));
|
||||
}
|
||||
}
|
||||
|
||||
void settingsManager3(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::Manager::getFloat("near clip", "Camera"));
|
||||
benchmark::DoNotOptimize(Settings::Manager::getBool("transparent postpass", "Post Processing"));
|
||||
benchmark::DoNotOptimize(Settings::Manager::getInt("reflection detail", "Water"));
|
||||
}
|
||||
}
|
||||
|
||||
void localStatic(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
static const float v = Settings::Manager::getFloat("sky blending start", "Fog");
|
||||
benchmark::DoNotOptimize(v);
|
||||
}
|
||||
}
|
||||
|
||||
void localStatic2(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
static const float v1 = Settings::Manager::getFloat("near clip", "Camera");
|
||||
static const bool v2 = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
||||
benchmark::DoNotOptimize(v1);
|
||||
benchmark::DoNotOptimize(v2);
|
||||
}
|
||||
}
|
||||
|
||||
void localStatic3(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
static const float v1 = Settings::Manager::getFloat("near clip", "Camera");
|
||||
static const bool v2 = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
||||
static const int v3 = Settings::Manager::getInt("reflection detail", "Water");
|
||||
benchmark::DoNotOptimize(v1);
|
||||
benchmark::DoNotOptimize(v2);
|
||||
benchmark::DoNotOptimize(v3);
|
||||
}
|
||||
}
|
||||
|
||||
void settingsStorage(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::fog().mSkyBlendingStart.get());
|
||||
}
|
||||
}
|
||||
|
||||
void settingsStorage2(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::postProcessing().mTransparentPostpass.get());
|
||||
benchmark::DoNotOptimize(Settings::camera().mNearClip.get());
|
||||
}
|
||||
}
|
||||
|
||||
void settingsStorage3(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::postProcessing().mTransparentPostpass.get());
|
||||
benchmark::DoNotOptimize(Settings::camera().mNearClip.get());
|
||||
benchmark::DoNotOptimize(Settings::water().mReflectionDetail.get());
|
||||
}
|
||||
}
|
||||
|
||||
void settingsStorageGet(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::get<float>("Fog", "sky blending start"));
|
||||
}
|
||||
}
|
||||
|
||||
void settingsStorageGet2(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::get<bool>("Post Processing", "transparent postpass"));
|
||||
benchmark::DoNotOptimize(Settings::get<float>("Camera", "near clip"));
|
||||
}
|
||||
}
|
||||
|
||||
void settingsStorageGet3(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(Settings::get<bool>("Post Processing", "transparent postpass"));
|
||||
benchmark::DoNotOptimize(Settings::get<float>("Camera", "near clip"));
|
||||
benchmark::DoNotOptimize(Settings::get<int>("Water", "reflection detail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(settingsManager);
|
||||
BENCHMARK(localStatic);
|
||||
BENCHMARK(settingsStorage);
|
||||
BENCHMARK(settingsStorageGet);
|
||||
|
||||
BENCHMARK(settingsManager2);
|
||||
BENCHMARK(localStatic2);
|
||||
BENCHMARK(settingsStorage2);
|
||||
BENCHMARK(settingsStorageGet2);
|
||||
|
||||
BENCHMARK(settingsManager3);
|
||||
BENCHMARK(localStatic3);
|
||||
BENCHMARK(settingsStorage3);
|
||||
BENCHMARK(settingsStorageGet3);
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const std::filesystem::path settingsDefaultPath = std::filesystem::path{ OPENMW_PROJECT_SOURCE_DIR } / "files"
|
||||
/ Misc::StringUtils::stringToU8String("settings-default.cfg");
|
||||
|
||||
Settings::SettingsFileParser parser;
|
||||
parser.loadSettingsFile(settingsDefaultPath, Settings::Manager::mDefaultSettings);
|
||||
|
||||
Settings::StaticValues::initDefaults();
|
||||
|
||||
Settings::Manager::mUserSettings = Settings::Manager::mDefaultSettings;
|
||||
Settings::Manager::mUserSettings.erase({ "Camera", "near clip" });
|
||||
Settings::Manager::mUserSettings.erase({ "Post Processing", "transparent postpass" });
|
||||
Settings::Manager::mUserSettings.erase({ "Water", "reflection detail" });
|
||||
|
||||
Settings::StaticValues::init();
|
||||
|
||||
benchmark::Initialize(&argc, argv);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
benchmark::Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,20 +1,27 @@
|
|||
set(BSATOOL
|
||||
bsatool.cpp
|
||||
bsatool.cpp
|
||||
)
|
||||
source_group(apps\\bsatool FILES ${BSATOOL})
|
||||
|
||||
# Main executable
|
||||
openmw_add_executable(bsatool
|
||||
${BSATOOL}
|
||||
${BSATOOL}
|
||||
)
|
||||
|
||||
target_link_libraries(bsatool
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(bsatool gcov)
|
||||
target_compile_options(bsatool PRIVATE --coverage)
|
||||
target_link_libraries(bsatool gcov)
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(bsatool PRIVATE
|
||||
<filesystem>
|
||||
<fstream>
|
||||
<vector>
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -1,63 +1,69 @@
|
|||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <components/bsa/ba2dx10file.hpp>
|
||||
#include <components/bsa/ba2gnrlfile.hpp>
|
||||
#include <components/bsa/compressedbsafile.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/files/conversion.hpp>
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
#include <components/misc/strings/conversion.hpp>
|
||||
|
||||
#define BSATOOL_VERSION 1.1
|
||||
|
||||
// Create local aliases for brevity
|
||||
namespace bpo = boost::program_options;
|
||||
namespace bfs = boost::filesystem;
|
||||
|
||||
struct Arguments
|
||||
{
|
||||
std::string mode;
|
||||
std::string filename;
|
||||
std::string extractfile;
|
||||
std::string addfile;
|
||||
std::string outdir;
|
||||
std::filesystem::path filename;
|
||||
std::filesystem::path extractfile;
|
||||
std::filesystem::path addfile;
|
||||
std::filesystem::path outdir;
|
||||
|
||||
bool longformat;
|
||||
bool fullpath;
|
||||
};
|
||||
|
||||
bool parseOptions (int argc, char** argv, Arguments &info)
|
||||
bool parseOptions(int argc, char** argv, Arguments& info)
|
||||
{
|
||||
bpo::options_description desc("Inspect and extract files from Bethesda BSA archives\n\n"
|
||||
"Usages:\n"
|
||||
" bsatool list [-l] archivefile\n"
|
||||
" List the files presents in the input archive.\n\n"
|
||||
" bsatool extract [-f] archivefile [file_to_extract] [output_directory]\n"
|
||||
" Extract a file from the input archive.\n\n"
|
||||
" bsatool extractall archivefile [output_directory]\n"
|
||||
" Extract all files from the input archive.\n\n"
|
||||
" bsatool add [-a] archivefile file_to_add\n"
|
||||
" Add a file to the input archive.\n\n"
|
||||
" bsatool create [-c] archivefile\n"
|
||||
" Create an archive.\n\n"
|
||||
"Allowed options");
|
||||
bpo::options_description desc(R"(Inspect and extract files from Bethesda BSA archives
|
||||
|
||||
desc.add_options()
|
||||
("help,h", "print help message.")
|
||||
("version,v", "print version information and quit.")
|
||||
("long,l", "Include extra information in archive listing.")
|
||||
("full-path,f", "Create directory hierarchy on file extraction "
|
||||
"(always true for extractall).")
|
||||
;
|
||||
Usages:
|
||||
bsatool list [-l] archivefile\n
|
||||
List the files presents in the input archive.
|
||||
|
||||
bsatool extract [-f] archivefile [file_to_extract] [output_directory]
|
||||
Extract a file from the input archive.
|
||||
|
||||
bsatool extractall archivefile [output_directory]
|
||||
Extract all files from the input archive.
|
||||
|
||||
bsatool add [-a] archivefile file_to_add
|
||||
Add a file to the input archive.
|
||||
|
||||
bsatool create [-c] archivefile
|
||||
Create an archive.
|
||||
Allowed options)");
|
||||
|
||||
auto addOption = desc.add_options();
|
||||
addOption("help,h", "print help message.");
|
||||
addOption("version,v", "print version information and quit.");
|
||||
addOption("long,l", "Include extra information in archive listing.");
|
||||
addOption("full-path,f", "Create directory hierarchy on file extraction (always true for extractall).");
|
||||
|
||||
// input-file is hidden and used as a positional argument
|
||||
bpo::options_description hidden("Hidden Options");
|
||||
|
||||
hidden.add_options()
|
||||
( "mode,m", bpo::value<std::string>(), "bsatool mode")
|
||||
( "input-file,i", bpo::value< std::vector<std::string> >(), "input file")
|
||||
;
|
||||
auto addHiddenOption = hidden.add_options();
|
||||
addHiddenOption("mode,m", bpo::value<std::string>(), "bsatool mode");
|
||||
addHiddenOption("input-file,i", bpo::value<Files::MaybeQuotedPathContainer>(), "input file");
|
||||
|
||||
bpo::positional_options_description p;
|
||||
p.add("mode", 1).add("input-file", 3);
|
||||
|
@ -69,81 +75,82 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
|||
bpo::variables_map variables;
|
||||
try
|
||||
{
|
||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
|
||||
.options(all).positional(p).run();
|
||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).options(all).positional(p).run();
|
||||
bpo::store(valid_opts, variables);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
|
||||
<< desc << std::endl;
|
||||
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n" << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bpo::notify(variables);
|
||||
|
||||
if (variables.count ("help"))
|
||||
if (variables.count("help"))
|
||||
{
|
||||
std::cout << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (variables.count ("version"))
|
||||
if (variables.count("version"))
|
||||
{
|
||||
std::cout << "BSATool version " << BSATOOL_VERSION << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!variables.count("mode"))
|
||||
{
|
||||
std::cout << "ERROR: no mode specified!\n\n"
|
||||
<< desc << std::endl;
|
||||
std::cout << "ERROR: no mode specified!\n\n" << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
info.mode = variables["mode"].as<std::string>();
|
||||
if (!(info.mode == "list" || info.mode == "extract" || info.mode == "extractall" || info.mode == "add" || info.mode == "create"))
|
||||
if (!(info.mode == "list" || info.mode == "extract" || info.mode == "extractall" || info.mode == "add"
|
||||
|| info.mode == "create"))
|
||||
{
|
||||
std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"\n\n"
|
||||
<< desc << std::endl;
|
||||
std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"\n\n" << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!variables.count("input-file"))
|
||||
{
|
||||
std::cout << "\nERROR: missing BSA archive\n\n"
|
||||
<< desc << std::endl;
|
||||
std::cout << "\nERROR: missing BSA archive\n\n" << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
info.filename = variables["input-file"].as< std::vector<std::string> >()[0];
|
||||
auto inputFiles = variables["input-file"].as<Files::MaybeQuotedPathContainer>();
|
||||
|
||||
info.filename = inputFiles[0].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26
|
||||
// due to implementation bugs.
|
||||
|
||||
// Default output to the working directory
|
||||
info.outdir = ".";
|
||||
info.outdir = std::filesystem::current_path();
|
||||
|
||||
if (info.mode == "extract")
|
||||
{
|
||||
if (variables["input-file"].as< std::vector<std::string> >().size() < 2)
|
||||
if (inputFiles.size() < 2)
|
||||
{
|
||||
std::cout << "\nERROR: file to extract unspecified\n\n"
|
||||
<< desc << std::endl;
|
||||
std::cout << "\nERROR: file to extract unspecified\n\n" << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||
info.extractfile = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||
if (variables["input-file"].as< std::vector<std::string> >().size() > 2)
|
||||
info.outdir = variables["input-file"].as< std::vector<std::string> >()[2];
|
||||
if (inputFiles.size() > 1)
|
||||
info.extractfile = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||
// MSVC 14.26 due to implementation bugs.
|
||||
if (inputFiles.size() > 2)
|
||||
info.outdir = inputFiles[2].u8string(); // This call to u8string is redundant, but required to build on
|
||||
// MSVC 14.26 due to implementation bugs.
|
||||
}
|
||||
else if (info.mode == "add")
|
||||
{
|
||||
if (variables["input-file"].as< std::vector<std::string> >().size() < 1)
|
||||
if (inputFiles.empty())
|
||||
{
|
||||
std::cout << "\nERROR: file to add unspecified\n\n"
|
||||
<< desc << std::endl;
|
||||
std::cout << "\nERROR: file to add unspecified\n\n" << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||
info.addfile = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||
if (inputFiles.size() > 1)
|
||||
info.addfile = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||
// MSVC 14.26 due to implementation bugs.
|
||||
}
|
||||
else if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||
info.outdir = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||
else if (inputFiles.size() > 1)
|
||||
info.outdir = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||
// MSVC 14.26 due to implementation bugs.
|
||||
|
||||
info.longformat = variables.count("long") != 0;
|
||||
info.fullpath = variables.count("full-path") != 0;
|
||||
|
@ -151,65 +158,14 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
|||
return true;
|
||||
}
|
||||
|
||||
int list(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info);
|
||||
int extract(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info);
|
||||
int extractAll(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info);
|
||||
int add(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
Arguments info;
|
||||
if(!parseOptions (argc, argv, info))
|
||||
return 1;
|
||||
|
||||
// Open file
|
||||
std::unique_ptr<Bsa::BSAFile> bsa;
|
||||
|
||||
Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(info.filename);
|
||||
|
||||
if (bsaVersion == Bsa::BSAVER_COMPRESSED)
|
||||
bsa = std::make_unique<Bsa::CompressedBSAFile>(Bsa::CompressedBSAFile());
|
||||
else
|
||||
bsa = std::make_unique<Bsa::BSAFile>(Bsa::BSAFile());
|
||||
|
||||
if (info.mode == "create")
|
||||
{
|
||||
bsa->open(info.filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bsa->open(info.filename);
|
||||
|
||||
if (info.mode == "list")
|
||||
return list(bsa, info);
|
||||
else if (info.mode == "extract")
|
||||
return extract(bsa, info);
|
||||
else if (info.mode == "extractall")
|
||||
return extractAll(bsa, info);
|
||||
else if (info.mode == "add")
|
||||
return add(bsa, info);
|
||||
else
|
||||
{
|
||||
std::cout << "Unsupported mode. That is not supposed to happen." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "ERROR reading BSA archive\nDetails:\n" << e.what() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int list(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
||||
template <typename File>
|
||||
int list(std::unique_ptr<File>& bsa, Arguments& info)
|
||||
{
|
||||
// List all files
|
||||
const Bsa::BSAFile::FileList &files = bsa->getList();
|
||||
const auto& files = bsa->getList();
|
||||
for (const auto& file : files)
|
||||
{
|
||||
if(info.longformat)
|
||||
if (info.longformat)
|
||||
{
|
||||
// Long format
|
||||
std::ios::fmtflags f(std::cout.flags());
|
||||
|
@ -225,48 +181,57 @@ int list(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int extract(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
||||
template <typename File>
|
||||
int extract(std::unique_ptr<File>& bsa, Arguments& info)
|
||||
{
|
||||
std::string archivePath = info.extractfile;
|
||||
Misc::StringUtils::replaceAll(archivePath, "/", "\\");
|
||||
auto archivePath = info.extractfile.u8string();
|
||||
Misc::StringUtils::replaceAll(archivePath, u8"/", u8"\\");
|
||||
|
||||
std::string extractPath = info.extractfile;
|
||||
Misc::StringUtils::replaceAll(extractPath, "\\", "/");
|
||||
auto extractPath = info.extractfile.u8string();
|
||||
Misc::StringUtils::replaceAll(extractPath, u8"\\", u8"/");
|
||||
|
||||
if (!bsa->exists(archivePath.c_str()))
|
||||
Files::IStreamPtr stream;
|
||||
// Get a stream for the file to extract
|
||||
for (auto it = bsa->getList().rbegin(); it != bsa->getList().rend(); ++it)
|
||||
{
|
||||
std::cout << "ERROR: file '" << archivePath << "' not found\n";
|
||||
std::cout << "In archive: " << info.filename << std::endl;
|
||||
if (Misc::StringUtils::ciEqual(Misc::StringUtils::stringToU8String(it->name()), archivePath))
|
||||
{
|
||||
stream = bsa->getFile(&*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!stream)
|
||||
{
|
||||
std::cout << "ERROR: file '" << Misc::StringUtils::u8StringToString(archivePath) << "' not found\n";
|
||||
std::cout << "In archive: " << Files::pathToUnicodeString(info.filename) << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Get the target path (the path the file will be extracted to)
|
||||
bfs::path relPath (extractPath);
|
||||
bfs::path outdir (info.outdir);
|
||||
std::filesystem::path relPath(extractPath);
|
||||
|
||||
bfs::path target;
|
||||
std::filesystem::path target;
|
||||
if (info.fullpath)
|
||||
target = outdir / relPath;
|
||||
target = info.outdir / relPath;
|
||||
else
|
||||
target = outdir / relPath.filename();
|
||||
target = info.outdir / relPath.filename();
|
||||
|
||||
// Create the directory hierarchy
|
||||
bfs::create_directories(target.parent_path());
|
||||
std::filesystem::create_directories(target.parent_path());
|
||||
|
||||
bfs::file_status s = bfs::status(target.parent_path());
|
||||
if (!bfs::is_directory(s))
|
||||
std::filesystem::file_status s = std::filesystem::status(target.parent_path());
|
||||
if (!std::filesystem::is_directory(s))
|
||||
{
|
||||
std::cout << "ERROR: " << target.parent_path() << " is not a directory." << std::endl;
|
||||
std::cout << "ERROR: " << Files::pathToUnicodeString(target.parent_path()) << " is not a directory."
|
||||
<< std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Get a stream for the file to extract
|
||||
Files::IStreamPtr stream = bsa->getFile(archivePath.c_str());
|
||||
|
||||
bfs::ofstream out(target, std::ios::binary);
|
||||
std::ofstream out(target, std::ios::binary);
|
||||
|
||||
// Write the file to disk
|
||||
std::cout << "Extracting " << info.extractfile << " to " << target << std::endl;
|
||||
std::cout << "Extracting " << Files::pathToUnicodeString(info.extractfile) << " to "
|
||||
<< Files::pathToUnicodeString(target) << std::endl;
|
||||
|
||||
out << stream->rdbuf();
|
||||
out.close();
|
||||
|
@ -274,34 +239,34 @@ int extract(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int extractAll(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
||||
template <typename File>
|
||||
int extractAll(std::unique_ptr<File>& bsa, Arguments& info)
|
||||
{
|
||||
for (const auto &file : bsa->getList())
|
||||
for (const auto& file : bsa->getList())
|
||||
{
|
||||
std::string extractPath(file.name());
|
||||
Misc::StringUtils::replaceAll(extractPath, "\\", "/");
|
||||
|
||||
// Get the target path (the path the file will be extracted to)
|
||||
bfs::path target (info.outdir);
|
||||
target /= extractPath;
|
||||
auto target = info.outdir;
|
||||
target /= Misc::StringUtils::stringToU8String(extractPath);
|
||||
|
||||
// Create the directory hierarchy
|
||||
bfs::create_directories(target.parent_path());
|
||||
std::filesystem::create_directories(target.parent_path());
|
||||
|
||||
bfs::file_status s = bfs::status(target.parent_path());
|
||||
if (!bfs::is_directory(s))
|
||||
std::filesystem::file_status s = std::filesystem::status(target.parent_path());
|
||||
if (!std::filesystem::is_directory(s))
|
||||
{
|
||||
std::cout << "ERROR: " << target.parent_path() << " is not a directory." << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Get a stream for the file to extract
|
||||
// (inefficient because getFile iter on the list again)
|
||||
Files::IStreamPtr data = bsa->getFile(file.name());
|
||||
bfs::ofstream out(target, std::ios::binary);
|
||||
Files::IStreamPtr data = bsa->getFile(&file);
|
||||
std::ofstream out(target, std::ios::binary);
|
||||
|
||||
// Write the file to disk
|
||||
std::cout << "Extracting " << target << std::endl;
|
||||
std::cout << "Extracting " << Files::pathToUnicodeString(target) << std::endl;
|
||||
out << data->rdbuf();
|
||||
out.close();
|
||||
}
|
||||
|
@ -309,10 +274,71 @@ int extractAll(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int add(std::unique_ptr<Bsa::BSAFile>& bsa, Arguments& info)
|
||||
template <typename File>
|
||||
int add(std::unique_ptr<File>& bsa, Arguments& info)
|
||||
{
|
||||
boost::filesystem::fstream stream(info.addfile, std::ios_base::binary | std::ios_base::out | std::ios_base::in);
|
||||
bsa->addFile(info.addfile, stream);
|
||||
std::fstream stream(info.addfile, std::ios_base::binary | std::ios_base::out | std::ios_base::in);
|
||||
bsa->addFile(Files::pathToUnicodeString(info.addfile), stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename File>
|
||||
int call(Arguments& info)
|
||||
{
|
||||
std::unique_ptr<File> bsa = std::make_unique<File>();
|
||||
if (info.mode == "create")
|
||||
{
|
||||
bsa->open(info.filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bsa->open(info.filename);
|
||||
|
||||
if (info.mode == "list")
|
||||
return list(bsa, info);
|
||||
else if (info.mode == "extract")
|
||||
return extract(bsa, info);
|
||||
else if (info.mode == "extractall")
|
||||
return extractAll(bsa, info);
|
||||
else if (info.mode == "add")
|
||||
return add(bsa, info);
|
||||
else
|
||||
{
|
||||
std::cout << "Unsupported mode. That is not supposed to happen." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
Arguments info;
|
||||
if (!parseOptions(argc, argv, info))
|
||||
return 1;
|
||||
|
||||
// Open file
|
||||
|
||||
Bsa::BsaVersion bsaVersion = Bsa::BSAFile::detectVersion(info.filename);
|
||||
|
||||
switch (bsaVersion)
|
||||
{
|
||||
case Bsa::BSAVER_COMPRESSED:
|
||||
return call<Bsa::CompressedBSAFile>(info);
|
||||
case Bsa::BSAVER_BA2_GNRL:
|
||||
return call<Bsa::BA2GNRLFile>(info);
|
||||
case Bsa::BSAVER_BA2_DX10:
|
||||
return call<Bsa::BA2DX10File>(info);
|
||||
case Bsa::BSAVER_UNCOMPRESSED:
|
||||
return call<Bsa::BSAFile>(info);
|
||||
default:
|
||||
throw std::runtime_error("Unrecognised BSA archive");
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "ERROR reading BSA archive\nDetails:\n" << e.what() << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
|
27
apps/bulletobjecttool/CMakeLists.txt
Normal file
27
apps/bulletobjecttool/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
set(BULLETMESHTOOL
|
||||
main.cpp
|
||||
)
|
||||
source_group(apps\\bulletobjecttool FILES ${BULLETMESHTOOL})
|
||||
|
||||
openmw_add_executable(openmw-bulletobjecttool ${BULLETMESHTOOL})
|
||||
|
||||
target_link_libraries(openmw-bulletobjecttool
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
target_compile_options(openmw-bulletobjecttool PRIVATE --coverage)
|
||||
target_link_libraries(openmw-bulletobjecttool gcov)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
install(TARGETS openmw-bulletobjecttool RUNTIME DESTINATION ".")
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(openmw-bulletobjecttool PRIVATE
|
||||
<string>
|
||||
<vector>
|
||||
)
|
||||
endif()
|
206
apps/bulletobjecttool/main.cpp
Normal file
206
apps/bulletobjecttool/main.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
#include <components/debug/debugging.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/esm3/readerscache.hpp>
|
||||
#include <components/esmloader/esmdata.hpp>
|
||||
#include <components/esmloader/load.hpp>
|
||||
#include <components/fallback/fallback.hpp>
|
||||
#include <components/fallback/validate.hpp>
|
||||
#include <components/files/collections.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/files/multidircollection.hpp>
|
||||
#include <components/misc/strings/conversion.hpp>
|
||||
#include <components/platform/platform.hpp>
|
||||
#include <components/resource/bulletshape.hpp>
|
||||
#include <components/resource/bulletshapemanager.hpp>
|
||||
#include <components/resource/foreachbulletobject.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
#include <components/resource/niffilemanager.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/version/version.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/registerarchives.hpp>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <charconv>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
using StringsVector = std::vector<std::string>;
|
||||
|
||||
constexpr std::string_view applicationName = "BulletObjectTool";
|
||||
|
||||
bpo::options_description makeOptionsDescription()
|
||||
{
|
||||
using Fallback::FallbackMap;
|
||||
|
||||
bpo::options_description result;
|
||||
auto addOption = result.add_options();
|
||||
addOption("help", "print help message");
|
||||
|
||||
addOption("version", "print version information and quit");
|
||||
|
||||
addOption("data",
|
||||
bpo::value<Files::MaybeQuotedPathContainer>()
|
||||
->default_value(Files::MaybeQuotedPathContainer(), "data")
|
||||
->multitoken()
|
||||
->composing(),
|
||||
"set data directories (later directories have higher priority)");
|
||||
|
||||
addOption("data-local",
|
||||
bpo::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(
|
||||
Files::MaybeQuotedPathContainer::value_type(), ""),
|
||||
"set local data directory (highest priority)");
|
||||
|
||||
addOption("fallback-archive",
|
||||
bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")->multitoken()->composing(),
|
||||
"set fallback BSA archives (later archives have higher priority)");
|
||||
|
||||
addOption("resources",
|
||||
bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"),
|
||||
"set resources directory");
|
||||
|
||||
addOption("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")->multitoken()->composing(),
|
||||
"content file(s): esm/esp, or omwgame/omwaddon/omwscripts");
|
||||
|
||||
addOption("encoding", bpo::value<std::string>()->default_value("win1252"),
|
||||
"Character encoding used in OpenMW game messages:\n"
|
||||
"\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, "
|
||||
"Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
|
||||
"\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
|
||||
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
||||
|
||||
addOption("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "")->multitoken()->composing(),
|
||||
"fallback values");
|
||||
|
||||
Files::ConfigurationManager::addCommonOptions(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct WriteArray
|
||||
{
|
||||
const float (&mValue)[3];
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, const WriteArray& value)
|
||||
{
|
||||
for (std::size_t i = 0; i < 2; ++i)
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue[i] << ", ";
|
||||
return stream << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue[2];
|
||||
}
|
||||
};
|
||||
|
||||
int runBulletObjectTool(int argc, char* argv[])
|
||||
{
|
||||
Platform::init();
|
||||
|
||||
bpo::options_description desc = makeOptionsDescription();
|
||||
|
||||
bpo::parsed_options options = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||
bpo::variables_map variables;
|
||||
|
||||
bpo::store(options, variables);
|
||||
bpo::notify(variables);
|
||||
|
||||
if (variables.find("help") != variables.end())
|
||||
{
|
||||
getRawStdout() << desc << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Files::ConfigurationManager config;
|
||||
config.readConfiguration(variables, desc);
|
||||
|
||||
setupLogging(config.getLogPath(), applicationName);
|
||||
|
||||
const std::string encoding(variables["encoding"].as<std::string>());
|
||||
Log(Debug::Info) << ToUTF8::encodingUsingMessage(encoding);
|
||||
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(encoding));
|
||||
|
||||
Files::PathContainer dataDirs(asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>()));
|
||||
|
||||
auto local = variables["data-local"].as<Files::MaybeQuotedPathContainer::value_type>();
|
||||
if (!local.empty())
|
||||
dataDirs.push_back(std::move(local));
|
||||
|
||||
config.filterOutNonExistingPaths(dataDirs);
|
||||
|
||||
const auto resDir = variables["resources"].as<Files::MaybeQuotedPath>();
|
||||
const auto v = Version::getOpenmwVersion(resDir);
|
||||
Log(Debug::Info) << v.describe();
|
||||
dataDirs.insert(dataDirs.begin(), resDir / "vfs");
|
||||
const auto fileCollections = Files::Collections(dataDirs);
|
||||
const auto archives = variables["fallback-archive"].as<StringsVector>();
|
||||
const auto contentFiles = variables["content"].as<StringsVector>();
|
||||
|
||||
Fallback::Map::init(variables["fallback"].as<Fallback::FallbackMap>().mMap);
|
||||
|
||||
VFS::Manager vfs;
|
||||
|
||||
VFS::registerArchives(&vfs, fileCollections, archives, true);
|
||||
|
||||
Settings::Manager::load(config);
|
||||
|
||||
ESM::ReadersCache readers;
|
||||
EsmLoader::Query query;
|
||||
query.mLoadActivators = true;
|
||||
query.mLoadCells = true;
|
||||
query.mLoadContainers = true;
|
||||
query.mLoadDoors = true;
|
||||
query.mLoadGameSettings = true;
|
||||
query.mLoadLands = true;
|
||||
query.mLoadStatics = true;
|
||||
const EsmLoader::EsmData esmData
|
||||
= EsmLoader::loadEsmData(query, contentFiles, fileCollections, readers, &encoder);
|
||||
|
||||
Resource::ImageManager imageManager(&vfs);
|
||||
Resource::NifFileManager nifFileManager(&vfs);
|
||||
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager);
|
||||
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager);
|
||||
|
||||
Resource::forEachBulletObject(
|
||||
readers, vfs, bulletShapeManager, esmData, [](const ESM::Cell& cell, const Resource::BulletObject& object) {
|
||||
Log(Debug::Verbose) << "Found bullet object in " << (cell.isExterior() ? "exterior" : "interior")
|
||||
<< " cell \"" << cell.getDescription() << "\":"
|
||||
<< " fileName=\"" << object.mShape->mFileName << '"'
|
||||
<< " fileHash=" << Misc::StringUtils::toHex(object.mShape->mFileHash)
|
||||
<< " collisionShape=" << std::boolalpha
|
||||
<< (object.mShape->mCollisionShape == nullptr)
|
||||
<< " avoidCollisionShape=" << std::boolalpha
|
||||
<< (object.mShape->mAvoidCollisionShape == nullptr) << " position=("
|
||||
<< WriteArray{ object.mPosition.pos } << ')' << " rotation=("
|
||||
<< WriteArray{ object.mPosition.rot } << ')'
|
||||
<< " scale=" << std::setprecision(std::numeric_limits<float>::max_exponent10)
|
||||
<< object.mScale;
|
||||
});
|
||||
|
||||
Log(Debug::Info) << "Done";
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
return wrapApplication(runBulletObjectTool, argc, argv, applicationName);
|
||||
}
|
|
@ -1,23 +1,34 @@
|
|||
set(ESMTOOL
|
||||
esmtool.cpp
|
||||
labels.hpp
|
||||
labels.cpp
|
||||
record.hpp
|
||||
record.cpp
|
||||
esmtool.cpp
|
||||
labels.hpp
|
||||
labels.cpp
|
||||
record.hpp
|
||||
record.cpp
|
||||
arguments.hpp
|
||||
tes4.hpp
|
||||
tes4.cpp
|
||||
)
|
||||
source_group(apps\\esmtool FILES ${ESMTOOL})
|
||||
|
||||
# Main executable
|
||||
openmw_add_executable(esmtool
|
||||
${ESMTOOL}
|
||||
${ESMTOOL}
|
||||
)
|
||||
|
||||
target_link_libraries(esmtool
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
components
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(esmtool gcov)
|
||||
target_compile_options(esmtool PRIVATE --coverage)
|
||||
target_link_libraries(esmtool gcov)
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(esmtool PRIVATE
|
||||
<fstream>
|
||||
<string>
|
||||
<vector>
|
||||
)
|
||||
endif()
|
||||
|
|
29
apps/esmtool/arguments.hpp
Normal file
29
apps/esmtool/arguments.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef OPENMW_ESMTOOL_ARGUMENTS_H
|
||||
#define OPENMW_ESMTOOL_ARGUMENTS_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/format.hpp>
|
||||
|
||||
namespace EsmTool
|
||||
{
|
||||
struct Arguments
|
||||
{
|
||||
std::optional<ESM::Format> mRawFormat;
|
||||
bool quiet_given = false;
|
||||
bool loadcells_given = false;
|
||||
bool plain_given = false;
|
||||
|
||||
std::string mode;
|
||||
std::string encoding;
|
||||
std::filesystem::path filename;
|
||||
std::filesystem::path outname;
|
||||
|
||||
std::vector<std::string> types;
|
||||
std::string name;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,25 +1,25 @@
|
|||
#include "labels.hpp"
|
||||
|
||||
#include <components/esm/loadbody.hpp>
|
||||
#include <components/esm/loadcell.hpp>
|
||||
#include <components/esm/loadcont.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/loadench.hpp>
|
||||
#include <components/esm/loadlevlist.hpp>
|
||||
#include <components/esm/loadligh.hpp>
|
||||
#include <components/esm/loadmgef.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/loadrace.hpp>
|
||||
#include <components/esm/loadspel.hpp>
|
||||
#include <components/esm/loadweap.hpp>
|
||||
#include <components/esm3/loadbody.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/esm3/loadcont.hpp>
|
||||
#include <components/esm3/loadcrea.hpp>
|
||||
#include <components/esm3/loadench.hpp>
|
||||
#include <components/esm3/loadlevlist.hpp>
|
||||
#include <components/esm3/loadligh.hpp>
|
||||
#include <components/esm3/loadmgef.hpp>
|
||||
#include <components/esm3/loadnpc.hpp>
|
||||
#include <components/esm3/loadrace.hpp>
|
||||
#include <components/esm3/loadspel.hpp>
|
||||
#include <components/esm3/loadweap.hpp>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/strings/format.hpp>
|
||||
|
||||
std::string bodyPartLabel(int idx)
|
||||
std::string_view bodyPartLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 26)
|
||||
{
|
||||
static const char *bodyPartLabels[] = {
|
||||
static constexpr std::string_view bodyPartLabels[] = {
|
||||
"Head",
|
||||
"Hair",
|
||||
"Neck",
|
||||
|
@ -46,7 +46,7 @@ std::string bodyPartLabel(int idx)
|
|||
"Right Shoulder",
|
||||
"Left Shoulder",
|
||||
"Weapon",
|
||||
"Tail"
|
||||
"Tail",
|
||||
};
|
||||
return bodyPartLabels[idx];
|
||||
}
|
||||
|
@ -54,11 +54,11 @@ std::string bodyPartLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string meshPartLabel(int idx)
|
||||
std::string_view meshPartLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= ESM::BodyPart::MP_Tail)
|
||||
{
|
||||
static const char *meshPartLabels[] = {
|
||||
static constexpr std::string_view meshPartLabels[] = {
|
||||
"Head",
|
||||
"Hair",
|
||||
"Neck",
|
||||
|
@ -73,7 +73,7 @@ std::string meshPartLabel(int idx)
|
|||
"Knee",
|
||||
"Upper Leg",
|
||||
"Clavicle",
|
||||
"Tail"
|
||||
"Tail",
|
||||
};
|
||||
return meshPartLabels[idx];
|
||||
}
|
||||
|
@ -81,14 +81,14 @@ std::string meshPartLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string meshTypeLabel(int idx)
|
||||
std::string_view meshTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= ESM::BodyPart::MT_Armor)
|
||||
{
|
||||
static const char *meshTypeLabels[] = {
|
||||
static constexpr std::string_view meshTypeLabels[] = {
|
||||
"Skin",
|
||||
"Clothing",
|
||||
"Armor"
|
||||
"Armor",
|
||||
};
|
||||
return meshTypeLabels[idx];
|
||||
}
|
||||
|
@ -96,11 +96,11 @@ std::string meshTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string clothingTypeLabel(int idx)
|
||||
std::string_view clothingTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 9)
|
||||
{
|
||||
static const char *clothingTypeLabels[] = {
|
||||
static constexpr std::string_view clothingTypeLabels[] = {
|
||||
"Pants",
|
||||
"Shoes",
|
||||
"Shirt",
|
||||
|
@ -110,7 +110,7 @@ std::string clothingTypeLabel(int idx)
|
|||
"Left Glove",
|
||||
"Skirt",
|
||||
"Ring",
|
||||
"Amulet"
|
||||
"Amulet",
|
||||
};
|
||||
return clothingTypeLabels[idx];
|
||||
}
|
||||
|
@ -118,11 +118,11 @@ std::string clothingTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string armorTypeLabel(int idx)
|
||||
std::string_view armorTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 10)
|
||||
{
|
||||
static const char *armorTypeLabels[] = {
|
||||
static constexpr std::string_view armorTypeLabels[] = {
|
||||
"Helmet",
|
||||
"Cuirass",
|
||||
"Left Pauldron",
|
||||
|
@ -133,7 +133,7 @@ std::string armorTypeLabel(int idx)
|
|||
"Right Gauntlet",
|
||||
"Shield",
|
||||
"Left Bracer",
|
||||
"Right Bracer"
|
||||
"Right Bracer",
|
||||
};
|
||||
return armorTypeLabels[idx];
|
||||
}
|
||||
|
@ -141,16 +141,16 @@ std::string armorTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string dialogTypeLabel(int idx)
|
||||
std::string_view dialogTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 4)
|
||||
{
|
||||
static const char *dialogTypeLabels[] = {
|
||||
static constexpr std::string_view dialogTypeLabels[] = {
|
||||
"Topic",
|
||||
"Voice",
|
||||
"Greeting",
|
||||
"Persuasion",
|
||||
"Journal"
|
||||
"Journal",
|
||||
};
|
||||
return dialogTypeLabels[idx];
|
||||
}
|
||||
|
@ -160,16 +160,16 @@ std::string dialogTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string questStatusLabel(int idx)
|
||||
std::string_view questStatusLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 4)
|
||||
{
|
||||
static const char *questStatusLabels[] = {
|
||||
static constexpr std::string_view questStatusLabels[] = {
|
||||
"None",
|
||||
"Name",
|
||||
"Finished",
|
||||
"Restart",
|
||||
"Deleted"
|
||||
"Deleted",
|
||||
};
|
||||
return questStatusLabels[idx];
|
||||
}
|
||||
|
@ -177,11 +177,11 @@ std::string questStatusLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string creatureTypeLabel(int idx)
|
||||
std::string_view creatureTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 3)
|
||||
{
|
||||
static const char *creatureTypeLabels[] = {
|
||||
static constexpr std::string_view creatureTypeLabels[] = {
|
||||
"Creature",
|
||||
"Daedra",
|
||||
"Undead",
|
||||
|
@ -193,11 +193,11 @@ std::string creatureTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string soundTypeLabel(int idx)
|
||||
std::string_view soundTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 7)
|
||||
{
|
||||
static const char *soundTypeLabels[] = {
|
||||
static constexpr std::string_view soundTypeLabels[] = {
|
||||
"Left Foot",
|
||||
"Right Foot",
|
||||
"Swim Left",
|
||||
|
@ -205,7 +205,7 @@ std::string soundTypeLabel(int idx)
|
|||
"Moan",
|
||||
"Roar",
|
||||
"Scream",
|
||||
"Land"
|
||||
"Land",
|
||||
};
|
||||
return soundTypeLabels[idx];
|
||||
}
|
||||
|
@ -213,11 +213,11 @@ std::string soundTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string weaponTypeLabel(int idx)
|
||||
std::string_view weaponTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 13)
|
||||
{
|
||||
static const char *weaponTypeLabels[] = {
|
||||
static constexpr std::string_view weaponTypeLabels[] = {
|
||||
"Short Blade One Hand",
|
||||
"Long Blade One Hand",
|
||||
"Long Blade Two Hand",
|
||||
|
@ -231,7 +231,7 @@ std::string weaponTypeLabel(int idx)
|
|||
"Marksman Crossbow",
|
||||
"Marksman Thrown",
|
||||
"Arrow",
|
||||
"Bolt"
|
||||
"Bolt",
|
||||
};
|
||||
return weaponTypeLabels[idx];
|
||||
}
|
||||
|
@ -239,21 +239,29 @@ std::string weaponTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string aiTypeLabel(int type)
|
||||
std::string_view aiTypeLabel(ESM::AiPackageType type)
|
||||
{
|
||||
if (type == ESM::AI_Wander) return "Wander";
|
||||
else if (type == ESM::AI_Travel) return "Travel";
|
||||
else if (type == ESM::AI_Follow) return "Follow";
|
||||
else if (type == ESM::AI_Escort) return "Escort";
|
||||
else if (type == ESM::AI_Activate) return "Activate";
|
||||
else return "Invalid";
|
||||
switch (type)
|
||||
{
|
||||
case ESM::AI_Wander:
|
||||
return "Wander";
|
||||
case ESM::AI_Travel:
|
||||
return "Travel";
|
||||
case ESM::AI_Follow:
|
||||
return "Follow";
|
||||
case ESM::AI_Escort:
|
||||
return "Escort";
|
||||
case ESM::AI_Activate:
|
||||
return "Activate";
|
||||
}
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string magicEffectLabel(int idx)
|
||||
std::string_view magicEffectLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 142)
|
||||
{
|
||||
const char* magicEffectLabels [] = {
|
||||
static constexpr std::string_view magicEffectLabels[] = {
|
||||
"Water Breathing",
|
||||
"Swift Swim",
|
||||
"Water Walking",
|
||||
|
@ -396,7 +404,7 @@ std::string magicEffectLabel(int idx)
|
|||
"sEffectSummonCreature02",
|
||||
"sEffectSummonCreature03",
|
||||
"sEffectSummonCreature04",
|
||||
"sEffectSummonCreature05"
|
||||
"sEffectSummonCreature05",
|
||||
};
|
||||
return magicEffectLabels[idx];
|
||||
}
|
||||
|
@ -404,11 +412,11 @@ std::string magicEffectLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string attributeLabel(int idx)
|
||||
std::string_view attributeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 7)
|
||||
{
|
||||
const char* attributeLabels [] = {
|
||||
static constexpr std::string_view attributeLabels[] = {
|
||||
"Strength",
|
||||
"Intelligence",
|
||||
"Willpower",
|
||||
|
@ -416,7 +424,7 @@ std::string attributeLabel(int idx)
|
|||
"Speed",
|
||||
"Endurance",
|
||||
"Personality",
|
||||
"Luck"
|
||||
"Luck",
|
||||
};
|
||||
return attributeLabels[idx];
|
||||
}
|
||||
|
@ -424,17 +432,17 @@ std::string attributeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string spellTypeLabel(int idx)
|
||||
std::string_view spellTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 5)
|
||||
{
|
||||
const char* spellTypeLabels [] = {
|
||||
static constexpr std::string_view spellTypeLabels[] = {
|
||||
"Spells",
|
||||
"Abilities",
|
||||
"Blight Disease",
|
||||
"Disease",
|
||||
"Curse",
|
||||
"Powers"
|
||||
"Powers",
|
||||
};
|
||||
return spellTypeLabels[idx];
|
||||
}
|
||||
|
@ -442,14 +450,14 @@ std::string spellTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string specializationLabel(int idx)
|
||||
std::string_view specializationLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 2)
|
||||
{
|
||||
const char* specializationLabels [] = {
|
||||
static constexpr std::string_view specializationLabels[] = {
|
||||
"Combat",
|
||||
"Magic",
|
||||
"Stealth"
|
||||
"Stealth",
|
||||
};
|
||||
return specializationLabels[idx];
|
||||
}
|
||||
|
@ -457,11 +465,11 @@ std::string specializationLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string skillLabel(int idx)
|
||||
std::string_view skillLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 26)
|
||||
{
|
||||
const char* skillLabels [] = {
|
||||
static constexpr std::string_view skillLabels[] = {
|
||||
"Block",
|
||||
"Armorer",
|
||||
"Medium Armor",
|
||||
|
@ -488,7 +496,7 @@ std::string skillLabel(int idx)
|
|||
"Marksman",
|
||||
"Mercantile",
|
||||
"Speechcraft",
|
||||
"Hand-to-hand"
|
||||
"Hand-to-hand",
|
||||
};
|
||||
return skillLabels[idx];
|
||||
}
|
||||
|
@ -496,11 +504,11 @@ std::string skillLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string apparatusTypeLabel(int idx)
|
||||
std::string_view apparatusTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 3)
|
||||
{
|
||||
const char* apparatusTypeLabels [] = {
|
||||
static constexpr std::string_view apparatusTypeLabels[] = {
|
||||
"Mortar",
|
||||
"Alembic",
|
||||
"Calcinator",
|
||||
|
@ -512,14 +520,14 @@ std::string apparatusTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string rangeTypeLabel(int idx)
|
||||
std::string_view rangeTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 2)
|
||||
{
|
||||
const char* rangeTypeLabels [] = {
|
||||
static constexpr std::string_view rangeTypeLabels[] = {
|
||||
"Self",
|
||||
"Touch",
|
||||
"Target"
|
||||
"Target",
|
||||
};
|
||||
return rangeTypeLabels[idx];
|
||||
}
|
||||
|
@ -527,17 +535,17 @@ std::string rangeTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string schoolLabel(int idx)
|
||||
std::string_view schoolLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 5)
|
||||
{
|
||||
const char* schoolLabels [] = {
|
||||
static constexpr std::string_view schoolLabels[] = {
|
||||
"Alteration",
|
||||
"Conjuration",
|
||||
"Destruction",
|
||||
"Illusion",
|
||||
"Mysticism",
|
||||
"Restoration"
|
||||
"Restoration",
|
||||
};
|
||||
return schoolLabels[idx];
|
||||
}
|
||||
|
@ -545,15 +553,15 @@ std::string schoolLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string enchantTypeLabel(int idx)
|
||||
std::string_view enchantTypeLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 3)
|
||||
{
|
||||
const char* enchantTypeLabels [] = {
|
||||
static constexpr std::string_view enchantTypeLabels[] = {
|
||||
"Cast Once",
|
||||
"Cast When Strikes",
|
||||
"Cast When Used",
|
||||
"Constant Effect"
|
||||
"Constant Effect",
|
||||
};
|
||||
return enchantTypeLabels[idx];
|
||||
}
|
||||
|
@ -561,11 +569,11 @@ std::string enchantTypeLabel(int idx)
|
|||
return "Invalid";
|
||||
}
|
||||
|
||||
std::string ruleFunction(int idx)
|
||||
std::string_view ruleFunction(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 72)
|
||||
{
|
||||
std::string ruleFunctions[] = {
|
||||
static constexpr std::string_view ruleFunctions[] = {
|
||||
"Reaction Low",
|
||||
"Reaction High",
|
||||
"Rank Requirement",
|
||||
|
@ -638,7 +646,7 @@ std::string ruleFunction(int idx)
|
|||
"Alarm",
|
||||
"Flee",
|
||||
"Should Attack",
|
||||
"Werewolf"
|
||||
"Werewolf",
|
||||
};
|
||||
return ruleFunctions[idx];
|
||||
}
|
||||
|
@ -653,13 +661,15 @@ std::string ruleFunction(int idx)
|
|||
std::string bodyPartFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
|
||||
if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::BodyPart::BPF_Female|
|
||||
ESM::BodyPart::BPF_NotPlayable));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::BodyPart::BPF_Female)
|
||||
properties += "Female ";
|
||||
if (flags & ESM::BodyPart::BPF_NotPlayable)
|
||||
properties += "NotPlayable ";
|
||||
int unused = (0xFFFFFFFF ^ (ESM::BodyPart::BPF_Female | ESM::BodyPart::BPF_NotPlayable));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -667,20 +677,23 @@ std::string bodyPartFlags(int flags)
|
|||
std::string cellFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Cell::HasWater) properties += "HasWater ";
|
||||
if (flags & ESM::Cell::Interior) properties += "Interior ";
|
||||
if (flags & ESM::Cell::NoSleep) properties += "NoSleep ";
|
||||
if (flags & ESM::Cell::QuasiEx) properties += "QuasiEx ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::Cell::HasWater)
|
||||
properties += "HasWater ";
|
||||
if (flags & ESM::Cell::Interior)
|
||||
properties += "Interior ";
|
||||
if (flags & ESM::Cell::NoSleep)
|
||||
properties += "NoSleep ";
|
||||
if (flags & ESM::Cell::QuasiEx)
|
||||
properties += "QuasiEx ";
|
||||
// This used value is not in the ESM component.
|
||||
if (flags & 0x00000040) properties += "Unknown ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Cell::HasWater|
|
||||
ESM::Cell::Interior|
|
||||
ESM::Cell::NoSleep|
|
||||
ESM::Cell::QuasiEx|
|
||||
0x00000040));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags & 0x00000040)
|
||||
properties += "Unknown ";
|
||||
int unused = (0xFFFFFFFF
|
||||
^ (ESM::Cell::HasWater | ESM::Cell::Interior | ESM::Cell::NoSleep | ESM::Cell::QuasiEx | 0x00000040));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -688,15 +701,17 @@ std::string cellFlags(int flags)
|
|||
std::string containerFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Container::Unknown) properties += "Unknown ";
|
||||
if (flags & ESM::Container::Organic) properties += "Organic ";
|
||||
if (flags & ESM::Container::Respawn) properties += "Respawn ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Container::Unknown|
|
||||
ESM::Container::Organic|
|
||||
ESM::Container::Respawn));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::Container::Unknown)
|
||||
properties += "Unknown ";
|
||||
if (flags & ESM::Container::Organic)
|
||||
properties += "Organic ";
|
||||
if (flags & ESM::Container::Respawn)
|
||||
properties += "Respawn ";
|
||||
int unused = (0xFFFFFFFF ^ (ESM::Container::Unknown | ESM::Container::Organic | ESM::Container::Respawn));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -704,25 +719,29 @@ std::string containerFlags(int flags)
|
|||
std::string creatureFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Creature::Base) properties += "Base ";
|
||||
if (flags & ESM::Creature::Walks) properties += "Walks ";
|
||||
if (flags & ESM::Creature::Swims) properties += "Swims ";
|
||||
if (flags & ESM::Creature::Flies) properties += "Flies ";
|
||||
if (flags & ESM::Creature::Bipedal) properties += "Bipedal ";
|
||||
if (flags & ESM::Creature::Respawn) properties += "Respawn ";
|
||||
if (flags & ESM::Creature::Weapon) properties += "Weapon ";
|
||||
if (flags & ESM::Creature::Essential) properties += "Essential ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Creature::Base|
|
||||
ESM::Creature::Walks|
|
||||
ESM::Creature::Swims|
|
||||
ESM::Creature::Flies|
|
||||
ESM::Creature::Bipedal|
|
||||
ESM::Creature::Respawn|
|
||||
ESM::Creature::Weapon|
|
||||
ESM::Creature::Essential));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::Creature::Base)
|
||||
properties += "Base ";
|
||||
if (flags & ESM::Creature::Walks)
|
||||
properties += "Walks ";
|
||||
if (flags & ESM::Creature::Swims)
|
||||
properties += "Swims ";
|
||||
if (flags & ESM::Creature::Flies)
|
||||
properties += "Flies ";
|
||||
if (flags & ESM::Creature::Bipedal)
|
||||
properties += "Bipedal ";
|
||||
if (flags & ESM::Creature::Respawn)
|
||||
properties += "Respawn ";
|
||||
if (flags & ESM::Creature::Weapon)
|
||||
properties += "Weapon ";
|
||||
if (flags & ESM::Creature::Essential)
|
||||
properties += "Essential ";
|
||||
int unused = (0xFFFFFFFF
|
||||
^ (ESM::Creature::Base | ESM::Creature::Walks | ESM::Creature::Swims | ESM::Creature::Flies
|
||||
| ESM::Creature::Bipedal | ESM::Creature::Respawn | ESM::Creature::Weapon | ESM::Creature::Essential));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%02X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -730,9 +749,12 @@ std::string creatureFlags(int flags)
|
|||
std::string enchantmentFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Enchantment::Autocalc) properties += "Autocalc ";
|
||||
if (flags & (0xFFFFFFFF ^ ESM::Enchantment::Autocalc)) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::Enchantment::Autocalc)
|
||||
properties += "Autocalc ";
|
||||
if (flags & (0xFFFFFFFF ^ ESM::Enchantment::Autocalc))
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -743,11 +765,16 @@ std::string landFlags(int flags)
|
|||
// The ESM component says that this first four bits are used, but
|
||||
// only the first three bits are used as far as I can tell.
|
||||
// There's also no enumeration of the bit in the ESM component.
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & 0x00000001) properties += "Unknown1 ";
|
||||
if (flags & 0x00000004) properties += "Unknown3 ";
|
||||
if (flags & 0x00000002) properties += "Unknown2 ";
|
||||
if (flags & 0xFFFFFFF8) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & 0x00000001)
|
||||
properties += "Unknown1 ";
|
||||
if (flags & 0x00000004)
|
||||
properties += "Unknown3 ";
|
||||
if (flags & 0x00000002)
|
||||
properties += "Unknown2 ";
|
||||
if (flags & 0xFFFFFFF8)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -755,13 +782,15 @@ std::string landFlags(int flags)
|
|||
std::string itemListFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::ItemLevList::AllLevels) properties += "AllLevels ";
|
||||
if (flags & ESM::ItemLevList::Each) properties += "Each ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::ItemLevList::AllLevels|
|
||||
ESM::ItemLevList::Each));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::ItemLevList::AllLevels)
|
||||
properties += "AllLevels ";
|
||||
if (flags & ESM::ItemLevList::Each)
|
||||
properties += "Each ";
|
||||
int unused = (0xFFFFFFFF ^ (ESM::ItemLevList::AllLevels | ESM::ItemLevList::Each));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -769,10 +798,13 @@ std::string itemListFlags(int flags)
|
|||
std::string creatureListFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::CreatureLevList::AllLevels) properties += "AllLevels ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::CreatureLevList::AllLevels)
|
||||
properties += "AllLevels ";
|
||||
int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels);
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -780,27 +812,31 @@ std::string creatureListFlags(int flags)
|
|||
std::string lightFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Light::Dynamic) properties += "Dynamic ";
|
||||
if (flags & ESM::Light::Fire) properties += "Fire ";
|
||||
if (flags & ESM::Light::Carry) properties += "Carry ";
|
||||
if (flags & ESM::Light::Flicker) properties += "Flicker ";
|
||||
if (flags & ESM::Light::FlickerSlow) properties += "FlickerSlow ";
|
||||
if (flags & ESM::Light::Pulse) properties += "Pulse ";
|
||||
if (flags & ESM::Light::PulseSlow) properties += "PulseSlow ";
|
||||
if (flags & ESM::Light::Negative) properties += "Negative ";
|
||||
if (flags & ESM::Light::OffDefault) properties += "OffDefault ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Light::Dynamic|
|
||||
ESM::Light::Fire|
|
||||
ESM::Light::Carry|
|
||||
ESM::Light::Flicker|
|
||||
ESM::Light::FlickerSlow|
|
||||
ESM::Light::Pulse|
|
||||
ESM::Light::PulseSlow|
|
||||
ESM::Light::Negative|
|
||||
ESM::Light::OffDefault));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::Light::Dynamic)
|
||||
properties += "Dynamic ";
|
||||
if (flags & ESM::Light::Fire)
|
||||
properties += "Fire ";
|
||||
if (flags & ESM::Light::Carry)
|
||||
properties += "Carry ";
|
||||
if (flags & ESM::Light::Flicker)
|
||||
properties += "Flicker ";
|
||||
if (flags & ESM::Light::FlickerSlow)
|
||||
properties += "FlickerSlow ";
|
||||
if (flags & ESM::Light::Pulse)
|
||||
properties += "Pulse ";
|
||||
if (flags & ESM::Light::PulseSlow)
|
||||
properties += "PulseSlow ";
|
||||
if (flags & ESM::Light::Negative)
|
||||
properties += "Negative ";
|
||||
if (flags & ESM::Light::OffDefault)
|
||||
properties += "OffDefault ";
|
||||
int unused = (0xFFFFFFFF
|
||||
^ (ESM::Light::Dynamic | ESM::Light::Fire | ESM::Light::Carry | ESM::Light::Flicker | ESM::Light::FlickerSlow
|
||||
| ESM::Light::Pulse | ESM::Light::PulseSlow | ESM::Light::Negative | ESM::Light::OffDefault));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -808,27 +844,47 @@ std::string lightFlags(int flags)
|
|||
std::string magicEffectFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::MagicEffect::TargetAttribute) properties += "TargetAttribute ";
|
||||
if (flags & ESM::MagicEffect::TargetSkill) properties += "TargetSkill ";
|
||||
if (flags & ESM::MagicEffect::NoDuration) properties += "NoDuration ";
|
||||
if (flags & ESM::MagicEffect::NoMagnitude) properties += "NoMagnitude ";
|
||||
if (flags & ESM::MagicEffect::Harmful) properties += "Harmful ";
|
||||
if (flags & ESM::MagicEffect::ContinuousVfx) properties += "ContinuousVFX ";
|
||||
if (flags & ESM::MagicEffect::CastSelf) properties += "CastSelf ";
|
||||
if (flags & ESM::MagicEffect::CastTouch) properties += "CastTouch ";
|
||||
if (flags & ESM::MagicEffect::CastTarget) properties += "CastTarget ";
|
||||
if (flags & ESM::MagicEffect::AppliedOnce) properties += "AppliedOnce ";
|
||||
if (flags & ESM::MagicEffect::Stealth) properties += "Stealth ";
|
||||
if (flags & ESM::MagicEffect::NonRecastable) properties += "NonRecastable ";
|
||||
if (flags & ESM::MagicEffect::IllegalDaedra) properties += "IllegalDaedra ";
|
||||
if (flags & ESM::MagicEffect::Unreflectable) properties += "Unreflectable ";
|
||||
if (flags & ESM::MagicEffect::CasterLinked) properties += "CasterLinked ";
|
||||
if (flags & ESM::MagicEffect::AllowSpellmaking) properties += "AllowSpellmaking ";
|
||||
if (flags & ESM::MagicEffect::AllowEnchanting) properties += "AllowEnchanting ";
|
||||
if (flags & ESM::MagicEffect::NegativeLight) properties += "NegativeLight ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::MagicEffect::TargetAttribute)
|
||||
properties += "TargetAttribute ";
|
||||
if (flags & ESM::MagicEffect::TargetSkill)
|
||||
properties += "TargetSkill ";
|
||||
if (flags & ESM::MagicEffect::NoDuration)
|
||||
properties += "NoDuration ";
|
||||
if (flags & ESM::MagicEffect::NoMagnitude)
|
||||
properties += "NoMagnitude ";
|
||||
if (flags & ESM::MagicEffect::Harmful)
|
||||
properties += "Harmful ";
|
||||
if (flags & ESM::MagicEffect::ContinuousVfx)
|
||||
properties += "ContinuousVFX ";
|
||||
if (flags & ESM::MagicEffect::CastSelf)
|
||||
properties += "CastSelf ";
|
||||
if (flags & ESM::MagicEffect::CastTouch)
|
||||
properties += "CastTouch ";
|
||||
if (flags & ESM::MagicEffect::CastTarget)
|
||||
properties += "CastTarget ";
|
||||
if (flags & ESM::MagicEffect::AppliedOnce)
|
||||
properties += "AppliedOnce ";
|
||||
if (flags & ESM::MagicEffect::Stealth)
|
||||
properties += "Stealth ";
|
||||
if (flags & ESM::MagicEffect::NonRecastable)
|
||||
properties += "NonRecastable ";
|
||||
if (flags & ESM::MagicEffect::IllegalDaedra)
|
||||
properties += "IllegalDaedra ";
|
||||
if (flags & ESM::MagicEffect::Unreflectable)
|
||||
properties += "Unreflectable ";
|
||||
if (flags & ESM::MagicEffect::CasterLinked)
|
||||
properties += "CasterLinked ";
|
||||
if (flags & ESM::MagicEffect::AllowSpellmaking)
|
||||
properties += "AllowSpellmaking ";
|
||||
if (flags & ESM::MagicEffect::AllowEnchanting)
|
||||
properties += "AllowEnchanting ";
|
||||
if (flags & ESM::MagicEffect::NegativeLight)
|
||||
properties += "NegativeLight ";
|
||||
|
||||
if (flags & 0xFFFC0000) properties += "Invalid ";
|
||||
if (flags & 0xFFFC0000)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -836,21 +892,24 @@ std::string magicEffectFlags(int flags)
|
|||
std::string npcFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::NPC::Base) properties += "Base ";
|
||||
if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
|
||||
if (flags & ESM::NPC::Female) properties += "Female ";
|
||||
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
||||
if (flags & ESM::NPC::Essential) properties += "Essential ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::NPC::Base)
|
||||
properties += "Base ";
|
||||
if (flags & ESM::NPC::Autocalc)
|
||||
properties += "Autocalc ";
|
||||
if (flags & ESM::NPC::Female)
|
||||
properties += "Female ";
|
||||
if (flags & ESM::NPC::Respawn)
|
||||
properties += "Respawn ";
|
||||
if (flags & ESM::NPC::Essential)
|
||||
properties += "Essential ";
|
||||
// Whether corpses persist is a bit that is unaccounted for,
|
||||
// however relatively few NPCs have this bit set.
|
||||
int unused = (0xFF ^
|
||||
(ESM::NPC::Base|
|
||||
ESM::NPC::Autocalc|
|
||||
ESM::NPC::Female|
|
||||
ESM::NPC::Respawn|
|
||||
ESM::NPC::Essential));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
int unused
|
||||
= (0xFF ^ (ESM::NPC::Base | ESM::NPC::Autocalc | ESM::NPC::Female | ESM::NPC::Respawn | ESM::NPC::Essential));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%02X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -858,14 +917,16 @@ std::string npcFlags(int flags)
|
|||
std::string raceFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
// All races have the playable flag set in Bethesda files.
|
||||
if (flags & ESM::Race::Playable) properties += "Playable ";
|
||||
if (flags & ESM::Race::Beast) properties += "Beast ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Race::Playable|
|
||||
ESM::Race::Beast));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags & ESM::Race::Playable)
|
||||
properties += "Playable ";
|
||||
if (flags & ESM::Race::Beast)
|
||||
properties += "Beast ";
|
||||
int unused = (0xFFFFFFFF ^ (ESM::Race::Playable | ESM::Race::Beast));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -873,15 +934,17 @@ std::string raceFlags(int flags)
|
|||
std::string spellFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Spell::F_Autocalc) properties += "Autocalc ";
|
||||
if (flags & ESM::Spell::F_PCStart) properties += "PCStart ";
|
||||
if (flags & ESM::Spell::F_Always) properties += "Always ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Spell::F_Autocalc|
|
||||
ESM::Spell::F_PCStart|
|
||||
ESM::Spell::F_Always));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::Spell::F_Autocalc)
|
||||
properties += "Autocalc ";
|
||||
if (flags & ESM::Spell::F_PCStart)
|
||||
properties += "PCStart ";
|
||||
if (flags & ESM::Spell::F_Always)
|
||||
properties += "Always ";
|
||||
int unused = (0xFFFFFFFF ^ (ESM::Spell::F_Autocalc | ESM::Spell::F_PCStart | ESM::Spell::F_Always));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
@ -889,16 +952,38 @@ std::string spellFlags(int flags)
|
|||
std::string weaponFlags(int flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
// The interpretation of the flags are still unclear to me.
|
||||
// Apparently you can't be Silver without being Magical? Many of
|
||||
// the "Magical" weapons don't have enchantments of any sort.
|
||||
if (flags & ESM::Weapon::Magical) properties += "Magical ";
|
||||
if (flags & ESM::Weapon::Silver) properties += "Silver ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Weapon::Magical|
|
||||
ESM::Weapon::Silver));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
if (flags & ESM::Weapon::Magical)
|
||||
properties += "Magical ";
|
||||
if (flags & ESM::Weapon::Silver)
|
||||
properties += "Silver ";
|
||||
int unused = (0xFFFFFFFF ^ (ESM::Weapon::Magical | ESM::Weapon::Silver));
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
||||
std::string recordFlags(uint32_t flags)
|
||||
{
|
||||
std::string properties;
|
||||
if (flags == 0)
|
||||
properties += "[None] ";
|
||||
if (flags & ESM::FLAG_Deleted)
|
||||
properties += "Deleted ";
|
||||
if (flags & ESM::FLAG_Persistent)
|
||||
properties += "Persistent ";
|
||||
if (flags & ESM::FLAG_Ignored)
|
||||
properties += "Ignored ";
|
||||
if (flags & ESM::FLAG_Blocked)
|
||||
properties += "Blocked ";
|
||||
int unused = ~(ESM::FLAG_Deleted | ESM::FLAG_Persistent | ESM::FLAG_Ignored | ESM::FLAG_Blocked);
|
||||
if (flags & unused)
|
||||
properties += "Invalid ";
|
||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||
return properties;
|
||||
}
|
||||
|
|
|
@ -2,26 +2,29 @@
|
|||
#define OPENMW_ESMTOOL_LABELS_H
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
std::string bodyPartLabel(int idx);
|
||||
std::string meshPartLabel(int idx);
|
||||
std::string meshTypeLabel(int idx);
|
||||
std::string clothingTypeLabel(int idx);
|
||||
std::string armorTypeLabel(int idx);
|
||||
std::string dialogTypeLabel(int idx);
|
||||
std::string questStatusLabel(int idx);
|
||||
std::string creatureTypeLabel(int idx);
|
||||
std::string soundTypeLabel(int idx);
|
||||
std::string weaponTypeLabel(int idx);
|
||||
#include <components/esm3/aipackage.hpp>
|
||||
|
||||
std::string_view bodyPartLabel(int idx);
|
||||
std::string_view meshPartLabel(int idx);
|
||||
std::string_view meshTypeLabel(int idx);
|
||||
std::string_view clothingTypeLabel(int idx);
|
||||
std::string_view armorTypeLabel(int idx);
|
||||
std::string_view dialogTypeLabel(int idx);
|
||||
std::string_view questStatusLabel(int idx);
|
||||
std::string_view creatureTypeLabel(int idx);
|
||||
std::string_view soundTypeLabel(int idx);
|
||||
std::string_view weaponTypeLabel(int idx);
|
||||
|
||||
// This function's a bit different because the types are record types,
|
||||
// not consecutive values.
|
||||
std::string aiTypeLabel(int type);
|
||||
std::string_view aiTypeLabel(ESM::AiPackageType type);
|
||||
|
||||
// This one's also a bit different, because it enumerates dialog
|
||||
// select rule functions, not types. Structurally, it still converts
|
||||
// indexes to strings for display.
|
||||
std::string ruleFunction(int idx);
|
||||
std::string_view ruleFunction(int idx);
|
||||
|
||||
// The labels below here can all be loaded from GMSTs, but are not
|
||||
// currently because among other things, that requires loading the
|
||||
|
@ -32,15 +35,15 @@ std::string ruleFunction(int idx);
|
|||
// and the indexes for referencing the types in other records in the
|
||||
// database. Then a single label function could work for all types.
|
||||
|
||||
std::string magicEffectLabel(int idx);
|
||||
std::string attributeLabel(int idx);
|
||||
std::string spellTypeLabel(int idx);
|
||||
std::string specializationLabel(int idx);
|
||||
std::string skillLabel(int idx);
|
||||
std::string apparatusTypeLabel(int idx);
|
||||
std::string rangeTypeLabel(int idx);
|
||||
std::string schoolLabel(int idx);
|
||||
std::string enchantTypeLabel(int idx);
|
||||
std::string_view magicEffectLabel(int idx);
|
||||
std::string_view attributeLabel(int idx);
|
||||
std::string_view spellTypeLabel(int idx);
|
||||
std::string_view specializationLabel(int idx);
|
||||
std::string_view skillLabel(int idx);
|
||||
std::string_view apparatusTypeLabel(int idx);
|
||||
std::string_view rangeTypeLabel(int idx);
|
||||
std::string_view schoolLabel(int idx);
|
||||
std::string_view enchantTypeLabel(int idx);
|
||||
|
||||
// The are the flag functions that convert a bitmask into a list of
|
||||
// human readble strings representing the set bits.
|
||||
|
@ -60,6 +63,8 @@ std::string raceFlags(int flags);
|
|||
std::string spellFlags(int flags);
|
||||
std::string weaponFlags(int flags);
|
||||
|
||||
std::string recordFlags(uint32_t flags);
|
||||
|
||||
// Missing flags functions:
|
||||
// aiServicesFlags, possibly more
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,12 @@
|
|||
#ifndef OPENMW_ESMTOOL_RECORD_H
|
||||
#define OPENMW_ESMTOOL_RECORD_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <components/esm/records.hpp>
|
||||
#include <components/esm3/cellstate.hpp>
|
||||
#include <components/esm3/fogstate.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -13,7 +16,8 @@ namespace ESM
|
|||
|
||||
namespace EsmTool
|
||||
{
|
||||
template <class T> class Record;
|
||||
template <class T>
|
||||
class Record;
|
||||
|
||||
class RecordBase
|
||||
{
|
||||
|
@ -24,45 +28,48 @@ namespace EsmTool
|
|||
bool mPrintPlain;
|
||||
|
||||
public:
|
||||
RecordBase ()
|
||||
: mFlags(0)
|
||||
, mPrintPlain(false)
|
||||
RecordBase()
|
||||
: mFlags(0)
|
||||
, mPrintPlain(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~RecordBase() {}
|
||||
virtual ~RecordBase() = default;
|
||||
|
||||
virtual std::string getId() const = 0;
|
||||
|
||||
uint32_t getFlags() const {
|
||||
return mFlags;
|
||||
}
|
||||
uint32_t getFlags() const { return mFlags; }
|
||||
|
||||
void setFlags(uint32_t flags) {
|
||||
mFlags = flags;
|
||||
}
|
||||
void setFlags(uint32_t flags) { mFlags = flags; }
|
||||
|
||||
ESM::NAME getType() const {
|
||||
return mType;
|
||||
}
|
||||
ESM::NAME getType() const { return mType; }
|
||||
|
||||
void setPrintPlain(bool plain) {
|
||||
mPrintPlain = plain;
|
||||
}
|
||||
void setPrintPlain(bool plain) { mPrintPlain = plain; }
|
||||
|
||||
virtual void load(ESM::ESMReader &esm) = 0;
|
||||
virtual void save(ESM::ESMWriter &esm) = 0;
|
||||
virtual void load(ESM::ESMReader& esm) = 0;
|
||||
virtual void save(ESM::ESMWriter& esm) = 0;
|
||||
virtual void print() = 0;
|
||||
|
||||
static RecordBase *create(ESM::NAME type);
|
||||
static std::unique_ptr<RecordBase> create(ESM::NAME type);
|
||||
|
||||
// just make it a bit shorter
|
||||
template <class T>
|
||||
Record<T> *cast() {
|
||||
return static_cast<Record<T> *>(this);
|
||||
Record<T>* cast()
|
||||
{
|
||||
return static_cast<Record<T>*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
struct CellState
|
||||
{
|
||||
ESM::CellState mCellState;
|
||||
ESM::FogState mFogState;
|
||||
|
||||
void load(ESM::ESMReader& reader, bool& deleted);
|
||||
|
||||
void save(ESM::ESMWriter& /*writer*/, bool /*deleted*/) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Record : public RecordBase
|
||||
{
|
||||
|
@ -72,75 +79,119 @@ namespace EsmTool
|
|||
public:
|
||||
Record()
|
||||
: mIsDeleted(false)
|
||||
{}
|
||||
|
||||
std::string getId() const override {
|
||||
return mData.mId;
|
||||
{
|
||||
}
|
||||
|
||||
T &get() {
|
||||
return mData;
|
||||
}
|
||||
std::string getId() const override { return mData.mId.toDebugString(); }
|
||||
|
||||
void save(ESM::ESMWriter &esm) override {
|
||||
mData.save(esm, mIsDeleted);
|
||||
}
|
||||
T& get() { return mData; }
|
||||
|
||||
void load(ESM::ESMReader &esm) override {
|
||||
mData.load(esm, mIsDeleted);
|
||||
}
|
||||
void save(ESM::ESMWriter& esm) override { mData.save(esm, mIsDeleted); }
|
||||
|
||||
void load(ESM::ESMReader& esm) override { mData.load(esm, mIsDeleted); }
|
||||
|
||||
void print() override;
|
||||
};
|
||||
|
||||
template<> std::string Record<ESM::Cell>::getId() const;
|
||||
template<> std::string Record<ESM::Land>::getId() const;
|
||||
template<> std::string Record<ESM::MagicEffect>::getId() const;
|
||||
template<> std::string Record<ESM::Pathgrid>::getId() const;
|
||||
template<> std::string Record<ESM::Skill>::getId() const;
|
||||
|
||||
template<> void Record<ESM::Activator>::print();
|
||||
template<> void Record<ESM::Potion>::print();
|
||||
template<> void Record<ESM::Armor>::print();
|
||||
template<> void Record<ESM::Apparatus>::print();
|
||||
template<> void Record<ESM::BodyPart>::print();
|
||||
template<> void Record<ESM::Book>::print();
|
||||
template<> void Record<ESM::BirthSign>::print();
|
||||
template<> void Record<ESM::Cell>::print();
|
||||
template<> void Record<ESM::Class>::print();
|
||||
template<> void Record<ESM::Clothing>::print();
|
||||
template<> void Record<ESM::Container>::print();
|
||||
template<> void Record<ESM::Creature>::print();
|
||||
template<> void Record<ESM::Dialogue>::print();
|
||||
template<> void Record<ESM::Door>::print();
|
||||
template<> void Record<ESM::Enchantment>::print();
|
||||
template<> void Record<ESM::Faction>::print();
|
||||
template<> void Record<ESM::Global>::print();
|
||||
template<> void Record<ESM::GameSetting>::print();
|
||||
template<> void Record<ESM::DialInfo>::print();
|
||||
template<> void Record<ESM::Ingredient>::print();
|
||||
template<> void Record<ESM::Land>::print();
|
||||
template<> void Record<ESM::CreatureLevList>::print();
|
||||
template<> void Record<ESM::ItemLevList>::print();
|
||||
template<> void Record<ESM::Light>::print();
|
||||
template<> void Record<ESM::Lockpick>::print();
|
||||
template<> void Record<ESM::Probe>::print();
|
||||
template<> void Record<ESM::Repair>::print();
|
||||
template<> void Record<ESM::LandTexture>::print();
|
||||
template<> void Record<ESM::MagicEffect>::print();
|
||||
template<> void Record<ESM::Miscellaneous>::print();
|
||||
template<> void Record<ESM::NPC>::print();
|
||||
template<> void Record<ESM::Pathgrid>::print();
|
||||
template<> void Record<ESM::Race>::print();
|
||||
template<> void Record<ESM::Region>::print();
|
||||
template<> void Record<ESM::Script>::print();
|
||||
template<> void Record<ESM::Skill>::print();
|
||||
template<> void Record<ESM::SoundGenerator>::print();
|
||||
template<> void Record<ESM::Sound>::print();
|
||||
template<> void Record<ESM::Spell>::print();
|
||||
template<> void Record<ESM::StartScript>::print();
|
||||
template<> void Record<ESM::Static>::print();
|
||||
template<> void Record<ESM::Weapon>::print();
|
||||
template <>
|
||||
std::string Record<ESM::Cell>::getId() const;
|
||||
template <>
|
||||
std::string Record<ESM::Land>::getId() const;
|
||||
template <>
|
||||
std::string Record<ESM::MagicEffect>::getId() const;
|
||||
template <>
|
||||
std::string Record<ESM::Pathgrid>::getId() const;
|
||||
template <>
|
||||
std::string Record<ESM::Skill>::getId() const;
|
||||
template <>
|
||||
std::string Record<CellState>::getId() const;
|
||||
|
||||
template <>
|
||||
void Record<ESM::Activator>::print();
|
||||
template <>
|
||||
void Record<ESM::Potion>::print();
|
||||
template <>
|
||||
void Record<ESM::Armor>::print();
|
||||
template <>
|
||||
void Record<ESM::Apparatus>::print();
|
||||
template <>
|
||||
void Record<ESM::BodyPart>::print();
|
||||
template <>
|
||||
void Record<ESM::Book>::print();
|
||||
template <>
|
||||
void Record<ESM::BirthSign>::print();
|
||||
template <>
|
||||
void Record<ESM::Cell>::print();
|
||||
template <>
|
||||
void Record<ESM::Class>::print();
|
||||
template <>
|
||||
void Record<ESM::Clothing>::print();
|
||||
template <>
|
||||
void Record<ESM::Container>::print();
|
||||
template <>
|
||||
void Record<ESM::Creature>::print();
|
||||
template <>
|
||||
void Record<ESM::Dialogue>::print();
|
||||
template <>
|
||||
void Record<ESM::Door>::print();
|
||||
template <>
|
||||
void Record<ESM::Enchantment>::print();
|
||||
template <>
|
||||
void Record<ESM::Faction>::print();
|
||||
template <>
|
||||
void Record<ESM::Global>::print();
|
||||
template <>
|
||||
void Record<ESM::GameSetting>::print();
|
||||
template <>
|
||||
void Record<ESM::DialInfo>::print();
|
||||
template <>
|
||||
void Record<ESM::Ingredient>::print();
|
||||
template <>
|
||||
void Record<ESM::Land>::print();
|
||||
template <>
|
||||
void Record<ESM::CreatureLevList>::print();
|
||||
template <>
|
||||
void Record<ESM::ItemLevList>::print();
|
||||
template <>
|
||||
void Record<ESM::Light>::print();
|
||||
template <>
|
||||
void Record<ESM::Lockpick>::print();
|
||||
template <>
|
||||
void Record<ESM::Probe>::print();
|
||||
template <>
|
||||
void Record<ESM::Repair>::print();
|
||||
template <>
|
||||
void Record<ESM::LandTexture>::print();
|
||||
template <>
|
||||
void Record<ESM::MagicEffect>::print();
|
||||
template <>
|
||||
void Record<ESM::Miscellaneous>::print();
|
||||
template <>
|
||||
void Record<ESM::NPC>::print();
|
||||
template <>
|
||||
void Record<ESM::Pathgrid>::print();
|
||||
template <>
|
||||
void Record<ESM::Race>::print();
|
||||
template <>
|
||||
void Record<ESM::Region>::print();
|
||||
template <>
|
||||
void Record<ESM::Script>::print();
|
||||
template <>
|
||||
void Record<ESM::Skill>::print();
|
||||
template <>
|
||||
void Record<ESM::SoundGenerator>::print();
|
||||
template <>
|
||||
void Record<ESM::Sound>::print();
|
||||
template <>
|
||||
void Record<ESM::Spell>::print();
|
||||
template <>
|
||||
void Record<ESM::StartScript>::print();
|
||||
template <>
|
||||
void Record<ESM::Static>::print();
|
||||
template <>
|
||||
void Record<ESM::Weapon>::print();
|
||||
template <>
|
||||
void Record<CellState>::print();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
564
apps/esmtool/tes4.cpp
Normal file
564
apps/esmtool/tes4.cpp
Normal file
|
@ -0,0 +1,564 @@
|
|||
#include "tes4.hpp"
|
||||
#include "arguments.hpp"
|
||||
#include "labels.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
#include <components/esm/typetraits.hpp>
|
||||
#include <components/esm4/reader.hpp>
|
||||
#include <components/esm4/readerutils.hpp>
|
||||
#include <components/esm4/records.hpp>
|
||||
#include <components/esm4/typetraits.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
namespace EsmTool
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct Params
|
||||
{
|
||||
const bool mQuite;
|
||||
|
||||
explicit Params(const Arguments& info)
|
||||
: mQuite(info.quiet_given || info.mode == "clone")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::string toString(ESM4::GroupType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ESM4::Grp_RecordType:
|
||||
return "RecordType";
|
||||
case ESM4::Grp_WorldChild:
|
||||
return "WorldChild";
|
||||
case ESM4::Grp_InteriorCell:
|
||||
return "InteriorCell";
|
||||
case ESM4::Grp_InteriorSubCell:
|
||||
return "InteriorSubCell";
|
||||
case ESM4::Grp_ExteriorCell:
|
||||
return "ExteriorCell";
|
||||
case ESM4::Grp_ExteriorSubCell:
|
||||
return "ExteriorSubCell";
|
||||
case ESM4::Grp_CellChild:
|
||||
return "CellChild";
|
||||
case ESM4::Grp_TopicChild:
|
||||
return "TopicChild";
|
||||
case ESM4::Grp_CellPersistentChild:
|
||||
return "CellPersistentChild";
|
||||
case ESM4::Grp_CellTemporaryChild:
|
||||
return "CellTemporaryChild";
|
||||
case ESM4::Grp_CellVisibleDistChild:
|
||||
return "CellVisibleDistChild";
|
||||
}
|
||||
|
||||
return "Unknown (" + std::to_string(type) + ")";
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct WriteArray
|
||||
{
|
||||
std::string_view mPrefix;
|
||||
const T& mValue;
|
||||
|
||||
explicit WriteArray(std::string_view prefix, const T& value)
|
||||
: mPrefix(prefix)
|
||||
, mValue(value)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct WriteData
|
||||
{
|
||||
const T& mValue;
|
||||
|
||||
explicit WriteData(const T& value)
|
||||
: mValue(value)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
std::ostream& operator<<(std::ostream& stream, const WriteArray<T>& write)
|
||||
{
|
||||
for (const auto& value : write.mValue)
|
||||
stream << write.mPrefix << value;
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::ostream& operator<<(std::ostream& stream, const WriteData<T>& /*write*/)
|
||||
{
|
||||
return stream << " ?";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const WriteData<ESM4::GameSetting::Data>& write)
|
||||
{
|
||||
std::visit([&](const auto& v) { stream << v; }, write.mValue);
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void readTypedRecord(const Params& params, ESM4::Reader& reader)
|
||||
{
|
||||
reader.getRecordData();
|
||||
|
||||
T value;
|
||||
value.load(reader);
|
||||
|
||||
if (params.mQuite)
|
||||
return;
|
||||
|
||||
std::cout << "\n Record: " << ESM::NAME(reader.hdr().record.typeId).toStringView();
|
||||
if constexpr (ESM4::hasFormId<T>)
|
||||
std::cout << "\n FormId: 0x" << ESM4::formIdToString(value.mFormId);
|
||||
if constexpr (ESM::hasId<T>)
|
||||
{
|
||||
if constexpr (std::is_same_v<decltype(value.mId), ESM4::FormId>)
|
||||
std::cout << "\n FormId: 0x" << ESM4::formIdToString(value.mId);
|
||||
else
|
||||
std::cout << "\n Id: " << value.mId;
|
||||
}
|
||||
if constexpr (ESM4::hasFlags<T>)
|
||||
std::cout << "\n Record flags: " << recordFlags(value.mFlags);
|
||||
if constexpr (ESM4::hasParentFormId<T>)
|
||||
std::cout << "\n ParentFormId: 0x" << ESM4::formIdToString(value.mParentFormId);
|
||||
if constexpr (ESM4::hasParent<T>)
|
||||
std::cout << "\n Parent: " << value.mParent;
|
||||
if constexpr (ESM4::hasEditorId<T>)
|
||||
std::cout << "\n EditorId: " << value.mEditorId;
|
||||
if constexpr (ESM::hasModel<T>)
|
||||
std::cout << "\n Model: " << value.mModel;
|
||||
if constexpr (ESM4::hasNif<T>)
|
||||
std::cout << "\n Nif:" << WriteArray("\n - ", value.mNif);
|
||||
if constexpr (ESM4::hasKf<T>)
|
||||
std::cout << "\n Kf:" << WriteArray("\n - ", value.mKf);
|
||||
if constexpr (ESM4::hasType<T>)
|
||||
std::cout << "\n Type: " << value.mType;
|
||||
if constexpr (ESM4::hasValue<T>)
|
||||
std::cout << "\n Value: " << value.mValue;
|
||||
if constexpr (ESM4::hasData<T>)
|
||||
std::cout << "\n Data: " << WriteData(value.mData);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
bool readRecord(const Params& params, ESM4::Reader& reader)
|
||||
{
|
||||
switch (static_cast<ESM4::RecordTypes>(reader.hdr().record.typeId))
|
||||
{
|
||||
case ESM4::REC_AACT:
|
||||
break;
|
||||
case ESM4::REC_ACHR:
|
||||
readTypedRecord<ESM4::ActorCharacter>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ACRE:
|
||||
readTypedRecord<ESM4::ActorCreature>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ACTI:
|
||||
readTypedRecord<ESM4::Activator>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ADDN:
|
||||
break;
|
||||
case ESM4::REC_ALCH:
|
||||
readTypedRecord<ESM4::Potion>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ALOC:
|
||||
readTypedRecord<ESM4::MediaLocationController>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_AMMO:
|
||||
readTypedRecord<ESM4::Ammunition>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ANIO:
|
||||
readTypedRecord<ESM4::AnimObject>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_APPA:
|
||||
readTypedRecord<ESM4::Apparatus>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ARMA:
|
||||
readTypedRecord<ESM4::ArmorAddon>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ARMO:
|
||||
readTypedRecord<ESM4::Armor>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ARTO:
|
||||
break;
|
||||
case ESM4::REC_ASPC:
|
||||
readTypedRecord<ESM4::AcousticSpace>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_ASTP:
|
||||
break;
|
||||
case ESM4::REC_AVIF:
|
||||
break;
|
||||
case ESM4::REC_BOOK:
|
||||
readTypedRecord<ESM4::Book>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_BPTD:
|
||||
readTypedRecord<ESM4::BodyPartData>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CAMS:
|
||||
break;
|
||||
case ESM4::REC_CCRD:
|
||||
break;
|
||||
case ESM4::REC_CELL:
|
||||
readTypedRecord<ESM4::Cell>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CLAS:
|
||||
readTypedRecord<ESM4::Class>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CLFM:
|
||||
readTypedRecord<ESM4::Colour>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CLMT:
|
||||
break;
|
||||
case ESM4::REC_CLOT:
|
||||
readTypedRecord<ESM4::Clothing>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CMNY:
|
||||
break;
|
||||
case ESM4::REC_COBJ:
|
||||
break;
|
||||
case ESM4::REC_COLL:
|
||||
break;
|
||||
case ESM4::REC_CONT:
|
||||
readTypedRecord<ESM4::Container>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CPTH:
|
||||
break;
|
||||
case ESM4::REC_CREA:
|
||||
readTypedRecord<ESM4::Creature>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_CSTY:
|
||||
break;
|
||||
case ESM4::REC_DEBR:
|
||||
break;
|
||||
case ESM4::REC_DIAL:
|
||||
readTypedRecord<ESM4::Dialogue>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_DLBR:
|
||||
break;
|
||||
case ESM4::REC_DLVW:
|
||||
break;
|
||||
case ESM4::REC_DOBJ:
|
||||
readTypedRecord<ESM4::DefaultObj>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_DOOR:
|
||||
readTypedRecord<ESM4::Door>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_DUAL:
|
||||
break;
|
||||
case ESM4::REC_ECZN:
|
||||
break;
|
||||
case ESM4::REC_EFSH:
|
||||
break;
|
||||
case ESM4::REC_ENCH:
|
||||
break;
|
||||
case ESM4::REC_EQUP:
|
||||
break;
|
||||
case ESM4::REC_EXPL:
|
||||
break;
|
||||
case ESM4::REC_EYES:
|
||||
readTypedRecord<ESM4::Eyes>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_FACT:
|
||||
break;
|
||||
case ESM4::REC_FLOR:
|
||||
readTypedRecord<ESM4::Flora>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_FLST:
|
||||
readTypedRecord<ESM4::FormIdList>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_FSTP:
|
||||
break;
|
||||
case ESM4::REC_FSTS:
|
||||
break;
|
||||
case ESM4::REC_FURN:
|
||||
readTypedRecord<ESM4::Furniture>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_GLOB:
|
||||
readTypedRecord<ESM4::GlobalVariable>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_GMST:
|
||||
readTypedRecord<ESM4::GameSetting>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_GRAS:
|
||||
readTypedRecord<ESM4::Grass>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_GRUP:
|
||||
break;
|
||||
case ESM4::REC_HAIR:
|
||||
readTypedRecord<ESM4::Hair>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_HAZD:
|
||||
break;
|
||||
case ESM4::REC_HDPT:
|
||||
readTypedRecord<ESM4::HeadPart>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_IDLE:
|
||||
// FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm
|
||||
// readTypedRecord<ESM4::IdleAnimation>(params, reader);
|
||||
return true;
|
||||
break;
|
||||
case ESM4::REC_IDLM:
|
||||
readTypedRecord<ESM4::IdleMarker>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_IMAD:
|
||||
break;
|
||||
case ESM4::REC_IMGS:
|
||||
break;
|
||||
case ESM4::REC_IMOD:
|
||||
readTypedRecord<ESM4::ItemMod>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_INFO:
|
||||
readTypedRecord<ESM4::DialogInfo>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_INGR:
|
||||
readTypedRecord<ESM4::Ingredient>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_IPCT:
|
||||
break;
|
||||
case ESM4::REC_IPDS:
|
||||
break;
|
||||
case ESM4::REC_KEYM:
|
||||
readTypedRecord<ESM4::Key>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_KYWD:
|
||||
break;
|
||||
case ESM4::REC_LAND:
|
||||
readTypedRecord<ESM4::Land>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LCRT:
|
||||
break;
|
||||
case ESM4::REC_LCTN:
|
||||
break;
|
||||
case ESM4::REC_LGTM:
|
||||
readTypedRecord<ESM4::LightingTemplate>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LIGH:
|
||||
readTypedRecord<ESM4::Light>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LSCR:
|
||||
break;
|
||||
case ESM4::REC_LTEX:
|
||||
readTypedRecord<ESM4::LandTexture>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LVLC:
|
||||
readTypedRecord<ESM4::LevelledCreature>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LVLI:
|
||||
readTypedRecord<ESM4::LevelledItem>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LVLN:
|
||||
readTypedRecord<ESM4::LevelledNpc>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_LVSP:
|
||||
break;
|
||||
case ESM4::REC_MATO:
|
||||
readTypedRecord<ESM4::Material>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_MATT:
|
||||
break;
|
||||
case ESM4::REC_MESG:
|
||||
break;
|
||||
case ESM4::REC_MGEF:
|
||||
break;
|
||||
case ESM4::REC_MISC:
|
||||
readTypedRecord<ESM4::MiscItem>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_MOVT:
|
||||
break;
|
||||
case ESM4::REC_MSET:
|
||||
readTypedRecord<ESM4::MediaSet>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_MSTT:
|
||||
readTypedRecord<ESM4::MovableStatic>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_MUSC:
|
||||
readTypedRecord<ESM4::Music>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_MUST:
|
||||
break;
|
||||
case ESM4::REC_NAVI:
|
||||
readTypedRecord<ESM4::Navigation>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_NAVM:
|
||||
readTypedRecord<ESM4::NavMesh>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_NOTE:
|
||||
readTypedRecord<ESM4::Note>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_NPC_:
|
||||
readTypedRecord<ESM4::Npc>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_OTFT:
|
||||
readTypedRecord<ESM4::Outfit>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_PACK:
|
||||
readTypedRecord<ESM4::AIPackage>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_PERK:
|
||||
break;
|
||||
case ESM4::REC_PGRD:
|
||||
readTypedRecord<ESM4::Pathgrid>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_PGRE:
|
||||
readTypedRecord<ESM4::PlacedGrenade>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_PHZD:
|
||||
break;
|
||||
case ESM4::REC_PROJ:
|
||||
break;
|
||||
case ESM4::REC_PWAT:
|
||||
readTypedRecord<ESM4::PlaceableWater>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_QUST:
|
||||
readTypedRecord<ESM4::Quest>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_RACE:
|
||||
readTypedRecord<ESM4::Race>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_REFR:
|
||||
readTypedRecord<ESM4::Reference>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_REGN:
|
||||
readTypedRecord<ESM4::Region>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_RELA:
|
||||
break;
|
||||
case ESM4::REC_REVB:
|
||||
break;
|
||||
case ESM4::REC_RFCT:
|
||||
break;
|
||||
case ESM4::REC_ROAD:
|
||||
readTypedRecord<ESM4::Road>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SBSP:
|
||||
readTypedRecord<ESM4::SubSpace>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SCEN:
|
||||
break;
|
||||
case ESM4::REC_SCOL:
|
||||
readTypedRecord<ESM4::StaticCollection>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SCPT:
|
||||
readTypedRecord<ESM4::Script>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SCRL:
|
||||
readTypedRecord<ESM4::Scroll>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SGST:
|
||||
readTypedRecord<ESM4::SigilStone>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SHOU:
|
||||
break;
|
||||
case ESM4::REC_SLGM:
|
||||
readTypedRecord<ESM4::SoulGem>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SMBN:
|
||||
break;
|
||||
case ESM4::REC_SMEN:
|
||||
break;
|
||||
case ESM4::REC_SMQN:
|
||||
break;
|
||||
case ESM4::REC_SNCT:
|
||||
break;
|
||||
case ESM4::REC_SNDR:
|
||||
readTypedRecord<ESM4::SoundReference>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SOPM:
|
||||
break;
|
||||
case ESM4::REC_SOUN:
|
||||
readTypedRecord<ESM4::Sound>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_SPEL:
|
||||
break;
|
||||
case ESM4::REC_SPGD:
|
||||
break;
|
||||
case ESM4::REC_STAT:
|
||||
readTypedRecord<ESM4::Static>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_TACT:
|
||||
readTypedRecord<ESM4::TalkingActivator>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_TERM:
|
||||
readTypedRecord<ESM4::Terminal>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_TES4:
|
||||
readTypedRecord<ESM4::Header>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_TREE:
|
||||
readTypedRecord<ESM4::Tree>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_TXST:
|
||||
readTypedRecord<ESM4::TextureSet>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_VTYP:
|
||||
break;
|
||||
case ESM4::REC_WATR:
|
||||
break;
|
||||
case ESM4::REC_WEAP:
|
||||
readTypedRecord<ESM4::Weapon>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_WOOP:
|
||||
break;
|
||||
case ESM4::REC_WRLD:
|
||||
readTypedRecord<ESM4::World>(params, reader);
|
||||
return true;
|
||||
case ESM4::REC_WTHR:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!params.mQuite)
|
||||
std::cout << "\n Unsupported record: " << ESM::NAME(reader.hdr().record.typeId).toStringView() << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int loadTes4(const Arguments& info, std::unique_ptr<std::ifstream>&& stream)
|
||||
{
|
||||
std::cout << "Loading TES4 file: " << info.filename << '\n';
|
||||
|
||||
try
|
||||
{
|
||||
const ToUTF8::StatelessUtf8Encoder encoder(ToUTF8::calculateEncoding(info.encoding));
|
||||
ESM4::Reader reader(std::move(stream), info.filename, nullptr, &encoder, true);
|
||||
const Params params(info);
|
||||
|
||||
if (!params.mQuite)
|
||||
{
|
||||
std::cout << "Author: " << reader.getAuthor() << '\n'
|
||||
<< "Description: " << reader.getDesc() << '\n'
|
||||
<< "File format version: " << reader.esmVersion() << '\n';
|
||||
|
||||
if (const std::vector<ESM::MasterData>& masterData = reader.getGameFiles(); !masterData.empty())
|
||||
{
|
||||
std::cout << "Masters:" << '\n';
|
||||
for (const auto& master : masterData)
|
||||
std::cout << " " << master.name << ", " << master.size << " bytes\n";
|
||||
}
|
||||
}
|
||||
|
||||
auto visitorRec = [¶ms](ESM4::Reader& reader) { return readRecord(params, reader); };
|
||||
auto visitorGroup = [¶ms](ESM4::Reader& reader) {
|
||||
if (params.mQuite)
|
||||
return;
|
||||
auto groupType = static_cast<ESM4::GroupType>(reader.hdr().group.type);
|
||||
std::cout << "\nGroup: " << toString(groupType) << " "
|
||||
<< ESM::NAME(reader.hdr().group.typeId).toStringView() << '\n';
|
||||
};
|
||||
ESM4::ReaderUtils::readAll(reader, visitorRec, visitorGroup);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cout << "\nERROR:\n\n " << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
15
apps/esmtool/tes4.hpp
Normal file
15
apps/esmtool/tes4.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef OPENMW_ESMTOOL_TES4_H
|
||||
#define OPENMW_ESMTOOL_TES4_H
|
||||
|
||||
#include <fstream>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
|
||||
namespace EsmTool
|
||||
{
|
||||
struct Arguments;
|
||||
|
||||
int loadTes4(const Arguments& info, std::unique_ptr<std::ifstream>&& stream);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -5,7 +5,6 @@ set(ESSIMPORTER_FILES
|
|||
importnpcc.cpp
|
||||
importcrec.cpp
|
||||
importcellref.cpp
|
||||
importacdt.cpp
|
||||
importinventory.cpp
|
||||
importklst.cpp
|
||||
importcntc.cpp
|
||||
|
@ -36,15 +35,24 @@ openmw_add_executable(openmw-essimporter
|
|||
|
||||
target_link_libraries(openmw-essimporter
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(openmw-essimporter gcov)
|
||||
target_compile_options(openmw-essimporter PRIVATE --coverage)
|
||||
target_link_libraries(openmw-essimporter gcov)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
INSTALL(TARGETS openmw-essimporter RUNTIME DESTINATION ".")
|
||||
INSTALL(TARGETS openmw-essimporter RUNTIME DESTINATION ".")
|
||||
endif(WIN32)
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
|
||||
target_precompile_headers(openmw-essimporter PRIVATE
|
||||
<algorithm>
|
||||
<filesystem>
|
||||
<fstream>
|
||||
<string>
|
||||
<vector>
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
#include "convertacdt.hpp"
|
||||
|
||||
|
@ -18,36 +18,36 @@ namespace ESSImport
|
|||
return mwIndex;
|
||||
}
|
||||
|
||||
void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats)
|
||||
void convertACDT(const ACDT& acdt, ESM::CreatureStats& cStats)
|
||||
{
|
||||
for (int i=0; i<3; ++i)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
int writeIndex = translateDynamicIndex(i);
|
||||
cStats.mDynamic[writeIndex].mBase = acdt.mDynamic[i][1];
|
||||
cStats.mDynamic[writeIndex].mMod = acdt.mDynamic[i][1];
|
||||
cStats.mDynamic[writeIndex].mMod = 0.f;
|
||||
cStats.mDynamic[writeIndex].mCurrent = acdt.mDynamic[i][0];
|
||||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
cStats.mAttributes[i].mBase = static_cast<int>(acdt.mAttributes[i][1]);
|
||||
cStats.mAttributes[i].mMod = static_cast<int>(acdt.mAttributes[i][0]);
|
||||
cStats.mAttributes[i].mCurrent = static_cast<int>(acdt.mAttributes[i][0]);
|
||||
cStats.mAttributes[i].mBase = acdt.mAttributes[i][1];
|
||||
cStats.mAttributes[i].mMod = 0.f;
|
||||
cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0];
|
||||
}
|
||||
cStats.mGoldPool = acdt.mGoldPool;
|
||||
cStats.mTalkedTo = (acdt.mFlags & TalkedToPlayer) != 0;
|
||||
cStats.mAttacked = (acdt.mFlags & Attacked) != 0;
|
||||
}
|
||||
|
||||
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats)
|
||||
void convertACSC(const ACSC& acsc, ESM::CreatureStats& cStats)
|
||||
{
|
||||
cStats.mDead = (acsc.mFlags & Dead) != 0;
|
||||
}
|
||||
|
||||
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)
|
||||
void convertNpcData(const ActorData& actorData, ESM::NpcStats& npcStats)
|
||||
{
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
npcStats.mSkills[i].mMod = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mMod = 0.f;
|
||||
npcStats.mSkills[i].mCurrent = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mBase = actorData.mSkills[i][0];
|
||||
}
|
||||
|
@ -55,32 +55,29 @@ namespace ESSImport
|
|||
npcStats.mTimeToStartDrowning = actorData.mACDT.mBreathMeter;
|
||||
}
|
||||
|
||||
void convertANIS (const ANIS& anis, ESM::AnimationState& state)
|
||||
void convertANIS(const ANIS& anis, ESM::AnimationState& state)
|
||||
{
|
||||
static const char* animGroups[] =
|
||||
{
|
||||
"Idle", "Idle2", "Idle3", "Idle4", "Idle5", "Idle6", "Idle7", "Idle8", "Idle9", "Idlehh", "Idle1h", "Idle2c",
|
||||
"Idle2w", "IdleSwim", "IdleSpell", "IdleCrossbow", "IdleSneak", "IdleStorm", "Torch", "Hit1", "Hit2", "Hit3",
|
||||
"Hit4", "Hit5", "SwimHit1", "SwimHit2", "SwimHit3", "Death1", "Death2", "Death3", "Death4", "Death5",
|
||||
"DeathKnockDown", "DeathKnockOut", "KnockDown", "KnockOut", "SwimDeath", "SwimDeath2", "SwimDeath3",
|
||||
"SwimDeathKnockDown", "SwimDeathKnockOut", "SwimKnockOut", "SwimKnockDown", "SwimWalkForward",
|
||||
"SwimWalkBack", "SwimWalkLeft", "SwimWalkRight", "SwimRunForward", "SwimRunBack", "SwimRunLeft",
|
||||
"SwimRunRight", "SwimTurnLeft", "SwimTurnRight", "WalkForward", "WalkBack", "WalkLeft", "WalkRight",
|
||||
"TurnLeft", "TurnRight", "RunForward", "RunBack", "RunLeft", "RunRight", "SneakForward", "SneakBack",
|
||||
"SneakLeft", "SneakRight", "Jump", "WalkForwardhh", "WalkBackhh", "WalkLefthh", "WalkRighthh",
|
||||
"TurnLefthh", "TurnRighthh", "RunForwardhh", "RunBackhh", "RunLefthh", "RunRighthh", "SneakForwardhh",
|
||||
"SneakBackhh", "SneakLefthh", "SneakRighthh", "Jumphh", "WalkForward1h", "WalkBack1h", "WalkLeft1h",
|
||||
"WalkRight1h", "TurnLeft1h", "TurnRight1h", "RunForward1h", "RunBack1h", "RunLeft1h", "RunRight1h",
|
||||
"SneakForward1h", "SneakBack1h", "SneakLeft1h", "SneakRight1h", "Jump1h", "WalkForward2c", "WalkBack2c",
|
||||
"WalkLeft2c", "WalkRight2c", "TurnLeft2c", "TurnRight2c", "RunForward2c", "RunBack2c", "RunLeft2c",
|
||||
"RunRight2c", "SneakForward2c", "SneakBack2c", "SneakLeft2c", "SneakRight2c", "Jump2c", "WalkForward2w",
|
||||
"WalkBack2w", "WalkLeft2w", "WalkRight2w", "TurnLeft2w", "TurnRight2w", "RunForward2w", "RunBack2w",
|
||||
"RunLeft2w", "RunRight2w", "SneakForward2w", "SneakBack2w", "SneakLeft2w", "SneakRight2w", "Jump2w",
|
||||
"SpellCast", "SpellTurnLeft", "SpellTurnRight", "Attack1", "Attack2", "Attack3", "SwimAttack1",
|
||||
static const char* animGroups[] = { "Idle", "Idle2", "Idle3", "Idle4", "Idle5", "Idle6", "Idle7", "Idle8",
|
||||
"Idle9", "Idlehh", "Idle1h", "Idle2c", "Idle2w", "IdleSwim", "IdleSpell", "IdleCrossbow", "IdleSneak",
|
||||
"IdleStorm", "Torch", "Hit1", "Hit2", "Hit3", "Hit4", "Hit5", "SwimHit1", "SwimHit2", "SwimHit3", "Death1",
|
||||
"Death2", "Death3", "Death4", "Death5", "DeathKnockDown", "DeathKnockOut", "KnockDown", "KnockOut",
|
||||
"SwimDeath", "SwimDeath2", "SwimDeath3", "SwimDeathKnockDown", "SwimDeathKnockOut", "SwimKnockOut",
|
||||
"SwimKnockDown", "SwimWalkForward", "SwimWalkBack", "SwimWalkLeft", "SwimWalkRight", "SwimRunForward",
|
||||
"SwimRunBack", "SwimRunLeft", "SwimRunRight", "SwimTurnLeft", "SwimTurnRight", "WalkForward", "WalkBack",
|
||||
"WalkLeft", "WalkRight", "TurnLeft", "TurnRight", "RunForward", "RunBack", "RunLeft", "RunRight",
|
||||
"SneakForward", "SneakBack", "SneakLeft", "SneakRight", "Jump", "WalkForwardhh", "WalkBackhh", "WalkLefthh",
|
||||
"WalkRighthh", "TurnLefthh", "TurnRighthh", "RunForwardhh", "RunBackhh", "RunLefthh", "RunRighthh",
|
||||
"SneakForwardhh", "SneakBackhh", "SneakLefthh", "SneakRighthh", "Jumphh", "WalkForward1h", "WalkBack1h",
|
||||
"WalkLeft1h", "WalkRight1h", "TurnLeft1h", "TurnRight1h", "RunForward1h", "RunBack1h", "RunLeft1h",
|
||||
"RunRight1h", "SneakForward1h", "SneakBack1h", "SneakLeft1h", "SneakRight1h", "Jump1h", "WalkForward2c",
|
||||
"WalkBack2c", "WalkLeft2c", "WalkRight2c", "TurnLeft2c", "TurnRight2c", "RunForward2c", "RunBack2c",
|
||||
"RunLeft2c", "RunRight2c", "SneakForward2c", "SneakBack2c", "SneakLeft2c", "SneakRight2c", "Jump2c",
|
||||
"WalkForward2w", "WalkBack2w", "WalkLeft2w", "WalkRight2w", "TurnLeft2w", "TurnRight2w", "RunForward2w",
|
||||
"RunBack2w", "RunLeft2w", "RunRight2w", "SneakForward2w", "SneakBack2w", "SneakLeft2w", "SneakRight2w",
|
||||
"Jump2w", "SpellCast", "SpellTurnLeft", "SpellTurnRight", "Attack1", "Attack2", "Attack3", "SwimAttack1",
|
||||
"SwimAttack2", "SwimAttack3", "HandToHand", "Crossbow", "BowAndArrow", "ThrowWeapon", "WeaponOneHand",
|
||||
"WeaponTwoHand", "WeaponTwoWide", "Shield", "PickProbe", "InventoryHandToHand", "InventoryWeaponOneHand",
|
||||
"InventoryWeaponTwoHand", "InventoryWeaponTwoWide"
|
||||
};
|
||||
"InventoryWeaponTwoHand", "InventoryWeaponTwoWide" };
|
||||
|
||||
if (anis.mGroupIndex < (sizeof(animGroups) / sizeof(*animGroups)))
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef OPENMW_ESSIMPORT_CONVERTACDT_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTACDT_H
|
||||
|
||||
#include <components/esm/creaturestats.hpp>
|
||||
#include <components/esm/npcstats.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
#include <components/esm/animationstate.hpp>
|
||||
#include <components/esm3/animationstate.hpp>
|
||||
#include <components/esm3/creaturestats.hpp>
|
||||
#include <components/esm3/loadskil.hpp>
|
||||
#include <components/esm3/npcstats.hpp>
|
||||
|
||||
#include "importacdt.hpp"
|
||||
|
||||
|
@ -14,13 +14,12 @@ namespace ESSImport
|
|||
// OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka
|
||||
int translateDynamicIndex(int mwIndex);
|
||||
|
||||
void convertACDT(const ACDT& acdt, ESM::CreatureStats& cStats);
|
||||
void convertACSC(const ACSC& acsc, ESM::CreatureStats& cStats);
|
||||
|
||||
void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats);
|
||||
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats);
|
||||
void convertNpcData(const ActorData& actorData, ESM::NpcStats& npcStats);
|
||||
|
||||
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats);
|
||||
|
||||
void convertANIS (const ANIS& anis, ESM::AnimationState& state);
|
||||
void convertANIS(const ANIS& anis, ESM::AnimationState& state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertCNTC(const CNTC &cntc, ESM::ContainerState &state)
|
||||
void convertCNTC(const CNTC& cntc, ESM::ContainerState& state)
|
||||
{
|
||||
convertInventory(cntc.mInventory, state.mInventory);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "importcntc.hpp"
|
||||
|
||||
#include <components/esm/containerstate.hpp>
|
||||
#include <components/esm3/containerstate.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertCREC(const CREC &crec, ESM::CreatureState &state)
|
||||
void convertCREC(const CREC& crec, ESM::CreatureState& state)
|
||||
{
|
||||
convertInventory(crec.mInventory, state.mInventory);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "importcrec.hpp"
|
||||
|
||||
#include <components/esm/creaturestate.hpp>
|
||||
#include <components/esm3/creaturestate.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
#include "converter.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <components/esm/creaturestate.hpp>
|
||||
#include <components/esm/containerstate.hpp>
|
||||
#include <components/esm3/containerstate.hpp>
|
||||
#include <components/esm3/creaturestate.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
#include "convertcrec.hpp"
|
||||
#include "convertcntc.hpp"
|
||||
#include "convertcrec.hpp"
|
||||
#include "convertscri.hpp"
|
||||
|
||||
namespace
|
||||
|
@ -19,7 +19,7 @@ namespace
|
|||
|
||||
void convertImage(char* data, int size, int width, int height, GLenum pf, const std::string& out)
|
||||
{
|
||||
osg::ref_ptr<osg::Image> image (new osg::Image);
|
||||
osg::ref_ptr<osg::Image> image(new osg::Image);
|
||||
image->allocateImage(width, height, 1, pf, GL_UNSIGNED_BYTE);
|
||||
memcpy(image->data(), data, size);
|
||||
image->flipVertical();
|
||||
|
@ -27,7 +27,6 @@ namespace
|
|||
osgDB::writeImageFile(*image, out);
|
||||
}
|
||||
|
||||
|
||||
void convertCellRef(const ESSImport::CellRef& cellref, ESM::ObjectState& objstate)
|
||||
{
|
||||
objstate.mEnabled = cellref.mEnabled;
|
||||
|
@ -35,11 +34,11 @@ namespace
|
|||
objstate.mRef.mRefNum = cellref.mRefNum;
|
||||
if (cellref.mDeleted)
|
||||
objstate.mCount = 0;
|
||||
convertSCRI(cellref.mSCRI, objstate.mLocals);
|
||||
convertSCRI(cellref.mActorData.mSCRI, objstate.mLocals);
|
||||
objstate.mHasLocals = !objstate.mLocals.mVariables.empty();
|
||||
|
||||
if (cellref.mHasANIS)
|
||||
convertANIS(cellref.mANIS, objstate.mAnimationState);
|
||||
if (cellref.mActorData.mHasANIS)
|
||||
convertANIS(cellref.mActorData.mANIS, objstate.mAnimationState);
|
||||
}
|
||||
|
||||
bool isIndexedRefId(const std::string& indexedRefId)
|
||||
|
@ -51,28 +50,28 @@ namespace
|
|||
return false; // entirely numeric refid, this is a reference to
|
||||
// a dynamically created record e.g. player-enchanted weapon
|
||||
|
||||
std::string index = indexedRefId.substr(indexedRefId.size()-8);
|
||||
std::string index = indexedRefId.substr(indexedRefId.size() - 8);
|
||||
return index.find_first_not_of("0123456789ABCDEF") == std::string::npos;
|
||||
}
|
||||
|
||||
void splitIndexedRefId(const std::string& indexedRefId, int& refIndex, std::string& refId)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::hex << indexedRefId.substr(indexedRefId.size()-8,8);
|
||||
stream << std::hex << indexedRefId.substr(indexedRefId.size() - 8, 8);
|
||||
stream >> refIndex;
|
||||
|
||||
refId = indexedRefId.substr(0,indexedRefId.size()-8);
|
||||
refId = indexedRefId.substr(0, indexedRefId.size() - 8);
|
||||
}
|
||||
|
||||
int convertActorId(const std::string& indexedRefId, ESSImport::Context& context)
|
||||
{
|
||||
if (isIndexedRefId(indexedRefId))
|
||||
{
|
||||
int refIndex;
|
||||
int refIndex = 0;
|
||||
std::string refId;
|
||||
splitIndexedRefId(indexedRefId, refIndex, refId);
|
||||
|
||||
auto it = context.mActorIdMap.find(std::make_pair(refIndex, refId));
|
||||
auto it = context.mActorIdMap.find(std::make_pair(refIndex, ESM::RefId::stringRefId(refId)));
|
||||
if (it == context.mActorIdMap.end())
|
||||
return -1;
|
||||
return it->second;
|
||||
|
@ -89,14 +88,13 @@ namespace
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
|
||||
struct MAPH
|
||||
{
|
||||
unsigned int size;
|
||||
unsigned int value;
|
||||
};
|
||||
|
||||
void ConvertFMAP::read(ESM::ESMReader &esm)
|
||||
void ConvertFMAP::read(ESM::ESMReader& esm)
|
||||
{
|
||||
MAPH maph;
|
||||
esm.getHNT(maph, "MAPH");
|
||||
|
@ -104,63 +102,63 @@ namespace ESSImport
|
|||
esm.getSubNameIs("MAPD");
|
||||
esm.getSubHeader();
|
||||
data.resize(esm.getSubSize());
|
||||
esm.getExact(&data[0], data.size());
|
||||
esm.getExact(data.data(), data.size());
|
||||
|
||||
mGlobalMapImage = new osg::Image;
|
||||
mGlobalMapImage->allocateImage(maph.size, maph.size, 1, GL_RGB, GL_UNSIGNED_BYTE);
|
||||
memcpy(mGlobalMapImage->data(), &data[0], data.size());
|
||||
memcpy(mGlobalMapImage->data(), data.data(), data.size());
|
||||
|
||||
// to match openmw size
|
||||
// FIXME: filtering?
|
||||
mGlobalMapImage->scaleImage(maph.size*2, maph.size*2, 1, GL_UNSIGNED_BYTE);
|
||||
mGlobalMapImage->scaleImage(maph.size * 2, maph.size * 2, 1, GL_UNSIGNED_BYTE);
|
||||
}
|
||||
|
||||
void ConvertFMAP::write(ESM::ESMWriter &esm)
|
||||
void ConvertFMAP::write(ESM::ESMWriter& esm)
|
||||
{
|
||||
int numcells = mGlobalMapImage->s() / 18; // NB truncating, doesn't divide perfectly
|
||||
// with the 512x512 map the game has by default
|
||||
int cellSize = mGlobalMapImage->s()/numcells;
|
||||
// with the 512x512 map the game has by default
|
||||
int cellSize = mGlobalMapImage->s() / numcells;
|
||||
|
||||
// Note the upper left corner of the (0,0) cell should be at (width/2, height/2)
|
||||
|
||||
mContext->mGlobalMapState.mBounds.mMinX = -numcells/2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxX = (numcells-1)/2;
|
||||
mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxY = numcells/2;
|
||||
mContext->mGlobalMapState.mBounds.mMinX = -numcells / 2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxX = (numcells - 1) / 2;
|
||||
mContext->mGlobalMapState.mBounds.mMinY = -(numcells - 1) / 2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxY = numcells / 2;
|
||||
|
||||
osg::ref_ptr<osg::Image> image2 (new osg::Image);
|
||||
int width = cellSize*numcells;
|
||||
int height = cellSize*numcells;
|
||||
osg::ref_ptr<osg::Image> image2(new osg::Image);
|
||||
int width = cellSize * numcells;
|
||||
int height = cellSize * numcells;
|
||||
std::vector<unsigned char> data;
|
||||
data.resize(width*height*4, 0);
|
||||
data.resize(width * height * 4, 0);
|
||||
|
||||
image2->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
memcpy(image2->data(), &data[0], data.size());
|
||||
memcpy(image2->data(), data.data(), data.size());
|
||||
|
||||
for (const auto & exploredCell : mContext->mExploredCells)
|
||||
for (const auto& exploredCell : mContext->mExploredCells)
|
||||
{
|
||||
if (exploredCell.first > mContext->mGlobalMapState.mBounds.mMaxX
|
||||
|| exploredCell.first < mContext->mGlobalMapState.mBounds.mMinX
|
||||
|| exploredCell.second > mContext->mGlobalMapState.mBounds.mMaxY
|
||||
|| exploredCell.second < mContext->mGlobalMapState.mBounds.mMinY)
|
||||
|| exploredCell.first < mContext->mGlobalMapState.mBounds.mMinX
|
||||
|| exploredCell.second > mContext->mGlobalMapState.mBounds.mMaxY
|
||||
|| exploredCell.second < mContext->mGlobalMapState.mBounds.mMinY)
|
||||
{
|
||||
// out of bounds, I think this could happen, since the original engine had a fixed-size map
|
||||
continue;
|
||||
}
|
||||
|
||||
int imageLeftSrc = mGlobalMapImage->s()/2;
|
||||
int imageTopSrc = mGlobalMapImage->t()/2;
|
||||
int imageLeftSrc = mGlobalMapImage->s() / 2;
|
||||
int imageTopSrc = mGlobalMapImage->t() / 2;
|
||||
imageLeftSrc += exploredCell.first * cellSize;
|
||||
imageTopSrc -= exploredCell.second * cellSize;
|
||||
int imageLeftDst = width/2;
|
||||
int imageTopDst = height/2;
|
||||
int imageLeftDst = width / 2;
|
||||
int imageTopDst = height / 2;
|
||||
imageLeftDst += exploredCell.first * cellSize;
|
||||
imageTopDst -= exploredCell.second * cellSize;
|
||||
for (int x=0; x<cellSize; ++x)
|
||||
for (int y=0; y<cellSize; ++y)
|
||||
for (int x = 0; x < cellSize; ++x)
|
||||
for (int y = 0; y < cellSize; ++y)
|
||||
{
|
||||
unsigned int col = *(unsigned int*)mGlobalMapImage->data(imageLeftSrc+x, imageTopSrc+y, 0);
|
||||
*(unsigned int*)image2->data(imageLeftDst+x, imageTopDst+y, 0) = col;
|
||||
unsigned int col = *(unsigned int*)mGlobalMapImage->data(imageLeftSrc + x, imageTopSrc + y, 0);
|
||||
*(unsigned int*)image2->data(imageLeftDst + x, imageTopDst + y, 0) = col;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,7 +175,8 @@ namespace ESSImport
|
|||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image2, ostream);
|
||||
if (!result.success())
|
||||
{
|
||||
std::cerr << "Error: can't write global map image: " << result.message() << " code " << result.status() << std::endl;
|
||||
std::cerr << "Error: can't write global map image: " << result.message() << " code " << result.status()
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -189,7 +188,7 @@ namespace ESSImport
|
|||
esm.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
void ConvertCell::read(ESM::ESMReader &esm)
|
||||
void ConvertCell::read(ESM::ESMReader& esm)
|
||||
{
|
||||
ESM::Cell cell;
|
||||
bool isDeleted = false;
|
||||
|
@ -203,9 +202,9 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
// note if the player is in a nameless exterior cell, we will assign the cellId later based on player position
|
||||
if (cell.mName == mContext->mPlayerCellName)
|
||||
if (Misc::StringUtils::ciEqual(cell.mName, mContext->mPlayerCellName))
|
||||
{
|
||||
mContext->mPlayer.mCellId = cell.getCellId();
|
||||
mContext->mPlayer.mCellId = cell.mId;
|
||||
}
|
||||
|
||||
Cell newcell;
|
||||
|
@ -234,15 +233,15 @@ namespace ESSImport
|
|||
|
||||
esm.getExact(nam8, 32);
|
||||
|
||||
newcell.mFogOfWar.reserve(16*16);
|
||||
for (int x=0; x<16; ++x)
|
||||
newcell.mFogOfWar.reserve(16 * 16);
|
||||
for (int x = 0; x < 16; ++x)
|
||||
{
|
||||
for (int y=0; y<16; ++y)
|
||||
for (int y = 0; y < 16; ++y)
|
||||
{
|
||||
size_t pos = x*16+y;
|
||||
size_t bytepos = pos/8;
|
||||
assert(bytepos<32);
|
||||
int bit = pos%8;
|
||||
size_t pos = x * 16 + y;
|
||||
size_t bytepos = pos / 8;
|
||||
assert(bytepos < 32);
|
||||
int bit = pos % 8;
|
||||
newcell.mFogOfWar.push_back(((nam8[bytepos] >> bit) & (0x1)) ? 0xffffffff : 0x000000ff);
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +251,8 @@ namespace ESSImport
|
|||
std::ostringstream filename;
|
||||
filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga";
|
||||
|
||||
convertImage((char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size()*4, 16, 16, GL_RGBA, filename.str());
|
||||
convertImage(
|
||||
(char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size() * 4, 16, 16, GL_RGBA, filename.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,17 +268,17 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
std::vector<CellRef> cellrefs;
|
||||
while (esm.hasMoreSubs() && esm.isNextSub("FRMR"))
|
||||
while (esm.hasMoreSubs() && esm.peekNextSub("FRMR"))
|
||||
{
|
||||
CellRef ref;
|
||||
ref.load (esm);
|
||||
ref.load(esm);
|
||||
cellrefs.push_back(ref);
|
||||
}
|
||||
|
||||
while (esm.isNextSub("MPCD"))
|
||||
{
|
||||
float notepos[3];
|
||||
esm.getHT(notepos, 3*sizeof(float));
|
||||
esm.getHTSized<3 * sizeof(float)>(notepos);
|
||||
|
||||
// Markers seem to be arranged in a 32*32 grid, notepos has grid-indices.
|
||||
// This seems to be the reason markers can't be placed everywhere in interior cells,
|
||||
|
@ -301,35 +301,37 @@ namespace ESSImport
|
|||
marker.mWorldX = notepos[0];
|
||||
marker.mWorldY = notepos[1];
|
||||
marker.mNote = note;
|
||||
marker.mCell = cell.getCellId();
|
||||
marker.mCell = cell.mId;
|
||||
mMarkers.push_back(marker);
|
||||
}
|
||||
|
||||
newcell.mRefs = cellrefs;
|
||||
|
||||
|
||||
if (cell.isExterior())
|
||||
mExtCells[std::make_pair(cell.mData.mX, cell.mData.mY)] = newcell;
|
||||
else
|
||||
mIntCells[cell.mName] = newcell;
|
||||
}
|
||||
|
||||
void ConvertCell::writeCell(const Cell &cell, ESM::ESMWriter& esm)
|
||||
void ConvertCell::writeCell(const Cell& cell, ESM::ESMWriter& esm)
|
||||
{
|
||||
ESM::Cell esmcell = cell.mCell;
|
||||
esm.startRecord(ESM::REC_CSTA);
|
||||
ESM::CellState csta;
|
||||
csta.mHasFogOfWar = 0;
|
||||
csta.mId = esmcell.getCellId();
|
||||
csta.mId.save(esm);
|
||||
csta.mLastRespawn.mDay = 0;
|
||||
csta.mLastRespawn.mHour = 0;
|
||||
csta.mId = esmcell.mId;
|
||||
csta.mIsInterior = !esmcell.isExterior();
|
||||
esm.writeCellId(csta.mId);
|
||||
// TODO csta.mLastRespawn;
|
||||
// shouldn't be needed if we respawn on global schedule like in original MW
|
||||
csta.mWaterLevel = esmcell.mWater;
|
||||
csta.save(esm);
|
||||
|
||||
for (const auto & cellref : cell.mRefs)
|
||||
for (const auto& cellref : cell.mRefs)
|
||||
{
|
||||
ESM::CellRef out (cellref);
|
||||
ESM::CellRef out(cellref);
|
||||
|
||||
// TODO: use mContext->mCreatures/mNpcs
|
||||
|
||||
|
@ -337,88 +339,90 @@ namespace ESSImport
|
|||
{
|
||||
// non-indexed RefNum, i.e. no CREC/NPCC/CNTC record associated with it
|
||||
// this could be any type of object really (even creatures/npcs too)
|
||||
out.mRefID = cellref.mIndexedRefId;
|
||||
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
|
||||
out.mRefID = ESM::RefId::stringRefId(cellref.mIndexedRefId);
|
||||
|
||||
ESM::ObjectState objstate;
|
||||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
objstate.mRef.mRefID = out.mRefID;
|
||||
objstate.mHasCustomState = false;
|
||||
convertCellRef(cellref, objstate);
|
||||
esm.writeHNT ("OBJE", 0);
|
||||
esm.writeHNT("OBJE", 0);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int refIndex;
|
||||
splitIndexedRefId(cellref.mIndexedRefId, refIndex, out.mRefID);
|
||||
int refIndex = 0;
|
||||
std::string outStringId;
|
||||
splitIndexedRefId(cellref.mIndexedRefId, refIndex, outStringId);
|
||||
out.mRefID = ESM::RefId::stringRefId(outStringId);
|
||||
|
||||
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
|
||||
|
||||
std::map<std::pair<int, std::string>, NPCC>::const_iterator npccIt = mContext->mNpcChanges.find(
|
||||
std::make_pair(refIndex, out.mRefID));
|
||||
auto npccIt = mContext->mNpcChanges.find(std::make_pair(refIndex, out.mRefID));
|
||||
if (npccIt != mContext->mNpcChanges.end())
|
||||
{
|
||||
ESM::NpcState objstate;
|
||||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
objstate.mRef.mRefID = out.mRefID;
|
||||
// TODO: need more micromanagement here so we don't overwrite values
|
||||
// from the ESM with default values
|
||||
if (cellref.mHasACDT)
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
if (cellref.mHasACSC)
|
||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
||||
convertNpcData(cellref, objstate.mNpcStats);
|
||||
if (cellref.mActorData.mHasACDT)
|
||||
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||
else
|
||||
objstate.mCreatureStats.mMissingACDT = true;
|
||||
if (cellref.mActorData.mHasACSC)
|
||||
convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats);
|
||||
convertNpcData(cellref.mActorData, objstate.mNpcStats);
|
||||
convertNPCC(npccIt->second, objstate);
|
||||
convertCellRef(cellref, objstate);
|
||||
|
||||
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
||||
mContext->mActorIdMap.insert(std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||
mContext->mActorIdMap.insert(
|
||||
std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||
|
||||
esm.writeHNT ("OBJE", ESM::REC_NPC_);
|
||||
esm.writeHNT("OBJE", ESM::REC_NPC_);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<std::pair<int, std::string>, CNTC>::const_iterator cntcIt = mContext->mContainerChanges.find(
|
||||
std::make_pair(refIndex, out.mRefID));
|
||||
auto cntcIt = mContext->mContainerChanges.find(std::make_pair(refIndex, out.mRefID));
|
||||
if (cntcIt != mContext->mContainerChanges.end())
|
||||
{
|
||||
ESM::ContainerState objstate;
|
||||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
objstate.mRef.mRefID = out.mRefID;
|
||||
convertCNTC(cntcIt->second, objstate);
|
||||
convertCellRef(cellref, objstate);
|
||||
esm.writeHNT ("OBJE", ESM::REC_CONT);
|
||||
esm.writeHNT("OBJE", ESM::REC_CONT);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<std::pair<int, std::string>, CREC>::const_iterator crecIt = mContext->mCreatureChanges.find(
|
||||
std::make_pair(refIndex, out.mRefID));
|
||||
auto crecIt = mContext->mCreatureChanges.find(std::make_pair(refIndex, out.mRefID));
|
||||
if (crecIt != mContext->mCreatureChanges.end())
|
||||
{
|
||||
ESM::CreatureState objstate;
|
||||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
objstate.mRef.mRefID = out.mRefID;
|
||||
// TODO: need more micromanagement here so we don't overwrite values
|
||||
// from the ESM with default values
|
||||
if (cellref.mHasACDT)
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
if (cellref.mHasACSC)
|
||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
||||
if (cellref.mActorData.mHasACDT)
|
||||
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||
else
|
||||
objstate.mCreatureStats.mMissingACDT = true;
|
||||
if (cellref.mActorData.mHasACSC)
|
||||
convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats);
|
||||
convertCREC(crecIt->second, objstate);
|
||||
convertCellRef(cellref, objstate);
|
||||
|
||||
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
||||
mContext->mActorIdMap.insert(std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||
mContext->mActorIdMap.insert(
|
||||
std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||
|
||||
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
||||
esm.writeHNT("OBJE", ESM::REC_CREA);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
}
|
||||
|
@ -432,15 +436,15 @@ namespace ESSImport
|
|||
esm.endRecord(ESM::REC_CSTA);
|
||||
}
|
||||
|
||||
void ConvertCell::write(ESM::ESMWriter &esm)
|
||||
void ConvertCell::write(ESM::ESMWriter& esm)
|
||||
{
|
||||
for (const auto & cell : mIntCells)
|
||||
for (const auto& cell : mIntCells)
|
||||
writeCell(cell.second, esm);
|
||||
|
||||
for (const auto & cell : mExtCells)
|
||||
for (const auto& cell : mExtCells)
|
||||
writeCell(cell.second, esm);
|
||||
|
||||
for (const auto & marker : mMarkers)
|
||||
for (const auto& marker : mMarkers)
|
||||
{
|
||||
esm.startRecord(ESM::REC_MARK);
|
||||
marker.save(esm);
|
||||
|
@ -462,7 +466,7 @@ namespace ESSImport
|
|||
ESM::ProjectileState out;
|
||||
convertBaseState(out, pnam);
|
||||
|
||||
out.mBowId = pnam.mBowId.toString();
|
||||
out.mBowId = ESM::RefId::stringRefId(pnam.mBowId.toString());
|
||||
out.mVelocity = pnam.mVelocity;
|
||||
out.mAttackStrength = pnam.mAttackStrength;
|
||||
|
||||
|
@ -476,16 +480,18 @@ namespace ESSImport
|
|||
convertBaseState(out, pnam);
|
||||
|
||||
auto it = std::find_if(mContext->mActiveSpells.begin(), mContext->mActiveSpells.end(),
|
||||
[&pnam](const SPLM::ActiveSpell& spell) -> bool { return spell.mIndex == pnam.mSplmIndex; });
|
||||
[&pnam](const SPLM::ActiveSpell& spell) -> bool { return spell.mIndex == pnam.mSplmIndex; });
|
||||
|
||||
if (it == mContext->mActiveSpells.end())
|
||||
{
|
||||
std::cerr << "Warning: Skipped conversion for magic projectile \"" << pnam.mArrowId.toString() << "\" (invalid spell link)" << std::endl;
|
||||
std::cerr << "Warning: Skipped conversion for magic projectile \"" << pnam.mArrowId.toString()
|
||||
<< "\" (invalid spell link)" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
out.mSpellId = it->mSPDT.mId.toString();
|
||||
out.mSpellId = ESM::RefId::stringRefId(it->mSPDT.mId.toString());
|
||||
out.mSpeed = pnam.mSpeed * 0.001f; // not sure where this factor comes from
|
||||
out.mSlot = 0;
|
||||
|
||||
esm.startRecord(ESM::REC_MPRJ);
|
||||
out.save(esm);
|
||||
|
@ -496,11 +502,11 @@ namespace ESSImport
|
|||
|
||||
void ConvertPROJ::convertBaseState(ESM::BaseProjectileState& base, const PROJ::PNAM& pnam)
|
||||
{
|
||||
base.mId = pnam.mArrowId.toString();
|
||||
base.mId = ESM::RefId::stringRefId(pnam.mArrowId.toString());
|
||||
base.mPosition = pnam.mPosition;
|
||||
|
||||
osg::Quat orient;
|
||||
orient.makeRotate(osg::Vec3f(0,1,0), pnam.mVelocity);
|
||||
orient.makeRotate(osg::Vec3f(0, 1, 0), pnam.mVelocity);
|
||||
base.mOrientation = orient;
|
||||
|
||||
base.mActorId = convertActorId(pnam.mActorId.toString(), *mContext);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,22 +1,23 @@
|
|||
#include "convertinventory.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertInventory(const Inventory &inventory, ESM::InventoryState &state)
|
||||
void convertInventory(const Inventory& inventory, ESM::InventoryState& state)
|
||||
{
|
||||
int index = 0;
|
||||
for (const auto & item : inventory.mItems)
|
||||
for (const auto& item : inventory.mItems)
|
||||
{
|
||||
ESM::ObjectState objstate;
|
||||
objstate.blank();
|
||||
objstate.mRef = item;
|
||||
objstate.mRef.mRefID = Misc::StringUtils::lowerCase(item.mId);
|
||||
objstate.mRef.mRefID = ESM::RefId::stringRefId(item.mId);
|
||||
objstate.mCount = std::abs(item.mCount); // restocking items have negative count in the savefile
|
||||
// openmw handles them differently, so no need to set any flags
|
||||
// openmw handles them differently, so no need to set any flags
|
||||
state.mItems.push_back(objstate);
|
||||
if (item.mRelativeEquipmentSlot != -1)
|
||||
// Note we should really write the absolute slot here, which we do not know about
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
#include "importinventory.hpp"
|
||||
|
||||
#include <components/esm/inventorystate.hpp>
|
||||
#include <components/esm3/inventorystate.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertInventory (const Inventory& inventory, ESM::InventoryState& state);
|
||||
void convertInventory(const Inventory& inventory, ESM::InventoryState& state);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertNPCC(const NPCC &npcc, ESM::NpcState &npcState)
|
||||
void convertNPCC(const NPCC& npcc, ESM::NpcState& npcState)
|
||||
{
|
||||
npcState.mNpcStats.mDisposition = npcc.mNPDT.mDisposition;
|
||||
npcState.mNpcStats.mReputation = npcc.mNPDT.mReputation;
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
#include "importnpcc.hpp"
|
||||
|
||||
#include <components/esm/npcstate.hpp>
|
||||
#include <components/esm3/npcstate.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertNPCC (const NPCC& npcc, ESM::NpcState& npcState);
|
||||
void convertNPCC(const NPCC& npcc, ESM::NpcState& npcState);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,35 @@
|
|||
#include "convertplayer.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<ESM::RefId>& outDialogueTopics,
|
||||
bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
|
||||
{
|
||||
out.mBirthsign = pcdt.mBirthsign;
|
||||
out.mObject.mPosition.rot[0]
|
||||
= -atan2(pcdt.mPNAM.mVerticalRotation.mData[2][1], pcdt.mPNAM.mVerticalRotation.mData[2][2]);
|
||||
|
||||
out.mBirthsign = ESM::RefId::stringRefId(pcdt.mBirthsign);
|
||||
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
||||
for (const auto & essFaction : pcdt.mFactions)
|
||||
for (const auto& essFaction : pcdt.mFactions)
|
||||
{
|
||||
ESM::NpcStats::Faction faction;
|
||||
faction.mExpelled = (essFaction.mFlags & 0x2) != 0;
|
||||
faction.mRank = essFaction.mRank;
|
||||
faction.mReputation = essFaction.mReputation;
|
||||
out.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(essFaction.mFactionName.toString())] = faction;
|
||||
out.mObject.mNpcStats.mFactions[ESM::RefId::stringRefId(essFaction.mFactionName.toString())] = faction;
|
||||
}
|
||||
for (int i=0; i<3; ++i)
|
||||
for (size_t i = 0; i < out.mObject.mNpcStats.mSpecIncreases.size(); ++i)
|
||||
out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i];
|
||||
for (int i=0; i<8; ++i)
|
||||
for (size_t i = 0; i < out.mObject.mNpcStats.mSkillIncrease.size(); ++i)
|
||||
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
for (int i=0; i<27; ++i)
|
||||
for (size_t i = 0; i < out.mObject.mNpcStats.mSkills.size(); ++i)
|
||||
out.mObject.mNpcStats.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
|
@ -35,9 +42,9 @@ namespace ESSImport
|
|||
teleportingEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_TeleportingDisabled);
|
||||
levitationEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_LevitationDisabled);
|
||||
|
||||
for (const auto & knownDialogueTopic : pcdt.mKnownDialogueTopics)
|
||||
for (const auto& knownDialogueTopic : pcdt.mKnownDialogueTopics)
|
||||
{
|
||||
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(knownDialogueTopic));
|
||||
outDialogueTopics.push_back(ESM::RefId::stringRefId(knownDialogueTopic));
|
||||
}
|
||||
|
||||
controls.mViewSwitchDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ViewSwitchDisabled;
|
||||
|
@ -54,19 +61,9 @@ namespace ESSImport
|
|||
|
||||
const PCDT::PNAM::MarkLocation& mark = pcdt.mPNAM.mMarkLocation;
|
||||
|
||||
ESM::CellId cell;
|
||||
cell.mWorldspace = ESM::CellId::sDefaultWorldspace;
|
||||
cell.mPaged = true;
|
||||
|
||||
cell.mIndex.mX = mark.mCellX;
|
||||
cell.mIndex.mY = mark.mCellY;
|
||||
|
||||
// TODO: Figure out a better way to detect interiors. (0, 0) is a valid exterior cell.
|
||||
if (mark.mCellX == 0 && mark.mCellY == 0)
|
||||
{
|
||||
cell.mWorldspace = pcdt.mMNAM;
|
||||
cell.mPaged = false;
|
||||
}
|
||||
bool interior = mark.mCellX == 0 && mark.mCellY == 0;
|
||||
ESM::RefId cell = ESM::Cell::generateIdForCell(!interior, pcdt.mMNAM, mark.mCellX, mark.mCellY);
|
||||
|
||||
out.mMarkedCell = cell;
|
||||
out.mMarkedPosition.pos[0] = mark.mX;
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
|
||||
#include "importplayer.hpp"
|
||||
|
||||
#include <components/esm/player.hpp>
|
||||
#include <components/esm/controlsstate.hpp>
|
||||
#include <components/esm3/controlsstate.hpp>
|
||||
#include <components/esm3/player.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<ESM::RefId>& outDialogueTopics,
|
||||
bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
#include "convertscpt.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "convertscri.hpp"
|
||||
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCPT(const SCPT &scpt, ESM::GlobalScript &out)
|
||||
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out)
|
||||
{
|
||||
out.mId = Misc::StringUtils::lowerCase(scpt.mSCHD.mName.toString());
|
||||
out.mId = ESM::RefId::stringRefId(scpt.mSCHD.mName.toString());
|
||||
out.mRunning = scpt.mRunning;
|
||||
out.mTargetRef.unset(); // TODO: convert target reference of global script
|
||||
out.mTargetRef = ESM::RefNum{}; // TODO: convert target reference of global script
|
||||
convertSCRI(scpt.mSCRI, out.mLocals);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#ifndef OPENMW_ESSIMPORT_CONVERTSCPT_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTSCPT_H
|
||||
|
||||
#include <components/esm/globalscript.hpp>
|
||||
#include <components/esm3/globalscript.hpp>
|
||||
|
||||
#include "importscpt.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out);
|
||||
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCRI(const SCRI &scri, ESM::Locals &locals)
|
||||
void convertSCRI(const SCRI& scri, ESM::Locals& locals)
|
||||
{
|
||||
// order *is* important, as we do not have variable names available in this format
|
||||
storeVariables<short, ESM::VT_Short> (scri.mShorts, locals, scri.mScript);
|
||||
storeVariables<int, ESM::VT_Int> (scri.mLongs, locals, scri.mScript);
|
||||
storeVariables<float, ESM::VT_Float> (scri.mFloats, locals, scri.mScript);
|
||||
storeVariables<short, ESM::VT_Short>(scri.mShorts, locals, scri.mScript);
|
||||
storeVariables<int, ESM::VT_Int>(scri.mLongs, locals, scri.mScript);
|
||||
storeVariables<float, ESM::VT_Float>(scri.mFloats, locals, scri.mScript);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
#include "importscri.hpp"
|
||||
|
||||
#include <components/esm/locals.hpp>
|
||||
#include <components/esm3/locals.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// Convert script variable assignments
|
||||
void convertSCRI (const SCRI& scri, ESM::Locals& locals);
|
||||
void convertSCRI(const SCRI& scri, ESM::Locals& locals);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
#include "importacdt.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
#include <components/esm/cellref.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void ActorData::load(ESM::ESMReader &esm)
|
||||
{
|
||||
if (esm.isNextSub("ACTN"))
|
||||
{
|
||||
/*
|
||||
Activation flags:
|
||||
ActivationFlag_UseEnabled = 1
|
||||
ActivationFlag_OnActivate = 2
|
||||
ActivationFlag_OnDeath = 10h
|
||||
ActivationFlag_OnKnockout = 20h
|
||||
ActivationFlag_OnMurder = 40h
|
||||
ActivationFlag_DoorOpening = 100h
|
||||
ActivationFlag_DoorClosing = 200h
|
||||
ActivationFlag_DoorJammedOpening = 400h
|
||||
ActivationFlag_DoorJammedClosing = 800h
|
||||
*/
|
||||
esm.skipHSub();
|
||||
}
|
||||
|
||||
if (esm.isNextSub("STPR"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("MNAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
bool isDeleted = false;
|
||||
ESM::CellRef::loadData(esm, isDeleted);
|
||||
|
||||
mHasACDT = false;
|
||||
if (esm.isNextSub("ACDT"))
|
||||
{
|
||||
mHasACDT = true;
|
||||
esm.getHT(mACDT);
|
||||
}
|
||||
|
||||
mHasACSC = false;
|
||||
if (esm.isNextSub("ACSC"))
|
||||
{
|
||||
mHasACSC = true;
|
||||
esm.getHT(mACSC);
|
||||
}
|
||||
|
||||
if (esm.isNextSub("ACSL"))
|
||||
esm.skipHSubSize(112);
|
||||
|
||||
if (esm.isNextSub("CSTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
if (esm.isNextSub("LSTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
// unsure at which point between LSTN and TGTN
|
||||
if (esm.isNextSub("CSHN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
// unsure if before or after CSTN/LSTN
|
||||
if (esm.isNextSub("LSHN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
while (esm.isNextSub("TGTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
while (esm.isNextSub("FGTN"))
|
||||
esm.getHString(); // fight target?
|
||||
|
||||
// unsure at which point between TGTN and CRED
|
||||
if (esm.isNextSub("AADT"))
|
||||
{
|
||||
// occurred when a creature was in the middle of its attack, 44 bytes
|
||||
esm.skipHSub();
|
||||
}
|
||||
|
||||
// unsure at which point between FGTN and CHRD
|
||||
if (esm.isNextSub("PWPC"))
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("PWPS"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("WNAM"))
|
||||
{
|
||||
std::string id = esm.getHString();
|
||||
|
||||
if (esm.isNextSub("XNAM"))
|
||||
mSelectedEnchantItem = esm.getHString();
|
||||
else
|
||||
mSelectedSpell = id;
|
||||
|
||||
if (esm.isNextSub("YNAM"))
|
||||
esm.skipHSub(); // 4 byte, 0
|
||||
}
|
||||
|
||||
while (esm.isNextSub("APUD"))
|
||||
{
|
||||
// used power
|
||||
esm.getSubHeader();
|
||||
std::string id = esm.getString(32);
|
||||
(void)id;
|
||||
// timestamp can't be used: this is the total hours passed, calculated by
|
||||
// timestamp = 24 * (365 * year + cumulativeDays[month] + day)
|
||||
// unfortunately cumulativeDays[month] is not clearly defined,
|
||||
// in the (non-MCP) vanilla version the first month was missing, but MCP added it.
|
||||
double timestamp;
|
||||
esm.getT(timestamp);
|
||||
}
|
||||
|
||||
// FIXME: not all actors have this, add flag
|
||||
if (esm.isNextSub("CHRD")) // npc only
|
||||
esm.getHExact(mSkills, 27*2*sizeof(int));
|
||||
|
||||
if (esm.isNextSub("CRED")) // creature only
|
||||
esm.getHExact(mCombatStats, 3*2*sizeof(int));
|
||||
|
||||
mSCRI.load(esm);
|
||||
|
||||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub();
|
||||
|
||||
mHasANIS = false;
|
||||
if (esm.isNextSub("ANIS"))
|
||||
{
|
||||
mHasANIS = true;
|
||||
esm.getHT(mANIS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <components/esm/cellref.hpp>
|
||||
|
||||
#include "importscri.hpp"
|
||||
|
||||
namespace ESM
|
||||
|
@ -40,7 +38,8 @@ namespace ESSImport
|
|||
float mDynamic[3][2];
|
||||
unsigned char mUnknown3[16];
|
||||
float mAttributes[8][2];
|
||||
float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
|
||||
float mMagicEffects[27]; // Effect attributes:
|
||||
// https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
|
||||
unsigned char mUnknown4[4];
|
||||
unsigned int mGoldPool;
|
||||
unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe
|
||||
|
@ -63,7 +62,7 @@ namespace ESSImport
|
|||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct ActorData : public ESM::CellRef
|
||||
struct ActorData
|
||||
{
|
||||
bool mHasACDT;
|
||||
ACDT mACDT;
|
||||
|
@ -85,10 +84,6 @@ namespace ESSImport
|
|||
|
||||
bool mHasANIS;
|
||||
ANIS mANIS; // scripted animation state
|
||||
|
||||
virtual void load(ESM::ESMReader& esm);
|
||||
|
||||
virtual ~ActorData() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,32 +1,152 @@
|
|||
#include "importcellref.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void CellRef::load(ESM::ESMReader &esm)
|
||||
void CellRef::load(ESM::ESMReader& esm)
|
||||
{
|
||||
blank();
|
||||
|
||||
// (FRMR subrecord name is already read by the loop in ConvertCell)
|
||||
esm.getHT(mRefNum.mIndex); // FRMR
|
||||
esm.getHNT(mRefNum.mIndex, "FRMR");
|
||||
|
||||
// this is required since openmw supports more than 255 content files
|
||||
int pluginIndex = (mRefNum.mIndex & 0xff000000) >> 24;
|
||||
mRefNum.mContentFile = pluginIndex-1;
|
||||
mRefNum.mContentFile = pluginIndex - 1;
|
||||
mRefNum.mIndex &= 0x00ffffff;
|
||||
|
||||
mIndexedRefId = esm.getHNString("NAME");
|
||||
|
||||
ActorData::load(esm);
|
||||
if (esm.isNextSub("ACTN"))
|
||||
{
|
||||
/*
|
||||
Activation flags:
|
||||
ActivationFlag_UseEnabled = 1
|
||||
ActivationFlag_OnActivate = 2
|
||||
ActivationFlag_OnDeath = 10h
|
||||
ActivationFlag_OnKnockout = 20h
|
||||
ActivationFlag_OnMurder = 40h
|
||||
ActivationFlag_DoorOpening = 100h
|
||||
ActivationFlag_DoorClosing = 200h
|
||||
ActivationFlag_DoorJammedOpening = 400h
|
||||
ActivationFlag_DoorJammedClosing = 800h
|
||||
*/
|
||||
esm.skipHSub();
|
||||
}
|
||||
|
||||
if (esm.isNextSub("STPR"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("MNAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
bool isDeleted = false;
|
||||
ESM::CellRef::loadData(esm, isDeleted);
|
||||
|
||||
mActorData.mHasACDT = false;
|
||||
if (esm.isNextSub("ACDT"))
|
||||
{
|
||||
mActorData.mHasACDT = true;
|
||||
esm.getHT(mActorData.mACDT);
|
||||
}
|
||||
|
||||
mActorData.mHasACSC = false;
|
||||
if (esm.isNextSub("ACSC"))
|
||||
{
|
||||
mActorData.mHasACSC = true;
|
||||
esm.getHT(mActorData.mACSC);
|
||||
}
|
||||
|
||||
if (esm.isNextSub("ACSL"))
|
||||
esm.skipHSubSize(112);
|
||||
|
||||
if (esm.isNextSub("CSTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
if (esm.isNextSub("LSTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
// unsure at which point between LSTN and TGTN
|
||||
if (esm.isNextSub("CSHN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
// unsure if before or after CSTN/LSTN
|
||||
if (esm.isNextSub("LSHN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
while (esm.isNextSub("TGTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
|
||||
while (esm.isNextSub("FGTN"))
|
||||
esm.getHString(); // fight target?
|
||||
|
||||
// unsure at which point between TGTN and CRED
|
||||
if (esm.isNextSub("AADT"))
|
||||
{
|
||||
// occurred when a creature was in the middle of its attack, 44 bytes
|
||||
esm.skipHSub();
|
||||
}
|
||||
|
||||
// unsure at which point between FGTN and CHRD
|
||||
if (esm.isNextSub("PWPC"))
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("PWPS"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("WNAM"))
|
||||
{
|
||||
std::string id = esm.getHString();
|
||||
|
||||
if (esm.isNextSub("XNAM"))
|
||||
mActorData.mSelectedEnchantItem = esm.getHString();
|
||||
else
|
||||
mActorData.mSelectedSpell = id;
|
||||
|
||||
if (esm.isNextSub("YNAM"))
|
||||
esm.skipHSub(); // 4 byte, 0
|
||||
}
|
||||
|
||||
while (esm.isNextSub("APUD"))
|
||||
{
|
||||
// used power
|
||||
esm.getSubHeader();
|
||||
std::string id = esm.getMaybeFixedStringSize(32);
|
||||
(void)id;
|
||||
// timestamp can't be used: this is the total hours passed, calculated by
|
||||
// timestamp = 24 * (365 * year + cumulativeDays[month] + day)
|
||||
// unfortunately cumulativeDays[month] is not clearly defined,
|
||||
// in the (non-MCP) vanilla version the first month was missing, but MCP added it.
|
||||
double timestamp;
|
||||
esm.getT(timestamp);
|
||||
}
|
||||
|
||||
// FIXME: not all actors have this, add flag
|
||||
if (esm.isNextSub("CHRD")) // npc only
|
||||
esm.getHExact(mActorData.mSkills, 27 * 2 * sizeof(int));
|
||||
|
||||
if (esm.isNextSub("CRED")) // creature only
|
||||
esm.getHExact(mActorData.mCombatStats, 3 * 2 * sizeof(int));
|
||||
|
||||
mActorData.mSCRI.load(esm);
|
||||
|
||||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub();
|
||||
|
||||
mActorData.mHasANIS = false;
|
||||
if (esm.isNextSub("ANIS"))
|
||||
{
|
||||
mActorData.mHasANIS = true;
|
||||
esm.getHT(mActorData.mANIS);
|
||||
}
|
||||
|
||||
if (esm.isNextSub("LVCR"))
|
||||
{
|
||||
// occurs on levelled creature spawner references
|
||||
// probably some identifier for the creature that has been spawned?
|
||||
unsigned char lvcr;
|
||||
esm.getHT(lvcr);
|
||||
//std::cout << "LVCR: " << (int)lvcr << std::endl;
|
||||
// std::cout << "LVCR: " << (int)lvcr << std::endl;
|
||||
}
|
||||
|
||||
mEnabled = true;
|
||||
|
@ -35,8 +155,8 @@ namespace ESSImport
|
|||
// DATA should occur for all references, except levelled creature spawners
|
||||
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
||||
// alarmvoi0000.ess
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
esm.getHNOTSized<24>(mPos, "DATA");
|
||||
esm.getHNOTSized<24>(mPos, "DATA");
|
||||
|
||||
mDeleted = 0;
|
||||
if (esm.isNextSub("DELE"))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <components/esm/cellref.hpp>
|
||||
#include <components/esm3/cellref.hpp>
|
||||
|
||||
#include "importacdt.hpp"
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace ESM
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
struct CellRef : public ActorData
|
||||
struct CellRef : public ESM::CellRef
|
||||
{
|
||||
std::string mIndexedRefId;
|
||||
|
||||
|
@ -25,9 +25,11 @@ namespace ESSImport
|
|||
|
||||
bool mDeleted;
|
||||
|
||||
void load(ESM::ESMReader& esm) override;
|
||||
ActorData mActorData;
|
||||
|
||||
virtual ~CellRef() = default;
|
||||
void load(ESM::ESMReader& esm);
|
||||
|
||||
~CellRef() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importcntc.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void CNTC::load(ESM::ESMReader &esm)
|
||||
void CNTC::load(ESM::ESMReader& esm)
|
||||
{
|
||||
mIndex = 0;
|
||||
esm.getHNT(mIndex, "INDX");
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importcrec.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void CREC::load(ESM::ESMReader &esm)
|
||||
void CREC::load(ESM::ESMReader& esm)
|
||||
{
|
||||
esm.getHNT(mIndex, "INDX");
|
||||
|
||||
|
@ -14,9 +14,8 @@ namespace ESSImport
|
|||
float scale;
|
||||
esm.getHNOT(scale, "XSCL");
|
||||
|
||||
|
||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||
|| esm.isNextSub("AI_A"))
|
||||
|| esm.isNextSub("AI_A"))
|
||||
mAiPackages.add(esm);
|
||||
|
||||
mInventory.load(esm);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define OPENMW_ESSIMPORT_CREC_H
|
||||
|
||||
#include "importinventory.hpp"
|
||||
#include <components/esm/aipackage.hpp>
|
||||
#include <components/esm3/aipackage.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importdial.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void DIAL::load(ESM::ESMReader &esm)
|
||||
void DIAL::load(ESM::ESMReader& esm)
|
||||
{
|
||||
// See ESM::Dialogue::Type enum, not sure why we would need this here though
|
||||
int type = 0;
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
#include "importer.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osg/ImageUtils>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
|
||||
#include <components/esm/savedgame.hpp>
|
||||
#include <components/esm/player.hpp>
|
||||
#include <components/esm3/player.hpp>
|
||||
#include <components/esm3/savedgame.hpp>
|
||||
|
||||
#include <components/esm/loadalch.hpp>
|
||||
#include <components/esm/loadspel.hpp>
|
||||
#include <components/esm/loadarmo.hpp>
|
||||
#include <components/esm/loadweap.hpp>
|
||||
#include <components/esm/loadclot.hpp>
|
||||
#include <components/esm/loadench.hpp>
|
||||
#include <components/esm/loadlevlist.hpp>
|
||||
#include <components/esm3/cellid.hpp>
|
||||
#include <components/esm3/loadalch.hpp>
|
||||
#include <components/esm3/loadarmo.hpp>
|
||||
#include <components/esm3/loadclot.hpp>
|
||||
#include <components/esm3/loadench.hpp>
|
||||
#include <components/esm3/loadlevlist.hpp>
|
||||
#include <components/esm3/loadspel.hpp>
|
||||
#include <components/esm3/loadweap.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
|
@ -36,25 +36,25 @@ namespace
|
|||
|
||||
void writeScreenshot(const ESM::Header& fileHeader, ESM::SavedGame& out)
|
||||
{
|
||||
if (fileHeader.mSCRS.size() != 128*128*4)
|
||||
if (fileHeader.mSCRS.size() != 128 * 128 * 4)
|
||||
{
|
||||
std::cerr << "Error: unexpected screenshot size " << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Image> image (new osg::Image);
|
||||
osg::ref_ptr<osg::Image> image(new osg::Image);
|
||||
image->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE);
|
||||
|
||||
// need to convert pixel format from BGRA to RGB as the jpg readerwriter doesn't support it otherwise
|
||||
auto it = fileHeader.mSCRS.begin();
|
||||
for (int y=0; y<128; ++y)
|
||||
for (int y = 0; y < 128; ++y)
|
||||
{
|
||||
for (int x=0; x<128; ++x)
|
||||
for (int x = 0; x < 128; ++x)
|
||||
{
|
||||
assert(image->data(x,y));
|
||||
*(image->data(x,y)+2) = *it++;
|
||||
*(image->data(x,y)+1) = *it++;
|
||||
*image->data(x,y) = *it++;
|
||||
assert(image->data(x, y));
|
||||
*(image->data(x, y) + 2) = *it++;
|
||||
*(image->data(x, y) + 1) = *it++;
|
||||
*image->data(x, y) = *it++;
|
||||
++it; // skip alpha
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,8 @@ namespace
|
|||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image, ostream);
|
||||
if (!result.success())
|
||||
{
|
||||
std::cerr << "Error: can't write screenshot: " << result.message() << " code " << result.status() << std::endl;
|
||||
std::cerr << "Error: can't write screenshot: " << result.message() << " code " << result.status()
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -86,12 +87,12 @@ namespace
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
Importer::Importer(const std::string &essfile, const std::string &outfile, const std::string &encoding)
|
||||
Importer::Importer(
|
||||
const std::filesystem::path& essfile, const std::filesystem::path& outfile, const std::string& encoding)
|
||||
: mEssFile(essfile)
|
||||
, mOutFile(outfile)
|
||||
, mEncoding(encoding)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
struct File
|
||||
|
@ -113,7 +114,7 @@ namespace ESSImport
|
|||
std::vector<Record> mRecords;
|
||||
};
|
||||
|
||||
void read(const std::string& filename, File& file)
|
||||
void read(const std::filesystem::path& filename, File& file)
|
||||
{
|
||||
ESM::ESMReader esm;
|
||||
esm.open(filename);
|
||||
|
@ -144,14 +145,14 @@ namespace ESSImport
|
|||
void Importer::compare()
|
||||
{
|
||||
// data that always changes (and/or is already fully decoded) should be blacklisted
|
||||
std::set<std::pair<std::string, std::string> > blacklist;
|
||||
std::set<std::pair<std::string, std::string>> blacklist;
|
||||
blacklist.insert(std::make_pair("GLOB", "FLTV")); // gamehour
|
||||
blacklist.insert(std::make_pair("REFR", "DATA")); // player position
|
||||
blacklist.insert(std::make_pair("CELL", "NAM8")); // fog of war
|
||||
blacklist.insert(std::make_pair("GAME", "GMDT")); // weather data, current time always changes
|
||||
blacklist.insert(std::make_pair("CELL", "DELE")); // first 3 bytes are uninitialized
|
||||
|
||||
// this changes way too often, name suggests some renderer internal data?
|
||||
// this changes way too often, name suggests some renderer internal data?
|
||||
blacklist.insert(std::make_pair("CELL", "ND3D"));
|
||||
blacklist.insert(std::make_pair("REFR", "ND3D"));
|
||||
|
||||
|
@ -161,7 +162,7 @@ namespace ESSImport
|
|||
read(mOutFile, file2); // todo rename variable
|
||||
|
||||
// FIXME: use max(size1, size2)
|
||||
for (unsigned int i=0; i<file1.mRecords.size(); ++i)
|
||||
for (size_t i = 0; i < file1.mRecords.size(); ++i)
|
||||
{
|
||||
File::Record rec = file1.mRecords[i];
|
||||
|
||||
|
@ -184,14 +185,15 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
// FIXME: use max(size1, size2)
|
||||
for (unsigned int j=0; j<rec.mSubrecords.size(); ++j)
|
||||
for (size_t j = 0; j < rec.mSubrecords.size(); ++j)
|
||||
{
|
||||
File::Subrecord sub = rec.mSubrecords[j];
|
||||
|
||||
if (j >= rec2.mSubrecords.size())
|
||||
{
|
||||
std::ios::fmtflags f(std::cout.flags());
|
||||
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset << std::endl;
|
||||
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset
|
||||
<< std::endl;
|
||||
std::cout.flags(f);
|
||||
return;
|
||||
}
|
||||
|
@ -201,8 +203,9 @@ namespace ESSImport
|
|||
if (sub.mName != sub2.mName)
|
||||
{
|
||||
std::ios::fmtflags f(std::cout.flags());
|
||||
std::cout << "Different subrecord name (" << rec.mName << "." << sub.mName << " vs. " << sub2.mName << ") at (1) 0x" << std::hex << sub.mFileOffset
|
||||
<< " (2) 0x" << sub2.mFileOffset << std::endl;
|
||||
std::cout << "Different subrecord name (" << rec.mName << "." << sub.mName << " vs. " << sub2.mName
|
||||
<< ") at (1) 0x" << std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset
|
||||
<< std::endl;
|
||||
std::cout.flags(f);
|
||||
break; // TODO: try to recover
|
||||
}
|
||||
|
@ -214,11 +217,11 @@ namespace ESSImport
|
|||
|
||||
std::ios::fmtflags f(std::cout.flags());
|
||||
|
||||
std::cout << "Different subrecord data for " << rec.mName << "." << sub.mName << " at (1) 0x" << std::hex << sub.mFileOffset
|
||||
<< " (2) 0x" << sub2.mFileOffset << std::endl;
|
||||
std::cout << "Different subrecord data for " << rec.mName << "." << sub.mName << " at (1) 0x"
|
||||
<< std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset << std::endl;
|
||||
|
||||
std::cout << "Data 1:" << std::endl;
|
||||
for (unsigned int k=0; k<sub.mData.size(); ++k)
|
||||
for (size_t k = 0; k < sub.mData.size(); ++k)
|
||||
{
|
||||
bool different = false;
|
||||
if (k >= sub2.mData.size() || sub2.mData[k] != sub.mData[k])
|
||||
|
@ -233,7 +236,7 @@ namespace ESSImport
|
|||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Data 2:" << std::endl;
|
||||
for (unsigned int k=0; k<sub2.mData.size(); ++k)
|
||||
for (size_t k = 0; k < sub2.mData.size(); ++k)
|
||||
{
|
||||
bool different = false;
|
||||
if (k >= sub.mData.size() || sub.mData[k] != sub2.mData[k])
|
||||
|
@ -264,48 +267,48 @@ namespace ESSImport
|
|||
const ESM::Header& header = esm.getHeader();
|
||||
context.mPlayerCellName = header.mGameData.mCurrentCell.toString();
|
||||
|
||||
const unsigned int recREFR = ESM::FourCC<'R','E','F','R'>::value;
|
||||
const unsigned int recPCDT = ESM::FourCC<'P','C','D','T'>::value;
|
||||
const unsigned int recFMAP = ESM::FourCC<'F','M','A','P'>::value;
|
||||
const unsigned int recKLST = ESM::FourCC<'K','L','S','T'>::value;
|
||||
const unsigned int recSTLN = ESM::FourCC<'S','T','L','N'>::value;
|
||||
const unsigned int recGAME = ESM::FourCC<'G','A','M','E'>::value;
|
||||
const unsigned int recJOUR = ESM::FourCC<'J','O','U','R'>::value;
|
||||
const unsigned int recSPLM = ESM::FourCC<'S','P','L','M'>::value;
|
||||
const unsigned int recREFR = ESM::fourCC("REFR");
|
||||
const unsigned int recPCDT = ESM::fourCC("PCDT");
|
||||
const unsigned int recFMAP = ESM::fourCC("FMAP");
|
||||
const unsigned int recKLST = ESM::fourCC("KLST");
|
||||
const unsigned int recSTLN = ESM::fourCC("STLN");
|
||||
const unsigned int recGAME = ESM::fourCC("GAME");
|
||||
const unsigned int recJOUR = ESM::fourCC("JOUR");
|
||||
const unsigned int recSPLM = ESM::fourCC("SPLM");
|
||||
|
||||
std::map<unsigned int, std::shared_ptr<Converter> > converters;
|
||||
converters[ESM::REC_GLOB] = std::shared_ptr<Converter>(new ConvertGlobal());
|
||||
converters[ESM::REC_BOOK] = std::shared_ptr<Converter>(new ConvertBook());
|
||||
converters[ESM::REC_NPC_] = std::shared_ptr<Converter>(new ConvertNPC());
|
||||
converters[ESM::REC_CREA] = std::shared_ptr<Converter>(new ConvertCREA());
|
||||
converters[ESM::REC_NPCC] = std::shared_ptr<Converter>(new ConvertNPCC());
|
||||
converters[ESM::REC_CREC] = std::shared_ptr<Converter>(new ConvertCREC());
|
||||
converters[recREFR ] = std::shared_ptr<Converter>(new ConvertREFR());
|
||||
converters[recPCDT ] = std::shared_ptr<Converter>(new ConvertPCDT());
|
||||
converters[recFMAP ] = std::shared_ptr<Converter>(new ConvertFMAP());
|
||||
converters[recKLST ] = std::shared_ptr<Converter>(new ConvertKLST());
|
||||
converters[recSTLN ] = std::shared_ptr<Converter>(new ConvertSTLN());
|
||||
converters[recGAME ] = std::shared_ptr<Converter>(new ConvertGAME());
|
||||
converters[ESM::REC_CELL] = std::shared_ptr<Converter>(new ConvertCell());
|
||||
converters[ESM::REC_ALCH] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Potion>());
|
||||
converters[ESM::REC_CLAS] = std::shared_ptr<Converter>(new ConvertClass());
|
||||
converters[ESM::REC_SPEL] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Spell>());
|
||||
converters[ESM::REC_ARMO] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Armor>());
|
||||
converters[ESM::REC_WEAP] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Weapon>());
|
||||
converters[ESM::REC_CLOT] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Clothing>());
|
||||
converters[ESM::REC_ENCH] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Enchantment>());
|
||||
converters[ESM::REC_WEAP] = std::shared_ptr<Converter>(new DefaultConverter<ESM::Weapon>());
|
||||
converters[ESM::REC_LEVC] = std::shared_ptr<Converter>(new DefaultConverter<ESM::CreatureLevList>());
|
||||
converters[ESM::REC_LEVI] = std::shared_ptr<Converter>(new DefaultConverter<ESM::ItemLevList>());
|
||||
converters[ESM::REC_CNTC] = std::shared_ptr<Converter>(new ConvertCNTC());
|
||||
converters[ESM::REC_FACT] = std::shared_ptr<Converter>(new ConvertFACT());
|
||||
converters[ESM::REC_INFO] = std::shared_ptr<Converter>(new ConvertINFO());
|
||||
converters[ESM::REC_DIAL] = std::shared_ptr<Converter>(new ConvertDIAL());
|
||||
converters[ESM::REC_QUES] = std::shared_ptr<Converter>(new ConvertQUES());
|
||||
converters[recJOUR ] = std::shared_ptr<Converter>(new ConvertJOUR());
|
||||
converters[ESM::REC_SCPT] = std::shared_ptr<Converter>(new ConvertSCPT());
|
||||
converters[ESM::REC_PROJ] = std::shared_ptr<Converter>(new ConvertPROJ());
|
||||
converters[recSPLM] = std::shared_ptr<Converter>(new ConvertSPLM());
|
||||
std::map<unsigned int, std::unique_ptr<Converter>> converters;
|
||||
converters[ESM::REC_GLOB] = std::make_unique<ConvertGlobal>();
|
||||
converters[ESM::REC_BOOK] = std::make_unique<ConvertBook>();
|
||||
converters[ESM::REC_NPC_] = std::make_unique<ConvertNPC>();
|
||||
converters[ESM::REC_CREA] = std::make_unique<ConvertCREA>();
|
||||
converters[ESM::REC_NPCC] = std::make_unique<ConvertNPCC>();
|
||||
converters[ESM::REC_CREC] = std::make_unique<ConvertCREC>();
|
||||
converters[recREFR] = std::make_unique<ConvertREFR>();
|
||||
converters[recPCDT] = std::make_unique<ConvertPCDT>();
|
||||
converters[recFMAP] = std::make_unique<ConvertFMAP>();
|
||||
converters[recKLST] = std::make_unique<ConvertKLST>();
|
||||
converters[recSTLN] = std::make_unique<ConvertSTLN>();
|
||||
converters[recGAME] = std::make_unique<ConvertGAME>();
|
||||
converters[ESM::REC_CELL] = std::make_unique<ConvertCell>();
|
||||
converters[ESM::REC_ALCH] = std::make_unique<DefaultConverter<ESM::Potion>>();
|
||||
converters[ESM::REC_CLAS] = std::make_unique<ConvertClass>();
|
||||
converters[ESM::REC_SPEL] = std::make_unique<DefaultConverter<ESM::Spell>>();
|
||||
converters[ESM::REC_ARMO] = std::make_unique<DefaultConverter<ESM::Armor>>();
|
||||
converters[ESM::REC_WEAP] = std::make_unique<DefaultConverter<ESM::Weapon>>();
|
||||
converters[ESM::REC_CLOT] = std::make_unique<DefaultConverter<ESM::Clothing>>();
|
||||
converters[ESM::REC_ENCH] = std::make_unique<DefaultConverter<ESM::Enchantment>>();
|
||||
converters[ESM::REC_WEAP] = std::make_unique<DefaultConverter<ESM::Weapon>>();
|
||||
converters[ESM::REC_LEVC] = std::make_unique<DefaultConverter<ESM::CreatureLevList>>();
|
||||
converters[ESM::REC_LEVI] = std::make_unique<DefaultConverter<ESM::ItemLevList>>();
|
||||
converters[ESM::REC_CNTC] = std::make_unique<ConvertCNTC>();
|
||||
converters[ESM::REC_FACT] = std::make_unique<ConvertFACT>();
|
||||
converters[ESM::REC_INFO] = std::make_unique<ConvertINFO>();
|
||||
converters[ESM::REC_DIAL] = std::make_unique<ConvertDIAL>();
|
||||
converters[ESM::REC_QUES] = std::make_unique<ConvertQUES>();
|
||||
converters[recJOUR] = std::make_unique<ConvertJOUR>();
|
||||
converters[ESM::REC_SCPT] = std::make_unique<ConvertSCPT>();
|
||||
converters[ESM::REC_PROJ] = std::make_unique<ConvertPROJ>();
|
||||
converters[recSPLM] = std::make_unique<ConvertSPLM>();
|
||||
|
||||
// TODO:
|
||||
// - REGN (weather in certain regions?)
|
||||
|
@ -314,7 +317,7 @@ namespace ESSImport
|
|||
|
||||
std::set<unsigned int> unknownRecords;
|
||||
|
||||
for (const auto & converter : converters)
|
||||
for (const auto& converter : converters)
|
||||
{
|
||||
converter.second->setContext(context);
|
||||
}
|
||||
|
@ -324,17 +327,18 @@ namespace ESSImport
|
|||
ESM::NAME n = esm.getRecName();
|
||||
esm.getRecHeader();
|
||||
|
||||
auto it = converters.find(n.intval);
|
||||
auto it = converters.find(n.toInt());
|
||||
if (it != converters.end())
|
||||
{
|
||||
it->second->read(esm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unknownRecords.insert(n.intval).second)
|
||||
if (unknownRecords.insert(n.toInt()).second)
|
||||
{
|
||||
std::ios::fmtflags f(std::cerr.flags());
|
||||
std::cerr << "Error: unknown record " << n.toString() << " (0x" << std::hex << esm.getFileOffset() << ")" << std::endl;
|
||||
std::cerr << "Error: unknown record " << n.toString() << " (0x" << std::hex << esm.getFileOffset()
|
||||
<< ")" << std::endl;
|
||||
std::cerr.flags(f);
|
||||
}
|
||||
|
||||
|
@ -344,23 +348,23 @@ namespace ESSImport
|
|||
|
||||
ESM::ESMWriter writer;
|
||||
|
||||
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
||||
writer.setFormatVersion(ESM::CurrentSaveGameFormatVersion);
|
||||
|
||||
boost::filesystem::ofstream stream(boost::filesystem::path(mOutFile), std::ios::out | std::ios::binary);
|
||||
std::ofstream stream(mOutFile, std::ios::out | std::ios::binary);
|
||||
// all unused
|
||||
writer.setVersion(0);
|
||||
writer.setType(0);
|
||||
writer.setAuthor("");
|
||||
writer.setDescription("");
|
||||
writer.setRecordCount (0);
|
||||
writer.setRecordCount(0);
|
||||
|
||||
for (const auto & master : header.mMaster)
|
||||
for (const auto& master : header.mMaster)
|
||||
writer.addMaster(master.name, 0); // not using the size information anyway -> use value of 0
|
||||
|
||||
writer.save (stream);
|
||||
writer.save(stream);
|
||||
|
||||
ESM::SavedGame profile;
|
||||
for (const auto & master : header.mMaster)
|
||||
for (const auto& master : header.mMaster)
|
||||
{
|
||||
profile.mContentFiles.push_back(master.name);
|
||||
}
|
||||
|
@ -369,7 +373,8 @@ namespace ESSImport
|
|||
profile.mInGameTime.mGameHour = context.mHour;
|
||||
profile.mInGameTime.mMonth = context.mMonth;
|
||||
profile.mInGameTime.mYear = context.mYear;
|
||||
profile.mPlayerCell = header.mGameData.mCurrentCell.toString();
|
||||
profile.mTimePlayed = 0;
|
||||
profile.mPlayerCellName = context.mPlayerCellName;
|
||||
if (context.mPlayerBase.mClass == "NEWCLASSID_CHARGEN")
|
||||
profile.mPlayerClassName = context.mCustomPlayerClassName;
|
||||
else
|
||||
|
@ -379,14 +384,13 @@ namespace ESSImport
|
|||
|
||||
writeScreenshot(header, profile);
|
||||
|
||||
writer.startRecord (ESM::REC_SAVE);
|
||||
profile.save (writer);
|
||||
writer.endRecord (ESM::REC_SAVE);
|
||||
writer.startRecord(ESM::REC_SAVE);
|
||||
profile.save(writer);
|
||||
writer.endRecord(ESM::REC_SAVE);
|
||||
|
||||
// Writing order should be Dynamic Store -> Cells -> Player,
|
||||
// so that references to dynamic records can be recognized when loading
|
||||
for (std::map<unsigned int, std::shared_ptr<Converter> >::const_iterator it = converters.begin();
|
||||
it != converters.end(); ++it)
|
||||
for (auto it = converters.begin(); it != converters.end(); ++it)
|
||||
{
|
||||
if (it->second->getStage() != 0)
|
||||
continue;
|
||||
|
@ -394,12 +398,11 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
writer.startRecord(ESM::REC_NPC_);
|
||||
context.mPlayerBase.mId = "player";
|
||||
context.mPlayerBase.mId = ESM::RefId::stringRefId("Player");
|
||||
context.mPlayerBase.save(writer);
|
||||
writer.endRecord(ESM::REC_NPC_);
|
||||
|
||||
for (std::map<unsigned int, std::shared_ptr<Converter> >::const_iterator it = converters.begin();
|
||||
it != converters.end(); ++it)
|
||||
for (auto it = converters.begin(); it != converters.end(); ++it)
|
||||
{
|
||||
if (it->second->getStage() != 1)
|
||||
continue;
|
||||
|
@ -407,14 +410,11 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
writer.startRecord(ESM::REC_PLAY);
|
||||
if (context.mPlayer.mCellId.mPaged)
|
||||
{
|
||||
// exterior cell -> determine cell coordinates based on position
|
||||
int cellX = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[0] / Constants::CellSizeInUnits));
|
||||
int cellY = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[1] / Constants::CellSizeInUnits));
|
||||
context.mPlayer.mCellId.mIndex.mX = cellX;
|
||||
context.mPlayer.mCellId.mIndex.mY = cellY;
|
||||
}
|
||||
ESM::CellId cellId = ESM::CellId::extractFromRefId(context.mPlayer.mCellId);
|
||||
int cellX = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[0] / Constants::CellSizeInUnits));
|
||||
int cellY = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[1] / Constants::CellSizeInUnits));
|
||||
|
||||
context.mPlayer.mCellId = ESM::Cell::generateIdForCell(cellId.mPaged, cellId.mWorldspace, cellX, cellY);
|
||||
context.mPlayer.save(writer);
|
||||
writer.endRecord(ESM::REC_PLAY);
|
||||
|
||||
|
@ -423,15 +423,14 @@ namespace ESSImport
|
|||
writer.endRecord(ESM::REC_ACTC);
|
||||
|
||||
// Stage 2 requires cell references to be written / actors IDs assigned
|
||||
for (std::map<unsigned int, std::shared_ptr<Converter> >::const_iterator it = converters.begin();
|
||||
it != converters.end(); ++it)
|
||||
for (auto it = converters.begin(); it != converters.end(); ++it)
|
||||
{
|
||||
if (it->second->getStage() != 2)
|
||||
continue;
|
||||
it->second->write(writer);
|
||||
}
|
||||
|
||||
writer.startRecord (ESM::REC_DIAS);
|
||||
writer.startRecord(ESM::REC_DIAS);
|
||||
context.mDialogueState.save(writer);
|
||||
writer.endRecord(ESM::REC_DIAS);
|
||||
|
||||
|
@ -440,5 +439,4 @@ namespace ESSImport
|
|||
writer.endRecord(ESM::REC_INPU);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef OPENMW_ESSIMPORTER_IMPORTER_H
|
||||
#define OPENMW_ESSIMPORTER_IMPORTER_H
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
@ -9,15 +9,16 @@ namespace ESSImport
|
|||
class Importer
|
||||
{
|
||||
public:
|
||||
Importer(const std::string& essfile, const std::string& outfile, const std::string& encoding);
|
||||
Importer(
|
||||
const std::filesystem::path& essfile, const std::filesystem::path& outfile, const std::string& encoding);
|
||||
|
||||
void run();
|
||||
|
||||
void compare();
|
||||
|
||||
private:
|
||||
std::string mEssFile;
|
||||
std::string mOutFile;
|
||||
std::filesystem::path mEssFile;
|
||||
std::filesystem::path mOutFile;
|
||||
std::string mEncoding;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,22 +3,19 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/player.hpp>
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
#include <components/esm/globalmap.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/controlsstate.hpp>
|
||||
#include <components/esm3/controlsstate.hpp>
|
||||
#include <components/esm3/dialoguestate.hpp>
|
||||
#include <components/esm3/globalmap.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/esm3/loadcrea.hpp>
|
||||
#include <components/esm3/loadnpc.hpp>
|
||||
#include <components/esm3/player.hpp>
|
||||
|
||||
#include "importnpcc.hpp"
|
||||
#include "importcrec.hpp"
|
||||
#include "importcntc.hpp"
|
||||
#include "importplayer.hpp"
|
||||
#include "importcrec.hpp"
|
||||
#include "importnpcc.hpp"
|
||||
#include "importsplm.h"
|
||||
|
||||
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
|
@ -36,7 +33,7 @@ namespace ESSImport
|
|||
ESM::ControlsState mControlsState;
|
||||
|
||||
// cells which should show an explored overlay on the global map
|
||||
std::set<std::pair<int, int> > mExploredCells;
|
||||
std::set<std::pair<int, int>> mExploredCells;
|
||||
|
||||
ESM::GlobalMap mGlobalMapState;
|
||||
|
||||
|
@ -44,15 +41,15 @@ namespace ESSImport
|
|||
float mHour;
|
||||
|
||||
// key <refIndex, refId>
|
||||
std::map<std::pair<int, std::string>, CREC> mCreatureChanges;
|
||||
std::map<std::pair<int, std::string>, NPCC> mNpcChanges;
|
||||
std::map<std::pair<int, std::string>, CNTC> mContainerChanges;
|
||||
std::map<std::pair<int, ESM::RefId>, CREC> mCreatureChanges;
|
||||
std::map<std::pair<int, ESM::RefId>, NPCC> mNpcChanges;
|
||||
std::map<std::pair<int, ESM::RefId>, CNTC> mContainerChanges;
|
||||
|
||||
std::map<std::pair<int, std::string>, int> mActorIdMap;
|
||||
std::map<std::pair<int, ESM::RefId>, int> mActorIdMap;
|
||||
int mNextActorId;
|
||||
|
||||
std::map<std::string, ESM::Creature> mCreatures;
|
||||
std::map<std::string, ESM::NPC> mNpcs;
|
||||
std::map<ESM::RefId, ESM::Creature> mCreatures;
|
||||
std::map<ESM::RefId, ESM::NPC> mNpcs;
|
||||
|
||||
std::vector<SPLM::ActiveSpell> mActiveSpells;
|
||||
|
||||
|
@ -63,20 +60,15 @@ namespace ESSImport
|
|||
, mHour(0.f)
|
||||
, mNextActorId(0)
|
||||
{
|
||||
ESM::CellId playerCellId;
|
||||
playerCellId.mPaged = true;
|
||||
playerCellId.mIndex.mX = playerCellId.mIndex.mY = 0;
|
||||
mPlayer.mCellId = playerCellId;
|
||||
mPlayer.mLastKnownExteriorPosition[0]
|
||||
= mPlayer.mLastKnownExteriorPosition[1]
|
||||
= mPlayer.mLastKnownExteriorPosition[2]
|
||||
= 0.0f;
|
||||
mPlayer.mCellId = ESM::RefId::esm3ExteriorCell(0, 0);
|
||||
mPlayer.mLastKnownExteriorPosition[0] = mPlayer.mLastKnownExteriorPosition[1]
|
||||
= mPlayer.mLastKnownExteriorPosition[2] = 0.0f;
|
||||
mPlayer.mHasMark = 0;
|
||||
mPlayer.mCurrentCrimeId = -1; // TODO
|
||||
mPlayer.mPaidCrimeId = -1;
|
||||
mPlayer.mObject.blank();
|
||||
mPlayer.mObject.mEnabled = true;
|
||||
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
||||
mPlayer.mObject.mRef.mRefID = ESM::RefId::stringRefId("player"); // REFR.mRefID would be PlayerSaveGame
|
||||
mPlayer.mObject.mCreatureStats.mActorId = generateActorId();
|
||||
|
||||
mGlobalMapState.mBounds.mMinX = 0;
|
||||
|
@ -87,10 +79,7 @@ namespace ESSImport
|
|||
mPlayerBase.blank();
|
||||
}
|
||||
|
||||
int generateActorId()
|
||||
{
|
||||
return mNextActorId++;
|
||||
}
|
||||
int generateActorId() { return mNextActorId++; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
#include "importgame.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void GAME::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getSubNameIs("GMDT");
|
||||
esm.getSubHeader();
|
||||
if (esm.getSubSize() == 92)
|
||||
void GAME::load(ESM::ESMReader& esm)
|
||||
{
|
||||
esm.getExact(&mGMDT, 92);
|
||||
mGMDT.mSecundaPhase = 0;
|
||||
}
|
||||
else if (esm.getSubSize() == 96)
|
||||
{
|
||||
esm.getT(mGMDT);
|
||||
}
|
||||
else
|
||||
esm.fail("unexpected subrecord size for GAME.GMDT");
|
||||
esm.getSubNameIs("GMDT");
|
||||
esm.getSubHeader();
|
||||
if (esm.getSubSize() == 92)
|
||||
{
|
||||
esm.getExact(&mGMDT, 92);
|
||||
mGMDT.mSecundaPhase = 0;
|
||||
}
|
||||
else if (esm.getSubSize() == 96)
|
||||
{
|
||||
esm.getT(mGMDT);
|
||||
}
|
||||
else
|
||||
esm.fail("unexpected subrecord size for GAME.GMDT");
|
||||
|
||||
mGMDT.mWeatherTransition &= (0x000000ff);
|
||||
mGMDT.mSecundaPhase &= (0x000000ff);
|
||||
mGMDT.mMasserPhase &= (0x000000ff);
|
||||
}
|
||||
mGMDT.mWeatherTransition &= (0x000000ff);
|
||||
mGMDT.mSecundaPhase &= (0x000000ff);
|
||||
mGMDT.mMasserPhase &= (0x000000ff);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,13 +14,13 @@ namespace ESSImport
|
|||
{
|
||||
struct GMDT
|
||||
{
|
||||
char mCellName[64] {};
|
||||
int mFogColour {0};
|
||||
float mFogDensity {0.f};
|
||||
int mCurrentWeather {0}, mNextWeather {0};
|
||||
int mWeatherTransition {0}; // 0-100 transition between weathers, top 3 bytes may be garbage
|
||||
float mTimeOfNextTransition {0.f}; // weather changes when gamehour == timeOfNextTransition
|
||||
int mMasserPhase {0}, mSecundaPhase {0}; // top 3 bytes may be garbage
|
||||
char mCellName[64]{};
|
||||
int mFogColour{ 0 };
|
||||
float mFogDensity{ 0.f };
|
||||
int mCurrentWeather{ 0 }, mNextWeather{ 0 };
|
||||
int mWeatherTransition{ 0 }; // 0-100 transition between weathers, top 3 bytes may be garbage
|
||||
float mTimeOfNextTransition{ 0.f }; // weather changes when gamehour == timeOfNextTransition
|
||||
int mMasserPhase{ 0 }, mSecundaPhase{ 0 }; // top 3 bytes may be garbage
|
||||
};
|
||||
|
||||
GMDT mGMDT;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importinfo.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void INFO::load(ESM::ESMReader &esm)
|
||||
void INFO::load(ESM::ESMReader& esm)
|
||||
{
|
||||
mInfo = esm.getHNString("INAM");
|
||||
mActorRefId = esm.getHNString("ACDT");
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void Inventory::load(ESM::ESMReader &esm)
|
||||
void Inventory::load(ESM::ESMReader& esm)
|
||||
{
|
||||
while (esm.isNextSub("NPCO"))
|
||||
{
|
||||
|
@ -19,11 +19,10 @@ namespace ESSImport
|
|||
item.mCount = contItem.mCount;
|
||||
item.mRelativeEquipmentSlot = -1;
|
||||
item.mLockLevel = 0;
|
||||
item.mRefNum.unset();
|
||||
|
||||
unsigned int itemCount = std::abs(item.mCount);
|
||||
bool separateStacks = false;
|
||||
for (unsigned int i=0;i<itemCount;++i)
|
||||
for (unsigned int i = 0; i < itemCount; ++i)
|
||||
{
|
||||
bool newStack = esm.isNextSub("XIDX");
|
||||
if (newStack)
|
||||
|
@ -40,7 +39,7 @@ namespace ESSImport
|
|||
bool isDeleted = false;
|
||||
item.ESM::CellRef::loadData(esm, isDeleted);
|
||||
|
||||
int charge=-1;
|
||||
int charge = -1;
|
||||
esm.getHNOT(charge, "XHLT");
|
||||
item.mChargeInt = charge;
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTINVENTORY_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTINVENTORY_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/cellref.hpp>
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
#include <components/esm3/cellref.hpp>
|
||||
|
||||
#include "importscri.hpp"
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importjour.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void JOUR::load(ESM::ESMReader &esm)
|
||||
void JOUR::load(ESM::ESMReader& esm)
|
||||
{
|
||||
mText = esm.getHNString("NAME");
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importklst.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void KLST::load(ESM::ESMReader &esm)
|
||||
void KLST::load(ESM::ESMReader& esm)
|
||||
{
|
||||
while (esm.isNextSub("KNAM"))
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef OPENMW_ESSIMPORT_KLST_H
|
||||
#define OPENMW_ESSIMPORT_KLST_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#include "importnpcc.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void NPCC::load(ESM::ESMReader &esm)
|
||||
void NPCC::load(ESM::ESMReader& esm)
|
||||
{
|
||||
esm.getHNT(mNPDT, "NPDT");
|
||||
|
||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||
|| esm.isNextSub("AI_A"))
|
||||
|| esm.isNextSub("AI_A"))
|
||||
mAiPackages.add(esm);
|
||||
|
||||
mInventory.load(esm);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef OPENMW_ESSIMPORT_NPCC_H
|
||||
#define OPENMW_ESSIMPORT_NPCC_H
|
||||
|
||||
#include <components/esm/loadcont.hpp>
|
||||
|
||||
#include <components/esm/aipackage.hpp>
|
||||
#include <components/esm3/aipackage.hpp>
|
||||
|
||||
#include "importinventory.hpp"
|
||||
|
||||
|
@ -29,7 +27,7 @@ namespace ESSImport
|
|||
Inventory mInventory;
|
||||
ESM::AIPackageList mAiPackages;
|
||||
|
||||
void load(ESM::ESMReader &esm);
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,22 +1,11 @@
|
|||
#include "importplayer.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void REFR::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mRefNum.mIndex, "FRMR");
|
||||
|
||||
mRefID = esm.getHNString("NAME");
|
||||
|
||||
mActorData.load(esm);
|
||||
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
}
|
||||
|
||||
void PCDT::load(ESM::ESMReader &esm)
|
||||
void PCDT::load(ESM::ESMReader& esm)
|
||||
{
|
||||
while (esm.isNextSub("DNAM"))
|
||||
{
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
#ifndef OPENMW_ESSIMPORT_PLAYER_H
|
||||
#define OPENMW_ESSIMPORT_PLAYER_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm/cellref.hpp>
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
|
||||
#include "importacdt.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
|
@ -18,108 +14,102 @@ namespace ESM
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// Player-agnostic player data
|
||||
struct REFR
|
||||
{
|
||||
ActorData mActorData;
|
||||
|
||||
std::string mRefID;
|
||||
ESM::Position mPos;
|
||||
ESM::RefNum mRefNum;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
/// Other player data
|
||||
struct PCDT
|
||||
{
|
||||
int mBounty;
|
||||
std::string mBirthsign;
|
||||
|
||||
std::vector<std::string> mKnownDialogueTopics;
|
||||
|
||||
enum PlayerFlags
|
||||
/// Other player data
|
||||
struct PCDT
|
||||
{
|
||||
PlayerFlags_ViewSwitchDisabled = 0x1,
|
||||
PlayerFlags_ControlsDisabled = 0x4,
|
||||
PlayerFlags_Sleeping = 0x10,
|
||||
PlayerFlags_Waiting = 0x40,
|
||||
PlayerFlags_WeaponDrawn = 0x80,
|
||||
PlayerFlags_SpellDrawn = 0x100,
|
||||
PlayerFlags_InJail = 0x200,
|
||||
PlayerFlags_JumpingDisabled = 0x1000,
|
||||
PlayerFlags_LookingDisabled = 0x2000,
|
||||
PlayerFlags_VanityModeDisabled = 0x4000,
|
||||
PlayerFlags_WeaponDrawingDisabled = 0x8000,
|
||||
PlayerFlags_SpellDrawingDisabled = 0x10000,
|
||||
PlayerFlags_ThirdPerson = 0x20000,
|
||||
PlayerFlags_TeleportingDisabled = 0x40000,
|
||||
PlayerFlags_LevitationDisabled = 0x80000
|
||||
};
|
||||
int mBounty;
|
||||
std::string mBirthsign;
|
||||
|
||||
std::vector<std::string> mKnownDialogueTopics;
|
||||
|
||||
enum PlayerFlags
|
||||
{
|
||||
PlayerFlags_ViewSwitchDisabled = 0x1,
|
||||
PlayerFlags_ControlsDisabled = 0x4,
|
||||
PlayerFlags_Sleeping = 0x10,
|
||||
PlayerFlags_Waiting = 0x40,
|
||||
PlayerFlags_WeaponDrawn = 0x80,
|
||||
PlayerFlags_SpellDrawn = 0x100,
|
||||
PlayerFlags_InJail = 0x200,
|
||||
PlayerFlags_JumpingDisabled = 0x1000,
|
||||
PlayerFlags_LookingDisabled = 0x2000,
|
||||
PlayerFlags_VanityModeDisabled = 0x4000,
|
||||
PlayerFlags_WeaponDrawingDisabled = 0x8000,
|
||||
PlayerFlags_SpellDrawingDisabled = 0x10000,
|
||||
PlayerFlags_ThirdPerson = 0x20000,
|
||||
PlayerFlags_TeleportingDisabled = 0x40000,
|
||||
PlayerFlags_LevitationDisabled = 0x80000
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct FNAM
|
||||
{
|
||||
unsigned char mRank;
|
||||
unsigned char mUnknown1[3];
|
||||
int mReputation;
|
||||
unsigned char mFlags; // 0x1: unknown, 0x2: expelled
|
||||
unsigned char mUnknown2[3];
|
||||
ESM::NAME32 mFactionName;
|
||||
};
|
||||
|
||||
struct PNAM
|
||||
{
|
||||
struct MarkLocation
|
||||
struct FNAM
|
||||
{
|
||||
float mX, mY, mZ; // worldspace position
|
||||
float mRotZ; // Z angle in radians
|
||||
int mCellX, mCellY; // grid coordinates; for interior cells this is always (0, 0)
|
||||
unsigned char mRank;
|
||||
unsigned char mUnknown1[3];
|
||||
int mReputation;
|
||||
unsigned char mFlags; // 0x1: unknown, 0x2: expelled
|
||||
unsigned char mUnknown2[3];
|
||||
ESM::NAME32 mFactionName;
|
||||
};
|
||||
|
||||
int mPlayerFlags; // controls, camera and draw state
|
||||
unsigned int mLevelProgress;
|
||||
float mSkillProgress[27]; // skill progress, non-uniform scaled
|
||||
unsigned char mSkillIncreases[8]; // number of skill increases for each attribute
|
||||
int mTelekinesisRangeBonus; // in units; seems redundant
|
||||
float mVisionBonus; // range: <0.0, 1.0>; affected by light spells and Get/Mod/SetPCVisionBonus
|
||||
int mDetectKeyMagnitude; // seems redundant
|
||||
int mDetectEnchantmentMagnitude; // seems redundant
|
||||
int mDetectAnimalMagnitude; // seems redundant
|
||||
MarkLocation mMarkLocation;
|
||||
unsigned char mUnknown3[40];
|
||||
unsigned char mSpecIncreases[3]; // number of skill increases for each specialization
|
||||
unsigned char mUnknown4;
|
||||
};
|
||||
struct PNAM
|
||||
{
|
||||
struct MarkLocation
|
||||
{
|
||||
float mX, mY, mZ; // worldspace position
|
||||
float mRotZ; // Z angle in radians
|
||||
int mCellX, mCellY; // grid coordinates; for interior cells this is always (0, 0)
|
||||
};
|
||||
|
||||
struct ENAM
|
||||
{
|
||||
int mCellX;
|
||||
int mCellY;
|
||||
};
|
||||
struct Rotation
|
||||
{
|
||||
float mData[3][3];
|
||||
};
|
||||
|
||||
struct AADT // 44 bytes
|
||||
{
|
||||
int animGroupIndex; // See convertANIS() for the mapping.
|
||||
unsigned char mUnknown5[40];
|
||||
};
|
||||
int mPlayerFlags; // controls, camera and draw state
|
||||
unsigned int mLevelProgress;
|
||||
float mSkillProgress[27]; // skill progress, non-uniform scaled
|
||||
unsigned char mSkillIncreases[8]; // number of skill increases for each attribute
|
||||
int mTelekinesisRangeBonus; // in units; seems redundant
|
||||
float mVisionBonus; // range: <0.0, 1.0>; affected by light spells and Get/Mod/SetPCVisionBonus
|
||||
int mDetectKeyMagnitude; // seems redundant
|
||||
int mDetectEnchantmentMagnitude; // seems redundant
|
||||
int mDetectAnimalMagnitude; // seems redundant
|
||||
MarkLocation mMarkLocation;
|
||||
unsigned char mUnknown3[4];
|
||||
Rotation mVerticalRotation;
|
||||
unsigned char mSpecIncreases[3]; // number of skill increases for each specialization
|
||||
unsigned char mUnknown4;
|
||||
};
|
||||
|
||||
struct ENAM
|
||||
{
|
||||
int mCellX;
|
||||
int mCellY;
|
||||
};
|
||||
|
||||
struct AADT // 44 bytes
|
||||
{
|
||||
int animGroupIndex; // See convertANIS() for the mapping.
|
||||
unsigned char mUnknown5[40];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
std::vector<FNAM> mFactions;
|
||||
PNAM mPNAM;
|
||||
std::vector<FNAM> mFactions;
|
||||
PNAM mPNAM;
|
||||
|
||||
bool mHasMark;
|
||||
std::string mMNAM; // mark cell name; can also be sDefaultCellname or region name
|
||||
bool mHasMark;
|
||||
std::string mMNAM; // mark cell name; can also be sDefaultCellname or region name
|
||||
|
||||
bool mHasENAM;
|
||||
ENAM mENAM; // last exterior cell
|
||||
bool mHasENAM;
|
||||
ENAM mENAM; // last exterior cell
|
||||
|
||||
bool mHasAADT;
|
||||
AADT mAADT;
|
||||
bool mHasAADT;
|
||||
AADT mAADT;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
#include "importproj.h"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void ESSImport::PROJ::load(ESM::ESMReader& esm)
|
||||
{
|
||||
while (esm.isNextSub("PNAM"))
|
||||
void ESSImport::PROJ::load(ESM::ESMReader& esm)
|
||||
{
|
||||
PNAM pnam;
|
||||
esm.getHT(pnam);
|
||||
mProjectiles.push_back(pnam);
|
||||
while (esm.isNextSub("PNAM"))
|
||||
{
|
||||
PNAM pnam;
|
||||
esm.getHT(pnam);
|
||||
mProjectiles.push_back(pnam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||
|
||||
#include <vector>
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -13,34 +13,34 @@ namespace ESM
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
struct PROJ
|
||||
{
|
||||
struct PROJ
|
||||
{
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct PNAM // 184 bytes
|
||||
{
|
||||
float mAttackStrength;
|
||||
float mSpeed;
|
||||
unsigned char mUnknown[4*2];
|
||||
float mFlightTime;
|
||||
int mSplmIndex; // reference to a SPLM record (0 for ballistic projectiles)
|
||||
unsigned char mUnknown2[4];
|
||||
ESM::Vector3 mVelocity;
|
||||
ESM::Vector3 mPosition;
|
||||
unsigned char mUnknown3[4*9];
|
||||
ESM::NAME32 mActorId; // indexed refID (with the exception of "PlayerSaveGame")
|
||||
ESM::NAME32 mArrowId;
|
||||
ESM::NAME32 mBowId;
|
||||
struct PNAM // 184 bytes
|
||||
{
|
||||
float mAttackStrength;
|
||||
float mSpeed;
|
||||
unsigned char mUnknown[4 * 2];
|
||||
float mFlightTime;
|
||||
int mSplmIndex; // reference to a SPLM record (0 for ballistic projectiles)
|
||||
unsigned char mUnknown2[4];
|
||||
ESM::Vector3 mVelocity;
|
||||
ESM::Vector3 mPosition;
|
||||
unsigned char mUnknown3[4 * 9];
|
||||
ESM::NAME32 mActorId; // indexed refID (with the exception of "PlayerSaveGame")
|
||||
ESM::NAME32 mArrowId;
|
||||
ESM::NAME32 mBowId;
|
||||
|
||||
bool isMagic() const { return mSplmIndex != 0; }
|
||||
};
|
||||
bool isMagic() const { return mSplmIndex != 0; }
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
std::vector<PNAM> mProjectiles;
|
||||
std::vector<PNAM> mProjectiles;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "importques.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void QUES::load(ESM::ESMReader &esm)
|
||||
void QUES::load(ESM::ESMReader& esm)
|
||||
{
|
||||
while (esm.isNextSub("DATA"))
|
||||
mInfo.push_back(esm.getHString());
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
#include "importscpt.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void SCPT::load(ESM::ESMReader &esm)
|
||||
void SCPT::load(ESM::ESMReader& esm)
|
||||
{
|
||||
esm.getHNT(mSCHD, "SCHD");
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
#include "importscri.hpp"
|
||||
|
||||
#include <components/esm/loadscpt.hpp>
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
#include <components/esm3/loadscpt.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -15,8 +16,8 @@ namespace ESSImport
|
|||
|
||||
struct SCHD
|
||||
{
|
||||
ESM::NAME32 mName;
|
||||
ESM::Script::SCHDstruct mData;
|
||||
ESM::NAME32 mName;
|
||||
ESM::Script::SCHDstruct mData;
|
||||
};
|
||||
|
||||
// A running global script
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue